 Chromium Code Reviews
 Chromium Code Reviews Issue 275103012:
  Add WOW64 support and DeleteEmptyKey to base::win::registry.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 275103012:
  Add WOW64 support and DeleteEmptyKey to base::win::registry.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| Index: base/win/registry.cc | 
| diff --git a/base/win/registry.cc b/base/win/registry.cc | 
| index 7330d08aa277e0ab5a67d84492176556bdd9dde0..17969275f42bfc079acee2afb3d1ca39d0233b18 100644 | 
| --- a/base/win/registry.cc | 
| +++ b/base/win/registry.cc | 
| @@ -10,8 +10,7 @@ | 
| #include "base/logging.h" | 
| #include "base/strings/string_util.h" | 
| #include "base/threading/thread_restrictions.h" | 
| - | 
| -#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
 | 
| +#include "base/win/windows_version.h" | 
| namespace base { | 
| namespace win { | 
| @@ -76,6 +75,7 @@ LONG RegKey::CreateWithDisposition(HKEY rootkey, const wchar_t* subkey, | 
| if (result == ERROR_SUCCESS) { | 
| Close(); | 
| key_ = subhkey; | 
| + 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.
 | 
| } | 
| return result; | 
| @@ -86,10 +86,10 @@ LONG RegKey::CreateKey(const wchar_t* name, REGSAM access) { | 
| HKEY subkey = NULL; | 
| LONG result = RegCreateKeyEx(key_, name, 0, NULL, REG_OPTION_NON_VOLATILE, | 
| access, NULL, &subkey, NULL); | 
| - if (result == ERROR_SUCCESS) { | 
| - Close(); | 
| - | 
| - key_ = subkey; | 
| + if (result == ERROR_SUCCESS) { | 
| + Close(); | 
| + key_ = subkey; | 
| + wow64access_ = access & KEY_WOW64_RES; | 
| } | 
| return result; | 
| @@ -103,6 +103,7 @@ LONG RegKey::Open(HKEY rootkey, const wchar_t* subkey, REGSAM access) { | 
| if (result == ERROR_SUCCESS) { | 
| Close(); | 
| key_ = subhkey; | 
| + wow64access_ = access & KEY_WOW64_RES; | 
| } | 
| return result; | 
| @@ -118,6 +119,7 @@ LONG RegKey::OpenKey(const wchar_t* relative_key_name, REGSAM access) { | 
| if (result == ERROR_SUCCESS) { | 
| Close(); | 
| key_ = subkey; | 
| + wow64access_ = access & KEY_WOW64_RES; | 
| } | 
| return result; | 
| } | 
| @@ -168,8 +170,19 @@ LONG RegKey::GetValueNameAt(int index, std::wstring* name) const { | 
| LONG RegKey::DeleteKey(const wchar_t* name) { | 
| DCHECK(key_); | 
| DCHECK(name); | 
| - LONG result = SHDeleteKey(key_, name); | 
| - return result; | 
| + HKEY subkey; | 
| + | 
| + // Verify the key exists before attempting delete to replicate previous | 
| + // behavior. | 
| + 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.
 | 
| + 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.
 | 
| + RegCloseKey(subkey); | 
| + 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
 | 
| + | 
| + 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.
 | 
| + } else { | 
| + return result; | 
| + } | 
| } | 
| LONG RegKey::DeleteValue(const wchar_t* value_name) { | 
| @@ -342,6 +355,84 @@ LONG RegKey::StopWatching() { | 
| return result; | 
| } | 
| +// static | 
| +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
 | 
| + const wchar_t* lpSubKey, | 
| + REGSAM samDesired, | 
| + DWORD Reserved) { | 
| + typedef LSTATUS(WINAPI *RegDeleteKeyExPtr)( | 
| + HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); | 
| + | 
| + 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
 | 
| + RegDeleteKeyExPtr reg_delete_key_ex_func = | 
| + reinterpret_cast<RegDeleteKeyExPtr>( | 
| + GetProcAddress(GetModuleHandleA("advapi32.dll"), | 
| + "RegDeleteKeyExW")); | 
| + if (reg_delete_key_ex_func) | 
| + return reg_delete_key_ex_func(hKey, lpSubKey, samDesired, Reserved); | 
| + } else { | 
| + // Windows XP does not support RegDeleteKeyEx. | 
| + return RegDeleteKey(hKey, lpSubKey); | 
| + } | 
| + | 
| + return ERROR_GEN_FAILURE; | 
| +} | 
| + | 
| +// 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
 | 
| +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.
 | 
| + LONG result; | 
| + DWORD key_size; | 
| + wchar_t key_name[MAX_PATH]; | 
| + 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.
 | 
| + 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.
 | 
| + | 
| + // First, see if the key can be deleted without having to recurse. | 
| + result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0); | 
| + | 
| + if (result == ERROR_SUCCESS) | 
| + return result; | 
| + | 
| + 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.
 | 
| + | 
| + 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.
 | 
| + if (result == ERROR_FILE_NOT_FOUND) { | 
| + return ERROR_SUCCESS; | 
| + } else { | 
| + return result; | 
| + } | 
| + } | 
| + | 
| + // Check for an ending slash and add one if it is missing. | 
| + 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.
 | 
| + name += L"\\"; | 
| + | 
| + // Enumerate the keys | 
| + key_size = MAX_PATH; | 
| + 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.
 | 
| + | 
| + 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.
 | 
| + do { | 
| + 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.
 | 
| + | 
| + full_name += key_name; | 
| + | 
| + if (RegDelRecurse(root_key, full_name, access) != ERROR_SUCCESS) | 
| + break; | 
| + | 
| + key_size = MAX_PATH; | 
| + result = RegEnumKeyEx(hKey, 0, key_name, &key_size, NULL, | 
| + 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.
 | 
| + } while (result == ERROR_SUCCESS); | 
| + } | 
| + | 
| + RegCloseKey(hKey); | 
| + | 
| + // Try again to delete the key. | 
| + result = RegDeleteKeyExWrapper(root_key, name.c_str(), access, 0); | 
| + | 
| + return result; | 
| +} | 
| + | 
| // RegistryValueIterator ------------------------------------------------------ | 
| RegistryValueIterator::RegistryValueIterator(HKEY root_key, |