[Chrome ELF] New NT registry API.

This CL is part of a chain of CLs:
1) "MITIGATION_EXTENSION_POINT_DISABLE support for children" (https://codereview.chromium.org/1835003003)
2) "MITIGATION_EXTENSION_POINT_DISABLE emergency off finch" (https://codereview.chromium.org/1836523004/)
-> THIS
4) "Early browser security support" (https://codereview.chromium.org/1656453002)
5) "Turn on MITIGATION_EXTENSION_POINT_DISABLE" (https://codereview.chromium.org/1854323002)

Added new chrome_elf_reg utility for a registry API that doesn't touch advapi32 (useful from DllMain).
Direct calls to ntdll.  Updated Chrome ELF to always use this new registry API.

Adjusted the existing DLL blacklist to use a REG_MULTI_SZ comma-separated list instead of lots of individual reg values.

Small changes to organize file structure and functional components under chrome_elf.  Old common code now sits under "hook_util", "nt_registry", "breakpad", "dll_hash", and "blacklist".

Fairly big changes to the chrome_elf tests (blacklist_test.cc, blacklist_test_main_dll.cc and
chrome_elf_util_unittest.cc) were needed.  Since ntdll bypasses any registry redirection
(that tests use to keep the hive safe and isolated), I added in a way for the tests to access
the redirection path (and pass that information on to the test DLL).  This way the NT reg
API can work with redirection during tests.

Tests:
1) chrome_elf_unittests, chrome_elf_util_unittest.cc: ChromeElfUtilTest.NTRegistry is new
(...but run all tests to exercise the new API being used by blacklist and utils).
2) unit_tests, chrome_elf_init_unittest_win.cc: ChromeBlacklistTrialTest*

BUG=557798
CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win10_chromium_x64_rel_ng

Review-Url: https://codereview.chromium.org/1841573002
Cr-Commit-Position: refs/heads/master@{#405307}
diff --git a/chrome_elf/chrome_elf_util_unittest.cc b/chrome_elf/chrome_elf_util_unittest.cc
index 210901e..dc4f1e1 100644
--- a/chrome_elf/chrome_elf_util_unittest.cc
+++ b/chrome_elf/chrome_elf_util_unittest.cc
@@ -3,10 +3,14 @@
 // found in the LICENSE file.
 
 #include <tuple>
+#include <windows.h>
+#include <versionhelpers.h>  // windows.h must be before.
 
 #include "base/test/test_reg_util_win.h"
 #include "base/win/registry.h"
 #include "chrome/install_static/install_util.h"
+#include "chrome_elf/chrome_elf_constants.h"
+#include "chrome_elf/nt_registry/nt_registry.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -41,18 +45,130 @@
   EXPECT_FALSE(IsNonBrowserProcess());
 }
 
+//------------------------------------------------------------------------------
+// NT registry API tests (chrome_elf_reg)
+//------------------------------------------------------------------------------
+
+TEST(ChromeElfUtilTest, NTRegistry) {
+  HANDLE key_handle;
+  const wchar_t* dword_val_name = L"DwordTestValue";
+  DWORD dword_val = 1234;
+  const wchar_t* sz_val_name = L"SzTestValue";
+  base::string16 sz_val = L"blah de blah de blahhhhh.";
+  const wchar_t* sz_val_name2 = L"SzTestValueEmpty";
+  base::string16 sz_val2 = L"";
+  const wchar_t* multisz_val_name = L"SzmultiTestValue";
+  std::vector<base::string16> multisz_val;
+  base::string16 multi1 = L"one";
+  base::string16 multi2 = L"two";
+  base::string16 multi3 = L"three";
+  const wchar_t* multisz_val_name2 = L"SzmultiTestValueBad";
+  base::string16 multi_empty = L"";
+  const wchar_t* sz_new_key_1 = L"test\\new\\subkey";
+  const wchar_t* sz_new_key_2 = L"test\\new\\subkey\\blah\\";
+  const wchar_t* sz_new_key_3 = L"\\test\\new\\subkey\\\\blah2";
+
+  // Set up registry override for this test.
+  base::string16 temp;
+  registry_util::RegistryOverrideManager override_manager;
+  override_manager.OverrideRegistry(HKEY_CURRENT_USER, &temp);
+  ::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1);
+
+  // Create a temp key to play under.
+  ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, elf_sec::kRegSecurityPath,
+                               KEY_ALL_ACCESS, &key_handle));
+
+  // Exercise the supported getter & setter functions.
+  EXPECT_TRUE(nt::SetRegValueDWORD(key_handle, dword_val_name, dword_val));
+  EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name, sz_val));
+  EXPECT_TRUE(nt::SetRegValueSZ(key_handle, sz_val_name2, sz_val2));
+
+  DWORD get_dword = 0;
+  base::string16 get_sz;
+  EXPECT_TRUE(nt::QueryRegValueDWORD(key_handle, dword_val_name, &get_dword) &&
+              get_dword == dword_val);
+  EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name, &get_sz) &&
+              get_sz.compare(sz_val) == 0);
+  EXPECT_TRUE(nt::QueryRegValueSZ(key_handle, sz_val_name2, &get_sz) &&
+              get_sz.compare(sz_val2) == 0);
+
+  multisz_val.push_back(multi1);
+  multisz_val.push_back(multi2);
+  multisz_val.push_back(multi3);
+  EXPECT_TRUE(
+      nt::SetRegValueMULTISZ(key_handle, multisz_val_name, multisz_val));
+  multisz_val.clear();
+  multisz_val.push_back(multi_empty);
+  EXPECT_TRUE(
+      nt::SetRegValueMULTISZ(key_handle, multisz_val_name2, multisz_val));
+  multisz_val.clear();
+
+  EXPECT_TRUE(
+      nt::QueryRegValueMULTISZ(key_handle, multisz_val_name, &multisz_val));
+  if (multisz_val.size() == 3) {
+    EXPECT_TRUE(multi1.compare(multisz_val.at(0)) == 0);
+    EXPECT_TRUE(multi2.compare(multisz_val.at(1)) == 0);
+    EXPECT_TRUE(multi3.compare(multisz_val.at(2)) == 0);
+  } else {
+    EXPECT_TRUE(false);
+  }
+  multisz_val.clear();
+
+  EXPECT_TRUE(
+      nt::QueryRegValueMULTISZ(key_handle, multisz_val_name2, &multisz_val));
+  if (multisz_val.size() == 1) {
+    EXPECT_TRUE(multi_empty.compare(multisz_val.at(0)) == 0);
+  } else {
+    EXPECT_TRUE(false);
+  }
+  multisz_val.clear();
+
+  // Clean up
+  EXPECT_TRUE(nt::DeleteRegKey(key_handle));
+  nt::CloseRegKey(key_handle);
+
+  // More tests for CreateRegKey recursion.
+  ASSERT_TRUE(
+      nt::CreateRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS, nullptr));
+  EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_1, KEY_ALL_ACCESS,
+                             &key_handle, nullptr));
+  EXPECT_TRUE(nt::DeleteRegKey(key_handle));
+  nt::CloseRegKey(key_handle);
+
+  ASSERT_TRUE(
+      nt::CreateRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS, nullptr));
+  EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, sz_new_key_2, KEY_ALL_ACCESS,
+                             &key_handle, nullptr));
+  EXPECT_TRUE(nt::DeleteRegKey(key_handle));
+  nt::CloseRegKey(key_handle);
+
+  ASSERT_TRUE(
+      nt::CreateRegKey(nt::HKCU, sz_new_key_3, KEY_ALL_ACCESS, nullptr));
+  EXPECT_TRUE(nt::OpenRegKey(nt::HKCU, L"test\\new\\subkey\\blah2",
+                             KEY_ALL_ACCESS, &key_handle, nullptr));
+  EXPECT_TRUE(nt::DeleteRegKey(key_handle));
+  nt::CloseRegKey(key_handle);
+
+  ASSERT_TRUE(nt::CreateRegKey(nt::HKCU, nullptr, KEY_ALL_ACCESS, &key_handle));
+  nt::CloseRegKey(key_handle);
+}
+
 // Parameterized test with paramters:
 // 1: product: "canary" or "google"
 // 2: install level: "user" or "system"
 // 3: install mode: "single" or "multi"
-class ChromeElfUtilTest :
-    public testing::TestWithParam<std::tuple<const char*,
-                                             const char*,
-                                             const char*> > {
+class ChromeElfUtilTest
+    : public testing::TestWithParam<
+          std::tuple<const char*, const char*, const char*>> {
  protected:
   void SetUp() override {
-    override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE);
-    override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
+    base::string16 temp;
+    override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, &temp);
+    ::wcsncpy(nt::HKLM_override, temp.c_str(), nt::g_kRegMaxPathLen - 1);
+    temp.clear();
+    override_manager_.OverrideRegistry(HKEY_CURRENT_USER, &temp);
+    ::wcsncpy(nt::HKCU_override, temp.c_str(), nt::g_kRegMaxPathLen - 1);
+
     const char* app;
     const char* level;
     const char* mode;
@@ -67,8 +183,8 @@
       chrome_path_ = kCanaryExePath;
     } else {
       app_guid_ = kAppGuidGoogleChrome;
-      chrome_path_ = (system_level_ ? kChromeSystemExePath :
-                                      kChromeUserExePath);
+      chrome_path_ =
+          (system_level_ ? kChromeSystemExePath : kChromeUserExePath);
     }
     if (multi_install_) {
       SetMultiInstallStateInRegistry(system_level_, true);
@@ -85,10 +201,13 @@
 
   void SetUsageStat(DWORD value, bool state_medium) {
     LONG result = base::win::RegKey(
-        system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-        BuildKey(state_medium ? kRegPathClientStateMedium : kRegPathClientState,
-                 app_guid_).c_str(),
-        KEY_SET_VALUE).WriteValue(kRegValueUsageStats, value);
+                      system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
+                      BuildKey(state_medium ? kRegPathClientStateMedium
+                                            : kRegPathClientState,
+                               app_guid_)
+                          .c_str(),
+                      KEY_SET_VALUE)
+                      .WriteValue(kRegValueUsageStats, value);
     ASSERT_EQ(ERROR_SUCCESS, result);
   }
 
@@ -108,10 +227,11 @@
   }
 
   void SetChannelName(const base::string16& channel_name) {
-    LONG result = base::win::RegKey(
-      system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-      BuildKey(kRegPathClientState, app_guid_).c_str(),
-      KEY_SET_VALUE).WriteValue(kRegApField, channel_name.c_str());
+    LONG result =
+        base::win::RegKey(
+            system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
+            BuildKey(kRegPathClientState, app_guid_).c_str(), KEY_SET_VALUE)
+            .WriteValue(kRegApField, channel_name.c_str());
     ASSERT_EQ(ERROR_SUCCESS, result);
   }
 
@@ -130,195 +250,195 @@
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
 
     SetChannelName(L"-full");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
 
     SetChannelName(L"1.1-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
 
     SetChannelName(L"1.1-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
 
     SetChannelName(L"1.1-bar");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
 
     SetChannelName(L"1n1-foobar");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
 
     SetChannelName(L"foo-1.1-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
     SetChannelName(L"2.0-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
 
     SetChannelName(L"2.0-dev");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"dev-m", channel);
+      EXPECT_STREQ(L"dev-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelDev, channel);
+      EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str());
     }
     SetChannelName(L"2.0-DEV");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"dev-m", channel);
+      EXPECT_STREQ(L"dev-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelDev, channel);
+      EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str());
     }
     SetChannelName(L"2.0-dev-eloper");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"dev-m", channel);
+      EXPECT_STREQ(L"dev-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelDev, channel);
+      EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str());
     }
     SetChannelName(L"2.0-doom");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"dev-m", channel);
+      EXPECT_STREQ(L"dev-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelDev, channel);
+      EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str());
     }
     SetChannelName(L"250-doom");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"dev-m", channel);
+      EXPECT_STREQ(L"dev-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelDev, channel);
+      EXPECT_STREQ(install_static::kChromeChannelDev, channel.c_str());
     }
     SetChannelName(L"bar-2.0-dev");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
     SetChannelName(L"1.0-dev");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
 
     SetChannelName(L"x64-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
     SetChannelName(L"bar-x64-beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
     SetChannelName(L"x64-Beta");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"beta-m", channel);
+      EXPECT_STREQ(L"beta-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelBeta, channel);
+      EXPECT_STREQ(install_static::kChromeChannelBeta, channel.c_str());
     }
 
     SetChannelName(L"x64-stable");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
     SetChannelName(L"baz-x64-stable");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
     SetChannelName(L"x64-Stable");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
 
     SetChannelName(L"fuzzy");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
     SetChannelName(L"foo");
     install_static::GetChromeChannelName(!system_level_, add_modifier,
                                          &channel);
     if (multi_install_ && add_modifier) {
-      EXPECT_EQ(L"-m", channel);
+      EXPECT_STREQ(L"-m", channel.c_str());
     } else {
-      EXPECT_EQ(install_static::kChromeChannelStable, channel);
+      EXPECT_STREQ(install_static::kChromeChannelStable, channel.c_str());
     }
   }
 
@@ -386,15 +506,17 @@
 // This test tests the install_static::GetChromeChannelName function and is
 // based on the ChannelInfoTest.Channels in channel_info_unittest.cc
 TEST_P(ChromeElfUtilTest, InstallStaticGetChannelNameTest) {
-  PerformChannelNameTests(true);  // add_modifier
-  PerformChannelNameTests(false); // !add_modifier
+  PerformChannelNameTests(true);   // add_modifier
+  PerformChannelNameTests(false);  // !add_modifier
 }
 
-INSTANTIATE_TEST_CASE_P(Canary, ChromeElfUtilTest,
+INSTANTIATE_TEST_CASE_P(Canary,
+                        ChromeElfUtilTest,
                         testing::Combine(testing::Values("canary"),
                                          testing::Values("user"),
                                          testing::Values("single")));
-INSTANTIATE_TEST_CASE_P(GoogleChrome, ChromeElfUtilTest,
+INSTANTIATE_TEST_CASE_P(GoogleChrome,
+                        ChromeElfUtilTest,
                         testing::Combine(testing::Values("google"),
                                          testing::Values("user", "system"),
                                          testing::Values("single", "multi")));