| /* |
| * 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; |
| } |