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)
8 * Thomas Weidenmueller <w3seek@reactos.com>
12 * 20050502 Fireball imported some stuff from WINE
15 /* INCLUDES *****************************************************************/
19 #include <wine/debug.h>
21 /* DEFINES ******************************************************************/
23 #define MAX_DEFAULT_HANDLES 6
24 #define REG_MAX_NAME_SIZE 256
25 #define REG_MAX_DATA_SIZE 2048
27 /* GLOBALS ******************************************************************/
29 static RTL_CRITICAL_SECTION HandleTableCS
;
30 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
31 static HANDLE ProcessHeap
;
32 static BOOLEAN DefaultHandlesDisabled
= FALSE
;
33 static BOOLEAN DefaultHandleHKUDisabled
= FALSE
;
35 /* PROTOTYPES ***************************************************************/
37 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
38 static VOID
CloseDefaultKeys(VOID
);
39 #define ClosePredefKey(Handle) \
40 if ((ULONG_PTR)Handle & 0x1) { \
43 #define IsPredefKey(HKey) \
44 (((ULONG)(HKey) & 0xF0000000) == 0x80000000)
45 #define GetPredefKeyIndex(HKey) \
46 ((ULONG)(HKey) & 0x0FFFFFFF)
48 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
49 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
50 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
51 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
54 /* FUNCTIONS ****************************************************************/
55 /* check if value type needs string conversion (Ansi<->Unicode) */
56 __inline
static int is_string( DWORD type
)
58 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
61 /************************************************************************
62 * RegInitDefaultHandles
67 TRACE("RegInitialize()\n");
69 ProcessHeap
= RtlGetProcessHeap();
70 RtlZeroMemory (DefaultHandleTable
,
71 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
72 RtlInitializeCriticalSection (&HandleTableCS
);
78 /************************************************************************
84 TRACE("RegCleanup()\n");
87 RtlDeleteCriticalSection (&HandleTableCS
);
94 OpenPredefinedKey(IN ULONG Index
,
101 case 0: /* HKEY_CLASSES_ROOT */
102 Status
= OpenClassesRootKey (Handle
);
105 case 1: /* HKEY_CURRENT_USER */
106 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
110 case 2: /* HKEY_LOCAL_MACHINE */
111 Status
= OpenLocalMachineKey (Handle
);
114 case 3: /* HKEY_USERS */
115 Status
= OpenUsersKey (Handle
);
118 case 4: /* HKEY_PERFORMANCE_DATA */
119 Status
= OpenPerformanceDataKey (Handle
);
123 case 5: /* HKEY_CURRENT_CONFIG */
124 Status
= OpenCurrentConfigKey (Handle
);
127 case 6: /* HKEY_DYN_DATA */
128 Status
= STATUS_NOT_IMPLEMENTED
;
132 WARN("MapDefaultHandle() no handle creator\n");
133 Status
= STATUS_INVALID_PARAMETER
;
142 MapDefaultKey (OUT PHANDLE RealKey
,
147 BOOLEAN DoOpen
, DefDisabled
;
148 NTSTATUS Status
= STATUS_SUCCESS
;
150 TRACE("MapDefaultKey (Key %x)\n", Key
);
152 if (!IsPredefKey(Key
))
154 *RealKey
= (HANDLE
)((ULONG_PTR
)Key
& ~0x1);
155 return STATUS_SUCCESS
;
158 /* Handle special cases here */
159 Index
= GetPredefKeyIndex(Key
);
160 if (Index
>= MAX_DEFAULT_HANDLES
)
162 return STATUS_INVALID_PARAMETER
;
165 RtlEnterCriticalSection (&HandleTableCS
);
167 if (Key
== HKEY_CURRENT_USER
)
168 DefDisabled
= DefaultHandleHKUDisabled
;
170 DefDisabled
= DefaultHandlesDisabled
;
174 Handle
= &DefaultHandleTable
[Index
];
175 DoOpen
= (*Handle
== NULL
);
185 /* create/open the default handle */
186 Status
= OpenPredefinedKey(Index
,
190 if (NT_SUCCESS(Status
))
195 *(PULONG_PTR
)Handle
|= 0x1;
198 RtlLeaveCriticalSection (&HandleTableCS
);
205 CloseDefaultKeys (VOID
)
209 RtlEnterCriticalSection (&HandleTableCS
);
210 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
212 if (DefaultHandleTable
[i
] != NULL
)
214 NtClose (DefaultHandleTable
[i
]);
215 DefaultHandleTable
[i
] = NULL
;
218 RtlLeaveCriticalSection (&HandleTableCS
);
223 OpenClassesRootKey (PHANDLE KeyHandle
)
225 OBJECT_ATTRIBUTES Attributes
;
226 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\CLASSES");
228 TRACE("OpenClassesRootKey()\n");
230 InitializeObjectAttributes (&Attributes
,
232 OBJ_CASE_INSENSITIVE
,
235 return NtOpenKey (KeyHandle
,
242 OpenLocalMachineKey (PHANDLE KeyHandle
)
244 OBJECT_ATTRIBUTES Attributes
;
245 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine");
248 TRACE("OpenLocalMachineKey()\n");
250 InitializeObjectAttributes (&Attributes
,
252 OBJ_CASE_INSENSITIVE
,
255 Status
= NtOpenKey (KeyHandle
,
259 TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
265 OpenUsersKey (PHANDLE KeyHandle
)
267 OBJECT_ATTRIBUTES Attributes
;
268 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\User");
270 TRACE("OpenUsersKey()\n");
272 InitializeObjectAttributes (&Attributes
,
274 OBJ_CASE_INSENSITIVE
,
277 return NtOpenKey (KeyHandle
,
284 OpenCurrentConfigKey (PHANDLE KeyHandle
)
286 OBJECT_ATTRIBUTES Attributes
;
287 UNICODE_STRING KeyName
=
288 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
290 TRACE("OpenCurrentConfigKey()\n");
292 InitializeObjectAttributes (&Attributes
,
294 OBJ_CASE_INSENSITIVE
,
297 return NtOpenKey (KeyHandle
,
303 /************************************************************************
304 * RegDisablePredefinedCache
309 RegDisablePredefinedCache(VOID
)
311 RtlEnterCriticalSection (&HandleTableCS
);
312 DefaultHandleHKUDisabled
= TRUE
;
313 RtlLeaveCriticalSection (&HandleTableCS
);
314 return ERROR_SUCCESS
;
318 /************************************************************************
319 * RegDisablePredefinedCacheEx
324 RegDisablePredefinedCacheEx(VOID
)
326 RtlEnterCriticalSection (&HandleTableCS
);
327 DefaultHandlesDisabled
= TRUE
;
328 DefaultHandleHKUDisabled
= TRUE
;
329 RtlLeaveCriticalSection (&HandleTableCS
);
330 return ERROR_SUCCESS
;
334 /************************************************************************
335 * RegOverridePredefKey
340 RegOverridePredefKey(IN HKEY hKey
,
341 IN HKEY hNewHKey OPTIONAL
)
343 LONG ErrorCode
= ERROR_SUCCESS
;
345 if ((hKey
== HKEY_CLASSES_ROOT
||
346 hKey
== HKEY_CURRENT_CONFIG
||
347 hKey
== HKEY_CURRENT_USER
||
348 hKey
== HKEY_LOCAL_MACHINE
||
349 hKey
== HKEY_PERFORMANCE_DATA
||
350 hKey
== HKEY_USERS
) &&
351 !IsPredefKey(hNewHKey
))
356 Index
= GetPredefKeyIndex(hKey
);
357 Handle
= &DefaultHandleTable
[Index
];
359 if (hNewHKey
== NULL
)
361 /* restore the default mapping */
362 NTSTATUS Status
= OpenPredefinedKey(Index
,
364 if (!NT_SUCCESS(Status
))
366 return RtlNtStatusToDosError(Status
);
369 ASSERT(hNewHKey
!= NULL
);
372 RtlEnterCriticalSection (&HandleTableCS
);
374 /* close the currently mapped handle if existing */
380 /* update the mapping */
383 RtlLeaveCriticalSection (&HandleTableCS
);
386 ErrorCode
= ERROR_INVALID_HANDLE
;
392 /************************************************************************
398 RegCloseKey (HKEY hKey
)
402 /* don't close null handle or a pseudo handle */
403 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
405 return ERROR_INVALID_HANDLE
;
408 Status
= NtClose (hKey
);
409 if (!NT_SUCCESS(Status
))
411 return RtlNtStatusToDosError (Status
);
414 return ERROR_SUCCESS
;
419 RegpCopyTree(IN HKEY hKeySrc
,
424 LIST_ENTRY ListEntry
;
427 } REGP_COPY_KEYS
, *PREGP_COPY_KEYS
;
429 LIST_ENTRY copyQueueHead
;
430 PREGP_COPY_KEYS copyKeys
, newCopyKeys
;
433 KEY_VALUE_FULL_INFORMATION
*KeyValue
;
434 KEY_NODE_INFORMATION
*KeyNode
;
437 ULONG Index
, BufferSizeRequired
, BufferSize
= 0x200;
438 NTSTATUS Status
= STATUS_SUCCESS
;
439 NTSTATUS Status2
= STATUS_SUCCESS
;
441 InitializeListHead(©QueueHead
);
443 Info
.Buffer
= RtlAllocateHeap(ProcessHeap
,
446 if (Info
.Buffer
== NULL
)
448 return STATUS_INSUFFICIENT_RESOURCES
;
451 copyKeys
= RtlAllocateHeap(ProcessHeap
,
453 sizeof(REGP_COPY_KEYS
));
454 if (copyKeys
!= NULL
)
456 copyKeys
->hKeySrc
= hKeySrc
;
457 copyKeys
->hKeyDest
= hKeyDest
;
458 InsertHeadList(©QueueHead
,
459 ©Keys
->ListEntry
);
461 /* FIXME - copy security from hKeySrc to hKeyDest or just for the subkeys? */
465 copyKeys
= CONTAINING_RECORD(copyQueueHead
.Flink
,
469 /* enumerate all values and copy them */
473 Status2
= NtEnumerateValueKey(copyKeys
->hKeySrc
,
475 KeyValueFullInformation
,
478 &BufferSizeRequired
);
479 if (NT_SUCCESS(Status2
))
481 UNICODE_STRING ValueName
;
484 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
485 ValueName
.Length
= Info
.KeyValue
->NameLength
;
486 ValueName
.MaximumLength
= ValueName
.Length
;
487 ValueName
.Buffer
= Info
.KeyValue
->Name
;
489 Data
= (PVOID
)((ULONG_PTR
)Info
.KeyValue
+ Info
.KeyValue
->DataOffset
);
491 Status2
= NtSetValueKey(copyKeys
->hKeyDest
,
493 Info
.KeyValue
->TitleIndex
,
496 Info
.KeyValue
->DataLength
);
498 /* don't break, let's try to copy as many values as possible */
499 if (!NT_SUCCESS(Status2
) && NT_SUCCESS(Status
))
506 else if (Status2
== STATUS_BUFFER_OVERFLOW
)
510 ASSERT(BufferSize
< BufferSizeRequired
);
512 Buffer
= RtlReAllocateHeap(ProcessHeap
,
518 Info
.Buffer
= Buffer
;
523 /* don't break, let's try to copy as many values as possible */
524 Status2
= STATUS_INSUFFICIENT_RESOURCES
;
527 if (NT_SUCCESS(Status
))
535 /* break to avoid an infinite loop in case of denied access or
537 if (Status2
!= STATUS_NO_MORE_ENTRIES
&& NT_SUCCESS(Status
))
546 /* enumerate all subkeys and open and enqueue them */
550 Status2
= NtEnumerateKey(copyKeys
->hKeySrc
,
555 &BufferSizeRequired
);
556 if (NT_SUCCESS(Status2
))
558 HANDLE KeyHandle
, NewKeyHandle
;
559 OBJECT_ATTRIBUTES ObjectAttributes
;
560 UNICODE_STRING SubKeyName
, ClassName
;
562 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
563 SubKeyName
.Length
= Info
.KeyNode
->NameLength
;
564 SubKeyName
.MaximumLength
= SubKeyName
.Length
;
565 SubKeyName
.Buffer
= Info
.KeyNode
->Name
;
566 ClassName
.Length
= Info
.KeyNode
->ClassLength
;
567 ClassName
.MaximumLength
= ClassName
.Length
;
568 ClassName
.Buffer
= (PWSTR
)((ULONG_PTR
)Info
.KeyNode
+ Info
.KeyNode
->ClassOffset
);
570 /* open the subkey with sufficient rights */
572 InitializeObjectAttributes(&ObjectAttributes
,
574 OBJ_CASE_INSENSITIVE
,
578 Status2
= NtOpenKey(&KeyHandle
,
579 KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
581 if (NT_SUCCESS(Status2
))
583 /* FIXME - attempt to query the security information */
585 InitializeObjectAttributes(&ObjectAttributes
,
587 OBJ_CASE_INSENSITIVE
,
591 Status2
= NtCreateKey(&NewKeyHandle
,
594 Info
.KeyNode
->TitleIndex
,
598 if (NT_SUCCESS(Status2
))
600 newCopyKeys
= RtlAllocateHeap(ProcessHeap
,
602 sizeof(REGP_COPY_KEYS
));
603 if (newCopyKeys
!= NULL
)
605 /* save the handles and enqueue the subkey */
606 newCopyKeys
->hKeySrc
= KeyHandle
;
607 newCopyKeys
->hKeyDest
= NewKeyHandle
;
608 InsertTailList(©QueueHead
,
609 &newCopyKeys
->ListEntry
);
614 NtClose(NewKeyHandle
);
616 Status2
= STATUS_INSUFFICIENT_RESOURCES
;
625 if (!NT_SUCCESS(Status2
) && NT_SUCCESS(Status
))
632 else if (Status2
== STATUS_BUFFER_OVERFLOW
)
636 ASSERT(BufferSize
< BufferSizeRequired
);
638 Buffer
= RtlReAllocateHeap(ProcessHeap
,
644 Info
.Buffer
= Buffer
;
649 /* don't break, let's try to copy as many keys as possible */
650 Status2
= STATUS_INSUFFICIENT_RESOURCES
;
653 if (NT_SUCCESS(Status
))
661 /* break to avoid an infinite loop in case of denied access or
663 if (Status2
!= STATUS_NO_MORE_ENTRIES
&& NT_SUCCESS(Status
))
672 /* close the handles and remove the entry from the list */
673 if (copyKeys
->hKeySrc
!= hKeySrc
)
675 NtClose(copyKeys
->hKeySrc
);
677 if (copyKeys
->hKeyDest
!= hKeyDest
)
679 NtClose(copyKeys
->hKeyDest
);
682 RemoveEntryList(©Keys
->ListEntry
);
684 RtlFreeHeap(ProcessHeap
,
687 } while (!IsListEmpty(©QueueHead
));
690 Status
= STATUS_INSUFFICIENT_RESOURCES
;
692 RtlFreeHeap(ProcessHeap
,
700 /************************************************************************
706 RegCopyTreeW(IN HKEY hKeySrc
,
707 IN LPCWSTR lpSubKey OPTIONAL
,
710 HANDLE DestKeyHandle
, KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
713 Status
= MapDefaultKey(&KeyHandle
,
715 if (!NT_SUCCESS(Status
))
717 return RtlNtStatusToDosError(Status
);
720 Status
= MapDefaultKey(&DestKeyHandle
,
722 if (!NT_SUCCESS(Status
))
727 if (lpSubKey
!= NULL
)
729 OBJECT_ATTRIBUTES ObjectAttributes
;
730 UNICODE_STRING SubKeyName
;
732 RtlInitUnicodeString(&SubKeyName
,
735 InitializeObjectAttributes(&ObjectAttributes
,
737 OBJ_CASE_INSENSITIVE
,
741 Status
= NtOpenKey(&SubKeyHandle
,
742 KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
744 if (!NT_SUCCESS(Status
))
749 CurKey
= SubKeyHandle
;
754 Status
= RegpCopyTree(CurKey
,
757 if (SubKeyHandle
!= NULL
)
759 NtClose(SubKeyHandle
);
763 ClosePredefKey(DestKeyHandle
);
765 ClosePredefKey(KeyHandle
);
767 if (!NT_SUCCESS(Status
))
769 return RtlNtStatusToDosError(Status
);
772 return ERROR_SUCCESS
;
776 /************************************************************************
782 RegCopyTreeA(IN HKEY hKeySrc
,
783 IN LPCSTR lpSubKey OPTIONAL
,
786 UNICODE_STRING SubKeyName
= {0};
789 if (lpSubKey
!= NULL
&&
790 !RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
793 return ERROR_NOT_ENOUGH_MEMORY
;
796 Ret
= RegCopyTreeW(hKeySrc
,
800 RtlFreeUnicodeString(&SubKeyName
);
806 /************************************************************************
807 * RegConnectRegistryA
812 RegConnectRegistryA (IN LPCSTR lpMachineName
,
816 UNICODE_STRING MachineName
= {0};
819 if (lpMachineName
!= NULL
&&
820 !RtlCreateUnicodeStringFromAsciiz(&MachineName
,
821 (LPSTR
)lpMachineName
))
823 return ERROR_NOT_ENOUGH_MEMORY
;
826 Ret
= RegConnectRegistryW(MachineName
.Buffer
,
830 RtlFreeUnicodeString(&MachineName
);
836 /************************************************************************
837 * RegConnectRegistryW
842 RegConnectRegistryW (LPCWSTR lpMachineName
,
846 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
847 return ERROR_CALL_NOT_IMPLEMENTED
;
851 /************************************************************************
854 * Create key and all necessary intermediate keys
857 CreateNestedKey(PHKEY KeyHandle
,
858 POBJECT_ATTRIBUTES ObjectAttributes
,
859 PUNICODE_STRING ClassString
,
862 DWORD
*lpdwDisposition
)
864 OBJECT_ATTRIBUTES LocalObjectAttributes
;
865 UNICODE_STRING LocalKeyName
;
868 ULONG FullNameLength
;
871 HANDLE LocalKeyHandle
;
873 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
879 (PULONG
)lpdwDisposition
);
880 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
881 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
884 /* Copy object attributes */
885 RtlCopyMemory (&LocalObjectAttributes
,
887 sizeof(OBJECT_ATTRIBUTES
));
888 RtlCreateUnicodeString (&LocalKeyName
,
889 ObjectAttributes
->ObjectName
->Buffer
);
890 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
891 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
893 /* Remove the last part of the key name and try to create the key again. */
894 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
896 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
897 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
899 Status
= STATUS_UNSUCCESSFUL
;
903 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
905 Status
= NtCreateKey (&LocalKeyHandle
,
907 &LocalObjectAttributes
,
912 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
915 if (!NT_SUCCESS(Status
))
917 RtlFreeUnicodeString (&LocalKeyName
);
921 /* Add removed parts of the key name and create them too. */
922 Length
= wcslen (LocalKeyName
.Buffer
);
925 NtClose (LocalKeyHandle
);
927 LocalKeyName
.Buffer
[Length
] = L
'\\';
928 Length
= wcslen (LocalKeyName
.Buffer
);
929 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
931 if (Length
== FullNameLength
)
933 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
939 (PULONG
)lpdwDisposition
);
942 Status
= NtCreateKey (&LocalKeyHandle
,
944 &LocalObjectAttributes
,
949 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
950 if (!NT_SUCCESS(Status
))
954 RtlFreeUnicodeString (&LocalKeyName
);
960 /************************************************************************
966 RegCreateKeyExA (HKEY hKey
,
972 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
974 LPDWORD lpdwDisposition
)
976 UNICODE_STRING SubKeyString
;
977 UNICODE_STRING ClassString
;
978 OBJECT_ATTRIBUTES Attributes
;
982 TRACE("RegCreateKeyExA() called\n");
984 /* get the real parent key */
985 Status
= MapDefaultKey (&ParentKey
,
987 if (!NT_SUCCESS(Status
))
989 return RtlNtStatusToDosError (Status
);
991 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
995 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
999 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
1001 InitializeObjectAttributes (&Attributes
,
1003 OBJ_CASE_INSENSITIVE
,
1005 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
1006 Status
= CreateNestedKey(phkResult
,
1008 (lpClass
== NULL
)? NULL
: &ClassString
,
1012 RtlFreeUnicodeString (&SubKeyString
);
1013 if (lpClass
!= NULL
)
1015 RtlFreeUnicodeString (&ClassString
);
1018 ClosePredefKey(ParentKey
);
1020 TRACE("Status %x\n", Status
);
1021 if (!NT_SUCCESS(Status
))
1023 return RtlNtStatusToDosError (Status
);
1026 return ERROR_SUCCESS
;
1030 /************************************************************************
1036 RegCreateKeyExW (HKEY hKey
,
1042 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
1044 LPDWORD lpdwDisposition
)
1046 UNICODE_STRING SubKeyString
;
1047 UNICODE_STRING ClassString
;
1048 OBJECT_ATTRIBUTES Attributes
;
1052 TRACE("RegCreateKeyExW() called\n");
1054 /* get the real parent key */
1055 Status
= MapDefaultKey (&ParentKey
,
1057 if (!NT_SUCCESS(Status
))
1059 return RtlNtStatusToDosError(Status
);
1061 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
1063 RtlInitUnicodeString (&ClassString
,
1065 RtlInitUnicodeString (&SubKeyString
,
1067 InitializeObjectAttributes (&Attributes
,
1069 OBJ_CASE_INSENSITIVE
,
1071 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
1072 Status
= CreateNestedKey(phkResult
,
1074 (lpClass
== NULL
)? NULL
: &ClassString
,
1079 ClosePredefKey(ParentKey
);
1081 TRACE("Status %x\n", Status
);
1082 if (!NT_SUCCESS(Status
))
1084 return RtlNtStatusToDosError (Status
);
1087 return ERROR_SUCCESS
;
1091 /************************************************************************
1097 RegCreateKeyA (HKEY hKey
,
1101 return RegCreateKeyExA (hKey
,
1113 /************************************************************************
1119 RegCreateKeyW (HKEY hKey
,
1123 return RegCreateKeyExW (hKey
,
1135 /************************************************************************
1141 RegDeleteKeyA (HKEY hKey
,
1144 OBJECT_ATTRIBUTES ObjectAttributes
;
1145 UNICODE_STRING SubKeyName
;
1150 Status
= MapDefaultKey (&ParentKey
,
1152 if (!NT_SUCCESS(Status
))
1154 return RtlNtStatusToDosError (Status
);
1157 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
1159 InitializeObjectAttributes(&ObjectAttributes
,
1161 OBJ_CASE_INSENSITIVE
,
1165 Status
= NtOpenKey (&TargetKey
,
1168 RtlFreeUnicodeString (&SubKeyName
);
1169 if (!NT_SUCCESS(Status
))
1174 Status
= NtDeleteKey (TargetKey
);
1175 NtClose (TargetKey
);
1178 ClosePredefKey(ParentKey
);
1180 if (!NT_SUCCESS(Status
))
1182 return RtlNtStatusToDosError(Status
);
1185 return ERROR_SUCCESS
;
1189 /************************************************************************
1195 RegDeleteKeyW (HKEY hKey
,
1198 OBJECT_ATTRIBUTES ObjectAttributes
;
1199 UNICODE_STRING SubKeyName
;
1204 Status
= MapDefaultKey (&ParentKey
,
1206 if (!NT_SUCCESS(Status
))
1208 return RtlNtStatusToDosError (Status
);
1211 RtlInitUnicodeString (&SubKeyName
,
1213 InitializeObjectAttributes (&ObjectAttributes
,
1215 OBJ_CASE_INSENSITIVE
,
1218 Status
= NtOpenKey (&TargetKey
,
1221 if (!NT_SUCCESS(Status
))
1226 Status
= NtDeleteKey (TargetKey
);
1227 NtClose (TargetKey
);
1230 ClosePredefKey(ParentKey
);
1232 if (!NT_SUCCESS(Status
))
1234 return RtlNtStatusToDosError (Status
);
1237 return ERROR_SUCCESS
;
1241 /************************************************************************
1242 * RegDeleteKeyValueW
1247 RegDeleteKeyValueW(IN HKEY hKey
,
1248 IN LPCWSTR lpSubKey OPTIONAL
,
1249 IN LPCWSTR lpValueName OPTIONAL
)
1251 UNICODE_STRING ValueName
;
1252 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1255 Status
= MapDefaultKey(&KeyHandle
,
1257 if (!NT_SUCCESS(Status
))
1259 return RtlNtStatusToDosError(Status
);
1262 if (lpSubKey
!= NULL
)
1264 OBJECT_ATTRIBUTES ObjectAttributes
;
1265 UNICODE_STRING SubKeyName
;
1267 RtlInitUnicodeString(&SubKeyName
,
1270 InitializeObjectAttributes(&ObjectAttributes
,
1272 OBJ_CASE_INSENSITIVE
,
1276 Status
= NtOpenKey(&SubKeyHandle
,
1279 if (!NT_SUCCESS(Status
))
1284 CurKey
= SubKeyHandle
;
1289 RtlInitUnicodeString(&ValueName
,
1290 (LPWSTR
)lpValueName
);
1292 Status
= NtDeleteValueKey(CurKey
,
1295 if (SubKeyHandle
!= NULL
)
1297 NtClose(SubKeyHandle
);
1301 ClosePredefKey(KeyHandle
);
1303 if (!NT_SUCCESS(Status
))
1305 return RtlNtStatusToDosError(Status
);
1308 return ERROR_SUCCESS
;
1312 /************************************************************************
1313 * RegDeleteKeyValueA
1318 RegDeleteKeyValueA(IN HKEY hKey
,
1319 IN LPCSTR lpSubKey OPTIONAL
,
1320 IN LPCSTR lpValueName OPTIONAL
)
1322 UNICODE_STRING SubKey
= {0}, ValueName
= {0};
1325 if (lpSubKey
!= NULL
&&
1326 !RtlCreateUnicodeStringFromAsciiz(&SubKey
,
1329 return ERROR_NOT_ENOUGH_MEMORY
;
1332 if (lpValueName
!= NULL
&&
1333 !RtlCreateUnicodeStringFromAsciiz(&ValueName
,
1334 (LPSTR
)lpValueName
))
1336 RtlFreeUnicodeString(&SubKey
);
1337 return ERROR_NOT_ENOUGH_MEMORY
;
1340 Ret
= RegDeleteKeyValueW(hKey
,
1344 RtlFreeUnicodeString(&SubKey
);
1345 RtlFreeUnicodeString(&ValueName
);
1352 RegpDeleteTree(IN HKEY hKey
)
1356 LIST_ENTRY ListEntry
;
1358 } REGP_DEL_KEYS
, *PREG_DEL_KEYS
;
1360 LIST_ENTRY delQueueHead
;
1361 PREG_DEL_KEYS delKeys
, newDelKeys
;
1364 PKEY_BASIC_INFORMATION BasicInfo
;
1365 PREG_DEL_KEYS KeyDelRoot
;
1366 NTSTATUS Status
= STATUS_SUCCESS
;
1367 NTSTATUS Status2
= STATUS_SUCCESS
;
1369 InitializeListHead(&delQueueHead
);
1371 ProcessHeap
= RtlGetProcessHeap();
1373 /* NOTE: no need to allocate enough memory for an additional KEY_BASIC_INFORMATION
1374 structure for the root key, we only do that for subkeys as we need to
1375 allocate REGP_DEL_KEYS structures anyway! */
1376 KeyDelRoot
= RtlAllocateHeap(ProcessHeap
,
1378 sizeof(REGP_DEL_KEYS
));
1379 if (KeyDelRoot
!= NULL
)
1381 KeyDelRoot
->KeyHandle
= hKey
;
1382 InsertTailList(&delQueueHead
,
1383 &KeyDelRoot
->ListEntry
);
1387 delKeys
= CONTAINING_RECORD(delQueueHead
.Flink
,
1396 /* check if this key contains subkeys and delete them first by queuing
1397 them at the head of the list */
1398 Status2
= NtEnumerateKey(delKeys
->KeyHandle
,
1400 KeyBasicInformation
,
1405 if (NT_SUCCESS(Status2
))
1407 OBJECT_ATTRIBUTES ObjectAttributes
;
1408 UNICODE_STRING SubKeyName
;
1410 ASSERT(newDelKeys
!= NULL
);
1411 ASSERT(BasicInfo
!= NULL
);
1413 /* don't use RtlInitUnicodeString as the string is not NULL-terminated! */
1414 SubKeyName
.Length
= BasicInfo
->NameLength
;
1415 SubKeyName
.MaximumLength
= BasicInfo
->NameLength
;
1416 SubKeyName
.Buffer
= BasicInfo
->Name
;
1418 InitializeObjectAttributes(&ObjectAttributes
,
1420 OBJ_CASE_INSENSITIVE
,
1424 /* open the subkey */
1425 Status2
= NtOpenKey(&newDelKeys
->KeyHandle
,
1426 DELETE
| KEY_ENUMERATE_SUB_KEYS
,
1428 if (!NT_SUCCESS(Status2
))
1433 /* enqueue this key to the head of the deletion queue */
1434 InsertHeadList(&delQueueHead
,
1435 &newDelKeys
->ListEntry
);
1437 /* try again from the head of the list */
1442 if (Status2
== STATUS_BUFFER_TOO_SMALL
)
1444 newDelKeys
= RtlAllocateHeap(ProcessHeap
,
1446 BufferSize
+ sizeof(REGP_DEL_KEYS
));
1447 if (newDelKeys
!= NULL
)
1449 BasicInfo
= (PKEY_BASIC_INFORMATION
)(newDelKeys
+ 1);
1452 goto ReadFirstSubKey
;
1456 /* don't break, let's try to delete as many keys as possible */
1457 Status2
= STATUS_INSUFFICIENT_RESOURCES
;
1458 goto SubKeyFailureNoFree
;
1461 else if (Status2
== STATUS_BUFFER_OVERFLOW
)
1463 PREG_DEL_KEYS newDelKeys2
;
1465 ASSERT(newDelKeys
!= NULL
);
1467 /* we need more memory to query the key name */
1468 newDelKeys2
= RtlReAllocateHeap(ProcessHeap
,
1471 BufferSize
+ sizeof(REGP_DEL_KEYS
));
1472 if (newDelKeys2
!= NULL
)
1474 newDelKeys
= newDelKeys2
;
1475 BasicInfo
= (PKEY_BASIC_INFORMATION
)(newDelKeys
+ 1);
1478 goto ReadFirstSubKey
;
1482 /* don't break, let's try to delete as many keys as possible */
1483 Status2
= STATUS_INSUFFICIENT_RESOURCES
;
1486 else if (Status2
== STATUS_NO_MORE_ENTRIES
)
1488 /* in some race conditions where another thread would delete
1489 the same tree at the same time, newDelKeys could actually
1491 if (newDelKeys
!= NULL
)
1493 RtlFreeHeap(ProcessHeap
,
1501 /* newDelKeys can be NULL here when NtEnumerateKey returned an
1502 error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
1503 if (newDelKeys
!= NULL
)
1505 RtlFreeHeap(ProcessHeap
,
1510 SubKeyFailureNoFree
:
1511 /* don't break, let's try to delete as many keys as possible */
1512 if (NT_SUCCESS(Status
))
1518 Status2
= NtDeleteKey(delKeys
->KeyHandle
);
1520 /* NOTE: do NOT close the handle anymore, it's invalid already! */
1522 if (!NT_SUCCESS(Status2
))
1524 /* close the key handle so we don't leak handles for keys we were
1525 unable to delete. But only do this for handles not supplied
1528 if (delKeys
->KeyHandle
!= hKey
)
1530 NtClose(delKeys
->KeyHandle
);
1533 if (NT_SUCCESS(Status
))
1535 /* don't break, let's try to delete as many keys as possible */
1540 /* remove the entry from the list */
1541 RemoveEntryList(&delKeys
->ListEntry
);
1543 RtlFreeHeap(ProcessHeap
,
1546 } while (!IsListEmpty(&delQueueHead
));
1549 Status
= STATUS_INSUFFICIENT_RESOURCES
;
1555 /************************************************************************
1561 RegDeleteTreeW(IN HKEY hKey
,
1562 IN LPCWSTR lpSubKey OPTIONAL
)
1564 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1567 Status
= MapDefaultKey(&KeyHandle
,
1569 if (!NT_SUCCESS(Status
))
1571 return RtlNtStatusToDosError(Status
);
1574 if (lpSubKey
!= NULL
)
1576 OBJECT_ATTRIBUTES ObjectAttributes
;
1577 UNICODE_STRING SubKeyName
;
1579 RtlInitUnicodeString(&SubKeyName
,
1582 InitializeObjectAttributes(&ObjectAttributes
,
1584 OBJ_CASE_INSENSITIVE
,
1588 Status
= NtOpenKey(&SubKeyHandle
,
1589 DELETE
| KEY_ENUMERATE_SUB_KEYS
,
1591 if (!NT_SUCCESS(Status
))
1596 CurKey
= SubKeyHandle
;
1601 Status
= RegpDeleteTree(CurKey
);
1603 if (NT_SUCCESS(Status
))
1605 /* make sure we only close hKey (KeyHandle) when the caller specified a
1606 subkey, because the handle would be invalid already! */
1607 if (CurKey
!= KeyHandle
)
1609 ClosePredefKey(KeyHandle
);
1612 return ERROR_SUCCESS
;
1616 /* make sure we close all handles we created! */
1617 if (SubKeyHandle
!= NULL
)
1619 NtClose(SubKeyHandle
);
1623 ClosePredefKey(KeyHandle
);
1625 return RtlNtStatusToDosError(Status
);
1630 /************************************************************************
1636 RegDeleteTreeA(IN HKEY hKey
,
1637 IN LPCSTR lpSubKey OPTIONAL
)
1639 UNICODE_STRING SubKeyName
= {0};
1642 if (lpSubKey
!= NULL
&&
1643 !RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1646 return ERROR_NOT_ENOUGH_MEMORY
;
1649 Ret
= RegDeleteTreeW(hKey
,
1652 RtlFreeUnicodeString(&SubKeyName
);
1658 /************************************************************************
1659 * RegDisableReflectionKey
1664 RegDisableReflectionKey(IN HKEY hBase
)
1666 DPRINT1("RegDisableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase
);
1667 return ERROR_CALL_NOT_IMPLEMENTED
;
1671 /************************************************************************
1672 * RegEnableReflectionKey
1677 RegEnableReflectionKey(IN HKEY hBase
)
1679 DPRINT1("RegEnableReflectionKey(0x%p) UNIMPLEMENTED!\n", hBase
);
1680 return ERROR_CALL_NOT_IMPLEMENTED
;
1684 /************************************************************************
1690 RegSetKeyValueW(IN HKEY hKey
,
1691 IN LPCWSTR lpSubKey OPTIONAL
,
1692 IN LPCWSTR lpValueName OPTIONAL
,
1694 IN LPCVOID lpData OPTIONAL
,
1697 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1701 Status
= MapDefaultKey(&KeyHandle
,
1703 if (!NT_SUCCESS(Status
))
1705 return RtlNtStatusToDosError(Status
);
1708 if (lpSubKey
!= NULL
)
1710 OBJECT_ATTRIBUTES ObjectAttributes
;
1711 UNICODE_STRING SubKeyName
;
1713 RtlInitUnicodeString(&SubKeyName
,
1716 InitializeObjectAttributes(&ObjectAttributes
,
1718 OBJ_CASE_INSENSITIVE
,
1722 Status
= NtOpenKey(&SubKeyHandle
,
1725 if (!NT_SUCCESS(Status
))
1727 Ret
= RtlNtStatusToDosError(Status
);
1731 CurKey
= SubKeyHandle
;
1736 Ret
= RegSetValueExW(CurKey
,
1743 if (SubKeyHandle
!= NULL
)
1745 NtClose(SubKeyHandle
);
1749 ClosePredefKey(KeyHandle
);
1755 /************************************************************************
1761 RegSetKeyValueA(IN HKEY hKey
,
1762 IN LPCSTR lpSubKey OPTIONAL
,
1763 IN LPCSTR lpValueName OPTIONAL
,
1765 IN LPCVOID lpData OPTIONAL
,
1768 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1772 Status
= MapDefaultKey(&KeyHandle
,
1774 if (!NT_SUCCESS(Status
))
1776 return RtlNtStatusToDosError(Status
);
1779 if (lpSubKey
!= NULL
)
1781 OBJECT_ATTRIBUTES ObjectAttributes
;
1782 UNICODE_STRING SubKeyName
;
1784 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1787 Ret
= ERROR_NOT_ENOUGH_MEMORY
;
1791 InitializeObjectAttributes(&ObjectAttributes
,
1793 OBJ_CASE_INSENSITIVE
,
1797 Status
= NtOpenKey(&SubKeyHandle
,
1801 RtlFreeUnicodeString(&SubKeyName
);
1803 if (!NT_SUCCESS(Status
))
1805 Ret
= RtlNtStatusToDosError(Status
);
1809 CurKey
= SubKeyHandle
;
1814 Ret
= RegSetValueExA(CurKey
,
1821 if (SubKeyHandle
!= NULL
)
1823 NtClose(SubKeyHandle
);
1827 ClosePredefKey(KeyHandle
);
1833 /************************************************************************
1839 RegDeleteValueA (HKEY hKey
,
1842 UNICODE_STRING ValueName
;
1846 Status
= MapDefaultKey (&KeyHandle
,
1848 if (!NT_SUCCESS(Status
))
1850 return RtlNtStatusToDosError (Status
);
1853 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
1854 (LPSTR
)lpValueName
);
1855 Status
= NtDeleteValueKey (KeyHandle
,
1857 RtlFreeUnicodeString (&ValueName
);
1859 ClosePredefKey(KeyHandle
);
1861 if (!NT_SUCCESS(Status
))
1863 return RtlNtStatusToDosError (Status
);
1866 return ERROR_SUCCESS
;
1870 /************************************************************************
1876 RegDeleteValueW (HKEY hKey
,
1877 LPCWSTR lpValueName
)
1879 UNICODE_STRING ValueName
;
1883 Status
= MapDefaultKey (&KeyHandle
,
1885 if (!NT_SUCCESS(Status
))
1887 return RtlNtStatusToDosError (Status
);
1890 RtlInitUnicodeString (&ValueName
,
1891 (LPWSTR
)lpValueName
);
1893 Status
= NtDeleteValueKey (KeyHandle
,
1896 ClosePredefKey(KeyHandle
);
1898 if (!NT_SUCCESS(Status
))
1900 return RtlNtStatusToDosError (Status
);
1903 return ERROR_SUCCESS
;
1907 /************************************************************************
1913 RegEnumKeyA (HKEY hKey
,
1921 return RegEnumKeyExA (hKey
,
1932 /************************************************************************
1938 RegEnumKeyW (HKEY hKey
,
1946 return RegEnumKeyExW (hKey
,
1957 /************************************************************************
1963 RegEnumKeyExA (HKEY hKey
,
1970 PFILETIME lpftLastWriteTime
)
1974 KEY_NODE_INFORMATION Node
;
1975 KEY_BASIC_INFORMATION Basic
;
1978 UNICODE_STRING StringU
;
1979 ANSI_STRING StringA
;
1980 LONG ErrorCode
= ERROR_SUCCESS
;
1982 DWORD ClassLength
= 0;
1988 TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
1989 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
1991 if ((lpClass
) && (!lpcbClass
))
1993 return ERROR_INVALID_PARAMETER
;
1996 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1997 if (!NT_SUCCESS(Status
))
1999 return RtlNtStatusToDosError (Status
);
2004 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
2015 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2022 /* The class name should start at a dword boundary */
2023 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
2027 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
2030 KeyInfo
= RtlAllocateHeap (ProcessHeap
, 0, BufferSize
);
2031 if (KeyInfo
== NULL
)
2033 ErrorCode
= ERROR_OUTOFMEMORY
;
2037 Status
= NtEnumerateKey (KeyHandle
,
2039 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
2043 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
2044 if (!NT_SUCCESS(Status
))
2046 ErrorCode
= RtlNtStatusToDosError (Status
);
2050 if (lpClass
== NULL
)
2052 if (KeyInfo
->Basic
.NameLength
> NameLength
)
2054 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2058 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
2059 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
2060 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
2065 if (KeyInfo
->Node
.NameLength
> NameLength
||
2066 KeyInfo
->Node
.ClassLength
> ClassLength
)
2068 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2072 StringA
.Buffer
= lpClass
;
2074 StringA
.MaximumLength
= *lpcbClass
;
2075 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
2076 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
2077 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
2078 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
2079 lpClass
[StringA
.Length
] = 0;
2080 *lpcbClass
= StringA
.Length
;
2081 StringU
.Buffer
= KeyInfo
->Node
.Name
;
2082 StringU
.Length
= KeyInfo
->Node
.NameLength
;
2083 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
2087 if (ErrorCode
== ERROR_SUCCESS
)
2089 StringA
.Buffer
= lpName
;
2091 StringA
.MaximumLength
= *lpcbName
;
2092 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
2093 lpName
[StringA
.Length
] = 0;
2094 *lpcbName
= StringA
.Length
;
2095 if (lpftLastWriteTime
!= NULL
)
2097 if (lpClass
== NULL
)
2099 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
2100 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
2104 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
2105 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
2111 TRACE("Key Namea0 Length %d\n", StringU
.Length
);
2112 TRACE("Key Namea1 Length %d\n", NameLength
);
2113 TRACE("Key Namea Length %d\n", *lpcbName
);
2114 TRACE("Key Namea %s\n", lpName
);
2116 RtlFreeHeap (ProcessHeap
,
2121 ClosePredefKey(KeyHandle
);
2127 /************************************************************************
2133 RegEnumKeyExW (HKEY hKey
,
2140 PFILETIME lpftLastWriteTime
)
2144 KEY_NODE_INFORMATION Node
;
2145 KEY_BASIC_INFORMATION Basic
;
2151 ULONG ClassLength
= 0;
2153 LONG ErrorCode
= ERROR_SUCCESS
;
2156 Status
= MapDefaultKey(&KeyHandle
,
2158 if (!NT_SUCCESS(Status
))
2160 return RtlNtStatusToDosError (Status
);
2165 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
2176 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2183 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
2187 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
2190 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
2193 if (KeyInfo
== NULL
)
2195 ErrorCode
= ERROR_OUTOFMEMORY
;
2199 Status
= NtEnumerateKey (KeyHandle
,
2201 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
2205 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
2206 if (!NT_SUCCESS(Status
))
2208 ErrorCode
= RtlNtStatusToDosError (Status
);
2212 if (lpClass
== NULL
)
2214 if (KeyInfo
->Basic
.NameLength
> NameLength
)
2216 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2220 RtlCopyMemory (lpName
,
2221 KeyInfo
->Basic
.Name
,
2222 KeyInfo
->Basic
.NameLength
);
2223 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
2224 lpName
[*lpcbName
] = 0;
2229 if (KeyInfo
->Node
.NameLength
> NameLength
||
2230 KeyInfo
->Node
.ClassLength
> ClassLength
)
2232 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2236 RtlCopyMemory (lpName
,
2238 KeyInfo
->Node
.NameLength
);
2239 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
2240 lpName
[*lpcbName
] = 0;
2241 RtlCopyMemory (lpClass
,
2242 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
2243 KeyInfo
->Node
.ClassLength
);
2244 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
2245 lpClass
[*lpcbClass
] = 0;
2249 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
2251 if (lpClass
== NULL
)
2253 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
2254 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
2258 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
2259 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
2264 RtlFreeHeap (ProcessHeap
,
2269 ClosePredefKey(KeyHandle
);
2274 /************************************************************************
2280 RegEnumValueA( HKEY hKey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
2281 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
2286 char buffer
[256], *buf_ptr
= buffer
;
2287 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
2288 static const int info_size
= FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION
, Name
);
2290 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2291 // hkey, index, value, val_count, reserved, type, data, count );
2293 /* NT only checks count, not val_count */
2294 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
2295 status
= MapDefaultKey (&KeyHandle
, hKey
);
2296 if (!NT_SUCCESS(status
))
2298 return RtlNtStatusToDosError (status
);
2301 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
2302 if (data
) total_size
+= *count
;
2303 total_size
= min( sizeof(buffer
), total_size
);
2305 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
2306 buffer
, total_size
, &total_size
);
2307 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
2309 /* we need to fetch the contents for a string type even if not requested,
2310 * because we need to compute the length of the ASCII string. */
2311 if (value
|| data
|| is_string(info
->Type
))
2313 /* retry with a dynamically allocated buffer */
2314 while (status
== STATUS_BUFFER_OVERFLOW
)
2316 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
2317 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
2319 status
= STATUS_INSUFFICIENT_RESOURCES
;
2322 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
2323 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
2324 buf_ptr
, total_size
, &total_size
);
2327 if (status
) goto done
;
2329 if (is_string(info
->Type
))
2332 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
2333 total_size
- info
->DataOffset
);
2336 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
2339 RtlUnicodeToMultiByteN( (PCHAR
)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
2340 total_size
- info
->DataOffset
);
2341 /* if the type is REG_SZ and data is not 0-terminated
2342 * and there is enough space in the buffer NT appends a \0 */
2343 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
2346 info
->DataLength
= len
;
2350 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
2351 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
2354 if (value
&& !status
)
2358 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
2359 if (len
>= *val_count
)
2361 status
= STATUS_BUFFER_OVERFLOW
;
2364 len
= *val_count
- 1;
2365 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
2371 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
2377 else status
= STATUS_SUCCESS
;
2379 if (type
) *type
= info
->Type
;
2380 if (count
) *count
= info
->DataLength
;
2383 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
2384 ClosePredefKey(KeyHandle
);
2385 return RtlNtStatusToDosError(status
);
2388 /******************************************************************************
2389 * RegEnumValueW [ADVAPI32.@]
2393 * hkey [I] Handle to key to query
2394 * index [I] Index of value to query
2395 * value [O] Value string
2396 * val_count [I/O] Size of value buffer (in wchars)
2397 * reserved [I] Reserved
2398 * type [O] Type code
2399 * data [O] Value data
2400 * count [I/O] Size of data buffer (in bytes)
2403 * Success: ERROR_SUCCESS
2404 * Failure: nonzero error code from Winerror.h
2407 RegEnumValueW( HKEY hKey
, DWORD index
, LPWSTR value
, PDWORD val_count
,
2408 PDWORD reserved
, PDWORD type
, LPBYTE data
, PDWORD count
)
2413 char buffer
[256], *buf_ptr
= buffer
;
2414 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
2415 static const int info_size
= FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION
, Name
);
2417 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
2418 // hkey, index, value, val_count, reserved, type, data, count );
2420 /* NT only checks count, not val_count */
2421 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
2423 status
= MapDefaultKey (&KeyHandle
, hKey
);
2424 if (!NT_SUCCESS(status
))
2426 return RtlNtStatusToDosError (status
);
2429 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
2430 if (data
) total_size
+= *count
;
2431 total_size
= min( sizeof(buffer
), total_size
);
2433 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
2434 buffer
, total_size
, &total_size
);
2435 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
2439 /* retry with a dynamically allocated buffer */
2440 while (status
== STATUS_BUFFER_OVERFLOW
)
2442 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
2443 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
2445 status
= ERROR_NOT_ENOUGH_MEMORY
;
2448 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
2449 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
2450 buf_ptr
, total_size
, &total_size
);
2453 if (status
) goto done
;
2457 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
2459 status
= STATUS_BUFFER_OVERFLOW
;
2462 memcpy( value
, info
->Name
, info
->NameLength
);
2463 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
2464 value
[*val_count
] = 0;
2469 if (total_size
- info
->DataOffset
> *count
)
2471 status
= STATUS_BUFFER_OVERFLOW
;
2474 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
2475 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
2477 /* if the type is REG_SZ and data is not 0-terminated
2478 * and there is enough space in the buffer NT appends a \0 */
2479 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
2480 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
2484 else status
= STATUS_SUCCESS
;
2487 if (type
) *type
= info
->Type
;
2488 if (count
) *count
= info
->DataLength
;
2491 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
2492 ClosePredefKey(KeyHandle
);
2493 return RtlNtStatusToDosError(status
);
2496 /************************************************************************
2502 RegFlushKey(HKEY hKey
)
2507 if (hKey
== HKEY_PERFORMANCE_DATA
)
2509 return ERROR_SUCCESS
;
2512 Status
= MapDefaultKey (&KeyHandle
,
2514 if (!NT_SUCCESS(Status
))
2516 return RtlNtStatusToDosError (Status
);
2519 Status
= NtFlushKey (KeyHandle
);
2521 ClosePredefKey(KeyHandle
);
2523 if (!NT_SUCCESS(Status
))
2525 return RtlNtStatusToDosError (Status
);
2528 return ERROR_SUCCESS
;
2532 /************************************************************************
2538 RegGetKeySecurity(HKEY hKey
,
2539 SECURITY_INFORMATION SecurityInformation
,
2540 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
2541 LPDWORD lpcbSecurityDescriptor
)
2546 if (hKey
== HKEY_PERFORMANCE_DATA
)
2548 return ERROR_INVALID_HANDLE
;
2551 Status
= MapDefaultKey(&KeyHandle
,
2553 if (!NT_SUCCESS(Status
))
2555 TRACE("MapDefaultKey() failed (Status %lx)\n", Status
);
2556 return RtlNtStatusToDosError (Status
);
2559 Status
= NtQuerySecurityObject(KeyHandle
,
2560 SecurityInformation
,
2561 pSecurityDescriptor
,
2562 *lpcbSecurityDescriptor
,
2563 lpcbSecurityDescriptor
);
2566 ClosePredefKey(KeyHandle
);
2568 if (!NT_SUCCESS(Status
))
2570 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
2571 return RtlNtStatusToDosError (Status
);
2574 return ERROR_SUCCESS
;
2578 /************************************************************************
2584 RegLoadKeyA (HKEY hKey
,
2588 UNICODE_STRING FileName
;
2589 UNICODE_STRING KeyName
;
2592 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
2594 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2597 ErrorCode
= RegLoadKeyW (hKey
,
2601 RtlFreeUnicodeString (&FileName
);
2602 RtlFreeUnicodeString (&KeyName
);
2608 /************************************************************************
2614 RegLoadKeyW (HKEY hKey
,
2618 OBJECT_ATTRIBUTES FileObjectAttributes
;
2619 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2620 UNICODE_STRING FileName
;
2621 UNICODE_STRING KeyName
;
2624 LONG ErrorCode
= ERROR_SUCCESS
;
2626 if (hKey
== HKEY_PERFORMANCE_DATA
)
2628 return ERROR_INVALID_HANDLE
;
2631 Status
= MapDefaultKey (&KeyHandle
,
2633 if (!NT_SUCCESS(Status
))
2635 return RtlNtStatusToDosError (Status
);
2638 if (!RtlDosPathNameToNtPathName_U (lpFile
,
2643 ErrorCode
= ERROR_BAD_PATHNAME
;
2647 InitializeObjectAttributes (&FileObjectAttributes
,
2649 OBJ_CASE_INSENSITIVE
,
2653 RtlInitUnicodeString (&KeyName
,
2656 InitializeObjectAttributes (&KeyObjectAttributes
,
2658 OBJ_CASE_INSENSITIVE
,
2662 Status
= NtLoadKey (&KeyObjectAttributes
,
2663 &FileObjectAttributes
);
2665 RtlFreeHeap (RtlGetProcessHeap (),
2669 if (!NT_SUCCESS(Status
))
2671 ErrorCode
= RtlNtStatusToDosError (Status
);
2676 ClosePredefKey(KeyHandle
);
2682 /************************************************************************
2683 * RegNotifyChangeKeyValue
2688 RegNotifyChangeKeyValue (HKEY hKey
,
2690 DWORD dwNotifyFilter
,
2694 IO_STATUS_BLOCK IoStatusBlock
;
2697 LONG ErrorCode
= ERROR_SUCCESS
;
2699 if (hKey
== HKEY_PERFORMANCE_DATA
)
2701 return ERROR_INVALID_HANDLE
;
2704 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
2706 return ERROR_INVALID_PARAMETER
;
2709 Status
= MapDefaultKey (&KeyHandle
,
2711 if (!NT_SUCCESS(Status
))
2713 return RtlNtStatusToDosError (Status
);
2716 /* FIXME: Remote key handles must fail */
2718 Status
= NtNotifyChangeKey (KeyHandle
,
2728 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
2730 ErrorCode
= RtlNtStatusToDosError (Status
);
2733 ClosePredefKey(KeyHandle
);
2739 /************************************************************************
2740 * RegOpenCurrentUser
2745 RegOpenCurrentUser (IN REGSAM samDesired
,
2746 OUT PHKEY phkResult
)
2750 Status
= RtlOpenCurrentUser((ACCESS_MASK
)samDesired
,
2751 (PHANDLE
)phkResult
);
2752 if (!NT_SUCCESS(Status
))
2754 /* NOTE - don't set the last error code! just return the error! */
2755 return RtlNtStatusToDosError(Status
);
2758 return ERROR_SUCCESS
;
2762 /************************************************************************
2765 * 20050503 Fireball - imported from WINE
2770 RegOpenKeyA (HKEY hKey
,
2774 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2776 if (!hKey
&& lpSubKey
&& phkResult
)
2778 return ERROR_INVALID_HANDLE
;
2781 if (!lpSubKey
|| !*lpSubKey
)
2784 return ERROR_SUCCESS
;
2787 return RegOpenKeyExA( hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2791 /************************************************************************
2796 * 20050503 Fireball - imported from WINE
2801 RegOpenKeyW (HKEY hKey
,
2805 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2807 if (!hKey
&& lpSubKey
&& phkResult
)
2809 return ERROR_INVALID_HANDLE
;
2812 if (!lpSubKey
|| !*lpSubKey
)
2815 return ERROR_SUCCESS
;
2817 return RegOpenKeyExW(hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2821 /************************************************************************
2827 RegOpenKeyExA (HKEY hKey
,
2833 OBJECT_ATTRIBUTES ObjectAttributes
;
2834 UNICODE_STRING SubKeyString
;
2837 LONG ErrorCode
= ERROR_SUCCESS
;
2839 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2840 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2842 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2843 if (!NT_SUCCESS(Status
))
2845 return RtlNtStatusToDosError (Status
);
2848 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
, (LPSTR
)lpSubKey
);
2849 InitializeObjectAttributes (&ObjectAttributes
,
2851 OBJ_CASE_INSENSITIVE
,
2855 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2856 RtlFreeUnicodeString (&SubKeyString
);
2857 if (!NT_SUCCESS(Status
))
2859 ErrorCode
= RtlNtStatusToDosError (Status
);
2862 ClosePredefKey(KeyHandle
);
2868 /************************************************************************
2874 RegOpenKeyExW (HKEY hKey
,
2880 OBJECT_ATTRIBUTES ObjectAttributes
;
2881 UNICODE_STRING SubKeyString
;
2884 LONG ErrorCode
= ERROR_SUCCESS
;
2886 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2887 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2889 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2890 if (!NT_SUCCESS(Status
))
2892 return RtlNtStatusToDosError (Status
);
2895 if (lpSubKey
!= NULL
)
2896 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)lpSubKey
);
2898 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)L
"");
2900 InitializeObjectAttributes (&ObjectAttributes
,
2902 OBJ_CASE_INSENSITIVE
,
2906 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2908 if (!NT_SUCCESS(Status
))
2910 ErrorCode
= RtlNtStatusToDosError (Status
);
2913 ClosePredefKey(KeyHandle
);
2919 /************************************************************************
2920 * RegOpenUserClassesRoot
2925 RegOpenUserClassesRoot (IN HANDLE hToken
,
2927 IN REGSAM samDesired
,
2928 OUT PHKEY phkResult
)
2930 const WCHAR UserClassesKeyPrefix
[] = L
"\\Registry\\User\\";
2931 const WCHAR UserClassesKeySuffix
[] = L
"_Classes";
2932 PTOKEN_USER TokenUserData
;
2933 ULONG RequiredLength
;
2934 UNICODE_STRING UserSidString
, UserClassesKeyRoot
;
2935 OBJECT_ATTRIBUTES ObjectAttributes
;
2938 /* check parameters */
2939 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
2941 return ERROR_INVALID_PARAMETER
;
2945 * Get the user sid from the token
2949 /* determine how much memory we need */
2950 Status
= NtQueryInformationToken(hToken
,
2955 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2957 /* NOTE - as opposed to all other registry functions windows does indeed
2958 change the last error code in case the caller supplied a invalid
2959 handle for example! */
2960 return RtlNtStatusToDosError (Status
);
2963 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2966 if (TokenUserData
== NULL
)
2968 return ERROR_NOT_ENOUGH_MEMORY
;
2971 /* attempt to read the information */
2972 Status
= NtQueryInformationToken(hToken
,
2977 if (!NT_SUCCESS(Status
))
2979 RtlFreeHeap(ProcessHeap
,
2982 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2984 /* the information appears to have changed?! try again */
2988 /* NOTE - as opposed to all other registry functions windows does indeed
2989 change the last error code in case the caller supplied a invalid
2990 handle for example! */
2991 return RtlNtStatusToDosError (Status
);
2995 * Build the absolute path for the user's registry in the form
2996 * "\Registry\User\<SID>_Classes"
2998 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2999 TokenUserData
->User
.Sid
,
3002 /* we don't need the user data anymore, free it */
3003 RtlFreeHeap(ProcessHeap
,
3007 if (!NT_SUCCESS(Status
))
3009 return RtlNtStatusToDosError (Status
);
3012 /* allocate enough memory for the entire key string */
3013 UserClassesKeyRoot
.Length
= 0;
3014 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
3015 sizeof(UserClassesKeyPrefix
) +
3016 sizeof(UserClassesKeySuffix
);
3017 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
3019 UserClassesKeyRoot
.MaximumLength
);
3020 if (UserClassesKeyRoot
.Buffer
== NULL
)
3022 RtlFreeUnicodeString(&UserSidString
);
3023 return RtlNtStatusToDosError (Status
);
3026 /* build the string */
3027 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
3028 UserClassesKeyPrefix
);
3029 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
3031 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
3032 UserClassesKeySuffix
);
3034 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
3040 InitializeObjectAttributes (&ObjectAttributes
,
3041 &UserClassesKeyRoot
,
3042 OBJ_CASE_INSENSITIVE
,
3046 Status
= NtOpenKey((PHANDLE
)phkResult
,
3050 RtlFreeUnicodeString(&UserSidString
);
3051 RtlFreeUnicodeString(&UserClassesKeyRoot
);
3053 if (!NT_SUCCESS(Status
))
3055 return RtlNtStatusToDosError (Status
);
3058 return ERROR_SUCCESS
;
3062 /************************************************************************
3068 RegQueryInfoKeyA (HKEY hKey
,
3073 LPDWORD lpcbMaxSubKeyLen
,
3074 LPDWORD lpcbMaxClassLen
,
3076 LPDWORD lpcbMaxValueNameLen
,
3077 LPDWORD lpcbMaxValueLen
,
3078 LPDWORD lpcbSecurityDescriptor
,
3079 PFILETIME lpftLastWriteTime
)
3081 WCHAR ClassName
[MAX_PATH
];
3082 UNICODE_STRING UnicodeString
;
3083 ANSI_STRING AnsiString
;
3086 RtlInitUnicodeString (&UnicodeString
,
3088 if (lpClass
!= NULL
)
3090 UnicodeString
.Buffer
= &ClassName
[0];
3091 UnicodeString
.MaximumLength
= sizeof(ClassName
);
3092 AnsiString
.MaximumLength
= *lpcbClass
;
3095 ErrorCode
= RegQueryInfoKeyW (hKey
,
3096 UnicodeString
.Buffer
,
3103 lpcbMaxValueNameLen
,
3105 lpcbSecurityDescriptor
,
3107 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
3109 AnsiString
.Buffer
= lpClass
;
3110 AnsiString
.Length
= 0;
3111 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
3112 RtlUnicodeStringToAnsiString (&AnsiString
,
3115 *lpcbClass
= AnsiString
.Length
;
3116 lpClass
[AnsiString
.Length
] = 0;
3123 /************************************************************************
3129 RegQueryInfoKeyW (HKEY hKey
,
3134 LPDWORD lpcbMaxSubKeyLen
,
3135 LPDWORD lpcbMaxClassLen
,
3137 LPDWORD lpcbMaxValueNameLen
,
3138 LPDWORD lpcbMaxValueLen
,
3139 LPDWORD lpcbSecurityDescriptor
,
3140 PFILETIME lpftLastWriteTime
)
3142 KEY_FULL_INFORMATION FullInfoBuffer
;
3143 PKEY_FULL_INFORMATION FullInfo
;
3145 ULONG ClassLength
= 0;
3149 LONG ErrorCode
= ERROR_SUCCESS
;
3151 if ((lpClass
) && (!lpcbClass
))
3153 return ERROR_INVALID_PARAMETER
;
3156 Status
= MapDefaultKey (&KeyHandle
,
3158 if (!NT_SUCCESS(Status
))
3160 return RtlNtStatusToDosError (Status
);
3163 if (lpClass
!= NULL
)
3167 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
3174 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
3175 FullInfo
= RtlAllocateHeap (ProcessHeap
,
3178 if (FullInfo
== NULL
)
3180 ErrorCode
= ERROR_OUTOFMEMORY
;
3184 FullInfo
->ClassLength
= ClassLength
;
3188 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
3189 FullInfo
= &FullInfoBuffer
;
3190 FullInfo
->ClassLength
= 0;
3192 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
3194 Status
= NtQueryKey (KeyHandle
,
3199 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
3200 if (!NT_SUCCESS(Status
))
3202 if (lpClass
!= NULL
)
3204 RtlFreeHeap (ProcessHeap
,
3209 ErrorCode
= RtlNtStatusToDosError (Status
);
3213 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
3214 if (lpcSubKeys
!= NULL
)
3216 *lpcSubKeys
= FullInfo
->SubKeys
;
3219 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
3220 if (lpcbMaxSubKeyLen
!= NULL
)
3222 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
3225 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
3226 if (lpcbMaxClassLen
!= NULL
)
3228 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
3231 TRACE("Values %lu\n", FullInfo
->Values
);
3232 if (lpcValues
!= NULL
)
3234 *lpcValues
= FullInfo
->Values
;
3237 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
3238 if (lpcbMaxValueNameLen
!= NULL
)
3240 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
3243 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
3244 if (lpcbMaxValueLen
!= NULL
)
3246 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
3249 if (lpcbSecurityDescriptor
!= NULL
)
3251 Status
= NtQuerySecurityObject(KeyHandle
,
3252 OWNER_SECURITY_INFORMATION
|
3253 GROUP_SECURITY_INFORMATION
|
3254 DACL_SECURITY_INFORMATION
,
3257 lpcbSecurityDescriptor
);
3258 if (!NT_SUCCESS(Status
))
3260 if (lpClass
!= NULL
)
3262 RtlFreeHeap(ProcessHeap
,
3267 ErrorCode
= RtlNtStatusToDosError (Status
);
3273 if (lpftLastWriteTime
!= NULL
)
3275 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
3276 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
3279 if (lpClass
!= NULL
)
3281 if (FullInfo
->ClassLength
> ClassLength
)
3283 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
3287 RtlCopyMemory (lpClass
,
3289 FullInfo
->ClassLength
);
3290 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
3291 lpClass
[*lpcbClass
] = 0;
3294 RtlFreeHeap (ProcessHeap
,
3300 ClosePredefKey(KeyHandle
);
3306 /************************************************************************
3307 * RegQueryMultipleValuesA
3312 RegQueryMultipleValuesA (HKEY hKey
,
3319 DWORD maxBytes
= *ldwTotsize
;
3320 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
3323 if (maxBytes
>= (1024*1024))
3324 return ERROR_TRANSFER_TOO_LONG
;
3328 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
3329 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
3331 for (i
= 0; i
< num_vals
; i
++)
3333 val_list
[i
].ve_valuelen
= 0;
3334 ErrorCode
= RegQueryValueExA (hKey
,
3335 val_list
[i
].ve_valuename
,
3339 &val_list
[i
].ve_valuelen
);
3340 if (ErrorCode
!= ERROR_SUCCESS
)
3345 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
3347 ErrorCode
= RegQueryValueExA (hKey
,
3348 val_list
[i
].ve_valuename
,
3350 &val_list
[i
].ve_type
,
3352 &val_list
[i
].ve_valuelen
);
3353 if (ErrorCode
!= ERROR_SUCCESS
)
3358 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
3360 bufptr
+= val_list
[i
].ve_valuelen
;
3363 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
3366 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
3370 /************************************************************************
3371 * RegQueryMultipleValuesW
3376 RegQueryMultipleValuesW (HKEY hKey
,
3383 DWORD maxBytes
= *ldwTotsize
;
3384 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
3387 if (maxBytes
>= (1024*1024))
3388 return ERROR_TRANSFER_TOO_LONG
;
3392 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
3393 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
3395 for (i
= 0; i
< num_vals
; i
++)
3397 val_list
[i
].ve_valuelen
= 0;
3398 ErrorCode
= RegQueryValueExW (hKey
,
3399 val_list
[i
].ve_valuename
,
3403 &val_list
[i
].ve_valuelen
);
3404 if (ErrorCode
!= ERROR_SUCCESS
)
3409 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
3411 ErrorCode
= RegQueryValueExW (hKey
,
3412 val_list
[i
].ve_valuename
,
3414 &val_list
[i
].ve_type
,
3416 &val_list
[i
].ve_valuelen
);
3417 if (ErrorCode
!= ERROR_SUCCESS
)
3422 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
3424 bufptr
+= val_list
[i
].ve_valuelen
;
3427 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
3430 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
3434 /************************************************************************
3435 * RegQueryReflectionKey
3440 RegQueryReflectionKey(IN HKEY hBase
,
3441 OUT BOOL
* bIsReflectionDisabled
)
3443 DPRINT1("RegQueryReflectionKey(0x%p, 0x%p) UNIMPLEMENTED!\n",
3444 hBase
, bIsReflectionDisabled
);
3445 return ERROR_CALL_NOT_IMPLEMENTED
;
3449 /************************************************************************
3455 RegQueryValueExW (HKEY hKey
,
3456 LPCWSTR lpValueName
,
3462 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
3463 UNICODE_STRING ValueName
;
3468 LONG ErrorCode
= ERROR_SUCCESS
;
3469 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
3471 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
3472 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
3474 Status
= MapDefaultKey (&KeyHandle
,
3476 if (!NT_SUCCESS(Status
))
3478 return RtlNtStatusToDosError (Status
);
3481 if (lpData
!= NULL
&& lpcbData
== NULL
)
3483 ErrorCode
= ERROR_INVALID_PARAMETER
;
3487 RtlInitUnicodeString (&ValueName
,
3489 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
3490 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
3493 if (ValueInfo
== NULL
)
3495 ErrorCode
= ERROR_OUTOFMEMORY
;
3499 Status
= NtQueryValueKey (KeyHandle
,
3501 KeyValuePartialInformation
,
3505 TRACE("Status 0x%X\n", Status
);
3506 if (Status
== STATUS_BUFFER_OVERFLOW
)
3508 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
3510 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
3512 else if (!NT_SUCCESS(Status
))
3514 ErrorCode
= RtlNtStatusToDosError (Status
);
3516 if (lpcbData
!= NULL
)
3518 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
3524 *lpType
= ValueInfo
->Type
;
3527 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
3529 RtlMoveMemory (lpData
,
3531 min(ValueInfo
->DataLength
, MaxCopy
));
3534 if ((ValueInfo
->Type
== REG_SZ
) ||
3535 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
3536 (ValueInfo
->Type
== REG_EXPAND_SZ
))
3538 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
3540 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
3543 if (lpcbData
!= NULL
)
3545 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
3546 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
3551 if (lpcbData
!= NULL
)
3553 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
3554 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
3558 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
3560 RtlFreeHeap (ProcessHeap
,
3565 ClosePredefKey(KeyHandle
);
3571 /************************************************************************
3577 RegQueryValueExA (HKEY hKey
,
3584 UNICODE_STRING ValueName
;
3585 UNICODE_STRING ValueData
;
3586 ANSI_STRING AnsiString
;
3591 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
3592 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
3594 if (lpData
!= NULL
&& lpcbData
== NULL
)
3596 return ERROR_INVALID_PARAMETER
;
3601 ValueData
.Length
= 0;
3602 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
3603 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3605 ValueData
.MaximumLength
);
3606 if (!ValueData
.Buffer
)
3608 return ERROR_OUTOFMEMORY
;
3613 ValueData
.Buffer
= NULL
;
3614 ValueData
.Length
= 0;
3615 ValueData
.MaximumLength
= 0;
3618 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3619 (LPSTR
)lpValueName
);
3621 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
3622 ErrorCode
= RegQueryValueExW (hKey
,
3626 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
3628 TRACE("ErrorCode %lu\n", ErrorCode
);
3629 RtlFreeUnicodeString(&ValueName
);
3631 if (ErrorCode
== ERROR_SUCCESS
||
3632 ErrorCode
== ERROR_MORE_DATA
)
3639 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
3641 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3643 RtlInitAnsiString(&AnsiString
, NULL
);
3644 AnsiString
.Buffer
= (LPSTR
)lpData
;
3645 AnsiString
.MaximumLength
= *lpcbData
;
3646 ValueData
.Length
= Length
;
3647 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
3648 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
3650 Length
= Length
/ sizeof(WCHAR
);
3652 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3654 if (*lpcbData
< Length
)
3656 ErrorCode
= ERROR_MORE_DATA
;
3660 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
3664 if (lpcbData
!= NULL
)
3670 if (ValueData
.Buffer
!= NULL
)
3672 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
3679 /************************************************************************
3685 RegQueryValueA (HKEY hKey
,
3690 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3691 UNICODE_STRING SubKeyName
;
3692 UNICODE_STRING Value
;
3693 ANSI_STRING AnsiString
;
3697 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
3698 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3700 if (lpValue
!= NULL
&&
3703 return ERROR_INVALID_PARAMETER
;
3706 RtlInitUnicodeString (&SubKeyName
,
3708 RtlInitUnicodeString (&Value
,
3710 if (lpSubKey
!= NULL
&&
3711 strlen(lpSubKey
) != 0)
3713 RtlInitAnsiString (&AnsiString
,
3715 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3716 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3717 RtlAnsiStringToUnicodeString (&SubKeyName
,
3722 if (lpValue
!= NULL
)
3724 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
3725 Value
.MaximumLength
= ValueSize
;
3726 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3729 if (Value
.Buffer
== NULL
)
3731 return ERROR_OUTOFMEMORY
;
3739 ErrorCode
= RegQueryValueW (hKey
,
3740 (LPCWSTR
)SubKeyName
.Buffer
,
3743 if (ErrorCode
== ERROR_SUCCESS
)
3745 Value
.Length
= ValueSize
;
3746 RtlInitAnsiString (&AnsiString
,
3748 AnsiString
.Buffer
= lpValue
;
3749 AnsiString
.MaximumLength
= *lpcbValue
;
3750 RtlUnicodeStringToAnsiString (&AnsiString
,
3755 *lpcbValue
= ValueSize
;
3756 if (Value
.Buffer
!= NULL
)
3758 RtlFreeHeap (ProcessHeap
,
3767 /************************************************************************
3773 RegQueryValueW (HKEY hKey
,
3778 OBJECT_ATTRIBUTES ObjectAttributes
;
3779 UNICODE_STRING SubKeyString
;
3786 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
3787 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3789 Status
= MapDefaultKey (&KeyHandle
,
3791 if (!NT_SUCCESS(Status
))
3793 return RtlNtStatusToDosError (Status
);
3796 if (lpSubKey
!= NULL
&&
3797 wcslen(lpSubKey
) != 0)
3799 RtlInitUnicodeString (&SubKeyString
,
3801 InitializeObjectAttributes (&ObjectAttributes
,
3803 OBJ_CASE_INSENSITIVE
,
3806 Status
= NtOpenKey (&RealKey
,
3809 if (!NT_SUCCESS(Status
))
3811 ErrorCode
= RtlNtStatusToDosError (Status
);
3814 CloseRealKey
= TRUE
;
3819 CloseRealKey
= FALSE
;
3822 ErrorCode
= RegQueryValueExW (RealKey
,
3827 (LPDWORD
)lpcbValue
);
3834 ClosePredefKey(KeyHandle
);
3840 /************************************************************************
3846 RegReplaceKeyA (HKEY hKey
,
3851 UNICODE_STRING SubKey
;
3852 UNICODE_STRING NewFile
;
3853 UNICODE_STRING OldFile
;
3856 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
3858 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
3860 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
3863 ErrorCode
= RegReplaceKeyW (hKey
,
3868 RtlFreeUnicodeString (&OldFile
);
3869 RtlFreeUnicodeString (&NewFile
);
3870 RtlFreeUnicodeString (&SubKey
);
3876 /************************************************************************
3882 RegReplaceKeyW (HKEY hKey
,
3887 OBJECT_ATTRIBUTES KeyObjectAttributes
;
3888 OBJECT_ATTRIBUTES NewObjectAttributes
;
3889 OBJECT_ATTRIBUTES OldObjectAttributes
;
3890 UNICODE_STRING SubKeyName
;
3891 UNICODE_STRING NewFileName
;
3892 UNICODE_STRING OldFileName
;
3893 BOOLEAN CloseRealKey
;
3894 HANDLE RealKeyHandle
;
3897 LONG ErrorCode
= ERROR_SUCCESS
;
3899 if (hKey
== HKEY_PERFORMANCE_DATA
)
3901 return ERROR_INVALID_HANDLE
;
3904 Status
= MapDefaultKey (&KeyHandle
,
3906 if (!NT_SUCCESS(Status
))
3908 return RtlNtStatusToDosError (Status
);
3911 /* Open the real key */
3912 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
3914 RtlInitUnicodeString (&SubKeyName
,
3916 InitializeObjectAttributes (&KeyObjectAttributes
,
3918 OBJ_CASE_INSENSITIVE
,
3921 Status
= NtOpenKey (&RealKeyHandle
,
3923 &KeyObjectAttributes
);
3924 if (!NT_SUCCESS(Status
))
3926 ErrorCode
= RtlNtStatusToDosError (Status
);
3929 CloseRealKey
= TRUE
;
3933 RealKeyHandle
= KeyHandle
;
3934 CloseRealKey
= FALSE
;
3937 /* Convert new file name */
3938 if (!RtlDosPathNameToNtPathName_U (lpNewFile
,
3945 NtClose (RealKeyHandle
);
3947 ErrorCode
= ERROR_INVALID_PARAMETER
;
3951 InitializeObjectAttributes (&NewObjectAttributes
,
3953 OBJ_CASE_INSENSITIVE
,
3957 /* Convert old file name */
3958 if (!RtlDosPathNameToNtPathName_U (lpOldFile
,
3963 RtlFreeHeap (RtlGetProcessHeap (),
3965 NewFileName
.Buffer
);
3968 NtClose (RealKeyHandle
);
3970 ErrorCode
= ERROR_INVALID_PARAMETER
;
3974 InitializeObjectAttributes (&OldObjectAttributes
,
3976 OBJ_CASE_INSENSITIVE
,
3980 Status
= NtReplaceKey (&NewObjectAttributes
,
3982 &OldObjectAttributes
);
3984 RtlFreeHeap (RtlGetProcessHeap (),
3986 OldFileName
.Buffer
);
3987 RtlFreeHeap (RtlGetProcessHeap (),
3989 NewFileName
.Buffer
);
3993 NtClose (RealKeyHandle
);
3996 if (!NT_SUCCESS(Status
))
3998 return RtlNtStatusToDosError (Status
);
4002 ClosePredefKey(KeyHandle
);
4008 /************************************************************************
4014 RegRestoreKeyA (HKEY hKey
,
4018 UNICODE_STRING FileName
;
4021 RtlCreateUnicodeStringFromAsciiz (&FileName
,
4024 ErrorCode
= RegRestoreKeyW (hKey
,
4028 RtlFreeUnicodeString (&FileName
);
4034 /************************************************************************
4040 RegRestoreKeyW (HKEY hKey
,
4044 OBJECT_ATTRIBUTES ObjectAttributes
;
4045 IO_STATUS_BLOCK IoStatusBlock
;
4046 UNICODE_STRING FileName
;
4051 if (hKey
== HKEY_PERFORMANCE_DATA
)
4053 return ERROR_INVALID_HANDLE
;
4056 Status
= MapDefaultKey (&KeyHandle
,
4058 if (!NT_SUCCESS(Status
))
4060 return RtlNtStatusToDosError (Status
);
4063 if (!RtlDosPathNameToNtPathName_U (lpFile
,
4068 Status
= STATUS_INVALID_PARAMETER
;
4072 InitializeObjectAttributes (&ObjectAttributes
,
4074 OBJ_CASE_INSENSITIVE
,
4078 Status
= NtOpenFile (&FileHandle
,
4083 FILE_SYNCHRONOUS_IO_NONALERT
);
4084 RtlFreeHeap (RtlGetProcessHeap(),
4087 if (!NT_SUCCESS(Status
))
4092 Status
= NtRestoreKey (KeyHandle
,
4095 NtClose (FileHandle
);
4098 ClosePredefKey(KeyHandle
);
4100 if (!NT_SUCCESS(Status
))
4102 return RtlNtStatusToDosError (Status
);
4105 return ERROR_SUCCESS
;
4109 /************************************************************************
4115 RegSaveKeyA (HKEY hKey
,
4117 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
4119 UNICODE_STRING FileName
;
4122 RtlCreateUnicodeStringFromAsciiz (&FileName
,
4124 ErrorCode
= RegSaveKeyW (hKey
,
4126 lpSecurityAttributes
);
4127 RtlFreeUnicodeString (&FileName
);
4133 /************************************************************************
4139 RegSaveKeyW (HKEY hKey
,
4141 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
4143 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
4144 OBJECT_ATTRIBUTES ObjectAttributes
;
4145 UNICODE_STRING FileName
;
4146 IO_STATUS_BLOCK IoStatusBlock
;
4151 Status
= MapDefaultKey (&KeyHandle
,
4153 if (!NT_SUCCESS(Status
))
4155 return RtlNtStatusToDosError (Status
);
4158 if (!RtlDosPathNameToNtPathName_U (lpFile
,
4163 Status
= STATUS_INVALID_PARAMETER
;
4167 if (lpSecurityAttributes
!= NULL
)
4169 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
4172 InitializeObjectAttributes (&ObjectAttributes
,
4174 OBJ_CASE_INSENSITIVE
,
4176 SecurityDescriptor
);
4177 Status
= NtCreateFile (&FileHandle
,
4178 GENERIC_WRITE
| SYNCHRONIZE
,
4182 FILE_ATTRIBUTE_NORMAL
,
4185 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
4188 RtlFreeHeap (RtlGetProcessHeap (),
4191 if (!NT_SUCCESS(Status
))
4196 Status
= NtSaveKey (KeyHandle
,
4198 NtClose (FileHandle
);
4201 ClosePredefKey(KeyHandle
);
4203 if (!NT_SUCCESS(Status
))
4205 return RtlNtStatusToDosError (Status
);
4208 return ERROR_SUCCESS
;
4212 /************************************************************************
4218 RegSetKeySecurity (HKEY hKey
,
4219 SECURITY_INFORMATION SecurityInformation
,
4220 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
4225 if (hKey
== HKEY_PERFORMANCE_DATA
)
4227 return ERROR_INVALID_HANDLE
;
4230 Status
= MapDefaultKey (&KeyHandle
,
4232 if (!NT_SUCCESS(Status
))
4234 return RtlNtStatusToDosError (Status
);
4237 Status
= NtSetSecurityObject (KeyHandle
,
4238 SecurityInformation
,
4239 pSecurityDescriptor
);
4241 ClosePredefKey(KeyHandle
);
4243 if (!NT_SUCCESS(Status
))
4245 return RtlNtStatusToDosError (Status
);
4248 return ERROR_SUCCESS
;
4252 /************************************************************************
4258 RegSetValueExA (HKEY hKey
,
4265 UNICODE_STRING ValueName
;
4267 ANSI_STRING AnsiString
;
4268 UNICODE_STRING Data
;
4273 if (lpValueName
!= NULL
&&
4274 strlen(lpValueName
) != 0)
4276 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
4278 pValueName
= (LPWSTR
)ValueName
.Buffer
;
4285 if (((dwType
== REG_SZ
) ||
4286 (dwType
== REG_MULTI_SZ
) ||
4287 (dwType
== REG_EXPAND_SZ
)) &&
4290 /* NT adds one if the caller forgot the NULL-termination character */
4291 if (lpData
[cbData
- 1] != '\0')
4296 RtlInitAnsiString (&AnsiString
,
4298 AnsiString
.Buffer
= (PSTR
)lpData
;
4299 AnsiString
.Length
= cbData
- 1;
4300 AnsiString
.MaximumLength
= cbData
;
4301 RtlAnsiStringToUnicodeString (&Data
,
4304 pData
= (LPBYTE
)Data
.Buffer
;
4305 DataSize
= cbData
* sizeof(WCHAR
);
4309 RtlInitUnicodeString (&Data
,
4311 pData
= (LPBYTE
)lpData
;
4315 ErrorCode
= RegSetValueExW (hKey
,
4321 if (pValueName
!= NULL
)
4323 RtlFreeHeap (ProcessHeap
,
4328 if (Data
.Buffer
!= NULL
)
4330 RtlFreeHeap (ProcessHeap
,
4339 /************************************************************************
4345 RegSetValueExW (HKEY hKey
,
4346 LPCWSTR lpValueName
,
4352 UNICODE_STRING ValueName
;
4353 PUNICODE_STRING pValueName
;
4357 Status
= MapDefaultKey (&KeyHandle
,
4359 if (!NT_SUCCESS(Status
))
4361 return RtlNtStatusToDosError (Status
);
4364 if (lpValueName
!= NULL
)
4366 RtlInitUnicodeString (&ValueName
,
4371 RtlInitUnicodeString (&ValueName
, L
"");
4373 pValueName
= &ValueName
;
4375 if (((dwType
== REG_SZ
) ||
4376 (dwType
== REG_MULTI_SZ
) ||
4377 (dwType
== REG_EXPAND_SZ
)) &&
4378 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
4380 /* NT adds one if the caller forgot the NULL-termination character */
4381 cbData
+= sizeof(WCHAR
);
4384 Status
= NtSetValueKey (KeyHandle
,
4391 ClosePredefKey(KeyHandle
);
4393 if (!NT_SUCCESS(Status
))
4395 return RtlNtStatusToDosError (Status
);
4398 return ERROR_SUCCESS
;
4402 /************************************************************************
4408 RegSetValueA (HKEY hKey
,
4417 if (dwType
!= REG_SZ
)
4419 return ERROR_INVALID_PARAMETER
;
4422 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
4424 ret
= RegCreateKeyA(hKey
,
4428 if (ret
!= ERROR_SUCCESS
)
4436 ret
= RegSetValueExA(hSubKey
,
4440 (CONST BYTE
*)lpData
,
4441 strlen(lpData
) + 1);
4443 if (hSubKey
!= hKey
)
4445 RegCloseKey(hSubKey
);
4452 /************************************************************************
4458 RegSetValueW (HKEY hKey
,
4464 OBJECT_ATTRIBUTES ObjectAttributes
;
4465 UNICODE_STRING SubKeyString
;
4472 Status
= MapDefaultKey (&KeyHandle
,
4474 if (!NT_SUCCESS(Status
))
4476 return RtlNtStatusToDosError (Status
);
4479 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
4481 RtlInitUnicodeString (&SubKeyString
,
4483 InitializeObjectAttributes (&ObjectAttributes
,
4485 OBJ_CASE_INSENSITIVE
,
4488 Status
= NtOpenKey (&RealKey
,
4491 if (!NT_SUCCESS(Status
))
4493 ErrorCode
= RtlNtStatusToDosError (Status
);
4496 CloseRealKey
= TRUE
;
4501 CloseRealKey
= FALSE
;
4504 ErrorCode
= RegSetValueExW (RealKey
,
4510 if (CloseRealKey
== TRUE
)
4516 ClosePredefKey(KeyHandle
);
4522 /************************************************************************
4528 RegUnLoadKeyA (HKEY hKey
,
4531 UNICODE_STRING KeyName
;
4534 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
4537 ErrorCode
= RegUnLoadKeyW (hKey
,
4540 RtlFreeUnicodeString (&KeyName
);
4546 /************************************************************************
4552 RegUnLoadKeyW (HKEY hKey
,
4555 OBJECT_ATTRIBUTES ObjectAttributes
;
4556 UNICODE_STRING KeyName
;
4560 if (hKey
== HKEY_PERFORMANCE_DATA
)
4562 return ERROR_INVALID_HANDLE
;
4565 Status
= MapDefaultKey (&KeyHandle
, hKey
);
4566 if (!NT_SUCCESS(Status
))
4568 return RtlNtStatusToDosError (Status
);
4571 RtlInitUnicodeString (&KeyName
,
4574 InitializeObjectAttributes (&ObjectAttributes
,
4576 OBJ_CASE_INSENSITIVE
,
4580 Status
= NtUnloadKey (&ObjectAttributes
);
4582 ClosePredefKey(KeyHandle
);
4584 if (!NT_SUCCESS(Status
))
4586 return RtlNtStatusToDosError (Status
);
4589 return ERROR_SUCCESS
;
4593 /************************************************************************
4599 RegLoadMUIStringW(IN HKEY hKey
,
4600 IN LPCWSTR pszValue OPTIONAL
,
4601 OUT LPWSTR pszOutBuf
,
4604 IN LPCWSTR pszDirectory OPTIONAL
)
4606 DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
4607 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
4608 return ERROR_CALL_NOT_IMPLEMENTED
;
4612 /************************************************************************
4618 RegLoadMUIStringA(IN HKEY hKey
,
4619 IN LPCSTR pszValue OPTIONAL
,
4620 OUT LPSTR pszOutBuf
,
4623 IN LPCSTR pszDirectory OPTIONAL
)
4625 DPRINT1("RegLoadMUIStringA(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
4626 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
4627 return ERROR_CALL_NOT_IMPLEMENTED
;