OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <windows.h> | 5 #include <windows.h> |
6 #include <winspool.h> | 6 #include <winspool.h> |
7 | 7 |
8 #include "base/at_exit.h" | 8 #include "base/at_exit.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/file_version_info_win.h" | |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/path_service.h" | 13 #include "base/path_service.h" |
13 #include "base/process_util.h" | 14 #include "base/process_util.h" |
14 #include "base/win/scoped_handle.h" | 15 #include "base/win/scoped_handle.h" |
15 #include "base/win/windows_version.h" | 16 #include "cloud_print/virtual_driver/win/virtual_driver_common_resources.h" |
16 #include "cloud_print/virtual_driver/win/virtual_driver_consts.h" | |
17 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" | 17 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" |
18 #include "grit/virtual_driver_setup_resources.h" | |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 bool IsSystem64Bit() { | |
22 base::win::OSInfo::WindowsArchitecture arch = | |
23 base::win::OSInfo::GetInstance()->architecture(); | |
24 return (arch == base::win::OSInfo::X64_ARCHITECTURE) || | |
25 (arch == base::win::OSInfo::IA64_ARCHITECTURE); | |
26 } | |
27 | |
28 HRESULT GetGpdPath(FilePath* path) { | 22 HRESULT GetGpdPath(FilePath* path) { |
29 if (!PathService::Get(base::DIR_EXE, path)) { | 23 if (!PathService::Get(base::DIR_EXE, path)) { |
30 LOG(ERROR) << "Unable to get install path."; | 24 LOG(ERROR) << "Unable to get install path."; |
31 return ERROR_PATH_NOT_FOUND; | 25 return ERROR_PATH_NOT_FOUND; |
32 } | 26 } |
33 *path = path->Append(L"gcp.gpd"); | 27 wchar_t driver_name[MAX_PATH]; |
28 cloud_print::LoadLocalString(IDS_GCP_DRIVER, | |
29 driver_name, | |
30 MAX_PATH); | |
31 *path = path->Append(driver_name); | |
34 return S_OK; | 32 return S_OK; |
35 } | 33 } |
36 | 34 |
37 const wchar_t *GetPortMonitorDllName() { | |
38 if (IsSystem64Bit()) { | |
39 return cloud_print::kPortMonitorDllName64; | |
40 } else { | |
41 return cloud_print::kPortMonitorDllName32; | |
42 } | |
43 } | |
44 | |
45 HRESULT GetPortMonitorDllPath(FilePath* path) { | 35 HRESULT GetPortMonitorDllPath(FilePath* path) { |
46 if (!PathService::Get(base::DIR_EXE, path)) { | 36 if (!PathService::Get(base::DIR_EXE, path)) { |
47 LOG(ERROR) << "Unable to get install path."; | 37 LOG(ERROR) << "Unable to get install path."; |
48 return ERROR_PATH_NOT_FOUND; | 38 return ERROR_PATH_NOT_FOUND; |
49 } | 39 } |
50 *path = path->Append(GetPortMonitorDllName()); | 40 FilePath dll_name; |
41 cloud_print::GetPortMonitorDllName(&dll_name); | |
42 *path = path->Append(dll_name); | |
51 return S_OK; | 43 return S_OK; |
52 } | 44 } |
53 | 45 |
54 HRESULT GetPortMonitorInstallPath(FilePath* path) { | 46 HRESULT GetPortMonitorInstallPath(FilePath* path) { |
55 if (IsSystem64Bit()) { | 47 if (cloud_print::IsSystem64Bit()) { |
56 if (!PathService::Get(base::DIR_WINDOWS, path)) { | 48 if (!PathService::Get(base::DIR_WINDOWS, path)) { |
57 return ERROR_PATH_NOT_FOUND; | 49 return ERROR_PATH_NOT_FOUND; |
58 } | 50 } |
59 // Sysnative will bypass filesystem redirection and give us | 51 // Sysnative will bypass filesystem redirection and give us |
60 // the location of the 64bit system32 from a 32 bit process. | 52 // the location of the 64bit system32 from a 32 bit process. |
61 *path = path->Append(L"sysnative"); | 53 *path = path->Append(L"sysnative"); |
62 } else { | 54 } else { |
63 if (!PathService::Get(base::DIR_SYSTEM, path)) { | 55 if (!PathService::Get(base::DIR_SYSTEM, path)) { |
64 LOG(ERROR) << "Unable to get system path."; | 56 LOG(ERROR) << "Unable to get system path."; |
65 return ERROR_PATH_NOT_FOUND; | 57 return ERROR_PATH_NOT_FOUND; |
66 } | 58 } |
67 } | 59 } |
68 *path = path->Append(GetPortMonitorDllName()); | 60 FilePath dll_name; |
61 cloud_print::GetPortMonitorDllName(&dll_name); | |
62 *path = path->Append(dll_name); | |
69 return S_OK; | 63 return S_OK; |
70 } | 64 } |
71 | 65 |
72 HRESULT GetRegsvr32Path(FilePath* path) { | 66 HRESULT GetRegsvr32Path(FilePath* path) { |
73 if (!PathService::Get(base::DIR_SYSTEM, path)) { | 67 if (!PathService::Get(base::DIR_SYSTEM, path)) { |
74 LOG(ERROR) << "Unable to get system path."; | 68 LOG(ERROR) << "Unable to get system path."; |
75 return ERROR_PATH_NOT_FOUND; | 69 return ERROR_PATH_NOT_FOUND; |
76 } | 70 } |
77 *path = path->Append(FilePath(L"regsvr32.exe")); | 71 *path = path->Append(FilePath(L"regsvr32.exe")); |
78 return S_OK; | 72 return S_OK; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 } | 126 } |
133 if (!install) { | 127 if (!install) { |
134 if (!file_util::Delete(target_path, false)) { | 128 if (!file_util::Delete(target_path, false)) { |
135 LOG(ERROR) << "Unable to delete " << target_path.value(); | 129 LOG(ERROR) << "Unable to delete " << target_path.value(); |
136 return ERROR_ACCESS_DENIED; | 130 return ERROR_ACCESS_DENIED; |
137 } | 131 } |
138 } | 132 } |
139 return S_OK; | 133 return S_OK; |
140 } | 134 } |
141 | 135 |
136 DWORDLONG GetVersionNumber() { | |
137 DWORDLONG retval = 0; | |
138 scoped_ptr<FileVersionInfo> version_info( | |
139 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | |
140 if (version_info.get()) { | |
141 FileVersionInfoWin* version_info_win = | |
142 static_cast<FileVersionInfoWin*>(version_info.get()); | |
143 VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); | |
144 retval = fixed_file_info->dwFileVersionMS; | |
145 retval <<= 32; | |
146 retval |= fixed_file_info->dwFileVersionMS; | |
147 } | |
148 return retval; | |
149 } | |
150 | |
142 HRESULT InstallGpd() { | 151 HRESULT InstallGpd() { |
152 DRIVER_INFO_6 driver_info = {0}; | |
143 HRESULT result = S_OK; | 153 HRESULT result = S_OK; |
154 | |
155 // Set up paths for the files we depend on. | |
144 FilePath source_path; | 156 FilePath source_path; |
157 FilePath driver_dir; | |
158 cloud_print::GetPrinterDriverDir(&driver_dir); | |
159 wchar_t buffer[MAX_PATH]; | |
160 cloud_print::LoadLocalString(IDS_XPS_DRIVER, buffer, MAX_PATH); | |
sanjeevr
2011/05/09 19:39:11
Do the DLL names need to be in the resource?
| |
161 FilePath xps_path = driver_dir.Append(buffer); | |
162 cloud_print::LoadLocalString(IDS_UI_DRIVER, buffer, MAX_PATH); | |
163 FilePath ui_path = driver_dir.Append(buffer); | |
164 cloud_print::LoadLocalString(IDS_UI_HELP, buffer, MAX_PATH); | |
165 FilePath ui_help_path = driver_dir.Append(buffer); | |
145 result = GetGpdPath(&source_path); | 166 result = GetGpdPath(&source_path); |
146 if (!SUCCEEDED(result)) { | 167 if (!SUCCEEDED(result)) { |
147 return result; | 168 return result; |
148 } | 169 } |
149 FilePath driver_dir; | |
150 cloud_print::GetPrinterDriverDir(&driver_dir); | |
151 FilePath xps_path = driver_dir.Append(L"mxdwdrv.dll"); | |
152 FilePath ui_path = driver_dir.Append(L"unidrvui.dll"); | |
153 FilePath ui_help_path = driver_dir.Append(L"unidrv.hlp"); | |
154 DRIVER_INFO_6 driver_info = {0}; | |
155 driver_info.cVersion = 3; | |
156 // None of the print API structures likes constant strings even though they | 170 // None of the print API structures likes constant strings even though they |
157 // don't modify the string. const_casting is the cleanest option. | 171 // don't modify the string. const_casting is the cleanest option. |
158 driver_info.pName = const_cast<LPWSTR>(cloud_print::kVirtualDriverName); | 172 driver_info.pDataFile = const_cast<LPWSTR>(source_path.value().c_str()); |
173 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); | |
159 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); | 174 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); |
160 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); | 175 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); |
161 driver_info.pDataFile = const_cast<LPWSTR>(source_path.value().c_str()); | 176 |
162 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); | 177 // Set up user visible strings. |
163 // TODO(abodenha@chromium.org) Pull these strings from resources. | 178 wchar_t manufacturer[MAX_PATH]; |
164 driver_info.pszMfgName = L"Google"; | 179 cloud_print::LoadLocalString(IDS_GOOGLE, manufacturer, MAX_PATH); |
165 driver_info.pszProvider = driver_info.pszMfgName; | 180 driver_info.pszMfgName = manufacturer; |
166 driver_info.pszOEMUrl = L"http://www.google.com/cloudprint"; | 181 driver_info.pszProvider = manufacturer; |
167 driver_info.dwlDriverVersion = 1; | 182 wchar_t oem_url[MAX_PATH]; |
168 driver_info.pDefaultDataType = L"RAW"; | 183 cloud_print::LoadLocalString(IDS_GCP_URL, oem_url, MAX_PATH); |
184 driver_info.pszOEMUrl = oem_url; | |
185 driver_info.dwlDriverVersion = GetVersionNumber(); | |
186 wchar_t driver_name[MAX_PATH]; | |
187 cloud_print::LoadLocalString(IDS_DRIVER_NAME, | |
188 driver_name, | |
189 MAX_PATH); | |
190 driver_info.pName = driver_name; | |
191 | |
192 // Set up supported data type and print system version. | |
193 wchar_t data_type[MAX_PATH]; | |
194 cloud_print::LoadLocalString(IDS_DATA_TYPE, data_type, MAX_PATH); | |
195 driver_info.pDefaultDataType = data_type; | |
196 driver_info.cVersion = 3; | |
197 | |
169 // TODO(abodenha@chromium.org) Properly handle dependencies. | 198 // TODO(abodenha@chromium.org) Properly handle dependencies. |
170 // GPD files are often dependent on various Windows core drivers. | 199 // GPD files are often dependent on various Windows core drivers. |
171 // I haven't found a reliable way to express those dependencies | 200 // I haven't found a reliable way to express those dependencies |
172 // other than using an INF for installation. | 201 // other than using an INF for installation. |
173 if (!AddPrinterDriverEx(NULL, | 202 if (!AddPrinterDriverEx(NULL, |
174 6, | 203 6, |
175 reinterpret_cast<BYTE*>(&driver_info), | 204 reinterpret_cast<BYTE*>(&driver_info), |
176 APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY)) { | 205 APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY)) { |
177 result = cloud_print::GetLastHResult(); | 206 result = cloud_print::GetLastHResult(); |
178 LOG(ERROR) << "Unable to add printer driver"; | 207 LOG(ERROR) << "Unable to add printer driver"; |
179 return result; | 208 return result; |
180 } | 209 } |
181 return S_OK; | 210 return S_OK; |
182 } | 211 } |
183 | 212 |
184 HRESULT UninstallGpd() { | 213 HRESULT UninstallGpd() { |
185 int tries = 10; | 214 int tries = 10; |
215 wchar_t driver_name[MAX_PATH]; | |
216 cloud_print::LoadLocalString(IDS_DRIVER_NAME, driver_name, MAX_PATH); | |
186 while (!DeletePrinterDriverEx(NULL, | 217 while (!DeletePrinterDriverEx(NULL, |
187 NULL, | 218 NULL, |
188 const_cast<LPWSTR> | 219 driver_name, |
189 (cloud_print::kVirtualDriverName), | |
190 DPD_DELETE_UNUSED_FILES, | 220 DPD_DELETE_UNUSED_FILES, |
191 0) && tries > 0) { | 221 0) && tries > 0) { |
222 if (GetLastError() == ERROR_UNKNOWN_PRINTER_DRIVER) { | |
223 LOG(WARNING) << "Print driver is already uninstalled."; | |
224 return S_OK; | |
225 } | |
192 // After deleting the printer it can take a few seconds before | 226 // After deleting the printer it can take a few seconds before |
193 // the driver is free for deletion. Retry a few times before giving up. | 227 // the driver is free for deletion. Retry a few times before giving up. |
194 LOG(WARNING) << "Attempt to delete printer driver failed. Retrying."; | 228 LOG(WARNING) << "Attempt to delete printer driver failed. Retrying."; |
195 tries--; | 229 tries--; |
196 Sleep(2000); | 230 Sleep(2000); |
197 } | 231 } |
198 if (tries <= 0) { | 232 if (tries <= 0) { |
199 HRESULT result = cloud_print::GetLastHResult(); | 233 HRESULT result = S_OK; |
200 LOG(ERROR) << "Unable to delete printer driver."; | 234 LOG(ERROR) << "Unable to delete printer driver."; |
201 return result; | 235 return result; |
202 } | 236 } |
203 return S_OK; | 237 return S_OK; |
204 } | 238 } |
205 | 239 |
206 HRESULT InstallPrinter(void) { | 240 HRESULT InstallPrinter(void) { |
207 PRINTER_INFO_2 printer_info = {0}; | 241 PRINTER_INFO_2 printer_info = {0}; |
208 printer_info.pPrinterName = | 242 wchar_t driver_name[MAX_PATH]; |
209 const_cast<LPWSTR>(cloud_print::kVirtualDriverName); | 243 cloud_print::LoadLocalString(IDS_DRIVER_NAME, driver_name, MAX_PATH); |
210 printer_info.pPortName = const_cast<LPWSTR>(cloud_print::kPortName); | 244 printer_info.pDriverName = driver_name; |
211 printer_info.pDriverName = | 245 printer_info.pPrinterName = driver_name; |
212 const_cast<LPWSTR>(cloud_print::kVirtualDriverName); | 246 printer_info.pComment = driver_name; |
213 printer_info.pPrinterName = printer_info.pDriverName; | 247 wchar_t port_name[MAX_PATH]; |
214 // TODO(abodenha@chromium.org) pComment should be localized. | 248 cloud_print::LoadLocalString(IDS_PORT_NAME, port_name, MAX_PATH); |
215 printer_info.pComment = const_cast<LPWSTR>(cloud_print::kVirtualDriverName); | 249 printer_info.pPortName = port_name; |
216 printer_info.Attributes = PRINTER_ATTRIBUTE_DIRECT|PRINTER_ATTRIBUTE_LOCAL; | 250 printer_info.Attributes = PRINTER_ATTRIBUTE_DIRECT|PRINTER_ATTRIBUTE_LOCAL; |
217 printer_info.pPrintProcessor = L"winprint"; | 251 wchar_t print_processor[MAX_PATH]; |
218 printer_info.pDatatype = L"RAW"; | 252 cloud_print::LoadLocalString(IDS_PRINT_PROCESSOR, print_processor, MAX_PATH); |
253 printer_info.pPrintProcessor = print_processor; | |
254 wchar_t data_type[MAX_PATH]; | |
255 cloud_print::LoadLocalString(IDS_DATA_TYPE, data_type, MAX_PATH); | |
256 printer_info.pDatatype = data_type; | |
219 HANDLE handle = AddPrinter(NULL, 2, reinterpret_cast<BYTE*>(&printer_info)); | 257 HANDLE handle = AddPrinter(NULL, 2, reinterpret_cast<BYTE*>(&printer_info)); |
220 if (handle == NULL) { | 258 if (handle == NULL) { |
221 HRESULT result = cloud_print::GetLastHResult(); | 259 HRESULT result = cloud_print::GetLastHResult(); |
222 LOG(ERROR) << "Unable to add printer"; | 260 LOG(ERROR) << "Unable to add printer"; |
223 return result; | 261 return result; |
224 } | 262 } |
225 ClosePrinter(handle); | 263 ClosePrinter(handle); |
226 return S_OK; | 264 return S_OK; |
227 } | 265 } |
228 | 266 |
229 HRESULT UninstallPrinter(void) { | 267 HRESULT UninstallPrinter(void) { |
230 HANDLE handle = NULL; | 268 HANDLE handle = NULL; |
231 PRINTER_DEFAULTS printer_defaults = {0}; | 269 PRINTER_DEFAULTS printer_defaults = {0}; |
232 printer_defaults.DesiredAccess = PRINTER_ALL_ACCESS; | 270 printer_defaults.DesiredAccess = PRINTER_ALL_ACCESS; |
233 if (!OpenPrinter(const_cast<LPWSTR>(cloud_print::kVirtualDriverName), | 271 wchar_t driver_name[MAX_PATH]; |
234 &handle, | 272 cloud_print::LoadLocalString(IDS_DRIVER_NAME, driver_name, MAX_PATH); |
235 &printer_defaults)) { | 273 if (!OpenPrinter(driver_name, &handle, &printer_defaults)) { |
236 // If we can't open the printer, it was probably already removed. | 274 // If we can't open the printer, it was probably already removed. |
237 LOG(WARNING) << "Unable to open printer"; | 275 LOG(WARNING) << "Unable to open printer"; |
238 return S_OK; | 276 return S_OK; |
239 } | 277 } |
240 if (!DeletePrinter(handle)) { | 278 if (!DeletePrinter(handle)) { |
241 HRESULT result = cloud_print::GetLastHResult(); | 279 HRESULT result = cloud_print::GetLastHResult(); |
242 LOG(ERROR) << "Unable to delete printer"; | 280 LOG(ERROR) << "Unable to delete printer"; |
243 ClosePrinter(handle); | 281 ClosePrinter(handle); |
244 return result; | 282 return result; |
245 } | 283 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
295 __in int nCmdShow) { | 333 __in int nCmdShow) { |
296 base::AtExitManager at_exit_manager; | 334 base::AtExitManager at_exit_manager; |
297 CommandLine::Init(0, NULL); | 335 CommandLine::Init(0, NULL); |
298 HRESULT retval = S_OK; | 336 HRESULT retval = S_OK; |
299 if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { | 337 if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { |
300 retval = UninstallVirtualDriver(); | 338 retval = UninstallVirtualDriver(); |
301 } else { | 339 } else { |
302 retval = InstallVirtualDriver(); | 340 retval = InstallVirtualDriver(); |
303 } | 341 } |
304 if (!CommandLine::ForCurrentProcess()->HasSwitch("silent")) { | 342 if (!CommandLine::ForCurrentProcess()->HasSwitch("silent")) { |
305 cloud_print::DisplayWindowsMessage(NULL, retval); | 343 wchar_t driver_name[MAX_PATH]; |
344 cloud_print::LoadLocalString(IDS_DRIVER_NAME, driver_name, MAX_PATH); | |
345 cloud_print::DisplayWindowsMessage(NULL, retval, driver_name); | |
306 } | 346 } |
307 return retval; | 347 return retval; |
308 } | 348 } |
309 | 349 |
OLD | NEW |