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. 4 5 #include <windows.h> 6 #include <atlsecurity.h> // NOLINT 7 #include "base/logging.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/win/registry.h" 10 #include "chrome/installer/util/delete_reg_key_work_item.h" 11 #include "chrome/installer/util/registry_test_data.h" 12 #include "chrome/installer/util/work_item.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 using base::win::RegKey; 16 17 class DeleteRegKeyWorkItemTest : public testing::Test { 18 protected: 19 static void TearDownTestCase() { 20 logging::CloseLogFile(); 21 } 22 23 virtual void SetUp() { 24 ASSERT_TRUE(test_data_.Initialize(HKEY_CURRENT_USER, L"SOFTWARE\\TmpTmp")); 25 } 26 27 RegistryTestData test_data_; 28 }; 29 30 // Test that deleting a key that doesn't exist succeeds, and that rollback does 31 // nothing. 32 TEST_F(DeleteRegKeyWorkItemTest, TestNoKey) { 33 const std::wstring key_paths[] = { 34 std::wstring(test_data_.base_path() + L"\\NoKeyHere"), 35 std::wstring(test_data_.base_path() + L"\\NoKeyHere\\OrHere") 36 }; 37 RegKey key; 38 for (size_t i = 0; i < arraysize(key_paths); ++i) { 39 const std::wstring& key_path = key_paths[i]; 40 scoped_ptr<DeleteRegKeyWorkItem> item( 41 WorkItem::CreateDeleteRegKeyWorkItem(test_data_.root_key(), key_path)); 42 EXPECT_TRUE(item->Do()); 43 EXPECT_NE(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_path.c_str(), 44 KEY_READ)); 45 item->Rollback(); 46 item.reset(); 47 EXPECT_NE(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_path.c_str(), 48 KEY_READ)); 49 } 50 } 51 52 // Test that deleting an empty key succeeds, and that rollback brings it back. 53 TEST_F(DeleteRegKeyWorkItemTest, TestEmptyKey) { 54 RegKey key; 55 const std::wstring& key_path = test_data_.empty_key_path(); 56 scoped_ptr<DeleteRegKeyWorkItem> item( 57 WorkItem::CreateDeleteRegKeyWorkItem(test_data_.root_key(), key_path)); 58 EXPECT_TRUE(item->Do()); 59 EXPECT_NE(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_path.c_str(), 60 KEY_READ)); 61 item->Rollback(); 62 item.reset(); 63 EXPECT_EQ(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_path.c_str(), 64 KEY_READ)); 65 } 66 67 // Test that deleting a key with subkeys and values succeeds, and that rollback 68 // brings them all back. 69 TEST_F(DeleteRegKeyWorkItemTest, TestNonEmptyKey) { 70 RegKey key; 71 const std::wstring& key_path = test_data_.non_empty_key_path(); 72 scoped_ptr<DeleteRegKeyWorkItem> item( 73 WorkItem::CreateDeleteRegKeyWorkItem(test_data_.root_key(), key_path)); 74 EXPECT_TRUE(item->Do()); 75 EXPECT_NE(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_path.c_str(), 76 KEY_READ)); 77 item->Rollback(); 78 item.reset(); 79 test_data_.ExpectMatchesNonEmptyKey(test_data_.root_key(), key_path.c_str()); 80 } 81 82 // Test that deleting a key with subkeys we can't delete fails, and that 83 // everything is there after rollback. 84 // Showing as flaky on windows. 85 // http://crbug.com/74654 86 TEST_F(DeleteRegKeyWorkItemTest, DISABLED_TestUndeletableKey) { 87 RegKey key; 88 std::wstring key_name(test_data_.base_path() + L"\\UndeletableKey"); 89 EXPECT_EQ(ERROR_SUCCESS, key.Create(test_data_.root_key(), key_name.c_str(), 90 KEY_WRITE)); 91 EXPECT_EQ(ERROR_SUCCESS, key.WriteValue(NULL, key_name.c_str())); 92 DWORD dw_value = 1; 93 RegKey subkey; 94 RegKey subkey2; 95 EXPECT_EQ(ERROR_SUCCESS, subkey.Create(key.Handle(), L"Subkey", 96 KEY_WRITE | WRITE_DAC)); 97 EXPECT_EQ(ERROR_SUCCESS, subkey.WriteValue(L"SomeValue", 1U)); 98 EXPECT_EQ(ERROR_SUCCESS, subkey2.Create(subkey.Handle(), L"Subkey2", 99 KEY_WRITE | WRITE_DAC)); 100 EXPECT_EQ(ERROR_SUCCESS, subkey2.WriteValue(L"", 2U)); 101 CSecurityDesc sec_desc; 102 sec_desc.FromString(L"D:PAI(A;OICI;KR;;;BU)"); // builtin users read 103 EXPECT_EQ(ERROR_SUCCESS, 104 RegSetKeySecurity(subkey.Handle(), DACL_SECURITY_INFORMATION, 105 const_cast<SECURITY_DESCRIPTOR*>( 106 sec_desc.GetPSECURITY_DESCRIPTOR()))); 107 sec_desc.FromString(L"D:PAI(A;OICI;KA;;;BU)"); // builtin users all access 108 EXPECT_EQ(ERROR_SUCCESS, 109 RegSetKeySecurity(subkey2.Handle(), DACL_SECURITY_INFORMATION, 110 const_cast<SECURITY_DESCRIPTOR*>( 111 sec_desc.GetPSECURITY_DESCRIPTOR()))); 112 subkey2.Close(); 113 subkey.Close(); 114 key.Close(); 115 scoped_ptr<DeleteRegKeyWorkItem> item( 116 WorkItem::CreateDeleteRegKeyWorkItem(test_data_.root_key(), key_name)); 117 EXPECT_FALSE(item->Do()); 118 EXPECT_EQ(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_name.c_str(), 119 KEY_QUERY_VALUE)); 120 item->Rollback(); 121 item.reset(); 122 EXPECT_EQ(ERROR_SUCCESS, key.Open(test_data_.root_key(), key_name.c_str(), 123 KEY_QUERY_VALUE)); 124 std::wstring str_value; 125 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(NULL, &str_value)); 126 EXPECT_EQ(key_name, str_value); 127 EXPECT_EQ(ERROR_SUCCESS, key.OpenKey(L"Subkey", KEY_READ | WRITE_DAC)); 128 dw_value = 0; 129 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"SomeValue", &dw_value)); 130 EXPECT_EQ(1U, dw_value); 131 // Give users all access to the subkey so it can be deleted. 132 EXPECT_EQ(ERROR_SUCCESS, 133 RegSetKeySecurity(key.Handle(), DACL_SECURITY_INFORMATION, 134 const_cast<SECURITY_DESCRIPTOR*>( 135 sec_desc.GetPSECURITY_DESCRIPTOR()))); 136 EXPECT_EQ(ERROR_SUCCESS, key.OpenKey(L"Subkey2", KEY_QUERY_VALUE)); 137 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"", &dw_value)); 138 EXPECT_EQ(2U, dw_value); 139 } 140