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 );
+}