Changed to use new server-side registry support.

diff --git a/dlls/advapi32/Makefile.in b/dlls/advapi32/Makefile.in
index fd09ec5..20788d0 100644
--- a/dlls/advapi32/Makefile.in
+++ b/dlls/advapi32/Makefile.in
@@ -11,6 +11,7 @@
 	advapi.c \
 	crypt.c \
 	eventlog.c \
+	registry.c \
 	security.c \
 	service.c
 
diff --git a/dlls/advapi32/registry.c b/dlls/advapi32/registry.c
new file mode 100644
index 0000000..6b8b581
--- /dev/null
+++ b/dlls/advapi32/registry.c
@@ -0,0 +1,1065 @@
+/*
+ * Registry management
+ *
+ * Copyright (C) 1999 Alexandre Julliard
+ *
+ * Based on misc/registry.c code
+ * Copyright (C) 1996 Marcus Meissner
+ * Copyright (C) 1998 Matthew Becker
+ * Copyright (C) 1999 Sylvain St-Germain
+ *
+ * This file is concerned about handle management and interaction with the Wine server.
+ * Registry file I/O is in misc/registry.c.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "wine/winbase16.h"
+#include "winversion.h"
+#include "file.h"
+#include "heap.h"
+#include "server.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(reg)
+
+
+/* Ansi->Unicode conversion without string delimiters */
+static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n )
+{
+    LPWSTR p = dst;
+    while (n-- > 0) *p++ = (WCHAR)*src++;
+    return dst;
+}
+
+/* Unicode->Ansi conversion without string delimiters */
+static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n )
+{
+    LPSTR p = dst;
+    while (n-- > 0) *p++ = (CHAR)*src++;
+    return dst;
+}
+
+/* check if value type needs string conversion (Ansi<->Unicode) */
+static inline int is_string( DWORD type )
+{
+    return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
+}
+
+/* copy key value data into a user-specified buffer
+ *
+ * 'len' is the total length of the data
+ * 'count' is the size of the user-specified buffer
+ * and is updated to reflect the length copied
+ */
+static DWORD copy_data( void *data, const void *src, DWORD len, DWORD *count )
+{
+    DWORD ret = ERROR_SUCCESS;
+    if (data)
+    {
+        if (*count < len) ret = ERROR_MORE_DATA;
+        else memcpy( data, src, len );
+    }
+    *count = len;
+    return ret;
+}
+
+/* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
+static DWORD copy_data_WtoA( void *data, const void *src, DWORD len, DWORD *count, DWORD type )
+{
+    DWORD ret = ERROR_SUCCESS;
+    if (is_string( type ))
+    {
+        /* need to convert from Unicode */
+        len /= sizeof(WCHAR);
+        if (data)
+        {
+            if (*count < len) ret = ERROR_MORE_DATA;
+            else memcpyWtoA( data, src, len );
+        }
+    }
+    else if (data)
+    {
+        if (*count < len) ret = ERROR_MORE_DATA;
+        else memcpy( data, src, len );
+    }
+    *count = len;
+    return ret;
+}
+
+/* copy a key name into the request buffer */
+static inline DWORD copy_nameW( LPWSTR dest, LPCWSTR name )
+{
+    if (name)
+    {
+        if (lstrlenW(name) > MAX_PATH) return ERROR_MORE_DATA;
+        lstrcpyW( dest, name );
+    }
+    else dest[0] = 0;
+    return ERROR_SUCCESS;
+}
+
+/* copy a key name into the request buffer */
+static inline DWORD copy_nameAtoW( LPWSTR dest, LPCSTR name )
+{
+    if (name)
+    {
+        if (strlen(name) > MAX_PATH) return ERROR_MORE_DATA;
+        lstrcpyAtoW( dest, name );
+    }
+    else dest[0] = 0;
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ *           RegCreateKeyExW   [ADVAPI32.131]
+ *
+ * PARAMS
+ *    hkey       [I] Handle of an open key
+ *    name       [I] Address of subkey name
+ *    reserved   [I] Reserved - must be 0
+ *    class      [I] Address of class string
+ *    options    [I] Special options flag
+ *    access     [I] Desired security access
+ *    sa         [I] Address of key security structure
+ *    retkey     [O] Address of buffer for opened handle
+ *    dispos     [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
+ */
+DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
+                              DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, 
+                              LPHKEY retkey, LPDWORD dispos )
+{
+    DWORD ret;
+    struct create_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
+           debugstr_w(class), options, access, sa, retkey, dispos );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+    if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
+
+    req->parent  = hkey;
+    req->access  = access;
+    req->options = options;
+    req->modif   = time(NULL);
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
+               server_remaining(req->class) / sizeof(WCHAR) );
+    if ((ret = server_call_noerr( REQ_CREATE_KEY )) == ERROR_SUCCESS)
+    {
+        *retkey = req->hkey;
+        if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegCreateKeyExA   [ADVAPI32.130]
+ */
+DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
+                              DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, 
+                              LPHKEY retkey, LPDWORD dispos )
+{
+    DWORD ret;
+    struct create_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
+           debugstr_a(class), options, access, sa, retkey, dispos );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+    if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
+
+    req->parent  = hkey;
+    req->access  = access;
+    req->options = options;
+    req->modif   = time(NULL);
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    lstrcpynAtoW( req->class, class ? class : "",
+                  server_remaining(req->class) / sizeof(WCHAR) );
+    if ((ret = server_call_noerr( REQ_CREATE_KEY )) == ERROR_SUCCESS)
+    {
+        *retkey = req->hkey;
+        if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegCreateKeyW   [ADVAPI32.132]
+ */
+DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
+{
+    /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
+    /* but at least my version of NT (4.0 SP5) doesn't do this.  -- AJ */
+    return RegCreateKeyExW( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
+                            KEY_ALL_ACCESS, NULL, retkey, NULL );
+}
+
+
+/******************************************************************************
+ *           RegCreateKeyA   [ADVAPI32.129]
+ */
+DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
+{
+    return RegCreateKeyExA( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
+                            KEY_ALL_ACCESS, NULL, retkey, NULL );
+}
+
+
+
+/******************************************************************************
+ *           RegOpenKeyExW   [ADVAPI32.150]
+ *
+ * Opens the specified key
+ *
+ * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
+ *
+ * PARAMS
+ *    hkey       [I] Handle of open key
+ *    name       [I] Name of subkey to open
+ *    reserved   [I] Reserved - must be zero
+ *    access     [I] Security access mask
+ *    retkey     [O] Handle to open key
+ *
+ * RETURNS
+ *    Success: ERROR_SUCCESS
+ *    Failure: Error code
+ */
+DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
+{
+    DWORD ret;
+    struct open_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
+
+    if (!retkey) return ERROR_INVALID_PARAMETER;
+
+    req->parent = hkey;
+    req->access = access;
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    if ((ret = server_call_noerr( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegOpenKeyExA   [ADVAPI32.149]
+ */
+DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
+{
+    DWORD ret;
+    struct open_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
+
+    if (!retkey) return ERROR_INVALID_PARAMETER;
+
+    req->parent = hkey;
+    req->access = access;
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    if ((ret = server_call_noerr( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegOpenKeyW   [ADVAPI32.151]
+ *
+ * PARAMS
+ *    hkey    [I] Handle of open key
+ *    name    [I] Address of name of subkey to open
+ *    retkey  [O] Handle to open key
+ *
+ * RETURNS
+ *    Success: ERROR_SUCCESS
+ *    Failure: Error code
+ */
+DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
+{
+    return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
+}
+
+
+/******************************************************************************
+ *           RegOpenKeyA   [ADVAPI32.148]
+ */
+DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
+{
+    return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
+}
+
+
+
+/******************************************************************************
+ *           RegEnumKeyExW   [ADVAPI32.139]
+ *
+ * PARAMS
+ *    hkey         [I] Handle to key to enumerate
+ *    index        [I] Index of subkey to enumerate
+ *    name         [O] Buffer for subkey name
+ *    name_len     [O] Size of subkey buffer
+ *    reserved     [I] Reserved
+ *    class        [O] Buffer for class string
+ *    class_len    [O] Size of class buffer
+ *    ft           [O] Time key last written to
+ */
+DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
+                            LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
+{
+    DWORD ret, len, cls_len;
+    struct enum_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
+           name_len ? *name_len : -1, reserved, class, class_len, ft );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    req->index = index;
+    if ((ret = server_call_noerr( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+
+    len = lstrlenW( req->name ) + 1;
+    cls_len = lstrlenW( req->class ) + 1;
+    if (len > *name_len) return ERROR_MORE_DATA;
+    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+
+    memcpy( name, req->name, len * sizeof(WCHAR) );
+    *name_len = len - 1;
+    if (class_len)
+    {
+        if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
+        *class_len = cls_len - 1;
+    }
+    if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ *           RegEnumKeyExA   [ADVAPI32.138]
+ */
+DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
+                            LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
+{
+    DWORD ret, len, cls_len;
+    struct enum_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
+           name_len ? *name_len : -1, reserved, class, class_len, ft );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    req->index = index;
+    if ((ret = server_call_noerr( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
+
+    len = lstrlenW( req->name ) + 1;
+    cls_len = lstrlenW( req->class ) + 1;
+    if (len > *name_len) return ERROR_MORE_DATA;
+    if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
+
+    memcpyWtoA( name, req->name, len );
+    *name_len = len - 1;
+    if (class_len)
+    {
+        if (class) memcpyWtoA( class, req->class, cls_len );
+        *class_len = cls_len - 1;
+    }
+    if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ *           RegEnumKeyW   [ADVAPI32.140]
+ */
+DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
+{
+    return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
+}
+
+
+/******************************************************************************
+ *           RegEnumKeyA   [ADVAPI32.137]
+ */
+DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
+{
+    return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
+}
+
+
+/******************************************************************************
+ *           RegQueryInfoKeyW   [ADVAPI32.153]
+ *
+ * PARAMS
+ *    hkey       [I] Handle to key to query
+ *    class      [O] Buffer for class string
+ *    class_len  [O] Size of class string buffer
+ *    reserved   [I] Reserved
+ *    subkeys    [O] Buffer for number of subkeys
+ *    max_subkey [O] Buffer for longest subkey name length
+ *    max_class  [O] Buffer for longest class string length
+ *    values     [O] Buffer for number of value entries
+ *    max_value  [O] Buffer for longest value name length
+ *    max_data   [O] Buffer for longest value data length
+ *    security   [O] Buffer for security descriptor length
+ *    modif      [O] Modification time
+ *
+ * - win95 allows class to be valid and class_len to be NULL 
+ * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
+ * - both allow class to be NULL and class_len to be NULL 
+ * (it's hard to test validity, so test !NULL instead)
+ */
+DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
+                               LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
+                               LPDWORD values, LPDWORD max_value, LPDWORD max_data,
+                               LPDWORD security, FILETIME *modif )
+{
+    DWORD ret;
+    struct query_key_info_request *req = get_req_buffer();
+
+
+    TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
+           reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
+
+    if (class && !class_len && (VERSION_GetVersion() == NT40))
+        return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    if ((ret = server_call_noerr( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+
+    if (class)
+    {
+        if (class_len && (lstrlenW(req->class) + 1 > *class_len))
+        {
+            *class_len = lstrlenW(req->class);
+            return ERROR_MORE_DATA;
+        }
+        lstrcpyW( class, req->class );
+    }
+    if (class_len) *class_len = lstrlenW( req->class );
+    if (subkeys) *subkeys = req->subkeys;
+    if (max_subkey) *max_subkey = req->max_subkey;
+    if (max_class) *max_class = req->max_class;
+    if (values) *values = req->values;
+    if (max_value) *max_value = req->max_value;
+    if (max_data) *max_data = req->max_data;
+    if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ *           RegQueryInfoKeyA   [ADVAPI32.152]
+ */
+DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
+                               LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
+                               LPDWORD values, LPDWORD max_value, LPDWORD max_data,
+                               LPDWORD security, FILETIME *modif )
+{
+    DWORD ret;
+    struct query_key_info_request *req = get_req_buffer();
+
+
+    TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
+           reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
+
+    if (class && !class_len && (VERSION_GetVersion() == NT40))
+        return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    if ((ret = server_call_noerr( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
+
+    if (class)
+    {
+        if (class_len && (lstrlenW(req->class) + 1 > *class_len))
+        {
+            *class_len = lstrlenW(req->class);
+            return ERROR_MORE_DATA;
+        }
+        lstrcpyWtoA( class, req->class );
+    }
+    if (class_len) *class_len = lstrlenW( req->class );
+    if (subkeys) *subkeys = req->subkeys;
+    if (max_subkey) *max_subkey = req->max_subkey;
+    if (max_class) *max_class = req->max_class;
+    if (values) *values = req->values;
+    if (max_value) *max_value = req->max_value;
+    if (max_data) *max_data = req->max_data;
+    if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
+    return ERROR_SUCCESS;
+}
+
+
+/******************************************************************************
+ *           RegCloseKey   [ADVAPI32.126]
+ *
+ * Releases the handle of the specified key
+ *
+ * PARAMS
+ *    hkey [I] Handle of key to close
+ *
+ * RETURNS
+ *    Success: ERROR_SUCCESS
+ *    Failure: Error code
+ */
+DWORD WINAPI RegCloseKey( HKEY hkey )
+{
+    struct close_key_request *req = get_req_buffer();
+    TRACE( "(0x%x)\n", hkey );
+    req->hkey = hkey;
+    return server_call_noerr( REQ_CLOSE_KEY );
+}
+
+
+/******************************************************************************
+ *           RegDeleteKeyW   [ADVAPI32.134]
+ *
+ * PARAMS
+ *    hkey   [I] Handle to open key
+ *    name   [I] Name of subkey to delete
+ *
+ * RETURNS
+ *    Success: ERROR_SUCCESS
+ *    Failure: Error code
+ */
+DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
+{
+    DWORD ret;
+    struct delete_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
+
+    req->hkey = hkey;
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    return server_call_noerr( REQ_DELETE_KEY );
+}
+
+
+/******************************************************************************
+ *           RegDeleteKeyA   [ADVAPI32.133]
+ */
+DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
+{
+    DWORD ret;
+    struct delete_key_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
+
+    req->hkey = hkey;
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
+    return server_call_noerr( REQ_DELETE_KEY );
+}
+
+
+
+/******************************************************************************
+ *           RegSetValueExW   [ADVAPI32.170]
+ *
+ * Sets the data and type of a value under a register key
+ *
+ * PARAMS
+ *    hkey       [I] Handle of key to set value for
+ *    name       [I] Name of value to set
+ *    reserved   [I] Reserved - must be zero
+ *    type       [I] Flag for value type
+ *    data       [I] Address of value data
+ *    count      [I] Size of value data
+ *
+ * RETURNS
+ *    Success: ERROR_SUCCESS
+ *    Failure: Error code
+ *
+ * NOTES
+ *   win95 does not care about count for REG_SZ and finds out the len by itself (js) 
+ *   NT does definitely care (aj)
+ */
+DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
+                             DWORD type, CONST BYTE *data, DWORD count )
+{
+    DWORD ret;
+    struct set_key_value_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+
+    if (count && type == REG_SZ)
+    {
+        LPCWSTR str = (LPCWSTR)data;
+        /* if user forgot to count terminating null, add it (yes NT does this) */
+        if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
+            count += sizeof(WCHAR);
+    }
+    if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY;  /* FIXME */
+    req->hkey = hkey;
+    req->type = type;
+    req->len = count;
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    memcpy( req->data, data, count );
+    return server_call_noerr( REQ_SET_KEY_VALUE );
+}
+
+
+/******************************************************************************
+ *           RegSetValueExA   [ADVAPI32.169]
+ */
+DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
+			     CONST BYTE *data, DWORD count )
+{
+    DWORD ret;
+    struct set_key_value_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
+
+    if (reserved) return ERROR_INVALID_PARAMETER;
+
+    if (count && type == REG_SZ)
+    {
+        /* if user forgot to count terminating null, add it (yes NT does this) */
+        if (data[count-1] && !data[count]) count++;
+    }
+    if (is_string( type ))
+    {
+        /* need to convert to Unicode */
+        count *= sizeof(WCHAR);
+        if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY;  /* FIXME */
+        memcpyAtoW( (LPWSTR)req->data, data, count / sizeof(WCHAR) );
+    }
+    else
+    {
+        if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY;  /* FIXME */
+        memcpy( req->data, data, count );
+    }
+    req->hkey = hkey;
+    req->type = type;
+    req->len = count;
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    return server_call_noerr( REQ_SET_KEY_VALUE );
+}
+
+
+/******************************************************************************
+ *           RegSetValueW   [ADVAPI32.171]
+ */
+DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
+{
+    HKEY subkey = hkey;
+    DWORD ret;
+
+    TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
+
+    if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
+
+    if (name && name[0])  /* need to create the subkey */
+    {
+        if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
+    }
+
+    ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data,
+                          (lstrlenW( data ) + 1) * sizeof(WCHAR) );
+    if (subkey != hkey) RegCloseKey( subkey );
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegSetValueA   [ADVAPI32.168]
+ */
+DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
+{
+    HKEY subkey = hkey;
+    DWORD ret;
+
+    TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
+
+    if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
+
+    if (name && name[0])  /* need to create the subkey */
+    {
+        if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
+    }
+    ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 );
+    if (subkey != hkey) RegCloseKey( subkey );
+    return ret;
+}
+
+
+
+/******************************************************************************
+ *           RegQueryValueExW   [ADVAPI32.158]
+ *
+ * Retrieves type and data for a specified name associated with an open key
+ *
+ * PARAMS
+ *    hkey      [I]   Handle of key to query
+ *    name      [I]   Name of value to query
+ *    reserved  [I]   Reserved - must be NULL
+ *    type      [O]   Address of buffer for value type.  If NULL, the type
+ *                        is not required.
+ *    data      [O]   Address of data buffer.  If NULL, the actual data is
+ *                        not required.
+ *    count     [I/O] Address of data buffer size
+ *
+ * RETURNS 
+ *    ERROR_SUCCESS:   Success
+ *    ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
+ * 		       buffer is left untouched. The MS-documentation is wrong (js) !!!
+ */
+DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
+			       LPBYTE data, LPDWORD count )
+{
+    DWORD ret;
+    struct get_key_value_request *req = get_req_buffer();
+
+    TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
+          hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
+
+    if (!count || reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if ((ret = server_call_noerr( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
+    {
+        if (type) *type = req->type;
+        ret = copy_data( data, req->data, req->len, count );
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegQueryValueExA   [ADVAPI32.157]
+ *
+ * NOTES:
+ * the documentation is wrong: if the buffer is to small it remains untouched 
+ */
+DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
+			       LPBYTE data, LPDWORD count )
+{
+    DWORD ret;
+    struct get_key_value_request *req = get_req_buffer();
+
+    TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
+          hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
+
+    if (!count || reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    if ((ret = server_call_noerr( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
+    {
+        if (type) *type = req->type;
+        ret = copy_data_WtoA( data, req->data, req->len, count, req->type );
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegQueryValueW   [ADVAPI32.159]
+ */
+DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
+{
+    DWORD ret;
+    HKEY subkey = hkey;
+
+    TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
+
+    if (name && name[0])
+    {
+        if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
+    }
+    ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
+    if (subkey != hkey) RegCloseKey( subkey );
+    if (ret == ERROR_FILE_NOT_FOUND)
+    {
+        /* return empty string if default value not found */
+        if (data) *data = 0;
+        if (count) *count = 1;
+        ret = ERROR_SUCCESS;
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegQueryValueA   [ADVAPI32.156]
+ */
+DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
+{
+    DWORD ret;
+    HKEY subkey = hkey;
+
+    TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
+
+    if (name && name[0])
+    {
+        if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
+    }
+    ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
+    if (subkey != hkey) RegCloseKey( subkey );
+    if (ret == ERROR_FILE_NOT_FOUND)
+    {
+        /* return empty string if default value not found */
+        if (data) *data = 0;
+        if (count) *count = 1;
+        ret = ERROR_SUCCESS;
+    }
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegEnumValueW   [ADVAPI32.142]
+ *
+ * PARAMS
+ *    hkey       [I] Handle to key to query
+ *    index      [I] Index of value to query
+ *    value      [O] Value string
+ *    val_count  [I/O] Size of value buffer (in wchars)
+ *    reserved   [I] Reserved
+ *    type       [O] Type code
+ *    data       [O] Value data
+ *    count      [I/O] Size of data buffer (in bytes)
+ */
+
+DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
+                            LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
+{
+    DWORD ret, len;
+    struct enum_key_value_request *req = get_req_buffer();
+
+    TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
+          hkey, index, value, val_count, reserved, type, data, count );
+
+    /* NT only checks count, not val_count */
+    if (!count || reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    req->index = index;
+    if ((ret = server_call_noerr( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
+
+    len = lstrlenW( req->name ) + 1;
+    if (len > *val_count) return ERROR_MORE_DATA;
+    memcpy( value, req->name, len * sizeof(WCHAR) );
+    *val_count = len - 1;
+
+    if (type) *type = req->type;
+    return copy_data( data, req->data, req->len, count );
+}
+
+
+/******************************************************************************
+ *           RegEnumValueA   [ADVAPI32.141]
+ */
+DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
+                            LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
+{
+    DWORD ret, len;
+    struct enum_key_value_request *req = get_req_buffer();
+
+    TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
+          hkey, index, value, val_count, reserved, type, data, count );
+
+    /* NT only checks count, not val_count */
+    if (!count || reserved) return ERROR_INVALID_PARAMETER;
+
+    req->hkey = hkey;
+    req->index = index;
+    if ((ret = server_call_noerr( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
+
+    len = lstrlenW( req->name ) + 1;
+    if (len > *val_count) return ERROR_MORE_DATA;
+    memcpyWtoA( value, req->name, len );
+    *val_count = len - 1;
+
+    if (type) *type = req->type;
+    return copy_data_WtoA( data, req->data, req->len, count, req->type );
+}
+
+
+
+/******************************************************************************
+ *           RegDeleteValueW   [ADVAPI32.136]
+ *
+ * PARAMS
+ *    hkey   [I] handle to key
+ *    name   [I] name of value to delete
+ *
+ * RETURNS
+ *    error status
+ */
+DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
+{
+    DWORD ret;
+    struct delete_key_value_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
+
+    req->hkey = hkey;
+    if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
+    return server_call_noerr( REQ_DELETE_KEY_VALUE );
+}
+
+
+/******************************************************************************
+ *           RegDeleteValueA   [ADVAPI32.135]
+ */
+DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
+{
+    DWORD ret;
+    struct delete_key_value_request *req = get_req_buffer();
+
+    TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
+
+    req->hkey = hkey;
+    if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
+    return server_call_noerr( REQ_DELETE_KEY_VALUE );
+}
+
+
+/******************************************************************************
+ *           RegLoadKeyW   [ADVAPI32.185]
+ *
+ * PARAMS
+ *    hkey      [I] Handle of open key
+ *    subkey    [I] Address of name of subkey
+ *    filename  [I] Address of filename for registry information
+ */
+LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
+{
+    struct load_registry_request *req = get_req_buffer();
+    HANDLE file;
+    DWORD ret, err = GetLastError();
+
+    TRACE( "(%x,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) );
+
+    if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
+    if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
+
+    if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
+    {
+        ret = GetLastError();
+        goto done;
+    }
+    req->hkey  = hkey;
+    req->file  = file;
+    if ((ret = copy_nameW( req->name, subkey )) != ERROR_SUCCESS) goto done;
+    ret = server_call_noerr( REQ_LOAD_REGISTRY );
+    CloseHandle( file );
+
+ done:
+    SetLastError( err );  /* restore the last error code */
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegLoadKeyA   [ADVAPI32.184]
+ */
+LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
+{
+    struct load_registry_request *req = get_req_buffer();
+    HANDLE file;
+    DWORD ret, err = GetLastError();
+
+    TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
+
+    if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
+    if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
+
+    if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+                             FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
+    {
+        ret = GetLastError();
+        goto done;
+    }
+    req->hkey  = hkey;
+    req->file  = file;
+    if ((ret = copy_nameAtoW( req->name, subkey )) != ERROR_SUCCESS) goto done;
+    ret = server_call_noerr( REQ_LOAD_REGISTRY );
+    CloseHandle( file );
+
+ done:
+    SetLastError( err );  /* restore the last error code */
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegSaveKeyA   [ADVAPI32.165]
+ *
+ * PARAMS
+ *    hkey   [I] Handle of key where save begins
+ *    lpFile [I] Address of filename to save to
+ *    sa     [I] Address of security structure
+ */
+LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
+{
+    struct save_registry_request *req = get_req_buffer();
+    char buffer[1024];
+    int count = 0;
+    LPSTR name;
+    DWORD ret, err;
+    HFILE handle;
+
+    TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
+
+    if (!file || !*file) return ERROR_INVALID_PARAMETER;
+
+    err = GetLastError();
+    GetFullPathNameA( file, sizeof(buffer), buffer, &name );
+    for (;;)
+    {
+        sprintf( name, "reg%04x.tmp", count++ );
+        handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
+                            CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
+        if (handle != INVALID_HANDLE_VALUE) break;
+        if ((ret = GetLastError()) != ERROR_FILE_EXISTS) goto done;
+    }
+
+    req->hkey = hkey;
+    req->file = handle;
+    ret = server_call_noerr( REQ_SAVE_REGISTRY );
+    CloseHandle( handle );
+    if (!ret)
+    {
+        if (!MoveFileExA( buffer, file, MOVEFILE_REPLACE_EXISTING ))
+        {
+            ERR( "Failed to move %s to %s\n", buffer, file );
+            ret = GetLastError();
+        }
+    }
+    if (ret) DeleteFileA( buffer );
+
+done:
+    SetLastError( err );  /* restore last error code */
+    return ret;
+}
+
+
+/******************************************************************************
+ *           RegSaveKeyW   [ADVAPI32.166]
+ */
+LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
+{
+    LPSTR fileA = HEAP_strdupWtoA( GetProcessHeap(), 0, file );
+    DWORD ret = RegSaveKeyA( hkey, fileA, sa );
+    if (fileA) HeapFree( GetProcessHeap(), 0, fileA );
+    return ret;
+}
diff --git a/dlls/shell32/shell.spec b/dlls/shell32/shell.spec
index 656c321..adafd39 100644
--- a/dlls/shell32/shell.spec
+++ b/dlls/shell32/shell.spec
@@ -3,7 +3,7 @@
 
   1 pascal   RegOpenKey(long str ptr) RegOpenKey16
   2 pascal   RegCreateKey(long str ptr) RegCreateKey16
-  3 pascal   RegCloseKey(long) RegCloseKey
+  3 pascal   RegCloseKey(long) RegCloseKey16
   4 pascal   RegDeleteKey(long str) RegDeleteKey16
   5 pascal   RegSetValue(long str long str long) RegSetValue16
   6 pascal   RegQueryValue(long str ptr ptr) RegQueryValue16
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 7f32d63..369bd2f 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -226,7 +226,7 @@
 217 pascal RegOpenKey(long str ptr) RegOpenKey16                          # Both 95/NT
 218 pascal RegCreateKey(long str ptr) RegCreateKey16
 219 pascal RegDeleteKey(long str) RegDeleteKey16
-220 pascal RegCloseKey(long) RegCloseKey                                  # Both 95/NT
+220 pascal RegCloseKey(long) RegCloseKey16                                # Both 95/NT
 221 pascal RegSetValue(long str long ptr long) RegSetValue16
 222 pascal RegDeleteValue(long str) RegDeleteValue16
 223 pascal RegEnumValue(long long ptr ptr ptr ptr ptr ptr) RegEnumValue16 # Both 95/NT
diff --git a/include/wine/winbase16.h b/include/wine/winbase16.h
index 428cde9..7f8158f 100644
--- a/include/wine/winbase16.h
+++ b/include/wine/winbase16.h
@@ -166,16 +166,17 @@
 HGLOBAL16   WINAPI LockSegment16(HGLOBAL16);
 FARPROC16   WINAPI MakeProcInstance16(FARPROC16,HANDLE16);
 VOID        WINAPI OutputDebugString16(LPCSTR);
+DWORD       WINAPI RegCloseKey16(HKEY);
 DWORD       WINAPI RegCreateKey16(HKEY,LPCSTR,LPHKEY);
 DWORD       WINAPI RegDeleteKey16(HKEY,LPCSTR);
 DWORD       WINAPI RegDeleteValue16(HKEY,LPSTR);
 DWORD       WINAPI RegEnumKey16(HKEY,DWORD,LPSTR,DWORD);
 DWORD       WINAPI RegEnumValue16(HKEY,DWORD,LPSTR,LPDWORD,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
 DWORD       WINAPI RegOpenKey16(HKEY,LPCSTR,LPHKEY);
-DWORD       WINAPI RegQueryValue16(HKEY,LPSTR,LPSTR,LPDWORD);
-DWORD       WINAPI RegQueryValueEx16(HKEY,LPSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
+DWORD       WINAPI RegQueryValue16(HKEY,LPCSTR,LPSTR,LPDWORD);
+DWORD       WINAPI RegQueryValueEx16(HKEY,LPCSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
 DWORD       WINAPI RegSetValue16(HKEY,LPCSTR,DWORD,LPCSTR,DWORD);
-DWORD       WINAPI RegSetValueEx16(HKEY,LPSTR,DWORD,DWORD,LPBYTE,DWORD);
+DWORD       WINAPI RegSetValueEx16(HKEY,LPCSTR,DWORD,DWORD,CONST BYTE*,DWORD);
 BOOL16      WINAPI RemoveDirectory16(LPCSTR);
 BOOL16      WINAPI SetCurrentDirectory16(LPCSTR);
 UINT16      WINAPI SetErrorMode16(UINT16);
diff --git a/include/winnt.h b/include/winnt.h
index e00a560..691bd3d 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -1282,6 +1282,9 @@
 #define GENERIC_EXECUTE            0x20000000
 #define GENERIC_ALL                0x10000000
 
+#define MAXIMUM_ALLOWED            0x02000000
+#define ACCESS_SYSTEM_SECURITY     0x01000000
+
 #define EVENT_MODIFY_STATE         0x0002
 #define EVENT_ALL_ACCESS           (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
 
diff --git a/include/winreg.h b/include/winreg.h
index 9b5e4cf..f072694 100644
--- a/include/winreg.h
+++ b/include/winreg.h
@@ -50,7 +50,6 @@
 #define	REG_OPTION_VOLATILE		0x00000001
 #define	REG_OPTION_CREATE_LINK		0x00000002
 #define	REG_OPTION_BACKUP_RESTORE	0x00000004 /* FIXME */
-#define	REG_OPTION_TAINTED		0x80000000 /* Internal? */
 
 #define REG_CREATED_NEW_KEY	0x00000001
 #define REG_OPENED_EXISTING_KEY	0x00000002
diff --git a/misc/registry.c b/misc/registry.c
index 2c93d17..7e22ddb 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -46,9 +46,9 @@
 #include "options.h"
 #include "winreg.h"
 #include "winversion.h"
+#include "server.h"
 
-DECLARE_DEBUG_CHANNEL(reg)
-DECLARE_DEBUG_CHANNEL(string)
+DEFAULT_DEBUG_CHANNEL(reg)
 
 static void REGISTRY_Init(void);
 /* FIXME: following defines should be configured global ... */
@@ -66,56 +66,11 @@
 #define KEY_REGISTRY                "Software\\The WINE team\\WINE\\Registry"
 #define VAL_SAVEUPDATED             "SaveOnlyUpdatedKeys"
 
-/* one value of a key */
-typedef struct tagKEYVALUE
-{
-    LPWSTR   name;          /* name of value (UNICODE) or NULL for win31 */
-    DWORD    type;          /* type of value */
-    DWORD    len;           /* length of data in BYTEs */
-    DWORD    lastmodified;  /* time of seconds since 1.1.1970 */
-    LPBYTE   data;          /* content, may be strings, binaries, etc. */
-} KEYVALUE,*LPKEYVALUE;
-
-/* a registry key */
-typedef struct tagKEYSTRUCT
-{
-    LPWSTR               keyname;       /* name of THIS key (UNICODE) */
-    DWORD                flags;         /* flags. */
-    LPWSTR               class;
-    /* values */
-    DWORD                nrofvalues;    /* nr of values in THIS key */
-    LPKEYVALUE           values;        /* values in THIS key */
-    /* key management pointers */
-    struct tagKEYSTRUCT	*next;          /* next key on same hierarchy */
-    struct tagKEYSTRUCT	*nextsub;       /* keys that hang below THIS key */
-} KEYSTRUCT, *LPKEYSTRUCT;
-
-
-static KEYSTRUCT	*key_classes_root=NULL;	/* windows 3.1 global values */
-static KEYSTRUCT	*key_current_user=NULL;	/* user specific values */
-static KEYSTRUCT	*key_local_machine=NULL;/* machine specific values */
-static KEYSTRUCT	*key_users=NULL;	/* all users? */
-
-/* dynamic, not saved */
-static KEYSTRUCT	*key_performance_data=NULL;
-static KEYSTRUCT	*key_current_config=NULL;
-static KEYSTRUCT	*key_dyn_data=NULL;
 
 /* what valuetypes do we need to convert? */
 #define UNICONVMASK	((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
 
 
-static struct openhandle {
-	LPKEYSTRUCT	lpkey;
-	HKEY		hkey;
-	REGSAM		accessmask;
-}  *openhandles=NULL;
-static int	nrofopenhandles=0;
-/* Starts after 1 because 0,1 are reserved for Win16 */
-/* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd
-         HKEYs for remote registry access */
-static int	currenthandle=2;
-
 
 /*
  * QUESTION
@@ -136,19 +91,6 @@
     return NULL;
 }
 
-static LPWSTR strdupW(LPCWSTR a) {
-	LPWSTR	b;
-	int	len;
-
-    if(a) {
-	len=sizeof(WCHAR)*(lstrlenW(a)+1);
-	b=(LPWSTR)xmalloc(len);
-	memcpy(b,a,len);
-	return b;
-    }
-    return NULL;
-}
-
 LPWSTR strcvtA2W(LPCSTR src, int nchars)
 
 {
@@ -158,388 +100,6 @@
    dest[nchars] = 0;
    return dest;
 }
-/*
- * we need to convert A to W with '\0' in strings (MULTI_SZ) 
- */
-
-static LPWSTR  lmemcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
-{	LPWSTR p = dst;
-
-	TRACE_(reg)("\"%s\" %i\n",src, n);
-
-	while (n-- > 0) *p++ = (WCHAR)(unsigned char)*src++;
-
-	return dst;
-}
-static LPSTR lmemcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
-{	LPSTR p = dst;
-
-	TRACE_(string)("L\"%s\" %i\n",debugstr_w(src), n);
-
-	while (n-- > 0) *p++ = (CHAR)*src++;
-
-	return dst;
-}
-
-static void debug_print_value (LPBYTE lpbData, LPKEYVALUE key)
-{
-  if (TRACE_ON(reg) && lpbData) 
-  { 
-    switch(key->type)
-    { 
-      case REG_EXPAND_SZ:
-      case REG_SZ:
-        TRACE_(reg)(" Value %s, Data(sz)=%s\n", 
-          debugstr_w(key->name), 
-          debugstr_w((LPCWSTR)lpbData));
-        break;
-
-      case REG_DWORD:
-        TRACE_(reg)(" Value %s, Data(dword)=0x%08lx\n",
-          debugstr_w(key->name), 
-          (DWORD)*lpbData);
-        break;
-    
-      case REG_MULTI_SZ:
-      { 
-        int i;
-        LPCWSTR ptr = (LPCWSTR)lpbData;
-        for (i=0;ptr[0];i++)
-        { 
-          TRACE_(reg)(" Value %s, MULTI_SZ(%i=%s)\n", 
-            debugstr_w(key->name), 
-            i, 
-            debugstr_w(ptr));
-
-          ptr += lstrlenW(ptr)+1;
-        }
-      }
-      break;
-
-      default:
-      { 
-        char szTemp[100];      /* 3*32 + 3 + 1 */
-        int i;
-        for ( i = 0; i < key->len ; i++)      
-        { 
-          sprintf (&(szTemp[i*3]),"%02x ", lpbData[i]);
-          if (i>=31)
-          { 
-            sprintf (&(szTemp[i*3+3]),"...");
-            break;
-          }
-        }
-        TRACE_(reg)(" Value %s, Data(raw)=(%s)\n", 
-          debugstr_w(key->name), 
-          szTemp);                  
-      }
-    } /* switch */
-  } /* if */
-}
-
-
-/******************************************************************************
- * is_standard_hkey [Internal]
- * Determines if a hkey is a standard key
- */
-static BOOL is_standard_hkey( HKEY hkey )
-{
-    switch(hkey) {
-        case 0x00000000:
-        case 0x00000001:
-        case HKEY_CLASSES_ROOT:
-        case HKEY_CURRENT_CONFIG:
-        case HKEY_CURRENT_USER:
-        case HKEY_LOCAL_MACHINE:
-        case HKEY_USERS:
-        case HKEY_PERFORMANCE_DATA:
-        case HKEY_DYN_DATA:
-            return TRUE;
-        default:
-            return FALSE;
-    }
-}
-
-/******************************************************************************
- * add_handle [Internal]
- */
-static void add_handle( HKEY hkey, LPKEYSTRUCT lpkey, REGSAM accessmask )
-{
-    int i;
-
-    TRACE_(reg)("(0x%x,%p,0x%lx)\n",hkey,lpkey,accessmask);
-    /* Check for duplicates */
-    for (i=0;i<nrofopenhandles;i++) {
-        if (openhandles[i].lpkey==lpkey) {
-            /* This is not really an error - the user is allowed to create
-               two (or more) handles to the same key */
-            /*WARN(reg, "Adding key %p twice\n",lpkey);*/
-        }
-        if (openhandles[i].hkey==hkey) {
-            WARN_(reg)("Adding handle %x twice\n",hkey);
-        }
-    }
-    openhandles=xrealloc( openhandles, 
-                          sizeof(struct openhandle)*(nrofopenhandles+1));
-
-    openhandles[i].lpkey = lpkey;
-    openhandles[i].hkey = hkey;
-    openhandles[i].accessmask = accessmask;
-    nrofopenhandles++;
-}
-
-
-/******************************************************************************
- * get_handle [Internal]
- *
- * RETURNS
- *    Success: Pointer to key
- *    Failure: NULL
- */
-static LPKEYSTRUCT get_handle( HKEY hkey )
-{
-    int i;
-
-    for (i=0; i<nrofopenhandles; i++)
-        if (openhandles[i].hkey == hkey)
-            return openhandles[i].lpkey;
-    WARN_(reg)("Could not find handle 0x%x\n",hkey);
-    return NULL;
-}
-
-
-/******************************************************************************
- * remove_handle [Internal]
- *
- * PARAMS
- *    hkey [I] Handle of key to remove
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: ERROR_INVALID_HANDLE
- */
-static DWORD remove_handle( HKEY hkey )
-{
-    int i;
-
-    for (i=0;i<nrofopenhandles;i++)
-        if (openhandles[i].hkey==hkey)
-            break;
-
-    if (i == nrofopenhandles) {
-        WARN_(reg)("Could not find handle 0x%x\n",hkey);
-        return ERROR_INVALID_HANDLE;
-    }
-
-    memcpy( openhandles+i,
-            openhandles+i+1,
-            sizeof(struct openhandle)*(nrofopenhandles-i-1)
-    );
-    openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
-    nrofopenhandles--;
-    return ERROR_SUCCESS;
-}
-
-/******************************************************************************
- * lookup_hkey [Internal]
- * 
- * Just as the name says. Creates the root keys on demand, so we can call the
- * Reg* functions at any time.
- *
- * RETURNS
- *    Success: Pointer to key structure
- *    Failure: NULL
- */
-#define ADD_ROOT_KEY(xx) \
-	xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
-	memset(xx,'\0',sizeof(KEYSTRUCT));\
-	xx->keyname= strdupA2W("<should_not_appear_anywhere>");
-
-static LPKEYSTRUCT lookup_hkey( HKEY hkey )
-{
-  switch (hkey) {
-  /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
-   * some programs. Do not remove those cases. -MM
-   */
- 	case 0x00000000:
-  case 0x00000001:
-  case HKEY_CLASSES_ROOT: 
-  {
-    if (!key_classes_root) 
-    {
-      HKEY	cl_r_hkey;
-
-      /* calls lookup_hkey recursively, TWICE */
-      if ( RegCreateKey16(
-            HKEY_LOCAL_MACHINE,
-            "SOFTWARE\\Classes",
-            &cl_r_hkey) != ERROR_SUCCESS) 
-      {
-        ERR_(reg)("Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
-        exit(1);
-      }
-
-      key_classes_root = lookup_hkey(cl_r_hkey);
-    }
-    return key_classes_root;
-  }
-
-  case HKEY_CURRENT_USER:
-    if (!key_current_user) {
-      ADD_ROOT_KEY(key_current_user);
-    }
-    return key_current_user;
-
-  case HKEY_LOCAL_MACHINE:
-    if (!key_local_machine) {
-      ADD_ROOT_KEY(key_local_machine);
-      REGISTRY_Init();
-    }
-    return key_local_machine;
-
-  case HKEY_USERS:
-    if (!key_users) {
-      ADD_ROOT_KEY(key_users);
-    }
-    return key_users;
-
-  case HKEY_PERFORMANCE_DATA:
-    if (!key_performance_data) {
-      ADD_ROOT_KEY(key_performance_data);
-    }
-    return key_performance_data;
-
-  case HKEY_DYN_DATA:
-    if (!key_dyn_data) {
-      ADD_ROOT_KEY(key_dyn_data);
-    }
-    return key_dyn_data;
-
-  case HKEY_CURRENT_CONFIG:
-    if (!key_current_config) {
-      ADD_ROOT_KEY(key_current_config);
-    }
-    return key_current_config;
-
-  default:
-    return get_handle(hkey);
-
-  }
-  /*NOTREACHED*/
-}
-
-
-/*
- * recursively searches for lpkey_to_find in the root key branch
- * given in lpcurrkey.
- */
-static int subkey_found(LPKEYSTRUCT lpcurrkey, LPKEYSTRUCT lpkey_to_find)
-{
-	while (lpcurrkey)
-	{
-		if (lpcurrkey == lpkey_to_find)
-			return 1;
-		if (subkey_found(lpcurrkey->nextsub, lpkey_to_find))
-			return 1;
-
-		lpcurrkey = lpcurrkey->next;
-	}
-
-	TRACE_(reg)("No key found in this root key branch\n");
-	return 0;
-}
-
-
-/*
- * finds the corresponding root key for a sub key, i.e. e.g. HKEY_CLASSES_ROOT.
- */ 
-static HKEY find_root_key(LPKEYSTRUCT lpkey)
-{
-	typedef struct tagROOT_KEYS {
-    		KEYSTRUCT *lpkey;
-    		HKEY hkey;
-	} ROOT_KEYS;
-	ROOT_KEYS root_keys[4];
-	int i;
-
-	root_keys[0].lpkey = key_classes_root;
-	root_keys[0].hkey = HKEY_CLASSES_ROOT;
-	root_keys[1].lpkey = key_current_user;
-	root_keys[1].hkey = HKEY_CURRENT_USER;
-	root_keys[2].lpkey = key_local_machine;
-	root_keys[2].hkey = HKEY_LOCAL_MACHINE;
-	root_keys[3].lpkey = key_users;
-	root_keys[3].hkey = HKEY_USERS;
-
-	for (i=0; i<4;i++)
-	{
-		if (subkey_found(root_keys[i].lpkey, lpkey))
-				return root_keys[i].hkey;				
-	}
-	ERR_(reg)("Didn't find corresponding root key entry ! Search strategy broken ??\n");
-	return 0;
-#undef ROOT_KEYS
-}
-#undef ADD_ROOT_KEY
-/* so we don't accidently access them ... */
-#define key_current_config NULL NULL
-#define key_current_user NULL NULL
-#define key_users NULL NULL
-#define key_local_machine NULL NULL
-#define key_classes_root NULL NULL
-#define key_dyn_data NULL NULL
-#define key_performance_data NULL NULL
-
-/******************************************************************************
- * split_keypath [Internal]
- * splits the unicode string 'wp' into an array of strings.
- * the array is allocated by this function. 
- * Free the array using FREE_KEY_PATH
- *
- * PARAMS
- *    wp  [I] String to split up
- *    wpv [O] Array of pointers to strings
- *    wpc [O] Number of components
- */
-static void split_keypath( LPCWSTR wp, LPWSTR **wpv, int *wpc)
-{
-    int	i,j,len;
-    LPWSTR ws;
-
-    TRACE_(reg)("(%s,%p,%p)\n",debugstr_w(wp),wpv,wpc);
-
-    ws	= HEAP_strdupW( SystemHeap, 0, wp );
-
-    /* We know we have at least one substring */
-    *wpc = 1;
-
-    /* Replace each backslash with NULL, and increment the count */
-    for (i=0;ws[i];i++) {
-        if (ws[i]=='\\') {
-            ws[i]=0;
-            (*wpc)++;
-        }
-    }
-
-    len = i;
-
-    /* Allocate the space for the array of pointers, leaving room for the
-       NULL at the end */
-    *wpv = (LPWSTR*)HeapAlloc( SystemHeap, 0, sizeof(LPWSTR)*(*wpc+2));
-    (*wpv)[0]= ws;
-
-    /* Assign each pointer to the appropriate character in the string */
-    j = 1;
-    for (i=1;i<len;i++)
-        if (ws[i-1]==0) {
-            (*wpv)[j++]=ws+i;
-            /*TRACE_(reg) (" Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1]));*/
-        }
-
-    (*wpv)[j]=NULL;
-}
-#define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
-
 
 
 
@@ -553,12 +113,12 @@
 
 	TRACE_(reg)("(void)\n");
 
-	RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
+	RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
 	RegCloseKey(hkey);
 
         /* This was an Open, but since it is called before the real registries
            are loaded, it was changed to a Create - MTB 980507*/
-	RegCreateKey16(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
+	RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
 	RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
 	RegCloseKey(hkey);
 
@@ -576,8 +136,8 @@
 	 * 						SysServices
 	 */
 	if (-1!=gethostname(buf,200)) {
-		RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
-		RegSetValueEx16(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
+		RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
+		RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
 		RegCloseKey(hkey);
 	}
 }
@@ -613,131 +173,6 @@
  * SaveOnlyUpdatedKeys=yes
  */
 
-/******************************************************************************
- * _save_check_tainted [Internal]
- */
-static int _save_check_tainted( LPKEYSTRUCT lpkey )
-{
-	int tainted = 0;
-
-	while (lpkey) {
-		if (_save_check_tainted(lpkey->nextsub))
-			lpkey->flags |= REG_OPTION_TAINTED;
-	  	if (lpkey->flags & REG_OPTION_TAINTED)
-		        tainted = 1;
-		lpkey	= lpkey->next;
-	}
-	return tainted;
-}
-
-/******************************************************************************
- * _save_USTRING [Internal]
- */
-static void _save_USTRING( FILE *F, LPWSTR wstr, int escapeeq )
-{
-	LPWSTR	s;
-	int	doescape;
-
-	if (wstr==NULL)
-		return;
-	s=wstr;
-	while (*s) {
-		doescape=0;
-		if (*s>0x7f)
-			doescape = 1;
-		if (*s=='\n')
-			doescape = 1;
-		if (escapeeq && *s=='=')
-			doescape = 1;
-		if (*s=='\\')
-                        fputc(*s,F); /* if \\ then put it twice. */
-		if (doescape)
-			fprintf(F,"\\u%04x",*((unsigned short*)s));
-		else
-			fputc(*s,F);
-		s++;
-	}
-}
-
-/******************************************************************************
- * _savesubkey [Internal]
- *
- * NOTES
- *  REG_MULTI_SZ is handled as binary (like in win95) (js)
- */
-static int _savesubkey( FILE *F, LPKEYSTRUCT lpkey, int level, int all )
-{
-	LPKEYSTRUCT	lpxkey;
-	int		i,tabs,j;
-
-	lpxkey	= lpkey;
-	while (lpxkey) {
-		if (	!(lpxkey->flags & REG_OPTION_VOLATILE) &&
-			(all || (lpxkey->flags & REG_OPTION_TAINTED))
-		) {
-			for (tabs=level;tabs--;)
-				fputc('\t',F);
-			_save_USTRING(F,lpxkey->keyname,1);
-			fputs("\n",F);
-			for (i=0;i<lpxkey->nrofvalues;i++) {
-				LPKEYVALUE	val=lpxkey->values+i;
-
-				for (tabs=level+1;tabs--;)
-					fputc('\t',F);
-				_save_USTRING(F,val->name,0);
-				fputc('=',F);
-				fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
-				if ( val->type == REG_SZ || val->type == REG_EXPAND_SZ )
-					_save_USTRING(F,(LPWSTR)val->data,0);
-				else
-					for (j=0;j<val->len;j++)
-						fprintf(F,"%02x",*((unsigned char*)val->data+j));
-				fputs("\n",F);
-			}
-			/* descend recursively */
-			if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
-				return 0;
-		}
-		lpxkey=lpxkey->next;
-	}
-	return 1;
-}
-
-
-/******************************************************************************
- * _savesubreg [Internal]
- */
-static int _savesubreg( FILE *F, LPKEYSTRUCT lpkey, int all )
-{
-	fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
-	_save_check_tainted(lpkey->nextsub);
-	return _savesubkey(F,lpkey->nextsub,0,all);
-}
-
-
-/******************************************************************************
- * _savereg [Internal]
- */
-static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all )
-{
-	FILE	*F;
-
-	F=fopen(fn,"w");
-	if (F==NULL) {
-		WARN_(reg)("Couldn't open %s for writing: %s\n",
-			fn,strerror(errno)
-		);
-		return FALSE;
-	}
-	if (!_savesubreg(F,lpkey,all)) {
-		fclose(F);
-		unlink(fn);
-		WARN_(reg)("Failed to save keys, perhaps no more diskspace for %s?\n",fn);
-		return FALSE;
-	}
-	fclose(F);
-        return TRUE;
-}
 
 
 /******************************************************************************
@@ -745,9 +180,9 @@
  *
  * Saves main registry branch specified by hkey.
  */
-static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
+static void SHELL_SaveRegistryBranch(HKEY hkey)
 {
-    char   *fn, *home, *tmp;
+    char   *fn, *home;
 
     /* Find out what to save to, get from config file */
     BOOL writeToHome = PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1);
@@ -766,7 +201,7 @@
         fn = xmalloc( MAX_PATHNAME_LEN ); 
         if (writeToAlt && PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "",
                                                     fn, MAX_PATHNAME_LEN - 1))
-            _savereg(lookup_hkey(HKEY_CURRENT_USER),fn,all);
+            RegSaveKeyA( HKEY_CURRENT_USER, fn, NULL );
         free (fn);
 
         if (home && writeToHome)
@@ -779,18 +214,7 @@
             /* create the directory. don't care about errorcodes. */
             mkdir(fn,0755); /* drwxr-xr-x */
             strcat(fn,"/"SAVE_CURRENT_USER);
-
-            tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
-            strcpy(tmp,fn);
-            strcat(tmp,".tmp");
-  
-            if (_savereg(lookup_hkey(HKEY_CURRENT_USER),tmp,all)) {
-                if (-1==rename(tmp,fn)) {
-                    perror("rename tmp registry");
-                    unlink(tmp);
-                }
-            }
-            free(tmp);
+            RegSaveKeyA( HKEY_CURRENT_USER, fn, NULL );
             free(fn);
         }
         break;
@@ -799,7 +223,7 @@
         fn = xmalloc ( MAX_PATHNAME_LEN);
         if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltLocalMachineFile", "", 
                                                     fn, MAX_PATHNAME_LEN - 1))
-            _savereg(lookup_hkey(HKEY_LOCAL_MACHINE), fn, all);
+            RegSaveKeyA( HKEY_LOCAL_MACHINE, fn, NULL );
         free (fn);
 
         if (home && writeToHome)
@@ -808,18 +232,7 @@
                                strlen(SAVE_LOCAL_MACHINE) + 2);
             strcpy(fn,home);
             strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
-
-            tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
-            strcpy(tmp,fn);
-            strcat(tmp,".tmp");
-
-            if (_savereg(lookup_hkey(HKEY_LOCAL_MACHINE),tmp,all)) {
-                if (-1==rename(tmp,fn)) {
-                    perror("rename tmp registry");
-                    unlink(tmp);
-                }
-            }
-            free(tmp);
+            RegSaveKeyA( HKEY_LOCAL_MACHINE, fn, NULL );
             free(fn);
         }
         break;
@@ -827,7 +240,7 @@
         fn = xmalloc( MAX_PATHNAME_LEN );
         if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltUserFile", "", 
                                                     fn, MAX_PATHNAME_LEN - 1))
-            _savereg(lookup_hkey(HKEY_LOCAL_MACHINE), fn, all);
+            RegSaveKeyA( HKEY_USERS, fn, NULL );
         free (fn);
 
         if (home && writeToHome)
@@ -836,17 +249,7 @@
                                strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
             strcpy(fn,home);
             strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
-
-            tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
-            strcpy(tmp,fn);
-            strcat(tmp,".tmp");
-            if ( _savereg(lookup_hkey(HKEY_USERS),tmp,FALSE)) {
-                if (-1==rename(tmp,fn)) {
-                    perror("rename tmp registry");
-                    unlink(tmp);
-                }
-            }
-            free(tmp);
+            RegSaveKeyA( HKEY_USERS, fn, NULL );
             free(fn);
         }
         break;
@@ -862,6 +265,7 @@
  */
 void SHELL_SaveRegistry( void )
 {
+    struct set_registry_levels_request *req = get_req_buffer();
     char   buf[4];
     HKEY   hkey;
     int    all;
@@ -869,7 +273,7 @@
     TRACE_(reg)("(void)\n");
 
     all=0;
-    if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) 
+    if (RegOpenKeyA(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) 
     {
         strcpy(buf,"yes");
     } 
@@ -888,14 +292,18 @@
             strcpy(buf,"yes");
         }
         RegCloseKey(hkey);
-}
+    }
 
-    if (lstrcmpiA(buf,"yes"))
-		all = 1;
+    if (lstrcmpiA(buf,"yes")) all = 1;
 
-	SHELL_SaveRegistryBranch(HKEY_CURRENT_USER, all);
-	SHELL_SaveRegistryBranch(HKEY_LOCAL_MACHINE, all);
-	SHELL_SaveRegistryBranch(HKEY_USERS, all);
+    /* set saving level (0 for saving everything, 1 for saving only modified keys) */
+    req->current = 1;
+    req->saving  = !all;
+    server_call( REQ_SET_REGISTRY_LEVELS );
+
+    SHELL_SaveRegistryBranch(HKEY_CURRENT_USER);
+    SHELL_SaveRegistryBranch(HKEY_LOCAL_MACHINE);
+    SHELL_SaveRegistryBranch(HKEY_USERS);
 }
 
 
@@ -906,90 +314,22 @@
 /******************************************************************************
  * _find_or_add_key [Internal]
  */
-static LPKEYSTRUCT _find_or_add_key( LPKEYSTRUCT lpkey, LPWSTR keyname )
+static inline HKEY _find_or_add_key( HKEY hkey, LPWSTR keyname )
 {
-	LPKEYSTRUCT	lpxkey,*lplpkey;
-
-	if ((!keyname) || (keyname[0]==0)) {
-		free(keyname);
-		return lpkey;
-	}
-	lplpkey= &(lpkey->nextsub);
-	lpxkey	= *lplpkey;
-	while (lpxkey) {
-		if (	tolower(lpxkey->keyname[0])==tolower(keyname[0]) && 
-			!lstrcmpiW(lpxkey->keyname,keyname)
-		)
-			break;
-		lplpkey	= &(lpxkey->next);
-		lpxkey	= *lplpkey;
-	}
-	if (lpxkey==NULL) {
-		*lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
-		lpxkey	= *lplpkey;
-		memset(lpxkey,'\0',sizeof(KEYSTRUCT));
-		lpxkey->keyname	= keyname;
-	} else
-		free(keyname);
-	return lpxkey;
+    HKEY subkey;
+    if (RegCreateKeyW( hkey, keyname, &subkey ) != ERROR_SUCCESS) subkey = 0;
+    if (keyname) free( keyname );
+    return subkey;
 }
 
 /******************************************************************************
  * _find_or_add_value [Internal]
  */
-static void _find_or_add_value( LPKEYSTRUCT lpkey, LPWSTR name, DWORD type,
-                                LPBYTE data, DWORD len, DWORD lastmodified )
+static void _find_or_add_value( HKEY hkey, LPWSTR name, DWORD type, LPBYTE data, DWORD len )
 {
-	LPKEYVALUE	val=NULL;
-	int		i;
-
-	if (name && !*name) {/* empty string equals default (NULL) value */
-		free(name);
-		name = NULL;
-	}
-
-	for (i=0;i<lpkey->nrofvalues;i++) {
-		val=lpkey->values+i;
-		if (name==NULL) {
-			if (val->name==NULL)
-				break;
-		} else {
-			if (	val->name!=NULL &&
-				tolower(val->name[0])==tolower(name[0]) &&
-				!lstrcmpiW(val->name,name)
-			)
-				break;
-		}
-	}
-	if (i==lpkey->nrofvalues) {
-		lpkey->values = xrealloc(
-			lpkey->values,
-			(++lpkey->nrofvalues)*sizeof(KEYVALUE)
-		);
-		val=lpkey->values+i;
-		memset(val,'\0',sizeof(KEYVALUE));
-		val->name = name;
-	} else {
-		if (name)
-			free(name);
-	}
-	if (val->lastmodified<lastmodified) {
-		val->lastmodified=lastmodified;
-		val->type = type;
-
-                if ((type == REG_SZ || type == REG_EXPAND_SZ) && !data){
-
-                    data=xmalloc(sizeof(WCHAR));
-                    memset(data,0,sizeof(WCHAR));
-                    len =sizeof(WCHAR);
-                }
-
-		val->len  = len;
-		if (val->data) 
-			free(val->data);
-		val->data = data;
-	} else
-		free(data);
+    RegSetValueExW( hkey, name, 0, type, data, len );
+    if (name) free( name );
+    if (data) free( data );
 }
 
 
@@ -1052,11 +392,6 @@
 
 	/* read up to "=" or "\0" or "\n" */
 	s	= buf;
-	if (*s == '=') {
-		/* empty string is the win3.1 default value(NULL)*/
-		*str	= NULL;
-		return s;
-	}
 	*str	= (LPWSTR)xmalloc(2*strlen(buf)+2);
 	ws	= *str;
 	while (*s && (*s!='\n') && (*s!='=')) {
@@ -1093,12 +428,6 @@
 		}
 	}
 	*ws	= 0;
-	ws	= *str;
-	if (*ws)
-		*str	= strdupW(*str);
-	else
-		*str	= NULL;
-	free(ws);
 	return s;
 }
 
@@ -1113,21 +442,17 @@
  *    Success: 1
  *    Failure: 0
  */
-static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
-                             int *buflen, DWORD optflag )
+static int _wine_loadsubkey( FILE *F, HKEY hkey, int level, char **buf, int *buflen )
 {
-	LPKEYSTRUCT	lpxkey;
+    	HKEY subkey;
 	int		i;
 	char		*s;
 	LPWSTR		name;
 
-    TRACE_(reg)("(%p,%p,%d,%s,%d,%lx)\n", F, lpkey, level, debugstr_a(*buf),
-          *buflen, optflag);
-
-    lpkey->flags |= optflag;
+    TRACE_(reg)("(%p,%x,%d,%s,%d)\n", F, hkey, level, debugstr_a(*buf), *buflen);
 
     /* Good.  We already got a line here ... so parse it */
-    lpxkey = NULL;
+    subkey = 0;
     while (1) {
         i=0;s=*buf;
         while (*s=='\t') {
@@ -1135,11 +460,11 @@
             i++;
         }
         if (i>level) {
-            if (lpxkey==NULL) {
+            if (!subkey) {
                 WARN_(reg)("Got a subhierarchy without resp. key?\n");
                 return 0;
             }
-	    if (!_wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag))
+	    if (!_wine_loadsubkey(F,subkey,level+1,buf,buflen))
 	       if (!_wine_read_line(F,buf,buflen))
 		  return 1;
             continue;
@@ -1156,7 +481,7 @@
 		switch (0) {
 		default:
 			if (*s=='\0') {
-				lpxkey=_find_or_add_key(lpkey,name);
+				subkey=_find_or_add_key(hkey,name);
 			} else {
 				LPBYTE		data;
 				int		len,lastmodified,type;
@@ -1179,10 +504,7 @@
 				}
 				if (type == REG_SZ || type == REG_EXPAND_SZ) {
 					s=_wine_read_USTRING(s,(LPWSTR*)&data);
-					if (data)
-						len = lstrlenW((LPWSTR)data)*2+2;
-					else	
-						len = 0;
+                                        len = lstrlenW((LPWSTR)data)*2+2;
 				} else {
 					len=strlen(s)/2;
 					data = (LPBYTE)xmalloc(len+1);
@@ -1204,7 +526,7 @@
 						s++;
 					}
 				}
-				_find_or_add_value(lpkey,name,type,data,len,lastmodified);
+				_find_or_add_value(hkey,name,type,data,len);
 			}
 		}
 		/* read the next line */
@@ -1218,7 +540,7 @@
 /******************************************************************************
  * _wine_loadsubreg [Internal]
  */
-static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag )
+static int _wine_loadsubreg( FILE *F, HKEY hkey, const char *fn )
 {
 	int	ver;
 	char	*buf;
@@ -1242,7 +564,7 @@
 		free(buf);
 		return 0;
 	}
-	if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
+	if (!_wine_loadsubkey(F,hkey,0,&buf,&buflen)) {
 		free(buf);
 		return 0;
 	}
@@ -1254,22 +576,18 @@
 /******************************************************************************
  * _wine_loadreg [Internal]
  */
-static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag )
+static void _wine_loadreg( HKEY hkey, char *fn )
 {
     FILE *F;
 
-    TRACE_(reg)("(%p,%s,%lx)\n",lpkey,debugstr_a(fn),optflag);
+    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(fn));
 
     F = fopen(fn,"rb");
     if (F==NULL) {
         WARN_(reg)("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
         return;
     }
-    if (!_wine_loadsubreg(F,lpkey,optflag)) {
-        fclose(F);
-        unlink(fn);
-        return;
-    }
+    _wine_loadsubreg(F,hkey,fn);
     fclose(F);
 }
 
@@ -1284,95 +602,66 @@
  * which is bad...
  */
 
- /* Forward declaration of recusive agent */
-static void _flush_reg(LPKEYSTRUCT from);
-
-static void _flush_registry( LPKEYSTRUCT from )
+static void _flush_registry( HKEY hkey )
 {
-  /* make sure we have something... */
-  if (from == NULL)
-    return;
+    WCHAR name[MAX_PATH];
 
-  /* Launch the recusive agent on sub branches */
-  _flush_reg( from->nextsub );
-  _flush_reg( from->next );
-
-  /* Initialize pointers */
-  from->nextsub = NULL;
-  from->next    = NULL;
-}
-static void _flush_reg( LPKEYSTRUCT from )
-{
-	int	j;
-
-  /* make sure we have something... */
-  if (from == NULL)
-    return;
-
-  /* 
-   * do the same for the child keys 
-   */
-  if (from->nextsub != NULL)
-    _flush_reg(from->nextsub);
-
-  /* 
-   * do the same for the sibling keys 
-   */
-  if (from->next != NULL)
-    _flush_reg(from->next);
-
-  /*
-   * iterate through this key's values and delete them
-   */
-  for (j=0;j<from->nrofvalues;j++) 
-  {
-    free( (from->values+j)->name);
-    free( (from->values+j)->data);
-  }
-
-  /*
-   * free the structure
-   */
-  if ( from != NULL )
-    free(from);
+    for (;;)
+    {
+        HKEY subkey;
+        /* FIXME: we assume that deleting a key will move the other ones up, */
+        /* so that we can always use index 0 until there are no more keys    */
+        if (RegEnumKeyW( hkey, 0, name, sizeof(name) ) != ERROR_SUCCESS) break;
+        if (RegOpenKeyW( hkey, name, &subkey ) != ERROR_SUCCESS) break;
+        _flush_registry( subkey );
+        if (RegDeleteKeyW( subkey, NULL ) != ERROR_SUCCESS) break;
+        RegCloseKey( subkey );
+    }
 }
 
 
 /******************************************************************************
  * _copy_registry [Internal]
  */
-static void _copy_registry( LPKEYSTRUCT from, LPKEYSTRUCT to )
+static void _copy_registry( HKEY from, HKEY to )
 {
-	LPKEYSTRUCT	lpxkey;
-	int		j;
-	LPKEYVALUE	valfrom;
+    int index;
+    HKEY subkey;
+    FILETIME ft;
+    DWORD type, name_len, len;
+    static WCHAR name[MAX_PATH];
+    static BYTE data[2048];
 
-	from=from->nextsub;
-	while (from) {
-		lpxkey = _find_or_add_key(to,strdupW(from->keyname));
+    /* copy values */
+    index = 0;
+    for (;;)
+    {
+        len = sizeof(data);
+        name_len = sizeof(name);
+        if (RegEnumValueW( from, index++, name, &name_len,
+                           NULL, &type, data, &len ) != ERROR_SUCCESS) break;
+        RegSetValueW( to, name, type, (LPCWSTR)data, len );
+    }
 
-		for (j=0;j<from->nrofvalues;j++) {
-			LPWSTR	name;
-			LPBYTE	data;
-
-			valfrom = from->values+j;
-			name=valfrom->name;
-			if (name) name=strdupW(name);
-			data=(LPBYTE)xmalloc(valfrom->len);
-			memcpy(data,valfrom->data,valfrom->len);
-
-			_find_or_add_value(
-				lpxkey,
-				name,
-				valfrom->type,
-				data,
-				valfrom->len,
-				valfrom->lastmodified
-			);
-		}
-		_copy_registry(from,lpxkey);
-		from = from->next;
-	}
+    /* copy subkeys */
+    index = 0;
+    for (;;)
+    {
+        name_len = sizeof(name);
+        if (RegEnumKeyExW( from, index++, name, &name_len,
+                           NULL, NULL, 0, &ft ) != ERROR_SUCCESS)
+            break;
+        if (RegOpenKeyW( from, name, &subkey ) == ERROR_SUCCESS)
+        {
+            HKEY newsub;
+            if (RegCreateKeyW( to, name, &newsub ) == ERROR_SUCCESS)
+            {
+                _copy_registry( subkey, newsub );
+                RegCloseKey( newsub );
+            }
+            RegCloseKey( subkey );
+        }
+    }
 }
 
 
@@ -1496,8 +785,7 @@
 /******************************************************************************
  * _w95_processKey [Internal]
  */
-static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey, 
-                                   int nrLS, int nrMS, struct _w95_info *info )
+static HKEY _w95_processKey ( HKEY hkey, int nrLS, int nrMS, struct _w95_info *info )
 
 {
   /* Disk Key Header structure (RGDB part) */
@@ -1531,11 +819,11 @@
 	int     off_next_rgdb;
 	char    *next = rgdbdata;
 	int     nrgdb, i;
-	LPKEYSTRUCT	lpxkey;
+        HKEY subkey;
 	
 	do {
 	  curdata = next;
-	  if (strncmp(curdata, "RGDB", 4)) return (NULL);
+	  if (strncmp(curdata, "RGDB", 4)) return 0;
 	    
 	  memcpy(&off_next_rgdb,curdata+4,4);
 	  next = curdata + off_next_rgdb;
@@ -1565,13 +853,13 @@
 	  curdata += xdkh->nextkeyoff;
 	};
 
-	if (dkh.nrLS != nrLS) return (NULL);
+	if (dkh.nrLS != nrLS) return 0;
 
 	if (nrgdb != dkh.nrMS)
-	  return (NULL);
+	  return 0;
 
         assert((dkh.keynamelen<2) || curdata[0]);
-	lpxkey=_find_or_add_key(lpkey,strcvtA2W(curdata, dkh.keynamelen));
+	subkey=_find_or_add_key(hkey,strcvtA2W(curdata, dkh.keynamelen));
 	curdata += dkh.keynamelen;
 
 	for (i=0;i< dkh.values; i++) {
@@ -1597,22 +885,15 @@
 
 	  curdata += dkv.valdatalen;
 	  
-	  _find_or_add_value(
-			     lpxkey,
-			     name,
-			     dkv.type,
-			     data,
-			     len,
-			     info->lastmodified
-			     );
+	  _find_or_add_value( subkey, name, dkv.type, data, len );
 	}
-	return (lpxkey);
+	return subkey;
 }
 
 /******************************************************************************
  * _w95_walkrgkn [Internal]
  */
-static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off, 
+static void _w95_walkrgkn( HKEY prevkey, char *off, 
                            struct _w95_info *info )
 
 {
@@ -1627,23 +908,21 @@
     unsigned short		nrLS;
     unsigned short		nrMS;
   } *dke = (struct dke *)off;
-  LPKEYSTRUCT  lpxkey;
+  HKEY subkey;
 
   if (dke == NULL) {
     dke = (struct dke *) ((char *)info->rgknbuffer);
   }
 
-  lpxkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info);
+  subkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info);
   /* XXX <-- This is a hack*/
-  if (!lpxkey) {
-    lpxkey = prevkey;
-  }
+  if (!subkey) subkey = prevkey;
 
   if (dke->nextsub != -1 && 
       ((dke->nextsub - 0x20) < info->rgknsize) 
       && (dke->nextsub > 0x20)) {
     
-    _w95_walkrgkn(lpxkey, 
+    _w95_walkrgkn(subkey, 
 		  info->rgknbuffer + dke->nextsub - 0x20, 
 		  info);
   }
@@ -1655,15 +934,13 @@
 		  info->rgknbuffer + dke->next - 0x20,
 		  info);
   }
-
-  return;
 }
 
 
 /******************************************************************************
  * _w95_loadreg [Internal]
  */
-static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey )
+static void _w95_loadreg( char* fn, HKEY hkey )
 {
 	HFILE		hfd;
 	char		magic[5];
@@ -1723,7 +1000,7 @@
 		return;
 	_lclose(hfd);
 
-	_w95_walkrgkn(lpkey, NULL, &info);
+	_w95_walkrgkn(hkey, NULL, &info);
 
 	free (info.rgdbbuffer);
 	free (info.rgknbuffer);
@@ -1816,15 +1093,14 @@
 		unsigned char *txt,
 		struct _w31_tabent *tab,
 		struct _w31_header *head,
-		LPKEYSTRUCT	lpkey,
+		HKEY hkey,
 		time_t		lastmodified,
 		int		level
 ) {
 	struct _w31_dirent	*dir;
 	struct _w31_keyent	*key;
 	struct _w31_valent	*val;
-	LPKEYSTRUCT		xlpkey = NULL;
-	LPWSTR			name,value;
+        HKEY subkey = 0;
 	static char		tail[400];
 
 	while (idx!=0) {
@@ -1839,28 +1115,24 @@
 			 * toplevel subdirectory belong to \SOFTWARE\Classes
 			 */
 			if (!level && !lstrcmpA(tail,".classes")) {
-				__w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
+				__w31_dumptree(dir->child_idx,txt,tab,head,hkey,lastmodified,level+1);
 				idx=dir->sibling_idx;
 				continue;
 			}
-			name=strdupA2W(tail);
-
-			xlpkey=_find_or_add_key(lpkey,name);
-
+                        if (RegCreateKeyA( hkey, tail, &subkey ) != ERROR_SUCCESS) subkey = 0;
 			/* only add if leaf node or valued node */
 			if (dir->value_idx!=0||dir->child_idx==0) {
 				if (dir->value_idx) {
 					val=(struct _w31_valent*)&tab[dir->value_idx];
 					memcpy(tail,&txt[val->string_off],val->length);
 					tail[val->length]='\0';
-					value=strdupA2W(tail);
-					_find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlenW(value)*2+2,lastmodified);
+                                        RegSetValueA( hkey, NULL, REG_SZ, tail, 0 );
 				}
 			}
 		} else {
 			TRACE_(reg)("strange: no directory key name, idx=%04x\n", idx);
 		}
-		__w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
+		__w31_dumptree(dir->child_idx,txt,tab,head,subkey,lastmodified,level+1);
 		idx=dir->sibling_idx;
 	}
 }
@@ -1878,7 +1150,6 @@
 	OFSTRUCT		ofs;
 	BY_HANDLE_FILE_INFORMATION hfinfo;
 	time_t			lastmodified;
-	LPKEYSTRUCT		lpkey;
 
 	TRACE_(reg)("(void)\n");
 
@@ -1933,8 +1204,7 @@
 		return;
 	}
 	lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
-	lpkey = lookup_hkey(HKEY_CLASSES_ROOT);
-	__w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
+	__w31_dumptree(tab[0].w1,txt,tab,&head,HKEY_CLASSES_ROOT,lastmodified,0);
 	free(tab);
 	free(txt);
 	_lclose(hf);
@@ -1947,24 +1217,27 @@
  */
 void SHELL_LoadRegistry( void )
 {
+  struct set_registry_levels_request *req = get_req_buffer();
   char	      *fn, *home;
-  LPKEYSTRUCT	lpkey, HKCU, HKU, HKLM;
   HKEY		    hkey;
 
   TRACE_(reg)("(void)\n");
 
-  HKCU = lookup_hkey(HKEY_CURRENT_USER);
-  HKU  = lookup_hkey(HKEY_USERS);
-  HKLM = lookup_hkey(HKEY_LOCAL_MACHINE);
+  REGISTRY_Init();
+
+  /* set level to 0 for loading system files */
+  req->current = 0;
+  req->saving  = 0;
+  server_call( REQ_SET_REGISTRY_LEVELS );
 
   if (PROFILE_GetWineIniBool ("registry", "LoadWindowsRegistryFiles", 1)) 
   { 
       /* Load windows 3.1 entries */
       _w31_loadreg();
       /* Load windows 95 entries */
-      _w95_loadreg("C:\\system.1st",	HKLM);
-      _w95_loadreg("system.dat",	HKLM);
-      _w95_loadreg("user.dat",	HKU);
+      _w95_loadreg("C:\\system.1st", HKEY_LOCAL_MACHINE);
+      _w95_loadreg("system.dat", HKEY_LOCAL_MACHINE);
+      _w95_loadreg("user.dat", HKEY_USERS);
   }
 
   if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1))
@@ -1972,14 +1245,19 @@
       /* 
        * Load the global HKU hive directly from sysconfdir
        */ 
-      _wine_loadreg( HKU, SAVE_USERS_DEFAULT, 0);
+      _wine_loadreg( HKEY_USERS, SAVE_USERS_DEFAULT );
 
       /* 
        * Load the global machine defaults directly form sysconfdir
        */
-      _wine_loadreg( HKLM, SAVE_LOCAL_MACHINE_DEFAULT, 0);
+      _wine_loadreg( HKEY_LOCAL_MACHINE, SAVE_LOCAL_MACHINE_DEFAULT );
   }
 
+  /* set level to 1 for loading user files */
+  req->current = 1;
+  req->saving  = 0;
+  server_call( REQ_SET_REGISTRY_LEVELS );
+
   /*
    * Load the user saved registries 
    */
@@ -1994,13 +1272,13 @@
                          strlen(SAVE_LOCAL_USERS_DEFAULT)+2);
       strcpy(fn, home);
       strcat(fn, WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
-      _wine_loadreg(HKU, fn, REG_OPTION_TAINTED); 
+      _wine_loadreg( HKEY_USERS, fn ); 
       free(fn);
 
       fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + strlen(SAVE_CURRENT_USER)+2);
       strcpy(fn, home);
       strcat(fn, WINE_PREFIX"/"SAVE_CURRENT_USER);
-      _wine_loadreg(HKCU, fn, REG_OPTION_TAINTED);
+      _wine_loadreg( HKEY_CURRENT_USER, fn );
       free(fn);
 
       /* 
@@ -2010,7 +1288,7 @@
       fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_MACHINE)+2);
       strcpy(fn,home);
       strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
-      _wine_loadreg(HKLM, fn, REG_OPTION_TAINTED);
+      _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
       free(fn);
   }
   
@@ -2024,7 +1302,7 @@
       if ( PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", 
                                      fn, MAX_PATHNAME_LEN - 1)) 
        {
-         _wine_loadreg(HKCU,fn,REG_OPTION_TAINTED);
+         _wine_loadreg( HKEY_CURRENT_USER, fn );
        }
       free (fn);
       /*
@@ -2035,7 +1313,7 @@
       if ( PROFILE_GetWineIniString ( "registry", "AltUserFile", "",
                                       fn, MAX_PATHNAME_LEN - 1))
        {
-         _wine_loadreg(HKU,fn,REG_OPTION_TAINTED);
+         _wine_loadreg( HKEY_USERS, fn );
        }
       free (fn);
       /*
@@ -2046,7 +1324,7 @@
       if (PROFILE_GetWineIniString ( "registry", "AltLocalMachineFile", "",
                                      fn, MAX_PATHNAME_LEN - 1))
        {
-         _wine_loadreg(HKLM,fn,REG_OPTION_TAINTED); 
+         _wine_loadreg( HKEY_LOCAL_MACHINE, fn );
        }
       free (fn);
     }
@@ -2055,14 +1333,10 @@
    * Obtain the handle of the HKU\.Default key.
    * in order to copy HKU\.Default\* onto HKEY_CURRENT_USER 
    */
-  RegCreateKey16(HKEY_USERS,".Default",&hkey);
-  lpkey = lookup_hkey(hkey);
-  if(!lpkey){
-     WARN_(reg)("Could not create global user default key\n");
-  } else {
-    _copy_registry(lpkey, HKCU );
-  }
-
+  if (RegCreateKeyA(HKEY_USERS,".Default",&hkey) != ERROR_SUCCESS)
+      WARN_(reg)("Could not create global user default key\n");
+  else
+    _copy_registry( hkey, HKEY_CURRENT_USER );
   RegCloseKey(hkey);
 
   /* 
@@ -2073,7 +1347,7 @@
    */
 
   /* Allways flush the HKU hive and reload it only with user's personal HKU */
-  _flush_registry(HKU); 
+  _flush_registry( HKEY_USERS ); 
 
   /* Reload user's local HKU hive */
   if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1))
@@ -2084,7 +1358,7 @@
       strcpy(fn,home);
       strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
 
-      _wine_loadreg( HKU, fn, REG_OPTION_TAINTED);
+      _wine_loadreg( HKEY_USERS, fn );
 
       free(fn);
   }
@@ -2115,1406 +1389,8 @@
 
 
 /********************* API FUNCTIONS ***************************************/
-/*
- * Open Keys.
- *
- * All functions are stubs to RegOpenKeyEx32W where all the
- * magic happens. 
- *
- * Callpath:
- * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
- *                                  RegOpenKey32W   -> RegOpenKeyEx32W 
- */
-
-
-/******************************************************************************
- * RegOpenKeyEx32W [ADVAPI32.150]
- * Opens the specified key
- *
- * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
- *
- * PARAMS
- *    hkey       [I] Handle of open key
- *    lpszSubKey [I] Name of subkey to open
- *    dwReserved [I] Reserved - must be zero
- *    samDesired [I] Security access mask
- *    retkey     [O] Address of handle of open key
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: Error code
- */
-DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved,
-                              REGSAM samDesired, LPHKEY retkey )
-{
-	LPKEYSTRUCT	lpNextKey,lpxkey;
-	LPWSTR		*wps;
-	int		wpc,i;
-
-    TRACE_(reg)("(0x%x,%s,%ld,%lx,%p)\n", hkey,debugstr_w(lpszSubKey),dwReserved,
-          samDesired,retkey);
-
-    lpNextKey = lookup_hkey( hkey );
-    if (!lpNextKey)
-        return ERROR_INVALID_HANDLE;
-
-    if (!lpszSubKey || !*lpszSubKey) {
-        /* Either NULL or pointer to empty string, so return a new handle
-           to the original hkey */
-        currenthandle += 2;
-        add_handle(currenthandle,lpNextKey,samDesired);
-        *retkey=currenthandle;
-        return ERROR_SUCCESS;
-    }
-
-    if (lpszSubKey[0] == '\\') {
-        WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
-        return ERROR_BAD_PATHNAME;
-    }
-
-	split_keypath(lpszSubKey,&wps,&wpc);
-	i = 0;
-	while ((i<wpc) && (wps[i][0]=='\0')) i++;
-	lpxkey = lpNextKey;
-
-    while (wps[i]) {
-        lpxkey=lpNextKey->nextsub;
-        while (lpxkey) {
-            if (!lstrcmpiW(wps[i],lpxkey->keyname)) {
-                break;
-            }
-            lpxkey=lpxkey->next;
-        }
-
-        if (!lpxkey) {
-            TRACE_(reg)("Could not find subkey %s\n",debugstr_w(wps[i]));
-            FREE_KEY_PATH;
-            return ERROR_FILE_NOT_FOUND;
-        }
-        i++;
-        lpNextKey = lpxkey;
-    }
-
-    currenthandle += 2;
-    add_handle(currenthandle,lpxkey,samDesired);
-    *retkey = currenthandle;
-    TRACE_(reg)("  Returning %x\n", currenthandle);
-    FREE_KEY_PATH;
-    return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegOpenKeyEx32A [ADVAPI32.149]
- */
-DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
-                              REGSAM samDesired, LPHKEY retkey )
-{
-    LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
-    DWORD ret;
-
-    TRACE_(reg)("(%x,%s,%ld,%lx,%p)\n",hkey,debugstr_a(lpszSubKey),dwReserved,
-          samDesired,retkey);
-    ret = RegOpenKeyExW( hkey, lpszSubKeyW, dwReserved, samDesired, retkey );
-    free(lpszSubKeyW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegOpenKey32W [ADVAPI32.151]
- *
- * PARAMS
- *    hkey       [I] Handle of open key
- *    lpszSubKey [I] Address of name of subkey to open
- *    retkey     [O] Address of handle of open key
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: Error code
- */
-DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
-{
-    TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_w(lpszSubKey),retkey);
-    return RegOpenKeyExW( hkey, lpszSubKey, 0, KEY_ALL_ACCESS, retkey );
-}
-
-
-/******************************************************************************
- * RegOpenKey32A [ADVAPI32.148]
- */
-DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
-{
-    DWORD ret;
-    LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
-    TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
-    ret =  RegOpenKeyW( hkey, lpszSubKeyW, retkey );
-    free(lpszSubKeyW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegOpenKey16 [SHELL.1] [KERNEL.217]
- */
-DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
-{
-    TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
-    return RegOpenKeyA( hkey, lpszSubKey, retkey );
-}
-
-
-/* 
- * Create keys
- * 
- * All those functions convert their respective 
- * arguments and call RegCreateKeyExW at the end.
- *
- * We stay away from the Ex functions as long as possible because there are
- * differences in the return values
- *
- * Callpath:
- *                                      RegCreateKeyEx32A \
- * RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W   -> RegCreateKeyEx32W
- */
-
-
-/******************************************************************************
- * RegCreateKeyEx32W [ADVAPI32.131]
- *
- * PARAMS
- *    hkey         [I] Handle of an open key
- *    lpszSubKey   [I] Address of subkey name
- *    dwReserved   [I] Reserved - must be 0
- *    lpszClass    [I] Address of class string
- *    fdwOptions   [I] Special options flag
- *    samDesired   [I] Desired security access
- *    lpSecAttribs [I] Address of key security structure
- *    retkey       [O] Address of buffer for opened handle
- *    lpDispos     [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
- */
-DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey, 
-                                DWORD dwReserved, LPWSTR lpszClass, 
-                                DWORD fdwOptions, REGSAM samDesired,
-                                LPSECURITY_ATTRIBUTES lpSecAttribs, 
-                                LPHKEY retkey, LPDWORD lpDispos )
-{
-	LPKEYSTRUCT	*lplpPrevKey,lpNextKey,lpxkey;
-	LPWSTR		*wps;
-	int		wpc,i;
-
-    TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey,
-		debugstr_w(lpszSubKey), dwReserved, debugstr_w(lpszClass),
-		fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos);
-
-    lpNextKey = lookup_hkey(hkey);
-    if (!lpNextKey)
-        return ERROR_INVALID_HANDLE;
-
-    /* Check for valid options */
-    switch(fdwOptions) {
-        case REG_OPTION_NON_VOLATILE:
-        case REG_OPTION_VOLATILE:
-        case REG_OPTION_BACKUP_RESTORE:
-            break;
-        default:
-            return ERROR_INVALID_PARAMETER;
-    }
-
-    /* Sam has to be a combination of the following */
-    if (!(samDesired & 
-          (KEY_ALL_ACCESS | KEY_CREATE_LINK | KEY_CREATE_SUB_KEY | 
-           KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_NOTIFY |
-           KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE | KEY_WRITE)))
-        return ERROR_INVALID_PARAMETER;
-
-	if (!lpszSubKey || !*lpszSubKey) {
-                currenthandle += 2;
-		add_handle(currenthandle,lpNextKey,samDesired);
-		*retkey=currenthandle;
-                TRACE_(reg)("Returning %x\n", currenthandle);
-		lpNextKey->flags|=REG_OPTION_TAINTED;
-		return ERROR_SUCCESS;
-	}
-
-    if (lpszSubKey[0] == '\\') {
-        WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
-        return ERROR_BAD_PATHNAME;
-    }
-
-	split_keypath(lpszSubKey,&wps,&wpc);
-	i 	= 0;
-	while ((i<wpc) && (wps[i][0]=='\0')) i++;
-	lpxkey	= lpNextKey;
-	while (wps[i]) {
-		lpxkey=lpNextKey->nextsub;
-		while (lpxkey) {
-			if (!lstrcmpiW(wps[i],lpxkey->keyname))
-				break;
-			lpxkey=lpxkey->next;
-		}
-		if (!lpxkey)
-			break;
-		i++;
-		lpNextKey	= lpxkey;
-	}
-	if (lpxkey) {
-                currenthandle += 2;
-		add_handle(currenthandle,lpxkey,samDesired);
-		lpxkey->flags  |= REG_OPTION_TAINTED;
-		*retkey		= currenthandle;
-                TRACE_(reg)("Returning %x\n", currenthandle);
-		if (lpDispos)
-			*lpDispos	= REG_OPENED_EXISTING_KEY;
-		FREE_KEY_PATH;
-		return ERROR_SUCCESS;
-	}
-
-	/* Good.  Now the hard part */
-	while (wps[i]) {
-		lplpPrevKey	= &(lpNextKey->nextsub);
-		lpxkey		= *lplpPrevKey;
-		while (lpxkey) {
-			lplpPrevKey	= &(lpxkey->next);
-			lpxkey		= *lplpPrevKey;
-		}
-		*lplpPrevKey=malloc(sizeof(KEYSTRUCT));
-		if (!*lplpPrevKey) {
-			FREE_KEY_PATH;
-                        TRACE_(reg)("Returning OUTOFMEMORY\n");
-			return ERROR_OUTOFMEMORY;
-		}
-		memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
-                TRACE_(reg)("Adding %s\n", debugstr_w(wps[i]));
-		(*lplpPrevKey)->keyname	= strdupW(wps[i]);
-		(*lplpPrevKey)->next	= NULL;
-		(*lplpPrevKey)->nextsub	= NULL;
-		(*lplpPrevKey)->values	= NULL;
-		(*lplpPrevKey)->nrofvalues = 0;
-		(*lplpPrevKey)->flags 	= REG_OPTION_TAINTED;
-		if (lpszClass)
-			(*lplpPrevKey)->class = strdupW(lpszClass);
-		else
-			(*lplpPrevKey)->class = NULL;
-		lpNextKey	= *lplpPrevKey;
-		i++;
-	}
-        currenthandle += 2;
-	add_handle(currenthandle,lpNextKey,samDesired);
-
-	/*FIXME: flag handling correct? */
-	lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
-	if (lpszClass)
-		lpNextKey->class = strdupW(lpszClass);
-	else
-		lpNextKey->class = NULL;
-	*retkey		= currenthandle;
-        TRACE_(reg)("Returning %x\n", currenthandle);
-	if (lpDispos)
-		*lpDispos	= REG_CREATED_NEW_KEY;
-	FREE_KEY_PATH;
-	return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegCreateKeyEx32A [ADVAPI32.130]
- */
-DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
-                                LPSTR lpszClass, DWORD fdwOptions, 
-                                REGSAM samDesired, 
-                                LPSECURITY_ATTRIBUTES lpSecAttribs, 
-                                LPHKEY retkey, LPDWORD lpDispos )
-{
-    LPWSTR lpszSubKeyW, lpszClassW;
-    DWORD  ret;
-
-    TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",hkey,debugstr_a(lpszSubKey),
-          dwReserved,debugstr_a(lpszClass),fdwOptions,samDesired,lpSecAttribs,
-          retkey,lpDispos);
-
-    lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
-    lpszClassW = lpszClass?strdupA2W(lpszClass):NULL;
-
-    ret = RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW, 
-                             fdwOptions, samDesired, lpSecAttribs, retkey, 
-                             lpDispos );
-
-    if(lpszSubKeyW) free(lpszSubKeyW);
-    if(lpszClassW) free(lpszClassW);
-
-    return ret;
-}
-
-
-/******************************************************************************
- * RegCreateKey32W [ADVAPI32.132]
- */
-DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
-{
-    DWORD junk;
-    LPKEYSTRUCT	lpNextKey;
-
-    TRACE_(reg)("(%x,%s,%p)\n", hkey,debugstr_w(lpszSubKey),retkey);
-
-    /* This check is here because the return value is different than the
-       one from the Ex functions */
-    lpNextKey = lookup_hkey(hkey);
-    if (!lpNextKey)
-        return ERROR_BADKEY;
-
-    return RegCreateKeyExW( hkey, lpszSubKey, 0, NULL, 
-                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
-                              retkey, &junk);
-}
-
-
-/******************************************************************************
- * RegCreateKey32A [ADVAPI32.129]
- */
-DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
-{
-    DWORD ret;
-    LPWSTR lpszSubKeyW;
-
-    TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
-    lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
-    ret = RegCreateKeyW( hkey, lpszSubKeyW, retkey );
-    if(lpszSubKeyW) free(lpszSubKeyW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegCreateKey16 [SHELL.2] [KERNEL.218]
- */
-DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
-{
-    TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
-    return RegCreateKeyA( hkey, lpszSubKey, retkey );
-}
-
-
-/* 
- * Query Value Functions
- * Win32 differs between keynames and valuenames. 
- * multiple values may belong to one key, the special value
- * with name NULL is the default value used by the win31
- * compat functions.
- *
- * Callpath:
- * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
- *                                        RegQueryValue32W -> RegQueryValueEx32W
- */
-
-
-/******************************************************************************
- * RegQueryValueEx32W [ADVAPI32.158]
- * Retrieves type and data for a specified name associated with an open key
- *
- * PARAMS
- *    hkey          [I]   Handle of key to query
- *    lpValueName   [I]   Name of value to query
- *    lpdwReserved  [I]   Reserved - must be NULL
- *    lpdwType      [O]   Address of buffer for value type.  If NULL, the type
- *                        is not required.
- *    lpbData       [O]   Address of data buffer.  If NULL, the actual data is
- *                        not required.
- *    lpcbData      [I/O] Address of data buffer size
- *
- * RETURNS 
- *    ERROR_SUCCESS:   Success
- *    ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
- * 		       buffer is left untouched. The MS-documentation is wrong (js) !!!
- */
-DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR lpValueName,
-			       LPDWORD lpdwReserved, LPDWORD lpdwType,
-			       LPBYTE lpbData, LPDWORD lpcbData )
-{
-	LPKEYSTRUCT	lpkey;
-	int		i;
-	DWORD		ret;
-
-	TRACE_(reg)("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(lpValueName),
-          lpdwReserved, lpdwType, lpbData, lpcbData, lpcbData?*lpcbData:0);
-
-	lpkey = lookup_hkey(hkey);
-
-	if (!lpkey)
-	  return ERROR_INVALID_HANDLE;
-
-	if ((lpbData && ! lpcbData) || lpdwReserved)
-	  return ERROR_INVALID_PARAMETER;
-
-	/* An empty name string is equivalent to NULL */
-	if (lpValueName && !*lpValueName)
-	  lpValueName = NULL;
-
-	if (lpValueName==NULL) 
-	{ /* Use key's unnamed or default value, if any */
-	  for (i=0;i<lpkey->nrofvalues;i++)
-	    if (lpkey->values[i].name==NULL)
-	      break;
-	} 
-	else 
-	{ /* Search for the key name */
-	  for (i=0;i<lpkey->nrofvalues;i++)
-	    if ( lpkey->values[i].name && !lstrcmpiW(lpValueName,lpkey->values[i].name))
-	      break;
-	}
-
-	if (i==lpkey->nrofvalues) 
-	{ TRACE_(reg)(" Key not found\n");
-	  if (lpValueName==NULL) 
-	  { /* Empty keyname not found */
-	    if (lpbData) 
-	    { *(WCHAR*)lpbData = 0;
-	      *lpcbData	= 2;
-	    }
-	    if (lpdwType)
-	      *lpdwType	= REG_SZ;
-	    TRACE_(reg)(" Returning an empty string\n");
-	    return ERROR_SUCCESS;
-	  }
-	  return ERROR_FILE_NOT_FOUND;
-	}
-
-	ret = ERROR_SUCCESS;
-
-	if (lpdwType) 					/* type required ?*/
-	  *lpdwType = lpkey->values[i].type;
-
-	if (lpbData)					/* data required ?*/
-	{ if (*lpcbData >= lpkey->values[i].len)	/* buffer large enought ?*/
-	    memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
-	  else {
-	    *lpcbData = lpkey->values[i].len;
-	    ret = ERROR_MORE_DATA;
-	  }
-	}
-
-	if (lpcbData) 					/* size required ?*/
-	{ *lpcbData = lpkey->values[i].len;
-	}
-
-	debug_print_value ( lpbData, &lpkey->values[i]);
-
-	TRACE_(reg)(" (ret=%lx, type=%lx, len=%ld)\n", ret, lpdwType?*lpdwType:0,lpcbData?*lpcbData:0);
-
-	return ret;
-}
-
-
-/******************************************************************************
- * RegQueryValue32W [ADVAPI32.159]
- */
-DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR lpszSubKey, LPWSTR lpszData,
-                               LPLONG lpcbData )
-{
-	HKEY	xhkey;
-	DWORD	ret,lpdwType;
-
-    TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_w(lpszSubKey),lpszData,
-          lpcbData?*lpcbData:0);
-
-    /* Only open subkey, if we really do descend */
-    if (lpszSubKey && *lpszSubKey) {
-        ret = RegOpenKeyW( hkey, lpszSubKey, &xhkey );
-        if (ret != ERROR_SUCCESS) {
-            WARN_(reg)("Could not open %s\n", debugstr_w(lpszSubKey));
-            return ret;
-        }
-    } else
-        xhkey = hkey;
-
-    lpdwType = REG_SZ;
-    ret = RegQueryValueExW( xhkey, NULL, NULL, &lpdwType, (LPBYTE)lpszData,
-                              lpcbData );
-    if (xhkey != hkey)
-        RegCloseKey(xhkey);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegQueryValueEx32A [ADVAPI32.157]
- *
- * NOTES:
- * the documantation is wrong: if the buffer is to small it remains untouched 
- *
- * FIXME: check returnvalue (len) for an empty key
- */
-DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR lpszValueName,
-			       LPDWORD lpdwReserved, LPDWORD lpdwType,
-			       LPBYTE lpbData, LPDWORD lpcbData )
-{
-	LPWSTR	lpszValueNameW;
-	LPBYTE	mybuf = NULL;
-	DWORD	ret, mytype, mylen = 0;
-
-	TRACE_(reg)("(%x,%s,%p,%p,%p,%p=%ld)\n", hkey,debugstr_a(lpszValueName),
-          lpdwReserved,lpdwType,lpbData,lpcbData,lpcbData?*lpcbData:0);
-
-	if (!lpcbData && lpbData)			/* buffer without size is illegal */
-	{  return ERROR_INVALID_PARAMETER;
-	}
-
-	lpszValueNameW = lpszValueName ? strdupA2W(lpszValueName) : NULL;	
-	
-	/* get just the type first */
-	ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, &mytype, NULL, NULL );
-	
-	if ( ret != ERROR_SUCCESS )			/* failed ?? */
-	{ if(lpszValueNameW) free(lpszValueNameW);
-	  return ret;
-	}
-	
-	if (lpcbData)					/* at least length requested? */
-	{ if (UNICONVMASK & (1<<(mytype)))		/* string requested? */
-	  { if (lpbData )				/* value requested? */
-	    { mylen = 2*( *lpcbData );
-	      mybuf = (LPBYTE)xmalloc( mylen );
-	    }
-
-	    ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, mybuf, &mylen );
-
-	    if (ret == ERROR_SUCCESS )
-	    { if ( lpbData )
-	      { lmemcpynWtoA(lpbData, (LPWSTR)mybuf, mylen/2);
-	      }
-	    }
-
-	    *lpcbData = mylen/2;			/* size is in byte! */
-	  }
-	  else						/* no strings, call it straight */
-	  { ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, lpbData, lpcbData );
-	  }
-	}
-	
-	if (lpdwType)					/* type when requested */
-	{ *lpdwType = mytype;
-	}
-
-	TRACE_(reg)(" (ret=%lx,type=%lx, len=%ld)\n", ret,mytype,lpcbData?*lpcbData:0);
-	
-	if(mybuf) free(mybuf);
-	if(lpszValueNameW) free(lpszValueNameW);
-	return ret;
-}
-
-
-/******************************************************************************
- * RegQueryValueEx16 [KERNEL.225]
- */
-DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPSTR lpszValueName,
-                                LPDWORD lpdwReserved, LPDWORD lpdwType,
-                                LPBYTE lpbData, LPDWORD lpcbData )
-{
-    TRACE_(reg)("(%x,%s,%p,%p,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
-          lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
-    return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
-                               lpbData, lpcbData );
-}
-
-
-/******************************************************************************
- * RegQueryValue32A [ADVAPI32.156]
- */
-DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR lpszSubKey, LPSTR lpszData,
-                               LPLONG lpcbData )
-{
-    HKEY xhkey;
-    DWORD ret, dwType;
-
-    TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
-          lpcbData?*lpcbData:0);
-
-    if (lpszSubKey && *lpszSubKey) {
-        ret = RegOpenKey16( hkey, lpszSubKey, &xhkey );
-        if( ret != ERROR_SUCCESS )
-            return ret;
-    } else
-        xhkey = hkey;
-
-    dwType = REG_SZ;
-    ret = RegQueryValueExA( xhkey, NULL,NULL, &dwType, (LPBYTE)lpszData,
-                              lpcbData );
-    if( xhkey != hkey )
-        RegCloseKey( xhkey );
-    return ret;
-}
-
-
-/******************************************************************************
- * RegQueryValue16 [SHELL.6] [KERNEL.224]
- *
- * NOTES
- *    Is this HACK still applicable?
- *
- * HACK
- *    The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
- *    mask out the high 16 bit.  This (not so much incidently) hopefully fixes
- *    Aldus FH4)
- */
-DWORD WINAPI RegQueryValue16( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData,
-                              LPDWORD lpcbData )
-{
-    TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
-          lpcbData?*lpcbData:0);
-
-    if (lpcbData)
-        *lpcbData &= 0xFFFF;
-    return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData);
-}
-
-
-/*
- * Setting values of Registry keys
- *
- * Callpath:
- * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
- *                                    RegSetValue32W   -> RegSetValueEx32W
- */
-
-
-/******************************************************************************
- * RegSetValueEx32W [ADVAPI32.170]
- * Sets the data and type of a value under a register key
- *
- * PARAMS
- *    hkey          [I] Handle of key to set value for
- *    lpszValueName [I] Name of value to set
- *    dwReserved    [I] Reserved - must be zero
- *    dwType        [I] Flag for value type
- *    lpbData       [I] Address of value data
- *    cbData        [I] Size of value data
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: Error code
- *
- * NOTES
- *   win95 does not care about cbData for REG_SZ and finds out the len by itself (js) 
- */
-DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR lpszValueName, 
-			     DWORD dwReserved, DWORD dwType,
-			     CONST BYTE *lpbData, DWORD cbData)
-{
-	LPKEYSTRUCT lpkey;
-	int i;
-
-	TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(lpszValueName),
-          dwReserved, dwType, lpbData, cbData);
-
-	lpkey = lookup_hkey( hkey );
-
-	if (!lpkey)
-          return ERROR_INVALID_HANDLE;
-
-	lpkey->flags |= REG_OPTION_TAINTED;
-
-	if (lpszValueName==NULL) {
-             /* Sets type and name for key's unnamed or default value */
-		for (i=0;i<lpkey->nrofvalues;i++)
-			if (lpkey->values[i].name==NULL)
-				break;
-	} else {
-		for (i=0;i<lpkey->nrofvalues;i++)
-			if (	lpkey->values[i].name &&
-				!lstrcmpiW(lpszValueName,lpkey->values[i].name)
-			)
-				break;
-	}
-	if (i==lpkey->nrofvalues) {
-		lpkey->values = (LPKEYVALUE)xrealloc(
-					lpkey->values,
-					(lpkey->nrofvalues+1)*sizeof(KEYVALUE)
-				);
-		lpkey->nrofvalues++;
-		memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
-	}
-	if (lpkey->values[i].name==NULL) {
-		if (lpszValueName)
-			lpkey->values[i].name = strdupW(lpszValueName);
-		else
-			lpkey->values[i].name = NULL;
-	}
-
-	if (dwType == REG_SZ)
-	  cbData = 2 * (lstrlenW ((LPCWSTR)lpbData) + 1);
-	  
-	lpkey->values[i].len	= cbData;
-	lpkey->values[i].type	= dwType;
-	if (lpkey->values[i].data !=NULL)
-		free(lpkey->values[i].data);
-	lpkey->values[i].data	= (LPBYTE)xmalloc(cbData);
-	lpkey->values[i].lastmodified = time(NULL);
-	memcpy(lpkey->values[i].data,lpbData,cbData);
-	return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegSetValueEx32A [ADVAPI32.169]
- *
- * NOTES
- *   win95 does not care about cbData for REG_SZ and finds out the len by itself (js) 
- */
-DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR lpszValueName,
-			     DWORD dwReserved, DWORD dwType,
-			     CONST BYTE *lpbData, DWORD cbData )
-{
-	LPBYTE	buf;
-	LPWSTR	lpszValueNameW;
-	DWORD	ret;
-
-	if (!lpbData)
-		return (ERROR_INVALID_PARAMETER);
-		
-	TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
-          dwReserved,dwType,lpbData,cbData);
-
-	if ((1<<dwType) & UNICONVMASK) 
-	{ if (dwType == REG_SZ)
-	    cbData = strlen ((LPCSTR)lpbData)+1;
-
-	  buf = (LPBYTE)xmalloc( cbData *2 );
-	  lmemcpynAtoW ((LPVOID)buf, lpbData, cbData );
-	  cbData=2*cbData;
-	} 
-	else
-	  buf=(LPBYTE)lpbData;
-
-	if (lpszValueName)
-	  lpszValueNameW = strdupA2W(lpszValueName);
-	else
-	  lpszValueNameW = NULL;
-
-	ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
-
-	if (lpszValueNameW)
-	  free(lpszValueNameW);
-
-	if (buf!=lpbData)
-	  free(buf);
-
-	return ret;
-}
-
-
-/******************************************************************************
- * RegSetValueEx16 [KERNEL.226]
- */
-DWORD WINAPI RegSetValueEx16( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved,
-                              DWORD dwType, LPBYTE lpbData, DWORD cbData )
-{
-    TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
-          dwReserved,dwType,lpbData,cbData);
-    return RegSetValueExA( hkey, lpszValueName, dwReserved, dwType, lpbData,
-                             cbData );
-}
-
-
-/******************************************************************************
- * RegSetValue32W	[ADVAPI32.171]
- */
-DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType,
-                             LPCWSTR lpszData, DWORD cbData )
-{
-	HKEY	xhkey;
-	DWORD	ret;
-
-	TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",
-		hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData
-	);
-	if (lpszSubKey && *lpszSubKey) {
-		ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey);
-		if (ret!=ERROR_SUCCESS)
-			return ret;
-	} else
-		xhkey=hkey;
-	if (dwType!=REG_SZ) {
-		TRACE_(reg)("dwType=%ld - Changing to REG_SZ\n",dwType);
-		dwType=REG_SZ;
-	}
-	if (cbData!=2*lstrlenW(lpszData)+2) {
-		TRACE_(reg)("Len=%ld != strlen(%s)+1=%d!\n",
-			cbData,debugstr_w(lpszData),2*lstrlenW(lpszData)+2
-		);
-		cbData=2*lstrlenW(lpszData)+2;
-	}
-	ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
-	if (hkey!=xhkey)
-		RegCloseKey(xhkey);
-	return ret;
-}
-
-
-/******************************************************************************
- * RegSetValue32A [ADVAPI32.168]
- *
- */
-DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
-                             LPCSTR lpszData, DWORD cbData )
-{
-	DWORD	ret;
-	HKEY	xhkey;
-
-	TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,lpszSubKey,dwType,lpszData,cbData);
-	if (lpszSubKey && *lpszSubKey) {
-		ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
-		if (ret!=ERROR_SUCCESS)
-			return ret;
-	} else
-		xhkey=hkey;
-
-	if (dwType!=REG_SZ) {
-		TRACE_(reg)("dwType=%ld!\n",dwType);
-		dwType=REG_SZ;
-	}
-	if (cbData!=strlen(lpszData)+1)
-		cbData=strlen(lpszData)+1;
-	ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
-	if (xhkey!=hkey)
-		RegCloseKey(xhkey);
-	return ret;
-}
-
-
-/******************************************************************************
- * RegSetValue16 [KERNEL.221] [SHELL.5]
- */
-DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR lpszSubKey, DWORD	dwType,
-                            LPCSTR lpszData, DWORD cbData )
-{
-    TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,debugstr_a(lpszSubKey),dwType,
-          debugstr_a(lpszData),cbData);
-    return RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData);
-}
-
-
-/* 
- * Key Enumeration
- *
- * Callpath:
- * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
- *                                  RegEnumKey32W   -> RegEnumKeyEx32W
- */
-
-
-/******************************************************************************
- * RegEnumKeyEx32W [ADVAPI32.139]
- *
- * PARAMS
- *    hkey         [I] Handle to key to enumerate
- *    iSubKey      [I] Index of subkey to enumerate
- *    lpszName     [O] Buffer for subkey name
- *    lpcchName    [O] Size of subkey buffer
- *    lpdwReserved [I] Reserved
- *    lpszClass    [O] Buffer for class string
- *    lpcchClass   [O] Size of class buffer
- *    ft           [O] Time key last written to
- */
-DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
-                              LPDWORD lpcchName, LPDWORD lpdwReserved,
-                              LPWSTR lpszClass, LPDWORD lpcchClass, 
-                              FILETIME *ft )
-{
-    LPKEYSTRUCT	lpkey,lpxkey;
-
-    TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n",hkey,iSubkey,lpszName,
-		lpcchName,lpcchName? *lpcchName : -1,lpdwReserved,lpszClass,
-		lpcchClass,ft);
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
-    if (!lpcchName)
-        return ERROR_INVALID_PARAMETER;
-
-    if (!lpkey->nextsub)
-        return ERROR_NO_MORE_ITEMS;
-    lpxkey=lpkey->nextsub;
-
-    /* Traverse the subkeys */
-    while (iSubkey && lpxkey) {
-        iSubkey--;
-	lpxkey=lpxkey->next;
-    }
-
-    if (iSubkey || !lpxkey)
-        return ERROR_NO_MORE_ITEMS;
-    if (lstrlenW(lpxkey->keyname)+1>*lpcchName) {
-        *lpcchName = lstrlenW(lpxkey->keyname);
-	return ERROR_MORE_DATA;
-    }
-    memcpy(lpszName,lpxkey->keyname,lstrlenW(lpxkey->keyname)*2+2);
-    *lpcchName = lstrlenW(lpszName);
-
-    if (lpszClass) {
-        /* FIXME: what should we write into it? */
-      *lpszClass	= 0;
-      *lpcchClass	= 2;
-    }
-    return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegEnumKeyW [ADVAPI32.140]
- */
-DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName, 
-                            DWORD lpcchName )
-{
-    DWORD ret;
-    TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
-    ret = RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,NULL);
-
-    /* If lpszName is NULL then we have a slightly different behaviour than
-       RegEnumKeyExW */
-    if(lpszName == NULL && ret == ERROR_MORE_DATA)
-        ret = ERROR_SUCCESS;
-
-    return ret;
-}
-
-
-/******************************************************************************
- * RegEnumKeyEx32A [ADVAPI32.138]
- */
-DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
-                              LPDWORD lpcchName, LPDWORD lpdwReserved, 
-                              LPSTR lpszClass, LPDWORD lpcchClass, 
-                              FILETIME *ft )
-{
-    DWORD	ret;
-    LPWSTR	lpszNameW, lpszClassW;
-
-    TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n",
-		hkey,iSubkey,lpszName,lpcchName,lpcchName? *lpcchName : -1,
-		lpdwReserved,lpszClass,lpcchClass,ft);
-
-    lpszNameW = lpszName ? (LPWSTR)xmalloc(*lpcchName * 2) : NULL;
-    lpszClassW = lpszClass ? (LPWSTR)xmalloc(*lpcchClass * 2) : NULL;
-
-    ret = RegEnumKeyExW(hkey, iSubkey, lpszNameW, lpcchName, lpdwReserved,
-			lpszClassW, lpcchClass, ft);
-
-    if (ret == ERROR_SUCCESS) {
-        lstrcpyWtoA(lpszName,lpszNameW);
-	if (lpszClassW)
-	    lstrcpyWtoA(lpszClass,lpszClassW);
-    }
-    if (lpszNameW)
-        free(lpszNameW);
-    if (lpszClassW)
-        free(lpszClassW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegEnumKeyA [ADVAPI32.137]
- */
-DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
-                            DWORD lpcchName )
-{
-    DWORD ret;
-    TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
-    ret = RegEnumKeyExA( hkey, iSubkey, lpszName, &lpcchName, NULL, NULL, 
-			 NULL, NULL );
-
-    /* If lpszName is NULL then we have a slightly different behaviour than
-       RegEnumKeyExA */
-    if(lpszName == NULL && ret == ERROR_MORE_DATA)
-        ret = ERROR_SUCCESS;
-
-    return ret;
-}
-
-
-/******************************************************************************
- * RegEnumKey16 [SHELL.7] [KERNEL.216]
- */
-DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
-                           DWORD lpcchName )
-{
-    TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
-    return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName);
-}
-
-
-/* 
- * Enumerate Registry Values
- *
- * Callpath:
- * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
- */
-
-
-/******************************************************************************
- * RegEnumValue32W [ADVAPI32.142]
- *
- * PARAMS
- *    hkey        [I] Handle to key to query
- *    iValue      [I] Index of value to query
- *    lpszValue   [O] Value string
- *    lpcchValue  [I/O] Size of value buffer (in wchars)
- *    lpdReserved [I] Reserved
- *    lpdwType    [O] Type code
- *    lpbData     [O] Value data
- *    lpcbData    [I/O] Size of data buffer (in bytes)
- *
- * Note:  wide character functions that take and/or return "character counts"
- *  use TCHAR (that is unsigned short or char) not byte counts.
- */
-DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue,
-                              LPDWORD lpcchValue, LPDWORD lpdReserved,
-                              LPDWORD lpdwType, LPBYTE lpbData, 
-                              LPDWORD lpcbData )
-{
-	LPKEYSTRUCT	lpkey;
-	LPKEYVALUE	val;
-
-	TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,debugstr_w(lpszValue),
-          lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData);
-
-	lpkey = lookup_hkey( hkey );
-	
-	if (!lpcbData && lpbData)
-		return ERROR_INVALID_PARAMETER;
-		
-	if (!lpkey)
-		return ERROR_INVALID_HANDLE;
-
-	if (lpkey->nrofvalues <= iValue)
-		return ERROR_NO_MORE_ITEMS;
-
-	val = &(lpkey->values[iValue]);
-
-	if (val->name) {
-	        if (lstrlenW(val->name)+1>*lpcchValue) {
-			*lpcchValue = lstrlenW(val->name)+1;
-			return ERROR_MORE_DATA;
-		}
-		memcpy(lpszValue,val->name,2 * (lstrlenW(val->name)+1) );
-		*lpcchValue=lstrlenW(val->name);
-	} else {
-		*lpszValue	= 0;
-		*lpcchValue	= 0;
-	}
-
-	/* Can be NULL if the type code is not required */
-	if (lpdwType)
-		*lpdwType = val->type;
-
-	if (lpbData) {
-		if (val->len>*lpcbData) {
-			*lpcbData = val->len;
-			return ERROR_MORE_DATA;
-		}
-		memcpy(lpbData,val->data,val->len);
-		*lpcbData = val->len;
-	}
-
-	debug_print_value ( val->data, val );
-	return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegEnumValue32A [ADVAPI32.141]
- */
-DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue,
-                              LPDWORD lpcchValue, LPDWORD lpdReserved,
-                              LPDWORD lpdwType, LPBYTE lpbData, 
-                              LPDWORD lpcbData )
-{
-	LPWSTR	lpszValueW;
-	LPBYTE	lpbDataW;
-	DWORD	ret,lpcbDataW;
-	DWORD dwType;
-
-	TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
-		lpdReserved,lpdwType,lpbData,lpcbData);
-
-	lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
-	if (lpbData) {
-		lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
-		lpcbDataW = *lpcbData;
-	} else
-		lpbDataW = NULL;
-
-	ret = RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue, 
-				lpdReserved, &dwType, lpbDataW, &lpcbDataW );
-
-	if (lpdwType)
-		*lpdwType = dwType;
-
-	if (ret==ERROR_SUCCESS) {
-		lstrcpyWtoA(lpszValue,lpszValueW);
-		if (lpbData) {
-			if ((1<<dwType) & UNICONVMASK) {
-				lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW);
-			} else {
-				if (lpcbDataW > *lpcbData) {
-					*lpcbData = lpcbDataW;
-					ret	= ERROR_MORE_DATA;
-				} else
-					memcpy(lpbData,lpbDataW,lpcbDataW);
-			}
-			*lpcbData = lpcbDataW;
-		}
-	}
-    if (lpbDataW) free(lpbDataW);
-    if (lpszValueW) free(lpszValueW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegEnumValue16 [KERNEL.223]
- */
-DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD iValue, LPSTR lpszValue, 
-                             LPDWORD lpcchValue, LPDWORD lpdReserved, 
-                             LPDWORD lpdwType, LPBYTE lpbData, 
-                             LPDWORD lpcbData )
-{
-    TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
-          lpdReserved,lpdwType,lpbData,lpcbData);
-    return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved, 
-                            lpdwType, lpbData, lpcbData );
-}
-
-
-/******************************************************************************
- * RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126]
- * Releases the handle of the specified key
- *
- * PARAMS
- *    hkey [I] Handle of key to close
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: Error code
- */
-DWORD WINAPI RegCloseKey( HKEY hkey )
-{
-    TRACE_(reg)("(%x)\n",hkey);
-
-    /* The standard handles are allowed to succeed, even though they are not
-       closed */
-    if (is_standard_hkey(hkey))
-        return ERROR_SUCCESS;
-
-    return remove_handle(hkey);
-}
-
-
-/* 
- * Delete registry key
- *
- * Callpath:
- * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
- */
-
-
-/******************************************************************************
- * RegDeleteKey32W [ADVAPI32.134]
- *
- * PARAMS
- *    hkey       [I] Handle to open key
- *    lpszSubKey [I] Name of subkey to delete
- *
- * RETURNS
- *    Success: ERROR_SUCCESS
- *    Failure: Error code
- */
-DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR lpszSubKey )
-{
-	LPKEYSTRUCT	*lplpPrevKey,lpNextKey,lpxkey;
-	LPWSTR		*wps;
-	int		wpc,i;
-
-    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszSubKey));
-
-    lpNextKey = lookup_hkey(hkey);
-    if (!lpNextKey)
-        return ERROR_INVALID_HANDLE;
-
-    /* Subkey param cannot be NULL */
-    if (!lpszSubKey || !*lpszSubKey)
-        return ERROR_BADKEY;
-
-    /* We need to know the previous key in the hier. */
-	split_keypath(lpszSubKey,&wps,&wpc);
-	i 	= 0;
-	lpxkey	= lpNextKey;
-	while (i<wpc-1) {
-		lpxkey=lpNextKey->nextsub;
-		while (lpxkey) {
-			TRACE_(reg)("  Scanning [%s]\n",
-				     debugstr_w(lpxkey->keyname));
-			if (!lstrcmpiW(wps[i],lpxkey->keyname))
-				break;
-			lpxkey=lpxkey->next;
-		}
-		if (!lpxkey) {
-			FREE_KEY_PATH;
-			TRACE_(reg)("  Not found.\n");
-			/* not found is success */
-			return ERROR_SUCCESS;
-		}
-		i++;
-		lpNextKey	= lpxkey;
-	}
-	lpxkey	= lpNextKey->nextsub;
-	lplpPrevKey = &(lpNextKey->nextsub);
-	while (lpxkey) {
-		TRACE_(reg)("  Scanning [%s]\n",
-			     debugstr_w(lpxkey->keyname));
-		if (!lstrcmpiW(wps[i],lpxkey->keyname))
-			break;
-		lplpPrevKey	= &(lpxkey->next);
-		lpxkey		= lpxkey->next;
-	}
-
-	if (!lpxkey) {
-		FREE_KEY_PATH;
-		WARN_(reg)("  Not found.\n");
-		return ERROR_FILE_NOT_FOUND;
-	}
-
-	if (lpxkey->nextsub) {
-		FREE_KEY_PATH;
-		WARN_(reg)("  Not empty.\n");
-		return ERROR_CANTWRITE;
-	}
-	*lplpPrevKey	= lpxkey->next;
-	free(lpxkey->keyname);
-	if (lpxkey->class)
-		free(lpxkey->class);
-	if (lpxkey->values)
-		free(lpxkey->values);
-	free(lpxkey);
-	FREE_KEY_PATH;
-	TRACE_(reg)("  Done.\n");
-	return	ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegDeleteKey32A [ADVAPI32.133]
- */
-DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR lpszSubKey )
-{
-    LPWSTR lpszSubKeyW;
-    DWORD  ret;
-
-    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
-    lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
-    ret = RegDeleteKeyW( hkey, lpszSubKeyW );
-    if(lpszSubKeyW) free(lpszSubKeyW);
-    return ret;
-}
-
-
-/******************************************************************************
- * RegDeleteKey16 [SHELL.4] [KERNEL.219]
- */
-DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR lpszSubKey )
-{
-    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
-    return RegDeleteKeyA( hkey, lpszSubKey );
-}
-
-
-/* 
- * Delete registry value
- *
- * Callpath:
- * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
- */
-
-
-/******************************************************************************
- * RegDeleteValue32W [ADVAPI32.136]
- *
- * PARAMS
- *    hkey      [I]
- *    lpszValue [I]
- *
- * RETURNS
- */
-DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR lpszValue )
-{
-	DWORD		i;
-	LPKEYSTRUCT	lpkey;
-	LPKEYVALUE	val;
-
-    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszValue));
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
-	if (lpszValue) {
-		for (i=0;i<lpkey->nrofvalues;i++)
-			if (	lpkey->values[i].name &&
-				!lstrcmpiW(lpkey->values[i].name,lpszValue)
-			)
-				break;
-	} else {
-		for (i=0;i<lpkey->nrofvalues;i++)
-			if (lpkey->values[i].name==NULL)
-				break;
-	}
-
-    if (i == lpkey->nrofvalues)
-        return ERROR_FILE_NOT_FOUND;
-
-	val	= lpkey->values+i;
-	if (val->name) free(val->name);
-	if (val->data) free(val->data);
-	memcpy(	
-		lpkey->values+i,
-		lpkey->values+i+1,
-		sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
-	);
-	lpkey->values	= (LPKEYVALUE)xrealloc(
-				lpkey->values,
-				(lpkey->nrofvalues-1)*sizeof(KEYVALUE)
-			);
-	lpkey->nrofvalues--;
-	return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegDeleteValue32A [ADVAPI32.135]
- */
-DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR lpszValue )
-{
-    LPWSTR lpszValueW;
-    DWORD  ret;
-
-    TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszValue));
-    lpszValueW = lpszValue?strdupA2W(lpszValue):NULL;
-    ret = RegDeleteValueW( hkey, lpszValueW );
-    if(lpszValueW) free(lpszValueW);
-    return ret;
-}
 
 
-/******************************************************************************
- * RegDeleteValue16 [KERNEL.222]
- */
-DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue )
-{
-    TRACE_(reg)("(%x,%s)\n", hkey,debugstr_a(lpszValue));
-    return RegDeleteValueA( hkey, lpszValue );
-}
 
 
 /******************************************************************************
@@ -3524,9 +1400,6 @@
  *
  * FIXME: does it really wait until data is written ?
  *
- * I guess that we can remove the REG_OPTION_TAINTED flag from every key
- * written if this function really works (and only if !).
- *
  * PARAMS
  *    hkey [I] Handle of key to write
  *
@@ -3536,177 +1409,10 @@
  */
 DWORD WINAPI RegFlushKey( HKEY hkey )
 {
-    LPKEYSTRUCT	lpkey;
-
-    TRACE_(reg)("(%x)\n", hkey);
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_BADKEY;
-
-	SHELL_SaveRegistryBranch(find_root_key(lpkey), TRUE);
-        return ERROR_SUCCESS;
+    FIXME( "(%x): stub\n", hkey );
+    return ERROR_SUCCESS;
 }
 
-
-/* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
-
-
-/******************************************************************************
- * RegQueryInfoKey32W [ADVAPI32.153]
- *
- * PARAMS
- *    hkey                   [I] Handle to key to query
- *    lpszClass              [O] Buffer for class string
- *    lpcchClass             [O] Size of class string buffer
- *    lpdwReserved           [I] Reserved
- *    lpcSubKeys             [I] Buffer for number of subkeys
- *    lpcchMaxSubKey         [O] Buffer for longest subkey name length
- *    lpcchMaxClass          [O] Buffer for longest class string length
- *    lpcValues              [O] Buffer for number of value entries
- *    lpcchMaxValueName      [O] Buffer for longest value name length
- *    lpccbMaxValueData      [O] Buffer for longest value data length
- *    lpcbSecurityDescriptor [O] Buffer for security descriptor length
- *    ft
- * - win95 allows lpszClass to be valid and lpcchClass to be NULL 
- * - winnt returns ERROR_INVALID_PARAMETER if lpszClass is valid and
- *   lpcchClass is NULL
- * - both allow lpszClass to be NULL and lpcchClass to be NULL 
- * (it's hard to test validity, so test !NULL instead)
- */
-DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass, 
-                                 LPDWORD lpcchClass, LPDWORD lpdwReserved,
-                                 LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey,
-                                 LPDWORD lpcchMaxClass, LPDWORD lpcValues,
-                                 LPDWORD lpcchMaxValueName, 
-                                 LPDWORD lpccbMaxValueData, 
-                                 LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
-{
-	LPKEYSTRUCT	lpkey,lpxkey;
-	int		nrofkeys,maxsubkey,maxclass,maxvname,maxvdata;
-	int		i;
-
-	TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
-		hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
-		lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
-		lpccbMaxValueData,lpcbSecurityDescriptor,ft
-	);
-	lpkey = lookup_hkey(hkey);
-	if (!lpkey)
-		return ERROR_INVALID_HANDLE;
-	if (lpszClass) {
-   	        if (VERSION_GetVersion() == NT40 && lpcchClass == NULL) {
-		    return ERROR_INVALID_PARAMETER;
-		}
-		/* either lpcchClass is valid or this is win95 and lpcchClass
-		   could be invalid */
-		if (lpkey->class) {
-		        DWORD classLen = lstrlenW(lpkey->class);
-
-			if (lpcchClass && classLen+1>*lpcchClass) {
-				*lpcchClass=classLen+1;
-				return ERROR_MORE_DATA;
-			}
-			if (lpcchClass)
-			    *lpcchClass=classLen;
-			memcpy(lpszClass,lpkey->class, classLen*2 + 2);
-		} else {
-			*lpszClass	= 0;
-			if (lpcchClass)
-			    *lpcchClass	= 0;
-		}
-	} else {
-		if (lpcchClass)
-			*lpcchClass	= lstrlenW(lpkey->class);
-	}
-	lpxkey=lpkey->nextsub;
-	nrofkeys=maxsubkey=maxclass=maxvname=maxvdata=0;
-	while (lpxkey) {
-		nrofkeys++;
-		if (lstrlenW(lpxkey->keyname)>maxsubkey)
-			maxsubkey=lstrlenW(lpxkey->keyname);
-		if (lpxkey->class && lstrlenW(lpxkey->class)>maxclass)
-			maxclass=lstrlenW(lpxkey->class);
-		lpxkey=lpxkey->next;
-	}
-	for (i=0;i<lpkey->nrofvalues;i++) {
-		LPKEYVALUE	val=lpkey->values+i;
-
-		if (val->name && lstrlenW(val->name)>maxvname)
-			maxvname=lstrlenW(val->name);
-		if (val->len>maxvdata)
-			maxvdata=val->len;
-	}
-	if (!maxclass) maxclass	= 1;
-	if (!maxvname) maxvname	= 1;
-	if (lpcValues)
-		*lpcValues	= lpkey->nrofvalues;
-	if (lpcSubKeys)
-		*lpcSubKeys	= nrofkeys;
-	if (lpcchMaxSubkey)
-		*lpcchMaxSubkey	= maxsubkey;
-	if (lpcchMaxClass)
-		*lpcchMaxClass	= maxclass;
-	if (lpcchMaxValueName)
-		*lpcchMaxValueName= maxvname;
-	if (lpccbMaxValueData)
-		*lpccbMaxValueData= maxvdata;
-	return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegQueryInfoKey32A [ADVAPI32.152]
- */
-DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass,
-                                 LPDWORD lpdwReserved, LPDWORD lpcSubKeys,
-                                 LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass,
-                                 LPDWORD lpcValues, LPDWORD lpcchMaxValueName,
-                                 LPDWORD lpccbMaxValueData, 
-                                 LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
-{
-	LPWSTR		lpszClassW = NULL;
-	DWORD		ret;
-
-	TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
-		hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
-		lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
-		lpccbMaxValueData,lpcbSecurityDescriptor,ft
-	);
-	if (lpszClass) {
-		if (lpcchClass) {
-		    lpszClassW  = (LPWSTR)xmalloc((*lpcchClass) * 2);
-		} else if (VERSION_GetVersion() == WIN95) {
-		    /* win95  allows lpcchClass to be null */
-		    /* we don't know how big lpszClass is, would 
-		       MAX_PATHNAME_LEN be the correct default? */
-		    lpszClassW  = (LPWSTR)xmalloc(MAX_PATHNAME_LEN*2); 
-		}
-
-	} else
-		lpszClassW  = NULL;
-	ret=RegQueryInfoKeyW(
-		hkey,
-		lpszClassW,
-		lpcchClass,
-		lpdwReserved,
-		lpcSubKeys,
-		lpcchMaxSubkey,
-		lpcchMaxClass,
-		lpcValues,
-		lpcchMaxValueName,
-		lpccbMaxValueData,
-		lpcbSecurityDescriptor,
-		ft
-	);
-	if (ret==ERROR_SUCCESS && lpszClass)
-		lstrcpyWtoA(lpszClass,lpszClassW);
-	if (lpszClassW)
-		free(lpszClassW);
-	return ret;
-}
-
-
 /******************************************************************************
  * RegConnectRegistry32W [ADVAPI32.128]
  *
@@ -3762,15 +1468,9 @@
                                PSECURITY_DESCRIPTOR pSecurityDescriptor,
                                LPDWORD lpcbSecurityDescriptor )
 {
-    LPKEYSTRUCT	lpkey;
-
     TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
           lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
 
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
     /* FIXME: Check for valid SecurityInformation values */
 
     if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
@@ -3784,49 +1484,6 @@
 
 
 /******************************************************************************
- * RegLoadKey32W [ADVAPI32.???]
- *
- * PARAMS
- *    hkey       [I] Handle of open key
- *    lpszSubKey [I] Address of name of subkey
- *    lpszFile   [I] Address of filename for registry information
- */
-LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPCWSTR lpszFile )
-{
-    LPKEYSTRUCT	lpkey;
-    TRACE_(reg)("(%x,%s,%s)\n",hkey,debugstr_w(lpszSubKey),debugstr_w(lpszFile));
-
-    /* Do this check before the hkey check */
-    if (!lpszSubKey || !*lpszSubKey || !lpszFile || !*lpszFile)
-        return ERROR_INVALID_PARAMETER;
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
-    FIXME_(reg)("(%x,%s,%s): stub\n",hkey,debugstr_w(lpszSubKey),
-          debugstr_w(lpszFile));
-
-    return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegLoadKey32A [ADVAPI32.???]
- */
-LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR lpszSubKey, LPCSTR lpszFile )
-{
-    LONG ret;
-    LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
-    LPWSTR lpszFileW = strdupA2W(lpszFile);
-    ret = RegLoadKeyW( hkey, lpszSubKeyW, lpszFileW );
-    if(lpszFileW) free(lpszFileW);
-    if(lpszSubKeyW) free(lpszSubKeyW);
-    return ret;
-}
-
-
-/******************************************************************************
  * RegNotifyChangeKeyValue [ADVAPI32.???]
  *
  * PARAMS
@@ -3840,17 +1497,8 @@
                                      DWORD fdwNotifyFilter, HANDLE hEvent,
                                      BOOL fAsync )
 {
-    LPKEYSTRUCT	lpkey;
-    TRACE_(reg)("(%x,%i,%ld,%x,%i)\n",hkey,fWatchSubTree,fdwNotifyFilter,
-          hEvent,fAsync);
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
     FIXME_(reg)("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
           hEvent,fAsync);
-
     return ERROR_SUCCESS;
 }
 
@@ -3893,8 +1541,6 @@
 LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
                                PSECURITY_DESCRIPTOR pSecurityDesc )
 {
-    LPKEYSTRUCT	lpkey;
-
     TRACE_(reg)("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
 
     /* It seems to perform this check before the hkey check */
@@ -3909,10 +1555,6 @@
     if (!pSecurityDesc)
         return ERROR_INVALID_PARAMETER;
 
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
     FIXME_(reg)(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
 
     return ERROR_SUCCESS;
@@ -3920,49 +1562,6 @@
 
 
 /******************************************************************************
- * RegSaveKey32W [ADVAPI32.166]
- *
- * PARAMS
- *    hkey   [I] Handle of key where save begins
- *    lpFile [I] Address of filename to save to
- *    sa     [I] Address of security structure
- */
-LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR lpFile, 
-                           LPSECURITY_ATTRIBUTES sa )
-{
-    LPKEYSTRUCT	lpkey;
-
-    TRACE_(reg)("(%x,%s,%p)\n", hkey, debugstr_w(lpFile), sa);
-
-    /* It appears to do this check before the hkey check */
-    if (!lpFile || !*lpFile)
-        return ERROR_INVALID_PARAMETER;
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
-    FIXME_(reg)("(%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa);
-
-    return ERROR_SUCCESS;
-}
-
-
-/******************************************************************************
- * RegSaveKey32A [ADVAPI32.165]
- */
-LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile, 
-                           LPSECURITY_ATTRIBUTES sa )
-{
-    LONG ret;
-    LPWSTR lpFileW = strdupA2W(lpFile);
-    ret = RegSaveKeyW( hkey, lpFileW, sa );
-    free(lpFileW);
-    return ret;
-}
-
-
-/******************************************************************************
  * RegRestoreKey32W [ADVAPI32.164]
  *
  * PARAMS
@@ -3972,18 +1571,12 @@
  */
 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
 {
-    LPKEYSTRUCT	lpkey;
-
     TRACE_(reg)("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
 
     /* It seems to do this check before the hkey check */
     if (!lpFile || !*lpFile)
         return ERROR_INVALID_PARAMETER;
 
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
     FIXME_(reg)("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
 
     /* Check for file existence */
@@ -4017,18 +1610,8 @@
 LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
                               LPCWSTR lpOldFile )
 {
-    LPKEYSTRUCT	lpkey;
-
-    TRACE_(reg)("(%x,%s,%s,%s)\n",hkey,debugstr_w(lpSubKey),
-          debugstr_w(lpNewFile),debugstr_w(lpOldFile));
-
-    lpkey = lookup_hkey( hkey );
-    if (!lpkey)
-        return ERROR_INVALID_HANDLE;
-
     FIXME_(reg)("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), 
           debugstr_w(lpNewFile),debugstr_w(lpOldFile));
-
     return ERROR_SUCCESS;
 }
 
@@ -4050,3 +1633,128 @@
     return ret;
 }
 
+
+
+
+
+
+/* 16-bit functions */
+
+/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
+ * some programs. Do not remove those cases. -MM
+ */
+static inline void fix_win16_hkey( HKEY *hkey )
+{
+    if (*hkey == 0 || *hkey == 1) *hkey = HKEY_CLASSES_ROOT;
+}
+
+/******************************************************************************
+ *           RegEnumKey16   [KERNEL.216] [SHELL.7]
+ */
+DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
+{
+    fix_win16_hkey( &hkey );
+    return RegEnumKeyA( hkey, index, name, name_len );
+}
+
+/******************************************************************************
+ *           RegOpenKey16   [KERNEL.217] [SHELL.1]
+ */
+DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
+{
+    fix_win16_hkey( &hkey );
+    return RegOpenKeyA( hkey, name, retkey );
+}
+
+/******************************************************************************
+ *           RegCreateKey16   [KERNEL.218] [SHELL.2]
+ */
+DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR name, LPHKEY retkey )
+{
+    fix_win16_hkey( &hkey );
+    return RegCreateKeyA( hkey, name, retkey );
+}
+
+/******************************************************************************
+ *           RegDeleteKey16   [KERNEL.219] [SHELL.4]
+ */
+DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR name )
+{
+    fix_win16_hkey( &hkey );
+    return RegDeleteKeyA( hkey, name );
+}
+
+/******************************************************************************
+ *           RegCloseKey16   [KERNEL.220] [SHELL.3]
+ */
+DWORD WINAPI RegCloseKey16( HKEY hkey )
+{
+    fix_win16_hkey( &hkey );
+    return RegCloseKey( hkey );
+}
+
+/******************************************************************************
+ *           RegSetValue16   [KERNEL.221] [SHELL.5]
+ */
+DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
+{
+    fix_win16_hkey( &hkey );
+    return RegSetValueA( hkey, name, type, data, count );
+}
+
+/******************************************************************************
+ *           RegDeleteValue16  [KERNEL.222]
+ */
+DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR name )
+{
+    fix_win16_hkey( &hkey );
+    return RegDeleteValueA( hkey, name );
+}
+
+/******************************************************************************
+ *           RegEnumValue16   [KERNEL.223]
+ */
+DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
+                             LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
+{
+    fix_win16_hkey( &hkey );
+    return RegEnumValueA( hkey, index, value, val_count, reserved, type, data, count );
+}
+
+/******************************************************************************
+ *           RegQueryValue16   [KERNEL.224] [SHELL.6]
+ *
+ * NOTES
+ *    Is this HACK still applicable?
+ *
+ * HACK
+ *    The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
+ *    mask out the high 16 bit.  This (not so much incidently) hopefully fixes
+ *    Aldus FH4)
+ */
+DWORD WINAPI RegQueryValue16( HKEY hkey, LPCSTR name, LPSTR data, LPDWORD count )
+{
+    fix_win16_hkey( &hkey );
+    if (count) *count &= 0xffff;
+    return RegQueryValueA( hkey, name, data, count );
+}
+
+/******************************************************************************
+ *           RegQueryValueEx16   [KERNEL.225]
+ */
+DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
+                                LPBYTE data, LPDWORD count )
+{
+    fix_win16_hkey( &hkey );
+    return RegQueryValueExA( hkey, name, reserved, type, data, count );
+}
+
+/******************************************************************************
+ *           RegSetValueEx16   [KERNEL.226]
+ */
+DWORD WINAPI RegSetValueEx16( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
+                              CONST BYTE *data, DWORD count )
+{
+    fix_win16_hkey( &hkey );
+    return RegSetValueExA( hkey, name, reserved, type, data, count );
+}