+/*
+ * Registry functions
+ *
+ * Copyright (C) 1999 Juergen Schmied
+ * Copyright (C) 2000 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * 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 "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "winerror.h"
+#include "wine/unicode.h"
+#include "wine/library.h"
+#include "wine/server.h"
#include "windef.h"
-#include "wintypes.h"
+#include "winbase.h"
#include "winreg.h"
-#include "ntdll.h"
-#include "ntddk.h"
+#include "winternl.h"
+#include "ntdll_misc.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(reg);
+
+/* maximum length of a key/value name in bytes (without terminating null) */
+#define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
-#include "debug.h"
/******************************************************************************
- * NtCreateKey [NTDLL]
- * ZwCreateKey
+ * NtCreateKey [NTDLL.@]
+ * ZwCreateKey [NTDLL.@]
*/
-NTSTATUS WINAPI NtCreateKey(
- PHANDLE KeyHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes,
- ULONG TitleIndex,
- PUNICODE_STRING Class,
- ULONG CreateOptions,
- PULONG Disposition)
+NTSTATUS WINAPI NtCreateKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
+ ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
+ PULONG dispos )
{
- FIXME(ntdll,"(%p,0x%08lx,%p (%s),0x%08lx, %p(%s),0x%08lx,%p),stub!\n",
- KeyHandle, DesiredAccess, ObjectAttributes,debugstr_w(ObjectAttributes->ObjectName->Buffer),
- TitleIndex, Class, debugstr_w(Class->Buffer), CreateOptions, Disposition);
- return 0;
+ NTSTATUS ret;
+
+ TRACE( "(%p,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
+ debugstr_us(class), options, access, retkey );
+
+ if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
+ if (!retkey) return STATUS_INVALID_PARAMETER;
+
+ SERVER_START_REQ( create_key )
+ {
+ req->parent = attr->RootDirectory;
+ req->access = access;
+ req->options = options;
+ req->modif = 0;
+ req->namelen = attr->ObjectName->Length;
+ wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
+ if (class) wine_server_add_data( req, class->Buffer, class->Length );
+ if (!(ret = wine_server_call( req )))
+ {
+ *retkey = reply->hkey;
+ if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
+ }
+ }
+ SERVER_END_REQ;
+ TRACE("<- %p\n", *retkey);
+ return ret;
}
/******************************************************************************
- * NtDeleteKey [NTDLL]
- * ZwDeleteKey
+ * RtlpNtCreateKey [NTDLL.@]
+ *
+ * See NtCreateKey.
*/
-NTSTATUS NtDeleteKey(HANDLE KeyHandle)
+NTSTATUS WINAPI RtlpNtCreateKey( PHKEY retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
+ ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
+ PULONG dispos )
{
- FIXME(ntdll,"(0x%08x) stub!\n",
- KeyHandle);
- return 1;
+ if (attr)
+ attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
+
+ return NtCreateKey(retkey, access, attr, 0, NULL, 0, dispos);
}
/******************************************************************************
- * NtDeleteValueKey [NTDLL]
- * ZwDeleteValueKey
+ * NtOpenKey [NTDLL.@]
+ * ZwOpenKey [NTDLL.@]
+ *
+ * OUT PHKEY retkey (returns 0 when failure)
+ * IN ACCESS_MASK access
+ * IN POBJECT_ATTRIBUTES attr
*/
-NTSTATUS WINAPI NtDeleteValueKey(
- IN HANDLE KeyHandle,
- IN PUNICODE_STRING ValueName)
+NTSTATUS WINAPI NtOpenKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
{
- FIXME(ntdll,"(0x%08x,%p(%s)) stub!\n",
- KeyHandle, ValueName,debugstr_w(ValueName->Buffer));
- return 1;
+ NTSTATUS ret;
+ DWORD len = attr->ObjectName->Length;
+
+ TRACE( "(%p,%s,%lx,%p)\n", attr->RootDirectory,
+ debugstr_us(attr->ObjectName), access, retkey );
+ if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
+ if (!retkey) return STATUS_INVALID_PARAMETER;
+
+ SERVER_START_REQ( open_key )
+ {
+ req->parent = attr->RootDirectory;
+ req->access = access;
+ wine_server_add_data( req, attr->ObjectName->Buffer, len );
+ ret = wine_server_call( req );
+ *retkey = reply->hkey;
+ }
+ SERVER_END_REQ;
+ TRACE("<- %p\n", *retkey);
+ return ret;
}
+
/******************************************************************************
- * NtEnumerateKey [NTDLL]
- * ZwEnumerateKey
+ * RtlpNtOpenKey [NTDLL.@]
+ *
+ * See NtOpenKey.
*/
-NTSTATUS WINAPI NtEnumerateKey(
- HANDLE KeyHandle,
- ULONG Index,
- KEY_INFORMATION_CLASS KeyInformationClass,
- PVOID KeyInformation,
- ULONG Length,
- PULONG ResultLength)
+NTSTATUS WINAPI RtlpNtOpenKey( PHKEY retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
{
- FIXME(ntdll,"(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p) stub\n",
- KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
- return 1;
+ if (attr)
+ attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
+ return NtOpenKey(retkey, access, attr);
}
/******************************************************************************
- * NtEnumerateValueKey [NTDLL]
- * ZwEnumerateValueKey
+ * NtDeleteKey [NTDLL.@]
+ * ZwDeleteKey [NTDLL.@]
*/
-NTSTATUS WINAPI NtEnumerateValueKey(
- HANDLE KeyHandle,
- ULONG Index,
- KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
- PVOID KeyInformation,
- ULONG Length,
- PULONG ResultLength)
+NTSTATUS WINAPI NtDeleteKey( HKEY hkey )
+{
+ NTSTATUS ret;
+
+ TRACE( "(%p)\n", hkey );
+
+ SERVER_START_REQ( delete_key )
+ {
+ req->hkey = hkey;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+/******************************************************************************
+ * RtlpNtMakeTemporaryKey [NTDLL.@]
+ *
+ * See NtDeleteKey.
+ */
+NTSTATUS WINAPI RtlpNtMakeTemporaryKey( HKEY hkey )
{
- FIXME(ntdll,"(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p) stub!\n",
- KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
- return 1;
+ return NtDeleteKey(hkey);
}
/******************************************************************************
- * NtFlushKey [NTDLL]
- * ZwFlushKey
+ * NtDeleteValueKey [NTDLL.@]
+ * ZwDeleteValueKey [NTDLL.@]
*/
-NTSTATUS NtFlushKey(HANDLE KeyHandle)
+NTSTATUS WINAPI NtDeleteValueKey( HKEY hkey, const UNICODE_STRING *name )
{
- FIXME(ntdll,"(0x%08x) stub!\n",
- KeyHandle);
- return 1;
+ NTSTATUS ret;
+
+ TRACE( "(%p,%s)\n", hkey, debugstr_us(name) );
+ if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
+
+ SERVER_START_REQ( delete_key_value )
+ {
+ req->hkey = hkey;
+ wine_server_add_data( req, name->Buffer, name->Length );
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+
+/******************************************************************************
+ * enumerate_key
+ *
+ * Implementation of NtQueryKey and NtEnumerateKey
+ */
+static NTSTATUS enumerate_key( HKEY handle, int index, KEY_INFORMATION_CLASS info_class,
+ void *info, DWORD length, DWORD *result_len )
+
+{
+ NTSTATUS ret;
+ void *data_ptr;
+ size_t fixed_size;
+
+ switch(info_class)
+ {
+ case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
+ case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
+ case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
+ default:
+ FIXME( "Information class %d not implemented\n", info_class );
+ return STATUS_INVALID_PARAMETER;
+ }
+ fixed_size = (char *)data_ptr - (char *)info;
+
+ SERVER_START_REQ( enum_key )
+ {
+ req->hkey = handle;
+ req->index = index;
+ req->info_class = info_class;
+ if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
+ if (!(ret = wine_server_call( req )))
+ {
+ LARGE_INTEGER modif;
+
+ RtlSecondsSince1970ToTime( reply->modif, &modif );
+
+ switch(info_class)
+ {
+ case KeyBasicInformation:
+ {
+ KEY_BASIC_INFORMATION keyinfo;
+ fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
+ keyinfo.LastWriteTime = modif;
+ keyinfo.TitleIndex = 0;
+ keyinfo.NameLength = reply->namelen;
+ memcpy( info, &keyinfo, min( length, fixed_size ) );
+ }
+ break;
+ case KeyFullInformation:
+ {
+ KEY_FULL_INFORMATION keyinfo;
+ fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
+ keyinfo.LastWriteTime = modif;
+ keyinfo.TitleIndex = 0;
+ keyinfo.ClassLength = wine_server_reply_size(reply);
+ keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
+ keyinfo.SubKeys = reply->subkeys;
+ keyinfo.MaxNameLen = reply->max_subkey;
+ keyinfo.MaxClassLen = reply->max_class;
+ keyinfo.Values = reply->values;
+ keyinfo.MaxValueNameLen = reply->max_value;
+ keyinfo.MaxValueDataLen = reply->max_data;
+ memcpy( info, &keyinfo, min( length, fixed_size ) );
+ }
+ break;
+ case KeyNodeInformation:
+ {
+ KEY_NODE_INFORMATION keyinfo;
+ fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
+ keyinfo.LastWriteTime = modif;
+ keyinfo.TitleIndex = 0;
+ keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
+ keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
+ keyinfo.NameLength = reply->namelen;
+ memcpy( info, &keyinfo, min( length, fixed_size ) );
+ }
+ break;
+ }
+ *result_len = fixed_size + reply->total;
+ if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+
+
+/******************************************************************************
+ * NtEnumerateKey [NTDLL.@]
+ * ZwEnumerateKey [NTDLL.@]
+ *
+ * NOTES
+ * the name copied into the buffer is NOT 0-terminated
+ */
+NTSTATUS WINAPI NtEnumerateKey( HKEY handle, ULONG index, KEY_INFORMATION_CLASS info_class,
+ void *info, DWORD length, DWORD *result_len )
+{
+ /* -1 means query key, so avoid it here */
+ if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
+ return enumerate_key( handle, index, info_class, info, length, result_len );
+}
+
+
+/******************************************************************************
+ * RtlpNtEnumerateSubKey [NTDLL.@]
+ *
+ */
+NTSTATUS WINAPI RtlpNtEnumerateSubKey( HKEY handle, UNICODE_STRING *out, ULONG index )
+{
+ KEY_BASIC_INFORMATION *info;
+ DWORD dwLen, dwResultLen;
+ NTSTATUS ret;
+
+ if (out->Length)
+ {
+ dwLen = out->Length + sizeof(KEY_BASIC_INFORMATION);
+ info = (KEY_BASIC_INFORMATION*)RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
+ if (!info)
+ return STATUS_NO_MEMORY;
+ }
+ else
+ {
+ dwLen = 0;
+ info = NULL;
+ }
+
+ ret = NtEnumerateKey( handle, index, KeyBasicInformation, info, dwLen, &dwResultLen );
+ dwResultLen -= sizeof(KEY_BASIC_INFORMATION);
+
+ if (ret == STATUS_BUFFER_OVERFLOW)
+ out->Length = dwResultLen;
+ else if (!ret)
+ {
+ if (out->Length < info->NameLength)
+ {
+ out->Length = dwResultLen;
+ ret = STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ {
+ out->Length = info->NameLength;
+ memcpy(out->Buffer, info->Name, info->NameLength);
+ }
+ }
+
+ if (info)
+ RtlFreeHeap( GetProcessHeap(), 0, info );
+ return ret;
}
/******************************************************************************
- * NtLoadKey [NTDLL]
- * ZwLoadKey
+ * NtQueryKey [NTDLL.@]
+ * ZwQueryKey [NTDLL.@]
*/
-NTSTATUS WINAPI NtLoadKey(
- PHANDLE KeyHandle,
- POBJECT_ATTRIBUTES ObjectAttributes)
+NTSTATUS WINAPI NtQueryKey( HKEY handle, KEY_INFORMATION_CLASS info_class,
+ void *info, DWORD length, DWORD *result_len )
{
- FIXME(ntdll,"(%p,%p (%s)),stub!\n",
- KeyHandle, ObjectAttributes,debugstr_w(ObjectAttributes->ObjectName->Buffer));
- return 0;
+ return enumerate_key( handle, -1, info_class, info, length, result_len );
+}
+
+
+/* fill the key value info structure for a specific info class */
+static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
+ DWORD length, int type, int name_len, int data_len )
+{
+ switch(info_class)
+ {
+ case KeyValueBasicInformation:
+ {
+ KEY_VALUE_BASIC_INFORMATION keyinfo;
+ keyinfo.TitleIndex = 0;
+ keyinfo.Type = type;
+ keyinfo.NameLength = name_len;
+ length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
+ memcpy( info, &keyinfo, length );
+ break;
+ }
+ case KeyValueFullInformation:
+ {
+ KEY_VALUE_FULL_INFORMATION keyinfo;
+ keyinfo.TitleIndex = 0;
+ keyinfo.Type = type;
+ keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
+ keyinfo.DataLength = data_len;
+ keyinfo.NameLength = name_len;
+ length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
+ memcpy( info, &keyinfo, length );
+ break;
+ }
+ case KeyValuePartialInformation:
+ {
+ KEY_VALUE_PARTIAL_INFORMATION keyinfo;
+ keyinfo.TitleIndex = 0;
+ keyinfo.Type = type;
+ keyinfo.DataLength = data_len;
+ length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
+ memcpy( info, &keyinfo, length );
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+/******************************************************************************
+ * NtEnumerateValueKey [NTDLL.@]
+ * ZwEnumerateValueKey [NTDLL.@]
+ */
+NTSTATUS WINAPI NtEnumerateValueKey( HKEY handle, ULONG index,
+ KEY_VALUE_INFORMATION_CLASS info_class,
+ void *info, DWORD length, DWORD *result_len )
+{
+ NTSTATUS ret;
+ void *ptr;
+ size_t fixed_size;
+
+ TRACE( "(%p,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
+
+ /* compute the length we want to retrieve */
+ switch(info_class)
+ {
+ case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
+ case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
+ case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
+ default:
+ FIXME( "Information class %d not implemented\n", info_class );
+ return STATUS_INVALID_PARAMETER;
+ }
+ fixed_size = (char *)ptr - (char *)info;
+ SERVER_START_REQ( enum_key_value )
+ {
+ req->hkey = handle;
+ req->index = index;
+ req->info_class = info_class;
+ if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
+ if (!(ret = wine_server_call( req )))
+ {
+ copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
+ wine_server_reply_size(reply) - reply->namelen );
+ *result_len = fixed_size + reply->total;
+ if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ SERVER_END_REQ;
+ return ret;
}
+
/******************************************************************************
- * NtNotifyChangeKey [NTDLL]
- * ZwNotifyChangeKey
+ * NtQueryValueKey [NTDLL.@]
+ * ZwQueryValueKey [NTDLL.@]
+ *
+ * NOTES
+ * the name in the KeyValueInformation is never set
+ */
+NTSTATUS WINAPI NtQueryValueKey( HKEY handle, const UNICODE_STRING *name,
+ KEY_VALUE_INFORMATION_CLASS info_class,
+ void *info, DWORD length, DWORD *result_len )
+{
+ NTSTATUS ret;
+ UCHAR *data_ptr;
+ int fixed_size = 0;
+
+ TRACE( "(%p,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
+
+ if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
+
+ /* compute the length we want to retrieve */
+ switch(info_class)
+ {
+ case KeyValueBasicInformation:
+ fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
+ data_ptr = NULL;
+ break;
+ case KeyValueFullInformation:
+ data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
+ fixed_size = (char *)data_ptr - (char *)info;
+ break;
+ case KeyValuePartialInformation:
+ data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
+ fixed_size = (char *)data_ptr - (char *)info;
+ break;
+ default:
+ FIXME( "Information class %d not implemented\n", info_class );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ SERVER_START_REQ( get_key_value )
+ {
+ req->hkey = handle;
+ wine_server_add_data( req, name->Buffer, name->Length );
+ if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
+ if (!(ret = wine_server_call( req )))
+ {
+ copy_key_value_info( info_class, info, length, reply->type,
+ 0, wine_server_reply_size(reply) );
+ *result_len = fixed_size + reply->total;
+ if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ SERVER_END_REQ;
+ return ret;
+}
+
+/******************************************************************************
+ * RtlpNtQueryValueKey [NTDLL.@]
+ *
+ */
+NTSTATUS WINAPI RtlpNtQueryValueKey( HKEY handle, ULONG *result_type, PBYTE dest,
+ DWORD *result_len )
+{
+ KEY_VALUE_PARTIAL_INFORMATION *info;
+ UNICODE_STRING name;
+ NTSTATUS ret;
+ DWORD dwResultLen;
+ DWORD dwLen = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + result_len ? *result_len : 0;
+
+ info = (KEY_VALUE_PARTIAL_INFORMATION*)RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
+ if (!info)
+ return STATUS_NO_MEMORY;
+
+ name.Length = 0;
+ ret = NtQueryValueKey( handle, &name, KeyValuePartialInformation, info, dwLen, &dwResultLen );
+
+ if (!ret || ret == STATUS_BUFFER_OVERFLOW)
+ {
+ if (result_len)
+ *result_len = info->DataLength;
+
+ if (result_type)
+ *result_type = info->Type;
+
+ if (ret != STATUS_BUFFER_OVERFLOW)
+ memcpy( dest, info->Data, info->DataLength );
+ }
+
+ RtlFreeHeap( GetProcessHeap(), 0, info );
+ return ret;
+}
+
+/******************************************************************************
+ * NtFlushKey [NTDLL.@]
+ * ZwFlushKey [NTDLL.@]
+ */
+NTSTATUS WINAPI NtFlushKey(HKEY key)
+{
+ NTSTATUS ret;
+
+ TRACE("key=%p\n", key);
+
+ SERVER_START_REQ( flush_key )
+ {
+ req->hkey = key;
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ return ret;
+}
+
+/******************************************************************************
+ * NtLoadKey [NTDLL.@]
+ * ZwLoadKey [NTDLL.@]
+ */
+NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
+{
+ FIXME("stub!\n");
+ dump_ObjectAttributes(attr);
+ dump_ObjectAttributes(file);
+ return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * NtNotifyChangeKey [NTDLL.@]
+ * ZwNotifyChangeKey [NTDLL.@]
*/
NTSTATUS WINAPI NtNotifyChangeKey(
- IN HANDLE KeyHandle,
+ IN HKEY KeyHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
IN ULONG Length,
IN BOOLEAN WatchSubtree)
{
- FIXME(ntdll,"(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
+ FIXME("(%p,%p,%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 0;
-}
-
-
-/******************************************************************************
- * NtOpenKey [NTDLL.129]
- * ZwOpenKey
- * OUT PHANDLE KeyHandle,
- * IN ACCESS_MASK DesiredAccess,
- * IN POBJECT_ATTRIBUTES ObjectAttributes
- */
-NTSTATUS WINAPI NtOpenKey(
- PHANDLE KeyHandle,
- ACCESS_MASK DesiredAccess,
- POBJECT_ATTRIBUTES ObjectAttributes)
-{
- FIXME(ntdll,"(%p,0x%08lx,%p (%s)),stub!\n",
- KeyHandle, DesiredAccess, ObjectAttributes,debugstr_w(ObjectAttributes->ObjectName->Buffer));
- return 0;
-}
-
-/******************************************************************************
- * NtQueryKey [NTDLL]
- * ZwQueryKey
- */
-NTSTATUS WINAPI NtQueryKey(
- HANDLE KeyHandle,
- KEY_INFORMATION_CLASS KeyInformationClass,
- PVOID KeyInformation,
- ULONG Length,
- PULONG ResultLength)
-{
- FIXME(ntdll,"(0x%08x,0x%08x,%p,0x%08lx,%p) stub\n",
- KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
- return 0;
+ return STATUS_SUCCESS;
}
/******************************************************************************
*/
NTSTATUS WINAPI NtQueryMultipleValueKey(
- HANDLE KeyHandle,
+ HKEY KeyHandle,
PVALENTW ListOfValuesToQuery,
ULONG NumberOfItems,
PVOID MultipleValueInformation,
ULONG Length,
PULONG ReturnLength)
{
- FIXME(ntdll,"(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
+ FIXME("(%p,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
Length,ReturnLength);
- return 0;
-}
-
-/******************************************************************************
- * NtQueryValueKey [NTDLL]
- * ZwQueryValueKey
- */
-NTSTATUS WINAPI NtQueryValueKey(
- HANDLE KeyHandle,
- PUNICODE_STRING ValueName,
- KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
- PVOID KeyValueInformation,
- ULONG Length,
- PULONG ResultLength)
-{
- FIXME(ntdll,"(0x%08x,%p,0x%08x,%p,0x%08lx,%p) stub\n",
- KeyHandle, ValueName, KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
- return 0;
+ return STATUS_SUCCESS;
}
/******************************************************************************
- * NtReplaceKey [NTDLL]
- * ZwReplaceKey
+ * NtReplaceKey [NTDLL.@]
+ * ZwReplaceKey [NTDLL.@]
*/
NTSTATUS WINAPI NtReplaceKey(
IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN HANDLE Key,
+ IN HKEY Key,
IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
{
- FIXME(ntdll,"(%p(%s),0x%08x,%p (%s)),stub!\n",
- ObjectAttributes,debugstr_w(ObjectAttributes->ObjectName->Buffer),Key,
- ReplacedObjectAttributes,debugstr_w(ReplacedObjectAttributes->ObjectName->Buffer));
- return 0;
-
+ FIXME("(%p),stub!\n", Key);
+ dump_ObjectAttributes(ObjectAttributes);
+ dump_ObjectAttributes(ReplacedObjectAttributes);
+ return STATUS_SUCCESS;
}
/******************************************************************************
- * NtRestoreKey [NTDLL]
- * ZwRestoreKey
+ * NtRestoreKey [NTDLL.@]
+ * ZwRestoreKey [NTDLL.@]
*/
NTSTATUS WINAPI NtRestoreKey(
- HANDLE KeyHandle,
+ HKEY KeyHandle,
HANDLE FileHandle,
ULONG RestoreFlags)
{
- FIXME(ntdll,"(0x%08x,0x%08x,0x%08lx) stub\n",
+ FIXME("(%p,%p,0x%08lx) stub\n",
KeyHandle, FileHandle, RestoreFlags);
- return 0;
-
+ return STATUS_SUCCESS;
}
/******************************************************************************
- * NtSaveKey [NTDLL]
- * ZwSaveKey
+ * NtSaveKey [NTDLL.@]
+ * ZwSaveKey [NTDLL.@]
*/
NTSTATUS WINAPI NtSaveKey(
- IN HANDLE KeyHandle,
+ IN HKEY KeyHandle,
IN HANDLE FileHandle)
{
- FIXME(ntdll,"(0x%08x,0x%08x) stub\n",
+ FIXME("(%p,%p) stub\n",
KeyHandle, FileHandle);
- return 0;
+ return STATUS_SUCCESS;
}
/******************************************************************************
- * NtSetInformationKey [NTDLL]
- * ZwSetInformationKey
+ * NtSetInformationKey [NTDLL.@]
+ * ZwSetInformationKey [NTDLL.@]
*/
NTSTATUS WINAPI NtSetInformationKey(
- IN HANDLE KeyHandle,
+ IN HKEY KeyHandle,
IN const int KeyInformationClass,
IN PVOID KeyInformation,
IN ULONG KeyInformationLength)
{
- FIXME(ntdll,"(0x%08x,0x%08x,%p,0x%08lx) stub\n",
+ FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
- return 0;
+ return STATUS_SUCCESS;
}
+
+
/******************************************************************************
- * NtSetValueKey [NTDLL]
- * ZwSetValueKey
+ * NtSetValueKey [NTDLL.@]
+ * ZwSetValueKey [NTDLL.@]
+ *
+ * NOTES
+ * win95 does not care about count for REG_SZ and finds out the len by itself (js)
+ * NT does definitely care (aj)
*/
-NTSTATUS WINAPI NtSetValueKey(
- HANDLE KeyHandle,
- PUNICODE_STRING ValueName,
- ULONG TitleIndex,
- ULONG Type,
- PVOID Data,
- ULONG DataSize)
+NTSTATUS WINAPI NtSetValueKey( HKEY hkey, const UNICODE_STRING *name, ULONG TitleIndex,
+ ULONG type, const void *data, ULONG count )
{
- FIXME(ntdll,"(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n",
- KeyHandle, ValueName,debugstr_w(ValueName->Buffer), TitleIndex, Type, Data, DataSize);
- return 1;
+ NTSTATUS ret;
+
+ TRACE( "(%p,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
+ if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
+
+ SERVER_START_REQ( set_key_value )
+ {
+ req->hkey = hkey;
+ req->type = type;
+ req->namelen = name->Length;
+ wine_server_add_data( req, name->Buffer, name->Length );
+ wine_server_add_data( req, data, count );
+ ret = wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ return ret;
}
/******************************************************************************
- * NtUnloadKey [NTDLL]
- * ZwUnloadKey
+ * RtlpNtSetValueKey [NTDLL.@]
+ *
+ */
+NTSTATUS WINAPI RtlpNtSetValueKey( HKEY hkey, ULONG type, const void *data,
+ ULONG count )
+{
+ UNICODE_STRING name;
+
+ name.Length = 0;
+ return NtSetValueKey( hkey, &name, 0, type, data, count );
+}
+
+/******************************************************************************
+ * NtUnloadKey [NTDLL.@]
+ * ZwUnloadKey [NTDLL.@]
*/
NTSTATUS WINAPI NtUnloadKey(
- IN HANDLE KeyHandle)
+ IN HKEY KeyHandle)
{
- FIXME(ntdll,"(0x%08x) stub\n",
+ FIXME("(%p) stub\n",
KeyHandle);
- return 0;
+ return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ * RtlFormatCurrentUserKeyPath [NTDLL.@]
+ *
+ * NOTE: under NT the user name part of the path is an SID.
+ */
+NTSTATUS WINAPI RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath)
+{
+ const char *user = wine_get_user_name();
+ char *buffer;
+ ANSI_STRING AnsiPath;
+ NTSTATUS ret;
+
+ if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, strlen(user)+16 )))
+ return STATUS_NO_MEMORY;
+
+ strcpy( buffer, "\\Registry\\User\\" );
+ strcat( buffer, user );
+ RtlInitAnsiString( &AnsiPath, buffer );
+ ret = RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
+ RtlFreeAnsiString( &AnsiPath );
+ return ret;
+}
+
+/******************************************************************************
+ * RtlOpenCurrentUser [NTDLL.@]
+ *
+ * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
+ * registry (odd handle) and fails
+ *
+ */
+DWORD WINAPI RtlOpenCurrentUser(
+ IN ACCESS_MASK DesiredAccess, /* [in] */
+ OUT PHKEY KeyHandle) /* [out] 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 = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
+ RtlFreeUnicodeString(&ObjectName);
+ return ret;
}