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

Side by Side Diff: chrome_elf/nt_registry/nt_registry.cc

Issue 2345913003: [chrome_elf] NTRegistry - added wow64 redirection support. (Closed)
Patch Set: clang fixes. 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome_elf/nt_registry/nt_registry.h" 5 #include "chrome_elf/nt_registry/nt_registry.h"
6 6
7 #include <mutex>
8
7 namespace { 9 namespace {
8 10
9 // Function pointers used for registry access. 11 // Function pointers used for registry access.
10 RtlInitUnicodeStringFunction g_rtl_init_unicode_string = nullptr; 12 RtlInitUnicodeStringFunction g_rtl_init_unicode_string = nullptr;
11 NtCreateKeyFunction g_nt_create_key = nullptr; 13 NtCreateKeyFunction g_nt_create_key = nullptr;
12 NtDeleteKeyFunction g_nt_delete_key = nullptr; 14 NtDeleteKeyFunction g_nt_delete_key = nullptr;
13 NtOpenKeyExFunction g_nt_open_key_ex = nullptr; 15 NtOpenKeyExFunction g_nt_open_key_ex = nullptr;
14 NtCloseFunction g_nt_close = nullptr; 16 NtCloseFunction g_nt_close = nullptr;
15 NtQueryValueKeyFunction g_nt_query_value_key = nullptr; 17 NtQueryValueKeyFunction g_nt_query_value_key = nullptr;
16 NtSetValueKeyFunction g_nt_set_value_key = nullptr; 18 NtSetValueKeyFunction g_nt_set_value_key = nullptr;
17 19
18 // Lazy init. No concern about concurrency in chrome_elf. 20 // Lazy init. No concern about concurrency in chrome_elf.
19 bool g_initialized = false; 21 bool g_initialized = false;
20 bool g_system_install = false; 22 bool g_system_install = false;
21 bool g_reg_redirection = false; 23 bool g_reg_redirection = false;
22 const size_t g_kMaxPathLen = 255; 24 const size_t g_kMaxPathLen = 255;
23 wchar_t g_kRegPathHKLM[] = L"\\Registry\\Machine\\"; 25 wchar_t g_kRegPathHKLM[] = L"\\Registry\\Machine\\";
24 wchar_t g_kRegPathHKCU[g_kMaxPathLen] = L""; 26 wchar_t g_kRegPathHKCU[g_kMaxPathLen] = L"";
25 wchar_t g_current_user_sid_string[g_kMaxPathLen] = L""; 27 wchar_t g_current_user_sid_string[g_kMaxPathLen] = L"";
26 wchar_t g_override_path[g_kMaxPathLen] = L""; 28 wchar_t g_override_path[g_kMaxPathLen] = L"";
27 29
28 // Not using install_util, to prevent circular dependency. 30 //------------------------------------------------------------------------------
31 // Initialization - LOCAL
32 //------------------------------------------------------------------------------
33
34 // Not using install_static, to prevent circular dependency.
29 bool IsThisProcSystem() { 35 bool IsThisProcSystem() {
30 wchar_t program_dir[MAX_PATH] = {}; 36 wchar_t program_dir[MAX_PATH] = {};
31 wchar_t* cmd_line = GetCommandLineW(); 37 wchar_t* cmd_line = GetCommandLineW();
32 // If our command line starts with the "Program Files" or 38 // If our command line starts with the "Program Files" or
33 // "Program Files (x86)" path, we're system. 39 // "Program Files (x86)" path, we're system.
34 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH); 40 DWORD ret = ::GetEnvironmentVariable(L"PROGRAMFILES", program_dir, MAX_PATH);
35 if (ret && ret < MAX_PATH && !::wcsncmp(cmd_line, program_dir, ret)) 41 if (ret && ret < MAX_PATH && !::wcsncmp(cmd_line, program_dir, ret))
36 return true; 42 return true;
37 43
38 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, MAX_PATH); 44 ret = ::GetEnvironmentVariable(L"PROGRAMFILES(X86)", program_dir, MAX_PATH);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 ::wcsncpy(g_current_user_sid_string, ptr, (g_kMaxPathLen - 1)); 104 ::wcsncpy(g_current_user_sid_string, ptr, (g_kMaxPathLen - 1));
99 rtl_free_unicode_str(&current_user_reg_path); 105 rtl_free_unicode_str(&current_user_reg_path);
100 106
101 // Figure out if we're a system or user install. 107 // Figure out if we're a system or user install.
102 g_system_install = IsThisProcSystem(); 108 g_system_install = IsThisProcSystem();
103 109
104 g_initialized = true; 110 g_initialized = true;
105 return true; 111 return true;
106 } 112 }
107 113
114 //------------------------------------------------------------------------------
115 // Reg Redirection - LOCAL
116 // NOTE: On >= Win7, reflection support was removed.
117 //
118 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384253(v=vs.85).as px
119 //------------------------------------------------------------------------------
120
121 // By default no WOW64 redirection will be done for any process, unless
122 // explicitly requested with the KEY_WOW64_32KEY access flag.
123 // This global setting can be changed via nt::ChangeDefaultWow64Redirection().
124 bool g_defaultRedirection = false;
125
126 typedef struct Node {
grt (UTC plus 2) 2016/09/20 10:39:54 nit: remove typedef
penny 2016/09/23 23:50:58 Done.
127 const wchar_t* to_match;
128 // If a match, the state of whether to redirect or not becomes:
129 bool if_match_set_to;
grt (UTC plus 2) 2016/09/20 10:39:54 consider replacing these two bools with something
penny 2016/09/23 23:50:58 Done. Good idea, thanks.
130 // If redirect state was set to true, the WOW64 subkey should be inserted
131 // right before (or after) this match. Unfortunately not consistent.
132 bool redirect_before;
133 // |next| is nullptr or an array of Nodes.
grt (UTC plus 2) 2016/09/20 10:39:54 nit "...Nodes of length |array_len|."
penny 2016/09/23 23:50:58 Done.
134 size_t array_len;
grt (UTC plus 2) 2016/09/20 10:39:54 nit: swap these two so that they are in the same o
penny 2016/09/23 23:50:58 Done.
135 const Node* next;
136 } Node;
137
138 const Node classes_subtree[5] = {{L"CLSID", true, true, 0, nullptr},
grt (UTC plus 2) 2016/09/20 10:39:53 constexpr Node... same for the other constants bel
grt (UTC plus 2) 2016/09/20 10:39:54 nit: remove "5" since the initializer makes the si
penny 2016/09/23 23:50:58 Done.
penny 2016/09/23 23:50:58 Done. TIL, thanks!
139 {L"DirectShow", true, true, 0, nullptr},
140 {L"Interface", true, true, 0, nullptr},
141 {L"Media Type", true, true, 0, nullptr},
142 {L"MediaFoundation", true, true, 0, nullptr}};
143
144 const Node hklm_software_subtree[49] = {
145 {L"Classes", false, false, sizeof(classes_subtree) / sizeof(Node),
grt (UTC plus 2) 2016/09/20 10:39:54 nit: #include <stdlib.h> and use _countof(classes_
penny 2016/09/23 23:50:57 Done. Excellent, thank you.
146 classes_subtree},
147
148 {L"Clients", false, false, 0, nullptr},
149 {L"Microsoft\\COM3", false, false, 0, nullptr},
150 {L"Microsoft\\Cryptography\\Calais\\Current", false, false, 0, nullptr},
151 {L"Microsoft\\Cryptography\\Calais\\Readers", false, false, 0, nullptr},
152 {L"Microsoft\\Cryptography\\Services", false, false, 0, nullptr},
153
154 {L"Microsoft\\CTF\\SystemShared", false, false, 0, nullptr},
155 {L"Microsoft\\CTF\\TIP", false, false, 0, nullptr},
156 {L"Microsoft\\DFS", false, false, 0, nullptr},
157 {L"Microsoft\\Driver Signing", false, false, 0, nullptr},
158 {L"Microsoft\\EnterpriseCertificates", false, false, 0, nullptr},
159
160 {L"Microsoft\\EventSystem", false, false, 0, nullptr},
161 {L"Microsoft\\MSMQ", false, false, 0, nullptr},
162 {L"Microsoft\\Non-Driver Signing", false, false, 0, nullptr},
163 {L"Microsoft\\Notepad\\DefaultFonts", false, false, 0, nullptr},
164 {L"Microsoft\\OLE", false, false, 0, nullptr},
165
166 {L"Microsoft\\RAS", false, false, 0, nullptr},
167 {L"Microsoft\\RPC", false, false, 0, nullptr},
168 {L"Microsoft\\SOFTWARE\\Microsoft\\Shared Tools\\MSInfo", false, false, 0,
169 nullptr},
170 {L"Microsoft\\SystemCertificates", false, false, 0, nullptr},
171 {L"Microsoft\\TermServLicensing", false, false, 0, nullptr},
172
173 {L"Microsoft\\Transaction Server", false, false, 0, nullptr},
174 {L"Microsoft\\Windows\\CurrentVersion\\App Paths", false, false, 0,
175 nullptr},
176 {L"Microsoft\\Windows\\CurrentVersion\\Control Panel\\Cursors\\Schemes",
177 false, false, 0, nullptr},
178 {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoplayHandlers", false,
179 false, 0, nullptr},
180 {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons", false, false,
181 0, nullptr},
182
183 {L"Microsoft\\Windows\\CurrentVersion\\Explorer\\KindMap", false, false, 0,
184 nullptr},
185 {L"Microsoft\\Windows\\CurrentVersion\\Group Policy", false, false, 0,
186 nullptr},
187 {L"Microsoft\\Windows\\CurrentVersion\\Policies", false, false, 0, nullptr},
188 {L"Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", false, false, 0,
189 nullptr},
190 {L"Microsoft\\Windows\\CurrentVersion\\Setup", false, false, 0, nullptr},
191
192 {L"Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations", false, false,
193 0, nullptr},
194 {L"Microsoft\\Windows NT\\CurrentVersion\\Console", false, false, 0,
195 nullptr},
196 {L"Microsoft\\Windows NT\\CurrentVersion\\FontDpi", false, false, 0,
197 nullptr},
198 {L"Microsoft\\Windows NT\\CurrentVersion\\FontLink", false, false, 0,
199 nullptr},
200 {L"Microsoft\\Windows NT\\CurrentVersion\\FontMapper", false, false, 0,
201 nullptr},
202
203 {L"Microsoft\\Windows NT\\CurrentVersion\\Fonts", false, false, 0, nullptr},
204 {L"Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes", false, false, 0,
205 nullptr},
206 {L"Microsoft\\Windows NT\\CurrentVersion\\Gre_Initialize", false, false, 0,
207 nullptr},
208 {L"Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options",
209 false, false, 0, nullptr},
210 {L"Microsoft\\Windows NT\\CurrentVersion\\LanguagePack", false, false, 0,
211 nullptr},
212
213 {L"Microsoft\\Windows NT\\CurrentVersion\\NetworkCards", false, false, 0,
214 nullptr},
215 {L"Microsoft\\Windows NT\\CurrentVersion\\Perflib", false, false, 0,
216 nullptr},
217 {L"Microsoft\\Windows NT\\CurrentVersion\\Ports", false, false, 0, nullptr},
218 {L"Microsoft\\Windows NT\\CurrentVersion\\Print", false, false, 0, nullptr},
219 {L"Microsoft\\Windows NT\\CurrentVersion\\ProfileList", false, false, 0,
220 nullptr},
221
222 {L"Microsoft\\Windows NT\\CurrentVersion\\Time Zones", false, false, 0,
223 nullptr},
224 {L"Policies", false, false, 0, nullptr},
225 {L"RegisteredApplications", false, false, 0, nullptr},
226 };
227
228 const Node g_redirectionDecisionTreeHKCU = {
grt (UTC plus 2) 2016/09/20 10:39:54 suggested comment: // HKCU is shared by default wi
penny 2016/09/23 23:50:58 Acknowledged.
229 L"SOFTWARE\\Classes", false, false, sizeof(classes_subtree) / sizeof(Node),
230 classes_subtree};
231
232 const Node g_redirectionDecisionTreeHKLM = {
grt (UTC plus 2) 2016/09/20 10:39:54 suggested comment: // HKLM\SOFTWARE is redirected
grt (UTC plus 2) 2016/09/21 10:14:06 i think this is more accurate, no? // HKLM\SOFTWAR
penny 2016/09/23 23:50:57 Acknowledged.
penny 2016/09/23 23:50:58 Acknowledged.
233 L"SOFTWARE", true, false, sizeof(hklm_software_subtree) / sizeof(Node),
234 hklm_software_subtree};
235
236 // Main redirection handler function.
237 // If redirection is required, change is made to |subkey_path| in place.
238 //
239 // This function should be called BEFORE concatenating |subkey_path| with the
240 // root hive or calling ParseFullRegPath(). Also, |subkey_path| should neither
241 // start nor end with a path seperator.
grt (UTC plus 2) 2016/09/21 10:14:06 DCHECK/assert this requirement? it seems like an e
penny 2016/09/23 23:50:58 Done.
242 void ProcessRedirection(nt::ROOT_KEY root,
243 std::wstring* subkey_path,
grt (UTC plus 2) 2016/09/20 10:39:54 swap the order of the last two args; in/out args s
penny 2016/09/23 23:50:57 Done.
244 ACCESS_MASK access) {
245 const wchar_t* redirect_before = L"WOW6432Node\\";
grt (UTC plus 2) 2016/09/20 10:39:53 static constexpr wchar_t kRedirectBefore[] = ...
penny 2016/09/23 23:50:58 Done.
246 const wchar_t* redirect_after = L"\\WOW6432Node";
247
248 if (subkey_path == nullptr || subkey_path->empty() ||
249 (access & KEY_WOW64_32KEY && access & KEY_WOW64_64KEY))
250 return;
251
252 // Get rid of nt::AUTO.
grt (UTC plus 2) 2016/09/20 10:39:53 nit: "Convert nt::AUTO to the appropriate root key
penny 2016/09/23 23:50:57 Done.
253 nt::ROOT_KEY temp_root = root;
254 if (!root) {
grt (UTC plus 2) 2016/09/20 10:39:54 be explicit rather than assume AUTO == 0, and dens
penny 2016/09/23 23:50:58 Done.
255 if (g_system_install)
256 temp_root = nt::HKLM;
257 else
258 temp_root = nt::HKCU;
259 }
260 // No redirection during testing when there's already an override.
261 if (((temp_root == nt::HKCU) && (::wcslen(nt::HKCU_override) != 0)) ||
grt (UTC plus 2) 2016/09/20 10:39:54 don't compute a string length if you just want to
penny 2016/09/23 23:50:58 Done. Good one, thank you.
262 ((temp_root == nt::HKLM) && (::wcslen(nt::HKLM_override) != 0)))
263 return;
264
265 // WOW64 redirection only supported on x64 architecture. Return if x86.
266 SYSTEM_INFO system_info = {};
267 ::GetNativeSystemInfo(&system_info);
268 if (system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) {
grt (UTC plus 2) 2016/09/20 10:39:54 nit: omit braces for single-line conditional and b
penny 2016/09/23 23:50:58 Thank you - sometimes I slip back into old coding
269 return;
270 }
271
272 // Using BOOL type for compat with IsWow64Process() system API.
273 BOOL use_wow64 = false;
grt (UTC plus 2) 2016/09/20 10:39:54 i think bool is more natural for this since that's
penny 2016/09/23 23:50:58 Done.
274 if (g_defaultRedirection) {
275 // Check if running as wow64 process.
276 typedef decltype(IsWow64Process)* IsWow64ProcessFunc;
grt (UTC plus 2) 2016/09/20 10:39:54 nit: using IsWow64ProcessFunction = decltype(&
penny 2016/09/23 23:50:57 Done. This was a bit of a mind bend for my C mind
277 IsWow64ProcessFunc is_wow64_process = reinterpret_cast<IsWow64ProcessFunc>(
grt (UTC plus 2) 2016/09/20 10:39:54 nit: cache this since it won't change throughout t
penny 2016/09/23 23:50:58 Ack. I've moved this out into IsThisProcWow64().
278 ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "IsWow64Process"));
279 if (is_wow64_process) {
280 is_wow64_process(::GetCurrentProcess(), &use_wow64);
281 }
282 }
283
284 // Consider KEY_WOW64_32KEY and KEY_WOW64_64KEY override access flags.
285 if (access & KEY_WOW64_32KEY)
286 use_wow64 = true;
287
288 if (access & KEY_WOW64_64KEY)
289 use_wow64 = false;
290
291 // If !use_wow64, there's nothing more to do.
292 if (!use_wow64)
293 return;
294
295 // Pick which decision tree to use.
296 const Node* current = nullptr;
grt (UTC plus 2) 2016/09/20 10:39:54 ... = temp_root == nt::HKCU ? &g_redirectionDecisi
penny 2016/09/23 23:50:58 Done.
297 if (temp_root == nt::HKCU)
298 current = &g_redirectionDecisionTreeHKCU;
299 else
300 current = &g_redirectionDecisionTreeHKLM;
301
302 // The following loop works on the |subkey_path| from left to right.
303 // |position| tracks progress along |subkey_path|.
304 const wchar_t* position = subkey_path->data();
grt (UTC plus 2) 2016/09/20 10:39:54 use c_str() rather than data() since the code belo
penny 2016/09/23 23:50:58 Done.
305 // |redirect| holds the latest state of whether redirection is required.
306 bool redirect = false;
307 // |insertion_point| tracks latest spot for redirection subkey to be inserted.
308 const wchar_t* insertion_point = nullptr;
309 // |insert_string| tracks which redirection string would be inserted.
310 const wchar_t* insert_string = nullptr;
311
312 // The root of the tree is an array of 1.
313 size_t array_len = 1;
314 size_t index = 0;
315 while (index < array_len) {
316 size_t len = ::wcslen(current->to_match);
grt (UTC plus 2) 2016/09/21 10:14:06 it should be possible to get rid of this length co
penny 2016/09/23 23:50:58 wow. So you pushed me out of my comfort zone ther
317 // Make sure the remainder of the path is at least as long as the current
318 // subkey to match.
319 if (::wcslen(position) >= len) {
grt (UTC plus 2) 2016/09/20 10:39:54 rather than computing the string length through ea
penny 2016/09/23 23:50:57 Done. Did it a slightly different way - but no mor
320 // Do case insensitive comparisons.
321 if (::wcsnicmp(position, current->to_match, len) == 0) {
322 // Make sure not to match on a substring.
323 if (*(position + len) == L'\\' || *(position + len) == L'\0') {
324 // MATCH!
325 // -------------------------------------------------------------------
326 // 1) Update state of whether to redirect.
327 redirect = current->if_match_set_to;
328 if (redirect) {
329 // 1.5) If |redirect| state is now true,
330 // the new insertion point will be either right before or right
331 // after this match.
332 if (current->redirect_before) {
333 insertion_point = position;
334 insert_string = redirect_before;
335 } else {
336 insertion_point = position + len;
337 insert_string = redirect_after;
338 }
339 }
340 // 2) Adjust |position| along the subkey path.
341 position += len;
342 // 2.5) Increment the position, to move past path seperator(s).
343 while (*position == L'\\')
344 position++;
345 // 3) Move our loop parameters to the |next| array of Nodes.
346 array_len = current->array_len;
347 current = current->next;
348 index = 0;
349 // 4) Finish this loop and start on new array.
350 continue;
351 }
352 }
353 }
354
355 // Move to the next node in the array if we didn't match this loop.
356 current += 1;
grt (UTC plus 2) 2016/09/20 10:39:54 nit: ++current;
penny 2016/09/23 23:50:57 Done.
357 index++;
grt (UTC plus 2) 2016/09/20 10:39:54 personal nit: prefer pre-increment even for scalar
penny 2016/09/23 23:50:57 Done.
358 }
359
360 if (!redirect)
361 return;
362
363 // Insert the redirection into |subkey_path|, at |insertion_point|.
364 subkey_path->insert((insertion_point - subkey_path->data()), insert_string);
365 }
366
367 //------------------------------------------------------------------------------
368 // Reg Path Utilities - LOCAL
369 //------------------------------------------------------------------------------
370
108 const wchar_t* ConvertRootKey(nt::ROOT_KEY root) { 371 const wchar_t* ConvertRootKey(nt::ROOT_KEY root) {
109 nt::ROOT_KEY key = root; 372 nt::ROOT_KEY key = root;
110 373
111 if (!root) { 374 if (!root) {
112 // AUTO 375 // AUTO
113 key = g_system_install ? nt::HKLM : nt::HKCU; 376 key = g_system_install ? nt::HKLM : nt::HKCU;
114 } 377 }
115 378
116 if ((key == nt::HKCU) && (::wcslen(nt::HKCU_override) != 0)) { 379 if ((key == nt::HKCU) && (::wcslen(nt::HKCU_override) != 0)) {
117 std::wstring temp(g_kRegPathHKCU); 380 std::wstring temp(g_kRegPathHKCU);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 out_base->push_back(L'\\'); 454 out_base->push_back(L'\\');
192 } 455 }
193 subkeys->erase(subkeys->begin(), subkeys->begin() + num_base_tokens); 456 subkeys->erase(subkeys->begin(), subkeys->begin() + num_base_tokens);
194 } else { 457 } else {
195 out_base->assign(converted_root); 458 out_base->assign(converted_root);
196 } 459 }
197 460
198 return true; 461 return true;
199 } 462 }
200 463
464 //------------------------------------------------------------------------------
465 // Misc wrapper functions - LOCAL
466 //------------------------------------------------------------------------------
467
201 NTSTATUS CreateKeyWrapper(const std::wstring& key_path, 468 NTSTATUS CreateKeyWrapper(const std::wstring& key_path,
202 ACCESS_MASK access, 469 ACCESS_MASK access,
203 HANDLE* out_handle, 470 HANDLE* out_handle,
204 ULONG* create_or_open OPTIONAL) { 471 ULONG* create_or_open OPTIONAL) {
205 UNICODE_STRING key_path_uni = {}; 472 UNICODE_STRING key_path_uni = {};
206 g_rtl_init_unicode_string(&key_path_uni, key_path.c_str()); 473 g_rtl_init_unicode_string(&key_path_uni, key_path.c_str());
207 474
208 OBJECT_ATTRIBUTES obj = {}; 475 OBJECT_ATTRIBUTES obj = {};
209 InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL, 476 InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL,
210 nullptr); 477 nullptr);
(...skipping 14 matching lines...) Expand all
225 // Create, open, delete, close functions 492 // Create, open, delete, close functions
226 //------------------------------------------------------------------------------ 493 //------------------------------------------------------------------------------
227 494
228 bool CreateRegKey(ROOT_KEY root, 495 bool CreateRegKey(ROOT_KEY root,
229 const wchar_t* key_path, 496 const wchar_t* key_path,
230 ACCESS_MASK access, 497 ACCESS_MASK access,
231 HANDLE* out_handle OPTIONAL) { 498 HANDLE* out_handle OPTIONAL) {
232 if (!g_initialized) 499 if (!g_initialized)
233 InitNativeRegApi(); 500 InitNativeRegApi();
234 501
502 std::wstring redirected_key_path;
503 if (key_path) {
504 redirected_key_path = key_path;
505 ProcessRedirection(root, &redirected_key_path, access);
506 }
507
235 std::wstring current_path; 508 std::wstring current_path;
236 std::vector<std::wstring> subkeys; 509 std::vector<std::wstring> subkeys;
237 if (!ParseFullRegPath(ConvertRootKey(root), key_path, &current_path, 510 if (!ParseFullRegPath(ConvertRootKey(root), redirected_key_path.data(),
238 &subkeys)) 511 &current_path, &subkeys))
239 return false; 512 return false;
240 513
241 // Open the base hive first. It should always exist already. 514 // Open the base hive first. It should always exist already.
242 HANDLE last_handle = INVALID_HANDLE_VALUE; 515 HANDLE last_handle = INVALID_HANDLE_VALUE;
243 NTSTATUS status = 516 NTSTATUS status =
244 CreateKeyWrapper(current_path, access, &last_handle, nullptr); 517 CreateKeyWrapper(current_path, access, &last_handle, nullptr);
245 if (!NT_SUCCESS(status)) 518 if (!NT_SUCCESS(status))
246 return false; 519 return false;
247 520
248 size_t subkeys_size = subkeys.size(); 521 size_t subkeys_size = subkeys.size();
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 HANDLE* out_handle, 578 HANDLE* out_handle,
306 NTSTATUS* error_code OPTIONAL) { 579 NTSTATUS* error_code OPTIONAL) {
307 if (!g_initialized) 580 if (!g_initialized)
308 InitNativeRegApi(); 581 InitNativeRegApi();
309 582
310 NTSTATUS status = STATUS_UNSUCCESSFUL; 583 NTSTATUS status = STATUS_UNSUCCESSFUL;
311 UNICODE_STRING key_path_uni = {}; 584 UNICODE_STRING key_path_uni = {};
312 OBJECT_ATTRIBUTES obj = {}; 585 OBJECT_ATTRIBUTES obj = {};
313 *out_handle = INVALID_HANDLE_VALUE; 586 *out_handle = INVALID_HANDLE_VALUE;
314 587
315 std::wstring full_path(ConvertRootKey(root)); 588 std::wstring full_path;
316 full_path.append(key_path); 589 if (key_path) {
590 full_path = key_path;
591 ProcessRedirection(root, &full_path, access);
592 }
593 full_path.insert(0, ConvertRootKey(root));
317 594
318 g_rtl_init_unicode_string(&key_path_uni, full_path.c_str()); 595 g_rtl_init_unicode_string(&key_path_uni, full_path.c_str());
319 InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL, 596 InitializeObjectAttributes(&obj, &key_path_uni, OBJ_CASE_INSENSITIVE, NULL,
320 NULL); 597 NULL);
321 598
322 status = g_nt_open_key_ex(out_handle, access, &obj, 0); 599 status = g_nt_open_key_ex(out_handle, access, &obj, 0);
323 // See if caller wants the NTSTATUS. 600 // See if caller wants the NTSTATUS.
324 if (error_code) 601 if (error_code)
325 *error_code = status; 602 *error_code = status;
326 603
(...skipping 11 matching lines...) Expand all
338 615
339 status = g_nt_delete_key(key); 616 status = g_nt_delete_key(key);
340 617
341 if (NT_SUCCESS(status)) 618 if (NT_SUCCESS(status))
342 return true; 619 return true;
343 620
344 return false; 621 return false;
345 } 622 }
346 623
347 // wrapper function 624 // wrapper function
348 bool DeleteRegKey(ROOT_KEY root, const wchar_t* key_path) { 625 bool DeleteRegKey(ROOT_KEY root,
626 WOW64_OVERRIDE wow64_override,
627 const wchar_t* key_path) {
349 HANDLE key = INVALID_HANDLE_VALUE; 628 HANDLE key = INVALID_HANDLE_VALUE;
350 629
351 if (!OpenRegKey(root, key_path, DELETE, &key, nullptr)) 630 if (!OpenRegKey(root, key_path, DELETE | wow64_override, &key, nullptr))
352 return false; 631 return false;
353 632
354 if (!DeleteRegKey(key)) { 633 if (!DeleteRegKey(key)) {
355 CloseRegKey(key); 634 CloseRegKey(key);
356 return false; 635 return false;
357 } 636 }
358 637
359 CloseRegKey(key); 638 CloseRegKey(key);
360 return true; 639 return true;
361 } 640 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 return false; 702 return false;
424 703
425 *out_dword = *(reinterpret_cast<DWORD*>(value_bytes)); 704 *out_dword = *(reinterpret_cast<DWORD*>(value_bytes));
426 705
427 delete[] value_bytes; 706 delete[] value_bytes;
428 return true; 707 return true;
429 } 708 }
430 709
431 // wrapper function 710 // wrapper function
432 bool QueryRegValueDWORD(ROOT_KEY root, 711 bool QueryRegValueDWORD(ROOT_KEY root,
712 WOW64_OVERRIDE wow64_override,
433 const wchar_t* key_path, 713 const wchar_t* key_path,
434 const wchar_t* value_name, 714 const wchar_t* value_name,
435 DWORD* out_dword) { 715 DWORD* out_dword) {
436 HANDLE key = INVALID_HANDLE_VALUE; 716 HANDLE key = INVALID_HANDLE_VALUE;
437 717
438 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, 718 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
439 NULL))
440 return false; 719 return false;
441 720
442 if (!QueryRegValueDWORD(key, value_name, out_dword)) { 721 if (!QueryRegValueDWORD(key, value_name, out_dword)) {
443 CloseRegKey(key); 722 CloseRegKey(key);
444 return false; 723 return false;
445 } 724 }
446 725
447 CloseRegKey(key); 726 CloseRegKey(key);
448 return true; 727 return true;
449 } 728 }
(...skipping 11 matching lines...) Expand all
461 return false; 740 return false;
462 741
463 *out_sz = reinterpret_cast<wchar_t*>(value_bytes); 742 *out_sz = reinterpret_cast<wchar_t*>(value_bytes);
464 743
465 delete[] value_bytes; 744 delete[] value_bytes;
466 return true; 745 return true;
467 } 746 }
468 747
469 // wrapper function 748 // wrapper function
470 bool QueryRegValueSZ(ROOT_KEY root, 749 bool QueryRegValueSZ(ROOT_KEY root,
750 WOW64_OVERRIDE wow64_override,
471 const wchar_t* key_path, 751 const wchar_t* key_path,
472 const wchar_t* value_name, 752 const wchar_t* value_name,
473 std::wstring* out_sz) { 753 std::wstring* out_sz) {
474 HANDLE key = INVALID_HANDLE_VALUE; 754 HANDLE key = INVALID_HANDLE_VALUE;
475 755
476 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, 756 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
477 NULL))
478 return false; 757 return false;
479 758
480 if (!QueryRegValueSZ(key, value_name, out_sz)) { 759 if (!QueryRegValueSZ(key, value_name, out_sz)) {
481 CloseRegKey(key); 760 CloseRegKey(key);
482 return false; 761 return false;
483 } 762 }
484 763
485 CloseRegKey(key); 764 CloseRegKey(key);
486 return true; 765 return true;
487 } 766 }
(...skipping 27 matching lines...) Expand all
515 // Handle the case of "empty multi_sz". 794 // Handle the case of "empty multi_sz".
516 if (out_multi_sz->size() == 0) 795 if (out_multi_sz->size() == 0)
517 out_multi_sz->push_back(L""); 796 out_multi_sz->push_back(L"");
518 797
519 delete[] value_bytes; 798 delete[] value_bytes;
520 return true; 799 return true;
521 } 800 }
522 801
523 // wrapper function 802 // wrapper function
524 bool QueryRegValueMULTISZ(ROOT_KEY root, 803 bool QueryRegValueMULTISZ(ROOT_KEY root,
804 WOW64_OVERRIDE wow64_override,
525 const wchar_t* key_path, 805 const wchar_t* key_path,
526 const wchar_t* value_name, 806 const wchar_t* value_name,
527 std::vector<std::wstring>* out_multi_sz) { 807 std::vector<std::wstring>* out_multi_sz) {
528 HANDLE key = INVALID_HANDLE_VALUE; 808 HANDLE key = INVALID_HANDLE_VALUE;
529 809
530 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &key, 810 if (!OpenRegKey(root, key_path, KEY_QUERY_VALUE | wow64_override, &key, NULL))
531 NULL))
532 return false; 811 return false;
533 812
534 if (!QueryRegValueMULTISZ(key, value_name, out_multi_sz)) { 813 if (!QueryRegValueMULTISZ(key, value_name, out_multi_sz)) {
535 CloseRegKey(key); 814 CloseRegKey(key);
536 return false; 815 return false;
537 } 816 }
538 817
539 CloseRegKey(key); 818 CloseRegKey(key);
540 return true; 819 return true;
541 } 820 }
(...skipping 25 matching lines...) Expand all
567 } 846 }
568 847
569 // wrapper function 848 // wrapper function
570 bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value) { 849 bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value) {
571 return SetRegKeyValue(key, value_name, REG_DWORD, 850 return SetRegKeyValue(key, value_name, REG_DWORD,
572 reinterpret_cast<BYTE*>(&value), sizeof(value)); 851 reinterpret_cast<BYTE*>(&value), sizeof(value));
573 } 852 }
574 853
575 // wrapper function 854 // wrapper function
576 bool SetRegValueDWORD(ROOT_KEY root, 855 bool SetRegValueDWORD(ROOT_KEY root,
856 WOW64_OVERRIDE wow64_override,
577 const wchar_t* key_path, 857 const wchar_t* key_path,
578 const wchar_t* value_name, 858 const wchar_t* value_name,
579 DWORD value) { 859 DWORD value) {
580 HANDLE key = INVALID_HANDLE_VALUE; 860 HANDLE key = INVALID_HANDLE_VALUE;
581 861
582 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) 862 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
583 return false; 863 return false;
584 864
585 if (!SetRegValueDWORD(key, value_name, value)) { 865 if (!SetRegValueDWORD(key, value_name, value)) {
586 CloseRegKey(key); 866 CloseRegKey(key);
587 return false; 867 return false;
588 } 868 }
589 869
590 return true; 870 return true;
591 } 871 }
592 872
593 // wrapper function 873 // wrapper function
594 bool SetRegValueSZ(HANDLE key, 874 bool SetRegValueSZ(HANDLE key,
595 const wchar_t* value_name, 875 const wchar_t* value_name,
596 const std::wstring& value) { 876 const std::wstring& value) {
597 // Make sure the number of bytes in |value|, including EoS, fits in a DWORD. 877 // Make sure the number of bytes in |value|, including EoS, fits in a DWORD.
598 if (std::numeric_limits<DWORD>::max() < 878 if (std::numeric_limits<DWORD>::max() <
599 ((value.length() + 1) * sizeof(wchar_t))) 879 ((value.length() + 1) * sizeof(wchar_t)))
600 return false; 880 return false;
601 881
602 DWORD size = (static_cast<DWORD>((value.length() + 1) * sizeof(wchar_t))); 882 DWORD size = (static_cast<DWORD>((value.length() + 1) * sizeof(wchar_t)));
603 return SetRegKeyValue(key, value_name, REG_SZ, 883 return SetRegKeyValue(key, value_name, REG_SZ,
604 reinterpret_cast<const BYTE*>(value.c_str()), size); 884 reinterpret_cast<const BYTE*>(value.c_str()), size);
605 } 885 }
606 886
607 // wrapper function 887 // wrapper function
608 bool SetRegValueSZ(ROOT_KEY root, 888 bool SetRegValueSZ(ROOT_KEY root,
889 WOW64_OVERRIDE wow64_override,
609 const wchar_t* key_path, 890 const wchar_t* key_path,
610 const wchar_t* value_name, 891 const wchar_t* value_name,
611 const std::wstring& value) { 892 const std::wstring& value) {
612 HANDLE key = INVALID_HANDLE_VALUE; 893 HANDLE key = INVALID_HANDLE_VALUE;
613 894
614 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) 895 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
615 return false; 896 return false;
616 897
617 if (!SetRegValueSZ(key, value_name, value)) { 898 if (!SetRegValueSZ(key, value_name, value)) {
618 CloseRegKey(key); 899 CloseRegKey(key);
619 return false; 900 return false;
620 } 901 }
621 902
622 return true; 903 return true;
623 } 904 }
624 905
(...skipping 23 matching lines...) Expand all
648 if (std::numeric_limits<DWORD>::max() < builder.size()) 929 if (std::numeric_limits<DWORD>::max() < builder.size())
649 return false; 930 return false;
650 931
651 return SetRegKeyValue( 932 return SetRegKeyValue(
652 key, value_name, REG_MULTI_SZ, reinterpret_cast<BYTE*>(builder.data()), 933 key, value_name, REG_MULTI_SZ, reinterpret_cast<BYTE*>(builder.data()),
653 (static_cast<DWORD>(builder.size()) + 1) * sizeof(wchar_t)); 934 (static_cast<DWORD>(builder.size()) + 1) * sizeof(wchar_t));
654 } 935 }
655 936
656 // wrapper function 937 // wrapper function
657 bool SetRegValueMULTISZ(ROOT_KEY root, 938 bool SetRegValueMULTISZ(ROOT_KEY root,
939 WOW64_OVERRIDE wow64_override,
658 const wchar_t* key_path, 940 const wchar_t* key_path,
659 const wchar_t* value_name, 941 const wchar_t* value_name,
660 const std::vector<std::wstring>& values) { 942 const std::vector<std::wstring>& values) {
661 HANDLE key = INVALID_HANDLE_VALUE; 943 HANDLE key = INVALID_HANDLE_VALUE;
662 944
663 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | KEY_WOW64_32KEY, &key, NULL)) 945 if (!OpenRegKey(root, key_path, KEY_SET_VALUE | wow64_override, &key, NULL))
664 return false; 946 return false;
665 947
666 if (!SetRegValueMULTISZ(key, value_name, values)) { 948 if (!SetRegValueMULTISZ(key, value_name, values)) {
667 CloseRegKey(key); 949 CloseRegKey(key);
668 return false; 950 return false;
669 } 951 }
670 952
671 return true; 953 return true;
672 } 954 }
673 955
674 //------------------------------------------------------------------------------ 956 //------------------------------------------------------------------------------
675 // Utils 957 // Utils
676 //------------------------------------------------------------------------------ 958 //------------------------------------------------------------------------------
677 959
678 const wchar_t* GetCurrentUserSidString() { 960 const wchar_t* GetCurrentUserSidString() {
679 if (!g_initialized) 961 if (!g_initialized)
680 InitNativeRegApi(); 962 InitNativeRegApi();
681 963
682 return g_current_user_sid_string; 964 return g_current_user_sid_string;
683 } 965 }
684 966
967 void ChangeDefaultWow64Redirection(bool default_on) {
968 g_defaultRedirection = default_on;
969 }
970
685 }; // namespace nt 971 }; // namespace nt
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698