https://git.reactos.org/?p=reactos.git;a=commitdiff;h=40233a364435882d9c361…
commit 40233a364435882d9c361b9065c0ab2dc5380157
Author:     Doug Lyons <douglyons(a)douglyons.com>
AuthorDate: Thu Jun 29 14:33:44 2023 -0500
Commit:     GitHub <noreply(a)github.com>
CommitDate: Thu Jun 29 21:33:44 2023 +0200
    [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
---
 modules/rostests/apitests/advapi32/CMakeLists.txt  |   1 +
 .../rostests/apitests/advapi32/RegCreateKeyEx.c    | 230 +++++++++++++++++++++
 modules/rostests/apitests/advapi32/testlist.c      |   2 +
 3 files changed, 233 insertions(+)
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 <douglyons(a)douglyons.com>
+ */
+
+/*
+ * Idea based loosely on code from the following:
+ *
https://learn.microsoft.com/en-us/windows/win32/secauthz/creating-a-securit…
+ */
+
+#include <apitest.h>
+#include <stdio.h>
+
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#include <windef.h>
+#include <aclapi.h>
+
+
+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 },