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