15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file declares util functions for setup project. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/setup_util.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/cpu.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 17a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/kill.h" 18a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 19a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h" 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/version.h" 23558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/win/registry.h" 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/win/windows_version.h" 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/installer/setup/setup_constants.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/copy_tree_work_item.h" 27558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/installer/util/google_update_constants.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installation_state.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installer_state.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/work_item.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "courgette/courgette.h" 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "courgette/third_party/bsdiff.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/bspatch/mbspatch.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace installer { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Launches |setup_exe| with |command_line|, save --install-archive and its 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value if present. Returns false if the process failed to launch. Otherwise, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// waits indefinitely for it to exit and populates |exit_code| as expected. On 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the off chance that waiting itself fails, |exit_code| is set to 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WAIT_FOR_EXISTING_FAILED. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LaunchAndWaitForExistingInstall(const base::FilePath& setup_exe, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& command_line, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* exit_code) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(exit_code); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine new_cl(setup_exe); 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over all switches but --install-archive. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::SwitchMap switches(command_line.GetSwitches()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches.erase(switches::kInstallArchive); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CommandLine::SwitchMap::const_iterator i = switches.begin(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != switches.end(); ++i) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i->second.empty()) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cl.AppendSwitch(i->first); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cl.AppendSwitchNative(i->first, i->second); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over all arguments. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::StringVector args(command_line.GetArgs()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CommandLine::StringVector::const_iterator i = args.begin(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != args.end(); ++i) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_cl.AppendArgNative(*i); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Launch the process and wait for it to exit. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Launching existing installer with command: " 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << new_cl.GetCommandLineString(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle handle = INVALID_HANDLE_VALUE; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::LaunchProcess(new_cl, base::LaunchOptions(), &handle)) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "Failed to launch existing installer with command: " 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << new_cl.GetCommandLineString(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::WaitForExitCode(handle, exit_code)) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(DFATAL) << "Failed to get exit code from existing installer"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *exit_code = WAIT_FOR_EXISTING_FAILED; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Existing installer returned exit code " << *exit_code; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if product |type| cam be meaningfully installed without the 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// --multi-install flag. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool SupportsSingleInstall(BrowserDistribution::Type type) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (type == BrowserDistribution::CHROME_BROWSER || 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) type == BrowserDistribution::CHROME_FRAME); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint CourgettePatchFiles(const base::FilePath& src, 98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& patch, 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& dest) { 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VLOG(1) << "Applying Courgette patch " << patch.value() 101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " to file " << src.value() 102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " and generating file " << dest.value(); 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (src.empty() || patch.empty() || dest.empty()) 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return installer::PATCH_INVALID_ARGUMENTS; 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const courgette::Status patch_status = 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch courgette::ApplyEnsemblePatch(src.value().c_str(), 109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch patch.value().c_str(), 110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dest.value().c_str()); 111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int exit_code = (patch_status != courgette::C_OK) ? 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch static_cast<int>(patch_status) + kCourgetteErrorOffset : 0; 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_IF(ERROR, exit_code) 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << "Failed to apply Courgette patch " << patch.value() 116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " to file " << src.value() << " and generating file " << dest.value() 117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << ". err=" << exit_code; 118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return exit_code; 120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint BsdiffPatchFiles(const base::FilePath& src, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& patch, 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const base::FilePath& dest) { 125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch VLOG(1) << "Applying bsdiff patch " << patch.value() 126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " to file " << src.value() 127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " and generating file " << dest.value(); 128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (src.empty() || patch.empty() || dest.empty()) 130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return installer::PATCH_INVALID_ARGUMENTS; 131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int patch_status = courgette::ApplyBinaryPatch(src, patch, dest); 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const int exit_code = patch_status != OK ? 134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch patch_status + kBsdiffErrorOffset : 0; 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG_IF(ERROR, exit_code) 137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << "Failed to apply bsdiff patch " << patch.value() 138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << " to file " << src.value() << " and generating file " << dest.value() 139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << ". err=" << exit_code; 140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return exit_code; 142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Version* GetMaxVersionFromArchiveDir(const base::FilePath& chrome_path) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Looking for Chrome version folder under " << chrome_path.value(); 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator version_enum(chrome_path, false, 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::DIRECTORIES); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(tommi): The version directory really should match the version of 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // setup.exe. To begin with, we should at least DCHECK that that's true. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Version> max_version(new Version("0.0.0.0")); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool version_found = false; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!version_enum.Next().empty()) { 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::FileInfo find_data = version_enum.GetInfo(); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) VLOG(1) << "directory found: " << find_data.GetName().value(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Version> found_version( 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new Version(base::UTF16ToASCII(find_data.GetName().value()))); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (found_version->IsValid() && 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_version->CompareTo(*max_version.get()) > 0) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_version.reset(found_version.release()); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_found = true; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (version_found ? max_version.release() : NULL); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbase::FilePath FindArchiveToPatch(const InstallationState& original_state, 171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const InstallerState& installer_state) { 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Check based on the version number advertised to Google Update, since that 173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // is the value used to select a specific differential update. If an archive 174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // can't be found using that, fallback to using the newest version present. 175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath patch_source; 176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const ProductState* product = 177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch original_state.GetProductState(installer_state.system_install(), 178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer_state.state_type()); 179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (product) { 180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch patch_source = installer_state.GetInstallerDirectory(product->version()) 181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .Append(installer::kChromeArchive); 182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (base::PathExists(patch_source)) 183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return patch_source; 184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch scoped_ptr<Version> version( 186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch installer::GetMaxVersionFromArchiveDir(installer_state.target_path())); 187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (version) { 188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch patch_source = installer_state.GetInstallerDirectory(*version) 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch .Append(installer::kChromeArchive); 190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (base::PathExists(patch_source)) 191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return patch_source; 192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return base::FilePath(); 194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DeleteFileFromTempProcess(const base::FilePath& path, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 delay_before_delete_ms) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const wchar_t kRunDll32Path[] = 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"%SystemRoot%\\System32\\rundll32.exe"; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t rundll32[MAX_PATH]; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD size = 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExpandEnvironmentStrings(kRunDll32Path, rundll32, arraysize(rundll32)); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!size || size >= MAX_PATH) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STARTUPINFO startup = { sizeof(STARTUPINFO) }; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROCESS_INFORMATION pi = {0}; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL ok = ::CreateProcess(NULL, rundll32, NULL, NULL, FALSE, CREATE_SUSPENDED, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, NULL, &startup, &pi); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ok) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use the main thread of the new process to run: 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sleep(delay_before_delete_ms); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DeleteFile(path); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExitProcess(0); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This runs before the main routine of the process runs, so it doesn't 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // matter much which executable we choose except that we don't want to 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use e.g. a console app that causes a window to be created. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = (path.value().length() + 1) * sizeof(path.value()[0]); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* mem = ::VirtualAllocEx(pi.hProcess, NULL, size, MEM_COMMIT, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAGE_READWRITE); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mem) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SIZE_T written = 0; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::WriteProcessMemory( 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pi.hProcess, mem, path.value().c_str(), 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (path.value().size() + 1) * sizeof(path.value()[0]), &written); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll"); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAPCFUNC sleep = reinterpret_cast<PAPCFUNC>( 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetProcAddress(kernel32, "Sleep")); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAPCFUNC delete_file = reinterpret_cast<PAPCFUNC>( 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetProcAddress(kernel32, "DeleteFileW")); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PAPCFUNC exit_process = reinterpret_cast<PAPCFUNC>( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::GetProcAddress(kernel32, "ExitProcess")); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sleep || !delete_file || !exit_process) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ok = FALSE; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::QueueUserAPC(sleep, pi.hThread, delay_before_delete_ms); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::QueueUserAPC(delete_file, pi.hThread, 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ULONG_PTR>(mem)); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::QueueUserAPC(exit_process, pi.hThread, 0); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::ResumeThread(pi.hThread); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "VirtualAllocEx"; 245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ::TerminateProcess(pi.hProcess, ~static_cast<UINT>(0)); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(pi.hThread); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ::CloseHandle(pi.hProcess); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ok != FALSE; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetExistingHigherInstaller( 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallationState& original_state, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool system_install, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& installer_version, 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath* setup_exe) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(setup_exe); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool trying_single_browser = false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProductState* existing_state = 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(system_install, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BINARIES); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!existing_state) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The binaries aren't installed, but perhaps a single-install Chrome is. 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trying_single_browser = true; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_state = 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) original_state.GetProductState(system_install, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserDistribution::CHROME_BROWSER); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!existing_state || 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) existing_state->version().CompareTo(installer_version) <= 0) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *setup_exe = existing_state->GetSetupPath(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG_IF(1, !setup_exe->empty()) << "Found a higher version of " 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << (trying_single_browser ? "single-install Chrome." 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : "multi-install Chrome binaries."); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !setup_exe->empty(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DeferToExistingInstall(const base::FilePath& setup_exe, 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CommandLine& command_line, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const InstallerState& installer_state, 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& temp_path, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallStatus* install_status) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy a master_preferences file if there is one. 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath prefs_source_path(command_line.GetSwitchValueNative( 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kInstallerData)); 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath prefs_dest_path(installer_state.target_path().AppendASCII( 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kDefaultMasterPrefs)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<WorkItem> copy_prefs(WorkItem::CreateCopyTreeWorkItem( 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs_source_path, prefs_dest_path, temp_path, WorkItem::ALWAYS, 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath())); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's nothing to rollback if the copy fails, so punt if so. 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!copy_prefs->Do()) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_prefs.reset(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code = 0; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LaunchAndWaitForExistingInstall(setup_exe, command_line, &exit_code)) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (copy_prefs) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy_prefs->Rollback(); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *install_status = static_cast<InstallStatus>(exit_code); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// There are 4 disjoint cases => return values {false,true}: 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (1) Product is being uninstalled => false. 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (2) Product is being installed => true. 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (3) Current operation ignores product, product is absent => false. 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// (4) Current operation ignores product, product is present => true. 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool WillProductBePresentAfterSetup( 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const installer::InstallerState& installer_state, 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const installer::InstallationState& machine_state, 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserDistribution::Type type) { 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(SupportsSingleInstall(type) || installer_state.is_multi_install()); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ProductState* product_state = 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) machine_state.GetProductState(installer_state.system_install(), type); 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Determine if the product is present prior to the current operation. 3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_present = (product_state != NULL); 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_uninstall = installer_state.operation() == InstallerState::UNINSTALL; 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Determine if current operation affects the product. 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Product* product = installer_state.FindProduct(type); 3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_affected = (product != NULL); 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Decide among {(1),(2),(3),(4)}. 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_affected ? !is_uninstall : is_present; 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool AdjustProcessPriority() { 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (base::win::GetVersion() >= base::win::VERSION_VISTA) { 341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DWORD priority_class = ::GetPriorityClass(::GetCurrentProcess()); 342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (priority_class == 0) { 343868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PLOG(WARNING) << "Failed to get the process's priority class."; 344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (priority_class == BELOW_NORMAL_PRIORITY_CLASS || 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) priority_class == IDLE_PRIORITY_CLASS) { 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BOOL result = ::SetPriorityClass(::GetCurrentProcess(), 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PROCESS_MODE_BACKGROUND_BEGIN); 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PLOG_IF(WARNING, !result) << "Failed to enter background mode."; 349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return !!result; 350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return false; 353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 355558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochvoid MigrateGoogleUpdateStateMultiToSingle( 356558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool system_level, 357558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch BrowserDistribution::Type to_migrate, 358558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const installer::InstallationState& machine_state) { 359558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 360558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const ProductState* product = NULL; 361558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch BrowserDistribution* dist = NULL; 362558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch LONG result = ERROR_SUCCESS; 363558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch base::win::RegKey state_key; 364558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 365558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Product product_to_migrate( 366558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch BrowserDistribution::GetSpecificDistribution(to_migrate)); 367558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 368558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Copy usagestats from the binaries to the product's ClientState key. 369558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch product = machine_state.GetProductState(system_level, 370558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch BrowserDistribution::CHROME_BINARIES); 371558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch DWORD usagestats = 0; 372558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (product && product->GetUsageStats(&usagestats)) { 373558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch dist = product_to_migrate.distribution(); 374558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch result = state_key.Open(root, dist->GetStateKey().c_str(), 375558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch KEY_SET_VALUE); 376558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (result != ERROR_SUCCESS) { 377558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch LOG(ERROR) << "Failed opening ClientState key for " 3783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) << dist->GetDisplayName() << " to migrate usagestats."; 379558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else { 380558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch state_key.WriteValue(google_update::kRegUsageStatsField, usagestats); 381558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 382558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 383558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 384558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Remove the migrating product from the "ap" value of other multi-install 385558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // products. 386558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (int i = 0; i < BrowserDistribution::NUM_TYPES; ++i) { 387558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch BrowserDistribution::Type type = 388558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch static_cast<BrowserDistribution::Type>(i); 389558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (type == to_migrate) 390558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch continue; 391558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch product = machine_state.GetProductState(system_level, type); 392558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (product && product->is_multi_install()) { 393558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch installer::ChannelInfo channel_info; 394558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch dist = BrowserDistribution::GetSpecificDistribution(type); 395558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch result = state_key.Open(root, dist->GetStateKey().c_str(), 396558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch KEY_QUERY_VALUE | KEY_SET_VALUE); 397558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (result == ERROR_SUCCESS && 398558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_info.Initialize(state_key) && 399558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch product_to_migrate.SetChannelFlags(false, &channel_info)) { 4003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) VLOG(1) << "Moving " << dist->GetDisplayName() 401558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch << " to channel: " << channel_info.value(); 402558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_info.Write(&state_key); 403558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 404558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 405558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 406558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 407558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Remove -multi, all product modifiers, and everything else but the channel 408558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // name from the "ap" value of the product to migrate. 409558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch dist = product_to_migrate.distribution(); 410558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch result = state_key.Open(root, dist->GetStateKey().c_str(), 411558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch KEY_QUERY_VALUE | KEY_SET_VALUE); 412558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (result == ERROR_SUCCESS) { 413558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch installer::ChannelInfo channel_info; 414558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!channel_info.Initialize(state_key)) { 4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "Failed reading " << dist->GetDisplayName() 416558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch << " channel info."; 417558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else if (channel_info.RemoveAllModifiersAndSuffixes()) { 4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) VLOG(1) << "Moving " << dist->GetDisplayName() 419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch << " to channel: " << channel_info.value(); 420558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_info.Write(&state_key); 421558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 422558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 423558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 424558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsUninstallSuccess(InstallStatus install_status) { 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The following status values represent failed uninstalls: 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 15: CHROME_NOT_INSTALLED 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 20: UNINSTALL_FAILED 4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // 21: UNINSTALL_CANCELLED 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return (install_status == UNINSTALL_SUCCESSFUL || 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) install_status == UNINSTALL_REQUIRES_REBOOT); 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ContainsUnsupportedSwitch(const CommandLine& cmd_line) { 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const char* const kLegacySwitches[] = { 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome Frame ready-mode. 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ready-mode", 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ready-mode-opt-in", 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ready-mode-temp-opt-out", 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "ready-mode-end-temp-opt-out", 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Chrome Frame quick-enable. 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "quick-enable-cf", 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Installation of Chrome Frame. 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "chrome-frame", 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "migrate-chrome-frame", 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) }; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (size_t i = 0; i < arraysize(kLegacySwitches); ++i) { 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (cmd_line.HasSwitch(kLegacySwitches[i])) 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool IsProcessorSupported() { 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return base::CPU().has_sse2(); 456a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedTokenPrivilege::ScopedTokenPrivilege(const wchar_t* privilege_name) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : is_enabled_(false) { 460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) HANDLE temp_handle; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::OpenProcessToken(::GetCurrentProcess(), 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &temp_handle)) { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) token_.Set(temp_handle); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LUID privilege_luid; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::LookupPrivilegeValue(NULL, privilege_name, &privilege_luid)) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_.Close(); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Adjust the token's privileges to enable |privilege_name|. If this privilege 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was already enabled, |previous_privileges_|.PrivilegeCount will be set to 0 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and we then know not to disable this privilege upon destruction. 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TOKEN_PRIVILEGES tp; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp.PrivilegeCount = 1; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp.Privileges[0].Luid = privilege_luid; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD return_length; 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!::AdjustTokenPrivileges(token_.Get(), FALSE, &tp, 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sizeof(TOKEN_PRIVILEGES), 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &previous_privileges_, &return_length)) { 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_.Close(); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_enabled_ = true; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedTokenPrivilege::~ScopedTokenPrivilege() { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_enabled_ && previous_privileges_.PrivilegeCount != 0) { 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ::AdjustTokenPrivileges(token_.Get(), FALSE, &previous_privileges_, 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(TOKEN_PRIVILEGES), NULL, NULL); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace installer 500