Moved most remaining file functions to dlls/kernel.
[wine] / dlls / ntdll / reg.c
index 5d5be5d..b213193 100644 (file)
+/*
+ * 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,
@@ -124,44 +586,10 @@ NTSTATUS WINAPI NtNotifyChangeKey(
        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;
 }
 
 /******************************************************************************
@@ -170,117 +598,172 @@ NTSTATUS WINAPI NtQueryKey(
  */
 
 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;
 }