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/win_helper.h" | 5 #include "printing/backend/win_helper.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/file_version_info.h" | 9 #include "base/file_version_info.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 | 378 |
379 for (size_t i = 0; i < arraysize(info); ++i) { | 379 for (size_t i = 0; i < arraysize(info); ++i) { |
380 std::replace(info[i].begin(), info[i].end(), ';', ','); | 380 std::replace(info[i].begin(), info[i].end(), ';', ','); |
381 driver_info.append(info[i]); | 381 driver_info.append(info[i]); |
382 if (i < arraysize(info) - 1) | 382 if (i < arraysize(info) - 1) |
383 driver_info.append(";"); | 383 driver_info.append(";"); |
384 } | 384 } |
385 return driver_info; | 385 return driver_info; |
386 } | 386 } |
387 | 387 |
388 scoped_ptr<DEVMODE[]> XpsTicketToDevMode(const base::string16& printer_name, | 388 scoped_ptr<DEVMODE, base::FreeDeleter> XpsTicketToDevMode( |
389 const std::string& print_ticket) { | 389 const base::string16& printer_name, |
390 scoped_ptr<DEVMODE[]> scoped_dev_mode; | 390 const std::string& print_ticket) { |
| 391 scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode; |
391 printing::ScopedXPSInitializer xps_initializer; | 392 printing::ScopedXPSInitializer xps_initializer; |
392 if (!xps_initializer.initialized()) { | 393 if (!xps_initializer.initialized()) { |
393 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) | 394 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) |
394 return scoped_dev_mode.Pass(); | 395 return dev_mode.Pass(); |
395 } | 396 } |
396 | 397 |
397 printing::ScopedPrinterHandle printer; | 398 printing::ScopedPrinterHandle printer; |
398 if (!printer.OpenPrinter(printer_name.c_str())) | 399 if (!printer.OpenPrinter(printer_name.c_str())) |
399 return scoped_dev_mode.Pass(); | 400 return dev_mode.Pass(); |
400 | 401 |
401 base::win::ScopedComPtr<IStream> pt_stream; | 402 base::win::ScopedComPtr<IStream> pt_stream; |
402 HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive()); | 403 HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive()); |
403 if (FAILED(hr)) | 404 if (FAILED(hr)) |
404 return scoped_dev_mode.Pass(); | 405 return dev_mode.Pass(); |
405 | 406 |
406 HPTPROVIDER provider = NULL; | 407 HPTPROVIDER provider = NULL; |
407 hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider); | 408 hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider); |
408 if (SUCCEEDED(hr)) { | 409 if (SUCCEEDED(hr)) { |
409 ULONG size = 0; | 410 ULONG size = 0; |
410 DEVMODE* dm = NULL; | 411 DEVMODE* dm = NULL; |
411 // Use kPTJobScope, because kPTDocumentScope breaks duplex. | 412 // Use kPTJobScope, because kPTDocumentScope breaks duplex. |
412 hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider, | 413 hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider, |
413 pt_stream, | 414 pt_stream, |
414 kUserDefaultDevmode, | 415 kUserDefaultDevmode, |
415 kPTJobScope, | 416 kPTJobScope, |
416 &size, | 417 &size, |
417 &dm, | 418 &dm, |
418 NULL); | 419 NULL); |
419 if (SUCCEEDED(hr)) { | 420 if (SUCCEEDED(hr)) { |
420 // Correct DEVMODE using DocumentProperties. See documentation for | 421 // Correct DEVMODE using DocumentProperties. See documentation for |
421 // PTConvertPrintTicketToDevMode. | 422 // PTConvertPrintTicketToDevMode. |
422 scoped_dev_mode = CreateDevMode(printer, dm); | 423 dev_mode = CreateDevMode(printer, dm); |
423 printing::XPSModule::ReleaseMemory(dm); | 424 printing::XPSModule::ReleaseMemory(dm); |
424 } | 425 } |
425 printing::XPSModule::CloseProvider(provider); | 426 printing::XPSModule::CloseProvider(provider); |
426 } | 427 } |
427 return scoped_dev_mode.Pass(); | 428 return dev_mode.Pass(); |
428 } | 429 } |
429 | 430 |
430 scoped_ptr<DEVMODE[]> CreateDevModeWithColor(HANDLE printer, | 431 scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevModeWithColor( |
431 const base::string16& printer_name, | 432 HANDLE printer, |
432 bool color) { | 433 const base::string16& printer_name, |
433 scoped_ptr<DEVMODE[]> default = CreateDevMode(printer, NULL); | 434 bool color) { |
| 435 scoped_ptr<DEVMODE, base::FreeDeleter> default = CreateDevMode(printer, NULL); |
434 if (!default) | 436 if (!default) |
435 return default.Pass(); | 437 return default.Pass(); |
436 | 438 |
437 if ((default.get()->dmFields & DM_COLOR) && | 439 if ((default->dmFields & DM_COLOR) && |
438 ((default.get()->dmColor == DMCOLOR_COLOR) == color)) { | 440 ((default->dmColor == DMCOLOR_COLOR) == color)) { |
439 return default.Pass(); | 441 return default.Pass(); |
440 } | 442 } |
441 | 443 |
442 default.get()->dmFields |= DM_COLOR; | 444 default->dmFields |= DM_COLOR; |
443 default.get()->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; | 445 default->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; |
444 | 446 |
445 DriverInfo6 info_6; | 447 DriverInfo6 info_6; |
446 if (!info_6.Init(printer)) | 448 if (!info_6.Init(printer)) |
447 return default.Pass(); | 449 return default.Pass(); |
448 | 450 |
449 const DRIVER_INFO_6* p = info_6.get(); | 451 const DRIVER_INFO_6* p = info_6.get(); |
450 | 452 |
451 // Only HP known to have issues. | 453 // Only HP known to have issues. |
452 if (!p->pszMfgName || wcscmp(p->pszMfgName, L"HP") != 0) | 454 if (!p->pszMfgName || wcscmp(p->pszMfgName, L"HP") != 0) |
453 return default.Pass(); | 455 return default.Pass(); |
454 | 456 |
455 // Need XPS for this workaround. | 457 // Need XPS for this workaround. |
456 printing::ScopedXPSInitializer xps_initializer; | 458 printing::ScopedXPSInitializer xps_initializer; |
457 if (!xps_initializer.initialized()) | 459 if (!xps_initializer.initialized()) |
458 return default.Pass(); | 460 return default.Pass(); |
459 | 461 |
460 const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome; | 462 const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome; |
461 std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color); | 463 std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color); |
462 scoped_ptr<DEVMODE[]> ticket = printing::XpsTicketToDevMode(printer_name, | 464 scoped_ptr<DEVMODE, base::FreeDeleter> ticket = |
463 xps_ticket); | 465 printing::XpsTicketToDevMode(printer_name, xps_ticket); |
464 if (!ticket) | 466 if (!ticket) |
465 return default.Pass(); | 467 return default.Pass(); |
466 | 468 |
467 return ticket.Pass(); | 469 return ticket.Pass(); |
468 } | 470 } |
469 | 471 |
470 PRINTING_EXPORT scoped_ptr<DEVMODE[]> CreateDevMode(HANDLE printer, | 472 scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode(HANDLE printer, |
471 DEVMODE* in) { | 473 DEVMODE* in) { |
472 LONG buffer_size = DocumentProperties(NULL, printer, L"", NULL, NULL, 0); | 474 LONG buffer_size = DocumentProperties(NULL, printer, L"", NULL, NULL, 0); |
473 if (buffer_size <= 0) | 475 if (buffer_size < static_cast<int>(sizeof(DEVMODE))) |
474 return scoped_ptr<DEVMODE[]>(); | 476 return scoped_ptr<DEVMODE, base::FreeDeleter>(); |
475 CHECK_GE(buffer_size, static_cast<int>(sizeof(DEVMODE))); | 477 scoped_ptr<DEVMODE, base::FreeDeleter> out( |
476 scoped_ptr<DEVMODE[]> out( | 478 reinterpret_cast<DEVMODE*>(malloc(buffer_size))); |
477 reinterpret_cast<DEVMODE*>(new uint8[buffer_size])); | |
478 DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER; | 479 DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER; |
479 if (DocumentProperties(NULL, printer, L"", out.get(), in, flags) != IDOK) | 480 if (DocumentProperties(NULL, printer, L"", out.get(), in, flags) != IDOK) |
480 return scoped_ptr<DEVMODE[]>(); | 481 return scoped_ptr<DEVMODE, base::FreeDeleter>(); |
481 CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); | 482 CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); |
482 return out.Pass(); | 483 return out.Pass(); |
483 } | 484 } |
484 | 485 |
485 } // namespace printing | 486 } // namespace printing |
OLD | NEW |