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"
24 #include "wine/winestring.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 a key name into the request buffer */
55 static inline DWORD
copy_nameW( LPWSTR dest
, LPCWSTR name
)
59 if (strlenW(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
60 strcpyW( dest
, name
);
66 /* copy a key name into the request buffer */
67 static inline DWORD
copy_nameAtoW( LPWSTR dest
, LPCSTR name
)
71 if (strlen(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
72 lstrcpyAtoW( dest
, name
);
78 /* do a server call without setting the last error code */
79 static inline int reg_server_call( enum request req
)
81 unsigned int res
= server_call_noerr( req
);
82 if (res
) res
= RtlNtStatusToDosError(res
);
86 /******************************************************************************
87 * RegCreateKeyExW [ADVAPI32.131]
90 * hkey [I] Handle of an open key
91 * name [I] Address of subkey name
92 * reserved [I] Reserved - must be 0
93 * class [I] Address of class string
94 * options [I] Special options flag
95 * access [I] Desired security access
96 * sa [I] Address of key security structure
97 * retkey [O] Address of buffer for opened handle
98 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
101 * in case of failing retkey remains untouched
103 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
104 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
105 LPHKEY retkey
, LPDWORD dispos
)
108 struct create_key_request
*req
= get_req_buffer();
110 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_w(name
), reserved
,
111 debugstr_w(class), options
, access
, sa
, retkey
, dispos
);
113 if (reserved
) return ERROR_INVALID_PARAMETER
;
114 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
117 req
->access
= access
;
118 req
->options
= options
;
119 req
->modif
= time(NULL
);
120 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
121 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
122 lstrcpynW( req
->class, class ? class : (LPWSTR
)"\0\0",
123 server_remaining(req
->class) / sizeof(WCHAR
) );
124 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
127 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
133 /******************************************************************************
134 * RegCreateKeyExA [ADVAPI32.130]
136 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
137 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
138 LPHKEY retkey
, LPDWORD dispos
)
141 struct create_key_request
*req
= get_req_buffer();
143 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_a(name
), reserved
,
144 debugstr_a(class), options
, access
, sa
, retkey
, dispos
);
146 if (reserved
) return ERROR_INVALID_PARAMETER
;
147 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
150 req
->access
= access
;
151 req
->options
= options
;
152 req
->modif
= time(NULL
);
153 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
154 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
155 lstrcpynAtoW( req
->class, class ? class : "",
156 server_remaining(req
->class) / sizeof(WCHAR
) );
157 if ((ret
= reg_server_call( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
160 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
166 /******************************************************************************
167 * RegCreateKeyW [ADVAPI32.132]
169 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
171 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
172 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
173 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
174 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
178 /******************************************************************************
179 * RegCreateKeyA [ADVAPI32.129]
181 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
183 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
184 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
189 /******************************************************************************
190 * RegOpenKeyExW [ADVAPI32.150]
192 * Opens the specified key
194 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
197 * hkey [I] Handle of open key
198 * name [I] Name of subkey to open
199 * reserved [I] Reserved - must be zero
200 * access [I] Security access mask
201 * retkey [O] Handle to open key
204 * Success: ERROR_SUCCESS
205 * Failure: Error code
208 * in case of failing is retkey = 0
210 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
213 struct open_key_request
*req
= get_req_buffer();
215 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_w(name
), reserved
, access
, retkey
);
217 if (!retkey
) return ERROR_INVALID_PARAMETER
;
221 req
->access
= access
;
222 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
223 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
224 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
229 /******************************************************************************
230 * RegOpenKeyExA [ADVAPI32.149]
232 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
235 struct open_key_request
*req
= get_req_buffer();
237 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_a(name
), reserved
, access
, retkey
);
239 if (!retkey
) return ERROR_INVALID_PARAMETER
;
243 req
->access
= access
;
244 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
245 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
246 if ((ret
= reg_server_call( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
251 /******************************************************************************
252 * RegOpenKeyW [ADVAPI32.151]
255 * hkey [I] Handle of open key
256 * name [I] Address of name of subkey to open
257 * retkey [O] Handle to open key
260 * Success: ERROR_SUCCESS
261 * Failure: Error code
264 * in case of failing is retkey = 0
266 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
268 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
272 /******************************************************************************
273 * RegOpenKeyA [ADVAPI32.148]
275 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
277 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
282 /******************************************************************************
283 * RegEnumKeyExW [ADVAPI32.139]
286 * hkey [I] Handle to key to enumerate
287 * index [I] Index of subkey to enumerate
288 * name [O] Buffer for subkey name
289 * name_len [O] Size of subkey buffer
290 * reserved [I] Reserved
291 * class [O] Buffer for class string
292 * class_len [O] Size of class buffer
293 * ft [O] Time key last written to
295 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
296 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
298 DWORD ret
, len
, cls_len
;
299 struct enum_key_request
*req
= get_req_buffer();
301 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
302 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
304 if (reserved
) return ERROR_INVALID_PARAMETER
;
308 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
310 len
= strlenW( req
->name
) + 1;
311 cls_len
= strlenW( req
->class ) + 1;
312 if (len
> *name_len
) return ERROR_MORE_DATA
;
313 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
315 memcpy( name
, req
->name
, len
* sizeof(WCHAR
) );
319 if (class) memcpy( class, req
->class, cls_len
* sizeof(WCHAR
) );
320 *class_len
= cls_len
- 1;
322 if (ft
) RtlSecondsSince1970ToTime( req
->modif
, ft
);
323 return ERROR_SUCCESS
;
327 /******************************************************************************
328 * RegEnumKeyExA [ADVAPI32.138]
330 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
331 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
333 DWORD ret
, len
, cls_len
;
334 struct enum_key_request
*req
= get_req_buffer();
336 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
337 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
339 if (reserved
) return ERROR_INVALID_PARAMETER
;
343 if ((ret
= reg_server_call( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
345 len
= strlenW( req
->name
) + 1;
346 cls_len
= strlenW( req
->class ) + 1;
347 if (len
> *name_len
) return ERROR_MORE_DATA
;
348 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
350 memcpyWtoA( name
, req
->name
, len
);
354 if (class) memcpyWtoA( class, req
->class, cls_len
);
355 *class_len
= cls_len
- 1;
357 if (ft
) RtlSecondsSince1970ToTime( req
->modif
, ft
);
358 return ERROR_SUCCESS
;
362 /******************************************************************************
363 * RegEnumKeyW [ADVAPI32.140]
365 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
367 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
371 /******************************************************************************
372 * RegEnumKeyA [ADVAPI32.137]
374 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
376 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
380 /******************************************************************************
381 * RegQueryInfoKeyW [ADVAPI32.153]
384 * hkey [I] Handle to key to query
385 * class [O] Buffer for class string
386 * class_len [O] Size of class string buffer
387 * reserved [I] Reserved
388 * subkeys [O] Buffer for number of subkeys
389 * max_subkey [O] Buffer for longest subkey name length
390 * max_class [O] Buffer for longest class string length
391 * values [O] Buffer for number of value entries
392 * max_value [O] Buffer for longest value name length
393 * max_data [O] Buffer for longest value data length
394 * security [O] Buffer for security descriptor length
395 * modif [O] Modification time
397 * - win95 allows class to be valid and class_len to be NULL
398 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
399 * - both allow class to be NULL and class_len to be NULL
400 * (it's hard to test validity, so test !NULL instead)
402 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
403 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
404 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
405 LPDWORD security
, FILETIME
*modif
)
408 struct query_key_info_request
*req
= get_req_buffer();
411 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
412 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
414 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
415 return ERROR_INVALID_PARAMETER
;
418 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
422 if (class_len
&& (strlenW(req
->class) + 1 > *class_len
))
424 *class_len
= strlenW(req
->class);
425 return ERROR_MORE_DATA
;
427 strcpyW( class, req
->class );
429 if (class_len
) *class_len
= strlenW( req
->class );
430 if (subkeys
) *subkeys
= req
->subkeys
;
431 if (max_subkey
) *max_subkey
= req
->max_subkey
;
432 if (max_class
) *max_class
= req
->max_class
;
433 if (values
) *values
= req
->values
;
434 if (max_value
) *max_value
= req
->max_value
;
435 if (max_data
) *max_data
= req
->max_data
;
436 if (modif
) RtlSecondsSince1970ToTime( req
->modif
, modif
);
437 return ERROR_SUCCESS
;
441 /******************************************************************************
442 * RegQueryInfoKeyA [ADVAPI32.152]
444 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
445 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
446 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
447 LPDWORD security
, FILETIME
*modif
)
450 struct query_key_info_request
*req
= get_req_buffer();
453 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
454 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
456 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
457 return ERROR_INVALID_PARAMETER
;
460 if ((ret
= reg_server_call( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
464 if (class_len
&& (strlenW(req
->class) + 1 > *class_len
))
466 *class_len
= strlenW(req
->class);
467 return ERROR_MORE_DATA
;
469 lstrcpyWtoA( class, req
->class );
471 if (class_len
) *class_len
= strlenW( req
->class );
472 if (subkeys
) *subkeys
= req
->subkeys
;
473 if (max_subkey
) *max_subkey
= req
->max_subkey
;
474 if (max_class
) *max_class
= req
->max_class
;
475 if (values
) *values
= req
->values
;
476 if (max_value
) *max_value
= req
->max_value
;
477 if (max_data
) *max_data
= req
->max_data
;
478 if (modif
) RtlSecondsSince1970ToTime( req
->modif
, modif
);
479 return ERROR_SUCCESS
;
483 /******************************************************************************
484 * RegCloseKey [ADVAPI32.126]
486 * Releases the handle of the specified key
489 * hkey [I] Handle of key to close
492 * Success: ERROR_SUCCESS
493 * Failure: Error code
495 DWORD WINAPI
RegCloseKey( HKEY hkey
)
497 struct close_key_request
*req
= get_req_buffer();
498 TRACE( "(0x%x)\n", hkey
);
500 return reg_server_call( REQ_CLOSE_KEY
);
504 /******************************************************************************
505 * RegDeleteKeyW [ADVAPI32.134]
508 * hkey [I] Handle to open key
509 * name [I] Name of subkey to delete
512 * Success: ERROR_SUCCESS
513 * Failure: Error code
515 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
518 struct delete_key_request
*req
= get_req_buffer();
520 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
523 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
524 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
525 return reg_server_call( REQ_DELETE_KEY
);
529 /******************************************************************************
530 * RegDeleteKeyA [ADVAPI32.133]
532 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
535 struct delete_key_request
*req
= get_req_buffer();
537 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
540 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
541 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
542 return reg_server_call( REQ_DELETE_KEY
);
547 /******************************************************************************
548 * RegSetValueExW [ADVAPI32.170]
550 * Sets the data and type of a value under a register key
553 * hkey [I] Handle of key to set value for
554 * name [I] Name of value to set
555 * reserved [I] Reserved - must be zero
556 * type [I] Flag for value type
557 * data [I] Address of value data
558 * count [I] Size of value data
561 * Success: ERROR_SUCCESS
562 * Failure: Error code
565 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
566 * NT does definitely care (aj)
568 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
569 DWORD type
, CONST BYTE
*data
, DWORD count
)
572 struct set_key_value_request
*req
= get_req_buffer();
573 unsigned int max
, pos
;
575 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_w(name
), reserved
, type
, data
, count
);
577 if (reserved
) return ERROR_INVALID_PARAMETER
;
579 if (count
&& type
== REG_SZ
)
581 LPCWSTR str
= (LPCWSTR
)data
;
582 /* if user forgot to count terminating null, add it (yes NT does this) */
583 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
584 count
+= sizeof(WCHAR
);
590 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
592 max
= server_remaining( req
->data
);
596 unsigned int len
= count
- pos
;
597 if (len
> max
) len
= max
;
600 memcpy( req
->data
, data
+ pos
, len
);
601 if ((ret
= reg_server_call( REQ_SET_KEY_VALUE
)) != ERROR_SUCCESS
) break;
608 /******************************************************************************
609 * RegSetValueExA [ADVAPI32.169]
611 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
612 CONST BYTE
*data
, DWORD count
)
615 struct set_key_value_request
*req
= get_req_buffer();
616 unsigned int max
, pos
;
618 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_a(name
), reserved
, type
, data
, count
);
620 if (reserved
) return ERROR_INVALID_PARAMETER
;
622 if (count
&& type
== REG_SZ
)
624 /* if user forgot to count terminating null, add it (yes NT does this) */
625 if (data
[count
-1] && !data
[count
]) count
++;
627 if (is_string( type
)) /* need to convert to Unicode */
628 count
*= sizeof(WCHAR
);
633 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
635 max
= server_remaining( req
->data
);
639 unsigned int len
= count
- pos
;
640 if (len
> max
) len
= max
;
644 if (is_string( type
))
645 memcpyAtoW( (LPWSTR
)req
->data
, data
+ pos
/sizeof(WCHAR
), len
/sizeof(WCHAR
) );
647 memcpy( req
->data
, data
+ pos
, len
);
648 if ((ret
= reg_server_call( REQ_SET_KEY_VALUE
)) != ERROR_SUCCESS
) break;
655 /******************************************************************************
656 * RegSetValueW [ADVAPI32.171]
658 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
663 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
665 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
667 if (name
&& name
[0]) /* need to create the subkey */
669 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
672 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
673 (strlenW( data
) + 1) * sizeof(WCHAR
) );
674 if (subkey
!= hkey
) RegCloseKey( subkey
);
679 /******************************************************************************
680 * RegSetValueA [ADVAPI32.168]
682 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
687 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
689 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
691 if (name
&& name
[0]) /* need to create the subkey */
693 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
695 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
696 if (subkey
!= hkey
) RegCloseKey( subkey
);
702 /******************************************************************************
703 * RegQueryValueExW [ADVAPI32.158]
705 * Retrieves type and data for a specified name associated with an open key
708 * hkey [I] Handle of key to query
709 * name [I] Name of value to query
710 * reserved [I] Reserved - must be NULL
711 * type [O] Address of buffer for value type. If NULL, the type
713 * data [O] Address of data buffer. If NULL, the actual data is
715 * count [I/O] Address of data buffer size
718 * ERROR_SUCCESS: Success
719 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
720 * buffer is left untouched. The MS-documentation is wrong (js) !!!
722 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
723 LPBYTE data
, LPDWORD count
)
726 struct get_key_value_request
*req
= get_req_buffer();
728 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
729 hkey
, debugstr_w(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
731 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
735 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
736 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
740 if (*count
< req
->len
) ret
= ERROR_MORE_DATA
;
744 unsigned int max
= server_remaining( req
->data
);
745 unsigned int pos
= 0;
746 while (pos
< req
->len
)
748 unsigned int len
= min( req
->len
- pos
, max
);
749 memcpy( data
+ pos
, req
->data
, len
);
750 if ((pos
+= len
) >= req
->len
) break;
752 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
753 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
756 /* if the type is REG_SZ and data is not 0-terminated
757 * and there is enough space in the buffer NT appends a \0 */
758 if (req
->len
&& is_string(req
->type
) &&
759 (req
->len
< *count
) && ((WCHAR
*)data
)[req
->len
-1]) ((WCHAR
*)data
)[req
->len
] = 0;
761 if (type
) *type
= req
->type
;
762 if (count
) *count
= req
->len
;
767 /******************************************************************************
768 * RegQueryValueExA [ADVAPI32.157]
771 * the documentation is wrong: if the buffer is to small it remains untouched
773 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
774 LPBYTE data
, LPDWORD count
)
776 DWORD ret
, total_len
;
777 struct get_key_value_request
*req
= get_req_buffer();
779 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
780 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
782 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
786 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
787 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
789 total_len
= is_string( req
->type
) ? req
->len
/sizeof(WCHAR
) : req
->len
;
793 if (*count
< total_len
) ret
= ERROR_MORE_DATA
;
797 unsigned int max
= server_remaining( req
->data
);
798 unsigned int pos
= 0;
799 while (pos
< req
->len
)
801 unsigned int len
= min( req
->len
- pos
, max
);
802 if (is_string( req
->type
))
803 memcpyWtoA( data
+ pos
/sizeof(WCHAR
), (WCHAR
*)req
->data
, len
/sizeof(WCHAR
) );
805 memcpy( data
+ pos
, req
->data
, len
);
806 if ((pos
+= len
) >= req
->len
) break;
808 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
809 if ((ret
= reg_server_call( REQ_GET_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
812 /* if the type is REG_SZ and data is not 0-terminated
813 * and there is enough space in the buffer NT appends a \0 */
814 if (total_len
&& is_string(req
->type
) && (total_len
< *count
) && data
[total_len
-1])
818 if (count
) *count
= total_len
;
819 if (type
) *type
= req
->type
;
824 /******************************************************************************
825 * RegQueryValueW [ADVAPI32.159]
827 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
832 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
836 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
838 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
839 if (subkey
!= hkey
) RegCloseKey( subkey
);
840 if (ret
== ERROR_FILE_NOT_FOUND
)
842 /* return empty string if default value not found */
844 if (count
) *count
= 1;
851 /******************************************************************************
852 * RegQueryValueA [ADVAPI32.156]
854 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
859 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
863 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
865 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
866 if (subkey
!= hkey
) RegCloseKey( subkey
);
867 if (ret
== ERROR_FILE_NOT_FOUND
)
869 /* return empty string if default value not found */
871 if (count
) *count
= 1;
878 /******************************************************************************
879 * RegEnumValueW [ADVAPI32.142]
882 * hkey [I] Handle to key to query
883 * index [I] Index of value to query
884 * value [O] Value string
885 * val_count [I/O] Size of value buffer (in wchars)
886 * reserved [I] Reserved
888 * data [O] Value data
889 * count [I/O] Size of data buffer (in bytes)
892 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
893 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
896 struct enum_key_value_request
*req
= get_req_buffer();
898 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
899 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
901 /* NT only checks count, not val_count */
902 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
907 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
909 len
= strlenW( req
->name
) + 1;
910 if (len
> *val_count
) return ERROR_MORE_DATA
;
911 memcpy( value
, req
->name
, len
* sizeof(WCHAR
) );
912 *val_count
= len
- 1;
916 if (*count
< req
->len
) ret
= ERROR_MORE_DATA
;
920 unsigned int max
= server_remaining( req
->data
);
921 unsigned int pos
= 0;
922 while (pos
< req
->len
)
924 unsigned int len
= min( req
->len
- pos
, max
);
925 memcpy( data
+ pos
, req
->data
, len
);
926 if ((pos
+= len
) >= req
->len
) break;
928 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
931 /* if the type is REG_SZ and data is not 0-terminated
932 * and there is enough space in the buffer NT appends a \0 */
933 if (req
->len
&& is_string(req
->type
) &&
934 (req
->len
< *count
) && ((WCHAR
*)data
)[req
->len
-1]) ((WCHAR
*)data
)[req
->len
] = 0;
936 if (type
) *type
= req
->type
;
937 if (count
) *count
= req
->len
;
942 /******************************************************************************
943 * RegEnumValueA [ADVAPI32.141]
945 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
946 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
948 DWORD ret
, len
, total_len
;
949 struct enum_key_value_request
*req
= get_req_buffer();
951 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
952 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
954 /* NT only checks count, not val_count */
955 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
960 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
962 len
= strlenW( req
->name
) + 1;
963 if (len
> *val_count
) return ERROR_MORE_DATA
;
964 memcpyWtoA( value
, req
->name
, len
);
965 *val_count
= len
- 1;
967 total_len
= is_string( req
->type
) ? req
->len
/sizeof(WCHAR
) : req
->len
;
971 if (*count
< total_len
) ret
= ERROR_MORE_DATA
;
975 unsigned int max
= server_remaining( req
->data
);
976 unsigned int pos
= 0;
977 while (pos
< req
->len
)
979 unsigned int len
= min( req
->len
- pos
, max
);
980 if (is_string( req
->type
))
981 memcpyWtoA( data
+ pos
/sizeof(WCHAR
), (WCHAR
*)req
->data
, len
/sizeof(WCHAR
) );
983 memcpy( data
+ pos
, req
->data
, len
);
984 if ((pos
+= len
) >= req
->len
) break;
986 if ((ret
= reg_server_call( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
989 /* if the type is REG_SZ and data is not 0-terminated
990 * and there is enough space in the buffer NT appends a \0 */
991 if (total_len
&& is_string(req
->type
) && (total_len
< *count
) && data
[total_len
-1])
995 if (count
) *count
= total_len
;
996 if (type
) *type
= req
->type
;
1002 /******************************************************************************
1003 * RegDeleteValueW [ADVAPI32.136]
1006 * hkey [I] handle to key
1007 * name [I] name of value to delete
1012 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1015 struct delete_key_value_request
*req
= get_req_buffer();
1017 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
1020 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
1021 return reg_server_call( REQ_DELETE_KEY_VALUE
);
1025 /******************************************************************************
1026 * RegDeleteValueA [ADVAPI32.135]
1028 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1031 struct delete_key_value_request
*req
= get_req_buffer();
1033 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
1036 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
1037 return reg_server_call( REQ_DELETE_KEY_VALUE
);
1041 /******************************************************************************
1042 * RegLoadKeyW [ADVAPI32.185]
1045 * hkey [I] Handle of open key
1046 * subkey [I] Address of name of subkey
1047 * filename [I] Address of filename for registry information
1049 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1051 struct load_registry_request
*req
= get_req_buffer();
1053 DWORD ret
, err
= GetLastError();
1055 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
1057 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1058 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1060 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1061 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
1063 ret
= GetLastError();
1068 if ((ret
= copy_nameW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
1069 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
1070 CloseHandle( file
);
1073 SetLastError( err
); /* restore the last error code */
1078 /******************************************************************************
1079 * RegLoadKeyA [ADVAPI32.184]
1081 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1083 struct load_registry_request
*req
= get_req_buffer();
1085 DWORD ret
, err
= GetLastError();
1087 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1089 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1090 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1092 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1093 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
1095 ret
= GetLastError();
1100 if ((ret
= copy_nameAtoW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
1101 ret
= reg_server_call( REQ_LOAD_REGISTRY
);
1102 CloseHandle( file
);
1105 SetLastError( err
); /* restore the last error code */
1110 /******************************************************************************
1111 * RegSaveKeyA [ADVAPI32.165]
1114 * hkey [I] Handle of key where save begins
1115 * lpFile [I] Address of filename to save to
1116 * sa [I] Address of security structure
1118 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1120 struct save_registry_request
*req
= get_req_buffer();
1127 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1129 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1131 err
= GetLastError();
1132 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1135 sprintf( name
, "reg%04x.tmp", count
++ );
1136 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1137 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, -1 );
1138 if (handle
!= INVALID_HANDLE_VALUE
) break;
1139 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1141 /* Something gone haywire ? Please report if this happens abnormally */
1143 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
);
1148 ret
= reg_server_call( REQ_SAVE_REGISTRY
);
1149 CloseHandle( handle
);
1152 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1154 ERR( "Failed to move %s to %s\n", buffer
, file
);
1155 ret
= GetLastError();
1158 if (ret
) DeleteFileA( buffer
);
1161 SetLastError( err
); /* restore last error code */
1166 /******************************************************************************
1167 * RegSaveKeyW [ADVAPI32.166]
1169 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1171 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1172 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1173 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);