4 * Copyright (C) 1999 Alexandre Julliard
6 * Based on misc/registry.c code
7 * Copyright (C) 1996 Marcus Meissner
8 * Copyright (C) 1998 Matthew Becker
9 * Copyright (C) 1999 Sylvain St-Germain
11 * This file is concerned about handle management and interaction with the Wine server.
12 * Registry file I/O is in misc/registry.c.
22 #include "wine/winbase16.h"
23 #include "winversion.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(reg
);
32 /* Ansi->Unicode conversion without string delimiters */
33 static LPWSTR
memcpyAtoW( LPWSTR dst
, LPCSTR src
, INT n
)
36 while (n
-- > 0) *p
++ = (WCHAR
)*src
++;
40 /* Unicode->Ansi conversion without string delimiters */
41 static LPSTR
memcpyWtoA( LPSTR dst
, LPCWSTR src
, INT n
)
44 while (n
-- > 0) *p
++ = (CHAR
)*src
++;
48 /* check if value type needs string conversion (Ansi<->Unicode) */
49 static inline int is_string( DWORD type
)
51 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
54 /* copy key value data into a user-specified buffer
56 * 'len' is the total length of the data
57 * 'count' is the size of the user-specified buffer
58 * and is updated to reflect the length copied
60 * if the type is REG_SZ and data is not 0-terminated and there is enough space in the
61 * buffer nt appends a \0
63 static DWORD
copy_data( void *data
, const void *src
, DWORD len
, DWORD
*count
, DWORD type
)
65 DWORD ret
= ERROR_SUCCESS
;
68 if (*count
< len
) ret
= ERROR_MORE_DATA
;
69 else memcpy( data
, src
, len
);
73 if (len
&& data
&& is_string( type
) && (len
< *count
) && ((WCHAR
*)data
)[len
-1])
74 ((WCHAR
*)data
)[len
] = 0;
80 /* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
81 static DWORD
copy_data_WtoA( void *data
, const void *src
, DWORD len
, DWORD
*count
, DWORD type
)
83 DWORD ret
= ERROR_SUCCESS
;
84 if (is_string( type
))
86 /* need to convert from Unicode */
90 if (*count
< len
) ret
= ERROR_MORE_DATA
;
93 memcpyWtoA( data
, src
, len
);
94 if ((len
< *count
) && ((char*)data
)[len
-1]) ((char *)data
)[len
] = 0;
100 if (*count
< len
) ret
= ERROR_MORE_DATA
;
101 else memcpy( data
, src
, len
);
103 if (count
) *count
= len
;
107 /* copy a key name into the request buffer */
108 static inline DWORD
copy_nameW( LPWSTR dest
, LPCWSTR name
)
112 if (lstrlenW(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
113 lstrcpyW( dest
, name
);
116 return ERROR_SUCCESS
;
119 /* copy a key name into the request buffer */
120 static inline DWORD
copy_nameAtoW( LPWSTR dest
, LPCSTR name
)
124 if (strlen(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
125 lstrcpyAtoW( dest
, name
);
128 return ERROR_SUCCESS
;
131 /* do a server call without setting the last error code */
132 static inline int reg_server_call( enum request req
)
134 unsigned int res
= server_call_noerr( req
);
135 if (res
) res
= RtlNtStatusToDosError(res
);
139 /******************************************************************************
140 * RegCreateKeyExW [ADVAPI32.131]
143 * hkey [I] Handle of an open key
144 * name [I] Address of subkey name
145 * reserved [I] Reserved - must be 0
146 * class [I] Address of class string
147 * options [I] Special options flag
148 * access [I] Desired security access
149 * sa [I] Address of key security structure
150 * retkey [O] Address of buffer for opened handle
151 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
154 * in case of failing retkey remains untouched
156 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
157 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
158 LPHKEY retkey
, LPDWORD dispos
)
161 struct create_key_request
*req
= get_req_buffer();
163 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_w(name
), reserved
,
164 debugstr_w(class), options
, access
, sa
, retkey
, dispos
);
166 if (reserved
) return ERROR_INVALID_PARAMETER
;
167 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
170 req
->access
= access
;
171 req
->options
= options
;
172 req
->modif
= time(NULL
);
173 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
174 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
175 lstrcpynW( req
->class, class ? class : (LPWSTR
)"\0\0",
176 server_remaining(req
->class) / sizeof(WCHAR
) );
177 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
180 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
186 /******************************************************************************
187 * RegCreateKeyExA [ADVAPI32.130]
189 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
190 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
191 LPHKEY retkey
, LPDWORD dispos
)
194 struct create_key_request
*req
= get_req_buffer();
196 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_a(name
), reserved
,
197 debugstr_a(class), options
, access
, sa
, retkey
, dispos
);
199 if (reserved
) return ERROR_INVALID_PARAMETER
;
200 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
203 req
->access
= access
;
204 req
->options
= options
;
205 req
->modif
= time(NULL
);
206 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
207 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
208 lstrcpynAtoW( req
->class, class ? class : "",
209 server_remaining(req
->class) / sizeof(WCHAR
) );
210 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
213 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
219 /******************************************************************************
220 * RegCreateKeyW [ADVAPI32.132]
222 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
224 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
225 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
226 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
227 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
231 /******************************************************************************
232 * RegCreateKeyA [ADVAPI32.129]
234 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
236 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
237 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
242 /******************************************************************************
243 * RegOpenKeyExW [ADVAPI32.150]
245 * Opens the specified key
247 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
250 * hkey [I] Handle of open key
251 * name [I] Name of subkey to open
252 * reserved [I] Reserved - must be zero
253 * access [I] Security access mask
254 * retkey [O] Handle to open key
257 * Success: ERROR_SUCCESS
258 * Failure: Error code
261 * in case of failing is retkey = 0
263 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
266 struct open_key_request
*req
= get_req_buffer();
268 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_w(name
), reserved
, access
, retkey
);
270 if (!retkey
) return ERROR_INVALID_PARAMETER
;
274 req
->access
= access
;
275 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
276 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
277 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
282 /******************************************************************************
283 * RegOpenKeyExA [ADVAPI32.149]
285 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
288 struct open_key_request
*req
= get_req_buffer();
290 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_a(name
), reserved
, access
, retkey
);
292 if (!retkey
) return ERROR_INVALID_PARAMETER
;
296 req
->access
= access
;
297 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
298 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
299 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
304 /******************************************************************************
305 * RegOpenKeyW [ADVAPI32.151]
308 * hkey [I] Handle of open key
309 * name [I] Address of name of subkey to open
310 * retkey [O] Handle to open key
313 * Success: ERROR_SUCCESS
314 * Failure: Error code
317 * in case of failing is retkey = 0
319 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
321 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
325 /******************************************************************************
326 * RegOpenKeyA [ADVAPI32.148]
328 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
330 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
335 /******************************************************************************
336 * RegEnumKeyExW [ADVAPI32.139]
339 * hkey [I] Handle to key to enumerate
340 * index [I] Index of subkey to enumerate
341 * name [O] Buffer for subkey name
342 * name_len [O] Size of subkey buffer
343 * reserved [I] Reserved
344 * class [O] Buffer for class string
345 * class_len [O] Size of class buffer
346 * ft [O] Time key last written to
348 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
349 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
351 DWORD ret
, len
, cls_len
;
352 struct enum_key_request
*req
= get_req_buffer();
354 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
355 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
357 if (reserved
) return ERROR_INVALID_PARAMETER
;
361 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
363 len
= lstrlenW( req
->name
) + 1;
364 cls_len
= lstrlenW( req
->class ) + 1;
365 if (len
> *name_len
) return ERROR_MORE_DATA
;
366 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
368 memcpy( name
, req
->name
, len
* sizeof(WCHAR
) );
372 if (class) memcpy( class, req
->class, cls_len
* sizeof(WCHAR
) );
373 *class_len
= cls_len
- 1;
375 if (ft
) DOSFS_UnixTimeToFileTime( req
->modif
, ft
, 0 );
376 return ERROR_SUCCESS
;
380 /******************************************************************************
381 * RegEnumKeyExA [ADVAPI32.138]
383 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
384 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
386 DWORD ret
, len
, cls_len
;
387 struct enum_key_request
*req
= get_req_buffer();
389 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
390 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
392 if (reserved
) return ERROR_INVALID_PARAMETER
;
396 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
398 len
= lstrlenW( req
->name
) + 1;
399 cls_len
= lstrlenW( req
->class ) + 1;
400 if (len
> *name_len
) return ERROR_MORE_DATA
;
401 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
403 memcpyWtoA( name
, req
->name
, len
);
407 if (class) memcpyWtoA( class, req
->class, cls_len
);
408 *class_len
= cls_len
- 1;
410 if (ft
) DOSFS_UnixTimeToFileTime( req
->modif
, ft
, 0 );
411 return ERROR_SUCCESS
;
415 /******************************************************************************
416 * RegEnumKeyW [ADVAPI32.140]
418 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
420 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
424 /******************************************************************************
425 * RegEnumKeyA [ADVAPI32.137]
427 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
429 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
433 /******************************************************************************
434 * RegQueryInfoKeyW [ADVAPI32.153]
437 * hkey [I] Handle to key to query
438 * class [O] Buffer for class string
439 * class_len [O] Size of class string buffer
440 * reserved [I] Reserved
441 * subkeys [O] Buffer for number of subkeys
442 * max_subkey [O] Buffer for longest subkey name length
443 * max_class [O] Buffer for longest class string length
444 * values [O] Buffer for number of value entries
445 * max_value [O] Buffer for longest value name length
446 * max_data [O] Buffer for longest value data length
447 * security [O] Buffer for security descriptor length
448 * modif [O] Modification time
450 * - win95 allows class to be valid and class_len to be NULL
451 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
452 * - both allow class to be NULL and class_len to be NULL
453 * (it's hard to test validity, so test !NULL instead)
455 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
456 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
457 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
458 LPDWORD security
, FILETIME
*modif
)
461 struct query_key_info_request
*req
= get_req_buffer();
464 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
465 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
467 if (class && !class_len
&& (VERSION_GetVersion() == NT40
))
468 return ERROR_INVALID_PARAMETER
;
471 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
475 if (class_len
&& (lstrlenW(req
->class) + 1 > *class_len
))
477 *class_len
= lstrlenW(req
->class);
478 return ERROR_MORE_DATA
;
480 lstrcpyW( class, req
->class );
482 if (class_len
) *class_len
= lstrlenW( req
->class );
483 if (subkeys
) *subkeys
= req
->subkeys
;
484 if (max_subkey
) *max_subkey
= req
->max_subkey
;
485 if (max_class
) *max_class
= req
->max_class
;
486 if (values
) *values
= req
->values
;
487 if (max_value
) *max_value
= req
->max_value
;
488 if (max_data
) *max_data
= req
->max_data
;
489 if (modif
) DOSFS_UnixTimeToFileTime( req
->modif
, modif
, 0 );
490 return ERROR_SUCCESS
;
494 /******************************************************************************
495 * RegQueryInfoKeyA [ADVAPI32.152]
497 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
498 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
499 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
500 LPDWORD security
, FILETIME
*modif
)
503 struct query_key_info_request
*req
= get_req_buffer();
506 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
507 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
509 if (class && !class_len
&& (VERSION_GetVersion() == NT40
))
510 return ERROR_INVALID_PARAMETER
;
513 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
517 if (class_len
&& (lstrlenW(req
->class) + 1 > *class_len
))
519 *class_len
= lstrlenW(req
->class);
520 return ERROR_MORE_DATA
;
522 lstrcpyWtoA( class, req
->class );
524 if (class_len
) *class_len
= lstrlenW( req
->class );
525 if (subkeys
) *subkeys
= req
->subkeys
;
526 if (max_subkey
) *max_subkey
= req
->max_subkey
;
527 if (max_class
) *max_class
= req
->max_class
;
528 if (values
) *values
= req
->values
;
529 if (max_value
) *max_value
= req
->max_value
;
530 if (max_data
) *max_data
= req
->max_data
;
531 if (modif
) DOSFS_UnixTimeToFileTime( req
->modif
, modif
, 0 );
532 return ERROR_SUCCESS
;
536 /******************************************************************************
537 * RegCloseKey [ADVAPI32.126]
539 * Releases the handle of the specified key
542 * hkey [I] Handle of key to close
545 * Success: ERROR_SUCCESS
546 * Failure: Error code
548 DWORD WINAPI
RegCloseKey( HKEY hkey
)
550 struct close_key_request
*req
= get_req_buffer();
551 TRACE( "(0x%x)\n", hkey
);
553 return reg_server_call( REQ_CLOSE_KEY
);
557 /******************************************************************************
558 * RegDeleteKeyW [ADVAPI32.134]
561 * hkey [I] Handle to open key
562 * name [I] Name of subkey to delete
565 * Success: ERROR_SUCCESS
566 * Failure: Error code
568 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
571 struct delete_key_request
*req
= get_req_buffer();
573 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
576 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
577 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
578 return reg_server_call( REQ_DELETE_KEY
);
582 /******************************************************************************
583 * RegDeleteKeyA [ADVAPI32.133]
585 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
588 struct delete_key_request
*req
= get_req_buffer();
590 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
593 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
594 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
595 return reg_server_call( REQ_DELETE_KEY
);
600 /******************************************************************************
601 * RegSetValueExW [ADVAPI32.170]
603 * Sets the data and type of a value under a register key
606 * hkey [I] Handle of key to set value for
607 * name [I] Name of value to set
608 * reserved [I] Reserved - must be zero
609 * type [I] Flag for value type
610 * data [I] Address of value data
611 * count [I] Size of value data
614 * Success: ERROR_SUCCESS
615 * Failure: Error code
618 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
619 * NT does definitely care (aj)
621 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
622 DWORD type
, CONST BYTE
*data
, DWORD count
)
625 struct set_key_value_request
*req
= get_req_buffer();
627 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_w(name
), reserved
, type
, data
, count
);
629 if (reserved
) return ERROR_INVALID_PARAMETER
;
631 if (count
&& type
== REG_SZ
)
633 LPCWSTR str
= (LPCWSTR
)data
;
634 /* if user forgot to count terminating null, add it (yes NT does this) */
635 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
636 count
+= sizeof(WCHAR
);
638 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
642 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
643 memcpy( req
->data
, data
, count
);
644 return reg_server_call( REQ_SET_KEY_VALUE
);
648 /******************************************************************************
649 * RegSetValueExA [ADVAPI32.169]
651 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
652 CONST BYTE
*data
, DWORD count
)
655 struct set_key_value_request
*req
= get_req_buffer();
657 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_a(name
), reserved
, type
, data
, count
);
659 if (reserved
) return ERROR_INVALID_PARAMETER
;
661 if (count
&& type
== REG_SZ
)
663 /* if user forgot to count terminating null, add it (yes NT does this) */
664 if (data
[count
-1] && !data
[count
]) count
++;
666 if (is_string( type
))
668 /* need to convert to Unicode */
669 count
*= sizeof(WCHAR
);
670 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
671 memcpyAtoW( (LPWSTR
)req
->data
, data
, count
/ sizeof(WCHAR
) );
675 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
676 memcpy( req
->data
, data
, count
);
681 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
682 return reg_server_call( REQ_SET_KEY_VALUE
);
686 /******************************************************************************
687 * RegSetValueW [ADVAPI32.171]
689 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
694 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
696 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
698 if (name
&& name
[0]) /* need to create the subkey */
700 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
703 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
704 (lstrlenW( data
) + 1) * sizeof(WCHAR
) );
705 if (subkey
!= hkey
) RegCloseKey( subkey
);
710 /******************************************************************************
711 * RegSetValueA [ADVAPI32.168]
713 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
718 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
720 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
722 if (name
&& name
[0]) /* need to create the subkey */
724 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
726 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
727 if (subkey
!= hkey
) RegCloseKey( subkey
);
733 /******************************************************************************
734 * RegQueryValueExW [ADVAPI32.158]
736 * Retrieves type and data for a specified name associated with an open key
739 * hkey [I] Handle of key to query
740 * name [I] Name of value to query
741 * reserved [I] Reserved - must be NULL
742 * type [O] Address of buffer for value type. If NULL, the type
744 * data [O] Address of data buffer. If NULL, the actual data is
746 * count [I/O] Address of data buffer size
749 * ERROR_SUCCESS: Success
750 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
751 * buffer is left untouched. The MS-documentation is wrong (js) !!!
753 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
754 LPBYTE data
, LPDWORD count
)
757 struct get_key_value_request
*req
= get_req_buffer();
759 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
760 hkey
, debugstr_w(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
762 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
765 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
766 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) == ERROR_SUCCESS
)
768 if (type
) *type
= req
->type
;
769 ret
= copy_data( data
, req
->data
, req
->len
, count
, req
->type
);
775 /******************************************************************************
776 * RegQueryValueExA [ADVAPI32.157]
779 * the documentation is wrong: if the buffer is to small it remains untouched
781 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
782 LPBYTE data
, LPDWORD count
)
785 struct get_key_value_request
*req
= get_req_buffer();
787 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
788 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
790 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
793 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
794 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) == ERROR_SUCCESS
)
796 if (type
) *type
= req
->type
;
797 ret
= copy_data_WtoA( data
, req
->data
, req
->len
, count
, req
->type
);
803 /******************************************************************************
804 * RegQueryValueW [ADVAPI32.159]
806 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
811 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
815 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
817 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
818 if (subkey
!= hkey
) RegCloseKey( subkey
);
819 if (ret
== ERROR_FILE_NOT_FOUND
)
821 /* return empty string if default value not found */
823 if (count
) *count
= 1;
830 /******************************************************************************
831 * RegQueryValueA [ADVAPI32.156]
833 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
838 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
842 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
844 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
845 if (subkey
!= hkey
) RegCloseKey( subkey
);
846 if (ret
== ERROR_FILE_NOT_FOUND
)
848 /* return empty string if default value not found */
850 if (count
) *count
= 1;
857 /******************************************************************************
858 * RegEnumValueW [ADVAPI32.142]
861 * hkey [I] Handle to key to query
862 * index [I] Index of value to query
863 * value [O] Value string
864 * val_count [I/O] Size of value buffer (in wchars)
865 * reserved [I] Reserved
867 * data [O] Value data
868 * count [I/O] Size of data buffer (in bytes)
871 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
872 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
875 struct enum_key_value_request
*req
= get_req_buffer();
877 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
878 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
880 /* NT only checks count, not val_count */
881 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
885 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
887 len
= lstrlenW( req
->name
) + 1;
888 if (len
> *val_count
) return ERROR_MORE_DATA
;
889 memcpy( value
, req
->name
, len
* sizeof(WCHAR
) );
890 *val_count
= len
- 1;
892 if (type
) *type
= req
->type
;
893 return copy_data( data
, req
->data
, req
->len
, count
, req
->type
);
897 /******************************************************************************
898 * RegEnumValueA [ADVAPI32.141]
900 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
901 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
904 struct enum_key_value_request
*req
= get_req_buffer();
906 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
907 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
909 /* NT only checks count, not val_count */
910 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
914 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
916 len
= lstrlenW( req
->name
) + 1;
917 if (len
> *val_count
) return ERROR_MORE_DATA
;
918 memcpyWtoA( value
, req
->name
, len
);
919 *val_count
= len
- 1;
921 if (type
) *type
= req
->type
;
922 return copy_data_WtoA( data
, req
->data
, req
->len
, count
, req
->type
);
927 /******************************************************************************
928 * RegDeleteValueW [ADVAPI32.136]
931 * hkey [I] handle to key
932 * name [I] name of value to delete
937 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
940 struct delete_key_value_request
*req
= get_req_buffer();
942 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
945 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
946 return reg_server_call( REQ_DELETE_KEY_VALUE
);
950 /******************************************************************************
951 * RegDeleteValueA [ADVAPI32.135]
953 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
956 struct delete_key_value_request
*req
= get_req_buffer();
958 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
961 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
962 return reg_server_call( REQ_DELETE_KEY_VALUE
);
966 /******************************************************************************
967 * RegLoadKeyW [ADVAPI32.185]
970 * hkey [I] Handle of open key
971 * subkey [I] Address of name of subkey
972 * filename [I] Address of filename for registry information
974 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
976 struct load_registry_request
*req
= get_req_buffer();
978 DWORD ret
, err
= GetLastError();
980 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
982 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
983 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
985 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
986 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
988 ret
= GetLastError();
993 if ((ret
= copy_nameW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
994 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
998 SetLastError( err
); /* restore the last error code */
1003 /******************************************************************************
1004 * RegLoadKeyA [ADVAPI32.184]
1006 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1008 struct load_registry_request
*req
= get_req_buffer();
1010 DWORD ret
, err
= GetLastError();
1012 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1014 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1015 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1017 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1018 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
1020 ret
= GetLastError();
1025 if ((ret
= copy_nameAtoW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
1026 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
1027 CloseHandle( file
);
1030 SetLastError( err
); /* restore the last error code */
1035 /******************************************************************************
1036 * RegSaveKeyA [ADVAPI32.165]
1039 * hkey [I] Handle of key where save begins
1040 * lpFile [I] Address of filename to save to
1041 * sa [I] Address of security structure
1043 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1045 struct save_registry_request
*req
= get_req_buffer();
1052 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1054 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1056 err
= GetLastError();
1057 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1060 sprintf( name
, "reg%04x.tmp", count
++ );
1061 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1062 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, -1 );
1063 if (handle
!= INVALID_HANDLE_VALUE
) break;
1064 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1069 ret
= reg_server_call( REQ_SAVE_REGISTRY
);
1070 CloseHandle( handle
);
1073 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1075 ERR( "Failed to move %s to %s\n", buffer
, file
);
1076 ret
= GetLastError();
1079 if (ret
) DeleteFileA( buffer
);
1082 SetLastError( err
); /* restore last error code */
1087 /******************************************************************************
1088 * RegSaveKeyW [ADVAPI32.166]
1090 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1092 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1093 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1094 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);