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/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/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/printing_info_win.h" | 17 #include "printing/backend/printing_info_win.h" |
18 #include "printing/backend/win_helper.h" | 18 #include "printing/backend/win_helper.h" |
19 | 19 |
20 namespace printing { | |
20 | 21 |
21 namespace { | 22 namespace { |
22 | 23 |
23 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { | 24 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { |
24 DCHECK(stream); | 25 DCHECK(stream); |
25 DCHECK(out); | 26 DCHECK(out); |
26 HGLOBAL hdata = NULL; | 27 HGLOBAL hdata = NULL; |
27 HRESULT hr = GetHGlobalFromStream(stream, &hdata); | 28 HRESULT hr = GetHGlobalFromStream(stream, &hdata); |
28 if (SUCCEEDED(hr)) { | 29 if (SUCCEEDED(hr)) { |
29 DCHECK(hdata); | 30 DCHECK(hdata); |
30 base::win::ScopedHGlobal<char> locked_data(hdata); | 31 base::win::ScopedHGlobal<char> locked_data(hdata); |
31 out->assign(locked_data.release(), locked_data.Size()); | 32 out->assign(locked_data.release(), locked_data.Size()); |
32 } | 33 } |
33 return hr; | 34 return hr; |
34 } | 35 } |
35 | 36 |
37 template <class T> | |
38 void GetDeviceCapabilityArray(const wchar_t* printer, | |
39 const wchar_t* port, | |
40 WORD id, | |
41 std::vector<T>* result) { | |
42 int count = DeviceCapabilities(printer, port, id, NULL, NULL); | |
43 if (count <= 0) | |
44 return; | |
45 result->resize(count); | |
46 CHECK_EQ(count, | |
47 DeviceCapabilities(printer, port, id, | |
Noam Samuel
2014/02/04 18:33:22
Misaligned.
Vitaly Buka (NO REVIEWS)
2014/02/04 18:48:24
Done.
| |
48 reinterpret_cast<LPTSTR>(result->data()), NULL)); | |
49 } | |
50 | |
51 void LoadPaper(const wchar_t* printer, | |
52 const wchar_t* port, | |
53 const DEVMODE* devmode, | |
54 PrinterSemanticCapsAndDefaults* caps) { | |
55 static const size_t kToUm = 100; | |
56 static const size_t kMaxPaperName = 64; | |
57 | |
58 short default_id = 0; | |
59 gfx::Size default_size; | |
60 | |
61 if (devmode) { | |
62 if ((devmode->dmFields & DM_PAPERSIZE) == DM_PAPERSIZE) | |
63 default_id = devmode->dmPaperSize; | |
64 if ((devmode->dmFields & DM_PAPERWIDTH) == DM_PAPERWIDTH) | |
65 default_size.set_width(devmode->dmPaperWidth * kToUm); | |
66 if ((devmode->dmFields & DM_PAPERLENGTH) == DM_PAPERLENGTH) | |
67 default_size.set_height(devmode->dmPaperLength * kToUm); | |
68 } | |
69 | |
70 struct PaperName { | |
71 wchar_t chars[kMaxPaperName]; | |
72 }; | |
73 | |
74 // Paper | |
75 std::vector<PaperName> names; | |
76 GetDeviceCapabilityArray(printer, port, DC_PAPERNAMES, &names); | |
77 | |
78 std::vector<POINT> sizes; | |
79 GetDeviceCapabilityArray(printer, port, DC_PAPERSIZE, &sizes); | |
80 | |
81 std::vector<WORD> ids; | |
82 GetDeviceCapabilityArray(printer, port, DC_PAPERS, &ids); | |
83 | |
84 DCHECK_EQ(ids.size(), sizes.size()); | |
85 DCHECK_EQ(names.size(), sizes.size()); | |
86 | |
87 if (ids.size() != sizes.size()) | |
88 ids.clear(); | |
89 if (names.size() != sizes.size()) | |
90 names.clear(); | |
91 | |
92 for (size_t i = 0; i < sizes.size(); ++i) { | |
93 PrinterSemanticCapsAndDefaults::Paper paper; | |
94 paper.size_um.SetSize(sizes[i].x * kToUm, sizes[i].y * kToUm); | |
95 if (!names.empty()) { | |
96 paper.name.assign(&names[i].chars, &names[i].chars + kMaxPaperName); | |
97 // Trim trailing zeros. | |
98 paper.name = paper.name.c_str(); | |
99 } | |
100 if (caps->default_paper < 0) { | |
101 if (!default_size.IsEmpty()) { | |
102 if (default_size == paper.size_um) | |
103 caps->default_paper = i; | |
104 } else if (default_id && !ids.empty() && ids[i] == default_id) { | |
105 caps->default_paper = i; | |
106 } | |
107 } | |
108 caps->papers.push_back(paper); | |
109 } | |
110 | |
111 if (caps->default_paper < 0) { | |
112 // Add default paper because DeviceCapabilities it was not found yet. | |
Noam Samuel
2014/02/04 18:33:22
"Add default paper because DeviceCapabilities hasn
Vitaly Buka (NO REVIEWS)
2014/02/04 18:48:24
Done.
| |
113 if (!default_size.IsEmpty()) { | |
114 caps->default_paper = caps->papers.size(); | |
115 PrinterSemanticCapsAndDefaults::Paper paper; | |
116 paper.size_um = default_size; | |
117 paper.name = "CUSTOM"; | |
118 caps->papers.push_back(paper); | |
119 } | |
120 } | |
121 } | |
122 | |
123 void LoadDpi(const wchar_t* printer, | |
124 const wchar_t* port, | |
125 const DEVMODE* devmode, | |
126 PrinterSemanticCapsAndDefaults* caps) { | |
127 gfx::Size default_dpi; | |
128 | |
129 if (devmode) { | |
130 if ((devmode->dmFields & DM_PRINTQUALITY) == DM_PRINTQUALITY && | |
131 devmode->dmPrintQuality > 0) { | |
132 default_dpi.SetSize(devmode->dmPrintQuality, devmode->dmPrintQuality); | |
133 if ((devmode->dmFields & DM_YRESOLUTION) == DM_PRINTQUALITY) { | |
134 default_dpi.set_height(devmode->dmYResolution); | |
135 } | |
136 } | |
137 } | |
138 | |
139 std::vector<POINT> dpis; | |
140 GetDeviceCapabilityArray(printer, port, DC_ENUMRESOLUTIONS, &dpis); | |
141 | |
142 for (size_t i = 0; i < dpis.size() ; ++i) { | |
143 gfx::Size dpi(dpis[i].x, dpis[i].y); | |
144 if (caps->default_dpi < 0 && default_dpi == dpi) | |
145 caps->default_dpi = i; | |
146 caps->dpis.push_back(dpi); | |
147 } | |
148 | |
149 if (caps->default_dpi < 0) { | |
150 // Add default dpi because DeviceCapabilities didn't return it. | |
151 if (!default_dpi.IsEmpty()) { | |
152 caps->default_dpi = caps->dpis.size(); | |
153 caps->dpis.push_back(default_dpi); | |
154 } | |
155 } | |
156 } | |
157 | |
36 } // namespace | 158 } // namespace |
37 | 159 |
38 namespace printing { | |
39 | |
40 class PrintBackendWin : public PrintBackend { | 160 class PrintBackendWin : public PrintBackend { |
41 public: | 161 public: |
42 PrintBackendWin() {} | 162 PrintBackendWin() {} |
43 | 163 |
44 // PrintBackend implementation. | 164 // PrintBackend implementation. |
45 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; | 165 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; |
46 virtual std::string GetDefaultPrinterName() OVERRIDE; | 166 virtual std::string GetDefaultPrinterName() OVERRIDE; |
47 virtual bool GetPrinterSemanticCapsAndDefaults( | 167 virtual bool GetPrinterSemanticCapsAndDefaults( |
48 const std::string& printer_name, | 168 const std::string& printer_name, |
49 PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE; | 169 PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( | 221 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( |
102 const std::string& printer_name, | 222 const std::string& printer_name, |
103 PrinterSemanticCapsAndDefaults* printer_info) { | 223 PrinterSemanticCapsAndDefaults* printer_info) { |
104 ScopedPrinterHandle printer_handle; | 224 ScopedPrinterHandle printer_handle; |
105 if (!printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { | 225 if (!printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { |
106 LOG(WARNING) << "Failed to open printer, error = " << GetLastError(); | 226 LOG(WARNING) << "Failed to open printer, error = " << GetLastError(); |
107 return false; | 227 return false; |
108 } | 228 } |
109 | 229 |
110 PrinterInfo5 info_5; | 230 PrinterInfo5 info_5; |
111 if (!info_5.Init(printer_handle)) { | 231 if (!info_5.Init(printer_handle)) |
112 return false; | 232 return false; |
113 } | 233 const wchar_t* name = info_5.get()->pPrinterName; |
114 DCHECK_EQ(info_5.get()->pPrinterName, base::UTF8ToUTF16(printer_name)); | 234 const wchar_t* port = info_5.get()->pPortName; |
235 DCHECK_EQ(name, base::UTF8ToUTF16(printer_name)); | |
115 | 236 |
116 PrinterSemanticCapsAndDefaults caps; | 237 PrinterSemanticCapsAndDefaults caps; |
117 | |
118 // Get printer capabilities. For more info see here: | |
119 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).a spx | |
120 caps.color_changeable = (::DeviceCapabilities(info_5.get()->pPrinterName, | |
121 info_5.get()->pPortName, | |
122 DC_COLORDEVICE, | |
123 NULL, | |
124 NULL) == 1); | |
125 | |
126 caps.duplex_capable = (::DeviceCapabilities(info_5.get()->pPrinterName, | |
127 info_5.get()->pPortName, | |
128 DC_DUPLEX, | |
129 NULL, | |
130 NULL) == 1); | |
131 | |
132 UserDefaultDevMode user_settings; | 238 UserDefaultDevMode user_settings; |
133 | |
134 if (user_settings.Init(printer_handle)) { | 239 if (user_settings.Init(printer_handle)) { |
135 if ((user_settings.get()->dmFields & DM_COLOR) == DM_COLOR) | 240 if ((user_settings.get()->dmFields & DM_COLOR) == DM_COLOR) |
136 caps.color_default = (user_settings.get()->dmColor == DMCOLOR_COLOR); | 241 caps.color_default = (user_settings.get()->dmColor == DMCOLOR_COLOR); |
137 | 242 |
138 if ((user_settings.get()->dmFields & DM_DUPLEX) == DM_DUPLEX) { | 243 if ((user_settings.get()->dmFields & DM_DUPLEX) == DM_DUPLEX) { |
139 switch (user_settings.get()->dmDuplex) { | 244 switch (user_settings.get()->dmDuplex) { |
140 case DMDUP_SIMPLEX: | 245 case DMDUP_SIMPLEX: |
141 caps.duplex_default = SIMPLEX; | 246 caps.duplex_default = SIMPLEX; |
142 break; | 247 break; |
143 case DMDUP_VERTICAL: | 248 case DMDUP_VERTICAL: |
144 caps.duplex_default = LONG_EDGE; | 249 caps.duplex_default = LONG_EDGE; |
145 break; | 250 break; |
146 case DMDUP_HORIZONTAL: | 251 case DMDUP_HORIZONTAL: |
147 caps.duplex_default = SHORT_EDGE; | 252 caps.duplex_default = SHORT_EDGE; |
148 break; | 253 break; |
149 default: | 254 default: |
150 NOTREACHED(); | 255 NOTREACHED(); |
151 } | 256 } |
152 } | 257 } |
258 | |
259 if ((user_settings.get()->dmFields & DM_COLLATE) == DM_COLLATE) | |
260 caps.collate_default = (user_settings.get()->dmCollate == DMCOLLATE_TRUE); | |
153 } else { | 261 } else { |
154 LOG(WARNING) << "Fallback to color/simplex mode."; | 262 LOG(WARNING) << "Fallback to color/simplex mode."; |
155 caps.color_default = caps.color_changeable; | 263 caps.color_default = caps.color_changeable; |
156 caps.duplex_default = SIMPLEX; | 264 caps.duplex_default = SIMPLEX; |
157 } | 265 } |
158 | 266 |
267 // Get printer capabilities. For more info see here: | |
268 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).a spx | |
269 caps.color_changeable = | |
270 (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL) == 1); | |
271 | |
272 caps.duplex_capable = | |
273 (DeviceCapabilities(name, port, DC_DUPLEX, NULL, NULL) == 1); | |
274 | |
275 caps.collate_capable = | |
276 (DeviceCapabilities(name, port, DC_COLLATE, NULL, NULL) == 1); | |
277 | |
278 caps.copies_capable = | |
279 (DeviceCapabilities(name, port, DC_COPIES, NULL, NULL) > 1); | |
280 | |
281 LoadPaper(name, port, user_settings.get(), &caps); | |
282 LoadDpi(name, port, user_settings.get(), &caps); | |
283 | |
159 *printer_info = caps; | 284 *printer_info = caps; |
160 return true; | 285 return true; |
161 } | 286 } |
162 | 287 |
163 bool PrintBackendWin::GetPrinterCapsAndDefaults( | 288 bool PrintBackendWin::GetPrinterCapsAndDefaults( |
164 const std::string& printer_name, | 289 const std::string& printer_name, |
165 PrinterCapsAndDefaults* printer_info) { | 290 PrinterCapsAndDefaults* printer_info) { |
166 ScopedXPSInitializer xps_initializer; | 291 ScopedXPSInitializer xps_initializer; |
167 if (!xps_initializer.initialized()) { | 292 if (!xps_initializer.initialized()) { |
168 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) | 293 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 ScopedPrinterHandle printer_handle; | 371 ScopedPrinterHandle printer_handle; |
247 return printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str()); | 372 return printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str()); |
248 } | 373 } |
249 | 374 |
250 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( | 375 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( |
251 const base::DictionaryValue* print_backend_settings) { | 376 const base::DictionaryValue* print_backend_settings) { |
252 return new PrintBackendWin; | 377 return new PrintBackendWin; |
253 } | 378 } |
254 | 379 |
255 } // namespace printing | 380 } // namespace printing |
OLD | NEW |