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
;
2313 /* check parameters */
2314 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
2316 return ERROR_INVALID_PARAMETER
;
2320 * Get the user sid from the token
2324 /* determine how much memory we need */
2325 Status
= NtQueryInformationToken(hToken
,
2330 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2332 /* NOTE - as opposed to all other registry functions windows does indeed
2333 change the last error code in case the caller supplied a invalid
2334 handle for example! */
2335 return RtlNtStatusToDosError (Status
);
2338 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2341 if (TokenUserData
== NULL
)
2343 return ERROR_NOT_ENOUGH_MEMORY
;
2346 /* attempt to read the information */
2347 Status
= NtQueryInformationToken(hToken
,
2352 if (!NT_SUCCESS(Status
))
2354 RtlFreeHeap(ProcessHeap
,
2357 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2359 /* the information appears to have changed?! try again */
2363 /* NOTE - as opposed to all other registry functions windows does indeed
2364 change the last error code in case the caller supplied a invalid
2365 handle for example! */
2366 return RtlNtStatusToDosError (Status
);
2370 * Build the absolute path for the user's registry in the form
2371 * "\Registry\User\<SID>_Classes"
2373 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2374 TokenUserData
->User
.Sid
,
2377 /* we don't need the user data anymore, free it */
2378 RtlFreeHeap(ProcessHeap
,
2382 if (!NT_SUCCESS(Status
))
2384 return RtlNtStatusToDosError (Status
);
2387 /* allocate enough memory for the entire key string */
2388 UserClassesKeyRoot
.Length
= 0;
2389 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
2390 sizeof(UserClassesKeyPrefix
) +
2391 sizeof(UserClassesKeySuffix
);
2392 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
2394 UserClassesKeyRoot
.MaximumLength
);
2395 if (UserClassesKeyRoot
.Buffer
== NULL
)
2397 RtlFreeUnicodeString(&UserSidString
);
2398 return RtlNtStatusToDosError (Status
);
2401 /* build the string */
2402 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2403 UserClassesKeyPrefix
);
2404 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
2406 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2407 UserClassesKeySuffix
);
2409 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
2415 InitializeObjectAttributes (&ObjectAttributes
,
2416 &UserClassesKeyRoot
,
2417 OBJ_CASE_INSENSITIVE
,
2421 Status
= NtOpenKey((PHANDLE
)phkResult
,
2425 RtlFreeUnicodeString(&UserSidString
);
2426 RtlFreeUnicodeString(&UserClassesKeyRoot
);
2428 if (!NT_SUCCESS(Status
))
2430 return RtlNtStatusToDosError (Status
);
2433 return ERROR_SUCCESS
;
2437 /************************************************************************
2443 RegQueryInfoKeyA (HKEY hKey
,
2448 LPDWORD lpcbMaxSubKeyLen
,
2449 LPDWORD lpcbMaxClassLen
,
2451 LPDWORD lpcbMaxValueNameLen
,
2452 LPDWORD lpcbMaxValueLen
,
2453 LPDWORD lpcbSecurityDescriptor
,
2454 PFILETIME lpftLastWriteTime
)
2456 WCHAR ClassName
[MAX_PATH
];
2457 UNICODE_STRING UnicodeString
;
2458 ANSI_STRING AnsiString
;
2461 RtlInitUnicodeString (&UnicodeString
,
2463 if (lpClass
!= NULL
)
2465 UnicodeString
.Buffer
= &ClassName
[0];
2466 UnicodeString
.MaximumLength
= sizeof(ClassName
);
2467 AnsiString
.MaximumLength
= *lpcbClass
;
2470 ErrorCode
= RegQueryInfoKeyW (hKey
,
2471 UnicodeString
.Buffer
,
2478 lpcbMaxValueNameLen
,
2480 lpcbSecurityDescriptor
,
2482 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
2484 AnsiString
.Buffer
= lpClass
;
2485 AnsiString
.Length
= 0;
2486 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
2487 RtlUnicodeStringToAnsiString (&AnsiString
,
2490 *lpcbClass
= AnsiString
.Length
;
2491 lpClass
[AnsiString
.Length
] = 0;
2498 /************************************************************************
2504 RegQueryInfoKeyW (HKEY hKey
,
2509 LPDWORD lpcbMaxSubKeyLen
,
2510 LPDWORD lpcbMaxClassLen
,
2512 LPDWORD lpcbMaxValueNameLen
,
2513 LPDWORD lpcbMaxValueLen
,
2514 LPDWORD lpcbSecurityDescriptor
,
2515 PFILETIME lpftLastWriteTime
)
2517 KEY_FULL_INFORMATION FullInfoBuffer
;
2518 PKEY_FULL_INFORMATION FullInfo
;
2520 ULONG ClassLength
= 0;
2524 LONG ErrorCode
= ERROR_SUCCESS
;
2526 if ((lpClass
) && (!lpcbClass
))
2528 return ERROR_INVALID_PARAMETER
;
2531 Status
= MapDefaultKey (&KeyHandle
,
2533 if (!NT_SUCCESS(Status
))
2535 return RtlNtStatusToDosError (Status
);
2538 if (lpClass
!= NULL
)
2542 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2549 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2550 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2553 if (FullInfo
== NULL
)
2555 ErrorCode
= ERROR_OUTOFMEMORY
;
2559 FullInfo
->ClassLength
= ClassLength
;
2563 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2564 FullInfo
= &FullInfoBuffer
;
2565 FullInfo
->ClassLength
= 0;
2567 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2569 Status
= NtQueryKey (KeyHandle
,
2574 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
2575 if (!NT_SUCCESS(Status
))
2577 if (lpClass
!= NULL
)
2579 RtlFreeHeap (ProcessHeap
,
2584 ErrorCode
= RtlNtStatusToDosError (Status
);
2588 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
2589 if (lpcSubKeys
!= NULL
)
2591 *lpcSubKeys
= FullInfo
->SubKeys
;
2594 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2595 if (lpcbMaxSubKeyLen
!= NULL
)
2597 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2600 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2601 if (lpcbMaxClassLen
!= NULL
)
2603 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2606 TRACE("Values %lu\n", FullInfo
->Values
);
2607 if (lpcValues
!= NULL
)
2609 *lpcValues
= FullInfo
->Values
;
2612 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2613 if (lpcbMaxValueNameLen
!= NULL
)
2615 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2618 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2619 if (lpcbMaxValueLen
!= NULL
)
2621 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2624 if (lpcbSecurityDescriptor
!= NULL
)
2626 Status
= NtQuerySecurityObject(KeyHandle
,
2627 OWNER_SECURITY_INFORMATION
|
2628 GROUP_SECURITY_INFORMATION
|
2629 DACL_SECURITY_INFORMATION
,
2632 lpcbSecurityDescriptor
);
2633 if (!NT_SUCCESS(Status
))
2635 if (lpClass
!= NULL
)
2637 RtlFreeHeap(ProcessHeap
,
2642 ErrorCode
= RtlNtStatusToDosError (Status
);
2647 if (lpftLastWriteTime
!= NULL
)
2649 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2650 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2653 if (lpClass
!= NULL
)
2655 if (FullInfo
->ClassLength
> ClassLength
)
2657 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2661 RtlCopyMemory (lpClass
,
2663 FullInfo
->ClassLength
);
2664 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2665 lpClass
[*lpcbClass
] = 0;
2668 RtlFreeHeap (ProcessHeap
,
2674 CloseDefaultKey(KeyHandle
);
2680 /************************************************************************
2681 * RegQueryMultipleValuesA
2686 RegQueryMultipleValuesA (HKEY hKey
,
2693 DWORD maxBytes
= *ldwTotsize
;
2694 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2697 if (maxBytes
>= (1024*1024))
2698 return ERROR_TRANSFER_TOO_LONG
;
2702 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
2703 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2705 for (i
= 0; i
< num_vals
; i
++)
2707 val_list
[i
].ve_valuelen
= 0;
2708 ErrorCode
= RegQueryValueExA (hKey
,
2709 val_list
[i
].ve_valuename
,
2713 &val_list
[i
].ve_valuelen
);
2714 if (ErrorCode
!= ERROR_SUCCESS
)
2719 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2721 ErrorCode
= RegQueryValueExA (hKey
,
2722 val_list
[i
].ve_valuename
,
2724 &val_list
[i
].ve_type
,
2726 &val_list
[i
].ve_valuelen
);
2727 if (ErrorCode
!= ERROR_SUCCESS
)
2732 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2734 bufptr
+= val_list
[i
].ve_valuelen
;
2737 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2740 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2744 /************************************************************************
2745 * RegQueryMultipleValuesW
2750 RegQueryMultipleValuesW (HKEY hKey
,
2757 DWORD maxBytes
= *ldwTotsize
;
2758 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2761 if (maxBytes
>= (1024*1024))
2762 return ERROR_TRANSFER_TOO_LONG
;
2766 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2767 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2769 for (i
= 0; i
< num_vals
; i
++)
2771 val_list
[i
].ve_valuelen
= 0;
2772 ErrorCode
= RegQueryValueExW (hKey
,
2773 val_list
[i
].ve_valuename
,
2777 &val_list
[i
].ve_valuelen
);
2778 if (ErrorCode
!= ERROR_SUCCESS
)
2783 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2785 ErrorCode
= RegQueryValueExW (hKey
,
2786 val_list
[i
].ve_valuename
,
2788 &val_list
[i
].ve_type
,
2790 &val_list
[i
].ve_valuelen
);
2791 if (ErrorCode
!= ERROR_SUCCESS
)
2796 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2798 bufptr
+= val_list
[i
].ve_valuelen
;
2801 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2804 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2808 /************************************************************************
2814 RegQueryValueExW (HKEY hKey
,
2815 LPCWSTR lpValueName
,
2821 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2822 UNICODE_STRING ValueName
;
2827 LONG ErrorCode
= ERROR_SUCCESS
;
2828 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2830 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2831 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2833 Status
= MapDefaultKey (&KeyHandle
,
2835 if (!NT_SUCCESS(Status
))
2837 return RtlNtStatusToDosError (Status
);
2840 if (lpData
!= NULL
&& lpcbData
== NULL
)
2842 ErrorCode
= ERROR_INVALID_PARAMETER
;
2846 RtlInitUnicodeString (&ValueName
,
2848 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2849 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2852 if (ValueInfo
== NULL
)
2854 ErrorCode
= ERROR_OUTOFMEMORY
;
2858 Status
= NtQueryValueKey (KeyHandle
,
2860 KeyValuePartialInformation
,
2864 TRACE("Status 0x%X\n", Status
);
2865 if (Status
== STATUS_BUFFER_OVERFLOW
)
2867 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2869 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2871 else if (!NT_SUCCESS(Status
))
2873 ErrorCode
= RtlNtStatusToDosError (Status
);
2875 if (lpcbData
!= NULL
)
2877 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2883 *lpType
= ValueInfo
->Type
;
2886 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2888 RtlMoveMemory (lpData
,
2890 min(ValueInfo
->DataLength
, MaxCopy
));
2893 if ((ValueInfo
->Type
== REG_SZ
) ||
2894 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2895 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2897 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2899 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2902 if (lpcbData
!= NULL
)
2904 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2905 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
2910 if (lpcbData
!= NULL
)
2912 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2913 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
2917 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2919 RtlFreeHeap (ProcessHeap
,
2924 CloseDefaultKey(KeyHandle
);
2930 /************************************************************************
2936 RegQueryValueExA (HKEY hKey
,
2943 UNICODE_STRING ValueName
;
2944 UNICODE_STRING ValueData
;
2945 ANSI_STRING AnsiString
;
2950 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
2951 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2953 if (lpData
!= NULL
&& lpcbData
== NULL
)
2955 return ERROR_INVALID_PARAMETER
;
2960 ValueData
.Length
= 0;
2961 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
2962 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2964 ValueData
.MaximumLength
);
2965 if (!ValueData
.Buffer
)
2967 return ERROR_OUTOFMEMORY
;
2972 ValueData
.Buffer
= NULL
;
2973 ValueData
.Length
= 0;
2974 ValueData
.MaximumLength
= 0;
2977 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2978 (LPSTR
)lpValueName
);
2980 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
2981 ErrorCode
= RegQueryValueExW (hKey
,
2985 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
2987 TRACE("ErrorCode %lu\n", ErrorCode
);
2988 RtlFreeUnicodeString(&ValueName
);
2990 if (ErrorCode
== ERROR_SUCCESS
||
2991 ErrorCode
== ERROR_MORE_DATA
)
2998 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
3000 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3002 RtlInitAnsiString(&AnsiString
, NULL
);
3003 AnsiString
.Buffer
= (LPSTR
)lpData
;
3004 AnsiString
.MaximumLength
= *lpcbData
;
3005 ValueData
.Length
= Length
;
3006 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
3007 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
3009 Length
= Length
/ sizeof(WCHAR
);
3011 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
3013 if (*lpcbData
< Length
)
3015 ErrorCode
= ERROR_MORE_DATA
;
3019 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
3023 if (lpcbData
!= NULL
)
3029 if (ValueData
.Buffer
!= NULL
)
3031 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
3038 /************************************************************************
3044 RegQueryValueA (HKEY hKey
,
3049 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3050 UNICODE_STRING SubKeyName
;
3051 UNICODE_STRING Value
;
3052 ANSI_STRING AnsiString
;
3056 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
3057 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3059 if (lpValue
!= NULL
&&
3062 return ERROR_INVALID_PARAMETER
;
3065 RtlInitUnicodeString (&SubKeyName
,
3067 RtlInitUnicodeString (&Value
,
3069 if (lpSubKey
!= NULL
&&
3070 strlen(lpSubKey
) != 0)
3072 RtlInitAnsiString (&AnsiString
,
3074 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3075 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3076 RtlAnsiStringToUnicodeString (&SubKeyName
,
3081 if (lpValue
!= NULL
)
3083 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
3084 Value
.MaximumLength
= ValueSize
;
3085 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3088 if (Value
.Buffer
== NULL
)
3090 return ERROR_OUTOFMEMORY
;
3098 ErrorCode
= RegQueryValueW (hKey
,
3099 (LPCWSTR
)SubKeyName
.Buffer
,
3102 if (ErrorCode
== ERROR_SUCCESS
)
3104 Value
.Length
= ValueSize
;
3105 RtlInitAnsiString (&AnsiString
,
3107 AnsiString
.Buffer
= lpValue
;
3108 AnsiString
.MaximumLength
= *lpcbValue
;
3109 RtlUnicodeStringToAnsiString (&AnsiString
,
3114 *lpcbValue
= ValueSize
;
3115 if (Value
.Buffer
!= NULL
)
3117 RtlFreeHeap (ProcessHeap
,
3126 /************************************************************************
3132 RegQueryValueW (HKEY hKey
,
3137 OBJECT_ATTRIBUTES ObjectAttributes
;
3138 UNICODE_STRING SubKeyString
;
3145 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
3146 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
3148 Status
= MapDefaultKey (&KeyHandle
,
3150 if (!NT_SUCCESS(Status
))
3152 return RtlNtStatusToDosError (Status
);
3155 if (lpSubKey
!= NULL
&&
3156 wcslen(lpSubKey
) != 0)
3158 RtlInitUnicodeString (&SubKeyString
,
3160 InitializeObjectAttributes (&ObjectAttributes
,
3162 OBJ_CASE_INSENSITIVE
,
3165 Status
= NtOpenKey (&RealKey
,
3168 if (!NT_SUCCESS(Status
))
3170 ErrorCode
= RtlNtStatusToDosError (Status
);
3173 CloseRealKey
= TRUE
;
3178 CloseRealKey
= FALSE
;
3181 ErrorCode
= RegQueryValueExW (RealKey
,
3186 (LPDWORD
)lpcbValue
);
3193 CloseDefaultKey(KeyHandle
);
3199 /************************************************************************
3205 RegReplaceKeyA (HKEY hKey
,
3210 UNICODE_STRING SubKey
;
3211 UNICODE_STRING NewFile
;
3212 UNICODE_STRING OldFile
;
3215 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
3217 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
3219 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
3222 ErrorCode
= RegReplaceKeyW (hKey
,
3227 RtlFreeUnicodeString (&OldFile
);
3228 RtlFreeUnicodeString (&NewFile
);
3229 RtlFreeUnicodeString (&SubKey
);
3235 /************************************************************************
3241 RegReplaceKeyW (HKEY hKey
,
3246 OBJECT_ATTRIBUTES KeyObjectAttributes
;
3247 OBJECT_ATTRIBUTES NewObjectAttributes
;
3248 OBJECT_ATTRIBUTES OldObjectAttributes
;
3249 UNICODE_STRING SubKeyName
;
3250 UNICODE_STRING NewFileName
;
3251 UNICODE_STRING OldFileName
;
3252 BOOLEAN CloseRealKey
;
3253 HANDLE RealKeyHandle
;
3256 LONG ErrorCode
= ERROR_SUCCESS
;
3258 if (hKey
== HKEY_PERFORMANCE_DATA
)
3260 return ERROR_INVALID_HANDLE
;
3263 Status
= MapDefaultKey (&KeyHandle
,
3265 if (!NT_SUCCESS(Status
))
3267 return RtlNtStatusToDosError (Status
);
3270 /* Open the real key */
3271 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
3273 RtlInitUnicodeString (&SubKeyName
,
3275 InitializeObjectAttributes (&KeyObjectAttributes
,
3277 OBJ_CASE_INSENSITIVE
,
3280 Status
= NtOpenKey (&RealKeyHandle
,
3282 &KeyObjectAttributes
);
3283 if (!NT_SUCCESS(Status
))
3285 ErrorCode
= RtlNtStatusToDosError (Status
);
3288 CloseRealKey
= TRUE
;
3292 RealKeyHandle
= KeyHandle
;
3293 CloseRealKey
= FALSE
;
3296 /* Convert new file name */
3297 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
3304 NtClose (RealKeyHandle
);
3306 ErrorCode
= ERROR_INVALID_PARAMETER
;
3310 InitializeObjectAttributes (&NewObjectAttributes
,
3312 OBJ_CASE_INSENSITIVE
,
3316 /* Convert old file name */
3317 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
3322 RtlFreeUnicodeString (&NewFileName
);
3325 NtClose (RealKeyHandle
);
3327 ErrorCode
= ERROR_INVALID_PARAMETER
;
3331 InitializeObjectAttributes (&OldObjectAttributes
,
3333 OBJ_CASE_INSENSITIVE
,
3337 Status
= NtReplaceKey (&NewObjectAttributes
,
3339 &OldObjectAttributes
);
3341 RtlFreeUnicodeString (&OldFileName
);
3342 RtlFreeUnicodeString (&NewFileName
);
3346 NtClose (RealKeyHandle
);
3349 if (!NT_SUCCESS(Status
))
3351 return RtlNtStatusToDosError (Status
);
3355 CloseDefaultKey(KeyHandle
);
3361 /************************************************************************
3367 RegRestoreKeyA (HKEY hKey
,
3371 UNICODE_STRING FileName
;
3374 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3377 ErrorCode
= RegRestoreKeyW (hKey
,
3381 RtlFreeUnicodeString (&FileName
);
3387 /************************************************************************
3393 RegRestoreKeyW (HKEY hKey
,
3397 OBJECT_ATTRIBUTES ObjectAttributes
;
3398 IO_STATUS_BLOCK IoStatusBlock
;
3399 UNICODE_STRING FileName
;
3404 if (hKey
== HKEY_PERFORMANCE_DATA
)
3406 return ERROR_INVALID_HANDLE
;
3409 Status
= MapDefaultKey (&KeyHandle
,
3411 if (!NT_SUCCESS(Status
))
3413 return RtlNtStatusToDosError (Status
);
3416 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
3421 Status
= STATUS_INVALID_PARAMETER
;
3425 InitializeObjectAttributes (&ObjectAttributes
,
3427 OBJ_CASE_INSENSITIVE
,
3431 Status
= NtOpenFile (&FileHandle
,
3436 FILE_SYNCHRONOUS_IO_NONALERT
);
3437 RtlFreeUnicodeString (&FileName
);
3438 if (!NT_SUCCESS(Status
))
3443 Status
= NtRestoreKey (KeyHandle
,
3446 NtClose (FileHandle
);
3449 CloseDefaultKey(KeyHandle
);
3451 if (!NT_SUCCESS(Status
))
3453 return RtlNtStatusToDosError (Status
);
3456 return ERROR_SUCCESS
;
3460 /************************************************************************
3466 RegSaveKeyA (HKEY hKey
,
3468 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3470 UNICODE_STRING FileName
;
3473 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3475 ErrorCode
= RegSaveKeyW (hKey
,
3477 lpSecurityAttributes
);
3478 RtlFreeUnicodeString (&FileName
);
3484 /************************************************************************
3490 RegSaveKeyW (HKEY hKey
,
3492 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3494 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
3495 OBJECT_ATTRIBUTES ObjectAttributes
;
3496 UNICODE_STRING FileName
;
3497 IO_STATUS_BLOCK IoStatusBlock
;
3502 Status
= MapDefaultKey (&KeyHandle
,
3504 if (!NT_SUCCESS(Status
))
3506 return RtlNtStatusToDosError (Status
);
3509 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
3514 Status
= STATUS_INVALID_PARAMETER
;
3518 if (lpSecurityAttributes
!= NULL
)
3520 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
3523 InitializeObjectAttributes (&ObjectAttributes
,
3525 OBJ_CASE_INSENSITIVE
,
3527 SecurityDescriptor
);
3528 Status
= NtCreateFile (&FileHandle
,
3529 GENERIC_WRITE
| SYNCHRONIZE
,
3533 FILE_ATTRIBUTE_NORMAL
,
3536 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
3539 RtlFreeUnicodeString (&FileName
);
3540 if (!NT_SUCCESS(Status
))
3545 Status
= NtSaveKey (KeyHandle
,
3547 NtClose (FileHandle
);
3550 CloseDefaultKey(KeyHandle
);
3552 if (!NT_SUCCESS(Status
))
3554 return RtlNtStatusToDosError (Status
);
3557 return ERROR_SUCCESS
;
3561 /************************************************************************
3567 RegSetKeySecurity (HKEY hKey
,
3568 SECURITY_INFORMATION SecurityInformation
,
3569 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3574 if (hKey
== HKEY_PERFORMANCE_DATA
)
3576 return ERROR_INVALID_HANDLE
;
3579 Status
= MapDefaultKey (&KeyHandle
,
3581 if (!NT_SUCCESS(Status
))
3583 return RtlNtStatusToDosError (Status
);
3586 Status
= NtSetSecurityObject (KeyHandle
,
3587 SecurityInformation
,
3588 pSecurityDescriptor
);
3590 CloseDefaultKey(KeyHandle
);
3592 if (!NT_SUCCESS(Status
))
3594 return RtlNtStatusToDosError (Status
);
3597 return ERROR_SUCCESS
;
3601 /************************************************************************
3607 RegSetValueExA (HKEY hKey
,
3614 UNICODE_STRING ValueName
;
3616 ANSI_STRING AnsiString
;
3617 UNICODE_STRING Data
;
3622 if (lpValueName
!= NULL
&&
3623 strlen(lpValueName
) != 0)
3625 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3627 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3634 if (((dwType
== REG_SZ
) ||
3635 (dwType
== REG_MULTI_SZ
) ||
3636 (dwType
== REG_EXPAND_SZ
)) &&
3639 /* NT adds one if the caller forgot the NULL-termination character */
3640 if (lpData
[cbData
- 1] != '\0')
3645 RtlInitAnsiString (&AnsiString
,
3647 AnsiString
.Buffer
= (PSTR
)lpData
;
3648 AnsiString
.Length
= cbData
- 1;
3649 AnsiString
.MaximumLength
= cbData
;
3650 RtlAnsiStringToUnicodeString (&Data
,
3653 pData
= (LPBYTE
)Data
.Buffer
;
3654 DataSize
= cbData
* sizeof(WCHAR
);
3658 RtlInitUnicodeString (&Data
,
3660 pData
= (LPBYTE
)lpData
;
3664 ErrorCode
= RegSetValueExW (hKey
,
3670 if (pValueName
!= NULL
)
3672 RtlFreeHeap (ProcessHeap
,
3677 if (Data
.Buffer
!= NULL
)
3679 RtlFreeHeap (ProcessHeap
,
3688 /************************************************************************
3694 RegSetValueExW (HKEY hKey
,
3695 LPCWSTR lpValueName
,
3701 UNICODE_STRING ValueName
;
3702 PUNICODE_STRING pValueName
;
3706 Status
= MapDefaultKey (&KeyHandle
,
3708 if (!NT_SUCCESS(Status
))
3710 return RtlNtStatusToDosError (Status
);
3713 if (lpValueName
!= NULL
)
3715 RtlInitUnicodeString (&ValueName
,
3720 RtlInitUnicodeString (&ValueName
, L
"");
3722 pValueName
= &ValueName
;
3724 if (((dwType
== REG_SZ
) ||
3725 (dwType
== REG_MULTI_SZ
) ||
3726 (dwType
== REG_EXPAND_SZ
)) &&
3727 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
3729 /* NT adds one if the caller forgot the NULL-termination character */
3730 cbData
+= sizeof(WCHAR
);
3733 Status
= NtSetValueKey (KeyHandle
,
3740 CloseDefaultKey(KeyHandle
);
3742 if (!NT_SUCCESS(Status
))
3744 return RtlNtStatusToDosError (Status
);
3747 return ERROR_SUCCESS
;
3751 /************************************************************************
3757 RegSetValueA (HKEY hKey
,
3766 if (dwType
!= REG_SZ
)
3768 return ERROR_INVALID_PARAMETER
;
3771 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
3773 ret
= RegCreateKeyA(hKey
,
3777 if (ret
!= ERROR_SUCCESS
)
3785 ret
= RegSetValueExA(hSubKey
,
3789 (CONST BYTE
*)lpData
,
3790 strlen(lpData
) + 1);
3792 if (hSubKey
!= hKey
)
3794 RegCloseKey(hSubKey
);
3801 /************************************************************************
3807 RegSetValueW (HKEY hKey
,
3813 OBJECT_ATTRIBUTES ObjectAttributes
;
3814 UNICODE_STRING SubKeyString
;
3821 Status
= MapDefaultKey (&KeyHandle
,
3823 if (!NT_SUCCESS(Status
))
3825 return RtlNtStatusToDosError (Status
);
3828 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3830 RtlInitUnicodeString (&SubKeyString
,
3832 InitializeObjectAttributes (&ObjectAttributes
,
3834 OBJ_CASE_INSENSITIVE
,
3837 Status
= NtOpenKey (&RealKey
,
3840 if (!NT_SUCCESS(Status
))
3842 ErrorCode
= RtlNtStatusToDosError (Status
);
3845 CloseRealKey
= TRUE
;
3850 CloseRealKey
= FALSE
;
3853 ErrorCode
= RegSetValueExW (RealKey
,
3859 if (CloseRealKey
== TRUE
)
3865 CloseDefaultKey(KeyHandle
);
3871 /************************************************************************
3877 RegUnLoadKeyA (HKEY hKey
,
3880 UNICODE_STRING KeyName
;
3883 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3886 ErrorCode
= RegUnLoadKeyW (hKey
,
3889 RtlFreeUnicodeString (&KeyName
);
3895 /************************************************************************
3901 RegUnLoadKeyW (HKEY hKey
,
3904 OBJECT_ATTRIBUTES ObjectAttributes
;
3905 UNICODE_STRING KeyName
;
3909 if (hKey
== HKEY_PERFORMANCE_DATA
)
3911 return ERROR_INVALID_HANDLE
;
3914 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3915 if (!NT_SUCCESS(Status
))
3917 return RtlNtStatusToDosError (Status
);
3920 RtlInitUnicodeString (&KeyName
,
3923 InitializeObjectAttributes (&ObjectAttributes
,
3925 OBJ_CASE_INSENSITIVE
,
3929 Status
= NtUnloadKey (&ObjectAttributes
);
3931 CloseDefaultKey(KeyHandle
);
3933 if (!NT_SUCCESS(Status
))
3935 return RtlNtStatusToDosError (Status
);
3938 return ERROR_SUCCESS
;
3942 /************************************************************************
3948 RegLoadMUIStringW(IN HKEY hKey
,
3949 IN LPCWSTR pszValue OPTIONAL
,
3950 OUT LPWSTR pszOutBuf
,
3953 IN LPCWSTR pszDirectory OPTIONAL
)
3955 DPRINT1("RegLoadMUIStringW(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
3956 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
3957 return ERROR_CALL_NOT_IMPLEMENTED
;
3961 /************************************************************************
3967 RegLoadMUIStringA(IN HKEY hKey
,
3968 IN LPCSTR pszValue OPTIONAL
,
3969 OUT LPSTR pszOutBuf
,
3972 IN LPCSTR pszDirectory OPTIONAL
)
3974 DPRINT1("RegLoadMUIStringA(0x%p, 0x%p, 0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
3975 hKey
, pszValue
, pszOutBuf
, cbOutBuf
, Reserved
, pszDirectory
);
3976 return ERROR_CALL_NOT_IMPLEMENTED
;