// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file declares util functions for setup project.

#include "chrome/installer/setup/setup_util.h"

#include <objbase.h>
#include <stddef.h>
#include <windows.h>
#include <wtsapi32.h>

#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <set>
#include <string>
#include <utility>

#include "base/base64.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/cpu.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.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 "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/install_static/install_details.h"
#include "chrome/install_static/install_modes.h"
#include "chrome/install_static/install_util.h"
#include "chrome/installer/setup/installer_state.h"
#include "chrome/installer/setup/setup_constants.h"
#include "chrome/installer/setup/user_hive_visitor.h"
#include "chrome/installer/util/google_update_constants.h"
#include "chrome/installer/util/google_update_settings.h"
#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/installation_state.h"
#include "chrome/installer/util/master_preferences.h"
#include "chrome/installer/util/master_preferences_constants.h"
#include "chrome/installer/util/util_constants.h"
#include "chrome/installer/util/work_item.h"
#include "chrome/installer/util/work_item_list.h"
#include "components/zucchini/zucchini.h"
#include "components/zucchini/zucchini_integration.h"
#include "courgette/courgette.h"
#include "courgette/third_party/bsdiff/bsdiff.h"

namespace installer {

namespace {

// Event log providers registry location.
constexpr wchar_t kEventLogProvidersRegPath[] =
    L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";

// Remove the registration of the browser's DelegateExecute verb handler class.
// This was once registered in support of "metro" mode on Windows 8.
void RemoveLegacyIExecuteCommandKey(const InstallerState& installer_state) {
  const base::string16 handler_class_uuid =
      install_static::GetLegacyCommandExecuteImplClsid();

  // No work to do if this mode of install never registered a DelegateExecute
  // verb handler.
  if (handler_class_uuid.empty())
    return;

  const HKEY root = installer_state.root_key();
  base::string16 delegate_execute_path(L"Software\\Classes\\CLSID\\");
  delegate_execute_path.append(handler_class_uuid);

  // Delete both 64 and 32 keys to handle 32->64 or 64->32 migration.
  for (REGSAM bitness : {KEY_WOW64_32KEY, KEY_WOW64_64KEY}) {
    if (base::win::RegKey(root, delegate_execute_path.c_str(),
                          KEY_QUERY_VALUE | bitness)
            .Valid()) {
      const bool success =
          InstallUtil::DeleteRegistryKey(root, delegate_execute_path, bitness);
      UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteIExecuteCommandClassKey",
                            success);
    }
  }
}

// Remove the registration of profile statistics. This used to be reported to
// Omaha, but no more.
void RemoveProfileStatistics(const InstallerState& installer_state) {
  const HKEY root = installer_state.root_key();
  bool found = false;
  bool deleted = true;
  if (installer_state.system_install()) {
    for (base::string16 key : {L"_NumAccounts", L"_NumSignedIn"}) {
      base::string16 path(install_static::GetClientStateMediumKeyPath() +
                          L"\\" + key);
      if (base::win::RegKey(root, path.c_str(),
                            KEY_QUERY_VALUE | KEY_WOW64_32KEY)
              .Valid()) {
        found = true;
        if (!InstallUtil::DeleteRegistryKey(root, path, KEY_WOW64_32KEY))
          deleted = false;
      }
    }
  } else {
    base::win::RegKey client_state;
    if (client_state.Open(root, install_static::GetClientStateKeyPath().c_str(),
                          KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_WOW64_32KEY) ==
        ERROR_SUCCESS) {
      for (const base::char16* value : {STRING16_LITERAL("_NumAccounts"),
                                        STRING16_LITERAL("_NumSignedIn"})) {
          if (!client_state.HasValue(value))
            continue;
          found = true;
          if (client_state.DeleteValue(value) != ERROR_SUCCESS)
            deleted = false;
        }
    }
  }
  if (found)
    UMA_HISTOGRAM_BOOLEAN("Setup.Install.RemoveProfileStatistics", deleted);
}

// "The binaries" once referred to the on-disk footprint of Chrome and/or Chrome
// Frame when the products were configured to share such on-disk bits. Support
// for this mode of install was dropped from ToT in December 2016. Remove any
// stray bits in the registry leftover from such installs.
void RemoveBinariesVersionKey(const InstallerState& installer_state) {
  base::string16 path(install_static::GetBinariesClientsKeyPath());
  if (base::win::RegKey(installer_state.root_key(), path.c_str(),
                        KEY_QUERY_VALUE | KEY_WOW64_32KEY)
          .Valid()) {
    const bool success = InstallUtil::DeleteRegistryKey(
        installer_state.root_key(), path, KEY_WOW64_32KEY);
    UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteBinariesClientsKey", success);
  }
}

// Remove leftover traces of multi-install Chrome Frame, if present. Once upon a
// time, Google Chrome Frame could be co-installed with Chrome such that they
// shared the same binaries on disk. Support for new installs of GCF was dropped
// from ToT in December 2013. Remove any stray bits in the registry leftover
// from an old multi-install GCF.
void RemoveMultiChromeFrame(const InstallerState& installer_state) {
// There never was a "Chromium Frame".
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  // To maximize cleanup, unconditionally delete GCF's Clients and ClientState
  // keys unless single-install GCF is present. This condition is satisfied if
  // both keys exist, Clients\pv contains a value, and
  // ClientState\UninstallString contains a path including "\Chrome Frame\".
  // Multi-install GCF would have had "\Chrome\", and anything else is garbage.

  static constexpr wchar_t kGcfGuid[] =
      L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
  base::string16 clients_key_path = install_static::GetClientsKeyPath(kGcfGuid);
  base::win::RegKey clients_key;
  base::string16 client_state_key_path =
      install_static::GetClientStateKeyPath(kGcfGuid);
  base::win::RegKey client_state_key;

  const bool has_clients_key =
      clients_key.Open(installer_state.root_key(), clients_key_path.c_str(),
                       KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
  const bool has_client_state_key =
      client_state_key.Open(installer_state.root_key(),
                            client_state_key_path.c_str(),
                            KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS;
  if (!has_clients_key && !has_client_state_key)
    return;  // Nothing to check or to clean.

  base::string16 value;
  if (has_clients_key && has_client_state_key &&
      clients_key.ReadValue(google_update::kRegVersionField, &value) ==
          ERROR_SUCCESS &&
      !value.empty() &&
      client_state_key.ReadValue(kUninstallStringField, &value) ==
          ERROR_SUCCESS &&
      value.find(L"\\Chrome Frame\\") != base::string16::npos) {
    return;  // Single-install Chrome Frame found.
  }
  client_state_key.Close();
  clients_key.Close();

  // Remnants of multi-install GCF or of a malformed GCF are present. Remove the
  // Clients and ClientState keys so that Google Update ceases to check for
  // updates, and the Programs and Features control panel entry to reduce user
  // confusion.
  constexpr int kOperations = 3;
  int success_count = 0;

  if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
                                     clients_key_path, KEY_WOW64_32KEY)) {
    ++success_count;
  }
  if (InstallUtil::DeleteRegistryKey(installer_state.root_key(),
                                     client_state_key_path, KEY_WOW64_32KEY)) {
    ++success_count;
  }
  if (InstallUtil::DeleteRegistryKey(
          installer_state.root_key(),
          L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"
          L"Google Chrome Frame",
          KEY_WOW64_32KEY)) {
    ++success_count;
  }
  DCHECK_LE(success_count, kOperations);

  // Used for a histogram; do not reorder.
  enum MultiChromeFrameRemovalResult {
    ALL_FAILED = 0,
    PARTIAL_SUCCESS = 1,
    SUCCESS = 2,
    NUM_RESULTS
  };
  MultiChromeFrameRemovalResult result =
      (success_count == kOperations ? SUCCESS : (success_count ? PARTIAL_SUCCESS
                                                               : ALL_FAILED));
  UMA_HISTOGRAM_ENUMERATION("Setup.Install.MultiChromeFrameRemoved", result,
                            NUM_RESULTS);
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

void RemoveAppLauncherVersionKey(const InstallerState& installer_state) {
// The app launcher was only registered for Google Chrome.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  static constexpr wchar_t kLauncherGuid[] =
      L"{FDA71E6F-AC4C-4a00-8B70-9958A68906BF}";

  base::string16 path = install_static::GetClientsKeyPath(kLauncherGuid);
  if (base::win::RegKey(installer_state.root_key(), path.c_str(),
                        KEY_QUERY_VALUE | KEY_WOW64_32KEY)
          .Valid()) {
    const bool succeeded = InstallUtil::DeleteRegistryKey(
        installer_state.root_key(), path, KEY_WOW64_32KEY);
    UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppLauncherClientsKey",
                          succeeded);
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

void RemoveAppHostExe(const InstallerState& installer_state) {
// The app host was only installed for Google Chrome.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  base::FilePath app_host(
      installer_state.target_path().Append(FILE_PATH_LITERAL("app_host.exe")));

  if (base::PathExists(app_host)) {
    const bool succeeded = base::DeleteFile(app_host, false);
    UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteAppHost", succeeded);
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

void RemoveLegacyChromeAppCommands(const InstallerState& installer_state) {
// These app commands were only registered for Google Chrome.
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  base::string16 path(GetCommandKey(L"install-extension"));

  if (base::win::RegKey(installer_state.root_key(), path.c_str(),
                        KEY_QUERY_VALUE | KEY_WOW64_32KEY)
          .Valid()) {
    const bool succeeded = InstallUtil::DeleteRegistryKey(
        installer_state.root_key(), path, KEY_WOW64_32KEY);
    UMA_HISTOGRAM_BOOLEAN("Setup.Install.DeleteInstallExtensionCommand",
                          succeeded);
  }
#endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
}

}  // namespace

const char kUnPackNTSTATUSMetricsName[] = "Setup.Install.LzmaUnPackNTSTATUS";
const char kUnPackResultMetricsName[] = "Setup.Install.LzmaUnPackResult";
const char kUnPackStatusMetricsName[] = "Setup.Install.LzmaUnPackStatus";

int CourgettePatchFiles(const base::FilePath& src,
                        const base::FilePath& patch,
                        const base::FilePath& dest) {
  VLOG(1) << "Applying Courgette patch " << patch.value()
          << " to file " << src.value()
          << " and generating file " << dest.value();

  if (src.empty() || patch.empty() || dest.empty())
    return installer::PATCH_INVALID_ARGUMENTS;

  const courgette::Status patch_status =
      courgette::ApplyEnsemblePatch(src.value().c_str(),
                                    patch.value().c_str(),
                                    dest.value().c_str());
  const int exit_code = (patch_status != courgette::C_OK) ?
      static_cast<int>(patch_status) + kCourgetteErrorOffset : 0;

  LOG_IF(ERROR, exit_code)
      << "Failed to apply Courgette patch " << patch.value()
      << " to file " << src.value() << " and generating file " << dest.value()
      << ". err=" << exit_code;

  return exit_code;
}

int BsdiffPatchFiles(const base::FilePath& src,
                     const base::FilePath& patch,
                     const base::FilePath& dest) {
  VLOG(1) << "Applying bsdiff patch " << patch.value()
          << " to file " << src.value()
          << " and generating file " << dest.value();

  if (src.empty() || patch.empty() || dest.empty())
    return installer::PATCH_INVALID_ARGUMENTS;

  const int patch_status = bsdiff::ApplyBinaryPatch(src, patch, dest);
  const int exit_code = patch_status != bsdiff::OK ?
                        patch_status + kBsdiffErrorOffset : 0;

  LOG_IF(ERROR, exit_code)
      << "Failed to apply bsdiff patch " << patch.value()
      << " to file " << src.value() << " and generating file " << dest.value()
      << ". err=" << exit_code;

  return exit_code;
}

int ZucchiniPatchFiles(const base::FilePath& src,
                       const base::FilePath& patch,
                       const base::FilePath& dest) {
  VLOG(1) << "Applying Zucchini patch " << patch.value() << " to file "
          << src.value() << " and generating file " << dest.value();

  if (src.empty() || patch.empty() || dest.empty())
    return installer::PATCH_INVALID_ARGUMENTS;

  const zucchini::status::Code patch_status = zucchini::Apply(src, patch, dest);
  const int exit_code =
      (patch_status != zucchini::status::kStatusSuccess)
          ? static_cast<int>(patch_status) + kZucchiniErrorOffset
          : 0;

  LOG_IF(ERROR, exit_code) << "Failed to apply Zucchini patch " << patch.value()
                           << " to file " << src.value()
                           << " and generating file " << dest.value()
                           << ". err=" << exit_code;

  return exit_code;
}

base::Version* GetMaxVersionFromArchiveDir(const base::FilePath& chrome_path) {
  VLOG(1) << "Looking for Chrome version folder under " << chrome_path.value();
  base::FileEnumerator version_enum(chrome_path, false,
      base::FileEnumerator::DIRECTORIES);
  // TODO(tommi): The version directory really should match the version of
  // setup.exe.  To begin with, we should at least DCHECK that that's true.

  std::unique_ptr<base::Version> max_version(new base::Version("0.0.0.0"));
  bool version_found = false;

  while (!version_enum.Next().empty()) {
    base::FileEnumerator::FileInfo find_data = version_enum.GetInfo();
    VLOG(1) << "directory found: " << find_data.GetName().value();

    std::unique_ptr<base::Version> found_version(
        new base::Version(base::UTF16ToASCII(find_data.GetName().value())));
    if (found_version->IsValid() &&
        found_version->CompareTo(*max_version.get()) > 0) {
      max_version = std::move(found_version);
      version_found = true;
    }
  }

  return (version_found ? max_version.release() : NULL);
}

base::FilePath FindArchiveToPatch(const InstallationState& original_state,
                                  const InstallerState& installer_state,
                                  const base::Version& desired_version) {
  if (desired_version.IsValid()) {
    base::FilePath archive(installer_state.GetInstallerDirectory(
        desired_version).Append(kChromeArchive));
    return base::PathExists(archive) ? archive : base::FilePath();
  }

  // Check based on the version number advertised to Google Update, since that
  // is the value used to select a specific differential update. If an archive
  // can't be found using that, fallback to using the newest version present.
  base::FilePath patch_source;
  const ProductState* product =
      original_state.GetProductState(installer_state.system_install());
  if (product) {
    patch_source = installer_state.GetInstallerDirectory(product->version())
        .Append(installer::kChromeArchive);
    if (base::PathExists(patch_source))
      return patch_source;
  }
  std::unique_ptr<base::Version> version(
      installer::GetMaxVersionFromArchiveDir(installer_state.target_path()));
  if (version) {
    patch_source = installer_state.GetInstallerDirectory(*version)
        .Append(installer::kChromeArchive);
    if (base::PathExists(patch_source))
      return patch_source;
  }
  return base::FilePath();
}

bool DeleteFileFromTempProcess(const base::FilePath& path,
                               uint32_t delay_before_delete_ms) {
  static const wchar_t kRunDll32Path[] =
      L"%SystemRoot%\\System32\\rundll32.exe";
  wchar_t rundll32[MAX_PATH];
  DWORD size =
      ExpandEnvironmentStrings(kRunDll32Path, rundll32, base::size(rundll32));
  if (!size || size >= MAX_PATH)
    return false;

  STARTUPINFO startup = { sizeof(STARTUPINFO) };
  PROCESS_INFORMATION pi = {0};
  BOOL ok = ::CreateProcess(NULL, rundll32, NULL, NULL, FALSE, CREATE_SUSPENDED,
                            NULL, NULL, &startup, &pi);
  if (ok) {
    // We use the main thread of the new process to run:
    //   Sleep(delay_before_delete_ms);
    //   DeleteFile(path);
    //   ExitProcess(0);
    // This runs before the main routine of the process runs, so it doesn't
    // matter much which executable we choose except that we don't want to
    // use e.g. a console app that causes a window to be created.
    size = static_cast<DWORD>(
        (path.value().length() + 1) * sizeof(path.value()[0]));
    void* mem = ::VirtualAllocEx(pi.hProcess, NULL, size, MEM_COMMIT,
                                 PAGE_READWRITE);
    if (mem) {
      SIZE_T written = 0;
      ::WriteProcessMemory(
          pi.hProcess, mem, path.value().c_str(),
          (path.value().size() + 1) * sizeof(path.value()[0]), &written);
      HMODULE kernel32 = ::GetModuleHandle(L"kernel32.dll");
      PAPCFUNC sleep = reinterpret_cast<PAPCFUNC>(
          ::GetProcAddress(kernel32, "Sleep"));
      PAPCFUNC delete_file = reinterpret_cast<PAPCFUNC>(
          ::GetProcAddress(kernel32, "DeleteFileW"));
      PAPCFUNC exit_process = reinterpret_cast<PAPCFUNC>(
          ::GetProcAddress(kernel32, "ExitProcess"));
      if (!sleep || !delete_file || !exit_process) {
        NOTREACHED();
        ok = FALSE;
      } else {
        ::QueueUserAPC(sleep, pi.hThread, delay_before_delete_ms);
        ::QueueUserAPC(delete_file, pi.hThread,
                       reinterpret_cast<ULONG_PTR>(mem));
        ::QueueUserAPC(exit_process, pi.hThread, 0);
        ::ResumeThread(pi.hThread);
      }
    } else {
      PLOG(ERROR) << "VirtualAllocEx";
      ::TerminateProcess(pi.hProcess, ~static_cast<UINT>(0));
    }
    ::CloseHandle(pi.hThread);
    ::CloseHandle(pi.hProcess);
  }

  return ok != FALSE;
}

bool AdjustProcessPriority() {
  DWORD priority_class = ::GetPriorityClass(::GetCurrentProcess());
  if (priority_class == BELOW_NORMAL_PRIORITY_CLASS ||
      priority_class == IDLE_PRIORITY_CLASS) {
    BOOL result = ::SetPriorityClass(::GetCurrentProcess(),
                                     PROCESS_MODE_BACKGROUND_BEGIN);
    PLOG_IF(WARNING, !result) << "Failed to enter background mode.";
    return !!result;
  }

  if (priority_class == 0)
    PLOG(WARNING) << "Failed to get the process's priority class.";

  return false;
}

bool IsUninstallSuccess(InstallStatus install_status) {
  // The following status values represent failed uninstalls:
  // 15: CHROME_NOT_INSTALLED
  // 20: UNINSTALL_FAILED
  // 21: UNINSTALL_CANCELLED
  return (install_status == UNINSTALL_SUCCESSFUL ||
          install_status == UNINSTALL_REQUIRES_REBOOT);
}

bool ContainsUnsupportedSwitch(const base::CommandLine& cmd_line) {
  static const char* const kLegacySwitches[] = {
    // Chrome Frame ready-mode.
    "ready-mode",
    "ready-mode-opt-in",
    "ready-mode-temp-opt-out",
    "ready-mode-end-temp-opt-out",
    // Chrome Frame quick-enable.
    "quick-enable-cf",
    // Installation of Chrome Frame.
    "chrome-frame",
    "migrate-chrome-frame",
    // Stand-alone App Launcher.
    "app-host",
    "app-launcher",
  };
  for (size_t i = 0; i < base::size(kLegacySwitches); ++i) {
    if (cmd_line.HasSwitch(kLegacySwitches[i]))
      return true;
  }
  return false;
}

bool IsProcessorSupported() {
#if defined(ARCH_CPU_X86_FAMILY)
  return base::CPU().has_sse2();
#elif defined(ARCH_CPU_ARM64)
  return true;
#else
#error Port
#endif
}

base::string16 GetCommandKey(const wchar_t* name) {
  base::string16 cmd_key = install_static::GetClientsKeyPath();
  cmd_key.append(1, base::FilePath::kSeparators[0])
      .append(google_update::kRegCommandsKey)
      .append(1, base::FilePath::kSeparators[0])
      .append(name);
  return cmd_key;
}

void DeleteRegistryKeyPartial(
    HKEY root,
    const base::string16& path,
    const std::vector<base::string16>& keys_to_preserve) {
  // Downcase the list of keys to preserve (all must be ASCII strings).
  std::set<base::string16> lowered_keys_to_preserve;
  std::transform(
      keys_to_preserve.begin(), keys_to_preserve.end(),
      std::inserter(lowered_keys_to_preserve, lowered_keys_to_preserve.begin()),
      [](const base::string16& str) {
        DCHECK(!str.empty());
        DCHECK(base::IsStringASCII(str));
        return base::ToLowerASCII(str);
      });
  base::win::RegKey key;
  LONG result = key.Open(root, path.c_str(), (KEY_ENUMERATE_SUB_KEYS |
                                              KEY_QUERY_VALUE | KEY_SET_VALUE));
  if (result != ERROR_SUCCESS) {
    LOG_IF(ERROR, result != ERROR_FILE_NOT_FOUND) << "Failed to open " << path
                                                  << "; result = " << result;
    return;
  }

  // Repeatedly iterate over all subkeys deleting those that should not be
  // preserved until only those remain. Multiple passes are needed since
  // deleting one key may change the enumeration order of all remaining keys.

  // Subkeys or values to be skipped on subsequent passes.
  std::set<base::string16> to_skip;
  DWORD index = 0;
  const size_t kMaxKeyNameLength = 256;  // MSDN says 255; +1 for terminator.
  base::string16 name(kMaxKeyNameLength, base::char16());
  bool did_delete = false;  // True if at least one item was deleted.
  while (true) {
    DWORD name_length = base::saturated_cast<DWORD>(name.capacity());
    name.resize(name_length);
    result = ::RegEnumKeyEx(key.Handle(), index, &name[0], &name_length,
                            nullptr, nullptr, nullptr, nullptr);
    if (result == ERROR_MORE_DATA) {
      // Unexpected, but perhaps the max key name length was raised. MSDN
      // doesn't clearly say that name_length will contain the necessary
      // length in this case, so double the buffer and try again.
      name.reserve(name.capacity() * 2);
      continue;
    }
    if (result == ERROR_NO_MORE_ITEMS) {
      if (!did_delete)
        break;  // All subkeys were deleted. The job is done.
      // Otherwise, loop again.
      did_delete = false;
      index = 0;
      continue;
    }
    if (result != ERROR_SUCCESS)
      break;
    // Shrink the string to the actual length of the name.
    name.resize(name_length);

    // Skip over this key if it couldn't be deleted on a previous iteration.
    if (to_skip.count(name)) {
      ++index;
      continue;
    }

    // Skip over this key if it is one of the keys to preserve.
    if (base::IsStringASCII(name) &&
        lowered_keys_to_preserve.count(base::ToLowerASCII(name))) {
      // Add the true name of the key to the list of keys to skip for subsequent
      // iterations.
      to_skip.insert(name);
      ++index;
      continue;
    }

    // Delete this key.
    result = key.DeleteKey(name.c_str());
    if (result != ERROR_SUCCESS) {
      LOG(ERROR) << "Failed to delete subkey " << name << " under path "
                 << path;
      // Skip over this key on subsequent iterations.
      to_skip.insert(name);
      ++index;
      continue;
    }
    did_delete = true;
  }

  // Delete the key if it no longer has any subkeys.
  if (to_skip.empty()) {
    result = key.DeleteEmptyKey(L"");
    LOG_IF(ERROR, result != ERROR_SUCCESS) << "Failed to delete empty key "
                                           << path << "; result: " << result;
    return;
  }

  // Delete all values since subkeys are being preserved.
  to_skip.clear();
  did_delete = false;
  index = 0;
  while (true) {
    DWORD name_length = base::saturated_cast<int16_t>(name.capacity());
    name.resize(name_length);
    result = ::RegEnumValue(key.Handle(), index, &name[0], &name_length,
                            nullptr, nullptr, nullptr, nullptr);
    if (result == ERROR_MORE_DATA) {
      if (name_length <
          static_cast<DWORD>(std::numeric_limits<int16_t>::max())) {
        // Double the space to hold the value name and try again.
        name.reserve(name.capacity() * 2);
        continue;
      }
      // Otherwise, the max has been exceeded. Nothing more to be done.
      break;
    }
    if (result == ERROR_NO_MORE_ITEMS) {
      if (!did_delete)
        break;  // All values were deleted. The job is done.
      // Otherwise, loop again.
      did_delete = false;
      index = 0;
      continue;
    }
    if (result != ERROR_SUCCESS)
      break;
    // Shrink the string to the actual length of the name.
    name.resize(name_length);

    // Skip over this value if it couldn't be deleted on a previous iteration.
    if (to_skip.count(name)) {
      ++index;
      continue;
    }

    // Delete this value.
    result = key.DeleteValue(name.c_str());
    if (result != ERROR_SUCCESS) {
      LOG(ERROR) << "Failed to delete value " << name << " in key " << path;
      // Skip over this value on subsequent iterations.
      to_skip.insert(name);
      ++index;
      continue;
    }
    did_delete = true;
  }
}

bool IsDowngradeAllowed(const MasterPreferences& prefs) {
  bool allow_downgrade = false;
  return prefs.GetBool(master_preferences::kAllowDowngrade, &allow_downgrade) &&
         allow_downgrade;
}

int GetInstallAge(const InstallerState& installer_state) {
  base::File::Info info;
  if (!base::GetFileInfo(installer_state.target_path(), &info))
    return -1;
  base::TimeDelta age = base::Time::Now() - info.creation_time;
  return age >= base::TimeDelta() ? age.InDays() : -1;
}

void RecordUnPackMetrics(UnPackStatus unpack_status,
                         base::Optional<int32_t> ntstatus,
                         base::Optional<DWORD> error_code,
                         UnPackConsumer consumer) {
  std::string consumer_name = "";

  switch (consumer) {
    case UnPackConsumer::CHROME_ARCHIVE_PATCH:
      consumer_name = "ChromeArchivePatch";
      break;
    case UnPackConsumer::COMPRESSED_CHROME_ARCHIVE:
      consumer_name = "CompressedChromeArchive";
      break;
    case UnPackConsumer::SETUP_EXE_PATCH:
      consumer_name = "SetupExePatch";
      break;
    case UnPackConsumer::UNCOMPRESSED_CHROME_ARCHIVE:
      consumer_name = "UncompressedChromeArchive";
      break;
  }

  base::UmaHistogramExactLinear(
      std::string(std::string(kUnPackStatusMetricsName) + "_" + consumer_name),
      unpack_status, UNPACK_STATUS_COUNT);

  if (error_code.has_value()) {
    base::UmaHistogramSparse(
        std::string(kUnPackResultMetricsName) + "_" + consumer_name,
        *error_code);
  }
  if (ntstatus.has_value()) {
    base::UmaHistogramSparse(
        std::string(kUnPackNTSTATUSMetricsName) + "_" + consumer_name,
        *ntstatus);
  }
}

void RegisterEventLogProvider(const base::FilePath& install_directory,
                              const base::Version& version) {
  base::string16 reg_path(kEventLogProvidersRegPath);
  reg_path.append(install_static::InstallDetails::Get().install_full_name());
  VLOG(1) << "Registering Chrome's event log provider at " << reg_path;

  std::unique_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
  work_item_list->set_log_message("Register event log provider");

  work_item_list->AddCreateRegKeyWorkItem(HKEY_LOCAL_MACHINE, reg_path,
                                          WorkItem::kWow64Default);
  // Speicifes the number of event categories defined in the dll.
  work_item_list->AddSetRegValueWorkItem(
      HKEY_LOCAL_MACHINE, reg_path, WorkItem::kWow64Default, L"CategoryCount",
      static_cast<DWORD>(1), true);
  // Specifies the event type emitted by this event source.
  work_item_list->AddSetRegValueWorkItem(
      HKEY_LOCAL_MACHINE, reg_path, WorkItem::kWow64Default, L"TypesSupported",
      static_cast<DWORD>(EVENTLOG_ERROR_TYPE | EVENTLOG_INFORMATION_TYPE |
                         EVENTLOG_WARNING_TYPE),
      true);

  const base::FilePath provider(
      install_directory.AppendASCII(version.GetString())
          .Append(FILE_PATH_LITERAL("eventlog_provider.dll")));

  static constexpr const wchar_t* kFileKeys[] = {
      L"CategoryMessageFile", L"EventMessageFile", L"ParameterMessageFile",
  };
  for (const wchar_t* file_key : kFileKeys) {
    work_item_list->AddSetRegValueWorkItem(HKEY_LOCAL_MACHINE, reg_path,
                                           WorkItem::kWow64Default, file_key,
                                           provider.value(), true);
  }

  // if the operation fails we log the error but still continue because none of
  // these are critical for the proper operation of the browser.
  if (!work_item_list->Do())
    work_item_list->Rollback();
}

void DeRegisterEventLogProvider() {
  base::string16 reg_path(kEventLogProvidersRegPath);
  reg_path.append(install_static::InstallDetails::Get().install_full_name());

  // TODO(http://crbug.com/668120): If the Event Viewer is open the provider dll
  // will fail to get deleted. This doesn't fail the uninstallation altogether
  // but leaves files behind.
  InstallUtil::DeleteRegistryKey(HKEY_LOCAL_MACHINE, reg_path,
                                 WorkItem::kWow64Default);
}

bool AreBinariesInstalled(const InstallerState& installer_state) {
  if (!install_static::InstallDetails::Get().supported_multi_install())
    return false;

  base::win::RegKey key;
  base::string16 pv;

  // True if the "pv" value exists and isn't empty.
  return key.Open(installer_state.root_key(),
                  install_static::GetBinariesClientsKeyPath().c_str(),
                  KEY_QUERY_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS &&
         key.ReadValue(google_update::kRegVersionField, &pv) == ERROR_SUCCESS &&
         !pv.empty();
}

void DoLegacyCleanups(const InstallerState& installer_state,
                      InstallStatus install_status) {
  // Do no harm if the install didn't succeed.
  if (InstallUtil::GetInstallReturnCode(install_status))
    return;

  // Cleanups that apply to any install mode.
  RemoveLegacyIExecuteCommandKey(installer_state);
  RemoveProfileStatistics(installer_state);

  // The cleanups below only apply to normal Chrome, not side-by-side (canary).
  if (!install_static::InstallDetails::Get().is_primary_mode())
    return;

  RemoveBinariesVersionKey(installer_state);
  RemoveMultiChromeFrame(installer_state);
  RemoveAppLauncherVersionKey(installer_state);
  RemoveAppHostExe(installer_state);
  RemoveLegacyChromeAppCommands(installer_state);
}

base::Time GetConsoleSessionStartTime() {
  constexpr DWORD kInvalidSessionId = 0xFFFFFFFF;
  DWORD console_session_id = ::WTSGetActiveConsoleSessionId();
  if (console_session_id == kInvalidSessionId)
    return base::Time();
  wchar_t* buffer = nullptr;
  DWORD buffer_size = 0;
  if (!::WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
                                    console_session_id, WTSSessionInfo, &buffer,
                                    &buffer_size)) {
    return base::Time();
  }
  base::ScopedClosureRunner wts_deleter(
      base::Bind(&::WTSFreeMemory, base::Unretained(buffer)));

  WTSINFO* wts_info = nullptr;
  if (buffer_size < sizeof(*wts_info))
    return base::Time();

  wts_info = reinterpret_cast<WTSINFO*>(buffer);
  FILETIME filetime = {wts_info->LogonTime.u.LowPart,
                       wts_info->LogonTime.u.HighPart};
  return base::Time::FromFileTime(filetime);
}

base::Optional<std::string> DecodeDMTokenSwitchValue(
    const base::string16& encoded_token) {
  if (encoded_token.empty()) {
    LOG(ERROR) << "Empty DMToken specified on the command line";
    return base::nullopt;
  }

  // The token passed on the command line is base64-encoded, but since this is
  // on Windows, it is passed in as a wide string containing base64 values only.
  std::string token;
  if (!base::IsStringASCII(encoded_token) ||
      !base::Base64Decode(base::UTF16ToASCII(encoded_token), &token)) {
    LOG(ERROR) << "DMToken passed on the command line is not correctly encoded";
    return base::nullopt;
  }

  return token;
}

bool StoreDMToken(const std::string& token) {
  DCHECK(install_static::IsSystemInstall());

  if (token.size() > kMaxDMTokenLength) {
    LOG(ERROR) << "DMToken length out of bounds";
    return false;
  }

  std::wstring path;
  std::wstring name;
  InstallUtil::GetMachineLevelUserCloudPolicyDMTokenRegistryPath(&path,
                                                                 &name);

  base::win::RegKey key;
  LONG result = key.Create(HKEY_LOCAL_MACHINE, path.c_str(),
                           KEY_WRITE | KEY_WOW64_64KEY);
  if (result != ERROR_SUCCESS) {
    LOG(ERROR) << "Unable to create/open registry key HKLM\\" << path
               << " for writing result=" << result;
    return false;
  }

  result =
      key.WriteValue(name.c_str(), token.data(),
                     base::saturated_cast<DWORD>(token.size()), REG_BINARY);
  if (result != ERROR_SUCCESS) {
    LOG(ERROR) << "Unable to write specified DMToken to the registry at HKLM\\"
               << path << "\\" << name << " result=" << result;
    return false;
  }

  VLOG(1) << "Successfully stored specified DMToken in the registry.";

  return true;
}

base::FilePath GetNotificationHelperPath(const base::FilePath& target_path,
                                         const base::Version& version) {
  return target_path.AppendASCII(version.GetString())
      .Append(kNotificationHelperExe);
}

base::FilePath GetElevationServicePath(const base::FilePath& target_path,
                                       const base::Version& version) {
  return target_path.AppendASCII(version.GetString())
      .Append(kElevationServiceExe);
}

base::string16 GetElevationServiceGuid(base::StringPiece16 prefix) {
  auto result = base::win::String16FromGUID(install_static::GetElevatorClsid());
  result.insert(0, prefix.data(), prefix.size());
  return result;
}

base::string16 GetElevationServiceClsidRegistryPath() {
  return GetElevationServiceGuid(L"Software\\Classes\\CLSID\\");
}

base::string16 GetElevationServiceAppidRegistryPath() {
  return GetElevationServiceGuid(L"Software\\Classes\\AppID\\");
}

base::string16 GetElevationServiceIid(base::StringPiece16 prefix) {
  auto result = base::win::String16FromGUID(install_static::GetElevatorIid());
  result.insert(0, prefix.data(), prefix.size());
  return result;
}

base::string16 GetElevationServiceIidRegistryPath() {
  return GetElevationServiceIid(L"Software\\Classes\\Interface\\");
}

base::string16 GetElevationServiceTypeLibRegistryPath() {
  return GetElevationServiceIid(L"Software\\Classes\\TypeLib\\");
}

}  // namespace installer
