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
);
838 RtlInitUnicodeString(&ValueName
,
839 (LPWSTR
)lpValueName
);
841 Status
= NtDeleteValueKey((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
844 if (SubKeyHandle
!= NULL
)
846 NtClose(SubKeyHandle
);
849 if (!NT_SUCCESS(Status
))
851 return RtlNtStatusToDosError(Status
);
854 return ERROR_SUCCESS
;
858 /************************************************************************
864 RegDeleteKeyValueA(IN HKEY hKey
,
865 IN LPCSTR lpSubKey OPTIONAL
,
866 IN LPCSTR lpValueName OPTIONAL
)
868 UNICODE_STRING SubKey
, ValueName
;
871 if (lpSubKey
!= NULL
)
873 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey
,
876 return ERROR_NOT_ENOUGH_MEMORY
;
880 RtlInitUnicodeString(&SubKey
,
883 if (lpValueName
!= NULL
)
885 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName
,
888 RtlFreeUnicodeString(&SubKey
);
889 return ERROR_NOT_ENOUGH_MEMORY
;
893 RtlInitUnicodeString(&ValueName
,
896 Ret
= RegDeleteKeyValueW(hKey
,
900 RtlFreeUnicodeString(&SubKey
);
901 RtlFreeUnicodeString(&ValueName
);
907 /************************************************************************
913 RegDeleteTreeW(IN HKEY hKey
,
914 IN LPCWSTR lpSubKey OPTIONAL
)
916 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
919 Status
= MapDefaultKey(&KeyHandle
,
921 if (!NT_SUCCESS(Status
))
923 return RtlNtStatusToDosError(Status
);
926 if (lpSubKey
!= NULL
)
928 OBJECT_ATTRIBUTES ObjectAttributes
;
929 UNICODE_STRING SubKeyName
;
931 RtlInitUnicodeString(&SubKeyName
,
934 InitializeObjectAttributes(&ObjectAttributes
,
936 OBJ_CASE_INSENSITIVE
,
940 Status
= NtOpenKey(&SubKeyHandle
,
941 DELETE
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
943 if (!NT_SUCCESS(Status
))
945 return RtlNtStatusToDosError(Status
);
949 /* FIXME - delete all keys recursively */
950 Status
= STATUS_NOT_IMPLEMENTED
;
952 if (SubKeyHandle
!= NULL
)
954 NtClose(SubKeyHandle
);
957 if (!NT_SUCCESS(Status
))
959 return RtlNtStatusToDosError(Status
);
962 return ERROR_SUCCESS
;
966 /************************************************************************
972 RegDeleteTreeA(IN HKEY hKey
,
973 IN LPCSTR lpSubKey OPTIONAL
)
975 UNICODE_STRING SubKeyName
;
978 if (lpSubKey
!= NULL
)
980 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
983 return ERROR_NOT_ENOUGH_MEMORY
;
987 RtlInitUnicodeString(&SubKeyName
,
990 Ret
= RegDeleteTreeW(hKey
,
993 RtlFreeUnicodeString(&SubKeyName
);
999 /************************************************************************
1005 RegSetKeyValueW(IN HKEY hKey
,
1006 IN LPCWSTR lpSubKey OPTIONAL
,
1007 IN LPCWSTR lpValueName OPTIONAL
,
1009 IN LPCVOID lpData OPTIONAL
,
1012 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
1016 Status
= MapDefaultKey(&KeyHandle
,
1018 if (!NT_SUCCESS(Status
))
1020 return RtlNtStatusToDosError(Status
);
1023 if (lpSubKey
!= NULL
)
1025 OBJECT_ATTRIBUTES ObjectAttributes
;
1026 UNICODE_STRING SubKeyName
;
1028 RtlInitUnicodeString(&SubKeyName
,
1031 InitializeObjectAttributes(&ObjectAttributes
,
1033 OBJ_CASE_INSENSITIVE
,
1037 Status
= NtOpenKey(&SubKeyHandle
,
1040 if (!NT_SUCCESS(Status
))
1042 return RtlNtStatusToDosError(Status
);
1046 Ret
= RegSetValueExW((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
1053 if (SubKeyHandle
!= NULL
)
1055 NtClose(SubKeyHandle
);
1062 /************************************************************************
1068 RegSetKeyValueA(IN HKEY hKey
,
1069 IN LPCSTR lpSubKey OPTIONAL
,
1070 IN LPCSTR lpValueName OPTIONAL
,
1072 IN LPCVOID lpData OPTIONAL
,
1075 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
1079 Status
= MapDefaultKey(&KeyHandle
,
1081 if (!NT_SUCCESS(Status
))
1083 return RtlNtStatusToDosError(Status
);
1086 if (lpSubKey
!= NULL
)
1088 OBJECT_ATTRIBUTES ObjectAttributes
;
1089 UNICODE_STRING SubKeyName
;
1091 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1094 return ERROR_NOT_ENOUGH_MEMORY
;
1097 InitializeObjectAttributes(&ObjectAttributes
,
1099 OBJ_CASE_INSENSITIVE
,
1103 Status
= NtOpenKey(&SubKeyHandle
,
1107 RtlFreeUnicodeString(&SubKeyName
);
1109 if (!NT_SUCCESS(Status
))
1111 return RtlNtStatusToDosError(Status
);
1115 Ret
= RegSetValueExA((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
1122 if (SubKeyHandle
!= NULL
)
1124 NtClose(SubKeyHandle
);
1131 /************************************************************************
1137 RegDeleteValueA (HKEY hKey
,
1140 UNICODE_STRING ValueName
;
1144 Status
= MapDefaultKey (&KeyHandle
,
1146 if (!NT_SUCCESS(Status
))
1148 return RtlNtStatusToDosError (Status
);
1151 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
1152 (LPSTR
)lpValueName
);
1153 Status
= NtDeleteValueKey (KeyHandle
,
1155 RtlFreeUnicodeString (&ValueName
);
1156 if (!NT_SUCCESS(Status
))
1158 return RtlNtStatusToDosError (Status
);
1161 return ERROR_SUCCESS
;
1165 /************************************************************************
1171 RegDeleteValueW (HKEY hKey
,
1172 LPCWSTR lpValueName
)
1174 UNICODE_STRING ValueName
;
1178 Status
= MapDefaultKey (&KeyHandle
,
1180 if (!NT_SUCCESS(Status
))
1182 return RtlNtStatusToDosError (Status
);
1185 RtlInitUnicodeString (&ValueName
,
1186 (LPWSTR
)lpValueName
);
1188 Status
= NtDeleteValueKey (KeyHandle
,
1190 if (!NT_SUCCESS(Status
))
1192 return RtlNtStatusToDosError (Status
);
1195 return ERROR_SUCCESS
;
1199 /************************************************************************
1205 RegEnumKeyA (HKEY hKey
,
1213 return RegEnumKeyExA (hKey
,
1224 /************************************************************************
1230 RegEnumKeyW (HKEY hKey
,
1238 return RegEnumKeyExW (hKey
,
1249 /************************************************************************
1255 RegEnumKeyExA (HKEY hKey
,
1262 PFILETIME lpftLastWriteTime
)
1266 KEY_NODE_INFORMATION Node
;
1267 KEY_BASIC_INFORMATION Basic
;
1270 UNICODE_STRING StringU
;
1271 ANSI_STRING StringA
;
1272 LONG ErrorCode
= ERROR_SUCCESS
;
1274 DWORD ClassLength
= 0;
1280 TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
1281 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
1283 if ((lpClass
) && (!lpcbClass
))
1285 return ERROR_INVALID_PARAMETER
;
1288 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1289 if (!NT_SUCCESS(Status
))
1291 return RtlNtStatusToDosError (Status
);
1296 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1307 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1314 /* The class name should start at a dword boundary */
1315 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1319 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1322 KeyInfo
= RtlAllocateHeap (ProcessHeap
, 0, BufferSize
);
1323 if (KeyInfo
== NULL
)
1325 return ERROR_OUTOFMEMORY
;
1328 Status
= NtEnumerateKey (KeyHandle
,
1330 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
1334 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1335 if (!NT_SUCCESS(Status
))
1337 ErrorCode
= RtlNtStatusToDosError (Status
);
1341 if (lpClass
== NULL
)
1343 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1345 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1349 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
1350 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
1351 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
1356 if (KeyInfo
->Node
.NameLength
> NameLength
||
1357 KeyInfo
->Node
.ClassLength
> ClassLength
)
1359 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1363 StringA
.Buffer
= lpClass
;
1365 StringA
.MaximumLength
= *lpcbClass
;
1366 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
1367 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
1368 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
1369 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1370 lpClass
[StringA
.Length
] = 0;
1371 *lpcbClass
= StringA
.Length
;
1372 StringU
.Buffer
= KeyInfo
->Node
.Name
;
1373 StringU
.Length
= KeyInfo
->Node
.NameLength
;
1374 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
1378 if (ErrorCode
== ERROR_SUCCESS
)
1380 StringA
.Buffer
= lpName
;
1382 StringA
.MaximumLength
= *lpcbName
;
1383 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1384 lpName
[StringA
.Length
] = 0;
1385 *lpcbName
= StringA
.Length
;
1386 if (lpftLastWriteTime
!= NULL
)
1388 if (lpClass
== NULL
)
1390 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1391 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1395 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1396 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1402 TRACE("Key Namea0 Length %d\n", StringU
.Length
);
1403 TRACE("Key Namea1 Length %d\n", NameLength
);
1404 TRACE("Key Namea Length %d\n", *lpcbName
);
1405 TRACE("Key Namea %s\n", lpName
);
1407 RtlFreeHeap (ProcessHeap
,
1415 /************************************************************************
1421 RegEnumKeyExW (HKEY hKey
,
1428 PFILETIME lpftLastWriteTime
)
1432 KEY_NODE_INFORMATION Node
;
1433 KEY_BASIC_INFORMATION Basic
;
1439 ULONG ClassLength
= 0;
1441 LONG ErrorCode
= ERROR_SUCCESS
;
1444 Status
= MapDefaultKey(&KeyHandle
,
1446 if (!NT_SUCCESS(Status
))
1448 return RtlNtStatusToDosError (Status
);
1453 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1464 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1471 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1475 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1478 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1481 if (KeyInfo
== NULL
)
1483 return ERROR_OUTOFMEMORY
;
1486 Status
= NtEnumerateKey (KeyHandle
,
1488 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1492 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1493 if (!NT_SUCCESS(Status
))
1495 ErrorCode
= RtlNtStatusToDosError (Status
);
1499 if (lpClass
== NULL
)
1501 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1503 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1507 RtlCopyMemory (lpName
,
1508 KeyInfo
->Basic
.Name
,
1509 KeyInfo
->Basic
.NameLength
);
1510 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1511 lpName
[*lpcbName
] = 0;
1516 if (KeyInfo
->Node
.NameLength
> NameLength
||
1517 KeyInfo
->Node
.ClassLength
> ClassLength
)
1519 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1523 RtlCopyMemory (lpName
,
1525 KeyInfo
->Node
.NameLength
);
1526 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1527 lpName
[*lpcbName
] = 0;
1528 RtlCopyMemory (lpClass
,
1529 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1530 KeyInfo
->Node
.ClassLength
);
1531 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1532 lpClass
[*lpcbClass
] = 0;
1536 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1538 if (lpClass
== NULL
)
1540 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1541 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1545 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1546 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1551 RtlFreeHeap (ProcessHeap
,
1558 /************************************************************************
1564 RegEnumValueA( HKEY hKey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1565 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1570 char buffer
[256], *buf_ptr
= buffer
;
1571 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1572 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1574 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1575 // hkey, index, value, val_count, reserved, type, data, count );
1577 /* NT only checks count, not val_count */
1578 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1579 status
= MapDefaultKey (&KeyHandle
, hKey
);
1580 if (!NT_SUCCESS(status
))
1582 return RtlNtStatusToDosError (status
);
1585 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1586 if (data
) total_size
+= *count
;
1587 total_size
= min( sizeof(buffer
), total_size
);
1589 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1590 buffer
, total_size
, &total_size
);
1591 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1593 /* we need to fetch the contents for a string type even if not requested,
1594 * because we need to compute the length of the ASCII string. */
1595 if (value
|| data
|| is_string(info
->Type
))
1597 /* retry with a dynamically allocated buffer */
1598 while (status
== STATUS_BUFFER_OVERFLOW
)
1600 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1601 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1602 return ERROR_NOT_ENOUGH_MEMORY
;
1603 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1604 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1605 buf_ptr
, total_size
, &total_size
);
1608 if (status
) goto done
;
1610 if (is_string(info
->Type
))
1613 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1614 total_size
- info
->DataOffset
);
1617 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1620 RtlUnicodeToMultiByteN( (PCHAR
)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1621 total_size
- info
->DataOffset
);
1622 /* if the type is REG_SZ and data is not 0-terminated
1623 * and there is enough space in the buffer NT appends a \0 */
1624 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1627 info
->DataLength
= len
;
1631 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1632 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1635 if (value
&& !status
)
1639 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1640 if (len
>= *val_count
)
1642 status
= STATUS_BUFFER_OVERFLOW
;
1645 len
= *val_count
- 1;
1646 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1652 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1658 else status
= STATUS_SUCCESS
;
1660 if (type
) *type
= info
->Type
;
1661 if (count
) *count
= info
->DataLength
;
1664 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1665 return RtlNtStatusToDosError(status
);
1668 /******************************************************************************
1669 * RegEnumValueW [ADVAPI32.@]
1673 * hkey [I] Handle to key to query
1674 * index [I] Index of value to query
1675 * value [O] Value string
1676 * val_count [I/O] Size of value buffer (in wchars)
1677 * reserved [I] Reserved
1678 * type [O] Type code
1679 * data [O] Value data
1680 * count [I/O] Size of data buffer (in bytes)
1683 * Success: ERROR_SUCCESS
1684 * Failure: nonzero error code from Winerror.h
1687 RegEnumValueW( HKEY hKey
, DWORD index
, LPWSTR value
, PDWORD val_count
,
1688 PDWORD reserved
, PDWORD type
, LPBYTE data
, PDWORD count
)
1693 char buffer
[256], *buf_ptr
= buffer
;
1694 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1695 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1697 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1698 // hkey, index, value, val_count, reserved, type, data, count );
1700 /* NT only checks count, not val_count */
1701 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1703 status
= MapDefaultKey (&KeyHandle
, hKey
);
1704 if (!NT_SUCCESS(status
))
1706 return RtlNtStatusToDosError (status
);
1709 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1710 if (data
) total_size
+= *count
;
1711 total_size
= min( sizeof(buffer
), total_size
);
1713 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1714 buffer
, total_size
, &total_size
);
1715 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1719 /* retry with a dynamically allocated buffer */
1720 while (status
== STATUS_BUFFER_OVERFLOW
)
1722 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1723 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1724 return ERROR_NOT_ENOUGH_MEMORY
;
1725 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1726 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1727 buf_ptr
, total_size
, &total_size
);
1730 if (status
) goto done
;
1734 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1736 status
= STATUS_BUFFER_OVERFLOW
;
1739 memcpy( value
, info
->Name
, info
->NameLength
);
1740 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1741 value
[*val_count
] = 0;
1746 if (total_size
- info
->DataOffset
> *count
)
1748 status
= STATUS_BUFFER_OVERFLOW
;
1751 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1752 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1754 /* if the type is REG_SZ and data is not 0-terminated
1755 * and there is enough space in the buffer NT appends a \0 */
1756 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1757 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1761 else status
= STATUS_SUCCESS
;
1764 if (type
) *type
= info
->Type
;
1765 if (count
) *count
= info
->DataLength
;
1768 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1769 return RtlNtStatusToDosError(status
);
1772 /************************************************************************
1778 RegFlushKey(HKEY hKey
)
1783 if (hKey
== HKEY_PERFORMANCE_DATA
)
1785 return ERROR_SUCCESS
;
1788 Status
= MapDefaultKey (&KeyHandle
,
1790 if (!NT_SUCCESS(Status
))
1792 return RtlNtStatusToDosError (Status
);
1795 Status
= NtFlushKey (KeyHandle
);
1796 if (!NT_SUCCESS(Status
))
1798 return RtlNtStatusToDosError (Status
);
1801 return ERROR_SUCCESS
;
1805 /************************************************************************
1811 RegGetKeySecurity(HKEY hKey
,
1812 SECURITY_INFORMATION SecurityInformation
,
1813 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1814 LPDWORD lpcbSecurityDescriptor
)
1819 if (hKey
== HKEY_PERFORMANCE_DATA
)
1821 return ERROR_INVALID_HANDLE
;
1824 Status
= MapDefaultKey(&KeyHandle
,
1826 if (!NT_SUCCESS(Status
))
1828 TRACE("MapDefaultKey() failed (Status %lx)\n", Status
);
1829 return RtlNtStatusToDosError (Status
);
1832 Status
= NtQuerySecurityObject(KeyHandle
,
1833 SecurityInformation
,
1834 pSecurityDescriptor
,
1835 *lpcbSecurityDescriptor
,
1836 lpcbSecurityDescriptor
);
1837 if (!NT_SUCCESS(Status
))
1839 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
1840 return RtlNtStatusToDosError (Status
);
1843 return ERROR_SUCCESS
;
1847 /************************************************************************
1853 RegLoadKeyA (HKEY hKey
,
1857 UNICODE_STRING FileName
;
1858 UNICODE_STRING KeyName
;
1861 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1863 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1866 ErrorCode
= RegLoadKeyW (hKey
,
1870 RtlFreeUnicodeString (&FileName
);
1871 RtlFreeUnicodeString (&KeyName
);
1877 /************************************************************************
1883 RegLoadKeyW (HKEY hKey
,
1887 OBJECT_ATTRIBUTES FileObjectAttributes
;
1888 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1889 UNICODE_STRING FileName
;
1890 UNICODE_STRING KeyName
;
1894 if (hKey
== HKEY_PERFORMANCE_DATA
)
1896 return ERROR_INVALID_HANDLE
;
1899 Status
= MapDefaultKey (&KeyHandle
,
1901 if (!NT_SUCCESS(Status
))
1903 return RtlNtStatusToDosError (Status
);
1906 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1911 return ERROR_BAD_PATHNAME
;
1914 InitializeObjectAttributes (&FileObjectAttributes
,
1916 OBJ_CASE_INSENSITIVE
,
1920 RtlInitUnicodeString (&KeyName
,
1923 InitializeObjectAttributes (&KeyObjectAttributes
,
1925 OBJ_CASE_INSENSITIVE
,
1929 Status
= NtLoadKey (&KeyObjectAttributes
,
1930 &FileObjectAttributes
);
1932 RtlFreeUnicodeString (&FileName
);
1934 if (!NT_SUCCESS(Status
))
1936 return RtlNtStatusToDosError (Status
);
1939 return ERROR_SUCCESS
;
1943 /************************************************************************
1944 * RegNotifyChangeKeyValue
1949 RegNotifyChangeKeyValue (HKEY hKey
,
1951 DWORD dwNotifyFilter
,
1955 IO_STATUS_BLOCK IoStatusBlock
;
1959 if (hKey
== HKEY_PERFORMANCE_DATA
)
1961 return ERROR_INVALID_HANDLE
;
1964 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1966 return ERROR_INVALID_PARAMETER
;
1969 Status
= MapDefaultKey (&KeyHandle
,
1971 if (!NT_SUCCESS(Status
))
1973 return RtlNtStatusToDosError (Status
);
1976 /* FIXME: Remote key handles must fail */
1978 Status
= NtNotifyChangeKey (KeyHandle
,
1988 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1990 return RtlNtStatusToDosError (Status
);
1993 return ERROR_SUCCESS
;
1997 /************************************************************************
1998 * RegOpenCurrentUser
2003 RegOpenCurrentUser (IN REGSAM samDesired
,
2004 OUT PHKEY phkResult
)
2008 Status
= RtlOpenCurrentUser((ACCESS_MASK
)samDesired
,
2009 (PHANDLE
)phkResult
);
2010 if (!NT_SUCCESS(Status
))
2012 /* NOTE - don't set the last error code! just return the error! */
2013 return RtlNtStatusToDosError(Status
);
2016 return ERROR_SUCCESS
;
2020 /************************************************************************
2023 * 20050503 Fireball - imported from WINE
2028 RegOpenKeyA (HKEY hKey
,
2032 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2034 if (!lpSubKey
|| !*lpSubKey
)
2037 return ERROR_SUCCESS
;
2040 return RegOpenKeyExA( hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2044 /************************************************************************
2049 * 20050503 Fireball - imported from WINE
2054 RegOpenKeyW (HKEY hKey
,
2058 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2060 if (!lpSubKey
|| !*lpSubKey
)
2063 return ERROR_SUCCESS
;
2065 return RegOpenKeyExW(hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2069 /************************************************************************
2075 RegOpenKeyExA (HKEY hKey
,
2081 OBJECT_ATTRIBUTES ObjectAttributes
;
2082 UNICODE_STRING SubKeyString
;
2086 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2087 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2089 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2090 if (!NT_SUCCESS(Status
))
2092 return RtlNtStatusToDosError (Status
);
2095 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
, (LPSTR
)lpSubKey
);
2096 InitializeObjectAttributes (&ObjectAttributes
,
2098 OBJ_CASE_INSENSITIVE
,
2102 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2103 RtlFreeUnicodeString (&SubKeyString
);
2104 if (!NT_SUCCESS(Status
))
2106 return RtlNtStatusToDosError (Status
);
2109 return ERROR_SUCCESS
;
2113 /************************************************************************
2119 RegOpenKeyExW (HKEY hKey
,
2125 OBJECT_ATTRIBUTES ObjectAttributes
;
2126 UNICODE_STRING SubKeyString
;
2130 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2131 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2133 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2134 if (!NT_SUCCESS(Status
))
2136 return RtlNtStatusToDosError (Status
);
2139 if (lpSubKey
!= NULL
)
2140 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)lpSubKey
);
2142 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)L
"");
2144 InitializeObjectAttributes (&ObjectAttributes
,
2146 OBJ_CASE_INSENSITIVE
,
2150 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2152 if (!NT_SUCCESS(Status
))
2154 return RtlNtStatusToDosError (Status
);
2157 return ERROR_SUCCESS
;
2161 /************************************************************************
2162 * RegOpenUserClassesRoot
2167 RegOpenUserClassesRoot (IN HANDLE hToken
,
2169 IN REGSAM samDesired
,
2170 OUT PHKEY phkResult
)
2172 const WCHAR UserClassesKeyPrefix
[] = L
"\\Registry\\User\\";
2173 const WCHAR UserClassesKeySuffix
[] = L
"_Classes";
2174 PTOKEN_USER TokenUserData
;
2175 ULONG RequiredLength
;
2176 UNICODE_STRING UserSidString
, UserClassesKeyRoot
;
2177 OBJECT_ATTRIBUTES ObjectAttributes
;
2181 /* check parameters */
2182 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
2184 return ERROR_INVALID_PARAMETER
;
2188 * Get the user sid from the token
2192 /* determine how much memory we need */
2193 Status
= NtQueryInformationToken(hToken
,
2198 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2200 /* NOTE - as opposed to all other registry functions windows does indeed
2201 change the last error code in case the caller supplied a invalid
2202 handle for example! */
2203 ErrorCode
= RtlNtStatusToDosError (Status
);
2207 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2210 if (TokenUserData
== NULL
)
2212 return ERROR_NOT_ENOUGH_MEMORY
;
2215 /* attempt to read the information */
2216 Status
= NtQueryInformationToken(hToken
,
2221 if (!NT_SUCCESS(Status
))
2223 RtlFreeHeap(ProcessHeap
,
2226 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2228 /* the information appears to have changed?! try again */
2232 /* NOTE - as opposed to all other registry functions windows does indeed
2233 change the last error code in case the caller supplied a invalid
2234 handle for example! */
2235 ErrorCode
= RtlNtStatusToDosError (Status
);
2240 * Build the absolute path for the user's registry in the form
2241 * "\Registry\User\<SID>_Classes"
2243 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2244 TokenUserData
->User
.Sid
,
2247 /* we don't need the user data anymore, free it */
2248 RtlFreeHeap(ProcessHeap
,
2252 if (!NT_SUCCESS(Status
))
2254 return RtlNtStatusToDosError (Status
);
2257 /* allocate enough memory for the entire key string */
2258 UserClassesKeyRoot
.Length
= 0;
2259 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
2260 sizeof(UserClassesKeyPrefix
) +
2261 sizeof(UserClassesKeySuffix
);
2262 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
2264 UserClassesKeyRoot
.MaximumLength
);
2265 if (UserClassesKeyRoot
.Buffer
== NULL
)
2267 RtlFreeUnicodeString(&UserSidString
);
2268 return RtlNtStatusToDosError (Status
);
2271 /* build the string */
2272 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2273 UserClassesKeyPrefix
);
2274 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
2276 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2277 UserClassesKeySuffix
);
2279 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
2285 InitializeObjectAttributes (&ObjectAttributes
,
2286 &UserClassesKeyRoot
,
2287 OBJ_CASE_INSENSITIVE
,
2291 Status
= NtOpenKey((PHANDLE
)phkResult
,
2295 RtlFreeUnicodeString(&UserSidString
);
2296 RtlFreeUnicodeString(&UserClassesKeyRoot
);
2298 if (!NT_SUCCESS(Status
))
2300 return RtlNtStatusToDosError (Status
);
2303 return ERROR_SUCCESS
;
2307 /************************************************************************
2313 RegQueryInfoKeyA (HKEY hKey
,
2318 LPDWORD lpcbMaxSubKeyLen
,
2319 LPDWORD lpcbMaxClassLen
,
2321 LPDWORD lpcbMaxValueNameLen
,
2322 LPDWORD lpcbMaxValueLen
,
2323 LPDWORD lpcbSecurityDescriptor
,
2324 PFILETIME lpftLastWriteTime
)
2326 WCHAR ClassName
[MAX_PATH
];
2327 UNICODE_STRING UnicodeString
;
2328 ANSI_STRING AnsiString
;
2331 RtlInitUnicodeString (&UnicodeString
,
2333 if (lpClass
!= NULL
)
2335 UnicodeString
.Buffer
= &ClassName
[0];
2336 UnicodeString
.MaximumLength
= sizeof(ClassName
);
2337 AnsiString
.MaximumLength
= *lpcbClass
;
2340 ErrorCode
= RegQueryInfoKeyW (hKey
,
2341 UnicodeString
.Buffer
,
2348 lpcbMaxValueNameLen
,
2350 lpcbSecurityDescriptor
,
2352 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
2354 AnsiString
.Buffer
= lpClass
;
2355 AnsiString
.Length
= 0;
2356 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
2357 RtlUnicodeStringToAnsiString (&AnsiString
,
2360 *lpcbClass
= AnsiString
.Length
;
2361 lpClass
[AnsiString
.Length
] = 0;
2368 /************************************************************************
2374 RegQueryInfoKeyW (HKEY hKey
,
2379 LPDWORD lpcbMaxSubKeyLen
,
2380 LPDWORD lpcbMaxClassLen
,
2382 LPDWORD lpcbMaxValueNameLen
,
2383 LPDWORD lpcbMaxValueLen
,
2384 LPDWORD lpcbSecurityDescriptor
,
2385 PFILETIME lpftLastWriteTime
)
2387 KEY_FULL_INFORMATION FullInfoBuffer
;
2388 PKEY_FULL_INFORMATION FullInfo
;
2390 ULONG ClassLength
= 0;
2394 LONG ErrorCode
= ERROR_SUCCESS
;
2396 if ((lpClass
) && (!lpcbClass
))
2398 return ERROR_INVALID_PARAMETER
;
2401 Status
= MapDefaultKey (&KeyHandle
,
2403 if (!NT_SUCCESS(Status
))
2405 return RtlNtStatusToDosError (Status
);
2408 if (lpClass
!= NULL
)
2412 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2419 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2420 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2423 if (FullInfo
== NULL
)
2425 return ERROR_OUTOFMEMORY
;
2428 FullInfo
->ClassLength
= ClassLength
;
2432 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2433 FullInfo
= &FullInfoBuffer
;
2434 FullInfo
->ClassLength
= 0;
2436 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2438 Status
= NtQueryKey (KeyHandle
,
2443 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
2444 if (!NT_SUCCESS(Status
))
2446 if (lpClass
!= NULL
)
2448 RtlFreeHeap (ProcessHeap
,
2453 return RtlNtStatusToDosError (Status
);
2456 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
2457 if (lpcSubKeys
!= NULL
)
2459 *lpcSubKeys
= FullInfo
->SubKeys
;
2462 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2463 if (lpcbMaxSubKeyLen
!= NULL
)
2465 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2468 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2469 if (lpcbMaxClassLen
!= NULL
)
2471 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2474 TRACE("Values %lu\n", FullInfo
->Values
);
2475 if (lpcValues
!= NULL
)
2477 *lpcValues
= FullInfo
->Values
;
2480 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2481 if (lpcbMaxValueNameLen
!= NULL
)
2483 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2486 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2487 if (lpcbMaxValueLen
!= NULL
)
2489 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2492 if (lpcbSecurityDescriptor
!= NULL
)
2494 Status
= NtQuerySecurityObject(KeyHandle
,
2495 OWNER_SECURITY_INFORMATION
|
2496 GROUP_SECURITY_INFORMATION
|
2497 DACL_SECURITY_INFORMATION
,
2500 lpcbSecurityDescriptor
);
2501 if (!NT_SUCCESS(Status
))
2503 if (lpClass
!= NULL
)
2505 RtlFreeHeap(ProcessHeap
,
2510 return RtlNtStatusToDosError (Status
);
2514 if (lpftLastWriteTime
!= NULL
)
2516 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2517 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2520 if (lpClass
!= NULL
)
2522 if (FullInfo
->ClassLength
> ClassLength
)
2524 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2528 RtlCopyMemory (lpClass
,
2530 FullInfo
->ClassLength
);
2531 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2532 lpClass
[*lpcbClass
] = 0;
2535 RtlFreeHeap (ProcessHeap
,
2544 /************************************************************************
2545 * RegQueryMultipleValuesA
2550 RegQueryMultipleValuesA (HKEY hKey
,
2557 DWORD maxBytes
= *ldwTotsize
;
2558 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2561 if (maxBytes
>= (1024*1024))
2562 return ERROR_TRANSFER_TOO_LONG
;
2566 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
2567 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2569 for (i
= 0; i
< num_vals
; i
++)
2571 val_list
[i
].ve_valuelen
= 0;
2572 ErrorCode
= RegQueryValueExA (hKey
,
2573 val_list
[i
].ve_valuename
,
2577 &val_list
[i
].ve_valuelen
);
2578 if (ErrorCode
!= ERROR_SUCCESS
)
2583 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2585 ErrorCode
= RegQueryValueExA (hKey
,
2586 val_list
[i
].ve_valuename
,
2588 &val_list
[i
].ve_type
,
2590 &val_list
[i
].ve_valuelen
);
2591 if (ErrorCode
!= ERROR_SUCCESS
)
2596 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2598 bufptr
+= val_list
[i
].ve_valuelen
;
2601 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2604 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2608 /************************************************************************
2609 * RegQueryMultipleValuesW
2614 RegQueryMultipleValuesW (HKEY hKey
,
2621 DWORD maxBytes
= *ldwTotsize
;
2622 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2625 if (maxBytes
>= (1024*1024))
2626 return ERROR_TRANSFER_TOO_LONG
;
2630 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2631 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2633 for (i
= 0; i
< num_vals
; i
++)
2635 val_list
[i
].ve_valuelen
= 0;
2636 ErrorCode
= RegQueryValueExW (hKey
,
2637 val_list
[i
].ve_valuename
,
2641 &val_list
[i
].ve_valuelen
);
2642 if (ErrorCode
!= ERROR_SUCCESS
)
2647 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2649 ErrorCode
= RegQueryValueExW (hKey
,
2650 val_list
[i
].ve_valuename
,
2652 &val_list
[i
].ve_type
,
2654 &val_list
[i
].ve_valuelen
);
2655 if (ErrorCode
!= ERROR_SUCCESS
)
2660 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2662 bufptr
+= val_list
[i
].ve_valuelen
;
2665 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2668 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2672 /************************************************************************
2678 RegQueryValueExW (HKEY hKey
,
2679 LPCWSTR lpValueName
,
2685 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2686 UNICODE_STRING ValueName
;
2691 LONG ErrorCode
= ERROR_SUCCESS
;
2692 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2694 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2695 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2697 Status
= MapDefaultKey (&KeyHandle
,
2699 if (!NT_SUCCESS(Status
))
2701 return RtlNtStatusToDosError (Status
);
2704 if (lpData
!= NULL
&& lpcbData
== NULL
)
2706 return ERROR_INVALID_PARAMETER
;
2709 RtlInitUnicodeString (&ValueName
,
2711 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2712 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2715 if (ValueInfo
== NULL
)
2717 return ERROR_OUTOFMEMORY
;
2720 Status
= NtQueryValueKey (KeyHandle
,
2722 KeyValuePartialInformation
,
2726 TRACE("Status 0x%X\n", Status
);
2727 if (Status
== STATUS_BUFFER_OVERFLOW
)
2729 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2731 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2733 else if (!NT_SUCCESS(Status
))
2735 ErrorCode
= RtlNtStatusToDosError (Status
);
2737 if (lpcbData
!= NULL
)
2739 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2745 *lpType
= ValueInfo
->Type
;
2748 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2750 RtlMoveMemory (lpData
,
2752 min(ValueInfo
->DataLength
, MaxCopy
));
2755 if ((ValueInfo
->Type
== REG_SZ
) ||
2756 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2757 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2759 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2761 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2764 if (lpcbData
!= NULL
)
2766 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2767 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
2772 if (lpcbData
!= NULL
)
2774 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2775 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
2779 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2781 RtlFreeHeap (ProcessHeap
,
2789 /************************************************************************
2795 RegQueryValueExA (HKEY hKey
,
2802 UNICODE_STRING ValueName
;
2803 UNICODE_STRING ValueData
;
2804 ANSI_STRING AnsiString
;
2809 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
2810 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2812 if (lpData
!= NULL
&& lpcbData
== NULL
)
2814 return ERROR_INVALID_PARAMETER
;
2819 ValueData
.Length
= 0;
2820 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
2821 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2823 ValueData
.MaximumLength
);
2824 if (!ValueData
.Buffer
)
2826 return ERROR_OUTOFMEMORY
;
2831 ValueData
.Buffer
= NULL
;
2832 ValueData
.Length
= 0;
2833 ValueData
.MaximumLength
= 0;
2836 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2837 (LPSTR
)lpValueName
);
2839 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
2840 ErrorCode
= RegQueryValueExW (hKey
,
2844 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
2846 TRACE("ErrorCode %lu\n", ErrorCode
);
2847 RtlFreeUnicodeString(&ValueName
);
2849 if (ErrorCode
== ERROR_SUCCESS
||
2850 ErrorCode
== ERROR_MORE_DATA
)
2857 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2859 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2861 RtlInitAnsiString(&AnsiString
, NULL
);
2862 AnsiString
.Buffer
= (LPSTR
)lpData
;
2863 AnsiString
.MaximumLength
= *lpcbData
;
2864 ValueData
.Length
= Length
;
2865 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2866 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2868 Length
= Length
/ sizeof(WCHAR
);
2870 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2872 if (*lpcbData
< Length
)
2874 ErrorCode
= ERROR_MORE_DATA
;
2878 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2882 if (lpcbData
!= NULL
)
2888 if (ValueData
.Buffer
!= NULL
)
2890 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2897 /************************************************************************
2903 RegQueryValueA (HKEY hKey
,
2908 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2909 UNICODE_STRING SubKeyName
;
2910 UNICODE_STRING Value
;
2911 ANSI_STRING AnsiString
;
2915 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
2916 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
2918 if (lpValue
!= NULL
&&
2921 return ERROR_INVALID_PARAMETER
;
2924 RtlInitUnicodeString (&SubKeyName
,
2926 RtlInitUnicodeString (&Value
,
2928 if (lpSubKey
!= NULL
&&
2929 strlen(lpSubKey
) != 0)
2931 RtlInitAnsiString (&AnsiString
,
2933 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2934 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2935 RtlAnsiStringToUnicodeString (&SubKeyName
,
2940 if (lpValue
!= NULL
)
2942 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2943 Value
.MaximumLength
= ValueSize
;
2944 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2947 if (Value
.Buffer
== NULL
)
2949 return ERROR_OUTOFMEMORY
;
2957 ErrorCode
= RegQueryValueW (hKey
,
2958 (LPCWSTR
)SubKeyName
.Buffer
,
2961 if (ErrorCode
== ERROR_SUCCESS
)
2963 Value
.Length
= ValueSize
;
2964 RtlInitAnsiString (&AnsiString
,
2966 AnsiString
.Buffer
= lpValue
;
2967 AnsiString
.MaximumLength
= *lpcbValue
;
2968 RtlUnicodeStringToAnsiString (&AnsiString
,
2973 *lpcbValue
= ValueSize
;
2974 if (Value
.Buffer
!= NULL
)
2976 RtlFreeHeap (ProcessHeap
,
2985 /************************************************************************
2991 RegQueryValueW (HKEY hKey
,
2996 OBJECT_ATTRIBUTES ObjectAttributes
;
2997 UNICODE_STRING SubKeyString
;
3004 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
3005 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3007 Status
= MapDefaultKey (&KeyHandle
,
3009 if (!NT_SUCCESS(Status
))
3011 return RtlNtStatusToDosError (Status
);
3014 if (lpSubKey
!= NULL
&&
3015 wcslen(lpSubKey
) != 0)
3017 RtlInitUnicodeString (&SubKeyString
,
3019 InitializeObjectAttributes (&ObjectAttributes
,
3021 OBJ_CASE_INSENSITIVE
,
3024 Status
= NtOpenKey (&RealKey
,
3027 if (!NT_SUCCESS(Status
))
3029 return RtlNtStatusToDosError (Status
);
3031 CloseRealKey
= TRUE
;
3036 CloseRealKey
= FALSE
;
3039 ErrorCode
= RegQueryValueExW (RealKey
,
3044 (LPDWORD
)lpcbValue
);
3054 /************************************************************************
3060 RegReplaceKeyA (HKEY hKey
,
3065 UNICODE_STRING SubKey
;
3066 UNICODE_STRING NewFile
;
3067 UNICODE_STRING OldFile
;
3070 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
3072 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
3074 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
3077 ErrorCode
= RegReplaceKeyW (hKey
,
3082 RtlFreeUnicodeString (&OldFile
);
3083 RtlFreeUnicodeString (&NewFile
);
3084 RtlFreeUnicodeString (&SubKey
);
3090 /************************************************************************
3096 RegReplaceKeyW (HKEY hKey
,
3101 OBJECT_ATTRIBUTES KeyObjectAttributes
;
3102 OBJECT_ATTRIBUTES NewObjectAttributes
;
3103 OBJECT_ATTRIBUTES OldObjectAttributes
;
3104 UNICODE_STRING SubKeyName
;
3105 UNICODE_STRING NewFileName
;
3106 UNICODE_STRING OldFileName
;
3107 BOOLEAN CloseRealKey
;
3108 HANDLE RealKeyHandle
;
3112 if (hKey
== HKEY_PERFORMANCE_DATA
)
3114 return ERROR_INVALID_HANDLE
;
3117 Status
= MapDefaultKey (&KeyHandle
,
3119 if (!NT_SUCCESS(Status
))
3121 return RtlNtStatusToDosError (Status
);
3124 /* Open the real key */
3125 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
3127 RtlInitUnicodeString (&SubKeyName
,
3129 InitializeObjectAttributes (&KeyObjectAttributes
,
3131 OBJ_CASE_INSENSITIVE
,
3134 Status
= NtOpenKey (&RealKeyHandle
,
3136 &KeyObjectAttributes
);
3137 if (!NT_SUCCESS(Status
))
3139 return RtlNtStatusToDosError (Status
);
3141 CloseRealKey
= TRUE
;
3145 RealKeyHandle
= KeyHandle
;
3146 CloseRealKey
= FALSE
;
3149 /* Convert new file name */
3150 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
3157 NtClose (RealKeyHandle
);
3159 return ERROR_INVALID_PARAMETER
;
3162 InitializeObjectAttributes (&NewObjectAttributes
,
3164 OBJ_CASE_INSENSITIVE
,
3168 /* Convert old file name */
3169 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
3174 RtlFreeUnicodeString (&NewFileName
);
3177 NtClose (RealKeyHandle
);
3179 return ERROR_INVALID_PARAMETER
;
3182 InitializeObjectAttributes (&OldObjectAttributes
,
3184 OBJ_CASE_INSENSITIVE
,
3188 Status
= NtReplaceKey (&NewObjectAttributes
,
3190 &OldObjectAttributes
);
3192 RtlFreeUnicodeString (&OldFileName
);
3193 RtlFreeUnicodeString (&NewFileName
);
3197 NtClose (RealKeyHandle
);
3200 if (!NT_SUCCESS(Status
))
3202 return RtlNtStatusToDosError (Status
);
3205 return ERROR_SUCCESS
;
3209 /************************************************************************
3215 RegRestoreKeyA (HKEY hKey
,
3219 UNICODE_STRING FileName
;
3222 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3225 ErrorCode
= RegRestoreKeyW (hKey
,
3229 RtlFreeUnicodeString (&FileName
);
3235 /************************************************************************
3241 RegRestoreKeyW (HKEY hKey
,
3245 OBJECT_ATTRIBUTES ObjectAttributes
;
3246 IO_STATUS_BLOCK IoStatusBlock
;
3247 UNICODE_STRING FileName
;
3252 if (hKey
== HKEY_PERFORMANCE_DATA
)
3254 return ERROR_INVALID_HANDLE
;
3257 Status
= MapDefaultKey (&KeyHandle
,
3259 if (!NT_SUCCESS(Status
))
3261 return RtlNtStatusToDosError (Status
);
3264 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
3269 return ERROR_INVALID_PARAMETER
;
3272 InitializeObjectAttributes (&ObjectAttributes
,
3274 OBJ_CASE_INSENSITIVE
,
3278 Status
= NtOpenFile (&FileHandle
,
3283 FILE_SYNCHRONOUS_IO_NONALERT
);
3284 RtlFreeUnicodeString (&FileName
);
3285 if (!NT_SUCCESS(Status
))
3287 return RtlNtStatusToDosError (Status
);
3290 Status
= NtRestoreKey (KeyHandle
,
3293 NtClose (FileHandle
);
3294 if (!NT_SUCCESS(Status
))
3296 return RtlNtStatusToDosError (Status
);
3299 return ERROR_SUCCESS
;
3303 /************************************************************************
3309 RegSaveKeyA (HKEY hKey
,
3311 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3313 UNICODE_STRING FileName
;
3316 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3318 ErrorCode
= RegSaveKeyW (hKey
,
3320 lpSecurityAttributes
);
3321 RtlFreeUnicodeString (&FileName
);
3327 /************************************************************************
3333 RegSaveKeyW (HKEY hKey
,
3335 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3337 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
3338 OBJECT_ATTRIBUTES ObjectAttributes
;
3339 UNICODE_STRING FileName
;
3340 IO_STATUS_BLOCK IoStatusBlock
;
3345 Status
= MapDefaultKey (&KeyHandle
,
3347 if (!NT_SUCCESS(Status
))
3349 return RtlNtStatusToDosError (Status
);
3352 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
3357 return ERROR_INVALID_PARAMETER
;
3360 if (lpSecurityAttributes
!= NULL
)
3362 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
3365 InitializeObjectAttributes (&ObjectAttributes
,
3367 OBJ_CASE_INSENSITIVE
,
3369 SecurityDescriptor
);
3370 Status
= NtCreateFile (&FileHandle
,
3371 GENERIC_WRITE
| SYNCHRONIZE
,
3375 FILE_ATTRIBUTE_NORMAL
,
3378 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
3381 RtlFreeUnicodeString (&FileName
);
3382 if (!NT_SUCCESS(Status
))
3384 return RtlNtStatusToDosError (Status
);
3387 Status
= NtSaveKey (KeyHandle
,
3389 NtClose (FileHandle
);
3390 if (!NT_SUCCESS(Status
))
3392 return RtlNtStatusToDosError (Status
);
3395 return ERROR_SUCCESS
;
3399 /************************************************************************
3405 RegSetKeySecurity (HKEY hKey
,
3406 SECURITY_INFORMATION SecurityInformation
,
3407 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3412 if (hKey
== HKEY_PERFORMANCE_DATA
)
3414 return ERROR_INVALID_HANDLE
;
3417 Status
= MapDefaultKey (&KeyHandle
,
3419 if (!NT_SUCCESS(Status
))
3421 return RtlNtStatusToDosError (Status
);
3424 Status
= NtSetSecurityObject (KeyHandle
,
3425 SecurityInformation
,
3426 pSecurityDescriptor
);
3427 if (!NT_SUCCESS(Status
))
3429 return RtlNtStatusToDosError (Status
);
3432 return ERROR_SUCCESS
;
3436 /************************************************************************
3442 RegSetValueExA (HKEY hKey
,
3449 UNICODE_STRING ValueName
;
3451 ANSI_STRING AnsiString
;
3452 UNICODE_STRING Data
;
3457 if (lpValueName
!= NULL
&&
3458 strlen(lpValueName
) != 0)
3460 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3462 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3469 if (((dwType
== REG_SZ
) ||
3470 (dwType
== REG_MULTI_SZ
) ||
3471 (dwType
== REG_EXPAND_SZ
)) &&
3474 /* NT adds one if the caller forgot the NULL-termination character */
3475 if (lpData
[cbData
- 1] != '\0')
3480 RtlInitAnsiString (&AnsiString
,
3482 AnsiString
.Buffer
= (PSTR
)lpData
;
3483 AnsiString
.Length
= cbData
- 1;
3484 AnsiString
.MaximumLength
= cbData
;
3485 RtlAnsiStringToUnicodeString (&Data
,
3488 pData
= (LPBYTE
)Data
.Buffer
;
3489 DataSize
= cbData
* sizeof(WCHAR
);
3493 RtlInitUnicodeString (&Data
,
3495 pData
= (LPBYTE
)lpData
;
3499 ErrorCode
= RegSetValueExW (hKey
,
3505 if (pValueName
!= NULL
)
3507 RtlFreeHeap (ProcessHeap
,
3512 if (Data
.Buffer
!= NULL
)
3514 RtlFreeHeap (ProcessHeap
,
3523 /************************************************************************
3529 RegSetValueExW (HKEY hKey
,
3530 LPCWSTR lpValueName
,
3536 UNICODE_STRING ValueName
;
3537 PUNICODE_STRING pValueName
;
3541 Status
= MapDefaultKey (&KeyHandle
,
3543 if (!NT_SUCCESS(Status
))
3545 return RtlNtStatusToDosError (Status
);
3548 if (lpValueName
!= NULL
)
3550 RtlInitUnicodeString (&ValueName
,
3555 RtlInitUnicodeString (&ValueName
, L
"");
3557 pValueName
= &ValueName
;
3559 if (((dwType
== REG_SZ
) ||
3560 (dwType
== REG_MULTI_SZ
) ||
3561 (dwType
== REG_EXPAND_SZ
)) &&
3562 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
3564 /* NT adds one if the caller forgot the NULL-termination character */
3565 cbData
+= sizeof(WCHAR
);
3568 Status
= NtSetValueKey (KeyHandle
,
3574 if (!NT_SUCCESS(Status
))
3576 return RtlNtStatusToDosError (Status
);
3579 return ERROR_SUCCESS
;
3583 /************************************************************************
3589 RegSetValueA (HKEY hKey
,
3598 if (dwType
!= REG_SZ
)
3600 return ERROR_INVALID_PARAMETER
;
3603 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
3605 ret
= RegCreateKeyA(hKey
,
3609 if (ret
!= ERROR_SUCCESS
)
3617 ret
= RegSetValueExA(hSubKey
,
3621 (CONST BYTE
*)lpData
,
3622 strlen(lpData
) + 1);
3624 if (hSubKey
!= hKey
)
3626 RegCloseKey(hSubKey
);
3633 /************************************************************************
3639 RegSetValueW (HKEY hKey
,
3645 OBJECT_ATTRIBUTES ObjectAttributes
;
3646 UNICODE_STRING SubKeyString
;
3653 Status
= MapDefaultKey (&KeyHandle
,
3655 if (!NT_SUCCESS(Status
))
3657 return RtlNtStatusToDosError (Status
);
3660 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3662 RtlInitUnicodeString (&SubKeyString
,
3664 InitializeObjectAttributes (&ObjectAttributes
,
3666 OBJ_CASE_INSENSITIVE
,
3669 Status
= NtOpenKey (&RealKey
,
3672 if (!NT_SUCCESS(Status
))
3674 return RtlNtStatusToDosError (Status
);
3676 CloseRealKey
= TRUE
;
3681 CloseRealKey
= FALSE
;
3684 ErrorCode
= RegSetValueExW (RealKey
,
3690 if (CloseRealKey
== TRUE
)
3699 /************************************************************************
3705 RegUnLoadKeyA (HKEY hKey
,
3708 UNICODE_STRING KeyName
;
3711 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3714 ErrorCode
= RegUnLoadKeyW (hKey
,
3717 RtlFreeUnicodeString (&KeyName
);
3723 /************************************************************************
3729 RegUnLoadKeyW (HKEY hKey
,
3732 OBJECT_ATTRIBUTES ObjectAttributes
;
3733 UNICODE_STRING KeyName
;
3737 if (hKey
== HKEY_PERFORMANCE_DATA
)
3739 return ERROR_INVALID_HANDLE
;
3742 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3743 if (!NT_SUCCESS(Status
))
3745 return RtlNtStatusToDosError (Status
);
3748 RtlInitUnicodeString (&KeyName
,
3751 InitializeObjectAttributes (&ObjectAttributes
,
3753 OBJ_CASE_INSENSITIVE
,
3757 Status
= NtUnloadKey (&ObjectAttributes
);
3759 if (!NT_SUCCESS(Status
))
3761 return RtlNtStatusToDosError (Status
);
3764 return ERROR_SUCCESS
;