Registry.cpp (5950B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include "TestCommon.h" 5 #include <AppInstallerStrings.h> 6 #include <winget/Registry.h> 7 8 using namespace std::string_literals; 9 using namespace std::string_view_literals; 10 using namespace AppInstaller::Registry; 11 using namespace AppInstaller::Utility; 12 using namespace TestCommon; 13 14 TEST_CASE("EmptyKey", "[registry]") 15 { 16 Key key; 17 REQUIRE(!key); 18 } 19 20 TEST_CASE("Constructor_NotFound", "[registry]") 21 { 22 Key key; 23 REQUIRE_THROWS_HR(key = Key(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Foo\\Bar\\Does\\Not\\Exist"), HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); 24 } 25 26 TEST_CASE("OpenIfExists_NotFound", "[registry]") 27 { 28 Key key = Key::OpenIfExists(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Foo\\Bar\\Does\\Not\\Exist"); 29 REQUIRE(!key); 30 } 31 32 TEST_CASE("CreateKeyAndDelete", "[registry]") 33 { 34 std::wstring subkey = L"Foo\\Bar"; 35 wil::unique_hkey root = RegCreateVolatileTestRoot(); 36 Key key = Key::Create(root.get(), subkey, REG_OPTION_VOLATILE); 37 REQUIRE(key); 38 Key::Delete(root.get(), subkey, KEY_WOW64_64KEY); 39 Key secondKey = Key::OpenIfExists(root.get(), subkey); 40 REQUIRE(!secondKey); 41 } 42 43 TEST_CASE("SetKeyValue", "[registry]") 44 { 45 std::wstring valueName = L"TestValueName"; 46 std::wstring valueValue = L"TestValueValue"; 47 std::wstring subkey = L"FooBar"; 48 49 wil::unique_hkey root = RegCreateVolatileTestRoot(); 50 Key key = Key::Create(root.get(), subkey, REG_OPTION_VOLATILE); 51 key.SetValue(valueName, valueValue, REG_SZ); 52 auto value = key[valueName]; 53 REQUIRE(value); 54 REQUIRE(value->GetType() == Value::Type::String); 55 REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); 56 } 57 58 TEST_CASE("EnumerateKeys", "[registry]") 59 { 60 wil::unique_hkey root = RegCreateVolatileTestRoot(); 61 62 std::vector<std::wstring> subKeyNames = { L"A", L"BEE", L"SEE", L"deigh" }; 63 for (const auto& name : subKeyNames) 64 { 65 RegCreateVolatileSubKey(root.get(), name); 66 } 67 68 Key key{ root.get(), L"" }; 69 70 for (const auto& subkey : key) 71 { 72 INFO(subkey.Name()); 73 74 std::wstring nameUtf16 = ConvertToUTF16(subkey.Name()); 75 76 auto itr = std::find(subKeyNames.begin(), subKeyNames.end(), nameUtf16); 77 if (itr == subKeyNames.end()) 78 { 79 FAIL(); 80 } 81 else 82 { 83 subKeyNames.erase(itr); 84 } 85 86 Key sk = subkey.Open(); 87 REQUIRE(sk); 88 } 89 90 REQUIRE(subKeyNames.empty()); 91 } 92 93 TEST_CASE("Values_String", "[registry]") 94 { 95 std::wstring valueName = L"TestValueName"; 96 std::wstring valueValue = L"TestValueValue"; 97 98 wil::unique_hkey root = RegCreateVolatileTestRoot(); 99 SetRegistryValue(root.get(), valueName, valueValue); 100 101 Key key{ root.get(), L"" }; 102 103 auto value = key[valueName]; 104 REQUIRE(value); 105 REQUIRE(value->GetType() == Value::Type::String); 106 REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); 107 } 108 109 TEST_CASE("Values_WideStringWithNarrowNull", "[registry]") 110 { 111 std::wstring valueName = L"TestValueName"; 112 std::wstring valueValue = L"TestValueValue"; 113 114 wil::unique_hkey root = RegCreateVolatileTestRoot(); 115 116 // Copy the bytes from the string value into a byte vector 117 std::vector<BYTE> valueBytes; 118 valueBytes.resize((valueValue.length() + 1) * sizeof(wchar_t)); 119 memcpy_s(valueBytes.data(), valueBytes.size(), valueValue.c_str(), (valueValue.length() + 1) * sizeof(wchar_t)); 120 // Remove the last byte to make a narrow null 121 valueBytes.resize(valueBytes.size() - 1); 122 123 SetRegistryValue(root.get(), valueName, valueBytes, REG_SZ); 124 125 Key key{ root.get(), L"" }; 126 127 auto value = key[valueName]; 128 REQUIRE(value); 129 REQUIRE(value->GetType() == Value::Type::String); 130 REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); 131 } 132 133 TEST_CASE("Values_ExpandString", "[registry]") 134 { 135 std::wstring valueName = L"TestValueName"; 136 std::wstring valueValue = L"%TEMP%"; 137 138 wil::unique_hkey root = RegCreateVolatileTestRoot(); 139 SetRegistryValue(root.get(), valueName, valueValue, REG_EXPAND_SZ); 140 141 Key key{ root.get(), L"" }; 142 143 auto value = key[valueName]; 144 REQUIRE(value); 145 REQUIRE(value->GetType() == Value::Type::ExpandString); 146 REQUIRE(value->GetValue<Value::Type::String>() == ConvertToUTF8(valueValue)); 147 148 wchar_t buffer[MAX_PATH]; 149 GetTempPathW(ARRAYSIZE(buffer), buffer); 150 151 std::string tempPath = ConvertToUTF8(buffer); 152 if (!tempPath.empty() && tempPath.back() == '\\') 153 { 154 tempPath.resize(tempPath.size() - 1); 155 } 156 157 REQUIRE(value->GetValue<Value::Type::ExpandString>() == tempPath); 158 } 159 160 TEST_CASE("Values_Binary", "[registry]") 161 { 162 std::wstring valueName = L"TestValueName"; 163 std::vector<BYTE> valueValue = { 2, 7, 3, 14, 42 }; 164 165 wil::unique_hkey root = RegCreateVolatileTestRoot(); 166 SetRegistryValue(root.get(), valueName, valueValue); 167 168 Key key{ root.get(), L"" }; 169 170 auto value = key[valueName]; 171 REQUIRE(value); 172 REQUIRE(value->GetType() == Value::Type::Binary); 173 174 auto result = value->GetValue<Value::Type::Binary>(); 175 REQUIRE(result.size() == valueValue.size()); 176 for (size_t i = 0; i < result.size(); ++i) 177 { 178 INFO(i); 179 REQUIRE(result[i] == valueValue[i]); 180 } 181 } 182 183 TEST_CASE("Values_DWORD", "[registry]") 184 { 185 std::wstring valueName = L"TestValueName"; 186 DWORD valueValue = 42; 187 188 wil::unique_hkey root = RegCreateVolatileTestRoot(); 189 SetRegistryValue(root.get(), valueName, valueValue); 190 191 Key key{ root.get(), L"" }; 192 193 auto value = key[valueName]; 194 REQUIRE(value); 195 REQUIRE(value->GetType() == Value::Type::DWord); 196 REQUIRE(value->GetValue<Value::Type::DWord>() == valueValue); 197 }