| 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 |