diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 19:15:46 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-13 19:15:46 +0000 |
commit | d825462fe6672a5c69a62b4827b6eca1059bb984 (patch) | |
tree | b90040d6eb399e6e5a3dcaf1bf63b6a2e52508b1 /printing | |
parent | e485920367d9a6a576a788ac84568ee474f5396a (diff) | |
download | chromium_src-d825462fe6672a5c69a62b4827b6eca1059bb984.zip chromium_src-d825462fe6672a5c69a62b4827b6eca1059bb984.tar.gz chromium_src-d825462fe6672a5c69a62b4827b6eca1059bb984.tar.bz2 |
Win32: Print the right number of pages.
BUG=48392
TEST=included.
Review URL: http://codereview.chromium.org/3113012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56063 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'printing')
-rw-r--r-- | printing/printing_context.h | 28 | ||||
-rw-r--r-- | printing/printing_context_win.cc | 56 | ||||
-rw-r--r-- | printing/printing_context_win_unittest.cc | 86 |
3 files changed, 136 insertions, 34 deletions
diff --git a/printing/printing_context.h b/printing/printing_context.h index ec8a7d8..8996fa9 100644 --- a/printing/printing_context.h +++ b/printing/printing_context.h @@ -16,6 +16,7 @@ #include "base/basictypes.h" #include "base/logging.h" +#include "base/scoped_ptr.h" #include "gfx/native_widget_types.h" #include "printing/print_settings.h" @@ -50,6 +51,24 @@ class PrintingContext { Result AskUserForSettings(gfx::NativeView parent_view, int max_pages, bool has_selection); +#if defined(OS_WIN) && defined(UNIT_TEST) + // Sets a fake PrintDlgEx function pointer in tests. + void SetPrintDialog(HRESULT (__stdcall *print_dialog_func)(LPPRINTDLGEX)) { + print_dialog_func_ = print_dialog_func; + } +#endif + +#if defined(OS_WIN) + // Allocates the HDC for a specific DEVMODE. + static bool AllocateContext(const std::wstring& printer_name, + const DEVMODE* dev_mode, + gfx::NativeDrawingContext* context); + + // Retrieves the content of a GetPrinter call. + static void GetPrinterHelper(HANDLE printer, int level, + scoped_array<uint8>* buffer); +#endif + // Selects the user's default printer and format. Updates the context with the // default device settings. Result UseDefaultSettings(); @@ -127,14 +146,9 @@ class PrintingContext { bool GetPrinterSettings(HANDLE printer, const std::wstring& device_name); - // Allocates the HDC for a specific DEVMODE. - bool AllocateContext(const std::wstring& printer_name, - const DEVMODE* dev_mode); - // Parses the result of a PRINTDLGEX result. Result ParseDialogResultEx(const PRINTDLGEX& dialog_options); Result ParseDialogResult(const PRINTDLG& dialog_options); - #elif defined(OS_MACOSX) // Read the settings from the given NSPrintInfo (and cache it for later use). void ParsePrintInfo(NSPrintInfo* print_info); @@ -161,6 +175,10 @@ class PrintingContext { #if defined(OS_WIN) // The dialog box for the time it is shown. volatile HWND dialog_box_; + + // Function pointer that defaults to PrintDlgEx. It can be changed using + // SetPrintDialog() in tests. + HRESULT (__stdcall *print_dialog_func_)(LPPRINTDLGEX); #endif // The dialog box has been dismissed. diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc index 6215cd4..188f031 100644 --- a/printing/printing_context_win.cc +++ b/printing/printing_context_win.cc @@ -16,23 +16,6 @@ using base::Time; -namespace { - -// Retrieves the content of a GetPrinter call. -void GetPrinterHelper(HANDLE printer, int level, scoped_array<uint8>* buffer) { - DWORD buf_size = 0; - GetPrinter(printer, level, NULL, 0, &buf_size); - if (buf_size) { - buffer->reset(new uint8[buf_size]); - memset(buffer->get(), 0, buf_size); - if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) { - buffer->reset(); - } - } -} - -} // namespace - namespace printing { class PrintingContext::CallbackHandler : public IPrintDialogCallback, @@ -144,7 +127,8 @@ PrintingContext::PrintingContext() dialog_box_(NULL), dialog_box_dismissed_(false), in_print_job_(false), - abort_printing_(false) { + abort_printing_(false), + print_dialog_func_(&PrintDlgEx) { } PrintingContext::~PrintingContext() { @@ -203,7 +187,7 @@ PrintingContext::Result PrintingContext::AskUserForSettings( } { - if (PrintDlgEx(&dialog_options) != S_OK) { + if ((*print_dialog_func_)(&dialog_options) != S_OK) { ResetSettings(); return FAILED; } @@ -438,7 +422,7 @@ bool PrintingContext::GetPrinterSettings(HANDLE printer, if (buffer.get()) { PRINTER_INFO_9* info_9 = reinterpret_cast<PRINTER_INFO_9*>(buffer.get()); if (info_9->pDevMode != NULL) { - if (!AllocateContext(device_name, info_9->pDevMode)) { + if (!AllocateContext(device_name, info_9->pDevMode, &context_)) { ResetSettings(); return false; } @@ -452,7 +436,7 @@ bool PrintingContext::GetPrinterSettings(HANDLE printer, if (buffer.get()) { PRINTER_INFO_8* info_8 = reinterpret_cast<PRINTER_INFO_8*>(buffer.get()); if (info_8->pDevMode != NULL) { - if (!AllocateContext(device_name, info_8->pDevMode)) { + if (!AllocateContext(device_name, info_8->pDevMode, &context_)) { ResetSettings(); return false; } @@ -467,7 +451,7 @@ bool PrintingContext::GetPrinterSettings(HANDLE printer, if (buffer.get()) { PRINTER_INFO_2* info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get()); if (info_2->pDevMode != NULL) { - if (!AllocateContext(device_name, info_2->pDevMode)) { + if (!AllocateContext(device_name, info_2->pDevMode, &context_)) { ResetSettings(); return false; } @@ -480,11 +464,13 @@ bool PrintingContext::GetPrinterSettings(HANDLE printer, return false; } +// static bool PrintingContext::AllocateContext(const std::wstring& printer_name, - const DEVMODE* dev_mode) { - context_ = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); - DCHECK(context_); - return context_ != NULL; + const DEVMODE* dev_mode, + gfx::NativeDrawingContext* context) { + *context = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode); + DCHECK(*context); + return *context != NULL; } PrintingContext::Result PrintingContext::ParseDialogResultEx( @@ -530,8 +516,8 @@ PrintingContext::Result PrintingContext::ParseDialogResultEx( } success = InitializeSettings(*dev_mode, device_name, - dialog_options.lpPageRanges, - dialog_options.nPageRanges, + page_ranges, + num_page_ranges, print_selection_only); } @@ -616,4 +602,18 @@ PrintingContext::Result PrintingContext::ParseDialogResult( return context_ ? OK : FAILED; } +// static +void PrintingContext::GetPrinterHelper(HANDLE printer, int level, + scoped_array<uint8>* buffer) { + DWORD buf_size = 0; + GetPrinter(printer, level, NULL, 0, &buf_size); + if (buf_size) { + buffer->reset(new uint8[buf_size]); + memset(buffer->get(), 0, buf_size); + if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) { + buffer->reset(); + } + } +} + } // namespace printing diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc index 9e19e3b..c2e377b 100644 --- a/printing/printing_context_win_unittest.cc +++ b/printing/printing_context_win_unittest.cc @@ -12,13 +12,88 @@ class PrintingContextTest : public PrintingTest<testing::Test> { }; +// This is a fake PrintDlgEx implementation that sets the right fields in +// |lppd| to trigger a bug in older revisions of PrintingContext. +HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) { + // The interesting bits: + // Pretend the user hit print + lppd->dwResultAction = PD_RESULT_PRINT; + + // Pretend the page range is 1-5, but since lppd->Flags does not have + // PD_SELECTION set, this really shouldn't matter. + lppd->nPageRanges = 1; + lppd->lpPageRanges = new PRINTPAGERANGE[1]; + lppd->lpPageRanges[0].nFromPage = 1; + lppd->lpPageRanges[0].nToPage = 5; + + // Painful paperwork. + std::wstring printer_name = PrintingContextTest::GetDefaultPrinter(); + HANDLE printer; + if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL)) + return E_FAIL; + + scoped_array<uint8> buffer; + DEVMODE* dev_mode = NULL; + PRINTER_INFO_2* info_2 = NULL; + + printing::PrintingContext::GetPrinterHelper(printer, 2, &buffer); + if (buffer.get()) { + info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get()); + if (info_2->pDevMode != NULL) + dev_mode = info_2->pDevMode; + } + if (!dev_mode) + return E_FAIL; + + if (!printing::PrintingContext::AllocateContext(printer_name, dev_mode, + &lppd->hDC)) { + return E_FAIL; + } + + size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra; + lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size); + if (!lppd->hDevMode) + return E_FAIL; + void* dev_mode_ptr = GlobalLock(lppd->hDevMode); + if (!dev_mode_ptr) + return E_FAIL; + memcpy(dev_mode_ptr, dev_mode, dev_mode_size); + GlobalUnlock(lppd->hDevMode); + + size_t driver_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pDriverName); + size_t printer_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPrinterName); + size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPortName); + size_t dev_names_size = sizeof(DEVNAMES) + driver_size + printer_size + + port_size; + lppd->hDevNames = GlobalAlloc(GHND, dev_names_size); + if (!lppd->hDevNames) + return E_FAIL; + void* dev_names_ptr = GlobalLock(lppd->hDevNames); + if (!dev_names_ptr) + return E_FAIL; + DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr); + dev_names->wDefault = 1; + dev_names->wDriverOffset = sizeof(DEVNAMES); + memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset, + info_2->pDriverName, driver_size); + dev_names->wDeviceOffset = dev_names->wDriverOffset + driver_size; + memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset, + info_2->pPrinterName, printer_size); + dev_names->wOutputOffset = dev_names->wDeviceOffset + printer_size; + memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset, + info_2->pPortName, port_size); + GlobalUnlock(lppd->hDevNames); + + return S_OK; +} + TEST_F(PrintingContextTest, Base) { printing::PrintSettings settings; settings.set_device_name(GetDefaultPrinter()); // Initialize it. printing::PrintingContext context; - EXPECT_EQ(context.InitWithSettings(settings), printing::PrintingContext::OK); + EXPECT_EQ(printing::PrintingContext::OK, context.InitWithSettings(settings)); // The print may lie to use and may not support world transformation. // Verify right now. @@ -26,3 +101,12 @@ TEST_F(PrintingContextTest, Base) { EXPECT_TRUE(SetWorldTransform(context.context(), &random_matrix)); EXPECT_TRUE(ModifyWorldTransform(context.context(), NULL, MWT_IDENTITY)); } + +TEST_F(PrintingContextTest, PrintAll) { + printing::PrintingContext context; + context.SetPrintDialog(&PrintDlgExMock); + ASSERT_EQ(printing::PrintingContext::OK, + context.AskUserForSettings(NULL, 123, false)); + printing::PrintSettings settings = context.settings(); + EXPECT_EQ(settings.ranges.size(), 0); +}
\ No newline at end of file |