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 <comdef.h> | 5 #include <comdef.h> |
6 #include <iomanip> | 6 #include <iomanip> |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <winspool.h> | 8 #include <winspool.h> |
9 #include <setupapi.h> // Must be included after windows.h | 9 #include <setupapi.h> // Must be included after windows.h |
10 | 10 |
11 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/file_util.h" | 13 #include "base/file_util.h" |
14 #include "base/file_version_info_win.h" | 14 #include "base/file_version_info_win.h" |
15 #include "base/files/scoped_temp_dir.h" | 15 #include "base/files/scoped_temp_dir.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/path_service.h" | 17 #include "base/path_service.h" |
18 #include "base/process.h" | 18 #include "base/process.h" |
19 #include "base/process_util.h" | 19 #include "base/process_util.h" |
20 #include "base/string16.h" | 20 #include "base/string16.h" |
21 #include "base/string_util.h" | 21 #include "base/string_util.h" |
22 #include "base/win/registry.h" | 22 #include "base/win/registry.h" |
23 #include "base/win/scoped_handle.h" | 23 #include "base/win/scoped_handle.h" |
24 #include "base/win/windows_version.h" | 24 #include "base/win/windows_version.h" |
25 #include "cloud_print/common/win/cloud_print_utils.h" | 25 #include "cloud_print/common/win/cloud_print_utils.h" |
| 26 #include "cloud_print/common/win/install_utils.h" |
26 #include "cloud_print/virtual_driver/win/virtual_driver_consts.h" | 27 #include "cloud_print/virtual_driver/win/virtual_driver_consts.h" |
27 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" | 28 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" |
28 #include "grit/virtual_driver_setup_resources.h" | 29 #include "grit/virtual_driver_setup_resources.h" |
29 | 30 |
30 #include <strsafe.h> // Must be after base headers to avoid deprecation | 31 #include <strsafe.h> // Must be after base headers to avoid deprecation |
31 // warnings. | 32 // warnings. |
32 | 33 |
| 34 namespace cloud_print { |
| 35 |
33 namespace { | 36 namespace { |
34 | 37 |
35 const wchar_t kNameValue[] = L"GCP Virtual Driver"; | 38 const wchar_t kNameValue[] = L"GCP Virtual Driver"; |
36 const wchar_t kUninstallRegistry[] = | 39 const wchar_t kUninstallId[] = L"{74AA24E0-AC50-4B28-BA46-9CF05467C9B7}"; |
37 L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" | |
38 L"{74AA24E0-AC50-4B28-BA46-9CF05467C9B7}"; | |
39 const wchar_t kInstallerName[] = L"virtual_driver_setup.exe"; | 40 const wchar_t kInstallerName[] = L"virtual_driver_setup.exe"; |
40 const wchar_t kGcpUrl[] = L"http://www.google.com/cloudprint"; | 41 const wchar_t kGcpUrl[] = L"http://www.google.com/cloudprint"; |
41 | 42 |
42 const wchar_t kDataFileName[] = L"gcp_driver.gpd"; | 43 const wchar_t kDataFileName[] = L"gcp_driver.gpd"; |
43 const wchar_t kDriverName[] = L"MXDWDRV.DLL"; | 44 const wchar_t kDriverName[] = L"MXDWDRV.DLL"; |
44 const wchar_t kUiDriverName[] = L"UNIDRVUI.DLL"; | 45 const wchar_t kUiDriverName[] = L"UNIDRVUI.DLL"; |
45 const wchar_t kHelpName[] = L"UNIDRV.HLP"; | 46 const wchar_t kHelpName[] = L"UNIDRV.HLP"; |
46 const wchar_t* kDependencyList[] = { | 47 const wchar_t* kDependencyList[] = { |
47 kDriverName, | 48 kDriverName, |
48 kHelpName, | 49 kHelpName, |
49 kUiDriverName, | 50 kUiDriverName, |
50 L"STDDTYPE.GDL", | 51 L"STDDTYPE.GDL", |
51 L"STDNAMES.GPD", | 52 L"STDNAMES.GPD", |
52 L"STDSCHEM.GDL", | 53 L"STDSCHEM.GDL", |
53 L"STDSCHMX.GDL", | 54 L"STDSCHMX.GDL", |
54 L"UNIDRV.DLL", | 55 L"UNIDRV.DLL", |
55 L"UNIRES.DLL", | 56 L"UNIRES.DLL", |
56 L"XPSSVCS.DLL", | 57 L"XPSSVCS.DLL", |
57 }; | 58 }; |
58 | 59 |
59 const char kDelete[] = "delete"; | 60 const char kDelete[] = "delete"; |
60 const char kInstallSwitch[] = "install"; | 61 const char kInstallSwitch[] = "install"; |
61 const char kRegisterSwitch[] = "register"; | 62 const char kRegisterSwitch[] = "register"; |
62 const char kUninstallSwitch[] = "uninstall"; | 63 const char kUninstallSwitch[] = "uninstall"; |
63 const char kUnregisterSwitch[] = "unregister"; | 64 const char kUnregisterSwitch[] = "unregister"; |
64 | 65 |
65 // Google update related constants. | |
66 const wchar_t kVersionKey[] = L"pv"; | |
67 const wchar_t kNameKey[] = L"name"; | |
68 const DWORD kInstallerResultFailedCustomError = 1; | |
69 const wchar_t kRegValueInstallerResult[] = L"InstallerResult"; | |
70 const wchar_t kRegValueInstallerResultUIString[] = L"InstallerResultUIString"; | |
71 | |
72 void SetGoogleUpdateKeys() { | |
73 base::win::RegKey key; | |
74 if (key.Create(HKEY_LOCAL_MACHINE, cloud_print::kGoogleUpdateClientsKey, | |
75 KEY_SET_VALUE) != ERROR_SUCCESS) { | |
76 LOG(ERROR) << "Unable to open key"; | |
77 } | |
78 | |
79 // Get the version from the resource file. | |
80 string16 version_string; | |
81 scoped_ptr<FileVersionInfo> version_info( | |
82 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | |
83 | |
84 if (version_info.get()) { | |
85 FileVersionInfoWin* version_info_win = | |
86 static_cast<FileVersionInfoWin*>(version_info.get()); | |
87 version_string = version_info_win->product_version(); | |
88 } else { | |
89 LOG(ERROR) << "Unable to get version string"; | |
90 // Use a random version string so that Google Update has something to go by. | |
91 version_string = L"0.0.0.99"; | |
92 } | |
93 | |
94 if (key.WriteValue(kVersionKey, version_string.c_str()) != ERROR_SUCCESS || | |
95 key.WriteValue(kNameKey, kNameValue) != ERROR_SUCCESS) { | |
96 LOG(ERROR) << "Unable to set registry keys"; | |
97 } | |
98 } | |
99 | |
100 void SetGoogleUpdateError(const string16& message) { | |
101 LOG(ERROR) << message; | |
102 base::win::RegKey key; | |
103 if (key.Create(HKEY_LOCAL_MACHINE, cloud_print::kGoogleUpdateClientStateKey, | |
104 KEY_SET_VALUE) != ERROR_SUCCESS) { | |
105 LOG(ERROR) << "Unable to open key"; | |
106 } | |
107 | |
108 if (key.WriteValue(kRegValueInstallerResult, | |
109 kInstallerResultFailedCustomError) != ERROR_SUCCESS || | |
110 key.WriteValue(kRegValueInstallerResultUIString, | |
111 message.c_str()) != ERROR_SUCCESS) { | |
112 LOG(ERROR) << "Unable to set registry keys"; | |
113 } | |
114 } | |
115 | |
116 void DeleteGoogleUpdateKeys() { | |
117 base::win::RegKey key; | |
118 if (key.Open(HKEY_LOCAL_MACHINE, cloud_print::kGoogleUpdateClientsKey, | |
119 DELETE) != ERROR_SUCCESS) { | |
120 LOG(ERROR) << "Unable to open key to delete"; | |
121 return; | |
122 } | |
123 if (key.DeleteKey(L"") != ERROR_SUCCESS) { | |
124 LOG(ERROR) << "Unable to delete key"; | |
125 } | |
126 } | |
127 | |
128 base::FilePath GetSystemPath(const string16& binary) { | 66 base::FilePath GetSystemPath(const string16& binary) { |
129 base::FilePath path; | 67 base::FilePath path; |
130 if (!PathService::Get(base::DIR_SYSTEM, &path)) { | 68 if (!PathService::Get(base::DIR_SYSTEM, &path)) { |
131 LOG(ERROR) << "Unable to get system path."; | 69 LOG(ERROR) << "Unable to get system path."; |
132 return path; | 70 return path; |
133 } | 71 } |
134 return path.Append(binary); | 72 return path.Append(binary); |
135 } | 73 } |
136 | 74 |
137 base::FilePath GetNativeSystemPath(const string16& binary) { | 75 base::FilePath GetNativeSystemPath(const string16& binary) { |
138 if (!cloud_print::IsSystem64Bit()) | 76 if (!IsSystem64Bit()) |
139 return GetSystemPath(binary); | 77 return GetSystemPath(binary); |
140 base::FilePath path; | 78 base::FilePath path; |
141 // Sysnative will bypass filesystem redirection and give us | 79 // Sysnative will bypass filesystem redirection and give us |
142 // the location of the 64bit system32 from a 32 bit process. | 80 // the location of the 64bit system32 from a 32 bit process. |
143 if (!PathService::Get(base::DIR_WINDOWS, &path)) { | 81 if (!PathService::Get(base::DIR_WINDOWS, &path)) { |
144 LOG(ERROR) << "Unable to get windows path."; | 82 LOG(ERROR) << "Unable to get windows path."; |
145 return path; | 83 return path; |
146 } | 84 } |
147 return path.Append(L"sysnative").Append(binary); | 85 return path.Append(L"sysnative").Append(binary); |
148 } | 86 } |
149 | 87 |
150 void SpoolerServiceCommand(const char* command) { | 88 void SpoolerServiceCommand(const char* command) { |
151 base::FilePath net_path = GetNativeSystemPath(L"net"); | 89 base::FilePath net_path = GetNativeSystemPath(L"net"); |
152 if (net_path.empty()) | 90 if (net_path.empty()) |
153 return; | 91 return; |
154 CommandLine command_line(net_path); | 92 CommandLine command_line(net_path); |
155 command_line.AppendArg(command); | 93 command_line.AppendArg(command); |
156 command_line.AppendArg("spooler"); | 94 command_line.AppendArg("spooler"); |
157 command_line.AppendArg("/y"); | 95 command_line.AppendArg("/y"); |
158 | 96 |
159 base::LaunchOptions options; | 97 base::LaunchOptions options; |
160 options.wait = true; | 98 options.wait = true; |
161 options.start_hidden = true; | 99 options.start_hidden = true; |
162 LOG(INFO) << command_line.GetCommandLineString(); | 100 LOG(INFO) << command_line.GetCommandLineString(); |
163 base::LaunchProcess(command_line, options, NULL); | 101 base::LaunchProcess(command_line, options, NULL); |
164 } | 102 } |
165 | 103 |
166 HRESULT RegisterPortMonitor(bool install, const base::FilePath& install_path) { | 104 HRESULT RegisterPortMonitor(bool install, const base::FilePath& install_path) { |
167 DCHECK(install || install_path.empty()); | 105 DCHECK(install || install_path.empty()); |
168 base::FilePath target_path = | 106 base::FilePath target_path = GetNativeSystemPath(GetPortMonitorDllName()); |
169 GetNativeSystemPath(cloud_print::GetPortMonitorDllName()); | |
170 if (target_path.empty()) { | 107 if (target_path.empty()) { |
171 LOG(ERROR) << "Unable to get port monitor target path."; | 108 LOG(ERROR) << "Unable to get port monitor target path."; |
172 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | 109 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); |
173 } | 110 } |
174 if (install) { | 111 if (install) { |
175 base::FilePath source_path = | 112 base::FilePath source_path = |
176 install_path.Append(cloud_print::GetPortMonitorDllName()); | 113 install_path.Append(GetPortMonitorDllName()); |
177 if (!file_util::CopyFile(source_path, target_path)) { | 114 if (!file_util::CopyFile(source_path, target_path)) { |
178 LOG(ERROR) << "Unable copy port monitor dll from " << | 115 LOG(ERROR) << "Unable copy port monitor dll from " << |
179 source_path.value() << " to " << target_path.value(); | 116 source_path.value() << " to " << target_path.value(); |
180 return cloud_print::GetLastHResult(); | 117 return GetLastHResult(); |
181 } | 118 } |
182 } else if (!file_util::PathExists(target_path)) { | 119 } else if (!file_util::PathExists(target_path)) { |
183 // Already removed. Just "succeed" silently. | 120 // Already removed. Just "succeed" silently. |
184 return S_OK; | 121 return S_OK; |
185 } | 122 } |
186 | 123 |
187 base::FilePath regsvr32_path = GetNativeSystemPath(L"regsvr32.exe"); | 124 base::FilePath regsvr32_path = GetNativeSystemPath(L"regsvr32.exe"); |
188 if (regsvr32_path.empty()) { | 125 if (regsvr32_path.empty()) { |
189 LOG(ERROR) << "Can't find regsvr32.exe."; | 126 LOG(ERROR) << "Can't find regsvr32.exe."; |
190 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | 127 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); |
191 } | 128 } |
192 | 129 |
193 CommandLine command_line(regsvr32_path); | 130 CommandLine command_line(regsvr32_path); |
194 command_line.AppendArg("/s"); | 131 command_line.AppendArg("/s"); |
195 if (!install) { | 132 if (!install) { |
196 command_line.AppendArg("/u"); | 133 command_line.AppendArg("/u"); |
197 } | 134 } |
198 | 135 |
199 // Use system32 path here because otherwise ::AddMonitor would fail. | 136 // Use system32 path here because otherwise ::AddMonitor would fail. |
200 command_line.AppendArgPath(GetSystemPath( | 137 command_line.AppendArgPath(GetSystemPath(GetPortMonitorDllName())); |
201 cloud_print::GetPortMonitorDllName())); | |
202 | 138 |
203 base::LaunchOptions options; | 139 base::LaunchOptions options; |
204 options.wait = true; | 140 options.wait = true; |
205 | 141 |
206 base::win::ScopedHandle regsvr32_handle; | 142 base::win::ScopedHandle regsvr32_handle; |
207 if (!base::LaunchProcess(command_line, options, regsvr32_handle.Receive())) { | 143 if (!base::LaunchProcess(command_line, options, regsvr32_handle.Receive())) { |
208 LOG(ERROR) << "Unable to launch regsvr32.exe."; | 144 LOG(ERROR) << "Unable to launch regsvr32.exe."; |
209 return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); | 145 return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); |
210 } | 146 } |
211 | 147 |
212 DWORD exit_code = S_OK; | 148 DWORD exit_code = S_OK; |
213 if (install) { | 149 if (install) { |
214 if (!GetExitCodeProcess(regsvr32_handle, &exit_code)) { | 150 if (!GetExitCodeProcess(regsvr32_handle, &exit_code)) { |
215 LOG(ERROR) << "Unable to get regsvr32.exe exit code."; | 151 LOG(ERROR) << "Unable to get regsvr32.exe exit code."; |
216 return cloud_print::GetLastHResult(); | 152 return GetLastHResult(); |
217 } | 153 } |
218 if (exit_code != 0) { | 154 if (exit_code != 0) { |
219 LOG(ERROR) << "Regsvr32.exe failed with " << exit_code; | 155 LOG(ERROR) << "Regsvr32.exe failed with " << exit_code; |
220 return HRESULT_FROM_WIN32(exit_code); | 156 return HRESULT_FROM_WIN32(exit_code); |
221 } | 157 } |
222 } else { | 158 } else { |
223 if (!file_util::Delete(target_path, false)) { | 159 if (!file_util::Delete(target_path, false)) { |
224 SpoolerServiceCommand("stop"); | 160 SpoolerServiceCommand("stop"); |
225 bool deleted = file_util::Delete(target_path, false); | 161 bool deleted = file_util::Delete(target_path, false); |
226 SpoolerServiceCommand("start"); | 162 SpoolerServiceCommand("start"); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 LOG(WARNING) << "File is missing: " << file_path.BaseName().value(); | 263 LOG(WARNING) << "File is missing: " << file_path.BaseName().value(); |
328 } | 264 } |
329 | 265 |
330 // Set up paths for the files we depend on. | 266 // Set up paths for the files we depend on. |
331 base::FilePath data_file = install_path.Append(kDataFileName); | 267 base::FilePath data_file = install_path.Append(kDataFileName); |
332 base::FilePath xps_path = temp_path.path().Append(kDriverName); | 268 base::FilePath xps_path = temp_path.path().Append(kDriverName); |
333 base::FilePath ui_path = temp_path.path().Append(kUiDriverName); | 269 base::FilePath ui_path = temp_path.path().Append(kUiDriverName); |
334 base::FilePath ui_help_path = temp_path.path().Append(kHelpName); | 270 base::FilePath ui_help_path = temp_path.path().Append(kHelpName); |
335 | 271 |
336 if (!file_util::PathExists(xps_path)) { | 272 if (!file_util::PathExists(xps_path)) { |
337 SetGoogleUpdateError(cloud_print::LoadLocalString(IDS_ERROR_NO_XPS)); | 273 SetGoogleUpdateError(kGoogleUpdateProductId, |
| 274 LoadLocalString(IDS_ERROR_NO_XPS)); |
338 return HRESULT_FROM_WIN32(ERROR_BAD_DRIVER); | 275 return HRESULT_FROM_WIN32(ERROR_BAD_DRIVER); |
339 } | 276 } |
340 | 277 |
341 DRIVER_INFO_6 driver_info = {0}; | 278 DRIVER_INFO_6 driver_info = {0}; |
342 // Set up supported print system version. Must be 3. | 279 // Set up supported print system version. Must be 3. |
343 driver_info.cVersion = 3; | 280 driver_info.cVersion = 3; |
344 | 281 |
345 // None of the print API structures likes constant strings even though they | 282 // None of the print API structures likes constant strings even though they |
346 // don't modify the string. const_casting is the cleanest option. | 283 // don't modify the string. const_casting is the cleanest option. |
347 driver_info.pDataFile = const_cast<LPWSTR>(data_file.value().c_str()); | 284 driver_info.pDataFile = const_cast<LPWSTR>(data_file.value().c_str()); |
348 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); | 285 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); |
349 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); | 286 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); |
350 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); | 287 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); |
351 | 288 |
352 string16 dependent_files(JoinString(dependent_array, L'\n')); | 289 string16 dependent_files(JoinString(dependent_array, L'\n')); |
353 dependent_files.push_back(L'\n'); | 290 dependent_files.push_back(L'\n'); |
354 std::replace(dependent_files.begin(), dependent_files.end(), L'\n', L'\0'); | 291 std::replace(dependent_files.begin(), dependent_files.end(), L'\n', L'\0'); |
355 driver_info.pDependentFiles = &dependent_files[0]; | 292 driver_info.pDependentFiles = &dependent_files[0]; |
356 | 293 |
357 // Set up user visible strings. | 294 // Set up user visible strings. |
358 string16 manufacturer = cloud_print::LoadLocalString(IDS_GOOGLE); | 295 string16 manufacturer = LoadLocalString(IDS_GOOGLE); |
359 driver_info.pszMfgName = const_cast<LPWSTR>(manufacturer.c_str()); | 296 driver_info.pszMfgName = const_cast<LPWSTR>(manufacturer.c_str()); |
360 driver_info.pszProvider = const_cast<LPWSTR>(manufacturer.c_str()); | 297 driver_info.pszProvider = const_cast<LPWSTR>(manufacturer.c_str()); |
361 driver_info.pszOEMUrl = const_cast<LPWSTR>(kGcpUrl); | 298 driver_info.pszOEMUrl = const_cast<LPWSTR>(kGcpUrl); |
362 driver_info.dwlDriverVersion = GetVersionNumber(); | 299 driver_info.dwlDriverVersion = GetVersionNumber(); |
363 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 300 string16 driver_name = LoadLocalString(IDS_DRIVER_NAME); |
364 driver_info.pName = const_cast<LPWSTR>(driver_name.c_str()); | 301 driver_info.pName = const_cast<LPWSTR>(driver_name.c_str()); |
365 | 302 |
366 if (!::AddPrinterDriverEx(NULL, 6, reinterpret_cast<BYTE*>(&driver_info), | 303 if (!::AddPrinterDriverEx(NULL, 6, reinterpret_cast<BYTE*>(&driver_info), |
367 APD_COPY_NEW_FILES | APD_COPY_FROM_DIRECTORY)) { | 304 APD_COPY_NEW_FILES | APD_COPY_FROM_DIRECTORY)) { |
368 LOG(ERROR) << "Unable to add printer driver"; | 305 LOG(ERROR) << "Unable to add printer driver"; |
369 return cloud_print::GetLastHResult(); | 306 return GetLastHResult(); |
370 } | 307 } |
371 return S_OK; | 308 return S_OK; |
372 } | 309 } |
373 | 310 |
374 HRESULT UninstallDriver() { | 311 HRESULT UninstallDriver() { |
375 int tries = 3; | 312 int tries = 3; |
376 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 313 string16 driver_name = LoadLocalString(IDS_DRIVER_NAME); |
377 while (!DeletePrinterDriverEx(NULL, | 314 while (!DeletePrinterDriverEx(NULL, |
378 NULL, | 315 NULL, |
379 const_cast<LPWSTR>(driver_name.c_str()), | 316 const_cast<LPWSTR>(driver_name.c_str()), |
380 DPD_DELETE_UNUSED_FILES, | 317 DPD_DELETE_UNUSED_FILES, |
381 0) && tries > 0) { | 318 0) && tries > 0) { |
382 if (GetLastError() == ERROR_UNKNOWN_PRINTER_DRIVER) { | 319 if (GetLastError() == ERROR_UNKNOWN_PRINTER_DRIVER) { |
383 LOG(WARNING) << "Print driver is already uninstalled."; | 320 LOG(WARNING) << "Print driver is already uninstalled."; |
384 return S_OK; | 321 return S_OK; |
385 } | 322 } |
386 // After deleting the printer it can take a few seconds before | 323 // After deleting the printer it can take a few seconds before |
387 // the driver is free for deletion. Retry a few times before giving up. | 324 // the driver is free for deletion. Retry a few times before giving up. |
388 LOG(WARNING) << "Attempt to delete printer driver failed. Retrying."; | 325 LOG(WARNING) << "Attempt to delete printer driver failed. Retrying."; |
389 tries--; | 326 tries--; |
390 Sleep(2000); | 327 Sleep(2000); |
391 } | 328 } |
392 if (tries <= 0) { | 329 if (tries <= 0) { |
393 HRESULT result = cloud_print::GetLastHResult(); | 330 HRESULT result = GetLastHResult(); |
394 LOG(ERROR) << "Unable to delete printer driver."; | 331 LOG(ERROR) << "Unable to delete printer driver."; |
395 return result; | 332 return result; |
396 } | 333 } |
397 return S_OK; | 334 return S_OK; |
398 } | 335 } |
399 | 336 |
400 HRESULT InstallPrinter(void) { | 337 HRESULT InstallPrinter(void) { |
401 PRINTER_INFO_2 printer_info = {0}; | 338 PRINTER_INFO_2 printer_info = {0}; |
402 | 339 |
403 // None of the print API structures likes constant strings even though they | 340 // None of the print API structures likes constant strings even though they |
404 // don't modify the string. const_casting is the cleanest option. | 341 // don't modify the string. const_casting is the cleanest option. |
405 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 342 string16 driver_name = LoadLocalString(IDS_DRIVER_NAME); |
406 printer_info.pDriverName = const_cast<LPWSTR>(driver_name.c_str()); | 343 printer_info.pDriverName = const_cast<LPWSTR>(driver_name.c_str()); |
407 printer_info.pPrinterName = const_cast<LPWSTR>(driver_name.c_str()); | 344 printer_info.pPrinterName = const_cast<LPWSTR>(driver_name.c_str()); |
408 printer_info.pComment = const_cast<LPWSTR>(driver_name.c_str()); | 345 printer_info.pComment = const_cast<LPWSTR>(driver_name.c_str()); |
409 printer_info.pLocation = const_cast<LPWSTR>(kGcpUrl); | 346 printer_info.pLocation = const_cast<LPWSTR>(kGcpUrl); |
410 string16 port_name; | 347 string16 port_name; |
411 printer_info.pPortName = const_cast<LPWSTR>(cloud_print::kPortName); | 348 printer_info.pPortName = const_cast<LPWSTR>(kPortName); |
412 printer_info.Attributes = PRINTER_ATTRIBUTE_DIRECT|PRINTER_ATTRIBUTE_LOCAL; | 349 printer_info.Attributes = PRINTER_ATTRIBUTE_DIRECT|PRINTER_ATTRIBUTE_LOCAL; |
413 printer_info.pPrintProcessor = L"winprint"; | 350 printer_info.pPrintProcessor = L"winprint"; |
414 HANDLE handle = AddPrinter(NULL, 2, reinterpret_cast<BYTE*>(&printer_info)); | 351 HANDLE handle = AddPrinter(NULL, 2, reinterpret_cast<BYTE*>(&printer_info)); |
415 if (handle == NULL) { | 352 if (handle == NULL) { |
416 HRESULT result = cloud_print::GetLastHResult(); | 353 HRESULT result = GetLastHResult(); |
417 LOG(ERROR) << "Unable to add printer"; | 354 LOG(ERROR) << "Unable to add printer"; |
418 return result; | 355 return result; |
419 } | 356 } |
420 ClosePrinter(handle); | 357 ClosePrinter(handle); |
421 return S_OK; | 358 return S_OK; |
422 } | 359 } |
423 | 360 |
424 HRESULT UninstallPrinter(void) { | 361 HRESULT UninstallPrinter(void) { |
425 HANDLE handle = NULL; | 362 HANDLE handle = NULL; |
426 PRINTER_DEFAULTS printer_defaults = {0}; | 363 PRINTER_DEFAULTS printer_defaults = {0}; |
427 printer_defaults.DesiredAccess = PRINTER_ALL_ACCESS; | 364 printer_defaults.DesiredAccess = PRINTER_ALL_ACCESS; |
428 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 365 string16 driver_name = LoadLocalString(IDS_DRIVER_NAME); |
429 if (!OpenPrinter(const_cast<LPWSTR>(driver_name.c_str()), | 366 if (!OpenPrinter(const_cast<LPWSTR>(driver_name.c_str()), |
430 &handle, | 367 &handle, |
431 &printer_defaults)) { | 368 &printer_defaults)) { |
432 // If we can't open the printer, it was probably already removed. | 369 // If we can't open the printer, it was probably already removed. |
433 LOG(WARNING) << "Unable to open printer"; | 370 LOG(WARNING) << "Unable to open printer"; |
434 return S_OK; | 371 return S_OK; |
435 } | 372 } |
436 if (!DeletePrinter(handle)) { | 373 if (!DeletePrinter(handle)) { |
437 HRESULT result = cloud_print::GetLastHResult(); | 374 HRESULT result = GetLastHResult(); |
438 LOG(ERROR) << "Unable to delete printer"; | 375 LOG(ERROR) << "Unable to delete printer"; |
439 ClosePrinter(handle); | 376 ClosePrinter(handle); |
440 return result; | 377 return result; |
441 } | 378 } |
442 ClosePrinter(handle); | 379 ClosePrinter(handle); |
443 return S_OK; | 380 return S_OK; |
444 } | 381 } |
445 | 382 |
446 void SetupUninstall(const base::FilePath& install_path) { | |
447 // Now write the Windows Uninstall entries | |
448 // Minimal error checking here since the install can contiunue | |
449 // if this fails. | |
450 base::win::RegKey key; | |
451 if (key.Create(HKEY_LOCAL_MACHINE, kUninstallRegistry, | |
452 KEY_SET_VALUE) != ERROR_SUCCESS) { | |
453 LOG(ERROR) << "Unable to open key"; | |
454 return; | |
455 } | |
456 CommandLine uninstall_command(install_path.Append(kInstallerName)); | |
457 uninstall_command.AppendArg("--uninstall"); | |
458 key.WriteValue(L"UninstallString", | |
459 uninstall_command.GetCommandLineString().c_str()); | |
460 key.WriteValue(L"InstallLocation", install_path.value().c_str()); | |
461 | |
462 | |
463 // Get the version resource. | |
464 scoped_ptr<FileVersionInfo> version_info( | |
465 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | |
466 | |
467 if (version_info.get()) { | |
468 FileVersionInfoWin* version_info_win = | |
469 static_cast<FileVersionInfoWin*>(version_info.get()); | |
470 key.WriteValue(L"DisplayVersion", | |
471 version_info_win->file_version().c_str()); | |
472 key.WriteValue(L"Publisher", version_info_win->company_name().c_str()); | |
473 } else { | |
474 LOG(ERROR) << "Unable to get version string"; | |
475 } | |
476 key.WriteValue(L"DisplayName", | |
477 cloud_print::LoadLocalString(IDS_DRIVER_NAME).c_str()); | |
478 key.WriteValue(L"NoModify", 1); | |
479 key.WriteValue(L"NoRepair", 1); | |
480 } | |
481 | |
482 void CleanupUninstall() { | |
483 ::RegDeleteKey(HKEY_LOCAL_MACHINE, kUninstallRegistry); | |
484 } | |
485 | |
486 bool IsOSSupported() { | 383 bool IsOSSupported() { |
487 // We don't support XP service pack 2 or older. | 384 // We don't support XP service pack 2 or older. |
488 base::win::Version version = base::win::GetVersion(); | 385 base::win::Version version = base::win::GetVersion(); |
489 return (version > base::win::VERSION_XP) || | 386 return (version > base::win::VERSION_XP) || |
490 ((version == base::win::VERSION_XP) && | 387 ((version == base::win::VERSION_XP) && |
491 (base::win::OSInfo::GetInstance()->service_pack().major >= 3)); | 388 (base::win::OSInfo::GetInstance()->service_pack().major >= 3)); |
492 } | 389 } |
493 | 390 |
494 HRESULT RegisterVirtualDriver(const base::FilePath& install_path) { | 391 HRESULT RegisterVirtualDriver(const base::FilePath& install_path) { |
495 HRESULT result = S_OK; | 392 HRESULT result = S_OK; |
(...skipping 18 matching lines...) Expand all Loading... |
514 | 411 |
515 result = InstallPrinter(); | 412 result = InstallPrinter(); |
516 if (FAILED(result) && | 413 if (FAILED(result) && |
517 result != HRESULT_FROM_WIN32(ERROR_PRINTER_ALREADY_EXISTS)) { | 414 result != HRESULT_FROM_WIN32(ERROR_PRINTER_ALREADY_EXISTS)) { |
518 LOG(ERROR) << "Unable to install printer."; | 415 LOG(ERROR) << "Unable to install printer."; |
519 return result; | 416 return result; |
520 } | 417 } |
521 return S_OK; | 418 return S_OK; |
522 } | 419 } |
523 | 420 |
524 void GetCurrentInstallPath(base::FilePath* install_path) { | |
525 base::win::RegKey key; | |
526 if (key.Open(HKEY_LOCAL_MACHINE, kUninstallRegistry, | |
527 KEY_QUERY_VALUE) != ERROR_SUCCESS) { | |
528 // Not installed. | |
529 *install_path = base::FilePath(); | |
530 return; | |
531 } | |
532 string16 install_path_value; | |
533 key.ReadValue(L"InstallLocation", &install_path_value); | |
534 *install_path = base::FilePath(install_path_value); | |
535 } | |
536 | |
537 HRESULT TryUnregisterVirtualDriver() { | 421 HRESULT TryUnregisterVirtualDriver() { |
538 HRESULT result = S_OK; | 422 HRESULT result = S_OK; |
539 result = UninstallPrinter(); | 423 result = UninstallPrinter(); |
540 if (FAILED(result)) { | 424 if (FAILED(result)) { |
541 LOG(ERROR) << "Unable to delete printer."; | 425 LOG(ERROR) << "Unable to delete printer."; |
542 return result; | 426 return result; |
543 } | 427 } |
544 result = UninstallDriver(); | 428 result = UninstallDriver(); |
545 if (FAILED(result)) { | 429 if (FAILED(result)) { |
546 LOG(ERROR) << "Unable to remove driver."; | 430 LOG(ERROR) << "Unable to remove driver."; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 } else { | 476 } else { |
593 LOG(ERROR) << "Improper termination of uninstall. " << status; | 477 LOG(ERROR) << "Improper termination of uninstall. " << status; |
594 return E_FAIL; | 478 return E_FAIL; |
595 } | 479 } |
596 } | 480 } |
597 } | 481 } |
598 return S_OK; | 482 return S_OK; |
599 } | 483 } |
600 | 484 |
601 HRESULT DoUninstall() { | 485 HRESULT DoUninstall() { |
602 DeleteGoogleUpdateKeys(); | 486 DeleteGoogleUpdateKeys(kGoogleUpdateProductId); |
603 HRESULT result = UnregisterVirtualDriver(); | 487 HRESULT result = UnregisterVirtualDriver(); |
604 if (FAILED(result)) | 488 if (FAILED(result)) |
605 return result; | 489 return result; |
606 CleanupUninstall(); | 490 DeleteUninstallKey(kUninstallId); |
607 base::FilePath installer_source; | 491 base::FilePath installer_source; |
608 if (PathService::Get(base::FILE_EXE, &installer_source)) | 492 if (PathService::Get(base::FILE_EXE, &installer_source)) |
609 return DeleteProgramDir(installer_source, false); | 493 return DeleteProgramDir(installer_source, false); |
610 return S_OK; | 494 return S_OK; |
611 } | 495 } |
612 | 496 |
613 HRESULT DoUnregister() { | 497 HRESULT DoUnregister() { |
614 return UnregisterVirtualDriver(); | 498 return UnregisterVirtualDriver(); |
615 } | 499 } |
616 | 500 |
(...skipping 12 matching lines...) Expand all Loading... |
629 Sleep(5000); // Give parent some time to exit. | 513 Sleep(5000); // Give parent some time to exit. |
630 return file_util::Delete(install_path, true) ? S_OK : E_FAIL; | 514 return file_util::Delete(install_path, true) ? S_OK : E_FAIL; |
631 } | 515 } |
632 | 516 |
633 HRESULT DoInstall(const base::FilePath& install_path) { | 517 HRESULT DoInstall(const base::FilePath& install_path) { |
634 HRESULT result = UnregisterVirtualDriver(); | 518 HRESULT result = UnregisterVirtualDriver(); |
635 if (FAILED(result)) { | 519 if (FAILED(result)) { |
636 LOG(ERROR) << "Unable to unregister."; | 520 LOG(ERROR) << "Unable to unregister."; |
637 return result; | 521 return result; |
638 } | 522 } |
639 base::FilePath old_install_path; | 523 base::FilePath old_install_path = GetInstallLocation(kUninstallId); |
640 GetCurrentInstallPath(&old_install_path); | |
641 if (!old_install_path.value().empty() && | 524 if (!old_install_path.value().empty() && |
642 install_path != old_install_path) { | 525 install_path != old_install_path) { |
643 if (file_util::DirectoryExists(old_install_path)) | 526 if (file_util::DirectoryExists(old_install_path)) |
644 file_util::Delete(old_install_path, true); | 527 file_util::Delete(old_install_path, true); |
645 } | 528 } |
646 SetupUninstall(install_path); | 529 CreateUninstallKey(kUninstallId, LoadLocalString(IDS_DRIVER_NAME), |
| 530 kUninstallSwitch); |
647 result = RegisterVirtualDriver(install_path); | 531 result = RegisterVirtualDriver(install_path); |
648 if (FAILED(result)) | 532 if (FAILED(result)) |
649 return result; | 533 return result; |
650 SetGoogleUpdateKeys(); | 534 SetGoogleUpdateKeys(kGoogleUpdateProductId, kNameValue); |
651 return result; | 535 return result; |
652 } | 536 } |
653 | 537 |
654 HRESULT ExecuteCommands() { | 538 HRESULT ExecuteCommands() { |
655 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 539 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
656 | 540 |
657 base::FilePath exe_path; | 541 base::FilePath exe_path; |
658 if (FAILED(PathService::Get(base::DIR_EXE, &exe_path)) || | 542 if (FAILED(PathService::Get(base::DIR_EXE, &exe_path)) || |
659 !file_util::DirectoryExists(exe_path)) { | 543 !file_util::DirectoryExists(exe_path)) { |
660 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); | 544 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); |
661 } | 545 } |
662 | 546 |
663 if (command_line.HasSwitch(kDelete)) { | 547 if (command_line.HasSwitch(kDelete)) { |
664 return DoDelete(command_line.GetSwitchValuePath(kDelete)); | 548 return DoDelete(command_line.GetSwitchValuePath(kDelete)); |
665 } else if (command_line.HasSwitch(kUninstallSwitch)) { | 549 } else if (command_line.HasSwitch(kUninstallSwitch)) { |
666 return DoUninstall(); | 550 return DoUninstall(); |
667 } else if (command_line.HasSwitch(kInstallSwitch)) { | 551 } else if (command_line.HasSwitch(kInstallSwitch)) { |
668 return DoInstall(exe_path); | 552 return DoInstall(exe_path); |
669 } else if (command_line.HasSwitch(kUnregisterSwitch)) { | 553 } else if (command_line.HasSwitch(kUnregisterSwitch)) { |
670 return DoUnregister(); | 554 return DoUnregister(); |
671 } else if (command_line.HasSwitch(kRegisterSwitch)) { | 555 } else if (command_line.HasSwitch(kRegisterSwitch)) { |
672 return DoRegister(exe_path); | 556 return DoRegister(exe_path); |
673 } | 557 } |
674 | 558 |
675 return E_INVALIDARG; | 559 return E_INVALIDARG; |
676 } | 560 } |
677 | 561 |
678 } // namespace | 562 } // namespace |
679 | 563 |
| 564 } // namespace cloud_print |
| 565 |
680 int WINAPI WinMain(__in HINSTANCE hInstance, | 566 int WINAPI WinMain(__in HINSTANCE hInstance, |
681 __in HINSTANCE hPrevInstance, | 567 __in HINSTANCE hPrevInstance, |
682 __in LPSTR lpCmdLine, | 568 __in LPSTR lpCmdLine, |
683 __in int nCmdShow) { | 569 __in int nCmdShow) { |
684 base::AtExitManager at_exit_manager; | 570 base::AtExitManager at_exit_manager; |
685 CommandLine::Init(0, NULL); | 571 CommandLine::Init(0, NULL); |
686 HRESULT retval = ExecuteCommands(); | 572 HRESULT retval = cloud_print::ExecuteCommands(); |
687 | 573 |
688 LOG(INFO) << _com_error(retval).ErrorMessage() << " HRESULT=0x" << | 574 LOG(INFO) << _com_error(retval).ErrorMessage() << " HRESULT=0x" << |
689 std::setbase(16) << retval; | 575 std::setbase(16) << retval; |
690 | 576 |
691 // Installer is silent by default as required by Google Update. | 577 // Installer is silent by default as required by Google Update. |
692 if (CommandLine::ForCurrentProcess()->HasSwitch("verbose")) { | 578 if (CommandLine::ForCurrentProcess()->HasSwitch("verbose")) { |
693 cloud_print::DisplayWindowsMessage(NULL, retval, | 579 cloud_print::DisplayWindowsMessage(NULL, retval, |
694 cloud_print::LoadLocalString(IDS_DRIVER_NAME)); | 580 cloud_print::LoadLocalString(IDS_DRIVER_NAME)); |
695 } | 581 } |
696 return retval; | 582 return retval; |
697 } | 583 } |
OLD | NEW |