Commit 2fab2ef1 authored by Alexandre Julliard's avatar Alexandre Julliard

Changed to use new server-side registry support.

parent d7e85d66
......@@ -11,6 +11,7 @@ C_SRCS = \
advapi.c \
crypt.c \
eventlog.c \
registry.c \
security.c \
service.c
......
/*
* Registry management
*
* Copyright (C) 1999 Alexandre Julliard
*
* Based on misc/registry.c code
* Copyright (C) 1996 Marcus Meissner
* Copyright (C) 1998 Matthew Becker
* Copyright (C) 1999 Sylvain St-Germain
*
* This file is concerned about handle management and interaction with the Wine server.
* Registry file I/O is in misc/registry.c.
*/
#include <stdlib.h>
#include <unistd.h>
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "wine/winbase16.h"
#include "winversion.h"
#include "file.h"
#include "heap.h"
#include "server.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(reg)
/* Ansi->Unicode conversion without string delimiters */
static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n )
{
LPWSTR p = dst;
while (n-- > 0) *p++ = (WCHAR)*src++;
return dst;
}
/* Unicode->Ansi conversion without string delimiters */
static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n )
{
LPSTR p = dst;
while (n-- > 0) *p++ = (CHAR)*src++;
return dst;
}
/* check if value type needs string conversion (Ansi<->Unicode) */
static inline int is_string( DWORD type )
{
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
}
/* copy key value data into a user-specified buffer
*
* 'len' is the total length of the data
* 'count' is the size of the user-specified buffer
* and is updated to reflect the length copied
*/
static DWORD copy_data( void *data, const void *src, DWORD len, DWORD *count )
{
DWORD ret = ERROR_SUCCESS;
if (data)
{
if (*count < len) ret = ERROR_MORE_DATA;
else memcpy( data, src, len );
}
*count = len;
return ret;
}
/* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
static DWORD copy_data_WtoA( void *data, const void *src, DWORD len, DWORD *count, DWORD type )
{
DWORD ret = ERROR_SUCCESS;
if (is_string( type ))
{
/* need to convert from Unicode */
len /= sizeof(WCHAR);
if (data)
{
if (*count < len) ret = ERROR_MORE_DATA;
else memcpyWtoA( data, src, len );
}
}
else if (data)
{
if (*count < len) ret = ERROR_MORE_DATA;
else memcpy( data, src, len );
}
*count = len;
return ret;
}
/* copy a key name into the request buffer */
static inline DWORD copy_nameW( LPWSTR dest, LPCWSTR name )
{
if (name)
{
if (lstrlenW(name) > MAX_PATH) return ERROR_MORE_DATA;
lstrcpyW( dest, name );
}
else dest[0] = 0;
return ERROR_SUCCESS;
}
/* copy a key name into the request buffer */
static inline DWORD copy_nameAtoW( LPWSTR dest, LPCSTR name )
{
if (name)
{
if (strlen(name) > MAX_PATH) return ERROR_MORE_DATA;
lstrcpyAtoW( dest, name );
}
else dest[0] = 0;
return ERROR_SUCCESS;
}
/******************************************************************************
* RegCreateKeyExW [ADVAPI32.131]
*
* PARAMS
* hkey [I] Handle of an open key
* name [I] Address of subkey name
* reserved [I] Reserved - must be 0
* class [I] Address of class string
* options [I] Special options flag
* access [I] Desired security access
* sa [I] Address of key security structure
* retkey [O] Address of buffer for opened handle
* dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
*/
DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
debugstr_w(class), options, access, sa, retkey, dispos );
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = server_call_noerr( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
}
/******************************************************************************
* RegCreateKeyExA [ADVAPI32.130]
*/
DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
LPHKEY retkey, LPDWORD dispos )
{
DWORD ret;
struct create_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
debugstr_a(class), options, access, sa, retkey, dispos );
if (reserved) return ERROR_INVALID_PARAMETER;
if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
req->parent = hkey;
req->access = access;
req->options = options;
req->modif = time(NULL);
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
lstrcpynAtoW( req->class, class ? class : "",
server_remaining(req->class) / sizeof(WCHAR) );
if ((ret = server_call_noerr( REQ_CREATE_KEY )) == ERROR_SUCCESS)
{
*retkey = req->hkey;
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
}
return ret;
}
/******************************************************************************
* RegCreateKeyW [ADVAPI32.132]
*/
DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
{
/* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
/* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
return RegCreateKeyExW( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, retkey, NULL );
}
/******************************************************************************
* RegCreateKeyA [ADVAPI32.129]
*/
DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
{
return RegCreateKeyExA( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, retkey, NULL );
}
/******************************************************************************
* RegOpenKeyExW [ADVAPI32.150]
*
* Opens the specified key
*
* Unlike RegCreateKeyEx, this does not create the key if it does not exist.
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Name of subkey to open
* reserved [I] Reserved - must be zero
* access [I] Security access mask
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
if (!retkey) return ERROR_INVALID_PARAMETER;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = server_call_noerr( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
}
/******************************************************************************
* RegOpenKeyExA [ADVAPI32.149]
*/
DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
{
DWORD ret;
struct open_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
if (!retkey) return ERROR_INVALID_PARAMETER;
req->parent = hkey;
req->access = access;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
if ((ret = server_call_noerr( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
return ret;
}
/******************************************************************************
* RegOpenKeyW [ADVAPI32.151]
*
* PARAMS
* hkey [I] Handle of open key
* name [I] Address of name of subkey to open
* retkey [O] Handle to open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
{
return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
}
/******************************************************************************
* RegOpenKeyA [ADVAPI32.148]
*/
DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
{
return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
}
/******************************************************************************
* RegEnumKeyExW [ADVAPI32.139]
*
* PARAMS
* hkey [I] Handle to key to enumerate
* index [I] Index of subkey to enumerate
* name [O] Buffer for subkey name
* name_len [O] Size of subkey buffer
* reserved [I] Reserved
* class [O] Buffer for class string
* class_len [O] Size of class buffer
* ft [O] Time key last written to
*/
DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
{
DWORD ret, len, cls_len;
struct enum_key_request *req = get_req_buffer();
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
name_len ? *name_len : -1, reserved, class, class_len, ft );
if (reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->index = index;
if ((ret = server_call_noerr( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
len = lstrlenW( req->name ) + 1;
cls_len = lstrlenW( req->class ) + 1;
if (len > *name_len) return ERROR_MORE_DATA;
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
memcpy( name, req->name, len * sizeof(WCHAR) );
*name_len = len - 1;
if (class_len)
{
if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
*class_len = cls_len - 1;
}
if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegEnumKeyExA [ADVAPI32.138]
*/
DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
{
DWORD ret, len, cls_len;
struct enum_key_request *req = get_req_buffer();
TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
name_len ? *name_len : -1, reserved, class, class_len, ft );
if (reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->index = index;
if ((ret = server_call_noerr( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
len = lstrlenW( req->name ) + 1;
cls_len = lstrlenW( req->class ) + 1;
if (len > *name_len) return ERROR_MORE_DATA;
if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
memcpyWtoA( name, req->name, len );
*name_len = len - 1;
if (class_len)
{
if (class) memcpyWtoA( class, req->class, cls_len );
*class_len = cls_len - 1;
}
if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegEnumKeyW [ADVAPI32.140]
*/
DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
{
return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
}
/******************************************************************************
* RegEnumKeyA [ADVAPI32.137]
*/
DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
{
return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
}
/******************************************************************************
* RegQueryInfoKeyW [ADVAPI32.153]
*
* PARAMS
* hkey [I] Handle to key to query
* class [O] Buffer for class string
* class_len [O] Size of class string buffer
* reserved [I] Reserved
* subkeys [O] Buffer for number of subkeys
* max_subkey [O] Buffer for longest subkey name length
* max_class [O] Buffer for longest class string length
* values [O] Buffer for number of value entries
* max_value [O] Buffer for longest value name length
* max_data [O] Buffer for longest value data length
* security [O] Buffer for security descriptor length
* modif [O] Modification time
*
* - win95 allows class to be valid and class_len to be NULL
* - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
* - both allow class to be NULL and class_len to be NULL
* (it's hard to test validity, so test !NULL instead)
*/
DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
LPDWORD security, FILETIME *modif )
{
DWORD ret;
struct query_key_info_request *req = get_req_buffer();
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
if (class && !class_len && (VERSION_GetVersion() == NT40))
return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
if ((ret = server_call_noerr( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
if (class)
{
if (class_len && (lstrlenW(req->class) + 1 > *class_len))
{
*class_len = lstrlenW(req->class);
return ERROR_MORE_DATA;
}
lstrcpyW( class, req->class );
}
if (class_len) *class_len = lstrlenW( req->class );
if (subkeys) *subkeys = req->subkeys;
if (max_subkey) *max_subkey = req->max_subkey;
if (max_class) *max_class = req->max_class;
if (values) *values = req->values;
if (max_value) *max_value = req->max_value;
if (max_data) *max_data = req->max_data;
if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegQueryInfoKeyA [ADVAPI32.152]
*/
DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
LPDWORD values, LPDWORD max_value, LPDWORD max_data,
LPDWORD security, FILETIME *modif )
{
DWORD ret;
struct query_key_info_request *req = get_req_buffer();
TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
if (class && !class_len && (VERSION_GetVersion() == NT40))
return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
if ((ret = server_call_noerr( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
if (class)
{
if (class_len && (lstrlenW(req->class) + 1 > *class_len))
{
*class_len = lstrlenW(req->class);
return ERROR_MORE_DATA;
}
lstrcpyWtoA( class, req->class );
}
if (class_len) *class_len = lstrlenW( req->class );
if (subkeys) *subkeys = req->subkeys;
if (max_subkey) *max_subkey = req->max_subkey;
if (max_class) *max_class = req->max_class;
if (values) *values = req->values;
if (max_value) *max_value = req->max_value;
if (max_data) *max_data = req->max_data;
if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegCloseKey [ADVAPI32.126]
*
* Releases the handle of the specified key
*
* PARAMS
* hkey [I] Handle of key to close
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegCloseKey( HKEY hkey )
{
struct close_key_request *req = get_req_buffer();
TRACE( "(0x%x)\n", hkey );
req->hkey = hkey;
return server_call_noerr( REQ_CLOSE_KEY );
}
/******************************************************************************
* RegDeleteKeyW [ADVAPI32.134]
*
* PARAMS
* hkey [I] Handle to open key
* name [I] Name of subkey to delete
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return server_call_noerr( REQ_DELETE_KEY );
}
/******************************************************************************
* RegDeleteKeyA [ADVAPI32.133]
*/
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
return server_call_noerr( REQ_DELETE_KEY );
}
/******************************************************************************
* RegSetValueExW [ADVAPI32.170]
*
* Sets the data and type of a value under a register key
*
* PARAMS
* hkey [I] Handle of key to set value for
* name [I] Name of value to set
* reserved [I] Reserved - must be zero
* type [I] Flag for value type
* data [I] Address of value data
* count [I] Size of value data
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* win95 does not care about count for REG_SZ and finds out the len by itself (js)
* NT does definitely care (aj)
*/
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
DWORD type, CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{
LPCWSTR str = (LPCWSTR)data;
/* if user forgot to count terminating null, add it (yes NT does this) */
if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
count += sizeof(WCHAR);
}
if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
req->hkey = hkey;
req->type = type;
req->len = count;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
memcpy( req->data, data, count );
return server_call_noerr( REQ_SET_KEY_VALUE );
}
/******************************************************************************
* RegSetValueExA [ADVAPI32.169]
*/
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
CONST BYTE *data, DWORD count )
{
DWORD ret;
struct set_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
if (reserved) return ERROR_INVALID_PARAMETER;
if (count && type == REG_SZ)
{
/* if user forgot to count terminating null, add it (yes NT does this) */
if (data[count-1] && !data[count]) count++;
}
if (is_string( type ))
{
/* need to convert to Unicode */
count *= sizeof(WCHAR);
if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
memcpyAtoW( (LPWSTR)req->data, data, count / sizeof(WCHAR) );
}
else
{
if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
memcpy( req->data, data, count );
}
req->hkey = hkey;
req->type = type;
req->len = count;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
return server_call_noerr( REQ_SET_KEY_VALUE );
}
/******************************************************************************
* RegSetValueW [ADVAPI32.171]
*/
DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
{
HKEY subkey = hkey;
DWORD ret;
TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
if (name && name[0]) /* need to create the subkey */
{
if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
}
ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data,
(lstrlenW( data ) + 1) * sizeof(WCHAR) );
if (subkey != hkey) RegCloseKey( subkey );
return ret;
}
/******************************************************************************
* RegSetValueA [ADVAPI32.168]
*/
DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
{
HKEY subkey = hkey;
DWORD ret;
TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
if (name && name[0]) /* need to create the subkey */
{
if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
}
ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 );
if (subkey != hkey) RegCloseKey( subkey );
return ret;
}
/******************************************************************************
* RegQueryValueExW [ADVAPI32.158]
*
* Retrieves type and data for a specified name associated with an open key
*
* PARAMS
* hkey [I] Handle of key to query
* name [I] Name of value to query
* reserved [I] Reserved - must be NULL
* type [O] Address of buffer for value type. If NULL, the type
* is not required.
* data [O] Address of data buffer. If NULL, the actual data is
* not required.
* count [I/O] Address of data buffer size
*
* RETURNS
* ERROR_SUCCESS: Success
* ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
{
DWORD ret;
struct get_key_value_request *req = get_req_buffer();
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
if (!count || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = server_call_noerr( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
{
if (type) *type = req->type;
ret = copy_data( data, req->data, req->len, count );
}
return ret;
}
/******************************************************************************
* RegQueryValueExA [ADVAPI32.157]
*
* NOTES:
* the documentation is wrong: if the buffer is to small it remains untouched
*/
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
LPBYTE data, LPDWORD count )
{
DWORD ret;
struct get_key_value_request *req = get_req_buffer();
TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
if (!count || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
if ((ret = server_call_noerr( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
{
if (type) *type = req->type;
ret = copy_data_WtoA( data, req->data, req->len, count, req->type );
}
return ret;
}
/******************************************************************************
* RegQueryValueW [ADVAPI32.159]
*/
DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
{
DWORD ret;
HKEY subkey = hkey;
TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
if (name && name[0])
{
if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
}
ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
if (subkey != hkey) RegCloseKey( subkey );
if (ret == ERROR_FILE_NOT_FOUND)
{
/* return empty string if default value not found */
if (data) *data = 0;
if (count) *count = 1;
ret = ERROR_SUCCESS;
}
return ret;
}
/******************************************************************************
* RegQueryValueA [ADVAPI32.156]
*/
DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
{
DWORD ret;
HKEY subkey = hkey;
TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
if (name && name[0])
{
if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
}
ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
if (subkey != hkey) RegCloseKey( subkey );
if (ret == ERROR_FILE_NOT_FOUND)
{
/* return empty string if default value not found */
if (data) *data = 0;
if (count) *count = 1;
ret = ERROR_SUCCESS;
}
return ret;
}
/******************************************************************************
* RegEnumValueW [ADVAPI32.142]
*
* PARAMS
* hkey [I] Handle to key to query
* index [I] Index of value to query
* value [O] Value string
* val_count [I/O] Size of value buffer (in wchars)
* reserved [I] Reserved
* type [O] Type code
* data [O] Value data
* count [I/O] Size of data buffer (in bytes)
*/
DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
{
DWORD ret, len;
struct enum_key_value_request *req = get_req_buffer();
TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
hkey, index, value, val_count, reserved, type, data, count );
/* NT only checks count, not val_count */
if (!count || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->index = index;
if ((ret = server_call_noerr( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
len = lstrlenW( req->name ) + 1;
if (len > *val_count) return ERROR_MORE_DATA;
memcpy( value, req->name, len * sizeof(WCHAR) );
*val_count = len - 1;
if (type) *type = req->type;
return copy_data( data, req->data, req->len, count );
}
/******************************************************************************
* RegEnumValueA [ADVAPI32.141]
*/
DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
{
DWORD ret, len;
struct enum_key_value_request *req = get_req_buffer();
TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
hkey, index, value, val_count, reserved, type, data, count );
/* NT only checks count, not val_count */
if (!count || reserved) return ERROR_INVALID_PARAMETER;
req->hkey = hkey;
req->index = index;
if ((ret = server_call_noerr( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
len = lstrlenW( req->name ) + 1;
if (len > *val_count) return ERROR_MORE_DATA;
memcpyWtoA( value, req->name, len );
*val_count = len - 1;
if (type) *type = req->type;
return copy_data_WtoA( data, req->data, req->len, count, req->type );
}
/******************************************************************************
* RegDeleteValueW [ADVAPI32.136]
*
* PARAMS
* hkey [I] handle to key
* name [I] name of value to delete
*
* RETURNS
* error status
*/
DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
req->hkey = hkey;
if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
return server_call_noerr( REQ_DELETE_KEY_VALUE );
}
/******************************************************************************
* RegDeleteValueA [ADVAPI32.135]
*/
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
{
DWORD ret;
struct delete_key_value_request *req = get_req_buffer();
TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
req->hkey = hkey;
if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
return server_call_noerr( REQ_DELETE_KEY_VALUE );
}
/******************************************************************************
* RegLoadKeyW [ADVAPI32.185]
*
* PARAMS
* hkey [I] Handle of open key
* subkey [I] Address of name of subkey
* filename [I] Address of filename for registry information
*/
LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
{
struct load_registry_request *req = get_req_buffer();
HANDLE file;
DWORD ret, err = GetLastError();
TRACE( "(%x,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) );
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
{
ret = GetLastError();
goto done;
}
req->hkey = hkey;
req->file = file;
if ((ret = copy_nameW( req->name, subkey )) != ERROR_SUCCESS) goto done;
ret = server_call_noerr( REQ_LOAD_REGISTRY );
CloseHandle( file );
done:
SetLastError( err ); /* restore the last error code */
return ret;
}
/******************************************************************************
* RegLoadKeyA [ADVAPI32.184]
*/
LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
{
struct load_registry_request *req = get_req_buffer();
HANDLE file;
DWORD ret, err = GetLastError();
TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
{
ret = GetLastError();
goto done;
}
req->hkey = hkey;
req->file = file;
if ((ret = copy_nameAtoW( req->name, subkey )) != ERROR_SUCCESS) goto done;
ret = server_call_noerr( REQ_LOAD_REGISTRY );
CloseHandle( file );
done:
SetLastError( err ); /* restore the last error code */
return ret;
}
/******************************************************************************
* RegSaveKeyA [ADVAPI32.165]
*
* PARAMS
* hkey [I] Handle of key where save begins
* lpFile [I] Address of filename to save to
* sa [I] Address of security structure
*/
LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
{
struct save_registry_request *req = get_req_buffer();
char buffer[1024];
int count = 0;
LPSTR name;
DWORD ret, err;
HFILE handle;
TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
if (!file || !*file) return ERROR_INVALID_PARAMETER;
err = GetLastError();
GetFullPathNameA( file, sizeof(buffer), buffer, &name );
for (;;)
{
sprintf( name, "reg%04x.tmp", count++ );
handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
if (handle != INVALID_HANDLE_VALUE) break;
if ((ret = GetLastError()) != ERROR_FILE_EXISTS) goto done;
}
req->hkey = hkey;
req->file = handle;
ret = server_call_noerr( REQ_SAVE_REGISTRY );
CloseHandle( handle );
if (!ret)
{
if (!MoveFileExA( buffer, file, MOVEFILE_REPLACE_EXISTING ))
{
ERR( "Failed to move %s to %s\n", buffer, file );
ret = GetLastError();
}
}
if (ret) DeleteFileA( buffer );
done:
SetLastError( err ); /* restore last error code */
return ret;
}
/******************************************************************************
* RegSaveKeyW [ADVAPI32.166]
*/
LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
{
LPSTR fileA = HEAP_strdupWtoA( GetProcessHeap(), 0, file );
DWORD ret = RegSaveKeyA( hkey, fileA, sa );
if (fileA) HeapFree( GetProcessHeap(), 0, fileA );
return ret;
}
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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)
......
......@@ -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
......
......@@ -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<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
static struct openhandle {
LPKEYSTRUCT lpkey;
HKEY hkey;
REGSAM accessmask;
} *openhandles=NULL;
static int nrofopenhandles=0;
/* Starts after 1 because 0,1 are reserved for Win16 */
/* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd
HKEYs for remote registry access */
static int currenthandle=2;
/*
* QUESTION
......@@ -136,19 +91,6 @@ static LPWSTR strdupA2W(LPCSTR src)
return NULL;
}
static LPWSTR strdupW(LPCWSTR a) {
LPWSTR b;
int len;
if(a) {
len=sizeof(WCHAR)*(lstrlenW(a)+1);
b=(LPWSTR)xmalloc(len);
memcpy(b,a,len);
return b;
}
return NULL;
}
LPWSTR strcvtA2W(LPCSTR src, int nchars)
{
......@@ -158,388 +100,6 @@ LPWSTR strcvtA2W(LPCSTR src, int nchars)
dest[nchars] = 0;
return dest;
}
/*
* we need to convert A to W with '\0' in strings (MULTI_SZ)
*/
static LPWSTR lmemcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
{ LPWSTR p = dst;
TRACE_(reg)("\"%s\" %i\n",src, n);
while (n-- > 0) *p++ = (WCHAR)(unsigned char)*src++;
return dst;
}
static LPSTR lmemcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
{ LPSTR p = dst;
TRACE_(string)("L\"%s\" %i\n",debugstr_w(src), n);
while (n-- > 0) *p++ = (CHAR)*src++;
return dst;
}
static void debug_print_value (LPBYTE lpbData, LPKEYVALUE key)
{
if (TRACE_ON(reg) && lpbData)
{
switch(key->type)
{
case REG_EXPAND_SZ:
case REG_SZ:
TRACE_(reg)(" Value %s, Data(sz)=%s\n",
debugstr_w(key->name),
debugstr_w((LPCWSTR)lpbData));
break;
case REG_DWORD:
TRACE_(reg)(" Value %s, Data(dword)=0x%08lx\n",
debugstr_w(key->name),
(DWORD)*lpbData);
break;
case REG_MULTI_SZ:
{
int i;
LPCWSTR ptr = (LPCWSTR)lpbData;
for (i=0;ptr[0];i++)
{
TRACE_(reg)(" Value %s, MULTI_SZ(%i=%s)\n",
debugstr_w(key->name),
i,
debugstr_w(ptr));
ptr += lstrlenW(ptr)+1;
}
}
break;
default:
{
char szTemp[100]; /* 3*32 + 3 + 1 */
int i;
for ( i = 0; i < key->len ; i++)
{
sprintf (&(szTemp[i*3]),"%02x ", lpbData[i]);
if (i>=31)
{
sprintf (&(szTemp[i*3+3]),"...");
break;
}
}
TRACE_(reg)(" Value %s, Data(raw)=(%s)\n",
debugstr_w(key->name),
szTemp);
}
} /* switch */
} /* if */
}
/******************************************************************************
* is_standard_hkey [Internal]
* Determines if a hkey is a standard key
*/
static BOOL is_standard_hkey( HKEY hkey )
{
switch(hkey) {
case 0x00000000:
case 0x00000001:
case HKEY_CLASSES_ROOT:
case HKEY_CURRENT_CONFIG:
case HKEY_CURRENT_USER:
case HKEY_LOCAL_MACHINE:
case HKEY_USERS:
case HKEY_PERFORMANCE_DATA:
case HKEY_DYN_DATA:
return TRUE;
default:
return FALSE;
}
}
/******************************************************************************
* add_handle [Internal]
*/
static void add_handle( HKEY hkey, LPKEYSTRUCT lpkey, REGSAM accessmask )
{
int i;
TRACE_(reg)("(0x%x,%p,0x%lx)\n",hkey,lpkey,accessmask);
/* Check for duplicates */
for (i=0;i<nrofopenhandles;i++) {
if (openhandles[i].lpkey==lpkey) {
/* This is not really an error - the user is allowed to create
two (or more) handles to the same key */
/*WARN(reg, "Adding key %p twice\n",lpkey);*/
}
if (openhandles[i].hkey==hkey) {
WARN_(reg)("Adding handle %x twice\n",hkey);
}
}
openhandles=xrealloc( openhandles,
sizeof(struct openhandle)*(nrofopenhandles+1));
openhandles[i].lpkey = lpkey;
openhandles[i].hkey = hkey;
openhandles[i].accessmask = accessmask;
nrofopenhandles++;
}
/******************************************************************************
* get_handle [Internal]
*
* RETURNS
* Success: Pointer to key
* Failure: NULL
*/
static LPKEYSTRUCT get_handle( HKEY hkey )
{
int i;
for (i=0; i<nrofopenhandles; i++)
if (openhandles[i].hkey == hkey)
return openhandles[i].lpkey;
WARN_(reg)("Could not find handle 0x%x\n",hkey);
return NULL;
}
/******************************************************************************
* remove_handle [Internal]
*
* PARAMS
* hkey [I] Handle of key to remove
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: ERROR_INVALID_HANDLE
*/
static DWORD remove_handle( HKEY hkey )
{
int i;
for (i=0;i<nrofopenhandles;i++)
if (openhandles[i].hkey==hkey)
break;
if (i == nrofopenhandles) {
WARN_(reg)("Could not find handle 0x%x\n",hkey);
return ERROR_INVALID_HANDLE;
}
memcpy( openhandles+i,
openhandles+i+1,
sizeof(struct openhandle)*(nrofopenhandles-i-1)
);
openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
nrofopenhandles--;
return ERROR_SUCCESS;
}
/******************************************************************************
* lookup_hkey [Internal]
*
* Just as the name says. Creates the root keys on demand, so we can call the
* Reg* functions at any time.
*
* RETURNS
* Success: Pointer to key structure
* Failure: NULL
*/
#define ADD_ROOT_KEY(xx) \
xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
memset(xx,'\0',sizeof(KEYSTRUCT));\
xx->keyname= strdupA2W("<should_not_appear_anywhere>");
static LPKEYSTRUCT lookup_hkey( HKEY hkey )
{
switch (hkey) {
/* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
* some programs. Do not remove those cases. -MM
*/
case 0x00000000:
case 0x00000001:
case HKEY_CLASSES_ROOT:
{
if (!key_classes_root)
{
HKEY cl_r_hkey;
/* calls lookup_hkey recursively, TWICE */
if ( RegCreateKey16(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Classes",
&cl_r_hkey) != ERROR_SUCCESS)
{
ERR_(reg)("Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
exit(1);
}
key_classes_root = lookup_hkey(cl_r_hkey);
}
return key_classes_root;
}
case HKEY_CURRENT_USER:
if (!key_current_user) {
ADD_ROOT_KEY(key_current_user);
}
return key_current_user;
case HKEY_LOCAL_MACHINE:
if (!key_local_machine) {
ADD_ROOT_KEY(key_local_machine);
REGISTRY_Init();
}
return key_local_machine;
case HKEY_USERS:
if (!key_users) {
ADD_ROOT_KEY(key_users);
}
return key_users;
case HKEY_PERFORMANCE_DATA:
if (!key_performance_data) {
ADD_ROOT_KEY(key_performance_data);
}
return key_performance_data;
case HKEY_DYN_DATA:
if (!key_dyn_data) {
ADD_ROOT_KEY(key_dyn_data);
}
return key_dyn_data;
case HKEY_CURRENT_CONFIG:
if (!key_current_config) {
ADD_ROOT_KEY(key_current_config);
}
return key_current_config;
default:
return get_handle(hkey);
}
/*NOTREACHED*/
}
/*
* recursively searches for lpkey_to_find in the root key branch
* given in lpcurrkey.
*/
static int subkey_found(LPKEYSTRUCT lpcurrkey, LPKEYSTRUCT lpkey_to_find)
{
while (lpcurrkey)
{
if (lpcurrkey == lpkey_to_find)
return 1;
if (subkey_found(lpcurrkey->nextsub, lpkey_to_find))
return 1;
lpcurrkey = lpcurrkey->next;
}
TRACE_(reg)("No key found in this root key branch\n");
return 0;
}
/*
* finds the corresponding root key for a sub key, i.e. e.g. HKEY_CLASSES_ROOT.
*/
static HKEY find_root_key(LPKEYSTRUCT lpkey)
{
typedef struct tagROOT_KEYS {
KEYSTRUCT *lpkey;
HKEY hkey;
} ROOT_KEYS;
ROOT_KEYS root_keys[4];
int i;
root_keys[0].lpkey = key_classes_root;
root_keys[0].hkey = HKEY_CLASSES_ROOT;
root_keys[1].lpkey = key_current_user;
root_keys[1].hkey = HKEY_CURRENT_USER;
root_keys[2].lpkey = key_local_machine;
root_keys[2].hkey = HKEY_LOCAL_MACHINE;
root_keys[3].lpkey = key_users;
root_keys[3].hkey = HKEY_USERS;
for (i=0; i<4;i++)
{
if (subkey_found(root_keys[i].lpkey, lpkey))
return root_keys[i].hkey;
}
ERR_(reg)("Didn't find corresponding root key entry ! Search strategy broken ??\n");
return 0;
#undef ROOT_KEYS
}
#undef ADD_ROOT_KEY
/* so we don't accidently access them ... */
#define key_current_config NULL NULL
#define key_current_user NULL NULL
#define key_users NULL NULL
#define key_local_machine NULL NULL
#define key_classes_root NULL NULL
#define key_dyn_data NULL NULL
#define key_performance_data NULL NULL
/******************************************************************************
* split_keypath [Internal]
* splits the unicode string 'wp' into an array of strings.
* the array is allocated by this function.
* Free the array using FREE_KEY_PATH
*
* PARAMS
* wp [I] String to split up
* wpv [O] Array of pointers to strings
* wpc [O] Number of components
*/
static void split_keypath( LPCWSTR wp, LPWSTR **wpv, int *wpc)
{
int i,j,len;
LPWSTR ws;
TRACE_(reg)("(%s,%p,%p)\n",debugstr_w(wp),wpv,wpc);
ws = HEAP_strdupW( SystemHeap, 0, wp );
/* We know we have at least one substring */
*wpc = 1;
/* Replace each backslash with NULL, and increment the count */
for (i=0;ws[i];i++) {
if (ws[i]=='\\') {
ws[i]=0;
(*wpc)++;
}
}
len = i;
/* Allocate the space for the array of pointers, leaving room for the
NULL at the end */
*wpv = (LPWSTR*)HeapAlloc( SystemHeap, 0, sizeof(LPWSTR)*(*wpc+2));
(*wpv)[0]= ws;
/* Assign each pointer to the appropriate character in the string */
j = 1;
for (i=1;i<len;i++)
if (ws[i-1]==0) {
(*wpv)[j++]=ws+i;
/*TRACE_(reg) (" Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1]));*/
}
(*wpv)[j]=NULL;
}
#define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
......@@ -553,12 +113,12 @@ static void REGISTRY_Init(void) {
TRACE_(reg)("(void)\n");
RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
RegCreateKeyA(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
RegCloseKey(hkey);
/* This was an Open, but since it is called before the real registries
are loaded, it was changed to a Create - MTB 980507*/
RegCreateKey16(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
RegCloseKey(hkey);
......@@ -576,8 +136,8 @@ static void REGISTRY_Init(void) {
* SysServices
*/
if (-1!=gethostname(buf,200)) {
RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
RegSetValueEx16(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
RegCreateKeyA(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
RegSetValueExA(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
RegCloseKey(hkey);
}
}
......@@ -613,131 +173,6 @@ static void REGISTRY_Init(void) {
* SaveOnlyUpdatedKeys=yes
*/
/******************************************************************************
* _save_check_tainted [Internal]
*/
static int _save_check_tainted( LPKEYSTRUCT lpkey )
{
int tainted = 0;
while (lpkey) {
if (_save_check_tainted(lpkey->nextsub))
lpkey->flags |= REG_OPTION_TAINTED;
if (lpkey->flags & REG_OPTION_TAINTED)
tainted = 1;
lpkey = lpkey->next;
}
return tainted;
}
/******************************************************************************
* _save_USTRING [Internal]
*/
static void _save_USTRING( FILE *F, LPWSTR wstr, int escapeeq )
{
LPWSTR s;
int doescape;
if (wstr==NULL)
return;
s=wstr;
while (*s) {
doescape=0;
if (*s>0x7f)
doescape = 1;
if (*s=='\n')
doescape = 1;
if (escapeeq && *s=='=')
doescape = 1;
if (*s=='\\')
fputc(*s,F); /* if \\ then put it twice. */
if (doescape)
fprintf(F,"\\u%04x",*((unsigned short*)s));
else
fputc(*s,F);
s++;
}
}
/******************************************************************************
* _savesubkey [Internal]
*
* NOTES
* REG_MULTI_SZ is handled as binary (like in win95) (js)
*/
static int _savesubkey( FILE *F, LPKEYSTRUCT lpkey, int level, int all )
{
LPKEYSTRUCT lpxkey;
int i,tabs,j;
lpxkey = lpkey;
while (lpxkey) {
if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
(all || (lpxkey->flags & REG_OPTION_TAINTED))
) {
for (tabs=level;tabs--;)
fputc('\t',F);
_save_USTRING(F,lpxkey->keyname,1);
fputs("\n",F);
for (i=0;i<lpxkey->nrofvalues;i++) {
LPKEYVALUE val=lpxkey->values+i;
for (tabs=level+1;tabs--;)
fputc('\t',F);
_save_USTRING(F,val->name,0);
fputc('=',F);
fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
if ( val->type == REG_SZ || val->type == REG_EXPAND_SZ )
_save_USTRING(F,(LPWSTR)val->data,0);
else
for (j=0;j<val->len;j++)
fprintf(F,"%02x",*((unsigned char*)val->data+j));
fputs("\n",F);
}
/* descend recursively */
if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
return 0;
}
lpxkey=lpxkey->next;
}
return 1;
}
/******************************************************************************
* _savesubreg [Internal]
*/
static int _savesubreg( FILE *F, LPKEYSTRUCT lpkey, int all )
{
fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
_save_check_tainted(lpkey->nextsub);
return _savesubkey(F,lpkey->nextsub,0,all);
}
/******************************************************************************
* _savereg [Internal]
*/
static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all )
{
FILE *F;
F=fopen(fn,"w");
if (F==NULL) {
WARN_(reg)("Couldn't open %s for writing: %s\n",
fn,strerror(errno)
);
return FALSE;
}
if (!_savesubreg(F,lpkey,all)) {
fclose(F);
unlink(fn);
WARN_(reg)("Failed to save keys, perhaps no more diskspace for %s?\n",fn);
return FALSE;
}
fclose(F);
return TRUE;
}
/******************************************************************************
......@@ -745,9 +180,9 @@ 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;i<lpkey->nrofvalues;i++) {
val=lpkey->values+i;
if (name==NULL) {
if (val->name==NULL)
break;
} else {
if ( val->name!=NULL &&
tolower(val->name[0])==tolower(name[0]) &&
!lstrcmpiW(val->name,name)
)
break;
}
}
if (i==lpkey->nrofvalues) {
lpkey->values = xrealloc(
lpkey->values,
(++lpkey->nrofvalues)*sizeof(KEYVALUE)
);
val=lpkey->values+i;
memset(val,'\0',sizeof(KEYVALUE));
val->name = name;
} else {
if (name)
free(name);
}
if (val->lastmodified<lastmodified) {
val->lastmodified=lastmodified;
val->type = type;
if ((type == REG_SZ || type == REG_EXPAND_SZ) && !data){
data=xmalloc(sizeof(WCHAR));
memset(data,0,sizeof(WCHAR));
len =sizeof(WCHAR);
}
val->len = len;
if (val->data)
free(val->data);
val->data = data;
} else
free(data);
RegSetValueExW( hkey, name, 0, type, data, len );
if (name) free( name );
if (data) free( data );
}
......@@ -1052,11 +392,6 @@ 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 )
{
/* make sure we have something... */
if (from == NULL)
return;
/* 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 )
static void _flush_registry( HKEY hkey )
{
int j;
/* make sure we have something... */
if (from == NULL)
return;
/*
* do the same for the child keys
*/
if (from->nextsub != NULL)
_flush_reg(from->nextsub);
/*
* do the same for the sibling keys
*/
if (from->next != NULL)
_flush_reg(from->next);
/*
* iterate through this key's values and delete them
*/
for (j=0;j<from->nrofvalues;j++)
{
free( (from->values+j)->name);
free( (from->values+j)->data);
}
WCHAR name[MAX_PATH];
/*
* 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;
from=from->nextsub;
while (from) {
lpxkey = _find_or_add_key(to,strdupW(from->keyname));
for (j=0;j<from->nrofvalues;j++) {
LPWSTR name;
LPBYTE data;
valfrom = from->values+j;
name=valfrom->name;
if (name) name=strdupW(name);
data=(LPBYTE)xmalloc(valfrom->len);
memcpy(data,valfrom->data,valfrom->len);
_find_or_add_value(
lpxkey,
name,
valfrom->type,
data,
valfrom->len,
valfrom->lastmodified
);
}
_copy_registry(from,lpxkey);
from = from->next;
}
int index;
HKEY subkey;
FILETIME ft;
DWORD type, name_len, len;
static WCHAR name[MAX_PATH];
static BYTE data[2048];
/* 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 );
}
/* 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,1418 +1389,17 @@ 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 ((i<wpc) && (wps[i][0]=='\0')) i++;
lpxkey = lpNextKey;
while (wps[i]) {
lpxkey=lpNextKey->nextsub;
while (lpxkey) {
if (!lstrcmpiW(wps[i],lpxkey->keyname)) {
break;
}
lpxkey=lpxkey->next;
}
if (!lpxkey) {
TRACE_(reg)("Could not find subkey %s\n",debugstr_w(wps[i]));
FREE_KEY_PATH;
return ERROR_FILE_NOT_FOUND;
}
i++;
lpNextKey = lpxkey;
}
currenthandle += 2;
add_handle(currenthandle,lpxkey,samDesired);
*retkey = currenthandle;
TRACE_(reg)(" Returning %x\n", currenthandle);
FREE_KEY_PATH;
return ERROR_SUCCESS;
}
/******************************************************************************
* RegOpenKeyEx32A [ADVAPI32.149]
*/
DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
REGSAM samDesired, LPHKEY retkey )
{
LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
DWORD ret;
TRACE_(reg)("(%x,%s,%ld,%lx,%p)\n",hkey,debugstr_a(lpszSubKey),dwReserved,
samDesired,retkey);
ret = RegOpenKeyExW( hkey, lpszSubKeyW, dwReserved, samDesired, retkey );
free(lpszSubKeyW);
return ret;
}
/******************************************************************************
* RegOpenKey32W [ADVAPI32.151]
*
* PARAMS
* hkey [I] Handle of open key
* lpszSubKey [I] Address of name of subkey to open
* retkey [O] Address of handle of open key
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
{
TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_w(lpszSubKey),retkey);
return RegOpenKeyExW( hkey, lpszSubKey, 0, KEY_ALL_ACCESS, retkey );
}
/******************************************************************************
* RegOpenKey32A [ADVAPI32.148]
*/
DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
{
DWORD ret;
LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
ret = RegOpenKeyW( hkey, lpszSubKeyW, retkey );
free(lpszSubKeyW);
return ret;
}
/******************************************************************************
* RegOpenKey16 [SHELL.1] [KERNEL.217]
*/
DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
{
TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
return RegOpenKeyA( hkey, lpszSubKey, retkey );
}
/*
* Create keys
*
* All those functions convert their respective
* arguments and call RegCreateKeyExW at the end.
*
* We stay away from the Ex functions as long as possible because there are
* differences in the return values
*
* Callpath:
* RegCreateKeyEx32A \
* RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W -> RegCreateKeyEx32W
*/
/******************************************************************************
* RegCreateKeyEx32W [ADVAPI32.131]
*
* PARAMS
* hkey [I] Handle of an open key
* lpszSubKey [I] Address of subkey name
* dwReserved [I] Reserved - must be 0
* lpszClass [I] Address of class string
* fdwOptions [I] Special options flag
* samDesired [I] Desired security access
* lpSecAttribs [I] Address of key security structure
* retkey [O] Address of buffer for opened handle
* lpDispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
*/
DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey,
DWORD dwReserved, LPWSTR lpszClass,
DWORD fdwOptions, REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecAttribs,
LPHKEY retkey, LPDWORD lpDispos )
{
LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
LPWSTR *wps;
int wpc,i;
TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey,
debugstr_w(lpszSubKey), dwReserved, debugstr_w(lpszClass),
fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos);
lpNextKey = lookup_hkey(hkey);
if (!lpNextKey)
return ERROR_INVALID_HANDLE;
/* Check for valid options */
switch(fdwOptions) {
case REG_OPTION_NON_VOLATILE:
case REG_OPTION_VOLATILE:
case REG_OPTION_BACKUP_RESTORE:
break;
default:
return ERROR_INVALID_PARAMETER;
}
/* Sam has to be a combination of the following */
if (!(samDesired &
(KEY_ALL_ACCESS | KEY_CREATE_LINK | KEY_CREATE_SUB_KEY |
KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_NOTIFY |
KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE | KEY_WRITE)))
return ERROR_INVALID_PARAMETER;
if (!lpszSubKey || !*lpszSubKey) {
currenthandle += 2;
add_handle(currenthandle,lpNextKey,samDesired);
*retkey=currenthandle;
TRACE_(reg)("Returning %x\n", currenthandle);
lpNextKey->flags|=REG_OPTION_TAINTED;
return ERROR_SUCCESS;
}
if (lpszSubKey[0] == '\\') {
WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
return ERROR_BAD_PATHNAME;
}
split_keypath(lpszSubKey,&wps,&wpc);
i = 0;
while ((i<wpc) && (wps[i][0]=='\0')) i++;
lpxkey = lpNextKey;
while (wps[i]) {
lpxkey=lpNextKey->nextsub;
while (lpxkey) {
if (!lstrcmpiW(wps[i],lpxkey->keyname))
break;
lpxkey=lpxkey->next;
}
if (!lpxkey)
break;
i++;
lpNextKey = lpxkey;
}
if (lpxkey) {
currenthandle += 2;
add_handle(currenthandle,lpxkey,samDesired);
lpxkey->flags |= REG_OPTION_TAINTED;
*retkey = currenthandle;
TRACE_(reg)("Returning %x\n", currenthandle);
if (lpDispos)
*lpDispos = REG_OPENED_EXISTING_KEY;
FREE_KEY_PATH;
return ERROR_SUCCESS;
}
/* Good. Now the hard part */
while (wps[i]) {
lplpPrevKey = &(lpNextKey->nextsub);
lpxkey = *lplpPrevKey;
while (lpxkey) {
lplpPrevKey = &(lpxkey->next);
lpxkey = *lplpPrevKey;
}
*lplpPrevKey=malloc(sizeof(KEYSTRUCT));
if (!*lplpPrevKey) {
FREE_KEY_PATH;
TRACE_(reg)("Returning OUTOFMEMORY\n");
return ERROR_OUTOFMEMORY;
}
memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
TRACE_(reg)("Adding %s\n", debugstr_w(wps[i]));
(*lplpPrevKey)->keyname = strdupW(wps[i]);
(*lplpPrevKey)->next = NULL;
(*lplpPrevKey)->nextsub = NULL;
(*lplpPrevKey)->values = NULL;
(*lplpPrevKey)->nrofvalues = 0;
(*lplpPrevKey)->flags = REG_OPTION_TAINTED;
if (lpszClass)
(*lplpPrevKey)->class = strdupW(lpszClass);
else
(*lplpPrevKey)->class = NULL;
lpNextKey = *lplpPrevKey;
i++;
}
currenthandle += 2;
add_handle(currenthandle,lpNextKey,samDesired);
/*FIXME: flag handling correct? */
lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
if (lpszClass)
lpNextKey->class = strdupW(lpszClass);
else
lpNextKey->class = NULL;
*retkey = currenthandle;
TRACE_(reg)("Returning %x\n", currenthandle);
if (lpDispos)
*lpDispos = REG_CREATED_NEW_KEY;
FREE_KEY_PATH;
return ERROR_SUCCESS;
}
/******************************************************************************
* RegCreateKeyEx32A [ADVAPI32.130]
*/
DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
LPSTR lpszClass, DWORD fdwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecAttribs,
LPHKEY retkey, LPDWORD lpDispos )
{
LPWSTR lpszSubKeyW, lpszClassW;
DWORD ret;
TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",hkey,debugstr_a(lpszSubKey),
dwReserved,debugstr_a(lpszClass),fdwOptions,samDesired,lpSecAttribs,
retkey,lpDispos);
lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
lpszClassW = lpszClass?strdupA2W(lpszClass):NULL;
ret = RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW,
fdwOptions, samDesired, lpSecAttribs, retkey,
lpDispos );
if(lpszSubKeyW) free(lpszSubKeyW);
if(lpszClassW) free(lpszClassW);
return ret;
}
/******************************************************************************
* RegCreateKey32W [ADVAPI32.132]
*/
DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
{
DWORD junk;
LPKEYSTRUCT lpNextKey;
TRACE_(reg)("(%x,%s,%p)\n", hkey,debugstr_w(lpszSubKey),retkey);
/* This check is here because the return value is different than the
one from the Ex functions */
lpNextKey = lookup_hkey(hkey);
if (!lpNextKey)
return ERROR_BADKEY;
return RegCreateKeyExW( hkey, lpszSubKey, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
retkey, &junk);
}
/******************************************************************************
* RegCreateKey32A [ADVAPI32.129]
*/
DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
{
DWORD ret;
LPWSTR lpszSubKeyW;
TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
ret = RegCreateKeyW( hkey, lpszSubKeyW, retkey );
if(lpszSubKeyW) free(lpszSubKeyW);
return ret;
}
/******************************************************************************
* RegCreateKey16 [SHELL.2] [KERNEL.218]
*/
DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
{
TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
return RegCreateKeyA( hkey, lpszSubKey, retkey );
}
/*
* Query Value Functions
* Win32 differs between keynames and valuenames.
* multiple values may belong to one key, the special value
* with name NULL is the default value used by the win31
* compat functions.
*
* Callpath:
* RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
* RegQueryValue32W -> RegQueryValueEx32W
*/
/******************************************************************************
* RegQueryValueEx32W [ADVAPI32.158]
* Retrieves type and data for a specified name associated with an open key
*
* PARAMS
* hkey [I] Handle of key to query
* lpValueName [I] Name of value to query
* lpdwReserved [I] Reserved - must be NULL
* lpdwType [O] Address of buffer for value type. If NULL, the type
* is not required.
* lpbData [O] Address of data buffer. If NULL, the actual data is
* not required.
* lpcbData [I/O] Address of data buffer size
*
* RETURNS
* ERROR_SUCCESS: Success
* ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
* buffer is left untouched. The MS-documentation is wrong (js) !!!
*/
DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR lpValueName,
LPDWORD lpdwReserved, LPDWORD lpdwType,
LPBYTE lpbData, LPDWORD lpcbData )
{
LPKEYSTRUCT lpkey;
int i;
DWORD ret;
TRACE_(reg)("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(lpValueName),
lpdwReserved, lpdwType, lpbData, lpcbData, lpcbData?*lpcbData:0);
lpkey = lookup_hkey(hkey);
if (!lpkey)
return ERROR_INVALID_HANDLE;
if ((lpbData && ! lpcbData) || lpdwReserved)
return ERROR_INVALID_PARAMETER;
/* An empty name string is equivalent to NULL */
if (lpValueName && !*lpValueName)
lpValueName = NULL;
if (lpValueName==NULL)
{ /* Use key's unnamed or default value, if any */
for (i=0;i<lpkey->nrofvalues;i++)
if (lpkey->values[i].name==NULL)
break;
}
else
{ /* Search for the key name */
for (i=0;i<lpkey->nrofvalues;i++)
if ( lpkey->values[i].name && !lstrcmpiW(lpValueName,lpkey->values[i].name))
break;
}
if (i==lpkey->nrofvalues)
{ TRACE_(reg)(" Key not found\n");
if (lpValueName==NULL)
{ /* Empty keyname not found */
if (lpbData)
{ *(WCHAR*)lpbData = 0;
*lpcbData = 2;
}
if (lpdwType)
*lpdwType = REG_SZ;
TRACE_(reg)(" Returning an empty string\n");
return ERROR_SUCCESS;
}
return ERROR_FILE_NOT_FOUND;
}
ret = ERROR_SUCCESS;
if (lpdwType) /* type required ?*/
*lpdwType = lpkey->values[i].type;
if (lpbData) /* data required ?*/
{ if (*lpcbData >= lpkey->values[i].len) /* buffer large enought ?*/
memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
else {
*lpcbData = lpkey->values[i].len;
ret = ERROR_MORE_DATA;
}
}
if (lpcbData) /* size required ?*/
{ *lpcbData = lpkey->values[i].len;
}
debug_print_value ( lpbData, &lpkey->values[i]);
TRACE_(reg)(" (ret=%lx, type=%lx, len=%ld)\n", ret, lpdwType?*lpdwType:0,lpcbData?*lpcbData:0);
return ret;
}
/******************************************************************************
* RegQueryValue32W [ADVAPI32.159]
*/
DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR lpszSubKey, LPWSTR lpszData,
LPLONG lpcbData )
{
HKEY xhkey;
DWORD ret,lpdwType;
TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_w(lpszSubKey),lpszData,
lpcbData?*lpcbData:0);
/* Only open subkey, if we really do descend */
if (lpszSubKey && *lpszSubKey) {
ret = RegOpenKeyW( hkey, lpszSubKey, &xhkey );
if (ret != ERROR_SUCCESS) {
WARN_(reg)("Could not open %s\n", debugstr_w(lpszSubKey));
return ret;
}
} else
xhkey = hkey;
lpdwType = REG_SZ;
ret = RegQueryValueExW( xhkey, NULL, NULL, &lpdwType, (LPBYTE)lpszData,
lpcbData );
if (xhkey != hkey)
RegCloseKey(xhkey);
return ret;
}
/******************************************************************************
* RegQueryValueEx32A [ADVAPI32.157]
*
* NOTES:
* the documantation is wrong: if the buffer is to small it remains untouched
*
* FIXME: check returnvalue (len) for an empty key
*/
DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR lpszValueName,
LPDWORD lpdwReserved, LPDWORD lpdwType,
LPBYTE lpbData, LPDWORD lpcbData )
{
LPWSTR lpszValueNameW;
LPBYTE mybuf = NULL;
DWORD ret, mytype, mylen = 0;
TRACE_(reg)("(%x,%s,%p,%p,%p,%p=%ld)\n", hkey,debugstr_a(lpszValueName),
lpdwReserved,lpdwType,lpbData,lpcbData,lpcbData?*lpcbData:0);
if (!lpcbData && lpbData) /* buffer without size is illegal */
{ return ERROR_INVALID_PARAMETER;
}
lpszValueNameW = lpszValueName ? strdupA2W(lpszValueName) : NULL;
/* get just the type first */
ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, &mytype, NULL, NULL );
if ( ret != ERROR_SUCCESS ) /* failed ?? */
{ if(lpszValueNameW) free(lpszValueNameW);
return ret;
}
if (lpcbData) /* at least length requested? */
{ if (UNICONVMASK & (1<<(mytype))) /* string requested? */
{ if (lpbData ) /* value requested? */
{ mylen = 2*( *lpcbData );
mybuf = (LPBYTE)xmalloc( mylen );
}
ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, mybuf, &mylen );
if (ret == ERROR_SUCCESS )
{ if ( lpbData )
{ lmemcpynWtoA(lpbData, (LPWSTR)mybuf, mylen/2);
}
}
*lpcbData = mylen/2; /* size is in byte! */
}
else /* no strings, call it straight */
{ ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, lpbData, lpcbData );
}
}
if (lpdwType) /* type when requested */
{ *lpdwType = mytype;
}
TRACE_(reg)(" (ret=%lx,type=%lx, len=%ld)\n", ret,mytype,lpcbData?*lpcbData:0);
if(mybuf) free(mybuf);
if(lpszValueNameW) free(lpszValueNameW);
return ret;
}
/******************************************************************************
* RegQueryValueEx16 [KERNEL.225]
*/
DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPSTR lpszValueName,
LPDWORD lpdwReserved, LPDWORD lpdwType,
LPBYTE lpbData, LPDWORD lpcbData )
{
TRACE_(reg)("(%x,%s,%p,%p,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
lpbData, lpcbData );
}
/******************************************************************************
* RegQueryValue32A [ADVAPI32.156]
*/
DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR lpszSubKey, LPSTR lpszData,
LPLONG lpcbData )
{
HKEY xhkey;
DWORD ret, dwType;
TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
lpcbData?*lpcbData:0);
if (lpszSubKey && *lpszSubKey) {
ret = RegOpenKey16( hkey, lpszSubKey, &xhkey );
if( ret != ERROR_SUCCESS )
return ret;
} else
xhkey = hkey;
dwType = REG_SZ;
ret = RegQueryValueExA( xhkey, NULL,NULL, &dwType, (LPBYTE)lpszData,
lpcbData );
if( xhkey != hkey )
RegCloseKey( xhkey );
return ret;
}
/******************************************************************************
* RegQueryValue16 [SHELL.6] [KERNEL.224]
*
* NOTES
* Is this HACK still applicable?
*
* HACK
* The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
* mask out the high 16 bit. This (not so much incidently) hopefully fixes
* Aldus FH4)
*/
DWORD WINAPI RegQueryValue16( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData,
LPDWORD lpcbData )
{
TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
lpcbData?*lpcbData:0);
if (lpcbData)
*lpcbData &= 0xFFFF;
return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData);
}
/*
* Setting values of Registry keys
*
* Callpath:
* RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
* RegSetValue32W -> RegSetValueEx32W
*/
/******************************************************************************
* RegSetValueEx32W [ADVAPI32.170]
* Sets the data and type of a value under a register key
*
* PARAMS
* hkey [I] Handle of key to set value for
* lpszValueName [I] Name of value to set
* dwReserved [I] Reserved - must be zero
* dwType [I] Flag for value type
* lpbData [I] Address of value data
* cbData [I] Size of value data
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*
* NOTES
* win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
*/
DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR lpszValueName,
DWORD dwReserved, DWORD dwType,
CONST BYTE *lpbData, DWORD cbData)
{
LPKEYSTRUCT lpkey;
int i;
TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(lpszValueName),
dwReserved, dwType, lpbData, cbData);
lpkey = lookup_hkey( hkey );
if (!lpkey)
return ERROR_INVALID_HANDLE;
lpkey->flags |= REG_OPTION_TAINTED;
if (lpszValueName==NULL) {
/* Sets type and name for key's unnamed or default value */
for (i=0;i<lpkey->nrofvalues;i++)
if (lpkey->values[i].name==NULL)
break;
} else {
for (i=0;i<lpkey->nrofvalues;i++)
if ( lpkey->values[i].name &&
!lstrcmpiW(lpszValueName,lpkey->values[i].name)
)
break;
}
if (i==lpkey->nrofvalues) {
lpkey->values = (LPKEYVALUE)xrealloc(
lpkey->values,
(lpkey->nrofvalues+1)*sizeof(KEYVALUE)
);
lpkey->nrofvalues++;
memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
}
if (lpkey->values[i].name==NULL) {
if (lpszValueName)
lpkey->values[i].name = strdupW(lpszValueName);
else
lpkey->values[i].name = NULL;
}
if (dwType == REG_SZ)
cbData = 2 * (lstrlenW ((LPCWSTR)lpbData) + 1);
lpkey->values[i].len = cbData;
lpkey->values[i].type = dwType;
if (lpkey->values[i].data !=NULL)
free(lpkey->values[i].data);
lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
lpkey->values[i].lastmodified = time(NULL);
memcpy(lpkey->values[i].data,lpbData,cbData);
return ERROR_SUCCESS;
}
/******************************************************************************
* RegSetValueEx32A [ADVAPI32.169]
*
* NOTES
* win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
*/
DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR lpszValueName,
DWORD dwReserved, DWORD dwType,
CONST BYTE *lpbData, DWORD cbData )
{
LPBYTE buf;
LPWSTR lpszValueNameW;
DWORD ret;
if (!lpbData)
return (ERROR_INVALID_PARAMETER);
TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
dwReserved,dwType,lpbData,cbData);
if ((1<<dwType) & UNICONVMASK)
{ if (dwType == REG_SZ)
cbData = strlen ((LPCSTR)lpbData)+1;
buf = (LPBYTE)xmalloc( cbData *2 );
lmemcpynAtoW ((LPVOID)buf, lpbData, cbData );
cbData=2*cbData;
}
else
buf=(LPBYTE)lpbData;
if (lpszValueName)
lpszValueNameW = strdupA2W(lpszValueName);
else
lpszValueNameW = NULL;
ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
if (lpszValueNameW)
free(lpszValueNameW);
if (buf!=lpbData)
free(buf);
return ret;
}
/******************************************************************************
* RegSetValueEx16 [KERNEL.226]
*/
DWORD WINAPI RegSetValueEx16( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved,
DWORD dwType, LPBYTE lpbData, DWORD cbData )
{
TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
dwReserved,dwType,lpbData,cbData);
return RegSetValueExA( hkey, lpszValueName, dwReserved, dwType, lpbData,
cbData );
}
/******************************************************************************
* RegSetValue32W [ADVAPI32.171]
*/
DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType,
LPCWSTR lpszData, DWORD cbData )
{
HKEY xhkey;
DWORD ret;
TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",
hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData
);
if (lpszSubKey && *lpszSubKey) {
ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey);
if (ret!=ERROR_SUCCESS)
return ret;
} else
xhkey=hkey;
if (dwType!=REG_SZ) {
TRACE_(reg)("dwType=%ld - Changing to REG_SZ\n",dwType);
dwType=REG_SZ;
}
if (cbData!=2*lstrlenW(lpszData)+2) {
TRACE_(reg)("Len=%ld != strlen(%s)+1=%d!\n",
cbData,debugstr_w(lpszData),2*lstrlenW(lpszData)+2
);
cbData=2*lstrlenW(lpszData)+2;
}
ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
if (hkey!=xhkey)
RegCloseKey(xhkey);
return ret;
}
/******************************************************************************
* RegSetValue32A [ADVAPI32.168]
*
*/
DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
LPCSTR lpszData, DWORD cbData )
{
DWORD ret;
HKEY xhkey;
TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,lpszSubKey,dwType,lpszData,cbData);
if (lpszSubKey && *lpszSubKey) {
ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
if (ret!=ERROR_SUCCESS)
return ret;
} else
xhkey=hkey;
if (dwType!=REG_SZ) {
TRACE_(reg)("dwType=%ld!\n",dwType);
dwType=REG_SZ;
}
if (cbData!=strlen(lpszData)+1)
cbData=strlen(lpszData)+1;
ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
if (xhkey!=hkey)
RegCloseKey(xhkey);
return ret;
}
/******************************************************************************
* RegSetValue16 [KERNEL.221] [SHELL.5]
*/
DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
LPCSTR lpszData, DWORD cbData )
{
TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,debugstr_a(lpszSubKey),dwType,
debugstr_a(lpszData),cbData);
return RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData);
}
/*
* Key Enumeration
*
* Callpath:
* RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
* RegEnumKey32W -> RegEnumKeyEx32W
*/
/******************************************************************************
* RegEnumKeyEx32W [ADVAPI32.139]
*
* PARAMS
* hkey [I] Handle to key to enumerate
* iSubKey [I] Index of subkey to enumerate
* lpszName [O] Buffer for subkey name
* lpcchName [O] Size of subkey buffer
* lpdwReserved [I] Reserved
* lpszClass [O] Buffer for class string
* lpcchClass [O] Size of class buffer
* ft [O] Time key last written to
*/
DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
LPDWORD lpcchName, LPDWORD lpdwReserved,
LPWSTR lpszClass, LPDWORD lpcchClass,
FILETIME *ft )
{
LPKEYSTRUCT lpkey,lpxkey;
TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n",hkey,iSubkey,lpszName,
lpcchName,lpcchName? *lpcchName : -1,lpdwReserved,lpszClass,
lpcchClass,ft);
lpkey = lookup_hkey( hkey );
if (!lpkey)
return ERROR_INVALID_HANDLE;
if (!lpcchName)
return ERROR_INVALID_PARAMETER;
if (!lpkey->nextsub)
return ERROR_NO_MORE_ITEMS;
lpxkey=lpkey->nextsub;
/* Traverse the subkeys */
while (iSubkey && lpxkey) {
iSubkey--;
lpxkey=lpxkey->next;
}
if (iSubkey || !lpxkey)
return ERROR_NO_MORE_ITEMS;
if (lstrlenW(lpxkey->keyname)+1>*lpcchName) {
*lpcchName = lstrlenW(lpxkey->keyname);
return ERROR_MORE_DATA;
}
memcpy(lpszName,lpxkey->keyname,lstrlenW(lpxkey->keyname)*2+2);
*lpcchName = lstrlenW(lpszName);
if (lpszClass) {
/* FIXME: what should we write into it? */
*lpszClass = 0;
*lpcchClass = 2;
}
return ERROR_SUCCESS;
}
/******************************************************************************
* RegEnumKeyW [ADVAPI32.140]
*/
DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
DWORD lpcchName )
{
DWORD ret;
TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
ret = RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,NULL);
/* If lpszName is NULL then we have a slightly different behaviour than
RegEnumKeyExW */
if(lpszName == NULL && ret == ERROR_MORE_DATA)
ret = ERROR_SUCCESS;
return ret;
}
/******************************************************************************
* RegEnumKeyEx32A [ADVAPI32.138]
*/
DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
LPDWORD lpcchName, LPDWORD lpdwReserved,
LPSTR lpszClass, LPDWORD lpcchClass,
FILETIME *ft )
{
DWORD ret;
LPWSTR lpszNameW, lpszClassW;
TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n",
hkey,iSubkey,lpszName,lpcchName,lpcchName? *lpcchName : -1,
lpdwReserved,lpszClass,lpcchClass,ft);
lpszNameW = lpszName ? (LPWSTR)xmalloc(*lpcchName * 2) : NULL;
lpszClassW = lpszClass ? (LPWSTR)xmalloc(*lpcchClass * 2) : NULL;
ret = RegEnumKeyExW(hkey, iSubkey, lpszNameW, lpcchName, lpdwReserved,
lpszClassW, lpcchClass, ft);
if (ret == ERROR_SUCCESS) {
lstrcpyWtoA(lpszName,lpszNameW);
if (lpszClassW)
lstrcpyWtoA(lpszClass,lpszClassW);
}
if (lpszNameW)
free(lpszNameW);
if (lpszClassW)
free(lpszClassW);
return ret;
}
/******************************************************************************
* RegEnumKeyA [ADVAPI32.137]
*/
DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
DWORD lpcchName )
{
DWORD ret;
TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
ret = RegEnumKeyExA( hkey, iSubkey, lpszName, &lpcchName, NULL, NULL,
NULL, NULL );
/* If lpszName is NULL then we have a slightly different behaviour than
RegEnumKeyExA */
if(lpszName == NULL && ret == ERROR_MORE_DATA)
ret = ERROR_SUCCESS;
return ret;
}
/******************************************************************************
* RegEnumKey16 [SHELL.7] [KERNEL.216]
*/
DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
DWORD lpcchName )
{
TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName);
}
/*
* Enumerate Registry Values
*
* Callpath:
* RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
*/
/******************************************************************************
* RegEnumValue32W [ADVAPI32.142]
*
* PARAMS
* hkey [I] Handle to key to query
* iValue [I] Index of value to query
* lpszValue [O] Value string
* lpcchValue [I/O] Size of value buffer (in wchars)
* lpdReserved [I] Reserved
* lpdwType [O] Type code
* lpbData [O] Value data
* lpcbData [I/O] Size of data buffer (in bytes)
*
* Note: wide character functions that take and/or return "character counts"
* use TCHAR (that is unsigned short or char) not byte counts.
*/
DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue,
LPDWORD lpcchValue, LPDWORD lpdReserved,
LPDWORD lpdwType, LPBYTE lpbData,
LPDWORD lpcbData )
{
LPKEYSTRUCT lpkey;
LPKEYVALUE val;
TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,debugstr_w(lpszValue),
lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData);
lpkey = lookup_hkey( hkey );
if (!lpcbData && lpbData)
return ERROR_INVALID_PARAMETER;
if (!lpkey)
return ERROR_INVALID_HANDLE;
if (lpkey->nrofvalues <= iValue)
return ERROR_NO_MORE_ITEMS;
val = &(lpkey->values[iValue]);
if (val->name) {
if (lstrlenW(val->name)+1>*lpcchValue) {
*lpcchValue = lstrlenW(val->name)+1;
return ERROR_MORE_DATA;
}
memcpy(lpszValue,val->name,2 * (lstrlenW(val->name)+1) );
*lpcchValue=lstrlenW(val->name);
} else {
*lpszValue = 0;
*lpcchValue = 0;
}
/* Can be NULL if the type code is not required */
if (lpdwType)
*lpdwType = val->type;
if (lpbData) {
if (val->len>*lpcbData) {
*lpcbData = val->len;
return ERROR_MORE_DATA;
}
memcpy(lpbData,val->data,val->len);
*lpcbData = val->len;
}
debug_print_value ( val->data, val );
return ERROR_SUCCESS;
}
/******************************************************************************
* RegEnumValue32A [ADVAPI32.141]
*/
DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue,
LPDWORD lpcchValue, LPDWORD lpdReserved,
LPDWORD lpdwType, LPBYTE lpbData,
LPDWORD lpcbData )
{
LPWSTR lpszValueW;
LPBYTE lpbDataW;
DWORD ret,lpcbDataW;
DWORD dwType;
TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
lpdReserved,lpdwType,lpbData,lpcbData);
lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
if (lpbData) {
lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
lpcbDataW = *lpcbData;
} else
lpbDataW = NULL;
ret = RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue,
lpdReserved, &dwType, lpbDataW, &lpcbDataW );
if (lpdwType)
*lpdwType = dwType;
if (ret==ERROR_SUCCESS) {
lstrcpyWtoA(lpszValue,lpszValueW);
if (lpbData) {
if ((1<<dwType) & UNICONVMASK) {
lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW);
} else {
if (lpcbDataW > *lpcbData) {
*lpcbData = lpcbDataW;
ret = ERROR_MORE_DATA;
} else
memcpy(lpbData,lpbDataW,lpcbDataW);
}
*lpcbData = lpcbDataW;
}
}
if (lpbDataW) free(lpbDataW);
if (lpszValueW) free(lpszValueW);
return ret;
}
/******************************************************************************
* RegEnumValue16 [KERNEL.223]
*/
DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD iValue, LPSTR lpszValue,
LPDWORD lpcchValue, LPDWORD lpdReserved,
LPDWORD lpdwType, LPBYTE lpbData,
LPDWORD lpcbData )
{
TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
lpdReserved,lpdwType,lpbData,lpcbData);
return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved,
lpdwType, lpbData, lpcbData );
}
/******************************************************************************
* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126]
* Releases the handle of the specified key
*
* PARAMS
* hkey [I] Handle of key to close
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegCloseKey( HKEY hkey )
{
TRACE_(reg)("(%x)\n",hkey);
/* The standard handles are allowed to succeed, even though they are not
closed */
if (is_standard_hkey(hkey))
return ERROR_SUCCESS;
return remove_handle(hkey);
}
/*
* Delete registry key
*
* Callpath:
* RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
*/
/******************************************************************************
* RegDeleteKey32W [ADVAPI32.134]
*
* PARAMS
* hkey [I] Handle to open key
* lpszSubKey [I] Name of subkey to delete
*
* RETURNS
* Success: ERROR_SUCCESS
* Failure: Error code
*/
DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR lpszSubKey )
{
LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
LPWSTR *wps;
int wpc,i;
TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszSubKey));
lpNextKey = lookup_hkey(hkey);
if (!lpNextKey)
return ERROR_INVALID_HANDLE;
/* Subkey param cannot be NULL */
if (!lpszSubKey || !*lpszSubKey)
return ERROR_BADKEY;
/* We need to know the previous key in the hier. */
split_keypath(lpszSubKey,&wps,&wpc);
i = 0;
lpxkey = lpNextKey;
while (i<wpc-1) {
lpxkey=lpNextKey->nextsub;
while (lpxkey) {
TRACE_(reg)(" Scanning [%s]\n",
debugstr_w(lpxkey->keyname));
if (!lstrcmpiW(wps[i],lpxkey->keyname))
break;
lpxkey=lpxkey->next;
}
if (!lpxkey) {
FREE_KEY_PATH;
TRACE_(reg)(" Not found.\n");
/* not found is success */
return ERROR_SUCCESS;
}
i++;
lpNextKey = lpxkey;
}
lpxkey = lpNextKey->nextsub;
lplpPrevKey = &(lpNextKey->nextsub);
while (lpxkey) {
TRACE_(reg)(" Scanning [%s]\n",
debugstr_w(lpxkey->keyname));
if (!lstrcmpiW(wps[i],lpxkey->keyname))
break;
lplpPrevKey = &(lpxkey->next);
lpxkey = lpxkey->next;
}
if (!lpxkey) {
FREE_KEY_PATH;
WARN_(reg)(" Not found.\n");
return ERROR_FILE_NOT_FOUND;
}
if (lpxkey->nextsub) {
FREE_KEY_PATH;
WARN_(reg)(" Not empty.\n");
return ERROR_CANTWRITE;
}
*lplpPrevKey = lpxkey->next;
free(lpxkey->keyname);
if (lpxkey->class)
free(lpxkey->class);
if (lpxkey->values)
free(lpxkey->values);
free(lpxkey);
FREE_KEY_PATH;
TRACE_(reg)(" Done.\n");
return ERROR_SUCCESS;
}
/******************************************************************************
* RegDeleteKey32A [ADVAPI32.133]
*/
DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR lpszSubKey )
{
LPWSTR lpszSubKeyW;
DWORD ret;
TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
ret = RegDeleteKeyW( hkey, lpszSubKeyW );
if(lpszSubKeyW) free(lpszSubKeyW);
return ret;
}
/******************************************************************************
* RegDeleteKey16 [SHELL.4] [KERNEL.219]
*/
DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR lpszSubKey )
{
TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
return RegDeleteKeyA( hkey, lpszSubKey );
}
/*
* Delete registry value
*
* Callpath:
* RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
*/
/******************************************************************************
* RegDeleteValue32W [ADVAPI32.136]
*
* PARAMS
* hkey [I]
* lpszValue [I]
*
* RETURNS
*/
DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR lpszValue )
{
DWORD i;
LPKEYSTRUCT lpkey;
LPKEYVALUE val;
TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszValue));
lpkey = lookup_hkey( hkey );
if (!lpkey)
return ERROR_INVALID_HANDLE;
if (lpszValue) {
for (i=0;i<lpkey->nrofvalues;i++)
if ( lpkey->values[i].name &&
!lstrcmpiW(lpkey->values[i].name,lpszValue)
)
break;
} else {
for (i=0;i<lpkey->nrofvalues;i++)
if (lpkey->values[i].name==NULL)
break;
}
if (i == lpkey->nrofvalues)
return ERROR_FILE_NOT_FOUND;
val = lpkey->values+i;
if (val->name) free(val->name);
if (val->data) free(val->data);
memcpy(
lpkey->values+i,
lpkey->values+i+1,
sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
);
lpkey->values = (LPKEYVALUE)xrealloc(
lpkey->values,
(lpkey->nrofvalues-1)*sizeof(KEYVALUE)
);
lpkey->nrofvalues--;
return ERROR_SUCCESS;
}
/******************************************************************************
* RegDeleteValue32A [ADVAPI32.135]
*/
DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR lpszValue )
{
LPWSTR lpszValueW;
DWORD ret;
TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszValue));
lpszValueW = lpszValue?strdupA2W(lpszValue):NULL;
ret = RegDeleteValueW( hkey, lpszValueW );
if(lpszValueW) free(lpszValueW);
return ret;
}
/******************************************************************************
* RegDeleteValue16 [KERNEL.222]
*/
DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue )
{
TRACE_(reg)("(%x,%s)\n", hkey,debugstr_a(lpszValue));
return RegDeleteValueA( hkey, lpszValue );
}
/******************************************************************************
* RegFlushKey [KERNEL.227] [ADVAPI32.143]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
* RegFlushKey [KERNEL.227] [ADVAPI32.143]
* Immediately writes key to registry.
* Only returns after data has been written to disk.
*
* 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: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
/******************************************************************************
* RegQueryInfoKey32W [ADVAPI32.153]
*
* PARAMS
* hkey [I] Handle to key to query
* lpszClass [O] Buffer for class string
* lpcchClass [O] Size of class string buffer
* lpdwReserved [I] Reserved
* lpcSubKeys [I] Buffer for number of subkeys
* lpcchMaxSubKey [O] Buffer for longest subkey name length
* lpcchMaxClass [O] Buffer for longest class string length
* lpcValues [O] Buffer for number of value entries
* lpcchMaxValueName [O] Buffer for longest value name length
* lpccbMaxValueData [O] Buffer for longest value data length
* lpcbSecurityDescriptor [O] Buffer for security descriptor length
* ft
* - win95 allows lpszClass to be valid and lpcchClass to be NULL
* - winnt returns ERROR_INVALID_PARAMETER if lpszClass is valid and
* lpcchClass is NULL
* - both allow lpszClass to be NULL and lpcchClass to be NULL
* (it's hard to test validity, so test !NULL instead)
*/
DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass,
LPDWORD lpcchClass, LPDWORD lpdwReserved,
LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey,
LPDWORD lpcchMaxClass, LPDWORD lpcValues,
LPDWORD lpcchMaxValueName,
LPDWORD lpccbMaxValueData,
LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
{
LPKEYSTRUCT lpkey,lpxkey;
int nrofkeys,maxsubkey,maxclass,maxvname,maxvdata;
int i;
TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
lpccbMaxValueData,lpcbSecurityDescriptor,ft
);
lpkey = lookup_hkey(hkey);
if (!lpkey)
return ERROR_INVALID_HANDLE;
if (lpszClass) {
if (VERSION_GetVersion() == NT40 && lpcchClass == NULL) {
return ERROR_INVALID_PARAMETER;
}
/* either lpcchClass is valid or this is win95 and lpcchClass
could be invalid */
if (lpkey->class) {
DWORD classLen = lstrlenW(lpkey->class);
if (lpcchClass && classLen+1>*lpcchClass) {
*lpcchClass=classLen+1;
return ERROR_MORE_DATA;
}
if (lpcchClass)
*lpcchClass=classLen;
memcpy(lpszClass,lpkey->class, classLen*2 + 2);
} else {
*lpszClass = 0;
if (lpcchClass)
*lpcchClass = 0;
}
} else {
if (lpcchClass)
*lpcchClass = lstrlenW(lpkey->class);
}
lpxkey=lpkey->nextsub;
nrofkeys=maxsubkey=maxclass=maxvname=maxvdata=0;
while (lpxkey) {
nrofkeys++;
if (lstrlenW(lpxkey->keyname)>maxsubkey)
maxsubkey=lstrlenW(lpxkey->keyname);
if (lpxkey->class && lstrlenW(lpxkey->class)>maxclass)
maxclass=lstrlenW(lpxkey->class);
lpxkey=lpxkey->next;
}
for (i=0;i<lpkey->nrofvalues;i++) {
LPKEYVALUE val=lpkey->values+i;
if (val->name && lstrlenW(val->name)>maxvname)
maxvname=lstrlenW(val->name);
if (val->len>maxvdata)
maxvdata=val->len;
}
if (!maxclass) maxclass = 1;
if (!maxvname) maxvname = 1;
if (lpcValues)
*lpcValues = lpkey->nrofvalues;
if (lpcSubKeys)
*lpcSubKeys = nrofkeys;
if (lpcchMaxSubkey)
*lpcchMaxSubkey = maxsubkey;
if (lpcchMaxClass)
*lpcchMaxClass = maxclass;
if (lpcchMaxValueName)
*lpcchMaxValueName= maxvname;
if (lpccbMaxValueData)
*lpccbMaxValueData= maxvdata;
return ERROR_SUCCESS;
}
/******************************************************************************
* RegQueryInfoKey32A [ADVAPI32.152]
*/
DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass,
LPDWORD lpdwReserved, LPDWORD lpcSubKeys,
LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass,
LPDWORD lpcValues, LPDWORD lpcchMaxValueName,
LPDWORD lpccbMaxValueData,
LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
{
LPWSTR lpszClassW = NULL;
DWORD ret;
TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
lpccbMaxValueData,lpcbSecurityDescriptor,ft
);
if (lpszClass) {
if (lpcchClass) {
lpszClassW = (LPWSTR)xmalloc((*lpcchClass) * 2);
} else if (VERSION_GetVersion() == WIN95) {
/* win95 allows lpcchClass to be null */
/* we don't know how big lpszClass is, would
MAX_PATHNAME_LEN be the correct default? */
lpszClassW = (LPWSTR)xmalloc(MAX_PATHNAME_LEN*2);
}
} else
lpszClassW = NULL;
ret=RegQueryInfoKeyW(
hkey,
lpszClassW,
lpcchClass,
lpdwReserved,
lpcSubKeys,
lpcchMaxSubkey,
lpcchMaxClass,
lpcValues,
lpcchMaxValueName,
lpccbMaxValueData,
lpcbSecurityDescriptor,
ft
);
if (ret==ERROR_SUCCESS && lpszClass)
lstrcpyWtoA(lpszClass,lpszClassW);
if (lpszClassW)
free(lpszClassW);
return ret;
FIXME( "(%x): stub\n", hkey );
return ERROR_SUCCESS;
}
/******************************************************************************
* 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))
......@@ -3784,49 +1484,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.???]
*
* PARAMS
......@@ -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,10 +1555,6 @@ 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;
......@@ -3920,49 +1562,6 @@ LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
/******************************************************************************
* RegSaveKey32W [ADVAPI32.166]
*
* PARAMS
* hkey [I] Handle of key where save begins
* lpFile [I] Address of filename to save to
* sa [I] Address of security structure
*/
LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR lpFile,
LPSECURITY_ATTRIBUTES sa )
{
LPKEYSTRUCT lpkey;
TRACE_(reg)("(%x,%s,%p)\n", hkey, debugstr_w(lpFile), sa);
/* It appears to do this check before the hkey check */
if (!lpFile || !*lpFile)
return ERROR_INVALID_PARAMETER;
lpkey = lookup_hkey( hkey );
if (!lpkey)
return ERROR_INVALID_HANDLE;
FIXME_(reg)("(%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa);
return ERROR_SUCCESS;
}
/******************************************************************************
* RegSaveKey32A [ADVAPI32.165]
*/
LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile,
LPSECURITY_ATTRIBUTES sa )
{
LONG ret;
LPWSTR lpFileW = strdupA2W(lpFile);
ret = RegSaveKeyW( hkey, lpFileW, sa );
free(lpFileW);
return ret;
}
/******************************************************************************
* RegRestoreKey32W [ADVAPI32.164]
*
* PARAMS
......@@ -3972,18 +1571,12 @@ LONG WINAPI 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 );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment