From 2fab2ef11fadbb2dbefa84fcc73d626d3883dd6e Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 23 Nov 1999 19:41:34 +0000 Subject: [PATCH] Changed to use new server-side registry support. --- dlls/advapi32/Makefile.in | 1 + dlls/advapi32/registry.c | 1065 ++++++++++++++ dlls/shell32/shell.spec | 2 +- if1632/kernel.spec | 2 +- include/wine/winbase16.h | 7 +- include/winnt.h | 3 + include/winreg.h | 1 - misc/registry.c | 2844 ++++--------------------------------- 8 files changed, 1351 insertions(+), 2574 deletions(-) create mode 100644 dlls/advapi32/registry.c diff --git a/dlls/advapi32/Makefile.in b/dlls/advapi32/Makefile.in index fd09ec551b6..20788d0912b 100644 --- a/dlls/advapi32/Makefile.in +++ b/dlls/advapi32/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ 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 00000000000..6b8b5810c0b --- /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 +#include + +#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 656c321a9c1..adafd39c929 100644 --- a/dlls/shell32/shell.spec +++ b/dlls/shell32/shell.spec @@ -3,7 +3,7 @@ type win16 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 7f32d63e247..369bd2f7738 100644 --- a/if1632/kernel.spec +++ b/if1632/kernel.spec @@ -226,7 +226,7 @@ file krnl386.exe 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 428cde970f7..7f8158fca4c 100644 --- a/include/wine/winbase16.h +++ b/include/wine/winbase16.h @@ -166,16 +166,17 @@ BOOL16 WINAPI LocalUnlock16(HLOCAL16); 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 e00a560077a..691bd3d3904 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -1282,6 +1282,9 @@ typedef enum tagSID_NAME_USE { #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 9b5e4cfd5ee..f072694f8f7 100644 --- a/include/winreg.h +++ b/include/winreg.h @@ -50,7 +50,6 @@ extern "C" { #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 2c93d17da2a..7e22ddb8bd2 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 @@ static void REGISTRY_Init(void); #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< 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;ikeyname= strdupA2W(""); - -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;inextsub)) - 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;inrofvalues;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;jlen;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 @@ static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all ) * * 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) /* 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) 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 @@ static void SHELL_SaveRegistryBranch(HKEY hkey, int all) */ void SHELL_SaveRegistry( void ) { + struct set_registry_levels_request *req = get_req_buffer(); char buf[4]; HKEY hkey; int all; @@ -869,7 +273,7 @@ void SHELL_SaveRegistry( void ) 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 @@ void SHELL_SaveRegistry( void ) 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 @@ void SHELL_SaveRegistry( void ) /****************************************************************************** * _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;inrofvalues;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->lastmodifiedlastmodified=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 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str ) /* 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 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str ) } } *ws = 0; - ws = *str; - if (*ws) - *str = strdupW(*str); - else - *str = NULL; - free(ws); return s; } @@ -1113,21 +442,17 @@ static char* _wine_read_USTRING( char *buf, LPWSTR *str ) * 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 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, 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 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, 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 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, } 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 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, 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 @@ static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, /****************************************************************************** * _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 @@ static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag ) 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 @@ static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag ) /****************************************************************************** * _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 @@ static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag ) * 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;jnrofvalues;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;jnrofvalues;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 @@ struct _w95_info { /****************************************************************************** * _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 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey, 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 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey, 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 @@ static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey, 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 @@ static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off, 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 @@ static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off, 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 @@ static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey ) return; _lclose(hfd); - _w95_walkrgkn(lpkey, NULL, &info); + _w95_walkrgkn(hkey, NULL, &info); free (info.rgdbbuffer); free (info.rgknbuffer); @@ -1816,15 +1093,14 @@ __w31_dumptree( unsigned short idx, 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 @@ __w31_dumptree( unsigned short idx, * 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 @@ void _w31_loadreg(void) { OFSTRUCT ofs; BY_HANDLE_FILE_INFORMATION hfinfo; time_t lastmodified; - LPKEYSTRUCT lpkey; TRACE_(reg)("(void)\n"); @@ -1933,8 +1204,7 @@ void _w31_loadreg(void) { 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 _w31_loadreg(void) { */ 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 @@ void SHELL_LoadRegistry( void ) /* * 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) * 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 @@ void SHELL_LoadRegistry( void ) */ /* 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 @@ void SHELL_LoadRegistry( void ) 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 @@ void SHELL_LoadRegistry( void ) /********************* 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 ((inextsub; - 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 ((inextsub; - 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;inrofvalues;i++) - if (lpkey->values[i].name==NULL) - break; - } - else - { /* Search for the key name */ - for (i=0;inrofvalues;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;inrofvalues;i++) - if (lpkey->values[i].name==NULL) - break; - } else { - for (i=0;inrofvalues;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< 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< *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 (inextsub; - 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;inrofvalues;i++) - if ( lpkey->values[i].name && - !lstrcmpiW(lpkey->values[i].name,lpszValue) - ) - break; - } else { - for (i=0;inrofvalues;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 @@ DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue ) * * 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 RegDeleteValue16( HKEY hkey, LPSTR lpszValue ) */ 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;inrofvalues;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 @@ LONG WINAPI RegGetKeySecurity( HKEY hkey, 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)) @@ -3783,49 +1483,6 @@ LONG WINAPI RegGetKeySecurity( HKEY hkey, } -/****************************************************************************** - * 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.???] * @@ -3840,17 +1497,8 @@ LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree, 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 RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey ) 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,59 +1555,12 @@ LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo, 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; } -/****************************************************************************** - * 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] * @@ -3972,18 +1571,12 @@ LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile, */ 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 RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags ) 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 @@ LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile, 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 ); +}