summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/service/cloud_print/cdd_conversion_win.cc31
-rw-r--r--chrome/service/cloud_print/print_system_win.cc77
-rw-r--r--printing/backend/print_backend_win.cc21
-rw-r--r--printing/backend/win_helper.cc134
-rw-r--r--printing/backend/win_helper.h16
-rw-r--r--printing/printing_context_win.cc86
6 files changed, 215 insertions, 150 deletions
diff --git a/chrome/service/cloud_print/cdd_conversion_win.cc b/chrome/service/cloud_print/cdd_conversion_win.cc
index 4965309..f71ed64 100644
--- a/chrome/service/cloud_print/cdd_conversion_win.cc
+++ b/chrome/service/cloud_print/cdd_conversion_win.cc
@@ -17,6 +17,7 @@ bool IsValidCjt(const std::string& print_ticket_data) {
scoped_ptr<DEVMODE[]> CjtToDevMode(const base::string16& printer_name,
const std::string& print_ticket) {
+ using namespace cloud_devices::printer;
cloud_devices::CloudDeviceDescription description;
if (!description.InitFromString(print_ticket))
return scoped_ptr<DEVMODE[]>();
@@ -25,21 +26,22 @@ scoped_ptr<DEVMODE[]> CjtToDevMode(const base::string16& printer_name,
if (!printer.OpenPrinter(printer_name.c_str()))
return scoped_ptr<DEVMODE[]>();
- wchar_t* mutable_name = const_cast<wchar_t*>(printer_name.c_str());
- LONG buffer_size =
- DocumentProperties(NULL, printer, mutable_name, NULL, NULL, 0);
- if (buffer_size <= 0)
+ scoped_ptr<DEVMODE[]> scoped_dev_mode;
+ {
+ ColorTicketItem color;
+ if (color.LoadFrom(description)) {
+ bool is_color = color.value().type == STANDARD_COLOR;
+ scoped_dev_mode = CreateDevModeWithColor(printer, printer_name, is_color);
+ } else {
+ scoped_dev_mode = printing::CreateDevMode(printer, NULL);
+ }
+ }
+
+ if (!scoped_dev_mode)
return scoped_ptr<DEVMODE[]>();
- scoped_ptr<DEVMODE[]> scoped_dev_mode(
- reinterpret_cast<DEVMODE*>(new uint8[buffer_size]));
DEVMODE* dev_mode = scoped_dev_mode.get();
- if (DocumentProperties(NULL, printer, mutable_name, dev_mode, NULL,
- DM_OUT_BUFFER) != IDOK) {
- return scoped_ptr<DEVMODE[]>();
- }
- using namespace cloud_devices::printer;
ColorTicketItem color;
DuplexTicketItem duplex;
OrientationTicketItem orientation;
@@ -120,12 +122,7 @@ scoped_ptr<DEVMODE[]> CjtToDevMode(const base::string16& printer_name,
}
}
- if (DocumentProperties(NULL, printer, mutable_name, dev_mode, dev_mode,
- DM_OUT_BUFFER | DM_IN_BUFFER) != IDOK) {
- return scoped_ptr<DEVMODE[]>();
- }
-
- return scoped_dev_mode.Pass();
+ return printing::CreateDevMode(printer, dev_mode);
}
std::string CapabilitiesToCdd(
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc
index 765ea0f..82d1c72 100644
--- a/chrome/service/cloud_print/print_system_win.cc
+++ b/chrome/service/cloud_print/print_system_win.cc
@@ -27,73 +27,6 @@ namespace cloud_print {
namespace {
-HRESULT StreamFromPrintTicket(const std::string& print_ticket,
- IStream** stream) {
- DCHECK(stream);
- HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
- if (FAILED(hr)) {
- return hr;
- }
- ULONG bytes_written = 0;
- (*stream)->Write(print_ticket.c_str(), print_ticket.length(), &bytes_written);
- DCHECK(bytes_written == print_ticket.length());
- LARGE_INTEGER pos = {0};
- ULARGE_INTEGER new_pos = {0};
- (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos);
- return S_OK;
-}
-
-scoped_ptr<DEVMODE[]> XpsTicketToDevMode(const base::string16& printer_name,
- const std::string& print_ticket) {
- scoped_ptr<DEVMODE[]> scoped_dev_mode;
- printing::ScopedXPSInitializer xps_initializer;
- if (!xps_initializer.initialized()) {
- // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
- return scoped_dev_mode.Pass();
- }
-
- printing::ScopedPrinterHandle printer;
- if (!printer.OpenPrinter(printer_name.c_str()))
- return scoped_dev_mode.Pass();
-
- base::win::ScopedComPtr<IStream> pt_stream;
- HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive());
- if (FAILED(hr))
- return scoped_dev_mode.Pass();
-
- HPTPROVIDER provider = NULL;
- hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider);
- if (SUCCEEDED(hr)) {
- ULONG size = 0;
- DEVMODE* dm = NULL;
- // Use kPTJobScope, because kPTDocumentScope breaks duplex.
- hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider,
- pt_stream,
- kUserDefaultDevmode,
- kPTJobScope,
- &size,
- &dm,
- NULL);
- if (SUCCEEDED(hr)) {
- // Correct DEVMODE using DocumentProperties. See documentation for
- // PTConvertPrintTicketToDevMode.
- wchar_t* mutable_name = const_cast<wchar_t*>(printer_name.c_str());
- LONG buffer_size = DocumentProperties(NULL, printer, mutable_name, NULL,
- dm, DM_IN_BUFFER);
- if (buffer_size <= 0)
- return scoped_ptr<DEVMODE[]>();
- scoped_dev_mode.reset(reinterpret_cast<DEVMODE*>(new uint8[buffer_size]));
- if (DocumentProperties(NULL, printer, mutable_name, scoped_dev_mode.get(),
- dm, DM_OUT_BUFFER | DM_IN_BUFFER) != IDOK) {
- scoped_dev_mode.reset();
- }
- printing::XPSModule::ReleaseMemory(dm);
- }
- printing::XPSModule::CloseProvider(provider);
- }
- return scoped_dev_mode.Pass();
-}
-
class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate {
public:
PrintSystemWatcherWin()
@@ -331,16 +264,16 @@ class JobSpoolerWin : public PrintSystem::JobSpooler {
NOTREACHED();
return false;
}
+ base::string16 printer_wide = base::UTF8ToWide(printer_name);
last_page_printed_ = -1;
// We only support PDF and XPS documents for now.
if (print_data_mime_type == kContentTypePDF) {
scoped_ptr<DEVMODE[]> dev_mode;
if (print_ticket_mime_type == kContentTypeJSON) {
- dev_mode = CjtToDevMode(base::UTF8ToWide(printer_name), print_ticket);
+ dev_mode = CjtToDevMode(printer_wide, print_ticket);
} else {
DCHECK(print_ticket_mime_type == kContentTypeXML);
- dev_mode = XpsTicketToDevMode(base::UTF8ToWide(printer_name),
- print_ticket);
+ dev_mode = printing::XpsTicketToDevMode(printer_wide, print_ticket);
}
if (!dev_mode) {
@@ -348,8 +281,8 @@ class JobSpoolerWin : public PrintSystem::JobSpooler {
return false;
}
- HDC dc = CreateDC(L"WINSPOOL", base::UTF8ToWide(printer_name).c_str(),
- NULL, dev_mode.get());
+ HDC dc = CreateDC(L"WINSPOOL", printer_wide.c_str(), NULL,
+ dev_mode.get());
if (!dc) {
NOTREACHED();
return false;
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc
index aaf8da1..bb7989f 100644
--- a/printing/backend/print_backend_win.cc
+++ b/printing/backend/print_backend_win.cc
@@ -314,27 +314,18 @@ bool PrintBackendWin::GetPrinterCapsAndDefaults(
}
ScopedPrinterHandle printer_handle;
if (printer_handle.OpenPrinter(printer_name_wide.c_str())) {
- LONG devmode_size = DocumentProperties(
- NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()),
- NULL, NULL, 0);
- if (devmode_size <= 0)
+ scoped_ptr<DEVMODE[]> devmode_out(CreateDevMode(printer_handle, NULL));
+ if (!devmode_out)
return false;
- scoped_ptr<BYTE[]> devmode_out_buffer(new BYTE[devmode_size]);
- DEVMODE* devmode_out =
- reinterpret_cast<DEVMODE*>(devmode_out_buffer.get());
- DocumentProperties(
- NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()),
- devmode_out, NULL, DM_OUT_BUFFER);
base::win::ScopedComPtr<IStream> printer_defaults_stream;
hr = CreateStreamOnHGlobal(NULL, TRUE,
printer_defaults_stream.Receive());
DCHECK(SUCCEEDED(hr));
if (printer_defaults_stream) {
- hr = XPSModule::ConvertDevModeToPrintTicket(provider,
- devmode_size,
- devmode_out,
- kPTJobScope,
- printer_defaults_stream);
+ DWORD dm_size = devmode_out.get()->dmSize +
+ devmode_out.get()->dmDriverExtra;
+ hr = XPSModule::ConvertDevModeToPrintTicket(provider, dm_size,
+ devmode_out.get(), kPTJobScope, printer_defaults_stream);
DCHECK(SUCCEEDED(hr));
if (SUCCEEDED(hr)) {
hr = StreamOnHGlobalToString(printer_defaults_stream.get(),
diff --git a/printing/backend/win_helper.cc b/printing/backend/win_helper.cc
index f7b3310..8a66720 100644
--- a/printing/backend/win_helper.cc
+++ b/printing/backend/win_helper.cc
@@ -10,7 +10,11 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/win/scoped_comptr.h"
#include "printing/backend/print_backend.h"
#include "printing/backend/print_backend_consts.h"
#include "printing/backend/printing_info_win.h"
@@ -75,6 +79,42 @@ PTReleaseMemoryProc g_release_memory_proc = NULL;
PTCloseProviderProc g_close_provider_proc = NULL;
StartXpsPrintJobProc g_start_xps_print_job_proc = NULL;
+HRESULT StreamFromPrintTicket(const std::string& print_ticket,
+ IStream** stream) {
+ DCHECK(stream);
+ HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ ULONG bytes_written = 0;
+ (*stream)->Write(print_ticket.c_str(),
+ base::checked_cast<ULONG>(print_ticket.length()),
+ &bytes_written);
+ DCHECK(bytes_written == print_ticket.length());
+ LARGE_INTEGER pos = {0};
+ ULARGE_INTEGER new_pos = {0};
+ (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos);
+ return S_OK;
+}
+
+const char kXpsTicketTemplate[] =
+ "<?xml version='1.0' encoding='UTF-8'?>"
+ "<psf:PrintTicket "
+ "xmlns:psf='"
+ "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' "
+ "xmlns:psk="
+ "'http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' "
+ "version='1'>"
+ "<psf:Feature name='psk:PageOutputColor'>"
+ "<psf:Option name='psk:%s'>"
+ "</psf:Option>"
+ "</psf:Feature>"
+ "</psf:PrintTicket>";
+
+const char kXpsTicketColor[] = "Color";
+const char kXpsTicketMonochrome[] = "Monochrome";
+
+
} // namespace
@@ -345,4 +385,98 @@ std::string GetDriverInfo(HANDLE printer) {
return driver_info;
}
+scoped_ptr<DEVMODE[]> XpsTicketToDevMode(const base::string16& printer_name,
+ const std::string& print_ticket) {
+ scoped_ptr<DEVMODE[]> scoped_dev_mode;
+ printing::ScopedXPSInitializer xps_initializer;
+ if (!xps_initializer.initialized()) {
+ // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
+ return scoped_dev_mode.Pass();
+ }
+
+ printing::ScopedPrinterHandle printer;
+ if (!printer.OpenPrinter(printer_name.c_str()))
+ return scoped_dev_mode.Pass();
+
+ base::win::ScopedComPtr<IStream> pt_stream;
+ HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive());
+ if (FAILED(hr))
+ return scoped_dev_mode.Pass();
+
+ HPTPROVIDER provider = NULL;
+ hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider);
+ if (SUCCEEDED(hr)) {
+ ULONG size = 0;
+ DEVMODE* dm = NULL;
+ // Use kPTJobScope, because kPTDocumentScope breaks duplex.
+ hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider,
+ pt_stream,
+ kUserDefaultDevmode,
+ kPTJobScope,
+ &size,
+ &dm,
+ NULL);
+ if (SUCCEEDED(hr)) {
+ // Correct DEVMODE using DocumentProperties. See documentation for
+ // PTConvertPrintTicketToDevMode.
+ scoped_dev_mode = CreateDevMode(printer, dm);
+ printing::XPSModule::ReleaseMemory(dm);
+ }
+ printing::XPSModule::CloseProvider(provider);
+ }
+ return scoped_dev_mode.Pass();
+}
+
+scoped_ptr<DEVMODE[]> CreateDevModeWithColor(HANDLE printer,
+ const base::string16& printer_name,
+ bool color) {
+ scoped_ptr<DEVMODE[]> default = CreateDevMode(printer, NULL);
+ if (default && (default.get()->dmFields & DM_COLOR) &&
+ (default.get()->dmColor == DMCOLOR_COLOR) == color) {
+ return default.Pass();
+ }
+
+ default.get()->dmFields |= DM_COLOR;
+ default.get()->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME;
+
+ DriverInfo6 info_6;
+ if (!info_6.Init(printer))
+ return default.Pass();
+
+ const DRIVER_INFO_6* p = info_6.get();
+
+ // Only HP known to have issues.
+ if (wcscmp(p->pszMfgName, L"HP") != 0)
+ return default.Pass();
+
+ // Need XPS for this workaround.
+ printing::ScopedXPSInitializer xps_initializer;
+ if (!xps_initializer.initialized())
+ return default.Pass();
+
+ const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome;
+ std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color);
+ scoped_ptr<DEVMODE[]> ticket = printing::XpsTicketToDevMode(printer_name,
+ xps_ticket);
+ if (!ticket)
+ return default.Pass();
+
+ return ticket.Pass();
+}
+
+PRINTING_EXPORT scoped_ptr<DEVMODE[]> CreateDevMode(HANDLE printer,
+ DEVMODE* in) {
+ DWORD flags = in ? (DM_IN_BUFFER) : 0;
+ LONG buffer_size = DocumentProperties(NULL, printer, L"", NULL, in, flags);
+ if (buffer_size <= 0)
+ return scoped_ptr<DEVMODE[]>();
+ scoped_ptr<DEVMODE[]> out(
+ reinterpret_cast<DEVMODE*>(new uint8[buffer_size]));
+ flags |= DM_OUT_BUFFER;
+ if (DocumentProperties(NULL, printer, L"", out.get(), in, flags) != IDOK)
+ return scoped_ptr<DEVMODE[]>();
+ DCHECK_EQ(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra);
+ return out.Pass();
+}
+
} // namespace printing
diff --git a/printing/backend/win_helper.h b/printing/backend/win_helper.h
index db66bf8..9b998d7 100644
--- a/printing/backend/win_helper.h
+++ b/printing/backend/win_helper.h
@@ -12,6 +12,7 @@
#include <string>
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/win/scoped_handle.h"
#include "printing/printing_export.h"
@@ -169,6 +170,21 @@ PRINTING_EXPORT bool InitBasicPrinterInfo(HANDLE printer,
PRINTING_EXPORT std::string GetDriverInfo(HANDLE printer);
+PRINTING_EXPORT scoped_ptr<DEVMODE[]> XpsTicketToDevMode(
+ const base::string16& printer_name,
+ const std::string& print_ticket);
+
+// Creates default DEVMODE and sets color option. Some devices need special
+// workaround for color.
+PRINTING_EXPORT scoped_ptr<DEVMODE[]> CreateDevModeWithColor(
+ HANDLE printer,
+ const base::string16& printer_name,
+ bool color);
+
+// Creates new DEVMODE. If |in| is not NULL copy settings from there.
+PRINTING_EXPORT scoped_ptr<DEVMODE[]> CreateDevMode(HANDLE printer,
+ DEVMODE* in);
+
} // namespace printing
#endif // PRINTING_BACKEND_WIN_HELPER_H_
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 973ef9f..7c381ca 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -343,61 +343,55 @@ PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
// Make printer changes local to Chrome.
// See MSDN documentation regarding DocumentProperties.
- scoped_ptr<uint8[]> buffer;
- DEVMODE* dev_mode = NULL;
- LONG buffer_size = DocumentProperties(NULL, printer, device_name_wide,
- NULL, NULL, 0);
- if (buffer_size > 0) {
- buffer.reset(new uint8[buffer_size]);
- memset(buffer.get(), 0, buffer_size);
- if (DocumentProperties(NULL, printer, device_name_wide,
- reinterpret_cast<PDEVMODE>(buffer.get()), NULL,
- DM_OUT_BUFFER) == IDOK) {
- dev_mode = reinterpret_cast<PDEVMODE>(buffer.get());
- }
- }
- if (dev_mode == NULL) {
- buffer.reset();
+ scoped_ptr<DEVMODE[]> scoped_dev_mode =
+ CreateDevModeWithColor(printer, device_name_wide,
+ settings_.color() != GRAY);
+ if (!scoped_dev_mode)
return OnError();
- }
- if (settings_.color() == GRAY)
- dev_mode->dmColor = DMCOLOR_MONOCHROME;
- else
- dev_mode->dmColor = DMCOLOR_COLOR;
-
- dev_mode->dmCopies = std::max(settings_.copies(), 1);
- if (dev_mode->dmCopies > 1) { // do not change collate unless multiple copies
- dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE :
- DMCOLLATE_FALSE;
- }
- switch (settings_.duplex_mode()) {
- case LONG_EDGE:
- dev_mode->dmDuplex = DMDUP_VERTICAL;
- break;
- case SHORT_EDGE:
- dev_mode->dmDuplex = DMDUP_HORIZONTAL;
- break;
- case SIMPLEX:
- dev_mode->dmDuplex = DMDUP_SIMPLEX;
- break;
- default: // UNKNOWN_DUPLEX_MODE
- break;
- }
- dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE :
- DMORIENT_PORTRAIT;
+ {
+ DEVMODE* dev_mode = scoped_dev_mode.get();
+ dev_mode->dmCopies = std::max(settings_.copies(), 1);
+ if (dev_mode->dmCopies > 1) { // do not change unless multiple copies
+ dev_mode->dmFields |= DM_COPIES;
+ dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE :
+ DMCOLLATE_FALSE;
+ }
+
+ switch (settings_.duplex_mode()) {
+ case LONG_EDGE:
+ dev_mode->dmFields |= DM_DUPLEX;
+ dev_mode->dmDuplex = DMDUP_VERTICAL;
+ break;
+ case SHORT_EDGE:
+ dev_mode->dmFields |= DM_DUPLEX;
+ dev_mode->dmDuplex = DMDUP_HORIZONTAL;
+ break;
+ case SIMPLEX:
+ dev_mode->dmFields |= DM_DUPLEX;
+ dev_mode->dmDuplex = DMDUP_SIMPLEX;
+ break;
+ default: // UNKNOWN_DUPLEX_MODE
+ break;
+ }
+
+ dev_mode->dmFields |= DM_ORIENTATION;
+ dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE :
+ DMORIENT_PORTRAIT;
+ }
// Update data using DocumentProperties.
- if (DocumentProperties(NULL, printer, device_name_wide, dev_mode, dev_mode,
- DM_IN_BUFFER | DM_OUT_BUFFER) != IDOK) {
+ scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get());
+ if (!scoped_dev_mode)
return OnError();
- }
// Set printer then refresh printer settings.
- if (!AllocateContext(settings_.device_name(), dev_mode, &context_)) {
+ if (!AllocateContext(settings_.device_name(), scoped_dev_mode.get(),
+ &context_)) {
return OnError();
}
- PrintSettingsInitializerWin::InitPrintSettings(context_, *dev_mode,
+ PrintSettingsInitializerWin::InitPrintSettings(context_,
+ *scoped_dev_mode.get(),
&settings_);
return OK;
}