Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(670)

Side by Side Diff: cloud_print/virtual_driver/win/install/setup.cc

Issue 14107007: Moved Google Update and install related code to cloud_print/common (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « cloud_print/common/win/install_utils.cc ('k') | cloud_print/virtual_driver/win/install/virtual_driver_install.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698