Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: printing/backend/print_backend_win.cc

Issue 3945003: Move useful printing backend code from chrome/service/cloud_print to printing... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: resolve merge conflict Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « printing/backend/print_backend_dummy.cc ('k') | printing/backend/win_helper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:mergeinfo
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "chrome/service/cloud_print/print_system.h" 5 #include "printing/backend/print_backend.h"
6 6
7 #include <windows.h>
8 #include <objidl.h> 7 #include <objidl.h>
9 #include <ocidl.h>
10 #include <olectl.h>
11 #include <prntvpt.h> 8 #include <prntvpt.h>
12 #include <winspool.h> 9 #include <winspool.h>
13 10
14 #include "base/lock.h"
15 #include "base/file_util.h"
16 #include "base/object_watcher.h"
17 #include "base/scoped_ptr.h" 11 #include "base/scoped_ptr.h"
12 #include "base/string_piece.h"
18 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
19 #include "base/win/scoped_bstr.h" 14 #include "base/win/scoped_bstr.h"
20 #include "base/win/scoped_comptr.h" 15 #include "base/win/scoped_comptr.h"
21 #include "chrome/service/cloud_print/cloud_print_consts.h" 16 #include "base/win/scoped_hglobal.h"
22 #include "chrome/service/service_process.h" 17 #include "printing/backend/print_backend_consts.h"
23 #include "chrome/service/service_utility_process_host.h" 18 #include "printing/backend/win_helper.h"
24 #include "gfx/rect.h"
25 #include "printing/native_metafile.h"
26 #include "printing/page_range.h"
27 19
28 #pragma comment(lib, "prntvpt.lib") 20 #pragma comment(lib, "prntvpt.lib")
29 #pragma comment(lib, "rpcrt4.lib")
30 21
31 using base::win::ScopedBstr; 22 using base::win::ScopedBstr;
32 using base::win::ScopedComPtr; 23 using base::win::ScopedComPtr;
24 using base::win::ScopedHGlobal;
33 25
34 namespace { 26 namespace {
35 27
36 class DevMode {
37 public:
38 DevMode() : dm_(NULL) {}
39 ~DevMode() { Free(); }
40
41 void Allocate(int size) {
42 Free();
43 dm_ = reinterpret_cast<DEVMODE*>(new char[size]);
44 }
45
46 void Free() {
47 if (dm_)
48 delete [] dm_;
49 dm_ = NULL;
50 }
51
52 DEVMODE* dm_;
53
54 private:
55 DISALLOW_COPY_AND_ASSIGN(DevMode);
56 };
57
58 bool InitXPSModule() {
59 HMODULE prntvpt_module = LoadLibrary(L"prntvpt.dll");
60 return (NULL != prntvpt_module);
61 }
62
63 inline HRESULT GetLastErrorHR() {
64 LONG error = GetLastError();
65 return HRESULT_FROM_WIN32(error);
66 }
67
68 HRESULT StreamFromPrintTicket(const std::string& print_ticket,
69 IStream** stream) {
70 DCHECK(stream);
71 HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream);
72 if (FAILED(hr)) {
73 return hr;
74 }
75 ULONG bytes_written = 0;
76 (*stream)->Write(print_ticket.c_str(), print_ticket.length(), &bytes_written);
77 DCHECK(bytes_written == print_ticket.length());
78 LARGE_INTEGER pos = {0};
79 ULARGE_INTEGER new_pos = {0};
80 (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos);
81 return S_OK;
82 }
83
84 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { 28 HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) {
85 DCHECK(stream); 29 DCHECK(stream);
86 DCHECK(out); 30 DCHECK(out);
87 HGLOBAL hdata = NULL; 31 HGLOBAL hdata = NULL;
88 HRESULT hr = GetHGlobalFromStream(stream, &hdata); 32 HRESULT hr = GetHGlobalFromStream(stream, &hdata);
89 if (SUCCEEDED(hr)) { 33 if (SUCCEEDED(hr)) {
90 DCHECK(hdata); 34 DCHECK(hdata);
91 ScopedHGlobal<char> locked_data(hdata); 35 ScopedHGlobal<char> locked_data(hdata);
92 out->assign(locked_data.release(), locked_data.Size()); 36 out->assign(locked_data.release(), locked_data.Size());
93 } 37 }
94 return hr; 38 return hr;
95 } 39 }
96 40
97 HRESULT PrintTicketToDevMode(const std::string& printer_name,
98 const std::string& print_ticket,
99 DevMode* dev_mode) {
100 DCHECK(dev_mode);
101
102 ScopedComPtr<IStream> pt_stream;
103 HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive());
104 if (FAILED(hr))
105 return hr;
106
107 HPTPROVIDER provider = NULL;
108 hr = PTOpenProvider(UTF8ToWide(printer_name).c_str(), 1, &provider);
109 if (SUCCEEDED(hr)) {
110 ULONG size = 0;
111 DEVMODE* dm = NULL;
112 hr = PTConvertPrintTicketToDevMode(provider,
113 pt_stream,
114 kUserDefaultDevmode,
115 kPTDocumentScope,
116 &size,
117 &dm,
118 NULL);
119 if (SUCCEEDED(hr)) {
120 dev_mode->Allocate(size);
121 memcpy(dev_mode->dm_, dm, size);
122 PTReleaseMemory(dm);
123 }
124 PTCloseProvider(provider);
125 }
126 return hr;
127 }
128
129 } // namespace 41 } // namespace
130 42
131 namespace cloud_print { 43 namespace printing {
132 44
133 class PrintSystemWatcherWin 45 class PrintBackendWin : public PrintBackend {
134 : public base::ObjectWatcher::Delegate {
135 public: 46 public:
136 PrintSystemWatcherWin() 47 PrintBackendWin() {}
137 : printer_(NULL), printer_change_(NULL), delegate_(NULL) { 48 virtual ~PrintBackendWin() {}
138 }
139 ~PrintSystemWatcherWin() {
140 Stop();
141 }
142 49
143 class Delegate {
144 public:
145 virtual void OnPrinterAdded() = 0;
146 virtual void OnPrinterDeleted() = 0;
147 virtual void OnPrinterChanged() = 0;
148 virtual void OnJobChanged() = 0;
149 };
150
151 bool Start(const std::string& printer_name, Delegate* delegate) {
152 delegate_ = delegate;
153 // An empty printer name means watch the current server, we need to pass
154 // NULL to OpenPrinter.
155 LPTSTR printer_name_to_use = NULL;
156 std::wstring printer_name_wide;
157 if (!printer_name.empty()) {
158 printer_name_wide = UTF8ToWide(printer_name);
159 printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str());
160 }
161 bool ret = false;
162 OpenPrinter(printer_name_to_use, &printer_, NULL);
163 if (printer_) {
164 printer_change_ = FindFirstPrinterChangeNotification(
165 printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL);
166 if (printer_change_) {
167 ret = watcher_.StartWatching(printer_change_, this);
168 }
169 }
170 if (!ret) {
171 Stop();
172 }
173 return ret;
174 }
175 bool Stop() {
176 watcher_.StopWatching();
177 if (printer_) {
178 ClosePrinter(printer_);
179 printer_ = NULL;
180 }
181 if (printer_change_) {
182 FindClosePrinterChangeNotification(printer_change_);
183 printer_change_ = NULL;
184 }
185 return true;
186 }
187
188 // base::ObjectWatcher::Delegate method
189 virtual void OnObjectSignaled(HANDLE object) {
190 DWORD change = 0;
191 FindNextPrinterChangeNotification(object, &change, NULL, NULL);
192
193 if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) &
194 (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) {
195 // For printer connections, we get spurious change notifications with
196 // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER.
197 // Ignore these.
198 if (change & PRINTER_CHANGE_ADD_PRINTER) {
199 delegate_->OnPrinterAdded();
200 } else if (change & PRINTER_CHANGE_DELETE_PRINTER) {
201 delegate_->OnPrinterDeleted();
202 } else if (change & PRINTER_CHANGE_SET_PRINTER) {
203 delegate_->OnPrinterChanged();
204 }
205 if (change & PRINTER_CHANGE_JOB) {
206 delegate_->OnJobChanged();
207 }
208 }
209 watcher_.StartWatching(printer_change_, this);
210 }
211
212 bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) {
213 DCHECK(printer_info);
214 if (!printer_)
215 return false;
216
217 DWORD bytes_needed = 0;
218 bool ret = false;
219 GetPrinter(printer_, 2, NULL, 0, &bytes_needed);
220 if (0 != bytes_needed) {
221 scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]);
222 if (GetPrinter(printer_, 2, printer_info_buffer.get(),
223 bytes_needed, &bytes_needed)) {
224 PRINTER_INFO_2* printer_info_win =
225 reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get());
226 printer_info->printer_name = WideToUTF8(printer_info_win->pPrinterName);
227 if (printer_info_win->pComment)
228 printer_info->printer_description =
229 WideToUTF8(printer_info_win->pComment);
230 if (printer_info_win->pLocation)
231 printer_info->options[kLocationTagName] =
232 WideToUTF8(printer_info_win->pLocation);
233 if (printer_info_win->pDriverName)
234 printer_info->options[kDriverNameTagName] =
235 WideToUTF8(printer_info_win->pDriverName);
236 printer_info->printer_status = printer_info_win->Status;
237 ret = true;
238 }
239 }
240 return ret;
241 }
242
243 private:
244 base::ObjectWatcher watcher_;
245 HANDLE printer_; // The printer being watched
246 HANDLE printer_change_; // Returned by FindFirstPrinterChangeNotifier
247 Delegate* delegate_; // Delegate to notify
248 bool did_signal_; // DoneWaiting was called
249 };
250
251 // This typedef is to workaround the issue with certain versions of
252 // Visual Studio where it gets confused between multiple Delegate.
253 // In this case, some compilers get confused and inherit
254 // PrintSystemWin watchers from wrong Delegate, giving C2664 and C2259 errors.
255 typedef PrintSystemWatcherWin::Delegate PrintSystemWatcherWinDelegate;
256
257 class PrintSystemWin : public PrintSystem {
258 public:
259 virtual void EnumeratePrinters(PrinterList* printer_list); 50 virtual void EnumeratePrinters(PrinterList* printer_list);
260 51
261 virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name, 52 virtual bool GetPrinterCapsAndDefaults(const std::string& printer_name,
262 PrinterCapsAndDefaults* printer_info); 53 PrinterCapsAndDefaults* printer_info);
263 54
264 virtual bool ValidatePrintTicket(const std::string& printer_name,
265 const std::string& print_ticket_data);
266
267 virtual bool GetJobDetails(const std::string& printer_name,
268 PlatformJobId job_id,
269 PrintJobDetails *job_details);
270
271 virtual bool IsValidPrinter(const std::string& printer_name); 55 virtual bool IsValidPrinter(const std::string& printer_name);
272
273 class PrintServerWatcherWin
274 : public PrintSystem::PrintServerWatcher,
275 public PrintSystemWatcherWinDelegate {
276 public:
277 PrintServerWatcherWin() {}
278
279 // PrintSystem::PrintServerWatcher interface
280 virtual bool StartWatching(
281 PrintSystem::PrintServerWatcher::Delegate* delegate) {
282 delegate_ = delegate;
283 return watcher_.Start(std::string(), this);
284 }
285 virtual bool StopWatching() {
286 bool ret = watcher_.Stop();
287 delegate_ = NULL;
288 return ret;
289 }
290
291 // PrintSystemWatcherWin::Delegate interface
292 virtual void OnPrinterAdded() {
293 delegate_->OnPrinterAdded();
294 }
295 virtual void OnPrinterDeleted() {
296 }
297 virtual void OnPrinterChanged() {
298 }
299 virtual void OnJobChanged() {
300 }
301
302 private:
303 PrintSystem::PrintServerWatcher::Delegate* delegate_;
304 PrintSystemWatcherWin watcher_;
305 DISALLOW_COPY_AND_ASSIGN(PrintServerWatcherWin);
306 };
307
308 class PrinterWatcherWin
309 : public PrintSystem::PrinterWatcher,
310 public PrintSystemWatcherWinDelegate {
311 public:
312 explicit PrinterWatcherWin(const std::string& printer_name)
313 : printer_name_(printer_name) {}
314
315 // PrintSystem::PrinterWatcher interface
316 virtual bool StartWatching(
317 PrintSystem::PrinterWatcher::Delegate* delegate) {
318 delegate_ = delegate;
319 return watcher_.Start(printer_name_, this);
320 }
321 virtual bool StopWatching() {
322 bool ret = watcher_.Stop();
323 delegate_ = NULL;
324 return ret;
325 }
326 virtual bool GetCurrentPrinterInfo(PrinterBasicInfo* printer_info) {
327 return watcher_.GetCurrentPrinterInfo(printer_info);
328 }
329
330 // PrintSystemWatcherWin::Delegate interface
331 virtual void OnPrinterAdded() {
332 NOTREACHED();
333 }
334 virtual void OnPrinterDeleted() {
335 delegate_->OnPrinterDeleted();
336 }
337 virtual void OnPrinterChanged() {
338 delegate_->OnPrinterChanged();
339 }
340 virtual void OnJobChanged() {
341 delegate_->OnJobChanged();
342 }
343
344 private:
345 std::string printer_name_;
346 PrintSystem::PrinterWatcher::Delegate* delegate_;
347 PrintSystemWatcherWin watcher_;
348 DISALLOW_COPY_AND_ASSIGN(PrinterWatcherWin);
349 };
350
351 class JobSpoolerWin : public PrintSystem::JobSpooler {
352 public:
353 JobSpoolerWin() : core_(new Core) {}
354 // PrintSystem::JobSpooler implementation.
355 virtual bool Spool(const std::string& print_ticket,
356 const FilePath& print_data_file_path,
357 const std::string& print_data_mime_type,
358 const std::string& printer_name,
359 const std::string& job_title,
360 JobSpooler::Delegate* delegate) {
361 return core_->Spool(print_ticket, print_data_file_path,
362 print_data_mime_type, printer_name, job_title,
363 delegate);
364 }
365 private:
366 // We use a Core class because we want a separate RefCountedThreadSafe
367 // implementation for ServiceUtilityProcessHost::Client.
368 class Core : public ServiceUtilityProcessHost::Client {
369 public:
370 Core()
371 : last_page_printed_(-1), job_id_(-1), delegate_(NULL), saved_dc_(0) {
372 }
373 ~Core() {
374 }
375 bool Spool(const std::string& print_ticket,
376 const FilePath& print_data_file_path,
377 const std::string& print_data_mime_type,
378 const std::string& printer_name,
379 const std::string& job_title,
380 JobSpooler::Delegate* delegate) {
381 if (delegate_) {
382 // We are already in the process of printing.
383 NOTREACHED();
384 return false;
385 }
386 last_page_printed_ = -1;
387 // We only support PDFs for now.
388 if (print_data_mime_type != "application/pdf") {
389 NOTREACHED();
390 return false;
391 }
392
393 if (!InitXPSModule()) {
394 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
395 return false;
396 }
397 DevMode pt_dev_mode;
398 HRESULT hr = PrintTicketToDevMode(printer_name, print_ticket,
399 &pt_dev_mode);
400 if (FAILED(hr)) {
401 NOTREACHED();
402 return false;
403 }
404 HDC dc = CreateDC(L"WINSPOOL", UTF8ToWide(printer_name).c_str(),
405 NULL, pt_dev_mode.dm_);
406 if (!dc) {
407 NOTREACHED();
408 return false;
409 }
410 hr = E_FAIL;
411 DOCINFO di = {0};
412 di.cbSize = sizeof(DOCINFO);
413 std::wstring doc_name = UTF8ToWide(job_title);
414 di.lpszDocName = doc_name.c_str();
415 job_id_ = StartDoc(dc, &di);
416 if (job_id_ <= 0)
417 return false;
418
419 printer_dc_.Set(dc);
420
421 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
422 saved_dc_ = SaveDC(printer_dc_.Get());
423 SetGraphicsMode(printer_dc_.Get(), GM_ADVANCED);
424 XFORM xform = {0};
425 xform.eM11 = xform.eM22 = static_cast<float>(printer_dpi) /
426 static_cast<float>(GetDeviceCaps(GetDC(NULL), LOGPIXELSX));
427 ModifyWorldTransform(printer_dc_.Get(), &xform, MWT_LEFTMULTIPLY);
428 print_data_file_path_ = print_data_file_path;
429 delegate_ = delegate;
430 RenderNextPDFPages();
431 return true;
432 }
433
434 // ServiceUtilityProcessHost::Client implementation.
435 virtual void OnRenderPDFPagesToMetafileSucceeded(
436 const printing::NativeMetafile& metafile,
437 int highest_rendered_page_number) {
438 metafile.SafePlayback(printer_dc_.Get());
439 bool done_printing = (highest_rendered_page_number !=
440 last_page_printed_ + kPageCountPerBatch);
441 last_page_printed_ = highest_rendered_page_number;
442 if (done_printing)
443 PrintJobDone();
444 else
445 RenderNextPDFPages();
446 }
447 virtual void OnRenderPDFPagesToMetafileFailed() {
448 PrintJobDone();
449 }
450 virtual void OnChildDied() {
451 PrintJobDone();
452 }
453 private:
454 void PrintJobDone() {
455 // If there is no delegate, then there is nothing pending to process.
456 if (!delegate_)
457 return;
458 RestoreDC(printer_dc_.Get(), saved_dc_);
459 EndDoc(printer_dc_.Get());
460 if (-1 == last_page_printed_) {
461 delegate_->OnJobSpoolFailed();
462 } else {
463 delegate_->OnJobSpoolSucceeded(job_id_);
464 }
465 delegate_ = NULL;
466 }
467 void RenderNextPDFPages() {
468 printing::PageRange range;
469 // Render 10 pages at a time.
470 range.from = last_page_printed_ + 1;
471 range.to = last_page_printed_ + kPageCountPerBatch;
472 std::vector<printing::PageRange> page_ranges;
473 page_ranges.push_back(range);
474
475 int printer_dpi = ::GetDeviceCaps(printer_dc_.Get(), LOGPIXELSX);
476 int dc_width = GetDeviceCaps(printer_dc_.Get(), PHYSICALWIDTH);
477 int dc_height = GetDeviceCaps(printer_dc_.Get(), PHYSICALHEIGHT);
478 gfx::Rect render_area(0, 0, dc_width, dc_height);
479 g_service_process->io_thread()->message_loop_proxy()->PostTask(
480 FROM_HERE,
481 NewRunnableMethod(
482 this,
483 &JobSpoolerWin::Core::RenderPDFPagesInSandbox,
484 print_data_file_path_,
485 render_area,
486 printer_dpi,
487 page_ranges,
488 base::MessageLoopProxy::CreateForCurrentThread()));
489 }
490 // Called on the service process IO thread.
491 void RenderPDFPagesInSandbox(
492 const FilePath& pdf_path, const gfx::Rect& render_area,
493 int render_dpi, const std::vector<printing::PageRange>& page_ranges,
494 const scoped_refptr<base::MessageLoopProxy>&
495 client_message_loop_proxy) {
496 DCHECK(g_service_process->io_thread()->message_loop_proxy()->
497 BelongsToCurrentThread());
498 scoped_ptr<ServiceUtilityProcessHost> utility_host(
499 new ServiceUtilityProcessHost(this, client_message_loop_proxy));
500 if (utility_host->StartRenderPDFPagesToMetafile(pdf_path,
501 render_area,
502 render_dpi,
503 page_ranges)) {
504 // The object will self-destruct when the child process dies.
505 utility_host.release();
506 }
507 }
508 // Some Cairo-generated PDFs from Chrome OS result in huge metafiles.
509 // So the PageCountPerBatch is set to 1 for now.
510 // TODO(sanjeevr): Figure out a smarter way to determine the pages per
511 // batch. Filed a bug to track this at
512 // http://code.google.com/p/chromium/issues/detail?id=57350.
513 static const int kPageCountPerBatch = 1;
514 int last_page_printed_;
515 PlatformJobId job_id_;
516 PrintSystem::JobSpooler::Delegate* delegate_;
517 int saved_dc_;
518 ScopedHDC printer_dc_;
519 FilePath print_data_file_path_;
520 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin::Core);
521 };
522 scoped_refptr<Core> core_;
523 DISALLOW_COPY_AND_ASSIGN(JobSpoolerWin);
524 };
525
526 virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher();
527 virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher(
528 const std::string& printer_name);
529 virtual PrintSystem::JobSpooler* CreateJobSpooler();
530 }; 56 };
531 57
532 void PrintSystemWin::EnumeratePrinters(PrinterList* printer_list) { 58 void PrintBackendWin::EnumeratePrinters(PrinterList* printer_list) {
533 DCHECK(printer_list); 59 DCHECK(printer_list);
534 DWORD bytes_needed = 0; 60 DWORD bytes_needed = 0;
535 DWORD count_returned = 0; 61 DWORD count_returned = 0;
536 BOOL ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, 62 BOOL ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2,
537 NULL, 0, &bytes_needed, &count_returned); 63 NULL, 0, &bytes_needed, &count_returned);
538 if (0 != bytes_needed) { 64 if (0 != bytes_needed) {
539 scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]); 65 scoped_ptr<BYTE> printer_info_buffer(new BYTE[bytes_needed]);
540 ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, 66 ret = EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2,
541 printer_info_buffer.get(), bytes_needed, &bytes_needed, 67 printer_info_buffer.get(), bytes_needed, &bytes_needed,
542 &count_returned); 68 &count_returned);
(...skipping 10 matching lines...) Expand all
553 info.options[kLocationTagName] = 79 info.options[kLocationTagName] =
554 WideToUTF8(printer_info[index].pLocation); 80 WideToUTF8(printer_info[index].pLocation);
555 if (printer_info[index].pDriverName) 81 if (printer_info[index].pDriverName)
556 info.options[kDriverNameTagName] = 82 info.options[kDriverNameTagName] =
557 WideToUTF8(printer_info[index].pDriverName); 83 WideToUTF8(printer_info[index].pDriverName);
558 printer_list->push_back(info); 84 printer_list->push_back(info);
559 } 85 }
560 } 86 }
561 } 87 }
562 88
563 bool PrintSystemWin::GetPrinterCapsAndDefaults( 89 bool PrintBackendWin::GetPrinterCapsAndDefaults(
564 const std::string& printer_name, 90 const std::string& printer_name,
565 PrinterCapsAndDefaults* printer_info) { 91 PrinterCapsAndDefaults* printer_info) {
566 if (!InitXPSModule()) { 92 if (!printing::InitXPSModule()) {
567 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) 93 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
568 return false; 94 return false;
569 } 95 }
570 if (!IsValidPrinter(printer_name)) { 96 if (!IsValidPrinter(printer_name)) {
571 return false; 97 return false;
572 } 98 }
573 DCHECK(printer_info); 99 DCHECK(printer_info);
574 HPTPROVIDER provider = NULL; 100 HPTPROVIDER provider = NULL;
575 std::wstring printer_name_wide = UTF8ToWide(printer_name); 101 std::wstring printer_name_wide = UTF8ToWide(printer_name);
576 HRESULT hr = PTOpenProvider(printer_name_wide.c_str(), 1, &provider); 102 HRESULT hr = PTOpenProvider(printer_name_wide.c_str(), 1, &provider);
(...skipping 18 matching lines...) Expand all
595 } 121 }
596 // TODO(sanjeevr): Add ScopedPrinterHandle 122 // TODO(sanjeevr): Add ScopedPrinterHandle
597 HANDLE printer_handle = NULL; 123 HANDLE printer_handle = NULL;
598 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle, 124 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle,
599 NULL); 125 NULL);
600 DCHECK(printer_handle); 126 DCHECK(printer_handle);
601 if (printer_handle) { 127 if (printer_handle) {
602 DWORD devmode_size = DocumentProperties( 128 DWORD devmode_size = DocumentProperties(
603 NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()), 129 NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()),
604 NULL, NULL, 0); 130 NULL, NULL, 0);
605 DCHECK(0 != devmode_size); 131 DCHECK_NE(0U, devmode_size);
606 scoped_ptr<BYTE> devmode_out_buffer(new BYTE[devmode_size]); 132 scoped_ptr<BYTE> devmode_out_buffer(new BYTE[devmode_size]);
607 DEVMODE* devmode_out = 133 DEVMODE* devmode_out =
608 reinterpret_cast<DEVMODE*>(devmode_out_buffer.get()); 134 reinterpret_cast<DEVMODE*>(devmode_out_buffer.get());
609 DocumentProperties( 135 DocumentProperties(
610 NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()), 136 NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()),
611 devmode_out, NULL, DM_OUT_BUFFER); 137 devmode_out, NULL, DM_OUT_BUFFER);
612 ScopedComPtr<IStream> printer_defaults_stream; 138 ScopedComPtr<IStream> printer_defaults_stream;
613 hr = CreateStreamOnHGlobal(NULL, TRUE, 139 hr = CreateStreamOnHGlobal(NULL, TRUE,
614 printer_defaults_stream.Receive()); 140 printer_defaults_stream.Receive());
615 DCHECK(SUCCEEDED(hr)); 141 DCHECK(SUCCEEDED(hr));
616 if (printer_defaults_stream) { 142 if (printer_defaults_stream) {
617 hr = PTConvertDevModeToPrintTicket(provider, devmode_size, 143 hr = PTConvertDevModeToPrintTicket(provider, devmode_size,
618 devmode_out, kPTJobScope, 144 devmode_out, kPTJobScope,
619 printer_defaults_stream); 145 printer_defaults_stream);
620 DCHECK(SUCCEEDED(hr)); 146 DCHECK(SUCCEEDED(hr));
621 if (SUCCEEDED(hr)) { 147 if (SUCCEEDED(hr)) {
622 hr = StreamOnHGlobalToString(printer_defaults_stream.get(), 148 hr = StreamOnHGlobalToString(printer_defaults_stream.get(),
623 &printer_info->printer_defaults); 149 &printer_info->printer_defaults);
624 DCHECK(SUCCEEDED(hr)); 150 DCHECK(SUCCEEDED(hr));
625 printer_info->defaults_mime_type = "text/xml"; 151 printer_info->defaults_mime_type = "text/xml";
626 } 152 }
627 } 153 }
628 ClosePrinter(printer_handle); 154 ClosePrinter(printer_handle);
629 } 155 }
630 PTCloseProvider(provider); 156 PTCloseProvider(provider);
631 } 157 }
632 return true; 158 return true;
633 } 159 }
634 160
635 bool PrintSystemWin::ValidatePrintTicket( 161 bool PrintBackendWin::IsValidPrinter(const std::string& printer_name) {
636 const std::string& printer_name,
637 const std::string& print_ticket_data) {
638 if (!InitXPSModule()) {
639 // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll)
640 return false;
641 }
642 bool ret = false;
643 HPTPROVIDER provider = NULL;
644 PTOpenProvider(UTF8ToWide(printer_name.c_str()).c_str(), 1, &provider);
645 if (provider) {
646 ScopedComPtr<IStream> print_ticket_stream;
647 CreateStreamOnHGlobal(NULL, TRUE, print_ticket_stream.Receive());
648 ULONG bytes_written = 0;
649 print_ticket_stream->Write(print_ticket_data.c_str(),
650 print_ticket_data.length(),
651 &bytes_written);
652 DCHECK(bytes_written == print_ticket_data.length());
653 LARGE_INTEGER pos = {0};
654 ULARGE_INTEGER new_pos = {0};
655 print_ticket_stream->Seek(pos, STREAM_SEEK_SET, &new_pos);
656 ScopedBstr error;
657 ScopedComPtr<IStream> result_ticket_stream;
658 CreateStreamOnHGlobal(NULL, TRUE, result_ticket_stream.Receive());
659 ret = SUCCEEDED(PTMergeAndValidatePrintTicket(provider,
660 print_ticket_stream.get(),
661 NULL,
662 kPTJobScope,
663 result_ticket_stream.get(),
664 error.Receive()));
665 PTCloseProvider(provider);
666 }
667 return ret;
668 }
669
670 bool PrintSystemWin::GetJobDetails(const std::string& printer_name,
671 PlatformJobId job_id,
672 PrintJobDetails *job_details) {
673 DCHECK(job_details);
674 HANDLE printer_handle = NULL;
675 std::wstring printer_name_wide = UTF8ToWide(printer_name);
676 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle,
677 NULL);
678 DCHECK(printer_handle);
679 bool ret = false;
680 if (printer_handle) {
681 DWORD bytes_needed = 0;
682 GetJob(printer_handle, job_id, 1, NULL, 0, &bytes_needed);
683 DWORD last_error = GetLastError();
684 if (ERROR_INVALID_PARAMETER != last_error) {
685 // ERROR_INVALID_PARAMETER normally means that the job id is not valid.
686 DCHECK(last_error == ERROR_INSUFFICIENT_BUFFER);
687 scoped_ptr<BYTE> job_info_buffer(new BYTE[bytes_needed]);
688 if (GetJob(printer_handle, job_id, 1, job_info_buffer.get(), bytes_needed,
689 &bytes_needed)) {
690 JOB_INFO_1 *job_info =
691 reinterpret_cast<JOB_INFO_1 *>(job_info_buffer.get());
692 if (job_info->pStatus) {
693 WideToUTF8(job_info->pStatus, wcslen(job_info->pStatus),
694 &job_details->status_message);
695 }
696 job_details->platform_status_flags = job_info->Status;
697 if ((job_info->Status & JOB_STATUS_COMPLETE) ||
698 (job_info->Status & JOB_STATUS_PRINTED)) {
699 job_details->status = PRINT_JOB_STATUS_COMPLETED;
700 } else if (job_info->Status & JOB_STATUS_ERROR) {
701 job_details->status = PRINT_JOB_STATUS_ERROR;
702 } else {
703 job_details->status = PRINT_JOB_STATUS_IN_PROGRESS;
704 }
705 job_details->total_pages = job_info->TotalPages;
706 job_details->pages_printed = job_info->PagesPrinted;
707 ret = true;
708 }
709 }
710 ClosePrinter(printer_handle);
711 }
712 return ret;
713 }
714
715 bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) {
716 std::wstring printer_name_wide = UTF8ToWide(printer_name); 162 std::wstring printer_name_wide = UTF8ToWide(printer_name);
717 HANDLE printer_handle = NULL; 163 HANDLE printer_handle = NULL;
718 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle, 164 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle,
719 NULL); 165 NULL);
720 bool ret = false; 166 bool ret = false;
721 if (printer_handle) { 167 if (printer_handle) {
722 ret = true; 168 ret = true;
723 ClosePrinter(printer_handle); 169 ClosePrinter(printer_handle);
724 } 170 }
725 return ret; 171 return ret;
726 } 172 }
727 173
728 PrintSystem::PrintServerWatcher* 174 scoped_refptr<PrintBackend> PrintBackend::CreateInstance(
729 PrintSystemWin::CreatePrintServerWatcher() { 175 const DictionaryValue* print_backend_settings) {
730 return new PrintServerWatcherWin(); 176 return new PrintBackendWin;
731 } 177 }
732 178
733 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( 179 } // namespace printing
734 const std::string& printer_name) {
735 DCHECK(!printer_name.empty());
736 return new PrinterWatcherWin(printer_name);
737 }
738
739 PrintSystem::JobSpooler*
740 PrintSystemWin::CreateJobSpooler() {
741 return new JobSpoolerWin();
742 }
743
744 std::string PrintSystem::GenerateProxyId() {
745 GUID proxy_id = {0};
746 HRESULT hr = UuidCreate(&proxy_id);
747 DCHECK(SUCCEEDED(hr));
748 wchar_t* proxy_id_as_string = NULL;
749 UuidToString(&proxy_id, reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string));
750 DCHECK(proxy_id_as_string);
751 std::string ret;
752 WideToUTF8(proxy_id_as_string, wcslen(proxy_id_as_string), &ret);
753 RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string));
754 return ret;
755 }
756
757 scoped_refptr<PrintSystem> PrintSystem::CreateInstance(
758 const DictionaryValue* print_system_settings) {
759 return new PrintSystemWin;
760 }
761
762 } // namespace cloud_print
763
OLDNEW
« no previous file with comments | « printing/backend/print_backend_dummy.cc ('k') | printing/backend/win_helper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698