 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| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <cstring> | 7 #include <cstring> | 
| 8 #include <vector> | 8 #include <vector> | 
| 9 | 9 | 
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" | 
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" | 
| 12 #include "base/win/windows_version.h" | |
| 
grt (UTC plus 2)
2014/05/16 15:44:43
unused
 
Will Harris
2014/05/16 22:55:45
used for OSInfo below
 | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" | 
| 13 | 14 | 
| 14 namespace base { | 15 namespace base { | 
| 15 namespace win { | 16 namespace win { | 
| 16 | 17 | 
| 17 namespace { | 18 namespace { | 
| 18 | 19 | 
| 19 const wchar_t kRootKey[] = L"Base_Registry_Unittest"; | 20 const wchar_t kRootKey[] = L"Base_Registry_Unittest"; | 
| 20 | 21 | 
| 21 class RegistryTest : public testing::Test { | 22 class RegistryTest : public testing::Test { | 
| 22 public: | 23 public: | 
| 23 RegistryTest() {} | 24 RegistryTest() {} | 
| 24 | 25 | 
| 25 protected: | 26 protected: | 
| 26 virtual void SetUp() OVERRIDE { | 27 virtual void SetUp() OVERRIDE { | 
| 27 // Create a temporary key. | 28 // Create a temporary key. | 
| 28 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); | 29 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); | 
| 29 key.DeleteKey(kRootKey); | 30 key.DeleteKey(kRootKey); | 
| 30 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ)); | 31 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ)); | 
| 31 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ)); | 32 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ)); | 
| 32 } | 33 } | 
| 33 | 34 | 
| 34 virtual void TearDown() OVERRIDE { | 35 virtual void TearDown() OVERRIDE { | 
| 35 // Clean up the temporary key. | 36 // Clean up the temporary key. | 
| 36 RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE); | 37 RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE); | 
| 37 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | 38 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | 
| 39 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ)); | |
| 40 | |
| 41 // Delete all variations of the Software key we created. | |
| 42 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 43 KEY_SET_VALUE | KEY_WOW64_32KEY)); | |
| 
grt (UTC plus 2)
2014/05/16 15:44:43
indentation. please try "git cl format". it wraps
 
Will Harris
2014/05/16 22:55:45
Done.
 | |
| 44 key.DeleteKey(kRootKey); | |
| 45 | |
| 46 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 47 KEY_SET_VALUE | KEY_WOW64_64KEY)); | |
| 48 key.DeleteKey(kRootKey); | |
| 38 } | 49 } | 
| 39 | 50 | 
| 40 private: | 51 private: | 
| 41 DISALLOW_COPY_AND_ASSIGN(RegistryTest); | 52 DISALLOW_COPY_AND_ASSIGN(RegistryTest); | 
| 42 }; | 53 }; | 
| 43 | 54 | 
| 44 TEST_F(RegistryTest, ValueTest) { | 55 TEST_F(RegistryTest, ValueTest) { | 
| 45 RegKey key; | 56 RegKey key; | 
| 46 | 57 | 
| 47 std::wstring foo_key(kRootKey); | 58 std::wstring foo_key(kRootKey); | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 ASSERT_EQ(arraysize(kData), iterator.ValueSize()); | 162 ASSERT_EQ(arraysize(kData), iterator.ValueSize()); | 
| 152 // Value() is NUL terminated. | 163 // Value() is NUL terminated. | 
| 153 int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t); | 164 int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t); | 
| 154 EXPECT_NE(L'\0', iterator.Value()[end-1]); | 165 EXPECT_NE(L'\0', iterator.Value()[end-1]); | 
| 155 EXPECT_EQ(L'\0', iterator.Value()[end]); | 166 EXPECT_EQ(L'\0', iterator.Value()[end]); | 
| 156 EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), arraysize(kData))); | 167 EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), arraysize(kData))); | 
| 157 ++iterator; | 168 ++iterator; | 
| 158 EXPECT_FALSE(iterator.Valid()); | 169 EXPECT_FALSE(iterator.Valid()); | 
| 159 } | 170 } | 
| 160 | 171 | 
| 172 TEST_F(RegistryTest, RecursiveDelete) { | |
| 
grt (UTC plus 2)
2014/05/16 15:44:43
DeleteKey was untested before?!??!?
 
Will Harris
2014/05/16 22:55:45
Yes - scary.  I tested the old SHDeleteKey code wi
 | |
| 173 RegKey key; | |
| 174 // Create kRootKey->Foo | |
| 175 // \->Bar | |
| 176 // \->Foo | |
| 177 // \->Moo | |
| 178 // \->Foo | |
| 179 // and delete kRootKey->Foo | |
| 180 std::wstring foo_key(kRootKey); | |
| 181 foo_key += L"\\Foo"; | |
| 182 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(), | |
| 183 KEY_WRITE)); | |
| 184 foo_key += L"\\Bar"; | |
| 185 | |
| 186 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(), | |
| 187 KEY_READ)); | |
| 188 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE)); | |
| 189 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE)); | |
| 190 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE)); | |
| 191 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(), | |
| 192 KEY_WRITE)); | |
| 193 foo_key += L"\\Foo"; | |
| 194 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE)); | |
| 195 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(), | |
| 196 KEY_READ)); | |
| 197 | |
| 198 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE)); | |
| 199 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar")); | |
| 200 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Foo")); | |
| 201 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Foo")); | |
| 202 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(), | |
| 203 KEY_READ)); | |
| 204 } | |
| 205 | |
| 206 // This test requires running as an Administrator as it tests redirected | |
| 207 // registry writes to HKLM\Software | |
| 
grt (UTC plus 2)
2014/05/16 15:44:43
can the Administrator requirement be removed by ma
 
Will Harris
2014/05/16 22:55:45
HKLM\Software is the only key that is universally
 | |
| 208 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx | |
| 209 TEST_F(RegistryTest, Wow64) { | |
| 210 RegKey key; | |
| 211 std::wstring foo_key(L"Software\\"); | |
| 212 foo_key += kRootKey; | |
| 213 foo_key += L"\\Foo"; | |
| 214 std::wstring foo_wow64_key(L"Software\\Wow6432Node\\"); | |
| 215 foo_wow64_key += kRootKey; | |
| 216 foo_wow64_key += L"\\Foo"; | |
| 217 | |
| 218 #if defined(_WIN64) | |
| 219 // Test 32-bit key access from 64-bit. | |
| 
grt (UTC plus 2)
2014/05/16 15:44:43
it looks like a lot of the _WIN64 part and the non
 
Will Harris
2014/05/16 22:55:45
I went ahead and split this test up a bit.
 | |
| 220 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 221 KEY_WRITE | KEY_WOW64_32KEY)); | |
| 222 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 223 KEY_READ)); | |
| 224 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 225 KEY_READ | KEY_WOW64_64KEY)); | |
| 226 | |
| 227 // Open the 64-bit view of the parent and try to delete the test key. | |
| 228 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 229 KEY_SET_VALUE)); | |
| 230 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 231 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 232 KEY_SET_VALUE | KEY_WOW64_64KEY)); | |
| 233 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 234 | |
| 235 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 236 KEY_SET_VALUE | KEY_WOW64_32KEY)); | |
| 237 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 238 | |
| 239 // Test 64-bit key access from 64-bit. | |
| 240 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 241 KEY_WRITE | KEY_WOW64_64KEY)); | |
| 242 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 243 KEY_READ)); | |
| 244 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 245 KEY_READ | KEY_WOW64_32KEY)); | |
| 246 | |
| 247 // Open the 32-bit view of the parent and try to delete the test key. | |
| 248 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 249 KEY_SET_VALUE | KEY_WOW64_32KEY)); | |
| 250 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 251 | |
| 252 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 253 KEY_SET_VALUE | KEY_WOW64_64KEY)); | |
| 254 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 255 #else | |
| 256 OSInfo* os_info = OSInfo::GetInstance(); | |
| 257 | |
| 258 if (os_info->wow64_status() == OSInfo::WOW64_ENABLED) { | |
| 259 // Test 64-bit key access from 32-bit. | |
| 260 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 261 KEY_WRITE | KEY_WOW64_64KEY)); | |
| 262 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 263 KEY_READ)); | |
| 264 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 265 KEY_READ | KEY_WOW64_32KEY)); | |
| 266 | |
| 267 // Open the 32-bit view of the parent and try to delete the test key. | |
| 268 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 269 KEY_SET_VALUE)); | |
| 270 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 271 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 272 KEY_SET_VALUE | KEY_WOW64_32KEY)); | |
| 273 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 274 | |
| 275 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 276 KEY_SET_VALUE | KEY_WOW64_64KEY)); | |
| 277 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 278 | |
| 279 // Test 32-bit key access from 32-bit. | |
| 280 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 281 KEY_WRITE | KEY_WOW64_32KEY)); | |
| 282 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 283 KEY_READ)); | |
| 284 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 285 KEY_READ | KEY_WOW64_64KEY)); | |
| 286 | |
| 287 // Test accessing the 32-bit values via Wow6432Node. | |
| 288 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, | |
| 289 foo_wow64_key.c_str(), KEY_READ)); | |
| 290 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, | |
| 291 foo_wow64_key.c_str(), KEY_READ | KEY_WOW64_64KEY)); | |
| 292 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, | |
| 293 foo_wow64_key.c_str(), KEY_READ | KEY_WOW64_32KEY)); | |
| 294 | |
| 295 // Open the 64-bit view of the parent and try to delete the test key. | |
| 296 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 297 KEY_SET_VALUE | KEY_WOW64_64KEY)); | |
| 298 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 299 | |
| 300 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 301 KEY_SET_VALUE | KEY_WOW64_32KEY)); | |
| 302 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 303 } else { | |
| 304 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_LOCAL_MACHINE, foo_key.c_str(), | |
| 305 KEY_READ)); | |
| 306 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, foo_wow64_key.c_str(), | |
| 307 KEY_READ)); | |
| 308 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software", | |
| 309 KEY_SET_VALUE)); | |
| 310 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey)); | |
| 311 } | |
| 312 #endif // _WIN64 | |
| 313 } | |
| 314 | |
| 315 | |
| 161 } // namespace | 316 } // namespace | 
| 162 | 317 | 
| 163 } // namespace win | 318 } // namespace win | 
| 164 } // namespace base | 319 } // namespace base | 
| OLD | NEW |