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
3 // found in the LICENSE file.
5 #include "base/win/registry.h"
10 #include "base/compiler_specific.h"
11 #include "base/stl_util.h"
12 #include "base/win/windows_version.h"
13 #include "testing/gtest/include/gtest/gtest.h"
20 class RegistryTest
: public testing::Test
{
23 static const REGSAM kNativeViewMask
= KEY_WOW64_64KEY
;
24 static const REGSAM kRedirectedViewMask
= KEY_WOW64_32KEY
;
26 static const REGSAM kNativeViewMask
= KEY_WOW64_32KEY
;
27 static const REGSAM kRedirectedViewMask
= KEY_WOW64_64KEY
;
31 virtual void SetUp() OVERRIDE
{
32 // Create a temporary key.
33 RegKey
key(HKEY_CURRENT_USER
, L
"", KEY_ALL_ACCESS
);
34 key
.DeleteKey(kRootKey
);
35 ASSERT_NE(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_READ
));
36 ASSERT_EQ(ERROR_SUCCESS
, key
.Create(HKEY_CURRENT_USER
, kRootKey
, KEY_READ
));
37 foo_software_key_
= L
"Software\\";
38 foo_software_key_
+= kRootKey
;
39 foo_software_key_
+= L
"\\Foo";
42 virtual void TearDown() OVERRIDE
{
43 // Clean up the temporary key.
44 RegKey
key(HKEY_CURRENT_USER
, L
"", KEY_SET_VALUE
);
45 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
46 ASSERT_NE(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_READ
));
49 static bool IsRedirectorPresent() {
53 return OSInfo::GetInstance()->wow64_status() == OSInfo::WOW64_ENABLED
;
57 const wchar_t* const kRootKey
= L
"Base_Registry_Unittest";
58 std::wstring foo_software_key_
;
61 DISALLOW_COPY_AND_ASSIGN(RegistryTest
);
65 const REGSAM
RegistryTest::kNativeViewMask
;
66 const REGSAM
RegistryTest::kRedirectedViewMask
;
68 TEST_F(RegistryTest
, ValueTest
) {
71 std::wstring
foo_key(kRootKey
);
73 ASSERT_EQ(ERROR_SUCCESS
, key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(),
77 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(),
78 KEY_READ
| KEY_SET_VALUE
));
79 ASSERT_TRUE(key
.Valid());
81 const wchar_t kStringValueName
[] = L
"StringValue";
82 const wchar_t kDWORDValueName
[] = L
"DWORDValue";
83 const wchar_t kInt64ValueName
[] = L
"Int64Value";
84 const wchar_t kStringData
[] = L
"string data";
85 const DWORD kDWORDData
= 0xdeadbabe;
86 const int64 kInt64Data
= 0xdeadbabedeadbabeLL
;
88 // Test value creation
89 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(kStringValueName
, kStringData
));
90 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(kDWORDValueName
, kDWORDData
));
91 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(kInt64ValueName
, &kInt64Data
,
92 sizeof(kInt64Data
), REG_QWORD
));
93 EXPECT_EQ(3U, key
.GetValueCount());
94 EXPECT_TRUE(key
.HasValue(kStringValueName
));
95 EXPECT_TRUE(key
.HasValue(kDWORDValueName
));
96 EXPECT_TRUE(key
.HasValue(kInt64ValueName
));
99 std::wstring string_value
;
100 DWORD dword_value
= 0;
101 int64 int64_value
= 0;
102 ASSERT_EQ(ERROR_SUCCESS
, key
.ReadValue(kStringValueName
, &string_value
));
103 ASSERT_EQ(ERROR_SUCCESS
, key
.ReadValueDW(kDWORDValueName
, &dword_value
));
104 ASSERT_EQ(ERROR_SUCCESS
, key
.ReadInt64(kInt64ValueName
, &int64_value
));
105 EXPECT_STREQ(kStringData
, string_value
.c_str());
106 EXPECT_EQ(kDWORDData
, dword_value
);
107 EXPECT_EQ(kInt64Data
, int64_value
);
109 // Make sure out args are not touched if ReadValue fails
110 const wchar_t* kNonExistent
= L
"NonExistent";
111 ASSERT_NE(ERROR_SUCCESS
, key
.ReadValue(kNonExistent
, &string_value
));
112 ASSERT_NE(ERROR_SUCCESS
, key
.ReadValueDW(kNonExistent
, &dword_value
));
113 ASSERT_NE(ERROR_SUCCESS
, key
.ReadInt64(kNonExistent
, &int64_value
));
114 EXPECT_STREQ(kStringData
, string_value
.c_str());
115 EXPECT_EQ(kDWORDData
, dword_value
);
116 EXPECT_EQ(kInt64Data
, int64_value
);
119 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteValue(kStringValueName
));
120 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteValue(kDWORDValueName
));
121 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteValue(kInt64ValueName
));
122 EXPECT_EQ(0U, key
.GetValueCount());
123 EXPECT_FALSE(key
.HasValue(kStringValueName
));
124 EXPECT_FALSE(key
.HasValue(kDWORDValueName
));
125 EXPECT_FALSE(key
.HasValue(kInt64ValueName
));
129 TEST_F(RegistryTest
, BigValueIteratorTest
) {
131 std::wstring
foo_key(kRootKey
);
133 ASSERT_EQ(ERROR_SUCCESS
, key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(),
135 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(),
136 KEY_READ
| KEY_SET_VALUE
));
137 ASSERT_TRUE(key
.Valid());
139 // Create a test value that is larger than MAX_PATH.
140 std::wstring
data(MAX_PATH
* 2, L
'a');
142 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(data
.c_str(), data
.c_str()));
144 RegistryValueIterator
iterator(HKEY_CURRENT_USER
, foo_key
.c_str());
145 ASSERT_TRUE(iterator
.Valid());
146 EXPECT_STREQ(data
.c_str(), iterator
.Name());
147 EXPECT_STREQ(data
.c_str(), iterator
.Value());
148 // ValueSize() is in bytes, including NUL.
149 EXPECT_EQ((MAX_PATH
* 2 + 1) * sizeof(wchar_t), iterator
.ValueSize());
151 EXPECT_FALSE(iterator
.Valid());
154 TEST_F(RegistryTest
, TruncatedCharTest
) {
156 std::wstring
foo_key(kRootKey
);
158 ASSERT_EQ(ERROR_SUCCESS
, key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(),
160 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(),
161 KEY_READ
| KEY_SET_VALUE
));
162 ASSERT_TRUE(key
.Valid());
164 const wchar_t kName
[] = L
"name";
165 // kData size is not a multiple of sizeof(wchar_t).
166 const uint8 kData
[] = { 1, 2, 3, 4, 5 };
167 EXPECT_EQ(5, arraysize(kData
));
168 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(kName
, kData
,
169 arraysize(kData
), REG_BINARY
));
171 RegistryValueIterator
iterator(HKEY_CURRENT_USER
, foo_key
.c_str());
172 ASSERT_TRUE(iterator
.Valid());
173 EXPECT_STREQ(kName
, iterator
.Name());
174 // ValueSize() is in bytes.
175 ASSERT_EQ(arraysize(kData
), iterator
.ValueSize());
176 // Value() is NUL terminated.
177 int end
= (iterator
.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
178 EXPECT_NE(L
'\0', iterator
.Value()[end
-1]);
179 EXPECT_EQ(L
'\0', iterator
.Value()[end
]);
180 EXPECT_EQ(0, std::memcmp(kData
, iterator
.Value(), arraysize(kData
)));
182 EXPECT_FALSE(iterator
.Valid());
185 TEST_F(RegistryTest
, RecursiveDelete
) {
187 // Create kRootKey->Foo
188 // \->Bar (TestValue)
189 // \->Foo (TestValue)
194 // and delete kRootKey->Foo
195 std::wstring
foo_key(kRootKey
);
197 ASSERT_EQ(ERROR_SUCCESS
,
198 key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
199 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Bar", KEY_WRITE
));
200 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(L
"TestValue", L
"TestData"));
201 ASSERT_EQ(ERROR_SUCCESS
,
202 key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
203 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Moo", KEY_WRITE
));
204 ASSERT_EQ(ERROR_SUCCESS
,
205 key
.Create(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
206 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Foo", KEY_WRITE
));
208 ASSERT_EQ(ERROR_SUCCESS
,
209 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
211 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Foo", KEY_WRITE
));
212 ASSERT_EQ(ERROR_SUCCESS
, key
.WriteValue(L
"TestValue", L
"TestData"));
213 ASSERT_EQ(ERROR_SUCCESS
,
214 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_READ
));
216 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_WRITE
));
217 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteKey(L
"Bar"));
218 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteEmptyKey(L
"Foo"));
219 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteEmptyKey(L
"Foo\\Bar\\Foo"));
220 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteEmptyKey(L
"Foo\\Bar"));
221 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteEmptyKey(L
"Foo\\Foo"));
223 ASSERT_EQ(ERROR_SUCCESS
,
224 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
225 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Bar", KEY_WRITE
));
226 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"Foo", KEY_WRITE
));
227 ASSERT_EQ(ERROR_SUCCESS
,
228 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_WRITE
));
229 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(L
""));
230 ASSERT_NE(ERROR_SUCCESS
,
231 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_READ
));
233 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_WRITE
));
234 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(L
"Foo"));
235 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteKey(L
"Foo"));
236 ASSERT_NE(ERROR_SUCCESS
,
237 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_READ
));
240 // This test requires running as an Administrator as it tests redirected
241 // registry writes to HKLM\Software
242 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx
243 // TODO(wfh): flaky test on Vista. See http://crbug.com/377917
244 TEST_F(RegistryTest
, DISABLED_Wow64RedirectedFromNative
) {
245 if (!IsRedirectorPresent())
250 // Test redirected key access from non-redirected.
251 ASSERT_EQ(ERROR_SUCCESS
,
252 key
.Create(HKEY_LOCAL_MACHINE
,
253 foo_software_key_
.c_str(),
254 KEY_WRITE
| kRedirectedViewMask
));
255 ASSERT_NE(ERROR_SUCCESS
,
256 key
.Open(HKEY_LOCAL_MACHINE
, foo_software_key_
.c_str(), KEY_READ
));
257 ASSERT_NE(ERROR_SUCCESS
,
258 key
.Open(HKEY_LOCAL_MACHINE
,
259 foo_software_key_
.c_str(),
260 KEY_READ
| kNativeViewMask
));
262 // Open the non-redirected view of the parent and try to delete the test key.
263 ASSERT_EQ(ERROR_SUCCESS
,
264 key
.Open(HKEY_LOCAL_MACHINE
, L
"Software", KEY_SET_VALUE
));
265 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
266 ASSERT_EQ(ERROR_SUCCESS
,
267 key
.Open(HKEY_LOCAL_MACHINE
,
269 KEY_SET_VALUE
| kNativeViewMask
));
270 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
272 // Open the redirected view and delete the key created above.
273 ASSERT_EQ(ERROR_SUCCESS
,
274 key
.Open(HKEY_LOCAL_MACHINE
,
276 KEY_SET_VALUE
| kRedirectedViewMask
));
277 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
280 // Test for the issue found in http://crbug.com/384587 where OpenKey would call
281 // Close() and reset wow64_access_ flag to 0 and cause a NOTREACHED to hit on a
282 // subsequent OpenKey call.
283 TEST_F(RegistryTest
, SameWowFlags
) {
286 ASSERT_EQ(ERROR_SUCCESS
,
287 key
.Open(HKEY_LOCAL_MACHINE
,
289 KEY_READ
| KEY_WOW64_64KEY
));
290 ASSERT_EQ(ERROR_SUCCESS
,
291 key
.OpenKey(L
"Microsoft",
292 KEY_READ
| KEY_WOW64_64KEY
));
293 ASSERT_EQ(ERROR_SUCCESS
,
294 key
.OpenKey(L
"Windows",
295 KEY_READ
| KEY_WOW64_64KEY
));
298 // TODO(wfh): flaky test on Vista. See http://crbug.com/377917
299 TEST_F(RegistryTest
, DISABLED_Wow64NativeFromRedirected
) {
300 if (!IsRedirectorPresent())
304 // Test non-redirected key access from redirected.
305 ASSERT_EQ(ERROR_SUCCESS
,
306 key
.Create(HKEY_LOCAL_MACHINE
,
307 foo_software_key_
.c_str(),
308 KEY_WRITE
| kNativeViewMask
));
309 ASSERT_EQ(ERROR_SUCCESS
,
310 key
.Open(HKEY_LOCAL_MACHINE
, foo_software_key_
.c_str(), KEY_READ
));
311 ASSERT_NE(ERROR_SUCCESS
,
312 key
.Open(HKEY_LOCAL_MACHINE
,
313 foo_software_key_
.c_str(),
314 KEY_READ
| kRedirectedViewMask
));
316 // Open the redirected view of the parent and try to delete the test key
317 // from the non-redirected view.
318 ASSERT_EQ(ERROR_SUCCESS
,
319 key
.Open(HKEY_LOCAL_MACHINE
,
321 KEY_SET_VALUE
| kRedirectedViewMask
));
322 ASSERT_NE(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
324 ASSERT_EQ(ERROR_SUCCESS
,
325 key
.Open(HKEY_LOCAL_MACHINE
,
327 KEY_SET_VALUE
| kNativeViewMask
));
328 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(kRootKey
));
331 TEST_F(RegistryTest
, OpenSubKey
) {
333 ASSERT_EQ(ERROR_SUCCESS
,
334 key
.Open(HKEY_CURRENT_USER
,
336 KEY_READ
| KEY_CREATE_SUB_KEY
));
338 ASSERT_NE(ERROR_SUCCESS
, key
.OpenKey(L
"foo", KEY_READ
));
339 ASSERT_EQ(ERROR_SUCCESS
, key
.CreateKey(L
"foo", KEY_READ
));
340 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_READ
));
341 ASSERT_EQ(ERROR_SUCCESS
, key
.OpenKey(L
"foo", KEY_READ
));
343 std::wstring
foo_key(kRootKey
);
345 ASSERT_EQ(ERROR_SUCCESS
,
346 key
.Open(HKEY_CURRENT_USER
, foo_key
.c_str(), KEY_READ
));
348 ASSERT_EQ(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kRootKey
, KEY_WRITE
));
349 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(L
"foo"));