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/unicode.h"
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(reg
);
30 /* check if value type needs string conversion (Ansi<->Unicode) */
31 static inline int is_string( DWORD type
)
33 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
37 /******************************************************************************
38 * RegCreateKeyExW [ADVAPI32.@]
41 * hkey [I] Handle of an open key
42 * name [I] Address of subkey name
43 * reserved [I] Reserved - must be 0
44 * class [I] Address of class string
45 * options [I] Special options flag
46 * access [I] Desired security access
47 * sa [I] Address of key security structure
48 * retkey [O] Address of buffer for opened handle
49 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
52 * in case of failing retkey remains untouched
54 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
55 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
56 LPHKEY retkey
, LPDWORD dispos
)
58 OBJECT_ATTRIBUTES attr
;
59 UNICODE_STRING nameW
, classW
;
61 if (reserved
) return ERROR_INVALID_PARAMETER
;
62 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
64 attr
.Length
= sizeof(attr
);
65 attr
.RootDirectory
= hkey
;
66 attr
.ObjectName
= &nameW
;
68 attr
.SecurityDescriptor
= NULL
;
69 attr
.SecurityQualityOfService
= NULL
;
70 RtlInitUnicodeString( &nameW
, name
);
71 RtlInitUnicodeString( &classW
, class );
73 return RtlNtStatusToDosError( NtCreateKey( retkey
, access
, &attr
, 0,
74 &classW
, options
, dispos
) );
78 /******************************************************************************
79 * RegCreateKeyExA [ADVAPI32.@]
81 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
82 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
83 LPHKEY retkey
, LPDWORD dispos
)
85 OBJECT_ATTRIBUTES attr
;
86 UNICODE_STRING classW
;
87 ANSI_STRING nameA
, classA
;
90 if (reserved
) return ERROR_INVALID_PARAMETER
;
91 if (!(access
& KEY_ALL_ACCESS
) || (access
& ~KEY_ALL_ACCESS
)) return ERROR_ACCESS_DENIED
;
93 attr
.Length
= sizeof(attr
);
94 attr
.RootDirectory
= hkey
;
95 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
97 attr
.SecurityDescriptor
= NULL
;
98 attr
.SecurityQualityOfService
= NULL
;
99 RtlInitAnsiString( &nameA
, name
);
100 RtlInitAnsiString( &classA
, class );
102 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
105 if (!(status
= RtlAnsiStringToUnicodeString( &classW
, &classA
, TRUE
)))
107 status
= NtCreateKey( retkey
, access
, &attr
, 0, &classW
, options
, dispos
);
108 RtlFreeUnicodeString( &classW
);
111 return RtlNtStatusToDosError( status
);
115 /******************************************************************************
116 * RegCreateKeyW [ADVAPI32.@]
118 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
120 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
121 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
122 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
123 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
127 /******************************************************************************
128 * RegCreateKeyA [ADVAPI32.@]
130 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
132 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
133 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
138 /******************************************************************************
139 * RegOpenKeyExW [ADVAPI32.@]
141 * Opens the specified key
143 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
146 * hkey [I] Handle of open key
147 * name [I] Name of subkey to open
148 * reserved [I] Reserved - must be zero
149 * access [I] Security access mask
150 * retkey [O] Handle to open key
153 * Success: ERROR_SUCCESS
154 * Failure: Error code
157 * in case of failing is retkey = 0
159 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
161 OBJECT_ATTRIBUTES attr
;
162 UNICODE_STRING nameW
;
164 attr
.Length
= sizeof(attr
);
165 attr
.RootDirectory
= hkey
;
166 attr
.ObjectName
= &nameW
;
168 attr
.SecurityDescriptor
= NULL
;
169 attr
.SecurityQualityOfService
= NULL
;
170 RtlInitUnicodeString( &nameW
, name
);
171 return RtlNtStatusToDosError( NtOpenKey( retkey
, access
, &attr
) );
175 /******************************************************************************
176 * RegOpenKeyExA [ADVAPI32.@]
178 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
180 OBJECT_ATTRIBUTES attr
;
184 attr
.Length
= sizeof(attr
);
185 attr
.RootDirectory
= hkey
;
186 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
188 attr
.SecurityDescriptor
= NULL
;
189 attr
.SecurityQualityOfService
= NULL
;
191 RtlInitAnsiString( &nameA
, name
);
192 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
195 status
= NtOpenKey( retkey
, access
, &attr
);
197 return RtlNtStatusToDosError( status
);
201 /******************************************************************************
202 * RegOpenKeyW [ADVAPI32.@]
205 * hkey [I] Handle of open key
206 * name [I] Address of name of subkey to open
207 * retkey [O] Handle to open key
210 * Success: ERROR_SUCCESS
211 * Failure: Error code
214 * in case of failing is retkey = 0
216 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
218 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
222 /******************************************************************************
223 * RegOpenKeyA [ADVAPI32.@]
225 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
227 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
231 /******************************************************************************
232 * RegOpenCurrentUser [ADVAPI32.@]
233 * FIXME: This function is supposed to retrieve a handle to the
234 * HKEY_CURRENT_USER for the user the current thread is impersonating.
235 * Since Wine does not currently allow threads to impersonate other users,
236 * this stub should work fine.
238 DWORD WINAPI
RegOpenCurrentUser( REGSAM access
, PHKEY retkey
)
240 return RegOpenKeyExA( HKEY_CURRENT_USER
, "", 0, access
, retkey
);
245 /******************************************************************************
246 * RegEnumKeyExW [ADVAPI32.@]
249 * hkey [I] Handle to key to enumerate
250 * index [I] Index of subkey to enumerate
251 * name [O] Buffer for subkey name
252 * name_len [O] Size of subkey buffer
253 * reserved [I] Reserved
254 * class [O] Buffer for class string
255 * class_len [O] Size of class buffer
256 * ft [O] Time key last written to
258 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
259 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
262 char buffer
[256], *buf_ptr
= buffer
;
263 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
266 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
267 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
269 if (reserved
) return ERROR_INVALID_PARAMETER
;
271 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
272 buffer
, sizeof(buffer
), &total_size
);
274 while (status
== STATUS_BUFFER_OVERFLOW
)
276 /* retry with a dynamically allocated buffer */
277 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
278 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
279 return ERROR_NOT_ENOUGH_MEMORY
;
280 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
281 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
282 buf_ptr
, total_size
, &total_size
);
287 DWORD len
= info
->NameLength
/ sizeof(WCHAR
);
288 DWORD cls_len
= info
->ClassLength
/ sizeof(WCHAR
);
290 if (ft
) *ft
= info
->LastWriteTime
;
292 if (len
>= *name_len
|| (class_len
&& (cls_len
>= *class_len
)))
293 status
= STATUS_BUFFER_OVERFLOW
;
297 memcpy( name
, info
->Name
, info
->NameLength
);
301 *class_len
= cls_len
;
304 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
311 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
312 return RtlNtStatusToDosError( status
);
316 /******************************************************************************
317 * RegEnumKeyExA [ADVAPI32.@]
319 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
320 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
323 char buffer
[256], *buf_ptr
= buffer
;
324 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
327 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
328 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
330 if (reserved
) return ERROR_INVALID_PARAMETER
;
332 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
333 buffer
, sizeof(buffer
), &total_size
);
335 while (status
== STATUS_BUFFER_OVERFLOW
)
337 /* retry with a dynamically allocated buffer */
338 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
339 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
340 return ERROR_NOT_ENOUGH_MEMORY
;
341 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
342 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
343 buf_ptr
, total_size
, &total_size
);
348 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
349 NULL
, 0, NULL
, NULL
);
350 DWORD cls_len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
351 info
->ClassLength
/ sizeof(WCHAR
),
352 NULL
, 0, NULL
, NULL
);
354 if (ft
) *ft
= info
->LastWriteTime
;
356 if (len
>= *name_len
|| (class_len
&& (cls_len
>= *class_len
)))
357 status
= STATUS_BUFFER_OVERFLOW
;
361 WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
362 name
, len
, NULL
, NULL
);
366 *class_len
= cls_len
;
369 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
370 info
->ClassLength
/ sizeof(WCHAR
),
371 class, cls_len
, NULL
, NULL
);
378 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
379 return RtlNtStatusToDosError( status
);
383 /******************************************************************************
384 * RegEnumKeyW [ADVAPI32.@]
386 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
388 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
392 /******************************************************************************
393 * RegEnumKeyA [ADVAPI32.@]
395 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
397 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
401 /******************************************************************************
402 * RegQueryInfoKeyW [ADVAPI32.@]
405 * hkey [I] Handle to key to query
406 * class [O] Buffer for class string
407 * class_len [O] Size of class string buffer
408 * reserved [I] Reserved
409 * subkeys [O] Buffer for number of subkeys
410 * max_subkey [O] Buffer for longest subkey name length
411 * max_class [O] Buffer for longest class string length
412 * values [O] Buffer for number of value entries
413 * max_value [O] Buffer for longest value name length
414 * max_data [O] Buffer for longest value data length
415 * security [O] Buffer for security descriptor length
416 * modif [O] Modification time
418 * - win95 allows class to be valid and class_len to be NULL
419 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
420 * - both allow class to be NULL and class_len to be NULL
421 * (it's hard to test validity, so test !NULL instead)
423 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
424 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
425 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
426 LPDWORD security
, FILETIME
*modif
)
429 char buffer
[256], *buf_ptr
= buffer
;
430 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)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
&& !(GetVersion() & 0x80000000 /*NT*/))
437 return ERROR_INVALID_PARAMETER
;
439 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
440 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
444 /* retry with a dynamically allocated buffer */
445 while (status
== STATUS_BUFFER_OVERFLOW
)
447 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
448 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
449 return ERROR_NOT_ENOUGH_MEMORY
;
450 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
451 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
454 if (status
) goto done
;
456 if (class_len
&& (info
->ClassLength
/sizeof(WCHAR
) + 1 > *class_len
))
458 status
= STATUS_BUFFER_OVERFLOW
;
462 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
463 class[info
->ClassLength
/sizeof(WCHAR
)] = 0;
466 else status
= STATUS_SUCCESS
;
468 if (class_len
) *class_len
= info
->ClassLength
/ sizeof(WCHAR
);
469 if (subkeys
) *subkeys
= info
->SubKeys
;
470 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
471 if (max_class
) *max_class
= info
->MaxClassLen
;
472 if (values
) *values
= info
->Values
;
473 if (max_value
) *max_value
= info
->MaxValueNameLen
;
474 if (max_data
) *max_data
= info
->MaxValueDataLen
;
475 if (modif
) *modif
= info
->LastWriteTime
;
478 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
479 return RtlNtStatusToDosError( status
);
483 /******************************************************************************
484 * RegQueryInfoKeyA [ADVAPI32.@]
486 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
487 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
488 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
489 LPDWORD security
, FILETIME
*modif
)
492 char buffer
[256], *buf_ptr
= buffer
;
493 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
494 DWORD total_size
, len
;
496 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
497 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
499 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
500 return ERROR_INVALID_PARAMETER
;
502 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
503 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
505 if (class || class_len
)
507 /* retry with a dynamically allocated buffer */
508 while (status
== STATUS_BUFFER_OVERFLOW
)
510 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
511 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
512 return ERROR_NOT_ENOUGH_MEMORY
;
513 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
514 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
517 if (status
) goto done
;
519 len
= WideCharToMultiByte( CP_ACP
, 0,
520 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
521 info
->ClassLength
/sizeof(WCHAR
),
522 NULL
, 0, NULL
, NULL
);
525 if (len
+ 1 > *class_len
) status
= STATUS_BUFFER_OVERFLOW
;
528 if (class && !status
)
530 WideCharToMultiByte( CP_ACP
, 0,
531 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
532 info
->ClassLength
/sizeof(WCHAR
),
533 class, len
, NULL
, NULL
);
537 else status
= STATUS_SUCCESS
;
539 if (subkeys
) *subkeys
= info
->SubKeys
;
540 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
541 if (max_class
) *max_class
= info
->MaxClassLen
;
542 if (values
) *values
= info
->Values
;
543 if (max_value
) *max_value
= info
->MaxValueNameLen
;
544 if (max_data
) *max_data
= info
->MaxValueDataLen
;
545 if (modif
) *modif
= info
->LastWriteTime
;
548 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
549 return RtlNtStatusToDosError( status
);
553 /******************************************************************************
554 * RegCloseKey [ADVAPI32.@]
556 * Releases the handle of the specified key
559 * hkey [I] Handle of key to close
562 * Success: ERROR_SUCCESS
563 * Failure: Error code
565 DWORD WINAPI
RegCloseKey( HKEY hkey
)
567 if (!hkey
|| hkey
>= 0x80000000) return ERROR_SUCCESS
;
568 return RtlNtStatusToDosError( NtClose( hkey
) );
572 /******************************************************************************
573 * RegDeleteKeyW [ADVAPI32.@]
576 * hkey [I] Handle to open key
577 * name [I] Name of subkey to delete
580 * Success: ERROR_SUCCESS
581 * Failure: Error code
583 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
588 if (!name
|| !*name
) return NtDeleteKey( hkey
);
589 if (!(ret
= RegOpenKeyExW( hkey
, name
, 0, 0, &tmp
)))
591 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
598 /******************************************************************************
599 * RegDeleteKeyA [ADVAPI32.@]
601 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
606 if (!name
|| !*name
) return NtDeleteKey( hkey
);
607 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, 0, &tmp
)))
609 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
617 /******************************************************************************
618 * RegSetValueExW [ADVAPI32.@]
620 * Sets the data and type of a value under a register key
623 * hkey [I] Handle of key to set value for
624 * name [I] Name of value to set
625 * reserved [I] Reserved - must be zero
626 * type [I] Flag for value type
627 * data [I] Address of value data
628 * count [I] Size of value data
631 * Success: ERROR_SUCCESS
632 * Failure: Error code
635 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
636 * NT does definitely care (aj)
638 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
639 DWORD type
, CONST BYTE
*data
, DWORD count
)
641 UNICODE_STRING nameW
;
643 if (count
&& is_string(type
))
645 LPCWSTR str
= (LPCWSTR
)data
;
646 /* if user forgot to count terminating null, add it (yes NT does this) */
647 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
648 count
+= sizeof(WCHAR
);
651 RtlInitUnicodeString( &nameW
, name
);
652 return RtlNtStatusToDosError( NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
) );
656 /******************************************************************************
657 * RegSetValueExA [ADVAPI32.@]
659 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
660 CONST BYTE
*data
, DWORD count
)
666 if (count
&& is_string(type
))
668 /* if user forgot to count terminating null, add it (yes NT does this) */
669 if (data
[count
-1] && !data
[count
]) count
++;
672 if (is_string( type
)) /* need to convert to Unicode */
674 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, data
, count
, NULL
, 0 );
675 if (!(dataW
= HeapAlloc( GetProcessHeap(), 0, lenW
*sizeof(WCHAR
) )))
676 return ERROR_OUTOFMEMORY
;
677 MultiByteToWideChar( CP_ACP
, 0, data
, count
, dataW
, lenW
);
678 count
= lenW
* sizeof(WCHAR
);
679 data
= (BYTE
*)dataW
;
682 RtlInitAnsiString( &nameA
, name
);
683 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
686 status
= NtSetValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
, 0, type
, data
, count
);
688 if (dataW
) HeapFree( GetProcessHeap(), 0, dataW
);
689 return RtlNtStatusToDosError( status
);
693 /******************************************************************************
694 * RegSetValueW [ADVAPI32.@]
696 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
701 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
703 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
705 if (name
&& name
[0]) /* need to create the subkey */
707 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
710 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
711 (strlenW( data
) + 1) * sizeof(WCHAR
) );
712 if (subkey
!= hkey
) RegCloseKey( subkey
);
717 /******************************************************************************
718 * RegSetValueA [ADVAPI32.@]
720 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
725 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
727 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
729 if (name
&& name
[0]) /* need to create the subkey */
731 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
733 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
734 if (subkey
!= hkey
) RegCloseKey( subkey
);
740 /******************************************************************************
741 * RegQueryValueExW [ADVAPI32.@]
743 * Retrieves type and data for a specified name associated with an open key
746 * hkey [I] Handle of key to query
747 * name [I] Name of value to query
748 * reserved [I] Reserved - must be NULL
749 * type [O] Address of buffer for value type. If NULL, the type
751 * data [O] Address of data buffer. If NULL, the actual data is
753 * count [I/O] Address of data buffer size
756 * ERROR_SUCCESS: Success
757 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
758 * buffer is left untouched. The MS-documentation is wrong (js) !!!
760 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
761 LPBYTE data
, LPDWORD count
)
764 UNICODE_STRING name_str
;
766 char buffer
[256], *buf_ptr
= buffer
;
767 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
768 static const int info_size
= sizeof(*info
) - sizeof(info
->Data
);
770 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
771 hkey
, debugstr_w(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
773 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
775 RtlInitUnicodeString( &name_str
, name
);
777 if (data
) total_size
= min( sizeof(buffer
), *count
+ info_size
);
778 else total_size
= info_size
;
780 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
781 buffer
, total_size
, &total_size
);
782 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
786 /* retry with a dynamically allocated buffer */
787 while (status
== STATUS_BUFFER_OVERFLOW
&& total_size
- info_size
<= *count
)
789 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
790 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
791 return ERROR_NOT_ENOUGH_MEMORY
;
792 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
793 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
794 buf_ptr
, total_size
, &total_size
);
799 memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
800 /* if the type is REG_SZ and data is not 0-terminated
801 * and there is enough space in the buffer NT appends a \0 */
802 if (total_size
- info_size
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
804 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info_size
);
805 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
808 else if (status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
810 else status
= STATUS_SUCCESS
;
812 if (type
) *type
= info
->Type
;
813 if (count
) *count
= total_size
- info_size
;
816 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
817 return RtlNtStatusToDosError(status
);
821 /******************************************************************************
822 * RegQueryValueExA [ADVAPI32.@]
825 * the documentation is wrong: if the buffer is too small it remains untouched
827 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
828 LPBYTE data
, LPDWORD count
)
833 char buffer
[256], *buf_ptr
= buffer
;
834 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
835 static const int info_size
= sizeof(*info
) - sizeof(info
->Data
);
837 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
838 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
840 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
842 RtlInitAnsiString( &nameA
, name
);
843 if ((status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
845 return RtlNtStatusToDosError(status
);
847 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
848 KeyValuePartialInformation
, buffer
, sizeof(buffer
), &total_size
);
849 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
851 /* we need to fetch the contents for a string type even if not requested,
852 * because we need to compute the length of the ASCII string. */
853 if (data
|| is_string(info
->Type
))
855 /* retry with a dynamically allocated buffer */
856 while (status
== STATUS_BUFFER_OVERFLOW
)
858 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
859 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
861 status
= STATUS_NO_MEMORY
;
864 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
865 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
866 KeyValuePartialInformation
, buf_ptr
, total_size
, &total_size
);
869 if (status
) goto done
;
871 if (is_string(info
->Type
))
873 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info_size
),
874 (total_size
- info_size
) /sizeof(WCHAR
),
875 NULL
, 0, NULL
, NULL
);
878 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
881 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info_size
),
882 (total_size
- info_size
) /sizeof(WCHAR
),
883 data
, len
, NULL
, NULL
);
884 /* if the type is REG_SZ and data is not 0-terminated
885 * and there is enough space in the buffer NT appends a \0 */
886 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
889 total_size
= len
+ info_size
;
893 if (total_size
- info_size
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
894 else memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
897 else status
= STATUS_SUCCESS
;
899 if (type
) *type
= info
->Type
;
900 if (count
) *count
= total_size
- info_size
;
903 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
904 return RtlNtStatusToDosError(status
);
908 /******************************************************************************
909 * RegQueryValueW [ADVAPI32.@]
911 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
916 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
920 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
922 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
923 if (subkey
!= hkey
) RegCloseKey( subkey
);
924 if (ret
== ERROR_FILE_NOT_FOUND
)
926 /* return empty string if default value not found */
928 if (count
) *count
= 1;
935 /******************************************************************************
936 * RegQueryValueA [ADVAPI32.@]
938 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
943 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
947 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
949 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
950 if (subkey
!= hkey
) RegCloseKey( subkey
);
951 if (ret
== ERROR_FILE_NOT_FOUND
)
953 /* return empty string if default value not found */
955 if (count
) *count
= 1;
962 /******************************************************************************
963 * RegEnumValueW [ADVAPI32.@]
966 * hkey [I] Handle to key to query
967 * index [I] Index of value to query
968 * value [O] Value string
969 * val_count [I/O] Size of value buffer (in wchars)
970 * reserved [I] Reserved
972 * data [O] Value data
973 * count [I/O] Size of data buffer (in bytes)
976 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
977 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
981 char buffer
[256], *buf_ptr
= buffer
;
982 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
983 static const int info_size
= sizeof(*info
) - sizeof(info
->Name
);
985 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
986 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
988 /* NT only checks count, not val_count */
989 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
991 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
992 if (data
) total_size
+= *count
;
993 total_size
= min( sizeof(buffer
), total_size
);
995 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
996 buffer
, total_size
, &total_size
);
997 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1001 /* retry with a dynamically allocated buffer */
1002 while (status
== STATUS_BUFFER_OVERFLOW
)
1004 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1005 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1006 return ERROR_NOT_ENOUGH_MEMORY
;
1007 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1008 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1009 buf_ptr
, total_size
, &total_size
);
1012 if (status
) goto done
;
1016 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1018 status
= STATUS_BUFFER_OVERFLOW
;
1021 memcpy( value
, info
->Name
, info
->NameLength
);
1022 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1023 value
[*val_count
] = 0;
1028 if (total_size
- info
->DataOffset
> *count
)
1030 status
= STATUS_BUFFER_OVERFLOW
;
1033 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1034 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1036 /* if the type is REG_SZ and data is not 0-terminated
1037 * and there is enough space in the buffer NT appends a \0 */
1038 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1039 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1043 else status
= STATUS_SUCCESS
;
1045 if (type
) *type
= info
->Type
;
1046 if (count
) *count
= info
->DataLength
;
1049 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1050 return RtlNtStatusToDosError(status
);
1054 /******************************************************************************
1055 * RegEnumValueA [ADVAPI32.@]
1057 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1058 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1062 char buffer
[256], *buf_ptr
= buffer
;
1063 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1064 static const int info_size
= sizeof(*info
) - sizeof(info
->Name
);
1066 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
1067 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1069 /* NT only checks count, not val_count */
1070 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1072 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1073 if (data
) total_size
+= *count
;
1074 total_size
= min( sizeof(buffer
), total_size
);
1076 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1077 buffer
, total_size
, &total_size
);
1078 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1080 /* we need to fetch the contents for a string type even if not requested,
1081 * because we need to compute the length of the ASCII string. */
1082 if (value
|| data
|| is_string(info
->Type
))
1084 /* retry with a dynamically allocated buffer */
1085 while (status
== STATUS_BUFFER_OVERFLOW
)
1087 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1088 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1089 return ERROR_NOT_ENOUGH_MEMORY
;
1090 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1091 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1092 buf_ptr
, total_size
, &total_size
);
1095 if (status
) goto done
;
1099 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
1100 NULL
, 0, NULL
, NULL
);
1101 if (len
>= *val_count
)
1103 status
= STATUS_BUFFER_OVERFLOW
;
1106 WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
1107 value
, len
, NULL
, NULL
);
1112 if (is_string(info
->Type
))
1114 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1115 (total_size
- info
->DataOffset
) / sizeof(WCHAR
),
1116 NULL
, 0, NULL
, NULL
);
1121 status
= STATUS_BUFFER_OVERFLOW
;
1124 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1125 (total_size
- info
->DataOffset
) / sizeof(WCHAR
),
1126 data
, len
, NULL
, NULL
);
1127 /* if the type is REG_SZ and data is not 0-terminated
1128 * and there is enough space in the buffer NT appends a \0 */
1129 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1131 info
->DataLength
= len
;
1135 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1136 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1139 else status
= STATUS_SUCCESS
;
1141 if (type
) *type
= info
->Type
;
1142 if (count
) *count
= info
->DataLength
;
1145 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1146 return RtlNtStatusToDosError(status
);
1151 /******************************************************************************
1152 * RegDeleteValueW [ADVAPI32.@]
1155 * hkey [I] handle to key
1156 * name [I] name of value to delete
1161 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1163 UNICODE_STRING nameW
;
1164 RtlInitUnicodeString( &nameW
, name
);
1165 return RtlNtStatusToDosError( NtDeleteValueKey( hkey
, &nameW
) );
1169 /******************************************************************************
1170 * RegDeleteValueA [ADVAPI32.@]
1172 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1177 RtlInitAnsiString( &nameA
, name
);
1178 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1181 status
= NtDeleteValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
);
1183 return RtlNtStatusToDosError( status
);
1187 /******************************************************************************
1188 * RegLoadKeyW [ADVAPI32.@]
1191 * hkey [I] Handle of open key
1192 * subkey [I] Address of name of subkey
1193 * filename [I] Address of filename for registry information
1195 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1198 DWORD ret
, len
, err
= GetLastError();
1200 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
1202 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1203 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1205 len
= strlenW( subkey
) * sizeof(WCHAR
);
1206 if (len
> MAX_PATH
*sizeof(WCHAR
)) return ERROR_INVALID_PARAMETER
;
1208 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1209 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1211 ret
= GetLastError();
1215 SERVER_START_VAR_REQ( load_registry
, len
)
1219 memcpy( server_data_ptr(req
), subkey
, len
);
1220 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1223 CloseHandle( file
);
1226 SetLastError( err
); /* restore the last error code */
1231 /******************************************************************************
1232 * RegLoadKeyA [ADVAPI32.@]
1234 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1237 DWORD ret
, len
, err
= GetLastError();
1239 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1241 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1242 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1244 len
= MultiByteToWideChar( CP_ACP
, 0, subkey
, strlen(subkey
), NULL
, 0 ) * sizeof(WCHAR
);
1245 if (len
> MAX_PATH
*sizeof(WCHAR
)) return ERROR_INVALID_PARAMETER
;
1247 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1248 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1250 ret
= GetLastError();
1254 SERVER_START_VAR_REQ( load_registry
, len
)
1258 MultiByteToWideChar( CP_ACP
, 0, subkey
, strlen(subkey
),
1259 server_data_ptr(req
), len
/sizeof(WCHAR
) );
1260 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1263 CloseHandle( file
);
1266 SetLastError( err
); /* restore the last error code */
1271 /******************************************************************************
1272 * RegSaveKeyA [ADVAPI32.@]
1275 * hkey [I] Handle of key where save begins
1276 * lpFile [I] Address of filename to save to
1277 * sa [I] Address of security structure
1279 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1287 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1289 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1291 err
= GetLastError();
1292 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1295 sprintf( name
, "reg%04x.tmp", count
++ );
1296 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1297 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1298 if (handle
!= INVALID_HANDLE_VALUE
) break;
1299 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1301 /* Something gone haywire ? Please report if this happens abnormally */
1303 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
);
1306 SERVER_START_REQ( save_registry
)
1310 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1314 CloseHandle( handle
);
1317 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1319 ERR( "Failed to move %s to %s\n", buffer
, file
);
1320 ret
= GetLastError();
1323 if (ret
) DeleteFileA( buffer
);
1326 SetLastError( err
); /* restore last error code */
1331 /******************************************************************************
1332 * RegSaveKeyW [ADVAPI32.@]
1334 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1336 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1337 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1338 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);
1343 /******************************************************************************
1344 * RegRestoreKeyW [ADVAPI32.@]
1347 * hkey [I] Handle of key where restore begins
1348 * lpFile [I] Address of filename containing saved tree
1349 * dwFlags [I] Optional flags
1351 LONG WINAPI
RegRestoreKeyW( HKEY hkey
, LPCWSTR lpFile
, DWORD dwFlags
)
1353 TRACE("(%x,%s,%ld)\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1355 /* It seems to do this check before the hkey check */
1356 if (!lpFile
|| !*lpFile
)
1357 return ERROR_INVALID_PARAMETER
;
1359 FIXME("(%x,%s,%ld): stub\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1361 /* Check for file existence */
1363 return ERROR_SUCCESS
;
1367 /******************************************************************************
1368 * RegRestoreKeyA [ADVAPI32.@]
1370 LONG WINAPI
RegRestoreKeyA( HKEY hkey
, LPCSTR lpFile
, DWORD dwFlags
)
1372 LPWSTR lpFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpFile
);
1373 LONG ret
= RegRestoreKeyW( hkey
, lpFileW
, dwFlags
);
1374 HeapFree( GetProcessHeap(), 0, lpFileW
);
1379 /******************************************************************************
1380 * RegUnLoadKeyW [ADVAPI32.@]
1383 * hkey [I] Handle of open key
1384 * lpSubKey [I] Address of name of subkey to unload
1386 LONG WINAPI
RegUnLoadKeyW( HKEY hkey
, LPCWSTR lpSubKey
)
1388 FIXME("(%x,%s): stub\n",hkey
, debugstr_w(lpSubKey
));
1389 return ERROR_SUCCESS
;
1393 /******************************************************************************
1394 * RegUnLoadKeyA [ADVAPI32.@]
1396 LONG WINAPI
RegUnLoadKeyA( HKEY hkey
, LPCSTR lpSubKey
)
1398 LPWSTR lpSubKeyW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey
);
1399 LONG ret
= RegUnLoadKeyW( hkey
, lpSubKeyW
);
1400 if(lpSubKeyW
) HeapFree( GetProcessHeap(), 0, lpSubKeyW
);
1405 /******************************************************************************
1406 * RegReplaceKeyW [ADVAPI32.@]
1409 * hkey [I] Handle of open key
1410 * lpSubKey [I] Address of name of subkey
1411 * lpNewFile [I] Address of filename for file with new data
1412 * lpOldFile [I] Address of filename for backup file
1414 LONG WINAPI
RegReplaceKeyW( HKEY hkey
, LPCWSTR lpSubKey
, LPCWSTR lpNewFile
,
1417 FIXME("(%x,%s,%s,%s): stub\n", hkey
, debugstr_w(lpSubKey
),
1418 debugstr_w(lpNewFile
),debugstr_w(lpOldFile
));
1419 return ERROR_SUCCESS
;
1423 /******************************************************************************
1424 * RegReplaceKeyA [ADVAPI32.@]
1426 LONG WINAPI
RegReplaceKeyA( HKEY hkey
, LPCSTR lpSubKey
, LPCSTR lpNewFile
,
1429 LPWSTR lpSubKeyW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey
);
1430 LPWSTR lpNewFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpNewFile
);
1431 LPWSTR lpOldFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpOldFile
);
1432 LONG ret
= RegReplaceKeyW( hkey
, lpSubKeyW
, lpNewFileW
, lpOldFileW
);
1433 HeapFree( GetProcessHeap(), 0, lpOldFileW
);
1434 HeapFree( GetProcessHeap(), 0, lpNewFileW
);
1435 HeapFree( GetProcessHeap(), 0, lpSubKeyW
);
1440 /******************************************************************************
1441 * RegSetKeySecurity [ADVAPI32.@]
1444 * hkey [I] Open handle of key to set
1445 * SecurityInfo [I] Descriptor contents
1446 * pSecurityDesc [I] Address of descriptor for key
1448 LONG WINAPI
RegSetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInfo
,
1449 PSECURITY_DESCRIPTOR pSecurityDesc
)
1451 TRACE("(%x,%ld,%p)\n",hkey
,SecurityInfo
,pSecurityDesc
);
1453 /* It seems to perform this check before the hkey check */
1454 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) ||
1455 (SecurityInfo
& GROUP_SECURITY_INFORMATION
) ||
1456 (SecurityInfo
& DACL_SECURITY_INFORMATION
) ||
1457 (SecurityInfo
& SACL_SECURITY_INFORMATION
)) {
1460 return ERROR_INVALID_PARAMETER
;
1463 return ERROR_INVALID_PARAMETER
;
1465 FIXME(":(%x,%ld,%p): stub\n",hkey
,SecurityInfo
,pSecurityDesc
);
1467 return ERROR_SUCCESS
;
1471 /******************************************************************************
1472 * RegGetKeySecurity [ADVAPI32.@]
1473 * Retrieves a copy of security descriptor protecting the registry key
1476 * hkey [I] Open handle of key to set
1477 * SecurityInformation [I] Descriptor contents
1478 * pSecurityDescriptor [O] Address of descriptor for key
1479 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1482 * Success: ERROR_SUCCESS
1483 * Failure: Error code
1485 LONG WINAPI
RegGetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInformation
,
1486 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1487 LPDWORD lpcbSecurityDescriptor
)
1489 TRACE("(%x,%ld,%p,%ld)\n",hkey
,SecurityInformation
,pSecurityDescriptor
,
1490 lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1492 /* FIXME: Check for valid SecurityInformation values */
1494 if (*lpcbSecurityDescriptor
< sizeof(SECURITY_DESCRIPTOR
))
1495 return ERROR_INSUFFICIENT_BUFFER
;
1497 FIXME("(%x,%ld,%p,%ld): stub\n",hkey
,SecurityInformation
,
1498 pSecurityDescriptor
,lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1500 return ERROR_SUCCESS
;
1504 /******************************************************************************
1505 * RegFlushKey [ADVAPI32.@]
1506 * Immediately writes key to registry.
1507 * Only returns after data has been written to disk.
1509 * FIXME: does it really wait until data is written ?
1512 * hkey [I] Handle of key to write
1515 * Success: ERROR_SUCCESS
1516 * Failure: Error code
1518 DWORD WINAPI
RegFlushKey( HKEY hkey
)
1520 FIXME( "(%x): stub\n", hkey
);
1521 return ERROR_SUCCESS
;
1525 /******************************************************************************
1526 * RegConnectRegistryW [ADVAPI32.@]
1529 * lpMachineName [I] Address of name of remote computer
1530 * hHey [I] Predefined registry handle
1531 * phkResult [I] Address of buffer for remote registry handle
1533 LONG WINAPI
RegConnectRegistryW( LPCWSTR lpMachineName
, HKEY hKey
,
1536 TRACE("(%s,%x,%p): stub\n",debugstr_w(lpMachineName
),hKey
,phkResult
);
1538 if (!lpMachineName
|| !*lpMachineName
) {
1539 /* Use the local machine name */
1540 return RegOpenKeyA( hKey
, "", phkResult
);
1543 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName
));
1544 return ERROR_BAD_NETPATH
;
1548 /******************************************************************************
1549 * RegConnectRegistryA [ADVAPI32.@]
1551 LONG WINAPI
RegConnectRegistryA( LPCSTR machine
, HKEY hkey
, LPHKEY reskey
)
1553 LPWSTR machineW
= HEAP_strdupAtoW( GetProcessHeap(), 0, machine
);
1554 DWORD ret
= RegConnectRegistryW( machineW
, hkey
, reskey
);
1555 HeapFree( GetProcessHeap(), 0, machineW
);
1560 /******************************************************************************
1561 * RegNotifyChangeKeyValue [ADVAPI32.@]
1564 * hkey [I] Handle of key to watch
1565 * fWatchSubTree [I] Flag for subkey notification
1566 * fdwNotifyFilter [I] Changes to be reported
1567 * hEvent [I] Handle of signaled event
1568 * fAsync [I] Flag for asynchronous reporting
1570 LONG WINAPI
RegNotifyChangeKeyValue( HKEY hkey
, BOOL fWatchSubTree
,
1571 DWORD fdwNotifyFilter
, HANDLE hEvent
,
1574 FIXME("(%x,%i,%ld,%x,%i): stub\n",hkey
,fWatchSubTree
,fdwNotifyFilter
,
1576 return ERROR_SUCCESS
;