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.
21 #include "wine/winbase16.h"
22 #include "winversion.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 key value data into a user-specified buffer
55 * 'len' is the total length of the data
56 * 'count' is the size of the user-specified buffer
57 * and is updated to reflect the length copied
59 * if the type is REG_SZ and data is not 0-terminated and there is enough space in the
60 * buffer nt appends a \0
62 static DWORD copy_data( void *data, const void *src, DWORD len, DWORD *count, DWORD type )
64 DWORD ret = ERROR_SUCCESS;
67 if (*count < len) ret = ERROR_MORE_DATA;
68 else memcpy( data, src, len );
72 if (is_string( type ) && len && (len < *count) && ((WCHAR *)data)[len-1])
73 ((WCHAR *)data)[len] = 0;
79 /* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
80 static DWORD copy_data_WtoA( void *data, const void *src, DWORD len, DWORD *count, DWORD type )
82 DWORD ret = ERROR_SUCCESS;
83 if (is_string( type ))
85 /* need to convert from Unicode */
89 if (*count < len) ret = ERROR_MORE_DATA;
92 memcpyWtoA( data, src, len );
93 if ((len < *count) && ((char*)data)[len-1]) ((char *)data)[len] = 0;
99 if (*count < len) ret = ERROR_MORE_DATA;
100 else memcpy( data, src, len );
102 if (count) *count = len;
106 /* copy a key name into the request buffer */
107 static inline DWORD copy_nameW( LPWSTR dest, LPCWSTR name )
111 if (lstrlenW(name) > MAX_PATH) return ERROR_MORE_DATA;
112 lstrcpyW( dest, name );
115 return ERROR_SUCCESS;
118 /* copy a key name into the request buffer */
119 static inline DWORD copy_nameAtoW( LPWSTR dest, LPCSTR name )
123 if (strlen(name) > MAX_PATH) return ERROR_MORE_DATA;
124 lstrcpyAtoW( dest, name );
127 return ERROR_SUCCESS;
130 /* do a server call without setting the last error code */
131 static inline int reg_server_call( enum request req )
133 unsigned int res = server_call_noerr( req );
134 if (res) res = RtlNtStatusToDosError(res);
138 /******************************************************************************
139 * RegCreateKeyExW [ADVAPI32.131]
142 * hkey [I] Handle of an open key
143 * name [I] Address of subkey name
144 * reserved [I] Reserved - must be 0
145 * class [I] Address of class string
146 * options [I] Special options flag
147 * access [I] Desired security access
148 * sa [I] Address of key security structure
149 * retkey [O] Address of buffer for opened handle
150 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
153 * in case of failing retkey remains untouched
155 DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
156 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
157 LPHKEY retkey, LPDWORD dispos )
160 struct create_key_request *req = get_req_buffer();
162 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
163 debugstr_w(class), options, access, sa, retkey, dispos );
165 if (reserved) return ERROR_INVALID_PARAMETER;
166 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
169 req->access = access;
170 req->options = options;
171 req->modif = time(NULL);
172 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
173 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
174 lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
175 server_remaining(req->class) / sizeof(WCHAR) );
176 if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
179 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
185 /******************************************************************************
186 * RegCreateKeyExA [ADVAPI32.130]
188 DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
189 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
190 LPHKEY retkey, LPDWORD dispos )
193 struct create_key_request *req = get_req_buffer();
195 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
196 debugstr_a(class), options, access, sa, retkey, dispos );
198 if (reserved) return ERROR_INVALID_PARAMETER;
199 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
202 req->access = access;
203 req->options = options;
204 req->modif = time(NULL);
205 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
206 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
207 lstrcpynAtoW( req->class, class ? class : "",
208 server_remaining(req->class) / sizeof(WCHAR) );
209 if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
212 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
218 /******************************************************************************
219 * RegCreateKeyW [ADVAPI32.132]
221 DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
223 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
224 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
225 return RegCreateKeyExW( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
226 KEY_ALL_ACCESS, NULL, retkey, NULL );
230 /******************************************************************************
231 * RegCreateKeyA [ADVAPI32.129]
233 DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
235 return RegCreateKeyExA( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
236 KEY_ALL_ACCESS, NULL, retkey, NULL );
241 /******************************************************************************
242 * RegOpenKeyExW [ADVAPI32.150]
244 * Opens the specified key
246 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
249 * hkey [I] Handle of open key
250 * name [I] Name of subkey to open
251 * reserved [I] Reserved - must be zero
252 * access [I] Security access mask
253 * retkey [O] Handle to open key
256 * Success: ERROR_SUCCESS
257 * Failure: Error code
260 * in case of failing is retkey = 0
262 DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
265 struct open_key_request *req = get_req_buffer();
267 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
269 if (!retkey) return ERROR_INVALID_PARAMETER;
273 req->access = access;
274 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
275 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
276 if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
281 /******************************************************************************
282 * RegOpenKeyExA [ADVAPI32.149]
284 DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
287 struct open_key_request *req = get_req_buffer();
289 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
291 if (!retkey) return ERROR_INVALID_PARAMETER;
295 req->access = access;
296 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
297 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
298 if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
303 /******************************************************************************
304 * RegOpenKeyW [ADVAPI32.151]
307 * hkey [I] Handle of open key
308 * name [I] Address of name of subkey to open
309 * retkey [O] Handle to open key
312 * Success: ERROR_SUCCESS
313 * Failure: Error code
316 * in case of failing is retkey = 0
318 DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
320 return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
324 /******************************************************************************
325 * RegOpenKeyA [ADVAPI32.148]
327 DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
329 return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
334 /******************************************************************************
335 * RegEnumKeyExW [ADVAPI32.139]
338 * hkey [I] Handle to key to enumerate
339 * index [I] Index of subkey to enumerate
340 * name [O] Buffer for subkey name
341 * name_len [O] Size of subkey buffer
342 * reserved [I] Reserved
343 * class [O] Buffer for class string
344 * class_len [O] Size of class buffer
345 * ft [O] Time key last written to
347 DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
348 LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
350 DWORD ret, len, cls_len;
351 struct enum_key_request *req = get_req_buffer();
353 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
354 name_len ? *name_len : -1, reserved, class, class_len, ft );
356 if (reserved) return ERROR_INVALID_PARAMETER;
360 if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
362 len = lstrlenW( req->name ) + 1;
363 cls_len = lstrlenW( req->class ) + 1;
364 if (len > *name_len) return ERROR_MORE_DATA;
365 if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
367 memcpy( name, req->name, len * sizeof(WCHAR) );
371 if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
372 *class_len = cls_len - 1;
374 if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
375 return ERROR_SUCCESS;
379 /******************************************************************************
380 * RegEnumKeyExA [ADVAPI32.138]
382 DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
383 LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
385 DWORD ret, len, cls_len;
386 struct enum_key_request *req = get_req_buffer();
388 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
389 name_len ? *name_len : -1, reserved, class, class_len, ft );
391 if (reserved) return ERROR_INVALID_PARAMETER;
395 if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
397 len = lstrlenW( req->name ) + 1;
398 cls_len = lstrlenW( req->class ) + 1;
399 if (len > *name_len) return ERROR_MORE_DATA;
400 if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
402 memcpyWtoA( name, req->name, len );
406 if (class) memcpyWtoA( class, req->class, cls_len );
407 *class_len = cls_len - 1;
409 if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
410 return ERROR_SUCCESS;
414 /******************************************************************************
415 * RegEnumKeyW [ADVAPI32.140]
417 DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
419 return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
423 /******************************************************************************
424 * RegEnumKeyA [ADVAPI32.137]
426 DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
428 return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
432 /******************************************************************************
433 * RegQueryInfoKeyW [ADVAPI32.153]
436 * hkey [I] Handle to key to query
437 * class [O] Buffer for class string
438 * class_len [O] Size of class string buffer
439 * reserved [I] Reserved
440 * subkeys [O] Buffer for number of subkeys
441 * max_subkey [O] Buffer for longest subkey name length
442 * max_class [O] Buffer for longest class string length
443 * values [O] Buffer for number of value entries
444 * max_value [O] Buffer for longest value name length
445 * max_data [O] Buffer for longest value data length
446 * security [O] Buffer for security descriptor length
447 * modif [O] Modification time
449 * - win95 allows class to be valid and class_len to be NULL
450 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
451 * - both allow class to be NULL and class_len to be NULL
452 * (it's hard to test validity, so test !NULL instead)
454 DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
455 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
456 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
457 LPDWORD security, FILETIME *modif )
460 struct query_key_info_request *req = get_req_buffer();
463 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
464 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
466 if (class && !class_len && (VERSION_GetVersion() == NT40))
467 return ERROR_INVALID_PARAMETER;
470 if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
474 if (class_len && (lstrlenW(req->class) + 1 > *class_len))
476 *class_len = lstrlenW(req->class);
477 return ERROR_MORE_DATA;
479 lstrcpyW( class, req->class );
481 if (class_len) *class_len = lstrlenW( req->class );
482 if (subkeys) *subkeys = req->subkeys;
483 if (max_subkey) *max_subkey = req->max_subkey;
484 if (max_class) *max_class = req->max_class;
485 if (values) *values = req->values;
486 if (max_value) *max_value = req->max_value;
487 if (max_data) *max_data = req->max_data;
488 if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
489 return ERROR_SUCCESS;
493 /******************************************************************************
494 * RegQueryInfoKeyA [ADVAPI32.152]
496 DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
497 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
498 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
499 LPDWORD security, FILETIME *modif )
502 struct query_key_info_request *req = get_req_buffer();
505 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
506 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
508 if (class && !class_len && (VERSION_GetVersion() == NT40))
509 return ERROR_INVALID_PARAMETER;
512 if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
516 if (class_len && (lstrlenW(req->class) + 1 > *class_len))
518 *class_len = lstrlenW(req->class);
519 return ERROR_MORE_DATA;
521 lstrcpyWtoA( class, req->class );
523 if (class_len) *class_len = lstrlenW( req->class );
524 if (subkeys) *subkeys = req->subkeys;
525 if (max_subkey) *max_subkey = req->max_subkey;
526 if (max_class) *max_class = req->max_class;
527 if (values) *values = req->values;
528 if (max_value) *max_value = req->max_value;
529 if (max_data) *max_data = req->max_data;
530 if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
531 return ERROR_SUCCESS;
535 /******************************************************************************
536 * RegCloseKey [ADVAPI32.126]
538 * Releases the handle of the specified key
541 * hkey [I] Handle of key to close
544 * Success: ERROR_SUCCESS
545 * Failure: Error code
547 DWORD WINAPI RegCloseKey( HKEY hkey )
549 struct close_key_request *req = get_req_buffer();
550 TRACE( "(0x%x)\n", hkey );
552 return reg_server_call( REQ_CLOSE_KEY );
556 /******************************************************************************
557 * RegDeleteKeyW [ADVAPI32.134]
560 * hkey [I] Handle to open key
561 * name [I] Name of subkey to delete
564 * Success: ERROR_SUCCESS
565 * Failure: Error code
567 DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
570 struct delete_key_request *req = get_req_buffer();
572 TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
575 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
576 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
577 return reg_server_call( REQ_DELETE_KEY );
581 /******************************************************************************
582 * RegDeleteKeyA [ADVAPI32.133]
584 DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
587 struct delete_key_request *req = get_req_buffer();
589 TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
592 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
593 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
594 return reg_server_call( REQ_DELETE_KEY );
599 /******************************************************************************
600 * RegSetValueExW [ADVAPI32.170]
602 * Sets the data and type of a value under a register key
605 * hkey [I] Handle of key to set value for
606 * name [I] Name of value to set
607 * reserved [I] Reserved - must be zero
608 * type [I] Flag for value type
609 * data [I] Address of value data
610 * count [I] Size of value data
613 * Success: ERROR_SUCCESS
614 * Failure: Error code
617 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
618 * NT does definitely care (aj)
620 DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
621 DWORD type, CONST BYTE *data, DWORD count )
624 struct set_key_value_request *req = get_req_buffer();
626 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
628 if (reserved) return ERROR_INVALID_PARAMETER;
630 if (count && type == REG_SZ)
632 LPCWSTR str = (LPCWSTR)data;
633 /* if user forgot to count terminating null, add it (yes NT does this) */
634 if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
635 count += sizeof(WCHAR);
637 if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
641 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
642 memcpy( req->data, data, count );
643 return reg_server_call( REQ_SET_KEY_VALUE );
647 /******************************************************************************
648 * RegSetValueExA [ADVAPI32.169]
650 DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
651 CONST BYTE *data, DWORD count )
654 struct set_key_value_request *req = get_req_buffer();
656 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
658 if (reserved) return ERROR_INVALID_PARAMETER;
660 if (count && type == REG_SZ)
662 /* if user forgot to count terminating null, add it (yes NT does this) */
663 if (data[count-1] && !data[count]) count++;
665 if (is_string( type ))
667 /* need to convert to Unicode */
668 count *= sizeof(WCHAR);
669 if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
670 memcpyAtoW( (LPWSTR)req->data, data, count / sizeof(WCHAR) );
674 if (count >= server_remaining( req->data )) return ERROR_OUTOFMEMORY; /* FIXME */
675 memcpy( req->data, data, count );
680 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
681 return reg_server_call( REQ_SET_KEY_VALUE );
685 /******************************************************************************
686 * RegSetValueW [ADVAPI32.171]
688 DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
693 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
695 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
697 if (name && name[0]) /* need to create the subkey */
699 if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
702 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data,
703 (lstrlenW( data ) + 1) * sizeof(WCHAR) );
704 if (subkey != hkey) RegCloseKey( subkey );
709 /******************************************************************************
710 * RegSetValueA [ADVAPI32.168]
712 DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
717 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
719 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
721 if (name && name[0]) /* need to create the subkey */
723 if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
725 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 );
726 if (subkey != hkey) RegCloseKey( subkey );
732 /******************************************************************************
733 * RegQueryValueExW [ADVAPI32.158]
735 * Retrieves type and data for a specified name associated with an open key
738 * hkey [I] Handle of key to query
739 * name [I] Name of value to query
740 * reserved [I] Reserved - must be NULL
741 * type [O] Address of buffer for value type. If NULL, the type
743 * data [O] Address of data buffer. If NULL, the actual data is
745 * count [I/O] Address of data buffer size
748 * ERROR_SUCCESS: Success
749 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
750 * buffer is left untouched. The MS-documentation is wrong (js) !!!
752 DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
753 LPBYTE data, LPDWORD count )
756 struct get_key_value_request *req = get_req_buffer();
758 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
759 hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
761 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
764 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
765 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
767 if (type) *type = req->type;
768 ret = copy_data( data, req->data, req->len, count, req->type );
774 /******************************************************************************
775 * RegQueryValueExA [ADVAPI32.157]
778 * the documentation is wrong: if the buffer is to small it remains untouched
780 DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
781 LPBYTE data, LPDWORD count )
784 struct get_key_value_request *req = get_req_buffer();
786 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
787 hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
789 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
792 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
793 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) == ERROR_SUCCESS)
795 if (type) *type = req->type;
796 ret = copy_data_WtoA( data, req->data, req->len, count, req->type );
802 /******************************************************************************
803 * RegQueryValueW [ADVAPI32.159]
805 DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
810 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
814 if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
816 ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
817 if (subkey != hkey) RegCloseKey( subkey );
818 if (ret == ERROR_FILE_NOT_FOUND)
820 /* return empty string if default value not found */
822 if (count) *count = 1;
829 /******************************************************************************
830 * RegQueryValueA [ADVAPI32.156]
832 DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
837 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
841 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
843 ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
844 if (subkey != hkey) RegCloseKey( subkey );
845 if (ret == ERROR_FILE_NOT_FOUND)
847 /* return empty string if default value not found */
849 if (count) *count = 1;
856 /******************************************************************************
857 * RegEnumValueW [ADVAPI32.142]
860 * hkey [I] Handle to key to query
861 * index [I] Index of value to query
862 * value [O] Value string
863 * val_count [I/O] Size of value buffer (in wchars)
864 * reserved [I] Reserved
866 * data [O] Value data
867 * count [I/O] Size of data buffer (in bytes)
870 DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
871 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
874 struct enum_key_value_request *req = get_req_buffer();
876 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
877 hkey, index, value, val_count, reserved, type, data, count );
879 /* NT only checks count, not val_count */
880 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
884 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
886 len = lstrlenW( req->name ) + 1;
887 if (len > *val_count) return ERROR_MORE_DATA;
888 memcpy( value, req->name, len * sizeof(WCHAR) );
889 *val_count = len - 1;
891 if (type) *type = req->type;
892 return copy_data( data, req->data, req->len, count, req->type );
896 /******************************************************************************
897 * RegEnumValueA [ADVAPI32.141]
899 DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
900 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
903 struct enum_key_value_request *req = get_req_buffer();
905 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
906 hkey, index, value, val_count, reserved, type, data, count );
908 /* NT only checks count, not val_count */
909 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
913 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
915 len = lstrlenW( req->name ) + 1;
916 if (len > *val_count) return ERROR_MORE_DATA;
917 memcpyWtoA( value, req->name, len );
918 *val_count = len - 1;
920 if (type) *type = req->type;
921 return copy_data_WtoA( data, req->data, req->len, count, req->type );
926 /******************************************************************************
927 * RegDeleteValueW [ADVAPI32.136]
930 * hkey [I] handle to key
931 * name [I] name of value to delete
936 DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
939 struct delete_key_value_request *req = get_req_buffer();
941 TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
944 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
945 return reg_server_call( REQ_DELETE_KEY_VALUE );
949 /******************************************************************************
950 * RegDeleteValueA [ADVAPI32.135]
952 DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
955 struct delete_key_value_request *req = get_req_buffer();
957 TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
960 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
961 return reg_server_call( REQ_DELETE_KEY_VALUE );
965 /******************************************************************************
966 * RegLoadKeyW [ADVAPI32.185]
969 * hkey [I] Handle of open key
970 * subkey [I] Address of name of subkey
971 * filename [I] Address of filename for registry information
973 LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
975 struct load_registry_request *req = get_req_buffer();
977 DWORD ret, err = GetLastError();
979 TRACE( "(%x,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) );
981 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
982 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
984 if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
985 FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
987 ret = GetLastError();
992 if ((ret = copy_nameW( req->name, subkey )) != ERROR_SUCCESS) goto done;
993 ret = reg_server_call( REQ_LOAD_REGISTRY );
997 SetLastError( err ); /* restore the last error code */
1002 /******************************************************************************
1003 * RegLoadKeyA [ADVAPI32.184]
1005 LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
1007 struct load_registry_request *req = get_req_buffer();
1009 DWORD ret, err = GetLastError();
1011 TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
1013 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
1014 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
1016 if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1017 FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
1019 ret = GetLastError();
1024 if ((ret = copy_nameAtoW( req->name, subkey )) != ERROR_SUCCESS) goto done;
1025 ret = reg_server_call( REQ_LOAD_REGISTRY );
1026 CloseHandle( file );
1029 SetLastError( err ); /* restore the last error code */
1034 /******************************************************************************
1035 * RegSaveKeyA [ADVAPI32.165]
1038 * hkey [I] Handle of key where save begins
1039 * lpFile [I] Address of filename to save to
1040 * sa [I] Address of security structure
1042 LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
1044 struct save_registry_request *req = get_req_buffer();
1051 TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
1053 if (!file || !*file) return ERROR_INVALID_PARAMETER;
1055 err = GetLastError();
1056 GetFullPathNameA( file, sizeof(buffer), buffer, &name );
1059 sprintf( name, "reg%04x.tmp", count++ );
1060 handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
1061 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
1062 if (handle != INVALID_HANDLE_VALUE) break;
1063 if ((ret = GetLastError()) != ERROR_FILE_EXISTS) goto done;
1068 ret = reg_server_call( REQ_SAVE_REGISTRY );
1069 CloseHandle( handle );
1072 if (!MoveFileExA( buffer, file, MOVEFILE_REPLACE_EXISTING ))
1074 ERR( "Failed to move %s to %s\n", buffer, file );
1075 ret = GetLastError();
1078 if (ret) DeleteFileA( buffer );
1081 SetLastError( err ); /* restore last error code */
1086 /******************************************************************************
1087 * RegSaveKeyW [ADVAPI32.166]
1089 LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
1091 LPSTR fileA = HEAP_strdupWtoA( GetProcessHeap(), 0, file );
1092 DWORD ret = RegSaveKeyA( hkey, fileA, sa );
1093 if (fileA) HeapFree( GetProcessHeap(), 0, fileA );