15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstring>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/win/windows_version.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace win {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class RegistryTest : public testing::Test {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(_WIN64)
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const REGSAM kNativeViewMask = KEY_WOW64_64KEY;
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const REGSAM kRedirectedViewMask = KEY_WOW64_32KEY;
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const REGSAM kNativeViewMask = KEY_WOW64_32KEY;
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const REGSAM kRedirectedViewMask = KEY_WOW64_64KEY;
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  //  _WIN64
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegistryTest() {}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a temporary key.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    key.DeleteKey(kRootKey);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    foo_software_key_ = L"Software\\";
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    foo_software_key_ += kRootKey;
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    foo_software_key_ += L"\\Foo";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clean up the temporary key.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static bool IsRedirectorPresent() {
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(_WIN64)
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#else
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return OSInfo::GetInstance()->wow64_status() == OSInfo::WOW64_ENABLED;
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const wchar_t* const kRootKey = L"Base_Registry_Unittest";
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::wstring foo_software_key_;
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(RegistryTest);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const REGSAM RegistryTest::kNativeViewMask;
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const REGSAM RegistryTest::kRedirectedViewMask;
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RegistryTest, ValueTest) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegKey key;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring foo_key(kRootKey);
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  foo_key += L"\\Foo";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      KEY_READ));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      KEY_READ | KEY_SET_VALUE));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(key.Valid());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t kStringValueName[] = L"StringValue";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t kDWORDValueName[] = L"DWORDValue";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t kInt64ValueName[] = L"Int64Value";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t kStringData[] = L"string data";
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DWORD kDWORDData = 0xdeadbabe;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int64 kInt64Data = 0xdeadbabedeadbabeLL;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test value creation
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kStringValueName, kStringData));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kDWORDValueName, kDWORDData));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kInt64ValueName, &kInt64Data,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            sizeof(kInt64Data), REG_QWORD));
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(3U, key.GetValueCount());
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(key.HasValue(kStringValueName));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(key.HasValue(kDWORDValueName));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(key.HasValue(kInt64ValueName));
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test Read
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring string_value;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD dword_value = 0;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 int64_value = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(kDWORDValueName, &dword_value));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.ReadInt64(kInt64ValueName, &int64_value));
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_STREQ(kStringData, string_value.c_str());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kDWORDData, dword_value);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kInt64Data, int64_value);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure out args are not touched if ReadValue fails
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const wchar_t* kNonExistent = L"NonExistent";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_STREQ(kStringData, string_value.c_str());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kDWORDData, dword_value);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(kInt64Data, int64_value);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Test delete
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kStringValueName));
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kDWORDValueName));
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kInt64ValueName));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0U, key.GetValueCount());
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(key.HasValue(kStringValueName));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(key.HasValue(kDWORDValueName));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(key.HasValue(kInt64ValueName));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RegistryTest, BigValueIteratorTest) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegKey key;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring foo_key(kRootKey);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  foo_key += L"\\Foo";
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      KEY_READ));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    KEY_READ | KEY_SET_VALUE));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(key.Valid());
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a test value that is larger than MAX_PATH.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring data(MAX_PATH * 2, L'a');
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(data.c_str(), data.c_str()));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(iterator.Valid());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ(data.c_str(), iterator.Name());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ(data.c_str(), iterator.Value());
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ValueSize() is in bytes, including NUL.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(wchar_t), iterator.ValueSize());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++iterator;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(iterator.Valid());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(RegistryTest, TruncatedCharTest) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegKey key;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring foo_key(kRootKey);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  foo_key += L"\\Foo";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      KEY_READ));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    KEY_READ | KEY_SET_VALUE));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(key.Valid());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const wchar_t kName[] = L"name";
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // kData size is not a multiple of sizeof(wchar_t).
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8 kData[] = { 1, 2, 3, 4, 5 };
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(5, arraysize(kData));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kName, kData,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          arraysize(kData), REG_BINARY));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(iterator.Valid());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_STREQ(kName, iterator.Name());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ValueSize() is in bytes.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(arraysize(kData), iterator.ValueSize());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Value() is NUL terminated.
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_NE(L'\0', iterator.Value()[end-1]);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(L'\0', iterator.Value()[end]);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), arraysize(kData)));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++iterator;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(iterator.Valid());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RegistryTest, RecursiveDelete) {
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegKey key;
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Create kRootKey->Foo
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                  \->Bar (TestValue)
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                     \->Foo (TestValue)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                        \->Bar
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                           \->Foo
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                  \->Moo
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  //                  \->Foo
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // and delete kRootKey->Foo
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::wstring foo_key(kRootKey);
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_key += L"\\Foo";
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE));
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_key += L"\\Bar";
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_key += L"\\Foo";
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo"));
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar\\Foo"));
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar"));
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Foo"));
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L""));
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS,
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS,
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This test requires running as an Administrator as it tests redirected
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// registry writes to HKLM\Software
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(wfh): flaky test on Vista.  See http://crbug.com/377917
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RegistryTest, DISABLED_Wow64RedirectedFromNative) {
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsRedirectorPresent())
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegKey key;
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Test redirected key access from non-redirected.
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Create(HKEY_LOCAL_MACHINE,
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       foo_software_key_.c_str(),
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       KEY_WRITE | kRedirectedViewMask));
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS,
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS,
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     foo_software_key_.c_str(),
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_READ | kNativeViewMask));
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Open the non-redirected view of the parent and try to delete the test key.
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE));
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     L"Software",
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_SET_VALUE | kNativeViewMask));
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Open the redirected view and delete the key created above.
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     L"Software",
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_SET_VALUE | kRedirectedViewMask));
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Test for the issue found in http://crbug.com/384587 where OpenKey would call
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Close() and reset wow64_access_ flag to 0 and cause a NOTREACHED to hit on a
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// subsequent OpenKey call.
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)TEST_F(RegistryTest, SameWowFlags) {
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RegKey key;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     L"Software",
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     KEY_READ | KEY_WOW64_64KEY));
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            key.OpenKey(L"Microsoft",
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        KEY_READ | KEY_WOW64_64KEY));
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            key.OpenKey(L"Windows",
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                        KEY_READ | KEY_WOW64_64KEY));
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(wfh): flaky test on Vista.  See http://crbug.com/377917
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RegistryTest, DISABLED_Wow64NativeFromRedirected) {
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsRedirectorPresent())
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegKey key;
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Test non-redirected key access from redirected.
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Create(HKEY_LOCAL_MACHINE,
307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       foo_software_key_.c_str(),
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       KEY_WRITE | kNativeViewMask));
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS,
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     foo_software_key_.c_str(),
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_READ | kRedirectedViewMask));
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Open the redirected view of the parent and try to delete the test key
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // from the non-redirected view.
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     L"Software",
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_SET_VALUE | kRedirectedViewMask));
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_LOCAL_MACHINE,
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     L"Software",
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_SET_VALUE | kNativeViewMask));
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)TEST_F(RegistryTest, OpenSubKey) {
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  RegKey key;
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER,
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     kRootKey,
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     KEY_READ | KEY_CREATE_SUB_KEY));
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_NE(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"foo", KEY_READ));
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::wstring foo_key(kRootKey);
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  foo_key += L"\\Foo";
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS,
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)            key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace win
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
356