blob: 94108cd14e5559b8064b5fd2b7ada23afd660b05 [file] [log] [blame]
[email protected]d0767cb542009-10-08 17:38:301// Copyright (c) 2009 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]8ff1d422009-07-07 21:31:395#include "printing/printing_context.h"
initial.commit09911bf2008-07-26 23:55:296
7#include <winspool.h>
8
9#include "base/file_util.h"
[email protected]d0767cb542009-10-08 17:38:3010#include "base/i18n/file_util_icu.h"
[email protected]260d1572009-10-09 18:50:3511#include "base/i18n/time_formatting.h"
[email protected]dcccb942009-02-01 18:23:0012#include "base/message_loop.h"
13#include "base/time.h"
[email protected]d9d42992010-09-13 19:39:1914#include "base/utf_string_conversions.h"
[email protected]8ff1d422009-07-07 21:31:3915#include "printing/printed_document.h"
[email protected]c399a8a2008-11-22 19:38:0016#include "skia/ext/platform_device_win.h"
initial.commit09911bf2008-07-26 23:55:2917
[email protected]e1acf6f2008-10-27 20:43:3318using base::Time;
19
initial.commit09911bf2008-07-26 23:55:2920namespace printing {
21
[email protected]5930cb62009-12-08 02:04:2222class PrintingContext::CallbackHandler : public IPrintDialogCallback,
23 public IObjectWithSite {
initial.commit09911bf2008-07-26 23:55:2924 public:
25 CallbackHandler(PrintingContext& owner, HWND owner_hwnd)
26 : owner_(owner),
27 owner_hwnd_(owner_hwnd),
28 services_(NULL) {
29 }
30
31 ~CallbackHandler() {
32 if (services_)
33 services_->Release();
34 }
35
36 IUnknown* ToIUnknown() {
37 return static_cast<IUnknown*>(static_cast<IPrintDialogCallback*>(this));
38 }
39
40 // IUnknown
41 virtual HRESULT WINAPI QueryInterface(REFIID riid, void**object) {
42 if (riid == IID_IUnknown) {
43 *object = ToIUnknown();
44 } else if (riid == IID_IPrintDialogCallback) {
45 *object = static_cast<IPrintDialogCallback*>(this);
46 } else if (riid == IID_IObjectWithSite) {
47 *object = static_cast<IObjectWithSite*>(this);
48 } else {
49 return E_NOINTERFACE;
50 }
51 return S_OK;
52 }
53
54 // No real ref counting.
55 virtual ULONG WINAPI AddRef() {
56 return 1;
57 }
58 virtual ULONG WINAPI Release() {
59 return 1;
60 }
61
62 // IPrintDialogCallback methods
63 virtual HRESULT WINAPI InitDone() {
64 return S_OK;
65 }
66
67 virtual HRESULT WINAPI SelectionChange() {
68 if (services_) {
69 // TODO(maruel): Get the devmode for the new printer with
70 // services_->GetCurrentDevMode(&devmode, &size), send that information
71 // back to our client and continue. The client needs to recalculate the
72 // number of rendered pages and send back this information here.
73 }
74 return S_OK;
75 }
76
77 virtual HRESULT WINAPI HandleMessage(HWND dialog,
78 UINT message,
79 WPARAM wparam,
80 LPARAM lparam,
81 LRESULT* result) {
82 // Cheap way to retrieve the window handle.
83 if (!owner_.dialog_box_) {
84 // The handle we receive is the one of the groupbox in the General tab. We
85 // need to get the grand-father to get the dialog box handle.
86 owner_.dialog_box_ = GetAncestor(dialog, GA_ROOT);
87 // Trick to enable the owner window. This can cause issues with navigation
88 // events so it may have to be disabled if we don't fix the side-effects.
89 EnableWindow(owner_hwnd_, TRUE);
90 }
91 return S_FALSE;
92 }
93
94 virtual HRESULT WINAPI SetSite(IUnknown* site) {
95 if (!site) {
96 DCHECK(services_);
97 services_->Release();
98 services_ = NULL;
99 // The dialog box is destroying, PrintJob::Worker don't need the handle
100 // anymore.
101 owner_.dialog_box_ = NULL;
102 } else {
103 DCHECK(services_ == NULL);
104 HRESULT hr = site->QueryInterface(IID_IPrintDialogServices,
105 reinterpret_cast<void**>(&services_));
106 DCHECK(SUCCEEDED(hr));
107 }
108 return S_OK;
109 }
110
111 virtual HRESULT WINAPI GetSite(REFIID riid, void** site) {
112 return E_NOTIMPL;
113 }
114
115 private:
116 PrintingContext& owner_;
117 HWND owner_hwnd_;
118 IPrintDialogServices* services_;
119
[email protected]5930cb62009-12-08 02:04:22120 DISALLOW_COPY_AND_ASSIGN(CallbackHandler);
initial.commit09911bf2008-07-26 23:55:29121};
122
123PrintingContext::PrintingContext()
[email protected]b75dca82009-10-13 18:46:21124 : context_(NULL),
[email protected]0ae80b892008-10-15 17:56:40125#ifndef NDEBUG
initial.commit09911bf2008-07-26 23:55:29126 page_number_(-1),
127#endif
128 dialog_box_(NULL),
129 dialog_box_dismissed_(false),
[email protected]8ff1d422009-07-07 21:31:39130 in_print_job_(false),
[email protected]d8254622010-08-13 19:15:46131 abort_printing_(false),
132 print_dialog_func_(&PrintDlgEx) {
initial.commit09911bf2008-07-26 23:55:29133}
134
135PrintingContext::~PrintingContext() {
136 ResetSettings();
137}
138
[email protected]b7191422010-09-21 19:18:05139void PrintingContext::AskUserForSettings(HWND view,
140 int max_pages,
141 bool has_selection,
142 PrintSettingsCallback* callback) {
initial.commit09911bf2008-07-26 23:55:29143 DCHECK(!in_print_job_);
144 dialog_box_dismissed_ = false;
[email protected]fc7904622010-05-12 19:26:40145
146 HWND window;
147 if (!view || !IsWindow(view)) {
148 // TODO(maruel): bug 1214347 Get the right browser window instead.
149 window = GetDesktopWindow();
150 } else {
151 window = GetAncestor(view, GA_ROOTOWNER);
152 }
153 DCHECK(window);
154
initial.commit09911bf2008-07-26 23:55:29155 // Show the OS-dependent dialog box.
156 // If the user press
157 // - OK, the settings are reset and reinitialized with the new settings. OK is
158 // returned.
159 // - Apply then Cancel, the settings are reset and reinitialized with the new
160 // settings. CANCEL is returned.
161 // - Cancel, the settings are not changed, the previous setting, if it was
162 // initialized before, are kept. CANCEL is returned.
163 // On failure, the settings are reset and FAILED is returned.
164 PRINTDLGEX dialog_options = { sizeof(PRINTDLGEX) };
165 dialog_options.hwndOwner = window;
[email protected]c8ad40c2009-06-08 17:05:21166 // Disable options we don't support currently.
initial.commit09911bf2008-07-26 23:55:29167 // TODO(maruel): Reuse the previously loaded settings!
168 dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE |
[email protected]c8ad40c2009-06-08 17:05:21169 PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE;
170 if (!has_selection)
171 dialog_options.Flags |= PD_NOSELECTION;
172
initial.commit09911bf2008-07-26 23:55:29173 PRINTPAGERANGE ranges[32];
174 dialog_options.nStartPage = START_PAGE_GENERAL;
175 if (max_pages) {
176 // Default initialize to print all the pages.
177 memset(ranges, 0, sizeof(ranges));
178 ranges[0].nFromPage = 1;
179 ranges[0].nToPage = max_pages;
180 dialog_options.nPageRanges = 1;
181 dialog_options.nMaxPageRanges = arraysize(ranges);
[email protected]3a0e4a32009-06-09 19:07:05182 dialog_options.nMinPage = 1;
initial.commit09911bf2008-07-26 23:55:29183 dialog_options.nMaxPage = max_pages;
184 dialog_options.lpPageRanges = ranges;
185 } else {
186 // No need to bother, we don't know how many pages are available.
187 dialog_options.Flags |= PD_NOPAGENUMS;
188 }
189
190 {
[email protected]d8254622010-08-13 19:15:46191 if ((*print_dialog_func_)(&dialog_options) != S_OK) {
initial.commit09911bf2008-07-26 23:55:29192 ResetSettings();
[email protected]b7191422010-09-21 19:18:05193 callback->Run(FAILED);
initial.commit09911bf2008-07-26 23:55:29194 }
195 }
196 // TODO(maruel): Support PD_PRINTTOFILE.
[email protected]b7191422010-09-21 19:18:05197 callback->Run(ParseDialogResultEx(dialog_options));
initial.commit09911bf2008-07-26 23:55:29198}
199
200PrintingContext::Result PrintingContext::UseDefaultSettings() {
201 DCHECK(!in_print_job_);
202
203 PRINTDLG dialog_options = { sizeof(PRINTDLG) };
204 dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
205 if (PrintDlg(&dialog_options) == 0) {
206 ResetSettings();
207 return FAILED;
208 }
209 return ParseDialogResult(dialog_options);
210}
211
212PrintingContext::Result PrintingContext::InitWithSettings(
213 const PrintSettings& settings) {
214 DCHECK(!in_print_job_);
215 settings_ = settings;
216 // TODO(maruel): settings_->ToDEVMODE()
217 HANDLE printer;
218 if (!OpenPrinter(const_cast<wchar_t*>(settings_.device_name().c_str()),
219 &printer,
220 NULL))
221 return FAILED;
222
223 Result status = OK;
224
225 if (!GetPrinterSettings(printer, settings_.device_name()))
226 status = FAILED;
227
228 // Close the printer after retrieving the context.
229 ClosePrinter(printer);
230
231 if (status != OK)
232 ResetSettings();
233 return status;
234}
235
236void PrintingContext::ResetSettings() {
[email protected]b75dca82009-10-13 18:46:21237 if (context_ != NULL) {
238 DeleteDC(context_);
239 context_ = NULL;
initial.commit09911bf2008-07-26 23:55:29240 }
241 settings_.Clear();
242 in_print_job_ = false;
243
[email protected]0ae80b892008-10-15 17:56:40244#ifndef NDEBUG
initial.commit09911bf2008-07-26 23:55:29245 page_number_ = -1;
246#endif
247}
248
249PrintingContext::Result PrintingContext::NewDocument(
[email protected]d9d42992010-09-13 19:39:19250 const string16& document_name) {
initial.commit09911bf2008-07-26 23:55:29251 DCHECK(!in_print_job_);
[email protected]b75dca82009-10-13 18:46:21252 if (!context_)
[email protected]c8ad40c2009-06-08 17:05:21253 return OnError();
initial.commit09911bf2008-07-26 23:55:29254
255 // Set the flag used by the AbortPrintJob dialog procedure.
256 abort_printing_ = false;
257
258 in_print_job_ = true;
259
260 // Register the application's AbortProc function with GDI.
[email protected]b75dca82009-10-13 18:46:21261 if (SP_ERROR == SetAbortProc(context_, &AbortProc))
[email protected]c8ad40c2009-06-08 17:05:21262 return OnError();
initial.commit09911bf2008-07-26 23:55:29263
264 DOCINFO di = { sizeof(DOCINFO) };
[email protected]d9d42992010-09-13 19:39:19265 di.lpszDocName = UTF16ToWide(document_name).c_str();
initial.commit09911bf2008-07-26 23:55:29266
267 // Is there a debug dump directory specified? If so, force to print to a file.
[email protected]d9d42992010-09-13 19:39:19268 FilePath debug_dump_path = PrintedDocument::debug_dump_path();
initial.commit09911bf2008-07-26 23:55:29269 if (!debug_dump_path.empty()) {
270 // Create a filename.
271 std::wstring filename;
272 Time now(Time::Now());
[email protected]5cca3a52008-08-19 22:35:29273 filename = base::TimeFormatShortDateNumeric(now);
initial.commit09911bf2008-07-26 23:55:29274 filename += L"_";
[email protected]5cca3a52008-08-19 22:35:29275 filename += base::TimeFormatTimeOfDay(now);
initial.commit09911bf2008-07-26 23:55:29276 filename += L"_";
[email protected]d9d42992010-09-13 19:39:19277 filename += UTF16ToWide(document_name);
initial.commit09911bf2008-07-26 23:55:29278 filename += L"_";
279 filename += L"buffer.prn";
[email protected]de2943352009-10-22 23:06:12280 file_util::ReplaceIllegalCharactersInPath(&filename, '_');
[email protected]d9d42992010-09-13 19:39:19281 debug_dump_path.Append(filename);
282 di.lpszOutput = debug_dump_path.value().c_str();
initial.commit09911bf2008-07-26 23:55:29283 }
284
[email protected]daee4972009-07-09 14:28:24285 // No message loop running in unit tests.
286 DCHECK(!MessageLoop::current() ? true :
287 !MessageLoop::current()->NestableTasksAllowed());
288
initial.commit09911bf2008-07-26 23:55:29289 // Begin a print job by calling the StartDoc function.
290 // NOTE: StartDoc() starts a message loop. That causes a lot of problems with
291 // IPC. Make sure recursive task processing is disabled.
[email protected]b75dca82009-10-13 18:46:21292 if (StartDoc(context_, &di) <= 0)
[email protected]c8ad40c2009-06-08 17:05:21293 return OnError();
initial.commit09911bf2008-07-26 23:55:29294
[email protected]0ae80b892008-10-15 17:56:40295#ifndef NDEBUG
initial.commit09911bf2008-07-26 23:55:29296 page_number_ = 0;
297#endif
298 return OK;
299}
300
301PrintingContext::Result PrintingContext::NewPage() {
302 if (abort_printing_)
303 return CANCEL;
[email protected]3b52c982010-09-27 20:40:36304
305 DCHECK(context_);
initial.commit09911bf2008-07-26 23:55:29306 DCHECK(in_print_job_);
307
308 // Inform the driver that the application is about to begin sending data.
[email protected]b75dca82009-10-13 18:46:21309 if (StartPage(context_) <= 0)
[email protected]c8ad40c2009-06-08 17:05:21310 return OnError();
initial.commit09911bf2008-07-26 23:55:29311
[email protected]0ae80b892008-10-15 17:56:40312#ifndef NDEBUG
initial.commit09911bf2008-07-26 23:55:29313 ++page_number_;
314#endif
315
316 return OK;
317}
318
319PrintingContext::Result PrintingContext::PageDone() {
320 if (abort_printing_)
321 return CANCEL;
322 DCHECK(in_print_job_);
323
[email protected]b75dca82009-10-13 18:46:21324 if (EndPage(context_) <= 0)
[email protected]c8ad40c2009-06-08 17:05:21325 return OnError();
initial.commit09911bf2008-07-26 23:55:29326 return OK;
327}
328
329PrintingContext::Result PrintingContext::DocumentDone() {
330 if (abort_printing_)
331 return CANCEL;
332 DCHECK(in_print_job_);
[email protected]60745412010-09-27 23:46:07333 DCHECK(context_);
initial.commit09911bf2008-07-26 23:55:29334
335 // Inform the driver that document has ended.
[email protected]b75dca82009-10-13 18:46:21336 if (EndDoc(context_) <= 0)
[email protected]c8ad40c2009-06-08 17:05:21337 return OnError();
initial.commit09911bf2008-07-26 23:55:29338
339 ResetSettings();
340 return OK;
341}
342
343void PrintingContext::Cancel() {
344 abort_printing_ = true;
345 in_print_job_ = false;
[email protected]b75dca82009-10-13 18:46:21346 if (context_)
347 CancelDC(context_);
initial.commit09911bf2008-07-26 23:55:29348 DismissDialog();
349}
350
351void PrintingContext::DismissDialog() {
352 if (dialog_box_) {
353 DestroyWindow(dialog_box_);
354 dialog_box_dismissed_ = true;
355 }
356}
357
[email protected]c8ad40c2009-06-08 17:05:21358PrintingContext::Result PrintingContext::OnError() {
[email protected]b75dca82009-10-13 18:46:21359 // This will close context_ and clear settings_.
initial.commit09911bf2008-07-26 23:55:29360 ResetSettings();
361 return abort_printing_ ? CANCEL : FAILED;
362}
363
364// static
365BOOL PrintingContext::AbortProc(HDC hdc, int nCode) {
366 if (nCode) {
367 // TODO(maruel): Need a way to find the right instance to set. Should
368 // leverage PrintJobManager here?
369 // abort_printing_ = true;
370 }
371 return true;
372}
373
374bool PrintingContext::InitializeSettings(const DEVMODE& dev_mode,
375 const std::wstring& new_device_name,
376 const PRINTPAGERANGE* ranges,
[email protected]c8ad40c2009-06-08 17:05:21377 int number_ranges,
378 bool selection_only) {
[email protected]b75dca82009-10-13 18:46:21379 skia::PlatformDevice::InitializeDC(context_);
380 DCHECK(GetDeviceCaps(context_, CLIPCAPS));
381 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB);
382 DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64);
initial.commit09911bf2008-07-26 23:55:29383 // Some printers don't advertise these.
[email protected]b75dca82009-10-13 18:46:21384 // DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING);
385 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA);
386 // DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA);
initial.commit09911bf2008-07-26 23:55:29387
388 // StretchDIBits() support is needed for printing.
[email protected]b75dca82009-10-13 18:46:21389 if (!(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB) ||
390 !(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64)) {
initial.commit09911bf2008-07-26 23:55:29391 NOTREACHED();
392 ResetSettings();
393 return false;
394 }
395
396 DCHECK(!in_print_job_);
[email protected]b75dca82009-10-13 18:46:21397 DCHECK(context_);
initial.commit09911bf2008-07-26 23:55:29398 PageRanges ranges_vector;
[email protected]82270452009-06-19 15:58:01399 if (!selection_only) {
400 // Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
401 ranges_vector.reserve(number_ranges);
402 for (int i = 0; i < number_ranges; ++i) {
403 PageRange range;
404 // Transfer from 1-based to 0-based.
405 range.from = ranges[i].nFromPage - 1;
406 range.to = ranges[i].nToPage - 1;
407 ranges_vector.push_back(range);
408 }
initial.commit09911bf2008-07-26 23:55:29409 }
[email protected]b75dca82009-10-13 18:46:21410 settings_.Init(context_,
[email protected]c8ad40c2009-06-08 17:05:21411 dev_mode,
412 ranges_vector,
413 new_device_name,
414 selection_only);
initial.commit09911bf2008-07-26 23:55:29415 return true;
416}
417
418bool PrintingContext::GetPrinterSettings(HANDLE printer,
419 const std::wstring& device_name) {
420 DCHECK(!in_print_job_);
421 scoped_array<uint8> buffer;
422
423 // A PRINTER_INFO_9 structure specifying the per-user default printer
424 // settings.
425 GetPrinterHelper(printer, 9, &buffer);
426 if (buffer.get()) {
427 PRINTER_INFO_9* info_9 = reinterpret_cast<PRINTER_INFO_9*>(buffer.get());
428 if (info_9->pDevMode != NULL) {
[email protected]d8254622010-08-13 19:15:46429 if (!AllocateContext(device_name, info_9->pDevMode, &context_)) {
initial.commit09911bf2008-07-26 23:55:29430 ResetSettings();
431 return false;
432 }
[email protected]c8ad40c2009-06-08 17:05:21433 return InitializeSettings(*info_9->pDevMode, device_name, NULL, 0, false);
initial.commit09911bf2008-07-26 23:55:29434 }
435 buffer.reset();
436 }
437
438 // A PRINTER_INFO_8 structure specifying the global default printer settings.
439 GetPrinterHelper(printer, 8, &buffer);
440 if (buffer.get()) {
441 PRINTER_INFO_8* info_8 = reinterpret_cast<PRINTER_INFO_8*>(buffer.get());
442 if (info_8->pDevMode != NULL) {
[email protected]d8254622010-08-13 19:15:46443 if (!AllocateContext(device_name, info_8->pDevMode, &context_)) {
initial.commit09911bf2008-07-26 23:55:29444 ResetSettings();
445 return false;
446 }
[email protected]c8ad40c2009-06-08 17:05:21447 return InitializeSettings(*info_8->pDevMode, device_name, NULL, 0, false);
initial.commit09911bf2008-07-26 23:55:29448 }
449 buffer.reset();
450 }
451
452 // A PRINTER_INFO_2 structure specifying the driver's default printer
453 // settings.
454 GetPrinterHelper(printer, 2, &buffer);
455 if (buffer.get()) {
456 PRINTER_INFO_2* info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get());
457 if (info_2->pDevMode != NULL) {
[email protected]d8254622010-08-13 19:15:46458 if (!AllocateContext(device_name, info_2->pDevMode, &context_)) {
initial.commit09911bf2008-07-26 23:55:29459 ResetSettings();
460 return false;
461 }
[email protected]c8ad40c2009-06-08 17:05:21462 return InitializeSettings(*info_2->pDevMode, device_name, NULL, 0, false);
initial.commit09911bf2008-07-26 23:55:29463 }
464 buffer.reset();
465 }
466 // Failed to retrieve the printer settings.
467 ResetSettings();
468 return false;
469}
470
[email protected]d8254622010-08-13 19:15:46471// static
initial.commit09911bf2008-07-26 23:55:29472bool PrintingContext::AllocateContext(const std::wstring& printer_name,
[email protected]d8254622010-08-13 19:15:46473 const DEVMODE* dev_mode,
474 gfx::NativeDrawingContext* context) {
475 *context = CreateDC(L"WINSPOOL", printer_name.c_str(), NULL, dev_mode);
476 DCHECK(*context);
477 return *context != NULL;
initial.commit09911bf2008-07-26 23:55:29478}
479
480PrintingContext::Result PrintingContext::ParseDialogResultEx(
481 const PRINTDLGEX& dialog_options) {
482 // If the user clicked OK or Apply then Cancel, but not only Cancel.
483 if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
484 // Start fresh.
485 ResetSettings();
486
487 DEVMODE* dev_mode = NULL;
488 if (dialog_options.hDevMode) {
489 dev_mode =
490 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
491 DCHECK(dev_mode);
492 }
493
494 std::wstring device_name;
495 if (dialog_options.hDevNames) {
496 DEVNAMES* dev_names =
497 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
498 DCHECK(dev_names);
499 if (dev_names) {
500 device_name =
501 reinterpret_cast<const wchar_t*>(
502 reinterpret_cast<const wchar_t*>(dev_names) +
503 dev_names->wDeviceOffset);
504 GlobalUnlock(dialog_options.hDevNames);
505 }
506 }
507
508 bool success = false;
509 if (dev_mode && !device_name.empty()) {
[email protected]b75dca82009-10-13 18:46:21510 context_ = dialog_options.hDC;
[email protected]c8ad40c2009-06-08 17:05:21511 PRINTPAGERANGE* page_ranges = NULL;
512 DWORD num_page_ranges = 0;
513 bool print_selection_only = false;
initial.commit09911bf2008-07-26 23:55:29514 if (dialog_options.Flags & PD_PAGENUMS) {
[email protected]c8ad40c2009-06-08 17:05:21515 page_ranges = dialog_options.lpPageRanges;
516 num_page_ranges = dialog_options.nPageRanges;
initial.commit09911bf2008-07-26 23:55:29517 }
[email protected]c8ad40c2009-06-08 17:05:21518 if (dialog_options.Flags & PD_SELECTION) {
519 print_selection_only = true;
520 }
521 success = InitializeSettings(*dev_mode,
522 device_name,
[email protected]d8254622010-08-13 19:15:46523 page_ranges,
524 num_page_ranges,
[email protected]c8ad40c2009-06-08 17:05:21525 print_selection_only);
initial.commit09911bf2008-07-26 23:55:29526 }
527
528 if (!success && dialog_options.hDC) {
529 DeleteDC(dialog_options.hDC);
[email protected]b75dca82009-10-13 18:46:21530 context_ = NULL;
initial.commit09911bf2008-07-26 23:55:29531 }
532
533 if (dev_mode) {
534 GlobalUnlock(dialog_options.hDevMode);
535 }
536 } else {
537 if (dialog_options.hDC) {
538 DeleteDC(dialog_options.hDC);
539 }
540 }
541
542 if (dialog_options.hDevMode != NULL)
543 GlobalFree(dialog_options.hDevMode);
544 if (dialog_options.hDevNames != NULL)
545 GlobalFree(dialog_options.hDevNames);
546
547 switch (dialog_options.dwResultAction) {
548 case PD_RESULT_PRINT:
[email protected]b75dca82009-10-13 18:46:21549 return context_ ? OK : FAILED;
initial.commit09911bf2008-07-26 23:55:29550 case PD_RESULT_APPLY:
[email protected]b75dca82009-10-13 18:46:21551 return context_ ? CANCEL : FAILED;
initial.commit09911bf2008-07-26 23:55:29552 case PD_RESULT_CANCEL:
553 return CANCEL;
554 default:
555 return FAILED;
556 }
557}
558
559PrintingContext::Result PrintingContext::ParseDialogResult(
560 const PRINTDLG& dialog_options) {
561 // If the user clicked OK or Apply then Cancel, but not only Cancel.
562 // Start fresh.
563 ResetSettings();
564
565 DEVMODE* dev_mode = NULL;
566 if (dialog_options.hDevMode) {
567 dev_mode =
568 reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
569 DCHECK(dev_mode);
570 }
571
572 std::wstring device_name;
573 if (dialog_options.hDevNames) {
574 DEVNAMES* dev_names =
575 reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
576 DCHECK(dev_names);
577 if (dev_names) {
578 device_name =
579 reinterpret_cast<const wchar_t*>(
580 reinterpret_cast<const wchar_t*>(dev_names) +
581 dev_names->wDeviceOffset);
582 GlobalUnlock(dialog_options.hDevNames);
583 }
584 }
585
586 bool success = false;
587 if (dev_mode && !device_name.empty()) {
[email protected]b75dca82009-10-13 18:46:21588 context_ = dialog_options.hDC;
[email protected]c8ad40c2009-06-08 17:05:21589 success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
initial.commit09911bf2008-07-26 23:55:29590 }
591
592 if (!success && dialog_options.hDC) {
593 DeleteDC(dialog_options.hDC);
[email protected]b75dca82009-10-13 18:46:21594 context_ = NULL;
initial.commit09911bf2008-07-26 23:55:29595 }
596
597 if (dev_mode) {
598 GlobalUnlock(dialog_options.hDevMode);
599 }
600
601 if (dialog_options.hDevMode != NULL)
602 GlobalFree(dialog_options.hDevMode);
603 if (dialog_options.hDevNames != NULL)
604 GlobalFree(dialog_options.hDevNames);
605
[email protected]b75dca82009-10-13 18:46:21606 return context_ ? OK : FAILED;
initial.commit09911bf2008-07-26 23:55:29607}
608
[email protected]d8254622010-08-13 19:15:46609// static
610void PrintingContext::GetPrinterHelper(HANDLE printer, int level,
611 scoped_array<uint8>* buffer) {
612 DWORD buf_size = 0;
613 GetPrinter(printer, level, NULL, 0, &buf_size);
614 if (buf_size) {
615 buffer->reset(new uint8[buf_size]);
616 memset(buffer->get(), 0, buf_size);
617 if (!GetPrinter(printer, level, buffer->get(), buf_size, &buf_size)) {
618 buffer->reset();
619 }
620 }
621}
622
initial.commit09911bf2008-07-26 23:55:29623} // namespace printing