3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/reg/reg.c
6 * PURPOSE: Registry functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
11 * 20050502 Fireball imported some stuff from WINE
14 /* INCLUDES *****************************************************************/
18 #include <wine/debug.h>
20 /* DEFINES ******************************************************************/
22 #define MAX_DEFAULT_HANDLES 6
23 #define REG_MAX_NAME_SIZE 256
24 #define REG_MAX_DATA_SIZE 2048
26 /* FIXME: should go into msvcrt.h header? */
27 #define offsetof(s,m) (size_t)&(((s*)NULL)->m)
29 /* GLOBALS ******************************************************************/
31 static RTL_CRITICAL_SECTION HandleTableCS
;
32 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
33 static HANDLE ProcessHeap
;
35 /* PROTOTYPES ***************************************************************/
37 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
38 static VOID
CloseDefaultKeys(VOID
);
40 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
41 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
42 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
43 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
46 /* FUNCTIONS ****************************************************************/
47 /* check if value type needs string conversion (Ansi<->Unicode) */
48 inline static int is_string( DWORD type
)
50 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
53 /************************************************************************
54 * RegInitDefaultHandles
59 TRACE("RegInitialize()\n");
61 ProcessHeap
= RtlGetProcessHeap();
62 RtlZeroMemory (DefaultHandleTable
,
63 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
64 RtlInitializeCriticalSection (&HandleTableCS
);
70 /************************************************************************
76 TRACE("RegCleanup()\n");
79 RtlDeleteCriticalSection (&HandleTableCS
);
86 MapDefaultKey (PHANDLE RealKey
,
91 NTSTATUS Status
= STATUS_SUCCESS
;
93 TRACE("MapDefaultKey (Key %x)\n", Key
);
95 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
97 *RealKey
= (HANDLE
)Key
;
98 return STATUS_SUCCESS
;
101 /* Handle special cases here */
102 Index
= (ULONG
)Key
& 0x0FFFFFFF;
103 if (Index
>= MAX_DEFAULT_HANDLES
)
105 return STATUS_INVALID_PARAMETER
;
108 RtlEnterCriticalSection (&HandleTableCS
);
109 Handle
= &DefaultHandleTable
[Index
];
112 /* create/open the default handle */
115 case 0: /* HKEY_CLASSES_ROOT */
116 Status
= OpenClassesRootKey (Handle
);
119 case 1: /* HKEY_CURRENT_USER */
120 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
124 case 2: /* HKEY_LOCAL_MACHINE */
125 Status
= OpenLocalMachineKey (Handle
);
128 case 3: /* HKEY_USERS */
129 Status
= OpenUsersKey (Handle
);
132 case 4: /* HKEY_PERFORMANCE_DATA */
133 Status
= OpenPerformanceDataKey (Handle
);
136 case 5: /* HKEY_CURRENT_CONFIG */
137 Status
= OpenCurrentConfigKey (Handle
);
140 case 6: /* HKEY_DYN_DATA */
141 Status
= STATUS_NOT_IMPLEMENTED
;
145 WARN("MapDefaultHandle() no handle creator\n");
146 Status
= STATUS_INVALID_PARAMETER
;
149 RtlLeaveCriticalSection (&HandleTableCS
);
151 if (NT_SUCCESS(Status
))
161 CloseDefaultKeys (VOID
)
165 RtlEnterCriticalSection (&HandleTableCS
);
166 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
168 if (DefaultHandleTable
[i
] != NULL
)
170 NtClose (DefaultHandleTable
[i
]);
171 DefaultHandleTable
[i
] = NULL
;
174 RtlLeaveCriticalSection (&HandleTableCS
);
179 OpenClassesRootKey (PHANDLE KeyHandle
)
181 OBJECT_ATTRIBUTES Attributes
;
182 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\CLASSES");
184 TRACE("OpenClassesRootKey()\n");
186 InitializeObjectAttributes (&Attributes
,
188 OBJ_CASE_INSENSITIVE
,
191 return NtOpenKey (KeyHandle
,
198 OpenLocalMachineKey (PHANDLE KeyHandle
)
200 OBJECT_ATTRIBUTES Attributes
;
201 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine");
204 TRACE("OpenLocalMachineKey()\n");
206 InitializeObjectAttributes (&Attributes
,
208 OBJ_CASE_INSENSITIVE
,
211 Status
= NtOpenKey (KeyHandle
,
215 TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
221 OpenUsersKey (PHANDLE KeyHandle
)
223 OBJECT_ATTRIBUTES Attributes
;
224 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\User");
226 TRACE("OpenUsersKey()\n");
228 InitializeObjectAttributes (&Attributes
,
230 OBJ_CASE_INSENSITIVE
,
233 return NtOpenKey (KeyHandle
,
240 OpenCurrentConfigKey (PHANDLE KeyHandle
)
242 OBJECT_ATTRIBUTES Attributes
;
243 UNICODE_STRING KeyName
=
244 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
246 TRACE("OpenCurrentConfigKey()\n");
248 InitializeObjectAttributes (&Attributes
,
250 OBJ_CASE_INSENSITIVE
,
253 return NtOpenKey (KeyHandle
,
259 /************************************************************************
265 RegCloseKey (HKEY hKey
)
269 /* don't close null handle or a pseudo handle */
270 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
272 return ERROR_INVALID_HANDLE
;
275 Status
= NtClose (hKey
);
276 if (!NT_SUCCESS(Status
))
278 return RtlNtStatusToDosError (Status
);
281 return ERROR_SUCCESS
;
285 /************************************************************************
286 * RegConnectRegistryA
291 RegConnectRegistryA (LPCSTR lpMachineName
,
295 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
296 return ERROR_CALL_NOT_IMPLEMENTED
;
300 /************************************************************************
306 RegCopyTreeW(IN HKEY hKeySrc
,
307 IN LPCWSTR lpSubKey OPTIONAL
,
310 HANDLE DestKeyHandle
, KeyHandle
, SubKeyHandle
= NULL
;
313 Status
= MapDefaultKey(&KeyHandle
,
315 if (!NT_SUCCESS(Status
))
317 return RtlNtStatusToDosError(Status
);
320 Status
= MapDefaultKey(&DestKeyHandle
,
322 if (!NT_SUCCESS(Status
))
324 return RtlNtStatusToDosError(Status
);
327 if (lpSubKey
!= NULL
)
329 OBJECT_ATTRIBUTES ObjectAttributes
;
330 UNICODE_STRING SubKeyName
;
332 RtlInitUnicodeString(&SubKeyName
,
335 InitializeObjectAttributes(&ObjectAttributes
,
337 OBJ_CASE_INSENSITIVE
,
341 Status
= NtOpenKey(&SubKeyHandle
,
344 if (!NT_SUCCESS(Status
))
346 return RtlNtStatusToDosError(Status
);
350 /* FIXME - copy all keys and values recursively */
351 Status
= STATUS_NOT_IMPLEMENTED
;
353 if (SubKeyHandle
!= NULL
)
355 NtClose(SubKeyHandle
);
358 if (!NT_SUCCESS(Status
))
360 return RtlNtStatusToDosError(Status
);
363 return ERROR_SUCCESS
;
367 /************************************************************************
373 RegCopyTreeA(IN HKEY hKeySrc
,
374 IN LPCSTR lpSubKey OPTIONAL
,
377 UNICODE_STRING SubKeyName
;
380 if (lpSubKey
!= NULL
)
382 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
385 return ERROR_NOT_ENOUGH_MEMORY
;
389 RtlInitUnicodeString(&SubKeyName
,
392 Ret
= RegCopyTreeW(hKeySrc
,
396 RtlFreeUnicodeString(&SubKeyName
);
402 /************************************************************************
403 * RegConnectRegistryW
408 RegConnectRegistryW (LPCWSTR lpMachineName
,
412 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
413 return ERROR_CALL_NOT_IMPLEMENTED
;
417 /************************************************************************
420 * Create key and all necessary intermediate keys
423 CreateNestedKey(PHKEY KeyHandle
,
424 POBJECT_ATTRIBUTES ObjectAttributes
,
425 PUNICODE_STRING ClassString
,
428 DWORD
*lpdwDisposition
)
430 OBJECT_ATTRIBUTES LocalObjectAttributes
;
431 UNICODE_STRING LocalKeyName
;
434 ULONG FullNameLength
;
437 HANDLE LocalKeyHandle
;
439 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
445 (PULONG
)lpdwDisposition
);
446 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
447 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
450 /* Copy object attributes */
451 RtlCopyMemory (&LocalObjectAttributes
,
453 sizeof(OBJECT_ATTRIBUTES
));
454 RtlCreateUnicodeString (&LocalKeyName
,
455 ObjectAttributes
->ObjectName
->Buffer
);
456 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
457 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
459 /* Remove the last part of the key name and try to create the key again. */
460 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
462 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
463 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
465 Status
= STATUS_UNSUCCESSFUL
;
469 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
471 Status
= NtCreateKey (&LocalKeyHandle
,
473 &LocalObjectAttributes
,
478 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
481 if (!NT_SUCCESS(Status
))
483 RtlFreeUnicodeString (&LocalKeyName
);
487 /* Add removed parts of the key name and create them too. */
488 Length
= wcslen (LocalKeyName
.Buffer
);
491 NtClose (LocalKeyHandle
);
493 LocalKeyName
.Buffer
[Length
] = L
'\\';
494 Length
= wcslen (LocalKeyName
.Buffer
);
495 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
497 if (Length
== FullNameLength
)
499 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
505 (PULONG
)lpdwDisposition
);
508 Status
= NtCreateKey (&LocalKeyHandle
,
510 &LocalObjectAttributes
,
515 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
516 if (!NT_SUCCESS(Status
))
520 RtlFreeUnicodeString (&LocalKeyName
);
526 /************************************************************************
532 RegCreateKeyExA (HKEY hKey
,
538 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
540 LPDWORD lpdwDisposition
)
542 UNICODE_STRING SubKeyString
;
543 UNICODE_STRING ClassString
;
544 OBJECT_ATTRIBUTES Attributes
;
548 TRACE("RegCreateKeyExA() called\n");
550 /* get the real parent key */
551 Status
= MapDefaultKey (&ParentKey
,
553 if (!NT_SUCCESS(Status
))
555 return RtlNtStatusToDosError (Status
);
557 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
561 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
565 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
567 InitializeObjectAttributes (&Attributes
,
569 OBJ_CASE_INSENSITIVE
,
571 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
572 Status
= CreateNestedKey(phkResult
,
574 (lpClass
== NULL
)? NULL
: &ClassString
,
578 RtlFreeUnicodeString (&SubKeyString
);
581 RtlFreeUnicodeString (&ClassString
);
584 TRACE("Status %x\n", Status
);
585 if (!NT_SUCCESS(Status
))
587 return RtlNtStatusToDosError (Status
);
590 return ERROR_SUCCESS
;
594 /************************************************************************
600 RegCreateKeyExW (HKEY hKey
,
606 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
608 LPDWORD lpdwDisposition
)
610 UNICODE_STRING SubKeyString
;
611 UNICODE_STRING ClassString
;
612 OBJECT_ATTRIBUTES Attributes
;
616 TRACE("RegCreateKeyExW() called\n");
618 /* get the real parent key */
619 Status
= MapDefaultKey (&ParentKey
,
621 if (!NT_SUCCESS(Status
))
623 return RtlNtStatusToDosError(Status
);
625 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
627 RtlInitUnicodeString (&ClassString
,
629 RtlInitUnicodeString (&SubKeyString
,
631 InitializeObjectAttributes (&Attributes
,
633 OBJ_CASE_INSENSITIVE
,
635 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
636 Status
= CreateNestedKey(phkResult
,
638 (lpClass
== NULL
)? NULL
: &ClassString
,
642 TRACE("Status %x\n", Status
);
643 if (!NT_SUCCESS(Status
))
645 return RtlNtStatusToDosError (Status
);
648 return ERROR_SUCCESS
;
652 /************************************************************************
658 RegCreateKeyA (HKEY hKey
,
662 return RegCreateKeyExA (hKey
,
674 /************************************************************************
680 RegCreateKeyW (HKEY hKey
,
684 return RegCreateKeyExW (hKey
,
696 /************************************************************************
702 RegDeleteKeyA (HKEY hKey
,
705 OBJECT_ATTRIBUTES ObjectAttributes
;
706 UNICODE_STRING SubKeyName
;
711 Status
= MapDefaultKey (&ParentKey
,
713 if (!NT_SUCCESS(Status
))
715 return RtlNtStatusToDosError (Status
);
718 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
720 InitializeObjectAttributes(&ObjectAttributes
,
722 OBJ_CASE_INSENSITIVE
,
726 Status
= NtOpenKey (&TargetKey
,
729 RtlFreeUnicodeString (&SubKeyName
);
730 if (!NT_SUCCESS(Status
))
732 return RtlNtStatusToDosError (Status
);
735 Status
= NtDeleteKey (TargetKey
);
737 if (!NT_SUCCESS(Status
))
739 return RtlNtStatusToDosError(Status
);
742 return ERROR_SUCCESS
;
746 /************************************************************************
752 RegDeleteKeyW (HKEY hKey
,
755 OBJECT_ATTRIBUTES ObjectAttributes
;
756 UNICODE_STRING SubKeyName
;
761 Status
= MapDefaultKey (&ParentKey
,
763 if (!NT_SUCCESS(Status
))
765 return RtlNtStatusToDosError (Status
);
768 RtlInitUnicodeString (&SubKeyName
,
770 InitializeObjectAttributes (&ObjectAttributes
,
772 OBJ_CASE_INSENSITIVE
,
775 Status
= NtOpenKey (&TargetKey
,
778 if (!NT_SUCCESS(Status
))
780 return RtlNtStatusToDosError (Status
);
783 Status
= NtDeleteKey (TargetKey
);
785 if (!NT_SUCCESS(Status
))
787 return RtlNtStatusToDosError (Status
);
790 return ERROR_SUCCESS
;
794 /************************************************************************
800 RegDeleteKeyValueW(IN HKEY hKey
,
801 IN LPCWSTR lpSubKey OPTIONAL
,
802 IN LPCWSTR lpValueName OPTIONAL
)
804 UNICODE_STRING ValueName
;
805 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
808 Status
= MapDefaultKey(&KeyHandle
,
810 if (!NT_SUCCESS(Status
))
812 return RtlNtStatusToDosError(Status
);
815 if (lpSubKey
!= NULL
)
817 OBJECT_ATTRIBUTES ObjectAttributes
;
818 UNICODE_STRING SubKeyName
;
820 RtlInitUnicodeString(&SubKeyName
,
823 InitializeObjectAttributes(&ObjectAttributes
,
825 OBJ_CASE_INSENSITIVE
,
829 Status
= NtOpenKey(&SubKeyHandle
,
832 if (!NT_SUCCESS(Status
))
834 return RtlNtStatusToDosError(Status
);
837 KeyHandle
= SubKeyHandle
;
840 RtlInitUnicodeString(&ValueName
,
841 (LPWSTR
)lpValueName
);
843 Status
= NtDeleteValueKey(KeyHandle
,
846 if (SubKeyHandle
!= NULL
)
848 NtClose(SubKeyHandle
);
851 if (!NT_SUCCESS(Status
))
853 return RtlNtStatusToDosError(Status
);
856 return ERROR_SUCCESS
;
860 /************************************************************************
866 RegDeleteKeyValueA(IN HKEY hKey
,
867 IN LPCSTR lpSubKey OPTIONAL
,
868 IN LPCSTR lpValueName OPTIONAL
)
870 UNICODE_STRING SubKey
, ValueName
;
873 if (lpSubKey
!= NULL
)
875 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey
,
878 return ERROR_NOT_ENOUGH_MEMORY
;
882 RtlInitUnicodeString(&SubKey
,
885 if (lpValueName
!= NULL
)
887 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName
,
890 RtlFreeUnicodeString(&SubKey
);
891 return ERROR_NOT_ENOUGH_MEMORY
;
895 RtlInitUnicodeString(&ValueName
,
898 Ret
= RegDeleteKeyValueW(hKey
,
902 RtlFreeUnicodeString(&SubKey
);
903 RtlFreeUnicodeString(&ValueName
);
909 /************************************************************************
915 RegDeleteTreeW(IN HKEY hKey
,
916 IN LPCWSTR lpSubKey OPTIONAL
)
918 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
921 Status
= MapDefaultKey(&KeyHandle
,
923 if (!NT_SUCCESS(Status
))
925 return RtlNtStatusToDosError(Status
);
928 if (lpSubKey
!= NULL
)
930 OBJECT_ATTRIBUTES ObjectAttributes
;
931 UNICODE_STRING SubKeyName
;
933 RtlInitUnicodeString(&SubKeyName
,
936 InitializeObjectAttributes(&ObjectAttributes
,
938 OBJ_CASE_INSENSITIVE
,
942 Status
= NtOpenKey(&SubKeyHandle
,
943 DELETE
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
945 if (!NT_SUCCESS(Status
))
947 return RtlNtStatusToDosError(Status
);
950 KeyHandle
= SubKeyHandle
;
953 /* FIXME - delete all keys recursively */
954 Status
= STATUS_NOT_IMPLEMENTED
;
956 if (SubKeyHandle
!= NULL
)
958 NtClose(SubKeyHandle
);
961 if (!NT_SUCCESS(Status
))
963 return RtlNtStatusToDosError(Status
);
966 return ERROR_SUCCESS
;
970 /************************************************************************
976 RegDeleteTreeA(IN HKEY hKey
,
977 IN LPCSTR lpSubKey OPTIONAL
)
979 UNICODE_STRING SubKeyName
;
982 if (lpSubKey
!= NULL
)
984 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
987 return ERROR_NOT_ENOUGH_MEMORY
;
991 RtlInitUnicodeString(&SubKeyName
,
994 Ret
= RegDeleteTreeW(hKey
,
997 RtlFreeUnicodeString(&SubKeyName
);
1003 /************************************************************************
1009 RegSetKeyValueW(IN HKEY hKey
,
1010 IN LPCWSTR lpSubKey OPTIONAL
,
1011 IN LPCWSTR lpValueName OPTIONAL
,
1013 IN LPCVOID lpData OPTIONAL
,
1016 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
1020 Status
= MapDefaultKey(&KeyHandle
,
1022 if (!NT_SUCCESS(Status
))
1024 return RtlNtStatusToDosError(Status
);
1027 if (lpSubKey
!= NULL
)
1029 OBJECT_ATTRIBUTES ObjectAttributes
;
1030 UNICODE_STRING SubKeyName
;
1032 RtlInitUnicodeString(&SubKeyName
,
1035 InitializeObjectAttributes(&ObjectAttributes
,
1037 OBJ_CASE_INSENSITIVE
,
1041 Status
= NtOpenKey(&SubKeyHandle
,
1044 if (!NT_SUCCESS(Status
))
1046 return RtlNtStatusToDosError(Status
);
1049 KeyHandle
= SubKeyHandle
;
1052 Ret
= RegSetValueExW(KeyHandle
,
1059 if (SubKeyHandle
!= NULL
)
1061 NtClose(SubKeyHandle
);
1068 /************************************************************************
1074 RegSetKeyValueA(IN HKEY hKey
,
1075 IN LPCSTR lpSubKey OPTIONAL
,
1076 IN LPCSTR lpValueName OPTIONAL
,
1078 IN LPCVOID lpData OPTIONAL
,
1081 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
1085 Status
= MapDefaultKey(&KeyHandle
,
1087 if (!NT_SUCCESS(Status
))
1089 return RtlNtStatusToDosError(Status
);
1092 if (lpSubKey
!= NULL
)
1094 OBJECT_ATTRIBUTES ObjectAttributes
;
1095 UNICODE_STRING SubKeyName
;
1097 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1100 return ERROR_NOT_ENOUGH_MEMORY
;
1103 InitializeObjectAttributes(&ObjectAttributes
,
1105 OBJ_CASE_INSENSITIVE
,
1109 Status
= NtOpenKey(&SubKeyHandle
,
1113 RtlFreeUnicodeString(&SubKeyName
);
1115 if (!NT_SUCCESS(Status
))
1117 return RtlNtStatusToDosError(Status
);
1120 KeyHandle
= SubKeyHandle
;
1123 Ret
= RegSetValueExA(KeyHandle
,
1130 if (SubKeyHandle
!= NULL
)
1132 NtClose(SubKeyHandle
);
1139 /************************************************************************
1145 RegDeleteValueA (HKEY hKey
,
1148 UNICODE_STRING ValueName
;
1152 Status
= MapDefaultKey (&KeyHandle
,
1154 if (!NT_SUCCESS(Status
))
1156 return RtlNtStatusToDosError (Status
);
1159 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
1160 (LPSTR
)lpValueName
);
1161 Status
= NtDeleteValueKey (KeyHandle
,
1163 RtlFreeUnicodeString (&ValueName
);
1164 if (!NT_SUCCESS(Status
))
1166 return RtlNtStatusToDosError (Status
);
1169 return ERROR_SUCCESS
;
1173 /************************************************************************
1179 RegDeleteValueW (HKEY hKey
,
1180 LPCWSTR lpValueName
)
1182 UNICODE_STRING ValueName
;
1186 Status
= MapDefaultKey (&KeyHandle
,
1188 if (!NT_SUCCESS(Status
))
1190 return RtlNtStatusToDosError (Status
);
1193 RtlInitUnicodeString (&ValueName
,
1194 (LPWSTR
)lpValueName
);
1196 Status
= NtDeleteValueKey (KeyHandle
,
1198 if (!NT_SUCCESS(Status
))
1200 return RtlNtStatusToDosError (Status
);
1203 return ERROR_SUCCESS
;
1207 /************************************************************************
1213 RegEnumKeyA (HKEY hKey
,
1221 return RegEnumKeyExA (hKey
,
1232 /************************************************************************
1238 RegEnumKeyW (HKEY hKey
,
1246 return RegEnumKeyExW (hKey
,
1257 /************************************************************************
1263 RegEnumKeyExA (HKEY hKey
,
1270 PFILETIME lpftLastWriteTime
)
1274 KEY_NODE_INFORMATION Node
;
1275 KEY_BASIC_INFORMATION Basic
;
1278 UNICODE_STRING StringU
;
1279 ANSI_STRING StringA
;
1280 LONG ErrorCode
= ERROR_SUCCESS
;
1282 DWORD ClassLength
= 0;
1288 TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
1289 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
1291 if ((lpClass
) && (!lpcbClass
))
1293 return ERROR_INVALID_PARAMETER
;
1296 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1297 if (!NT_SUCCESS(Status
))
1299 return RtlNtStatusToDosError (Status
);
1304 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1315 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1322 /* The class name should start at a dword boundary */
1323 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1327 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1330 KeyInfo
= RtlAllocateHeap (ProcessHeap
, 0, BufferSize
);
1331 if (KeyInfo
== NULL
)
1333 return ERROR_OUTOFMEMORY
;
1336 Status
= NtEnumerateKey (KeyHandle
,
1338 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
1342 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1343 if (!NT_SUCCESS(Status
))
1345 ErrorCode
= RtlNtStatusToDosError (Status
);
1349 if (lpClass
== NULL
)
1351 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1353 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1357 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
1358 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
1359 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
1364 if (KeyInfo
->Node
.NameLength
> NameLength
||
1365 KeyInfo
->Node
.ClassLength
> ClassLength
)
1367 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1371 StringA
.Buffer
= lpClass
;
1373 StringA
.MaximumLength
= *lpcbClass
;
1374 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
1375 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
1376 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
1377 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1378 lpClass
[StringA
.Length
] = 0;
1379 *lpcbClass
= StringA
.Length
;
1380 StringU
.Buffer
= KeyInfo
->Node
.Name
;
1381 StringU
.Length
= KeyInfo
->Node
.NameLength
;
1382 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
1386 if (ErrorCode
== ERROR_SUCCESS
)
1388 StringA
.Buffer
= lpName
;
1390 StringA
.MaximumLength
= *lpcbName
;
1391 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1392 lpName
[StringA
.Length
] = 0;
1393 *lpcbName
= StringA
.Length
;
1394 if (lpftLastWriteTime
!= NULL
)
1396 if (lpClass
== NULL
)
1398 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1399 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1403 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1404 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1410 TRACE("Key Namea0 Length %d\n", StringU
.Length
);
1411 TRACE("Key Namea1 Length %d\n", NameLength
);
1412 TRACE("Key Namea Length %d\n", *lpcbName
);
1413 TRACE("Key Namea %s\n", lpName
);
1415 RtlFreeHeap (ProcessHeap
,
1423 /************************************************************************
1429 RegEnumKeyExW (HKEY hKey
,
1436 PFILETIME lpftLastWriteTime
)
1440 KEY_NODE_INFORMATION Node
;
1441 KEY_BASIC_INFORMATION Basic
;
1447 ULONG ClassLength
= 0;
1449 LONG ErrorCode
= ERROR_SUCCESS
;
1452 Status
= MapDefaultKey(&KeyHandle
,
1454 if (!NT_SUCCESS(Status
))
1456 return RtlNtStatusToDosError (Status
);
1461 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1472 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1479 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1483 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1486 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1489 if (KeyInfo
== NULL
)
1491 return ERROR_OUTOFMEMORY
;
1494 Status
= NtEnumerateKey (KeyHandle
,
1496 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1500 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1501 if (!NT_SUCCESS(Status
))
1503 ErrorCode
= RtlNtStatusToDosError (Status
);
1507 if (lpClass
== NULL
)
1509 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1511 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1515 RtlCopyMemory (lpName
,
1516 KeyInfo
->Basic
.Name
,
1517 KeyInfo
->Basic
.NameLength
);
1518 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1519 lpName
[*lpcbName
] = 0;
1524 if (KeyInfo
->Node
.NameLength
> NameLength
||
1525 KeyInfo
->Node
.ClassLength
> ClassLength
)
1527 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1531 RtlCopyMemory (lpName
,
1533 KeyInfo
->Node
.NameLength
);
1534 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1535 lpName
[*lpcbName
] = 0;
1536 RtlCopyMemory (lpClass
,
1537 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1538 KeyInfo
->Node
.ClassLength
);
1539 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1540 lpClass
[*lpcbClass
] = 0;
1544 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1546 if (lpClass
== NULL
)
1548 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1549 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1553 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1554 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1559 RtlFreeHeap (ProcessHeap
,
1566 /************************************************************************
1572 RegEnumValueA( HKEY hKey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1573 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1578 char buffer
[256], *buf_ptr
= buffer
;
1579 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1580 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1582 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1583 // hkey, index, value, val_count, reserved, type, data, count );
1585 /* NT only checks count, not val_count */
1586 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1587 status
= MapDefaultKey (&KeyHandle
, hKey
);
1588 if (!NT_SUCCESS(status
))
1590 return RtlNtStatusToDosError (status
);
1593 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1594 if (data
) total_size
+= *count
;
1595 total_size
= min( sizeof(buffer
), total_size
);
1597 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1598 buffer
, total_size
, &total_size
);
1599 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1601 /* we need to fetch the contents for a string type even if not requested,
1602 * because we need to compute the length of the ASCII string. */
1603 if (value
|| data
|| is_string(info
->Type
))
1605 /* retry with a dynamically allocated buffer */
1606 while (status
== STATUS_BUFFER_OVERFLOW
)
1608 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1609 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1610 return ERROR_NOT_ENOUGH_MEMORY
;
1611 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1612 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1613 buf_ptr
, total_size
, &total_size
);
1616 if (status
) goto done
;
1618 if (is_string(info
->Type
))
1621 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1622 total_size
- info
->DataOffset
);
1625 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1628 RtlUnicodeToMultiByteN( (PCHAR
)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1629 total_size
- info
->DataOffset
);
1630 /* if the type is REG_SZ and data is not 0-terminated
1631 * and there is enough space in the buffer NT appends a \0 */
1632 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1635 info
->DataLength
= len
;
1639 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1640 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1643 if (value
&& !status
)
1647 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1648 if (len
>= *val_count
)
1650 status
= STATUS_BUFFER_OVERFLOW
;
1653 len
= *val_count
- 1;
1654 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1660 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1666 else status
= STATUS_SUCCESS
;
1668 if (type
) *type
= info
->Type
;
1669 if (count
) *count
= info
->DataLength
;
1672 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1673 return RtlNtStatusToDosError(status
);
1676 /******************************************************************************
1677 * RegEnumValueW [ADVAPI32.@]
1681 * hkey [I] Handle to key to query
1682 * index [I] Index of value to query
1683 * value [O] Value string
1684 * val_count [I/O] Size of value buffer (in wchars)
1685 * reserved [I] Reserved
1686 * type [O] Type code
1687 * data [O] Value data
1688 * count [I/O] Size of data buffer (in bytes)
1691 * Success: ERROR_SUCCESS
1692 * Failure: nonzero error code from Winerror.h
1695 RegEnumValueW( HKEY hKey
, DWORD index
, LPWSTR value
, PDWORD val_count
,
1696 PDWORD reserved
, PDWORD type
, LPBYTE data
, PDWORD count
)
1701 char buffer
[256], *buf_ptr
= buffer
;
1702 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1703 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1705 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1706 // hkey, index, value, val_count, reserved, type, data, count );
1708 /* NT only checks count, not val_count */
1709 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1711 status
= MapDefaultKey (&KeyHandle
, hKey
);
1712 if (!NT_SUCCESS(status
))
1714 return RtlNtStatusToDosError (status
);
1717 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1718 if (data
) total_size
+= *count
;
1719 total_size
= min( sizeof(buffer
), total_size
);
1721 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1722 buffer
, total_size
, &total_size
);
1723 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1727 /* retry with a dynamically allocated buffer */
1728 while (status
== STATUS_BUFFER_OVERFLOW
)
1730 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1731 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1732 return ERROR_NOT_ENOUGH_MEMORY
;
1733 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1734 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1735 buf_ptr
, total_size
, &total_size
);
1738 if (status
) goto done
;
1742 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1744 status
= STATUS_BUFFER_OVERFLOW
;
1747 memcpy( value
, info
->Name
, info
->NameLength
);
1748 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1749 value
[*val_count
] = 0;
1754 if (total_size
- info
->DataOffset
> *count
)
1756 status
= STATUS_BUFFER_OVERFLOW
;
1759 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1760 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1762 /* if the type is REG_SZ and data is not 0-terminated
1763 * and there is enough space in the buffer NT appends a \0 */
1764 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1765 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1769 else status
= STATUS_SUCCESS
;
1772 if (type
) *type
= info
->Type
;
1773 if (count
) *count
= info
->DataLength
;
1776 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1777 return RtlNtStatusToDosError(status
);
1780 /************************************************************************
1786 RegFlushKey(HKEY hKey
)
1791 if (hKey
== HKEY_PERFORMANCE_DATA
)
1793 return ERROR_SUCCESS
;
1796 Status
= MapDefaultKey (&KeyHandle
,
1798 if (!NT_SUCCESS(Status
))
1800 return RtlNtStatusToDosError (Status
);
1803 Status
= NtFlushKey (KeyHandle
);
1804 if (!NT_SUCCESS(Status
))
1806 return RtlNtStatusToDosError (Status
);
1809 return ERROR_SUCCESS
;
1813 /************************************************************************
1819 RegGetKeySecurity(HKEY hKey
,
1820 SECURITY_INFORMATION SecurityInformation
,
1821 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1822 LPDWORD lpcbSecurityDescriptor
)
1827 if (hKey
== HKEY_PERFORMANCE_DATA
)
1829 return ERROR_INVALID_HANDLE
;
1832 Status
= MapDefaultKey(&KeyHandle
,
1834 if (!NT_SUCCESS(Status
))
1836 TRACE("MapDefaultKey() failed (Status %lx)\n", Status
);
1837 return RtlNtStatusToDosError (Status
);
1840 Status
= NtQuerySecurityObject(KeyHandle
,
1841 SecurityInformation
,
1842 pSecurityDescriptor
,
1843 *lpcbSecurityDescriptor
,
1844 lpcbSecurityDescriptor
);
1845 if (!NT_SUCCESS(Status
))
1847 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
1848 return RtlNtStatusToDosError (Status
);
1851 return ERROR_SUCCESS
;
1855 /************************************************************************
1861 RegLoadKeyA (HKEY hKey
,
1865 UNICODE_STRING FileName
;
1866 UNICODE_STRING KeyName
;
1869 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1871 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1874 ErrorCode
= RegLoadKeyW (hKey
,
1878 RtlFreeUnicodeString (&FileName
);
1879 RtlFreeUnicodeString (&KeyName
);
1885 /************************************************************************
1891 RegLoadKeyW (HKEY hKey
,
1895 OBJECT_ATTRIBUTES FileObjectAttributes
;
1896 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1897 UNICODE_STRING FileName
;
1898 UNICODE_STRING KeyName
;
1902 if (hKey
== HKEY_PERFORMANCE_DATA
)
1904 return ERROR_INVALID_HANDLE
;
1907 Status
= MapDefaultKey (&KeyHandle
,
1909 if (!NT_SUCCESS(Status
))
1911 return RtlNtStatusToDosError (Status
);
1914 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1919 return ERROR_BAD_PATHNAME
;
1922 InitializeObjectAttributes (&FileObjectAttributes
,
1924 OBJ_CASE_INSENSITIVE
,
1928 RtlInitUnicodeString (&KeyName
,
1931 InitializeObjectAttributes (&KeyObjectAttributes
,
1933 OBJ_CASE_INSENSITIVE
,
1937 Status
= NtLoadKey (&KeyObjectAttributes
,
1938 &FileObjectAttributes
);
1940 RtlFreeUnicodeString (&FileName
);
1942 if (!NT_SUCCESS(Status
))
1944 return RtlNtStatusToDosError (Status
);
1947 return ERROR_SUCCESS
;
1951 /************************************************************************
1952 * RegNotifyChangeKeyValue
1957 RegNotifyChangeKeyValue (HKEY hKey
,
1959 DWORD dwNotifyFilter
,
1963 IO_STATUS_BLOCK IoStatusBlock
;
1967 if (hKey
== HKEY_PERFORMANCE_DATA
)
1969 return ERROR_INVALID_HANDLE
;
1972 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1974 return ERROR_INVALID_PARAMETER
;
1977 Status
= MapDefaultKey (&KeyHandle
,
1979 if (!NT_SUCCESS(Status
))
1981 return RtlNtStatusToDosError (Status
);
1984 /* FIXME: Remote key handles must fail */
1986 Status
= NtNotifyChangeKey (KeyHandle
,
1996 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1998 return RtlNtStatusToDosError (Status
);
2001 return ERROR_SUCCESS
;
2005 /************************************************************************
2006 * RegOpenCurrentUser
2011 RegOpenCurrentUser (IN REGSAM samDesired
,
2012 OUT PHKEY phkResult
)
2016 Status
= RtlOpenCurrentUser((ACCESS_MASK
)samDesired
,
2017 (PHANDLE
)phkResult
);
2018 if (!NT_SUCCESS(Status
))
2020 /* NOTE - don't set the last error code! just return the error! */
2021 return RtlNtStatusToDosError(Status
);
2024 return ERROR_SUCCESS
;
2028 /************************************************************************
2031 * 20050503 Fireball - imported from WINE
2036 RegOpenKeyA (HKEY hKey
,
2040 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2042 if (!lpSubKey
|| !*lpSubKey
)
2045 return ERROR_SUCCESS
;
2048 return RegOpenKeyExA( hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2052 /************************************************************************
2057 * 20050503 Fireball - imported from WINE
2062 RegOpenKeyW (HKEY hKey
,
2066 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2068 if (!lpSubKey
|| !*lpSubKey
)
2071 return ERROR_SUCCESS
;
2073 return RegOpenKeyExW(hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2077 /************************************************************************
2083 RegOpenKeyExA (HKEY hKey
,
2089 OBJECT_ATTRIBUTES ObjectAttributes
;
2090 UNICODE_STRING SubKeyString
;
2094 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2095 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2097 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2098 if (!NT_SUCCESS(Status
))
2100 return RtlNtStatusToDosError (Status
);
2103 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
, (LPSTR
)lpSubKey
);
2104 InitializeObjectAttributes (&ObjectAttributes
,
2106 OBJ_CASE_INSENSITIVE
,
2110 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2111 RtlFreeUnicodeString (&SubKeyString
);
2112 if (!NT_SUCCESS(Status
))
2114 return RtlNtStatusToDosError (Status
);
2117 return ERROR_SUCCESS
;
2121 /************************************************************************
2127 RegOpenKeyExW (HKEY hKey
,
2133 OBJECT_ATTRIBUTES ObjectAttributes
;
2134 UNICODE_STRING SubKeyString
;
2138 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2139 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2141 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2142 if (!NT_SUCCESS(Status
))
2144 return RtlNtStatusToDosError (Status
);
2147 if (lpSubKey
!= NULL
)
2148 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)lpSubKey
);
2150 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)L
"");
2152 InitializeObjectAttributes (&ObjectAttributes
,
2154 OBJ_CASE_INSENSITIVE
,
2158 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2160 if (!NT_SUCCESS(Status
))
2162 return RtlNtStatusToDosError (Status
);
2165 return ERROR_SUCCESS
;
2169 /************************************************************************
2170 * RegOpenUserClassesRoot
2175 RegOpenUserClassesRoot (IN HANDLE hToken
,
2177 IN REGSAM samDesired
,
2178 OUT PHKEY phkResult
)
2180 const WCHAR UserClassesKeyPrefix
[] = L
"\\Registry\\User\\";
2181 const WCHAR UserClassesKeySuffix
[] = L
"_Classes";
2182 PTOKEN_USER TokenUserData
;
2183 ULONG RequiredLength
;
2184 UNICODE_STRING UserSidString
, UserClassesKeyRoot
;
2185 OBJECT_ATTRIBUTES ObjectAttributes
;
2189 /* check parameters */
2190 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
2192 return ERROR_INVALID_PARAMETER
;
2196 * Get the user sid from the token
2200 /* determine how much memory we need */
2201 Status
= NtQueryInformationToken(hToken
,
2206 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2208 /* NOTE - as opposed to all other registry functions windows does indeed
2209 change the last error code in case the caller supplied a invalid
2210 handle for example! */
2211 ErrorCode
= RtlNtStatusToDosError (Status
);
2215 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2218 if (TokenUserData
== NULL
)
2220 return ERROR_NOT_ENOUGH_MEMORY
;
2223 /* attempt to read the information */
2224 Status
= NtQueryInformationToken(hToken
,
2229 if (!NT_SUCCESS(Status
))
2231 RtlFreeHeap(ProcessHeap
,
2234 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2236 /* the information appears to have changed?! try again */
2240 /* NOTE - as opposed to all other registry functions windows does indeed
2241 change the last error code in case the caller supplied a invalid
2242 handle for example! */
2243 ErrorCode
= RtlNtStatusToDosError (Status
);
2248 * Build the absolute path for the user's registry in the form
2249 * "\Registry\User\<SID>_Classes"
2251 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2252 TokenUserData
->User
.Sid
,
2255 /* we don't need the user data anymore, free it */
2256 RtlFreeHeap(ProcessHeap
,
2260 if (!NT_SUCCESS(Status
))
2262 return RtlNtStatusToDosError (Status
);
2265 /* allocate enough memory for the entire key string */
2266 UserClassesKeyRoot
.Length
= 0;
2267 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
2268 sizeof(UserClassesKeyPrefix
) +
2269 sizeof(UserClassesKeySuffix
);
2270 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
2272 UserClassesKeyRoot
.MaximumLength
);
2273 if (UserClassesKeyRoot
.Buffer
== NULL
)
2275 RtlFreeUnicodeString(&UserSidString
);
2276 return RtlNtStatusToDosError (Status
);
2279 /* build the string */
2280 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2281 UserClassesKeyPrefix
);
2282 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
2284 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2285 UserClassesKeySuffix
);
2287 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
2293 InitializeObjectAttributes (&ObjectAttributes
,
2294 &UserClassesKeyRoot
,
2295 OBJ_CASE_INSENSITIVE
,
2299 Status
= NtOpenKey((PHANDLE
)phkResult
,
2303 RtlFreeUnicodeString(&UserSidString
);
2304 RtlFreeUnicodeString(&UserClassesKeyRoot
);
2306 if (!NT_SUCCESS(Status
))
2308 return RtlNtStatusToDosError (Status
);
2311 return ERROR_SUCCESS
;
2315 /************************************************************************
2321 RegQueryInfoKeyA (HKEY hKey
,
2326 LPDWORD lpcbMaxSubKeyLen
,
2327 LPDWORD lpcbMaxClassLen
,
2329 LPDWORD lpcbMaxValueNameLen
,
2330 LPDWORD lpcbMaxValueLen
,
2331 LPDWORD lpcbSecurityDescriptor
,
2332 PFILETIME lpftLastWriteTime
)
2334 WCHAR ClassName
[MAX_PATH
];
2335 UNICODE_STRING UnicodeString
;
2336 ANSI_STRING AnsiString
;
2339 RtlInitUnicodeString (&UnicodeString
,
2341 if (lpClass
!= NULL
)
2343 UnicodeString
.Buffer
= &ClassName
[0];
2344 UnicodeString
.MaximumLength
= sizeof(ClassName
);
2345 AnsiString
.MaximumLength
= *lpcbClass
;
2348 ErrorCode
= RegQueryInfoKeyW (hKey
,
2349 UnicodeString
.Buffer
,
2356 lpcbMaxValueNameLen
,
2358 lpcbSecurityDescriptor
,
2360 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
2362 AnsiString
.Buffer
= lpClass
;
2363 AnsiString
.Length
= 0;
2364 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
2365 RtlUnicodeStringToAnsiString (&AnsiString
,
2368 *lpcbClass
= AnsiString
.Length
;
2369 lpClass
[AnsiString
.Length
] = 0;
2376 /************************************************************************
2382 RegQueryInfoKeyW (HKEY hKey
,
2387 LPDWORD lpcbMaxSubKeyLen
,
2388 LPDWORD lpcbMaxClassLen
,
2390 LPDWORD lpcbMaxValueNameLen
,
2391 LPDWORD lpcbMaxValueLen
,
2392 LPDWORD lpcbSecurityDescriptor
,
2393 PFILETIME lpftLastWriteTime
)
2395 KEY_FULL_INFORMATION FullInfoBuffer
;
2396 PKEY_FULL_INFORMATION FullInfo
;
2398 ULONG ClassLength
= 0;
2402 LONG ErrorCode
= ERROR_SUCCESS
;
2404 if ((lpClass
) && (!lpcbClass
))
2406 return ERROR_INVALID_PARAMETER
;
2409 Status
= MapDefaultKey (&KeyHandle
,
2411 if (!NT_SUCCESS(Status
))
2413 return RtlNtStatusToDosError (Status
);
2416 if (lpClass
!= NULL
)
2420 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2427 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2428 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2431 if (FullInfo
== NULL
)
2433 return ERROR_OUTOFMEMORY
;
2436 FullInfo
->ClassLength
= ClassLength
;
2440 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2441 FullInfo
= &FullInfoBuffer
;
2442 FullInfo
->ClassLength
= 0;
2444 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2446 Status
= NtQueryKey (KeyHandle
,
2451 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
2452 if (!NT_SUCCESS(Status
))
2454 if (lpClass
!= NULL
)
2456 RtlFreeHeap (ProcessHeap
,
2461 return RtlNtStatusToDosError (Status
);
2464 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
2465 if (lpcSubKeys
!= NULL
)
2467 *lpcSubKeys
= FullInfo
->SubKeys
;
2470 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2471 if (lpcbMaxSubKeyLen
!= NULL
)
2473 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2476 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2477 if (lpcbMaxClassLen
!= NULL
)
2479 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2482 TRACE("Values %lu\n", FullInfo
->Values
);
2483 if (lpcValues
!= NULL
)
2485 *lpcValues
= FullInfo
->Values
;
2488 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2489 if (lpcbMaxValueNameLen
!= NULL
)
2491 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2494 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2495 if (lpcbMaxValueLen
!= NULL
)
2497 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2500 if (lpcbSecurityDescriptor
!= NULL
)
2502 Status
= NtQuerySecurityObject(KeyHandle
,
2503 OWNER_SECURITY_INFORMATION
|
2504 GROUP_SECURITY_INFORMATION
|
2505 DACL_SECURITY_INFORMATION
,
2508 lpcbSecurityDescriptor
);
2509 if (!NT_SUCCESS(Status
))
2511 if (lpClass
!= NULL
)
2513 RtlFreeHeap(ProcessHeap
,
2518 return RtlNtStatusToDosError (Status
);
2522 if (lpftLastWriteTime
!= NULL
)
2524 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2525 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2528 if (lpClass
!= NULL
)
2530 if (FullInfo
->ClassLength
> ClassLength
)
2532 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2536 RtlCopyMemory (lpClass
,
2538 FullInfo
->ClassLength
);
2539 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2540 lpClass
[*lpcbClass
] = 0;
2543 RtlFreeHeap (ProcessHeap
,
2552 /************************************************************************
2553 * RegQueryMultipleValuesA
2558 RegQueryMultipleValuesA (HKEY hKey
,
2565 DWORD maxBytes
= *ldwTotsize
;
2566 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2569 if (maxBytes
>= (1024*1024))
2570 return ERROR_TRANSFER_TOO_LONG
;
2574 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
2575 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2577 for (i
= 0; i
< num_vals
; i
++)
2579 val_list
[i
].ve_valuelen
= 0;
2580 ErrorCode
= RegQueryValueExA (hKey
,
2581 val_list
[i
].ve_valuename
,
2585 &val_list
[i
].ve_valuelen
);
2586 if (ErrorCode
!= ERROR_SUCCESS
)
2591 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2593 ErrorCode
= RegQueryValueExA (hKey
,
2594 val_list
[i
].ve_valuename
,
2596 &val_list
[i
].ve_type
,
2598 &val_list
[i
].ve_valuelen
);
2599 if (ErrorCode
!= ERROR_SUCCESS
)
2604 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2606 bufptr
+= val_list
[i
].ve_valuelen
;
2609 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2612 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2616 /************************************************************************
2617 * RegQueryMultipleValuesW
2622 RegQueryMultipleValuesW (HKEY hKey
,
2629 DWORD maxBytes
= *ldwTotsize
;
2630 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2633 if (maxBytes
>= (1024*1024))
2634 return ERROR_TRANSFER_TOO_LONG
;
2638 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2639 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2641 for (i
= 0; i
< num_vals
; i
++)
2643 val_list
[i
].ve_valuelen
= 0;
2644 ErrorCode
= RegQueryValueExW (hKey
,
2645 val_list
[i
].ve_valuename
,
2649 &val_list
[i
].ve_valuelen
);
2650 if (ErrorCode
!= ERROR_SUCCESS
)
2655 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2657 ErrorCode
= RegQueryValueExW (hKey
,
2658 val_list
[i
].ve_valuename
,
2660 &val_list
[i
].ve_type
,
2662 &val_list
[i
].ve_valuelen
);
2663 if (ErrorCode
!= ERROR_SUCCESS
)
2668 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2670 bufptr
+= val_list
[i
].ve_valuelen
;
2673 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2676 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2680 /************************************************************************
2686 RegQueryValueExW (HKEY hKey
,
2687 LPCWSTR lpValueName
,
2693 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2694 UNICODE_STRING ValueName
;
2699 LONG ErrorCode
= ERROR_SUCCESS
;
2700 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2702 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2703 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2705 Status
= MapDefaultKey (&KeyHandle
,
2707 if (!NT_SUCCESS(Status
))
2709 return RtlNtStatusToDosError (Status
);
2712 if (lpData
!= NULL
&& lpcbData
== NULL
)
2714 return ERROR_INVALID_PARAMETER
;
2717 RtlInitUnicodeString (&ValueName
,
2719 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2720 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2723 if (ValueInfo
== NULL
)
2725 return ERROR_OUTOFMEMORY
;
2728 Status
= NtQueryValueKey (KeyHandle
,
2730 KeyValuePartialInformation
,
2734 TRACE("Status 0x%X\n", Status
);
2735 if (Status
== STATUS_BUFFER_OVERFLOW
)
2737 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2739 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2741 else if (!NT_SUCCESS(Status
))
2743 ErrorCode
= RtlNtStatusToDosError (Status
);
2745 if (lpcbData
!= NULL
)
2747 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2753 *lpType
= ValueInfo
->Type
;
2756 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2758 RtlMoveMemory (lpData
,
2760 min(ValueInfo
->DataLength
, MaxCopy
));
2763 if ((ValueInfo
->Type
== REG_SZ
) ||
2764 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2765 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2767 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2769 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2772 if (lpcbData
!= NULL
)
2774 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2775 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
2780 if (lpcbData
!= NULL
)
2782 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2783 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
2787 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2789 RtlFreeHeap (ProcessHeap
,
2797 /************************************************************************
2803 RegQueryValueExA (HKEY hKey
,
2810 UNICODE_STRING ValueName
;
2811 UNICODE_STRING ValueData
;
2812 ANSI_STRING AnsiString
;
2817 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
2818 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2820 if (lpData
!= NULL
&& lpcbData
== NULL
)
2822 return ERROR_INVALID_PARAMETER
;
2827 ValueData
.Length
= 0;
2828 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
2829 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2831 ValueData
.MaximumLength
);
2832 if (!ValueData
.Buffer
)
2834 return ERROR_OUTOFMEMORY
;
2839 ValueData
.Buffer
= NULL
;
2840 ValueData
.Length
= 0;
2841 ValueData
.MaximumLength
= 0;
2844 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2845 (LPSTR
)lpValueName
);
2847 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
2848 ErrorCode
= RegQueryValueExW (hKey
,
2852 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
2854 TRACE("ErrorCode %lu\n", ErrorCode
);
2855 RtlFreeUnicodeString(&ValueName
);
2857 if (ErrorCode
== ERROR_SUCCESS
||
2858 ErrorCode
== ERROR_MORE_DATA
)
2865 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2867 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2869 RtlInitAnsiString(&AnsiString
, NULL
);
2870 AnsiString
.Buffer
= (LPSTR
)lpData
;
2871 AnsiString
.MaximumLength
= *lpcbData
;
2872 ValueData
.Length
= Length
;
2873 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2874 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2876 Length
= Length
/ sizeof(WCHAR
);
2878 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2880 if (*lpcbData
< Length
)
2882 ErrorCode
= ERROR_MORE_DATA
;
2886 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2890 if (lpcbData
!= NULL
)
2896 if (ValueData
.Buffer
!= NULL
)
2898 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2905 /************************************************************************
2911 RegQueryValueA (HKEY hKey
,
2916 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2917 UNICODE_STRING SubKeyName
;
2918 UNICODE_STRING Value
;
2919 ANSI_STRING AnsiString
;
2923 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
2924 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
2926 if (lpValue
!= NULL
&&
2929 return ERROR_INVALID_PARAMETER
;
2932 RtlInitUnicodeString (&SubKeyName
,
2934 RtlInitUnicodeString (&Value
,
2936 if (lpSubKey
!= NULL
&&
2937 strlen(lpSubKey
) != 0)
2939 RtlInitAnsiString (&AnsiString
,
2941 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2942 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2943 RtlAnsiStringToUnicodeString (&SubKeyName
,
2948 if (lpValue
!= NULL
)
2950 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2951 Value
.MaximumLength
= ValueSize
;
2952 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2955 if (Value
.Buffer
== NULL
)
2957 return ERROR_OUTOFMEMORY
;
2965 ErrorCode
= RegQueryValueW (hKey
,
2966 (LPCWSTR
)SubKeyName
.Buffer
,
2969 if (ErrorCode
== ERROR_SUCCESS
)
2971 Value
.Length
= ValueSize
;
2972 RtlInitAnsiString (&AnsiString
,
2974 AnsiString
.Buffer
= lpValue
;
2975 AnsiString
.MaximumLength
= *lpcbValue
;
2976 RtlUnicodeStringToAnsiString (&AnsiString
,
2981 *lpcbValue
= ValueSize
;
2982 if (Value
.Buffer
!= NULL
)
2984 RtlFreeHeap (ProcessHeap
,
2993 /************************************************************************
2999 RegQueryValueW (HKEY hKey
,
3004 OBJECT_ATTRIBUTES ObjectAttributes
;
3005 UNICODE_STRING SubKeyString
;
3012 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
3013 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3015 Status
= MapDefaultKey (&KeyHandle
,
3017 if (!NT_SUCCESS(Status
))
3019 return RtlNtStatusToDosError (Status
);
3022 if (lpSubKey
!= NULL
&&
3023 wcslen(lpSubKey
) != 0)
3025 RtlInitUnicodeString (&SubKeyString
,
3027 InitializeObjectAttributes (&ObjectAttributes
,
3029 OBJ_CASE_INSENSITIVE
,
3032 Status
= NtOpenKey (&RealKey
,
3035 if (!NT_SUCCESS(Status
))
3037 return RtlNtStatusToDosError (Status
);
3039 CloseRealKey
= TRUE
;
3044 CloseRealKey
= FALSE
;
3047 ErrorCode
= RegQueryValueExW (RealKey
,
3052 (LPDWORD
)lpcbValue
);
3062 /************************************************************************
3068 RegReplaceKeyA (HKEY hKey
,
3073 UNICODE_STRING SubKey
;
3074 UNICODE_STRING NewFile
;
3075 UNICODE_STRING OldFile
;
3078 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
3080 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
3082 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
3085 ErrorCode
= RegReplaceKeyW (hKey
,
3090 RtlFreeUnicodeString (&OldFile
);
3091 RtlFreeUnicodeString (&NewFile
);
3092 RtlFreeUnicodeString (&SubKey
);
3098 /************************************************************************
3104 RegReplaceKeyW (HKEY hKey
,
3109 OBJECT_ATTRIBUTES KeyObjectAttributes
;
3110 OBJECT_ATTRIBUTES NewObjectAttributes
;
3111 OBJECT_ATTRIBUTES OldObjectAttributes
;
3112 UNICODE_STRING SubKeyName
;
3113 UNICODE_STRING NewFileName
;
3114 UNICODE_STRING OldFileName
;
3115 BOOLEAN CloseRealKey
;
3116 HANDLE RealKeyHandle
;
3120 if (hKey
== HKEY_PERFORMANCE_DATA
)
3122 return ERROR_INVALID_HANDLE
;
3125 Status
= MapDefaultKey (&KeyHandle
,
3127 if (!NT_SUCCESS(Status
))
3129 return RtlNtStatusToDosError (Status
);
3132 /* Open the real key */
3133 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
3135 RtlInitUnicodeString (&SubKeyName
,
3137 InitializeObjectAttributes (&KeyObjectAttributes
,
3139 OBJ_CASE_INSENSITIVE
,
3142 Status
= NtOpenKey (&RealKeyHandle
,
3144 &KeyObjectAttributes
);
3145 if (!NT_SUCCESS(Status
))
3147 return RtlNtStatusToDosError (Status
);
3149 CloseRealKey
= TRUE
;
3153 RealKeyHandle
= KeyHandle
;
3154 CloseRealKey
= FALSE
;
3157 /* Convert new file name */
3158 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
3165 NtClose (RealKeyHandle
);
3167 return ERROR_INVALID_PARAMETER
;
3170 InitializeObjectAttributes (&NewObjectAttributes
,
3172 OBJ_CASE_INSENSITIVE
,
3176 /* Convert old file name */
3177 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
3182 RtlFreeUnicodeString (&NewFileName
);
3185 NtClose (RealKeyHandle
);
3187 return ERROR_INVALID_PARAMETER
;
3190 InitializeObjectAttributes (&OldObjectAttributes
,
3192 OBJ_CASE_INSENSITIVE
,
3196 Status
= NtReplaceKey (&NewObjectAttributes
,
3198 &OldObjectAttributes
);
3200 RtlFreeUnicodeString (&OldFileName
);
3201 RtlFreeUnicodeString (&NewFileName
);
3205 NtClose (RealKeyHandle
);
3208 if (!NT_SUCCESS(Status
))
3210 return RtlNtStatusToDosError (Status
);
3213 return ERROR_SUCCESS
;
3217 /************************************************************************
3223 RegRestoreKeyA (HKEY hKey
,
3227 UNICODE_STRING FileName
;
3230 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3233 ErrorCode
= RegRestoreKeyW (hKey
,
3237 RtlFreeUnicodeString (&FileName
);
3243 /************************************************************************
3249 RegRestoreKeyW (HKEY hKey
,
3253 OBJECT_ATTRIBUTES ObjectAttributes
;
3254 IO_STATUS_BLOCK IoStatusBlock
;
3255 UNICODE_STRING FileName
;
3260 if (hKey
== HKEY_PERFORMANCE_DATA
)
3262 return ERROR_INVALID_HANDLE
;
3265 Status
= MapDefaultKey (&KeyHandle
,
3267 if (!NT_SUCCESS(Status
))
3269 return RtlNtStatusToDosError (Status
);
3272 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
3277 return ERROR_INVALID_PARAMETER
;
3280 InitializeObjectAttributes (&ObjectAttributes
,
3282 OBJ_CASE_INSENSITIVE
,
3286 Status
= NtOpenFile (&FileHandle
,
3291 FILE_SYNCHRONOUS_IO_NONALERT
);
3292 RtlFreeUnicodeString (&FileName
);
3293 if (!NT_SUCCESS(Status
))
3295 return RtlNtStatusToDosError (Status
);
3298 Status
= NtRestoreKey (KeyHandle
,
3301 NtClose (FileHandle
);
3302 if (!NT_SUCCESS(Status
))
3304 return RtlNtStatusToDosError (Status
);
3307 return ERROR_SUCCESS
;
3311 /************************************************************************
3317 RegSaveKeyA (HKEY hKey
,
3319 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3321 UNICODE_STRING FileName
;
3324 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3326 ErrorCode
= RegSaveKeyW (hKey
,
3328 lpSecurityAttributes
);
3329 RtlFreeUnicodeString (&FileName
);
3335 /************************************************************************
3341 RegSaveKeyW (HKEY hKey
,
3343 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3345 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
3346 OBJECT_ATTRIBUTES ObjectAttributes
;
3347 UNICODE_STRING FileName
;
3348 IO_STATUS_BLOCK IoStatusBlock
;
3353 Status
= MapDefaultKey (&KeyHandle
,
3355 if (!NT_SUCCESS(Status
))
3357 return RtlNtStatusToDosError (Status
);
3360 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
3365 return ERROR_INVALID_PARAMETER
;
3368 if (lpSecurityAttributes
!= NULL
)
3370 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
3373 InitializeObjectAttributes (&ObjectAttributes
,
3375 OBJ_CASE_INSENSITIVE
,
3377 SecurityDescriptor
);
3378 Status
= NtCreateFile (&FileHandle
,
3379 GENERIC_WRITE
| SYNCHRONIZE
,
3383 FILE_ATTRIBUTE_NORMAL
,
3386 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
3389 RtlFreeUnicodeString (&FileName
);
3390 if (!NT_SUCCESS(Status
))
3392 return RtlNtStatusToDosError (Status
);
3395 Status
= NtSaveKey (KeyHandle
,
3397 NtClose (FileHandle
);
3398 if (!NT_SUCCESS(Status
))
3400 return RtlNtStatusToDosError (Status
);
3403 return ERROR_SUCCESS
;
3407 /************************************************************************
3413 RegSetKeySecurity (HKEY hKey
,
3414 SECURITY_INFORMATION SecurityInformation
,
3415 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3420 if (hKey
== HKEY_PERFORMANCE_DATA
)
3422 return ERROR_INVALID_HANDLE
;
3425 Status
= MapDefaultKey (&KeyHandle
,
3427 if (!NT_SUCCESS(Status
))
3429 return RtlNtStatusToDosError (Status
);
3432 Status
= NtSetSecurityObject (KeyHandle
,
3433 SecurityInformation
,
3434 pSecurityDescriptor
);
3435 if (!NT_SUCCESS(Status
))
3437 return RtlNtStatusToDosError (Status
);
3440 return ERROR_SUCCESS
;
3444 /************************************************************************
3450 RegSetValueExA (HKEY hKey
,
3457 UNICODE_STRING ValueName
;
3459 ANSI_STRING AnsiString
;
3460 UNICODE_STRING Data
;
3465 if (lpValueName
!= NULL
&&
3466 strlen(lpValueName
) != 0)
3468 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3470 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3477 if (((dwType
== REG_SZ
) ||
3478 (dwType
== REG_MULTI_SZ
) ||
3479 (dwType
== REG_EXPAND_SZ
)) &&
3482 /* NT adds one if the caller forgot the NULL-termination character */
3483 if (lpData
[cbData
- 1] != '\0')
3488 RtlInitAnsiString (&AnsiString
,
3490 AnsiString
.Buffer
= (PSTR
)lpData
;
3491 AnsiString
.Length
= cbData
- 1;
3492 AnsiString
.MaximumLength
= cbData
;
3493 RtlAnsiStringToUnicodeString (&Data
,
3496 pData
= (LPBYTE
)Data
.Buffer
;
3497 DataSize
= cbData
* sizeof(WCHAR
);
3501 RtlInitUnicodeString (&Data
,
3503 pData
= (LPBYTE
)lpData
;
3507 ErrorCode
= RegSetValueExW (hKey
,
3513 if (pValueName
!= NULL
)
3515 RtlFreeHeap (ProcessHeap
,
3520 if (Data
.Buffer
!= NULL
)
3522 RtlFreeHeap (ProcessHeap
,
3531 /************************************************************************
3537 RegSetValueExW (HKEY hKey
,
3538 LPCWSTR lpValueName
,
3544 UNICODE_STRING ValueName
;
3545 PUNICODE_STRING pValueName
;
3549 Status
= MapDefaultKey (&KeyHandle
,
3551 if (!NT_SUCCESS(Status
))
3553 return RtlNtStatusToDosError (Status
);
3556 if (lpValueName
!= NULL
)
3558 RtlInitUnicodeString (&ValueName
,
3563 RtlInitUnicodeString (&ValueName
, L
"");
3565 pValueName
= &ValueName
;
3567 if (((dwType
== REG_SZ
) ||
3568 (dwType
== REG_MULTI_SZ
) ||
3569 (dwType
== REG_EXPAND_SZ
)) &&
3570 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
3572 /* NT adds one if the caller forgot the NULL-termination character */
3573 cbData
+= sizeof(WCHAR
);
3576 Status
= NtSetValueKey (KeyHandle
,
3582 if (!NT_SUCCESS(Status
))
3584 return RtlNtStatusToDosError (Status
);
3587 return ERROR_SUCCESS
;
3591 /************************************************************************
3597 RegSetValueA (HKEY hKey
,
3606 if (dwType
!= REG_SZ
)
3608 return ERROR_INVALID_PARAMETER
;
3611 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
3613 ret
= RegCreateKeyA(hKey
,
3617 if (ret
!= ERROR_SUCCESS
)
3625 ret
= RegSetValueExA(hSubKey
,
3629 (CONST BYTE
*)lpData
,
3630 strlen(lpData
) + 1);
3632 if (hSubKey
!= hKey
)
3634 RegCloseKey(hSubKey
);
3641 /************************************************************************
3647 RegSetValueW (HKEY hKey
,
3653 OBJECT_ATTRIBUTES ObjectAttributes
;
3654 UNICODE_STRING SubKeyString
;
3661 Status
= MapDefaultKey (&KeyHandle
,
3663 if (!NT_SUCCESS(Status
))
3665 return RtlNtStatusToDosError (Status
);
3668 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3670 RtlInitUnicodeString (&SubKeyString
,
3672 InitializeObjectAttributes (&ObjectAttributes
,
3674 OBJ_CASE_INSENSITIVE
,
3677 Status
= NtOpenKey (&RealKey
,
3680 if (!NT_SUCCESS(Status
))
3682 return RtlNtStatusToDosError (Status
);
3684 CloseRealKey
= TRUE
;
3689 CloseRealKey
= FALSE
;
3692 ErrorCode
= RegSetValueExW (RealKey
,
3698 if (CloseRealKey
== TRUE
)
3707 /************************************************************************
3713 RegUnLoadKeyA (HKEY hKey
,
3716 UNICODE_STRING KeyName
;
3719 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3722 ErrorCode
= RegUnLoadKeyW (hKey
,
3725 RtlFreeUnicodeString (&KeyName
);
3731 /************************************************************************
3737 RegUnLoadKeyW (HKEY hKey
,
3740 OBJECT_ATTRIBUTES ObjectAttributes
;
3741 UNICODE_STRING KeyName
;
3745 if (hKey
== HKEY_PERFORMANCE_DATA
)
3747 return ERROR_INVALID_HANDLE
;
3750 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3751 if (!NT_SUCCESS(Status
))
3753 return RtlNtStatusToDosError (Status
);
3756 RtlInitUnicodeString (&KeyName
,
3759 InitializeObjectAttributes (&ObjectAttributes
,
3761 OBJ_CASE_INSENSITIVE
,
3765 Status
= NtUnloadKey (&ObjectAttributes
);
3767 if (!NT_SUCCESS(Status
))
3769 return RtlNtStatusToDosError (Status
);
3772 return ERROR_SUCCESS
;