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 nameW
, 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
= &nameW
;
97 attr
.SecurityDescriptor
= NULL
;
98 attr
.SecurityQualityOfService
= NULL
;
99 RtlInitAnsiString( &nameA
, name
);
100 RtlInitAnsiString( &classA
, class );
102 /* FIXME: should use Unicode buffer in TEB */
103 if (!(status
= RtlAnsiStringToUnicodeString( &nameW
, &nameA
, TRUE
)))
105 if (!(status
= RtlAnsiStringToUnicodeString( &classW
, &classA
, TRUE
)))
107 status
= NtCreateKey( retkey
, access
, &attr
, 0, &classW
, options
, dispos
);
108 RtlFreeUnicodeString( &classW
);
110 RtlFreeUnicodeString( &nameW
);
112 return RtlNtStatusToDosError( status
);
116 /******************************************************************************
117 * RegCreateKeyW [ADVAPI32.@]
119 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
121 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
122 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
123 return RegCreateKeyExW( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
124 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
128 /******************************************************************************
129 * RegCreateKeyA [ADVAPI32.@]
131 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
133 return RegCreateKeyExA( hkey
, name
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
134 KEY_ALL_ACCESS
, NULL
, retkey
, NULL
);
139 /******************************************************************************
140 * RegOpenKeyExW [ADVAPI32.@]
142 * Opens the specified key
144 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
147 * hkey [I] Handle of open key
148 * name [I] Name of subkey to open
149 * reserved [I] Reserved - must be zero
150 * access [I] Security access mask
151 * retkey [O] Handle to open key
154 * Success: ERROR_SUCCESS
155 * Failure: Error code
158 * in case of failing is retkey = 0
160 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
162 OBJECT_ATTRIBUTES attr
;
163 UNICODE_STRING nameW
;
165 attr
.Length
= sizeof(attr
);
166 attr
.RootDirectory
= hkey
;
167 attr
.ObjectName
= &nameW
;
169 attr
.SecurityDescriptor
= NULL
;
170 attr
.SecurityQualityOfService
= NULL
;
171 RtlInitUnicodeString( &nameW
, name
);
172 return RtlNtStatusToDosError( NtOpenKey( retkey
, access
, &attr
) );
176 /******************************************************************************
177 * RegOpenKeyExA [ADVAPI32.@]
179 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, LPHKEY retkey
)
181 OBJECT_ATTRIBUTES attr
;
182 UNICODE_STRING nameW
;
186 attr
.Length
= sizeof(attr
);
187 attr
.RootDirectory
= hkey
;
188 attr
.ObjectName
= &nameW
;
190 attr
.SecurityDescriptor
= NULL
;
191 attr
.SecurityQualityOfService
= NULL
;
193 RtlInitAnsiString( &nameA
, name
);
194 /* FIXME: should use Unicode buffer in TEB */
195 if (!(status
= RtlAnsiStringToUnicodeString( &nameW
, &nameA
, TRUE
)))
197 status
= NtOpenKey( retkey
, access
, &attr
);
198 RtlFreeUnicodeString( &nameW
);
200 return RtlNtStatusToDosError( status
);
204 /******************************************************************************
205 * RegOpenKeyW [ADVAPI32.@]
208 * hkey [I] Handle of open key
209 * name [I] Address of name of subkey to open
210 * retkey [O] Handle to open key
213 * Success: ERROR_SUCCESS
214 * Failure: Error code
217 * in case of failing is retkey = 0
219 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, LPHKEY retkey
)
221 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
225 /******************************************************************************
226 * RegOpenKeyA [ADVAPI32.@]
228 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, LPHKEY retkey
)
230 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
234 /******************************************************************************
235 * RegOpenCurrentUser [ADVAPI32.@]
236 * FIXME: This function is supposed to retrieve a handle to the
237 * HKEY_CURRENT_USER for the user the current thread is impersonating.
238 * Since Wine does not currently allow threads to impersonate other users,
239 * this stub should work fine.
241 DWORD WINAPI
RegOpenCurrentUser( REGSAM access
, PHKEY retkey
)
243 return RegOpenKeyExA( HKEY_CURRENT_USER
, "", 0, access
, retkey
);
248 /******************************************************************************
249 * RegEnumKeyExW [ADVAPI32.@]
252 * hkey [I] Handle to key to enumerate
253 * index [I] Index of subkey to enumerate
254 * name [O] Buffer for subkey name
255 * name_len [O] Size of subkey buffer
256 * reserved [I] Reserved
257 * class [O] Buffer for class string
258 * class_len [O] Size of class buffer
259 * ft [O] Time key last written to
261 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
262 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
265 char buffer
[256], *buf_ptr
= buffer
;
266 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
269 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
270 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
272 if (reserved
) return ERROR_INVALID_PARAMETER
;
274 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
275 buffer
, sizeof(buffer
), &total_size
);
277 while (status
== STATUS_BUFFER_OVERFLOW
)
279 /* retry with a dynamically allocated buffer */
280 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
281 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
282 return ERROR_NOT_ENOUGH_MEMORY
;
283 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
284 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
285 buf_ptr
, total_size
, &total_size
);
290 DWORD len
= info
->NameLength
/ sizeof(WCHAR
);
291 DWORD cls_len
= info
->ClassLength
/ sizeof(WCHAR
);
293 if (ft
) *ft
= info
->LastWriteTime
;
295 if (len
>= *name_len
|| (class_len
&& (cls_len
>= *class_len
)))
296 status
= STATUS_BUFFER_OVERFLOW
;
300 memcpy( name
, info
->Name
, info
->NameLength
);
304 *class_len
= cls_len
;
307 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
314 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
315 return RtlNtStatusToDosError( status
);
319 /******************************************************************************
320 * RegEnumKeyExA [ADVAPI32.@]
322 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
323 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
326 char buffer
[256], *buf_ptr
= buffer
;
327 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
330 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
331 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
333 if (reserved
) return ERROR_INVALID_PARAMETER
;
335 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
336 buffer
, sizeof(buffer
), &total_size
);
338 while (status
== STATUS_BUFFER_OVERFLOW
)
340 /* retry with a dynamically allocated buffer */
341 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
342 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
343 return ERROR_NOT_ENOUGH_MEMORY
;
344 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
345 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
346 buf_ptr
, total_size
, &total_size
);
351 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
352 NULL
, 0, NULL
, NULL
);
353 DWORD cls_len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
354 info
->ClassLength
/ sizeof(WCHAR
),
355 NULL
, 0, NULL
, NULL
);
357 if (ft
) *ft
= info
->LastWriteTime
;
359 if (len
>= *name_len
|| (class_len
&& (cls_len
>= *class_len
)))
360 status
= STATUS_BUFFER_OVERFLOW
;
364 WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
365 name
, len
, NULL
, NULL
);
369 *class_len
= cls_len
;
372 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
373 info
->ClassLength
/ sizeof(WCHAR
),
374 class, cls_len
, NULL
, NULL
);
381 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
382 return RtlNtStatusToDosError( status
);
386 /******************************************************************************
387 * RegEnumKeyW [ADVAPI32.@]
389 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
391 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
395 /******************************************************************************
396 * RegEnumKeyA [ADVAPI32.@]
398 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
400 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
404 /******************************************************************************
405 * RegQueryInfoKeyW [ADVAPI32.@]
408 * hkey [I] Handle to key to query
409 * class [O] Buffer for class string
410 * class_len [O] Size of class string buffer
411 * reserved [I] Reserved
412 * subkeys [O] Buffer for number of subkeys
413 * max_subkey [O] Buffer for longest subkey name length
414 * max_class [O] Buffer for longest class string length
415 * values [O] Buffer for number of value entries
416 * max_value [O] Buffer for longest value name length
417 * max_data [O] Buffer for longest value data length
418 * security [O] Buffer for security descriptor length
419 * modif [O] Modification time
421 * - win95 allows class to be valid and class_len to be NULL
422 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
423 * - both allow class to be NULL and class_len to be NULL
424 * (it's hard to test validity, so test !NULL instead)
426 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
427 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
428 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
429 LPDWORD security
, FILETIME
*modif
)
432 char buffer
[256], *buf_ptr
= buffer
;
433 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
436 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
437 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
439 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
440 return ERROR_INVALID_PARAMETER
;
442 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
443 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
447 /* retry with a dynamically allocated buffer */
448 while (status
== STATUS_BUFFER_OVERFLOW
)
450 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
451 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
452 return ERROR_NOT_ENOUGH_MEMORY
;
453 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
454 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
457 if (status
) goto done
;
459 if (class_len
&& (info
->ClassLength
/sizeof(WCHAR
) + 1 > *class_len
))
461 status
= STATUS_BUFFER_OVERFLOW
;
465 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
466 class[info
->ClassLength
/sizeof(WCHAR
)] = 0;
469 else status
= STATUS_SUCCESS
;
471 if (class_len
) *class_len
= info
->ClassLength
/ sizeof(WCHAR
);
472 if (subkeys
) *subkeys
= info
->SubKeys
;
473 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
474 if (max_class
) *max_class
= info
->MaxClassLen
;
475 if (values
) *values
= info
->Values
;
476 if (max_value
) *max_value
= info
->MaxValueNameLen
;
477 if (max_data
) *max_data
= info
->MaxValueDataLen
;
478 if (modif
) *modif
= info
->LastWriteTime
;
481 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
482 return RtlNtStatusToDosError( status
);
486 /******************************************************************************
487 * RegQueryInfoKeyA [ADVAPI32.@]
489 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
490 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
491 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
492 LPDWORD security
, FILETIME
*modif
)
495 char buffer
[256], *buf_ptr
= buffer
;
496 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
497 DWORD total_size
, len
;
499 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
500 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
502 if (class && !class_len
&& !(GetVersion() & 0x80000000 /*NT*/))
503 return ERROR_INVALID_PARAMETER
;
505 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
506 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
508 if (class || class_len
)
510 /* retry with a dynamically allocated buffer */
511 while (status
== STATUS_BUFFER_OVERFLOW
)
513 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
514 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
515 return ERROR_NOT_ENOUGH_MEMORY
;
516 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
517 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
520 if (status
) goto done
;
522 len
= WideCharToMultiByte( CP_ACP
, 0,
523 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
524 info
->ClassLength
/sizeof(WCHAR
),
525 NULL
, 0, NULL
, NULL
);
528 if (len
+ 1 > *class_len
) status
= STATUS_BUFFER_OVERFLOW
;
531 if (class && !status
)
533 WideCharToMultiByte( CP_ACP
, 0,
534 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
535 info
->ClassLength
/sizeof(WCHAR
),
536 class, len
, NULL
, NULL
);
540 else status
= STATUS_SUCCESS
;
542 if (subkeys
) *subkeys
= info
->SubKeys
;
543 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
544 if (max_class
) *max_class
= info
->MaxClassLen
;
545 if (values
) *values
= info
->Values
;
546 if (max_value
) *max_value
= info
->MaxValueNameLen
;
547 if (max_data
) *max_data
= info
->MaxValueDataLen
;
548 if (modif
) *modif
= info
->LastWriteTime
;
551 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
552 return RtlNtStatusToDosError( status
);
556 /******************************************************************************
557 * RegCloseKey [ADVAPI32.@]
559 * Releases the handle of the specified key
562 * hkey [I] Handle of key to close
565 * Success: ERROR_SUCCESS
566 * Failure: Error code
568 DWORD WINAPI
RegCloseKey( HKEY hkey
)
570 if (!hkey
|| hkey
>= 0x80000000) return ERROR_SUCCESS
;
571 return RtlNtStatusToDosError( NtClose( hkey
) );
575 /******************************************************************************
576 * RegDeleteKeyW [ADVAPI32.@]
579 * hkey [I] Handle to open key
580 * name [I] Name of subkey to delete
583 * Success: ERROR_SUCCESS
584 * Failure: Error code
586 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
591 if (!name
|| !*name
) return NtDeleteKey( hkey
);
592 if (!(ret
= RegOpenKeyExW( hkey
, name
, 0, 0, &tmp
)))
594 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
601 /******************************************************************************
602 * RegDeleteKeyA [ADVAPI32.@]
604 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
609 if (!name
|| !*name
) return NtDeleteKey( hkey
);
610 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, 0, &tmp
)))
612 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
620 /******************************************************************************
621 * RegSetValueExW [ADVAPI32.@]
623 * Sets the data and type of a value under a register key
626 * hkey [I] Handle of key to set value for
627 * name [I] Name of value to set
628 * reserved [I] Reserved - must be zero
629 * type [I] Flag for value type
630 * data [I] Address of value data
631 * count [I] Size of value data
634 * Success: ERROR_SUCCESS
635 * Failure: Error code
638 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
639 * NT does definitely care (aj)
641 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
642 DWORD type
, CONST BYTE
*data
, DWORD count
)
644 UNICODE_STRING nameW
;
646 if (count
&& is_string(type
))
648 LPCWSTR str
= (LPCWSTR
)data
;
649 /* if user forgot to count terminating null, add it (yes NT does this) */
650 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
651 count
+= sizeof(WCHAR
);
654 RtlInitUnicodeString( &nameW
, name
);
655 return RtlNtStatusToDosError( NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
) );
659 /******************************************************************************
660 * RegSetValueExA [ADVAPI32.@]
662 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
663 CONST BYTE
*data
, DWORD count
)
665 UNICODE_STRING nameW
;
670 if (count
&& is_string(type
))
672 /* if user forgot to count terminating null, add it (yes NT does this) */
673 if (data
[count
-1] && !data
[count
]) count
++;
676 if (is_string( type
)) /* need to convert to Unicode */
678 DWORD lenW
= MultiByteToWideChar( CP_ACP
, 0, data
, count
, NULL
, 0 );
679 if (!(dataW
= HeapAlloc( GetProcessHeap(), 0, lenW
*sizeof(WCHAR
) )))
680 return ERROR_OUTOFMEMORY
;
681 MultiByteToWideChar( CP_ACP
, 0, data
, count
, dataW
, lenW
);
682 count
= lenW
* sizeof(WCHAR
);
683 data
= (BYTE
*)dataW
;
686 RtlInitAnsiString( &nameA
, name
);
687 /* FIXME: should use Unicode buffer in TEB */
688 if (!(status
= RtlAnsiStringToUnicodeString( &nameW
, &nameA
, TRUE
)))
690 status
= NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
);
691 RtlFreeUnicodeString( &nameW
);
693 if (dataW
) HeapFree( GetProcessHeap(), 0, dataW
);
694 return RtlNtStatusToDosError( status
);
698 /******************************************************************************
699 * RegSetValueW [ADVAPI32.@]
701 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
706 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
708 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
710 if (name
&& name
[0]) /* need to create the subkey */
712 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
715 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
716 (strlenW( data
) + 1) * sizeof(WCHAR
) );
717 if (subkey
!= hkey
) RegCloseKey( subkey
);
722 /******************************************************************************
723 * RegSetValueA [ADVAPI32.@]
725 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
730 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
732 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
734 if (name
&& name
[0]) /* need to create the subkey */
736 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
738 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
739 if (subkey
!= hkey
) RegCloseKey( subkey
);
745 /******************************************************************************
746 * RegQueryValueExW [ADVAPI32.@]
748 * Retrieves type and data for a specified name associated with an open key
751 * hkey [I] Handle of key to query
752 * name [I] Name of value to query
753 * reserved [I] Reserved - must be NULL
754 * type [O] Address of buffer for value type. If NULL, the type
756 * data [O] Address of data buffer. If NULL, the actual data is
758 * count [I/O] Address of data buffer size
761 * ERROR_SUCCESS: Success
762 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
763 * buffer is left untouched. The MS-documentation is wrong (js) !!!
765 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
766 LPBYTE data
, LPDWORD count
)
769 UNICODE_STRING name_str
;
771 char buffer
[256], *buf_ptr
= buffer
;
772 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
773 static const int info_size
= sizeof(*info
) - sizeof(info
->Data
);
775 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
776 hkey
, debugstr_w(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
778 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
780 RtlInitUnicodeString( &name_str
, name
);
782 if (data
) total_size
= min( sizeof(buffer
), *count
+ info_size
);
783 else total_size
= info_size
;
785 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
786 buffer
, total_size
, &total_size
);
787 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
791 /* retry with a dynamically allocated buffer */
792 while (status
== STATUS_BUFFER_OVERFLOW
&& total_size
- info_size
<= *count
)
794 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
795 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
796 return ERROR_NOT_ENOUGH_MEMORY
;
797 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
798 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
799 buf_ptr
, total_size
, &total_size
);
804 memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
805 /* if the type is REG_SZ and data is not 0-terminated
806 * and there is enough space in the buffer NT appends a \0 */
807 if (total_size
- info_size
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
809 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info_size
);
810 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
813 else if (status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
815 else status
= STATUS_SUCCESS
;
817 if (type
) *type
= info
->Type
;
818 if (count
) *count
= total_size
- info_size
;
821 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
822 return RtlNtStatusToDosError(status
);
826 /******************************************************************************
827 * RegQueryValueExA [ADVAPI32.@]
830 * the documentation is wrong: if the buffer is too small it remains untouched
832 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
833 LPBYTE data
, LPDWORD count
)
837 UNICODE_STRING nameW
;
839 char buffer
[256], *buf_ptr
= buffer
;
840 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
841 static const int info_size
= sizeof(*info
) - sizeof(info
->Data
);
843 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
844 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
846 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
848 RtlInitAnsiString( &nameA
, name
);
849 /* FIXME: should use Unicode buffer in TEB */
850 if ((status
= RtlAnsiStringToUnicodeString( &nameW
, &nameA
, TRUE
)))
851 return RtlNtStatusToDosError(status
);
853 status
= NtQueryValueKey( hkey
, &nameW
, KeyValuePartialInformation
,
854 buffer
, sizeof(buffer
), &total_size
);
855 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
857 /* we need to fetch the contents for a string type even if not requested,
858 * because we need to compute the length of the ASCII string. */
859 if (data
|| is_string(info
->Type
))
861 /* retry with a dynamically allocated buffer */
862 while (status
== STATUS_BUFFER_OVERFLOW
)
864 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
865 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
867 status
= STATUS_NO_MEMORY
;
870 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
871 status
= NtQueryValueKey( hkey
, &nameW
, KeyValuePartialInformation
,
872 buf_ptr
, total_size
, &total_size
);
875 if (status
) goto done
;
877 if (is_string(info
->Type
))
879 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info_size
),
880 (total_size
- info_size
) /sizeof(WCHAR
),
881 NULL
, 0, NULL
, NULL
);
884 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
887 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info_size
),
888 (total_size
- info_size
) /sizeof(WCHAR
),
889 data
, len
, NULL
, NULL
);
890 /* if the type is REG_SZ and data is not 0-terminated
891 * and there is enough space in the buffer NT appends a \0 */
892 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
895 total_size
= len
+ info_size
;
899 if (total_size
- info_size
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
900 else memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
903 else status
= STATUS_SUCCESS
;
905 if (type
) *type
= info
->Type
;
906 if (count
) *count
= total_size
- info_size
;
909 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
910 RtlFreeUnicodeString( &nameW
);
911 return RtlNtStatusToDosError(status
);
915 /******************************************************************************
916 * RegQueryValueW [ADVAPI32.@]
918 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
923 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
927 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
929 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
930 if (subkey
!= hkey
) RegCloseKey( subkey
);
931 if (ret
== ERROR_FILE_NOT_FOUND
)
933 /* return empty string if default value not found */
935 if (count
) *count
= 1;
942 /******************************************************************************
943 * RegQueryValueA [ADVAPI32.@]
945 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
950 TRACE("(%x,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
954 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
956 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
957 if (subkey
!= hkey
) RegCloseKey( subkey
);
958 if (ret
== ERROR_FILE_NOT_FOUND
)
960 /* return empty string if default value not found */
962 if (count
) *count
= 1;
969 /******************************************************************************
970 * RegEnumValueW [ADVAPI32.@]
973 * hkey [I] Handle to key to query
974 * index [I] Index of value to query
975 * value [O] Value string
976 * val_count [I/O] Size of value buffer (in wchars)
977 * reserved [I] Reserved
979 * data [O] Value data
980 * count [I/O] Size of data buffer (in bytes)
983 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
984 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
988 char buffer
[256], *buf_ptr
= buffer
;
989 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
990 static const int info_size
= sizeof(*info
) - sizeof(info
->Name
);
992 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
993 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
995 /* NT only checks count, not val_count */
996 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
998 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
999 if (data
) total_size
+= *count
;
1000 total_size
= min( sizeof(buffer
), total_size
);
1002 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1003 buffer
, total_size
, &total_size
);
1004 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1008 /* retry with a dynamically allocated buffer */
1009 while (status
== STATUS_BUFFER_OVERFLOW
)
1011 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1012 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1013 return ERROR_NOT_ENOUGH_MEMORY
;
1014 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1015 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1016 buf_ptr
, total_size
, &total_size
);
1019 if (status
) goto done
;
1023 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1025 status
= STATUS_BUFFER_OVERFLOW
;
1028 memcpy( value
, info
->Name
, info
->NameLength
);
1029 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1030 value
[*val_count
] = 0;
1035 if (total_size
- info
->DataOffset
> *count
)
1037 status
= STATUS_BUFFER_OVERFLOW
;
1040 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1041 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1043 /* if the type is REG_SZ and data is not 0-terminated
1044 * and there is enough space in the buffer NT appends a \0 */
1045 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1046 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1050 else status
= STATUS_SUCCESS
;
1052 if (type
) *type
= info
->Type
;
1053 if (count
) *count
= info
->DataLength
;
1056 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1057 return RtlNtStatusToDosError(status
);
1061 /******************************************************************************
1062 * RegEnumValueA [ADVAPI32.@]
1064 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1065 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1069 char buffer
[256], *buf_ptr
= buffer
;
1070 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1071 static const int info_size
= sizeof(*info
) - sizeof(info
->Name
);
1073 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
1074 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1076 /* NT only checks count, not val_count */
1077 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1079 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1080 if (data
) total_size
+= *count
;
1081 total_size
= min( sizeof(buffer
), total_size
);
1083 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1084 buffer
, total_size
, &total_size
);
1085 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1087 /* we need to fetch the contents for a string type even if not requested,
1088 * because we need to compute the length of the ASCII string. */
1089 if (value
|| data
|| is_string(info
->Type
))
1091 /* retry with a dynamically allocated buffer */
1092 while (status
== STATUS_BUFFER_OVERFLOW
)
1094 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1095 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1096 return ERROR_NOT_ENOUGH_MEMORY
;
1097 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1098 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1099 buf_ptr
, total_size
, &total_size
);
1102 if (status
) goto done
;
1106 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
1107 NULL
, 0, NULL
, NULL
);
1108 if (len
>= *val_count
)
1110 status
= STATUS_BUFFER_OVERFLOW
;
1113 WideCharToMultiByte( CP_ACP
, 0, info
->Name
, info
->NameLength
/sizeof(WCHAR
),
1114 value
, len
, NULL
, NULL
);
1119 if (is_string(info
->Type
))
1121 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1122 (total_size
- info
->DataOffset
) / sizeof(WCHAR
),
1123 NULL
, 0, NULL
, NULL
);
1128 status
= STATUS_BUFFER_OVERFLOW
;
1131 WideCharToMultiByte( CP_ACP
, 0, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1132 (total_size
- info
->DataOffset
) / sizeof(WCHAR
),
1133 data
, len
, NULL
, NULL
);
1134 /* if the type is REG_SZ and data is not 0-terminated
1135 * and there is enough space in the buffer NT appends a \0 */
1136 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1138 info
->DataLength
= len
;
1142 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1143 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1146 else status
= STATUS_SUCCESS
;
1148 if (type
) *type
= info
->Type
;
1149 if (count
) *count
= info
->DataLength
;
1152 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1153 return RtlNtStatusToDosError(status
);
1158 /******************************************************************************
1159 * RegDeleteValueW [ADVAPI32.@]
1162 * hkey [I] handle to key
1163 * name [I] name of value to delete
1168 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1170 UNICODE_STRING nameW
;
1171 RtlInitUnicodeString( &nameW
, name
);
1172 return RtlNtStatusToDosError( NtDeleteValueKey( hkey
, &nameW
) );
1176 /******************************************************************************
1177 * RegDeleteValueA [ADVAPI32.@]
1179 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1181 UNICODE_STRING nameW
;
1185 RtlInitAnsiString( &nameA
, name
);
1186 /* FIXME: should use Unicode buffer in TEB */
1187 if (!(status
= RtlAnsiStringToUnicodeString( &nameW
, &nameA
, TRUE
)))
1189 status
= NtDeleteValueKey( hkey
, &nameW
);
1190 RtlFreeUnicodeString( &nameW
);
1192 return RtlNtStatusToDosError( status
);
1196 /******************************************************************************
1197 * RegLoadKeyW [ADVAPI32.@]
1200 * hkey [I] Handle of open key
1201 * subkey [I] Address of name of subkey
1202 * filename [I] Address of filename for registry information
1204 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1207 DWORD ret
, len
, err
= GetLastError();
1209 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
1211 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1212 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1214 len
= strlenW( subkey
) * sizeof(WCHAR
);
1215 if (len
> MAX_PATH
*sizeof(WCHAR
)) return ERROR_INVALID_PARAMETER
;
1217 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1218 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1220 ret
= GetLastError();
1224 SERVER_START_VAR_REQ( load_registry
, len
)
1228 memcpy( server_data_ptr(req
), subkey
, len
);
1229 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1232 CloseHandle( file
);
1235 SetLastError( err
); /* restore the last error code */
1240 /******************************************************************************
1241 * RegLoadKeyA [ADVAPI32.@]
1243 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1246 DWORD ret
, len
, err
= GetLastError();
1248 TRACE( "(%x,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1250 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1251 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1253 len
= MultiByteToWideChar( CP_ACP
, 0, subkey
, strlen(subkey
), NULL
, 0 ) * sizeof(WCHAR
);
1254 if (len
> MAX_PATH
*sizeof(WCHAR
)) return ERROR_INVALID_PARAMETER
;
1256 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1257 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1259 ret
= GetLastError();
1263 SERVER_START_VAR_REQ( load_registry
, len
)
1267 MultiByteToWideChar( CP_ACP
, 0, subkey
, strlen(subkey
),
1268 server_data_ptr(req
), len
/sizeof(WCHAR
) );
1269 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1272 CloseHandle( file
);
1275 SetLastError( err
); /* restore the last error code */
1280 /******************************************************************************
1281 * RegSaveKeyA [ADVAPI32.@]
1284 * hkey [I] Handle of key where save begins
1285 * lpFile [I] Address of filename to save to
1286 * sa [I] Address of security structure
1288 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1296 TRACE( "(%x,%s,%p)\n", hkey
, debugstr_a(file
), sa
);
1298 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1300 err
= GetLastError();
1301 GetFullPathNameA( file
, sizeof(buffer
), buffer
, &name
);
1304 sprintf( name
, "reg%04x.tmp", count
++ );
1305 handle
= CreateFileA( buffer
, GENERIC_WRITE
, 0, NULL
,
1306 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1307 if (handle
!= INVALID_HANDLE_VALUE
) break;
1308 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1310 /* Something gone haywire ? Please report if this happens abnormally */
1312 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
);
1315 SERVER_START_REQ( save_registry
)
1319 ret
= RtlNtStatusToDosError( SERVER_CALL() );
1323 CloseHandle( handle
);
1326 if (!MoveFileExA( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1328 ERR( "Failed to move %s to %s\n", buffer
, file
);
1329 ret
= GetLastError();
1332 if (ret
) DeleteFileA( buffer
);
1335 SetLastError( err
); /* restore last error code */
1340 /******************************************************************************
1341 * RegSaveKeyW [ADVAPI32.@]
1343 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1345 LPSTR fileA
= HEAP_strdupWtoA( GetProcessHeap(), 0, file
);
1346 DWORD ret
= RegSaveKeyA( hkey
, fileA
, sa
);
1347 if (fileA
) HeapFree( GetProcessHeap(), 0, fileA
);
1352 /******************************************************************************
1353 * RegRestoreKeyW [ADVAPI32.@]
1356 * hkey [I] Handle of key where restore begins
1357 * lpFile [I] Address of filename containing saved tree
1358 * dwFlags [I] Optional flags
1360 LONG WINAPI
RegRestoreKeyW( HKEY hkey
, LPCWSTR lpFile
, DWORD dwFlags
)
1362 TRACE("(%x,%s,%ld)\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1364 /* It seems to do this check before the hkey check */
1365 if (!lpFile
|| !*lpFile
)
1366 return ERROR_INVALID_PARAMETER
;
1368 FIXME("(%x,%s,%ld): stub\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1370 /* Check for file existence */
1372 return ERROR_SUCCESS
;
1376 /******************************************************************************
1377 * RegRestoreKeyA [ADVAPI32.@]
1379 LONG WINAPI
RegRestoreKeyA( HKEY hkey
, LPCSTR lpFile
, DWORD dwFlags
)
1381 LPWSTR lpFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpFile
);
1382 LONG ret
= RegRestoreKeyW( hkey
, lpFileW
, dwFlags
);
1383 HeapFree( GetProcessHeap(), 0, lpFileW
);
1388 /******************************************************************************
1389 * RegUnLoadKeyW [ADVAPI32.@]
1392 * hkey [I] Handle of open key
1393 * lpSubKey [I] Address of name of subkey to unload
1395 LONG WINAPI
RegUnLoadKeyW( HKEY hkey
, LPCWSTR lpSubKey
)
1397 FIXME("(%x,%s): stub\n",hkey
, debugstr_w(lpSubKey
));
1398 return ERROR_SUCCESS
;
1402 /******************************************************************************
1403 * RegUnLoadKeyA [ADVAPI32.@]
1405 LONG WINAPI
RegUnLoadKeyA( HKEY hkey
, LPCSTR lpSubKey
)
1407 LPWSTR lpSubKeyW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey
);
1408 LONG ret
= RegUnLoadKeyW( hkey
, lpSubKeyW
);
1409 if(lpSubKeyW
) HeapFree( GetProcessHeap(), 0, lpSubKeyW
);
1414 /******************************************************************************
1415 * RegReplaceKeyW [ADVAPI32.@]
1418 * hkey [I] Handle of open key
1419 * lpSubKey [I] Address of name of subkey
1420 * lpNewFile [I] Address of filename for file with new data
1421 * lpOldFile [I] Address of filename for backup file
1423 LONG WINAPI
RegReplaceKeyW( HKEY hkey
, LPCWSTR lpSubKey
, LPCWSTR lpNewFile
,
1426 FIXME("(%x,%s,%s,%s): stub\n", hkey
, debugstr_w(lpSubKey
),
1427 debugstr_w(lpNewFile
),debugstr_w(lpOldFile
));
1428 return ERROR_SUCCESS
;
1432 /******************************************************************************
1433 * RegReplaceKeyA [ADVAPI32.@]
1435 LONG WINAPI
RegReplaceKeyA( HKEY hkey
, LPCSTR lpSubKey
, LPCSTR lpNewFile
,
1438 LPWSTR lpSubKeyW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey
);
1439 LPWSTR lpNewFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpNewFile
);
1440 LPWSTR lpOldFileW
= HEAP_strdupAtoW( GetProcessHeap(), 0, lpOldFile
);
1441 LONG ret
= RegReplaceKeyW( hkey
, lpSubKeyW
, lpNewFileW
, lpOldFileW
);
1442 HeapFree( GetProcessHeap(), 0, lpOldFileW
);
1443 HeapFree( GetProcessHeap(), 0, lpNewFileW
);
1444 HeapFree( GetProcessHeap(), 0, lpSubKeyW
);
1449 /******************************************************************************
1450 * RegSetKeySecurity [ADVAPI32.@]
1453 * hkey [I] Open handle of key to set
1454 * SecurityInfo [I] Descriptor contents
1455 * pSecurityDesc [I] Address of descriptor for key
1457 LONG WINAPI
RegSetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInfo
,
1458 PSECURITY_DESCRIPTOR pSecurityDesc
)
1460 TRACE("(%x,%ld,%p)\n",hkey
,SecurityInfo
,pSecurityDesc
);
1462 /* It seems to perform this check before the hkey check */
1463 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) ||
1464 (SecurityInfo
& GROUP_SECURITY_INFORMATION
) ||
1465 (SecurityInfo
& DACL_SECURITY_INFORMATION
) ||
1466 (SecurityInfo
& SACL_SECURITY_INFORMATION
)) {
1469 return ERROR_INVALID_PARAMETER
;
1472 return ERROR_INVALID_PARAMETER
;
1474 FIXME(":(%x,%ld,%p): stub\n",hkey
,SecurityInfo
,pSecurityDesc
);
1476 return ERROR_SUCCESS
;
1480 /******************************************************************************
1481 * RegGetKeySecurity [ADVAPI32.@]
1482 * Retrieves a copy of security descriptor protecting the registry key
1485 * hkey [I] Open handle of key to set
1486 * SecurityInformation [I] Descriptor contents
1487 * pSecurityDescriptor [O] Address of descriptor for key
1488 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1491 * Success: ERROR_SUCCESS
1492 * Failure: Error code
1494 LONG WINAPI
RegGetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInformation
,
1495 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1496 LPDWORD lpcbSecurityDescriptor
)
1498 TRACE("(%x,%ld,%p,%ld)\n",hkey
,SecurityInformation
,pSecurityDescriptor
,
1499 lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1501 /* FIXME: Check for valid SecurityInformation values */
1503 if (*lpcbSecurityDescriptor
< sizeof(SECURITY_DESCRIPTOR
))
1504 return ERROR_INSUFFICIENT_BUFFER
;
1506 FIXME("(%x,%ld,%p,%ld): stub\n",hkey
,SecurityInformation
,
1507 pSecurityDescriptor
,lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1509 return ERROR_SUCCESS
;
1513 /******************************************************************************
1514 * RegFlushKey [ADVAPI32.@]
1515 * Immediately writes key to registry.
1516 * Only returns after data has been written to disk.
1518 * FIXME: does it really wait until data is written ?
1521 * hkey [I] Handle of key to write
1524 * Success: ERROR_SUCCESS
1525 * Failure: Error code
1527 DWORD WINAPI
RegFlushKey( HKEY hkey
)
1529 FIXME( "(%x): stub\n", hkey
);
1530 return ERROR_SUCCESS
;
1534 /******************************************************************************
1535 * RegConnectRegistryW [ADVAPI32.@]
1538 * lpMachineName [I] Address of name of remote computer
1539 * hHey [I] Predefined registry handle
1540 * phkResult [I] Address of buffer for remote registry handle
1542 LONG WINAPI
RegConnectRegistryW( LPCWSTR lpMachineName
, HKEY hKey
,
1545 TRACE("(%s,%x,%p): stub\n",debugstr_w(lpMachineName
),hKey
,phkResult
);
1547 if (!lpMachineName
|| !*lpMachineName
) {
1548 /* Use the local machine name */
1549 return RegOpenKeyA( hKey
, "", phkResult
);
1552 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName
));
1553 return ERROR_BAD_NETPATH
;
1557 /******************************************************************************
1558 * RegConnectRegistryA [ADVAPI32.@]
1560 LONG WINAPI
RegConnectRegistryA( LPCSTR machine
, HKEY hkey
, LPHKEY reskey
)
1562 LPWSTR machineW
= HEAP_strdupAtoW( GetProcessHeap(), 0, machine
);
1563 DWORD ret
= RegConnectRegistryW( machineW
, hkey
, reskey
);
1564 HeapFree( GetProcessHeap(), 0, machineW
);
1569 /******************************************************************************
1570 * RegNotifyChangeKeyValue [ADVAPI32.@]
1573 * hkey [I] Handle of key to watch
1574 * fWatchSubTree [I] Flag for subkey notification
1575 * fdwNotifyFilter [I] Changes to be reported
1576 * hEvent [I] Handle of signaled event
1577 * fAsync [I] Flag for asynchronous reporting
1579 LONG WINAPI
RegNotifyChangeKeyValue( HKEY hkey
, BOOL fWatchSubTree
,
1580 DWORD fdwNotifyFilter
, HANDLE hEvent
,
1583 FIXME("(%x,%i,%ld,%x,%i): stub\n",hkey
,fWatchSubTree
,fdwNotifyFilter
,
1585 return ERROR_SUCCESS
;