mirror of
https://github.com/reactos/wine.git
synced 2024-11-30 15:10:27 +00:00
715 lines
21 KiB
C
715 lines
21 KiB
C
/*
|
|
* registry functions
|
|
*
|
|
* NOTES:
|
|
* HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
|
|
* HKEY_USERS \\REGISTRY\\USER
|
|
* HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
|
|
* HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
|
|
*/
|
|
|
|
#include "debugtools.h"
|
|
#include "winreg.h"
|
|
#include "winerror.h"
|
|
#include "file.h"
|
|
#include "server.h"
|
|
#include "ntddk.h"
|
|
#include "crtdll.h"
|
|
#include "ntdll_misc.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(ntdll);
|
|
|
|
/* copy a key name into the request buffer */
|
|
static inline NTSTATUS copy_nameU( LPWSTR Dest, PUNICODE_STRING Name, UINT Offset )
|
|
{
|
|
if (Name->Buffer)
|
|
{
|
|
if ((Name->Length-Offset) > MAX_PATH) return STATUS_BUFFER_OVERFLOW;
|
|
lstrcpyW( Dest, Name->Buffer+Offset );
|
|
}
|
|
else Dest[0] = 0;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/* translates predefined paths to HKEY_ constants */
|
|
static BOOLEAN _NtKeyToWinKey(
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
OUT UINT * Offset, /* offset within ObjectName */
|
|
OUT HKEY * KeyHandle) /* translated handle */
|
|
{
|
|
static const WCHAR KeyPath_HKLM[] = {
|
|
'\\','R','E','G','I','S','T','R','Y',
|
|
'\\','M','A','C','H','I','N','E',0};
|
|
static const WCHAR KeyPath_HKU [] = {
|
|
'\\','R','E','G','I','S','T','R','Y',
|
|
'\\','U','S','E','R',0};
|
|
static const WCHAR KeyPath_HCC [] = {
|
|
'\\','R','E','G','I','S','T','R','Y',
|
|
'\\','M','A','C','H','I','N','E',
|
|
'\\','S','Y','S','T','E','M',
|
|
'\\','C','U','R','R','E','N','T','C','O','N','T','R','O','L','S','E','T',
|
|
'\\','H','A','R','D','W','A','R','E','P','R','O','F','I','L','E','S',
|
|
'\\','C','U','R','R','E','N','T',0};
|
|
static const WCHAR KeyPath_HCR [] = {
|
|
'\\','R','E','G','I','S','T','R','Y',
|
|
'\\','M','A','C','H','I','N','E',
|
|
'\\','S','O','F','T','W','A','R','E',
|
|
'\\','C','L','A','S','S','E','S',0};
|
|
int len;
|
|
PUNICODE_STRING ObjectName = ObjectAttributes->ObjectName;
|
|
|
|
if(ObjectAttributes->RootDirectory)
|
|
{
|
|
len = 0;
|
|
*KeyHandle = ObjectAttributes->RootDirectory;
|
|
}
|
|
else if((ObjectName->Length > (len=lstrlenW(KeyPath_HKLM)))
|
|
&& (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HKLM,len)))
|
|
{ *KeyHandle = HKEY_LOCAL_MACHINE;
|
|
}
|
|
else if((ObjectName->Length > (len=lstrlenW(KeyPath_HKU)))
|
|
&& (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HKU,len)))
|
|
{ *KeyHandle = HKEY_USERS;
|
|
}
|
|
else if((ObjectName->Length > (len=lstrlenW(KeyPath_HCR)))
|
|
&& (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HCR,len)))
|
|
{ *KeyHandle = HKEY_CLASSES_ROOT;
|
|
}
|
|
else if((ObjectName->Length > (len=lstrlenW(KeyPath_HCC)))
|
|
&& (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HCC,len)))
|
|
{ *KeyHandle = HKEY_CURRENT_CONFIG;
|
|
}
|
|
else
|
|
{
|
|
*KeyHandle = 0;
|
|
*Offset = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
if (len > 0 && ObjectName->Buffer[len] == (WCHAR)'\\') len++;
|
|
*Offset = len;
|
|
|
|
TRACE("off=%u hkey=0x%08x\n", *Offset, *KeyHandle);
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtCreateKey [NTDLL]
|
|
* ZwCreateKey
|
|
*/
|
|
NTSTATUS WINAPI NtCreateKey(
|
|
PHANDLE KeyHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
ULONG TitleIndex,
|
|
PUNICODE_STRING Class,
|
|
ULONG CreateOptions,
|
|
PULONG Disposition)
|
|
{
|
|
struct create_key_request *req = get_req_buffer();
|
|
UINT ObjectNameOffset;
|
|
HKEY RootDirectory;
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(%p,0x%08lx,0x%08lx,%p(%s),0x%08lx,%p)\n",
|
|
KeyHandle, DesiredAccess, TitleIndex, Class, debugstr_us(Class), CreateOptions, Disposition);
|
|
dump_ObjectAttributes(ObjectAttributes);
|
|
|
|
if (!KeyHandle)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
_NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
|
|
|
|
req->parent = RootDirectory;
|
|
req->access = DesiredAccess;
|
|
req->options = CreateOptions;
|
|
req->modif = time(NULL);
|
|
|
|
if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
if (Class)
|
|
{
|
|
int ClassLen = Class->Length+1;
|
|
if ( ClassLen*sizeof(WCHAR) > server_remaining(req->class)) return STATUS_BUFFER_OVERFLOW;
|
|
lstrcpynW( req->class, Class->Buffer, ClassLen);
|
|
}
|
|
else
|
|
req->class[0] = 0x0000;
|
|
|
|
if (!(ret = server_call_noerr(REQ_CREATE_KEY)))
|
|
{
|
|
*KeyHandle = req->hkey;
|
|
if (Disposition) *Disposition = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtOpenKey [NTDLL.129]
|
|
* ZwOpenKey
|
|
* OUT PHANDLE KeyHandle (returns 0 when failure)
|
|
* IN ACCESS_MASK DesiredAccess
|
|
* IN POBJECT_ATTRIBUTES ObjectAttributes
|
|
*/
|
|
NTSTATUS WINAPI NtOpenKey(
|
|
PHANDLE KeyHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
{
|
|
struct open_key_request *req = get_req_buffer();
|
|
UINT ObjectNameOffset;
|
|
HKEY RootDirectory;
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(%p,0x%08lx)\n", KeyHandle, DesiredAccess);
|
|
dump_ObjectAttributes(ObjectAttributes);
|
|
|
|
if (!KeyHandle) return STATUS_INVALID_PARAMETER;
|
|
*KeyHandle = 0;
|
|
|
|
_NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
|
|
|
|
req->parent = RootDirectory;
|
|
req->access = DesiredAccess;
|
|
|
|
if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS)
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
if (!(ret = server_call_noerr(REQ_OPEN_KEY)))
|
|
{
|
|
*KeyHandle = req->hkey;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtDeleteKey [NTDLL]
|
|
* ZwDeleteKey
|
|
*/
|
|
NTSTATUS WINAPI NtDeleteKey(HANDLE KeyHandle)
|
|
{
|
|
FIXME("(0x%08x) stub!\n",
|
|
KeyHandle);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtDeleteValueKey [NTDLL]
|
|
* ZwDeleteValueKey
|
|
*/
|
|
NTSTATUS WINAPI NtDeleteValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN PUNICODE_STRING ValueName)
|
|
{
|
|
FIXME("(0x%08x,%p(%s)) stub!\n",
|
|
KeyHandle, ValueName,debugstr_us(ValueName));
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtEnumerateKey [NTDLL]
|
|
* ZwEnumerateKey
|
|
*
|
|
* NOTES
|
|
* the name copied into the buffer is NOT 0-terminated
|
|
*/
|
|
NTSTATUS WINAPI NtEnumerateKey(
|
|
HANDLE KeyHandle,
|
|
ULONG Index,
|
|
KEY_INFORMATION_CLASS KeyInformationClass,
|
|
PVOID KeyInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength)
|
|
{
|
|
struct enum_key_request *req = get_req_buffer();
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
|
|
KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
|
|
|
|
req->hkey = KeyHandle;
|
|
req->index = Index;
|
|
if ((ret = server_call_noerr(REQ_ENUM_KEY)) != STATUS_SUCCESS) return ret;
|
|
|
|
switch (KeyInformationClass)
|
|
{
|
|
case KeyBasicInformation:
|
|
{
|
|
PKEY_BASIC_INFORMATION kbi = KeyInformation;
|
|
UINT NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
*ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kbi->LastWriteTime, 0);
|
|
kbi->TitleIndex = 0;
|
|
kbi->NameLength = NameLength;
|
|
memcpy (kbi->Name, req->name, NameLength);
|
|
}
|
|
break;
|
|
case KeyFullInformation:
|
|
{
|
|
PKEY_FULL_INFORMATION kfi = KeyInformation;
|
|
kfi->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
|
|
kfi->ClassOffset = (kfi->ClassLength) ?
|
|
sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
|
|
*ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kfi->LastWriteTime, 0);
|
|
kfi->TitleIndex = 0;
|
|
/* kfi->SubKeys = req->subkeys;
|
|
kfi->MaxNameLength = req->max_subkey;
|
|
kfi->MaxClassLength = req->max_class;
|
|
kfi->Values = req->values;
|
|
kfi->MaxValueNameLen = req->max_value;
|
|
kfi->MaxValueDataLen = req->max_data;
|
|
*/
|
|
FIXME("incomplete\n");
|
|
if (kfi->ClassLength) memcpy (kfi->Class, req->class, kfi->ClassLength);
|
|
}
|
|
break;
|
|
case KeyNodeInformation:
|
|
{
|
|
PKEY_NODE_INFORMATION kni = KeyInformation;
|
|
kni->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
|
|
kni->NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
kni->ClassOffset = (kni->ClassLength) ?
|
|
sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
|
|
|
|
*ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kni->LastWriteTime, 0);
|
|
kni->TitleIndex = 0;
|
|
memcpy (kni->Name, req->name, kni->NameLength);
|
|
if (kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
|
|
}
|
|
break;
|
|
default:
|
|
FIXME("KeyInformationClass not implemented\n");
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
TRACE("buf=%lu len=%lu\n", Length, *ResultLength);
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtQueryKey [NTDLL]
|
|
* ZwQueryKey
|
|
*/
|
|
NTSTATUS WINAPI NtQueryKey(
|
|
HANDLE KeyHandle,
|
|
KEY_INFORMATION_CLASS KeyInformationClass,
|
|
PVOID KeyInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength)
|
|
{
|
|
struct query_key_info_request *req = get_req_buffer();
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(0x%08x,0x%08x,%p,0x%08lx,%p) stub\n",
|
|
KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
|
|
|
|
req->hkey = KeyHandle;
|
|
if ((ret = server_call_noerr(REQ_QUERY_KEY_INFO)) != STATUS_SUCCESS) return ret;
|
|
|
|
switch (KeyInformationClass)
|
|
{
|
|
case KeyBasicInformation:
|
|
{
|
|
PKEY_BASIC_INFORMATION kbi = KeyInformation;
|
|
UINT NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
*ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kbi->LastWriteTime, 0);
|
|
kbi->TitleIndex = 0;
|
|
kbi->NameLength = NameLength;
|
|
memcpy (kbi->Name, req->name, NameLength);
|
|
}
|
|
break;
|
|
case KeyFullInformation:
|
|
{
|
|
PKEY_FULL_INFORMATION kfi = KeyInformation;
|
|
kfi->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
|
|
kfi->ClassOffset = (kfi->ClassLength) ?
|
|
sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
|
|
|
|
*ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kfi->LastWriteTime, 0);
|
|
kfi->TitleIndex = 0;
|
|
kfi->SubKeys = req->subkeys;
|
|
kfi->MaxNameLen = req->max_subkey;
|
|
kfi->MaxClassLen = req->max_class;
|
|
kfi->Values = req->values;
|
|
kfi->MaxValueNameLen = req->max_value;
|
|
kfi->MaxValueDataLen = req->max_data;
|
|
if(kfi->ClassLength) memcpy ((char *) KeyInformation + kfi->ClassOffset, req->class, kfi->ClassLength);
|
|
}
|
|
break;
|
|
case KeyNodeInformation:
|
|
{
|
|
PKEY_NODE_INFORMATION kni = KeyInformation;
|
|
kni->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
|
|
kni->NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
kni->ClassOffset = (kni->ClassLength) ?
|
|
sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
|
|
|
|
*ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
|
|
if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
DOSFS_UnixTimeToFileTime(req->modif, &kni->LastWriteTime, 0);
|
|
kni->TitleIndex = 0;
|
|
memcpy (kni->Name, req->name, kni->NameLength);
|
|
if(kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
|
|
}
|
|
break;
|
|
default:
|
|
FIXME("KeyInformationClass not implemented\n");
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtEnumerateValueKey [NTDLL]
|
|
* ZwEnumerateValueKey
|
|
*/
|
|
NTSTATUS WINAPI NtEnumerateValueKey(
|
|
HANDLE KeyHandle,
|
|
ULONG Index,
|
|
KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
|
|
PVOID KeyInformation,
|
|
ULONG Length,
|
|
PULONG ResultLength)
|
|
{
|
|
struct enum_key_value_request *req = get_req_buffer();
|
|
UINT NameLength;
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
|
|
KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
|
|
|
|
req->hkey = KeyHandle;
|
|
req->index = Index;
|
|
if ((ret = server_call_noerr(REQ_ENUM_KEY_VALUE)) != STATUS_SUCCESS) return ret;
|
|
|
|
switch (KeyInformationClass)
|
|
{
|
|
case KeyBasicInformation:
|
|
{
|
|
PKEY_VALUE_BASIC_INFORMATION kbi = KeyInformation;
|
|
|
|
NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
|
|
if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
kbi->TitleIndex = 0;
|
|
kbi->Type = req->type;
|
|
kbi->NameLength = NameLength;
|
|
memcpy(kbi->Name, req->name, kbi->NameLength);
|
|
}
|
|
break;
|
|
case KeyValueFullInformation:
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION kbi = KeyInformation;
|
|
UINT DataOffset;
|
|
|
|
NameLength = lstrlenW(req->name) * sizeof(WCHAR);
|
|
DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + NameLength;
|
|
*ResultLength = DataOffset + req->len;
|
|
|
|
if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
kbi->TitleIndex = 0;
|
|
kbi->Type = req->type;
|
|
kbi->DataOffset = DataOffset;
|
|
kbi->DataLength = req->len;
|
|
kbi->NameLength = NameLength;
|
|
memcpy(kbi->Name, req->name, kbi->NameLength);
|
|
memcpy(((LPBYTE)kbi) + DataOffset, req->data, req->len);
|
|
}
|
|
break;
|
|
case KeyValuePartialInformation:
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION kbi = KeyInformation;
|
|
|
|
*ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(WCHAR) + req->len;
|
|
|
|
if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
|
|
|
|
kbi->TitleIndex = 0;
|
|
kbi->Type = req->type;
|
|
kbi->DataLength = req->len;
|
|
memcpy(kbi->Data, req->data, req->len);
|
|
}
|
|
break;
|
|
default:
|
|
FIXME("not implemented\n");
|
|
}
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtFlushKey [NTDLL]
|
|
* ZwFlushKey
|
|
*/
|
|
NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
|
|
{
|
|
FIXME("(0x%08x) stub!\n",
|
|
KeyHandle);
|
|
return 1;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtLoadKey [NTDLL]
|
|
* ZwLoadKey
|
|
*/
|
|
NTSTATUS WINAPI NtLoadKey(
|
|
PHANDLE KeyHandle,
|
|
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
{
|
|
FIXME("(%p),stub!\n", KeyHandle);
|
|
dump_ObjectAttributes(ObjectAttributes);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtNotifyChangeKey [NTDLL]
|
|
* ZwNotifyChangeKey
|
|
*/
|
|
NTSTATUS WINAPI NtNotifyChangeKey(
|
|
IN HANDLE KeyHandle,
|
|
IN HANDLE Event,
|
|
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
|
|
IN PVOID ApcContext OPTIONAL,
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
IN ULONG CompletionFilter,
|
|
IN BOOLEAN Asynchroneous,
|
|
OUT PVOID ChangeBuffer,
|
|
IN ULONG Length,
|
|
IN BOOLEAN WatchSubtree)
|
|
{
|
|
FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
|
|
KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
|
|
Asynchroneous, ChangeBuffer, Length, WatchSubtree);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtQueryMultipleValueKey [NTDLL]
|
|
* ZwQueryMultipleValueKey
|
|
*/
|
|
|
|
NTSTATUS WINAPI NtQueryMultipleValueKey(
|
|
HANDLE KeyHandle,
|
|
PVALENTW ListOfValuesToQuery,
|
|
ULONG NumberOfItems,
|
|
PVOID MultipleValueInformation,
|
|
ULONG Length,
|
|
PULONG ReturnLength)
|
|
{
|
|
FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
|
|
KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
|
|
Length,ReturnLength);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtQueryValueKey [NTDLL]
|
|
* ZwQueryValueKey
|
|
*
|
|
* NOTES
|
|
* the name in the KeyValueInformation is never set
|
|
*/
|
|
NTSTATUS WINAPI NtQueryValueKey(
|
|
IN HANDLE KeyHandle,
|
|
IN PUNICODE_STRING ValueName,
|
|
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
|
|
OUT PVOID KeyValueInformation,
|
|
IN ULONG Length,
|
|
OUT PULONG ResultLength)
|
|
{
|
|
struct get_key_value_request *req = get_req_buffer();
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n",
|
|
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
|
|
|
|
req->hkey = KeyHandle;
|
|
if (copy_nameU(req->name, ValueName, 0) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW;
|
|
if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret;
|
|
|
|
switch(KeyValueInformationClass)
|
|
{
|
|
case KeyValueBasicInformation:
|
|
{
|
|
PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation;
|
|
kbi->Type = req->type;
|
|
|
|
*ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR);
|
|
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
kbi->NameLength = 0;
|
|
}
|
|
break;
|
|
case KeyValueFullInformation:
|
|
{
|
|
PKEY_VALUE_FULL_INFORMATION kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation;
|
|
ULONG DataOffset;
|
|
kfi->Type = req->type;
|
|
|
|
DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR);
|
|
*ResultLength = DataOffset + req->len;
|
|
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
kfi->NameLength = 0;
|
|
kfi->DataOffset = DataOffset;
|
|
kfi->DataLength = req->len;
|
|
memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len);
|
|
}
|
|
break;
|
|
case KeyValuePartialInformation:
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
|
|
kpi->Type = req->type;
|
|
|
|
*ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len;
|
|
if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
|
|
|
|
kpi->DataLength = req->len;
|
|
memcpy(kpi->Data, req->data, req->len);
|
|
}
|
|
break;
|
|
default:
|
|
FIXME("KeyValueInformationClass not implemented\n");
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtReplaceKey [NTDLL]
|
|
* ZwReplaceKey
|
|
*/
|
|
NTSTATUS WINAPI NtReplaceKey(
|
|
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
|
IN HANDLE Key,
|
|
IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
|
|
{
|
|
FIXME("(0x%08x),stub!\n", Key);
|
|
dump_ObjectAttributes(ObjectAttributes);
|
|
dump_ObjectAttributes(ReplacedObjectAttributes);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/******************************************************************************
|
|
* NtRestoreKey [NTDLL]
|
|
* ZwRestoreKey
|
|
*/
|
|
NTSTATUS WINAPI NtRestoreKey(
|
|
HANDLE KeyHandle,
|
|
HANDLE FileHandle,
|
|
ULONG RestoreFlags)
|
|
{
|
|
FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
|
|
KeyHandle, FileHandle, RestoreFlags);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/******************************************************************************
|
|
* NtSaveKey [NTDLL]
|
|
* ZwSaveKey
|
|
*/
|
|
NTSTATUS WINAPI NtSaveKey(
|
|
IN HANDLE KeyHandle,
|
|
IN HANDLE FileHandle)
|
|
{
|
|
FIXME("(0x%08x,0x%08x) stub\n",
|
|
KeyHandle, FileHandle);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/******************************************************************************
|
|
* NtSetInformationKey [NTDLL]
|
|
* ZwSetInformationKey
|
|
*/
|
|
NTSTATUS WINAPI NtSetInformationKey(
|
|
IN HANDLE KeyHandle,
|
|
IN const int KeyInformationClass,
|
|
IN PVOID KeyInformation,
|
|
IN ULONG KeyInformationLength)
|
|
{
|
|
FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
|
|
KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
/******************************************************************************
|
|
* NtSetValueKey [NTDLL]
|
|
* ZwSetValueKey
|
|
*/
|
|
NTSTATUS WINAPI NtSetValueKey(
|
|
HANDLE KeyHandle,
|
|
PUNICODE_STRING ValueName,
|
|
ULONG TitleIndex,
|
|
ULONG Type,
|
|
PVOID Data,
|
|
ULONG DataSize)
|
|
{
|
|
FIXME("(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n",
|
|
KeyHandle, ValueName,debugstr_us(ValueName), TitleIndex, Type, Data, DataSize);
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
* NtUnloadKey [NTDLL]
|
|
* ZwUnloadKey
|
|
*/
|
|
NTSTATUS WINAPI NtUnloadKey(
|
|
IN HANDLE KeyHandle)
|
|
{
|
|
FIXME("(0x%08x) stub\n",
|
|
KeyHandle);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* RtlFormatCurrentUserKeyPath [NTDLL.371]
|
|
*/
|
|
NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
|
|
IN OUT PUNICODE_STRING KeyPath)
|
|
{
|
|
/* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
|
|
LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
|
|
ANSI_STRING AnsiPath;
|
|
|
|
FIXME("(%p) stub\n",KeyPath);
|
|
RtlInitAnsiString(&AnsiPath, Path);
|
|
return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
|
|
}
|
|
|
|
/******************************************************************************
|
|
* RtlOpenCurrentUser [NTDLL]
|
|
*
|
|
* if we return just HKEY_CURRENT_USER the advapi try's to find a remote
|
|
* registry (odd handle) and fails
|
|
*
|
|
*/
|
|
DWORD WINAPI RtlOpenCurrentUser(
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT PHANDLE KeyHandle) /* handle of HKEY_CURRENT_USER */
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING ObjectName;
|
|
NTSTATUS ret;
|
|
|
|
TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
|
|
|
|
RtlFormatCurrentUserKeyPath(&ObjectName);
|
|
InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
|
|
ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
|
|
RtlFreeUnicodeString(&ObjectName);
|
|
return ret;
|
|
}
|