OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "printing/backend/print_backend.h" | 5 #include "printing/backend/print_backend.h" |
6 | 6 |
7 #include <objidl.h> | 7 #include <objidl.h> |
8 #include <winspool.h> | 8 #include <winspool.h> |
9 | 9 |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/string_piece.h" | 11 #include "base/string_piece.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "base/win/scoped_bstr.h" | 13 #include "base/win/scoped_bstr.h" |
14 #include "base/win/scoped_comptr.h" | 14 #include "base/win/scoped_comptr.h" |
15 #include "base/win/scoped_hglobal.h" | 15 #include "base/win/scoped_hglobal.h" |
16 #include "printing/backend/print_backend_consts.h" | 16 #include "printing/backend/print_backend_consts.h" |
17 #include "printing/backend/win_helper.h" | 17 #include "printing/backend/win_helper.h" |
18 | 18 |
19 namespace { | 19 namespace { |
20 | 20 |
| 21 // This class is designed to work with PRINTER_INFO_X structures |
| 22 // and calls GetPrinter internally with correctly allocated buffer. |
| 23 template <typename T> |
| 24 class PrinterInfo { |
| 25 public: |
| 26 bool GetPrinterInfo(HANDLE printer, int level) { |
| 27 DWORD buf_size = 0; |
| 28 GetPrinter(printer, level, NULL, 0, &buf_size); |
| 29 if (buf_size == 0) |
| 30 return false; |
| 31 buffer_.reset(new uint8[buf_size]); |
| 32 memset(buffer_.get(), 0, buf_size); |
| 33 return !!GetPrinter(printer, level, buffer_.get(), buf_size, &buf_size); |
| 34 } |
| 35 |
| 36 const T* get() const { |
| 37 return reinterpret_cast<T*>(buffer_.get()); |
| 38 } |
| 39 |
| 40 private: |
| 41 scoped_array<uint8> buffer_; |
| 42 }; |
| 43 |
21 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { | 44 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { |
22 DCHECK(stream); | 45 DCHECK(stream); |
23 DCHECK(out); | 46 DCHECK(out); |
24 HGLOBAL hdata = NULL; | 47 HGLOBAL hdata = NULL; |
25 HRESULT hr = GetHGlobalFromStream(stream, &hdata); | 48 HRESULT hr = GetHGlobalFromStream(stream, &hdata); |
26 if (SUCCEEDED(hr)) { | 49 if (SUCCEEDED(hr)) { |
27 DCHECK(hdata); | 50 DCHECK(hdata); |
28 base::win::ScopedHGlobal<char> locked_data(hdata); | 51 base::win::ScopedHGlobal<char> locked_data(hdata); |
29 out->assign(locked_data.release(), locked_data.Size()); | 52 out->assign(locked_data.release(), locked_data.Size()); |
30 } | 53 } |
31 return hr; | 54 return hr; |
32 } | 55 } |
33 | 56 |
34 } // namespace | 57 } // namespace |
35 | 58 |
36 namespace printing { | 59 namespace printing { |
37 | 60 |
38 class PrintBackendWin : public PrintBackend { | 61 class PrintBackendWin : public PrintBackend { |
39 public: | 62 public: |
40 PrintBackendWin() {} | 63 PrintBackendWin() {} |
41 | 64 |
42 // PrintBackend implementation. | 65 // PrintBackend implementation. |
43 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; | 66 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; |
44 virtual std::string GetDefaultPrinterName() OVERRIDE; | 67 virtual std::string GetDefaultPrinterName() OVERRIDE; |
| 68 virtual bool GetPrinterSemanticCapsAndDefaults( |
| 69 const std::string& printer_name, |
| 70 PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE; |
45 virtual bool GetPrinterCapsAndDefaults( | 71 virtual bool GetPrinterCapsAndDefaults( |
46 const std::string& printer_name, | 72 const std::string& printer_name, |
47 PrinterCapsAndDefaults* printer_info) OVERRIDE; | 73 PrinterCapsAndDefaults* printer_info) OVERRIDE; |
48 virtual std::string GetPrinterDriverInfo( | 74 virtual std::string GetPrinterDriverInfo( |
49 const std::string& printer_name) OVERRIDE; | 75 const std::string& printer_name) OVERRIDE; |
50 virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE; | 76 virtual bool IsValidPrinter(const std::string& printer_name) OVERRIDE; |
51 | 77 |
52 protected: | 78 protected: |
53 virtual ~PrintBackendWin() {} | 79 virtual ~PrintBackendWin() {} |
54 }; | 80 }; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 } | 112 } |
87 | 113 |
88 std::string PrintBackendWin::GetDefaultPrinterName() { | 114 std::string PrintBackendWin::GetDefaultPrinterName() { |
89 DWORD size = MAX_PATH; | 115 DWORD size = MAX_PATH; |
90 TCHAR default_printer_name[MAX_PATH]; | 116 TCHAR default_printer_name[MAX_PATH]; |
91 if (!::GetDefaultPrinter(default_printer_name, &size)) | 117 if (!::GetDefaultPrinter(default_printer_name, &size)) |
92 return std::string(); | 118 return std::string(); |
93 return WideToUTF8(default_printer_name); | 119 return WideToUTF8(default_printer_name); |
94 } | 120 } |
95 | 121 |
| 122 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( |
| 123 const std::string& printer_name, |
| 124 PrinterSemanticCapsAndDefaults* printer_info) { |
| 125 ScopedPrinterHandle printer_handle; |
| 126 OpenPrinter(const_cast<LPTSTR>(UTF8ToWide(printer_name).c_str()), |
| 127 printer_handle.Receive(), NULL); |
| 128 DCHECK(printer_handle); |
| 129 if (!printer_handle.IsValid()) |
| 130 return false; |
| 131 |
| 132 PrinterInfo<PRINTER_INFO_5> info_5; |
| 133 if (!info_5.GetPrinterInfo(printer_handle, 5)) |
| 134 return false; |
| 135 |
| 136 // Get printer capabilities. For more info see here: |
| 137 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).a
spx |
| 138 bool color_supported = (DeviceCapabilities(info_5.get()->pPrinterName, |
| 139 info_5.get()->pPortName, |
| 140 DC_COLORDEVICE, |
| 141 NULL, |
| 142 NULL) == 1); |
| 143 |
| 144 bool duplex_supported = (DeviceCapabilities(info_5.get()->pPrinterName, |
| 145 info_5.get()->pPortName, |
| 146 DC_DUPLEX, |
| 147 NULL, |
| 148 NULL) == 1); |
| 149 |
| 150 // PRINTER_INFO_9 retrieves current user settings. |
| 151 PrinterInfo<PRINTER_INFO_9> info_9; |
| 152 if (!info_9.GetPrinterInfo(printer_handle, 9)) |
| 153 return false; |
| 154 DEVMODE* devmode = info_9.get()->pDevMode; |
| 155 |
| 156 // Sometimes user settings are not available (have not been setted up yet). |
| 157 // Use printer default settings (PRINTER_INFO_8) in this case. |
| 158 PrinterInfo<PRINTER_INFO_8> info_8; |
| 159 if (!devmode) { |
| 160 if (info_8.GetPrinterInfo(printer_handle, 8)) |
| 161 devmode = info_8.get()->pDevMode; |
| 162 } |
| 163 if (!devmode) |
| 164 return false; |
| 165 |
| 166 PrinterSemanticCapsAndDefaults caps; |
| 167 caps.color_capable = color_supported; |
| 168 if ((devmode->dmFields & DM_COLOR) == DM_COLOR) |
| 169 caps.color_default = (devmode->dmColor == DMCOLOR_COLOR); |
| 170 |
| 171 caps.duplex_capable = duplex_supported; |
| 172 if ((devmode->dmFields & DM_DUPLEX) == DM_DUPLEX) { |
| 173 switch (devmode->dmDuplex) { |
| 174 case DMDUP_SIMPLEX: |
| 175 caps.duplex_default = SIMPLEX; |
| 176 break; |
| 177 case DMDUP_VERTICAL: |
| 178 caps.duplex_default = LONG_EDGE; |
| 179 break; |
| 180 case DMDUP_HORIZONTAL: |
| 181 caps.duplex_default = SHORT_EDGE; |
| 182 break; |
| 183 default: |
| 184 NOTREACHED(); |
| 185 } |
| 186 } |
| 187 |
| 188 *printer_info = caps; |
| 189 return true; |
| 190 } |
| 191 |
96 bool PrintBackendWin::GetPrinterCapsAndDefaults( | 192 bool PrintBackendWin::GetPrinterCapsAndDefaults( |
97 const std::string& printer_name, | 193 const std::string& printer_name, |
98 PrinterCapsAndDefaults* printer_info) { | 194 PrinterCapsAndDefaults* printer_info) { |
99 ScopedXPSInitializer xps_initializer; | 195 ScopedXPSInitializer xps_initializer; |
100 if (!xps_initializer.initialized()) { | 196 if (!xps_initializer.initialized()) { |
101 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) | 197 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) |
102 return false; | 198 return false; |
103 } | 199 } |
104 if (!IsValidPrinter(printer_name)) { | 200 if (!IsValidPrinter(printer_name)) { |
105 return false; | 201 return false; |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 printer_handle.Receive(), NULL); | 281 printer_handle.Receive(), NULL); |
186 return printer_handle.IsValid(); | 282 return printer_handle.IsValid(); |
187 } | 283 } |
188 | 284 |
189 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( | 285 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( |
190 const base::DictionaryValue* print_backend_settings) { | 286 const base::DictionaryValue* print_backend_settings) { |
191 return new PrintBackendWin; | 287 return new PrintBackendWin; |
192 } | 288 } |
193 | 289 |
194 } // namespace printing | 290 } // namespace printing |
OLD | NEW |