| Index: chrome/installer/setup/setup_util.cc
|
| diff --git a/chrome/installer/setup/setup_util.cc b/chrome/installer/setup/setup_util.cc
|
| index 7f0af711a95fcb73d42ea3a7ccce098c9eafc24b..b9575d02240b68b59d2ec4aad4f047e0ff133d7e 100644
|
| --- a/chrome/installer/setup/setup_util.cc
|
| +++ b/chrome/installer/setup/setup_util.cc
|
| @@ -7,6 +7,7 @@
|
| #include "chrome/installer/setup/setup_util.h"
|
|
|
| #include <windows.h>
|
| +#include <stdint.h>
|
|
|
| #include "base/command_line.h"
|
| #include "base/cpu.h"
|
| @@ -17,15 +18,21 @@
|
| #include "base/process/kill.h"
|
| #include "base/process/launch.h"
|
| #include "base/process/process_handle.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| #include "base/strings/string_util.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/version.h"
|
| #include "base/win/registry.h"
|
| +#include "base/win/win_util.h"
|
| #include "base/win/windows_version.h"
|
| #include "chrome/installer/setup/setup_constants.h"
|
| +#include "chrome/installer/setup/update_active_setup_version_work_item.h"
|
| +#include "chrome/installer/util/app_registration_data.h"
|
| #include "chrome/installer/util/app_registration_data.h"
|
| #include "chrome/installer/util/copy_tree_work_item.h"
|
| #include "chrome/installer/util/google_update_constants.h"
|
| +#include "chrome/installer/util/install_util.h"
|
| #include "chrome/installer/util/installation_state.h"
|
| #include "chrome/installer/util/installer_state.h"
|
| #include "chrome/installer/util/master_preferences.h"
|
| @@ -95,6 +102,104 @@ bool SupportsSingleInstall(BrowserDistribution::Type type) {
|
|
|
| } // namespace
|
|
|
| +bool UpdateLastOSUpgradeHandledByActiveSetup(BrowserDistribution* dist) {
|
| + // FIRST: Find the value of the latest OS upgrade registered in the Active
|
| + // Setup version (bumped on every major OS upgrade), defaults to 0 if no OS
|
| + // upgrade was ever encountered by this install.
|
| + DWORD latest_os_upgrade = 0;
|
| +
|
| + {
|
| + const base::string16 active_setup_key_path(
|
| + InstallUtil::GetActiveSetupPath(dist));
|
| +
|
| + base::win::RegKey active_setup_key;
|
| + if (active_setup_key.Open(HKEY_LOCAL_MACHINE, active_setup_key_path.c_str(),
|
| + KEY_QUERY_VALUE) == ERROR_SUCCESS) {
|
| + base::string16 existing_version;
|
| + if (active_setup_key.ReadValue(L"Version",
|
| + &existing_version) == ERROR_SUCCESS) {
|
| + std::vector<base::string16> version_components =
|
| + base::SplitString(existing_version, L",", base::TRIM_WHITESPACE,
|
| + base::SPLIT_WANT_NONEMPTY);
|
| + uint32_t latest_os_upgrade_uint = 0;
|
| + if (version_components.size() == 4U &&
|
| + base::StringToUint(
|
| + version_components[UpdateActiveSetupVersionWorkItem::
|
| + VersionComponent::OS_UPGRADES],
|
| + &latest_os_upgrade_uint)) {
|
| + latest_os_upgrade = static_cast<DWORD>(latest_os_upgrade_uint);
|
| + } else {
|
| + LOG(ERROR) << "Failed to parse OS_UPGRADES component of "
|
| + << existing_version;
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Whether the read failed or the existing value is 0, do not proceed.
|
| + if (latest_os_upgrade == 0U)
|
| + return false;
|
| +
|
| + static const wchar_t kLastOSUpgradeHandledRegName[] = L"LastOSUpgradeHandled";
|
| +
|
| + // SECOND: Find out the value of the last OS upgrade handled, defaults to 0 if
|
| + // none was ever handled.
|
| + DWORD last_os_upgrade_handled = 0;
|
| +
|
| + base::string16 last_upgrade_handled_key_path =
|
| + dist->GetAppRegistrationData().GetStateMediumKey();
|
| + last_upgrade_handled_key_path.push_back(L'\\');
|
| + last_upgrade_handled_key_path.append(kLastOSUpgradeHandledRegName);
|
| +
|
| + base::string16 user_specific_value;
|
| + // This should never fail. If it does, the beacon will be written in the key's
|
| + // default value, which is okay since the majority case is likely a machine
|
| + // with a single user.
|
| + if (!base::win::GetUserSidString(&user_specific_value))
|
| + NOTREACHED();
|
| +
|
| + base::win::RegKey last_upgrade_key;
|
| + if (last_upgrade_key.Create(
|
| + HKEY_LOCAL_MACHINE, last_upgrade_handled_key_path.c_str(),
|
| + KEY_WOW64_32KEY | KEY_QUERY_VALUE | KEY_SET_VALUE) != ERROR_SUCCESS) {
|
| + LOG(ERROR) << "Failed to create LastOSUpgradeHandled value @ "
|
| + << last_upgrade_handled_key_path;
|
| + // If the key is not read/writeable, do not proceed as this could result in
|
| + // handling an OS upgrade twice.
|
| + return false;
|
| + }
|
| +
|
| + // It's okay for this read to fail (i.e. there is an OS upgrade available but
|
| + // this user never handled one yet).
|
| + last_upgrade_key.ReadValueDW(user_specific_value.c_str(),
|
| + &last_os_upgrade_handled);
|
| +
|
| + // THIRD: Figure out whether the latest OS upgrade has been handled already.
|
| +
|
| + if (last_os_upgrade_handled >= latest_os_upgrade) {
|
| + LOG_IF(ERROR, last_os_upgrade_handled > latest_os_upgrade)
|
| + << "Last OS upgrade handled is somehow ahead of the latest OS upgrade?";
|
| + VLOG_IF(1, last_os_upgrade_handled == latest_os_upgrade)
|
| + << "Latest OS upgrade already handled.";
|
| + return false;
|
| + }
|
| +
|
| + // At this point |last_os_upgrade_handled < latest_os_upgrade| so,
|
| + // FOURTH: store the fact that the latest OS upgrade has been handled and
|
| + // return true for the caller to act accordingly.
|
| +
|
| + if (last_upgrade_key.WriteValue(user_specific_value.c_str(),
|
| + latest_os_upgrade) != ERROR_SUCCESS) {
|
| + LOG(ERROR) << "Failed to save latest_os_upgrade value ("
|
| + << latest_os_upgrade << ") to " << last_upgrade_handled_key_path;
|
| + // Do not proceed if the write fails as this could otherwise result in
|
| + // handling this OS upgrade multiple times.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| int CourgettePatchFiles(const base::FilePath& src,
|
| const base::FilePath& patch,
|
| const base::FilePath& dest) {
|
|
|