1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Tests for RegCreateKeyExW. 5 * COPYRIGHT: Copyright 2023 Doug Lyons <douglyons@douglyons.com> 6 */ 7 8 /* 9 * Idea based loosely on code from the following: 10 * https://learn.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c-- 11 */ 12 13 #include <apitest.h> 14 #include <stdio.h> 15 16 #define WIN32_NO_STATUS 17 #define _INC_WINDOWS 18 #define COM_NO_WINDOWS_H 19 #include <windef.h> 20 #include <aclapi.h> 21 22 23 START_TEST(RegCreateKeyEx) 24 { 25 HKEY hkey_main; 26 DWORD dwRes, dwDisposition; 27 PACL pACL = NULL; 28 PSECURITY_DESCRIPTOR pSD = NULL; 29 PSID pEveryoneSID = NULL, pAdminSID = NULL; 30 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = {SECURITY_WORLD_SID_AUTHORITY}; 31 SID_IDENTIFIER_AUTHORITY SIDAuthNT = {SECURITY_NT_AUTHORITY}; 32 EXPLICIT_ACCESSW ea[2]; 33 SECURITY_ATTRIBUTES sa = { 0 }; 34 LONG lRes; 35 BOOL bRes; 36 LONG ErrorCode = 0; 37 HKEY hkSub = NULL; 38 39 // If any of the test keys already exist, delete them to ensure proper testing 40 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) 41 { 42 RegCloseKey(hkey_main); 43 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey"); 44 ok_dec(ErrorCode, ERROR_SUCCESS); 45 if (ErrorCode != ERROR_SUCCESS) 46 { 47 skip("'HKCU\\mykey' cannot be deleted. Terminating test\n"); 48 goto Cleanup; 49 } 50 } 51 52 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey1", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) 53 { 54 RegCloseKey(hkey_main); 55 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey1"); 56 ok_dec(ErrorCode, ERROR_SUCCESS); 57 if (ErrorCode != ERROR_SUCCESS) 58 { 59 skip("'HKCU\\mykey1' cannot be deleted. Terminating test\n"); 60 goto Cleanup; 61 } 62 } 63 64 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey2", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) 65 { 66 RegCloseKey(hkey_main); 67 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey2"); 68 ok_dec(ErrorCode, ERROR_SUCCESS); 69 if (ErrorCode != ERROR_SUCCESS) 70 { 71 skip("'HKCU\\mykey2' cannot be deleted. Terminating test\n"); 72 goto Cleanup; 73 } 74 } 75 76 // Setup GetLastError to known value for tests 77 SetLastError(0xdeadbeef); 78 79 // Create a well-known SID for the Everyone group. 80 bRes = AllocateAndInitializeSid(&SIDAuthWorld, 1, 81 SECURITY_WORLD_RID, 82 0, 0, 0, 0, 0, 0, 0, 83 &pEveryoneSID); 84 ok(bRes, "AllocateAndInitializeSid Error %ld\n", GetLastError()); 85 if (!bRes) 86 { 87 skip("EveryoneSID not initialized. Terminating test\n"); 88 goto Cleanup; 89 } 90 91 // Initialize an EXPLICIT_ACCESS structure for an ACE. 92 // The ACE will allow Everyone read access to the key. 93 ZeroMemory(&ea, sizeof(ea)); 94 ea[0].grfAccessPermissions = KEY_READ; 95 ea[0].grfAccessMode = SET_ACCESS; 96 ea[0].grfInheritance= NO_INHERITANCE; 97 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; 98 ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 99 ea[0].Trustee.ptstrName = pEveryoneSID; 100 101 // Create a SID for the BUILTIN\Administrators group. 102 bRes = AllocateAndInitializeSid(&SIDAuthNT, 2, 103 SECURITY_BUILTIN_DOMAIN_RID, 104 DOMAIN_ALIAS_RID_ADMINS, 105 0, 0, 0, 0, 0, 0, 106 &pAdminSID); 107 ok(bRes, "AllocateAndInitializeSid Error %ld\n", GetLastError()); 108 if (!bRes) 109 { 110 skip("AdminSID not initialized. Terminating test\n"); 111 goto Cleanup; 112 } 113 114 // Initialize an EXPLICIT_ACCESS structure for an ACE. 115 // The ACE will allow the Administrators group full access to the key. 116 ea[1].grfAccessPermissions = KEY_ALL_ACCESS; 117 ea[1].grfAccessMode = SET_ACCESS; 118 ea[1].grfInheritance= NO_INHERITANCE; 119 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; 120 ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; 121 ea[1].Trustee.ptstrName = pAdminSID; 122 123 // Create a new ACL that contains the new ACEs. 124 dwRes = SetEntriesInAclW(_countof(ea), ea, NULL, &pACL); 125 ok(dwRes == ERROR_SUCCESS, "SetEntriesInAcl Error %ld\n", GetLastError()); 126 if (dwRes != ERROR_SUCCESS) 127 goto Cleanup; 128 129 // Initialize a security descriptor. 130 pSD = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); 131 ok(pSD != NULL, "LocalAlloc Error %ld\n", GetLastError()); 132 if (pSD == NULL) 133 goto Cleanup; 134 135 bRes = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); 136 ok(bRes, "InitializeSecurityDescriptor Error %ld\n", GetLastError()); 137 if (!bRes) 138 goto Cleanup; 139 140 // Add the ACL to the security descriptor. 141 bRes = SetSecurityDescriptorDacl(pSD, 142 TRUE, // bDaclPresent flag 143 pACL, 144 FALSE); // not a default DACL 145 ok(bRes, "SetSecurityDescriptorDacl Error %ld\n", GetLastError()); 146 if (!bRes) 147 goto Cleanup; 148 149 // Initialize a security attributes structure. 150 sa.lpSecurityDescriptor = pSD; 151 sa.bInheritHandle = FALSE; 152 153 // Use the security attributes to set the security descriptor 154 // with an nlength that is 0. 155 sa.nLength = 0; 156 lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey", 0, L"", 0, 157 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 158 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); 159 ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); 160 if (dwDisposition != REG_CREATED_NEW_KEY) 161 goto Cleanup; 162 163 // Test the -A function 164 lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey", 0, "", 0, 165 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 166 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); 167 ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); 168 if (dwDisposition != REG_OPENED_EXISTING_KEY) 169 goto Cleanup; 170 171 // Use the security attributes to set the security descriptor 172 // with an nlength that is too short, but not 0. 173 sa.nLength = sizeof(SECURITY_ATTRIBUTES) / 2; 174 lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey1", 0, L"", 0, 175 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 176 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); 177 ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); 178 if (dwDisposition != REG_CREATED_NEW_KEY) 179 goto Cleanup; 180 181 // Test the -A function 182 lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey1", 0, "", 0, 183 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 184 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); 185 ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); 186 if (dwDisposition != REG_OPENED_EXISTING_KEY) 187 goto Cleanup; 188 189 // Use the security attributes to set the security descriptor 190 // with an nlength that is too long. 191 sa.nLength = sizeof(SECURITY_ATTRIBUTES) + 10; 192 lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey2", 0, L"", 0, 193 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 194 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); 195 ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); 196 if (dwDisposition != REG_CREATED_NEW_KEY) 197 goto Cleanup; 198 199 // Test the -A function 200 lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey2", 0, "", 0, 201 KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 202 ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); 203 ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); 204 if (dwDisposition != REG_OPENED_EXISTING_KEY) 205 goto Cleanup; 206 207 Cleanup: 208 209 if (pEveryoneSID) 210 FreeSid(pEveryoneSID); 211 if (pAdminSID) 212 FreeSid(pAdminSID); 213 if (pACL) 214 LocalFree(pACL); 215 if (pSD) 216 LocalFree(pSD); 217 if (hkSub) 218 RegCloseKey(hkSub); 219 220 // Delete the subkeys created for testing 221 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey"); 222 ok_dec(ErrorCode, ERROR_SUCCESS); 223 224 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey1"); 225 ok_dec(ErrorCode, ERROR_SUCCESS); 226 227 ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey2"); 228 ok_dec(ErrorCode, ERROR_SUCCESS); 229 } 230 231