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 "wine/unicode.h"
26 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(reg
);
31 /* Ansi->Unicode conversion without string delimiters */
32 static LPWSTR
memcpyAtoW( LPWSTR dst
, LPCSTR src
, INT n
)
35 while (n
-- > 0) *p
++ = (WCHAR
)*src
++;
39 /* Unicode->Ansi conversion without string delimiters */
40 static LPSTR
memcpyWtoA( LPSTR dst
, LPCWSTR src
, INT n
)
43 while (n
-- > 0) *p
++ = (CHAR
)*src
++;
47 /* check if value type needs string conversion (Ansi<->Unicode) */
48 static inline int is_string( DWORD type
)
50 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
53 /* copy a key name into the request buffer */
54 static inline DWORD
copy_nameW( LPWSTR dest
, LPCWSTR name
)
58 if (strlenW(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
59 strcpyW( dest
, name
);
65 /* copy a key name into the request buffer */
66 static inline DWORD
copy_nameAtoW( LPWSTR dest
, LPCSTR name
)
70 if (strlen(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
71 lstrcpyAtoW( dest
, name
);
77 /* do a server call without setting the last error code */
78 static inline int reg_server_call( enum request req
)
80 unsigned int res
= server_call_noerr( req
);
81 if (res
) res
= RtlNtStatusToDosError(res
);
85 /******************************************************************************
86 * RegCreateKeyExW [ADVAPI32.131]
89 * hkey [I] Handle of an open key
90 * name [I] Address of subkey name
91 * reserved [I] Reserved - must be 0
92 * class [I] Address of class string
93 * options [I] Special options flag
94 * access [I] Desired security access
95 * sa [I] Address of key security structure
96 * retkey [O] Address of buffer for opened handle
97 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
100 * in case of failing retkey remains untouched
102 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
103 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
104 LPHKEY retkey
, LPDWORD dispos
)
107 struct create_key_request
*req
= get_req_buffer();
109 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_w(name
), reserved
,
110 debugstr_w(class), options
, access
, sa
, retkey
, dispos
);
112 if (reserved
) return ERROR_INVALID_PARAMETER
;
113 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
116 req
->access
= access
;
117 req
->options
= options
;
118 req
->modif
= time(NULL
);
119 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
120 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
121 lstrcpynW( req
->class, class ? class : (LPWSTR
)"\0\0",
122 server_remaining(req
->class) / sizeof(WCHAR
) );
123 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
126 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
132 /******************************************************************************
133 * RegCreateKeyExA [ADVAPI32.130]
135 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
136 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
137 LPHKEY retkey
, LPDWORD dispos
)
140 struct create_key_request
*req
= get_req_buffer();
142 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_a(name
), reserved
,
143 debugstr_a(class), options
, access
, sa
, retkey
, dispos
);
145 if (reserved
) return ERROR_INVALID_PARAMETER
;
146 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
149 req
->access
= access
;
150 req
->options
= options
;
151 req
->modif
= time(NULL
);
152 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
153 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
154 lstrcpynAtoW( req
->class, class ? class : "",
155 server_remaining(req
->class) / sizeof(WCHAR
) );
156 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
159 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
165 /******************************************************************************
166 * RegCreateKeyW [ADVAPI32.132]
168 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
170 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
171 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
172 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
173 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
177 /******************************************************************************
178 * RegCreateKeyA [ADVAPI32.129]
180 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
182 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
183 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
188 /******************************************************************************
189 * RegOpenKeyExW [ADVAPI32.150]
191 * Opens the specified key
193 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
196 * hkey [I] Handle of open key
197 * name [I] Name of subkey to open
198 * reserved [I] Reserved - must be zero
199 * access [I] Security access mask
200 * retkey [O] Handle to open key
203 * Success: ERROR_SUCCESS
204 * Failure: Error code
207 * in case of failing is retkey = 0
209 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
212 struct open_key_request
*req
= get_req_buffer();
214 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_w(name
), reserved
, access
, retkey
);
216 if (!retkey
) return ERROR_INVALID_PARAMETER
;
220 req
->access
= access
;
221 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
222 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
223 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
228 /******************************************************************************
229 * RegOpenKeyExA [ADVAPI32.149]
231 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
234 struct open_key_request
*req
= get_req_buffer();
236 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_a(name
), reserved
, access
, retkey
);
238 if (!retkey
) return ERROR_INVALID_PARAMETER
;
242 req
->access
= access
;
243 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
244 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
245 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
250 /******************************************************************************
251 * RegOpenKeyW [ADVAPI32.151]
254 * hkey [I] Handle of open key
255 * name [I] Address of name of subkey to open
256 * retkey [O] Handle to open key
259 * Success: ERROR_SUCCESS
260 * Failure: Error code
263 * in case of failing is retkey = 0
265 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
267 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
271 /******************************************************************************
272 * RegOpenKeyA [ADVAPI32.148]
274 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
276 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
281 /******************************************************************************
282 * RegEnumKeyExW [ADVAPI32.139]
285 * hkey [I] Handle to key to enumerate
286 * index [I] Index of subkey to enumerate
287 * name [O] Buffer for subkey name
288 * name_len [O] Size of subkey buffer
289 * reserved [I] Reserved
290 * class [O] Buffer for class string
291 * class_len [O] Size of class buffer
292 * ft [O] Time key last written to
294 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
295 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
297 DWORD ret
, len
, cls_len
;
298 struct enum_key_request
*req
= get_req_buffer();
300 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
301 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
303 if (reserved
) return ERROR_INVALID_PARAMETER
;
307 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
309 len
= strlenW( req
->name
) + 1;
310 cls_len
= strlenW( req
->class ) + 1;
311 if (len
> *name_len
) return ERROR_MORE_DATA
;
312 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
314 memcpy( name
, req
->name
, len
* sizeof(WCHAR
) );
318 if (class) memcpy( class, req
->class, cls_len
* sizeof(WCHAR
) );
319 *class_len
= cls_len
- 1;
321 if (ft
) RtlSecondsSince1970ToTime( req
->modif
, ft
);
322 return ERROR_SUCCESS
;
326 /******************************************************************************
327 * RegEnumKeyExA [ADVAPI32.138]
329 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
330 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
332 DWORD ret
, len
, cls_len
;
333 struct enum_key_request
*req
= get_req_buffer();
335 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
336 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
338 if (reserved
) return ERROR_INVALID_PARAMETER
;
342 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
344 len
= strlenW( req
->name
) + 1;
345 cls_len
= strlenW( req
->class ) + 1;
346 if (len
> *name_len
) return ERROR_MORE_DATA
;
347 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
349 memcpyWtoA( name
, req
->name
, len
);
353 if (class) memcpyWtoA( class, req
->class, cls_len
);
354 *class_len
= cls_len
- 1;
356 if (ft
) RtlSecondsSince1970ToTime( req
->modif
, ft
);
357 return ERROR_SUCCESS
;
361 /******************************************************************************
362 * RegEnumKeyW [ADVAPI32.140]
364 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
366 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
370 /******************************************************************************
371 * RegEnumKeyA [ADVAPI32.137]
373 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
375 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
379 /******************************************************************************
380 * RegQueryInfoKeyW [ADVAPI32.153]
383 * hkey [I] Handle to key to query
384 * class [O] Buffer for class string
385 * class_len [O] Size of class string buffer
386 * reserved [I] Reserved
387 * subkeys [O] Buffer for number of subkeys
388 * max_subkey [O] Buffer for longest subkey name length
389 * max_class [O] Buffer for longest class string length
390 * values [O] Buffer for number of value entries
391 * max_value [O] Buffer for longest value name length
392 * max_data [O] Buffer for longest value data length
393 * security [O] Buffer for security descriptor length
394 * modif [O] Modification time
396 * - win95 allows class to be valid and class_len to be NULL
397 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
398 * - both allow class to be NULL and class_len to be NULL
399 * (it's hard to test validity, so test !NULL instead)
401 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
402 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
403 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
404 LPDWORD security
, FILETIME
*modif
)
407 struct query_key_info_request
*req
= get_req_buffer();
410 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
411 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
413 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
414 return ERROR_INVALID_PARAMETER
;
417 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
421 if (class_len
&& (strlenW(req
->class) + 1 > *class_len
))
423 *class_len
= strlenW(req
->class);
424 return ERROR_MORE_DATA
;
426 strcpyW( class, req
->class );
428 if (class_len
) *class_len
= strlenW( req
->class );
429 if (subkeys
) *subkeys
= req
->subkeys
;
430 if (max_subkey
) *max_subkey
= req
->max_subkey
;
431 if (max_class
) *max_class
= req
->max_class
;
432 if (values
) *values
= req
->values
;
433 if (max_value
) *max_value
= req
->max_value
;
434 if (max_data
) *max_data
= req
->max_data
;
435 if (modif
) RtlSecondsSince1970ToTime( req
->modif
, modif
);
436 return ERROR_SUCCESS
;
440 /******************************************************************************
441 * RegQueryInfoKeyA [ADVAPI32.152]
443 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
444 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
445 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
446 LPDWORD security
, FILETIME
*modif
)
449 struct query_key_info_request
*req
= get_req_buffer();
452 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
453 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
455 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
456 return ERROR_INVALID_PARAMETER
;
459 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
463 if (class_len
&& (strlenW(req
->class) + 1 > *class_len
))
465 *class_len
= strlenW(req
->class);
466 return ERROR_MORE_DATA
;
468 lstrcpyWtoA( class, req
->class );
470 if (class_len
) *class_len
= strlenW( req
->class );
471 if (subkeys
) *subkeys
= req
->subkeys
;
472 if (max_subkey
) *max_subkey
= req
->max_subkey
;
473 if (max_class
) *max_class
= req
->max_class
;
474 if (values
) *values
= req
->values
;
475 if (max_value
) *max_value
= req
->max_value
;
476 if (max_data
) *max_data
= req
->max_data
;
477 if (modif
) RtlSecondsSince1970ToTime( req
->modif
, modif
);
478 return ERROR_SUCCESS
;
482 /******************************************************************************
483 * RegCloseKey [ADVAPI32.126]
485 * Releases the handle of the specified key
488 * hkey [I] Handle of key to close
491 * Success: ERROR_SUCCESS
492 * Failure: Error code
494 DWORD WINAPI
RegCloseKey( HKEY hkey
)
496 struct close_key_request
*req
= get_req_buffer();
497 TRACE( "(0x%x)\n", hkey
);
499 return reg_server_call( REQ_CLOSE_KEY
);
503 /******************************************************************************
504 * RegDeleteKeyW [ADVAPI32.134]
507 * hkey [I] Handle to open key
508 * name [I] Name of subkey to delete
511 * Success: ERROR_SUCCESS
512 * Failure: Error code
514 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
517 struct delete_key_request
*req
= get_req_buffer();
519 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
522 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
523 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
524 return reg_server_call( REQ_DELETE_KEY
);
528 /******************************************************************************
529 * RegDeleteKeyA [ADVAPI32.133]
531 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
534 struct delete_key_request
*req
= get_req_buffer();
536 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
539 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
540 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
541 return reg_server_call( REQ_DELETE_KEY
);
546 /******************************************************************************
547 * RegSetValueExW [ADVAPI32.170]
549 * Sets the data and type of a value under a register key
552 * hkey [I] Handle of key to set value for
553 * name [I] Name of value to set
554 * reserved [I] Reserved - must be zero
555 * type [I] Flag for value type
556 * data [I] Address of value data
557 * count [I] Size of value data
560 * Success: ERROR_SUCCESS
561 * Failure: Error code
564 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
565 * NT does definitely care (aj)
567 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
568 DWORD type
, CONST BYTE
*data
, DWORD count
)
571 struct set_key_value_request
*req
= get_req_buffer();
572 unsigned int max
, pos
;
574 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_w(name
), reserved
, type
, data
, count
);
576 if (reserved
) return ERROR_INVALID_PARAMETER
;
578 if (count
&& type
== REG_SZ
)
580 LPCWSTR str
= (LPCWSTR
)data
;
581 /* if user forgot to count terminating null, add it (yes NT does this) */
582 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
583 count
+= sizeof(WCHAR
);
589 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
591 max
= server_remaining( req
->data
);
595 unsigned int len
= count
- pos
;
596 if (len
> max
) len
= max
;
599 memcpy( req
->data
, data
+ pos
, len
);
600 if ((ret
= reg_server_call( REQ_SET_KEY_VALUE
)) != ERROR_SUCCESS
) break;
607 /******************************************************************************
608 * RegSetValueExA [ADVAPI32.169]
610 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
611 CONST BYTE
*data
, DWORD count
)
614 struct set_key_value_request
*req
= get_req_buffer();
615 unsigned int max
, pos
;
617 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_a(name
), reserved
, type
, data
, count
);
619 if (reserved
) return ERROR_INVALID_PARAMETER
;
621 if (count
&& type
== REG_SZ
)
623 /* if user forgot to count terminating null, add it (yes NT does this) */
624 if (data
[count
-1] && !data
[count
]) count
++;
626 if (is_string( type
)) /* need to convert to Unicode */
627 count
*= sizeof(WCHAR
);
632 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
634 max
= server_remaining( req
->data
);
638 unsigned int len
= count
- pos
;
639 if (len
> max
) len
= max
;
643 if (is_string( type
))
644 memcpyAtoW( (LPWSTR
)req
->data
, data
+ pos
/sizeof(WCHAR
), len
/sizeof(WCHAR
) );
646 memcpy( req
->data
, data
+ pos
, len
);
647 if ((ret
= reg_server_call( REQ_SET_KEY_VALUE
)) != ERROR_SUCCESS
) break;
654 /******************************************************************************
655 * RegSetValueW [ADVAPI32.171]
657 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
662 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
664 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
666 if (name
&& name
[0]) /* need to create the subkey */
668 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
671 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
672 (strlenW( data
) + 1) * sizeof(WCHAR
) );
673 if (subkey
!= hkey
) RegCloseKey( subkey
);
678 /******************************************************************************
679 * RegSetValueA [ADVAPI32.168]
681 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
686 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
688 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
690 if (name
&& name
[0]) /* need to create the subkey */
692 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
694 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
695 if (subkey
!= hkey
) RegCloseKey( subkey
);
701 /******************************************************************************
702 * RegQueryValueExW [ADVAPI32.158]
704 * Retrieves type and data for a specified name associated with an open key
707 * hkey [I] Handle of key to query
708 * name [I] Name of value to query
709 * reserved [I] Reserved - must be NULL
710 * type [O] Address of buffer for value type. If NULL, the type
712 * data [O] Address of data buffer. If NULL, the actual data is
714 * count [I/O] Address of data buffer size
717 * ERROR_SUCCESS: Success
718 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
719 * buffer is left untouched. The MS-documentation is wrong (js) !!!
721 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
722 LPBYTE data
, LPDWORD count
)
725 struct get_key_value_request
*req
= get_req_buffer();
727 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
728 hkey
, debugstr_w(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
730 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
734 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
735 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
739 if (*count
< req
->len
) ret
= ERROR_MORE_DATA
;
743 unsigned int max
= server_remaining( req
->data
);
744 unsigned int pos
= 0;
745 while (pos
< req
->len
)
747 unsigned int len
= min( req
->len
- pos
, max
);
748 memcpy( data
+ pos
, req
->data
, len
);
749 if ((pos
+= len
) >= req
->len
) break;
751 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
752 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
755 /* if the type is REG_SZ and data is not 0-terminated
756 * and there is enough space in the buffer NT appends a \0 */
757 if (req
->len
&& is_string(req
->type
) &&
758 (req
->len
< *count
) && ((WCHAR
*)data
)[req
->len
-1]) ((WCHAR
*)data
)[req
->len
] = 0;
760 if (type
) *type
= req
->type
;
761 if (count
) *count
= req
->len
;
766 /******************************************************************************
767 * RegQueryValueExA [ADVAPI32.157]
770 * the documentation is wrong: if the buffer is to small it remains untouched
772 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
773 LPBYTE data
, LPDWORD count
)
775 DWORD ret
, total_len
;
776 struct get_key_value_request
*req
= get_req_buffer();
778 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
779 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
781 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
785 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
786 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
788 total_len
= is_string( req
->type
) ? req
->len
/sizeof(WCHAR
) : req
->len
;
792 if (*count
< total_len
) ret
= ERROR_MORE_DATA
;
796 unsigned int max
= server_remaining( req
->data
);
797 unsigned int pos
= 0;
798 while (pos
< req
->len
)
800 unsigned int len
= min( req
->len
- pos
, max
);
801 if (is_string( req
->type
))
802 memcpyWtoA( data
+ pos
/sizeof(WCHAR
), (WCHAR
*)req
->data
, len
/sizeof(WCHAR
) );
804 memcpy( data
+ pos
, req
->data
, len
);
805 if ((pos
+= len
) >= req
->len
) break;
807 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
808 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
811 /* if the type is REG_SZ and data is not 0-terminated
812 * and there is enough space in the buffer NT appends a \0 */
813 if (total_len
&& is_string(req
->type
) && (total_len
< *count
) && data
[total_len
-1])
817 if (count
) *count
= total_len
;
818 if (type
) *type
= req
->type
;
823 /******************************************************************************
824 * RegQueryValueW [ADVAPI32.159]
826 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
831 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
835 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
837 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
838 if (subkey
!= hkey
) RegCloseKey( subkey
);
839 if (ret
== ERROR_FILE_NOT_FOUND
)
841 /* return empty string if default value not found */
843 if (count
) *count
= 1;
850 /******************************************************************************
851 * RegQueryValueA [ADVAPI32.156]
853 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
858 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
862 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
864 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
865 if (subkey
!= hkey
) RegCloseKey( subkey
);
866 if (ret
== ERROR_FILE_NOT_FOUND
)
868 /* return empty string if default value not found */
870 if (count
) *count
= 1;
877 /******************************************************************************
878 * RegEnumValueW [ADVAPI32.142]
881 * hkey [I] Handle to key to query
882 * index [I] Index of value to query
883 * value [O] Value string
884 * val_count [I/O] Size of value buffer (in wchars)
885 * reserved [I] Reserved
887 * data [O] Value data
888 * count [I/O] Size of data buffer (in bytes)
891 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
892 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
895 struct enum_key_value_request
*req
= get_req_buffer();
897 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
898 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
900 /* NT only checks count, not val_count */
901 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
906 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
908 len
= strlenW( req
->name
) + 1;
909 if (len
> *val_count
) return ERROR_MORE_DATA
;
910 memcpy( value
, req
->name
, len
* sizeof(WCHAR
) );
911 *val_count
= len
- 1;
915 if (*count
< req
->len
) ret
= ERROR_MORE_DATA
;
919 unsigned int max
= server_remaining( req
->data
);
920 unsigned int pos
= 0;
921 while (pos
< req
->len
)
923 unsigned int len
= min( req
->len
- pos
, max
);
924 memcpy( data
+ pos
, req
->data
, len
);
925 if ((pos
+= len
) >= req
->len
) break;
927 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
930 /* if the type is REG_SZ and data is not 0-terminated
931 * and there is enough space in the buffer NT appends a \0 */
932 if (req
->len
&& is_string(req
->type
) &&
933 (req
->len
< *count
) && ((WCHAR
*)data
)[req
->len
-1]) ((WCHAR
*)data
)[req
->len
] = 0;
935 if (type
) *type
= req
->type
;
936 if (count
) *count
= req
->len
;
941 /******************************************************************************
942 * RegEnumValueA [ADVAPI32.141]
944 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
945 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
947 DWORD ret
, len
, total_len
;
948 struct enum_key_value_request
*req
= get_req_buffer();
950 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
951 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
953 /* NT only checks count, not val_count */
954 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
959 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
961 len
= strlenW( req
->name
) + 1;
962 if (len
> *val_count
) return ERROR_MORE_DATA
;
963 memcpyWtoA( value
, req
->name
, len
);
964 *val_count
= len
- 1;
966 total_len
= is_string( req
->type
) ? req
->len
/sizeof(WCHAR
) : req
->len
;
970 if (*count
< total_len
) ret
= ERROR_MORE_DATA
;
974 unsigned int max
= server_remaining( req
->data
);
975 unsigned int pos
= 0;
976 while (pos
< req
->len
)
978 unsigned int len
= min( req
->len
- pos
, max
);
979 if (is_string( req
->type
))
980 memcpyWtoA( data
+ pos
/sizeof(WCHAR
), (WCHAR
*)req
->data
, len
/sizeof(WCHAR
) );
982 memcpy( data
+ pos
, req
->data
, len
);
983 if ((pos
+= len
) >= req
->len
) break;
985 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
988 /* if the type is REG_SZ and data is not 0-terminated
989 * and there is enough space in the buffer NT appends a \0 */
990 if (total_len
&& is_string(req
->type
) && (total_len
< *count
) && data
[total_len
-1])
994 if (count
) *count
= total_len
;
995 if (type
) *type
= req
->type
;
1001 /******************************************************************************
1002 * RegDeleteValueW [ADVAPI32.136]
1005 * hkey [I] handle to key
1006 * name [I] name of value to delete
1011 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1014 struct delete_key_value_request
*req
= get_req_buffer();
1016 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
1019 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
1020 return reg_server_call( REQ_DELETE_KEY_VALUE
);
1024 /******************************************************************************
1025 * RegDeleteValueA [ADVAPI32.135]
1027 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1030 struct delete_key_value_request
*req
= get_req_buffer();
1032 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
1035 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
1036 return reg_server_call( REQ_DELETE_KEY_VALUE
);
1040 /******************************************************************************
1041 * RegLoadKeyW [ADVAPI32.185]
1044 * hkey [I] Handle of open key
1045 * subkey [I] Address of name of subkey
1046 * filename [I] Address of filename for registry information
1048 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1050 struct load_registry_request
*req
= get_req_buffer();
1052 DWORD ret
, err
= GetLastError();
1054 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
1056 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1057 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1059 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1060 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
1062 ret
= GetLastError();
1067 if ((ret
= copy_nameW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
1068 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
1069 CloseHandle( file
);
1072 SetLastError( err
); /* restore the last error code */
1077 /******************************************************************************
1078 * RegLoadKeyA [ADVAPI32.184]
1080 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1082 struct load_registry_request
*req
= get_req_buffer();
1084 DWORD ret
, err
= GetLastError();
1086 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1088 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1089 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1091 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1092 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
1094 ret
= GetLastError();
1099 if ((ret
= copy_nameAtoW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
1100 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
1101 CloseHandle( file
);
1104 SetLastError( err
); /* restore the last error code */
1109 /******************************************************************************
1110 * RegSaveKeyA [ADVAPI32.165]
1113 * hkey [I] Handle of key where save begins
1114 * lpFile [I] Address of filename to save to
1115 * sa [I] Address of security structure
1117 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1119 struct save_registry_request
*req
= get_req_buffer();
1126 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1128 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1130 err
= GetLastError();
1131 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1134 sprintf( name
, "reg%04x.tmp", count
++ );
1135 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1136 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, -1 );
1137 if (handle
!= INVALID_HANDLE_VALUE
) break;
1138 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1140 /* Something gone haywire ? Please report if this happens abnormally */
1142 MESSAGE("Wow, we are already fiddling with a temp file %s with an ordinal as high as %d !\nYou might want to delete all corresponding temp files in that directory.\n", buffer
, count
);
1147 ret
= reg_server_call( REQ_SAVE_REGISTRY
);
1148 CloseHandle( handle
);
1151 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1153 ERR( "Failed to move %s to %s\n", buffer
, file
);
1154 ret
= GetLastError();
1157 if (ret
) DeleteFileA( buffer
);
1160 SetLastError( err
); /* restore last error code */
1165 /******************************************************************************
1166 * RegSaveKeyW [ADVAPI32.166]
1168 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1170 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1171 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1172 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);