15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/win_helper.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_version_info.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/numerics/safe_conversions.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/win/scoped_comptr.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "printing/backend/print_backend_consts.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "printing/backend/printing_info_win.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTOpenProviderProc)(PCWSTR printer_name, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD version, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER* provider); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTGetPrintCapabilitiesProc)(HPTPROVIDER provider, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* capabilities, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message); 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTConvertDevModeToPrintTicketProc)( 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER provider, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG devmode_size_in_bytes, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PDEVMODE devmode, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTConvertPrintTicketToDevModeProc)( 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER provider, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EDefaultDevmodeType base_devmode_type, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG* devmode_byte_count, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PDEVMODE* devmode, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTMergeAndValidatePrintTicketProc)( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER provider, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* base_ticket, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* delta_ticket, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* result_ticket, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTReleaseMemoryProc)(PVOID buffer); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* PTCloseProviderProc)(HPTPROVIDER provider); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef HRESULT (WINAPI* StartXpsPrintJobProc)( 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR printer_name, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR job_name, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR output_file_name, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE progress_event, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE completion_event, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT8* printable_pages_on, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT32 printable_pages_on_count, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJob** xps_print_job, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJobStream** document_stream, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJobStream** print_ticket_stream); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTOpenProviderProc g_open_provider_proc = NULL; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTGetPrintCapabilitiesProc g_get_print_capabilities_proc = NULL; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTConvertDevModeToPrintTicketProc g_convert_devmode_to_print_ticket_proc = NULL; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTConvertPrintTicketToDevModeProc g_convert_print_ticket_to_devmode_proc = NULL; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTMergeAndValidatePrintTicketProc g_merge_and_validate_print_ticket_proc = NULL; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTReleaseMemoryProc g_release_memory_proc = NULL; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PTCloseProviderProc g_close_provider_proc = NULL; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StartXpsPrintJobProc g_start_xps_print_job_proc = NULL; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)HRESULT StreamFromPrintTicket(const std::string& print_ticket, 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IStream** stream) { 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(stream); 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream); 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (FAILED(hr)) { 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return hr; 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ULONG bytes_written = 0; 905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*stream)->Write(print_ticket.c_str(), 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::checked_cast<ULONG>(print_ticket.length()), 925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &bytes_written); 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(bytes_written == print_ticket.length()); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LARGE_INTEGER pos = {0}; 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ULARGE_INTEGER new_pos = {0}; 965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos); 975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return S_OK; 985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kXpsTicketTemplate[] = 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "<?xml version='1.0' encoding='UTF-8'?>" 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "<psf:PrintTicket " 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "xmlns:psf='" 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' " 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "xmlns:psk=" 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "'http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' " 1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "version='1'>" 1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "<psf:Feature name='psk:PageOutputColor'>" 1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "<psf:Option name='psk:%s'>" 1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "</psf:Option>" 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "</psf:Feature>" 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "</psf:PrintTicket>"; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kXpsTicketColor[] = "Color"; 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kXpsTicketMonochrome[] = "Monochrome"; 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace printing { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XPSModule::Init() { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = InitImpl(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return initialized; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XPSModule::InitImpl() { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE prntvpt_module = LoadLibrary(L"prntvpt.dll"); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prntvpt_module == NULL) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_open_provider_proc = reinterpret_cast<PTOpenProviderProc>( 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTOpenProvider")); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_open_provider_proc) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_get_print_capabilities_proc = reinterpret_cast<PTGetPrintCapabilitiesProc>( 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTGetPrintCapabilities")); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_get_print_capabilities_proc) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_convert_devmode_to_print_ticket_proc = 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PTConvertDevModeToPrintTicketProc>( 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTConvertDevModeToPrintTicket")); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_convert_devmode_to_print_ticket_proc) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_convert_print_ticket_to_devmode_proc = 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PTConvertPrintTicketToDevModeProc>( 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTConvertPrintTicketToDevMode")); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_convert_print_ticket_to_devmode_proc) { 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_merge_and_validate_print_ticket_proc = 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PTMergeAndValidatePrintTicketProc>( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTMergeAndValidatePrintTicket")); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_merge_and_validate_print_ticket_proc) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_release_memory_proc = 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PTReleaseMemoryProc>( 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTReleaseMemory")); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_release_memory_proc) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_close_provider_proc = 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<PTCloseProviderProc>( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(prntvpt_module, "PTCloseProvider")); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_close_provider_proc) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)HRESULT XPSModule::OpenProvider(const base::string16& printer_name, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD version, 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER* provider) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_open_provider_proc(printer_name.c_str(), version, provider); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::GetPrintCapabilities(HPTPROVIDER provider, 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* capabilities, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_get_print_capabilities_proc(provider, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_ticket, 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) capabilities, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::ConvertDevModeToPrintTicket(HPTPROVIDER provider, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG devmode_size_in_bytes, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PDEVMODE devmode, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_convert_devmode_to_print_ticket_proc(provider, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devmode_size_in_bytes, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devmode, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scope, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_ticket); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::ConvertPrintTicketToDevMode( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HPTPROVIDER provider, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* print_ticket, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EDefaultDevmodeType base_devmode_type, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ULONG* devmode_byte_count, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PDEVMODE* devmode, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_convert_print_ticket_to_devmode_proc(provider, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_ticket, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_devmode_type, 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scope, 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devmode_byte_count, 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devmode, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::MergeAndValidatePrintTicket(HPTPROVIDER provider, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* base_ticket, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* delta_ticket, 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EPrintTicketScope scope, 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IStream* result_ticket, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BSTR* error_message) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_merge_and_validate_print_ticket_proc(provider, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_ticket, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delta_ticket, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scope, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_ticket, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::ReleaseMemory(PVOID buffer) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_release_memory_proc(buffer); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSModule::CloseProvider(HPTPROVIDER provider) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_close_provider_proc(provider); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedXPSInitializer::ScopedXPSInitializer() : initialized_(false) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!XPSModule::Init()) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calls to XPS APIs typically require the XPS provider to be opened with 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PTOpenProvider. PTOpenProvider calls CoInitializeEx with 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // COINIT_MULTITHREADED. We have seen certain buggy HP printer driver DLLs 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that call CoInitializeEx with COINIT_APARTMENTTHREADED in the context of 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PTGetPrintCapabilities. This call fails but the printer driver calls 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CoUninitialize anyway. This results in the apartment being torn down too 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // early and the msxml DLL being unloaded which in turn causes code in 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unidrvui.dll to have a dangling pointer to an XML document which causes a 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // crash. To protect ourselves from such drivers we make sure we always have 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an extra CoInitialize (calls to CoInitialize/CoUninitialize are 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // refcounted). 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this succeeded we are done because the PTOpenProvider call will provide 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the extra refcount on the apartment. If it failed because someone already 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called CoInitializeEx with COINIT_APARTMENTTHREADED, we try the other model 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to provide the additional refcount (since we don't know which model buggy 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // printer drivers will use). 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SUCCEEDED(hr)) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(SUCCEEDED(hr)); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = true; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedXPSInitializer::~ScopedXPSInitializer() { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (initialized_) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoUninitialize(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized_ = false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XPSPrintModule::Init() { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = InitImpl(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return initialized; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool XPSPrintModule::InitImpl() { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE xpsprint_module = LoadLibrary(L"xpsprint.dll"); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xpsprint_module == NULL) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_start_xps_print_job_proc = reinterpret_cast<StartXpsPrintJobProc>( 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetProcAddress(xpsprint_module, "StartXpsPrintJob")); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_start_xps_print_job_proc) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HRESULT XPSPrintModule::StartXpsPrintJob( 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR printer_name, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR job_name, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const LPCWSTR output_file_name, 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE progress_event, 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE completion_event, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT8* printable_pages_on, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UINT32 printable_pages_on_count, 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJob** xps_print_job, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJobStream** document_stream, 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IXpsPrintJobStream** print_ticket_stream) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_start_xps_print_job_proc(printer_name, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_name, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_file_name, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) progress_event, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completion_event, 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printable_pages_on, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printable_pages_on_count, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xps_print_job, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) document_stream, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print_ticket_stream); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InitBasicPrinterInfo(HANDLE printer, PrinterBasicInfo* printer_info) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(printer); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(printer_info); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!printer) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrinterInfo2 info_2; 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!info_2.Init(printer)) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printer_info->printer_name = base::WideToUTF8(info_2.get()->pPrinterName); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (info_2.get()->pComment) { 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printer_info->printer_description = 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(info_2.get()->pComment); 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (info_2.get()->pLocation) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printer_info->options[kLocationTagName] = 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(info_2.get()->pLocation); 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (info_2.get()->pDriverName) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printer_info->options[kDriverNameTagName] = 3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::WideToUTF8(info_2.get()->pDriverName); 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) printer_info->printer_status = info_2.get()->Status; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string driver_info = GetDriverInfo(printer); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!driver_info.empty()) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) printer_info->options[kDriverInfoTagName] = driver_info; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetDriverInfo(HANDLE printer) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(printer); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string driver_info; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!printer) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return driver_info; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DriverInfo6 info_6; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!info_6.Init(printer)) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return driver_info; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string info[4]; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info_6.get()->pName) 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info[0] = base::WideToUTF8(info_6.get()->pName); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info_6.get()->pDriverPath) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<FileVersionInfo> version_info( 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileVersionInfo::CreateFileVersionInfo( 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath(info_6.get()->pDriverPath))); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_info.get()) { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info[1] = base::WideToUTF8(version_info->file_version()); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info[2] = base::WideToUTF8(version_info->product_name()); 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) info[3] = base::WideToUTF8(version_info->product_version()); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(info); ++i) { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::replace(info[i].begin(), info[i].end(), ';', ','); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) driver_info.append(info[i]); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < arraysize(info) - 1) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) driver_info.append(";"); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return driver_info; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<DEVMODE, base::FreeDeleter> XpsTicketToDevMode( 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& printer_name, 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string& print_ticket) { 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode; 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printing::ScopedXPSInitializer xps_initializer; 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!xps_initializer.initialized()) { 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dev_mode.Pass(); 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printing::ScopedPrinterHandle printer; 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!printer.OpenPrinter(printer_name.c_str())) 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dev_mode.Pass(); 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::win::ScopedComPtr<IStream> pt_stream; 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive()); 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (FAILED(hr)) 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dev_mode.Pass(); 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HPTPROVIDER provider = NULL; 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider); 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (SUCCEEDED(hr)) { 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ULONG size = 0; 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DEVMODE* dm = NULL; 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Use kPTJobScope, because kPTDocumentScope breaks duplex. 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider, 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pt_stream, 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kUserDefaultDevmode, 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kPTJobScope, 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &size, 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) &dm, 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (SUCCEEDED(hr)) { 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Correct DEVMODE using DocumentProperties. See documentation for 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // PTConvertPrintTicketToDevMode. 4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci dev_mode = CreateDevMode(printer.Get(), dm); 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printing::XPSModule::ReleaseMemory(dm); 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printing::XPSModule::CloseProvider(provider); 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return dev_mode.Pass(); 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevModeWithColor( 432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HANDLE printer, 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::string16& printer_name, 434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool color) { 435116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<DEVMODE, base::FreeDeleter> default_ticket = 436116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CreateDevMode(printer, NULL); 437116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!default_ticket) 438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 440116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((default_ticket->dmFields & DM_COLOR) && 441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ((default_ticket->dmColor == DMCOLOR_COLOR) == color)) { 442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 445116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default_ticket->dmFields |= DM_COLOR; 446116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default_ticket->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DriverInfo6 info_6; 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!info_6.Init(printer)) 450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const DRIVER_INFO_6* p = info_6.get(); 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Only HP known to have issues. 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!p->pszMfgName || wcscmp(p->pszMfgName, L"HP") != 0) 456116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Need XPS for this workaround. 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) printing::ScopedXPSInitializer xps_initializer; 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!xps_initializer.initialized()) 461116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color); 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<DEVMODE, base::FreeDeleter> ticket = 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) printing::XpsTicketToDevMode(printer_name, xps_ticket); 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!ticket) 468116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return default_ticket.Pass(); 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ticket.Pass(); 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode(HANDLE printer, 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DEVMODE* in) { 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LONG buffer_size = DocumentProperties( 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, printer, const_cast<wchar_t*>(L""), NULL, NULL, 0); 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (buffer_size < static_cast<int>(sizeof(DEVMODE))) 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return scoped_ptr<DEVMODE, base::FreeDeleter>(); 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<DEVMODE, base::FreeDeleter> out( 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) reinterpret_cast<DEVMODE*>(malloc(buffer_size))); 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER; 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (DocumentProperties( 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, printer, const_cast<wchar_t*>(L""), out.get(), in, flags) != 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IDOK) { 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return scoped_ptr<DEVMODE, base::FreeDeleter>(); 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return out.Pass(); 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<DEVMODE, base::FreeDeleter> PromptDevMode( 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HANDLE printer, 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const base::string16& printer_name, 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DEVMODE* in, 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci HWND window, 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool* canceled) { 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LONG buffer_size = 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DocumentProperties(window, 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci printer, 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const_cast<wchar_t*>(printer_name.c_str()), 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NULL, 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NULL, 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0); 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (buffer_size < static_cast<int>(sizeof(DEVMODE))) 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<DEVMODE, base::FreeDeleter>(); 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<DEVMODE, base::FreeDeleter> out( 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reinterpret_cast<DEVMODE*>(malloc(buffer_size))); 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER | DM_IN_PROMPT; 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LONG result = DocumentProperties(window, 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci printer, 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const_cast<wchar_t*>(printer_name.c_str()), 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci out.get(), 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci in, 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci flags); 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (canceled) 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *canceled = (result == IDCANCEL); 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (result != IDOK) 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<DEVMODE, base::FreeDeleter>(); 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return out.Pass(); 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace printing 524