[ADVAPI32] Handle HKCR in RegDeleteValueA+W and RegDeleteKeyValueW (#6033)
authorWhindmar Saksit <whindsaks@proton.me>
Sun, 24 Mar 2024 17:28:26 +0000 (18:28 +0100)
committerGitHub <noreply@github.com>
Sun, 24 Mar 2024 17:28:26 +0000 (18:28 +0100)
- HKCR delete handling; delete the value in HKCU if it exists there, otherwise delete it in HKLM.
- Changed RegDeleteKeyValueW to just use the regular Reg functions to get HKCR handling for free.

dll/win32/advapi32/reg/hkcr.c
dll/win32/advapi32/reg/reg.c
dll/win32/advapi32/reg/reg.h

index 59d5305..c1ccb6b 100644 (file)
@@ -17,6 +17,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
 static const UNICODE_STRING HKLM_ClassesPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Classes");
 
+static
+BOOL
+ValueExists(_In_ HKEY hNormalKey, _In_ PUNICODE_STRING Name)
+{
+    KEY_VALUE_PARTIAL_INFORMATION kvi;
+    ULONG total_size = sizeof(kvi);
+    NTSTATUS status;
+
+    ASSERT(!IsHKCRKey(hNormalKey));
+    status = NtQueryValueKey(hNormalKey, Name, KeyValuePartialInformation,
+                             &kvi, total_size, &total_size);
+    return status != STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
 static
 LONG
 GetKeyName(HKEY hKey, PUNICODE_STRING KeyName)
@@ -107,7 +121,10 @@ GetFallbackHKCRKey(
     /* Get the key name */
     ErrorCode = GetKeyName(hKey, &KeyName);
     if (ErrorCode != ERROR_SUCCESS)
+    {
+        *MachineKey = hKey;
         return ErrorCode;
+    }
 
     /* See if we really need a conversion */
     if (RtlPrefixUnicodeString(&HKLM_ClassesPath, &KeyName, TRUE))
@@ -133,6 +150,7 @@ GetFallbackHKCRKey(
     if (ErrorCode != ERROR_SUCCESS)
     {
         RtlFreeUnicodeString(&KeyName);
+        *MachineKey = hKey;
         return ErrorCode;
     }
 
@@ -180,7 +198,10 @@ GetPreferredHKCRKey(
     /* Get the key name */
     ErrorCode = GetKeyName(hKey, &KeyName);
     if (ErrorCode != ERROR_SUCCESS)
+    {
+        *PreferredKey = hKey;
         return ErrorCode;
+    }
 
     /* See if we really need a conversion */
     if (!RtlPrefixUnicodeString(&HKLM_ClassesPath, &KeyName, TRUE))
@@ -198,6 +219,7 @@ GetPreferredHKCRKey(
     if (ErrorCode != ERROR_SUCCESS)
     {
         RtlFreeUnicodeString(&KeyName);
+        *PreferredKey = hKey;
         return ErrorCode;
     }
 
@@ -476,6 +498,50 @@ DeleteHKCRKey(
     return ErrorCode;
 }
 
+/* HKCR version of RegDeleteValueA+W */
+LONG
+WINAPI
+DeleteHKCRValue(
+    _In_ HKEY hKey,
+    _In_ PUNICODE_STRING ValueName)
+{
+    HKEY hActualKey;
+    LONG ErrorCode;
+
+    ASSERT(IsHKCRKey(hKey));
+    /* Remove the HKCR flag while we're working */
+    hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
+
+    /* Does the HKCU key and value exist? */
+    ErrorCode = GetPreferredHKCRKey(hKey, &hActualKey);
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        if (!ValueExists(hActualKey, ValueName))
+        {
+            if (hActualKey != hKey)
+            {
+                RegCloseKey(hActualKey);
+            }
+            ErrorCode = ERROR_FILE_NOT_FOUND;
+        }
+    }
+    if (ErrorCode == ERROR_FILE_NOT_FOUND)
+    {
+        ErrorCode = GetFallbackHKCRKey(hKey, &hActualKey, FALSE);
+    }
+
+    if (ErrorCode == ERROR_SUCCESS)
+    {
+        NTSTATUS Status = NtDeleteValueKey(hActualKey, ValueName);
+        ErrorCode = NT_SUCCESS(Status) ? ERROR_SUCCESS : RtlNtStatusToDosError(Status);
+    }
+    if (hActualKey != hKey)
+    {
+        RegCloseKey(hActualKey);
+    }
+    return ErrorCode;
+}
+
 /* HKCR version of RegQueryValueExW */
 LONG
 WINAPI
index 38a434f..10c4756 100644 (file)
@@ -1362,62 +1362,24 @@ RegDeleteKeyValueW(IN HKEY hKey,
                    IN LPCWSTR lpSubKey  OPTIONAL,
                    IN LPCWSTR lpValueName  OPTIONAL)
 {
-    UNICODE_STRING ValueName;
-    HANDLE KeyHandle, CurKey, SubKeyHandle = NULL;
-    NTSTATUS Status;
-
-    Status = MapDefaultKey(&KeyHandle,
-                           hKey);
-    if (!NT_SUCCESS(Status))
-    {
-        return RtlNtStatusToDosError(Status);
-    }
+    HKEY hSubKey = hKey;
+    LONG ErrorCode;
 
-    if (lpSubKey != NULL)
+    if (lpSubKey)
     {
-        OBJECT_ATTRIBUTES ObjectAttributes;
-        UNICODE_STRING SubKeyName;
-
-        RtlInitUnicodeString(&SubKeyName, lpSubKey);
-
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   &SubKeyName,
-                                   OBJ_CASE_INSENSITIVE,
-                                   KeyHandle,
-                                   NULL);
-
-        Status = NtOpenKey(&SubKeyHandle,
-                           KEY_SET_VALUE,
-                           &ObjectAttributes);
-        if (!NT_SUCCESS(Status))
+        ErrorCode = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hSubKey);
+        if (ErrorCode)
         {
-            goto Cleanup;
+            return ErrorCode;
         }
-
-        CurKey = SubKeyHandle;
     }
-    else
-        CurKey = KeyHandle;
-
-    RtlInitUnicodeString(&ValueName, lpValueName);
+    ErrorCode = RegDeleteValueW(hSubKey, lpValueName);
 
-    Status = NtDeleteValueKey(CurKey,
-                              &ValueName);
-
-    if (SubKeyHandle != NULL)
+    if (hSubKey != hKey)
     {
-        NtClose(SubKeyHandle);
-    }
-
-Cleanup:
-    ClosePredefKey(KeyHandle);
-
-    if (!NT_SUCCESS(Status))
-    {
-        return RtlNtStatusToDosError(Status);
+        RegCloseKey(hSubKey);
     }
-
-    return ERROR_SUCCESS;
+    return ErrorCode;
 }
 
 
@@ -1449,7 +1411,7 @@ RegDeleteKeyValueA(IN HKEY hKey,
 
     Ret = RegDeleteKeyValueW(hKey,
                              SubKey.Buffer,
-                             SubKey.Buffer);
+                             ValueName.Buffer);
 
     RtlFreeUnicodeString(&SubKey);
     RtlFreeUnicodeString(&ValueName);
@@ -2328,6 +2290,7 @@ RegDeleteValueA(HKEY hKey,
     UNICODE_STRING ValueName;
     HANDLE KeyHandle;
     NTSTATUS Status;
+    LONG ErrorCode = ERROR_SUCCESS;
 
     Status = MapDefaultKey(&KeyHandle,
                            hKey);
@@ -2336,19 +2299,25 @@ RegDeleteValueA(HKEY hKey,
         return RtlNtStatusToDosError(Status);
     }
 
-    RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName);
-    Status = NtDeleteValueKey(KeyHandle,
-                              &ValueName);
-    RtlFreeUnicodeString (&ValueName);
-
-    ClosePredefKey(KeyHandle);
-
-    if (!NT_SUCCESS(Status))
+    if (!RtlCreateUnicodeStringFromAsciiz(&ValueName, lpValueName))
     {
-        return RtlNtStatusToDosError(Status);
+        ClosePredefKey(KeyHandle);
+        return ERROR_NOT_ENOUGH_MEMORY;
     }
 
-    return ERROR_SUCCESS;
+    if (IsHKCRKey(KeyHandle))
+    {
+        ErrorCode = DeleteHKCRValue(KeyHandle, &ValueName);
+    }
+    else
+    {
+        Status = NtDeleteValueKey(KeyHandle, &ValueName);
+        if (!NT_SUCCESS(Status))
+            ErrorCode = RtlNtStatusToDosError(Status);
+    }
+    RtlFreeUnicodeString(&ValueName);
+    ClosePredefKey(KeyHandle);
+    return ErrorCode;
 }
 
 
@@ -2364,6 +2333,7 @@ RegDeleteValueW(HKEY hKey,
     UNICODE_STRING ValueName;
     NTSTATUS Status;
     HANDLE KeyHandle;
+    LONG ErrorCode = ERROR_SUCCESS;
 
     Status = MapDefaultKey(&KeyHandle,
                            hKey);
@@ -2374,17 +2344,18 @@ RegDeleteValueW(HKEY hKey,
 
     RtlInitUnicodeString(&ValueName, lpValueName);
 
-    Status = NtDeleteValueKey(KeyHandle,
-                              &ValueName);
-
-    ClosePredefKey(KeyHandle);
-
-    if (!NT_SUCCESS(Status))
+    if (IsHKCRKey(KeyHandle))
     {
-        return RtlNtStatusToDosError(Status);
+        ErrorCode = DeleteHKCRValue(KeyHandle, &ValueName);
     }
-
-    return ERROR_SUCCESS;
+    else
+    {
+        Status = NtDeleteValueKey(KeyHandle, &ValueName);
+        if (!NT_SUCCESS(Status))
+            ErrorCode = RtlNtStatusToDosError(Status);
+    }
+    ClosePredefKey(KeyHandle);
+    return ErrorCode;
 }
 
 
index 469f2b6..46a10dc 100644 (file)
@@ -52,6 +52,12 @@ DeleteHKCRKey(
     _In_ REGSAM RegSam,
     _In_ DWORD Reserved);
 
+LONG
+WINAPI
+DeleteHKCRValue(
+    _In_ HKEY hKey,
+    _In_ PUNICODE_STRING ValueName);
+
 LONG
 WINAPI
 QueryHKCRValue(