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
;
34 static BOOLEAN DefaultHandlesDisabled
= FALSE
;
36 /* PROTOTYPES ***************************************************************/
38 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
39 static VOID
CloseDefaultKeys(VOID
);
40 #define CloseDefaultKey(Handle) \
41 if ((ULONG_PTR)Handle & 0x1) { \
45 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
46 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
47 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
48 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
51 /* FUNCTIONS ****************************************************************/
52 /* check if value type needs string conversion (Ansi<->Unicode) */
53 inline static int is_string( DWORD type
)
55 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
58 /************************************************************************
59 * RegInitDefaultHandles
64 TRACE("RegInitialize()\n");
66 ProcessHeap
= RtlGetProcessHeap();
67 RtlZeroMemory (DefaultHandleTable
,
68 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
69 RtlInitializeCriticalSection (&HandleTableCS
);
75 /************************************************************************
81 TRACE("RegCleanup()\n");
84 RtlDeleteCriticalSection (&HandleTableCS
);
91 MapDefaultKey (OUT PHANDLE RealKey
,
97 NTSTATUS Status
= STATUS_SUCCESS
;
99 TRACE("MapDefaultKey (Key %x)\n", Key
);
101 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
103 *RealKey
= (HANDLE
)((ULONG_PTR
)Key
& ~0x1);
104 return STATUS_SUCCESS
;
107 /* Handle special cases here */
108 Index
= (ULONG
)Key
& 0x0FFFFFFF;
109 if (Index
>= MAX_DEFAULT_HANDLES
)
111 return STATUS_INVALID_PARAMETER
;
114 RtlEnterCriticalSection (&HandleTableCS
);
116 if (!DefaultHandlesDisabled
)
118 Handle
= &DefaultHandleTable
[Index
];
119 DoOpen
= (*Handle
== NULL
);
129 /* create/open the default handle */
132 case 0: /* HKEY_CLASSES_ROOT */
133 Status
= OpenClassesRootKey (Handle
);
136 case 1: /* HKEY_CURRENT_USER */
137 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
141 case 2: /* HKEY_LOCAL_MACHINE */
142 Status
= OpenLocalMachineKey (Handle
);
145 case 3: /* HKEY_USERS */
146 Status
= OpenUsersKey (Handle
);
149 case 4: /* HKEY_PERFORMANCE_DATA */
150 Status
= OpenPerformanceDataKey (Handle
);
153 case 5: /* HKEY_CURRENT_CONFIG */
154 Status
= OpenCurrentConfigKey (Handle
);
157 case 6: /* HKEY_DYN_DATA */
158 Status
= STATUS_NOT_IMPLEMENTED
;
162 WARN("MapDefaultHandle() no handle creator\n");
163 Status
= STATUS_INVALID_PARAMETER
;
168 if (NT_SUCCESS(Status
))
170 if (!DefaultHandlesDisabled
)
173 *(PULONG_PTR
)Handle
|= 0x1;
176 RtlLeaveCriticalSection (&HandleTableCS
);
183 CloseDefaultKeys (VOID
)
187 RtlEnterCriticalSection (&HandleTableCS
);
188 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
190 if (DefaultHandleTable
[i
] != NULL
)
192 NtClose (DefaultHandleTable
[i
]);
193 DefaultHandleTable
[i
] = NULL
;
196 RtlLeaveCriticalSection (&HandleTableCS
);
201 OpenClassesRootKey (PHANDLE KeyHandle
)
203 OBJECT_ATTRIBUTES Attributes
;
204 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\CLASSES");
206 TRACE("OpenClassesRootKey()\n");
208 InitializeObjectAttributes (&Attributes
,
210 OBJ_CASE_INSENSITIVE
,
213 return NtOpenKey (KeyHandle
,
220 OpenLocalMachineKey (PHANDLE KeyHandle
)
222 OBJECT_ATTRIBUTES Attributes
;
223 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine");
226 TRACE("OpenLocalMachineKey()\n");
228 InitializeObjectAttributes (&Attributes
,
230 OBJ_CASE_INSENSITIVE
,
233 Status
= NtOpenKey (KeyHandle
,
237 TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
243 OpenUsersKey (PHANDLE KeyHandle
)
245 OBJECT_ATTRIBUTES Attributes
;
246 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\User");
248 TRACE("OpenUsersKey()\n");
250 InitializeObjectAttributes (&Attributes
,
252 OBJ_CASE_INSENSITIVE
,
255 return NtOpenKey (KeyHandle
,
262 OpenCurrentConfigKey (PHANDLE KeyHandle
)
264 OBJECT_ATTRIBUTES Attributes
;
265 UNICODE_STRING KeyName
=
266 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
268 TRACE("OpenCurrentConfigKey()\n");
270 InitializeObjectAttributes (&Attributes
,
272 OBJ_CASE_INSENSITIVE
,
275 return NtOpenKey (KeyHandle
,
281 /************************************************************************
282 * RegDisablePredefinedCacheEx
287 RegDisablePredefinedCacheEx(VOID
)
289 RtlEnterCriticalSection (&HandleTableCS
);
290 DefaultHandlesDisabled
= TRUE
;
291 RtlLeaveCriticalSection (&HandleTableCS
);
292 return ERROR_SUCCESS
;
296 /************************************************************************
302 RegCloseKey (HKEY hKey
)
306 /* don't close null handle or a pseudo handle */
307 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
309 return ERROR_INVALID_HANDLE
;
312 Status
= NtClose (hKey
);
313 if (!NT_SUCCESS(Status
))
315 return RtlNtStatusToDosError (Status
);
318 return ERROR_SUCCESS
;
322 /************************************************************************
323 * RegConnectRegistryA
328 RegConnectRegistryA (LPCSTR lpMachineName
,
332 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
333 return ERROR_CALL_NOT_IMPLEMENTED
;
337 /************************************************************************
343 RegCopyTreeW(IN HKEY hKeySrc
,
344 IN LPCWSTR lpSubKey OPTIONAL
,
347 HANDLE DestKeyHandle
, KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
350 Status
= MapDefaultKey(&KeyHandle
,
352 if (!NT_SUCCESS(Status
))
354 return RtlNtStatusToDosError(Status
);
357 Status
= MapDefaultKey(&DestKeyHandle
,
359 if (!NT_SUCCESS(Status
))
364 if (lpSubKey
!= NULL
)
366 OBJECT_ATTRIBUTES ObjectAttributes
;
367 UNICODE_STRING SubKeyName
;
369 RtlInitUnicodeString(&SubKeyName
,
372 InitializeObjectAttributes(&ObjectAttributes
,
374 OBJ_CASE_INSENSITIVE
,
378 Status
= NtOpenKey(&SubKeyHandle
,
381 if (!NT_SUCCESS(Status
))
386 CurKey
= SubKeyHandle
;
391 /* FIXME - copy all keys and values recursively */
392 Status
= STATUS_NOT_IMPLEMENTED
;
394 if (SubKeyHandle
!= NULL
)
396 NtClose(SubKeyHandle
);
400 CloseDefaultKey(DestKeyHandle
);
402 CloseDefaultKey(KeyHandle
);
404 if (!NT_SUCCESS(Status
))
406 return RtlNtStatusToDosError(Status
);
409 return ERROR_SUCCESS
;
413 /************************************************************************
419 RegCopyTreeA(IN HKEY hKeySrc
,
420 IN LPCSTR lpSubKey OPTIONAL
,
423 UNICODE_STRING SubKeyName
;
426 if (lpSubKey
!= NULL
)
428 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
431 return ERROR_NOT_ENOUGH_MEMORY
;
435 RtlInitUnicodeString(&SubKeyName
,
438 Ret
= RegCopyTreeW(hKeySrc
,
442 RtlFreeUnicodeString(&SubKeyName
);
448 /************************************************************************
449 * RegConnectRegistryW
454 RegConnectRegistryW (LPCWSTR lpMachineName
,
458 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
459 return ERROR_CALL_NOT_IMPLEMENTED
;
463 /************************************************************************
466 * Create key and all necessary intermediate keys
469 CreateNestedKey(PHKEY KeyHandle
,
470 POBJECT_ATTRIBUTES ObjectAttributes
,
471 PUNICODE_STRING ClassString
,
474 DWORD
*lpdwDisposition
)
476 OBJECT_ATTRIBUTES LocalObjectAttributes
;
477 UNICODE_STRING LocalKeyName
;
480 ULONG FullNameLength
;
483 HANDLE LocalKeyHandle
;
485 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
491 (PULONG
)lpdwDisposition
);
492 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
493 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
496 /* Copy object attributes */
497 RtlCopyMemory (&LocalObjectAttributes
,
499 sizeof(OBJECT_ATTRIBUTES
));
500 RtlCreateUnicodeString (&LocalKeyName
,
501 ObjectAttributes
->ObjectName
->Buffer
);
502 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
503 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
505 /* Remove the last part of the key name and try to create the key again. */
506 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
508 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
509 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
511 Status
= STATUS_UNSUCCESSFUL
;
515 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
517 Status
= NtCreateKey (&LocalKeyHandle
,
519 &LocalObjectAttributes
,
524 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
527 if (!NT_SUCCESS(Status
))
529 RtlFreeUnicodeString (&LocalKeyName
);
533 /* Add removed parts of the key name and create them too. */
534 Length
= wcslen (LocalKeyName
.Buffer
);
537 NtClose (LocalKeyHandle
);
539 LocalKeyName
.Buffer
[Length
] = L
'\\';
540 Length
= wcslen (LocalKeyName
.Buffer
);
541 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
543 if (Length
== FullNameLength
)
545 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
551 (PULONG
)lpdwDisposition
);
554 Status
= NtCreateKey (&LocalKeyHandle
,
556 &LocalObjectAttributes
,
561 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
562 if (!NT_SUCCESS(Status
))
566 RtlFreeUnicodeString (&LocalKeyName
);
572 /************************************************************************
578 RegCreateKeyExA (HKEY hKey
,
584 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
586 LPDWORD lpdwDisposition
)
588 UNICODE_STRING SubKeyString
;
589 UNICODE_STRING ClassString
;
590 OBJECT_ATTRIBUTES Attributes
;
594 TRACE("RegCreateKeyExA() called\n");
596 /* get the real parent key */
597 Status
= MapDefaultKey (&ParentKey
,
599 if (!NT_SUCCESS(Status
))
601 return RtlNtStatusToDosError (Status
);
603 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
607 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
611 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
613 InitializeObjectAttributes (&Attributes
,
615 OBJ_CASE_INSENSITIVE
,
617 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
618 Status
= CreateNestedKey(phkResult
,
620 (lpClass
== NULL
)? NULL
: &ClassString
,
624 RtlFreeUnicodeString (&SubKeyString
);
627 RtlFreeUnicodeString (&ClassString
);
630 CloseDefaultKey(ParentKey
);
632 TRACE("Status %x\n", Status
);
633 if (!NT_SUCCESS(Status
))
635 return RtlNtStatusToDosError (Status
);
638 return ERROR_SUCCESS
;
642 /************************************************************************
648 RegCreateKeyExW (HKEY hKey
,
654 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
656 LPDWORD lpdwDisposition
)
658 UNICODE_STRING SubKeyString
;
659 UNICODE_STRING ClassString
;
660 OBJECT_ATTRIBUTES Attributes
;
664 TRACE("RegCreateKeyExW() called\n");
666 /* get the real parent key */
667 Status
= MapDefaultKey (&ParentKey
,
669 if (!NT_SUCCESS(Status
))
671 return RtlNtStatusToDosError(Status
);
673 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
675 RtlInitUnicodeString (&ClassString
,
677 RtlInitUnicodeString (&SubKeyString
,
679 InitializeObjectAttributes (&Attributes
,
681 OBJ_CASE_INSENSITIVE
,
683 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
684 Status
= CreateNestedKey(phkResult
,
686 (lpClass
== NULL
)? NULL
: &ClassString
,
691 CloseDefaultKey(ParentKey
);
693 TRACE("Status %x\n", Status
);
694 if (!NT_SUCCESS(Status
))
696 return RtlNtStatusToDosError (Status
);
699 return ERROR_SUCCESS
;
703 /************************************************************************
709 RegCreateKeyA (HKEY hKey
,
713 return RegCreateKeyExA (hKey
,
725 /************************************************************************
731 RegCreateKeyW (HKEY hKey
,
735 return RegCreateKeyExW (hKey
,
747 /************************************************************************
753 RegDeleteKeyA (HKEY hKey
,
756 OBJECT_ATTRIBUTES ObjectAttributes
;
757 UNICODE_STRING SubKeyName
;
762 Status
= MapDefaultKey (&ParentKey
,
764 if (!NT_SUCCESS(Status
))
766 return RtlNtStatusToDosError (Status
);
769 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
771 InitializeObjectAttributes(&ObjectAttributes
,
773 OBJ_CASE_INSENSITIVE
,
777 Status
= NtOpenKey (&TargetKey
,
780 RtlFreeUnicodeString (&SubKeyName
);
781 if (!NT_SUCCESS(Status
))
786 Status
= NtDeleteKey (TargetKey
);
790 CloseDefaultKey(ParentKey
);
792 if (!NT_SUCCESS(Status
))
794 return RtlNtStatusToDosError(Status
);
797 return ERROR_SUCCESS
;
801 /************************************************************************
807 RegDeleteKeyW (HKEY hKey
,
810 OBJECT_ATTRIBUTES ObjectAttributes
;
811 UNICODE_STRING SubKeyName
;
816 Status
= MapDefaultKey (&ParentKey
,
818 if (!NT_SUCCESS(Status
))
820 return RtlNtStatusToDosError (Status
);
823 RtlInitUnicodeString (&SubKeyName
,
825 InitializeObjectAttributes (&ObjectAttributes
,
827 OBJ_CASE_INSENSITIVE
,
830 Status
= NtOpenKey (&TargetKey
,
833 if (!NT_SUCCESS(Status
))
838 Status
= NtDeleteKey (TargetKey
);
842 CloseDefaultKey(ParentKey
);
844 if (!NT_SUCCESS(Status
))
846 return RtlNtStatusToDosError (Status
);
849 return ERROR_SUCCESS
;
853 /************************************************************************
859 RegDeleteKeyValueW(IN HKEY hKey
,
860 IN LPCWSTR lpSubKey OPTIONAL
,
861 IN LPCWSTR lpValueName OPTIONAL
)
863 UNICODE_STRING ValueName
;
864 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
867 Status
= MapDefaultKey(&KeyHandle
,
869 if (!NT_SUCCESS(Status
))
871 return RtlNtStatusToDosError(Status
);
874 if (lpSubKey
!= NULL
)
876 OBJECT_ATTRIBUTES ObjectAttributes
;
877 UNICODE_STRING SubKeyName
;
879 RtlInitUnicodeString(&SubKeyName
,
882 InitializeObjectAttributes(&ObjectAttributes
,
884 OBJ_CASE_INSENSITIVE
,
888 Status
= NtOpenKey(&SubKeyHandle
,
891 if (!NT_SUCCESS(Status
))
896 CurKey
= SubKeyHandle
;
901 RtlInitUnicodeString(&ValueName
,
902 (LPWSTR
)lpValueName
);
904 Status
= NtDeleteValueKey(CurKey
,
907 if (SubKeyHandle
!= NULL
)
909 NtClose(SubKeyHandle
);
913 CloseDefaultKey(KeyHandle
);
915 if (!NT_SUCCESS(Status
))
917 return RtlNtStatusToDosError(Status
);
920 return ERROR_SUCCESS
;
924 /************************************************************************
930 RegDeleteKeyValueA(IN HKEY hKey
,
931 IN LPCSTR lpSubKey OPTIONAL
,
932 IN LPCSTR lpValueName OPTIONAL
)
934 UNICODE_STRING SubKey
, ValueName
;
937 if (lpSubKey
!= NULL
)
939 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey
,
942 return ERROR_NOT_ENOUGH_MEMORY
;
946 RtlInitUnicodeString(&SubKey
,
949 if (lpValueName
!= NULL
)
951 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName
,
954 RtlFreeUnicodeString(&SubKey
);
955 return ERROR_NOT_ENOUGH_MEMORY
;
959 RtlInitUnicodeString(&ValueName
,
962 Ret
= RegDeleteKeyValueW(hKey
,
966 RtlFreeUnicodeString(&SubKey
);
967 RtlFreeUnicodeString(&ValueName
);
973 /************************************************************************
979 RegDeleteTreeW(IN HKEY hKey
,
980 IN LPCWSTR lpSubKey OPTIONAL
)
982 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
985 Status
= MapDefaultKey(&KeyHandle
,
987 if (!NT_SUCCESS(Status
))
989 return RtlNtStatusToDosError(Status
);
992 if (lpSubKey
!= NULL
)
994 OBJECT_ATTRIBUTES ObjectAttributes
;
995 UNICODE_STRING SubKeyName
;
997 RtlInitUnicodeString(&SubKeyName
,
1000 InitializeObjectAttributes(&ObjectAttributes
,
1002 OBJ_CASE_INSENSITIVE
,
1006 Status
= NtOpenKey(&SubKeyHandle
,
1007 DELETE
| KEY_ENUMERATE_SUB_KEYS
| KEY_QUERY_VALUE
,
1009 if (!NT_SUCCESS(Status
))
1014 CurKey
= SubKeyHandle
;
1019 /* FIXME - delete all keys recursively */
1020 Status
= STATUS_NOT_IMPLEMENTED
;
1022 if (SubKeyHandle
!= NULL
)
1024 NtClose(SubKeyHandle
);
1028 CloseDefaultKey(KeyHandle
);
1030 if (!NT_SUCCESS(Status
))
1032 return RtlNtStatusToDosError(Status
);
1035 return ERROR_SUCCESS
;
1039 /************************************************************************
1045 RegDeleteTreeA(IN HKEY hKey
,
1046 IN LPCSTR lpSubKey OPTIONAL
)
1048 UNICODE_STRING SubKeyName
;
1051 if (lpSubKey
!= NULL
)
1053 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1056 return ERROR_NOT_ENOUGH_MEMORY
;
1060 RtlInitUnicodeString(&SubKeyName
,
1063 Ret
= RegDeleteTreeW(hKey
,
1066 RtlFreeUnicodeString(&SubKeyName
);
1072 /************************************************************************
1078 RegSetKeyValueW(IN HKEY hKey
,
1079 IN LPCWSTR lpSubKey OPTIONAL
,
1080 IN LPCWSTR lpValueName OPTIONAL
,
1082 IN LPCVOID lpData OPTIONAL
,
1085 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1089 Status
= MapDefaultKey(&KeyHandle
,
1091 if (!NT_SUCCESS(Status
))
1093 return RtlNtStatusToDosError(Status
);
1096 if (lpSubKey
!= NULL
)
1098 OBJECT_ATTRIBUTES ObjectAttributes
;
1099 UNICODE_STRING SubKeyName
;
1101 RtlInitUnicodeString(&SubKeyName
,
1104 InitializeObjectAttributes(&ObjectAttributes
,
1106 OBJ_CASE_INSENSITIVE
,
1110 Status
= NtOpenKey(&SubKeyHandle
,
1113 if (!NT_SUCCESS(Status
))
1115 Ret
= RtlNtStatusToDosError(Status
);
1119 CurKey
= SubKeyHandle
;
1124 Ret
= RegSetValueExW(CurKey
,
1131 if (SubKeyHandle
!= NULL
)
1133 NtClose(SubKeyHandle
);
1137 CloseDefaultKey(KeyHandle
);
1143 /************************************************************************
1149 RegSetKeyValueA(IN HKEY hKey
,
1150 IN LPCSTR lpSubKey OPTIONAL
,
1151 IN LPCSTR lpValueName OPTIONAL
,
1153 IN LPCVOID lpData OPTIONAL
,
1156 HANDLE KeyHandle
, CurKey
, SubKeyHandle
= NULL
;
1160 Status
= MapDefaultKey(&KeyHandle
,
1162 if (!NT_SUCCESS(Status
))
1164 return RtlNtStatusToDosError(Status
);
1167 if (lpSubKey
!= NULL
)
1169 OBJECT_ATTRIBUTES ObjectAttributes
;
1170 UNICODE_STRING SubKeyName
;
1172 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
1175 Ret
= ERROR_NOT_ENOUGH_MEMORY
;
1179 InitializeObjectAttributes(&ObjectAttributes
,
1181 OBJ_CASE_INSENSITIVE
,
1185 Status
= NtOpenKey(&SubKeyHandle
,
1189 RtlFreeUnicodeString(&SubKeyName
);
1191 if (!NT_SUCCESS(Status
))
1193 Ret
= RtlNtStatusToDosError(Status
);
1197 CurKey
= SubKeyHandle
;
1202 Ret
= RegSetValueExA(CurKey
,
1209 if (SubKeyHandle
!= NULL
)
1211 NtClose(SubKeyHandle
);
1215 CloseDefaultKey(KeyHandle
);
1221 /************************************************************************
1227 RegDeleteValueA (HKEY hKey
,
1230 UNICODE_STRING ValueName
;
1234 Status
= MapDefaultKey (&KeyHandle
,
1236 if (!NT_SUCCESS(Status
))
1238 return RtlNtStatusToDosError (Status
);
1241 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
1242 (LPSTR
)lpValueName
);
1243 Status
= NtDeleteValueKey (KeyHandle
,
1245 RtlFreeUnicodeString (&ValueName
);
1247 CloseDefaultKey(KeyHandle
);
1249 if (!NT_SUCCESS(Status
))
1251 return RtlNtStatusToDosError (Status
);
1254 return ERROR_SUCCESS
;
1258 /************************************************************************
1264 RegDeleteValueW (HKEY hKey
,
1265 LPCWSTR lpValueName
)
1267 UNICODE_STRING ValueName
;
1271 Status
= MapDefaultKey (&KeyHandle
,
1273 if (!NT_SUCCESS(Status
))
1275 return RtlNtStatusToDosError (Status
);
1278 RtlInitUnicodeString (&ValueName
,
1279 (LPWSTR
)lpValueName
);
1281 Status
= NtDeleteValueKey (KeyHandle
,
1284 CloseDefaultKey(KeyHandle
);
1286 if (!NT_SUCCESS(Status
))
1288 return RtlNtStatusToDosError (Status
);
1291 return ERROR_SUCCESS
;
1295 /************************************************************************
1301 RegEnumKeyA (HKEY hKey
,
1309 return RegEnumKeyExA (hKey
,
1320 /************************************************************************
1326 RegEnumKeyW (HKEY hKey
,
1334 return RegEnumKeyExW (hKey
,
1345 /************************************************************************
1351 RegEnumKeyExA (HKEY hKey
,
1358 PFILETIME lpftLastWriteTime
)
1362 KEY_NODE_INFORMATION Node
;
1363 KEY_BASIC_INFORMATION Basic
;
1366 UNICODE_STRING StringU
;
1367 ANSI_STRING StringA
;
1368 LONG ErrorCode
= ERROR_SUCCESS
;
1370 DWORD ClassLength
= 0;
1376 TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
1377 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
1379 if ((lpClass
) && (!lpcbClass
))
1381 return ERROR_INVALID_PARAMETER
;
1384 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1385 if (!NT_SUCCESS(Status
))
1387 return RtlNtStatusToDosError (Status
);
1392 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1403 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1410 /* The class name should start at a dword boundary */
1411 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1415 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1418 KeyInfo
= RtlAllocateHeap (ProcessHeap
, 0, BufferSize
);
1419 if (KeyInfo
== NULL
)
1421 ErrorCode
= ERROR_OUTOFMEMORY
;
1425 Status
= NtEnumerateKey (KeyHandle
,
1427 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
1431 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1432 if (!NT_SUCCESS(Status
))
1434 ErrorCode
= RtlNtStatusToDosError (Status
);
1438 if (lpClass
== NULL
)
1440 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1442 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1446 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
1447 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
1448 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
1453 if (KeyInfo
->Node
.NameLength
> NameLength
||
1454 KeyInfo
->Node
.ClassLength
> ClassLength
)
1456 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1460 StringA
.Buffer
= lpClass
;
1462 StringA
.MaximumLength
= *lpcbClass
;
1463 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
1464 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
1465 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
1466 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1467 lpClass
[StringA
.Length
] = 0;
1468 *lpcbClass
= StringA
.Length
;
1469 StringU
.Buffer
= KeyInfo
->Node
.Name
;
1470 StringU
.Length
= KeyInfo
->Node
.NameLength
;
1471 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
1475 if (ErrorCode
== ERROR_SUCCESS
)
1477 StringA
.Buffer
= lpName
;
1479 StringA
.MaximumLength
= *lpcbName
;
1480 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1481 lpName
[StringA
.Length
] = 0;
1482 *lpcbName
= StringA
.Length
;
1483 if (lpftLastWriteTime
!= NULL
)
1485 if (lpClass
== NULL
)
1487 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1488 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1492 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1493 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1499 TRACE("Key Namea0 Length %d\n", StringU
.Length
);
1500 TRACE("Key Namea1 Length %d\n", NameLength
);
1501 TRACE("Key Namea Length %d\n", *lpcbName
);
1502 TRACE("Key Namea %s\n", lpName
);
1504 RtlFreeHeap (ProcessHeap
,
1509 CloseDefaultKey(KeyHandle
);
1515 /************************************************************************
1521 RegEnumKeyExW (HKEY hKey
,
1528 PFILETIME lpftLastWriteTime
)
1532 KEY_NODE_INFORMATION Node
;
1533 KEY_BASIC_INFORMATION Basic
;
1539 ULONG ClassLength
= 0;
1541 LONG ErrorCode
= ERROR_SUCCESS
;
1544 Status
= MapDefaultKey(&KeyHandle
,
1546 if (!NT_SUCCESS(Status
))
1548 return RtlNtStatusToDosError (Status
);
1553 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1564 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1571 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1575 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1578 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1581 if (KeyInfo
== NULL
)
1583 ErrorCode
= ERROR_OUTOFMEMORY
;
1587 Status
= NtEnumerateKey (KeyHandle
,
1589 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1593 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1594 if (!NT_SUCCESS(Status
))
1596 ErrorCode
= RtlNtStatusToDosError (Status
);
1600 if (lpClass
== NULL
)
1602 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1604 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1608 RtlCopyMemory (lpName
,
1609 KeyInfo
->Basic
.Name
,
1610 KeyInfo
->Basic
.NameLength
);
1611 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1612 lpName
[*lpcbName
] = 0;
1617 if (KeyInfo
->Node
.NameLength
> NameLength
||
1618 KeyInfo
->Node
.ClassLength
> ClassLength
)
1620 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1624 RtlCopyMemory (lpName
,
1626 KeyInfo
->Node
.NameLength
);
1627 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1628 lpName
[*lpcbName
] = 0;
1629 RtlCopyMemory (lpClass
,
1630 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1631 KeyInfo
->Node
.ClassLength
);
1632 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1633 lpClass
[*lpcbClass
] = 0;
1637 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1639 if (lpClass
== NULL
)
1641 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1642 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1646 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1647 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1652 RtlFreeHeap (ProcessHeap
,
1657 CloseDefaultKey(KeyHandle
);
1662 /************************************************************************
1668 RegEnumValueA( HKEY hKey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1669 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1674 char buffer
[256], *buf_ptr
= buffer
;
1675 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1676 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1678 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1679 // hkey, index, value, val_count, reserved, type, data, count );
1681 /* NT only checks count, not val_count */
1682 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1683 status
= MapDefaultKey (&KeyHandle
, hKey
);
1684 if (!NT_SUCCESS(status
))
1686 return RtlNtStatusToDosError (status
);
1689 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1690 if (data
) total_size
+= *count
;
1691 total_size
= min( sizeof(buffer
), total_size
);
1693 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1694 buffer
, total_size
, &total_size
);
1695 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1697 /* we need to fetch the contents for a string type even if not requested,
1698 * because we need to compute the length of the ASCII string. */
1699 if (value
|| data
|| is_string(info
->Type
))
1701 /* retry with a dynamically allocated buffer */
1702 while (status
== STATUS_BUFFER_OVERFLOW
)
1704 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1705 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1707 status
= STATUS_INSUFFICIENT_RESOURCES
;
1710 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1711 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1712 buf_ptr
, total_size
, &total_size
);
1715 if (status
) goto done
;
1717 if (is_string(info
->Type
))
1720 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1721 total_size
- info
->DataOffset
);
1724 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1727 RtlUnicodeToMultiByteN( (PCHAR
)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1728 total_size
- info
->DataOffset
);
1729 /* if the type is REG_SZ and data is not 0-terminated
1730 * and there is enough space in the buffer NT appends a \0 */
1731 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1734 info
->DataLength
= len
;
1738 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1739 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1742 if (value
&& !status
)
1746 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1747 if (len
>= *val_count
)
1749 status
= STATUS_BUFFER_OVERFLOW
;
1752 len
= *val_count
- 1;
1753 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1759 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1765 else status
= STATUS_SUCCESS
;
1767 if (type
) *type
= info
->Type
;
1768 if (count
) *count
= info
->DataLength
;
1771 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1772 CloseDefaultKey(KeyHandle
);
1773 return RtlNtStatusToDosError(status
);
1776 /******************************************************************************
1777 * RegEnumValueW [ADVAPI32.@]
1781 * hkey [I] Handle to key to query
1782 * index [I] Index of value to query
1783 * value [O] Value string
1784 * val_count [I/O] Size of value buffer (in wchars)
1785 * reserved [I] Reserved
1786 * type [O] Type code
1787 * data [O] Value data
1788 * count [I/O] Size of data buffer (in bytes)
1791 * Success: ERROR_SUCCESS
1792 * Failure: nonzero error code from Winerror.h
1795 RegEnumValueW( HKEY hKey
, DWORD index
, LPWSTR value
, PDWORD val_count
,
1796 PDWORD reserved
, PDWORD type
, LPBYTE data
, PDWORD count
)
1801 char buffer
[256], *buf_ptr
= buffer
;
1802 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1803 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1805 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1806 // hkey, index, value, val_count, reserved, type, data, count );
1808 /* NT only checks count, not val_count */
1809 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1811 status
= MapDefaultKey (&KeyHandle
, hKey
);
1812 if (!NT_SUCCESS(status
))
1814 return RtlNtStatusToDosError (status
);
1817 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1818 if (data
) total_size
+= *count
;
1819 total_size
= min( sizeof(buffer
), total_size
);
1821 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1822 buffer
, total_size
, &total_size
);
1823 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1827 /* retry with a dynamically allocated buffer */
1828 while (status
== STATUS_BUFFER_OVERFLOW
)
1830 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1831 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1833 status
= ERROR_NOT_ENOUGH_MEMORY
;
1836 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1837 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1838 buf_ptr
, total_size
, &total_size
);
1841 if (status
) goto done
;
1845 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1847 status
= STATUS_BUFFER_OVERFLOW
;
1850 memcpy( value
, info
->Name
, info
->NameLength
);
1851 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1852 value
[*val_count
] = 0;
1857 if (total_size
- info
->DataOffset
> *count
)
1859 status
= STATUS_BUFFER_OVERFLOW
;
1862 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1863 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1865 /* if the type is REG_SZ and data is not 0-terminated
1866 * and there is enough space in the buffer NT appends a \0 */
1867 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1868 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1872 else status
= STATUS_SUCCESS
;
1875 if (type
) *type
= info
->Type
;
1876 if (count
) *count
= info
->DataLength
;
1879 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1880 CloseDefaultKey(KeyHandle
);
1881 return RtlNtStatusToDosError(status
);
1884 /************************************************************************
1890 RegFlushKey(HKEY hKey
)
1895 if (hKey
== HKEY_PERFORMANCE_DATA
)
1897 return ERROR_SUCCESS
;
1900 Status
= MapDefaultKey (&KeyHandle
,
1902 if (!NT_SUCCESS(Status
))
1904 return RtlNtStatusToDosError (Status
);
1907 Status
= NtFlushKey (KeyHandle
);
1909 CloseDefaultKey(KeyHandle
);
1911 if (!NT_SUCCESS(Status
))
1913 return RtlNtStatusToDosError (Status
);
1916 return ERROR_SUCCESS
;
1920 /************************************************************************
1926 RegGetKeySecurity(HKEY hKey
,
1927 SECURITY_INFORMATION SecurityInformation
,
1928 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1929 LPDWORD lpcbSecurityDescriptor
)
1934 if (hKey
== HKEY_PERFORMANCE_DATA
)
1936 return ERROR_INVALID_HANDLE
;
1939 Status
= MapDefaultKey(&KeyHandle
,
1941 if (!NT_SUCCESS(Status
))
1943 TRACE("MapDefaultKey() failed (Status %lx)\n", Status
);
1944 return RtlNtStatusToDosError (Status
);
1947 Status
= NtQuerySecurityObject(KeyHandle
,
1948 SecurityInformation
,
1949 pSecurityDescriptor
,
1950 *lpcbSecurityDescriptor
,
1951 lpcbSecurityDescriptor
);
1953 CloseDefaultKey(KeyHandle
);
1955 if (!NT_SUCCESS(Status
))
1957 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
1958 return RtlNtStatusToDosError (Status
);
1961 return ERROR_SUCCESS
;
1965 /************************************************************************
1971 RegLoadKeyA (HKEY hKey
,
1975 UNICODE_STRING FileName
;
1976 UNICODE_STRING KeyName
;
1979 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1981 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1984 ErrorCode
= RegLoadKeyW (hKey
,
1988 RtlFreeUnicodeString (&FileName
);
1989 RtlFreeUnicodeString (&KeyName
);
1995 /************************************************************************
2001 RegLoadKeyW (HKEY hKey
,
2005 OBJECT_ATTRIBUTES FileObjectAttributes
;
2006 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2007 UNICODE_STRING FileName
;
2008 UNICODE_STRING KeyName
;
2011 LONG ErrorCode
= ERROR_SUCCESS
;
2013 if (hKey
== HKEY_PERFORMANCE_DATA
)
2015 return ERROR_INVALID_HANDLE
;
2018 Status
= MapDefaultKey (&KeyHandle
,
2020 if (!NT_SUCCESS(Status
))
2022 return RtlNtStatusToDosError (Status
);
2025 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2030 ErrorCode
= ERROR_BAD_PATHNAME
;
2034 InitializeObjectAttributes (&FileObjectAttributes
,
2036 OBJ_CASE_INSENSITIVE
,
2040 RtlInitUnicodeString (&KeyName
,
2043 InitializeObjectAttributes (&KeyObjectAttributes
,
2045 OBJ_CASE_INSENSITIVE
,
2049 Status
= NtLoadKey (&KeyObjectAttributes
,
2050 &FileObjectAttributes
);
2052 RtlFreeUnicodeString (&FileName
);
2054 if (!NT_SUCCESS(Status
))
2056 ErrorCode
= RtlNtStatusToDosError (Status
);
2061 CloseDefaultKey(KeyHandle
);
2067 /************************************************************************
2068 * RegNotifyChangeKeyValue
2073 RegNotifyChangeKeyValue (HKEY hKey
,
2075 DWORD dwNotifyFilter
,
2079 IO_STATUS_BLOCK IoStatusBlock
;
2082 LONG ErrorCode
= ERROR_SUCCESS
;
2084 if (hKey
== HKEY_PERFORMANCE_DATA
)
2086 return ERROR_INVALID_HANDLE
;
2089 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
2091 return ERROR_INVALID_PARAMETER
;
2094 Status
= MapDefaultKey (&KeyHandle
,
2096 if (!NT_SUCCESS(Status
))
2098 return RtlNtStatusToDosError (Status
);
2101 /* FIXME: Remote key handles must fail */
2103 Status
= NtNotifyChangeKey (KeyHandle
,
2113 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
2115 ErrorCode
= RtlNtStatusToDosError (Status
);
2118 CloseDefaultKey(KeyHandle
);
2124 /************************************************************************
2125 * RegOpenCurrentUser
2130 RegOpenCurrentUser (IN REGSAM samDesired
,
2131 OUT PHKEY phkResult
)
2135 Status
= RtlOpenCurrentUser((ACCESS_MASK
)samDesired
,
2136 (PHANDLE
)phkResult
);
2137 if (!NT_SUCCESS(Status
))
2139 /* NOTE - don't set the last error code! just return the error! */
2140 return RtlNtStatusToDosError(Status
);
2143 return ERROR_SUCCESS
;
2147 /************************************************************************
2150 * 20050503 Fireball - imported from WINE
2155 RegOpenKeyA (HKEY hKey
,
2159 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2161 if (!lpSubKey
|| !*lpSubKey
)
2164 return ERROR_SUCCESS
;
2167 return RegOpenKeyExA( hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2171 /************************************************************************
2176 * 20050503 Fireball - imported from WINE
2181 RegOpenKeyW (HKEY hKey
,
2185 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey
, lpSubKey
, phkResult
);
2187 if (!lpSubKey
|| !*lpSubKey
)
2190 return ERROR_SUCCESS
;
2192 return RegOpenKeyExW(hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
2196 /************************************************************************
2202 RegOpenKeyExA (HKEY hKey
,
2208 OBJECT_ATTRIBUTES ObjectAttributes
;
2209 UNICODE_STRING SubKeyString
;
2212 LONG ErrorCode
= ERROR_SUCCESS
;
2214 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2215 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2217 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2218 if (!NT_SUCCESS(Status
))
2220 return RtlNtStatusToDosError (Status
);
2223 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
, (LPSTR
)lpSubKey
);
2224 InitializeObjectAttributes (&ObjectAttributes
,
2226 OBJ_CASE_INSENSITIVE
,
2230 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2231 RtlFreeUnicodeString (&SubKeyString
);
2232 if (!NT_SUCCESS(Status
))
2234 ErrorCode
= RtlNtStatusToDosError (Status
);
2237 CloseDefaultKey(KeyHandle
);
2243 /************************************************************************
2249 RegOpenKeyExW (HKEY hKey
,
2255 OBJECT_ATTRIBUTES ObjectAttributes
;
2256 UNICODE_STRING SubKeyString
;
2259 LONG ErrorCode
= ERROR_SUCCESS
;
2261 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
2262 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
2264 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2265 if (!NT_SUCCESS(Status
))
2267 return RtlNtStatusToDosError (Status
);
2270 if (lpSubKey
!= NULL
)
2271 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)lpSubKey
);
2273 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)L
"");
2275 InitializeObjectAttributes (&ObjectAttributes
,
2277 OBJ_CASE_INSENSITIVE
,
2281 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
2283 if (!NT_SUCCESS(Status
))
2285 ErrorCode
= RtlNtStatusToDosError (Status
);
2288 CloseDefaultKey(KeyHandle
);
2294 /************************************************************************
2295 * RegOpenUserClassesRoot
2300 RegOpenUserClassesRoot (IN HANDLE hToken
,
2302 IN REGSAM samDesired
,
2303 OUT PHKEY phkResult
)
2305 const WCHAR UserClassesKeyPrefix
[] = L
"\\Registry\\User\\";
2306 const WCHAR UserClassesKeySuffix
[] = L
"_Classes";
2307 PTOKEN_USER TokenUserData
;
2308 ULONG RequiredLength
;
2309 UNICODE_STRING UserSidString
, UserClassesKeyRoot
;
2310 OBJECT_ATTRIBUTES ObjectAttributes
;
2314 /* check parameters */
2315 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
2317 return ERROR_INVALID_PARAMETER
;
2321 * Get the user sid from the token
2325 /* determine how much memory we need */
2326 Status
= NtQueryInformationToken(hToken
,
2331 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2333 /* NOTE - as opposed to all other registry functions windows does indeed
2334 change the last error code in case the caller supplied a invalid
2335 handle for example! */
2336 ErrorCode
= RtlNtStatusToDosError (Status
);
2340 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2343 if (TokenUserData
== NULL
)
2345 return ERROR_NOT_ENOUGH_MEMORY
;
2348 /* attempt to read the information */
2349 Status
= NtQueryInformationToken(hToken
,
2354 if (!NT_SUCCESS(Status
))
2356 RtlFreeHeap(ProcessHeap
,
2359 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2361 /* the information appears to have changed?! try again */
2365 /* NOTE - as opposed to all other registry functions windows does indeed
2366 change the last error code in case the caller supplied a invalid
2367 handle for example! */
2368 ErrorCode
= RtlNtStatusToDosError (Status
);
2373 * Build the absolute path for the user's registry in the form
2374 * "\Registry\User\<SID>_Classes"
2376 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2377 TokenUserData
->User
.Sid
,
2380 /* we don't need the user data anymore, free it */
2381 RtlFreeHeap(ProcessHeap
,
2385 if (!NT_SUCCESS(Status
))
2387 return RtlNtStatusToDosError (Status
);
2390 /* allocate enough memory for the entire key string */
2391 UserClassesKeyRoot
.Length
= 0;
2392 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
2393 sizeof(UserClassesKeyPrefix
) +
2394 sizeof(UserClassesKeySuffix
);
2395 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
2397 UserClassesKeyRoot
.MaximumLength
);
2398 if (UserClassesKeyRoot
.Buffer
== NULL
)
2400 RtlFreeUnicodeString(&UserSidString
);
2401 return RtlNtStatusToDosError (Status
);
2404 /* build the string */
2405 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2406 UserClassesKeyPrefix
);
2407 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
2409 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2410 UserClassesKeySuffix
);
2412 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
2418 InitializeObjectAttributes (&ObjectAttributes
,
2419 &UserClassesKeyRoot
,
2420 OBJ_CASE_INSENSITIVE
,
2424 Status
= NtOpenKey((PHANDLE
)phkResult
,
2428 RtlFreeUnicodeString(&UserSidString
);
2429 RtlFreeUnicodeString(&UserClassesKeyRoot
);
2431 if (!NT_SUCCESS(Status
))
2433 return RtlNtStatusToDosError (Status
);
2436 return ERROR_SUCCESS
;
2440 /************************************************************************
2446 RegQueryInfoKeyA (HKEY hKey
,
2451 LPDWORD lpcbMaxSubKeyLen
,
2452 LPDWORD lpcbMaxClassLen
,
2454 LPDWORD lpcbMaxValueNameLen
,
2455 LPDWORD lpcbMaxValueLen
,
2456 LPDWORD lpcbSecurityDescriptor
,
2457 PFILETIME lpftLastWriteTime
)
2459 WCHAR ClassName
[MAX_PATH
];
2460 UNICODE_STRING UnicodeString
;
2461 ANSI_STRING AnsiString
;
2464 RtlInitUnicodeString (&UnicodeString
,
2466 if (lpClass
!= NULL
)
2468 UnicodeString
.Buffer
= &ClassName
[0];
2469 UnicodeString
.MaximumLength
= sizeof(ClassName
);
2470 AnsiString
.MaximumLength
= *lpcbClass
;
2473 ErrorCode
= RegQueryInfoKeyW (hKey
,
2474 UnicodeString
.Buffer
,
2481 lpcbMaxValueNameLen
,
2483 lpcbSecurityDescriptor
,
2485 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
2487 AnsiString
.Buffer
= lpClass
;
2488 AnsiString
.Length
= 0;
2489 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
2490 RtlUnicodeStringToAnsiString (&AnsiString
,
2493 *lpcbClass
= AnsiString
.Length
;
2494 lpClass
[AnsiString
.Length
] = 0;
2501 /************************************************************************
2507 RegQueryInfoKeyW (HKEY hKey
,
2512 LPDWORD lpcbMaxSubKeyLen
,
2513 LPDWORD lpcbMaxClassLen
,
2515 LPDWORD lpcbMaxValueNameLen
,
2516 LPDWORD lpcbMaxValueLen
,
2517 LPDWORD lpcbSecurityDescriptor
,
2518 PFILETIME lpftLastWriteTime
)
2520 KEY_FULL_INFORMATION FullInfoBuffer
;
2521 PKEY_FULL_INFORMATION FullInfo
;
2523 ULONG ClassLength
= 0;
2527 LONG ErrorCode
= ERROR_SUCCESS
;
2529 if ((lpClass
) && (!lpcbClass
))
2531 return ERROR_INVALID_PARAMETER
;
2534 Status
= MapDefaultKey (&KeyHandle
,
2536 if (!NT_SUCCESS(Status
))
2538 return RtlNtStatusToDosError (Status
);
2541 if (lpClass
!= NULL
)
2545 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2552 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2553 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2556 if (FullInfo
== NULL
)
2558 ErrorCode
= ERROR_OUTOFMEMORY
;
2562 FullInfo
->ClassLength
= ClassLength
;
2566 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2567 FullInfo
= &FullInfoBuffer
;
2568 FullInfo
->ClassLength
= 0;
2570 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2572 Status
= NtQueryKey (KeyHandle
,
2577 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
2578 if (!NT_SUCCESS(Status
))
2580 if (lpClass
!= NULL
)
2582 RtlFreeHeap (ProcessHeap
,
2587 ErrorCode
= RtlNtStatusToDosError (Status
);
2591 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
2592 if (lpcSubKeys
!= NULL
)
2594 *lpcSubKeys
= FullInfo
->SubKeys
;
2597 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2598 if (lpcbMaxSubKeyLen
!= NULL
)
2600 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2603 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2604 if (lpcbMaxClassLen
!= NULL
)
2606 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2609 TRACE("Values %lu\n", FullInfo
->Values
);
2610 if (lpcValues
!= NULL
)
2612 *lpcValues
= FullInfo
->Values
;
2615 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2616 if (lpcbMaxValueNameLen
!= NULL
)
2618 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2621 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2622 if (lpcbMaxValueLen
!= NULL
)
2624 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2627 if (lpcbSecurityDescriptor
!= NULL
)
2629 Status
= NtQuerySecurityObject(KeyHandle
,
2630 OWNER_SECURITY_INFORMATION
|
2631 GROUP_SECURITY_INFORMATION
|
2632 DACL_SECURITY_INFORMATION
,
2635 lpcbSecurityDescriptor
);
2636 if (!NT_SUCCESS(Status
))
2638 if (lpClass
!= NULL
)
2640 RtlFreeHeap(ProcessHeap
,
2645 ErrorCode
= RtlNtStatusToDosError (Status
);
2650 if (lpftLastWriteTime
!= NULL
)
2652 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2653 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2656 if (lpClass
!= NULL
)
2658 if (FullInfo
->ClassLength
> ClassLength
)
2660 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2664 RtlCopyMemory (lpClass
,
2666 FullInfo
->ClassLength
);
2667 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2668 lpClass
[*lpcbClass
] = 0;
2671 RtlFreeHeap (ProcessHeap
,
2677 CloseDefaultKey(KeyHandle
);
2683 /************************************************************************
2684 * RegQueryMultipleValuesA
2689 RegQueryMultipleValuesA (HKEY hKey
,
2696 DWORD maxBytes
= *ldwTotsize
;
2697 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2700 if (maxBytes
>= (1024*1024))
2701 return ERROR_TRANSFER_TOO_LONG
;
2705 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
2706 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2708 for (i
= 0; i
< num_vals
; i
++)
2710 val_list
[i
].ve_valuelen
= 0;
2711 ErrorCode
= RegQueryValueExA (hKey
,
2712 val_list
[i
].ve_valuename
,
2716 &val_list
[i
].ve_valuelen
);
2717 if (ErrorCode
!= ERROR_SUCCESS
)
2722 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2724 ErrorCode
= RegQueryValueExA (hKey
,
2725 val_list
[i
].ve_valuename
,
2727 &val_list
[i
].ve_type
,
2729 &val_list
[i
].ve_valuelen
);
2730 if (ErrorCode
!= ERROR_SUCCESS
)
2735 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2737 bufptr
+= val_list
[i
].ve_valuelen
;
2740 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2743 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2747 /************************************************************************
2748 * RegQueryMultipleValuesW
2753 RegQueryMultipleValuesW (HKEY hKey
,
2760 DWORD maxBytes
= *ldwTotsize
;
2761 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2764 if (maxBytes
>= (1024*1024))
2765 return ERROR_TRANSFER_TOO_LONG
;
2769 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2770 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2772 for (i
= 0; i
< num_vals
; i
++)
2774 val_list
[i
].ve_valuelen
= 0;
2775 ErrorCode
= RegQueryValueExW (hKey
,
2776 val_list
[i
].ve_valuename
,
2780 &val_list
[i
].ve_valuelen
);
2781 if (ErrorCode
!= ERROR_SUCCESS
)
2786 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2788 ErrorCode
= RegQueryValueExW (hKey
,
2789 val_list
[i
].ve_valuename
,
2791 &val_list
[i
].ve_type
,
2793 &val_list
[i
].ve_valuelen
);
2794 if (ErrorCode
!= ERROR_SUCCESS
)
2799 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2801 bufptr
+= val_list
[i
].ve_valuelen
;
2804 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2807 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2811 /************************************************************************
2817 RegQueryValueExW (HKEY hKey
,
2818 LPCWSTR lpValueName
,
2824 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2825 UNICODE_STRING ValueName
;
2830 LONG ErrorCode
= ERROR_SUCCESS
;
2831 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2833 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2834 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2836 Status
= MapDefaultKey (&KeyHandle
,
2838 if (!NT_SUCCESS(Status
))
2840 return RtlNtStatusToDosError (Status
);
2843 if (lpData
!= NULL
&& lpcbData
== NULL
)
2845 ErrorCode
= ERROR_INVALID_PARAMETER
;
2849 RtlInitUnicodeString (&ValueName
,
2851 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2852 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2855 if (ValueInfo
== NULL
)
2857 ErrorCode
= ERROR_OUTOFMEMORY
;
2861 Status
= NtQueryValueKey (KeyHandle
,
2863 KeyValuePartialInformation
,
2867 TRACE("Status 0x%X\n", Status
);
2868 if (Status
== STATUS_BUFFER_OVERFLOW
)
2870 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2872 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2874 else if (!NT_SUCCESS(Status
))
2876 ErrorCode
= RtlNtStatusToDosError (Status
);
2878 if (lpcbData
!= NULL
)
2880 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2886 *lpType
= ValueInfo
->Type
;
2889 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2891 RtlMoveMemory (lpData
,
2893 min(ValueInfo
->DataLength
, MaxCopy
));
2896 if ((ValueInfo
->Type
== REG_SZ
) ||
2897 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2898 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2900 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2902 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2905 if (lpcbData
!= NULL
)
2907 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2908 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
2913 if (lpcbData
!= NULL
)
2915 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2916 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
2920 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2922 RtlFreeHeap (ProcessHeap
,
2927 CloseDefaultKey(KeyHandle
);
2933 /************************************************************************
2939 RegQueryValueExA (HKEY hKey
,
2946 UNICODE_STRING ValueName
;
2947 UNICODE_STRING ValueData
;
2948 ANSI_STRING AnsiString
;
2953 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
2954 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2956 if (lpData
!= NULL
&& lpcbData
== NULL
)
2958 return ERROR_INVALID_PARAMETER
;
2963 ValueData
.Length
= 0;
2964 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
2965 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2967 ValueData
.MaximumLength
);
2968 if (!ValueData
.Buffer
)
2970 return ERROR_OUTOFMEMORY
;
2975 ValueData
.Buffer
= NULL
;
2976 ValueData
.Length
= 0;
2977 ValueData
.MaximumLength
= 0;
2980 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2981 (LPSTR
)lpValueName
);
2983 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
2984 ErrorCode
= RegQueryValueExW (hKey
,
2988 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
2990 TRACE("ErrorCode %lu\n", ErrorCode
);
2991 RtlFreeUnicodeString(&ValueName
);
2993 if (ErrorCode
== ERROR_SUCCESS
||
2994 ErrorCode
== ERROR_MORE_DATA
)
3001 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
3003 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3005 RtlInitAnsiString(&AnsiString
, NULL
);
3006 AnsiString
.Buffer
= (LPSTR
)lpData
;
3007 AnsiString
.MaximumLength
= *lpcbData
;
3008 ValueData
.Length
= Length
;
3009 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
3010 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
3012 Length
= Length
/ sizeof(WCHAR
);
3014 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3016 if (*lpcbData
< Length
)
3018 ErrorCode
= ERROR_MORE_DATA
;
3022 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
3026 if (lpcbData
!= NULL
)
3032 if (ValueData
.Buffer
!= NULL
)
3034 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
3041 /************************************************************************
3047 RegQueryValueA (HKEY hKey
,
3052 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3053 UNICODE_STRING SubKeyName
;
3054 UNICODE_STRING Value
;
3055 ANSI_STRING AnsiString
;
3059 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
3060 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3062 if (lpValue
!= NULL
&&
3065 return ERROR_INVALID_PARAMETER
;
3068 RtlInitUnicodeString (&SubKeyName
,
3070 RtlInitUnicodeString (&Value
,
3072 if (lpSubKey
!= NULL
&&
3073 strlen(lpSubKey
) != 0)
3075 RtlInitAnsiString (&AnsiString
,
3077 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3078 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3079 RtlAnsiStringToUnicodeString (&SubKeyName
,
3084 if (lpValue
!= NULL
)
3086 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
3087 Value
.MaximumLength
= ValueSize
;
3088 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3091 if (Value
.Buffer
== NULL
)
3093 return ERROR_OUTOFMEMORY
;
3101 ErrorCode
= RegQueryValueW (hKey
,
3102 (LPCWSTR
)SubKeyName
.Buffer
,
3105 if (ErrorCode
== ERROR_SUCCESS
)
3107 Value
.Length
= ValueSize
;
3108 RtlInitAnsiString (&AnsiString
,
3110 AnsiString
.Buffer
= lpValue
;
3111 AnsiString
.MaximumLength
= *lpcbValue
;
3112 RtlUnicodeStringToAnsiString (&AnsiString
,
3117 *lpcbValue
= ValueSize
;
3118 if (Value
.Buffer
!= NULL
)
3120 RtlFreeHeap (ProcessHeap
,
3129 /************************************************************************
3135 RegQueryValueW (HKEY hKey
,
3140 OBJECT_ATTRIBUTES ObjectAttributes
;
3141 UNICODE_STRING SubKeyString
;
3148 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
3149 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3151 Status
= MapDefaultKey (&KeyHandle
,
3153 if (!NT_SUCCESS(Status
))
3155 return RtlNtStatusToDosError (Status
);
3158 if (lpSubKey
!= NULL
&&
3159 wcslen(lpSubKey
) != 0)
3161 RtlInitUnicodeString (&SubKeyString
,
3163 InitializeObjectAttributes (&ObjectAttributes
,
3165 OBJ_CASE_INSENSITIVE
,
3168 Status
= NtOpenKey (&RealKey
,
3171 if (!NT_SUCCESS(Status
))
3173 ErrorCode
= RtlNtStatusToDosError (Status
);
3176 CloseRealKey
= TRUE
;
3181 CloseRealKey
= FALSE
;
3184 ErrorCode
= RegQueryValueExW (RealKey
,
3189 (LPDWORD
)lpcbValue
);
3196 CloseDefaultKey(KeyHandle
);
3202 /************************************************************************
3208 RegReplaceKeyA (HKEY hKey
,
3213 UNICODE_STRING SubKey
;
3214 UNICODE_STRING NewFile
;
3215 UNICODE_STRING OldFile
;
3218 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
3220 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
3222 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
3225 ErrorCode
= RegReplaceKeyW (hKey
,
3230 RtlFreeUnicodeString (&OldFile
);
3231 RtlFreeUnicodeString (&NewFile
);
3232 RtlFreeUnicodeString (&SubKey
);
3238 /************************************************************************
3244 RegReplaceKeyW (HKEY hKey
,
3249 OBJECT_ATTRIBUTES KeyObjectAttributes
;
3250 OBJECT_ATTRIBUTES NewObjectAttributes
;
3251 OBJECT_ATTRIBUTES OldObjectAttributes
;
3252 UNICODE_STRING SubKeyName
;
3253 UNICODE_STRING NewFileName
;
3254 UNICODE_STRING OldFileName
;
3255 BOOLEAN CloseRealKey
;
3256 HANDLE RealKeyHandle
;
3259 LONG ErrorCode
= ERROR_SUCCESS
;
3261 if (hKey
== HKEY_PERFORMANCE_DATA
)
3263 return ERROR_INVALID_HANDLE
;
3266 Status
= MapDefaultKey (&KeyHandle
,
3268 if (!NT_SUCCESS(Status
))
3270 return RtlNtStatusToDosError (Status
);
3273 /* Open the real key */
3274 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
3276 RtlInitUnicodeString (&SubKeyName
,
3278 InitializeObjectAttributes (&KeyObjectAttributes
,
3280 OBJ_CASE_INSENSITIVE
,
3283 Status
= NtOpenKey (&RealKeyHandle
,
3285 &KeyObjectAttributes
);
3286 if (!NT_SUCCESS(Status
))
3288 ErrorCode
= RtlNtStatusToDosError (Status
);
3291 CloseRealKey
= TRUE
;
3295 RealKeyHandle
= KeyHandle
;
3296 CloseRealKey
= FALSE
;
3299 /* Convert new file name */
3300 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
3307 NtClose (RealKeyHandle
);
3309 ErrorCode
= ERROR_INVALID_PARAMETER
;
3313 InitializeObjectAttributes (&NewObjectAttributes
,
3315 OBJ_CASE_INSENSITIVE
,
3319 /* Convert old file name */
3320 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
3325 RtlFreeUnicodeString (&NewFileName
);
3328 NtClose (RealKeyHandle
);
3330 ErrorCode
= ERROR_INVALID_PARAMETER
;
3334 InitializeObjectAttributes (&OldObjectAttributes
,
3336 OBJ_CASE_INSENSITIVE
,
3340 Status
= NtReplaceKey (&NewObjectAttributes
,
3342 &OldObjectAttributes
);
3344 RtlFreeUnicodeString (&OldFileName
);
3345 RtlFreeUnicodeString (&NewFileName
);
3349 NtClose (RealKeyHandle
);
3352 if (!NT_SUCCESS(Status
))
3354 return RtlNtStatusToDosError (Status
);
3358 CloseDefaultKey(KeyHandle
);
3364 /************************************************************************
3370 RegRestoreKeyA (HKEY hKey
,
3374 UNICODE_STRING FileName
;
3377 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3380 ErrorCode
= RegRestoreKeyW (hKey
,
3384 RtlFreeUnicodeString (&FileName
);
3390 /************************************************************************
3396 RegRestoreKeyW (HKEY hKey
,
3400 OBJECT_ATTRIBUTES ObjectAttributes
;
3401 IO_STATUS_BLOCK IoStatusBlock
;
3402 UNICODE_STRING FileName
;
3407 if (hKey
== HKEY_PERFORMANCE_DATA
)
3409 return ERROR_INVALID_HANDLE
;
3412 Status
= MapDefaultKey (&KeyHandle
,
3414 if (!NT_SUCCESS(Status
))
3416 return RtlNtStatusToDosError (Status
);
3419 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
3424 Status
= STATUS_INVALID_PARAMETER
;
3428 InitializeObjectAttributes (&ObjectAttributes
,
3430 OBJ_CASE_INSENSITIVE
,
3434 Status
= NtOpenFile (&FileHandle
,
3439 FILE_SYNCHRONOUS_IO_NONALERT
);
3440 RtlFreeUnicodeString (&FileName
);
3441 if (!NT_SUCCESS(Status
))
3446 Status
= NtRestoreKey (KeyHandle
,
3449 NtClose (FileHandle
);
3452 CloseDefaultKey(KeyHandle
);
3454 if (!NT_SUCCESS(Status
))
3456 return RtlNtStatusToDosError (Status
);
3459 return ERROR_SUCCESS
;
3463 /************************************************************************
3469 RegSaveKeyA (HKEY hKey
,
3471 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3473 UNICODE_STRING FileName
;
3476 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3478 ErrorCode
= RegSaveKeyW (hKey
,
3480 lpSecurityAttributes
);
3481 RtlFreeUnicodeString (&FileName
);
3487 /************************************************************************
3493 RegSaveKeyW (HKEY hKey
,
3495 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3497 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
3498 OBJECT_ATTRIBUTES ObjectAttributes
;
3499 UNICODE_STRING FileName
;
3500 IO_STATUS_BLOCK IoStatusBlock
;
3505 Status
= MapDefaultKey (&KeyHandle
,
3507 if (!NT_SUCCESS(Status
))
3509 return RtlNtStatusToDosError (Status
);
3512 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
3517 Status
= STATUS_INVALID_PARAMETER
;
3521 if (lpSecurityAttributes
!= NULL
)
3523 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
3526 InitializeObjectAttributes (&ObjectAttributes
,
3528 OBJ_CASE_INSENSITIVE
,
3530 SecurityDescriptor
);
3531 Status
= NtCreateFile (&FileHandle
,
3532 GENERIC_WRITE
| SYNCHRONIZE
,
3536 FILE_ATTRIBUTE_NORMAL
,
3539 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
3542 RtlFreeUnicodeString (&FileName
);
3543 if (!NT_SUCCESS(Status
))
3548 Status
= NtSaveKey (KeyHandle
,
3550 NtClose (FileHandle
);
3553 CloseDefaultKey(KeyHandle
);
3555 if (!NT_SUCCESS(Status
))
3557 return RtlNtStatusToDosError (Status
);
3560 return ERROR_SUCCESS
;
3564 /************************************************************************
3570 RegSetKeySecurity (HKEY hKey
,
3571 SECURITY_INFORMATION SecurityInformation
,
3572 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3577 if (hKey
== HKEY_PERFORMANCE_DATA
)
3579 return ERROR_INVALID_HANDLE
;
3582 Status
= MapDefaultKey (&KeyHandle
,
3584 if (!NT_SUCCESS(Status
))
3586 return RtlNtStatusToDosError (Status
);
3589 Status
= NtSetSecurityObject (KeyHandle
,
3590 SecurityInformation
,
3591 pSecurityDescriptor
);
3593 CloseDefaultKey(KeyHandle
);
3595 if (!NT_SUCCESS(Status
))
3597 return RtlNtStatusToDosError (Status
);
3600 return ERROR_SUCCESS
;
3604 /************************************************************************
3610 RegSetValueExA (HKEY hKey
,
3617 UNICODE_STRING ValueName
;
3619 ANSI_STRING AnsiString
;
3620 UNICODE_STRING Data
;
3625 if (lpValueName
!= NULL
&&
3626 strlen(lpValueName
) != 0)
3628 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3630 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3637 if (((dwType
== REG_SZ
) ||
3638 (dwType
== REG_MULTI_SZ
) ||
3639 (dwType
== REG_EXPAND_SZ
)) &&
3642 /* NT adds one if the caller forgot the NULL-termination character */
3643 if (lpData
[cbData
- 1] != '\0')
3648 RtlInitAnsiString (&AnsiString
,
3650 AnsiString
.Buffer
= (PSTR
)lpData
;
3651 AnsiString
.Length
= cbData
- 1;
3652 AnsiString
.MaximumLength
= cbData
;
3653 RtlAnsiStringToUnicodeString (&Data
,
3656 pData
= (LPBYTE
)Data
.Buffer
;
3657 DataSize
= cbData
* sizeof(WCHAR
);
3661 RtlInitUnicodeString (&Data
,
3663 pData
= (LPBYTE
)lpData
;
3667 ErrorCode
= RegSetValueExW (hKey
,
3673 if (pValueName
!= NULL
)
3675 RtlFreeHeap (ProcessHeap
,
3680 if (Data
.Buffer
!= NULL
)
3682 RtlFreeHeap (ProcessHeap
,
3691 /************************************************************************
3697 RegSetValueExW (HKEY hKey
,
3698 LPCWSTR lpValueName
,
3704 UNICODE_STRING ValueName
;
3705 PUNICODE_STRING pValueName
;
3709 Status
= MapDefaultKey (&KeyHandle
,
3711 if (!NT_SUCCESS(Status
))
3713 return RtlNtStatusToDosError (Status
);
3716 if (lpValueName
!= NULL
)
3718 RtlInitUnicodeString (&ValueName
,
3723 RtlInitUnicodeString (&ValueName
, L
"");
3725 pValueName
= &ValueName
;
3727 if (((dwType
== REG_SZ
) ||
3728 (dwType
== REG_MULTI_SZ
) ||
3729 (dwType
== REG_EXPAND_SZ
)) &&
3730 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
3732 /* NT adds one if the caller forgot the NULL-termination character */
3733 cbData
+= sizeof(WCHAR
);
3736 Status
= NtSetValueKey (KeyHandle
,
3743 CloseDefaultKey(KeyHandle
);
3745 if (!NT_SUCCESS(Status
))
3747 return RtlNtStatusToDosError (Status
);
3750 return ERROR_SUCCESS
;
3754 /************************************************************************
3760 RegSetValueA (HKEY hKey
,
3769 if (dwType
!= REG_SZ
)
3771 return ERROR_INVALID_PARAMETER
;
3774 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
3776 ret
= RegCreateKeyA(hKey
,
3780 if (ret
!= ERROR_SUCCESS
)
3788 ret
= RegSetValueExA(hSubKey
,
3792 (CONST BYTE
*)lpData
,
3793 strlen(lpData
) + 1);
3795 if (hSubKey
!= hKey
)
3797 RegCloseKey(hSubKey
);
3804 /************************************************************************
3810 RegSetValueW (HKEY hKey
,
3816 OBJECT_ATTRIBUTES ObjectAttributes
;
3817 UNICODE_STRING SubKeyString
;
3824 Status
= MapDefaultKey (&KeyHandle
,
3826 if (!NT_SUCCESS(Status
))
3828 return RtlNtStatusToDosError (Status
);
3831 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3833 RtlInitUnicodeString (&SubKeyString
,
3835 InitializeObjectAttributes (&ObjectAttributes
,
3837 OBJ_CASE_INSENSITIVE
,
3840 Status
= NtOpenKey (&RealKey
,
3843 if (!NT_SUCCESS(Status
))
3845 ErrorCode
= RtlNtStatusToDosError (Status
);
3848 CloseRealKey
= TRUE
;
3853 CloseRealKey
= FALSE
;
3856 ErrorCode
= RegSetValueExW (RealKey
,
3862 if (CloseRealKey
== TRUE
)
3868 CloseDefaultKey(KeyHandle
);
3874 /************************************************************************
3880 RegUnLoadKeyA (HKEY hKey
,
3883 UNICODE_STRING KeyName
;
3886 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3889 ErrorCode
= RegUnLoadKeyW (hKey
,
3892 RtlFreeUnicodeString (&KeyName
);
3898 /************************************************************************
3904 RegUnLoadKeyW (HKEY hKey
,
3907 OBJECT_ATTRIBUTES ObjectAttributes
;
3908 UNICODE_STRING KeyName
;
3912 if (hKey
== HKEY_PERFORMANCE_DATA
)
3914 return ERROR_INVALID_HANDLE
;
3917 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3918 if (!NT_SUCCESS(Status
))
3920 return RtlNtStatusToDosError (Status
);
3923 RtlInitUnicodeString (&KeyName
,
3926 InitializeObjectAttributes (&ObjectAttributes
,
3928 OBJ_CASE_INSENSITIVE
,
3932 Status
= NtUnloadKey (&ObjectAttributes
);
3934 CloseDefaultKey(KeyHandle
);
3936 if (!NT_SUCCESS(Status
))
3938 return RtlNtStatusToDosError (Status
);
3941 return ERROR_SUCCESS
;
3945 /************************************************************************
3951 RegLoadMUIStringW(IN HKEY hKey
,
3952 IN LPCWSTR pszValue OPTIONAL
,
3953 OUT LPWSTR pszOutBuf
,
3956 IN LPCWSTR pszDirectory OPTIONAL
)
3958 DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
3959 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
3960 return ERROR_CALL_NOT_IMPLEMENTED
;
3964 /************************************************************************
3970 RegLoadMUIStringA(IN HKEY hKey
,
3971 IN LPCSTR pszValue OPTIONAL
,
3972 OUT LPSTR pszOutBuf
,
3975 IN LPCSTR pszDirectory OPTIONAL
)
3977 DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
3978 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
3979 return ERROR_CALL_NOT_IMPLEMENTED
;