From 40233a364435882d9c361b9065c0ab2dc5380157 Mon Sep 17 00:00:00 2001 From: Doug Lyons Date: Thu, 29 Jun 2023 14:33:44 -0500 Subject: [PATCH] [ADVAPI32_APITEST] Add new RegCreateKeyEx tests (#5234) * [ADVAPI32_APITEST] Add new RegCreateKeyEx tests * Remove trailing spaces. * Initialize SECURITY_ATTRIBUTES sa with zeroes. Add a set of tests for RegCreateKeyExW and -A. Created to prove the correctness of the already merged PR (#5230) JIRA issue: CORE-15471 --- .../rostests/apitests/advapi32/CMakeLists.txt | 1 + .../apitests/advapi32/RegCreateKeyEx.c | 230 ++++++++++++++++++ modules/rostests/apitests/advapi32/testlist.c | 2 + 3 files changed, 233 insertions(+) create mode 100644 modules/rostests/apitests/advapi32/RegCreateKeyEx.c diff --git a/modules/rostests/apitests/advapi32/CMakeLists.txt b/modules/rostests/apitests/advapi32/CMakeLists.txt index c5bccc3b0d0..8a9bab7abd6 100644 --- a/modules/rostests/apitests/advapi32/CMakeLists.txt +++ b/modules/rostests/apitests/advapi32/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND SOURCE IsTextUnicode.c LockServiceDatabase.c QueryServiceConfig2.c + RegCreateKeyEx.c RegEnumKey.c RegEnumValueW.c RegOpenKeyExW.c diff --git a/modules/rostests/apitests/advapi32/RegCreateKeyEx.c b/modules/rostests/apitests/advapi32/RegCreateKeyEx.c new file mode 100644 index 00000000000..18ffd88c779 --- /dev/null +++ b/modules/rostests/apitests/advapi32/RegCreateKeyEx.c @@ -0,0 +1,230 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Tests for RegCreateKeyExW. + * COPYRIGHT: Copyright 2023 Doug Lyons + */ + +/* + * Idea based loosely on code from the following: + * https://learn.microsoft.com/en-us/windows/win32/secauthz/creating-a-security-descriptor-for-a-new-object-in-c-- + */ + +#include +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#include +#include + + +START_TEST(RegCreateKeyEx) +{ + HKEY hkey_main; + DWORD dwRes, dwDisposition; + PACL pACL = NULL; + PSECURITY_DESCRIPTOR pSD = NULL; + PSID pEveryoneSID = NULL, pAdminSID = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = {SECURITY_WORLD_SID_AUTHORITY}; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = {SECURITY_NT_AUTHORITY}; + EXPLICIT_ACCESSW ea[2]; + SECURITY_ATTRIBUTES sa = { 0 }; + LONG lRes; + BOOL bRes; + LONG ErrorCode = 0; + HKEY hkSub = NULL; + + // If any of the test keys already exist, delete them to ensure proper testing + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) + { + RegCloseKey(hkey_main); + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey"); + ok_dec(ErrorCode, ERROR_SUCCESS); + if (ErrorCode != ERROR_SUCCESS) + { + skip("'HKCU\\mykey' cannot be deleted. Terminating test\n"); + goto Cleanup; + } + } + + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey1", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) + { + RegCloseKey(hkey_main); + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey1"); + ok_dec(ErrorCode, ERROR_SUCCESS); + if (ErrorCode != ERROR_SUCCESS) + { + skip("'HKCU\\mykey1' cannot be deleted. Terminating test\n"); + goto Cleanup; + } + } + + if (RegOpenKeyExW(HKEY_CURRENT_USER, L"mykey2", 0, KEY_ALL_ACCESS, &hkey_main) == ERROR_SUCCESS) + { + RegCloseKey(hkey_main); + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey2"); + ok_dec(ErrorCode, ERROR_SUCCESS); + if (ErrorCode != ERROR_SUCCESS) + { + skip("'HKCU\\mykey2' cannot be deleted. Terminating test\n"); + goto Cleanup; + } + } + + // Setup GetLastError to known value for tests + SetLastError(0xdeadbeef); + + // Create a well-known SID for the Everyone group. + bRes = AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID); + ok(bRes, "AllocateAndInitializeSid Error %ld\n", GetLastError()); + if (!bRes) + { + skip("EveryoneSID not initialized. Terminating test\n"); + goto Cleanup; + } + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow Everyone read access to the key. + ZeroMemory(&ea, sizeof(ea)); + ea[0].grfAccessPermissions = KEY_READ; + ea[0].grfAccessMode = SET_ACCESS; + ea[0].grfInheritance= NO_INHERITANCE; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea[0].Trustee.ptstrName = pEveryoneSID; + + // Create a SID for the BUILTIN\Administrators group. + bRes = AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSID); + ok(bRes, "AllocateAndInitializeSid Error %ld\n", GetLastError()); + if (!bRes) + { + skip("AdminSID not initialized. Terminating test\n"); + goto Cleanup; + } + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow the Administrators group full access to the key. + ea[1].grfAccessPermissions = KEY_ALL_ACCESS; + ea[1].grfAccessMode = SET_ACCESS; + ea[1].grfInheritance= NO_INHERITANCE; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = pAdminSID; + + // Create a new ACL that contains the new ACEs. + dwRes = SetEntriesInAclW(_countof(ea), ea, NULL, &pACL); + ok(dwRes == ERROR_SUCCESS, "SetEntriesInAcl Error %ld\n", GetLastError()); + if (dwRes != ERROR_SUCCESS) + goto Cleanup; + + // Initialize a security descriptor. + pSD = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + ok(pSD != NULL, "LocalAlloc Error %ld\n", GetLastError()); + if (pSD == NULL) + goto Cleanup; + + bRes = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); + ok(bRes, "InitializeSecurityDescriptor Error %ld\n", GetLastError()); + if (!bRes) + goto Cleanup; + + // Add the ACL to the security descriptor. + bRes = SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE); // not a default DACL + ok(bRes, "SetSecurityDescriptorDacl Error %ld\n", GetLastError()); + if (!bRes) + goto Cleanup; + + // Initialize a security attributes structure. + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + + // Use the security attributes to set the security descriptor + // with an nlength that is 0. + sa.nLength = 0; + lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey", 0, L"", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); + if (dwDisposition != REG_CREATED_NEW_KEY) + goto Cleanup; + + // Test the -A function + lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey", 0, "", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); + if (dwDisposition != REG_OPENED_EXISTING_KEY) + goto Cleanup; + + // Use the security attributes to set the security descriptor + // with an nlength that is too short, but not 0. + sa.nLength = sizeof(SECURITY_ATTRIBUTES) / 2; + lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey1", 0, L"", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); + if (dwDisposition != REG_CREATED_NEW_KEY) + goto Cleanup; + + // Test the -A function + lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey1", 0, "", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); + if (dwDisposition != REG_OPENED_EXISTING_KEY) + goto Cleanup; + + // Use the security attributes to set the security descriptor + // with an nlength that is too long. + sa.nLength = sizeof(SECURITY_ATTRIBUTES) + 10; + lRes = RegCreateKeyExW(HKEY_CURRENT_USER, L"mykey2", 0, L"", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExW returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_CREATED_NEW_KEY, "Should have created NEW key\n"); + if (dwDisposition != REG_CREATED_NEW_KEY) + goto Cleanup; + + // Test the -A function + lRes = RegCreateKeyExA(HKEY_CURRENT_USER, "mykey2", 0, "", 0, + KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); + ok(lRes == ERROR_SUCCESS, "RegCreateKeyExA returned '%ld', expected 0", lRes); + ok(dwDisposition == REG_OPENED_EXISTING_KEY, "Should have opened EXISTING key\n"); + if (dwDisposition != REG_OPENED_EXISTING_KEY) + goto Cleanup; + +Cleanup: + + if (pEveryoneSID) + FreeSid(pEveryoneSID); + if (pAdminSID) + FreeSid(pAdminSID); + if (pACL) + LocalFree(pACL); + if (pSD) + LocalFree(pSD); + if (hkSub) + RegCloseKey(hkSub); + + // Delete the subkeys created for testing + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey"); + ok_dec(ErrorCode, ERROR_SUCCESS); + + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey1"); + ok_dec(ErrorCode, ERROR_SUCCESS); + + ErrorCode = RegDeleteKeyW(HKEY_CURRENT_USER, L"mykey2"); + ok_dec(ErrorCode, ERROR_SUCCESS); +} + diff --git a/modules/rostests/apitests/advapi32/testlist.c b/modules/rostests/apitests/advapi32/testlist.c index dadd2f6ac18..67764a03204 100644 --- a/modules/rostests/apitests/advapi32/testlist.c +++ b/modules/rostests/apitests/advapi32/testlist.c @@ -10,6 +10,7 @@ extern void func_HKEY_CLASSES_ROOT(void); extern void func_IsTextUnicode(void); extern void func_LockServiceDatabase(void); extern void func_QueryServiceConfig2(void); +extern void func_RegCreateKeyEx(void); extern void func_RegEnumKey(void); extern void func_RegEnumValueW(void); extern void func_RegOpenKeyExW(void); @@ -30,6 +31,7 @@ const struct test winetest_testlist[] = { "IsTextUnicode" , func_IsTextUnicode }, { "LockServiceDatabase" , func_LockServiceDatabase }, { "QueryServiceConfig2", func_QueryServiceConfig2 }, + { "RegCreateKeyEx", func_RegCreateKeyEx }, { "RegEnumKey", func_RegEnumKey }, { "RegEnumValueW", func_RegEnumValueW }, { "RegQueryInfoKey", func_RegQueryInfoKey },