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

Side by Side Diff: base/win/registry.cc

Issue 275103012: Add WOW64 support and DeleteEmptyKey to base::win::registry. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: separate the wow64 code from the bug fixes Created 6 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "base/win/registry.h" 5 #include "base/win/registry.h"
6 6
7 #include <shlwapi.h> 7 #include <shlwapi.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 13 #include "base/win/windows_version.h"
14 #pragma comment(lib, "shlwapi.lib") // for SHDeleteKey
grt (UTC plus 2) 2014/05/16 15:44:43 w00t!
Will Harris 2014/05/16 22:55:45 :D
15 14
16 namespace base { 15 namespace base {
17 namespace win { 16 namespace win {
18 17
19 namespace { 18 namespace {
20 19
21 // RegEnumValue() reports the number of characters from the name that were 20 // RegEnumValue() reports the number of characters from the name that were
22 // written to the buffer, not how many there are. This constant is the maximum 21 // written to the buffer, not how many there are. This constant is the maximum
23 // name size, such that a buffer with this size should read any name. 22 // name size, such that a buffer with this size should read any name.
24 const DWORD MAX_REGISTRY_NAME_SIZE = 16384; 23 const DWORD MAX_REGISTRY_NAME_SIZE = 16384;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey, 68 LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey,
70 DWORD* disposition, REGSAM access) { 69 DWORD* disposition, REGSAM access) {
71 DCHECK(rootkey && subkey && access && disposition); 70 DCHECK(rootkey && subkey && access && disposition);
72 HKEY subhkey = NULL; 71 HKEY subhkey = NULL;
73 LONG result = RegCreateKeyEx(rootkey, subkey, 0, NULL, 72 LONG result = RegCreateKeyEx(rootkey, subkey, 0, NULL,
74 REG_OPTION_NON_VOLATILE, access, NULL, &subhkey, 73 REG_OPTION_NON_VOLATILE, access, NULL, &subhkey,
75 disposition); 74 disposition);
76 if (result == ERROR_SUCCESS) { 75 if (result == ERROR_SUCCESS) {
77 Close(); 76 Close();
78 key_ = subhkey; 77 key_ = subhkey;
78 wow64access_ = access & KEY_WOW64_RES;
grt (UTC plus 2) 2014/05/16 15:44:43 looks like this is an undocumented constant in win
Will Harris 2014/05/16 22:55:44 Done.
79 } 79 }
80 80
81 return result; 81 return result;
82 } 82 }
83 83
84 LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) { 84 LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) {
85 DCHECK(name && access); 85 DCHECK(name && access);
86 HKEY subkey = NULL; 86 HKEY subkey = NULL;
87 LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE, 87 LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE,
88 access, NULL, &subkey, NULL); 88 access, NULL, &subkey, NULL);
89 if (result == ERROR_SUCCESS) { 89 if (result == ERROR_SUCCESS) {
90 Close(); 90 Close();
91 91 key_ = subkey;
92 key_ = subkey; 92 wow64access_ = access & KEY_WOW64_RES;
93 } 93 }
94 94
95 return result; 95 return result;
96 } 96 }
97 97
98 LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { 98 LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) {
99 DCHECK(rootkey && subkey && access); 99 DCHECK(rootkey && subkey && access);
100 HKEY subhkey = NULL; 100 HKEY subhkey = NULL;
101 101
102 LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey); 102 LONG result = RegOpenKeyEx(rootkey, subkey, 0, access, &subhkey);
103 if (result == ERROR_SUCCESS) { 103 if (result == ERROR_SUCCESS) {
104 Close(); 104 Close();
105 key_ = subhkey; 105 key_ = subhkey;
106 wow64access_ = access & KEY_WOW64_RES;
106 } 107 }
107 108
108 return result; 109 return result;
109 } 110 }
110 111
111 LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) { 112 LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) {
112 DCHECK(relative_key_name && access); 113 DCHECK(relative_key_name && access);
113 HKEY subkey = NULL; 114 HKEY subkey = NULL;
114 LONG result = RegOpenKeyEx(key_, relative_key_name, 0, access, &subkey); 115 LONG result = RegOpenKeyEx(key_, relative_key_name, 0, access, &subkey);
115 116
116 // We have to close the current opened key before replacing it with the new 117 // We have to close the current opened key before replacing it with the new
117 // one. 118 // one.
118 if (result == ERROR_SUCCESS) { 119 if (result == ERROR_SUCCESS) {
119 Close(); 120 Close();
120 key_ = subkey; 121 key_ = subkey;
122 wow64access_ = access & KEY_WOW64_RES;
121 } 123 }
122 return result; 124 return result;
123 } 125 }
124 126
125 void RegKey::Close() { 127 void RegKey::Close() {
126 StopWatching(); 128 StopWatching();
127 if (key_) { 129 if (key_) {
128 ::RegCloseKey(key_); 130 ::RegCloseKey(key_);
129 key_ = NULL; 131 key_ = NULL;
130 } 132 }
(...skipping 30 matching lines...) Expand all
161 LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL); 163 LONG r = ::RegEnumValue(key_, index, buf, &bufsize, NULL, NULL, NULL, NULL);
162 if (r == ERROR_SUCCESS) 164 if (r == ERROR_SUCCESS)
163 *name = buf; 165 *name = buf;
164 166
165 return r; 167 return r;
166 } 168 }
167 169
168 LONG RegKey::DeleteKey(const wchar_t* name) { 170 LONG RegKey::DeleteKey(const wchar_t* name) {
169 DCHECK(key_); 171 DCHECK(key_);
170 DCHECK(name); 172 DCHECK(name);
171 LONG result = SHDeleteKey(key_, name); 173 HKEY subkey;
172 return result; 174
175 // Verify the key exists before attempting delete to replicate previous
176 // behavior.
177 LONG result = RegOpenKeyEx(key_, name, 0, KEY_READ | wow64access_, &subkey);
grt (UTC plus 2) 2014/05/16 15:44:43 if this is just an existence test, i think READ_CO
Will Harris 2014/05/16 22:55:44 Done.
178 if (result == ERROR_SUCCESS) {
grt (UTC plus 2) 2014/05/16 15:44:43 suggestion: if (result != ERROR_SUCCESS) ret
Will Harris 2014/05/16 22:55:44 Done.
179 RegCloseKey(subkey);
180 std::wstring keyname(name);
grt (UTC plus 2) 2014/05/16 15:44:43 new code should use string16. would you mind switc
Will Harris 2014/05/16 22:55:44 will do in another CL
181
182 return RegKey::RegDelRecurse(key_, keyname, wow64access_);
grt (UTC plus 2) 2014/05/16 15:44:43 remove RegKey::
Will Harris 2014/05/16 22:55:44 Done.
183 } else {
184 return result;
185 }
173 } 186 }
174 187
175 LONG RegKey::DeleteValue(const wchar_t* value_name) { 188 LONG RegKey::DeleteValue(const wchar_t* value_name) {
176 DCHECK(key_); 189 DCHECK(key_);
177 LONG result = RegDeleteValue(key_, value_name); 190 LONG result = RegDeleteValue(key_, value_name);
178 return result; 191 return result;
179 } 192 }
180 193
181 LONG RegKey::ReadValueDW(const wchar_t* name, DWORD* out_value) const { 194 LONG RegKey::ReadValueDW(const wchar_t* name, DWORD* out_value) const {
182 DCHECK(out_value); 195 DCHECK(out_value);
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 LONG RegKey::StopWatching() { 348 LONG RegKey::StopWatching() {
336 LONG result = ERROR_INVALID_HANDLE; 349 LONG result = ERROR_INVALID_HANDLE;
337 if (watch_event_) { 350 if (watch_event_) {
338 CloseHandle(watch_event_); 351 CloseHandle(watch_event_);
339 watch_event_ = 0; 352 watch_event_ = 0;
340 result = ERROR_SUCCESS; 353 result = ERROR_SUCCESS;
341 } 354 }
342 return result; 355 return result;
343 } 356 }
344 357
358 // static
359 LONG RegKey::RegDeleteKeyExWrapper(HKEY hKey,
grt (UTC plus 2) 2014/05/16 15:44:43 use chromium naming style rather than hungarian
Will Harris 2014/05/16 22:55:44 Was intentionally using these since it's a wrapper
360 const wchar_t* lpSubKey,
361 REGSAM samDesired,
362 DWORD Reserved) {
363 typedef LSTATUS(WINAPI *RegDeleteKeyExPtr)(
364 HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved);
365
366 if (base::win::GetVersion() >= VERSION_VISTA) {
grt (UTC plus 2) 2014/05/16 15:44:43 some versions prior to vista have RegDeleteKeyEx,
Will Harris 2014/05/16 22:55:44 Done. We need to support these Windows XP 64-bit
367 RegDeleteKeyExPtr reg_delete_key_ex_func =
368 reinterpret_cast<RegDeleteKeyExPtr>(
369 GetProcAddress(GetModuleHandleA("advapi32.dll"),
370 "RegDeleteKeyExW"));
371 if (reg_delete_key_ex_func)
372 return reg_delete_key_ex_func(hKey, lpSubKey, samDesired, Reserved);
373 } else {
374 // Windows XP does not support RegDeleteKeyEx.
375 return RegDeleteKey(hKey, lpSubKey);
376 }
377
378 return ERROR_GEN_FAILURE;
379 }
380
381 // static
grt (UTC plus 2) 2014/05/16 15:44:43 this isn't a static method according to the header
Will Harris 2014/05/16 22:55:44 Good spot - the static keyword was accidently drop
382 LONG RegKey::RegDelRecurse(HKEY root_key, std::wstring name, REGSAM access) {
grt (UTC plus 2) 2014/05/16 15:44:43 pass name by const ref
Will Harris 2014/05/16 22:55:44 Done.
383 LONG result;
384 DWORD key_size;
385 wchar_t key_name[MAX_PATH];
386 HKEY hKey;
grt (UTC plus 2) 2014/05/16 15:44:43 no hungarians allowed. i suggest target_key or som
Will Harris 2014/05/16 22:55:44 Done.
387 FILETIME ft;
grt (UTC plus 2) 2014/05/16 15:44:43 is this needed? msdn says that the last param to E
Will Harris 2014/05/16 22:55:44 Done.
388
389 // First, see if the key can be deleted without having to recurse.
390 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0);
391
392 if (result == ERROR_SUCCESS)
393 return result;
394
395 result = RegOpenKeyEx(root_key, name.c_str(), 0, KEY_READ | access, &hKey);
grt (UTC plus 2) 2014/05/16 15:44:43 request the least required access: KEY_READ -> KEY
Will Harris 2014/05/16 22:55:45 Done.
396
397 if (result != ERROR_SUCCESS) {
grt (UTC plus 2) 2014/05/16 15:44:43 if (result == ERROR_FILE_NOT_FOUND) return ERR
Will Harris 2014/05/16 22:55:44 Done.
398 if (result == ERROR_FILE_NOT_FOUND) {
399 return ERROR_SUCCESS;
400 } else {
401 return result;
402 }
403 }
404
405 // Check for an ending slash and add one if it is missing.
406 if (name[name.length() - 1] != L'\\')
grt (UTC plus 2) 2014/05/16 15:44:43 what if |name| is empty? perhaps the top of the fu
Will Harris 2014/05/16 22:55:45 Done.
407 name += L"\\";
408
409 // Enumerate the keys
410 key_size = MAX_PATH;
411 result = RegEnumKeyEx(hKey, 0, key_name, &key_size, NULL, NULL, NULL, &ft);
grt (UTC plus 2) 2014/05/16 15:44:43 i think cpu already mentioned this, but do somethi
Will Harris 2014/05/16 22:55:45 Done.
412
413 if (result == ERROR_SUCCESS) {
grt (UTC plus 2) 2014/05/16 15:44:43 can you get rid of if { do { with: for (; result
Will Harris 2014/05/16 22:55:44 Done.
414 do {
415 std::wstring full_name(name);
grt (UTC plus 2) 2014/05/16 15:44:43 pull full_name's definition out of the loop
Will Harris 2014/05/16 22:55:44 Done.
416
417 full_name += key_name;
418
419 if (RegDelRecurse(root_key, full_name, access) != ERROR_SUCCESS)
420 break;
421
422 key_size = MAX_PATH;
423 result = RegEnumKeyEx(hKey, 0, key_name, &key_size, NULL,
424 NULL, NULL, &ft);
grt (UTC plus 2) 2014/05/16 15:44:43 shouldn't this be aligned with hKey above? did "gi
Will Harris 2014/05/16 22:55:44 Done.
425 } while (result == ERROR_SUCCESS);
426 }
427
428 RegCloseKey(hKey);
429
430 // Try again to delete the key.
431 result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0);
432
433 return result;
434 }
435
345 // RegistryValueIterator ------------------------------------------------------ 436 // RegistryValueIterator ------------------------------------------------------
346 437
347 RegistryValueIterator::RegistryValueIterator(HKEY root_key, 438 RegistryValueIterator::RegistryValueIterator(HKEY root_key,
348 const wchar_t* folder_key) 439 const wchar_t* folder_key)
349 : name_(MAX_PATH, L'\0'), 440 : name_(MAX_PATH, L'\0'),
350 value_(MAX_PATH, L'\0') { 441 value_(MAX_PATH, L'\0') {
351 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_); 442 LONG result = RegOpenKeyEx(root_key, folder_key, 0, KEY_READ, &key_);
352 if (result != ERROR_SUCCESS) { 443 if (result != ERROR_SUCCESS) {
353 key_ = NULL; 444 key_ = NULL;
354 } else { 445 } else {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 if (ERROR_SUCCESS == r) 578 if (ERROR_SUCCESS == r)
488 return true; 579 return true;
489 } 580 }
490 581
491 name_[0] = '\0'; 582 name_[0] = '\0';
492 return false; 583 return false;
493 } 584 }
494 585
495 } // namespace win 586 } // namespace win
496 } // namespace base 587 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698