[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 LONG
GetFallbackHKCRKey( GetFallbackHKCRKey(
_In_ HKEY hKey, _In_ HKEY hKey,
_Out_ HKEY* MachineKey) _Out_ HKEY* MachineKey,
_In_ BOOL MustCreate)
{ {
UNICODE_STRING KeyName; UNICODE_STRING KeyName;
LPWSTR SubKeyName; LPWSTR SubKeyName;
@ -135,13 +136,29 @@ GetFallbackHKCRKey(
return ErrorCode; return ErrorCode;
} }
/* Open the key. */ if (MustCreate)
ErrorCode = RegOpenKeyExW( {
HKEY_LOCAL_MACHINE, ErrorCode = RegCreateKeyExW(
SubKeyName, HKEY_LOCAL_MACHINE,
0, SubKeyName,
SamDesired, 0,
MachineKey); NULL,
0,
SamDesired,
NULL,
MachineKey,
NULL);
}
else
{
/* Open the key. */
ErrorCode = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
SubKeyName,
0,
SamDesired,
MachineKey);
}
RtlFreeUnicodeString(&KeyName); RtlFreeUnicodeString(&KeyName);
@ -197,6 +214,110 @@ GetPreferredHKCRKey(
return ErrorCode; 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 */ /* Same as RegOpenKeyExW, but for HKEY_CLASSES_ROOT subkeys */
LONG LONG
WINAPI WINAPI
@ -248,7 +369,7 @@ OpenHKCRKey(
return ErrorCode; return ErrorCode;
/* If we're here, we must open from HKLM key. */ /* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey); ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS) if (ErrorCode != ERROR_SUCCESS)
{ {
/* Maybe the key doesn't exist in the HKLM view */ /* Maybe the key doesn't exist in the HKLM view */
@ -313,7 +434,7 @@ DeleteHKCRKey(
return ErrorCode; return ErrorCode;
/* If we're here, we must open from HKLM key. */ /* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey); ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS) if (ErrorCode != ERROR_SUCCESS)
{ {
/* Maybe the key doesn't exist in the HKLM view */ /* Maybe the key doesn't exist in the HKLM view */
@ -378,7 +499,7 @@ QueryHKCRValue(
return ErrorCode; return ErrorCode;
/* If we're here, we must open from HKLM key. */ /* If we're here, we must open from HKLM key. */
ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey); ErrorCode = GetFallbackHKCRKey(hKey, &QueriedKey, FALSE);
if (ErrorCode != ERROR_SUCCESS) if (ErrorCode != ERROR_SUCCESS)
{ {
/* Maybe the key doesn't exist in the HKLM view */ /* Maybe the key doesn't exist in the HKLM view */
@ -395,3 +516,72 @@ QueryHKCRValue(
return ErrorCode; 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 * @implemented
*/ */
LONG WINAPI LONG
RegCreateKeyExW(HKEY hKey, WINAPI
LPCWSTR lpSubKey, RegCreateKeyExW(
DWORD Reserved, _In_ HKEY hKey,
LPWSTR lpClass, _In_ LPCWSTR lpSubKey,
DWORD dwOptions, _In_ DWORD Reserved,
REGSAM samDesired, _In_opt_ LPWSTR lpClass,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwOptions,
PHKEY phkResult, _In_ REGSAM samDesired,
LPDWORD lpdwDisposition) _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_Out_ PHKEY phkResult,
_Out_opt_ LPDWORD lpdwDisposition)
{ {
UNICODE_STRING SubKeyString; UNICODE_STRING SubKeyString;
UNICODE_STRING ClassString; UNICODE_STRING ClassString;
@ -1117,6 +1119,22 @@ RegCreateKeyExW(HKEY hKey,
TRACE("ParentKey %p\n", ParentKey); 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) if (dwOptions & REG_OPTION_OPEN_LINK)
Attributes |= OBJ_OPENLINK; Attributes |= OBJ_OPENLINK;
@ -1144,9 +1162,6 @@ RegCreateKeyExW(HKEY hKey,
return RtlNtStatusToDosError(Status); return RtlNtStatusToDosError(Status);
} }
if (IsHKCRKey(ParentKey))
MakeHKCRKey(phkResult);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -4851,18 +4866,34 @@ RegSetValueExA(HKEY hKey,
* *
* @implemented * @implemented
*/ */
LONG WINAPI LONG
RegSetValueExW(HKEY hKey, WINAPI
LPCWSTR lpValueName, RegSetValueExW(
DWORD Reserved, _In_ HKEY hKey,
DWORD dwType, _In_ LPCWSTR lpValueName,
CONST BYTE* lpData, _In_ DWORD Reserved,
DWORD cbData) _In_ DWORD dwType,
_In_ CONST BYTE* lpData,
_In_ DWORD cbData)
{ {
UNICODE_STRING ValueName; UNICODE_STRING ValueName;
HANDLE KeyHandle; HANDLE KeyHandle;
NTSTATUS Status; 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)) if (is_string(dwType) && (cbData != 0))
{ {
PWSTR pwsData = (PWSTR)lpData; PWSTR pwsData = (PWSTR)lpData;
@ -4878,18 +4909,12 @@ RegSetValueExW(HKEY hKey,
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
_SEH2_YIELD(return ERROR_NOACCESS); ClosePredefKey(KeyHandle);
return ERROR_NOACCESS;
} }
_SEH2_END; _SEH2_END;
} }
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError(Status);
}
RtlInitUnicodeString(&ValueName, lpValueName); RtlInitUnicodeString(&ValueName, lpValueName);
Status = NtSetValueKey(KeyHandle, Status = NtSetValueKey(KeyHandle,

View file

@ -22,6 +22,19 @@ MakeHKCRKey(_Inout_ HKEY* hKey)
*hKey = (HKEY)((ULONG_PTR)(*hKey) | 0x2); *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 LONG
WINAPI WINAPI
OpenHKCRKey( OpenHKCRKey(
@ -49,3 +62,13 @@ QueryHKCRValue(
_In_ LPBYTE Data, _In_ LPBYTE Data,
_In_ LPDWORD Count); _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);