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 "chrome/service/cloud_print/print_system.h" | 5 #include "chrome/service/cloud_print/print_system.h" |
6 | 6 |
7 #include <objidl.h> | 7 #include <objidl.h> |
8 #include <winspool.h> | 8 #include <winspool.h> |
9 #include <xpsprint.h> | 9 #include <xpsprint.h> |
10 | 10 |
(...skipping 15 matching lines...) Expand all Loading... |
26 #include "printing/emf_win.h" | 26 #include "printing/emf_win.h" |
27 #include "printing/page_range.h" | 27 #include "printing/page_range.h" |
28 #include "printing/pdf_render_settings.h" | 28 #include "printing/pdf_render_settings.h" |
29 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
30 #include "ui/gfx/rect.h" | 30 #include "ui/gfx/rect.h" |
31 | 31 |
32 #pragma comment(lib, "rpcrt4.lib") // for UuidToString & Co. | 32 #pragma comment(lib, "rpcrt4.lib") // for UuidToString & Co. |
33 | 33 |
34 namespace { | 34 namespace { |
35 | 35 |
| 36 class PrinterChangeHandleTraits { |
| 37 public: |
| 38 static bool CloseHandle(HANDLE handle) { |
| 39 return ::FindClosePrinterChangeNotification(handle) != FALSE; |
| 40 } |
| 41 }; |
| 42 |
| 43 typedef base::win::GenericScopedHandle<PrinterChangeHandleTraits> |
| 44 ScopedPrinterChangeHandle; |
| 45 |
36 class DevMode { | 46 class DevMode { |
37 public: | 47 public: |
38 DevMode() : dm_(NULL) {} | 48 DevMode() : dm_(NULL) {} |
39 ~DevMode() { Free(); } | 49 ~DevMode() { Free(); } |
40 | 50 |
41 void Allocate(int size) { | 51 void Allocate(int size) { |
42 Free(); | 52 Free(); |
43 dm_ = reinterpret_cast<DEVMODE*>(new char[size]); | 53 dm_ = reinterpret_cast<DEVMODE*>(new char[size]); |
44 } | 54 } |
45 | 55 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 return hr; | 125 return hr; |
116 } | 126 } |
117 | 127 |
118 } // namespace | 128 } // namespace |
119 | 129 |
120 namespace cloud_print { | 130 namespace cloud_print { |
121 | 131 |
122 class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate { | 132 class PrintSystemWatcherWin : public base::win::ObjectWatcher::Delegate { |
123 public: | 133 public: |
124 PrintSystemWatcherWin() | 134 PrintSystemWatcherWin() |
125 : printer_(NULL), | 135 : delegate_(NULL), |
126 printer_change_(NULL), | |
127 delegate_(NULL), | |
128 did_signal_(false) { | 136 did_signal_(false) { |
129 } | 137 } |
130 ~PrintSystemWatcherWin() { | 138 ~PrintSystemWatcherWin() { |
131 Stop(); | 139 Stop(); |
132 } | 140 } |
133 | 141 |
134 class Delegate { | 142 class Delegate { |
135 public: | 143 public: |
136 virtual ~Delegate() {} | 144 virtual ~Delegate() {} |
137 virtual void OnPrinterAdded() = 0; | 145 virtual void OnPrinterAdded() = 0; |
138 virtual void OnPrinterDeleted() = 0; | 146 virtual void OnPrinterDeleted() = 0; |
139 virtual void OnPrinterChanged() = 0; | 147 virtual void OnPrinterChanged() = 0; |
140 virtual void OnJobChanged() = 0; | 148 virtual void OnJobChanged() = 0; |
141 }; | 149 }; |
142 | 150 |
143 bool Start(const std::string& printer_name, Delegate* delegate) { | 151 bool Start(const std::string& printer_name, Delegate* delegate) { |
144 delegate_ = delegate; | 152 delegate_ = delegate; |
145 // An empty printer name means watch the current server, we need to pass | 153 // An empty printer name means watch the current server, we need to pass |
146 // NULL to OpenPrinter. | 154 // NULL to OpenPrinter. |
147 LPTSTR printer_name_to_use = NULL; | 155 LPTSTR printer_name_to_use = NULL; |
148 std::wstring printer_name_wide; | 156 std::wstring printer_name_wide; |
149 if (!printer_name.empty()) { | 157 if (!printer_name.empty()) { |
150 printer_name_wide = UTF8ToWide(printer_name); | 158 printer_name_wide = UTF8ToWide(printer_name); |
151 printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str()); | 159 printer_name_to_use = const_cast<LPTSTR>(printer_name_wide.c_str()); |
152 } | 160 } |
153 bool ret = false; | 161 bool ret = false; |
154 OpenPrinter(printer_name_to_use, &printer_, NULL); | 162 OpenPrinter(printer_name_to_use, printer_.Receive(), NULL); |
155 if (printer_) { | 163 if (printer_.IsValid()) { |
156 printer_change_ = FindFirstPrinterChangeNotification( | 164 printer_change_.Set(FindFirstPrinterChangeNotification( |
157 printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL); | 165 printer_, PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB, 0, NULL)); |
158 if (printer_change_) { | 166 if (printer_change_.IsValid()) { |
159 ret = watcher_.StartWatching(printer_change_, this); | 167 ret = watcher_.StartWatching(printer_change_, this); |
160 } | 168 } |
161 } | 169 } |
162 if (!ret) { | 170 if (!ret) { |
163 Stop(); | 171 Stop(); |
164 } | 172 } |
165 return ret; | 173 return ret; |
166 } | 174 } |
167 bool Stop() { | 175 bool Stop() { |
168 watcher_.StopWatching(); | 176 watcher_.StopWatching(); |
169 if (printer_) { | 177 printer_.Close(); |
170 ClosePrinter(printer_); | 178 printer_change_.Close(); |
171 printer_ = NULL; | |
172 } | |
173 if (printer_change_) { | |
174 FindClosePrinterChangeNotification(printer_change_); | |
175 printer_change_ = NULL; | |
176 } | |
177 return true; | 179 return true; |
178 } | 180 } |
179 | 181 |
180 // base::ObjectWatcher::Delegate method | 182 // base::ObjectWatcher::Delegate method |
181 virtual void OnObjectSignaled(HANDLE object) { | 183 virtual void OnObjectSignaled(HANDLE object) { |
182 DWORD change = 0; | 184 DWORD change = 0; |
183 FindNextPrinterChangeNotification(object, &change, NULL, NULL); | 185 FindNextPrinterChangeNotification(object, &change, NULL, NULL); |
184 | 186 |
185 if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) & | 187 if (change != ((PRINTER_CHANGE_PRINTER|PRINTER_CHANGE_JOB) & |
186 (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) { | 188 (~PRINTER_CHANGE_FAILED_CONNECTION_PRINTER))) { |
187 // For printer connections, we get spurious change notifications with | 189 // For printer connections, we get spurious change notifications with |
188 // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER. | 190 // all flags set except PRINTER_CHANGE_FAILED_CONNECTION_PRINTER. |
189 // Ignore these. | 191 // Ignore these. |
190 if (change & PRINTER_CHANGE_ADD_PRINTER) { | 192 if (change & PRINTER_CHANGE_ADD_PRINTER) { |
191 delegate_->OnPrinterAdded(); | 193 delegate_->OnPrinterAdded(); |
192 } else if (change & PRINTER_CHANGE_DELETE_PRINTER) { | 194 } else if (change & PRINTER_CHANGE_DELETE_PRINTER) { |
193 delegate_->OnPrinterDeleted(); | 195 delegate_->OnPrinterDeleted(); |
194 } else if (change & PRINTER_CHANGE_SET_PRINTER) { | 196 } else if (change & PRINTER_CHANGE_SET_PRINTER) { |
195 delegate_->OnPrinterChanged(); | 197 delegate_->OnPrinterChanged(); |
196 } | 198 } |
197 if (change & PRINTER_CHANGE_JOB) { | 199 if (change & PRINTER_CHANGE_JOB) { |
198 delegate_->OnJobChanged(); | 200 delegate_->OnJobChanged(); |
199 } | 201 } |
200 } | 202 } |
201 watcher_.StartWatching(printer_change_, this); | 203 watcher_.StartWatching(printer_change_, this); |
202 } | 204 } |
203 | 205 |
204 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { | 206 bool GetCurrentPrinterInfo(printing::PrinterBasicInfo* printer_info) { |
205 DCHECK(printer_info); | 207 DCHECK(printer_info); |
206 if (!printer_) | 208 if (!printer_.IsValid()) |
207 return false; | 209 return false; |
208 | 210 |
209 DWORD bytes_needed = 0; | 211 DWORD bytes_needed = 0; |
210 bool ret = false; | 212 bool ret = false; |
211 GetPrinter(printer_, 2, NULL, 0, &bytes_needed); | 213 GetPrinter(printer_, 2, NULL, 0, &bytes_needed); |
212 if (0 != bytes_needed) { | 214 if (0 != bytes_needed) { |
213 scoped_array<BYTE> printer_info_buffer(new BYTE[bytes_needed]); | 215 scoped_array<BYTE> printer_info_buffer(new BYTE[bytes_needed]); |
214 if (GetPrinter(printer_, 2, printer_info_buffer.get(), | 216 if (GetPrinter(printer_, 2, printer_info_buffer.get(), |
215 bytes_needed, &bytes_needed)) { | 217 bytes_needed, &bytes_needed)) { |
216 PRINTER_INFO_2* printer_info_win = | 218 PRINTER_INFO_2* printer_info_win = |
(...skipping 10 matching lines...) Expand all Loading... |
227 WideToUTF8(printer_info_win->pDriverName); | 229 WideToUTF8(printer_info_win->pDriverName); |
228 printer_info->printer_status = printer_info_win->Status; | 230 printer_info->printer_status = printer_info_win->Status; |
229 ret = true; | 231 ret = true; |
230 } | 232 } |
231 } | 233 } |
232 return ret; | 234 return ret; |
233 } | 235 } |
234 | 236 |
235 private: | 237 private: |
236 base::win::ObjectWatcher watcher_; | 238 base::win::ObjectWatcher watcher_; |
237 HANDLE printer_; // The printer being watched | 239 printing::ScopedPrinterHandle printer_; // The printer being watched |
238 HANDLE printer_change_; // Returned by FindFirstPrinterChangeNotifier | 240 // Returned by FindFirstPrinterChangeNotifier. |
239 Delegate* delegate_; // Delegate to notify | 241 ScopedPrinterChangeHandle printer_change_; |
240 bool did_signal_; // DoneWaiting was called | 242 Delegate* delegate_; // Delegate to notify |
| 243 bool did_signal_; // DoneWaiting was called |
241 }; | 244 }; |
242 | 245 |
243 // This typedef is to workaround the issue with certain versions of | 246 // This typedef is to workaround the issue with certain versions of |
244 // Visual Studio where it gets confused between multiple Delegate. | 247 // Visual Studio where it gets confused between multiple Delegate. |
245 // In this case, some compilers get confused and inherit | 248 // In this case, some compilers get confused and inherit |
246 // PrintSystemWin watchers from wrong Delegate, giving C2664 and C2259 errors. | 249 // PrintSystemWin watchers from wrong Delegate, giving C2664 and C2259 errors. |
247 typedef PrintSystemWatcherWin::Delegate PrintSystemWatcherWinDelegate; | 250 typedef PrintSystemWatcherWin::Delegate PrintSystemWatcherWinDelegate; |
248 | 251 |
249 class PrintSystemWin : public PrintSystem { | 252 class PrintSystemWin : public PrintSystem { |
250 public: | 253 public: |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 error.Receive())); | 800 error.Receive())); |
798 printing::XPSModule::CloseProvider(provider); | 801 printing::XPSModule::CloseProvider(provider); |
799 } | 802 } |
800 return ret; | 803 return ret; |
801 } | 804 } |
802 | 805 |
803 bool PrintSystemWin::GetJobDetails(const std::string& printer_name, | 806 bool PrintSystemWin::GetJobDetails(const std::string& printer_name, |
804 PlatformJobId job_id, | 807 PlatformJobId job_id, |
805 PrintJobDetails *job_details) { | 808 PrintJobDetails *job_details) { |
806 DCHECK(job_details); | 809 DCHECK(job_details); |
807 HANDLE printer_handle = NULL; | 810 printing::ScopedPrinterHandle printer_handle; |
808 std::wstring printer_name_wide = UTF8ToWide(printer_name); | 811 std::wstring printer_name_wide = UTF8ToWide(printer_name); |
809 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), &printer_handle, | 812 OpenPrinter(const_cast<LPTSTR>(printer_name_wide.c_str()), |
810 NULL); | 813 printer_handle.Receive(), NULL); |
811 DCHECK(printer_handle); | 814 DCHECK(printer_handle.IsValid()); |
812 bool ret = false; | 815 bool ret = false; |
813 if (printer_handle) { | 816 if (printer_handle.IsValid()) { |
814 DWORD bytes_needed = 0; | 817 DWORD bytes_needed = 0; |
815 GetJob(printer_handle, job_id, 1, NULL, 0, &bytes_needed); | 818 GetJob(printer_handle, job_id, 1, NULL, 0, &bytes_needed); |
816 DWORD last_error = GetLastError(); | 819 DWORD last_error = GetLastError(); |
817 if (ERROR_INVALID_PARAMETER != last_error) { | 820 if (ERROR_INVALID_PARAMETER != last_error) { |
818 // ERROR_INVALID_PARAMETER normally means that the job id is not valid. | 821 // ERROR_INVALID_PARAMETER normally means that the job id is not valid. |
819 DCHECK(last_error == ERROR_INSUFFICIENT_BUFFER); | 822 DCHECK(last_error == ERROR_INSUFFICIENT_BUFFER); |
820 scoped_array<BYTE> job_info_buffer(new BYTE[bytes_needed]); | 823 scoped_array<BYTE> job_info_buffer(new BYTE[bytes_needed]); |
821 if (GetJob(printer_handle, job_id, 1, job_info_buffer.get(), bytes_needed, | 824 if (GetJob(printer_handle, job_id, 1, job_info_buffer.get(), bytes_needed, |
822 &bytes_needed)) { | 825 &bytes_needed)) { |
823 JOB_INFO_1 *job_info = | 826 JOB_INFO_1 *job_info = |
824 reinterpret_cast<JOB_INFO_1 *>(job_info_buffer.get()); | 827 reinterpret_cast<JOB_INFO_1 *>(job_info_buffer.get()); |
825 if (job_info->pStatus) { | 828 if (job_info->pStatus) { |
826 WideToUTF8(job_info->pStatus, wcslen(job_info->pStatus), | 829 WideToUTF8(job_info->pStatus, wcslen(job_info->pStatus), |
827 &job_details->status_message); | 830 &job_details->status_message); |
828 } | 831 } |
829 job_details->platform_status_flags = job_info->Status; | 832 job_details->platform_status_flags = job_info->Status; |
830 if ((job_info->Status & JOB_STATUS_COMPLETE) || | 833 if ((job_info->Status & JOB_STATUS_COMPLETE) || |
831 (job_info->Status & JOB_STATUS_PRINTED)) { | 834 (job_info->Status & JOB_STATUS_PRINTED)) { |
832 job_details->status = PRINT_JOB_STATUS_COMPLETED; | 835 job_details->status = PRINT_JOB_STATUS_COMPLETED; |
833 } else if (job_info->Status & JOB_STATUS_ERROR) { | 836 } else if (job_info->Status & JOB_STATUS_ERROR) { |
834 job_details->status = PRINT_JOB_STATUS_ERROR; | 837 job_details->status = PRINT_JOB_STATUS_ERROR; |
835 } else { | 838 } else { |
836 job_details->status = PRINT_JOB_STATUS_IN_PROGRESS; | 839 job_details->status = PRINT_JOB_STATUS_IN_PROGRESS; |
837 } | 840 } |
838 job_details->total_pages = job_info->TotalPages; | 841 job_details->total_pages = job_info->TotalPages; |
839 job_details->pages_printed = job_info->PagesPrinted; | 842 job_details->pages_printed = job_info->PagesPrinted; |
840 ret = true; | 843 ret = true; |
841 } | 844 } |
842 } | 845 } |
843 ClosePrinter(printer_handle); | |
844 } | 846 } |
845 return ret; | 847 return ret; |
846 } | 848 } |
847 | 849 |
848 PrintSystem::PrintServerWatcher* | 850 PrintSystem::PrintServerWatcher* |
849 PrintSystemWin::CreatePrintServerWatcher() { | 851 PrintSystemWin::CreatePrintServerWatcher() { |
850 return new PrintServerWatcherWin(); | 852 return new PrintServerWatcherWin(); |
851 } | 853 } |
852 | 854 |
853 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( | 855 PrintSystem::PrinterWatcher* PrintSystemWin::CreatePrinterWatcher( |
(...skipping 26 matching lines...) Expand all Loading... |
880 RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); | 882 RpcStringFree(reinterpret_cast<RPC_WSTR *>(&proxy_id_as_string)); |
881 return ret; | 883 return ret; |
882 } | 884 } |
883 | 885 |
884 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( | 886 scoped_refptr<PrintSystem> PrintSystem::CreateInstance( |
885 const base::DictionaryValue* print_system_settings) { | 887 const base::DictionaryValue* print_system_settings) { |
886 return new PrintSystemWin; | 888 return new PrintSystemWin; |
887 } | 889 } |
888 | 890 |
889 } // namespace cloud_print | 891 } // namespace cloud_print |
OLD | NEW |