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 static DWORD
copy_data( void *data
, const void *src
, DWORD len
, DWORD
*count
)
61 DWORD ret
= ERROR_SUCCESS
;
64 if (*count
< len
) ret
= ERROR_MORE_DATA
;
65 else memcpy( data
, src
, len
);
67 if (count
) *count
= len
;
71 /* same as copy_data but with optional Unicode->Ascii conversion depending on the type */
72 static DWORD
copy_data_WtoA( void *data
, const void *src
, DWORD len
, DWORD
*count
, DWORD type
)
74 DWORD ret
= ERROR_SUCCESS
;
75 if (is_string( type
))
77 /* need to convert from Unicode */
81 if (*count
< len
) ret
= ERROR_MORE_DATA
;
82 else memcpyWtoA( data
, src
, len
);
87 if (*count
< len
) ret
= ERROR_MORE_DATA
;
88 else memcpy( data
, src
, len
);
90 if (count
) *count
= len
;
94 /* copy a key name into the request buffer */
95 static inline DWORD
copy_nameW( LPWSTR dest
, LPCWSTR name
)
99 if (lstrlenW(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
100 lstrcpyW( dest
, name
);
103 return ERROR_SUCCESS
;
106 /* copy a key name into the request buffer */
107 static inline DWORD
copy_nameAtoW( LPWSTR dest
, LPCSTR name
)
111 if (strlen(name
) > MAX_PATH
) return ERROR_MORE_DATA
;
112 lstrcpyAtoW( dest
, name
);
115 return ERROR_SUCCESS
;
119 /******************************************************************************
120 * RegCreateKeyExW [ADVAPI32.131]
123 * hkey [I] Handle of an open key
124 * name [I] Address of subkey name
125 * reserved [I] Reserved - must be 0
126 * class [I] Address of class string
127 * options [I] Special options flag
128 * access [I] Desired security access
129 * sa [I] Address of key security structure
130 * retkey [O] Address of buffer for opened handle
131 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
133 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
134 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
135 LPHKEY retkey
, LPDWORD dispos
)
138 struct create_key_request
*req
= get_req_buffer();
140 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_w(name
), reserved
,
141 debugstr_w(class), options
, access
, sa
, retkey
, dispos
);
143 if (reserved
) return ERROR_INVALID_PARAMETER
;
144 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
147 req
->access
= access
;
148 req
->options
= options
;
149 req
->modif
= time(NULL
);
150 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
151 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
152 lstrcpynW( req
->class, class ? class : (LPWSTR
)"\0\0",
153 server_remaining(req
->class) / sizeof(WCHAR
) );
154 if ((ret
= server_call_noerr( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
157 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
163 /******************************************************************************
164 * RegCreateKeyExA [ADVAPI32.130]
166 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
167 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
168 LPHKEY retkey
, LPDWORD dispos
)
171 struct create_key_request
*req
= get_req_buffer();
173 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey
, debugstr_a(name
), reserved
,
174 debugstr_a(class), options
, access
, sa
, retkey
, dispos
);
176 if (reserved
) return ERROR_INVALID_PARAMETER
;
177 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
180 req
->access
= access
;
181 req
->options
= options
;
182 req
->modif
= time(NULL
);
183 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
184 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
185 lstrcpynAtoW( req
->class, class ? class : "",
186 server_remaining(req
->class) / sizeof(WCHAR
) );
187 if ((ret
= server_call_noerr( REQ_CREATE_KEY
)) == ERROR_SUCCESS
)
190 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
196 /******************************************************************************
197 * RegCreateKeyW [ADVAPI32.132]
199 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
201 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
202 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
203 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
204 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
208 /******************************************************************************
209 * RegCreateKeyA [ADVAPI32.129]
211 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
213 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
214 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
219 /******************************************************************************
220 * RegOpenKeyExW [ADVAPI32.150]
222 * Opens the specified key
224 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
227 * hkey [I] Handle of open key
228 * name [I] Name of subkey to open
229 * reserved [I] Reserved - must be zero
230 * access [I] Security access mask
231 * retkey [O] Handle to open key
234 * Success: ERROR_SUCCESS
235 * Failure: Error code
237 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
240 struct open_key_request
*req
= get_req_buffer();
242 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_w(name
), reserved
, access
, retkey
);
244 if (!retkey
) return ERROR_INVALID_PARAMETER
;
247 req
->access
= access
;
248 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
249 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
250 if ((ret
= server_call_noerr( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
255 /******************************************************************************
256 * RegOpenKeyExA [ADVAPI32.149]
258 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
261 struct open_key_request
*req
= get_req_buffer();
263 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey
, debugstr_a(name
), reserved
, access
, retkey
);
265 if (!retkey
) return ERROR_INVALID_PARAMETER
;
268 req
->access
= access
;
269 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
270 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
271 if ((ret
= server_call_noerr( REQ_OPEN_KEY
)) == ERROR_SUCCESS
) *retkey
= req
->hkey
;
276 /******************************************************************************
277 * RegOpenKeyW [ADVAPI32.151]
280 * hkey [I] Handle of open key
281 * name [I] Address of name of subkey to open
282 * retkey [O] Handle to open key
285 * Success: ERROR_SUCCESS
286 * Failure: Error code
288 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
290 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
294 /******************************************************************************
295 * RegOpenKeyA [ADVAPI32.148]
297 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
299 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
304 /******************************************************************************
305 * RegEnumKeyExW [ADVAPI32.139]
308 * hkey [I] Handle to key to enumerate
309 * index [I] Index of subkey to enumerate
310 * name [O] Buffer for subkey name
311 * name_len [O] Size of subkey buffer
312 * reserved [I] Reserved
313 * class [O] Buffer for class string
314 * class_len [O] Size of class buffer
315 * ft [O] Time key last written to
317 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
318 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
320 DWORD ret
, len
, cls_len
;
321 struct enum_key_request
*req
= get_req_buffer();
323 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
324 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
326 if (reserved
) return ERROR_INVALID_PARAMETER
;
330 if ((ret
= server_call_noerr( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
332 len
= lstrlenW( req
->name
) + 1;
333 cls_len
= lstrlenW( req
->class ) + 1;
334 if (len
> *name_len
) return ERROR_MORE_DATA
;
335 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
337 memcpy( name
, req
->name
, len
* sizeof(WCHAR
) );
341 if (class) memcpy( class, req
->class, cls_len
* sizeof(WCHAR
) );
342 *class_len
= cls_len
- 1;
344 if (ft
) DOSFS_UnixTimeToFileTime( req
->modif
, ft
, 0 );
345 return ERROR_SUCCESS
;
349 /******************************************************************************
350 * RegEnumKeyExA [ADVAPI32.138]
352 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
353 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
355 DWORD ret
, len
, cls_len
;
356 struct enum_key_request
*req
= get_req_buffer();
358 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
359 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
361 if (reserved
) return ERROR_INVALID_PARAMETER
;
365 if ((ret
= server_call_noerr( REQ_ENUM_KEY
)) != ERROR_SUCCESS
) return ret
;
367 len
= lstrlenW( req
->name
) + 1;
368 cls_len
= lstrlenW( req
->class ) + 1;
369 if (len
> *name_len
) return ERROR_MORE_DATA
;
370 if (class_len
&& (cls_len
> *class_len
)) return ERROR_MORE_DATA
;
372 memcpyWtoA( name
, req
->name
, len
);
376 if (class) memcpyWtoA( class, req
->class, cls_len
);
377 *class_len
= cls_len
- 1;
379 if (ft
) DOSFS_UnixTimeToFileTime( req
->modif
, ft
, 0 );
380 return ERROR_SUCCESS
;
384 /******************************************************************************
385 * RegEnumKeyW [ADVAPI32.140]
387 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
389 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
393 /******************************************************************************
394 * RegEnumKeyA [ADVAPI32.137]
396 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
398 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
402 /******************************************************************************
403 * RegQueryInfoKeyW [ADVAPI32.153]
406 * hkey [I] Handle to key to query
407 * class [O] Buffer for class string
408 * class_len [O] Size of class string buffer
409 * reserved [I] Reserved
410 * subkeys [O] Buffer for number of subkeys
411 * max_subkey [O] Buffer for longest subkey name length
412 * max_class [O] Buffer for longest class string length
413 * values [O] Buffer for number of value entries
414 * max_value [O] Buffer for longest value name length
415 * max_data [O] Buffer for longest value data length
416 * security [O] Buffer for security descriptor length
417 * modif [O] Modification time
419 * - win95 allows class to be valid and class_len to be NULL
420 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
421 * - both allow class to be NULL and class_len to be NULL
422 * (it's hard to test validity, so test !NULL instead)
424 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
425 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
426 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
427 LPDWORD security
, FILETIME
*modif
)
430 struct query_key_info_request
*req
= get_req_buffer();
433 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
434 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
436 if (class && !class_len
&& (VERSION_GetVersion() == NT40
))
437 return ERROR_INVALID_PARAMETER
;
440 if ((ret
= server_call_noerr( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
444 if (class_len
&& (lstrlenW(req
->class) + 1 > *class_len
))
446 *class_len
= lstrlenW(req
->class);
447 return ERROR_MORE_DATA
;
449 lstrcpyW( class, req
->class );
451 if (class_len
) *class_len
= lstrlenW( req
->class );
452 if (subkeys
) *subkeys
= req
->subkeys
;
453 if (max_subkey
) *max_subkey
= req
->max_subkey
;
454 if (max_class
) *max_class
= req
->max_class
;
455 if (values
) *values
= req
->values
;
456 if (max_value
) *max_value
= req
->max_value
;
457 if (max_data
) *max_data
= req
->max_data
;
458 if (modif
) DOSFS_UnixTimeToFileTime( req
->modif
, modif
, 0 );
459 return ERROR_SUCCESS
;
463 /******************************************************************************
464 * RegQueryInfoKeyA [ADVAPI32.152]
466 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
467 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
468 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
469 LPDWORD security
, FILETIME
*modif
)
472 struct query_key_info_request
*req
= get_req_buffer();
475 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
476 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
478 if (class && !class_len
&& (VERSION_GetVersion() == NT40
))
479 return ERROR_INVALID_PARAMETER
;
482 if ((ret
= server_call_noerr( REQ_QUERY_KEY_INFO
)) != ERROR_SUCCESS
) return ret
;
486 if (class_len
&& (lstrlenW(req
->class) + 1 > *class_len
))
488 *class_len
= lstrlenW(req
->class);
489 return ERROR_MORE_DATA
;
491 lstrcpyWtoA( class, req
->class );
493 if (class_len
) *class_len
= lstrlenW( req
->class );
494 if (subkeys
) *subkeys
= req
->subkeys
;
495 if (max_subkey
) *max_subkey
= req
->max_subkey
;
496 if (max_class
) *max_class
= req
->max_class
;
497 if (values
) *values
= req
->values
;
498 if (max_value
) *max_value
= req
->max_value
;
499 if (max_data
) *max_data
= req
->max_data
;
500 if (modif
) DOSFS_UnixTimeToFileTime( req
->modif
, modif
, 0 );
501 return ERROR_SUCCESS
;
505 /******************************************************************************
506 * RegCloseKey [ADVAPI32.126]
508 * Releases the handle of the specified key
511 * hkey [I] Handle of key to close
514 * Success: ERROR_SUCCESS
515 * Failure: Error code
517 DWORD WINAPI
RegCloseKey( HKEY hkey
)
519 struct close_key_request
*req
= get_req_buffer();
520 TRACE( "(0x%x)\n", hkey
);
522 return server_call_noerr( REQ_CLOSE_KEY
);
526 /******************************************************************************
527 * RegDeleteKeyW [ADVAPI32.134]
530 * hkey [I] Handle to open key
531 * name [I] Name of subkey to delete
534 * Success: ERROR_SUCCESS
535 * Failure: Error code
537 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
540 struct delete_key_request
*req
= get_req_buffer();
542 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
545 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
546 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
547 return server_call_noerr( REQ_DELETE_KEY
);
551 /******************************************************************************
552 * RegDeleteKeyA [ADVAPI32.133]
554 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
557 struct delete_key_request
*req
= get_req_buffer();
559 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
562 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
563 if (req
->name
[0] == '\\') return ERROR_BAD_PATHNAME
;
564 return server_call_noerr( REQ_DELETE_KEY
);
569 /******************************************************************************
570 * RegSetValueExW [ADVAPI32.170]
572 * Sets the data and type of a value under a register key
575 * hkey [I] Handle of key to set value for
576 * name [I] Name of value to set
577 * reserved [I] Reserved - must be zero
578 * type [I] Flag for value type
579 * data [I] Address of value data
580 * count [I] Size of value data
583 * Success: ERROR_SUCCESS
584 * Failure: Error code
587 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
588 * NT does definitely care (aj)
590 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
591 DWORD type
, CONST BYTE
*data
, DWORD count
)
594 struct set_key_value_request
*req
= get_req_buffer();
596 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey
, debugstr_w(name
), reserved
, type
, data
, count
);
598 if (reserved
) return ERROR_INVALID_PARAMETER
;
600 if (count
&& type
== REG_SZ
)
602 LPCWSTR str
= (LPCWSTR
)data
;
603 /* if user forgot to count terminating null, add it (yes NT does this) */
604 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
605 count
+= sizeof(WCHAR
);
607 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
611 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
612 memcpy( req
->data
, data
, count
);
613 return server_call_noerr( REQ_SET_KEY_VALUE
);
617 /******************************************************************************
618 * RegSetValueExA [ADVAPI32.169]
620 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
621 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_a(name
), reserved
, type
, data
, count
);
628 if (reserved
) return ERROR_INVALID_PARAMETER
;
630 if (count
&& type
== REG_SZ
)
632 /* if user forgot to count terminating null, add it (yes NT does this) */
633 if (data
[count
-1] && !data
[count
]) count
++;
635 if (is_string( type
))
637 /* need to convert to Unicode */
638 count
*= sizeof(WCHAR
);
639 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
640 memcpyAtoW( (LPWSTR
)req
->data
, data
, count
/ sizeof(WCHAR
) );
644 if (count
>= server_remaining( req
->data
)) return ERROR_OUTOFMEMORY
; /* FIXME */
645 memcpy( req
->data
, data
, count
);
650 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
651 return server_call_noerr( REQ_SET_KEY_VALUE
);
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 (lstrlenW( 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
;
734 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
735 if ((ret
= server_call_noerr( REQ_GET_KEY_VALUE
)) == ERROR_SUCCESS
)
737 if (type
) *type
= req
->type
;
738 ret
= copy_data( data
, req
->data
, req
->len
, count
);
744 /******************************************************************************
745 * RegQueryValueExA [ADVAPI32.157]
748 * the documentation is wrong: if the buffer is to small it remains untouched
750 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
751 LPBYTE data
, LPDWORD count
)
754 struct get_key_value_request
*req
= get_req_buffer();
756 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
757 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
759 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
762 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
763 if ((ret
= server_call_noerr( REQ_GET_KEY_VALUE
)) == ERROR_SUCCESS
)
765 if (type
) *type
= req
->type
;
766 ret
= copy_data_WtoA( data
, req
->data
, req
->len
, count
, req
->type
);
772 /******************************************************************************
773 * RegQueryValueW [ADVAPI32.159]
775 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
780 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
784 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
786 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
787 if (subkey
!= hkey
) RegCloseKey( subkey
);
788 if (ret
== ERROR_FILE_NOT_FOUND
)
790 /* return empty string if default value not found */
792 if (count
) *count
= 1;
799 /******************************************************************************
800 * RegQueryValueA [ADVAPI32.156]
802 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
807 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
811 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
813 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
814 if (subkey
!= hkey
) RegCloseKey( subkey
);
815 if (ret
== ERROR_FILE_NOT_FOUND
)
817 /* return empty string if default value not found */
819 if (count
) *count
= 1;
826 /******************************************************************************
827 * RegEnumValueW [ADVAPI32.142]
830 * hkey [I] Handle to key to query
831 * index [I] Index of value to query
832 * value [O] Value string
833 * val_count [I/O] Size of value buffer (in wchars)
834 * reserved [I] Reserved
836 * data [O] Value data
837 * count [I/O] Size of data buffer (in bytes)
840 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
841 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
844 struct enum_key_value_request
*req
= get_req_buffer();
846 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
847 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
849 /* NT only checks count, not val_count */
850 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
854 if ((ret
= server_call_noerr( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
856 len
= lstrlenW( req
->name
) + 1;
857 if (len
> *val_count
) return ERROR_MORE_DATA
;
858 memcpy( value
, req
->name
, len
* sizeof(WCHAR
) );
859 *val_count
= len
- 1;
861 if (type
) *type
= req
->type
;
862 return copy_data( data
, req
->data
, req
->len
, count
);
866 /******************************************************************************
867 * RegEnumValueA [ADVAPI32.141]
869 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
870 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
873 struct enum_key_value_request
*req
= get_req_buffer();
875 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
876 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
878 /* NT only checks count, not val_count */
879 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
883 if ((ret
= server_call_noerr( REQ_ENUM_KEY_VALUE
)) != ERROR_SUCCESS
) return ret
;
885 len
= lstrlenW( req
->name
) + 1;
886 if (len
> *val_count
) return ERROR_MORE_DATA
;
887 memcpyWtoA( value
, req
->name
, len
);
888 *val_count
= len
- 1;
890 if (type
) *type
= req
->type
;
891 return copy_data_WtoA( data
, req
->data
, req
->len
, count
, req
->type
);
896 /******************************************************************************
897 * RegDeleteValueW [ADVAPI32.136]
900 * hkey [I] handle to key
901 * name [I] name of value to delete
906 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
909 struct delete_key_value_request
*req
= get_req_buffer();
911 TRACE( "(0x%x,%s)\n", hkey
, debugstr_w(name
) );
914 if ((ret
= copy_nameW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
915 return server_call_noerr( REQ_DELETE_KEY_VALUE
);
919 /******************************************************************************
920 * RegDeleteValueA [ADVAPI32.135]
922 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
925 struct delete_key_value_request
*req
= get_req_buffer();
927 TRACE( "(0x%x,%s)\n", hkey
, debugstr_a(name
) );
930 if ((ret
= copy_nameAtoW( req
->name
, name
)) != ERROR_SUCCESS
) return ret
;
931 return server_call_noerr( REQ_DELETE_KEY_VALUE
);
935 /******************************************************************************
936 * RegLoadKeyW [ADVAPI32.185]
939 * hkey [I] Handle of open key
940 * subkey [I] Address of name of subkey
941 * filename [I] Address of filename for registry information
943 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
945 struct load_registry_request
*req
= get_req_buffer();
947 DWORD ret
, err
= GetLastError();
949 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
951 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
952 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
954 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
955 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
957 ret
= GetLastError();
962 if ((ret
= copy_nameW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
963 ret
= server_call_noerr( REQ_LOAD_REGISTRY
);
967 SetLastError( err
); /* restore the last error code */
972 /******************************************************************************
973 * RegLoadKeyA [ADVAPI32.184]
975 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
977 struct load_registry_request
*req
= get_req_buffer();
979 DWORD ret
, err
= GetLastError();
981 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
983 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
984 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
986 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
987 FILE_ATTRIBUTE_NORMAL
, -1 )) == INVALID_HANDLE_VALUE
)
989 ret
= GetLastError();
994 if ((ret
= copy_nameAtoW( req
->name
, subkey
)) != ERROR_SUCCESS
) goto done
;
995 ret
= server_call_noerr( REQ_LOAD_REGISTRY
);
999 SetLastError( err
); /* restore the last error code */
1004 /******************************************************************************
1005 * RegSaveKeyA [ADVAPI32.165]
1008 * hkey [I] Handle of key where save begins
1009 * lpFile [I] Address of filename to save to
1010 * sa [I] Address of security structure
1012 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1014 struct save_registry_request
*req
= get_req_buffer();
1021 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1023 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1025 err
= GetLastError();
1026 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1029 sprintf( name
, "reg%04x.tmp", count
++ );
1030 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1031 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, -1 );
1032 if (handle
!= INVALID_HANDLE_VALUE
) break;
1033 if ((ret
= GetLastError()) != ERROR_FILE_EXISTS
) goto done
;
1038 ret
= server_call_noerr( REQ_SAVE_REGISTRY
);
1039 CloseHandle( handle
);
1042 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1044 ERR( "Failed to move %s to %s\n", buffer
, file
);
1045 ret
= GetLastError();
1048 if (ret
) DeleteFileA( buffer
);
1051 SetLastError( err
); /* restore last error code */
1056 /******************************************************************************
1057 * RegSaveKeyW [ADVAPI32.166]
1059 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1061 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1062 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1063 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);