// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/updater/win/app_command_runner.h"

#include <windows.h>

#include <shellapi.h>

#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/base_paths_win.h"
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/string_util_impl_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "base/version.h"
#include "base/win/registry.h"
#include "base/win/scoped_localalloc.h"
#include "chrome/updater/updater_branding.h"
#include "chrome/updater/updater_scope.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/win_constants.h"

namespace updater {

namespace {

// Loads the AppCommand under:
//     Update\Clients\{`app_id`}\Commands\`command_id`
//         REG_SZ "CommandLine" == {command format}
HRESULT LoadAppCommandFormat(UpdaterScope scope,
                             const std::wstring& app_id,
                             const std::wstring& command_id,
                             std::wstring& command_format) {
  base::win::RegKey command_key;
  HRESULT hr = HRESULT_FROM_WIN32(command_key.Open(
      UpdaterScopeToHKeyRoot(scope),
      GetAppCommandKey(app_id, command_id).c_str(), Wow6432(KEY_QUERY_VALUE)));
  return SUCCEEDED(hr) ? HRESULT_FROM_WIN32(command_key.ReadValue(
                             kRegValueCommandLine, &command_format))
                       : hr;
}

// Loads the ProcessLauncher command in HKLM under:
//     Update\Clients\{`app_id`}
//         REG_SZ `command_id` == {command format}
//
// The legacy process launcher format is only supported for Google Chrome
// versions 110.0.5435.0 and below with the "cmd" command id. This is because
// the legacy process launcher command layout format can be used to interpret
// and/or execute unrelated registry entries. For instance, if the app_id is
// `{8A69D345-D564-463c-AFF1-A69D9E530F96}`, the older command would be
// registered under
// `SOFTWARE\Google\Update\Clients\{8A69D345-D564-463c-AFF1-A69D9E530F96}`
// REG_SZ `cmd`. Along with `cmd`, there are other properties of the app
// registered, such as the version "pv"="107.0.5304.107". So, `pv` is also a
// potential "command" for `IProcessLauncher`, which is unexpected.
HRESULT LoadLegacyProcessLauncherFormat(const std::wstring& app_id,
                                        const std::wstring& command_id,
                                        std::wstring& command_format) {
  static constexpr wchar_t kAllowedLegacyProcessLauncherAppNamePrefix[] =
      L"" BROWSER_PRODUCT_NAME_STRING;
  static constexpr char kAllowedLegacyProcessLauncherMaxAppVersion[] =
      "110.0.5435.0";
  static constexpr wchar_t kAllowedLegacyProcessLauncherCommandId[] = L"cmd";

  std::wstring pv;
  std::wstring name;
  if (command_id == kAllowedLegacyProcessLauncherCommandId) {
    base::win::RegKey app_key;
    HRESULT hr = HRESULT_FROM_WIN32(
        app_key.Open(HKEY_LOCAL_MACHINE, GetAppClientsKey(app_id).c_str(),
                     Wow6432(KEY_QUERY_VALUE)));
    if (FAILED(hr)) {
      return hr;
    }

    app_key.ReadValue(kRegValuePV, &pv);
    app_key.ReadValue(kRegValueName, &name);
    const base::Version app_version(base::WideToUTF8(pv));

    if (app_version.IsValid() &&
        app_version.CompareTo(
            base::Version(kAllowedLegacyProcessLauncherMaxAppVersion)) <= 0 &&
        base::StartsWith(name, kAllowedLegacyProcessLauncherAppNamePrefix)) {
      return HRESULT_FROM_WIN32(
          app_key.ReadValue(command_id.c_str(), &command_format));
    }
  }

  LOG(WARNING)
      << __func__
      << "Legacy ProcessLauncher format not supported, use more secure "
         "AppCommand format: "
      << app_id << ": " << pv << ": " << name << ": " << command_id;
  return E_INVALIDARG;
}

bool IsParentOf(int key, const base::FilePath& child) {
  base::FilePath path;
  return base::PathService::Get(key, &path) && path.IsParent(child);
}

bool IsSecureAppCommandExePath(UpdaterScope scope,
                               const base::FilePath& exe_path) {
  return exe_path.IsAbsolute() &&
         (!IsSystemInstall(scope) ||
          IsParentOf(base::DIR_PROGRAM_FILES, exe_path) ||
          IsParentOf(base::DIR_PROGRAM_FILESX86, exe_path) ||
          IsParentOf(base::DIR_PROGRAM_FILES6432, exe_path));
}

}  // namespace

AppCommandRunner::AppCommandRunner() = default;
AppCommandRunner::AppCommandRunner(const AppCommandRunner&) = default;
AppCommandRunner& AppCommandRunner::operator=(const AppCommandRunner&) =
    default;
AppCommandRunner::~AppCommandRunner() = default;

// static
HResultOr<AppCommandRunner> AppCommandRunner::LoadAppCommand(
    UpdaterScope scope,
    const std::wstring& app_id,
    const std::wstring& command_id) {
  std::wstring command_format;
  HRESULT hr = LoadAppCommandFormat(scope, app_id, command_id, command_format);
  if (FAILED(hr)) {
    if (IsSystemInstall(scope)) {
      hr = LoadLegacyProcessLauncherFormat(app_id, command_id, command_format);
    }
    if (FAILED(hr)) {
      return base::unexpected(hr);
    }
  }

  AppCommandRunner app_command_runner;
  hr = GetAppCommandFormatComponents(scope, command_format,
                                     app_command_runner.executable_,
                                     app_command_runner.parameters_);
  if (FAILED(hr)) {
    return base::unexpected(hr);
  }

  return app_command_runner;
}

// static
std::vector<AppCommandRunner>
AppCommandRunner::LoadAutoRunOnOsUpgradeAppCommands(
    UpdaterScope scope,
    const std::wstring& app_id) {
  const HKEY root = UpdaterScopeToHKeyRoot(scope);
  const std::wstring commands_key_name = GetAppCommandKey(app_id, L"");

  std::vector<AppCommandRunner> app_command_runners;
  for (base::win::RegistryKeyIterator it(root, commands_key_name.c_str(),
                                         KEY_WOW64_32KEY);
       it.Valid(); ++it) {
    const base::win::RegKey command_key(
        root, base::StrCat({commands_key_name, it.Name()}).c_str(),
        Wow6432(KEY_QUERY_VALUE));
    if (!command_key.Valid()) {
      continue;
    }

    DWORD auto_run = 0;
    if (command_key.ReadValueDW(kRegValueAutoRunOnOSUpgrade, &auto_run) !=
            ERROR_SUCCESS ||
        !auto_run) {
      continue;
    }

    HResultOr<AppCommandRunner> runner =
        LoadAppCommand(scope, app_id, it.Name());
    if (runner.has_value()) {
      app_command_runners.push_back(*std::move(runner));
    }
  }

  return app_command_runners;
}

HRESULT AppCommandRunner::Run(base::span<const std::wstring> substitutions,
                              base::Process& process) const {
  if (executable_.empty() || process.IsValid()) {
    return E_UNEXPECTED;
  }

  return ExecuteAppCommand(executable_, parameters_, substitutions, process);
}

// static
HRESULT AppCommandRunner::StartProcess(const base::FilePath& executable,
                                       const std::wstring& parameters,
                                       base::Process& process) {
  VLOG(2) << __func__ << ": " << executable << ": " << parameters;

  if (executable.empty() || process.IsValid()) {
    return E_UNEXPECTED;
  }

  // `executable` needs to be a full path to prevent `::CreateProcess` (which
  // `base::LaunchProcess` uses internally) from using the search path for path
  // resolution.
  if (!executable.IsAbsolute()) {
    LOG(ERROR) << __func__ << "!executable.IsAbsolute(): " << executable;
    return E_INVALIDARG;
  }

  base::LaunchOptions options = {};
  options.feedback_cursor_off = true;
  options.start_hidden = true;

  process = base::LaunchProcess(
      base::StrCat(
          {base::CommandLine::QuoteForCommandLineToArgvW(executable.value()),
           L" ", parameters}),
      options);
  if (!process.IsValid()) {
    const HRESULT hr = HRESULTFromLastError();
    LOG(ERROR) << __func__ << "base::LaunchProcess failed: " << hr;
    return hr;
  }

  VLOG(2) << __func__ << "Started process with PID: " << process.Pid();
  return S_OK;
}

// static
HRESULT AppCommandRunner::GetAppCommandFormatComponents(
    UpdaterScope scope,
    std::wstring command_format,
    base::FilePath& executable,
    std::vector<std::wstring>& parameters) {
  VLOG(2) << __func__ << ": " << scope << ": " << command_format;

  int num_args = 0;
  base::win::ScopedLocalAllocTyped<wchar_t*> argv(
      ::CommandLineToArgvW(&command_format[0], &num_args));
  if (!argv || num_args < 1) {
    LOG(ERROR) << __func__ << "!argv || num_args < 1: " << num_args;
    return E_INVALIDARG;
  }

  // SAFETY: the unsafe buffer is present due to the ::CommandLineToArgvW call.
  // When constructing the span, `num_args` is validated and checked as a valid
  // size_t value.
  UNSAFE_BUFFERS(const base::span<wchar_t*> safe_args{
      argv.get(), base::checked_cast<size_t>(num_args)});

  const base::FilePath exe(safe_args[0]);
  if (!IsSecureAppCommandExePath(scope, exe)) {
    LOG(WARNING) << __func__
                 << ": !IsSecureAppCommandExePath(scope, exe): " << exe;
    return E_INVALIDARG;
  }

  executable = exe;
  parameters.clear();
  for (size_t i = 1; i < safe_args.size(); ++i) {
    parameters.push_back(safe_args[i]);
  }

  return S_OK;
}

// static
std::optional<std::wstring> AppCommandRunner::FormatParameter(
    const std::wstring& parameter,
    base::span<const std::wstring> substitutions) {
  return base::internal::DoReplaceStringPlaceholders(
      /*format_string=*/parameter, /*subst=*/substitutions,
      /*placeholder_prefix=*/L'%',
      /*should_escape_multiple_placeholder_prefixes=*/false,
      /*is_strict_mode=*/true, /*offsets=*/nullptr);
}

// static
std::optional<std::wstring> AppCommandRunner::FormatAppCommandLine(
    const std::vector<std::wstring>& parameters,
    base::span<const std::wstring> substitutions) {
  std::wstring formatted_command_line;
  for (size_t i = 0; i < parameters.size(); ++i) {
    std::optional<std::wstring> formatted_parameter =
        FormatParameter(parameters[i], substitutions);
    if (!formatted_parameter) {
      VLOG(1) << __func__ << " FormatParameter failed: " << parameters[i]
              << ": " << substitutions.size();
      return std::nullopt;
    }

    static constexpr wchar_t kQuotableCharacters[] = L" \t\\\"";
    formatted_command_line.append(
        formatted_parameter->find_first_of(kQuotableCharacters) ==
                std::wstring::npos
            ? *formatted_parameter  // no quoting needed, use as-is.
            : base::CommandLine::QuoteForCommandLineToArgvW(
                  *formatted_parameter));

    if (i + 1 < parameters.size()) {
      formatted_command_line.push_back(L' ');
    }
  }

  return formatted_command_line;
}

// static
HRESULT AppCommandRunner::ExecuteAppCommand(
    const base::FilePath& executable,
    const std::vector<std::wstring>& parameters,
    base::span<const std::wstring> substitutions,
    base::Process& process) {
  VLOG(2) << __func__ << ": " << executable << ": "
          << base::JoinString(parameters, L",") << " : "
          << base::JoinString(substitutions, L",");

  const std::optional<std::wstring> command_line_parameters =
      FormatAppCommandLine(parameters, substitutions);
  if (!command_line_parameters) {
    LOG(ERROR) << __func__ << "!command_line_parameters";
    return E_INVALIDARG;
  }

  return StartProcess(executable, command_line_parameters.value(), process);
}

}  // namespace updater
