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, |
| 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; // Windows uses 0.1mm. |
| 56 static const size_t kMaxPaperName = 64; |
| 57 |
| 58 struct PaperName { |
| 59 wchar_t chars[kMaxPaperName]; |
| 60 }; |
| 61 |
| 62 // Paper |
| 63 std::vector<PaperName> names; |
| 64 GetDeviceCapabilityArray(printer, port, DC_PAPERNAMES, &names); |
| 65 |
| 66 std::vector<POINT> sizes; |
| 67 GetDeviceCapabilityArray(printer, port, DC_PAPERSIZE, &sizes); |
| 68 |
| 69 std::vector<WORD> ids; |
| 70 GetDeviceCapabilityArray(printer, port, DC_PAPERS, &ids); |
| 71 |
| 72 DCHECK_EQ(ids.size(), sizes.size()); |
| 73 DCHECK_EQ(names.size(), sizes.size()); |
| 74 |
| 75 if (ids.size() != sizes.size()) |
| 76 ids.clear(); |
| 77 if (names.size() != sizes.size()) |
| 78 names.clear(); |
| 79 |
| 80 for (size_t i = 0; i < sizes.size(); ++i) { |
| 81 PrinterSemanticCapsAndDefaults::Paper paper; |
| 82 paper.size_um.SetSize(sizes[i].x * kToUm, sizes[i].y * kToUm); |
| 83 if (!names.empty()) { |
| 84 paper.name.assign(&names[i].chars, &names[i].chars + kMaxPaperName); |
| 85 // Trim trailing zeros. |
| 86 paper.name = paper.name.c_str(); |
| 87 } |
| 88 caps->papers.push_back(paper); |
| 89 } |
| 90 |
| 91 if (devmode) { |
| 92 short default_id = 0; |
| 93 gfx::Size default_size; |
| 94 |
| 95 if ((devmode->dmFields & DM_PAPERSIZE) == DM_PAPERSIZE) |
| 96 default_id = devmode->dmPaperSize; |
| 97 if ((devmode->dmFields & DM_PAPERWIDTH) == DM_PAPERWIDTH) |
| 98 default_size.set_width(devmode->dmPaperWidth * kToUm); |
| 99 if ((devmode->dmFields & DM_PAPERLENGTH) == DM_PAPERLENGTH) |
| 100 default_size.set_height(devmode->dmPaperLength * kToUm); |
| 101 |
| 102 if (default_size.IsEmpty()) { |
| 103 for (size_t i = 0; i < ids.size(); ++i) { |
| 104 if (ids[i] == default_id) { |
| 105 PrinterSemanticCapsAndDefaults::Paper paper; |
| 106 paper.size_um.SetSize(sizes[i].x * kToUm, sizes[i].y * kToUm); |
| 107 if (!names.empty()) { |
| 108 paper.name.assign(&names[i].chars, &names[i].chars + kMaxPaperName); |
| 109 // Trim trailing zeros. |
| 110 paper.name = paper.name.c_str(); |
| 111 } |
| 112 caps->default_paper = paper; |
| 113 break; |
| 114 } |
| 115 } |
| 116 } else { |
| 117 caps->default_paper.size_um = default_size; |
| 118 } |
| 119 } |
| 120 } |
| 121 |
| 122 void LoadDpi(const wchar_t* printer, |
| 123 const wchar_t* port, |
| 124 const DEVMODE* devmode, |
| 125 PrinterSemanticCapsAndDefaults* caps) { |
| 126 std::vector<POINT> dpis; |
| 127 GetDeviceCapabilityArray(printer, port, DC_ENUMRESOLUTIONS, &dpis); |
| 128 |
| 129 for (size_t i = 0; i < dpis.size() ; ++i) |
| 130 caps->dpis.push_back(gfx::Size(dpis[i].x, dpis[i].y)); |
| 131 |
| 132 if (devmode) { |
| 133 if ((devmode->dmFields & DM_PRINTQUALITY) == DM_PRINTQUALITY && |
| 134 devmode->dmPrintQuality > 0) { |
| 135 caps->default_dpi.SetSize(devmode->dmPrintQuality, |
| 136 devmode->dmPrintQuality); |
| 137 if ((devmode->dmFields & DM_YRESOLUTION) == DM_PRINTQUALITY) { |
| 138 caps->default_dpi.set_height(devmode->dmYResolution); |
| 139 } |
| 140 } |
| 141 } |
| 142 } |
| 143 |
36 } // namespace | 144 } // namespace |
37 | 145 |
38 namespace printing { | |
39 | |
40 class PrintBackendWin : public PrintBackend { | 146 class PrintBackendWin : public PrintBackend { |
41 public: | 147 public: |
42 PrintBackendWin() {} | 148 PrintBackendWin() {} |
43 | 149 |
44 // PrintBackend implementation. | 150 // PrintBackend implementation. |
45 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; | 151 virtual bool EnumeratePrinters(PrinterList* printer_list) OVERRIDE; |
46 virtual std::string GetDefaultPrinterName() OVERRIDE; | 152 virtual std::string GetDefaultPrinterName() OVERRIDE; |
47 virtual bool GetPrinterSemanticCapsAndDefaults( | 153 virtual bool GetPrinterSemanticCapsAndDefaults( |
48 const std::string& printer_name, | 154 const std::string& printer_name, |
49 PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE; | 155 PrinterSemanticCapsAndDefaults* printer_info) OVERRIDE; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( | 207 bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( |
102 const std::string& printer_name, | 208 const std::string& printer_name, |
103 PrinterSemanticCapsAndDefaults* printer_info) { | 209 PrinterSemanticCapsAndDefaults* printer_info) { |
104 ScopedPrinterHandle printer_handle; | 210 ScopedPrinterHandle printer_handle; |
105 if (!printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { | 211 if (!printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { |
106 LOG(WARNING) << "Failed to open printer, error = " << GetLastError(); | 212 LOG(WARNING) << "Failed to open printer, error = " << GetLastError(); |
107 return false; | 213 return false; |
108 } | 214 } |
109 | 215 |
110 PrinterInfo5 info_5; | 216 PrinterInfo5 info_5; |
111 if (!info_5.Init(printer_handle)) { | 217 if (!info_5.Init(printer_handle)) |
112 return false; | 218 return false; |
113 } | 219 const wchar_t* name = info_5.get()->pPrinterName; |
114 DCHECK_EQ(info_5.get()->pPrinterName, base::UTF8ToUTF16(printer_name)); | 220 const wchar_t* port = info_5.get()->pPortName; |
| 221 DCHECK_EQ(name, base::UTF8ToUTF16(printer_name)); |
115 | 222 |
116 PrinterSemanticCapsAndDefaults caps; | 223 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; | 224 UserDefaultDevMode user_settings; |
133 | |
134 if (user_settings.Init(printer_handle)) { | 225 if (user_settings.Init(printer_handle)) { |
135 if ((user_settings.get()->dmFields & DM_COLOR) == DM_COLOR) | 226 if ((user_settings.get()->dmFields & DM_COLOR) == DM_COLOR) |
136 caps.color_default = (user_settings.get()->dmColor == DMCOLOR_COLOR); | 227 caps.color_default = (user_settings.get()->dmColor == DMCOLOR_COLOR); |
137 | 228 |
138 if ((user_settings.get()->dmFields & DM_DUPLEX) == DM_DUPLEX) { | 229 if ((user_settings.get()->dmFields & DM_DUPLEX) == DM_DUPLEX) { |
139 switch (user_settings.get()->dmDuplex) { | 230 switch (user_settings.get()->dmDuplex) { |
140 case DMDUP_SIMPLEX: | 231 case DMDUP_SIMPLEX: |
141 caps.duplex_default = SIMPLEX; | 232 caps.duplex_default = SIMPLEX; |
142 break; | 233 break; |
143 case DMDUP_VERTICAL: | 234 case DMDUP_VERTICAL: |
144 caps.duplex_default = LONG_EDGE; | 235 caps.duplex_default = LONG_EDGE; |
145 break; | 236 break; |
146 case DMDUP_HORIZONTAL: | 237 case DMDUP_HORIZONTAL: |
147 caps.duplex_default = SHORT_EDGE; | 238 caps.duplex_default = SHORT_EDGE; |
148 break; | 239 break; |
149 default: | 240 default: |
150 NOTREACHED(); | 241 NOTREACHED(); |
151 } | 242 } |
152 } | 243 } |
| 244 |
| 245 if ((user_settings.get()->dmFields & DM_COLLATE) == DM_COLLATE) |
| 246 caps.collate_default = (user_settings.get()->dmCollate == DMCOLLATE_TRUE); |
153 } else { | 247 } else { |
154 LOG(WARNING) << "Fallback to color/simplex mode."; | 248 LOG(WARNING) << "Fallback to color/simplex mode."; |
155 caps.color_default = caps.color_changeable; | 249 caps.color_default = caps.color_changeable; |
156 caps.duplex_default = SIMPLEX; | 250 caps.duplex_default = SIMPLEX; |
157 } | 251 } |
158 | 252 |
| 253 // Get printer capabilities. For more info see here: |
| 254 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).a
spx |
| 255 caps.color_changeable = |
| 256 (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL) == 1); |
| 257 |
| 258 caps.duplex_capable = |
| 259 (DeviceCapabilities(name, port, DC_DUPLEX, NULL, NULL) == 1); |
| 260 |
| 261 caps.collate_capable = |
| 262 (DeviceCapabilities(name, port, DC_COLLATE, NULL, NULL) == 1); |
| 263 |
| 264 caps.copies_capable = |
| 265 (DeviceCapabilities(name, port, DC_COPIES, NULL, NULL) > 1); |
| 266 |
| 267 LoadPaper(name, port, user_settings.get(), &caps); |
| 268 LoadDpi(name, port, user_settings.get(), &caps); |
| 269 |
159 *printer_info = caps; | 270 *printer_info = caps; |
160 return true; | 271 return true; |
161 } | 272 } |
162 | 273 |
163 bool PrintBackendWin::GetPrinterCapsAndDefaults( | 274 bool PrintBackendWin::GetPrinterCapsAndDefaults( |
164 const std::string& printer_name, | 275 const std::string& printer_name, |
165 PrinterCapsAndDefaults* printer_info) { | 276 PrinterCapsAndDefaults* printer_info) { |
166 ScopedXPSInitializer xps_initializer; | 277 ScopedXPSInitializer xps_initializer; |
167 if (!xps_initializer.initialized()) { | 278 if (!xps_initializer.initialized()) { |
168 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) | 279 // 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; | 357 ScopedPrinterHandle printer_handle; |
247 return printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str()); | 358 return printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str()); |
248 } | 359 } |
249 | 360 |
250 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( | 361 scoped_refptr<PrintBackend> PrintBackend::CreateInstance( |
251 const base::DictionaryValue* print_backend_settings) { | 362 const base::DictionaryValue* print_backend_settings) { |
252 return new PrintBackendWin; | 363 return new PrintBackendWin; |
253 } | 364 } |
254 | 365 |
255 } // namespace printing | 366 } // namespace printing |
OLD | NEW |