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 /* allowed bits for access mask */
48 #define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED)
50 #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
51 #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
52 #define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
54 static HKEY special_root_keys
[NB_SPECIAL_ROOT_KEYS
];
55 static BOOL hkcu_cache_disabled
;
57 static const WCHAR name_CLASSES_ROOT
[] =
58 {'M','a','c','h','i','n','e','\\',
59 'S','o','f','t','w','a','r','e','\\',
60 'C','l','a','s','s','e','s',0};
61 static const WCHAR name_LOCAL_MACHINE
[] =
62 {'M','a','c','h','i','n','e',0};
63 static const WCHAR name_USERS
[] =
65 static const WCHAR name_PERFORMANCE_DATA
[] =
66 {'P','e','r','f','D','a','t','a',0};
67 static const WCHAR name_CURRENT_CONFIG
[] =
68 {'M','a','c','h','i','n','e','\\',
69 'S','y','s','t','e','m','\\',
70 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
71 'H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\',
72 'C','u','r','r','e','n','t',0};
73 static const WCHAR name_DYN_DATA
[] =
74 {'D','y','n','D','a','t','a',0};
76 static const WCHAR
* const root_key_names
[NB_SPECIAL_ROOT_KEYS
] =
79 NULL
, /* HKEY_CURRENT_USER is determined dynamically */
82 name_PERFORMANCE_DATA
,
88 /* check if value type needs string conversion (Ansi<->Unicode) */
89 static inline int is_string( DWORD type
)
91 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
94 /* check if current version is NT or Win95 */
95 static inline int is_version_nt(void)
97 return !(GetVersion() & 0x80000000);
100 /* create one of the HKEY_* special root keys */
101 static HKEY
create_special_root_hkey( HANDLE hkey
, DWORD access
)
104 int idx
= (UINT_PTR
)hkey
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
;
106 if (hkey
== HKEY_CURRENT_USER
)
108 if (RtlOpenCurrentUser( access
, &hkey
)) return 0;
109 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey
);
111 /* don't cache the key in the table if caching is disabled */
112 if (hkcu_cache_disabled
)
117 OBJECT_ATTRIBUTES attr
;
120 attr
.Length
= sizeof(attr
);
121 attr
.RootDirectory
= 0;
122 attr
.ObjectName
= &name
;
124 attr
.SecurityDescriptor
= NULL
;
125 attr
.SecurityQualityOfService
= NULL
;
126 RtlInitUnicodeString( &name
, root_key_names
[idx
] );
127 if (NtCreateKey( &hkey
, access
, &attr
, 0, NULL
, 0, NULL
)) return 0;
128 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
131 if (!(ret
= InterlockedCompareExchangePointer( (void **)&special_root_keys
[idx
], hkey
, 0 )))
134 NtClose( hkey
); /* somebody beat us to it */
138 /* map the hkey from special root to normal key if necessary */
139 static inline HKEY
get_special_root_hkey( HKEY hkey
)
143 if ((hkey
>= HKEY_SPECIAL_ROOT_FIRST
) && (hkey
<= HKEY_SPECIAL_ROOT_LAST
))
145 if (!(ret
= special_root_keys
[(UINT_PTR
)hkey
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
]))
146 ret
= create_special_root_hkey( hkey
, KEY_ALL_ACCESS
);
152 /******************************************************************************
153 * RegCreateKeyExW [ADVAPI32.@]
155 * See RegCreateKeyExA.
157 LSTATUS WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPWSTR
class,
158 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
159 PHKEY retkey
, LPDWORD dispos
)
161 OBJECT_ATTRIBUTES attr
;
162 UNICODE_STRING nameW
, classW
;
164 if (reserved
) return ERROR_INVALID_PARAMETER
;
165 if (!(access
& KEY_ACCESS_MASK
) || (access
& ~KEY_ACCESS_MASK
)) return ERROR_ACCESS_DENIED
;
166 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
168 attr
.Length
= sizeof(attr
);
169 attr
.RootDirectory
= hkey
;
170 attr
.ObjectName
= &nameW
;
172 attr
.SecurityDescriptor
= NULL
;
173 attr
.SecurityQualityOfService
= NULL
;
174 RtlInitUnicodeString( &nameW
, name
);
175 RtlInitUnicodeString( &classW
, class );
177 return RtlNtStatusToDosError( NtCreateKey( (PHANDLE
)retkey
, access
, &attr
, 0,
178 &classW
, options
, dispos
) );
182 /******************************************************************************
183 * RegCreateKeyExA [ADVAPI32.@]
185 * Open a registry key, creating it if it doesn't exist.
188 * hkey [I] Handle of the parent registry key
189 * name [I] Name of the new key to open or create
190 * reserved [I] Reserved, pass 0
191 * class [I] The object type of the new key
192 * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h")
193 * access [I] Access level desired
194 * sa [I] Security attributes for the key
195 * retkey [O] Destination for the resulting handle
196 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
199 * Success: ERROR_SUCCESS.
200 * Failure: A standard Win32 error code. retkey remains untouched.
203 * MAXIMUM_ALLOWED in access mask not supported by server
205 LSTATUS WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPSTR
class,
206 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
207 PHKEY retkey
, LPDWORD dispos
)
209 OBJECT_ATTRIBUTES attr
;
210 UNICODE_STRING classW
;
211 ANSI_STRING nameA
, classA
;
214 if (reserved
) return ERROR_INVALID_PARAMETER
;
215 if (!is_version_nt())
217 access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
218 if (name
&& *name
== '\\') name
++; /* win9x,ME ignores one (and only one) beginning backslash */
220 else if (!(access
& KEY_ACCESS_MASK
) || (access
& ~KEY_ACCESS_MASK
)) return ERROR_ACCESS_DENIED
;
221 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
223 attr
.Length
= sizeof(attr
);
224 attr
.RootDirectory
= hkey
;
225 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
227 attr
.SecurityDescriptor
= NULL
;
228 attr
.SecurityQualityOfService
= NULL
;
229 RtlInitAnsiString( &nameA
, name
);
230 RtlInitAnsiString( &classA
, class );
232 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
235 if (!(status
= RtlAnsiStringToUnicodeString( &classW
, &classA
, TRUE
)))
237 status
= NtCreateKey( (PHANDLE
)retkey
, access
, &attr
, 0, &classW
, options
, dispos
);
238 RtlFreeUnicodeString( &classW
);
241 return RtlNtStatusToDosError( status
);
245 /******************************************************************************
246 * RegCreateKeyW [ADVAPI32.@]
248 * Creates the specified reg key.
251 * hKey [I] Handle to an open key.
252 * lpSubKey [I] Name of a key that will be opened or created.
253 * phkResult [O] Receives a handle to the opened or created key.
256 * Success: ERROR_SUCCESS
257 * Failure: nonzero error code defined in Winerror.h
259 LSTATUS WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR lpSubKey
, PHKEY phkResult
)
261 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
262 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
263 return RegCreateKeyExW( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
264 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
268 /******************************************************************************
269 * RegCreateKeyA [ADVAPI32.@]
273 LSTATUS WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR lpSubKey
, PHKEY phkResult
)
275 return RegCreateKeyExA( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
276 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
281 /******************************************************************************
282 * RegOpenKeyExW [ADVAPI32.@]
286 LSTATUS WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
288 OBJECT_ATTRIBUTES attr
;
289 UNICODE_STRING nameW
;
291 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
293 attr
.Length
= sizeof(attr
);
294 attr
.RootDirectory
= hkey
;
295 attr
.ObjectName
= &nameW
;
297 attr
.SecurityDescriptor
= NULL
;
298 attr
.SecurityQualityOfService
= NULL
;
299 RtlInitUnicodeString( &nameW
, name
);
300 return RtlNtStatusToDosError( NtOpenKey( (PHANDLE
)retkey
, access
, &attr
) );
304 /******************************************************************************
305 * RegOpenKeyExA [ADVAPI32.@]
307 * Open a registry key.
310 * hkey [I] Handle of open key
311 * name [I] Name of subkey to open
312 * reserved [I] Reserved - must be zero
313 * access [I] Security access mask
314 * retkey [O] Handle to open key
317 * Success: ERROR_SUCCESS
318 * Failure: A standard Win32 error code. retkey is set to 0.
321 * Unlike RegCreateKeyExA(), this function will not create the key if it
324 LSTATUS WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
326 OBJECT_ATTRIBUTES attr
;
330 if (!is_version_nt()) access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
332 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
334 attr
.Length
= sizeof(attr
);
335 attr
.RootDirectory
= hkey
;
336 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
338 attr
.SecurityDescriptor
= NULL
;
339 attr
.SecurityQualityOfService
= NULL
;
341 RtlInitAnsiString( &nameA
, name
);
342 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
345 status
= NtOpenKey( (PHANDLE
)retkey
, access
, &attr
);
347 return RtlNtStatusToDosError( status
);
351 /******************************************************************************
352 * RegOpenKeyW [ADVAPI32.@]
356 LSTATUS WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, PHKEY retkey
)
361 return ERROR_SUCCESS
;
363 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
367 /******************************************************************************
368 * RegOpenKeyA [ADVAPI32.@]
370 * Open a registry key.
373 * hkey [I] Handle of parent key to open the new key under
374 * name [I] Name of the key under hkey to open
375 * retkey [O] Destination for the resulting Handle
378 * Success: ERROR_SUCCESS
379 * Failure: A standard Win32 error code. retkey is set to 0.
381 LSTATUS WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, PHKEY retkey
)
386 return ERROR_SUCCESS
;
388 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
392 /******************************************************************************
393 * RegOpenCurrentUser [ADVAPI32.@]
395 * Get a handle to the HKEY_CURRENT_USER key for the user
396 * the current thread is impersonating.
399 * access [I] Desired access rights to the key
400 * retkey [O] Handle to the opened key
403 * Success: ERROR_SUCCESS
404 * Failure: nonzero error code from Winerror.h
407 * This function is supposed to retrieve a handle to the
408 * HKEY_CURRENT_USER for the user the current thread is impersonating.
409 * Since Wine does not currently allow threads to impersonate other users,
410 * this stub should work fine.
412 LSTATUS WINAPI
RegOpenCurrentUser( REGSAM access
, PHKEY retkey
)
414 return RegOpenKeyExA( HKEY_CURRENT_USER
, "", 0, access
, retkey
);
419 /******************************************************************************
420 * RegEnumKeyExW [ADVAPI32.@]
422 * Enumerate subkeys of the specified open registry key.
425 * hkey [I] Handle to key to enumerate
426 * index [I] Index of subkey to enumerate
427 * name [O] Buffer for subkey name
428 * name_len [O] Size of subkey buffer
429 * reserved [I] Reserved
430 * class [O] Buffer for class string
431 * class_len [O] Size of class buffer
432 * ft [O] Time key last written to
435 * Success: ERROR_SUCCESS
436 * Failure: System error code. If there are no more subkeys available, the
437 * function returns ERROR_NO_MORE_ITEMS.
439 LSTATUS WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
440 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
443 char buffer
[256], *buf_ptr
= buffer
;
444 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
447 TRACE( "(%p,%d,%p,%p(%d),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
448 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
450 if (reserved
) return ERROR_INVALID_PARAMETER
;
451 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
453 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
454 buffer
, sizeof(buffer
), &total_size
);
456 while (status
== STATUS_BUFFER_OVERFLOW
)
458 /* retry with a dynamically allocated buffer */
459 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
460 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
461 return ERROR_NOT_ENOUGH_MEMORY
;
462 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
463 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
464 buf_ptr
, total_size
, &total_size
);
469 DWORD len
= info
->NameLength
/ sizeof(WCHAR
);
470 DWORD cls_len
= info
->ClassLength
/ sizeof(WCHAR
);
472 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
474 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
475 status
= STATUS_BUFFER_OVERFLOW
;
479 memcpy( name
, info
->Name
, info
->NameLength
);
483 *class_len
= cls_len
;
486 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
493 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
494 return RtlNtStatusToDosError( status
);
498 /******************************************************************************
499 * RegEnumKeyExA [ADVAPI32.@]
503 LSTATUS WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
504 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
507 char buffer
[256], *buf_ptr
= buffer
;
508 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
511 TRACE( "(%p,%d,%p,%p(%d),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
512 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
514 if (reserved
) return ERROR_INVALID_PARAMETER
;
515 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
517 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
518 buffer
, sizeof(buffer
), &total_size
);
520 while (status
== STATUS_BUFFER_OVERFLOW
)
522 /* retry with a dynamically allocated buffer */
523 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
524 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
525 return ERROR_NOT_ENOUGH_MEMORY
;
526 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
527 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
528 buf_ptr
, total_size
, &total_size
);
535 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
536 RtlUnicodeToMultiByteSize( &cls_len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
538 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
540 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
541 status
= STATUS_BUFFER_OVERFLOW
;
545 RtlUnicodeToMultiByteN( name
, len
, NULL
, info
->Name
, info
->NameLength
);
549 *class_len
= cls_len
;
552 RtlUnicodeToMultiByteN( class, cls_len
, NULL
,
553 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
561 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
562 return RtlNtStatusToDosError( status
);
566 /******************************************************************************
567 * RegEnumKeyW [ADVAPI32.@]
569 * Enumerates subkeys of the specified open reg key.
572 * hKey [I] Handle to an open key.
573 * dwIndex [I] Index of the subkey of hKey to retrieve.
574 * lpName [O] Name of the subkey.
575 * cchName [I] Size of lpName in TCHARS.
578 * Success: ERROR_SUCCESS
579 * Failure: system error code. If there are no more subkeys available, the
580 * function returns ERROR_NO_MORE_ITEMS.
582 LSTATUS WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
584 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
588 /******************************************************************************
589 * RegEnumKeyA [ADVAPI32.@]
593 LSTATUS WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
595 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
599 /******************************************************************************
600 * RegQueryInfoKeyW [ADVAPI32.@]
602 * Retrieves information about the specified registry key.
605 * hkey [I] Handle to key to query
606 * class [O] Buffer for class string
607 * class_len [O] Size of class string buffer
608 * reserved [I] Reserved
609 * subkeys [O] Buffer for number of subkeys
610 * max_subkey [O] Buffer for longest subkey name length
611 * max_class [O] Buffer for longest class string length
612 * values [O] Buffer for number of value entries
613 * max_value [O] Buffer for longest value name length
614 * max_data [O] Buffer for longest value data length
615 * security [O] Buffer for security descriptor length
616 * modif [O] Modification time
619 * Success: ERROR_SUCCESS
620 * Failure: system error code.
623 * - win95 allows class to be valid and class_len to be NULL
624 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
625 * - both allow class to be NULL and class_len to be NULL
626 * (it's hard to test validity, so test !NULL instead)
628 LSTATUS WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
629 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
630 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
631 LPDWORD security
, FILETIME
*modif
)
634 char buffer
[256], *buf_ptr
= buffer
;
635 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
638 TRACE( "(%p,%p,%d,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
639 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
641 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
642 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
644 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
645 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
649 /* retry with a dynamically allocated buffer */
650 while (status
== STATUS_BUFFER_OVERFLOW
)
652 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
653 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
654 return ERROR_NOT_ENOUGH_MEMORY
;
655 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
656 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
659 if (status
) goto done
;
661 if (class_len
&& (info
->ClassLength
/sizeof(WCHAR
) + 1 > *class_len
))
663 status
= STATUS_BUFFER_OVERFLOW
;
667 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
668 class[info
->ClassLength
/sizeof(WCHAR
)] = 0;
671 else status
= STATUS_SUCCESS
;
673 if (class_len
) *class_len
= info
->ClassLength
/ sizeof(WCHAR
);
674 if (subkeys
) *subkeys
= info
->SubKeys
;
675 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
676 if (max_class
) *max_class
= info
->MaxClassLen
;
677 if (values
) *values
= info
->Values
;
678 if (max_value
) *max_value
= info
->MaxValueNameLen
;
679 if (max_data
) *max_data
= info
->MaxValueDataLen
;
680 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
683 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
684 return RtlNtStatusToDosError( status
);
688 /******************************************************************************
689 * RegQueryMultipleValuesA [ADVAPI32.@]
691 * Retrieves the type and data for a list of value names associated with a key.
694 * hKey [I] Handle to an open key.
695 * val_list [O] Array of VALENT structures that describes the entries.
696 * num_vals [I] Number of elements in val_list.
697 * lpValueBuf [O] Pointer to a buffer that receives the data for each value.
698 * ldwTotsize [I/O] Size of lpValueBuf.
701 * Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied.
702 * Failure: nonzero error code from Winerror.h ldwTotsize contains num needed
705 LSTATUS WINAPI
RegQueryMultipleValuesA( HKEY hkey
, PVALENTA val_list
, DWORD num_vals
,
706 LPSTR lpValueBuf
, LPDWORD ldwTotsize
)
709 DWORD maxBytes
= *ldwTotsize
;
711 LPSTR bufptr
= lpValueBuf
;
714 TRACE("(%p,%p,%d,%p,%p=%d)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
716 for(i
=0; i
< num_vals
; ++i
)
719 val_list
[i
].ve_valuelen
=0;
720 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
721 if(status
!= ERROR_SUCCESS
)
726 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
728 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
729 (LPBYTE
)bufptr
, &val_list
[i
].ve_valuelen
);
730 if(status
!= ERROR_SUCCESS
)
735 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
737 bufptr
+= val_list
[i
].ve_valuelen
;
740 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
742 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
746 /******************************************************************************
747 * RegQueryMultipleValuesW [ADVAPI32.@]
749 * See RegQueryMultipleValuesA.
751 LSTATUS WINAPI
RegQueryMultipleValuesW( HKEY hkey
, PVALENTW val_list
, DWORD num_vals
,
752 LPWSTR lpValueBuf
, LPDWORD ldwTotsize
)
755 DWORD maxBytes
= *ldwTotsize
;
757 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
760 TRACE("(%p,%p,%d,%p,%p=%d)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
762 for(i
=0; i
< num_vals
; ++i
)
764 val_list
[i
].ve_valuelen
=0;
765 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
766 if(status
!= ERROR_SUCCESS
)
771 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
773 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
774 (LPBYTE
)bufptr
, &val_list
[i
].ve_valuelen
);
775 if(status
!= ERROR_SUCCESS
)
780 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
782 bufptr
+= val_list
[i
].ve_valuelen
;
785 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
787 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
790 /******************************************************************************
791 * RegQueryInfoKeyA [ADVAPI32.@]
793 * Retrieves information about a registry key.
796 * hKey [I] Handle to an open key.
797 * lpClass [O] Class string of the key.
798 * lpcClass [I/O] size of lpClass.
799 * lpReserved [I] Reserved; must be NULL.
800 * lpcSubKeys [O] Number of subkeys contained by the key.
801 * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name.
802 * lpcMaxClassLen [O] Size of the longest string specifying a subkey
804 * lpcValues [O] Number of values associated with the key.
805 * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS.
806 * lpcMaxValueLen [O] Longest data component among the key's values
807 * lpcbSecurityDescriptor [O] Size of the key's security descriptor.
808 * lpftLastWriteTime [O] FILETIME structure that is the last write time.
811 * Success: ERROR_SUCCESS
812 * Failure: nonzero error code from Winerror.h
814 LSTATUS WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
815 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
816 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
817 LPDWORD security
, FILETIME
*modif
)
820 char buffer
[256], *buf_ptr
= buffer
;
821 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
822 DWORD total_size
, len
;
824 TRACE( "(%p,%p,%d,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
825 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
827 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
828 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
830 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
831 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
833 if (class || class_len
)
835 /* retry with a dynamically allocated buffer */
836 while (status
== STATUS_BUFFER_OVERFLOW
)
838 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
839 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
840 return ERROR_NOT_ENOUGH_MEMORY
;
841 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
842 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
845 if (status
) goto done
;
847 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
), info
->ClassLength
);
850 if (len
+ 1 > *class_len
) status
= STATUS_BUFFER_OVERFLOW
;
853 if (class && !status
)
855 RtlUnicodeToMultiByteN( class, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
860 else status
= STATUS_SUCCESS
;
862 if (subkeys
) *subkeys
= info
->SubKeys
;
863 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
864 if (max_class
) *max_class
= info
->MaxClassLen
;
865 if (values
) *values
= info
->Values
;
866 if (max_value
) *max_value
= info
->MaxValueNameLen
;
867 if (max_data
) *max_data
= info
->MaxValueDataLen
;
868 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
871 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
872 return RtlNtStatusToDosError( status
);
876 /******************************************************************************
877 * RegCloseKey [ADVAPI32.@]
879 * Close an open registry key.
882 * hkey [I] Handle of key to close
885 * Success: ERROR_SUCCESS
886 * Failure: Error code
888 LSTATUS WINAPI
RegCloseKey( HKEY hkey
)
890 if (!hkey
) return ERROR_INVALID_HANDLE
;
891 if (hkey
>= (HKEY
)0x80000000) return ERROR_SUCCESS
;
892 return RtlNtStatusToDosError( NtClose( hkey
) );
896 /******************************************************************************
897 * RegDeleteKeyW [ADVAPI32.@]
901 LSTATUS WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
906 if (!name
) return ERROR_INVALID_PARAMETER
;
908 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
910 if (!(ret
= RegOpenKeyExW( hkey
, name
, 0, DELETE
, &tmp
)))
912 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
915 TRACE("%s ret=%08x\n", debugstr_w(name
), ret
);
920 /******************************************************************************
921 * RegDeleteKeyA [ADVAPI32.@]
923 * Delete a registry key.
926 * hkey [I] Handle to parent key containing the key to delete
927 * name [I] Name of the key user hkey to delete
931 * MSDN is wrong when it says that hkey must be opened with the DELETE access
932 * right. In reality, it opens a new handle with DELETE access.
935 * Success: ERROR_SUCCESS
936 * Failure: Error code
938 LSTATUS WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
943 if (!name
) return ERROR_INVALID_PARAMETER
;
945 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
947 if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, DELETE
, &tmp
)))
949 if (!is_version_nt()) /* win95 does recursive key deletes */
953 while(!RegEnumKeyA(tmp
, 0, name
, sizeof(name
)))
955 if(RegDeleteKeyA(tmp
, name
)) /* recurse */
959 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
962 TRACE("%s ret=%08x\n", debugstr_a(name
), ret
);
968 /******************************************************************************
969 * RegSetValueExW [ADVAPI32.@]
971 * Set the data and contents of a registry value.
974 * hkey [I] Handle of key to set value for
975 * name [I] Name of value to set
976 * reserved [I] Reserved, must be zero
977 * type [I] Type of the value being set
978 * data [I] The new contents of the value to set
979 * count [I] Size of data
982 * Success: ERROR_SUCCESS
983 * Failure: Error code
985 LSTATUS WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
986 DWORD type
, CONST BYTE
*data
, DWORD count
)
988 UNICODE_STRING nameW
;
990 /* no need for version check, not implemented on win9x anyway */
991 if (count
&& is_string(type
))
993 LPCWSTR str
= (LPCWSTR
)data
;
994 /* if user forgot to count terminating null, add it (yes NT does this) */
995 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
996 count
+= sizeof(WCHAR
);
998 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1000 RtlInitUnicodeString( &nameW
, name
);
1001 return RtlNtStatusToDosError( NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
) );
1005 /******************************************************************************
1006 * RegSetValueExA [ADVAPI32.@]
1008 * See RegSetValueExW.
1011 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
1012 * NT does definitely care (aj)
1014 LSTATUS WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
1015 CONST BYTE
*data
, DWORD count
)
1018 WCHAR
*dataW
= NULL
;
1021 if (!is_version_nt()) /* win95 */
1025 if (!data
) return ERROR_INVALID_PARAMETER
;
1026 count
= strlen((const char *)data
) + 1;
1029 else if (count
&& is_string(type
))
1031 /* if user forgot to count terminating null, add it (yes NT does this) */
1032 if (data
[count
-1] && !data
[count
]) count
++;
1035 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1037 if (is_string( type
)) /* need to convert to Unicode */
1040 RtlMultiByteToUnicodeSize( &lenW
, (const char *)data
, count
);
1041 if (!(dataW
= HeapAlloc( GetProcessHeap(), 0, lenW
))) return ERROR_OUTOFMEMORY
;
1042 RtlMultiByteToUnicodeN( dataW
, lenW
, NULL
, (const char *)data
, count
);
1044 data
= (BYTE
*)dataW
;
1047 RtlInitAnsiString( &nameA
, name
);
1048 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1051 status
= NtSetValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
, 0, type
, data
, count
);
1053 HeapFree( GetProcessHeap(), 0, dataW
);
1054 return RtlNtStatusToDosError( status
);
1058 /******************************************************************************
1059 * RegSetValueW [ADVAPI32.@]
1061 * Sets the data for the default or unnamed value of a reg key.
1064 * hKey [I] Handle to an open key.
1065 * lpSubKey [I] Name of a subkey of hKey.
1066 * dwType [I] Type of information to store.
1067 * lpData [I] String that contains the data to set for the default value.
1068 * cbData [I] Size of lpData.
1071 * Success: ERROR_SUCCESS
1072 * Failure: nonzero error code from Winerror.h
1074 LSTATUS WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
1079 TRACE("(%p,%s,%d,%s,%d)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
1081 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
1083 if (name
&& name
[0]) /* need to create the subkey */
1085 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1088 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)data
,
1089 (strlenW( data
) + 1) * sizeof(WCHAR
) );
1090 if (subkey
!= hkey
) RegCloseKey( subkey
);
1095 /******************************************************************************
1096 * RegSetValueA [ADVAPI32.@]
1100 LSTATUS WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
1105 TRACE("(%p,%s,%d,%s,%d)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
1107 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
1109 if (name
&& name
[0]) /* need to create the subkey */
1111 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1113 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)data
, strlen(data
)+1 );
1114 if (subkey
!= hkey
) RegCloseKey( subkey
);
1120 /******************************************************************************
1121 * RegQueryValueExW [ADVAPI32.@]
1123 * See RegQueryValueExA.
1125 LSTATUS WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
1126 LPBYTE data
, LPDWORD count
)
1129 UNICODE_STRING name_str
;
1131 char buffer
[256], *buf_ptr
= buffer
;
1132 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1133 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1135 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
1136 hkey
, debugstr_w(name
), reserved
, type
, data
, count
,
1137 (count
&& data
) ? *count
: 0 );
1139 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1140 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1142 RtlInitUnicodeString( &name_str
, name
);
1144 if (data
) total_size
= min( sizeof(buffer
), *count
+ info_size
);
1147 total_size
= info_size
;
1148 if (count
) *count
= 0;
1151 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1152 buffer
, total_size
, &total_size
);
1153 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1157 /* retry with a dynamically allocated buffer */
1158 while (status
== STATUS_BUFFER_OVERFLOW
&& total_size
- info_size
<= *count
)
1160 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1161 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1162 return ERROR_NOT_ENOUGH_MEMORY
;
1163 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1164 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1165 buf_ptr
, total_size
, &total_size
);
1170 memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1171 /* if the type is REG_SZ and data is not 0-terminated
1172 * and there is enough space in the buffer NT appends a \0 */
1173 if (total_size
- info_size
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1175 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info_size
);
1176 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1179 else if (status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1181 else status
= STATUS_SUCCESS
;
1183 if (type
) *type
= info
->Type
;
1184 if (count
) *count
= total_size
- info_size
;
1187 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1188 return RtlNtStatusToDosError(status
);
1192 /******************************************************************************
1193 * RegQueryValueExA [ADVAPI32.@]
1195 * Get the type and contents of a specified value under with a key.
1198 * hkey [I] Handle of the key to query
1199 * name [I] Name of value under hkey to query
1200 * reserved [I] Reserved - must be NULL
1201 * type [O] Destination for the value type, or NULL if not required
1202 * data [O] Destination for the values contents, or NULL if not required
1203 * count [I/O] Size of data, updated with the number of bytes returned
1206 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
1207 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
1208 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
1209 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
1212 * MSDN states that if data is too small it is partially filled. In reality
1213 * it remains untouched.
1215 LSTATUS WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
1216 LPBYTE data
, LPDWORD count
)
1220 DWORD total_size
, datalen
= 0;
1221 char buffer
[256], *buf_ptr
= buffer
;
1222 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1223 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1225 TRACE("(%p,%s,%p,%p,%p,%p=%d)\n",
1226 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
1228 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1229 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1231 if (count
) datalen
= *count
;
1232 if (!data
&& count
) *count
= 0;
1234 /* this matches Win9x behaviour - NT sets *type to a random value */
1235 if (type
) *type
= REG_NONE
;
1237 RtlInitAnsiString( &nameA
, name
);
1238 if ((status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1240 return RtlNtStatusToDosError(status
);
1242 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1243 KeyValuePartialInformation
, buffer
, sizeof(buffer
), &total_size
);
1244 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1246 /* we need to fetch the contents for a string type even if not requested,
1247 * because we need to compute the length of the ASCII string. */
1248 if (data
|| is_string(info
->Type
))
1250 /* retry with a dynamically allocated buffer */
1251 while (status
== STATUS_BUFFER_OVERFLOW
)
1253 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1254 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1256 status
= STATUS_NO_MEMORY
;
1259 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1260 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1261 KeyValuePartialInformation
, buf_ptr
, total_size
, &total_size
);
1264 if (status
) goto done
;
1266 if (is_string(info
->Type
))
1270 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info_size
),
1271 total_size
- info_size
);
1274 if (len
> datalen
) status
= STATUS_BUFFER_OVERFLOW
;
1277 RtlUnicodeToMultiByteN( (char*)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info_size
),
1278 total_size
- info_size
);
1279 /* if the type is REG_SZ and data is not 0-terminated
1280 * and there is enough space in the buffer NT appends a \0 */
1281 if (len
< datalen
&& data
[len
-1]) data
[len
] = 0;
1284 total_size
= len
+ info_size
;
1288 if (total_size
- info_size
> datalen
) status
= STATUS_BUFFER_OVERFLOW
;
1289 else memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1292 else status
= STATUS_SUCCESS
;
1294 if (type
) *type
= info
->Type
;
1295 if (count
) *count
= total_size
- info_size
;
1298 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1299 return RtlNtStatusToDosError(status
);
1303 /******************************************************************************
1304 * RegQueryValueW [ADVAPI32.@]
1306 * Retrieves the data associated with the default or unnamed value of a key.
1309 * hkey [I] Handle to an open key.
1310 * name [I] Name of the subkey of hKey.
1311 * data [O] Receives the string associated with the default value
1313 * count [I/O] Size of lpValue in bytes.
1316 * Success: ERROR_SUCCESS
1317 * Failure: nonzero error code from Winerror.h
1319 LSTATUS WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
1324 TRACE("(%p,%s,%p,%d)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
1326 if (name
&& name
[0])
1328 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1330 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, (LPDWORD
)count
);
1331 if (subkey
!= hkey
) RegCloseKey( subkey
);
1332 if (ret
== ERROR_FILE_NOT_FOUND
)
1334 /* return empty string if default value not found */
1335 if (data
) *data
= 0;
1336 if (count
) *count
= sizeof(WCHAR
);
1337 ret
= ERROR_SUCCESS
;
1343 /******************************************************************************
1344 * RegQueryValueA [ADVAPI32.@]
1346 * See RegQueryValueW.
1348 LSTATUS WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
1353 TRACE("(%p,%s,%p,%d)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
1355 if (name
&& name
[0])
1357 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1359 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, (LPDWORD
)count
);
1360 if (subkey
!= hkey
) RegCloseKey( subkey
);
1361 if (ret
== ERROR_FILE_NOT_FOUND
)
1363 /* return empty string if default value not found */
1364 if (data
) *data
= 0;
1365 if (count
) *count
= 1;
1366 ret
= ERROR_SUCCESS
;
1372 /******************************************************************************
1373 * ADVAPI_ApplyRestrictions [internal]
1375 * Helper function for RegGetValueA/W.
1377 static VOID
ADVAPI_ApplyRestrictions( DWORD dwFlags
, DWORD dwType
,
1378 DWORD cbData
, PLONG ret
)
1380 /* Check if the type is restricted by the passed flags */
1381 if (*ret
== ERROR_SUCCESS
|| *ret
== ERROR_MORE_DATA
)
1387 case REG_NONE
: dwMask
= RRF_RT_REG_NONE
; break;
1388 case REG_SZ
: dwMask
= RRF_RT_REG_SZ
; break;
1389 case REG_EXPAND_SZ
: dwMask
= RRF_RT_REG_EXPAND_SZ
; break;
1390 case REG_MULTI_SZ
: dwMask
= RRF_RT_REG_MULTI_SZ
; break;
1391 case REG_BINARY
: dwMask
= RRF_RT_REG_BINARY
; break;
1392 case REG_DWORD
: dwMask
= RRF_RT_REG_DWORD
; break;
1393 case REG_QWORD
: dwMask
= RRF_RT_REG_QWORD
; break;
1396 if (dwFlags
& dwMask
)
1398 /* Type is not restricted, check for size mismatch */
1399 if (dwType
== REG_BINARY
)
1403 if ((dwFlags
& RRF_RT_DWORD
) == RRF_RT_DWORD
)
1405 else if ((dwFlags
& RRF_RT_QWORD
) == RRF_RT_QWORD
)
1408 if (cbExpect
&& cbData
!= cbExpect
)
1409 *ret
= ERROR_DATATYPE_MISMATCH
;
1412 else *ret
= ERROR_UNSUPPORTED_TYPE
;
1417 /******************************************************************************
1418 * RegGetValueW [ADVAPI32.@]
1420 * Retrieves the type and data for a value name associated with a key
1421 * optionally expanding it's content and restricting it's type.
1424 * hKey [I] Handle to an open key.
1425 * pszSubKey [I] Name of the subkey of hKey.
1426 * pszValue [I] Name of value under hKey/szSubKey to query.
1427 * dwFlags [I] Flags restricting the value type to retrieve.
1428 * pdwType [O] Destination for the values type, may be NULL.
1429 * pvData [O] Destination for the values content, may be NULL.
1430 * pcbData [I/O] Size of pvData, updated with the size required to
1431 * retrieve the whole content.
1434 * Success: ERROR_SUCCESS
1435 * Failure: nonzero error code from Winerror.h
1438 * - Unless RRF_NOEXPAND is specified REG_EXPAND_SZ is automatically expanded
1439 * and REG_SZ is retrieved instead.
1440 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1441 * without RRF_NOEXPAND is thus not allowed.
1443 LSTATUS WINAPI
RegGetValueW( HKEY hKey
, LPCWSTR pszSubKey
, LPCWSTR pszValue
,
1444 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
1447 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
1451 TRACE("(%p,%s,%s,%d,%p,%p,%p=%d)\n",
1452 hKey
, debugstr_w(pszSubKey
), debugstr_w(pszValue
), dwFlags
, pdwType
,
1453 pvData
, pcbData
, cbData
);
1455 if (pvData
&& !pcbData
)
1456 return ERROR_INVALID_PARAMETER
;
1457 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
))
1458 return ERROR_INVALID_PARAMETER
;
1460 if (pszSubKey
&& pszSubKey
[0])
1462 ret
= RegOpenKeyExW(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1463 if (ret
!= ERROR_SUCCESS
) return ret
;
1466 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
1468 /* If we are going to expand we need to read in the whole the value even
1469 * if the passed buffer was too small as the expanded string might be
1470 * smaller than the unexpanded one and could fit into cbData bytes. */
1471 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
1472 dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
))
1475 HeapFree(GetProcessHeap(), 0, pvBuf
);
1477 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
1480 ret
= ERROR_NOT_ENOUGH_MEMORY
;
1484 if (ret
== ERROR_MORE_DATA
|| !pvData
)
1485 ret
= RegQueryValueExW(hKey
, pszValue
, NULL
,
1486 &dwType
, pvBuf
, &cbData
);
1489 /* Even if cbData was large enough we have to copy the
1490 * string since ExpandEnvironmentStrings can't handle
1491 * overlapping buffers. */
1492 CopyMemory(pvBuf
, pvData
, cbData
);
1495 /* Both the type or the value itself could have been modified in
1496 * between so we have to keep retrying until the buffer is large
1497 * enough or we no longer have to expand the value. */
1498 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
1500 if (ret
== ERROR_SUCCESS
)
1502 /* Recheck dwType in case it changed since the first call */
1503 if (dwType
== REG_EXPAND_SZ
)
1505 cbData
= ExpandEnvironmentStringsW(pvBuf
, pvData
,
1506 pcbData
? *pcbData
: 0);
1508 if(pcbData
&& cbData
> *pcbData
)
1509 ret
= ERROR_MORE_DATA
;
1512 CopyMemory(pvData
, pvBuf
, *pcbData
);
1515 HeapFree(GetProcessHeap(), 0, pvBuf
);
1518 if (pszSubKey
&& pszSubKey
[0])
1521 ADVAPI_ApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
1523 if (pvData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
1524 ZeroMemory(pvData
, *pcbData
);
1526 if (pdwType
) *pdwType
= dwType
;
1527 if (pcbData
) *pcbData
= cbData
;
1533 /******************************************************************************
1534 * RegGetValueA [ADVAPI32.@]
1538 LSTATUS WINAPI
RegGetValueA( HKEY hKey
, LPCSTR pszSubKey
, LPCSTR pszValue
,
1539 DWORD dwFlags
, LPDWORD pdwType
, PVOID pvData
,
1542 DWORD dwType
, cbData
= pcbData
? *pcbData
: 0;
1546 TRACE("(%p,%s,%s,%d,%p,%p,%p=%d)\n",
1547 hKey
, pszSubKey
, pszValue
, dwFlags
, pdwType
, pvData
, pcbData
,
1550 if (pvData
&& !pcbData
)
1551 return ERROR_INVALID_PARAMETER
;
1552 if ((dwFlags
& RRF_RT_REG_EXPAND_SZ
) && !(dwFlags
& RRF_NOEXPAND
))
1553 return ERROR_INVALID_PARAMETER
;
1555 if (pszSubKey
&& pszSubKey
[0])
1557 ret
= RegOpenKeyExA(hKey
, pszSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1558 if (ret
!= ERROR_SUCCESS
) return ret
;
1561 ret
= RegQueryValueExA(hKey
, pszValue
, NULL
, &dwType
, pvData
, &cbData
);
1563 /* If we are going to expand we need to read in the whole the value even
1564 * if the passed buffer was too small as the expanded string might be
1565 * smaller than the unexpanded one and could fit into cbData bytes. */
1566 if ((ret
== ERROR_SUCCESS
|| ret
== ERROR_MORE_DATA
) &&
1567 dwType
== REG_EXPAND_SZ
&& !(dwFlags
& RRF_NOEXPAND
))
1570 HeapFree(GetProcessHeap(), 0, pvBuf
);
1572 pvBuf
= HeapAlloc(GetProcessHeap(), 0, cbData
);
1575 ret
= ERROR_NOT_ENOUGH_MEMORY
;
1579 if (ret
== ERROR_MORE_DATA
|| !pvData
)
1580 ret
= RegQueryValueExA(hKey
, pszValue
, NULL
,
1581 &dwType
, pvBuf
, &cbData
);
1584 /* Even if cbData was large enough we have to copy the
1585 * string since ExpandEnvironmentStrings can't handle
1586 * overlapping buffers. */
1587 CopyMemory(pvBuf
, pvData
, cbData
);
1590 /* Both the type or the value itself could have been modified in
1591 * between so we have to keep retrying until the buffer is large
1592 * enough or we no longer have to expand the value. */
1593 } while (dwType
== REG_EXPAND_SZ
&& ret
== ERROR_MORE_DATA
);
1595 if (ret
== ERROR_SUCCESS
)
1597 /* Recheck dwType in case it changed since the first call */
1598 if (dwType
== REG_EXPAND_SZ
)
1600 cbData
= ExpandEnvironmentStringsA(pvBuf
, pvData
,
1601 pcbData
? *pcbData
: 0);
1603 if(pcbData
&& cbData
> *pcbData
)
1604 ret
= ERROR_MORE_DATA
;
1607 CopyMemory(pvData
, pvBuf
, *pcbData
);
1610 HeapFree(GetProcessHeap(), 0, pvBuf
);
1613 if (pszSubKey
&& pszSubKey
[0])
1616 ADVAPI_ApplyRestrictions(dwFlags
, dwType
, cbData
, &ret
);
1618 if (pvData
&& ret
!= ERROR_SUCCESS
&& (dwFlags
& RRF_ZEROONFAILURE
))
1619 ZeroMemory(pvData
, *pcbData
);
1621 if (pdwType
) *pdwType
= dwType
;
1622 if (pcbData
) *pcbData
= cbData
;
1628 /******************************************************************************
1629 * RegEnumValueW [ADVAPI32.@]
1631 * Enumerates the values for the specified open registry key.
1634 * hkey [I] Handle to key to query
1635 * index [I] Index of value to query
1636 * value [O] Value string
1637 * val_count [I/O] Size of value buffer (in wchars)
1638 * reserved [I] Reserved
1639 * type [O] Type code
1640 * data [O] Value data
1641 * count [I/O] Size of data buffer (in bytes)
1644 * Success: ERROR_SUCCESS
1645 * Failure: nonzero error code from Winerror.h
1648 LSTATUS WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
1649 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1653 char buffer
[256], *buf_ptr
= buffer
;
1654 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1655 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1657 TRACE("(%p,%d,%p,%p,%p,%p,%p,%p)\n",
1658 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1660 /* NT only checks count, not val_count */
1661 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1662 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1664 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1665 if (data
) total_size
+= *count
;
1666 total_size
= min( sizeof(buffer
), total_size
);
1668 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1669 buffer
, total_size
, &total_size
);
1670 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1674 /* retry with a dynamically allocated buffer */
1675 while (status
== STATUS_BUFFER_OVERFLOW
)
1677 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1678 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1679 return ERROR_NOT_ENOUGH_MEMORY
;
1680 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1681 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1682 buf_ptr
, total_size
, &total_size
);
1685 if (status
) goto done
;
1689 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1691 status
= STATUS_BUFFER_OVERFLOW
;
1694 memcpy( value
, info
->Name
, info
->NameLength
);
1695 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1696 value
[*val_count
] = 0;
1701 if (total_size
- info
->DataOffset
> *count
)
1703 status
= STATUS_BUFFER_OVERFLOW
;
1706 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1707 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1709 /* if the type is REG_SZ and data is not 0-terminated
1710 * and there is enough space in the buffer NT appends a \0 */
1711 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1712 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1716 else status
= STATUS_SUCCESS
;
1719 if (type
) *type
= info
->Type
;
1720 if (count
) *count
= info
->DataLength
;
1723 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1724 return RtlNtStatusToDosError(status
);
1728 /******************************************************************************
1729 * RegEnumValueA [ADVAPI32.@]
1731 * See RegEnumValueW.
1733 LSTATUS WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1734 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1738 char buffer
[256], *buf_ptr
= buffer
;
1739 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1740 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1742 TRACE("(%p,%d,%p,%p,%p,%p,%p,%p)\n",
1743 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1745 /* NT only checks count, not val_count */
1746 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1747 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1749 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1750 if (data
) total_size
+= *count
;
1751 total_size
= min( sizeof(buffer
), total_size
);
1753 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1754 buffer
, total_size
, &total_size
);
1755 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1757 /* we need to fetch the contents for a string type even if not requested,
1758 * because we need to compute the length of the ASCII string. */
1759 if (value
|| data
|| is_string(info
->Type
))
1761 /* retry with a dynamically allocated buffer */
1762 while (status
== STATUS_BUFFER_OVERFLOW
)
1764 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1765 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1766 return ERROR_NOT_ENOUGH_MEMORY
;
1767 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1768 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1769 buf_ptr
, total_size
, &total_size
);
1772 if (status
) goto done
;
1774 if (is_string(info
->Type
))
1777 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1778 total_size
- info
->DataOffset
);
1781 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1784 RtlUnicodeToMultiByteN( (char*)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1785 total_size
- info
->DataOffset
);
1786 /* if the type is REG_SZ and data is not 0-terminated
1787 * and there is enough space in the buffer NT appends a \0 */
1788 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1791 info
->DataLength
= len
;
1795 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1796 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1799 if (value
&& !status
)
1803 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1804 if (len
>= *val_count
)
1806 status
= STATUS_BUFFER_OVERFLOW
;
1809 len
= *val_count
- 1;
1810 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1816 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1822 else status
= STATUS_SUCCESS
;
1824 if (type
) *type
= info
->Type
;
1825 if (count
) *count
= info
->DataLength
;
1828 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1829 return RtlNtStatusToDosError(status
);
1834 /******************************************************************************
1835 * RegDeleteValueW [ADVAPI32.@]
1837 * See RegDeleteValueA.
1839 LSTATUS WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1841 UNICODE_STRING nameW
;
1843 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1845 RtlInitUnicodeString( &nameW
, name
);
1846 return RtlNtStatusToDosError( NtDeleteValueKey( hkey
, &nameW
) );
1850 /******************************************************************************
1851 * RegDeleteValueA [ADVAPI32.@]
1853 * Delete a value from the registry.
1856 * hkey [I] Registry handle of the key holding the value
1857 * name [I] Name of the value under hkey to delete
1860 * Success: ERROR_SUCCESS
1861 * Failure: nonzero error code from Winerror.h
1863 LSTATUS WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1868 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1870 RtlInitAnsiString( &nameA
, name
);
1871 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1873 status
= NtDeleteValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
);
1874 return RtlNtStatusToDosError( status
);
1878 /******************************************************************************
1879 * RegLoadKeyW [ADVAPI32.@]
1881 * Create a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and store
1882 * registration information from a specified file into that subkey.
1885 * hkey [I] Handle of open key
1886 * subkey [I] Address of name of subkey
1887 * filename [I] Address of filename for registry information
1890 * Success: ERROR_SUCCESS
1891 * Failure: nonzero error code from Winerror.h
1893 LSTATUS WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1895 OBJECT_ATTRIBUTES destkey
, file
;
1896 UNICODE_STRING subkeyW
, filenameW
;
1899 if (!(hkey
= get_special_root_hkey(hkey
))) return ERROR_INVALID_HANDLE
;
1901 destkey
.Length
= sizeof(destkey
);
1902 destkey
.RootDirectory
= hkey
; /* root key: HKLM or HKU */
1903 destkey
.ObjectName
= &subkeyW
; /* name of the key */
1904 destkey
.Attributes
= 0;
1905 destkey
.SecurityDescriptor
= NULL
;
1906 destkey
.SecurityQualityOfService
= NULL
;
1907 RtlInitUnicodeString(&subkeyW
, subkey
);
1909 file
.Length
= sizeof(file
);
1910 file
.RootDirectory
= NULL
;
1911 file
.ObjectName
= &filenameW
; /* file containing the hive */
1912 file
.Attributes
= OBJ_CASE_INSENSITIVE
;
1913 file
.SecurityDescriptor
= NULL
;
1914 file
.SecurityQualityOfService
= NULL
;
1915 RtlDosPathNameToNtPathName_U(filename
, &filenameW
, NULL
, NULL
);
1917 status
= NtLoadKey(&destkey
, &file
);
1918 RtlFreeUnicodeString(&filenameW
);
1919 return RtlNtStatusToDosError( status
);
1923 /******************************************************************************
1924 * RegLoadKeyA [ADVAPI32.@]
1928 LSTATUS WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1930 UNICODE_STRING subkeyW
, filenameW
;
1931 STRING subkeyA
, filenameA
;
1935 RtlInitAnsiString(&subkeyA
, subkey
);
1936 RtlInitAnsiString(&filenameA
, filename
);
1938 RtlInitUnicodeString(&subkeyW
, NULL
);
1939 RtlInitUnicodeString(&filenameW
, NULL
);
1940 if (!(status
= RtlAnsiStringToUnicodeString(&subkeyW
, &subkeyA
, TRUE
)) &&
1941 !(status
= RtlAnsiStringToUnicodeString(&filenameW
, &filenameA
, TRUE
)))
1943 ret
= RegLoadKeyW(hkey
, subkeyW
.Buffer
, filenameW
.Buffer
);
1945 else ret
= RtlNtStatusToDosError(status
);
1946 RtlFreeUnicodeString(&subkeyW
);
1947 RtlFreeUnicodeString(&filenameW
);
1952 /******************************************************************************
1953 * RegSaveKeyW [ADVAPI32.@]
1955 * Save a key and all of its subkeys and values to a new file in the standard format.
1958 * hkey [I] Handle of key where save begins
1959 * lpFile [I] Address of filename to save to
1960 * sa [I] Address of security structure
1963 * Success: ERROR_SUCCESS
1964 * Failure: nonzero error code from Winerror.h
1966 LSTATUS WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1968 static const WCHAR format
[] =
1969 {'r','e','g','%','0','4','x','.','t','m','p',0};
1970 WCHAR buffer
[MAX_PATH
];
1976 TRACE( "(%p,%s,%p)\n", hkey
, debugstr_w(file
), sa
);
1978 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1979 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1981 err
= GetLastError();
1982 GetFullPathNameW( file
, sizeof(buffer
)/sizeof(WCHAR
), buffer
, &nameW
);
1986 snprintfW( nameW
, 16, format
, count
++ );
1987 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
,
1988 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1989 if (handle
!= INVALID_HANDLE_VALUE
) break;
1990 if ((ret
= GetLastError()) != ERROR_FILE_EXISTS
) goto done
;
1992 /* Something gone haywire ? Please report if this happens abnormally */
1994 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
);
1997 ret
= RtlNtStatusToDosError(NtSaveKey(hkey
, handle
));
1999 CloseHandle( handle
);
2002 if (!MoveFileExW( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
2004 ERR( "Failed to move %s to %s\n", debugstr_w(buffer
),
2006 ret
= GetLastError();
2009 if (ret
) DeleteFileW( buffer
);
2012 SetLastError( err
); /* restore last error code */
2017 /******************************************************************************
2018 * RegSaveKeyA [ADVAPI32.@]
2022 LSTATUS WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
2024 UNICODE_STRING
*fileW
= &NtCurrentTeb()->StaticUnicodeString
;
2028 RtlInitAnsiString(&fileA
, file
);
2029 if ((status
= RtlAnsiStringToUnicodeString(fileW
, &fileA
, FALSE
)))
2030 return RtlNtStatusToDosError( status
);
2031 return RegSaveKeyW(hkey
, fileW
->Buffer
, sa
);
2035 /******************************************************************************
2036 * RegRestoreKeyW [ADVAPI32.@]
2038 * Read the registry information from a file and copy it over a key.
2041 * hkey [I] Handle of key where restore begins
2042 * lpFile [I] Address of filename containing saved tree
2043 * dwFlags [I] Optional flags
2046 * Success: ERROR_SUCCESS
2047 * Failure: nonzero error code from Winerror.h
2049 LSTATUS WINAPI
RegRestoreKeyW( HKEY hkey
, LPCWSTR lpFile
, DWORD dwFlags
)
2051 TRACE("(%p,%s,%d)\n",hkey
,debugstr_w(lpFile
),dwFlags
);
2053 /* It seems to do this check before the hkey check */
2054 if (!lpFile
|| !*lpFile
)
2055 return ERROR_INVALID_PARAMETER
;
2057 FIXME("(%p,%s,%d): stub\n",hkey
,debugstr_w(lpFile
),dwFlags
);
2059 /* Check for file existence */
2061 return ERROR_SUCCESS
;
2065 /******************************************************************************
2066 * RegRestoreKeyA [ADVAPI32.@]
2068 * See RegRestoreKeyW.
2070 LSTATUS WINAPI
RegRestoreKeyA( HKEY hkey
, LPCSTR lpFile
, DWORD dwFlags
)
2072 UNICODE_STRING lpFileW
;
2075 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, lpFile
);
2076 ret
= RegRestoreKeyW( hkey
, lpFileW
.Buffer
, dwFlags
);
2077 RtlFreeUnicodeString( &lpFileW
);
2082 /******************************************************************************
2083 * RegUnLoadKeyW [ADVAPI32.@]
2085 * Unload a registry key and its subkeys from the registry.
2088 * hkey [I] Handle of open key
2089 * lpSubKey [I] Address of name of subkey to unload
2092 * Success: ERROR_SUCCESS
2093 * Failure: nonzero error code from Winerror.h
2095 LSTATUS WINAPI
RegUnLoadKeyW( HKEY hkey
, LPCWSTR lpSubKey
)
2099 OBJECT_ATTRIBUTES attr
;
2100 UNICODE_STRING subkey
;
2102 TRACE("(%p,%s)\n",hkey
, debugstr_w(lpSubKey
));
2104 ret
= RegOpenKeyW(hkey
,lpSubKey
,&shkey
);
2106 return ERROR_INVALID_PARAMETER
;
2108 RtlInitUnicodeString(&subkey
, lpSubKey
);
2109 InitializeObjectAttributes(&attr
, &subkey
, OBJ_CASE_INSENSITIVE
, shkey
, NULL
);
2110 ret
= RtlNtStatusToDosError(NtUnloadKey(&attr
));
2118 /******************************************************************************
2119 * RegUnLoadKeyA [ADVAPI32.@]
2121 * See RegUnLoadKeyW.
2123 LSTATUS WINAPI
RegUnLoadKeyA( HKEY hkey
, LPCSTR lpSubKey
)
2125 UNICODE_STRING lpSubKeyW
;
2128 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
2129 ret
= RegUnLoadKeyW( hkey
, lpSubKeyW
.Buffer
);
2130 RtlFreeUnicodeString( &lpSubKeyW
);
2135 /******************************************************************************
2136 * RegReplaceKeyW [ADVAPI32.@]
2138 * Replace the file backing a registry key and all its subkeys with another file.
2141 * hkey [I] Handle of open key
2142 * lpSubKey [I] Address of name of subkey
2143 * lpNewFile [I] Address of filename for file with new data
2144 * lpOldFile [I] Address of filename for backup file
2147 * Success: ERROR_SUCCESS
2148 * Failure: nonzero error code from Winerror.h
2150 LSTATUS WINAPI
RegReplaceKeyW( HKEY hkey
, LPCWSTR lpSubKey
, LPCWSTR lpNewFile
,
2153 FIXME("(%p,%s,%s,%s): stub\n", hkey
, debugstr_w(lpSubKey
),
2154 debugstr_w(lpNewFile
),debugstr_w(lpOldFile
));
2155 return ERROR_SUCCESS
;
2159 /******************************************************************************
2160 * RegReplaceKeyA [ADVAPI32.@]
2162 * See RegReplaceKeyW.
2164 LSTATUS WINAPI
RegReplaceKeyA( HKEY hkey
, LPCSTR lpSubKey
, LPCSTR lpNewFile
,
2167 UNICODE_STRING lpSubKeyW
;
2168 UNICODE_STRING lpNewFileW
;
2169 UNICODE_STRING lpOldFileW
;
2172 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
2173 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, lpOldFile
);
2174 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, lpNewFile
);
2175 ret
= RegReplaceKeyW( hkey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
2176 RtlFreeUnicodeString( &lpOldFileW
);
2177 RtlFreeUnicodeString( &lpNewFileW
);
2178 RtlFreeUnicodeString( &lpSubKeyW
);
2183 /******************************************************************************
2184 * RegSetKeySecurity [ADVAPI32.@]
2186 * Set the security of an open registry key.
2189 * hkey [I] Open handle of key to set
2190 * SecurityInfo [I] Descriptor contents
2191 * pSecurityDesc [I] Address of descriptor for key
2194 * Success: ERROR_SUCCESS
2195 * Failure: nonzero error code from Winerror.h
2197 LSTATUS WINAPI
RegSetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInfo
,
2198 PSECURITY_DESCRIPTOR pSecurityDesc
)
2200 TRACE("(%p,%d,%p)\n",hkey
,SecurityInfo
,pSecurityDesc
);
2202 /* It seems to perform this check before the hkey check */
2203 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) ||
2204 (SecurityInfo
& GROUP_SECURITY_INFORMATION
) ||
2205 (SecurityInfo
& DACL_SECURITY_INFORMATION
) ||
2206 (SecurityInfo
& SACL_SECURITY_INFORMATION
)) {
2209 return ERROR_INVALID_PARAMETER
;
2212 return ERROR_INVALID_PARAMETER
;
2214 FIXME(":(%p,%d,%p): stub\n",hkey
,SecurityInfo
,pSecurityDesc
);
2216 return ERROR_SUCCESS
;
2220 /******************************************************************************
2221 * RegGetKeySecurity [ADVAPI32.@]
2223 * Get a copy of the security descriptor for a given registry key.
2226 * hkey [I] Open handle of key to set
2227 * SecurityInformation [I] Descriptor contents
2228 * pSecurityDescriptor [O] Address of descriptor for key
2229 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
2232 * Success: ERROR_SUCCESS
2233 * Failure: Error code
2235 LSTATUS WINAPI
RegGetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInformation
,
2236 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
2237 LPDWORD lpcbSecurityDescriptor
)
2239 TRACE("(%p,%d,%p,%d)\n",hkey
,SecurityInformation
,pSecurityDescriptor
,
2240 lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
2242 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
2244 return RtlNtStatusToDosError( NtQuerySecurityObject( hkey
,
2245 SecurityInformation
, pSecurityDescriptor
,
2246 *lpcbSecurityDescriptor
, lpcbSecurityDescriptor
) );
2250 /******************************************************************************
2251 * RegFlushKey [ADVAPI32.@]
2253 * Immediately write a registry key to registry.
2256 * hkey [I] Handle of key to write
2259 * Success: ERROR_SUCCESS
2260 * Failure: Error code
2262 LSTATUS WINAPI
RegFlushKey( HKEY hkey
)
2264 hkey
= get_special_root_hkey( hkey
);
2265 if (!hkey
) return ERROR_INVALID_HANDLE
;
2267 return RtlNtStatusToDosError( NtFlushKey( hkey
) );
2271 /******************************************************************************
2272 * RegConnectRegistryW [ADVAPI32.@]
2274 * Establish a connection to a predefined registry key on another computer.
2277 * lpMachineName [I] Address of name of remote computer
2278 * hHey [I] Predefined registry handle
2279 * phkResult [I] Address of buffer for remote registry handle
2282 * Success: ERROR_SUCCESS
2283 * Failure: nonzero error code from Winerror.h
2285 LSTATUS WINAPI
RegConnectRegistryW( LPCWSTR lpMachineName
, HKEY hKey
,
2290 TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName
),hKey
,phkResult
);
2292 if (!lpMachineName
|| !*lpMachineName
) {
2293 /* Use the local machine name */
2294 ret
= RegOpenKeyW( hKey
, NULL
, phkResult
);
2297 WCHAR compName
[MAX_COMPUTERNAME_LENGTH
+ 1];
2298 DWORD len
= sizeof(compName
) / sizeof(WCHAR
);
2300 /* MSDN says lpMachineName must start with \\ : not so */
2301 if( lpMachineName
[0] == '\\' && lpMachineName
[1] == '\\')
2303 if (GetComputerNameW(compName
, &len
))
2305 if (!strcmpiW(lpMachineName
, compName
))
2306 ret
= RegOpenKeyW(hKey
, NULL
, phkResult
);
2309 FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName
));
2310 ret
= ERROR_BAD_NETPATH
;
2314 ret
= GetLastError();
2320 /******************************************************************************
2321 * RegConnectRegistryA [ADVAPI32.@]
2323 * See RegConnectRegistryW.
2325 LSTATUS WINAPI
RegConnectRegistryA( LPCSTR machine
, HKEY hkey
, PHKEY reskey
)
2327 UNICODE_STRING machineW
;
2330 RtlCreateUnicodeStringFromAsciiz( &machineW
, machine
);
2331 ret
= RegConnectRegistryW( machineW
.Buffer
, hkey
, reskey
);
2332 RtlFreeUnicodeString( &machineW
);
2337 /******************************************************************************
2338 * RegNotifyChangeKeyValue [ADVAPI32.@]
2340 * Notify the caller about changes to the attributes or contents of a registry key.
2343 * hkey [I] Handle of key to watch
2344 * fWatchSubTree [I] Flag for subkey notification
2345 * fdwNotifyFilter [I] Changes to be reported
2346 * hEvent [I] Handle of signaled event
2347 * fAsync [I] Flag for asynchronous reporting
2350 * Success: ERROR_SUCCESS
2351 * Failure: nonzero error code from Winerror.h
2353 LSTATUS WINAPI
RegNotifyChangeKeyValue( HKEY hkey
, BOOL fWatchSubTree
,
2354 DWORD fdwNotifyFilter
, HANDLE hEvent
,
2358 IO_STATUS_BLOCK iosb
;
2360 hkey
= get_special_root_hkey( hkey
);
2361 if (!hkey
) return ERROR_INVALID_HANDLE
;
2363 TRACE("(%p,%i,%d,%p,%i)\n", hkey
, fWatchSubTree
, fdwNotifyFilter
,
2366 status
= NtNotifyChangeKey( hkey
, hEvent
, NULL
, NULL
, &iosb
,
2367 fdwNotifyFilter
, fAsync
, NULL
, 0,
2370 if (status
&& status
!= STATUS_TIMEOUT
)
2371 return RtlNtStatusToDosError( status
);
2373 return ERROR_SUCCESS
;
2376 /******************************************************************************
2377 * RegOpenUserClassesRoot [ADVAPI32.@]
2379 * Open the HKEY_CLASSES_ROOT key for a user.
2382 * hToken [I] Handle of token representing the user
2383 * dwOptions [I] Reserved, must be 0
2384 * samDesired [I] Desired access rights
2385 * phkResult [O] Destination for the resulting key handle
2388 * Success: ERROR_SUCCESS
2389 * Failure: nonzero error code from Winerror.h
2392 * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the
2393 * "HKEY_LOCAL_MACHINE\Software\Classes" and the
2394 * "HKEY_CURRENT_USER\Software\Classes" keys merged together.
2396 LSTATUS WINAPI
RegOpenUserClassesRoot(
2403 FIXME("(%p, 0x%x, 0x%x, %p) semi-stub\n", hToken
, dwOptions
, samDesired
, phkResult
);
2405 *phkResult
= HKEY_CLASSES_ROOT
;
2406 return ERROR_SUCCESS
;
2409 /******************************************************************************
2410 * load_string [Internal]
2412 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
2413 * avoid importing user32, which is higher level than advapi32. Helper for
2416 static int load_string(HINSTANCE hModule
, UINT resId
, LPWSTR pwszBuffer
, INT cMaxChars
)
2423 /* Negative values have to be inverted. */
2424 if (HIWORD(resId
) == 0xffff)
2425 resId
= (UINT
)(-((INT
)resId
));
2427 /* Load the resource into memory and get a pointer to it. */
2428 hResource
= FindResourceW(hModule
, MAKEINTRESOURCEW(LOWORD(resId
>> 4) + 1), (LPWSTR
)RT_STRING
);
2429 if (!hResource
) return 0;
2430 hMemory
= LoadResource(hModule
, hResource
);
2431 if (!hMemory
) return 0;
2432 pString
= LockResource(hMemory
);
2434 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
2435 idxString
= resId
& 0xf;
2436 while (idxString
--) pString
+= *pString
+ 1;
2438 /* If no buffer is given, return length of the string. */
2439 if (!pwszBuffer
) return *pString
;
2441 /* Else copy over the string, respecting the buffer size. */
2442 cMaxChars
= (*pString
< cMaxChars
) ? *pString
: (cMaxChars
- 1);
2443 if (cMaxChars
>= 0) {
2444 memcpy(pwszBuffer
, pString
+1, cMaxChars
* sizeof(WCHAR
));
2445 pwszBuffer
[cMaxChars
] = '\0';
2451 /******************************************************************************
2452 * RegLoadMUIStringW [ADVAPI32.@]
2454 * Load the localized version of a string resource from some PE, respective
2455 * id and path of which are given in the registry value in the format
2456 * @[path]\dllname,-resourceId
2459 * hKey [I] Key, of which to load the string value from.
2460 * pszValue [I] The value to be loaded (Has to be of REG_EXPAND_SZ or REG_SZ type).
2461 * pszBuffer [O] Buffer to store the localized string in.
2462 * cbBuffer [I] Size of the destination buffer in bytes.
2463 * pcbData [O] Number of bytes written to pszBuffer (optional, may be NULL).
2464 * dwFlags [I] None supported yet.
2465 * pszBaseDir [I] Not supported yet.
2468 * Success: ERROR_SUCCESS,
2469 * Failure: nonzero error code from winerror.h
2472 * This is an API of Windows Vista, which wasn't available at the time this code
2473 * was written. We have to check for the correct behaviour once it's available.
2475 LSTATUS WINAPI
RegLoadMUIStringW(HKEY hKey
, LPCWSTR pwszValue
, LPWSTR pwszBuffer
, DWORD cbBuffer
,
2476 LPDWORD pcbData
, DWORD dwFlags
, LPCWSTR pwszBaseDir
)
2478 DWORD dwValueType
, cbData
;
2479 LPWSTR pwszTempBuffer
= NULL
, pwszExpandedBuffer
= NULL
;
2482 TRACE("(hKey = %p, pwszValue = %s, pwszBuffer = %p, cbBuffer = %d, pcbData = %p, "
2483 "dwFlags = %d, pwszBaseDir = %s) stub\n", hKey
, debugstr_w(pwszValue
), pwszBuffer
,
2484 cbBuffer
, pcbData
, dwFlags
, debugstr_w(pwszBaseDir
));
2486 /* Parameter sanity checks. */
2487 if (!hKey
|| !pwszBuffer
)
2488 return ERROR_INVALID_PARAMETER
;
2490 if (pwszBaseDir
&& *pwszBaseDir
) {
2491 FIXME("BaseDir parameter not yet supported!\n");
2492 return ERROR_INVALID_PARAMETER
;
2495 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
2496 result
= RegQueryValueExW(hKey
, pwszValue
, NULL
, &dwValueType
, NULL
, &cbData
);
2497 if (result
!= ERROR_SUCCESS
) goto cleanup
;
2498 if (!(dwValueType
== REG_SZ
|| dwValueType
== REG_EXPAND_SZ
) || !cbData
) {
2499 result
= ERROR_FILE_NOT_FOUND
;
2502 pwszTempBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2503 if (!pwszTempBuffer
) {
2504 result
= ERROR_NOT_ENOUGH_MEMORY
;
2507 result
= RegQueryValueExW(hKey
, pwszValue
, NULL
, &dwValueType
, (LPBYTE
)pwszTempBuffer
, &cbData
);
2508 if (result
!= ERROR_SUCCESS
) goto cleanup
;
2510 /* Expand environment variables, if appropriate, or copy the original string over. */
2511 if (dwValueType
== REG_EXPAND_SZ
) {
2512 cbData
= ExpandEnvironmentStringsW(pwszTempBuffer
, NULL
, 0) * sizeof(WCHAR
);
2513 if (!cbData
) goto cleanup
;
2514 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2515 if (!pwszExpandedBuffer
) {
2516 result
= ERROR_NOT_ENOUGH_MEMORY
;
2519 ExpandEnvironmentStringsW(pwszTempBuffer
, pwszExpandedBuffer
, cbData
);
2521 pwszExpandedBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
);
2522 memcpy(pwszExpandedBuffer
, pwszTempBuffer
, cbData
);
2525 /* If the value references a resource based string, parse the value and load the string.
2526 * Else just copy over the original value. */
2527 result
= ERROR_SUCCESS
;
2528 if (*pwszExpandedBuffer
!= '@') { /* '@' is the prefix for resource based string entries. */
2529 lstrcpynW(pwszBuffer
, pwszExpandedBuffer
, cbBuffer
/ sizeof(WCHAR
));
2531 WCHAR
*pComma
= strrchrW(pwszExpandedBuffer
, ',');
2535 /* Format of the expanded value is 'path_to_dll,-resId' */
2536 if (!pComma
|| pComma
[1] != '-') {
2537 result
= ERROR_BADKEY
;
2541 uiStringId
= atoiW(pComma
+2);
2544 hModule
= LoadLibraryW(pwszExpandedBuffer
+ 1);
2545 if (!hModule
|| !load_string(hModule
, uiStringId
, pwszBuffer
, cbBuffer
/sizeof(WCHAR
)))
2546 result
= ERROR_BADKEY
;
2547 FreeLibrary(hModule
);
2551 HeapFree(GetProcessHeap(), 0, pwszTempBuffer
);
2552 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer
);
2556 /******************************************************************************
2557 * RegLoadMUIStringA [ADVAPI32.@]
2559 * See RegLoadMUIStringW
2561 LSTATUS WINAPI
RegLoadMUIStringA(HKEY hKey
, LPCSTR pszValue
, LPSTR pszBuffer
, DWORD cbBuffer
,
2562 LPDWORD pcbData
, DWORD dwFlags
, LPCSTR pszBaseDir
)
2564 UNICODE_STRING valueW
, baseDirW
;
2566 DWORD cbData
= cbBuffer
* sizeof(WCHAR
);
2569 valueW
.Buffer
= baseDirW
.Buffer
= pwszBuffer
= NULL
;
2570 if (!RtlCreateUnicodeStringFromAsciiz(&valueW
, pszValue
) ||
2571 !RtlCreateUnicodeStringFromAsciiz(&baseDirW
, pszBaseDir
) ||
2572 !(pwszBuffer
= HeapAlloc(GetProcessHeap(), 0, cbData
)))
2574 result
= ERROR_NOT_ENOUGH_MEMORY
;
2578 result
= RegLoadMUIStringW(hKey
, valueW
.Buffer
, pwszBuffer
, cbData
, NULL
, dwFlags
,
2581 if (result
== ERROR_SUCCESS
) {
2582 cbData
= WideCharToMultiByte(CP_ACP
, 0, pwszBuffer
, -1, pszBuffer
, cbBuffer
, NULL
, NULL
);
2588 HeapFree(GetProcessHeap(), 0, pwszBuffer
);
2589 RtlFreeUnicodeString(&baseDirW
);
2590 RtlFreeUnicodeString(&valueW
);
2595 /******************************************************************************
2596 * RegDisablePredefinedCache [ADVAPI32.@]
2598 * Disables the caching of the HKEY_CLASSES_ROOT key for the process.
2604 * Success: ERROR_SUCCESS
2605 * Failure: nonzero error code from Winerror.h
2608 * This is useful for services that use impersonation.
2610 LSTATUS WINAPI
RegDisablePredefinedCache(void)
2612 HKEY hkey_current_user
;
2613 int idx
= (UINT_PTR
)HKEY_CURRENT_USER
- (UINT_PTR
)HKEY_SPECIAL_ROOT_FIRST
;
2615 /* prevent caching of future requests */
2616 hkcu_cache_disabled
= TRUE
;
2618 hkey_current_user
= InterlockedExchangePointer( (void **)&special_root_keys
[idx
], NULL
);
2620 if (hkey_current_user
)
2621 NtClose( hkey_current_user
);
2623 return ERROR_SUCCESS
;
2626 /******************************************************************************
2627 * RegDeleteTreeW [ADVAPI32.@]
2630 LSTATUS WINAPI
RegDeleteTreeW(HKEY hKey
, LPCWSTR lpszSubKey
)
2633 DWORD dwMaxSubkeyLen
, dwMaxValueLen
;
2634 DWORD dwMaxLen
, dwSize
;
2635 WCHAR szNameBuf
[MAX_PATH
], *lpszName
= szNameBuf
;
2636 HKEY hSubKey
= hKey
;
2638 TRACE("(hkey=%p,%p %s)\n", hKey
, lpszSubKey
, debugstr_w(lpszSubKey
));
2642 ret
= RegOpenKeyExW(hKey
, lpszSubKey
, 0, KEY_READ
, &hSubKey
);
2643 if (ret
) return ret
;
2646 /* Get highest length for keys, values */
2647 ret
= RegQueryInfoKeyW(hSubKey
, NULL
, NULL
, NULL
, NULL
,
2648 &dwMaxSubkeyLen
, NULL
, NULL
, &dwMaxValueLen
, NULL
, NULL
, NULL
);
2649 if (ret
) goto cleanup
;
2653 dwMaxLen
= max(dwMaxSubkeyLen
, dwMaxValueLen
);
2654 if (dwMaxLen
> sizeof(szNameBuf
)/sizeof(WCHAR
))
2656 /* Name too big: alloc a buffer for it */
2657 if (!(lpszName
= HeapAlloc( GetProcessHeap(), 0, dwMaxLen
*sizeof(WCHAR
))))
2659 ret
= ERROR_NOT_ENOUGH_MEMORY
;
2665 /* Recursively delete all the subkeys */
2669 if (RegEnumKeyExW(hSubKey
, 0, lpszName
, &dwSize
, NULL
,
2670 NULL
, NULL
, NULL
)) break;
2672 ret
= RegDeleteTreeW(hSubKey
, lpszName
);
2673 if (ret
) goto cleanup
;
2677 ret
= RegDeleteKeyW(hKey
, lpszSubKey
);
2682 if (RegEnumValueW(hKey
, 0, lpszName
, &dwSize
,
2683 NULL
, NULL
, NULL
, NULL
)) break;
2685 ret
= RegDeleteValueW(hKey
, lpszName
);
2686 if (ret
) goto cleanup
;
2690 /* Free buffer if allocated */
2691 if (lpszName
!= szNameBuf
)
2692 HeapFree( GetProcessHeap(), 0, lpszName
);
2694 RegCloseKey(hSubKey
);
2698 /******************************************************************************
2699 * RegDeleteTreeA [ADVAPI32.@]
2702 LSTATUS WINAPI
RegDeleteTreeA(HKEY hKey
, LPCSTR lpszSubKey
)
2705 UNICODE_STRING lpszSubKeyW
;
2707 if (lpszSubKey
) RtlCreateUnicodeStringFromAsciiz( &lpszSubKeyW
, lpszSubKey
);
2708 else lpszSubKeyW
.Buffer
= NULL
;
2709 ret
= RegDeleteTreeW( hKey
, lpszSubKeyW
.Buffer
);
2710 RtlFreeUnicodeString( &lpszSubKeyW
);