// Copyright 2018 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.

#include "chrome_elf/third_party_dlls/main.h"

#include <windows.h>

#include <string>

#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/hash/sha1.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/test_reg_util_win.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/install_static/install_util.h"
#include "chrome_elf/nt_registry/nt_registry.h"
#include "chrome_elf/sha1/sha1.h"
#include "chrome_elf/third_party_dlls/hook.h"
#include "chrome_elf/third_party_dlls/main_unittest_exe.h"
#include "chrome_elf/third_party_dlls/packed_list_file.h"
#include "chrome_elf/third_party_dlls/packed_list_format.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace third_party_dlls {
namespace {

constexpr wchar_t kTestExeFilename[] = L"third_party_dlls_test_exe.exe";
constexpr wchar_t kTestBlFileName[] = L"blfile";
constexpr wchar_t kTestDllName1[] = L"main_unittest_dll_1.dll";
constexpr wchar_t kTestDllName1MixedCase[] = L"MaiN_uniTtest_dLL_1.Dll";
constexpr wchar_t kTestDllName2[] = L"main_unittest_dll_2.dll";
constexpr wchar_t kChineseUnicode[] = {0x68D5, 0x8272, 0x72D0, 0x72F8, 0x002E,
                                       0x0064, 0x006C, 0x006C, 0x0000};
constexpr wchar_t kOldBlacklistDllName[] = L"libapi2hook.dll";

struct TestModuleData {
  std::string image_name;
  std::string section_path;
  std::string section_basename;
  DWORD timedatestamp;
  DWORD imagesize;
};

// NOTE: TestTimeouts::action_max_timeout() is not long enough here.
base::TimeDelta g_timeout = ::IsDebuggerPresent()
                                ? base::TimeDelta::FromMilliseconds(INFINITE)
                                : base::TimeDelta::FromMilliseconds(5000);

// Centralize child test process control.
void LaunchChildAndWait(const base::CommandLine& command_line, int* exit_code) {
  base::Process proc =
      base::LaunchProcess(command_line, base::LaunchOptionsForTest());
  ASSERT_TRUE(proc.IsValid());

  *exit_code = 0;
  if (!proc.WaitForExitWithTimeout(g_timeout, exit_code)) {
    // Timeout while waiting.  Try to cleanup.
    proc.Terminate(1, false);
    ADD_FAILURE();
  }

  return;
}

// Given the name and path of a test DLL, mine the data of interest out of it
// and return it via |test_module|.
// - Note: the DLL must be loaded into memory by NTLoader to mine all of the
//         desired data (not just read from disk).
bool GetTestModuleData(const std::wstring& file_name,
                       const std::wstring& file_path,
                       TestModuleData* test_module) {
  base::FilePath path(file_path);
  path = path.Append(file_name);

  // Map the target DLL into memory just long enough to mine data out of it.
  base::ScopedNativeLibrary test_dll(path);
  if (!test_dll.is_valid())
    return false;

  return GetDataFromImageForTesting(
      test_dll.get(), &test_module->timedatestamp, &test_module->imagesize,
      &test_module->image_name, &test_module->section_path,
      &test_module->section_basename);
}

// Turn given data into a PackedListModule structure.
// - |image_name| should be utf-8 at this point.
PackedListModule GeneratePackedListModule(const std::string& image_name,
                                          DWORD timedatestamp,
                                          DWORD imagesize) {
  // Internally, an empty string should not be passed in here.
  assert(!image_name.empty());

  // SHA1 hash the two strings into the new struct.
  PackedListModule packed_module;
  packed_module.code_id_hash =
      elf_sha1::SHA1HashString(GetFingerprintString(timedatestamp, imagesize));
  packed_module.basename_hash = elf_sha1::SHA1HashString(image_name);

  return packed_module;
}

inline std::wstring MakePath(const std::wstring& path,
                             const std::wstring& name) {
  std::wstring full_path(path);
  full_path.push_back(L'\\');
  full_path.append(name);
  return full_path;
}

inline bool MakeFileCopy(const std::wstring& old_path,
                         const std::wstring& old_name,
                         const std::wstring& new_path,
                         const std::wstring& new_name) {
  base::FilePath source(MakePath(old_path, old_name));
  base::FilePath destination(MakePath(new_path, new_name));
  return base::CopyFileW(source, destination);
}

// Utility function for protecting local registry.
void RegRedirect(nt::ROOT_KEY key,
                 registry_util::RegistryOverrideManager* rom) {
  ASSERT_NE(key, nt::AUTO);
  HKEY root = (key == nt::HKCU ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
  base::string16 temp;

  ASSERT_NO_FATAL_FAILURE(rom->OverrideRegistry(root, &temp));
  ASSERT_TRUE(nt::SetTestingOverride(key, temp));
}

// Utility function to disable local registry protection.
void CancelRegRedirect(nt::ROOT_KEY key) {
  ASSERT_NE(key, nt::AUTO);
  ASSERT_TRUE(nt::SetTestingOverride(key, base::string16()));
}

// Use NtRegistry to query status codes (it's more handy than base).
// - Returns true if the key value exists and is type REG_BINARY.
bool QueryStatusCodes(std::vector<ThirdPartyStatus>* status_array) {
  HANDLE handle = nullptr;
  if (!nt::OpenRegKey(nt::HKCU,
                      install_static::GetRegistryPath()
                          .append(kThirdPartyRegKeyName)
                          .c_str(),
                      KEY_QUERY_VALUE, &handle, nullptr)) {
    return false;
  }

  ULONG type = REG_NONE;
  std::vector<uint8_t> temp_buffer;
  bool success =
      nt::QueryRegKeyValue(handle, kStatusCodesRegValue, &type, &temp_buffer);
  nt::CloseRegKey(handle);

  if (!success || type != REG_BINARY)
    return false;

  ConvertBufferToStatusCodes(temp_buffer, status_array);

  return true;
}

//------------------------------------------------------------------------------
// ThirdPartyTest class
//------------------------------------------------------------------------------

class ThirdPartyTest : public testing::Test {
 protected:
  ThirdPartyTest() = default;

  void SetUp() override {
    // Setup temp test dir.
    ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());

    // Store full path to test file.
    base::FilePath path = scoped_temp_dir_.GetPath();
    path = path.Append(kTestBlFileName);
    bl_test_file_path_ = std::move(path.value());

    // Also store a copy of current exe directory for efficiency.
    base::FilePath exe;
    ASSERT_TRUE(base::PathService::Get(base::DIR_EXE, &exe));
    exe_dir_ = std::move(exe.value());

    // Create the blacklist file empty.
    base::File file(base::FilePath(bl_test_file_path_),
                    base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
                        base::File::FLAG_SHARE_DELETE |
                        base::File::FLAG_DELETE_ON_CLOSE);
    ASSERT_TRUE(file.IsValid());

    // Leave file handle open for DELETE_ON_CLOSE.
    bl_file_ = std::move(file);
  }

  void TearDown() override {}

  // Overwrite the content of the blacklist file.
  bool WriteModulesToBlacklist(const std::vector<PackedListModule>& list) {
    bl_file_.SetLength(0);

    // Write content {metadata}{array_of_modules}.
    PackedListMetadata meta = {kInitialVersion,
                               static_cast<uint32_t>(list.size())};

    if (bl_file_.Write(0, reinterpret_cast<const char*>(&meta), sizeof(meta)) !=
        static_cast<int>(sizeof(meta))) {
      return false;
    }
    int size = static_cast<int>(list.size() * sizeof(PackedListModule));
    if (bl_file_.Write(sizeof(PackedListMetadata),
                       reinterpret_cast<const char*>(list.data()),
                       size) != size) {
      return false;
    }

    return true;
  }

  const base::string16& GetBlTestFilePath() { return bl_test_file_path_; }
  const base::string16& GetExeDir() { return exe_dir_; }
  const std::wstring& GetScopedTempDirValue() {
    return scoped_temp_dir_.GetPath().value();
  }

 private:
  base::ScopedTempDir scoped_temp_dir_;
  base::File bl_file_;
  base::string16 bl_test_file_path_;
  base::string16 exe_dir_;

  DISALLOW_COPY_AND_ASSIGN(ThirdPartyTest);
};

//------------------------------------------------------------------------------
// Third-party tests
//
// These tests spawn a child test process to keep the hooking contained to a
// separate process.  This prevents test clashes in certain testing
// configurations.
//------------------------------------------------------------------------------

#if defined(OS_WIN)
#define MAYBE_Base DISABLED_Base
#else
#define MAYBE_Base Base
#endif
// Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest, MAYBE_Base) {
  // 1. Spawn the test process with NO blacklist.  Expect successful
  // initialization.
  base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line1.AppendArgNative(GetBlTestFilePath());
  cmd_line1.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestOnlyInitialization));

  int exit_code = 0;
  LaunchChildAndWait(cmd_line1, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadSuccess, exit_code);

  //----------------------------------------------------------------------------
  // 2. Spawn the test process with NO blacklist.  Expect successful DLL load.
  base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line2.AppendArgNative(GetBlTestFilePath());
  cmd_line2.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line2.AppendArgNative(MakePath(GetExeDir(), kTestDllName1));

  LaunchChildAndWait(cmd_line2, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadSuccess, exit_code);

  //----------------------------------------------------------------------------
  // 3. Spawn the test process with blacklist.  Expect failed DLL load.
  TestModuleData module_data = {};
  ASSERT_TRUE(GetTestModuleData(kTestDllName1, GetExeDir(), &module_data));

  // Note: image_name will be empty, as there is no export table in this test
  //       module.
  EXPECT_TRUE(module_data.image_name.empty());

  std::vector<PackedListModule> vector(1);
  vector.emplace_back(GeneratePackedListModule(module_data.section_basename,
                                               module_data.timedatestamp,
                                               module_data.imagesize));
  ASSERT_TRUE(WriteModulesToBlacklist(vector));

  base::CommandLine cmd_line3 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line3.AppendArgNative(GetBlTestFilePath());
  cmd_line3.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line3.AppendArgNative(MakePath(GetExeDir(), kTestDllName1));

  LaunchChildAndWait(cmd_line3, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);

  //----------------------------------------------------------------------------
  // 4. Spawn the test process with blacklist.  Expect failed DLL load.
  //    ** Rename the module with some upper-case characters to test that
  //       the hook matching handles case properly.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
                           kTestDllName1MixedCase));

  // Note: the blacklist is already set from the previous test.
  // Note: using the module with no export table for this test, to ensure that
  //       the section name (the rename) is used in the comparison.

  base::CommandLine cmd_line4 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line4.AppendArgNative(GetBlTestFilePath());
  cmd_line4.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line4.AppendArgNative(
      MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase));

  LaunchChildAndWait(cmd_line4, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);
}

// Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest, WideCharEncoding) {
  // Rename module to chinese unicode (kChineseUnicode).  Be sure to handle
  // any conversions to UTF8 appropriately here.  No ASCII.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
                           kChineseUnicode));

  // 1) Test a successful DLL load with no blacklist.
  base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line1.AppendArgNative(GetBlTestFilePath());
  cmd_line1.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line1.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));

  int exit_code = 0;
  LaunchChildAndWait(cmd_line1, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadSuccess, exit_code);

  //----------------------------------------------------------------------------
  // 2) Test a failed DLL load with blacklist.
  TestModuleData module_data = {};
  ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
                                &module_data));

  // Note: image_name will be empty, as there is no export table in this test
  //       module.
  EXPECT_TRUE(module_data.image_name.empty());

  std::vector<PackedListModule> vector;
  vector.emplace_back(GeneratePackedListModule(module_data.section_basename,
                                               module_data.timedatestamp,
                                               module_data.imagesize));
  ASSERT_TRUE(WriteModulesToBlacklist(vector));

  base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line2.AppendArgNative(GetBlTestFilePath());
  cmd_line2.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line2.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));

  LaunchChildAndWait(cmd_line2, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);
}

// Note: The test module used in this unittest has an export table.
TEST_F(ThirdPartyTest, WideCharEncodingWithExportDir) {
  // Rename module to chinese unicode (kChineseUnicode).  Be sure to handle
  // any conversions to UTF8 appropriately here.  No ASCII.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName2, GetScopedTempDirValue(),
                           kChineseUnicode));

  // 1) Test a successful DLL load with no blacklist.
  base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line1.AppendArgNative(GetBlTestFilePath());
  cmd_line1.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line1.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));

  int exit_code = 0;
  LaunchChildAndWait(cmd_line1, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadSuccess, exit_code);

  //----------------------------------------------------------------------------
  // 2) Test a failed DLL load with blacklist.
  TestModuleData module_data = {};
  ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
                                &module_data));
  // Ensure the export section was found as expected.
  EXPECT_FALSE(module_data.image_name.empty());

  // NOTE: a file rename does not affect the module name mined from the export
  //       table in the PE.  So image_name and section_basename will be
  //       different. Ensure blacklisting both section name and image name
  //       works!

  // 2a) Only blacklist the original DLL name, which should be mined out of the
  //     export table by the hook, and the load should be blocked.
  std::vector<PackedListModule> vector;
  vector.emplace_back(GeneratePackedListModule(
      base::UTF16ToASCII(kTestDllName2), module_data.timedatestamp,
      module_data.imagesize));
  ASSERT_TRUE(WriteModulesToBlacklist(vector));

  base::CommandLine cmd_line2 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line2.AppendArgNative(GetBlTestFilePath());
  cmd_line2.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line2.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));

  LaunchChildAndWait(cmd_line2, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);

  // 2b) Only blacklist the new DLL file name, which should be mined out of the
  //     section by the hook, and the load should be blocked.
  vector.clear();
  vector.emplace_back(GeneratePackedListModule(
      base::UTF16ToUTF8(kChineseUnicode), module_data.timedatestamp,
      module_data.imagesize));
  ASSERT_TRUE(WriteModulesToBlacklist(vector));

  base::CommandLine cmd_line3 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line3.AppendArgNative(GetBlTestFilePath());
  cmd_line3.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line3.AppendArgNative(MakePath(GetScopedTempDirValue(), kChineseUnicode));

  LaunchChildAndWait(cmd_line3, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);
}

// Note: The test module used in this unittest has no export table.
TEST_F(ThirdPartyTest, DeprecatedBlacklistSanityCheck) {
  // Rename module to something on the old, deprecated, hard-coded blacklist.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
                           kOldBlacklistDllName));

  // 1) Test a failed DLL load with no blacklist (the old, hard-coded blacklist
  //    should trigger a block).
  base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line1.AppendArgNative(GetBlTestFilePath());
  cmd_line1.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line1.AppendArgNative(
      MakePath(GetScopedTempDirValue(), kOldBlacklistDllName));

  int exit_code = 0;
  LaunchChildAndWait(cmd_line1, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadFailed, exit_code);
}

// Note: This test only sanity checks the two SHA1 libraries used on either side
//       of the Third-Party block.
//       This Side: chrome_elf\third_party_dlls\*,
//                  elf_sha1::SHA1HashString().
//       The Other Side: chrome\browser\conflicts\module_list_filter_win.cc,
//                       base::SHA1HashString().
TEST_F(ThirdPartyTest, SHA1SanityCheck) {
  // Rename module to chinese unicode (kChineseUnicode).  Be sure to handle
  // any conversions to UTF8 appropriately here.  No ASCII.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName1, GetScopedTempDirValue(),
                           kChineseUnicode));

  TestModuleData module_data = {};
  ASSERT_TRUE(GetTestModuleData(kChineseUnicode, GetScopedTempDirValue(),
                                &module_data));

  // Get hashes from elf_sha1.
  PackedListModule elf_sha1_generated = GeneratePackedListModule(
      base::UTF16ToUTF8(kChineseUnicode), module_data.timedatestamp,
      module_data.imagesize);

  // Get hashes from base_sha1.
  const std::string module_basename_hash =
      base::SHA1HashString(base::UTF16ToUTF8(kChineseUnicode));
  const std::string module_code_id_hash = base::SHA1HashString(
      GetFingerprintString(module_data.timedatestamp, module_data.imagesize));

  // Compare the hashes.
  EXPECT_EQ(::memcmp(&elf_sha1_generated.basename_hash[0],
                     module_basename_hash.data(), elf_sha1::kSHA1Length),
            0);
  EXPECT_EQ(::memcmp(&elf_sha1_generated.code_id_hash[0],
                     module_code_id_hash.data(), elf_sha1::kSHA1Length),
            0);
}

// Flaky: crbug.com/868233
#if defined(OS_WIN)
#define MAYBE_PathCaseSensitive DISABLED_PathCaseSensitive
#else
#define MAYBE_PathCaseSensitive PathCaseSensitive
#endif

// Test that full section path is left alone, in terms of case.
TEST_F(ThirdPartyTest, MAYBE_PathCaseSensitive) {
  // Rename module to have mixed case.
  ASSERT_TRUE(MakeFileCopy(GetExeDir(), kTestDllName2, GetScopedTempDirValue(),
                           kTestDllName1MixedCase));

  // 1) Sanity check that the hook GetDataFromImage() mining leaves the
  // section path alone.
  TestModuleData module_data = {};
  ASSERT_TRUE(GetTestModuleData(kTestDllName1MixedCase, GetScopedTempDirValue(),
                                &module_data));
  // Reminder: this string is actually UTF-8, but this test ensures it is ascii.
  // Also, |section_path| will be a device path, so convert to drive letter
  // before comparing.
  base::FilePath drive;
  ASSERT_TRUE(base::DevicePathToDriveLetterPath(
      base::FilePath(base::ASCIIToUTF16(module_data.section_path)), &drive));

  EXPECT_EQ(drive.value().compare(
                MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase)),
            0);

  // 2) Now check an actual log.  Successful DLL load with no blacklist is fine
  //    for this test.
  base::CommandLine cmd_line1 = base::CommandLine::FromString(kTestExeFilename);
  cmd_line1.AppendArgNative(GetBlTestFilePath());
  cmd_line1.AppendArgNative(
      base::NumberToString16(main_unittest_exe::kTestSingleDllLoad));
  cmd_line1.AppendArgNative(
      MakePath(GetScopedTempDirValue(), kTestDllName1MixedCase));

  int exit_code = 0;
  LaunchChildAndWait(cmd_line1, &exit_code);
  ASSERT_EQ(main_unittest_exe::kDllLoadSuccess, exit_code);
}

// Test the status-code passing in registry.
TEST_F(ThirdPartyTest, StatusCodes) {
  // 1. Enable reg override for test net.
  registry_util::RegistryOverrideManager override_manager;
  ASSERT_NO_FATAL_FAILURE(RegRedirect(nt::HKCU, &override_manager));

  // 2. Reset the registry key and value to empty.
  ASSERT_TRUE(ResetStatusCodesForTesting());

  // 3. Confirm key and empty value.
  std::vector<ThirdPartyStatus> code_array;
  EXPECT_TRUE(QueryStatusCodes(&code_array));
  EXPECT_EQ(0u, code_array.size());

  // 4. Add status codes, then verify.
  ASSERT_NO_FATAL_FAILURE(
      AddStatusCodeForTesting(ThirdPartyStatus::kFileEmpty));
  ASSERT_NO_FATAL_FAILURE(
      AddStatusCodeForTesting(ThirdPartyStatus::kLogsCreateMutexFailure));
  ASSERT_NO_FATAL_FAILURE(
      AddStatusCodeForTesting(ThirdPartyStatus::kHookVirtualProtectFailure));
  EXPECT_TRUE(QueryStatusCodes(&code_array));
  ASSERT_EQ(3u, code_array.size());
  EXPECT_EQ(ThirdPartyStatus::kFileEmpty, code_array[0]);
  EXPECT_EQ(ThirdPartyStatus::kLogsCreateMutexFailure, code_array[1]);
  EXPECT_EQ(ThirdPartyStatus::kHookVirtualProtectFailure, code_array[2]);

  // 5. Reset the registry value to empty.
  EXPECT_TRUE(ResetStatusCodesForTesting());
  EXPECT_TRUE(QueryStatusCodes(&code_array));
  EXPECT_EQ(0u, code_array.size());

  // 6. Disable reg override.
  ASSERT_NO_FATAL_FAILURE(CancelRegRedirect(nt::HKCU));
}

}  // namespace
}  // namespace third_party_dlls
