Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4907)

Unified Diff: chrome_elf/nt_registry/nt_registry.cc

Issue 2345913003: [chrome_elf] NTRegistry - added wow64 redirection support. (Closed)
Patch Set: Code review fixes, part 2. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome_elf/nt_registry/nt_registry.cc
diff --git a/chrome_elf/nt_registry/nt_registry.cc b/chrome_elf/nt_registry/nt_registry.cc
index 373f00945682e20e1c1108a244015bc4ec43ae2e..eb80359f529a261be6ad5cc142f3da8c243f3b00 100644
--- a/chrome_elf/nt_registry/nt_registry.cc
+++ b/chrome_elf/nt_registry/nt_registry.cc
@@ -4,6 +4,9 @@
#include "chrome_elf/nt_registry/nt_registry.h"
+#include <assert.h>
+#include <stdlib.h>
+
namespace {
// Function pointers used for registry access.
@@ -18,6 +21,7 @@ NtSetValueKeyFunction g_nt_set_value_key = nullptr;
// Lazy init. No concern about concurrency in chrome_elf.
bool g_initialized = false;
bool g_system_install = false;
+bool g_wow64_proc = false;
bool g_reg_redirection = false;
const size_t g_kMaxPathLen = 255;
wchar_t g_kRegPathHKLM[] = L"\\Registry\\Machine\\";
@@ -25,7 +29,11 @@ wchar_t g_kRegPathHKCU[g_kMaxPathLen] = L"";
wchar_t g_current_user_sid_string[g_kMaxPathLen] = L"";
wchar_t g_override_path[g_kMaxPathLen] = L"";
-// Not using install_util, to prevent circular dependency.
+//------------------------------------------------------------------------------
+// Initialization - LOCAL
+//------------------------------------------------------------------------------
+
+// Not using install_static, to prevent circular dependency.
bool IsThisProcSystem() {
wchar_t program_dir[MAX_PATH] = {};
wchar_t* cmd_line = GetCommandLineW();
@@ -42,6 +50,22 @@ bool IsThisProcSystem() {
return false;
}
+bool IsThisProcWow64() {
robertshield 2016/09/28 23:49:23 This function looks an awful lot like https://code
penny 2016/09/30 05:28:22 Commonalizified. I've exposed this information wi
+ // Using BOOL type for compat with IsWow64Process() system API.
+ BOOL is_wow64 = FALSE;
+
+ // API might not exist, so dynamic lookup.
+ using IsWow64ProcessFunction = decltype(&IsWow64Process);
+ IsWow64ProcessFunction is_wow64_process =
+ reinterpret_cast<IsWow64ProcessFunction>(::GetProcAddress(
+ ::GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
+ if (!is_wow64_process)
+ return false;
+ if (!is_wow64_process(::GetCurrentProcess(), &is_wow64))
+ return false;
+ return is_wow64 ? true : false;
+}
+
bool InitNativeRegApi() {
HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
@@ -98,13 +122,308 @@ bool InitNativeRegApi() {
::wcsncpy(g_current_user_sid_string, ptr, (g_kMaxPathLen - 1));
rtl_free_unicode_str(&current_user_reg_path);
- // Figure out if we're a system or user install.
+ // Figure out if this is a system or user install.
g_system_install = IsThisProcSystem();
+ // Figure out if this is a WOW64 process.
+ g_wow64_proc = IsThisProcWow64();
+
g_initialized = true;
return true;
}
+//------------------------------------------------------------------------------
+// Reg WOW64 Redirection - LOCAL
+//
+// How registry redirection works directly calling NTDLL APIs:
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// - NOTE: On >= Win7, reflection support was removed.
+// -
+// https://msdn.microsoft.com/en-us/library/windows/desktop/aa384253(v=vs.85).aspx
+//
+// - 1) 32-bit / WOW64 process:
+// a) Default access WILL be redirected to WOW64.
+// b) KEY_WOW64_32KEY access WILL be redirected to WOW64.
+// c) KEY_WOW64_64KEY access will NOT be redirected to WOW64.
+//
+// - 2) 64-bit process:
+// a) Default access will NOT be redirected to WOW64.
+// b) KEY_WOW64_32KEY access will NOT be redirected to WOW64.
+// c) KEY_WOW64_64KEY access will NOT be redirected to WOW64.
+//
+// - Key point from above is that NTDLL redirects and respects access
+// overrides for WOW64 calling processes. But does NOT do any of that if the
+// calling process is 64-bit. 2b is surprising and troublesome.
+//
+// How registry redirection works using these nt_registry APIs:
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// - These APIs will behave the same as NTDLL above, EXCEPT for 2b.
+// nt_registry APIs will respect the override access flags for all processes.
+//
+// - How the WOW64 redirection decision trees / Nodes work below:
+//
+// The HKLM and HKCU descision trees represent the information at the MSDN
robertshield 2016/09/28 23:49:23 nit: decision
penny 2016/09/30 05:28:22 Thank you. I dislike spelling or grammatical erro
+// link above... but in a way that generates a decision about whether a
+// registry path should be subject to WOW64 redirection. The tree is
+// traversed as you scan along the registry path in question.
+//
+// - Each Node contains a chunk of registry subkey(s) to match.
+// - If it is NOT matched, traversal is done.
+// - If it is matched:
+// - Current state of |redirection_type| for the whole registry path is
+// updated.
+// - If |next| is empty, traversal is done.
+// - Otherwise, |next| is an array of child Nodes to try to match against.
+// Loop.
+//------------------------------------------------------------------------------
+
+// This enum defines states for how to handle redirection.
+// NOTE: When WOW64 redirection should happen, the redirect subkey can be either
+// before or after the latest Node match. Unfortunately not consistent.
+enum RedirectionType { SHARED = 0, REDIRECTED_BEFORE, REDIRECTED_AFTER };
+
+struct Node {
+ template <size_t len, size_t n_len>
+ constexpr Node(const wchar_t (&wcs)[len],
+ RedirectionType rt,
+ const Node (&n)[n_len])
+ : to_match(wcs),
+ to_match_len(len - 1),
+ redirection_type(rt),
+ next(n),
+ next_len(n_len) {}
+
+ template <size_t len>
+ constexpr Node(const wchar_t (&wcs)[len], RedirectionType rt)
+ : to_match(wcs),
+ to_match_len(len - 1),
+ redirection_type(rt),
+ next(nullptr),
+ next_len(0) {}
+
+ const wchar_t* to_match;
+ size_t to_match_len;
+ // If a match, this is the new state of how to redirect.
+ RedirectionType redirection_type;
+ // |next| is nullptr or an array of Nodes of length |array_len|.
+ const Node* next;
+ size_t next_len;
+};
+
+// HKLM or HKCU SOFTWARE\Classes is shared by default. Specific subkeys under
+// Classes are redirected to SOFTWARE\WOW6432Node\Classes\<subkey> though.
+constexpr Node classes_subtree[] = {{L"CLSID", REDIRECTED_BEFORE},
grt (UTC plus 2) 2016/09/29 10:30:22 nit: kClassesSubtree
penny 2016/09/30 05:28:22 Sorry - I should have changed these at the same ti
+ {L"DirectShow", REDIRECTED_BEFORE},
+ {L"Interface", REDIRECTED_BEFORE},
+ {L"Media Type", REDIRECTED_BEFORE},
+ {L"MediaFoundation", REDIRECTED_BEFORE}};
+
+// These specific HKLM\SOFTWARE subkeys are shared. Specific
+// subkeys under Classes are redirected though... see classes_subtree.
+constexpr Node hklm_software_subtree[] = {
grt (UTC plus 2) 2016/09/29 10:30:22 nit: kHklmSoftwareSubtree
penny 2016/09/30 05:28:22 Sorry - I should have changed these at the same ti
+ // TODO(pennymac): when MS fixes compiler bug, or bots are all using clang,
+ // remove the "Classes" subkeys below and replace with:
+ // {L"Classes", SHARED, classes_subtree},
+ // https://connect.microsoft.com/VisualStudio/feedback/details/3104499
+ {L"Classes\\CLSID", REDIRECTED_BEFORE},
+ {L"Classes\\DirectShow", REDIRECTED_BEFORE},
+ {L"Classes\\Interface", REDIRECTED_BEFORE},
+ {L"Classes\\Media Type", REDIRECTED_BEFORE},
+ {L"Classes\\MediaFoundation", REDIRECTED_BEFORE},
+ {L"Classes", SHARED},
+
+ {L"Clients", SHARED},
+ {L"Microsoft\\COM3", SHARED},
+ {L"Microsoft\\Cryptography\\Calais\\Current", SHARED},
+ {L"Microsoft\\Cryptography\\Calais\\Readers", SHARED},
+ {L"Microsoft\\Cryptography\\Services", SHARED},
+
+ {L"Microsoft\\CTF\\SystemShared", SHARED},
+ {L"Microsoft\\CTF\\TIP", SHARED},
+ {L"Microsoft\\DFS", SHARED},
+ {L"Microsoft\\Driver Signing", SHARED},
+ {L"Microsoft\\EnterpriseCertificates", SHARED},
+
+ {L"Microsoft\\EventSystem", SHARED},
+ {L"Microsoft\\MSMQ", SHARED},
+ {L"Microsoft\\Non-Driver Signing", SHARED},
+ {L"Microsoft\\Notepad\\DefaultFonts", SHARED},
+ {L"Microsoft\\OLE", SHARED},
+
+ {L"Microsoft\\RAS", SHARED},
+ {L"Microsoft\\RPC", SHARED},
+ {L"Microsoft\\SOFTWARE\\Microsoft\\Shared Tools\\MSInfo", SHARED},
+ {L"Microsoft\\SystemCertificates", SHARED},
+ {L"Microsoft\\TermServLicensing", SHARED},
+
+ {L"Microsoft\\Transaction Server", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\App Paths", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes",
+ SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons", SHARED},
+
+ {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\KindMap", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Group Policy", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Policies", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", SHARED},
+ {L"Microsoft\\Windows\\CurrentVersion\\Setup", SHARED},
+
+ {L"Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Console", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\FontDpi", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\FontLink", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\FontMapper", SHARED},
+
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Fonts", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Gre_Initialize", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
+ SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\LanguagePack", SHARED},
+
+ {L"Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Perflib", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Ports", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Print", SHARED},
+ {L"Microsoft\\Windows NT\\CurrentVersion\\ProfileList", SHARED},
+
+ {L"Microsoft\\Windows NT\\CurrentVersion\\Time Zones", SHARED},
+ {L"Policies", SHARED},
+ {L"RegisteredApplications", SHARED}};
+
+// HKCU is entirely shared, except for a few specific Classes subkeys which
+// are redirected. See |classes_subtree|.
+constexpr Node g_redirectionDecisionTreeHKCU = {L"SOFTWARE\\Classes", SHARED,
grt (UTC plus 2) 2016/09/29 10:30:22 nit: kRedirectionDecisionTreeHkcu
penny 2016/09/30 05:28:22 Done.
+ classes_subtree};
+
+// HKLM\SOFTWARE is redirected by default to SOFTWARE\WOW6432Node. Specific
+// subkeys under SOFTWARE are shared though... see |hklm_software_subtree|.
+constexpr Node g_redirectionDecisionTreeHKLM = {L"SOFTWARE", REDIRECTED_AFTER,
grt (UTC plus 2) 2016/09/29 10:30:22 nit: kRedirectionDecisionTreeHklm
penny 2016/09/30 05:28:22 Done.
+ hklm_software_subtree};
+
+// Main redirection handler function.
+// If redirection is required, change is made to |subkey_path| in place.
+//
+// - This function should be called BEFORE concatenating |subkey_path| with the
+// root hive or calling ParseFullRegPath().
+// - Also, |subkey_path| should be passed to SanitizeSubkeyPath() before calling
grt (UTC plus 2) 2016/09/29 10:30:22 how about enforcing this by adding to the top of t
penny 2016/09/30 05:28:22 My take on this is that external APIs should be re
grt (UTC plus 2) 2016/09/30 09:32:16 Your philosophy on when to sanitize external input
penny 2016/10/01 01:44:25 I hear ya, and considered just changing ProcessRed
grt (UTC plus 2) 2016/10/02 20:10:53 Do the underlying Nt registry functions choke on m
penny 2016/10/03 19:18:48 I'm not sure at the moment. It (advapi or ntdll)
+// this function.
+void ProcessRedirection(nt::ROOT_KEY root,
+ ACCESS_MASK access,
+ std::wstring* subkey_path) {
+ static constexpr wchar_t kRedirectBefore[] = L"WOW6432Node\\";
+ static constexpr wchar_t kRedirectAfter[] = L"\\WOW6432Node";
+
+ if (subkey_path == nullptr || subkey_path->empty() ||
+ (access & KEY_WOW64_32KEY && access & KEY_WOW64_64KEY))
+ return;
+
+ // Convert nt::AUTO to the appropriate root key.
+ nt::ROOT_KEY temp_root = root;
+ if (root == nt::AUTO)
+ temp_root = g_system_install ? nt::HKLM : nt::HKCU;
+
+ // No redirection during testing when there's already an override.
+ // Otherwise, the testing redirect directory Software\Chromium\TempTestKeys
+ // would get WOW64 redirected if root_key == HKLM in this function.
+ if ((temp_root == nt::HKCU && *nt::HKCU_override) ||
+ (temp_root == nt::HKLM && *nt::HKLM_override))
+ return;
+
+ // WOW64 redirection only supported on x64 architecture. Return if x86.
+ SYSTEM_INFO system_info = {};
+ ::GetNativeSystemInfo(&system_info);
+ if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ return;
+
+ bool use_wow64 = g_wow64_proc;
+ // Consider KEY_WOW64_32KEY and KEY_WOW64_64KEY override access flags.
+ if (access & KEY_WOW64_32KEY)
+ use_wow64 = true;
+ if (access & KEY_WOW64_64KEY)
+ use_wow64 = false;
+
+ // If !use_wow64, there's nothing more to do.
+ if (!use_wow64)
+ return;
+
+ // Pick which decision tree to use.
+ const Node* current = (temp_root == nt::HKCU)
+ ? &g_redirectionDecisionTreeHKCU
+ : &g_redirectionDecisionTreeHKLM;
+
+ // The following loop works on the |subkey_path| from left to right.
+ // |position| tracks progress along |subkey_path|.
+ const wchar_t* position = subkey_path->c_str();
+ // Hold a count of chars left after position, for efficient calculations.
+ size_t chars_left = subkey_path->length();
+ // |redirect_state| holds the latest state of redirection requirement.
+ RedirectionType redirect_state = SHARED;
+ // |insertion_point| tracks latest spot for redirection subkey to be inserted.
+ const wchar_t* insertion_point = nullptr;
+ // |insert_string| tracks which redirection string would be inserted.
+ const wchar_t* insert_string = nullptr;
+
+ // The root of the tree is an array of 1.
grt (UTC plus 2) 2016/09/29 10:30:22 uber-nit: move the definition of |array_len| up so
penny 2016/09/30 05:28:22 Done.
+ size_t array_len = 1;
grt (UTC plus 2) 2016/09/29 10:30:22 nit: array_len -> node_array_len
penny 2016/09/30 05:28:23 I like this, thanks. More clear. I've also chang
+ size_t index = 0;
grt (UTC plus 2) 2016/09/29 10:30:22 nit: index -> node_index
penny 2016/09/30 05:28:23 Done.
+ while (index < array_len) {
+ size_t len = current->to_match_len;
grt (UTC plus 2) 2016/09/29 10:30:22 nit: len -> to_match_len
penny 2016/09/30 05:28:22 Done. current_to_match_len. I don't want any conf
+ // Make sure the remainder of the path is at least as long as the current
+ // subkey to match.
+ if (chars_left >= len) {
+ // Do case insensitive comparisons.
+ if (::wcsnicmp(position, current->to_match, len) == 0) {
+ // Make sure not to match on a substring.
+ if (*(position + len) == L'\\' || *(position + len) == L'\0') {
+ // MATCH!
+ // -------------------------------------------------------------------
+ // 1) Update state of redirection.
+ redirect_state = current->redirection_type;
+ // 1.5) If new state is to redirect, the new insertion point will be
+ // either right before or right after this match.
+ if (redirect_state == REDIRECTED_BEFORE) {
+ insertion_point = position;
+ insert_string = kRedirectBefore;
+ } else if (redirect_state == REDIRECTED_AFTER) {
+ insertion_point = position + len;
+ insert_string = kRedirectAfter;
+ }
+ // 2) Adjust |position| along the subkey path.
+ position += len;
+ chars_left -= len;
+ // 2.5) Increment the position, to move past path seperator(s).
+ while (*position == L'\\') {
+ ++position;
+ --chars_left;
+ }
+ // 3) Move our loop parameters to the |next| array of Nodes.
+ array_len = current->next_len;
+ current = current->next;
+ index = 0;
+ // 4) Finish this loop and start on new array.
+ continue;
+ }
+ }
+ }
+
+ // Move to the next node in the array if we didn't match this loop.
+ ++current;
+ ++index;
+ }
+
+ if (redirect_state == SHARED)
+ return;
+
+ // Insert the redirection into |subkey_path|, at |insertion_point|.
+ subkey_path->insert((insertion_point - subkey_path->data()), insert_string);
grt (UTC plus 2) 2016/09/29 10:30:22 nit: data -> c_str for consistency with the code a
penny 2016/09/30 05:28:22 Done.
+}
+
+//------------------------------------------------------------------------------
+// Reg Path Utilities - LOCAL
+//------------------------------------------------------------------------------
+
const wchar_t* ConvertRootKey(nt::ROOT_KEY root) {
nt::ROOT_KEY key = root;
@@ -113,14 +432,14 @@ const wchar_t* ConvertRootKey(nt::ROOT_KEY root) {
key = g_system_install ? nt::HKLM : nt::HKCU;
}
- if ((key == nt::HKCU) && (::wcslen(nt::HKCU_override) != 0)) {
+ if (key == nt::HKCU && *nt::HKCU_override) {
std::wstring temp(g_kRegPathHKCU);
temp.append(nt::HKCU_override);
temp.append(L"\\");
::wcsncpy(g_override_path, temp.c_str(), g_kMaxPathLen - 1);
g_reg_redirection = true;
return g_override_path;
- } else if ((key == nt::HKLM) && (::wcslen(nt::HKLM_override) != 0)) {
+ } else if (key == nt::HKLM && *nt::HKLM_override) {
std::wstring temp(g_kRegPathHKCU);
temp.append(nt::HKLM_override);
temp.append(L"\\");
@@ -136,9 +455,30 @@ const wchar_t* ConvertRootKey(nt::ROOT_KEY root) {
return g_kRegPathHKLM;
}
+// This utility should be called on an externally provided subkey path.
+// - Ensures there are no starting or trailing backslashes.
+// - Note from MSDN: "Key names cannot include the backslash character (\),
+// but any other printable character can be used."
+void SanitizeSubkeyPath(std::wstring* input) {
+ if (input == nullptr || input->empty())
grt (UTC plus 2) 2016/09/29 10:30:22 two comments here: since this is a private functi
penny 2016/09/30 05:28:22 I fully agree. Thank you.
+ return;
+
+ // Remove any trailing backslashes.
+ while (input->back() == L'\\')
grt (UTC plus 2) 2016/09/29 10:30:22 this provokes undefined behavior if the string con
penny 2016/09/30 05:28:22 TIL, don't call front/back on an empty std::wstrin
grt (UTC plus 2) 2016/09/30 09:32:16 I think it's much more clear and safe to use the s
penny 2016/10/01 01:44:25 I'm fully agreeing with you now. This is much nic
+ input->pop_back();
+
+ // Remove any starting backslashes.
+ size_t index = 0;
+ while (input->at(index) == L'\\')
grt (UTC plus 2) 2016/09/29 10:30:22 fyi: at() does bounds checking and throws exceptio
penny 2016/09/30 05:28:22 TIL. Thanks. Reading the docs, I think [] operat
+ ++index;
+ if (!index)
+ *input = input->substr(index);
+}
+
// Turns a root and subkey path into the registry base hive and the rest of the
// subkey tokens.
// - |converted_root| should come directly out of ConvertRootKey function.
+// - |subkey_path| should be passed to SanitizeSubkeyPath() first.
// - E.g. base hive: "\Registry\Machine\", "\Registry\User\<SID>\".
bool ParseFullRegPath(const wchar_t* converted_root,
const wchar_t* subkey_path,
@@ -198,6 +538,10 @@ bool ParseFullRegPath(const wchar_t* converted_root,
return true;
}
+//------------------------------------------------------------------------------
+// Misc wrapper functions - LOCAL
+//------------------------------------------------------------------------------
+
NTSTATUS CreateKeyWrapper(const std::wstring& key_path,
ACCESS_MASK access,
HANDLE* out_handle,
@@ -232,10 +576,17 @@ bool CreateRegKey(ROOT_KEY root,
if (!g_initialized)
InitNativeRegApi();
+ std::wstring redirected_key_path;
+ if (key_path) {
+ redirected_key_path = key_path;
+ SanitizeSubkeyPath(&redirected_key_path);
+ ProcessRedirection(root, access, &redirected_key_path);
+ }
+
std::wstring current_path;
std::vector<std::wstring> subkeys;
- if (!ParseFullRegPath(ConvertRootKey(root), key_path, &current_path,
- &subkeys))
+ if (!ParseFullRegPath(ConvertRootKey(root), redirected_key_path.c_str(),
grt (UTC plus 2) 2016/09/29 10:30:22 pass redirected_key_path directly as a const std::
penny 2016/09/30 05:28:22 Done.
+ &current_path, &subkeys))
return false;
// Open the base hive first. It should always exist already.
@@ -312,8 +663,13 @@ bool OpenRegKey(ROOT_KEY root,
OBJECT_ATTRIBUTES obj = {};
*out_handle = INVALID_HANDLE_VALUE;
- std::wstring full_path(ConvertRootKey(root));
- full_path.append(key_path);
+ std::wstring full_path;
+ if (key_path) {
+ full_path = key_path;
+ SanitizeSubkeyPath(&full_path);
+ ProcessRedirection(root, access, &full_path);
+ }
+ full_path.insert(0, ConvertRootKey(root));
g_rtl_init_unicode_string(&key_path_uni, full_path.c_str());
InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL,
@@ -345,10 +701,12 @@ bool DeleteRegKey(HANDLE key) {
}
// wrapper function
-bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path) {
+bool DeleteRegKey(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
+ const wchar_t* key_path) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, DELETE, &key, nullptr))
+ if (!OpenRegKey(root, key_path, DELETE | wow64_override, &key, nullptr))
return false;
if (!DeleteRegKey(key)) {
@@ -430,13 +788,13 @@ bool QueryRegValueDWORD(HANDLE key,
// wrapper function
bool QueryRegValueDWORD(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
DWORD* out_dword) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key,
- NULL))
+ if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
return false;
if (!QueryRegValueDWORD(key, value_name, out_dword)) {
@@ -468,13 +826,13 @@ bool QueryRegValueSZ(HANDLE key,
// wrapper function
bool QueryRegValueSZ(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
std::wstring* out_sz) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key,
- NULL))
+ if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
return false;
if (!QueryRegValueSZ(key, value_name, out_sz)) {
@@ -522,13 +880,13 @@ bool QueryRegValueMULTISZ(HANDLE key,
// wrapper function
bool QueryRegValueMULTISZ(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
std::vector<std::wstring>* out_multi_sz) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key,
- NULL))
+ if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
return false;
if (!QueryRegValueMULTISZ(key, value_name, out_multi_sz)) {
@@ -574,12 +932,13 @@ bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value) {
// wrapper function
bool SetRegValueDWORD(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
DWORD value) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL))
+ if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
return false;
if (!SetRegValueDWORD(key, value_name, value)) {
@@ -606,12 +965,13 @@ bool SetRegValueSZ(HANDLE key,
// wrapper function
bool SetRegValueSZ(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
const std::wstring& value) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL))
+ if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
return false;
if (!SetRegValueSZ(key, value_name, value)) {
@@ -655,12 +1015,13 @@ bool SetRegValueMULTISZ(HANDLE key,
// wrapper function
bool SetRegValueMULTISZ(ROOT_KEY root,
+ WOW64_OVERRIDE wow64_override,
const wchar_t* key_path,
const wchar_t* value_name,
const std::vector<std::wstring>& values) {
HANDLE key = INVALID_HANDLE_VALUE;
- if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL))
+ if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
return false;
if (!SetRegValueMULTISZ(key, value_name, values)) {

Powered by Google App Engine
This is Rietveld 408576698