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 <setupapi.h> // Must be included after windows.h |
6 #include <winspool.h> | 7 #include <winspool.h> |
7 | 8 |
8 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
9 #include "base/command_line.h" | 10 #include "base/command_line.h" |
10 #include "base/file_util.h" | 11 #include "base/file_util.h" |
11 #include "base/file_version_info_win.h" | 12 #include "base/file_version_info_win.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
14 #include "base/process_util.h" | 15 #include "base/process_util.h" |
15 #include "base/string16.h" | 16 #include "base/string16.h" |
16 #include "base/win/registry.h" | 17 #include "base/win/registry.h" |
17 #include "base/win/scoped_handle.h" | 18 #include "base/win/scoped_handle.h" |
18 #include "cloud_print/virtual_driver/win/virtual_driver_consts.h" | 19 #include "cloud_print/virtual_driver/win/virtual_driver_consts.h" |
19 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" | 20 #include "cloud_print/virtual_driver/win/virtual_driver_helpers.h" |
20 #include "grit/virtual_driver_setup_resources.h" | 21 #include "grit/virtual_driver_setup_resources.h" |
21 | 22 |
| 23 #include <strsafe.h> // Must be after base headers to avoid deprecation |
| 24 // warnings. |
| 25 |
22 namespace { | 26 namespace { |
23 const wchar_t kVersionKey[] = L"pv"; | 27 const wchar_t kVersionKey[] = L"pv"; |
24 const wchar_t kNameKey[] = L"name"; | 28 const wchar_t kNameKey[] = L"name"; |
25 const wchar_t kLangKey[] = L"lang"; | |
26 const wchar_t kNameValue[] = L"GCP Virtual Driver"; | 29 const wchar_t kNameValue[] = L"GCP Virtual Driver"; |
27 const wchar_t kLangValue[] = L"rn"; | 30 const wchar_t kPpdName[] = L"GCP-DRIVER.PPD"; |
| 31 const wchar_t kDriverName[] = L"MXDWDRV.DLL"; |
| 32 const wchar_t kUiDriverName[] = L"PS5UI.DLL"; |
| 33 const wchar_t kHelpName[] = L"PSCRIPT.HLP"; |
| 34 const wchar_t* kDependencyList[] = {kDriverName, kUiDriverName, kHelpName}; |
| 35 const wchar_t kUninstallRegistry[] = |
| 36 L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" |
| 37 L"{74AA24E0-AC50-4B28-BA46-9CF05467C9B7}"; |
| 38 const wchar_t kInstallerName[] = L"virtual_driver_setup.exe"; |
28 | 39 |
29 void SetRegistryKeys() { | 40 void SetOmahaKeys() { |
30 base::win::RegKey key; | 41 base::win::RegKey key; |
31 if (key.Create(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, | 42 if (key.Create(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, |
32 KEY_SET_VALUE) != ERROR_SUCCESS) { | 43 KEY_SET_VALUE) != ERROR_SUCCESS) { |
33 LOG(ERROR) << "Unable to open key"; | 44 LOG(ERROR) << "Unable to open key"; |
34 } | 45 } |
35 | 46 |
36 // Get the version from the resource file. | 47 // Get the version from the resource file. |
37 std::wstring version_string; | 48 std::wstring version_string; |
38 scoped_ptr<FileVersionInfo> version_info( | 49 scoped_ptr<FileVersionInfo> version_info( |
39 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); | 50 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); |
40 | 51 |
41 if (version_info.get()) { | 52 if (version_info.get()) { |
42 FileVersionInfoWin* version_info_win = | 53 FileVersionInfoWin* version_info_win = |
43 static_cast<FileVersionInfoWin*>(version_info.get()); | 54 static_cast<FileVersionInfoWin*>(version_info.get()); |
44 version_string = version_info_win->product_version(); | 55 version_string = version_info_win->product_version(); |
45 } else { | 56 } else { |
46 LOG(ERROR) << "Unable to get version string"; | 57 LOG(ERROR) << "Unable to get version string"; |
47 // Use a random version string so that Omaha has something to go by. | 58 // Use a random version string so that Omaha has something to go by. |
48 version_string = L"0.0.0.99"; | 59 version_string = L"0.0.0.99"; |
49 } | 60 } |
50 | 61 |
51 if (key.WriteValue(kVersionKey, version_string.c_str()) != ERROR_SUCCESS || | 62 if (key.WriteValue(kVersionKey, version_string.c_str()) != ERROR_SUCCESS || |
52 key.WriteValue(kNameKey, kNameValue) != ERROR_SUCCESS || | 63 key.WriteValue(kNameKey, kNameValue) != ERROR_SUCCESS) { |
53 key.WriteValue(kLangKey, kLangValue) != ERROR_SUCCESS) { | |
54 LOG(ERROR) << "Unable to set registry keys"; | 64 LOG(ERROR) << "Unable to set registry keys"; |
55 } | 65 } |
56 } | 66 } |
57 | 67 |
58 void DeleteRegistryKeys() { | 68 void DeleteOmahaKeys() { |
59 base::win::RegKey key; | 69 base::win::RegKey key; |
60 if (key.Open(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, | 70 if (key.Open(HKEY_LOCAL_MACHINE, cloud_print::kKeyLocation, |
61 DELETE) != ERROR_SUCCESS) { | 71 DELETE) != ERROR_SUCCESS) { |
62 LOG(ERROR) << "Unable to open key to delete"; | 72 LOG(ERROR) << "Unable to open key to delete"; |
63 } | 73 } |
64 if (key.DeleteKey(L"") != ERROR_SUCCESS) { | 74 if (key.DeleteKey(L"") != ERROR_SUCCESS) { |
65 LOG(ERROR) << "Unable to delete key"; | 75 LOG(ERROR) << "Unable to delete key"; |
66 } | 76 } |
67 } | 77 } |
68 | 78 |
69 HRESULT GetPpdPath(FilePath* path) { | 79 HRESULT GetNativeSystemPath(FilePath* path) { |
70 if (!PathService::Get(base::DIR_EXE, path)) { | |
71 LOG(ERROR) << "Unable to get install path."; | |
72 return ERROR_PATH_NOT_FOUND; | |
73 } | |
74 *path = path->Append(L"GCP-driver.ppd"); | |
75 return S_OK; | |
76 } | |
77 | |
78 HRESULT GetPortMonitorDllPath(FilePath* path) { | |
79 if (!PathService::Get(base::DIR_EXE, path)) { | |
80 LOG(ERROR) << "Unable to get install path."; | |
81 return ERROR_PATH_NOT_FOUND; | |
82 } | |
83 *path = path->Append(cloud_print::GetPortMonitorDllName()); | |
84 return S_OK; | |
85 } | |
86 | |
87 HRESULT GetPortMonitorInstallPath(FilePath* path) { | |
88 if (cloud_print::IsSystem64Bit()) { | 80 if (cloud_print::IsSystem64Bit()) { |
89 if (!PathService::Get(base::DIR_WINDOWS, path)) { | 81 if (!PathService::Get(base::DIR_WINDOWS, path)) { |
90 return ERROR_PATH_NOT_FOUND; | 82 return ERROR_PATH_NOT_FOUND; |
91 } | 83 } |
92 // Sysnative will bypass filesystem redirection and give us | 84 // Sysnative will bypass filesystem redirection and give us |
93 // the location of the 64bit system32 from a 32 bit process. | 85 // the location of the 64bit system32 from a 32 bit process. |
94 *path = path->Append(L"sysnative"); | 86 *path = path->Append(L"sysnative"); |
95 } else { | 87 } else { |
96 if (!PathService::Get(base::DIR_SYSTEM, path)) { | 88 if (!PathService::Get(base::DIR_SYSTEM, path)) { |
97 LOG(ERROR) << "Unable to get system path."; | 89 LOG(ERROR) << "Unable to get system path."; |
98 return ERROR_PATH_NOT_FOUND; | 90 return ERROR_PATH_NOT_FOUND; |
99 } | 91 } |
100 } | 92 } |
101 *path = path->Append(cloud_print::GetPortMonitorDllName()); | |
102 return S_OK; | 93 return S_OK; |
103 } | 94 } |
104 | 95 |
105 HRESULT GetRegsvr32Path(FilePath* path) { | 96 HRESULT GetPortMonitorTargetPath(FilePath* path) { |
106 if (!PathService::Get(base::DIR_SYSTEM, path)) { | 97 HRESULT result = GetNativeSystemPath(path); |
107 LOG(ERROR) << "Unable to get system path."; | 98 if (SUCCEEDED(result)) |
108 return ERROR_PATH_NOT_FOUND; | 99 *path = path->Append(cloud_print::GetPortMonitorDllName()); |
109 } | 100 return result; |
110 *path = path->Append(FilePath(L"regsvr32.exe")); | |
111 return S_OK; | |
112 } | 101 } |
113 | 102 |
114 HRESULT RegisterPortMonitor(bool install) { | 103 HRESULT GetRegsvr32Path(FilePath* path) { |
| 104 HRESULT result = GetNativeSystemPath(path); |
| 105 if (SUCCEEDED(result)) |
| 106 *path = path->Append(FilePath(L"regsvr32.exe")); |
| 107 return result; |
| 108 } |
| 109 |
| 110 HRESULT RegisterPortMonitor(bool install, const FilePath& install_path) { |
115 FilePath target_path; | 111 FilePath target_path; |
116 HRESULT result = S_OK; | 112 HRESULT result = S_OK; |
117 result = GetPortMonitorInstallPath(&target_path); | 113 result = GetPortMonitorTargetPath(&target_path); |
118 if (!SUCCEEDED(result)) { | 114 if (!SUCCEEDED(result)) { |
119 LOG(ERROR) << "Unable to get port monitor target path."; | 115 LOG(ERROR) << "Unable to get port monitor target path."; |
120 return result; | 116 return result; |
121 } | 117 } |
122 FilePath source_path; | 118 string16 source; |
123 result = GetPortMonitorDllPath(&source_path); | 119 source = cloud_print::GetPortMonitorDllName(); |
124 if (!SUCCEEDED(result)) { | |
125 LOG(ERROR) << "Unable to get dll source path."; | |
126 return result; | |
127 } | |
128 if (install) { | 120 if (install) { |
| 121 FilePath source_path = install_path.Append(source); |
129 if (!file_util::CopyFileW(source_path, target_path)) { | 122 if (!file_util::CopyFileW(source_path, target_path)) { |
130 LOG(ERROR) << "Unable copy port monitor dll from " << | 123 LOG(ERROR) << "Unable copy port monitor dll from " << |
131 source_path.value() << " to " << target_path.value(); | 124 source_path.value() << " to " << target_path.value(); |
132 return ERROR_ACCESS_DENIED; | 125 return ERROR_ACCESS_DENIED; |
133 } | 126 } |
134 } | 127 } |
135 FilePath regsvr32_path; | 128 FilePath regsvr32_path; |
136 result = GetRegsvr32Path(®svr32_path); | 129 result = GetRegsvr32Path(®svr32_path); |
137 if (!SUCCEEDED(result)) { | 130 if (!SUCCEEDED(result)) { |
138 LOG(ERROR) << "Can't find regsvr32.exe."; | 131 LOG(ERROR) << "Can't find regsvr32.exe."; |
139 return result; | 132 return result; |
140 } | 133 } |
141 | 134 |
142 CommandLine command_line(regsvr32_path); | 135 CommandLine command_line(regsvr32_path); |
143 command_line.AppendArg("/s"); | 136 command_line.AppendArg("/s"); |
144 if (!install) { | 137 if (!install) { |
145 command_line.AppendArg("/u"); | 138 command_line.AppendArg("/u"); |
146 } | 139 } |
147 command_line.AppendArgPath(source_path); | 140 |
| 141 FilePath final_path; |
| 142 if (!PathService::Get(base::DIR_SYSTEM, &final_path)) { |
| 143 LOG(ERROR) << "Unable to get system path."; |
| 144 return ERROR_PATH_NOT_FOUND; |
| 145 } |
| 146 final_path = final_path.Append(cloud_print::GetPortMonitorDllName()); |
| 147 command_line.AppendArgPath(final_path); |
148 | 148 |
149 base::LaunchOptions options; | 149 base::LaunchOptions options; |
150 HANDLE process_handle; | 150 HANDLE process_handle; |
151 options.wait = true; | 151 options.wait = true; |
152 if (!base::LaunchProcess(command_line, options, &process_handle)) { | 152 if (!base::LaunchProcess(command_line, options, &process_handle)) { |
153 LOG(ERROR) << "Unable to launch regsvr32.exe."; | 153 LOG(ERROR) << "Unable to launch regsvr32.exe."; |
154 return ERROR_NOT_SUPPORTED; | 154 return ERROR_NOT_SUPPORTED; |
155 } | 155 } |
156 base::win::ScopedHandle scoped_process_handle(process_handle); | 156 base::win::ScopedHandle scoped_process_handle(process_handle); |
157 | 157 |
(...skipping 24 matching lines...) Expand all Loading... |
182 FileVersionInfoWin* version_info_win = | 182 FileVersionInfoWin* version_info_win = |
183 static_cast<FileVersionInfoWin*>(version_info.get()); | 183 static_cast<FileVersionInfoWin*>(version_info.get()); |
184 VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); | 184 VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); |
185 retval = fixed_file_info->dwFileVersionMS; | 185 retval = fixed_file_info->dwFileVersionMS; |
186 retval <<= 32; | 186 retval <<= 32; |
187 retval |= fixed_file_info->dwFileVersionMS; | 187 retval |= fixed_file_info->dwFileVersionMS; |
188 } | 188 } |
189 return retval; | 189 return retval; |
190 } | 190 } |
191 | 191 |
192 HRESULT InstallPpd() { | 192 UINT CALLBACK CabinetCallback(PVOID data, |
| 193 UINT notification, |
| 194 UINT_PTR param1, |
| 195 UINT_PTR param2 ) { |
| 196 FilePath* temp_path = reinterpret_cast<FilePath*>(data); |
| 197 if (notification == SPFILENOTIFY_FILEINCABINET) { |
| 198 FILE_IN_CABINET_INFO* info = |
| 199 reinterpret_cast<FILE_IN_CABINET_INFO*>(param1); |
| 200 for (int i = 0; i < arraysize(kDependencyList); i++) { |
| 201 if (wcsstr(info->NameInCabinet, kDependencyList[i])) { |
| 202 StringCchCopy(info->FullTargetName, MAX_PATH, |
| 203 temp_path->Append(kDependencyList[i]).value().c_str()); |
| 204 return FILEOP_DOIT; |
| 205 } |
| 206 } |
| 207 |
| 208 return FILEOP_SKIP; |
| 209 } |
| 210 return NO_ERROR; |
| 211 } |
| 212 |
| 213 void ReadyPpdDependencies(const FilePath& install_path) { |
| 214 CORE_PRINTER_DRIVER driver; |
| 215 GetCorePrinterDrivers(NULL, |
| 216 NULL, |
| 217 L"{D20EA372-DD35-4950-9ED8-A6335AFE79F0}", |
| 218 1, |
| 219 &driver); |
| 220 DWORD size = MAX_PATH; |
| 221 wchar_t package_path[MAX_PATH]; |
| 222 GetPrinterDriverPackagePath(NULL, |
| 223 NULL, |
| 224 NULL, |
| 225 driver.szPackageID, |
| 226 package_path, |
| 227 MAX_PATH, |
| 228 &size); |
| 229 |
| 230 SetupIterateCabinet(package_path, |
| 231 0, |
| 232 CabinetCallback, |
| 233 const_cast<FilePath*>(&install_path)); |
| 234 } |
| 235 |
| 236 HRESULT InstallPpd(const FilePath& install_path) { |
193 DRIVER_INFO_6 driver_info = {0}; | 237 DRIVER_INFO_6 driver_info = {0}; |
194 HRESULT result = S_OK; | 238 HRESULT result = S_OK; |
195 | 239 |
196 // Set up paths for the files we depend on. | 240 // Set up paths for the files we depend on. |
197 FilePath source_path; | 241 FilePath ppd_path = install_path.Append(kPpdName); |
198 FilePath driver_dir; | 242 FilePath xps_path = install_path.Append(kDriverName); |
199 cloud_print::GetPrinterDriverDir(&driver_dir); | 243 FilePath ui_path = install_path.Append(kUiDriverName); |
200 FilePath xps_path = driver_dir.Append(L"mxdwdrv.dll"); | 244 FilePath ui_help_path = install_path.Append(kHelpName); |
201 FilePath ui_path = driver_dir.Append(L"ps5ui.dll"); | 245 ReadyPpdDependencies(install_path); |
202 FilePath ui_help_path = driver_dir.Append(L"unidrv.hlp"); | |
203 result = GetPpdPath(&source_path); | |
204 if (!SUCCEEDED(result)) { | |
205 return result; | |
206 } | |
207 // None of the print API structures likes constant strings even though they | 246 // None of the print API structures likes constant strings even though they |
208 // don't modify the string. const_casting is the cleanest option. | 247 // don't modify the string. const_casting is the cleanest option. |
209 driver_info.pDataFile = const_cast<LPWSTR>(source_path.value().c_str()); | 248 driver_info.pDataFile = const_cast<LPWSTR>(ppd_path.value().c_str()); |
210 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); | 249 driver_info.pHelpFile = const_cast<LPWSTR>(ui_help_path.value().c_str()); |
211 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); | 250 driver_info.pDriverPath = const_cast<LPWSTR>(xps_path.value().c_str()); |
212 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); | 251 driver_info.pConfigFile = const_cast<LPWSTR>(ui_path.value().c_str()); |
213 | 252 |
214 // Set up user visible strings. | 253 // Set up user visible strings. |
215 string16 manufacturer = cloud_print::LoadLocalString(IDS_GOOGLE); | 254 string16 manufacturer = cloud_print::LoadLocalString(IDS_GOOGLE); |
216 driver_info.pszMfgName = const_cast<LPWSTR>(manufacturer.c_str()); | 255 driver_info.pszMfgName = const_cast<LPWSTR>(manufacturer.c_str()); |
217 driver_info.pszProvider = const_cast<LPWSTR>(manufacturer.c_str()); | 256 driver_info.pszProvider = const_cast<LPWSTR>(manufacturer.c_str()); |
218 driver_info.pszOEMUrl = L"http://www.google.com/cloudprint"; | 257 driver_info.pszOEMUrl = L"http://www.google.com/cloudprint"; |
219 driver_info.dwlDriverVersion = GetVersionNumber(); | 258 driver_info.dwlDriverVersion = GetVersionNumber(); |
220 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 259 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); |
221 driver_info.pName = const_cast<LPWSTR>(driver_name.c_str()); | 260 driver_info.pName = const_cast<LPWSTR>(driver_name.c_str()); |
222 | 261 |
223 // Set up supported print system version. Must be 3. | 262 // Set up supported print system version. Must be 3. |
224 driver_info.cVersion = 3; | 263 driver_info.cVersion = 3; |
225 | 264 |
226 // TODO(abodenha@chromium.org) Properly handle dependencies. | |
227 // GPD files are often dependent on various Windows core drivers. | |
228 // I haven't found a reliable way to express those dependencies | |
229 // other than using an INF for installation. | |
230 if (!AddPrinterDriverEx(NULL, | 265 if (!AddPrinterDriverEx(NULL, |
231 6, | 266 6, |
232 reinterpret_cast<BYTE*>(&driver_info), | 267 reinterpret_cast<BYTE*>(&driver_info), |
233 APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY)) { | 268 APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY)) { |
234 result = cloud_print::GetLastHResult(); | 269 result = cloud_print::GetLastHResult(); |
235 LOG(ERROR) << "Unable to add printer driver"; | 270 LOG(ERROR) << "Unable to add printer driver"; |
236 return result; | |
237 } | 271 } |
238 return S_OK; | 272 return result; |
239 } | 273 } |
240 | 274 |
241 HRESULT UninstallPpd() { | 275 HRESULT UninstallPpd() { |
242 int tries = 10; | 276 int tries = 10; |
243 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); | 277 string16 driver_name = cloud_print::LoadLocalString(IDS_DRIVER_NAME); |
244 while (!DeletePrinterDriverEx(NULL, | 278 while (!DeletePrinterDriverEx(NULL, |
245 NULL, | 279 NULL, |
246 const_cast<LPWSTR>(driver_name.c_str()), | 280 const_cast<LPWSTR>(driver_name.c_str()), |
247 DPD_DELETE_UNUSED_FILES, | 281 DPD_DELETE_UNUSED_FILES, |
248 0) && tries > 0) { | 282 0) && tries > 0) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 if (!DeletePrinter(handle)) { | 336 if (!DeletePrinter(handle)) { |
303 HRESULT result = cloud_print::GetLastHResult(); | 337 HRESULT result = cloud_print::GetLastHResult(); |
304 LOG(ERROR) << "Unable to delete printer"; | 338 LOG(ERROR) << "Unable to delete printer"; |
305 ClosePrinter(handle); | 339 ClosePrinter(handle); |
306 return result; | 340 return result; |
307 } | 341 } |
308 ClosePrinter(handle); | 342 ClosePrinter(handle); |
309 return S_OK; | 343 return S_OK; |
310 } | 344 } |
311 | 345 |
312 HRESULT InstallVirtualDriver(void) { | 346 void SetupUninstall(const FilePath& install_path) { |
| 347 // Now write the Windows Uninstall entries |
| 348 // Minimal error checking here since the install can contiunue |
| 349 // if this fails. |
| 350 base::win::RegKey key; |
| 351 if (key.Create(HKEY_LOCAL_MACHINE, kUninstallRegistry, |
| 352 KEY_SET_VALUE) != ERROR_SUCCESS) { |
| 353 LOG(ERROR) << "Unable to open key"; |
| 354 return; |
| 355 } |
| 356 CommandLine uninstall_command(install_path.Append(kInstallerName)); |
| 357 uninstall_command.AppendArg("--uninstall"); |
| 358 key.WriteValue(L"UninstallString", |
| 359 uninstall_command.GetCommandLineString().c_str()); |
| 360 key.WriteValue(L"InstallLocation", install_path.value().c_str()); |
| 361 |
| 362 |
| 363 // Get the version resource. |
| 364 scoped_ptr<FileVersionInfo> version_info( |
| 365 FileVersionInfo::CreateFileVersionInfoForCurrentModule()); |
| 366 |
| 367 if (version_info.get()) { |
| 368 FileVersionInfoWin* version_info_win = |
| 369 static_cast<FileVersionInfoWin*>(version_info.get()); |
| 370 key.WriteValue(L"DisplayVersion", |
| 371 version_info_win->file_version().c_str()); |
| 372 key.WriteValue(L"Publisher", version_info_win->company_name().c_str()); |
| 373 } else { |
| 374 LOG(ERROR) << "Unable to get version string"; |
| 375 } |
| 376 key.WriteValue(L"DisplayName", |
| 377 cloud_print::LoadLocalString(IDS_DRIVER_NAME).c_str()); |
| 378 key.WriteValue(L"NoModify", 1); |
| 379 key.WriteValue(L"NoRepair", 1); |
| 380 } |
| 381 |
| 382 void CleanupUninstall() { |
| 383 ::RegDeleteKey(HKEY_LOCAL_MACHINE, kUninstallRegistry); |
| 384 } |
| 385 |
| 386 HRESULT InstallVirtualDriver(const FilePath& install_path) { |
313 HRESULT result = S_OK; | 387 HRESULT result = S_OK; |
314 result = RegisterPortMonitor(true); | 388 if (!file_util::CreateDirectory(install_path)) { |
| 389 LOG(ERROR) << "Can't create install directory"; |
| 390 return ERROR_ACCESS_DENIED; |
| 391 } |
| 392 SetupUninstall(install_path); |
| 393 result = RegisterPortMonitor(true, install_path); |
315 if (!SUCCEEDED(result)) { | 394 if (!SUCCEEDED(result)) { |
316 LOG(ERROR) << "Unable to register port monitor."; | 395 LOG(ERROR) << "Unable to register port monitor."; |
317 return result; | 396 return result; |
318 } | 397 } |
319 result = InstallPpd(); | 398 result = InstallPpd(install_path); |
320 if (!SUCCEEDED(result)) { | 399 if (!SUCCEEDED(result)) { |
321 LOG(ERROR) << "Unable to install Ppd."; | 400 LOG(ERROR) << "Unable to install Ppd."; |
322 return result; | 401 return result; |
323 } | 402 } |
324 result = InstallPrinter(); | 403 result = InstallPrinter(); |
325 if (!SUCCEEDED(result)) { | 404 if (!SUCCEEDED(result)) { |
326 LOG(ERROR) << "Unable to install printer."; | 405 LOG(ERROR) << "Unable to install printer."; |
327 return result; | 406 return result; |
328 } | 407 } |
329 SetRegistryKeys(); | 408 SetOmahaKeys(); |
330 return S_OK; | 409 return S_OK; |
331 } | 410 } |
332 | 411 |
333 HRESULT UninstallVirtualDriver(void) { | 412 HRESULT UninstallVirtualDriver(const FilePath& install_path) { |
334 HRESULT result = S_OK; | 413 HRESULT result = S_OK; |
335 result = UninstallPrinter(); | 414 result = UninstallPrinter(); |
336 if (!SUCCEEDED(result)) { | 415 if (!SUCCEEDED(result)) { |
337 LOG(ERROR) << "Unable to uninstall Ppd."; | 416 LOG(ERROR) << "Unable to uninstall Ppd."; |
338 return result; | 417 return result; |
339 } | 418 } |
340 result = UninstallPpd(); | 419 result = UninstallPpd(); |
341 if (!SUCCEEDED(result)) { | 420 if (!SUCCEEDED(result)) { |
342 LOG(ERROR) << "Unable to remove Ppd."; | 421 LOG(ERROR) << "Unable to remove Ppd."; |
343 return result; | 422 return result; |
344 } | 423 } |
345 result = RegisterPortMonitor(false); | 424 result = RegisterPortMonitor(false, install_path); |
346 if (!SUCCEEDED(result)) { | 425 if (!SUCCEEDED(result)) { |
347 LOG(ERROR) << "Unable to remove port monitor."; | 426 LOG(ERROR) << "Unable to remove port monitor."; |
348 return result; | 427 return result; |
349 } | 428 } |
350 DeleteRegistryKeys(); | 429 DeleteOmahaKeys(); |
| 430 file_util::Delete(install_path, true); |
| 431 CleanupUninstall(); |
351 return S_OK; | 432 return S_OK; |
352 } | 433 } |
353 | 434 |
| 435 HRESULT LaunchChildForUninstall() { |
| 436 FilePath installer_source; |
| 437 if (PathService::Get(base::FILE_EXE, &installer_source)) { |
| 438 FilePath temp_path; |
| 439 if (file_util::CreateTemporaryFile(&temp_path)) { |
| 440 file_util::Move(installer_source, temp_path); |
| 441 file_util::DeleteAfterReboot(temp_path); |
| 442 CommandLine command_line(temp_path); |
| 443 command_line.AppendArg("--douninstall"); |
| 444 base::LaunchOptions options; |
| 445 if (!base::LaunchProcess(command_line, options, NULL)) { |
| 446 LOG(ERROR) << "Unable to launch child uninstall."; |
| 447 return ERROR_NOT_SUPPORTED; |
| 448 } |
| 449 } |
| 450 } |
| 451 return S_OK; |
| 452 } |
354 } // namespace | 453 } // namespace |
355 | 454 |
356 int WINAPI WinMain(__in HINSTANCE hInstance, | 455 int WINAPI WinMain(__in HINSTANCE hInstance, |
357 __in HINSTANCE hPrevInstance, | 456 __in HINSTANCE hPrevInstance, |
358 __in LPSTR lpCmdLine, | 457 __in LPSTR lpCmdLine, |
359 __in int nCmdShow) { | 458 __in int nCmdShow) { |
360 base::AtExitManager at_exit_manager; | 459 base::AtExitManager at_exit_manager; |
361 CommandLine::Init(0, NULL); | 460 CommandLine::Init(0, NULL); |
362 HRESULT retval = S_OK; | 461 |
363 if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { | 462 FilePath install_path; |
364 retval = UninstallVirtualDriver(); | 463 HRESULT retval = PathService::Get(base::DIR_EXE, &install_path); |
365 } else { | 464 if (SUCCEEDED(retval)) { |
366 retval = InstallVirtualDriver(); | 465 if (CommandLine::ForCurrentProcess()->HasSwitch("douninstall")) { |
| 466 retval = UninstallVirtualDriver(install_path); |
| 467 } else if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { |
| 468 retval = LaunchChildForUninstall(); |
| 469 } else { |
| 470 retval = InstallVirtualDriver(install_path); |
| 471 } |
367 } | 472 } |
368 // Installer is silent by default as required by Omaha. | 473 // Installer is silent by default as required by Omaha. |
369 if (CommandLine::ForCurrentProcess()->HasSwitch("verbose")) { | 474 if (CommandLine::ForCurrentProcess()->HasSwitch("verbose")) { |
370 cloud_print::DisplayWindowsMessage(NULL, retval, | 475 cloud_print::DisplayWindowsMessage(NULL, retval, |
371 cloud_print::LoadLocalString(IDS_DRIVER_NAME)); | 476 cloud_print::LoadLocalString(IDS_DRIVER_NAME)); |
372 } | 477 } |
373 return retval; | 478 return retval; |
374 } | 479 } |
OLD | NEW |