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.
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
34 #define WIN32_NO_STATUS
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(reg
);
47 #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
48 #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
49 #define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
51 static HKEY special_root_keys
[NB_SPECIAL_ROOT_KEYS
];
52 static BOOL hkcu_cache_disabled
;
54 static const WCHAR name_CLASSES_ROOT
[] =
55 {'M','a','c','h','i','n','e','\\',
56 'S','o','f','t','w','a','r','e','\\',
57 'C','l','a','s','s','e','s',0};
58 static const WCHAR name_LOCAL_MACHINE
[] =
59 {'M','a','c','h','i','n','e',0};
60 static const WCHAR name_USERS
[] =
62 static const WCHAR name_PERFORMANCE_DATA
[] =
63 {'P','e','r','f','D','a','t','a',0};
64 static const WCHAR name_CURRENT_CONFIG
[] =
65 {'M','a','c','h','i','n','e','\\',
66 'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
68 'H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\',
69 'C','u','r','r','e','n','t',0};
70 static const WCHAR name_DYN_DATA
[] =
71 {'D','y','n','D','a','t','a',0};
73 static const WCHAR
* const root_key_names
[NB_SPECIAL_ROOT_KEYS
] =
76 NULL
, /* HKEY_CURRENT_USER is determined dynamically */
79 name_PERFORMANCE_DATA
,
85 /* check if value type needs string conversion (Ansi<->Unicode) */
86 static inline int is_string( DWORD type
)
88 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
91 /* check if current version is NT or Win95 */
92 static inline int is_version_nt(void)
94 return !(GetVersion() & 0x80000000);
97 /* create one of the HKEY_* special root keys */
98 static HKEY
create_special_root_hkey( HANDLE hkey
, DWORD access
)
101 int idx
= (UINT_PTR
)hkey
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
;
103 if (hkey
== HKEY_CURRENT_USER
)
105 if (RtlOpenCurrentUser( access
, &hkey
)) return 0;
106 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey
);
108 /* don't cache the key in the table if caching is disabled */
109 if (hkcu_cache_disabled
)
114 OBJECT_ATTRIBUTES attr
;
117 attr
.Length
= sizeof(attr
);
118 attr
.RootDirectory
= 0;
119 attr
.ObjectName
= &name
;
121 attr
.SecurityDescriptor
= NULL
;
122 attr
.SecurityQualityOfService
= NULL
;
123 RtlInitUnicodeString( &name
, root_key_names
[idx
] );
124 if (NtCreateKey( &hkey
, access
, &attr
, 0, NULL
, 0, NULL
)) return 0;
125 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
128 if (!(ret
= InterlockedCompareExchangePointer( (void **)&special_root_keys
[idx
], hkey
, 0 )))
131 NtClose( hkey
); /* somebody beat us to it */
135 /* map the hkey from special root to normal key if necessary */
136 static inline HKEY
get_special_root_hkey( HKEY hkey
)
140 if ((hkey
>= HKEY_SPECIAL_ROOT_FIRST
) && (hkey
<= HKEY_SPECIAL_ROOT_LAST
))
142 if (!(ret
= special_root_keys
[(UINT_PTR
)hkey
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
]))
143 ret
= create_special_root_hkey( hkey
, KEY_ALL_ACCESS
);
149 /******************************************************************************
150 * RegOverridePredefKey [ADVAPI32.@]
152 LSTATUS WINAPI
RegOverridePredefKey( HKEY hkey
, HKEY override
)
157 if ((hkey
< HKEY_SPECIAL_ROOT_FIRST
) || (hkey
> HKEY_SPECIAL_ROOT_LAST
))
158 return ERROR_INVALID_PARAMETER
;
159 idx
= (UINT_PTR
)hkey
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
;
163 NTSTATUS status
= NtDuplicateObject( GetCurrentProcess(), override
,
164 GetCurrentProcess(), (HANDLE
*)&override
,
165 0, 0, DUPLICATE_SAME_ACCESS
);
166 if (status
) return RtlNtStatusToDosError( status
);
169 old_key
= InterlockedExchangePointer( (void **)&special_root_keys
[idx
], override
);
170 if (old_key
) NtClose( old_key
);
171 return ERROR_SUCCESS
;
175 /******************************************************************************
176 * RegCreateKeyExW [ADVAPI32.@]
178 * See RegCreateKeyExA.
180 LSTATUS WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
181 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
182 PHKEY retkey
, LPDWORD dispos
)
184 OBJECT_ATTRIBUTES attr
;
185 UNICODE_STRING nameW
, classW
;
187 if (reserved
) return ERROR_INVALID_PARAMETER
;
188 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
190 attr
.Length
= sizeof(attr
);
191 attr
.RootDirectory
= hkey
;
192 attr
.ObjectName
= &nameW
;
194 attr
.SecurityDescriptor
= NULL
;
195 attr
.SecurityQualityOfService
= NULL
;
196 RtlInitUnicodeString( &nameW
, name
);
197 RtlInitUnicodeString( &classW
, class );
199 return RtlNtStatusToDosError( NtCreateKey( (PHANDLE
)retkey
, access
, &attr
, 0,
200 &classW
, options
, dispos
) );
204 /******************************************************************************
205 * RegCreateKeyExA [ADVAPI32.@]
207 * Open a registry key, creating it if it doesn't exist.
210 * hkey [I] Handle of the parent registry key
211 * name [I] Name of the new key to open or create
212 * reserved [I] Reserved, pass 0
213 * class [I] The object type of the new key
214 * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h")
215 * access [I] Access level desired
216 * sa [I] Security attributes for the key
217 * retkey [O] Destination for the resulting handle
218 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
221 * Success: ERROR_SUCCESS.
222 * Failure: A standard Win32 error code. retkey remains untouched.
225 * MAXIMUM_ALLOWED in access mask not supported by server
227 LSTATUS WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
228 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
229 PHKEY retkey
, LPDWORD dispos
)
231 OBJECT_ATTRIBUTES attr
;
232 UNICODE_STRING classW
;
233 ANSI_STRING nameA
, classA
;
236 if (reserved
) return ERROR_INVALID_PARAMETER
;
237 if (!is_version_nt())
239 access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
240 if (name
&& *name
== '\\') name
++; /* win9x,ME ignores one (and only one) beginning backslash */
242 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
244 attr
.Length
= sizeof(attr
);
245 attr
.RootDirectory
= hkey
;
246 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
248 attr
.SecurityDescriptor
= NULL
;
249 attr
.SecurityQualityOfService
= NULL
;
250 RtlInitAnsiString( &nameA
, name
);
251 RtlInitAnsiString( &classA
, class );
253 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
256 if (!(status
= RtlAnsiStringToUnicodeString( &classW
, &classA
, TRUE
)))
258 status
= NtCreateKey( (PHANDLE
)retkey
, access
, &attr
, 0, &classW
, options
, dispos
);
259 RtlFreeUnicodeString( &classW
);
262 return RtlNtStatusToDosError( status
);
266 /******************************************************************************
267 * RegCreateKeyW [ADVAPI32.@]
269 * Creates the specified reg key.
272 * hKey [I] Handle to an open key.
273 * lpSubKey [I] Name of a key that will be opened or created.
274 * phkResult [O] Receives a handle to the opened or created key.
277 * Success: ERROR_SUCCESS
278 * Failure: nonzero error code defined in Winerror.h
280 LSTATUS WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR lpSubKey
, PHKEY phkResult
)
282 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
283 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
284 return RegCreateKeyExW( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
285 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
289 /******************************************************************************
290 * RegCreateKeyA [ADVAPI32.@]
294 LSTATUS WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR lpSubKey
, PHKEY phkResult
)
296 return RegCreateKeyExA( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
297 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
302 /******************************************************************************
303 * RegOpenKeyExW [ADVAPI32.@]
307 LSTATUS WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
309 OBJECT_ATTRIBUTES attr
;
310 UNICODE_STRING nameW
;
312 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
314 attr
.Length
= sizeof(attr
);
315 attr
.RootDirectory
= hkey
;
316 attr
.ObjectName
= &nameW
;
318 attr
.SecurityDescriptor
= NULL
;
319 attr
.SecurityQualityOfService
= NULL
;
320 RtlInitUnicodeString( &nameW
, name
);
321 return RtlNtStatusToDosError( NtOpenKey( (PHANDLE
)retkey
, access
, &attr
) );
325 /******************************************************************************
326 * RegOpenKeyExA [ADVAPI32.@]
328 * Open a registry key.
331 * hkey [I] Handle of open key
332 * name [I] Name of subkey to open
333 * reserved [I] Reserved - must be zero
334 * access [I] Security access mask
335 * retkey [O] Handle to open key
338 * Success: ERROR_SUCCESS
339 * Failure: A standard Win32 error code. retkey is set to 0.
342 * Unlike RegCreateKeyExA(), this function will not create the key if it
345 LSTATUS WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
347 OBJECT_ATTRIBUTES attr
;
351 if (!is_version_nt()) access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
353 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
355 attr
.Length
= sizeof(attr
);
356 attr
.RootDirectory
= hkey
;
357 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
359 attr
.SecurityDescriptor
= NULL
;
360 attr
.SecurityQualityOfService
= NULL
;
362 RtlInitAnsiString( &nameA
, name
);
363 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
366 status
= NtOpenKey( (PHANDLE
)retkey
, access
, &attr
);
368 return RtlNtStatusToDosError( status
);
372 /******************************************************************************
373 * RegOpenKeyW [ADVAPI32.@]
377 LSTATUS WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, PHKEY retkey
)
382 return ERROR_SUCCESS
;
384 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
388 /******************************************************************************
389 * RegOpenKeyA [ADVAPI32.@]
391 * Open a registry key.
394 * hkey [I] Handle of parent key to open the new key under
395 * name [I] Name of the key under hkey to open
396 * retkey [O] Destination for the resulting Handle
399 * Success: ERROR_SUCCESS
400 * Failure: A standard Win32 error code. retkey is set to 0.
402 LSTATUS WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, PHKEY retkey
)
407 return ERROR_SUCCESS
;
409 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
413 /******************************************************************************
414 * RegOpenCurrentUser [ADVAPI32.@]
416 * Get a handle to the HKEY_CURRENT_USER key for the user
417 * the current thread is impersonating.
420 * access [I] Desired access rights to the key
421 * retkey [O] Handle to the opened key
424 * Success: ERROR_SUCCESS
425 * Failure: nonzero error code from Winerror.h
428 * This function is supposed to retrieve a handle to the
429 * HKEY_CURRENT_USER for the user the current thread is impersonating.
430 * Since Wine does not currently allow threads to impersonate other users,
431 * this stub should work fine.
433 LSTATUS WINAPI
RegOpenCurrentUser( REGSAM access
, PHKEY retkey
)
435 return RegOpenKeyExA( HKEY_CURRENT_USER
, "", 0, access
, retkey
);
440 /******************************************************************************
441 * RegEnumKeyExW [ADVAPI32.@]
443 * Enumerate subkeys of the specified open registry key.
446 * hkey [I] Handle to key to enumerate
447 * index [I] Index of subkey to enumerate
448 * name [O] Buffer for subkey name
449 * name_len [O] Size of subkey buffer
450 * reserved [I] Reserved
451 * class [O] Buffer for class string
452 * class_len [O] Size of class buffer
453 * ft [O] Time key last written to
456 * Success: ERROR_SUCCESS
457 * Failure: System error code. If there are no more subkeys available, the
458 * function returns ERROR_NO_MORE_ITEMS.
460 LSTATUS WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
461 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
464 char buffer
[256], *buf_ptr
= buffer
;
465 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
468 TRACE( "(%p,%d,%p,%p(%u),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
469 name_len
? *name_len
: 0, reserved
, class, class_len
, ft
);
471 if (reserved
) return ERROR_INVALID_PARAMETER
;
472 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
474 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
475 buffer
, sizeof(buffer
), &total_size
);
477 while (status
== STATUS_BUFFER_OVERFLOW
)
479 /* retry with a dynamically allocated buffer */
480 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
481 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
482 return ERROR_NOT_ENOUGH_MEMORY
;
483 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
484 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
485 buf_ptr
, total_size
, &total_size
);
490 DWORD len
= info
->NameLength
/ sizeof(WCHAR
);
491 DWORD cls_len
= info
->ClassLength
/ sizeof(WCHAR
);
493 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
495 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
496 status
= STATUS_BUFFER_OVERFLOW
;
500 memcpy( name
, info
->Name
, info
->NameLength
);
504 *class_len
= cls_len
;
507 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
514 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
515 return RtlNtStatusToDosError( status
);
519 /******************************************************************************
520 * RegEnumKeyExA [ADVAPI32.@]
524 LSTATUS WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
525 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
528 char buffer
[256], *buf_ptr
= buffer
;
529 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
532 TRACE( "(%p,%d,%p,%p(%u),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
533 name_len
? *name_len
: 0, reserved
, class, class_len
, ft
);
535 if (reserved
) return ERROR_INVALID_PARAMETER
;
536 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
538 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
539 buffer
, sizeof(buffer
), &total_size
);
541 while (status
== STATUS_BUFFER_OVERFLOW
)
543 /* retry with a dynamically allocated buffer */
544 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
545 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
546 return ERROR_NOT_ENOUGH_MEMORY
;
547 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
548 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
549 buf_ptr
, total_size
, &total_size
);
556 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
557 RtlUnicodeToMultiByteSize( &cls_len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
559 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
561 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
562 status
= STATUS_BUFFER_OVERFLOW
;
566 RtlUnicodeToMultiByteN( name
, len
, NULL
, info
->Name
, info
->NameLength
);
570 *class_len
= cls_len
;
573 RtlUnicodeToMultiByteN( class, cls_len
, NULL
,
574 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
582 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
583 return RtlNtStatusToDosError( status
);
587 /******************************************************************************
588 * RegEnumKeyW [ADVAPI32.@]
590 * Enumerates subkeys of the specified open reg key.
593 * hKey [I] Handle to an open key.
594 * dwIndex [I] Index of the subkey of hKey to retrieve.
595 * lpName [O] Name of the subkey.
596 * cchName [I] Size of lpName in TCHARS.
599 * Success: ERROR_SUCCESS
600 * Failure: system error code. If there are no more subkeys available, the
601 * function returns ERROR_NO_MORE_ITEMS.
603 LSTATUS WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
605 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
609 /******************************************************************************
610 * RegEnumKeyA [ADVAPI32.@]
614 LSTATUS WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
616 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
620 /******************************************************************************
621 * RegQueryInfoKeyW [ADVAPI32.@]
623 * Retrieves information about the specified registry key.
626 * hkey [I] Handle to key to query
627 * class [O] Buffer for class string
628 * class_len [O] Size of class string buffer
629 * reserved [I] Reserved
630 * subkeys [O] Buffer for number of subkeys
631 * max_subkey [O] Buffer for longest subkey name length
632 * max_class [O] Buffer for longest class string length
633 * values [O] Buffer for number of value entries
634 * max_value [O] Buffer for longest value name length
635 * max_data [O] Buffer for longest value data length
636 * security [O] Buffer for security descriptor length
637 * modif [O] Modification time
640 * Success: ERROR_SUCCESS
641 * Failure: system error code.
644 * - win95 allows class to be valid and class_len to be NULL
645 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
646 * - both allow class to be NULL and class_len to be NULL
647 * (it's hard to test validity, so test !NULL instead)
649 LSTATUS WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
650 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
651 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
652 LPDWORD security
, FILETIME
*modif
)
655 char buffer
[256], *buf_ptr
= buffer
;
656 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
659 TRACE( "(%p,%p,%d,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
660 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
662 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
663 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
665 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
666 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
670 /* retry with a dynamically allocated buffer */
671 while (status
== STATUS_BUFFER_OVERFLOW
)
673 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
674 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
675 return ERROR_NOT_ENOUGH_MEMORY
;
676 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
677 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
680 if (status
) goto done
;
682 if (class_len
&& (info
->ClassLength
/sizeof(WCHAR
) + 1 > *class_len
))
684 status
= STATUS_BUFFER_OVERFLOW
;
688 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
689 class[info
->ClassLength
/sizeof(WCHAR
)] = 0;
692 else status
= STATUS_SUCCESS
;
694 if (class_len
) *class_len
= info
->ClassLength
/ sizeof(WCHAR
);
695 if (subkeys
) *subkeys
= info
->SubKeys
;
696 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
697 if (max_class
) *max_class
= info
->MaxClassLen
;
698 if (values
) *values
= info
->Values
;
699 if (max_value
) *max_value
= info
->MaxValueNameLen
;
700 if (max_data
) *max_data
= info
->MaxValueDataLen
;
701 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
704 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
705 return RtlNtStatusToDosError( status
);
709 /******************************************************************************
710 * RegQueryMultipleValuesA [ADVAPI32.@]
712 * Retrieves the type and data for a list of value names associated with a key.
715 * hKey [I] Handle to an open key.
716 * val_list [O] Array of VALENT structures that describes the entries.
717 * num_vals [I] Number of elements in val_list.
718 * lpValueBuf [O] Pointer to a buffer that receives the data for each value.
719 * ldwTotsize [I/O] Size of lpValueBuf.
722 * Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied.
723 * Failure: nonzero error code from Winerror.h ldwTotsize contains num needed
726 LSTATUS WINAPI
RegQueryMultipleValuesA( HKEY hkey
, PVALENTA val_list
, DWORD num_vals
,
727 LPSTR lpValueBuf
, LPDWORD ldwTotsize
)
730 DWORD maxBytes
= *ldwTotsize
;
732 LPSTR bufptr
= lpValueBuf
;
735 TRACE("(%p,%p,%d,%p,%p=%d)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
737 for(i
=0; i
< num_vals
; ++i
)
740 val_list
[i
].ve_valuelen
=0;
741 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
742 if(status
!= ERROR_SUCCESS
)
747 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
749 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
750 (LPBYTE
)bufptr
, &val_list
[i
].ve_valuelen
);
751 if(status
!= ERROR_SUCCESS
)
756 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
758 bufptr
+= val_list
[i
].ve_valuelen
;
761 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
763 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
767 /******************************************************************************
768 * RegQueryMultipleValuesW [ADVAPI32.@]
770 * See RegQueryMultipleValuesA.
772 LSTATUS WINAPI
RegQueryMultipleValuesW( HKEY hkey
, PVALENTW val_list
, DWORD num_vals
,
773 LPWSTR lpValueBuf
, LPDWORD ldwTotsize
)
776 DWORD maxBytes
= *ldwTotsize
;
778 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
781 TRACE("(%p,%p,%d,%p,%p=%d)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
783 for(i
=0; i
< num_vals
; ++i
)
785 val_list
[i
].ve_valuelen
=0;
786 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
787 if(status
!= ERROR_SUCCESS
)
792 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
794 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
795 (LPBYTE
)bufptr
, &val_list
[i
].ve_valuelen
);
796 if(status
!= ERROR_SUCCESS
)
801 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
803 bufptr
+= val_list
[i
].ve_valuelen
;
806 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
808 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
811 /******************************************************************************
812 * RegQueryInfoKeyA [ADVAPI32.@]
814 * Retrieves information about a registry key.
817 * hKey [I] Handle to an open key.
818 * lpClass [O] Class string of the key.
819 * lpcClass [I/O] size of lpClass.
820 * lpReserved [I] Reserved; must be NULL.
821 * lpcSubKeys [O] Number of subkeys contained by the key.
822 * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name.
823 * lpcMaxClassLen [O] Size of the longest string specifying a subkey
825 * lpcValues [O] Number of values associated with the key.
826 * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS.
827 * lpcMaxValueLen [O] Longest data component among the key's values
828 * lpcbSecurityDescriptor [O] Size of the key's security descriptor.
829 * lpftLastWriteTime [O] FILETIME structure that is the last write time.
832 * Success: ERROR_SUCCESS
833 * Failure: nonzero error code from Winerror.h
835 LSTATUS WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
836 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
837 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
838 LPDWORD security
, FILETIME
*modif
)
841 char buffer
[256], *buf_ptr
= buffer
;
842 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
843 DWORD total_size
, len
;
845 TRACE( "(%p,%p,%d,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
846 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
848 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
849 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
851 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
852 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
854 if (class || class_len
)
856 /* retry with a dynamically allocated buffer */
857 while (status
== STATUS_BUFFER_OVERFLOW
)
859 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
860 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
861 return ERROR_NOT_ENOUGH_MEMORY
;
862 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
863 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
866 if (status
) goto done
;
868 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
), info
->ClassLength
);
871 if (len
+ 1 > *class_len
) status
= STATUS_BUFFER_OVERFLOW
;
874 if (class && !status
)
876 RtlUnicodeToMultiByteN( class, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
881 else status
= STATUS_SUCCESS
;
883 if (subkeys
) *subkeys
= info
->SubKeys
;
884 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
885 if (max_class
) *max_class
= info
->MaxClassLen
;
886 if (values
) *values
= info
->Values
;
887 if (max_value
) *max_value
= info
->MaxValueNameLen
;
888 if (max_data
) *max_data
= info
->MaxValueDataLen
;
889 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
892 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
893 return RtlNtStatusToDosError( status
);
897 /******************************************************************************
898 * RegCloseKey [ADVAPI32.@]
900 * Close an open registry key.
903 * hkey [I] Handle of key to close
906 * Success: ERROR_SUCCESS
907 * Failure: Error code
909 LSTATUS WINAPI
RegCloseKey( HKEY hkey
)
911 if (!hkey
) return ERROR_INVALID_HANDLE
;
912 if (hkey
>= (HKEY
)0x80000000) return ERROR_SUCCESS
;
913 return RtlNtStatusToDosError( NtClose( hkey
) );
917 /******************************************************************************
918 * RegDeleteKeyW [ADVAPI32.@]
922 LSTATUS WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
927 if (!name
) return ERROR_INVALID_PARAMETER
;
929 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
931 if (!(ret
= RegOpenKeyExW( hkey
, name
, 0, DELETE
, &tmp
)))
933 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
936 TRACE("%s ret=%08x\n", debugstr_w(name
), ret
);
941 /******************************************************************************
942 * RegDeleteKeyA [ADVAPI32.@]
944 * Delete a registry key.
947 * hkey [I] Handle to parent key containing the key to delete
948 * name [I] Name of the key user hkey to delete
952 * MSDN is wrong when it says that hkey must be opened with the DELETE access
953 * right. In reality, it opens a new handle with DELETE access.
956 * Success: ERROR_SUCCESS
957 * Failure: Error code
959 LSTATUS WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
964 if (!name
) return ERROR_INVALID_PARAMETER
;
966 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
968 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, DELETE
, &tmp
)))
970 if (!is_version_nt()) /* win95 does recursive key deletes */
974 while(!RegEnumKeyA(tmp
, 0, name
, sizeof(name
)))
976 if(RegDeleteKeyA(tmp
, name
)) /* recurse */
980 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
983 TRACE("%s ret=%08x\n", debugstr_a(name
), ret
);
989 /******************************************************************************
990 * RegSetValueExW [ADVAPI32.@]
992 * Set the data and contents of a registry value.
995 * hkey [I] Handle of key to set value for
996 * name [I] Name of value to set
997 * reserved [I] Reserved, must be zero
998 * type [I] Type of the value being set
999 * data [I] The new contents of the value to set
1000 * count [I] Size of data
1003 * Success: ERROR_SUCCESS
1004 * Failure: Error code
1006 LSTATUS WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
1007 DWORD type
, CONST BYTE
*data
, DWORD count
)
1009 UNICODE_STRING nameW
;
1011 /* no need for version check, not implemented on win9x anyway */
1012 if (count
&& is_string(type
))
1014 LPCWSTR str
= (LPCWSTR
)data
;
1015 /* if user forgot to count terminating null, add it (yes NT does this) */
1016 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
1017 count
+= sizeof(WCHAR
);
1019 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1021 RtlInitUnicodeString( &nameW
, name
);
1022 return RtlNtStatusToDosError( NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
) );
1026 /******************************************************************************
1027 * RegSetValueExA [ADVAPI32.@]
1029 * See RegSetValueExW.
1032 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
1033 * NT does definitely care (aj)
1035 LSTATUS WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
1036 CONST BYTE
*data
, DWORD count
)
1039 WCHAR
*dataW
= NULL
;
1042 if (!is_version_nt()) /* win95 */
1046 if (!data
) return ERROR_INVALID_PARAMETER
;
1047 count
= strlen((const char *)data
) + 1;
1050 else if (count
&& is_string(type
))
1052 /* if user forgot to count terminating null, add it (yes NT does this) */
1053 if (data
[count
-1] && !data
[count
]) count
++;
1056 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1058 if (is_string( type
)) /* need to convert to Unicode */
1061 RtlMultiByteToUnicodeSize( &lenW
, (const char *)data
, count
);
1062 if (!(dataW
= HeapAlloc( GetProcessHeap(), 0, lenW
))) return ERROR_OUTOFMEMORY
;
1063 RtlMultiByteToUnicodeN( dataW
, lenW
, NULL
, (const char *)data
, count
);
1065 data
= (BYTE
*)dataW
;
1068 RtlInitAnsiString( &nameA
, name
);
1069 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1072 status
= NtSetValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
, 0, type
, data
, count
);
1074 HeapFree( GetProcessHeap(), 0, dataW
);
1075 return RtlNtStatusToDosError( status
);
1079 /******************************************************************************
1080 * RegSetValueW [ADVAPI32.@]
1082 * Sets the data for the default or unnamed value of a reg key.
1085 * hKey [I] Handle to an open key.
1086 * lpSubKey [I] Name of a subkey of hKey.
1087 * dwType [I] Type of information to store.
1088 * lpData [I] String that contains the data to set for the default value.
1089 * cbData [I] Ignored.
1092 * Success: ERROR_SUCCESS
1093 * Failure: nonzero error code from Winerror.h
1095 LSTATUS WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
1100 TRACE("(%p,%s,%d,%s,%d)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
1102 if (type
!= REG_SZ
|| !data
) return ERROR_INVALID_PARAMETER
;
1104 if (name
&& name
[0]) /* need to create the subkey */
1106 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1109 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)data
,
1110 (strlenW( data
) + 1) * sizeof(WCHAR
) );
1111 if (subkey
!= hkey
) RegCloseKey( subkey
);
1116 /******************************************************************************
1117 * RegSetValueA [ADVAPI32.@]
1121 LSTATUS WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
1126 TRACE("(%p,%s,%d,%s,%d)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
1128 if (type
!= REG_SZ
|| !data
) return ERROR_INVALID_PARAMETER
;
1130 if (name
&& name
[0]) /* need to create the subkey */
1132 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1134 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)data
, strlen(data
)+1 );
1135 if (subkey
!= hkey
) RegCloseKey( subkey
);
1141 /******************************************************************************
1142 * RegQueryValueExW [ADVAPI32.@]
1144 * See RegQueryValueExA.
1146 LSTATUS WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
1147 LPBYTE data
, LPDWORD count
)
1150 UNICODE_STRING name_str
;
1152 char buffer
[256], *buf_ptr
= buffer
;
1153 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1154 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1156 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
1157 hkey
, debugstr_w(name
), reserved
, type
, data
, count
,
1158 (count
&& data
) ? *count
: 0 );
1160 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1161 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1163 RtlInitUnicodeString( &name_str
, name
);
1165 if (data
) total_size
= min( sizeof(buffer
), *count
+ info_size
);
1168 total_size
= info_size
;
1169 if (count
) *count
= 0;
1172 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1173 buffer
, total_size
, &total_size
);
1174 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1178 /* retry with a dynamically allocated buffer */
1179 while (status
== STATUS_BUFFER_OVERFLOW
&& total_size
- info_size
<= *count
)
1181 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1182 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1183 return ERROR_NOT_ENOUGH_MEMORY
;
1184 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1185 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1186 buf_ptr
, total_size
, &total_size
);
1191 memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1192 /* if the type is REG_SZ and data is not 0-terminated
1193 * and there is enough space in the buffer NT appends a \0 */
1194 if (total_size
- info_size
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1196 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info_size
);
1197 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1200 else if (status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1202 else status
= STATUS_SUCCESS
;
1204 if (type
) *type
= info
->Type
;
1205 if (count
) *count
= total_size
- info_size
;
1208 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1209 return RtlNtStatusToDosError(status
);
1213 /******************************************************************************
1214 * RegQueryValueExA [ADVAPI32.@]
1216 * Get the type and contents of a specified value under with a key.
1219 * hkey [I] Handle of the key to query
1220 * name [I] Name of value under hkey to query
1221 * reserved [I] Reserved - must be NULL
1222 * type [O] Destination for the value type, or NULL if not required
1223 * data [O] Destination for the values contents, or NULL if not required
1224 * count [I/O] Size of data, updated with the number of bytes returned
1227 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
1228 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
1229 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
1230 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
1233 * MSDN states that if data is too small it is partially filled. In reality
1234 * it remains untouched.
1236 LSTATUS WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
1237 LPBYTE data
, LPDWORD count
)
1241 DWORD total_size
, datalen
= 0;
1242 char buffer
[256], *buf_ptr
= buffer
;
1243 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1244 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1246 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
1247 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
1249 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1250 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1252 if (count
) datalen
= *count
;
1253 if (!data
&& count
) *count
= 0;
1255 /* this matches Win9x behaviour - NT sets *type to a random value */
1256 if (type
) *type
= REG_NONE
;
1258 RtlInitAnsiString( &nameA
, name
);
1259 if ((status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1261 return RtlNtStatusToDosError(status
);
1263 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1264 KeyValuePartialInformation
, buffer
, sizeof(buffer
), &total_size
);
1265 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1267 /* we need to fetch the contents for a string type even if not requested,
1268 * because we need to compute the length of the ASCII string. */
1269 if (data
|| is_string(info
->Type
))
1271 /* retry with a dynamically allocated buffer */
1272 while (status
== STATUS_BUFFER_OVERFLOW
)
1274 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1275 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1277 status
= STATUS_NO_MEMORY
;
1280 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1281 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1282 KeyValuePartialInformation
, buf_ptr
, total_size
, &total_size
);
1285 if (status
) goto done
;
1287 if (is_string(info
->Type
))
1291 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info_size
),
1292 total_size
- info_size
);
1295 if (len
> datalen
) status
= STATUS_BUFFER_OVERFLOW
;
1298 RtlUnicodeToMultiByteN( (char*)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info_size
),
1299 total_size
- info_size
);
1300 /* if the type is REG_SZ and data is not 0-terminated
1301 * and there is enough space in the buffer NT appends a \0 */
1302 if (len
< datalen
&& data
[len
-1]) data
[len
] = 0;
1305 total_size
= len
+ info_size
;
1309 if (total_size
- info_size
> datalen
) status
= STATUS_BUFFER_OVERFLOW
;
1310 else memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1313 else status
= STATUS_SUCCESS
;
1315 if (type
) *type
= info
->Type
;
1316 if (count
) *count
= total_size
- info_size
;
1319 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1320 return RtlNtStatusToDosError(status
);
1324 /******************************************************************************
1325 * RegQueryValueW [ADVAPI32.@]
1327 * Retrieves the data associated with the default or unnamed value of a key.
1330 * hkey [I] Handle to an open key.
1331 * name [I] Name of the subkey of hKey.
1332 * data [O] Receives the string associated with the default value
1334 * count [I/O] Size of lpValue in bytes.
1337 * Success: ERROR_SUCCESS
1338 * Failure: nonzero error code from Winerror.h
1340 LSTATUS WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
1345 TRACE("(%p,%s,%p,%d)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
1347 if (name
&& name
[0])
1349 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1351 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, (LPDWORD
)count
);
1352 if (subkey
!= hkey
) RegCloseKey( subkey
);
1353 if (ret
== ERROR_FILE_NOT_FOUND
)
1355 /* return empty string if default value not found */
1356 if (data
) *data
= 0;
1357 if (count
) *count
= sizeof(WCHAR
);
1358 ret
= ERROR_SUCCESS
;
1364 /******************************************************************************
1365 * RegQueryValueA [ADVAPI32.@]
1367 * See RegQueryValueW.
1369 LSTATUS WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
1374 TRACE("(%p,%s,%p,%d)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
1376 if (name
&& name
[0])
1378 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1380 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, (LPDWORD
)count
);
1381 if (subkey
!= hkey
) RegCloseKey( subkey
);
1382 if (ret
== ERROR_FILE_NOT_FOUND
)
1384 /* return empty string if default value not found */
1385 if (data
) *data
= 0;
1386 if (count
) *count
= 1;
1387 ret
= ERROR_SUCCESS
;
1393 /******************************************************************************
1394 * ADVAPI_ApplyRestrictions [internal]
1396 * Helper function for RegGetValueA/W.
1398 static VOID
ADVAPI_ApplyRestrictions( DWORD dwFlags
, DWORD dwType
,
1399 DWORD cbData
, PLONG ret
)
1401 /* Check if the type is restricted by the passed flags */
1402 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
1408 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
1409 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
1410 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
1411 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
1412 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
1413 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
1414 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
1417 if (dwFlags
& dwMask
)
1419 /* Type is not restricted, check for size mismatch */
1420 if (dwType
== REG_BINARY
)
1424 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
1426 else if ((dwFlags
& RRF_RT_QWORD
) == RRF_RT_QWORD
)
1429 if (cbExpect
&& cbData
!= cbExpect
)
1430 *ret
= ERROR_DATATYPE_MISMATCH
;
1433 else *ret
= ERROR_UNSUPPORTED_TYPE
;
1438 /******************************************************************************
1439 * RegGetValueW [ADVAPI32.@]
1441 * Retrieves the type and data for a value name associated with a key,
1442 * optionally expanding its content and restricting its type.
1445 * hKey [I] Handle to an open key.
1446 * pszSubKey [I] Name of the subkey of hKey.
1447 * pszValue [I] Name of value under hKey/szSubKey to query.
1448 * dwFlags [I] Flags restricting the value type to retrieve.
1449 * pdwType [O] Destination for the values type, may be NULL.
1450 * pvData [O] Destination for the values content, may be NULL.
1451 * pcbData [I/O] Size of pvData, updated with the size in bytes required to
1452 * retrieve the whole content, including the trailing '\0'
1456 * Success: ERROR_SUCCESS
1457 * Failure: nonzero error code from Winerror.h
1460 * - Unless RRF_NOEXPAND is specified, REG_EXPAND_SZ values are automatically
1461 * expanded and pdwType is set to REG_SZ instead.
1462 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1463 * without RRF_NOEXPAND is thus not allowed.
1464 * An exception is the case where RRF_RT_ANY is specified, because then
1465 * RRF_NOEXPAND is allowed.
1467 LSTATUS WINAPI
RegGetValueW( HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
,
1468 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
1471 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
1475 TRACE("(%p,%s,%s,%d,%p,%p,%p=%d)\n",
1476 hKey
, debugstr_w(pszSubKey
), debugstr_w(pszValue
), dwFlags
, pdwType
,
1477 pvData
, pcbData
, cbData
);
1479 if (pvData
&& !pcbData
)
1480 return ERROR_INVALID_PARAMETER
;
1481 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
) &&
1482 ((dwFlags
& RRF_RT_ANY
) != RRF_RT_ANY
))
1483 return ERROR_INVALID_PARAMETER
;
1485 if (pszSubKey
&& pszSubKey
[0])
1487 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1488 if (ret
!= ERROR_SUCCESS
) return ret
;
1491 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
1493 /* If we are going to expand we need to read in the whole the value even
1494 * if the passed buffer was too small as the expanded string might be
1495 * smaller than the unexpanded one and could fit into cbData bytes. */
1496 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
1497 dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
))
1500 HeapFree(GetProcessHeap(), 0, pvBuf
);
1502 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
1505 ret
= ERROR_NOT_ENOUGH_MEMORY
;
1509 if (ret
== ERROR_MORE_DATA
|| !pvData
)
1510 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
1511 &dwType
, pvBuf
, &cbData
);
1514 /* Even if cbData was large enough we have to copy the
1515 * string since ExpandEnvironmentStrings can't handle
1516 * overlapping buffers. */
1517 CopyMemory(pvBuf
, pvData
, cbData
);
1520 /* Both the type or the value itself could have been modified in
1521 * between so we have to keep retrying until the buffer is large
1522 * enough or we no longer have to expand the value. */
1523 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
1525 if (ret
== ERROR_SUCCESS
)
1527 /* Recheck dwType in case it changed since the first call */
1528 if (dwType
== REG_EXPAND_SZ
)
1530 cbData
= ExpandEnvironmentStringsW(pvBuf
, pvData
,
1531 pcbData
? *pcbData
: 0) * sizeof(WCHAR
);
1533 if(pvData
&& pcbData
&& cbData
> *pcbData
)
1534 ret
= ERROR_MORE_DATA
;
1537 CopyMemory(pvData
, pvBuf
, *pcbData
);
1540 HeapFree(GetProcessHeap(), 0, pvBuf
);
1543 if (pszSubKey
&& pszSubKey
[0])
1546 ADVAPI_ApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
1548 if (pvData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
1549 ZeroMemory(pvData
, *pcbData
);
1551 if (pdwType
) *pdwType
= dwType
;
1552 if (pcbData
) *pcbData
= cbData
;
1558 /******************************************************************************
1559 * RegGetValueA [ADVAPI32.@]
1563 LSTATUS WINAPI
RegGetValueA( HKEY hKey
, LPCSTR pszSubKey
, LPCSTR pszValue
,
1564 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
1567 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
1571 TRACE("(%p,%s,%s,%d,%p,%p,%p=%d)\n",
1572 hKey
, pszSubKey
, pszValue
, dwFlags
, pdwType
, pvData
, pcbData
,
1575 if (pvData
&& !pcbData
)
1576 return ERROR_INVALID_PARAMETER
;
1577 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
) &&
1578 ((dwFlags
& RRF_RT_ANY
) != RRF_RT_ANY
))
1579 return ERROR_INVALID_PARAMETER
;
1581 if (pszSubKey
&& pszSubKey
[0])
1583 ret
= RegOpenKeyExA(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1584 if (ret
!= ERROR_SUCCESS
) return ret
;
1587 ret
= RegQueryValueExA(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
1589 /* If we are going to expand we need to read in the whole the value even
1590 * if the passed buffer was too small as the expanded string might be
1591 * smaller than the unexpanded one and could fit into cbData bytes. */
1592 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
1593 dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
))
1596 HeapFree(GetProcessHeap(), 0, pvBuf
);
1598 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
1601 ret
= ERROR_NOT_ENOUGH_MEMORY
;
1605 if (ret
== ERROR_MORE_DATA
|| !pvData
)
1606 ret
= RegQueryValueExA(hKey
, pszValue
, NULL
,
1607 &dwType
, pvBuf
, &cbData
);
1610 /* Even if cbData was large enough we have to copy the
1611 * string since ExpandEnvironmentStrings can't handle
1612 * overlapping buffers. */
1613 CopyMemory(pvBuf
, pvData
, cbData
);
1616 /* Both the type or the value itself could have been modified in
1617 * between so we have to keep retrying until the buffer is large
1618 * enough or we no longer have to expand the value. */
1619 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
1621 if (ret
== ERROR_SUCCESS
)
1623 /* Recheck dwType in case it changed since the first call */
1624 if (dwType
== REG_EXPAND_SZ
)
1626 cbData
= ExpandEnvironmentStringsA(pvBuf
, pvData
,
1627 pcbData
? *pcbData
: 0);
1629 if(pvData
&& pcbData
&& cbData
> *pcbData
)
1630 ret
= ERROR_MORE_DATA
;
1633 CopyMemory(pvData
, pvBuf
, *pcbData
);
1636 HeapFree(GetProcessHeap(), 0, pvBuf
);
1639 if (pszSubKey
&& pszSubKey
[0])
1642 ADVAPI_ApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
1644 if (pvData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
1645 ZeroMemory(pvData
, *pcbData
);
1647 if (pdwType
) *pdwType
= dwType
;
1648 if (pcbData
) *pcbData
= cbData
;
1654 /******************************************************************************
1655 * RegEnumValueW [ADVAPI32.@]
1657 * Enumerates the values for the specified open registry key.
1660 * hkey [I] Handle to key to query
1661 * index [I] Index of value to query
1662 * value [O] Value string
1663 * val_count [I/O] Size of value buffer (in wchars)
1664 * reserved [I] Reserved
1665 * type [O] Type code
1666 * data [O] Value data
1667 * count [I/O] Size of data buffer (in bytes)
1670 * Success: ERROR_SUCCESS
1671 * Failure: nonzero error code from Winerror.h
1674 LSTATUS WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
1675 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1679 char buffer
[256], *buf_ptr
= buffer
;
1680 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1681 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1683 TRACE("(%p,%d,%p,%p,%p,%p,%p,%p)\n",
1684 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1686 /* NT only checks count, not val_count */
1687 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1688 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1690 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1691 if (data
) total_size
+= *count
;
1692 total_size
= min( sizeof(buffer
), total_size
);
1694 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1695 buffer
, total_size
, &total_size
);
1696 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1700 /* retry with a dynamically allocated buffer */
1701 while (status
== STATUS_BUFFER_OVERFLOW
)
1703 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1704 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1705 return ERROR_NOT_ENOUGH_MEMORY
;
1706 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1707 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1708 buf_ptr
, total_size
, &total_size
);
1711 if (status
) goto done
;
1715 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1717 status
= STATUS_BUFFER_OVERFLOW
;
1720 memcpy( value
, info
->Name
, info
->NameLength
);
1721 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1722 value
[*val_count
] = 0;
1727 if (total_size
- info
->DataOffset
> *count
)
1729 status
= STATUS_BUFFER_OVERFLOW
;
1732 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1733 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1735 /* if the type is REG_SZ and data is not 0-terminated
1736 * and there is enough space in the buffer NT appends a \0 */
1737 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1738 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1742 else status
= STATUS_SUCCESS
;
1745 if (type
) *type
= info
->Type
;
1746 if (count
) *count
= info
->DataLength
;
1749 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1750 return RtlNtStatusToDosError(status
);
1754 /******************************************************************************
1755 * RegEnumValueA [ADVAPI32.@]
1757 * See RegEnumValueW.
1759 LSTATUS WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1760 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1764 char buffer
[256], *buf_ptr
= buffer
;
1765 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1766 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1768 TRACE("(%p,%d,%p,%p,%p,%p,%p,%p)\n",
1769 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1771 /* NT only checks count, not val_count */
1772 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1773 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1775 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1776 if (data
) total_size
+= *count
;
1777 total_size
= min( sizeof(buffer
), total_size
);
1779 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1780 buffer
, total_size
, &total_size
);
1781 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1783 /* we need to fetch the contents for a string type even if not requested,
1784 * because we need to compute the length of the ASCII string. */
1785 if (value
|| data
|| is_string(info
->Type
))
1787 /* retry with a dynamically allocated buffer */
1788 while (status
== STATUS_BUFFER_OVERFLOW
)
1790 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1791 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1792 return ERROR_NOT_ENOUGH_MEMORY
;
1793 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1794 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1795 buf_ptr
, total_size
, &total_size
);
1798 if (status
) goto done
;
1800 if (is_string(info
->Type
))
1803 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1804 total_size
- info
->DataOffset
);
1807 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1810 RtlUnicodeToMultiByteN( (char*)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1811 total_size
- info
->DataOffset
);
1812 /* if the type is REG_SZ and data is not 0-terminated
1813 * and there is enough space in the buffer NT appends a \0 */
1814 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1817 info
->DataLength
= len
;
1821 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1822 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1825 if (value
&& !status
)
1829 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1830 if (len
>= *val_count
)
1832 status
= STATUS_BUFFER_OVERFLOW
;
1835 len
= *val_count
- 1;
1836 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1842 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1848 else status
= STATUS_SUCCESS
;
1850 if (type
) *type
= info
->Type
;
1851 if (count
) *count
= info
->DataLength
;
1854 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1855 return RtlNtStatusToDosError(status
);
1860 /******************************************************************************
1861 * RegDeleteValueW [ADVAPI32.@]
1863 * See RegDeleteValueA.
1865 LSTATUS WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1867 UNICODE_STRING nameW
;
1869 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1871 RtlInitUnicodeString( &nameW
, name
);
1872 return RtlNtStatusToDosError( NtDeleteValueKey( hkey
, &nameW
) );
1876 /******************************************************************************
1877 * RegDeleteValueA [ADVAPI32.@]
1879 * Delete a value from the registry.
1882 * hkey [I] Registry handle of the key holding the value
1883 * name [I] Name of the value under hkey to delete
1886 * Success: ERROR_SUCCESS
1887 * Failure: nonzero error code from Winerror.h
1889 LSTATUS WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1894 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1896 RtlInitAnsiString( &nameA
, name
);
1897 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1899 status
= NtDeleteValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
);
1900 return RtlNtStatusToDosError( status
);
1904 /******************************************************************************
1905 * RegLoadKeyW [ADVAPI32.@]
1907 * Create a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and store
1908 * registration information from a specified file into that subkey.
1911 * hkey [I] Handle of open key
1912 * subkey [I] Address of name of subkey
1913 * filename [I] Address of filename for registry information
1916 * Success: ERROR_SUCCESS
1917 * Failure: nonzero error code from Winerror.h
1919 LSTATUS WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1921 OBJECT_ATTRIBUTES destkey
, file
;
1922 UNICODE_STRING subkeyW
, filenameW
;
1925 if (!(hkey
= get_special_root_hkey(hkey
))) return ERROR_INVALID_HANDLE
;
1927 destkey
.Length
= sizeof(destkey
);
1928 destkey
.RootDirectory
= hkey
; /* root key: HKLM or HKU */
1929 destkey
.ObjectName
= &subkeyW
; /* name of the key */
1930 destkey
.Attributes
= 0;
1931 destkey
.SecurityDescriptor
= NULL
;
1932 destkey
.SecurityQualityOfService
= NULL
;
1933 RtlInitUnicodeString(&subkeyW
, subkey
);
1935 file
.Length
= sizeof(file
);
1936 file
.RootDirectory
= NULL
;
1937 file
.ObjectName
= &filenameW
; /* file containing the hive */
1938 file
.Attributes
= OBJ_CASE_INSENSITIVE
;
1939 file
.SecurityDescriptor
= NULL
;
1940 file
.SecurityQualityOfService
= NULL
;
1941 RtlDosPathNameToNtPathName_U(filename
, &filenameW
, NULL
, NULL
);
1943 status
= NtLoadKey(&destkey
, &file
);
1944 RtlFreeUnicodeString(&filenameW
);
1945 return RtlNtStatusToDosError( status
);
1949 /******************************************************************************
1950 * RegLoadKeyA [ADVAPI32.@]
1954 LSTATUS WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1956 UNICODE_STRING subkeyW
, filenameW
;
1957 STRING subkeyA
, filenameA
;
1961 RtlInitAnsiString(&subkeyA
, subkey
);
1962 RtlInitAnsiString(&filenameA
, filename
);
1964 RtlInitUnicodeString(&subkeyW
, NULL
);
1965 RtlInitUnicodeString(&filenameW
, NULL
);
1966 if (!(status
= RtlAnsiStringToUnicodeString(&subkeyW
, &subkeyA
, TRUE
)) &&
1967 !(status
= RtlAnsiStringToUnicodeString(&filenameW
, &filenameA
, TRUE
)))
1969 ret
= RegLoadKeyW(hkey
, subkeyW
.Buffer
, filenameW
.Buffer
);
1971 else ret
= RtlNtStatusToDosError(status
);
1972 RtlFreeUnicodeString(&subkeyW
);
1973 RtlFreeUnicodeString(&filenameW
);
1978 /******************************************************************************
1979 * RegSaveKeyW [ADVAPI32.@]
1981 * Save a key and all of its subkeys and values to a new file in the standard format.
1984 * hkey [I] Handle of key where save begins
1985 * lpFile [I] Address of filename to save to
1986 * sa [I] Address of security structure
1989 * Success: ERROR_SUCCESS
1990 * Failure: nonzero error code from Winerror.h
1992 LSTATUS WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1994 static const WCHAR format
[] =
1995 {'r','e','g','%','0','4','x','.','t','m','p',0};
1996 WCHAR buffer
[MAX_PATH
];
2002 TRACE( "(%p,%s,%p)\n", hkey
, debugstr_w(file
), sa
);
2004 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
2005 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
2007 err
= GetLastError();
2008 GetFullPathNameW( file
, sizeof(buffer
)/sizeof(WCHAR
), buffer
, &nameW
);
2012 snprintfW( nameW
, 16, format
, count
++ );
2013 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
,
2014 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
2015 if (handle
!= INVALID_HANDLE_VALUE
) break;
2016 if ((ret
= GetLastError()) != ERROR_FILE_EXISTS
) goto done
;
2018 /* Something gone haywire ? Please report if this happens abnormally */
2020 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", debugstr_w(buffer
), count
);
2023 ret
= RtlNtStatusToDosError(NtSaveKey(hkey
, handle
));
2025 CloseHandle( handle
);
2028 if (!MoveFileExW( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
2030 ERR( "Failed to move %s to %s\n", debugstr_w(buffer
),
2032 ret
= GetLastError();
2035 if (ret
) DeleteFileW( buffer
);
2038 SetLastError( err
); /* restore last error code */
2043 /******************************************************************************
2044 * RegSaveKeyA [ADVAPI32.@]
2048 LSTATUS WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
2050 UNICODE_STRING
*fileW
= &NtCurrentTeb()->StaticUnicodeString
;
2054 RtlInitAnsiString(&fileA
, file
);
2055 if ((status
= RtlAnsiStringToUnicodeString(fileW
, &fileA
, FALSE
)))
2056 return RtlNtStatusToDosError( status
);
2057 return RegSaveKeyW(hkey
, fileW
->Buffer
, sa
);
2061 /******************************************************************************
2062 * RegRestoreKeyW [ADVAPI32.@]
2064 * Read the registry information from a file and copy it over a key.
2067 * hkey [I] Handle of key where restore begins
2068 * lpFile [I] Address of filename containing saved tree
2069 * dwFlags [I] Optional flags
2072 * Success: ERROR_SUCCESS
2073 * Failure: nonzero error code from Winerror.h
2075 LSTATUS WINAPI
RegRestoreKeyW( HKEY hkey
, LPCWSTR lpFile
, DWORD dwFlags
)
2077 TRACE("(%p,%s,%d)\n",hkey
,debugstr_w(lpFile
),dwFlags
);
2079 /* It seems to do this check before the hkey check */
2080 if (!lpFile
|| !*lpFile
)
2081 return ERROR_INVALID_PARAMETER
;
2083 FIXME("(%p,%s,%d): stub\n",hkey
,debugstr_w(lpFile
),dwFlags
);
2085 /* Check for file existence */
2087 return ERROR_SUCCESS
;
2091 /******************************************************************************
2092 * RegRestoreKeyA [ADVAPI32.@]
2094 * See RegRestoreKeyW.
2096 LSTATUS WINAPI
RegRestoreKeyA( HKEY hkey
, LPCSTR lpFile
, DWORD dwFlags
)
2098 UNICODE_STRING lpFileW
;
2101 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, lpFile
);
2102 ret
= RegRestoreKeyW( hkey
, lpFileW
.Buffer
, dwFlags
);
2103 RtlFreeUnicodeString( &lpFileW
);
2108 /******************************************************************************
2109 * RegUnLoadKeyW [ADVAPI32.@]
2111 * Unload a registry key and its subkeys from the registry.
2114 * hkey [I] Handle of open key
2115 * lpSubKey [I] Address of name of subkey to unload
2118 * Success: ERROR_SUCCESS
2119 * Failure: nonzero error code from Winerror.h
2121 LSTATUS WINAPI
RegUnLoadKeyW( HKEY hkey
, LPCWSTR lpSubKey
)
2125 OBJECT_ATTRIBUTES attr
;
2126 UNICODE_STRING subkey
;
2128 TRACE("(%p,%s)\n",hkey
, debugstr_w(lpSubKey
));
2130 ret
= RegOpenKeyW(hkey
,lpSubKey
,&shkey
);
2132 return ERROR_INVALID_PARAMETER
;
2134 RtlInitUnicodeString(&subkey
, lpSubKey
);
2135 InitializeObjectAttributes(&attr
, &subkey
, OBJ_CASE_INSENSITIVE
, shkey
, NULL
);
2136 ret
= RtlNtStatusToDosError(NtUnloadKey(&attr
));
2144 /******************************************************************************
2145 * RegUnLoadKeyA [ADVAPI32.@]
2147 * See RegUnLoadKeyW.
2149 LSTATUS WINAPI
RegUnLoadKeyA( HKEY hkey
, LPCSTR lpSubKey
)
2151 UNICODE_STRING lpSubKeyW
;
2154 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
2155 ret
= RegUnLoadKeyW( hkey
, lpSubKeyW
.Buffer
);
2156 RtlFreeUnicodeString( &lpSubKeyW
);
2161 /******************************************************************************
2162 * RegReplaceKeyW [ADVAPI32.@]
2164 * Replace the file backing a registry key and all its subkeys with another file.
2167 * hkey [I] Handle of open key
2168 * lpSubKey [I] Address of name of subkey
2169 * lpNewFile [I] Address of filename for file with new data
2170 * lpOldFile [I] Address of filename for backup file
2173 * Success: ERROR_SUCCESS
2174 * Failure: nonzero error code from Winerror.h
2176 LSTATUS WINAPI
RegReplaceKeyW( HKEY hkey
, LPCWSTR lpSubKey
, LPCWSTR lpNewFile
,
2179 FIXME("(%p,%s,%s,%s): stub\n", hkey
, debugstr_w(lpSubKey
),
2180 debugstr_w(lpNewFile
),debugstr_w(lpOldFile
));
2181 return ERROR_SUCCESS
;
2185 /******************************************************************************
2186 * RegReplaceKeyA [ADVAPI32.@]
2188 * See RegReplaceKeyW.
2190 LSTATUS WINAPI
RegReplaceKeyA( HKEY hkey
, LPCSTR lpSubKey
, LPCSTR lpNewFile
,
2193 UNICODE_STRING lpSubKeyW
;
2194 UNICODE_STRING lpNewFileW
;
2195 UNICODE_STRING lpOldFileW
;
2198 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
2199 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, lpOldFile
);
2200 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, lpNewFile
);
2201 ret
= RegReplaceKeyW( hkey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
2202 RtlFreeUnicodeString( &lpOldFileW
);
2203 RtlFreeUnicodeString( &lpNewFileW
);
2204 RtlFreeUnicodeString( &lpSubKeyW
);
2209 /******************************************************************************
2210 * RegSetKeySecurity [ADVAPI32.@]
2212 * Set the security of an open registry key.
2215 * hkey [I] Open handle of key to set
2216 * SecurityInfo [I] Descriptor contents
2217 * pSecurityDesc [I] Address of descriptor for key
2220 * Success: ERROR_SUCCESS
2221 * Failure: nonzero error code from Winerror.h
2223 LSTATUS WINAPI
RegSetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInfo
,
2224 PSECURITY_DESCRIPTOR pSecurityDesc
)
2226 TRACE("(%p,%d,%p)\n",hkey
,SecurityInfo
,pSecurityDesc
);
2228 /* It seems to perform this check before the hkey check */
2229 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) ||
2230 (SecurityInfo
& GROUP_SECURITY_INFORMATION
) ||
2231 (SecurityInfo
& DACL_SECURITY_INFORMATION
) ||
2232 (SecurityInfo
& SACL_SECURITY_INFORMATION
)) {
2235 return ERROR_INVALID_PARAMETER
;
2238 return ERROR_INVALID_PARAMETER
;
2240 FIXME(":(%p,%d,%p): stub\n",hkey
,SecurityInfo
,pSecurityDesc
);
2242 return ERROR_SUCCESS
;
2246 /******************************************************************************
2247 * RegGetKeySecurity [ADVAPI32.@]
2249 * Get a copy of the security descriptor for a given registry key.
2252 * hkey [I] Open handle of key to set
2253 * SecurityInformation [I] Descriptor contents
2254 * pSecurityDescriptor [O] Address of descriptor for key
2255 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
2258 * Success: ERROR_SUCCESS
2259 * Failure: Error code
2261 LSTATUS WINAPI
RegGetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInformation
,
2262 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
2263 LPDWORD lpcbSecurityDescriptor
)
2265 TRACE("(%p,%d,%p,%d)\n",hkey
,SecurityInformation
,pSecurityDescriptor
,
2266 *lpcbSecurityDescriptor
);
2268 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
2270 return RtlNtStatusToDosError( NtQuerySecurityObject( hkey
,
2271 SecurityInformation
, pSecurityDescriptor
,
2272 *lpcbSecurityDescriptor
, lpcbSecurityDescriptor
) );
2276 /******************************************************************************
2277 * RegFlushKey [ADVAPI32.@]
2279 * Immediately write a registry key to registry.
2282 * hkey [I] Handle of key to write
2285 * Success: ERROR_SUCCESS
2286 * Failure: Error code
2288 LSTATUS WINAPI
RegFlushKey( HKEY hkey
)
2290 hkey
= get_special_root_hkey( hkey
);
2291 if (!hkey
) return ERROR_INVALID_HANDLE
;
2293 return RtlNtStatusToDosError( NtFlushKey( hkey
) );
2297 /******************************************************************************
2298 * RegConnectRegistryW [ADVAPI32.@]
2300 * Establish a connection to a predefined registry key on another computer.
2303 * lpMachineName [I] Address of name of remote computer
2304 * hHey [I] Predefined registry handle
2305 * phkResult [I] Address of buffer for remote registry handle
2308 * Success: ERROR_SUCCESS
2309 * Failure: nonzero error code from Winerror.h
2311 LSTATUS WINAPI
RegConnectRegistryW( LPCWSTR lpMachineName
, HKEY hKey
,
2316 TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName
),hKey
,phkResult
);
2318 if (!lpMachineName
|| !*lpMachineName
) {
2319 /* Use the local machine name */
2320 ret
= RegOpenKeyW( hKey
, NULL
, phkResult
);
2323 WCHAR compName
[MAX_COMPUTERNAME_LENGTH
+ 1];
2324 DWORD len
= sizeof(compName
) / sizeof(WCHAR
);
2326 /* MSDN says lpMachineName must start with \\ : not so */
2327 if( lpMachineName
[0] == '\\' && lpMachineName
[1] == '\\')
2329 if (GetComputerNameW(compName
, &len
))
2331 if (!strcmpiW(lpMachineName
, compName
))
2332 ret
= RegOpenKeyW(hKey
, NULL
, phkResult
);
2335 FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName
));
2336 ret
= ERROR_BAD_NETPATH
;
2340 ret
= GetLastError();
2346 /******************************************************************************
2347 * RegConnectRegistryA [ADVAPI32.@]
2349 * See RegConnectRegistryW.
2351 LSTATUS WINAPI
RegConnectRegistryA( LPCSTR machine
, HKEY hkey
, PHKEY reskey
)
2353 UNICODE_STRING machineW
;
2356 RtlCreateUnicodeStringFromAsciiz( &machineW
, machine
);
2357 ret
= RegConnectRegistryW( machineW
.Buffer
, hkey
, reskey
);
2358 RtlFreeUnicodeString( &machineW
);
2363 /******************************************************************************
2364 * RegNotifyChangeKeyValue [ADVAPI32.@]
2366 * Notify the caller about changes to the attributes or contents of a registry key.
2369 * hkey [I] Handle of key to watch
2370 * fWatchSubTree [I] Flag for subkey notification
2371 * fdwNotifyFilter [I] Changes to be reported
2372 * hEvent [I] Handle of signaled event
2373 * fAsync [I] Flag for asynchronous reporting
2376 * Success: ERROR_SUCCESS
2377 * Failure: nonzero error code from Winerror.h
2379 LSTATUS WINAPI
RegNotifyChangeKeyValue( HKEY hkey
, BOOL fWatchSubTree
,
2380 DWORD fdwNotifyFilter
, HANDLE hEvent
,
2384 IO_STATUS_BLOCK iosb
;
2386 hkey
= get_special_root_hkey( hkey
);
2387 if (!hkey
) return ERROR_INVALID_HANDLE
;
2389 TRACE("(%p,%i,%d,%p,%i)\n", hkey
, fWatchSubTree
, fdwNotifyFilter
,
2392 status
= NtNotifyChangeKey( hkey
, hEvent
, NULL
, NULL
, &iosb
,
2393 fdwNotifyFilter
, fAsync
, NULL
, 0,
2396 if (status
&& status
!= STATUS_TIMEOUT
)
2397 return RtlNtStatusToDosError( status
);
2399 return ERROR_SUCCESS
;
2402 /******************************************************************************
2403 * RegOpenUserClassesRoot [ADVAPI32.@]
2405 * Open the HKEY_CLASSES_ROOT key for a user.
2408 * hToken [I] Handle of token representing the user
2409 * dwOptions [I] Reserved, must be 0
2410 * samDesired [I] Desired access rights
2411 * phkResult [O] Destination for the resulting key handle
2414 * Success: ERROR_SUCCESS
2415 * Failure: nonzero error code from Winerror.h
2418 * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the
2419 * "HKEY_LOCAL_MACHINE\Software\Classes" and the
2420 * "HKEY_CURRENT_USER\Software\Classes" keys merged together.
2422 LSTATUS WINAPI
RegOpenUserClassesRoot(
2429 FIXME("(%p, 0x%x, 0x%x, %p) semi-stub\n", hToken
, dwOptions
, samDesired
, phkResult
);
2431 *phkResult
= HKEY_CLASSES_ROOT
;
2432 return ERROR_SUCCESS
;
2435 /******************************************************************************
2436 * load_string [Internal]
2438 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
2439 * avoid importing user32, which is higher level than advapi32. Helper for
2442 static int load_string(HINSTANCE hModule
, UINT resId
, LPWSTR pwszBuffer
, INT cMaxChars
)
2449 /* Negative values have to be inverted. */
2450 if (HIWORD(resId
) == 0xffff)
2451 resId
= (UINT
)(-((INT
)resId
));
2453 /* Load the resource into memory and get a pointer to it. */
2454 hResource
= FindResourceW(hModule
, MAKEINTRESOURCEW(LOWORD(resId
>> 4) + 1), (LPWSTR
)RT_STRING
);
2455 if (!hResource
) return 0;
2456 hMemory
= LoadResource(hModule
, hResource
);
2457 if (!hMemory
) return 0;
2458 pString
= LockResource(hMemory
);
2460 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
2461 idxString
= resId
& 0xf;
2462 while (idxString
--) pString
+= *pString
+ 1;
2464 /* If no buffer is given, return length of the string. */
2465 if (!pwszBuffer
) return *pString
;
2467 /* Else copy over the string, respecting the buffer size. */
2468 cMaxChars
= (*pString
< cMaxChars
) ? *pString
: (cMaxChars
- 1);
2469 if (cMaxChars
>= 0) {
2470 memcpy(pwszBuffer
, pString
+1, cMaxChars
* sizeof(WCHAR
));
2471 pwszBuffer
[cMaxChars
] = '\0';
2477 /******************************************************************************
2478 * RegLoadMUIStringW [ADVAPI32.@]
2480 * Load the localized version of a string resource from some PE, respective
2481 * id and path of which are given in the registry value in the format
2482 * @[path]\dllname,-resourceId
2485 * hKey [I] Key, of which to load the string value from.
2486 * pszValue [I] The value to be loaded (Has to be of REG_EXPAND_SZ or REG_SZ type).
2487 * pszBuffer [O] Buffer to store the localized string in.
2488 * cbBuffer [I] Size of the destination buffer in bytes.
2489 * pcbData [O] Number of bytes written to pszBuffer (optional, may be NULL).
2490 * dwFlags [I] None supported yet.
2491 * pszBaseDir [I] Not supported yet.
2494 * Success: ERROR_SUCCESS,
2495 * Failure: nonzero error code from winerror.h
2498 * This is an API of Windows Vista, which wasn't available at the time this code
2499 * was written. We have to check for the correct behaviour once it's available.
2501 LSTATUS WINAPI
RegLoadMUIStringW(HKEY hKey
, LPCWSTR pwszValue
, LPWSTR pwszBuffer
, DWORD cbBuffer
,
2502 LPDWORD pcbData
, DWORD dwFlags
, LPCWSTR pwszBaseDir
)
2504 DWORD dwValueType
, cbData
;
2505 LPWSTR pwszTempBuffer
= NULL
, pwszExpandedBuffer
= NULL
;
2508 TRACE("(hKey = %p, pwszValue = %s, pwszBuffer = %p, cbBuffer = %d, pcbData = %p, "
2509 "dwFlags = %d, pwszBaseDir = %s) stub\n", hKey
, debugstr_w(pwszValue
), pwszBuffer
,
2510 cbBuffer
, pcbData
, dwFlags
, debugstr_w(pwszBaseDir
));
2512 /* Parameter sanity checks. */
2513 if (!hKey
|| !pwszBuffer
)
2514 return ERROR_INVALID_PARAMETER
;
2516 if (pwszBaseDir
&& *pwszBaseDir
) {
2517 FIXME("BaseDir parameter not yet supported!\n");
2518 return ERROR_INVALID_PARAMETER
;
2521 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
2522 result
= RegQueryValueExW(hKey
, pwszValue
, NULL
, &dwValueType
, NULL
, &cbData
);
2523 if (result
!= ERROR_SUCCESS
) goto cleanup
;
2524 if (!(dwValueType
== REG_SZ
|| dwValueType
== REG_EXPAND_SZ
) || !cbData
) {
2525 result
= ERROR_FILE_NOT_FOUND
;
2528 pwszTempBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2529 if (!pwszTempBuffer
) {
2530 result
= ERROR_NOT_ENOUGH_MEMORY
;
2533 result
= RegQueryValueExW(hKey
, pwszValue
, NULL
, &dwValueType
, (LPBYTE
)pwszTempBuffer
, &cbData
);
2534 if (result
!= ERROR_SUCCESS
) goto cleanup
;
2536 /* Expand environment variables, if appropriate, or copy the original string over. */
2537 if (dwValueType
== REG_EXPAND_SZ
) {
2538 cbData
= ExpandEnvironmentStringsW(pwszTempBuffer
, NULL
, 0) * sizeof(WCHAR
);
2539 if (!cbData
) goto cleanup
;
2540 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2541 if (!pwszExpandedBuffer
) {
2542 result
= ERROR_NOT_ENOUGH_MEMORY
;
2545 ExpandEnvironmentStringsW(pwszTempBuffer
, pwszExpandedBuffer
, cbData
);
2547 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2548 memcpy(pwszExpandedBuffer
, pwszTempBuffer
, cbData
);
2551 /* If the value references a resource based string, parse the value and load the string.
2552 * Else just copy over the original value. */
2553 result
= ERROR_SUCCESS
;
2554 if (*pwszExpandedBuffer
!= '@') { /* '@' is the prefix for resource based string entries. */
2555 lstrcpynW(pwszBuffer
, pwszExpandedBuffer
, cbBuffer
/ sizeof(WCHAR
));
2557 WCHAR
*pComma
= strrchrW(pwszExpandedBuffer
, ',');
2561 /* Format of the expanded value is 'path_to_dll,-resId' */
2562 if (!pComma
|| pComma
[1] != '-') {
2563 result
= ERROR_BADKEY
;
2567 uiStringId
= atoiW(pComma
+2);
2570 hModule
= LoadLibraryW(pwszExpandedBuffer
+ 1);
2571 if (!hModule
|| !load_string(hModule
, uiStringId
, pwszBuffer
, cbBuffer
/sizeof(WCHAR
)))
2572 result
= ERROR_BADKEY
;
2573 FreeLibrary(hModule
);
2577 HeapFree(GetProcessHeap(), 0, pwszTempBuffer
);
2578 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer
);
2582 /******************************************************************************
2583 * RegLoadMUIStringA [ADVAPI32.@]
2585 * See RegLoadMUIStringW
2587 LSTATUS WINAPI
RegLoadMUIStringA(HKEY hKey
, LPCSTR pszValue
, LPSTR pszBuffer
, DWORD cbBuffer
,
2588 LPDWORD pcbData
, DWORD dwFlags
, LPCSTR pszBaseDir
)
2590 UNICODE_STRING valueW
, baseDirW
;
2592 DWORD cbData
= cbBuffer
* sizeof(WCHAR
);
2595 valueW
.Buffer
= baseDirW
.Buffer
= pwszBuffer
= NULL
;
2596 if (!RtlCreateUnicodeStringFromAsciiz(&valueW
, pszValue
) ||
2597 !RtlCreateUnicodeStringFromAsciiz(&baseDirW
, pszBaseDir
) ||
2598 !(pwszBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
)))
2600 result
= ERROR_NOT_ENOUGH_MEMORY
;
2604 result
= RegLoadMUIStringW(hKey
, valueW
.Buffer
, pwszBuffer
, cbData
, NULL
, dwFlags
,
2607 if (result
== ERROR_SUCCESS
) {
2608 cbData
= WideCharToMultiByte(CP_ACP
, 0, pwszBuffer
, -1, pszBuffer
, cbBuffer
, NULL
, NULL
);
2614 HeapFree(GetProcessHeap(), 0, pwszBuffer
);
2615 RtlFreeUnicodeString(&baseDirW
);
2616 RtlFreeUnicodeString(&valueW
);
2621 /******************************************************************************
2622 * RegDisablePredefinedCache [ADVAPI32.@]
2624 * Disables the caching of the HKEY_CLASSES_ROOT key for the process.
2630 * Success: ERROR_SUCCESS
2631 * Failure: nonzero error code from Winerror.h
2634 * This is useful for services that use impersonation.
2636 LSTATUS WINAPI
RegDisablePredefinedCache(void)
2638 HKEY hkey_current_user
;
2639 int idx
= (UINT_PTR
)HKEY_CURRENT_USER
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
;
2641 /* prevent caching of future requests */
2642 hkcu_cache_disabled
= TRUE
;
2644 hkey_current_user
= InterlockedExchangePointer( (void **)&special_root_keys
[idx
], NULL
);
2646 if (hkey_current_user
)
2647 NtClose( hkey_current_user
);
2649 return ERROR_SUCCESS
;
2652 /******************************************************************************
2653 * RegDeleteTreeW [ADVAPI32.@]
2656 LSTATUS WINAPI
RegDeleteTreeW(HKEY hKey
, LPCWSTR lpszSubKey
)
2659 DWORD dwMaxSubkeyLen
, dwMaxValueLen
;
2660 DWORD dwMaxLen
, dwSize
;
2661 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
2662 HKEY hSubKey
= hKey
;
2664 TRACE("(hkey=%p,%p %s)\n", hKey
, lpszSubKey
, debugstr_w(lpszSubKey
));
2668 ret
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
2669 if (ret
) return ret
;
2672 /* Get highest length for keys, values */
2673 ret
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
2674 &dwMaxSubkeyLen
, NULL
, NULL
, &dwMaxValueLen
, NULL
, NULL
, NULL
);
2675 if (ret
) goto cleanup
;
2679 dwMaxLen
= max(dwMaxSubkeyLen
, dwMaxValueLen
);
2680 if (dwMaxLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
2682 /* Name too big: alloc a buffer for it */
2683 if (!(lpszName
= HeapAlloc( GetProcessHeap(), 0, dwMaxLen
*sizeof(WCHAR
))))
2685 ret
= ERROR_NOT_ENOUGH_MEMORY
;
2691 /* Recursively delete all the subkeys */
2695 if (RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
,
2696 NULL
, NULL
, NULL
)) break;
2698 ret
= RegDeleteTreeW(hSubKey
, lpszName
);
2699 if (ret
) goto cleanup
;
2703 ret
= RegDeleteKeyW(hKey
, lpszSubKey
);
2708 if (RegEnumValueW(hKey
, 0, lpszName
, &dwSize
,
2709 NULL
, NULL
, NULL
, NULL
)) break;
2711 ret
= RegDeleteValueW(hKey
, lpszName
);
2712 if (ret
) goto cleanup
;
2716 /* Free buffer if allocated */
2717 if (lpszName
!= szNameBuf
)
2718 HeapFree( GetProcessHeap(), 0, lpszName
);
2720 RegCloseKey(hSubKey
);
2724 /******************************************************************************
2725 * RegDeleteTreeA [ADVAPI32.@]
2728 LSTATUS WINAPI
RegDeleteTreeA(HKEY hKey
, LPCSTR lpszSubKey
)
2731 UNICODE_STRING lpszSubKeyW
;
2733 if (lpszSubKey
) RtlCreateUnicodeStringFromAsciiz( &lpszSubKeyW
, lpszSubKey
);
2734 else lpszSubKeyW
.Buffer
= NULL
;
2735 ret
= RegDeleteTreeW( hKey
, lpszSubKeyW
.Buffer
);
2736 RtlFreeUnicodeString( &lpszSubKeyW
);