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_9) in this case. | |
Lei Zhang
2012/09/05 00:32:32
Did you mean PRINTER_INFO_8?
gene
2012/09/05 21:04:10
Of course. Thanks
| |
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 |