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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 #include "wine/unicode.h"
39 #include "wine/server.h"
40 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(reg
);
45 /* allowed bits for access mask */
46 #define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED)
48 #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
49 #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
50 #define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
52 static HKEY special_root_keys
[NB_SPECIAL_ROOT_KEYS
];
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 #define DECL_STR(key) { sizeof(name_##key)-sizeof(WCHAR), sizeof(name_##key), (LPWSTR)name_##key }
74 static UNICODE_STRING root_key_names
[NB_SPECIAL_ROOT_KEYS
] =
76 DECL_STR(CLASSES_ROOT
),
77 { 0, 0, NULL
}, /* HKEY_CURRENT_USER is determined dynamically */
78 DECL_STR(LOCAL_MACHINE
),
80 DECL_STR(PERFORMANCE_DATA
),
81 DECL_STR(CURRENT_CONFIG
),
87 /* check if value type needs string conversion (Ansi<->Unicode) */
88 inline static int is_string( DWORD type
)
90 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
93 /* check if current version is NT or Win95 */
94 inline static int is_version_nt(void)
96 return !(GetVersion() & 0x80000000);
99 /* create one of the HKEY_* special root keys */
100 static HKEY
create_special_root_hkey( HKEY hkey
, DWORD access
)
103 int idx
= (UINT
)hkey
- (UINT
)HKEY_SPECIAL_ROOT_FIRST
;
105 if (hkey
== HKEY_CURRENT_USER
)
107 if (RtlOpenCurrentUser( access
, &hkey
)) return 0;
108 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey
);
112 OBJECT_ATTRIBUTES attr
;
114 attr
.Length
= sizeof(attr
);
115 attr
.RootDirectory
= 0;
116 attr
.ObjectName
= &root_key_names
[idx
];
118 attr
.SecurityDescriptor
= NULL
;
119 attr
.SecurityQualityOfService
= NULL
;
120 if (NtCreateKey( &hkey
, access
, &attr
, 0, NULL
, 0, NULL
)) return 0;
121 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
124 if (!(ret
= InterlockedCompareExchangePointer( (void **)&special_root_keys
[idx
], hkey
, 0 )))
127 NtClose( hkey
); /* somebody beat us to it */
131 /* map the hkey from special root to normal key if necessary */
132 inline static HKEY
get_special_root_hkey( HKEY hkey
)
136 if ((hkey
>= HKEY_SPECIAL_ROOT_FIRST
) && (hkey
<= HKEY_SPECIAL_ROOT_LAST
))
138 if (!(ret
= special_root_keys
[(UINT
)hkey
- (UINT
)HKEY_SPECIAL_ROOT_FIRST
]))
139 ret
= create_special_root_hkey( hkey
, KEY_ALL_ACCESS
);
145 /******************************************************************************
146 * RegCreateKeyExW [ADVAPI32.@]
148 * See RegCreateKeyExA.
150 DWORD WINAPI
RegCreateKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, LPCWSTR
class,
151 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
152 PHKEY retkey
, LPDWORD dispos
)
154 OBJECT_ATTRIBUTES attr
;
155 UNICODE_STRING nameW
, classW
;
157 if (reserved
) return ERROR_INVALID_PARAMETER
;
158 if (!(access
& KEY_ACCESS_MASK
) || (access
& ~KEY_ACCESS_MASK
)) return ERROR_ACCESS_DENIED
;
159 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
161 attr
.Length
= sizeof(attr
);
162 attr
.RootDirectory
= hkey
;
163 attr
.ObjectName
= &nameW
;
165 attr
.SecurityDescriptor
= NULL
;
166 attr
.SecurityQualityOfService
= NULL
;
167 RtlInitUnicodeString( &nameW
, name
);
168 RtlInitUnicodeString( &classW
, class );
170 return RtlNtStatusToDosError( NtCreateKey( retkey
, access
, &attr
, 0,
171 &classW
, options
, dispos
) );
175 /******************************************************************************
176 * RegCreateKeyExA [ADVAPI32.@]
178 * Open a registry key, creating it if it doesn't exist.
181 * hkey [I] Handle of the parent registry key
182 * name [I] Name of the new key to open or create
183 * reserved [I] Reserved, pass 0
184 * class [I] The object type of the new key
185 * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h")
186 * access [I] Access level desired
187 * sa [I] Security attributes for the key
188 * retkey [O] Destination for the resulting handle
189 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
192 * Success: ERROR_SUCCESS.
193 * Failure: A standard Win32 error code. retkey remains untouched.
196 * MAXIMUM_ALLOWED in access mask not supported by server
198 DWORD WINAPI
RegCreateKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, LPCSTR
class,
199 DWORD options
, REGSAM access
, SECURITY_ATTRIBUTES
*sa
,
200 PHKEY retkey
, LPDWORD dispos
)
202 OBJECT_ATTRIBUTES attr
;
203 UNICODE_STRING classW
;
204 ANSI_STRING nameA
, classA
;
207 if (reserved
) return ERROR_INVALID_PARAMETER
;
208 if (!is_version_nt()) access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
209 else if (!(access
& KEY_ACCESS_MASK
) || (access
& ~KEY_ACCESS_MASK
)) return ERROR_ACCESS_DENIED
;
210 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
212 attr
.Length
= sizeof(attr
);
213 attr
.RootDirectory
= hkey
;
214 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
216 attr
.SecurityDescriptor
= NULL
;
217 attr
.SecurityQualityOfService
= NULL
;
218 RtlInitAnsiString( &nameA
, name
);
219 RtlInitAnsiString( &classA
, class );
221 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
224 if (!(status
= RtlAnsiStringToUnicodeString( &classW
, &classA
, TRUE
)))
226 status
= NtCreateKey( retkey
, access
, &attr
, 0, &classW
, options
, dispos
);
227 RtlFreeUnicodeString( &classW
);
230 return RtlNtStatusToDosError( status
);
234 /******************************************************************************
235 * RegCreateKeyW [ADVAPI32.@]
237 * Creates the specified reg key.
240 * hKey [I] Handle to an open key.
241 * lpSubKey [I] Name of a key that will be opened or created.
242 * phkResult [O] Receives a handle to the opened or created key.
245 * Success: ERROR_SUCCESS
246 * Failure: nonzero error code defined in Winerror.h
248 DWORD WINAPI
RegCreateKeyW( HKEY hkey
, LPCWSTR lpSubKey
, PHKEY phkResult
)
250 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
251 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
252 return RegCreateKeyExW( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
253 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
257 /******************************************************************************
258 * RegCreateKeyA [ADVAPI32.@]
262 DWORD WINAPI
RegCreateKeyA( HKEY hkey
, LPCSTR lpSubKey
, PHKEY phkResult
)
264 return RegCreateKeyExA( hkey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
,
265 KEY_ALL_ACCESS
, NULL
, phkResult
, NULL
);
270 /******************************************************************************
271 * RegOpenKeyExW [ADVAPI32.@]
275 DWORD WINAPI
RegOpenKeyExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
277 OBJECT_ATTRIBUTES attr
;
278 UNICODE_STRING nameW
;
280 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
282 attr
.Length
= sizeof(attr
);
283 attr
.RootDirectory
= hkey
;
284 attr
.ObjectName
= &nameW
;
286 attr
.SecurityDescriptor
= NULL
;
287 attr
.SecurityQualityOfService
= NULL
;
288 RtlInitUnicodeString( &nameW
, name
);
289 return RtlNtStatusToDosError( NtOpenKey( retkey
, access
, &attr
) );
293 /******************************************************************************
294 * RegOpenKeyExA [ADVAPI32.@]
296 * Open a registry key.
299 * hkey [I] Handle of open key
300 * name [I] Name of subkey to open
301 * reserved [I] Reserved - must be zero
302 * access [I] Security access mask
303 * retkey [O] Handle to open key
306 * Success: ERROR_SUCCESS
307 * Failure: A standard Win32 error code. retkey is set to 0.
310 * Unlike RegCreateKeyExA(), this function will not create the key if it
313 DWORD WINAPI
RegOpenKeyExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, REGSAM access
, PHKEY retkey
)
315 OBJECT_ATTRIBUTES attr
;
319 if (!is_version_nt()) access
= KEY_ALL_ACCESS
; /* Win95 ignores the access mask */
321 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
323 attr
.Length
= sizeof(attr
);
324 attr
.RootDirectory
= hkey
;
325 attr
.ObjectName
= &NtCurrentTeb()->StaticUnicodeString
;
327 attr
.SecurityDescriptor
= NULL
;
328 attr
.SecurityQualityOfService
= NULL
;
330 RtlInitAnsiString( &nameA
, name
);
331 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
334 status
= NtOpenKey( retkey
, access
, &attr
);
336 return RtlNtStatusToDosError( status
);
340 /******************************************************************************
341 * RegOpenKeyW [ADVAPI32.@]
345 DWORD WINAPI
RegOpenKeyW( HKEY hkey
, LPCWSTR name
, PHKEY retkey
)
347 return RegOpenKeyExW( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
351 /******************************************************************************
352 * RegOpenKeyA [ADVAPI32.@]
354 * Open a registry key.
357 * hkey [I] Handle of parent key to open the new key under
358 * name [I] Name of the key under hkey to open
359 * retkey [O] Destination for the resulting Handle
362 * Success: ERROR_SUCCESS
363 * Failure: A standard Win32 error code. retkey is set to 0.
365 DWORD WINAPI
RegOpenKeyA( HKEY hkey
, LPCSTR name
, PHKEY retkey
)
367 return RegOpenKeyExA( hkey
, name
, 0, KEY_ALL_ACCESS
, retkey
);
371 /******************************************************************************
372 * RegOpenCurrentUser [ADVAPI32.@]
374 * FIXME: This function is supposed to retrieve a handle to the
375 * HKEY_CURRENT_USER for the user the current thread is impersonating.
376 * Since Wine does not currently allow threads to impersonate other users,
377 * this stub should work fine.
379 DWORD WINAPI
RegOpenCurrentUser( REGSAM access
, PHKEY retkey
)
381 return RegOpenKeyExA( HKEY_CURRENT_USER
, "", 0, access
, retkey
);
386 /******************************************************************************
387 * RegEnumKeyExW [ADVAPI32.@]
390 * hkey [I] Handle to key to enumerate
391 * index [I] Index of subkey to enumerate
392 * name [O] Buffer for subkey name
393 * name_len [O] Size of subkey buffer
394 * reserved [I] Reserved
395 * class [O] Buffer for class string
396 * class_len [O] Size of class buffer
397 * ft [O] Time key last written to
400 * Success: ERROR_SUCCESS
401 * Failure: System error code. If there are no more subkeys available, the
402 * function returns ERROR_NO_MORE_ITEMS.
404 DWORD WINAPI
RegEnumKeyExW( HKEY hkey
, DWORD index
, LPWSTR name
, LPDWORD name_len
,
405 LPDWORD reserved
, LPWSTR
class, LPDWORD class_len
, FILETIME
*ft
)
408 char buffer
[256], *buf_ptr
= buffer
;
409 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
412 TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
413 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
415 if (reserved
) return ERROR_INVALID_PARAMETER
;
416 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
418 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
419 buffer
, sizeof(buffer
), &total_size
);
421 while (status
== STATUS_BUFFER_OVERFLOW
)
423 /* retry with a dynamically allocated buffer */
424 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
425 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
426 return ERROR_NOT_ENOUGH_MEMORY
;
427 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
428 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
429 buf_ptr
, total_size
, &total_size
);
434 DWORD len
= info
->NameLength
/ sizeof(WCHAR
);
435 DWORD cls_len
= info
->ClassLength
/ sizeof(WCHAR
);
437 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
439 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
440 status
= STATUS_BUFFER_OVERFLOW
;
444 memcpy( name
, info
->Name
, info
->NameLength
);
448 *class_len
= cls_len
;
451 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
458 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
459 return RtlNtStatusToDosError( status
);
463 /******************************************************************************
464 * RegEnumKeyExA [ADVAPI32.@]
468 DWORD WINAPI
RegEnumKeyExA( HKEY hkey
, DWORD index
, LPSTR name
, LPDWORD name_len
,
469 LPDWORD reserved
, LPSTR
class, LPDWORD class_len
, FILETIME
*ft
)
472 char buffer
[256], *buf_ptr
= buffer
;
473 KEY_NODE_INFORMATION
*info
= (KEY_NODE_INFORMATION
*)buffer
;
476 TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey
, index
, name
, name_len
,
477 name_len
? *name_len
: -1, reserved
, class, class_len
, ft
);
479 if (reserved
) return ERROR_INVALID_PARAMETER
;
480 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
482 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
483 buffer
, sizeof(buffer
), &total_size
);
485 while (status
== STATUS_BUFFER_OVERFLOW
)
487 /* retry with a dynamically allocated buffer */
488 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
489 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
490 return ERROR_NOT_ENOUGH_MEMORY
;
491 info
= (KEY_NODE_INFORMATION
*)buf_ptr
;
492 status
= NtEnumerateKey( hkey
, index
, KeyNodeInformation
,
493 buf_ptr
, total_size
, &total_size
);
500 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
501 RtlUnicodeToMultiByteSize( &cls_len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
503 if (ft
) *ft
= *(FILETIME
*)&info
->LastWriteTime
;
505 if (len
>= *name_len
|| (class && class_len
&& (cls_len
>= *class_len
)))
506 status
= STATUS_BUFFER_OVERFLOW
;
510 RtlUnicodeToMultiByteN( name
, len
, NULL
, info
->Name
, info
->NameLength
);
514 *class_len
= cls_len
;
517 RtlUnicodeToMultiByteN( class, cls_len
, NULL
,
518 (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
526 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
527 return RtlNtStatusToDosError( status
);
531 /******************************************************************************
532 * RegEnumKeyW [ADVAPI32.@]
534 * Enumerates subkyes of the specified open reg key.
537 * hKey [I] Handle to an open key.
538 * dwIndex [I] Index of the subkey of hKey to retrieve.
539 * lpName [O] Name of the subkey.
540 * cchName [I] Size of lpName in TCHARS.
543 * Success: ERROR_SUCCESS
544 * Failure: system error code. If there are no more subkeys available, the
545 * function returns ERROR_NO_MORE_ITEMS.
547 DWORD WINAPI
RegEnumKeyW( HKEY hkey
, DWORD index
, LPWSTR name
, DWORD name_len
)
549 return RegEnumKeyExW( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
553 /******************************************************************************
554 * RegEnumKeyA [ADVAPI32.@]
558 DWORD WINAPI
RegEnumKeyA( HKEY hkey
, DWORD index
, LPSTR name
, DWORD name_len
)
560 return RegEnumKeyExA( hkey
, index
, name
, &name_len
, NULL
, NULL
, NULL
, NULL
);
564 /******************************************************************************
565 * RegQueryInfoKeyW [ADVAPI32.@]
568 * hkey [I] Handle to key to query
569 * class [O] Buffer for class string
570 * class_len [O] Size of class string buffer
571 * reserved [I] Reserved
572 * subkeys [O] Buffer for number of subkeys
573 * max_subkey [O] Buffer for longest subkey name length
574 * max_class [O] Buffer for longest class string length
575 * values [O] Buffer for number of value entries
576 * max_value [O] Buffer for longest value name length
577 * max_data [O] Buffer for longest value data length
578 * security [O] Buffer for security descriptor length
579 * modif [O] Modification time
581 * - win95 allows class to be valid and class_len to be NULL
582 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
583 * - both allow class to be NULL and class_len to be NULL
584 * (it's hard to test validity, so test !NULL instead)
586 DWORD WINAPI
RegQueryInfoKeyW( HKEY hkey
, LPWSTR
class, LPDWORD class_len
, LPDWORD reserved
,
587 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
588 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
589 LPDWORD security
, FILETIME
*modif
)
592 char buffer
[256], *buf_ptr
= buffer
;
593 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
596 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
597 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
599 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
600 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
602 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
603 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
607 /* retry with a dynamically allocated buffer */
608 while (status
== STATUS_BUFFER_OVERFLOW
)
610 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
611 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
612 return ERROR_NOT_ENOUGH_MEMORY
;
613 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
614 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
617 if (status
) goto done
;
619 if (class_len
&& (info
->ClassLength
/sizeof(WCHAR
) + 1 > *class_len
))
621 status
= STATUS_BUFFER_OVERFLOW
;
625 memcpy( class, buf_ptr
+ info
->ClassOffset
, info
->ClassLength
);
626 class[info
->ClassLength
/sizeof(WCHAR
)] = 0;
629 else status
= STATUS_SUCCESS
;
631 if (class_len
) *class_len
= info
->ClassLength
/ sizeof(WCHAR
);
632 if (subkeys
) *subkeys
= info
->SubKeys
;
633 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
634 if (max_class
) *max_class
= info
->MaxClassLen
;
635 if (values
) *values
= info
->Values
;
636 if (max_value
) *max_value
= info
->MaxValueNameLen
;
637 if (max_data
) *max_data
= info
->MaxValueDataLen
;
638 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
641 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
642 return RtlNtStatusToDosError( status
);
646 /******************************************************************************
647 * RegQueryMultipleValuesA [ADVAPI32.@]
649 * Retrieves the type and data for a list of value names associated with a key.
652 * hKey [I] Handle to an open key.
653 * val_list [O] Array of VALENT structures that describes the entries.
654 * num_vals [I] Number of elements in val_list.
655 * lpValueBuf [O] Pointer to a buffer that receives the data for each value.
656 * ldwTotsize [I/O] Size of lpValueBuf.
659 * Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied.
660 * Failure: nonzero error code from Winerror.h ldwTotsize contains num needed
663 DWORD WINAPI
RegQueryMultipleValuesA(HKEY hkey
, PVALENTA val_list
, DWORD num_vals
,
664 LPSTR lpValueBuf
, LPDWORD ldwTotsize
)
667 DWORD maxBytes
= *ldwTotsize
;
669 LPSTR bufptr
= lpValueBuf
;
672 TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
674 for(i
=0; i
< num_vals
; ++i
)
677 val_list
[i
].ve_valuelen
=0;
678 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
679 if(status
!= ERROR_SUCCESS
)
684 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
686 status
= RegQueryValueExA(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
687 bufptr
, &val_list
[i
].ve_valuelen
);
688 if(status
!= ERROR_SUCCESS
)
693 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
695 bufptr
+= val_list
[i
].ve_valuelen
;
698 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
700 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
704 /******************************************************************************
705 * RegQueryMultipleValuesW [ADVAPI32.@]
707 * see RegQueryMultipleValuesA
709 DWORD WINAPI
RegQueryMultipleValuesW(HKEY hkey
, PVALENTW val_list
, DWORD num_vals
,
710 LPWSTR lpValueBuf
, LPDWORD ldwTotsize
)
713 DWORD maxBytes
= *ldwTotsize
;
715 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
718 TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
720 for(i
=0; i
< num_vals
; ++i
)
722 val_list
[i
].ve_valuelen
=0;
723 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
724 if(status
!= ERROR_SUCCESS
)
729 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
731 status
= RegQueryValueExW(hkey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
732 bufptr
, &val_list
[i
].ve_valuelen
);
733 if(status
!= ERROR_SUCCESS
)
738 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
740 bufptr
+= val_list
[i
].ve_valuelen
;
743 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
745 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
748 /******************************************************************************
749 * RegQueryInfoKeyA [ADVAPI32.@]
751 * Retrieves information about a registry key.
754 * hKey [I] Handle to an open key.
755 * lpClass [O] Class string of the key.
756 * lpcClass [I/O] size of lpClass.
757 * lpReserved [I] Reserved; must be NULL.
758 * lpcSubKeys [O] Number of subkeys contained by the key.
759 * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name.
760 * lpcMaxClassLen [O] Size of the longest string specifying a subkey
762 * lpcValues [O] Number of values associated with the key.
763 * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS.
764 * lpcMaxValueLen [O] Longest data component among the key's values
765 * lpcbSecurityDescriptor [O] Size of the key's security descriptor.
766 * lpftLastWriteTime [O] FILETIME strucutre that is the last write time.
769 * Success: ERROR_SUCCESS
770 * Failure: nonzero error code from Winerror.h
772 DWORD WINAPI
RegQueryInfoKeyA( HKEY hkey
, LPSTR
class, LPDWORD class_len
, LPDWORD reserved
,
773 LPDWORD subkeys
, LPDWORD max_subkey
, LPDWORD max_class
,
774 LPDWORD values
, LPDWORD max_value
, LPDWORD max_data
,
775 LPDWORD security
, FILETIME
*modif
)
778 char buffer
[256], *buf_ptr
= buffer
;
779 KEY_FULL_INFORMATION
*info
= (KEY_FULL_INFORMATION
*)buffer
;
780 DWORD total_size
, len
;
782 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey
, class, class_len
? *class_len
: 0,
783 reserved
, subkeys
, max_subkey
, values
, max_value
, max_data
, security
, modif
);
785 if (class && !class_len
&& is_version_nt()) return ERROR_INVALID_PARAMETER
;
786 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
788 status
= NtQueryKey( hkey
, KeyFullInformation
, buffer
, sizeof(buffer
), &total_size
);
789 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
791 if (class || class_len
)
793 /* retry with a dynamically allocated buffer */
794 while (status
== STATUS_BUFFER_OVERFLOW
)
796 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
797 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
798 return ERROR_NOT_ENOUGH_MEMORY
;
799 info
= (KEY_FULL_INFORMATION
*)buf_ptr
;
800 status
= NtQueryKey( hkey
, KeyFullInformation
, buf_ptr
, total_size
, &total_size
);
803 if (status
) goto done
;
805 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
), info
->ClassLength
);
808 if (len
+ 1 > *class_len
) status
= STATUS_BUFFER_OVERFLOW
;
811 if (class && !status
)
813 RtlUnicodeToMultiByteN( class, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->ClassOffset
),
818 else status
= STATUS_SUCCESS
;
820 if (subkeys
) *subkeys
= info
->SubKeys
;
821 if (max_subkey
) *max_subkey
= info
->MaxNameLen
;
822 if (max_class
) *max_class
= info
->MaxClassLen
;
823 if (values
) *values
= info
->Values
;
824 if (max_value
) *max_value
= info
->MaxValueNameLen
;
825 if (max_data
) *max_data
= info
->MaxValueDataLen
;
826 if (modif
) *modif
= *(FILETIME
*)&info
->LastWriteTime
;
829 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
830 return RtlNtStatusToDosError( status
);
834 /******************************************************************************
835 * RegCloseKey [ADVAPI32.@]
837 * Close an open registry key.
840 * hkey [I] Handle of key to close
843 * Success: ERROR_SUCCESS
844 * Failure: Error code
846 DWORD WINAPI
RegCloseKey( HKEY hkey
)
848 if (!hkey
|| hkey
>= (HKEY
)0x80000000) return ERROR_SUCCESS
;
849 return RtlNtStatusToDosError( NtClose( hkey
) );
853 /******************************************************************************
854 * RegDeleteKeyW [ADVAPI32.@]
858 DWORD WINAPI
RegDeleteKeyW( HKEY hkey
, LPCWSTR name
)
863 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
867 ret
= RtlNtStatusToDosError( NtDeleteKey( hkey
) );
869 else if (!(ret
= RegOpenKeyExW( hkey
, name
, 0, KEY_ENUMERATE_SUB_KEYS
, &tmp
)))
871 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
874 TRACE("%s ret=%08lx\n", debugstr_w(name
), ret
);
879 /******************************************************************************
880 * RegDeleteKeyA [ADVAPI32.@]
882 * Delete a registry key.
885 * hkey [I] Handle to parent key containing the key to delete
886 * name [I] Name of the key user hkey to delete
889 * Success: ERROR_SUCCESS
890 * Failure: Error code
892 DWORD WINAPI
RegDeleteKeyA( HKEY hkey
, LPCSTR name
)
897 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
901 ret
= RtlNtStatusToDosError( NtDeleteKey( hkey
) );
903 else if (!(ret
= RegOpenKeyExA( hkey
, name
, 0, KEY_ENUMERATE_SUB_KEYS
, &tmp
)))
905 if (!is_version_nt()) /* win95 does recursive key deletes */
909 while(!RegEnumKeyA(tmp
, 0, name
, sizeof(name
)))
911 if(RegDeleteKeyA(tmp
, name
)) /* recurse */
915 ret
= RtlNtStatusToDosError( NtDeleteKey( tmp
) );
918 TRACE("%s ret=%08lx\n", debugstr_a(name
), ret
);
924 /******************************************************************************
925 * RegSetValueExW [ADVAPI32.@]
927 * Set the data and contents of a registry value.
930 * hkey [I] Handle of key to set value for
931 * name [I] Name of value to set
932 * reserved [I] Reserved, must be zero
933 * type [I] Type of the value being set
934 * data [I] The new contents of the value to set
935 * count [I] Size of data
938 * Success: ERROR_SUCCESS
939 * Failure: Error code
941 DWORD WINAPI
RegSetValueExW( HKEY hkey
, LPCWSTR name
, DWORD reserved
,
942 DWORD type
, CONST BYTE
*data
, DWORD count
)
944 UNICODE_STRING nameW
;
946 /* no need for version check, not implemented on win9x anyway */
947 if (count
&& is_string(type
))
949 LPCWSTR str
= (LPCWSTR
)data
;
950 /* if user forgot to count terminating null, add it (yes NT does this) */
951 if (str
[count
/ sizeof(WCHAR
) - 1] && !str
[count
/ sizeof(WCHAR
)])
952 count
+= sizeof(WCHAR
);
954 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
956 RtlInitUnicodeString( &nameW
, name
);
957 return RtlNtStatusToDosError( NtSetValueKey( hkey
, &nameW
, 0, type
, data
, count
) );
961 /******************************************************************************
962 * RegSetValueExA [ADVAPI32.@]
967 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
968 * NT does definitely care (aj)
970 DWORD WINAPI
RegSetValueExA( HKEY hkey
, LPCSTR name
, DWORD reserved
, DWORD type
,
971 CONST BYTE
*data
, DWORD count
)
977 if (!is_version_nt()) /* win95 */
981 if (!data
) return ERROR_INVALID_PARAMETER
;
982 count
= strlen(data
) + 1;
985 else if (count
&& is_string(type
))
987 /* if user forgot to count terminating null, add it (yes NT does this) */
988 if (data
[count
-1] && !data
[count
]) count
++;
991 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
993 if (is_string( type
)) /* need to convert to Unicode */
996 RtlMultiByteToUnicodeSize( &lenW
, data
, count
);
997 if (!(dataW
= HeapAlloc( GetProcessHeap(), 0, lenW
))) return ERROR_OUTOFMEMORY
;
998 RtlMultiByteToUnicodeN( dataW
, lenW
, NULL
, data
, count
);
1000 data
= (BYTE
*)dataW
;
1003 RtlInitAnsiString( &nameA
, name
);
1004 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1007 status
= NtSetValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
, 0, type
, data
, count
);
1009 if (dataW
) HeapFree( GetProcessHeap(), 0, dataW
);
1010 return RtlNtStatusToDosError( status
);
1014 /******************************************************************************
1015 * RegSetValueW [ADVAPI32.@]
1017 * Sets the data for the default or unnamed value of a reg key.
1020 * hKey [I] Handle to an open key.
1021 * lpSubKey [I] Name of a subkey of hKey.
1022 * dwType [I] Type of information to store.
1023 * lpData [I] String that contains the data to set for the default value.
1024 * cbData [I] Size of lpData.
1027 * Success: ERROR_SUCCESS
1028 * Failure: nonzero error code from Winerror.h
1030 DWORD WINAPI
RegSetValueW( HKEY hkey
, LPCWSTR name
, DWORD type
, LPCWSTR data
, DWORD count
)
1035 TRACE("(%p,%s,%ld,%s,%ld)\n", hkey
, debugstr_w(name
), type
, debugstr_w(data
), count
);
1037 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
1039 if (name
&& name
[0]) /* need to create the subkey */
1041 if ((ret
= RegCreateKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1044 ret
= RegSetValueExW( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
,
1045 (strlenW( data
) + 1) * sizeof(WCHAR
) );
1046 if (subkey
!= hkey
) RegCloseKey( subkey
);
1051 /******************************************************************************
1052 * RegSetValueA [ADVAPI32.@]
1056 DWORD WINAPI
RegSetValueA( HKEY hkey
, LPCSTR name
, DWORD type
, LPCSTR data
, DWORD count
)
1061 TRACE("(%p,%s,%ld,%s,%ld)\n", hkey
, debugstr_a(name
), type
, debugstr_a(data
), count
);
1063 if (type
!= REG_SZ
) return ERROR_INVALID_PARAMETER
;
1065 if (name
&& name
[0]) /* need to create the subkey */
1067 if ((ret
= RegCreateKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1069 ret
= RegSetValueExA( subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)data
, strlen(data
)+1 );
1070 if (subkey
!= hkey
) RegCloseKey( subkey
);
1076 /******************************************************************************
1077 * RegQueryValueExW [ADVAPI32.@]
1079 * See RegQueryValueExA.
1081 DWORD WINAPI
RegQueryValueExW( HKEY hkey
, LPCWSTR name
, LPDWORD reserved
, LPDWORD type
,
1082 LPBYTE data
, LPDWORD count
)
1085 UNICODE_STRING name_str
;
1087 char buffer
[256], *buf_ptr
= buffer
;
1088 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1089 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1091 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
1092 hkey
, debugstr_w(name
), reserved
, type
, data
, count
,
1093 (count
&& data
) ? *count
: 0 );
1095 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1096 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1098 RtlInitUnicodeString( &name_str
, name
);
1100 if (data
) total_size
= min( sizeof(buffer
), *count
+ info_size
);
1101 else total_size
= info_size
;
1103 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1104 buffer
, total_size
, &total_size
);
1105 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1109 /* retry with a dynamically allocated buffer */
1110 while (status
== STATUS_BUFFER_OVERFLOW
&& total_size
- info_size
<= *count
)
1112 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1113 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1114 return ERROR_NOT_ENOUGH_MEMORY
;
1115 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1116 status
= NtQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
,
1117 buf_ptr
, total_size
, &total_size
);
1122 memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1123 /* if the type is REG_SZ and data is not 0-terminated
1124 * and there is enough space in the buffer NT appends a \0 */
1125 if (total_size
- info_size
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1127 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info_size
);
1128 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1131 else if (status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1133 else status
= STATUS_SUCCESS
;
1135 if (type
) *type
= info
->Type
;
1136 if (count
) *count
= total_size
- info_size
;
1139 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1140 return RtlNtStatusToDosError(status
);
1144 /******************************************************************************
1145 * RegQueryValueExA [ADVAPI32.@]
1147 * Get the type and contents of a specified value under with a key.
1150 * hkey [I] Handle of the key to query
1151 * name [I] Name of value under hkey to query
1152 * reserved [I] Reserved - must be NULL
1153 * type [O] Destination for the value type, or NULL if not required
1154 * data [O] Destination for the values contents, or NULL if not required
1155 * count [I/O] Size of data, updated with the number of bytes returned
1158 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
1159 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
1160 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
1161 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
1164 * MSDN states that if data is too small it is partially filled. In reality
1165 * it remains untouched.
1167 DWORD WINAPI
RegQueryValueExA( HKEY hkey
, LPCSTR name
, LPDWORD reserved
, LPDWORD type
,
1168 LPBYTE data
, LPDWORD count
)
1173 char buffer
[256], *buf_ptr
= buffer
;
1174 KEY_VALUE_PARTIAL_INFORMATION
*info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
1175 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
1177 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
1178 hkey
, debugstr_a(name
), reserved
, type
, data
, count
, count
? *count
: 0 );
1180 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1181 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1183 RtlInitAnsiString( &nameA
, name
);
1184 if ((status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1186 return RtlNtStatusToDosError(status
);
1188 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1189 KeyValuePartialInformation
, buffer
, sizeof(buffer
), &total_size
);
1190 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1192 /* we need to fetch the contents for a string type even if not requested,
1193 * because we need to compute the length of the ASCII string. */
1194 if (data
|| is_string(info
->Type
))
1196 /* retry with a dynamically allocated buffer */
1197 while (status
== STATUS_BUFFER_OVERFLOW
)
1199 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1200 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1202 status
= STATUS_NO_MEMORY
;
1205 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buf_ptr
;
1206 status
= NtQueryValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
,
1207 KeyValuePartialInformation
, buf_ptr
, total_size
, &total_size
);
1210 if (status
) goto done
;
1212 if (is_string(info
->Type
))
1216 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info_size
),
1217 total_size
- info_size
);
1220 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1223 RtlUnicodeToMultiByteN( data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info_size
),
1224 total_size
- info_size
);
1225 /* if the type is REG_SZ and data is not 0-terminated
1226 * and there is enough space in the buffer NT appends a \0 */
1227 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1230 total_size
= len
+ info_size
;
1234 if (total_size
- info_size
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1235 else memcpy( data
, buf_ptr
+ info_size
, total_size
- info_size
);
1238 else status
= STATUS_SUCCESS
;
1240 if (type
) *type
= info
->Type
;
1241 if (count
) *count
= total_size
- info_size
;
1244 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1245 return RtlNtStatusToDosError(status
);
1249 /******************************************************************************
1250 * RegQueryValueW [ADVAPI32.@]
1252 * Retrieves the data associated with the default or unnamed value of a key.
1255 * hkey [I] Handle to an open key.
1256 * name [I] Name of the subkey of hKey.
1257 * data [O] Receives the string associated with the default value
1259 * count [I/O] Size of lpValue in bytes.
1262 * Success: ERROR_SUCCESS
1263 * Failure: nonzero error code from Winerror.h
1265 DWORD WINAPI
RegQueryValueW( HKEY hkey
, LPCWSTR name
, LPWSTR data
, LPLONG count
)
1270 TRACE("(%p,%s,%p,%ld)\n", hkey
, debugstr_w(name
), data
, count
? *count
: 0 );
1272 if (name
&& name
[0])
1274 if ((ret
= RegOpenKeyW( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1276 ret
= RegQueryValueExW( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
1277 if (subkey
!= hkey
) RegCloseKey( subkey
);
1278 if (ret
== ERROR_FILE_NOT_FOUND
)
1280 /* return empty string if default value not found */
1281 if (data
) *data
= 0;
1282 if (count
) *count
= sizeof(WCHAR
);
1283 ret
= ERROR_SUCCESS
;
1289 /******************************************************************************
1290 * RegQueryValueA [ADVAPI32.@]
1292 * see RegQueryValueW
1294 DWORD WINAPI
RegQueryValueA( HKEY hkey
, LPCSTR name
, LPSTR data
, LPLONG count
)
1299 TRACE("(%p,%s,%p,%ld)\n", hkey
, debugstr_a(name
), data
, count
? *count
: 0 );
1301 if (name
&& name
[0])
1303 if ((ret
= RegOpenKeyA( hkey
, name
, &subkey
)) != ERROR_SUCCESS
) return ret
;
1305 ret
= RegQueryValueExA( subkey
, NULL
, NULL
, NULL
, (LPBYTE
)data
, count
);
1306 if (subkey
!= hkey
) RegCloseKey( subkey
);
1307 if (ret
== ERROR_FILE_NOT_FOUND
)
1309 /* return empty string if default value not found */
1310 if (data
) *data
= 0;
1311 if (count
) *count
= 1;
1312 ret
= ERROR_SUCCESS
;
1318 /******************************************************************************
1319 * RegEnumValueW [ADVAPI32.@]
1322 * hkey [I] Handle to key to query
1323 * index [I] Index of value to query
1324 * value [O] Value string
1325 * val_count [I/O] Size of value buffer (in wchars)
1326 * reserved [I] Reserved
1327 * type [O] Type code
1328 * data [O] Value data
1329 * count [I/O] Size of data buffer (in bytes)
1332 * Success: ERROR_SUCCESS
1333 * Failure: nonzero error code from Winerror.h
1336 DWORD WINAPI
RegEnumValueW( HKEY hkey
, DWORD index
, LPWSTR value
, LPDWORD val_count
,
1337 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1341 char buffer
[256], *buf_ptr
= buffer
;
1342 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1343 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1345 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1346 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1348 /* NT only checks count, not val_count */
1349 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1350 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1352 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1353 if (data
) total_size
+= *count
;
1354 total_size
= min( sizeof(buffer
), total_size
);
1356 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1357 buffer
, total_size
, &total_size
);
1358 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1362 /* retry with a dynamically allocated buffer */
1363 while (status
== STATUS_BUFFER_OVERFLOW
)
1365 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1366 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1367 return ERROR_NOT_ENOUGH_MEMORY
;
1368 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1369 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1370 buf_ptr
, total_size
, &total_size
);
1373 if (status
) goto done
;
1377 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1379 status
= STATUS_BUFFER_OVERFLOW
;
1382 memcpy( value
, info
->Name
, info
->NameLength
);
1383 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1384 value
[*val_count
] = 0;
1389 if (total_size
- info
->DataOffset
> *count
)
1391 status
= STATUS_BUFFER_OVERFLOW
;
1394 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1395 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1397 /* if the type is REG_SZ and data is not 0-terminated
1398 * and there is enough space in the buffer NT appends a \0 */
1399 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1400 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1404 else status
= STATUS_SUCCESS
;
1407 if (type
) *type
= info
->Type
;
1408 if (count
) *count
= info
->DataLength
;
1411 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1412 return RtlNtStatusToDosError(status
);
1416 /******************************************************************************
1417 * RegEnumValueA [ADVAPI32.@]
1421 DWORD WINAPI
RegEnumValueA( HKEY hkey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1422 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1426 char buffer
[256], *buf_ptr
= buffer
;
1427 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1428 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1430 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1431 hkey
, index
, value
, val_count
, reserved
, type
, data
, count
);
1433 /* NT only checks count, not val_count */
1434 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1435 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1437 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1438 if (data
) total_size
+= *count
;
1439 total_size
= min( sizeof(buffer
), total_size
);
1441 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1442 buffer
, total_size
, &total_size
);
1443 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1445 /* we need to fetch the contents for a string type even if not requested,
1446 * because we need to compute the length of the ASCII string. */
1447 if (value
|| data
|| is_string(info
->Type
))
1449 /* retry with a dynamically allocated buffer */
1450 while (status
== STATUS_BUFFER_OVERFLOW
)
1452 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1453 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1454 return ERROR_NOT_ENOUGH_MEMORY
;
1455 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1456 status
= NtEnumerateValueKey( hkey
, index
, KeyValueFullInformation
,
1457 buf_ptr
, total_size
, &total_size
);
1460 if (status
) goto done
;
1462 if (is_string(info
->Type
))
1465 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1466 total_size
- info
->DataOffset
);
1469 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1472 RtlUnicodeToMultiByteN( data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1473 total_size
- info
->DataOffset
);
1474 /* if the type is REG_SZ and data is not 0-terminated
1475 * and there is enough space in the buffer NT appends a \0 */
1476 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1479 info
->DataLength
= len
;
1483 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1484 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1487 if (value
&& !status
)
1491 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1492 if (len
>= *val_count
)
1494 status
= STATUS_BUFFER_OVERFLOW
;
1497 len
= *val_count
- 1;
1498 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1504 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1510 else status
= STATUS_SUCCESS
;
1512 if (type
) *type
= info
->Type
;
1513 if (count
) *count
= info
->DataLength
;
1516 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1517 return RtlNtStatusToDosError(status
);
1522 /******************************************************************************
1523 * RegDeleteValueW [ADVAPI32.@]
1525 * See RegDeleteValueA.
1527 DWORD WINAPI
RegDeleteValueW( HKEY hkey
, LPCWSTR name
)
1529 UNICODE_STRING nameW
;
1531 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1533 RtlInitUnicodeString( &nameW
, name
);
1534 return RtlNtStatusToDosError( NtDeleteValueKey( hkey
, &nameW
) );
1538 /******************************************************************************
1539 * RegDeleteValueA [ADVAPI32.@]
1541 * Delete a value from the registry.
1544 * hkey [I] Registry handle of the key holding the value
1545 * name [I] Name of the value under hkey to delete
1548 * Success: ERROR_SUCCESS
1549 * Failure: nonzero error code from Winerror.h
1551 DWORD WINAPI
RegDeleteValueA( HKEY hkey
, LPCSTR name
)
1556 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1558 RtlInitAnsiString( &nameA
, name
);
1559 if (!(status
= RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString
,
1561 status
= NtDeleteValueKey( hkey
, &NtCurrentTeb()->StaticUnicodeString
);
1562 return RtlNtStatusToDosError( status
);
1566 /******************************************************************************
1567 * RegLoadKeyW [ADVAPI32.@]
1570 * hkey [I] Handle of open key
1571 * subkey [I] Address of name of subkey
1572 * filename [I] Address of filename for registry information
1575 * Success: ERROR_SUCCES
1576 * Failure: nonzero error code from Winerror.h
1578 LONG WINAPI
RegLoadKeyW( HKEY hkey
, LPCWSTR subkey
, LPCWSTR filename
)
1581 DWORD ret
, len
, err
= GetLastError();
1584 TRACE( "(%p,%s,%s)\n", hkey
, debugstr_w(subkey
), debugstr_w(filename
) );
1586 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1587 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1588 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1590 len
= strlenW( subkey
) * sizeof(WCHAR
);
1591 if (len
> MAX_PATH
*sizeof(WCHAR
)) return ERROR_INVALID_PARAMETER
;
1593 if ((file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1594 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1596 ret
= GetLastError();
1600 RegCreateKeyW(hkey
,subkey
,&shkey
);
1602 SERVER_START_REQ( load_registry
)
1606 wine_server_add_data( req
, subkey
, len
);
1607 ret
= RtlNtStatusToDosError( wine_server_call(req
) );
1610 CloseHandle( file
);
1614 SetLastError( err
); /* restore the last error code */
1619 /******************************************************************************
1620 * RegLoadKeyA [ADVAPI32.@]
1624 LONG WINAPI
RegLoadKeyA( HKEY hkey
, LPCSTR subkey
, LPCSTR filename
)
1626 WCHAR buffer
[MAX_PATH
];
1628 DWORD ret
, len
, err
= GetLastError();
1631 TRACE( "(%p,%s,%s)\n", hkey
, debugstr_a(subkey
), debugstr_a(filename
) );
1633 if (!filename
|| !*filename
) return ERROR_INVALID_PARAMETER
;
1634 if (!subkey
|| !*subkey
) return ERROR_INVALID_PARAMETER
;
1635 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1637 if (!(len
= MultiByteToWideChar( CP_ACP
, 0, subkey
, strlen(subkey
), buffer
, MAX_PATH
)))
1638 return ERROR_INVALID_PARAMETER
;
1640 if ((file
= CreateFileA( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
1641 FILE_ATTRIBUTE_NORMAL
, 0 )) == INVALID_HANDLE_VALUE
)
1643 ret
= GetLastError();
1647 RegCreateKeyA(hkey
,subkey
,&shkey
);
1649 SERVER_START_REQ( load_registry
)
1653 wine_server_add_data( req
, buffer
, len
* sizeof(WCHAR
) );
1654 ret
= RtlNtStatusToDosError( wine_server_call(req
) );
1657 CloseHandle( file
);
1661 SetLastError( err
); /* restore the last error code */
1666 /******************************************************************************
1667 * RegSaveKeyW [ADVAPI32.@]
1670 * hkey [I] Handle of key where save begins
1671 * lpFile [I] Address of filename to save to
1672 * sa [I] Address of security structure
1675 * Success: ERROR_SUCCESS
1676 * Failure: nonzero error code from Winerror.h
1678 LONG WINAPI
RegSaveKeyW( HKEY hkey
, LPCWSTR file
, LPSECURITY_ATTRIBUTES sa
)
1680 static const WCHAR format
[] =
1681 {'r','e','g','%','0','4','x','.','t','m','p',0};
1682 WCHAR buffer
[MAX_PATH
];
1688 TRACE( "(%p,%s,%p)\n", hkey
, debugstr_w(file
), sa
);
1690 if (!file
|| !*file
) return ERROR_INVALID_PARAMETER
;
1691 if (!(hkey
= get_special_root_hkey( hkey
))) return ERROR_INVALID_HANDLE
;
1693 err
= GetLastError();
1694 GetFullPathNameW( file
, sizeof(buffer
)/sizeof(WCHAR
), buffer
, &nameW
);
1698 snprintfW( nameW
, 16, format
, count
++ );
1699 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
,
1700 CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1701 if (handle
!= INVALID_HANDLE_VALUE
) break;
1702 if ((ret
= GetLastError()) != ERROR_ALREADY_EXISTS
) goto done
;
1704 /* Something gone haywire ? Please report if this happens abnormally */
1706 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
);
1709 SERVER_START_REQ( save_registry
)
1713 ret
= RtlNtStatusToDosError( wine_server_call( req
) );
1717 CloseHandle( handle
);
1720 if (!MoveFileExW( buffer
, file
, MOVEFILE_REPLACE_EXISTING
))
1722 ERR( "Failed to move %s to %s\n", debugstr_w(buffer
),
1724 ret
= GetLastError();
1727 if (ret
) DeleteFileW( buffer
);
1730 SetLastError( err
); /* restore last error code */
1735 /******************************************************************************
1736 * RegSaveKeyA [ADVAPI32.@]
1740 LONG WINAPI
RegSaveKeyA( HKEY hkey
, LPCSTR file
, LPSECURITY_ATTRIBUTES sa
)
1742 UNICODE_STRING
*fileW
= &NtCurrentTeb()->StaticUnicodeString
;
1746 RtlInitAnsiString(&fileA
, file
);
1747 if ((status
= RtlAnsiStringToUnicodeString(fileW
, &fileA
, FALSE
)))
1748 return RtlNtStatusToDosError( status
);
1749 return RegSaveKeyW(hkey
, fileW
->Buffer
, sa
);
1753 /******************************************************************************
1754 * RegRestoreKeyW [ADVAPI32.@]
1757 * hkey [I] Handle of key where restore begins
1758 * lpFile [I] Address of filename containing saved tree
1759 * dwFlags [I] Optional flags
1762 * Success: ERROR_SUCCESS
1763 * Failure: nonzero error code from Winerror.h
1765 LONG WINAPI
RegRestoreKeyW( HKEY hkey
, LPCWSTR lpFile
, DWORD dwFlags
)
1767 TRACE("(%p,%s,%ld)\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1769 /* It seems to do this check before the hkey check */
1770 if (!lpFile
|| !*lpFile
)
1771 return ERROR_INVALID_PARAMETER
;
1773 FIXME("(%p,%s,%ld): stub\n",hkey
,debugstr_w(lpFile
),dwFlags
);
1775 /* Check for file existence */
1777 return ERROR_SUCCESS
;
1781 /******************************************************************************
1782 * RegRestoreKeyA [ADVAPI32.@]
1784 * see RegRestoreKeyW
1786 LONG WINAPI
RegRestoreKeyA( HKEY hkey
, LPCSTR lpFile
, DWORD dwFlags
)
1788 UNICODE_STRING lpFileW
;
1791 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, lpFile
);
1792 ret
= RegRestoreKeyW( hkey
, lpFileW
.Buffer
, dwFlags
);
1793 RtlFreeUnicodeString( &lpFileW
);
1798 /******************************************************************************
1799 * RegUnLoadKeyW [ADVAPI32.@]
1802 * hkey [I] Handle of open key
1803 * lpSubKey [I] Address of name of subkey to unload
1806 * Success: ERROR_SUCCESS
1807 * Failure: nonzero error code from Winerror.h
1809 LONG WINAPI
RegUnLoadKeyW( HKEY hkey
, LPCWSTR lpSubKey
)
1814 TRACE("(%p,%s)\n",hkey
, debugstr_w(lpSubKey
));
1816 ret
= RegOpenKeyW(hkey
,lpSubKey
,&shkey
);
1818 return ERROR_INVALID_PARAMETER
;
1820 SERVER_START_REQ( unload_registry
)
1823 ret
= RtlNtStatusToDosError( wine_server_call(req
) );
1832 /******************************************************************************
1833 * RegUnLoadKeyA [ADVAPI32.@]
1837 LONG WINAPI
RegUnLoadKeyA( HKEY hkey
, LPCSTR lpSubKey
)
1839 UNICODE_STRING lpSubKeyW
;
1842 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
1843 ret
= RegUnLoadKeyW( hkey
, lpSubKeyW
.Buffer
);
1844 RtlFreeUnicodeString( &lpSubKeyW
);
1849 /******************************************************************************
1850 * RegReplaceKeyW [ADVAPI32.@]
1853 * hkey [I] Handle of open key
1854 * lpSubKey [I] Address of name of subkey
1855 * lpNewFile [I] Address of filename for file with new data
1856 * lpOldFile [I] Address of filename for backup file
1859 * Success: ERROR_SUCCESS
1860 * Failure: nonzero error code from Winerror.h
1862 LONG WINAPI
RegReplaceKeyW( HKEY hkey
, LPCWSTR lpSubKey
, LPCWSTR lpNewFile
,
1865 FIXME("(%p,%s,%s,%s): stub\n", hkey
, debugstr_w(lpSubKey
),
1866 debugstr_w(lpNewFile
),debugstr_w(lpOldFile
));
1867 return ERROR_SUCCESS
;
1871 /******************************************************************************
1872 * RegReplaceKeyA [ADVAPI32.@]
1874 * see RegReplaceKeyW
1876 LONG WINAPI
RegReplaceKeyA( HKEY hkey
, LPCSTR lpSubKey
, LPCSTR lpNewFile
,
1879 UNICODE_STRING lpSubKeyW
;
1880 UNICODE_STRING lpNewFileW
;
1881 UNICODE_STRING lpOldFileW
;
1884 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, lpSubKey
);
1885 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, lpOldFile
);
1886 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, lpNewFile
);
1887 ret
= RegReplaceKeyW( hkey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
1888 RtlFreeUnicodeString( &lpOldFileW
);
1889 RtlFreeUnicodeString( &lpNewFileW
);
1890 RtlFreeUnicodeString( &lpSubKeyW
);
1895 /******************************************************************************
1896 * RegSetKeySecurity [ADVAPI32.@]
1899 * hkey [I] Open handle of key to set
1900 * SecurityInfo [I] Descriptor contents
1901 * pSecurityDesc [I] Address of descriptor for key
1904 * Success: ERROR_SUCCESS
1905 * Failure: nonzero error code from Winerror.h
1907 LONG WINAPI
RegSetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInfo
,
1908 PSECURITY_DESCRIPTOR pSecurityDesc
)
1910 TRACE("(%p,%ld,%p)\n",hkey
,SecurityInfo
,pSecurityDesc
);
1912 /* It seems to perform this check before the hkey check */
1913 if ((SecurityInfo
& OWNER_SECURITY_INFORMATION
) ||
1914 (SecurityInfo
& GROUP_SECURITY_INFORMATION
) ||
1915 (SecurityInfo
& DACL_SECURITY_INFORMATION
) ||
1916 (SecurityInfo
& SACL_SECURITY_INFORMATION
)) {
1919 return ERROR_INVALID_PARAMETER
;
1922 return ERROR_INVALID_PARAMETER
;
1924 FIXME(":(%p,%ld,%p): stub\n",hkey
,SecurityInfo
,pSecurityDesc
);
1926 return ERROR_SUCCESS
;
1930 /******************************************************************************
1931 * RegGetKeySecurity [ADVAPI32.@]
1933 * Get a copy of the security descriptor for a given registry key.
1936 * hkey [I] Open handle of key to set
1937 * SecurityInformation [I] Descriptor contents
1938 * pSecurityDescriptor [O] Address of descriptor for key
1939 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1942 * Success: ERROR_SUCCESS
1943 * Failure: Error code
1945 LONG WINAPI
RegGetKeySecurity( HKEY hkey
, SECURITY_INFORMATION SecurityInformation
,
1946 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1947 LPDWORD lpcbSecurityDescriptor
)
1949 TRACE("(%p,%ld,%p,%ld)\n",hkey
,SecurityInformation
,pSecurityDescriptor
,
1950 lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1952 /* FIXME: Check for valid SecurityInformation values */
1954 if (*lpcbSecurityDescriptor
< sizeof(SECURITY_DESCRIPTOR
))
1955 return ERROR_INSUFFICIENT_BUFFER
;
1957 FIXME("(%p,%ld,%p,%ld): stub\n",hkey
,SecurityInformation
,
1958 pSecurityDescriptor
,lpcbSecurityDescriptor
?*lpcbSecurityDescriptor
:0);
1960 /* Do not leave security descriptor filled with garbage */
1961 RtlCreateSecurityDescriptor(pSecurityDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
1963 return ERROR_SUCCESS
;
1967 /******************************************************************************
1968 * RegFlushKey [ADVAPI32.@]
1970 * Immediately write a registry key to registry.
1973 * hkey [I] Handle of key to write
1976 * Success: ERROR_SUCCESS
1977 * Failure: Error code
1979 DWORD WINAPI
RegFlushKey( HKEY hkey
)
1981 hkey
= get_special_root_hkey( hkey
);
1982 if (!hkey
) return ERROR_INVALID_HANDLE
;
1984 return RtlNtStatusToDosError( NtFlushKey( hkey
) );
1988 /******************************************************************************
1989 * RegConnectRegistryW [ADVAPI32.@]
1992 * lpMachineName [I] Address of name of remote computer
1993 * hHey [I] Predefined registry handle
1994 * phkResult [I] Address of buffer for remote registry handle
1997 * Success: ERROR_SUCCESS
1998 * Failure: nonzero error code from Winerror.h
2000 LONG WINAPI
RegConnectRegistryW( LPCWSTR lpMachineName
, HKEY hKey
,
2005 TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName
),hKey
,phkResult
);
2007 if (!lpMachineName
|| !*lpMachineName
) {
2008 /* Use the local machine name */
2009 ret
= RegOpenKeyW( hKey
, NULL
, phkResult
);
2011 else if (lpMachineName
[0] != '\\' || lpMachineName
[1] != '\\')
2012 ret
= ERROR_BAD_NETPATH
;
2015 WCHAR compName
[MAX_COMPUTERNAME_LENGTH
+ 1];
2016 DWORD len
= sizeof(compName
) / sizeof(WCHAR
);
2018 if (GetComputerNameW(compName
, &len
))
2020 if (!strcmpiW(lpMachineName
+ 2, compName
))
2021 ret
= RegOpenKeyW(hKey
, NULL
, phkResult
);
2024 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName
));
2025 ret
= ERROR_BAD_NETPATH
;
2029 ret
= GetLastError();
2035 /******************************************************************************
2036 * RegConnectRegistryA [ADVAPI32.@]
2038 * see RegConnectRegistryW
2040 LONG WINAPI
RegConnectRegistryA( LPCSTR machine
, HKEY hkey
, PHKEY reskey
)
2042 UNICODE_STRING machineW
;
2045 RtlCreateUnicodeStringFromAsciiz( &machineW
, machine
);
2046 ret
= RegConnectRegistryW( machineW
.Buffer
, hkey
, reskey
);
2047 RtlFreeUnicodeString( &machineW
);
2052 /******************************************************************************
2053 * RegNotifyChangeKeyValue [ADVAPI32.@]
2056 * hkey [I] Handle of key to watch
2057 * fWatchSubTree [I] Flag for subkey notification
2058 * fdwNotifyFilter [I] Changes to be reported
2059 * hEvent [I] Handle of signaled event
2060 * fAsync [I] Flag for asynchronous reporting
2063 * Success: ERROR_SUCCESS
2064 * Failure: nonzero error code from Winerror.h
2066 LONG WINAPI
RegNotifyChangeKeyValue( HKEY hkey
, BOOL fWatchSubTree
,
2067 DWORD fdwNotifyFilter
, HANDLE hEvent
,
2072 TRACE("(%p,%i,%ld,%p,%i)\n",hkey
,fWatchSubTree
,fdwNotifyFilter
,
2076 hEvent
= CreateEventA(NULL
, 0, 0, NULL
);
2078 SERVER_START_REQ( set_registry_notification
)
2081 req
->event
= hEvent
;
2082 req
->subtree
= fWatchSubTree
;
2083 req
->filter
= fdwNotifyFilter
;
2084 ret
= RtlNtStatusToDosError( wine_server_call(req
) );
2090 if( ret
== ERROR_SUCCESS
)
2091 WaitForSingleObject( hEvent
, INFINITE
);
2092 CloseHandle( hEvent
);
2098 /******************************************************************************
2099 * RegOpenUserClassesRoot [ADVAPI32.@]
2101 * Open the HKEY_CLASSES_ROOT key for a user.
2104 * hToken [I] Handle of token representing the user
2105 * dwOptions [I] Reserved, nust be 0
2106 * samDesired [I] Desired access rights
2107 * phkResult [O] Destination for the resulting key handle
2110 * Success: ERROR_SUCCESS
2111 * Failure: nonzero error code from Winerror.h
2114 * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the
2115 * "HKEY_LOCAL_MACHINE\Software\Classes" and the
2116 * "HKEY_CURRENT_USER\Software\Classes" keys merged together.
2118 LONG WINAPI
RegOpenUserClassesRoot(
2125 FIXME("(%p, 0x%lx, 0x%lx, %p) semi-stub\n", hToken
, dwOptions
, samDesired
, phkResult
);
2127 *phkResult
= HKEY_CLASSES_ROOT
;
2128 return ERROR_SUCCESS
;