1999-11-23 19:41:34 +00:00
/*
* 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>
2000-02-10 22:15:21 +00:00
# include <stdio.h>
1999-11-23 19:41:34 +00:00
# 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"
2000-02-10 22:15:21 +00:00
DEFAULT_DEBUG_CHANNEL ( reg ) ;
1999-11-23 19:41:34 +00:00
/* 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
2000-01-15 23:38:49 +00:00
*
* if the type is REG_SZ and data is not 0 - terminated and there is enough space in the
* buffer nt appends a \ 0
1999-11-23 19:41:34 +00:00
*/
2000-01-15 23:38:49 +00:00
static DWORD copy_data ( void * data , const void * src , DWORD len , DWORD * count , DWORD type )
1999-11-23 19:41:34 +00:00
{
DWORD ret = ERROR_SUCCESS ;
if ( data )
{
if ( * count < len ) ret = ERROR_MORE_DATA ;
else memcpy ( data , src , len ) ;
}
2000-01-15 23:38:49 +00:00
if ( count )
{
2000-02-20 13:57:13 +00:00
if ( len & & data & & is_string ( type ) & & ( len < * count ) & & ( ( WCHAR * ) data ) [ len - 1 ] )
2000-01-15 23:38:49 +00:00
( ( WCHAR * ) data ) [ len ] = 0 ;
* count = len ;
}
1999-11-23 19:41:34 +00:00
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 ;
2000-01-15 23:38:49 +00:00
else if ( len )
{
memcpyWtoA ( data , src , len ) ;
if ( ( len < * count ) & & ( ( char * ) data ) [ len - 1 ] ) ( ( char * ) data ) [ len ] = 0 ;
}
1999-11-23 19:41:34 +00:00
}
}
else if ( data )
{
if ( * count < len ) ret = ERROR_MORE_DATA ;
else memcpy ( data , src , len ) ;
}
1999-11-25 22:05:46 +00:00
if ( count ) * count = len ;
1999-11-23 19:41:34 +00:00
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 ;
}
2000-01-24 21:58:06 +00:00
/* do a server call without setting the last error code */
static inline int reg_server_call ( enum request req )
{
unsigned int res = server_call_noerr ( req ) ;
if ( res ) res = RtlNtStatusToDosError ( res ) ;
return res ;
}
1999-11-23 19:41:34 +00:00
/******************************************************************************
* 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
2000-01-09 21:10:18 +00:00
*
* NOTES
2000-01-15 23:38:49 +00:00
* in case of failing retkey remains untouched
1999-11-23 19:41:34 +00:00
*/
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 ) ) ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_CREATE_KEY ) ) = = ERROR_SUCCESS )
1999-11-23 19:41:34 +00:00
{
* 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 ) ) ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_CREATE_KEY ) ) = = ERROR_SUCCESS )
1999-11-23 19:41:34 +00:00
{
* 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
2000-01-09 21:10:18 +00:00
*
* NOTES
* in case of failing is retkey = 0
1999-11-23 19:41:34 +00:00
*/
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 ;
2000-01-09 21:10:18 +00:00
* retkey = 0 ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_OPEN_KEY ) ) = = ERROR_SUCCESS ) * retkey = req - > hkey ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-09 21:10:18 +00:00
* retkey = 0 ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_OPEN_KEY ) ) = = ERROR_SUCCESS ) * retkey = req - > hkey ;
1999-11-23 19:41:34 +00:00
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
2000-01-09 21:10:18 +00:00
*
* NOTES
* in case of failing is retkey = 0
1999-11-23 19:41:34 +00:00
*/
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_ENUM_KEY ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_ENUM_KEY ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_QUERY_KEY_INFO ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_QUERY_KEY_INFO ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_CLOSE_KEY ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_DELETE_KEY ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_DELETE_KEY ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ) ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_SET_KEY_VALUE ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_SET_KEY_VALUE ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ) ;
1999-11-25 22:05:46 +00:00
if ( ( data & & ! count ) | | reserved ) return ERROR_INVALID_PARAMETER ;
1999-11-23 19:41:34 +00:00
req - > hkey = hkey ;
if ( ( ret = copy_nameW ( req - > name , name ) ) ! = ERROR_SUCCESS ) return ret ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_GET_KEY_VALUE ) ) = = ERROR_SUCCESS )
1999-11-23 19:41:34 +00:00
{
if ( type ) * type = req - > type ;
2000-01-15 23:38:49 +00:00
ret = copy_data ( data , req - > data , req - > len , count , req - > type ) ;
1999-11-23 19:41:34 +00:00
}
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 ) ;
1999-11-25 22:05:46 +00:00
if ( ( data & & ! count ) | | reserved ) return ERROR_INVALID_PARAMETER ;
1999-11-23 19:41:34 +00:00
req - > hkey = hkey ;
if ( ( ret = copy_nameAtoW ( req - > name , name ) ) ! = ERROR_SUCCESS ) return ret ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_GET_KEY_VALUE ) ) = = ERROR_SUCCESS )
1999-11-23 19:41:34 +00:00
{
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 */
1999-11-25 22:05:46 +00:00
if ( ( data & & ! count ) | | reserved ) return ERROR_INVALID_PARAMETER ;
1999-11-23 19:41:34 +00:00
req - > hkey = hkey ;
req - > index = index ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_ENUM_KEY_VALUE ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-15 23:38:49 +00:00
return copy_data ( data , req - > data , req - > len , count , req - > type ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 */
1999-11-25 22:05:46 +00:00
if ( ( data & & ! count ) | | reserved ) return ERROR_INVALID_PARAMETER ;
1999-11-23 19:41:34 +00:00
req - > hkey = hkey ;
req - > index = index ;
2000-01-24 21:58:06 +00:00
if ( ( ret = reg_server_call ( REQ_ENUM_KEY_VALUE ) ) ! = ERROR_SUCCESS ) return ret ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_DELETE_KEY_VALUE ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ;
2000-01-24 21:58:06 +00:00
return reg_server_call ( REQ_DELETE_KEY_VALUE ) ;
1999-11-23 19:41:34 +00:00
}
/******************************************************************************
* 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 ;
2000-01-24 21:58:06 +00:00
ret = reg_server_call ( REQ_LOAD_REGISTRY ) ;
1999-11-23 19:41:34 +00:00
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 ;
2000-01-24 21:58:06 +00:00
ret = reg_server_call ( REQ_LOAD_REGISTRY ) ;
1999-11-23 19:41:34 +00:00
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 ;
2000-03-26 18:18:03 +00:00
if ( ( ret = GetLastError ( ) ) ! = ERROR_ALREADY_EXISTS ) goto done ;
2000-05-09 22:31:43 +00:00
/* Something gone haywire ? Please report if this happens abnormally */
if ( count > = 100 )
MESSAGE ( " Wow, we are already fiddling with a temp file %s with an ordinal as high as %d ! \n You might want to delete all corresponding temp files in that directory. \n " , buffer , count ) ;
1999-11-23 19:41:34 +00:00
}
req - > hkey = hkey ;
req - > file = handle ;
2000-01-24 21:58:06 +00:00
ret = reg_server_call ( REQ_SAVE_REGISTRY ) ;
1999-11-23 19:41:34 +00:00
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 ;
}