1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/win/registry.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <windows.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <shlobj.h>
10*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include <cstring>
13*6777b538SAndroid Build Coastguard Worker #include <iterator>
14*6777b538SAndroid Build Coastguard Worker #include <string_view>
15*6777b538SAndroid Build Coastguard Worker #include <utility>
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/memory/scoped_refptr.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/strings/strcat.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/test/bind.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/test/gmock_expected_support.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/test/mock_callback.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
28*6777b538SAndroid Build Coastguard Worker #include "base/test/test_mock_time_task_runner.h"
29*6777b538SAndroid Build Coastguard Worker #include "base/test/test_reg_util_win.h"
30*6777b538SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
31*6777b538SAndroid Build Coastguard Worker #include "base/win/win_util.h"
32*6777b538SAndroid Build Coastguard Worker #include "base/win/windows_version.h"
33*6777b538SAndroid Build Coastguard Worker #include "testing/gmock/include/gmock/gmock.h"
34*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker namespace base::win {
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker namespace {
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker constexpr wchar_t kRootKey[] = L"Base_Registry_Unittest";
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker // A test harness for registry tests that operate in HKCU. Each test is given
43*6777b538SAndroid Build Coastguard Worker // a valid key distinct from that used by other tests.
44*6777b538SAndroid Build Coastguard Worker class RegistryTest : public testing::Test {
45*6777b538SAndroid Build Coastguard Worker protected:
RegistryTest()46*6777b538SAndroid Build Coastguard Worker RegistryTest() : root_key_(std::wstring(L"Software\\") + kRootKey) {}
47*6777b538SAndroid Build Coastguard Worker
SetUp()48*6777b538SAndroid Build Coastguard Worker void SetUp() override {
49*6777b538SAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(registry_override_.OverrideRegistry(
50*6777b538SAndroid Build Coastguard Worker HKEY_CURRENT_USER, &override_path_));
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker // Create the test's root key.
53*6777b538SAndroid Build Coastguard Worker RegKey key(HKEY_CURRENT_USER, L"", KEY_CREATE_SUB_KEY);
54*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
55*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ));
56*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
57*6777b538SAndroid Build Coastguard Worker key.Create(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ));
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker // Returns the path to a key under HKCU that is made available for exclusive
61*6777b538SAndroid Build Coastguard Worker // use by a test.
root_key() const62*6777b538SAndroid Build Coastguard Worker const std::wstring& root_key() const { return root_key_; }
63*6777b538SAndroid Build Coastguard Worker
override_path() const64*6777b538SAndroid Build Coastguard Worker const std::wstring& override_path() const { return override_path_; }
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker private:
67*6777b538SAndroid Build Coastguard Worker registry_util::RegistryOverrideManager registry_override_;
68*6777b538SAndroid Build Coastguard Worker const std::wstring root_key_;
69*6777b538SAndroid Build Coastguard Worker std::wstring override_path_;
70*6777b538SAndroid Build Coastguard Worker };
71*6777b538SAndroid Build Coastguard Worker
72*6777b538SAndroid Build Coastguard Worker } // namespace
73*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,ValueTest)74*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, ValueTest) {
75*6777b538SAndroid Build Coastguard Worker RegKey key;
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, root_key().c_str(),
78*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_SET_VALUE));
79*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.Valid());
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker const wchar_t kStringValueName[] = L"StringValue";
82*6777b538SAndroid Build Coastguard Worker const wchar_t kDWORDValueName[] = L"DWORDValue";
83*6777b538SAndroid Build Coastguard Worker const wchar_t kInt64ValueName[] = L"Int64Value";
84*6777b538SAndroid Build Coastguard Worker const wchar_t kStringData[] = L"string data";
85*6777b538SAndroid Build Coastguard Worker const DWORD kDWORDData = 0xdeadbabe;
86*6777b538SAndroid Build Coastguard Worker const int64_t kInt64Data = 0xdeadbabedeadbabeLL;
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker // Test value creation
89*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kStringValueName, kStringData));
90*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kDWORDValueName, kDWORDData));
91*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kInt64ValueName, &kInt64Data,
92*6777b538SAndroid Build Coastguard Worker sizeof(kInt64Data), REG_QWORD));
93*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(key.GetValueCount(), base::test::ValueIs(3U));
94*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(key.HasValue(kStringValueName));
95*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(key.HasValue(kDWORDValueName));
96*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(key.HasValue(kInt64ValueName));
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker // Test Read
99*6777b538SAndroid Build Coastguard Worker std::wstring string_value;
100*6777b538SAndroid Build Coastguard Worker DWORD dword_value = 0;
101*6777b538SAndroid Build Coastguard Worker int64_t int64_value = 0;
102*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
103*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(kDWORDValueName, &dword_value));
104*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.ReadInt64(kInt64ValueName, &int64_value));
105*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kStringData, string_value);
106*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kDWORDData, dword_value);
107*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kInt64Data, int64_value);
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker // Make sure out args are not touched if ReadValue fails
110*6777b538SAndroid Build Coastguard Worker const wchar_t* kNonExistent = L"NonExistent";
111*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
112*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
113*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
114*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kStringData, string_value);
115*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kDWORDData, dword_value);
116*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(kInt64Data, int64_value);
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker // Test delete
119*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kStringValueName));
120*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kDWORDValueName));
121*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kInt64ValueName));
122*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(key.GetValueCount(), base::test::ValueIs(0U));
123*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(key.HasValue(kStringValueName));
124*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(key.HasValue(kDWORDValueName));
125*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(key.HasValue(kInt64ValueName));
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,BigValueIteratorTest)128*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, BigValueIteratorTest) {
129*6777b538SAndroid Build Coastguard Worker RegKey key;
130*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, root_key().c_str(),
131*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_SET_VALUE));
132*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.Valid());
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker // Create a test value that is larger than MAX_PATH.
135*6777b538SAndroid Build Coastguard Worker std::wstring data(MAX_PATH * 2, 'a');
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(data.c_str(), data.c_str()));
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker RegistryValueIterator iterator(HKEY_CURRENT_USER, root_key().c_str());
140*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(iterator.Valid());
141*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(data, iterator.Name());
142*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(data, iterator.Value());
143*6777b538SAndroid Build Coastguard Worker // ValueSize() is in bytes, including NUL.
144*6777b538SAndroid Build Coastguard Worker EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(wchar_t), iterator.ValueSize());
145*6777b538SAndroid Build Coastguard Worker ++iterator;
146*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(iterator.Valid());
147*6777b538SAndroid Build Coastguard Worker }
148*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,TruncatedCharTest)149*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, TruncatedCharTest) {
150*6777b538SAndroid Build Coastguard Worker RegKey key;
151*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, root_key().c_str(),
152*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_SET_VALUE));
153*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.Valid());
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker const wchar_t kName[] = L"name";
156*6777b538SAndroid Build Coastguard Worker // kData size is not a multiple of sizeof(wchar_t).
157*6777b538SAndroid Build Coastguard Worker const uint8_t kData[] = {1, 2, 3, 4, 5};
158*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(5u, std::size(kData));
159*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
160*6777b538SAndroid Build Coastguard Worker key.WriteValue(kName, kData, std::size(kData), REG_BINARY));
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker RegistryValueIterator iterator(HKEY_CURRENT_USER, root_key().c_str());
163*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(iterator.Valid());
164*6777b538SAndroid Build Coastguard Worker // Avoid having to use EXPECT_STREQ here by leveraging std::string_view's
165*6777b538SAndroid Build Coastguard Worker // operator== to perform a deep comparison.
166*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::wstring_view(kName), std::wstring_view(iterator.Name()));
167*6777b538SAndroid Build Coastguard Worker // ValueSize() is in bytes.
168*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(std::size(kData), iterator.ValueSize());
169*6777b538SAndroid Build Coastguard Worker // Value() is NUL terminated.
170*6777b538SAndroid Build Coastguard Worker int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
171*6777b538SAndroid Build Coastguard Worker EXPECT_NE('\0', iterator.Value()[end - 1]);
172*6777b538SAndroid Build Coastguard Worker EXPECT_EQ('\0', iterator.Value()[end]);
173*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), std::size(kData)));
174*6777b538SAndroid Build Coastguard Worker ++iterator;
175*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(iterator.Valid());
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker // Tests that the value iterator is okay with an empty key.
TEST_F(RegistryTest,ValueIteratorEmptyKey)179*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, ValueIteratorEmptyKey) {
180*6777b538SAndroid Build Coastguard Worker RegistryValueIterator iterator(HKEY_CURRENT_USER, root_key().c_str());
181*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(iterator.ValueCount(), 0U);
182*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(iterator.Valid());
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker // Tests that the default value is seen by a value iterator.
TEST_F(RegistryTest,ValueIteratorDefaultValue)186*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, ValueIteratorDefaultValue) {
187*6777b538SAndroid Build Coastguard Worker const std::wstring_view kTestString(L"i miss you");
188*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(RegKey(HKEY_CURRENT_USER, root_key().c_str(), KEY_SET_VALUE)
189*6777b538SAndroid Build Coastguard Worker .WriteValue(nullptr, kTestString.data()),
190*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
191*6777b538SAndroid Build Coastguard Worker RegistryValueIterator iterator(HKEY_CURRENT_USER, root_key().c_str());
192*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(iterator.ValueCount(), 1U);
193*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(iterator.Valid());
194*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::wstring_view(iterator.Name()), std::wstring_view());
195*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(iterator.ValueSize(), (kTestString.size() + 1) * sizeof(wchar_t));
196*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(iterator.Type(), REG_SZ);
197*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(std::wstring_view(iterator.Value()), kTestString);
198*6777b538SAndroid Build Coastguard Worker ++iterator;
199*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(iterator.Valid());
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,NonRecursiveDelete)202*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, NonRecursiveDelete) {
203*6777b538SAndroid Build Coastguard Worker RegKey key;
204*6777b538SAndroid Build Coastguard Worker // Create root_key()
205*6777b538SAndroid Build Coastguard Worker // \->Bar (TestValue)
206*6777b538SAndroid Build Coastguard Worker // \->Foo (TestValue)
207*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, root_key().c_str(),
208*6777b538SAndroid Build Coastguard Worker KEY_CREATE_SUB_KEY));
209*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
210*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
211*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
212*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
213*6777b538SAndroid Build Coastguard Worker key.Close();
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker const std::wstring bar_path = root_key() + L"\\Bar";
216*6777b538SAndroid Build Coastguard Worker // Non-recursive delete of Bar from root_key() should fail.
217*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
218*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_QUERY_VALUE));
219*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
220*6777b538SAndroid Build Coastguard Worker key.DeleteKey(L"Bar", RegKey::RecursiveDelete(false)));
221*6777b538SAndroid Build Coastguard Worker key.Close();
222*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(
223*6777b538SAndroid Build Coastguard Worker RegKey(HKEY_CURRENT_USER, bar_path.c_str(), KEY_QUERY_VALUE).Valid());
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker // Non-recursive delete of Bar from itself should fail.
226*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
227*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, bar_path.c_str(), KEY_QUERY_VALUE));
228*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"", RegKey::RecursiveDelete(false)));
229*6777b538SAndroid Build Coastguard Worker key.Close();
230*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(
231*6777b538SAndroid Build Coastguard Worker RegKey(HKEY_CURRENT_USER, root_key().c_str(), KEY_QUERY_VALUE).Valid());
232*6777b538SAndroid Build Coastguard Worker
233*6777b538SAndroid Build Coastguard Worker // Non-recursive delete of the subkey and then root_key() should succeed.
234*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
235*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, bar_path.c_str(), KEY_QUERY_VALUE));
236*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
237*6777b538SAndroid Build Coastguard Worker key.DeleteKey(L"Foo", RegKey::RecursiveDelete(false)));
238*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"", RegKey::RecursiveDelete(false)));
239*6777b538SAndroid Build Coastguard Worker key.Close();
240*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(
241*6777b538SAndroid Build Coastguard Worker RegKey(HKEY_CURRENT_USER, bar_path.c_str(), KEY_QUERY_VALUE).Valid());
242*6777b538SAndroid Build Coastguard Worker }
243*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,RecursiveDelete)244*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, RecursiveDelete) {
245*6777b538SAndroid Build Coastguard Worker RegKey key;
246*6777b538SAndroid Build Coastguard Worker // Create root_key()
247*6777b538SAndroid Build Coastguard Worker // \->Bar (TestValue)
248*6777b538SAndroid Build Coastguard Worker // \->Foo (TestValue)
249*6777b538SAndroid Build Coastguard Worker // \->Bar
250*6777b538SAndroid Build Coastguard Worker // \->Foo
251*6777b538SAndroid Build Coastguard Worker // \->Moo
252*6777b538SAndroid Build Coastguard Worker // \->Foo
253*6777b538SAndroid Build Coastguard Worker // and delete root_key()
254*6777b538SAndroid Build Coastguard Worker std::wstring key_path = root_key();
255*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
256*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_CREATE_SUB_KEY));
257*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
258*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
259*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
260*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_CREATE_SUB_KEY));
261*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE));
262*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
263*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_CREATE_SUB_KEY));
264*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker key_path += L"\\Bar";
267*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
268*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_CREATE_SUB_KEY));
269*6777b538SAndroid Build Coastguard Worker key_path += L"\\Foo";
270*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
271*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
272*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
273*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ));
274*6777b538SAndroid Build Coastguard Worker
275*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
276*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_CREATE_SUB_KEY));
277*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
278*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
279*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
280*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_WRITE));
281*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L""));
282*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
283*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ));
284*6777b538SAndroid Build Coastguard Worker
285*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
286*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_WRITE));
287*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
288*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
289*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
290*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ));
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,OpenSubKey)293*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, OpenSubKey) {
294*6777b538SAndroid Build Coastguard Worker RegKey key;
295*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, root_key().c_str(),
296*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_CREATE_SUB_KEY));
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
299*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"foo", KEY_READ));
300*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
301*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ));
302*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
303*6777b538SAndroid Build Coastguard Worker
304*6777b538SAndroid Build Coastguard Worker std::wstring foo_key = root_key() + L"\\Foo";
305*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
306*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
309*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_WRITE));
310*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
311*6777b538SAndroid Build Coastguard Worker }
312*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,InvalidRelativeKeyCreate)313*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, InvalidRelativeKeyCreate) {
314*6777b538SAndroid Build Coastguard Worker RegKey key(HKEY_CURRENT_USER,
315*6777b538SAndroid Build Coastguard Worker base::StrCat({this->root_key(), L"_DoesNotExist"}).c_str(),
316*6777b538SAndroid Build Coastguard Worker KEY_WOW64_32KEY | KEY_READ);
317*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.CreateKey(L"SomeSubKey", KEY_WOW64_32KEY | KEY_WRITE),
318*6777b538SAndroid Build Coastguard Worker ERROR_INVALID_HANDLE);
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,InvalidRelativeKeyOpen)321*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, InvalidRelativeKeyOpen) {
322*6777b538SAndroid Build Coastguard Worker RegKey key(HKEY_CURRENT_USER,
323*6777b538SAndroid Build Coastguard Worker base::StrCat({this->root_key(), L"_DoesNotExist"}).c_str(),
324*6777b538SAndroid Build Coastguard Worker KEY_WOW64_32KEY | KEY_READ);
325*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.OpenKey(L"SomeSubKey", KEY_WOW64_32KEY | KEY_READ),
326*6777b538SAndroid Build Coastguard Worker ERROR_INVALID_HANDLE);
327*6777b538SAndroid Build Coastguard Worker }
328*6777b538SAndroid Build Coastguard Worker
329*6777b538SAndroid Build Coastguard Worker namespace {
330*6777b538SAndroid Build Coastguard Worker
331*6777b538SAndroid Build Coastguard Worker class TestChangeDelegate {
332*6777b538SAndroid Build Coastguard Worker public:
333*6777b538SAndroid Build Coastguard Worker TestChangeDelegate() = default;
334*6777b538SAndroid Build Coastguard Worker ~TestChangeDelegate() = default;
335*6777b538SAndroid Build Coastguard Worker
OnKeyChanged(base::OnceClosure quit_closure)336*6777b538SAndroid Build Coastguard Worker void OnKeyChanged(base::OnceClosure quit_closure) {
337*6777b538SAndroid Build Coastguard Worker std::move(quit_closure).Run();
338*6777b538SAndroid Build Coastguard Worker called_ = true;
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker
WasCalled()341*6777b538SAndroid Build Coastguard Worker bool WasCalled() {
342*6777b538SAndroid Build Coastguard Worker bool was_called = called_;
343*6777b538SAndroid Build Coastguard Worker called_ = false;
344*6777b538SAndroid Build Coastguard Worker return was_called;
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker private:
348*6777b538SAndroid Build Coastguard Worker bool called_ = false;
349*6777b538SAndroid Build Coastguard Worker };
350*6777b538SAndroid Build Coastguard Worker
351*6777b538SAndroid Build Coastguard Worker } // namespace
352*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,ChangeCallback)353*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, ChangeCallback) {
354*6777b538SAndroid Build Coastguard Worker RegKey key;
355*6777b538SAndroid Build Coastguard Worker TestChangeDelegate delegate;
356*6777b538SAndroid Build Coastguard Worker test::TaskEnvironment task_environment;
357*6777b538SAndroid Build Coastguard Worker base::RunLoop loop1;
358*6777b538SAndroid Build Coastguard Worker base::RunLoop loop2;
359*6777b538SAndroid Build Coastguard Worker base::RunLoop loop3;
360*6777b538SAndroid Build Coastguard Worker
361*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
362*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ));
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.StartWatching(BindOnce(&TestChangeDelegate::OnKeyChanged,
365*6777b538SAndroid Build Coastguard Worker Unretained(&delegate),
366*6777b538SAndroid Build Coastguard Worker loop1.QuitWhenIdleClosure())));
367*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate.WasCalled());
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker // Make some change.
370*6777b538SAndroid Build Coastguard Worker RegKey key2;
371*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, root_key().c_str(),
372*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_SET_VALUE));
373*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key2.Valid());
374*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name", L"data"));
375*6777b538SAndroid Build Coastguard Worker
376*6777b538SAndroid Build Coastguard Worker // Allow delivery of the notification.
377*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate.WasCalled());
378*6777b538SAndroid Build Coastguard Worker loop1.Run();
379*6777b538SAndroid Build Coastguard Worker
380*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(delegate.WasCalled());
381*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate.WasCalled());
382*6777b538SAndroid Build Coastguard Worker
383*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.StartWatching(BindOnce(&TestChangeDelegate::OnKeyChanged,
384*6777b538SAndroid Build Coastguard Worker Unretained(&delegate),
385*6777b538SAndroid Build Coastguard Worker loop2.QuitWhenIdleClosure())));
386*6777b538SAndroid Build Coastguard Worker
387*6777b538SAndroid Build Coastguard Worker // Change something else.
388*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name2", L"data2"));
389*6777b538SAndroid Build Coastguard Worker loop2.Run();
390*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(delegate.WasCalled());
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key.StartWatching(BindOnce(&TestChangeDelegate::OnKeyChanged,
393*6777b538SAndroid Build Coastguard Worker Unretained(&delegate),
394*6777b538SAndroid Build Coastguard Worker loop3.QuitWhenIdleClosure())));
395*6777b538SAndroid Build Coastguard Worker loop3.RunUntilIdle();
396*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate.WasCalled());
397*6777b538SAndroid Build Coastguard Worker }
398*6777b538SAndroid Build Coastguard Worker
399*6777b538SAndroid Build Coastguard Worker namespace {
400*6777b538SAndroid Build Coastguard Worker
401*6777b538SAndroid Build Coastguard Worker // A thread that runs tasks from a TestMockTimeTaskRunner.
402*6777b538SAndroid Build Coastguard Worker class RegistryWatcherThread : public SimpleThread {
403*6777b538SAndroid Build Coastguard Worker public:
RegistryWatcherThread(scoped_refptr<base::TestMockTimeTaskRunner> task_runner)404*6777b538SAndroid Build Coastguard Worker explicit RegistryWatcherThread(
405*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::TestMockTimeTaskRunner> task_runner)
406*6777b538SAndroid Build Coastguard Worker : SimpleThread("RegistryWatcherThread"),
407*6777b538SAndroid Build Coastguard Worker task_runner_(std::move(task_runner)) {}
408*6777b538SAndroid Build Coastguard Worker
409*6777b538SAndroid Build Coastguard Worker private:
Run()410*6777b538SAndroid Build Coastguard Worker void Run() override {
411*6777b538SAndroid Build Coastguard Worker task_runner_->DetachFromThread();
412*6777b538SAndroid Build Coastguard Worker task_runner_->RunUntilIdle();
413*6777b538SAndroid Build Coastguard Worker }
414*6777b538SAndroid Build Coastguard Worker const scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
415*6777b538SAndroid Build Coastguard Worker };
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker } // namespace
418*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,WatcherNotSignaledOnInitiatingThreadExit)419*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, WatcherNotSignaledOnInitiatingThreadExit) {
420*6777b538SAndroid Build Coastguard Worker RegKey key;
421*6777b538SAndroid Build Coastguard Worker
422*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ),
423*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
424*6777b538SAndroid Build Coastguard Worker
425*6777b538SAndroid Build Coastguard Worker auto test_task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
426*6777b538SAndroid Build Coastguard Worker base::TestMockTimeTaskRunner::Type::kBoundToThread);
427*6777b538SAndroid Build Coastguard Worker ::testing::StrictMock<base::MockCallback<base::win::RegKey::ChangeCallback>>
428*6777b538SAndroid Build Coastguard Worker change_cb;
429*6777b538SAndroid Build Coastguard Worker
430*6777b538SAndroid Build Coastguard Worker test_task_runner->PostTask(FROM_HERE,
431*6777b538SAndroid Build Coastguard Worker BindOnce(IgnoreResult(&RegKey::StartWatching),
432*6777b538SAndroid Build Coastguard Worker Unretained(&key), change_cb.Get()));
433*6777b538SAndroid Build Coastguard Worker
434*6777b538SAndroid Build Coastguard Worker {
435*6777b538SAndroid Build Coastguard Worker // Start the watch on a thread that then goes away.
436*6777b538SAndroid Build Coastguard Worker RegistryWatcherThread watcher_thread(test_task_runner);
437*6777b538SAndroid Build Coastguard Worker watcher_thread.Start();
438*6777b538SAndroid Build Coastguard Worker watcher_thread.Join();
439*6777b538SAndroid Build Coastguard Worker }
440*6777b538SAndroid Build Coastguard Worker
441*6777b538SAndroid Build Coastguard Worker // Termination of the thread should not cause a notification to get sent.
442*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(&change_cb));
443*6777b538SAndroid Build Coastguard Worker test_task_runner->DetachFromThread();
444*6777b538SAndroid Build Coastguard Worker ASSERT_FALSE(test_task_runner->HasPendingTask());
445*6777b538SAndroid Build Coastguard Worker
446*6777b538SAndroid Build Coastguard Worker // Expect that a notification is sent when a change is made. Exit the run loop
447*6777b538SAndroid Build Coastguard Worker // when this happens.
448*6777b538SAndroid Build Coastguard Worker base::RunLoop run_loop;
449*6777b538SAndroid Build Coastguard Worker EXPECT_CALL(change_cb, Run).WillOnce([&run_loop]() { run_loop.Quit(); });
450*6777b538SAndroid Build Coastguard Worker
451*6777b538SAndroid Build Coastguard Worker // Make some change.
452*6777b538SAndroid Build Coastguard Worker RegKey key2;
453*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key2.Open(HKEY_CURRENT_USER, root_key().c_str(),
454*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_SET_VALUE),
455*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
456*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(key2.Valid());
457*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key2.WriteValue(L"name", L"data"), ERROR_SUCCESS);
458*6777b538SAndroid Build Coastguard Worker
459*6777b538SAndroid Build Coastguard Worker // Wait for the watcher to be signaled.
460*6777b538SAndroid Build Coastguard Worker run_loop.Run();
461*6777b538SAndroid Build Coastguard Worker }
462*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,TestMoveConstruct)463*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, TestMoveConstruct) {
464*6777b538SAndroid Build Coastguard Worker RegKey key;
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.Open(HKEY_CURRENT_USER, root_key().c_str(), KEY_SET_VALUE),
467*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
468*6777b538SAndroid Build Coastguard Worker RegKey key2(std::move(key));
469*6777b538SAndroid Build Coastguard Worker
470*6777b538SAndroid Build Coastguard Worker // The old key should be meaningless now.
471*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key.Handle(), nullptr);
472*6777b538SAndroid Build Coastguard Worker
473*6777b538SAndroid Build Coastguard Worker // And the new one should work just fine.
474*6777b538SAndroid Build Coastguard Worker EXPECT_NE(key2.Handle(), nullptr);
475*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key2.WriteValue(L"foo", 1U), ERROR_SUCCESS);
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTest,TestMoveAssign)478*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, TestMoveAssign) {
479*6777b538SAndroid Build Coastguard Worker RegKey key;
480*6777b538SAndroid Build Coastguard Worker RegKey key2;
481*6777b538SAndroid Build Coastguard Worker const wchar_t kFooValueName[] = L"foo";
482*6777b538SAndroid Build Coastguard Worker
483*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.Open(HKEY_CURRENT_USER, root_key().c_str(),
484*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE | KEY_QUERY_VALUE),
485*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
486*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key.WriteValue(kFooValueName, 1U), ERROR_SUCCESS);
487*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key2.Create(HKEY_CURRENT_USER, (root_key() + L"\\child").c_str(),
488*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE),
489*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
490*6777b538SAndroid Build Coastguard Worker key2 = std::move(key);
491*6777b538SAndroid Build Coastguard Worker
492*6777b538SAndroid Build Coastguard Worker // The old key should be meaningless now.
493*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key.Handle(), nullptr);
494*6777b538SAndroid Build Coastguard Worker
495*6777b538SAndroid Build Coastguard Worker // And the new one should hold what was the old one.
496*6777b538SAndroid Build Coastguard Worker EXPECT_NE(key2.Handle(), nullptr);
497*6777b538SAndroid Build Coastguard Worker DWORD foo = 0;
498*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(key2.ReadValueDW(kFooValueName, &foo), ERROR_SUCCESS);
499*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(foo, 1U);
500*6777b538SAndroid Build Coastguard Worker }
501*6777b538SAndroid Build Coastguard Worker
502*6777b538SAndroid Build Coastguard Worker // Verify that either the platform, or the API-integration, causes deletion
503*6777b538SAndroid Build Coastguard Worker // attempts via an invalid handle to fail with the expected error code.
TEST_F(RegistryTest,DeleteWithInvalidRegKey)504*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTest, DeleteWithInvalidRegKey) {
505*6777b538SAndroid Build Coastguard Worker RegKey key;
506*6777b538SAndroid Build Coastguard Worker
507*6777b538SAndroid Build Coastguard Worker static const wchar_t kFooName[] = L"foo";
508*6777b538SAndroid Build Coastguard Worker
509*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key.DeleteKey(kFooName), ERROR_INVALID_HANDLE);
510*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(key.DeleteValue(kFooName), ERROR_INVALID_HANDLE);
511*6777b538SAndroid Build Coastguard Worker }
512*6777b538SAndroid Build Coastguard Worker
513*6777b538SAndroid Build Coastguard Worker // A test harness for tests of RegKey::DeleteKey; parameterized on whether to
514*6777b538SAndroid Build Coastguard Worker // perform non-recursive or recursive deletes.
515*6777b538SAndroid Build Coastguard Worker class DeleteKeyRegistryTest
516*6777b538SAndroid Build Coastguard Worker : public RegistryTest,
517*6777b538SAndroid Build Coastguard Worker public ::testing::WithParamInterface<RegKey::RecursiveDelete> {
518*6777b538SAndroid Build Coastguard Worker protected:
519*6777b538SAndroid Build Coastguard Worker DeleteKeyRegistryTest() = default;
520*6777b538SAndroid Build Coastguard Worker
521*6777b538SAndroid Build Coastguard Worker private:
522*6777b538SAndroid Build Coastguard Worker };
523*6777b538SAndroid Build Coastguard Worker
524*6777b538SAndroid Build Coastguard Worker // Test that DeleteKey does not follow symbolic links.
TEST_P(DeleteKeyRegistryTest,DoesNotFollowLinks)525*6777b538SAndroid Build Coastguard Worker TEST_P(DeleteKeyRegistryTest, DoesNotFollowLinks) {
526*6777b538SAndroid Build Coastguard Worker // Create a subkey that should not be deleted.
527*6777b538SAndroid Build Coastguard Worker std::wstring target_path = root_key() + L"\\LinkTarget";
528*6777b538SAndroid Build Coastguard Worker {
529*6777b538SAndroid Build Coastguard Worker RegKey target;
530*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(target.Create(HKEY_CURRENT_USER, target_path.c_str(), KEY_WRITE),
531*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
532*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(target.WriteValue(L"IsTarget", 1U), ERROR_SUCCESS);
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker
535*6777b538SAndroid Build Coastguard Worker // Create a link to the above key.
536*6777b538SAndroid Build Coastguard Worker std::wstring source_path = root_key() + L"\\LinkSource";
537*6777b538SAndroid Build Coastguard Worker {
538*6777b538SAndroid Build Coastguard Worker HKEY link_handle = {};
539*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(RegCreateKeyEx(HKEY_CURRENT_USER, source_path.c_str(), 0, nullptr,
540*6777b538SAndroid Build Coastguard Worker REG_OPTION_CREATE_LINK | REG_OPTION_NON_VOLATILE,
541*6777b538SAndroid Build Coastguard Worker KEY_WRITE, nullptr, &link_handle, nullptr),
542*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
543*6777b538SAndroid Build Coastguard Worker RegKey link(std::exchange(link_handle, HKEY{}));
544*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(link.Valid());
545*6777b538SAndroid Build Coastguard Worker
546*6777b538SAndroid Build Coastguard Worker std::wstring user_sid;
547*6777b538SAndroid Build Coastguard Worker ASSERT_TRUE(GetUserSidString(&user_sid));
548*6777b538SAndroid Build Coastguard Worker
549*6777b538SAndroid Build Coastguard Worker std::wstring value =
550*6777b538SAndroid Build Coastguard Worker base::StrCat({L"\\Registry\\User\\", user_sid, L"\\", override_path(),
551*6777b538SAndroid Build Coastguard Worker L"\\", root_key(), L"\\LinkTarget"});
552*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(link.WriteValue(L"SymbolicLinkValue", value.data(),
553*6777b538SAndroid Build Coastguard Worker value.size() * sizeof(wchar_t), REG_LINK),
554*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
555*6777b538SAndroid Build Coastguard Worker }
556*6777b538SAndroid Build Coastguard Worker
557*6777b538SAndroid Build Coastguard Worker // Verify that the link works.
558*6777b538SAndroid Build Coastguard Worker {
559*6777b538SAndroid Build Coastguard Worker RegKey link;
560*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(link.Open(HKEY_CURRENT_USER, source_path.c_str(), KEY_READ),
561*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
562*6777b538SAndroid Build Coastguard Worker DWORD value = 0;
563*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(link.ReadValueDW(L"IsTarget", &value), ERROR_SUCCESS);
564*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(value, 1U);
565*6777b538SAndroid Build Coastguard Worker }
566*6777b538SAndroid Build Coastguard Worker
567*6777b538SAndroid Build Coastguard Worker // Now delete the link and ensure that it was deleted, but not the target.
568*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(RegKey(HKEY_CURRENT_USER, root_key().c_str(), KEY_READ)
569*6777b538SAndroid Build Coastguard Worker .DeleteKey(L"LinkSource", GetParam()),
570*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
571*6777b538SAndroid Build Coastguard Worker {
572*6777b538SAndroid Build Coastguard Worker RegKey source;
573*6777b538SAndroid Build Coastguard Worker ASSERT_NE(source.Open(HKEY_CURRENT_USER, source_path.c_str(), KEY_READ),
574*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
575*6777b538SAndroid Build Coastguard Worker }
576*6777b538SAndroid Build Coastguard Worker {
577*6777b538SAndroid Build Coastguard Worker RegKey target;
578*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(target.Open(HKEY_CURRENT_USER, target_path.c_str(), KEY_READ),
579*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS);
580*6777b538SAndroid Build Coastguard Worker }
581*6777b538SAndroid Build Coastguard Worker }
582*6777b538SAndroid Build Coastguard Worker
583*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(NonRecursive,
584*6777b538SAndroid Build Coastguard Worker DeleteKeyRegistryTest,
585*6777b538SAndroid Build Coastguard Worker ::testing::Values(RegKey::RecursiveDelete(false)));
586*6777b538SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(Recursive,
587*6777b538SAndroid Build Coastguard Worker DeleteKeyRegistryTest,
588*6777b538SAndroid Build Coastguard Worker ::testing::Values(RegKey::RecursiveDelete(true)));
589*6777b538SAndroid Build Coastguard Worker
590*6777b538SAndroid Build Coastguard Worker // A test harness for tests that use HKLM to test WoW redirection and such.
591*6777b538SAndroid Build Coastguard Worker // TODO(https://crbug.com/377917): The tests here that write to the registry are
592*6777b538SAndroid Build Coastguard Worker // disabled because they need work to handle parallel runs of different tests.
593*6777b538SAndroid Build Coastguard Worker class RegistryTestHKLM : public ::testing::Test {
594*6777b538SAndroid Build Coastguard Worker protected:
595*6777b538SAndroid Build Coastguard Worker enum : REGSAM {
596*6777b538SAndroid Build Coastguard Worker #if defined(_WIN64)
597*6777b538SAndroid Build Coastguard Worker kNativeViewMask = KEY_WOW64_64KEY,
598*6777b538SAndroid Build Coastguard Worker kRedirectedViewMask = KEY_WOW64_32KEY,
599*6777b538SAndroid Build Coastguard Worker #else
600*6777b538SAndroid Build Coastguard Worker kNativeViewMask = KEY_WOW64_32KEY,
601*6777b538SAndroid Build Coastguard Worker kRedirectedViewMask = KEY_WOW64_64KEY,
602*6777b538SAndroid Build Coastguard Worker #endif // _WIN64
603*6777b538SAndroid Build Coastguard Worker };
604*6777b538SAndroid Build Coastguard Worker
RegistryTestHKLM()605*6777b538SAndroid Build Coastguard Worker RegistryTestHKLM()
606*6777b538SAndroid Build Coastguard Worker : foo_software_key_(std::wstring(L"Software\\") + kRootKey + L"\\Foo") {}
607*6777b538SAndroid Build Coastguard Worker
IsRedirectorPresent()608*6777b538SAndroid Build Coastguard Worker static bool IsRedirectorPresent() {
609*6777b538SAndroid Build Coastguard Worker #if defined(_WIN64)
610*6777b538SAndroid Build Coastguard Worker return true;
611*6777b538SAndroid Build Coastguard Worker #else
612*6777b538SAndroid Build Coastguard Worker return OSInfo::GetInstance()->IsWowX86OnAMD64();
613*6777b538SAndroid Build Coastguard Worker #endif
614*6777b538SAndroid Build Coastguard Worker }
615*6777b538SAndroid Build Coastguard Worker
616*6777b538SAndroid Build Coastguard Worker const std::wstring foo_software_key_;
617*6777b538SAndroid Build Coastguard Worker };
618*6777b538SAndroid Build Coastguard Worker
619*6777b538SAndroid Build Coastguard Worker class RegistryTestHKLMAdmin : public RegistryTestHKLM {
620*6777b538SAndroid Build Coastguard Worker protected:
SetUp()621*6777b538SAndroid Build Coastguard Worker void SetUp() override {
622*6777b538SAndroid Build Coastguard Worker if (!IsRedirectorPresent()) {
623*6777b538SAndroid Build Coastguard Worker GTEST_SKIP();
624*6777b538SAndroid Build Coastguard Worker }
625*6777b538SAndroid Build Coastguard Worker if (!::IsUserAnAdmin()) {
626*6777b538SAndroid Build Coastguard Worker GTEST_SKIP();
627*6777b538SAndroid Build Coastguard Worker }
628*6777b538SAndroid Build Coastguard Worker // Clean up any stale registry keys.
629*6777b538SAndroid Build Coastguard Worker for (const REGSAM mask :
630*6777b538SAndroid Build Coastguard Worker {this->kNativeViewMask, this->kRedirectedViewMask}) {
631*6777b538SAndroid Build Coastguard Worker RegKey key;
632*6777b538SAndroid Build Coastguard Worker if (key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE | mask) ==
633*6777b538SAndroid Build Coastguard Worker ERROR_SUCCESS) {
634*6777b538SAndroid Build Coastguard Worker key.DeleteKey(kRootKey);
635*6777b538SAndroid Build Coastguard Worker }
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker }
638*6777b538SAndroid Build Coastguard Worker };
639*6777b538SAndroid Build Coastguard Worker
640*6777b538SAndroid Build Coastguard Worker // This test requires running as an Administrator as it tests redirected
641*6777b538SAndroid Build Coastguard Worker // registry writes to HKLM\Software
642*6777b538SAndroid Build Coastguard Worker // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx
TEST_F(RegistryTestHKLMAdmin,Wow64RedirectedFromNative)643*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTestHKLMAdmin, Wow64RedirectedFromNative) {
644*6777b538SAndroid Build Coastguard Worker RegKey key;
645*6777b538SAndroid Build Coastguard Worker
646*6777b538SAndroid Build Coastguard Worker // Test redirected key access from non-redirected.
647*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
648*6777b538SAndroid Build Coastguard Worker key.Create(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(),
649*6777b538SAndroid Build Coastguard Worker KEY_WRITE | kRedirectedViewMask));
650*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
651*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
652*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
653*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(),
654*6777b538SAndroid Build Coastguard Worker KEY_READ | kNativeViewMask));
655*6777b538SAndroid Build Coastguard Worker
656*6777b538SAndroid Build Coastguard Worker // Open the non-redirected view of the parent and try to delete the test key.
657*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
658*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE));
659*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
660*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
661*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE | kNativeViewMask));
662*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
663*6777b538SAndroid Build Coastguard Worker
664*6777b538SAndroid Build Coastguard Worker // Open the redirected view and delete the key created above.
665*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
666*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE | kRedirectedViewMask));
667*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
668*6777b538SAndroid Build Coastguard Worker }
669*6777b538SAndroid Build Coastguard Worker
670*6777b538SAndroid Build Coastguard Worker // Test for the issue found in http://crbug.com/384587 where OpenKey would call
671*6777b538SAndroid Build Coastguard Worker // Close() and reset wow64_access_ flag to 0 and cause a NOTREACHED to hit on a
672*6777b538SAndroid Build Coastguard Worker // subsequent OpenKey call.
TEST_F(RegistryTestHKLM,SameWowFlags)673*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTestHKLM, SameWowFlags) {
674*6777b538SAndroid Build Coastguard Worker RegKey key;
675*6777b538SAndroid Build Coastguard Worker
676*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
677*6777b538SAndroid Build Coastguard Worker KEY_READ | KEY_WOW64_64KEY));
678*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
679*6777b538SAndroid Build Coastguard Worker key.OpenKey(L"Microsoft", KEY_READ | KEY_WOW64_64KEY));
680*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"Windows", KEY_READ | KEY_WOW64_64KEY));
681*6777b538SAndroid Build Coastguard Worker }
682*6777b538SAndroid Build Coastguard Worker
TEST_F(RegistryTestHKLMAdmin,Wow64NativeFromRedirected)683*6777b538SAndroid Build Coastguard Worker TEST_F(RegistryTestHKLMAdmin, Wow64NativeFromRedirected) {
684*6777b538SAndroid Build Coastguard Worker RegKey key;
685*6777b538SAndroid Build Coastguard Worker
686*6777b538SAndroid Build Coastguard Worker // Test non-redirected key access from redirected.
687*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
688*6777b538SAndroid Build Coastguard Worker key.Create(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(),
689*6777b538SAndroid Build Coastguard Worker KEY_WRITE | kNativeViewMask));
690*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS,
691*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
692*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS,
693*6777b538SAndroid Build Coastguard Worker key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(),
694*6777b538SAndroid Build Coastguard Worker KEY_READ | kRedirectedViewMask));
695*6777b538SAndroid Build Coastguard Worker
696*6777b538SAndroid Build Coastguard Worker // Open the redirected view of the parent and try to delete the test key
697*6777b538SAndroid Build Coastguard Worker // from the non-redirected view.
698*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
699*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE | kRedirectedViewMask));
700*6777b538SAndroid Build Coastguard Worker ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
701*6777b538SAndroid Build Coastguard Worker
702*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_LOCAL_MACHINE, L"Software",
703*6777b538SAndroid Build Coastguard Worker KEY_SET_VALUE | kNativeViewMask));
704*6777b538SAndroid Build Coastguard Worker ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
705*6777b538SAndroid Build Coastguard Worker }
706*6777b538SAndroid Build Coastguard Worker
707*6777b538SAndroid Build Coastguard Worker } // namespace base::win
708