From 2449ed5d85cf4fb04d12a394fc43741c8137580b Mon Sep 17 00:00:00 2001 From: Whindmar Saksit Date: Sun, 24 Mar 2024 18:28:26 +0100 Subject: [PATCH] [ADVAPI32] Handle HKCR in RegDeleteValueA+W and RegDeleteKeyValueW (#6033) - 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 | 66 +++++++++++++++++++++ dll/win32/advapi32/reg/reg.c | 107 +++++++++++++--------------------- dll/win32/advapi32/reg/reg.h | 6 ++ 3 files changed, 111 insertions(+), 68 deletions(-) diff --git a/dll/win32/advapi32/reg/hkcr.c b/dll/win32/advapi32/reg/hkcr.c index 59d53052879..c1ccb6ba4de 100644 --- a/dll/win32/advapi32/reg/hkcr.c +++ b/dll/win32/advapi32/reg/hkcr.c @@ -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 diff --git a/dll/win32/advapi32/reg/reg.c b/dll/win32/advapi32/reg/reg.c index 38a434fddd7..10c4756928e 100644 --- a/dll/win32/advapi32/reg/reg.c +++ b/dll/win32/advapi32/reg/reg.c @@ -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; + HKEY hSubKey = hKey; + LONG ErrorCode; - Status = MapDefaultKey(&KeyHandle, - hKey); - if (!NT_SUCCESS(Status)) + if (lpSubKey) { - return RtlNtStatusToDosError(Status); - } - - if (lpSubKey != NULL) - { - 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; + ErrorCode = RegDeleteValueW(hSubKey, lpValueName); - RtlInitUnicodeString(&ValueName, lpValueName); - - Status = NtDeleteValueKey(CurKey, - &ValueName); - - if (SubKeyHandle != NULL) + if (hSubKey != hKey) { - NtClose(SubKeyHandle); + RegCloseKey(hSubKey); } - -Cleanup: - ClosePredefKey(KeyHandle); - - if (!NT_SUCCESS(Status)) - { - return RtlNtStatusToDosError(Status); - } - - 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; } diff --git a/dll/win32/advapi32/reg/reg.h b/dll/win32/advapi32/reg/reg.h index 469f2b6fbcd..46a10dc969f 100644 --- a/dll/win32/advapi32/reg/reg.h +++ b/dll/win32/advapi32/reg/reg.h @@ -52,6 +52,12 @@ DeleteHKCRKey( _In_ REGSAM RegSam, _In_ DWORD Reserved); +LONG +WINAPI +DeleteHKCRValue( + _In_ HKEY hKey, + _In_ PUNICODE_STRING ValueName); + LONG WINAPI QueryHKCRValue(