diff options
author | abodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 20:03:15 +0000 |
---|---|---|
committer | abodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-12 20:03:15 +0000 |
commit | b52c85433a02fae561d9d8f9a6a3d8fa0adb3ea8 (patch) | |
tree | 47023713f1498f9707c07d701b540d400bb24833 /cloud_print | |
parent | d9166c917084dbdc96df0cea7b5d926f24f4e990 (diff) | |
download | chromium_src-b52c85433a02fae561d9d8f9a6a3d8fa0adb3ea8.zip chromium_src-b52c85433a02fae561d9d8f9a6a3d8fa0adb3ea8.tar.gz chromium_src-b52c85433a02fae561d9d8f9a6a3d8fa0adb3ea8.tar.bz2 |
Modify overinstall flow for Google Cloud Printer to uninstall any previous version before installing.
The new flow retrieves the location of the uninstall exe from the registry and copies it to a temp location. It marks the temp uninstaller for deletion on reboot and then launches it and waits for it to exit.
Installation will proceed if there was no previous install or the uninstall succeeded.
BUG=123091
TEST=Verify 123091
Review URL: http://codereview.chromium.org/10054040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132037 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print')
-rw-r--r-- | cloud_print/virtual_driver/win/install/setup.cc | 79 |
1 files changed, 64 insertions, 15 deletions
diff --git a/cloud_print/virtual_driver/win/install/setup.cc b/cloud_print/virtual_driver/win/install/setup.cc index 98010d6..82dc313 100644 --- a/cloud_print/virtual_driver/win/install/setup.cc +++ b/cloud_print/virtual_driver/win/install/setup.cc @@ -12,6 +12,7 @@ #include "base/file_version_info_win.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/process.h" #include "base/process_util.h" #include "base/string16.h" #include "base/win/registry.h" @@ -120,14 +121,18 @@ HRESULT RegisterPortMonitor(bool install, const FilePath& install_path) { } string16 source; source = cloud_print::GetPortMonitorDllName(); + FilePath source_path = install_path.Append(source); if (install) { - FilePath source_path = install_path.Append(source); if (!file_util::CopyFileW(source_path, target_path)) { LOG(ERROR) << "Unable copy port monitor dll from " << source_path.value() << " to " << target_path.value(); return ERROR_ACCESS_DENIED; } + } else if (!file_util::PathExists(source_path)) { + // Already removed. Just "succeed" silently. + return S_OK; } + FilePath regsvr32_path; result = GetRegsvr32Path(®svr32_path); if (!SUCCEEDED(result)) { @@ -187,7 +192,7 @@ DWORDLONG GetVersionNumber() { VS_FIXEDFILEINFO* fixed_file_info = version_info_win->fixed_file_info(); retval = fixed_file_info->dwFileVersionMS; retval <<= 32; - retval |= fixed_file_info->dwFileVersionMS; + retval |= fixed_file_info->dwFileVersionLS; } return retval; } @@ -461,6 +466,11 @@ HRESULT UninstallVirtualDriver(const FilePath& install_path) { result = UninstallPpd(); if (!SUCCEEDED(result)) { LOG(ERROR) << "Unable to remove Ppd."; + // Put the printer back since we're not able to + // complete the uninstallation. + // TODO(abodenha@chromium.org) Figure out a better way to recover. + // See http://code.google.com/p/chromium/issues/detail?id=123039 + InstallPrinter(); return result; } result = RegisterPortMonitor(false, install_path); @@ -474,24 +484,60 @@ HRESULT UninstallVirtualDriver(const FilePath& install_path) { return S_OK; } +HRESULT DoLaunchUninstall(const FilePath& installer_source, bool wait) { + FilePath temp_path; + if (file_util::CreateTemporaryFile(&temp_path)) { + file_util::CopyFile(installer_source, temp_path); + file_util::DeleteAfterReboot(temp_path); + CommandLine command_line(temp_path); + command_line.AppendArg("--douninstall"); + base::LaunchOptions options; + options.wait = wait; + base::ProcessHandle process_handle; + if (!base::LaunchProcess(command_line, options, &process_handle)) { + LOG(ERROR) << "Unable to launch child uninstall."; + return ERROR_NOT_SUPPORTED; + } + if (wait) { + int exit_code = -1; + base::TerminationStatus status = + base::GetTerminationStatus(process_handle, &exit_code); + if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION) { + return exit_code; + } else { + LOG(ERROR) << "Improper termination of uninstall. " << status; + return E_FAIL; + } + } + } + return S_OK; +} + HRESULT LaunchChildForUninstall() { FilePath installer_source; if (PathService::Get(base::FILE_EXE, &installer_source)) { - FilePath temp_path; - if (file_util::CreateTemporaryFile(&temp_path)) { - file_util::Move(installer_source, temp_path); - file_util::DeleteAfterReboot(temp_path); - CommandLine command_line(temp_path); - command_line.AppendArg("--douninstall"); - base::LaunchOptions options; - if (!base::LaunchProcess(command_line, options, NULL)) { - LOG(ERROR) << "Unable to launch child uninstall."; - return ERROR_NOT_SUPPORTED; - } - } + return DoLaunchUninstall(installer_source, false); + } + return S_OK; +} + +HRESULT UninstallPreviousVersion() { + base::win::RegKey key; + if (key.Open(HKEY_LOCAL_MACHINE, kUninstallRegistry, + KEY_QUERY_VALUE) != ERROR_SUCCESS) { + // Not installed. + return S_OK; + } + string16 install_path; + key.ReadValue(L"InstallLocation", &install_path); + FilePath installer_source(install_path); + installer_source = installer_source.Append(kInstallerName); + if (file_util::PathExists(installer_source)) { + return DoLaunchUninstall(installer_source, true); } return S_OK; } + } // namespace int WINAPI WinMain(__in HINSTANCE hInstance, @@ -509,7 +555,10 @@ int WINAPI WinMain(__in HINSTANCE hInstance, } else if (CommandLine::ForCurrentProcess()->HasSwitch("uninstall")) { retval = LaunchChildForUninstall(); } else { - retval = InstallVirtualDriver(install_path); + retval = UninstallPreviousVersion(); + if (SUCCEEDED(retval)) { + retval = InstallVirtualDriver(install_path); + } } } // Installer is silent by default as required by Omaha. |