[ADVAPI32]

- Add implementation of RegCreateKeyEx and RegSetValueEx for HKCR subkeys
CORE-8582

svn path=/trunk/; revision=64444
This commit is contained in:
Jérôme Gardou 2014-10-01 17:48:32 +00:00
parent b0408707b8
commit e854412f52
3 changed files with 277 additions and 39 deletions

View file

@ -96,7 +96,8 @@ static
LONG
GetFallbackHKCRKey(
_In_ HKEY hKey,
_Out_ HKEY* MachineKey)
_Out_ HKEY* MachineKey,
_In_ BOOL MustCreate)
{
UNICODE_STRING KeyName;
LPWSTR SubKeyName;
@ -135,13 +136,29 @@ GetFallbackHKCRKey(
return ErrorCode;
}
/* Open the key. */
ErrorCode = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
SubKeyName,
0,
SamDesired,
MachineKey);
if (MustCreate)
{
ErrorCode = RegCreateKeyExW(
HKEY_LOCAL_MACHINE,
SubKeyName,
0,
NULL,
0,
SamDesired,
NULL,
MachineKey,
NULL);
}
else
{
/* Open the key. */
ErrorCode = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
SubKeyName,
0,
SamDesired,
MachineKey);
}
RtlFreeUnicodeString(&KeyName);
@ -197,6 +214,110 @@ GetPreferredHKCRKey(
return ErrorCode;
}
/* HKCR version of RegCreateKeyExW. */
LONG
WINAPI
CreateHKCRKey(
_In_ HKEY hKey,
_In_ LPCWSTR lpSubKey,
_In_ DWORD Reserved,
_In_opt_ LPWSTR lpClass,
_In_ DWORD dwOptions,
_In_ REGSAM samDesired,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_Out_ PHKEY phkResult,
_Out_opt_ LPDWORD lpdwDisposition)
{
LONG ErrorCode;
HKEY QueriedKey, TestKey;
ASSERT(IsHKCRKey(hKey));
/* Remove the HKCR flag while we're working */
hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
if (ErrorCode == ERROR_FILE_NOT_FOUND)
{
/* The current key doesn't exist on HKCU side, so we can only create it in HKLM */
ErrorCode = RegCreateKeyExW(
hKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition);
if (ErrorCode == ERROR_SUCCESS)
MakeHKCRKey(phkResult);
return ErrorCode;
}
if (ErrorCode != ERROR_SUCCESS)
{
/* Somehow we failed for another reason (maybe deleted key or whatever) */
return ErrorCode;
}
/* See if the subkey already exists in HKCU. */
ErrorCode = RegOpenKeyExW(QueriedKey, lpSubKey, 0, KEY_READ, &TestKey);
if (ErrorCode != ERROR_FILE_NOT_FOUND)
{
if (ErrorCode == ERROR_SUCCESS)
{
/* Great. Close the test one and do the real create operation */
RegCloseKey(TestKey);
ErrorCode = RegCreateKeyExW(
QueriedKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition);
if (ErrorCode == ERROR_SUCCESS)
MakeHKCRKey(phkResult);
}
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
return ERROR_SUCCESS;
}
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
/* So we must do the create operation in HKLM, creating the missing parent keys if needed. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, TRUE);
if (ErrorCode != ERROR_SUCCESS)
return ErrorCode;
/* Do the key creation */
ErrorCode = RegCreateKeyEx(
QueriedKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition);
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
if (ErrorCode == ERROR_SUCCESS)
MakeHKCRKey(phkResult);
return ErrorCode;
}
/* Same as RegOpenKeyExW, but for HKEY_CLASSES_ROOT subkeys */
LONG
WINAPI
@ -248,7 +369,7 @@ OpenHKCRKey(
return ErrorCode;
/* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey);
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS)
{
/* Maybe the key doesn't exist in the HKLM view */
@ -313,7 +434,7 @@ DeleteHKCRKey(
return ErrorCode;
/* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey);
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS)
{
/* Maybe the key doesn't exist in the HKLM view */
@ -378,7 +499,7 @@ QueryHKCRValue(
return ErrorCode;
/* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey);
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS)
{
/* Maybe the key doesn't exist in the HKLM view */
@ -395,3 +516,72 @@ QueryHKCRValue(
return ErrorCode;
}
/* HKCR version of RegSetValueExW */
LONG
WINAPI
SetHKCRValue(
_In_ HKEY hKey,
_In_ LPCWSTR Name,
_In_ DWORD Reserved,
_In_ DWORD Type,
_In_ CONST BYTE* Data,
_In_ DWORD DataSize)
{
HKEY QueriedKey;
LONG ErrorCode;
ASSERT(IsHKCRKey(hKey));
/* Remove the HKCR flag while we're working */
hKey = (HKEY)(((ULONG_PTR)hKey) & ~0x2);
ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
if (ErrorCode == ERROR_FILE_NOT_FOUND)
{
/* The key doesn't exist on HKCU side, no chance to put a value in it */
return RegSetValueExW(hKey, Name, Reserved, Type, Data, DataSize);
}
if (ErrorCode != ERROR_SUCCESS)
{
/* Somehow we failed for another reason (maybe deleted key or whatever) */
return ErrorCode;
}
/* Check if the value already exists in the preferred key */
ErrorCode = RegQueryValueExW(QueriedKey, Name, NULL, NULL, NULL, NULL);
if (ErrorCode != ERROR_FILE_NOT_FOUND)
{
if (ErrorCode == ERROR_SUCCESS)
{
/* Yes, so we have the right to modify it */
ErrorCode = RegSetValueExW(QueriedKey, Name, Reserved, Type, Data, DataSize);
}
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
return ErrorCode;
}
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
/* So we must set the value in the HKLM version */
ErrorCode = GetPreferredHKCRKey(hKey, &QueriedKey);
if (ErrorCode == ERROR_FILE_NOT_FOUND)
{
/* No choice: put this in HKCU */
return RegSetValueExW(hKey, Name, Reserved, Type, Data, DataSize);
}
else if (ErrorCode != ERROR_SUCCESS)
{
return ErrorCode;
}
ErrorCode = RegSetValueExW(QueriedKey, Name, Reserved, Type, Data, DataSize);
if (QueriedKey != hKey)
RegCloseKey(QueriedKey);
return ErrorCode;
}

View file

@ -1084,16 +1084,18 @@ Exit:
*
* @implemented
*/
LONG WINAPI
RegCreateKeyExW(HKEY hKey,
LPCWSTR lpSubKey,
DWORD Reserved,
LPWSTR lpClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
LPDWORD lpdwDisposition)
LONG
WINAPI
RegCreateKeyExW(
_In_ HKEY hKey,
_In_ LPCWSTR lpSubKey,
_In_ DWORD Reserved,
_In_opt_ LPWSTR lpClass,
_In_ DWORD dwOptions,
_In_ REGSAM samDesired,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_Out_ PHKEY phkResult,
_Out_opt_ LPDWORD lpdwDisposition)
{
UNICODE_STRING SubKeyString;
UNICODE_STRING ClassString;
@ -1117,6 +1119,22 @@ RegCreateKeyExW(HKEY hKey,
TRACE("ParentKey %p\n", ParentKey);
if (IsHKCRKey(ParentKey))
{
LONG ErrorCode = CreateHKCRKey(
ParentKey,
lpSubKey,
Reserved,
lpClass,
dwOptions,
samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition);
ClosePredefKey(ParentKey);
return ErrorCode;
}
if (dwOptions & REG_OPTION_OPEN_LINK)
Attributes |= OBJ_OPENLINK;
@ -1144,9 +1162,6 @@ RegCreateKeyExW(HKEY hKey,
return RtlNtStatusToDosError(Status);
}
if (IsHKCRKey(ParentKey))
MakeHKCRKey(phkResult);
return ERROR_SUCCESS;
}
@ -4851,18 +4866,34 @@ RegSetValueExA(HKEY hKey,
*
* @implemented
*/
LONG WINAPI
RegSetValueExW(HKEY hKey,
LPCWSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData)
LONG
WINAPI
RegSetValueExW(
_In_ HKEY hKey,
_In_ LPCWSTR lpValueName,
_In_ DWORD Reserved,
_In_ DWORD dwType,
_In_ CONST BYTE* lpData,
_In_ DWORD cbData)
{
UNICODE_STRING ValueName;
HANDLE KeyHandle;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
if (IsHKCRKey(KeyHandle))
{
LONG ErrorCode = SetHKCRValue(KeyHandle, lpValueName, Reserved, dwType, lpData, cbData);
ClosePredefKey(KeyHandle);
return ErrorCode;
}
if (is_string(dwType) && (cbData != 0))
{
PWSTR pwsData = (PWSTR)lpData;
@ -4878,18 +4909,12 @@ RegSetValueExW(HKEY hKey,
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return ERROR_NOACCESS);
ClosePredefKey(KeyHandle);
return ERROR_NOACCESS;
}
_SEH2_END;
}
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
RtlInitUnicodeString(&ValueName, lpValueName);
Status = NtSetValueKey(KeyHandle,

View file

@ -22,6 +22,19 @@ MakeHKCRKey(_Inout_ HKEY* hKey)
*hKey = (HKEY)((ULONG_PTR)(*hKey) | 0x2);
}
LONG
WINAPI
CreateHKCRKey(
_In_ HKEY hKey,
_In_ LPCWSTR lpSubKey,
_In_ DWORD Reserved,
_In_opt_ LPWSTR lpClass,
_In_ DWORD dwOptions,
_In_ REGSAM samDesired,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_Out_ PHKEY phkResult,
_Out_opt_ LPDWORD lpdwDisposition);
LONG
WINAPI
OpenHKCRKey(
@ -49,3 +62,13 @@ QueryHKCRValue(
_In_ LPBYTE Data,
_In_ LPDWORD Count);
LONG
WINAPI
SetHKCRValue(
_In_ HKEY hKey,
_In_ LPCWSTR Name,
_In_ DWORD Reserved,
_In_ DWORD Type,
_In_ CONST BYTE* Data,
_In_ DWORD DataSize);