3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/reg/reg.c
6 * PURPOSE: Registry functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
11 * 20050502 Fireball imported some stuff from WINE
14 /* INCLUDES *****************************************************************/
18 #include <wine/debug.h>
20 /* DEFINES ******************************************************************/
22 #define MAX_DEFAULT_HANDLES 6
23 #define REG_MAX_NAME_SIZE 256
24 #define REG_MAX_DATA_SIZE 2048
26 /* FIXME: should go into msvcrt.h header? */
27 #define offsetof(s,m) (size_t)&(((s*)NULL)->m)
29 /* GLOBALS ******************************************************************/
31 static RTL_CRITICAL_SECTION HandleTableCS
;
32 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
33 static HANDLE ProcessHeap
;
35 /* PROTOTYPES ***************************************************************/
37 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
38 static VOID
CloseDefaultKeys(VOID
);
40 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
41 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
42 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
43 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
46 /* FUNCTIONS ****************************************************************/
47 /* check if value type needs string conversion (Ansi<->Unicode) */
48 inline static int is_string( DWORD type
)
50 return (type
== REG_SZ
) || (type
== REG_EXPAND_SZ
) || (type
== REG_MULTI_SZ
);
53 /************************************************************************
54 * RegInitDefaultHandles
59 TRACE("RegInitialize()\n");
61 ProcessHeap
= RtlGetProcessHeap();
62 RtlZeroMemory (DefaultHandleTable
,
63 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
64 RtlInitializeCriticalSection (&HandleTableCS
);
70 /************************************************************************
76 TRACE("RegCleanup()\n");
79 RtlDeleteCriticalSection (&HandleTableCS
);
86 MapDefaultKey (PHANDLE RealKey
,
91 NTSTATUS Status
= STATUS_SUCCESS
;
93 TRACE("MapDefaultKey (Key %x)\n", Key
);
95 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
97 *RealKey
= (HANDLE
)Key
;
98 return STATUS_SUCCESS
;
101 /* Handle special cases here */
102 Index
= (ULONG
)Key
& 0x0FFFFFFF;
103 if (Index
>= MAX_DEFAULT_HANDLES
)
105 return STATUS_INVALID_PARAMETER
;
108 RtlEnterCriticalSection (&HandleTableCS
);
109 Handle
= &DefaultHandleTable
[Index
];
112 /* create/open the default handle */
115 case 0: /* HKEY_CLASSES_ROOT */
116 Status
= OpenClassesRootKey (Handle
);
119 case 1: /* HKEY_CURRENT_USER */
120 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
124 case 2: /* HKEY_LOCAL_MACHINE */
125 Status
= OpenLocalMachineKey (Handle
);
128 case 3: /* HKEY_USERS */
129 Status
= OpenUsersKey (Handle
);
132 case 4: /* HKEY_PERFORMANCE_DATA */
133 Status
= OpenPerformanceDataKey (Handle
);
136 case 5: /* HKEY_CURRENT_CONFIG */
137 Status
= OpenCurrentConfigKey (Handle
);
140 case 6: /* HKEY_DYN_DATA */
141 Status
= STATUS_NOT_IMPLEMENTED
;
145 WARN("MapDefaultHandle() no handle creator\n");
146 Status
= STATUS_INVALID_PARAMETER
;
149 RtlLeaveCriticalSection (&HandleTableCS
);
151 if (NT_SUCCESS(Status
))
161 CloseDefaultKeys (VOID
)
165 RtlEnterCriticalSection (&HandleTableCS
);
166 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
168 if (DefaultHandleTable
[i
] != NULL
)
170 NtClose (DefaultHandleTable
[i
]);
171 DefaultHandleTable
[i
] = NULL
;
174 RtlLeaveCriticalSection (&HandleTableCS
);
179 OpenClassesRootKey (PHANDLE KeyHandle
)
181 OBJECT_ATTRIBUTES Attributes
;
182 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\CLASSES");
184 TRACE("OpenClassesRootKey()\n");
186 InitializeObjectAttributes (&Attributes
,
188 OBJ_CASE_INSENSITIVE
,
191 return NtOpenKey (KeyHandle
,
198 OpenLocalMachineKey (PHANDLE KeyHandle
)
200 OBJECT_ATTRIBUTES Attributes
;
201 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine");
204 TRACE("OpenLocalMachineKey()\n");
206 InitializeObjectAttributes (&Attributes
,
208 OBJ_CASE_INSENSITIVE
,
211 Status
= NtOpenKey (KeyHandle
,
215 TRACE("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
221 OpenUsersKey (PHANDLE KeyHandle
)
223 OBJECT_ATTRIBUTES Attributes
;
224 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\User");
226 TRACE("OpenUsersKey()\n");
228 InitializeObjectAttributes (&Attributes
,
230 OBJ_CASE_INSENSITIVE
,
233 return NtOpenKey (KeyHandle
,
240 OpenCurrentConfigKey (PHANDLE KeyHandle
)
242 OBJECT_ATTRIBUTES Attributes
;
243 UNICODE_STRING KeyName
=
244 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
246 TRACE("OpenCurrentConfigKey()\n");
248 InitializeObjectAttributes (&Attributes
,
250 OBJ_CASE_INSENSITIVE
,
253 return NtOpenKey (KeyHandle
,
259 /************************************************************************
265 RegCloseKey (HKEY hKey
)
269 /* don't close null handle or a pseudo handle */
270 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
272 return ERROR_INVALID_HANDLE
;
275 Status
= NtClose (hKey
);
276 if (!NT_SUCCESS(Status
))
278 return RtlNtStatusToDosError (Status
);
281 return ERROR_SUCCESS
;
285 /************************************************************************
286 * RegConnectRegistryA
291 RegConnectRegistryA (LPCSTR lpMachineName
,
295 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
296 return ERROR_CALL_NOT_IMPLEMENTED
;
300 /************************************************************************
301 * RegConnectRegistryW
306 RegConnectRegistryW (LPCWSTR lpMachineName
,
310 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
311 return ERROR_CALL_NOT_IMPLEMENTED
;
315 /************************************************************************
318 * Create key and all necessary intermediate keys
321 CreateNestedKey(PHKEY KeyHandle
,
322 POBJECT_ATTRIBUTES ObjectAttributes
,
323 PUNICODE_STRING ClassString
,
326 DWORD
*lpdwDisposition
)
328 OBJECT_ATTRIBUTES LocalObjectAttributes
;
329 UNICODE_STRING LocalKeyName
;
332 ULONG FullNameLength
;
335 HANDLE LocalKeyHandle
;
337 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
343 (PULONG
)lpdwDisposition
);
344 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
345 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
348 /* Copy object attributes */
349 RtlCopyMemory (&LocalObjectAttributes
,
351 sizeof(OBJECT_ATTRIBUTES
));
352 RtlCreateUnicodeString (&LocalKeyName
,
353 ObjectAttributes
->ObjectName
->Buffer
);
354 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
355 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
357 /* Remove the last part of the key name and try to create the key again. */
358 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
360 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
361 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
363 Status
= STATUS_UNSUCCESSFUL
;
367 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
369 Status
= NtCreateKey (&LocalKeyHandle
,
371 &LocalObjectAttributes
,
376 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
379 if (!NT_SUCCESS(Status
))
381 RtlFreeUnicodeString (&LocalKeyName
);
385 /* Add removed parts of the key name and create them too. */
386 Length
= wcslen (LocalKeyName
.Buffer
);
389 NtClose (LocalKeyHandle
);
391 LocalKeyName
.Buffer
[Length
] = L
'\\';
392 Length
= wcslen (LocalKeyName
.Buffer
);
393 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
395 if (Length
== FullNameLength
)
397 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
403 (PULONG
)lpdwDisposition
);
406 Status
= NtCreateKey (&LocalKeyHandle
,
408 &LocalObjectAttributes
,
413 TRACE("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
414 if (!NT_SUCCESS(Status
))
418 RtlFreeUnicodeString (&LocalKeyName
);
424 /************************************************************************
430 RegCreateKeyExA (HKEY hKey
,
436 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
438 LPDWORD lpdwDisposition
)
440 UNICODE_STRING SubKeyString
;
441 UNICODE_STRING ClassString
;
442 OBJECT_ATTRIBUTES Attributes
;
446 TRACE("RegCreateKeyExA() called\n");
448 /* get the real parent key */
449 Status
= MapDefaultKey (&ParentKey
,
451 if (!NT_SUCCESS(Status
))
453 return RtlNtStatusToDosError (Status
);
455 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
459 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
463 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
465 InitializeObjectAttributes (&Attributes
,
467 OBJ_CASE_INSENSITIVE
,
469 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
470 Status
= CreateNestedKey(phkResult
,
472 (lpClass
== NULL
)? NULL
: &ClassString
,
476 RtlFreeUnicodeString (&SubKeyString
);
479 RtlFreeUnicodeString (&ClassString
);
482 TRACE("Status %x\n", Status
);
483 if (!NT_SUCCESS(Status
))
485 return RtlNtStatusToDosError (Status
);
488 return ERROR_SUCCESS
;
492 /************************************************************************
498 RegCreateKeyExW (HKEY hKey
,
504 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
506 LPDWORD lpdwDisposition
)
508 UNICODE_STRING SubKeyString
;
509 UNICODE_STRING ClassString
;
510 OBJECT_ATTRIBUTES Attributes
;
514 TRACE("RegCreateKeyExW() called\n");
516 /* get the real parent key */
517 Status
= MapDefaultKey (&ParentKey
,
519 if (!NT_SUCCESS(Status
))
521 return RtlNtStatusToDosError(Status
);
523 TRACE("ParentKey %x\n", (ULONG
)ParentKey
);
525 RtlInitUnicodeString (&ClassString
,
527 RtlInitUnicodeString (&SubKeyString
,
529 InitializeObjectAttributes (&Attributes
,
531 OBJ_CASE_INSENSITIVE
,
533 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
534 Status
= CreateNestedKey(phkResult
,
536 (lpClass
== NULL
)? NULL
: &ClassString
,
540 TRACE("Status %x\n", Status
);
541 if (!NT_SUCCESS(Status
))
543 return RtlNtStatusToDosError (Status
);
546 return ERROR_SUCCESS
;
550 /************************************************************************
556 RegCreateKeyA (HKEY hKey
,
560 return RegCreateKeyExA (hKey
,
572 /************************************************************************
578 RegCreateKeyW (HKEY hKey
,
582 return RegCreateKeyExW (hKey
,
594 /************************************************************************
600 RegDeleteKeyA (HKEY hKey
,
603 OBJECT_ATTRIBUTES ObjectAttributes
;
604 UNICODE_STRING SubKeyName
;
609 Status
= MapDefaultKey (&ParentKey
,
611 if (!NT_SUCCESS(Status
))
613 return RtlNtStatusToDosError (Status
);
616 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
618 InitializeObjectAttributes(&ObjectAttributes
,
620 OBJ_CASE_INSENSITIVE
,
624 Status
= NtOpenKey (&TargetKey
,
627 RtlFreeUnicodeString (&SubKeyName
);
628 if (!NT_SUCCESS(Status
))
630 return RtlNtStatusToDosError (Status
);
633 Status
= NtDeleteKey (TargetKey
);
635 if (!NT_SUCCESS(Status
))
637 return RtlNtStatusToDosError(Status
);
640 return ERROR_SUCCESS
;
644 /************************************************************************
650 RegDeleteKeyW (HKEY hKey
,
653 OBJECT_ATTRIBUTES ObjectAttributes
;
654 UNICODE_STRING SubKeyName
;
659 Status
= MapDefaultKey (&ParentKey
,
661 if (!NT_SUCCESS(Status
))
663 return RtlNtStatusToDosError (Status
);
666 RtlInitUnicodeString (&SubKeyName
,
668 InitializeObjectAttributes (&ObjectAttributes
,
670 OBJ_CASE_INSENSITIVE
,
673 Status
= NtOpenKey (&TargetKey
,
676 if (!NT_SUCCESS(Status
))
678 return RtlNtStatusToDosError (Status
);
681 Status
= NtDeleteKey (TargetKey
);
683 if (!NT_SUCCESS(Status
))
685 return RtlNtStatusToDosError (Status
);
688 return ERROR_SUCCESS
;
692 /************************************************************************
698 RegDeleteKeyValueW(IN HKEY hKey
,
699 IN LPCWSTR lpSubKey OPTIONAL
,
700 IN LPCWSTR lpValueName OPTIONAL
)
702 UNICODE_STRING ValueName
;
703 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
706 Status
= MapDefaultKey(&KeyHandle
,
708 if (!NT_SUCCESS(Status
))
710 return RtlNtStatusToDosError(Status
);
713 if (lpSubKey
!= NULL
)
715 OBJECT_ATTRIBUTES ObjectAttributes
;
716 UNICODE_STRING SubKeyName
;
718 RtlInitUnicodeString(&SubKeyName
,
721 InitializeObjectAttributes(&ObjectAttributes
,
723 OBJ_CASE_INSENSITIVE
,
727 Status
= NtOpenKey(&SubKeyHandle
,
730 if (!NT_SUCCESS(Status
))
732 return RtlNtStatusToDosError(Status
);
736 RtlInitUnicodeString(&ValueName
,
737 (LPWSTR
)lpValueName
);
739 Status
= NtDeleteValueKey((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
742 if (SubKeyHandle
!= NULL
)
744 NtClose(SubKeyHandle
);
747 if (!NT_SUCCESS(Status
))
749 return RtlNtStatusToDosError(Status
);
752 return ERROR_SUCCESS
;
756 /************************************************************************
762 RegDeleteKeyValueA(IN HKEY hKey
,
763 IN LPCSTR lpSubKey OPTIONAL
,
764 IN LPCSTR lpValueName OPTIONAL
)
766 UNICODE_STRING SubKey
, ValueName
;
769 if (lpSubKey
!= NULL
)
771 if (!RtlCreateUnicodeStringFromAsciiz(&SubKey
,
774 return ERROR_NOT_ENOUGH_MEMORY
;
778 RtlInitUnicodeString(&SubKey
,
781 if (lpValueName
!= NULL
)
783 if (!RtlCreateUnicodeStringFromAsciiz(&ValueName
,
786 RtlFreeUnicodeString(&SubKey
);
787 return ERROR_NOT_ENOUGH_MEMORY
;
791 RtlInitUnicodeString(&ValueName
,
794 Ret
= RegDeleteKeyValueW(hKey
,
798 RtlFreeUnicodeString(&SubKey
);
799 RtlFreeUnicodeString(&ValueName
);
805 /************************************************************************
811 RegSetKeyValueW(IN HKEY hKey
,
812 IN LPCWSTR lpSubKey OPTIONAL
,
813 IN LPCWSTR lpValueName OPTIONAL
,
815 IN LPCVOID lpData OPTIONAL
,
818 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
822 Status
= MapDefaultKey(&KeyHandle
,
824 if (!NT_SUCCESS(Status
))
826 return RtlNtStatusToDosError(Status
);
829 if (lpSubKey
!= NULL
)
831 OBJECT_ATTRIBUTES ObjectAttributes
;
832 UNICODE_STRING SubKeyName
;
834 RtlInitUnicodeString(&SubKeyName
,
837 InitializeObjectAttributes(&ObjectAttributes
,
839 OBJ_CASE_INSENSITIVE
,
843 Status
= NtOpenKey(&SubKeyHandle
,
846 if (!NT_SUCCESS(Status
))
848 return RtlNtStatusToDosError(Status
);
852 Ret
= RegSetValueExW((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
859 if (SubKeyHandle
!= NULL
)
861 NtClose(SubKeyHandle
);
868 /************************************************************************
874 RegSetKeyValueA(IN HKEY hKey
,
875 IN LPCSTR lpSubKey OPTIONAL
,
876 IN LPCSTR lpValueName OPTIONAL
,
878 IN LPCVOID lpData OPTIONAL
,
881 HANDLE KeyHandle
, SubKeyHandle
= NULL
;
885 Status
= MapDefaultKey(&KeyHandle
,
887 if (!NT_SUCCESS(Status
))
889 return RtlNtStatusToDosError(Status
);
892 if (lpSubKey
!= NULL
)
894 OBJECT_ATTRIBUTES ObjectAttributes
;
895 UNICODE_STRING SubKeyName
;
897 if (!RtlCreateUnicodeStringFromAsciiz(&SubKeyName
,
900 return RtlNtStatusToDosError(Status
);
903 InitializeObjectAttributes(&ObjectAttributes
,
905 OBJ_CASE_INSENSITIVE
,
909 Status
= NtOpenKey(&SubKeyHandle
,
913 RtlFreeUnicodeString(&SubKeyName
);
915 if (!NT_SUCCESS(Status
))
917 return RtlNtStatusToDosError(Status
);
921 Ret
= RegSetValueExA((SubKeyHandle
!= NULL
) ? SubKeyHandle
: KeyHandle
,
928 if (SubKeyHandle
!= NULL
)
930 NtClose(SubKeyHandle
);
937 /************************************************************************
943 RegDeleteValueA (HKEY hKey
,
946 UNICODE_STRING ValueName
;
950 Status
= MapDefaultKey (&KeyHandle
,
952 if (!NT_SUCCESS(Status
))
954 return RtlNtStatusToDosError (Status
);
957 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
959 Status
= NtDeleteValueKey (KeyHandle
,
961 RtlFreeUnicodeString (&ValueName
);
962 if (!NT_SUCCESS(Status
))
964 return RtlNtStatusToDosError (Status
);
967 return ERROR_SUCCESS
;
971 /************************************************************************
977 RegDeleteValueW (HKEY hKey
,
980 UNICODE_STRING ValueName
;
984 Status
= MapDefaultKey (&KeyHandle
,
986 if (!NT_SUCCESS(Status
))
988 return RtlNtStatusToDosError (Status
);
991 RtlInitUnicodeString (&ValueName
,
992 (LPWSTR
)lpValueName
);
994 Status
= NtDeleteValueKey (KeyHandle
,
996 if (!NT_SUCCESS(Status
))
998 return RtlNtStatusToDosError (Status
);
1001 return ERROR_SUCCESS
;
1005 /************************************************************************
1011 RegEnumKeyA (HKEY hKey
,
1019 return RegEnumKeyExA (hKey
,
1030 /************************************************************************
1036 RegEnumKeyW (HKEY hKey
,
1044 return RegEnumKeyExW (hKey
,
1055 /************************************************************************
1061 RegEnumKeyExA (HKEY hKey
,
1068 PFILETIME lpftLastWriteTime
)
1072 KEY_NODE_INFORMATION Node
;
1073 KEY_BASIC_INFORMATION Basic
;
1076 UNICODE_STRING StringU
;
1077 ANSI_STRING StringA
;
1078 LONG ErrorCode
= ERROR_SUCCESS
;
1080 DWORD ClassLength
= 0;
1086 TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
1087 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
1089 if ((lpClass
) && (!lpcbClass
))
1091 return ERROR_INVALID_PARAMETER
;
1094 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1095 if (!NT_SUCCESS(Status
))
1097 return RtlNtStatusToDosError (Status
);
1102 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1113 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1120 /* The class name should start at a dword boundary */
1121 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1125 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1128 KeyInfo
= RtlAllocateHeap (ProcessHeap
, 0, BufferSize
);
1129 if (KeyInfo
== NULL
)
1131 return ERROR_OUTOFMEMORY
;
1134 Status
= NtEnumerateKey (KeyHandle
,
1136 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
1140 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1141 if (!NT_SUCCESS(Status
))
1143 ErrorCode
= RtlNtStatusToDosError (Status
);
1147 if (lpClass
== NULL
)
1149 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1151 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1155 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
1156 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
1157 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
1162 if (KeyInfo
->Node
.NameLength
> NameLength
||
1163 KeyInfo
->Node
.ClassLength
> ClassLength
)
1165 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1169 StringA
.Buffer
= lpClass
;
1171 StringA
.MaximumLength
= *lpcbClass
;
1172 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
1173 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
1174 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
1175 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1176 lpClass
[StringA
.Length
] = 0;
1177 *lpcbClass
= StringA
.Length
;
1178 StringU
.Buffer
= KeyInfo
->Node
.Name
;
1179 StringU
.Length
= KeyInfo
->Node
.NameLength
;
1180 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
1184 if (ErrorCode
== ERROR_SUCCESS
)
1186 StringA
.Buffer
= lpName
;
1188 StringA
.MaximumLength
= *lpcbName
;
1189 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
1190 lpName
[StringA
.Length
] = 0;
1191 *lpcbName
= StringA
.Length
;
1192 if (lpftLastWriteTime
!= NULL
)
1194 if (lpClass
== NULL
)
1196 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1197 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1201 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1202 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1208 TRACE("Key Namea0 Length %d\n", StringU
.Length
);
1209 TRACE("Key Namea1 Length %d\n", NameLength
);
1210 TRACE("Key Namea Length %d\n", *lpcbName
);
1211 TRACE("Key Namea %s\n", lpName
);
1213 RtlFreeHeap (ProcessHeap
,
1221 /************************************************************************
1227 RegEnumKeyExW (HKEY hKey
,
1234 PFILETIME lpftLastWriteTime
)
1238 KEY_NODE_INFORMATION Node
;
1239 KEY_BASIC_INFORMATION Basic
;
1245 ULONG ClassLength
= 0;
1247 LONG ErrorCode
= ERROR_SUCCESS
;
1250 Status
= MapDefaultKey(&KeyHandle
,
1252 if (!NT_SUCCESS(Status
))
1254 return RtlNtStatusToDosError (Status
);
1259 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1270 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1277 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1281 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1284 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1287 if (KeyInfo
== NULL
)
1289 return ERROR_OUTOFMEMORY
;
1292 Status
= NtEnumerateKey (KeyHandle
,
1294 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1298 TRACE("NtEnumerateKey() returned status 0x%X\n", Status
);
1299 if (!NT_SUCCESS(Status
))
1301 ErrorCode
= RtlNtStatusToDosError (Status
);
1305 if (lpClass
== NULL
)
1307 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1309 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1313 RtlCopyMemory (lpName
,
1314 KeyInfo
->Basic
.Name
,
1315 KeyInfo
->Basic
.NameLength
);
1316 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1317 lpName
[*lpcbName
] = 0;
1322 if (KeyInfo
->Node
.NameLength
> NameLength
||
1323 KeyInfo
->Node
.ClassLength
> ClassLength
)
1325 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1329 RtlCopyMemory (lpName
,
1331 KeyInfo
->Node
.NameLength
);
1332 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1333 lpName
[*lpcbName
] = 0;
1334 RtlCopyMemory (lpClass
,
1335 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1336 KeyInfo
->Node
.ClassLength
);
1337 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1338 lpClass
[*lpcbClass
] = 0;
1342 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1344 if (lpClass
== NULL
)
1346 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1347 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1351 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1352 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1357 RtlFreeHeap (ProcessHeap
,
1364 /************************************************************************
1370 RegEnumValueA( HKEY hKey
, DWORD index
, LPSTR value
, LPDWORD val_count
,
1371 LPDWORD reserved
, LPDWORD type
, LPBYTE data
, LPDWORD count
)
1376 char buffer
[256], *buf_ptr
= buffer
;
1377 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1378 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1380 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1381 // hkey, index, value, val_count, reserved, type, data, count );
1383 /* NT only checks count, not val_count */
1384 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1385 status
= MapDefaultKey (&KeyHandle
, hKey
);
1386 if (!NT_SUCCESS(status
))
1388 return RtlNtStatusToDosError (status
);
1391 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1392 if (data
) total_size
+= *count
;
1393 total_size
= min( sizeof(buffer
), total_size
);
1395 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1396 buffer
, total_size
, &total_size
);
1397 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1399 /* we need to fetch the contents for a string type even if not requested,
1400 * because we need to compute the length of the ASCII string. */
1401 if (value
|| data
|| is_string(info
->Type
))
1403 /* retry with a dynamically allocated buffer */
1404 while (status
== STATUS_BUFFER_OVERFLOW
)
1406 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1407 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1408 return ERROR_NOT_ENOUGH_MEMORY
;
1409 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1410 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1411 buf_ptr
, total_size
, &total_size
);
1414 if (status
) goto done
;
1416 if (is_string(info
->Type
))
1419 RtlUnicodeToMultiByteSize( &len
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1420 total_size
- info
->DataOffset
);
1423 if (len
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1426 RtlUnicodeToMultiByteN( (PCHAR
)data
, len
, NULL
, (WCHAR
*)(buf_ptr
+ info
->DataOffset
),
1427 total_size
- info
->DataOffset
);
1428 /* if the type is REG_SZ and data is not 0-terminated
1429 * and there is enough space in the buffer NT appends a \0 */
1430 if (len
< *count
&& data
[len
-1]) data
[len
] = 0;
1433 info
->DataLength
= len
;
1437 if (total_size
- info
->DataOffset
> *count
) status
= STATUS_BUFFER_OVERFLOW
;
1438 else memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1441 if (value
&& !status
)
1445 RtlUnicodeToMultiByteSize( &len
, info
->Name
, info
->NameLength
);
1446 if (len
>= *val_count
)
1448 status
= STATUS_BUFFER_OVERFLOW
;
1451 len
= *val_count
- 1;
1452 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1458 RtlUnicodeToMultiByteN( value
, len
, NULL
, info
->Name
, info
->NameLength
);
1464 else status
= STATUS_SUCCESS
;
1466 if (type
) *type
= info
->Type
;
1467 if (count
) *count
= info
->DataLength
;
1470 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1471 return RtlNtStatusToDosError(status
);
1474 /******************************************************************************
1475 * RegEnumValueW [ADVAPI32.@]
1479 * hkey [I] Handle to key to query
1480 * index [I] Index of value to query
1481 * value [O] Value string
1482 * val_count [I/O] Size of value buffer (in wchars)
1483 * reserved [I] Reserved
1484 * type [O] Type code
1485 * data [O] Value data
1486 * count [I/O] Size of data buffer (in bytes)
1489 * Success: ERROR_SUCCESS
1490 * Failure: nonzero error code from Winerror.h
1493 RegEnumValueW( HKEY hKey
, DWORD index
, LPWSTR value
, PDWORD val_count
,
1494 PDWORD reserved
, PDWORD type
, LPBYTE data
, PDWORD count
)
1499 char buffer
[256], *buf_ptr
= buffer
;
1500 KEY_VALUE_FULL_INFORMATION
*info
= (KEY_VALUE_FULL_INFORMATION
*)buffer
;
1501 static const int info_size
= offsetof( KEY_VALUE_FULL_INFORMATION
, Name
);
1503 //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
1504 // hkey, index, value, val_count, reserved, type, data, count );
1506 /* NT only checks count, not val_count */
1507 if ((data
&& !count
) || reserved
) return ERROR_INVALID_PARAMETER
;
1509 status
= MapDefaultKey (&KeyHandle
, hKey
);
1510 if (!NT_SUCCESS(status
))
1512 return RtlNtStatusToDosError (status
);
1515 total_size
= info_size
+ (MAX_PATH
+ 1) * sizeof(WCHAR
);
1516 if (data
) total_size
+= *count
;
1517 total_size
= min( sizeof(buffer
), total_size
);
1519 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1520 buffer
, total_size
, &total_size
);
1521 if (status
&& status
!= STATUS_BUFFER_OVERFLOW
) goto done
;
1525 /* retry with a dynamically allocated buffer */
1526 while (status
== STATUS_BUFFER_OVERFLOW
)
1528 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1529 if (!(buf_ptr
= HeapAlloc( GetProcessHeap(), 0, total_size
)))
1530 return ERROR_NOT_ENOUGH_MEMORY
;
1531 info
= (KEY_VALUE_FULL_INFORMATION
*)buf_ptr
;
1532 status
= NtEnumerateValueKey( KeyHandle
, index
, KeyValueFullInformation
,
1533 buf_ptr
, total_size
, &total_size
);
1536 if (status
) goto done
;
1540 if (info
->NameLength
/sizeof(WCHAR
) >= *val_count
)
1542 status
= STATUS_BUFFER_OVERFLOW
;
1545 memcpy( value
, info
->Name
, info
->NameLength
);
1546 *val_count
= info
->NameLength
/ sizeof(WCHAR
);
1547 value
[*val_count
] = 0;
1552 if (total_size
- info
->DataOffset
> *count
)
1554 status
= STATUS_BUFFER_OVERFLOW
;
1557 memcpy( data
, buf_ptr
+ info
->DataOffset
, total_size
- info
->DataOffset
);
1558 if (total_size
- info
->DataOffset
<= *count
-sizeof(WCHAR
) && is_string(info
->Type
))
1560 /* if the type is REG_SZ and data is not 0-terminated
1561 * and there is enough space in the buffer NT appends a \0 */
1562 WCHAR
*ptr
= (WCHAR
*)(data
+ total_size
- info
->DataOffset
);
1563 if (ptr
> (WCHAR
*)data
&& ptr
[-1]) *ptr
= 0;
1567 else status
= STATUS_SUCCESS
;
1570 if (type
) *type
= info
->Type
;
1571 if (count
) *count
= info
->DataLength
;
1574 if (buf_ptr
!= buffer
) HeapFree( GetProcessHeap(), 0, buf_ptr
);
1575 return RtlNtStatusToDosError(status
);
1578 /************************************************************************
1584 RegFlushKey(HKEY hKey
)
1589 if (hKey
== HKEY_PERFORMANCE_DATA
)
1591 return ERROR_SUCCESS
;
1594 Status
= MapDefaultKey (&KeyHandle
,
1596 if (!NT_SUCCESS(Status
))
1598 return RtlNtStatusToDosError (Status
);
1601 Status
= NtFlushKey (KeyHandle
);
1602 if (!NT_SUCCESS(Status
))
1604 return RtlNtStatusToDosError (Status
);
1607 return ERROR_SUCCESS
;
1611 /************************************************************************
1617 RegGetKeySecurity(HKEY hKey
,
1618 SECURITY_INFORMATION SecurityInformation
,
1619 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1620 LPDWORD lpcbSecurityDescriptor
)
1625 if (hKey
== HKEY_PERFORMANCE_DATA
)
1627 return ERROR_INVALID_HANDLE
;
1630 Status
= MapDefaultKey(&KeyHandle
,
1632 if (!NT_SUCCESS(Status
))
1634 TRACE("MapDefaultKey() failed (Status %lx)\n", Status
);
1635 return RtlNtStatusToDosError (Status
);
1638 Status
= NtQuerySecurityObject(KeyHandle
,
1639 SecurityInformation
,
1640 pSecurityDescriptor
,
1641 *lpcbSecurityDescriptor
,
1642 lpcbSecurityDescriptor
);
1643 if (!NT_SUCCESS(Status
))
1645 WARN("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
1646 return RtlNtStatusToDosError (Status
);
1649 return ERROR_SUCCESS
;
1653 /************************************************************************
1659 RegLoadKeyA (HKEY hKey
,
1663 UNICODE_STRING FileName
;
1664 UNICODE_STRING KeyName
;
1667 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1669 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1672 ErrorCode
= RegLoadKeyW (hKey
,
1676 RtlFreeUnicodeString (&FileName
);
1677 RtlFreeUnicodeString (&KeyName
);
1683 /************************************************************************
1689 RegLoadKeyW (HKEY hKey
,
1693 OBJECT_ATTRIBUTES FileObjectAttributes
;
1694 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1695 UNICODE_STRING FileName
;
1696 UNICODE_STRING KeyName
;
1700 if (hKey
== HKEY_PERFORMANCE_DATA
)
1702 return ERROR_INVALID_HANDLE
;
1705 Status
= MapDefaultKey (&KeyHandle
,
1707 if (!NT_SUCCESS(Status
))
1709 return RtlNtStatusToDosError (Status
);
1712 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1717 return ERROR_BAD_PATHNAME
;
1720 InitializeObjectAttributes (&FileObjectAttributes
,
1722 OBJ_CASE_INSENSITIVE
,
1726 RtlInitUnicodeString (&KeyName
,
1729 InitializeObjectAttributes (&KeyObjectAttributes
,
1731 OBJ_CASE_INSENSITIVE
,
1735 Status
= NtLoadKey (&KeyObjectAttributes
,
1736 &FileObjectAttributes
);
1738 RtlFreeUnicodeString (&FileName
);
1740 if (!NT_SUCCESS(Status
))
1742 return RtlNtStatusToDosError (Status
);
1745 return ERROR_SUCCESS
;
1749 /************************************************************************
1750 * RegNotifyChangeKeyValue
1755 RegNotifyChangeKeyValue (HKEY hKey
,
1757 DWORD dwNotifyFilter
,
1761 IO_STATUS_BLOCK IoStatusBlock
;
1765 if (hKey
== HKEY_PERFORMANCE_DATA
)
1767 return ERROR_INVALID_HANDLE
;
1770 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1772 return ERROR_INVALID_PARAMETER
;
1775 Status
= MapDefaultKey (&KeyHandle
,
1777 if (!NT_SUCCESS(Status
))
1779 return RtlNtStatusToDosError (Status
);
1782 /* FIXME: Remote key handles must fail */
1784 Status
= NtNotifyChangeKey (KeyHandle
,
1794 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1796 return RtlNtStatusToDosError (Status
);
1799 return ERROR_SUCCESS
;
1803 /************************************************************************
1804 * RegOpenCurrentUser
1809 RegOpenCurrentUser (IN REGSAM samDesired
,
1810 OUT PHKEY phkResult
)
1814 Status
= RtlOpenCurrentUser((ACCESS_MASK
)samDesired
,
1815 (PHANDLE
)phkResult
);
1816 if (!NT_SUCCESS(Status
))
1818 /* NOTE - don't set the last error code! just return the error! */
1819 return RtlNtStatusToDosError(Status
);
1822 return ERROR_SUCCESS
;
1826 /************************************************************************
1829 * 20050503 Fireball - imported from WINE
1834 RegOpenKeyA (HKEY hKey
,
1838 TRACE("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey
, lpSubKey
, phkResult
);
1840 if (!lpSubKey
|| !*lpSubKey
)
1843 return ERROR_SUCCESS
;
1846 return RegOpenKeyExA( hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
1850 /************************************************************************
1855 * 20050503 Fireball - imported from WINE
1860 RegOpenKeyW (HKEY hKey
,
1864 TRACE("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey
, lpSubKey
, phkResult
);
1866 if (!lpSubKey
|| !*lpSubKey
)
1869 return ERROR_SUCCESS
;
1871 return RegOpenKeyExW(hKey
, lpSubKey
, 0, MAXIMUM_ALLOWED
, phkResult
);
1875 /************************************************************************
1881 RegOpenKeyExA (HKEY hKey
,
1887 OBJECT_ATTRIBUTES ObjectAttributes
;
1888 UNICODE_STRING SubKeyString
;
1892 TRACE("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
1893 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
1895 Status
= MapDefaultKey (&KeyHandle
, hKey
);
1896 if (!NT_SUCCESS(Status
))
1898 return RtlNtStatusToDosError (Status
);
1901 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
, (LPSTR
)lpSubKey
);
1902 InitializeObjectAttributes (&ObjectAttributes
,
1904 OBJ_CASE_INSENSITIVE
,
1908 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
1909 RtlFreeUnicodeString (&SubKeyString
);
1910 if (!NT_SUCCESS(Status
))
1912 return RtlNtStatusToDosError (Status
);
1915 return ERROR_SUCCESS
;
1919 /************************************************************************
1925 RegOpenKeyExW (HKEY hKey
,
1931 OBJECT_ATTRIBUTES ObjectAttributes
;
1932 UNICODE_STRING SubKeyString
;
1936 TRACE("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
1937 hKey
, lpSubKey
, ulOptions
, samDesired
, phkResult
);
1939 Status
= MapDefaultKey (&KeyHandle
, hKey
);
1940 if (!NT_SUCCESS(Status
))
1942 return RtlNtStatusToDosError (Status
);
1945 if (lpSubKey
!= NULL
)
1946 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)lpSubKey
);
1948 RtlInitUnicodeString (&SubKeyString
, (LPWSTR
)L
"");
1950 InitializeObjectAttributes (&ObjectAttributes
,
1952 OBJ_CASE_INSENSITIVE
,
1956 Status
= NtOpenKey ((PHANDLE
)phkResult
, samDesired
, &ObjectAttributes
);
1958 if (!NT_SUCCESS(Status
))
1960 return RtlNtStatusToDosError (Status
);
1963 return ERROR_SUCCESS
;
1967 /************************************************************************
1968 * RegOpenUserClassesRoot
1973 RegOpenUserClassesRoot (IN HANDLE hToken
,
1975 IN REGSAM samDesired
,
1976 OUT PHKEY phkResult
)
1978 const WCHAR UserClassesKeyPrefix
[] = L
"\\Registry\\User\\";
1979 const WCHAR UserClassesKeySuffix
[] = L
"_Classes";
1980 PTOKEN_USER TokenUserData
;
1981 ULONG RequiredLength
;
1982 UNICODE_STRING UserSidString
, UserClassesKeyRoot
;
1983 OBJECT_ATTRIBUTES ObjectAttributes
;
1987 /* check parameters */
1988 if (hToken
== NULL
|| dwOptions
!= 0 || phkResult
== NULL
)
1990 return ERROR_INVALID_PARAMETER
;
1994 * Get the user sid from the token
1998 /* determine how much memory we need */
1999 Status
= NtQueryInformationToken(hToken
,
2004 if (!NT_SUCCESS(Status
) && (Status
!= STATUS_BUFFER_TOO_SMALL
))
2006 /* NOTE - as opposed to all other registry functions windows does indeed
2007 change the last error code in case the caller supplied a invalid
2008 handle for example! */
2009 ErrorCode
= RtlNtStatusToDosError (Status
);
2013 TokenUserData
= RtlAllocateHeap(ProcessHeap
,
2016 if (TokenUserData
== NULL
)
2018 return ERROR_NOT_ENOUGH_MEMORY
;
2021 /* attempt to read the information */
2022 Status
= NtQueryInformationToken(hToken
,
2027 if (!NT_SUCCESS(Status
))
2029 RtlFreeHeap(ProcessHeap
,
2032 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2034 /* the information appears to have changed?! try again */
2038 /* NOTE - as opposed to all other registry functions windows does indeed
2039 change the last error code in case the caller supplied a invalid
2040 handle for example! */
2041 ErrorCode
= RtlNtStatusToDosError (Status
);
2046 * Build the absolute path for the user's registry in the form
2047 * "\Registry\User\<SID>_Classes"
2049 Status
= RtlConvertSidToUnicodeString(&UserSidString
,
2050 TokenUserData
->User
.Sid
,
2053 /* we don't need the user data anymore, free it */
2054 RtlFreeHeap(ProcessHeap
,
2058 if (!NT_SUCCESS(Status
))
2060 return RtlNtStatusToDosError (Status
);
2063 /* allocate enough memory for the entire key string */
2064 UserClassesKeyRoot
.Length
= 0;
2065 UserClassesKeyRoot
.MaximumLength
= UserSidString
.Length
+
2066 sizeof(UserClassesKeyPrefix
) +
2067 sizeof(UserClassesKeySuffix
);
2068 UserClassesKeyRoot
.Buffer
= RtlAllocateHeap(ProcessHeap
,
2070 UserClassesKeyRoot
.MaximumLength
);
2071 if (UserClassesKeyRoot
.Buffer
== NULL
)
2073 RtlFreeUnicodeString(&UserSidString
);
2074 return RtlNtStatusToDosError (Status
);
2077 /* build the string */
2078 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2079 UserClassesKeyPrefix
);
2080 RtlAppendUnicodeStringToString(&UserClassesKeyRoot
,
2082 RtlAppendUnicodeToString(&UserClassesKeyRoot
,
2083 UserClassesKeySuffix
);
2085 TRACE("RegOpenUserClassesRoot: Absolute path: %wZ\n", &UserClassesKeyRoot
);
2091 InitializeObjectAttributes (&ObjectAttributes
,
2092 &UserClassesKeyRoot
,
2093 OBJ_CASE_INSENSITIVE
,
2097 Status
= NtOpenKey((PHANDLE
)phkResult
,
2101 RtlFreeUnicodeString(&UserSidString
);
2102 RtlFreeUnicodeString(&UserClassesKeyRoot
);
2104 if (!NT_SUCCESS(Status
))
2106 return RtlNtStatusToDosError (Status
);
2109 return ERROR_SUCCESS
;
2113 /************************************************************************
2119 RegQueryInfoKeyA (HKEY hKey
,
2124 LPDWORD lpcbMaxSubKeyLen
,
2125 LPDWORD lpcbMaxClassLen
,
2127 LPDWORD lpcbMaxValueNameLen
,
2128 LPDWORD lpcbMaxValueLen
,
2129 LPDWORD lpcbSecurityDescriptor
,
2130 PFILETIME lpftLastWriteTime
)
2132 WCHAR ClassName
[MAX_PATH
];
2133 UNICODE_STRING UnicodeString
;
2134 ANSI_STRING AnsiString
;
2137 RtlInitUnicodeString (&UnicodeString
,
2139 if (lpClass
!= NULL
)
2141 UnicodeString
.Buffer
= &ClassName
[0];
2142 UnicodeString
.MaximumLength
= sizeof(ClassName
);
2143 AnsiString
.MaximumLength
= *lpcbClass
;
2146 ErrorCode
= RegQueryInfoKeyW (hKey
,
2147 UnicodeString
.Buffer
,
2154 lpcbMaxValueNameLen
,
2156 lpcbSecurityDescriptor
,
2158 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
2160 AnsiString
.Buffer
= lpClass
;
2161 AnsiString
.Length
= 0;
2162 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
2163 RtlUnicodeStringToAnsiString (&AnsiString
,
2166 *lpcbClass
= AnsiString
.Length
;
2167 lpClass
[AnsiString
.Length
] = 0;
2174 /************************************************************************
2180 RegQueryInfoKeyW (HKEY hKey
,
2185 LPDWORD lpcbMaxSubKeyLen
,
2186 LPDWORD lpcbMaxClassLen
,
2188 LPDWORD lpcbMaxValueNameLen
,
2189 LPDWORD lpcbMaxValueLen
,
2190 LPDWORD lpcbSecurityDescriptor
,
2191 PFILETIME lpftLastWriteTime
)
2193 KEY_FULL_INFORMATION FullInfoBuffer
;
2194 PKEY_FULL_INFORMATION FullInfo
;
2196 ULONG ClassLength
= 0;
2200 LONG ErrorCode
= ERROR_SUCCESS
;
2202 if ((lpClass
) && (!lpcbClass
))
2204 return ERROR_INVALID_PARAMETER
;
2207 Status
= MapDefaultKey (&KeyHandle
,
2209 if (!NT_SUCCESS(Status
))
2211 return RtlNtStatusToDosError (Status
);
2214 if (lpClass
!= NULL
)
2218 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2225 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2226 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2229 if (FullInfo
== NULL
)
2231 return ERROR_OUTOFMEMORY
;
2234 FullInfo
->ClassLength
= ClassLength
;
2238 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2239 FullInfo
= &FullInfoBuffer
;
2240 FullInfo
->ClassLength
= 0;
2242 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2244 Status
= NtQueryKey (KeyHandle
,
2249 TRACE("NtQueryKey() returned status 0x%X\n", Status
);
2250 if (!NT_SUCCESS(Status
))
2252 if (lpClass
!= NULL
)
2254 RtlFreeHeap (ProcessHeap
,
2259 return RtlNtStatusToDosError (Status
);
2262 TRACE("SubKeys %d\n", FullInfo
->SubKeys
);
2263 if (lpcSubKeys
!= NULL
)
2265 *lpcSubKeys
= FullInfo
->SubKeys
;
2268 TRACE("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2269 if (lpcbMaxSubKeyLen
!= NULL
)
2271 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2274 TRACE("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2275 if (lpcbMaxClassLen
!= NULL
)
2277 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2280 TRACE("Values %lu\n", FullInfo
->Values
);
2281 if (lpcValues
!= NULL
)
2283 *lpcValues
= FullInfo
->Values
;
2286 TRACE("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2287 if (lpcbMaxValueNameLen
!= NULL
)
2289 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2292 TRACE("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2293 if (lpcbMaxValueLen
!= NULL
)
2295 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2298 if (lpcbSecurityDescriptor
!= NULL
)
2300 Status
= NtQuerySecurityObject(KeyHandle
,
2301 OWNER_SECURITY_INFORMATION
|
2302 GROUP_SECURITY_INFORMATION
|
2303 DACL_SECURITY_INFORMATION
,
2306 lpcbSecurityDescriptor
);
2307 if (!NT_SUCCESS(Status
))
2309 if (lpClass
!= NULL
)
2311 RtlFreeHeap(ProcessHeap
,
2316 return RtlNtStatusToDosError (Status
);
2320 if (lpftLastWriteTime
!= NULL
)
2322 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2323 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2326 if (lpClass
!= NULL
)
2328 if (FullInfo
->ClassLength
> ClassLength
)
2330 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2334 RtlCopyMemory (lpClass
,
2336 FullInfo
->ClassLength
);
2337 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2338 lpClass
[*lpcbClass
] = 0;
2341 RtlFreeHeap (ProcessHeap
,
2350 /************************************************************************
2351 * RegQueryMultipleValuesA
2356 RegQueryMultipleValuesA (HKEY hKey
,
2363 DWORD maxBytes
= *ldwTotsize
;
2364 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2367 if (maxBytes
>= (1024*1024))
2368 return ERROR_TRANSFER_TOO_LONG
;
2372 TRACE("RegQueryMultipleValuesA(%p,%p,%ld,%p,%p=%ld)\n",
2373 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2375 for (i
= 0; i
< num_vals
; i
++)
2377 val_list
[i
].ve_valuelen
= 0;
2378 ErrorCode
= RegQueryValueExA (hKey
,
2379 val_list
[i
].ve_valuename
,
2383 &val_list
[i
].ve_valuelen
);
2384 if (ErrorCode
!= ERROR_SUCCESS
)
2389 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2391 ErrorCode
= RegQueryValueExA (hKey
,
2392 val_list
[i
].ve_valuename
,
2394 &val_list
[i
].ve_type
,
2396 &val_list
[i
].ve_valuelen
);
2397 if (ErrorCode
!= ERROR_SUCCESS
)
2402 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2404 bufptr
+= val_list
[i
].ve_valuelen
;
2407 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2410 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2414 /************************************************************************
2415 * RegQueryMultipleValuesW
2420 RegQueryMultipleValuesW (HKEY hKey
,
2427 DWORD maxBytes
= *ldwTotsize
;
2428 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2431 if (maxBytes
>= (1024*1024))
2432 return ERROR_TRANSFER_TOO_LONG
;
2436 TRACE ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2437 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2439 for (i
= 0; i
< num_vals
; i
++)
2441 val_list
[i
].ve_valuelen
= 0;
2442 ErrorCode
= RegQueryValueExW (hKey
,
2443 val_list
[i
].ve_valuename
,
2447 &val_list
[i
].ve_valuelen
);
2448 if (ErrorCode
!= ERROR_SUCCESS
)
2453 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2455 ErrorCode
= RegQueryValueExW (hKey
,
2456 val_list
[i
].ve_valuename
,
2458 &val_list
[i
].ve_type
,
2460 &val_list
[i
].ve_valuelen
);
2461 if (ErrorCode
!= ERROR_SUCCESS
)
2466 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2468 bufptr
+= val_list
[i
].ve_valuelen
;
2471 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2474 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2478 /************************************************************************
2484 RegQueryValueExW (HKEY hKey
,
2485 LPCWSTR lpValueName
,
2491 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2492 UNICODE_STRING ValueName
;
2497 LONG ErrorCode
= ERROR_SUCCESS
;
2498 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2500 TRACE("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2501 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2503 Status
= MapDefaultKey (&KeyHandle
,
2505 if (!NT_SUCCESS(Status
))
2507 return RtlNtStatusToDosError (Status
);
2510 if (lpData
!= NULL
&& lpcbData
== NULL
)
2512 return ERROR_INVALID_PARAMETER
;
2515 RtlInitUnicodeString (&ValueName
,
2517 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2518 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2521 if (ValueInfo
== NULL
)
2523 return ERROR_OUTOFMEMORY
;
2526 Status
= NtQueryValueKey (KeyHandle
,
2528 KeyValuePartialInformation
,
2532 TRACE("Status 0x%X\n", Status
);
2533 if (Status
== STATUS_BUFFER_OVERFLOW
)
2535 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2537 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2539 else if (!NT_SUCCESS(Status
))
2541 ErrorCode
= RtlNtStatusToDosError (Status
);
2543 if (lpcbData
!= NULL
)
2545 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2551 *lpType
= ValueInfo
->Type
;
2554 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2556 RtlMoveMemory (lpData
,
2558 min(ValueInfo
->DataLength
, MaxCopy
));
2561 if ((ValueInfo
->Type
== REG_SZ
) ||
2562 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2563 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2565 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2567 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2570 if (lpcbData
!= NULL
)
2572 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2573 TRACE("(string) Returning Size: %lu\n", *lpcbData
);
2578 if (lpcbData
!= NULL
)
2580 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2581 TRACE("(other) Returning Size: %lu\n", *lpcbData
);
2585 TRACE("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2587 RtlFreeHeap (ProcessHeap
,
2595 /************************************************************************
2601 RegQueryValueExA (HKEY hKey
,
2608 UNICODE_STRING ValueName
;
2609 UNICODE_STRING ValueData
;
2610 ANSI_STRING AnsiString
;
2615 TRACE("hKey 0x%X lpValueName %s lpData 0x%X lpcbData %d\n",
2616 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2618 if (lpData
!= NULL
&& lpcbData
== NULL
)
2620 return ERROR_INVALID_PARAMETER
;
2625 ValueData
.Length
= 0;
2626 ValueData
.MaximumLength
= (*lpcbData
+ 1) * sizeof(WCHAR
);
2627 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2629 ValueData
.MaximumLength
);
2630 if (!ValueData
.Buffer
)
2632 return ERROR_OUTOFMEMORY
;
2637 ValueData
.Buffer
= NULL
;
2638 ValueData
.Length
= 0;
2639 ValueData
.MaximumLength
= 0;
2642 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2643 (LPSTR
)lpValueName
);
2645 Length
= (lpcbData
== NULL
) ? 0 : *lpcbData
* sizeof(WCHAR
);
2646 ErrorCode
= RegQueryValueExW (hKey
,
2650 (lpData
== NULL
) ? NULL
: (LPBYTE
)ValueData
.Buffer
,
2652 TRACE("ErrorCode %lu\n", ErrorCode
);
2653 RtlFreeUnicodeString(&ValueName
);
2655 if (ErrorCode
== ERROR_SUCCESS
||
2656 ErrorCode
== ERROR_MORE_DATA
)
2663 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2665 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2667 RtlInitAnsiString(&AnsiString
, NULL
);
2668 AnsiString
.Buffer
= (LPSTR
)lpData
;
2669 AnsiString
.MaximumLength
= *lpcbData
;
2670 ValueData
.Length
= Length
;
2671 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2672 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2674 Length
= Length
/ sizeof(WCHAR
);
2676 else if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2678 if (*lpcbData
< Length
)
2680 ErrorCode
= ERROR_MORE_DATA
;
2684 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2688 if (lpcbData
!= NULL
)
2694 if (ValueData
.Buffer
!= NULL
)
2696 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2703 /************************************************************************
2709 RegQueryValueA (HKEY hKey
,
2714 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2715 UNICODE_STRING SubKeyName
;
2716 UNICODE_STRING Value
;
2717 ANSI_STRING AnsiString
;
2721 TRACE("hKey 0x%X lpSubKey %s lpValue %p lpcbValue %d\n",
2722 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
2724 if (lpValue
!= NULL
&&
2727 return ERROR_INVALID_PARAMETER
;
2730 RtlInitUnicodeString (&SubKeyName
,
2732 RtlInitUnicodeString (&Value
,
2734 if (lpSubKey
!= NULL
&&
2735 strlen(lpSubKey
) != 0)
2737 RtlInitAnsiString (&AnsiString
,
2739 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2740 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2741 RtlAnsiStringToUnicodeString (&SubKeyName
,
2746 if (lpValue
!= NULL
)
2748 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2749 Value
.MaximumLength
= ValueSize
;
2750 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2753 if (Value
.Buffer
== NULL
)
2755 return ERROR_OUTOFMEMORY
;
2763 ErrorCode
= RegQueryValueW (hKey
,
2764 (LPCWSTR
)SubKeyName
.Buffer
,
2767 if (ErrorCode
== ERROR_SUCCESS
)
2769 Value
.Length
= ValueSize
;
2770 RtlInitAnsiString (&AnsiString
,
2772 AnsiString
.Buffer
= lpValue
;
2773 AnsiString
.MaximumLength
= *lpcbValue
;
2774 RtlUnicodeStringToAnsiString (&AnsiString
,
2779 *lpcbValue
= ValueSize
;
2780 if (Value
.Buffer
!= NULL
)
2782 RtlFreeHeap (ProcessHeap
,
2791 /************************************************************************
2797 RegQueryValueW (HKEY hKey
,
2802 OBJECT_ATTRIBUTES ObjectAttributes
;
2803 UNICODE_STRING SubKeyString
;
2810 TRACE("hKey 0x%X lpSubKey %S lpValue %p lpcbValue %d\n",
2811 hKey
, lpSubKey
, lpValue
, lpcbValue
? *lpcbValue
: 0);
2813 Status
= MapDefaultKey (&KeyHandle
,
2815 if (!NT_SUCCESS(Status
))
2817 return RtlNtStatusToDosError (Status
);
2820 if (lpSubKey
!= NULL
&&
2821 wcslen(lpSubKey
) != 0)
2823 RtlInitUnicodeString (&SubKeyString
,
2825 InitializeObjectAttributes (&ObjectAttributes
,
2827 OBJ_CASE_INSENSITIVE
,
2830 Status
= NtOpenKey (&RealKey
,
2833 if (!NT_SUCCESS(Status
))
2835 return RtlNtStatusToDosError (Status
);
2837 CloseRealKey
= TRUE
;
2842 CloseRealKey
= FALSE
;
2845 ErrorCode
= RegQueryValueExW (RealKey
,
2850 (LPDWORD
)lpcbValue
);
2860 /************************************************************************
2866 RegReplaceKeyA (HKEY hKey
,
2871 UNICODE_STRING SubKey
;
2872 UNICODE_STRING NewFile
;
2873 UNICODE_STRING OldFile
;
2876 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
2878 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
2880 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
2883 ErrorCode
= RegReplaceKeyW (hKey
,
2888 RtlFreeUnicodeString (&OldFile
);
2889 RtlFreeUnicodeString (&NewFile
);
2890 RtlFreeUnicodeString (&SubKey
);
2896 /************************************************************************
2902 RegReplaceKeyW (HKEY hKey
,
2907 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2908 OBJECT_ATTRIBUTES NewObjectAttributes
;
2909 OBJECT_ATTRIBUTES OldObjectAttributes
;
2910 UNICODE_STRING SubKeyName
;
2911 UNICODE_STRING NewFileName
;
2912 UNICODE_STRING OldFileName
;
2913 BOOLEAN CloseRealKey
;
2914 HANDLE RealKeyHandle
;
2918 if (hKey
== HKEY_PERFORMANCE_DATA
)
2920 return ERROR_INVALID_HANDLE
;
2923 Status
= MapDefaultKey (&KeyHandle
,
2925 if (!NT_SUCCESS(Status
))
2927 return RtlNtStatusToDosError (Status
);
2930 /* Open the real key */
2931 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
2933 RtlInitUnicodeString (&SubKeyName
,
2935 InitializeObjectAttributes (&KeyObjectAttributes
,
2937 OBJ_CASE_INSENSITIVE
,
2940 Status
= NtOpenKey (&RealKeyHandle
,
2942 &KeyObjectAttributes
);
2943 if (!NT_SUCCESS(Status
))
2945 return RtlNtStatusToDosError (Status
);
2947 CloseRealKey
= TRUE
;
2951 RealKeyHandle
= KeyHandle
;
2952 CloseRealKey
= FALSE
;
2955 /* Convert new file name */
2956 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
2963 NtClose (RealKeyHandle
);
2965 return ERROR_INVALID_PARAMETER
;
2968 InitializeObjectAttributes (&NewObjectAttributes
,
2970 OBJ_CASE_INSENSITIVE
,
2974 /* Convert old file name */
2975 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
2980 RtlFreeUnicodeString (&NewFileName
);
2983 NtClose (RealKeyHandle
);
2985 return ERROR_INVALID_PARAMETER
;
2988 InitializeObjectAttributes (&OldObjectAttributes
,
2990 OBJ_CASE_INSENSITIVE
,
2994 Status
= NtReplaceKey (&NewObjectAttributes
,
2996 &OldObjectAttributes
);
2998 RtlFreeUnicodeString (&OldFileName
);
2999 RtlFreeUnicodeString (&NewFileName
);
3003 NtClose (RealKeyHandle
);
3006 if (!NT_SUCCESS(Status
))
3008 return RtlNtStatusToDosError (Status
);
3011 return ERROR_SUCCESS
;
3015 /************************************************************************
3021 RegRestoreKeyA (HKEY hKey
,
3025 UNICODE_STRING FileName
;
3028 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3031 ErrorCode
= RegRestoreKeyW (hKey
,
3035 RtlFreeUnicodeString (&FileName
);
3041 /************************************************************************
3047 RegRestoreKeyW (HKEY hKey
,
3051 OBJECT_ATTRIBUTES ObjectAttributes
;
3052 IO_STATUS_BLOCK IoStatusBlock
;
3053 UNICODE_STRING FileName
;
3058 if (hKey
== HKEY_PERFORMANCE_DATA
)
3060 return ERROR_INVALID_HANDLE
;
3063 Status
= MapDefaultKey (&KeyHandle
,
3065 if (!NT_SUCCESS(Status
))
3067 return RtlNtStatusToDosError (Status
);
3070 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
3075 return ERROR_INVALID_PARAMETER
;
3078 InitializeObjectAttributes (&ObjectAttributes
,
3080 OBJ_CASE_INSENSITIVE
,
3084 Status
= NtOpenFile (&FileHandle
,
3089 FILE_SYNCHRONOUS_IO_NONALERT
);
3090 RtlFreeUnicodeString (&FileName
);
3091 if (!NT_SUCCESS(Status
))
3093 return RtlNtStatusToDosError (Status
);
3096 Status
= NtRestoreKey (KeyHandle
,
3099 NtClose (FileHandle
);
3100 if (!NT_SUCCESS(Status
))
3102 return RtlNtStatusToDosError (Status
);
3105 return ERROR_SUCCESS
;
3109 /************************************************************************
3115 RegSaveKeyA (HKEY hKey
,
3117 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3119 UNICODE_STRING FileName
;
3122 RtlCreateUnicodeStringFromAsciiz (&FileName
,
3124 ErrorCode
= RegSaveKeyW (hKey
,
3126 lpSecurityAttributes
);
3127 RtlFreeUnicodeString (&FileName
);
3133 /************************************************************************
3139 RegSaveKeyW (HKEY hKey
,
3141 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
3143 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
3144 OBJECT_ATTRIBUTES ObjectAttributes
;
3145 UNICODE_STRING FileName
;
3146 IO_STATUS_BLOCK IoStatusBlock
;
3151 Status
= MapDefaultKey (&KeyHandle
,
3153 if (!NT_SUCCESS(Status
))
3155 return RtlNtStatusToDosError (Status
);
3158 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
3163 return ERROR_INVALID_PARAMETER
;
3166 if (lpSecurityAttributes
!= NULL
)
3168 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
3171 InitializeObjectAttributes (&ObjectAttributes
,
3173 OBJ_CASE_INSENSITIVE
,
3175 SecurityDescriptor
);
3176 Status
= NtCreateFile (&FileHandle
,
3177 GENERIC_WRITE
| SYNCHRONIZE
,
3181 FILE_ATTRIBUTE_NORMAL
,
3184 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
3187 RtlFreeUnicodeString (&FileName
);
3188 if (!NT_SUCCESS(Status
))
3190 return RtlNtStatusToDosError (Status
);
3193 Status
= NtSaveKey (KeyHandle
,
3195 NtClose (FileHandle
);
3196 if (!NT_SUCCESS(Status
))
3198 return RtlNtStatusToDosError (Status
);
3201 return ERROR_SUCCESS
;
3205 /************************************************************************
3211 RegSetKeySecurity (HKEY hKey
,
3212 SECURITY_INFORMATION SecurityInformation
,
3213 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3218 if (hKey
== HKEY_PERFORMANCE_DATA
)
3220 return ERROR_INVALID_HANDLE
;
3223 Status
= MapDefaultKey (&KeyHandle
,
3225 if (!NT_SUCCESS(Status
))
3227 return RtlNtStatusToDosError (Status
);
3230 Status
= NtSetSecurityObject (KeyHandle
,
3231 SecurityInformation
,
3232 pSecurityDescriptor
);
3233 if (!NT_SUCCESS(Status
))
3235 return RtlNtStatusToDosError (Status
);
3238 return ERROR_SUCCESS
;
3242 /************************************************************************
3248 RegSetValueExA (HKEY hKey
,
3255 UNICODE_STRING ValueName
;
3257 ANSI_STRING AnsiString
;
3258 UNICODE_STRING Data
;
3263 if (lpValueName
!= NULL
&&
3264 strlen(lpValueName
) != 0)
3266 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3268 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3275 if (((dwType
== REG_SZ
) ||
3276 (dwType
== REG_MULTI_SZ
) ||
3277 (dwType
== REG_EXPAND_SZ
)) &&
3280 /* NT adds one if the caller forgot the NULL-termination character */
3281 if (lpData
[cbData
- 1] != '\0')
3286 RtlInitAnsiString (&AnsiString
,
3288 AnsiString
.Buffer
= (PSTR
)lpData
;
3289 AnsiString
.Length
= cbData
- 1;
3290 AnsiString
.MaximumLength
= cbData
;
3291 RtlAnsiStringToUnicodeString (&Data
,
3294 pData
= (LPBYTE
)Data
.Buffer
;
3295 DataSize
= cbData
* sizeof(WCHAR
);
3299 RtlInitUnicodeString (&Data
,
3301 pData
= (LPBYTE
)lpData
;
3305 ErrorCode
= RegSetValueExW (hKey
,
3311 if (pValueName
!= NULL
)
3313 RtlFreeHeap (ProcessHeap
,
3318 if (Data
.Buffer
!= NULL
)
3320 RtlFreeHeap (ProcessHeap
,
3329 /************************************************************************
3335 RegSetValueExW (HKEY hKey
,
3336 LPCWSTR lpValueName
,
3342 UNICODE_STRING ValueName
;
3343 PUNICODE_STRING pValueName
;
3347 Status
= MapDefaultKey (&KeyHandle
,
3349 if (!NT_SUCCESS(Status
))
3351 return RtlNtStatusToDosError (Status
);
3354 if (lpValueName
!= NULL
)
3356 RtlInitUnicodeString (&ValueName
,
3361 RtlInitUnicodeString (&ValueName
, L
"");
3363 pValueName
= &ValueName
;
3365 if (((dwType
== REG_SZ
) ||
3366 (dwType
== REG_MULTI_SZ
) ||
3367 (dwType
== REG_EXPAND_SZ
)) &&
3368 (cbData
!= 0) && (*(((PWCHAR
)lpData
) + (cbData
/ sizeof(WCHAR
)) - 1) != L
'\0'))
3370 /* NT adds one if the caller forgot the NULL-termination character */
3371 cbData
+= sizeof(WCHAR
);
3374 Status
= NtSetValueKey (KeyHandle
,
3380 if (!NT_SUCCESS(Status
))
3382 return RtlNtStatusToDosError (Status
);
3385 return ERROR_SUCCESS
;
3389 /************************************************************************
3395 RegSetValueA (HKEY hKey
,
3404 if (dwType
!= REG_SZ
)
3406 return ERROR_INVALID_PARAMETER
;
3409 if (lpSubKey
!= NULL
&& lpSubKey
[0] != '\0')
3411 ret
= RegCreateKeyA(hKey
,
3415 if (ret
!= ERROR_SUCCESS
)
3423 ret
= RegSetValueExA(hSubKey
,
3427 (CONST BYTE
*)lpData
,
3428 strlen(lpData
) + 1);
3430 if (hSubKey
!= hKey
)
3432 RegCloseKey(hSubKey
);
3439 /************************************************************************
3445 RegSetValueW (HKEY hKey
,
3451 OBJECT_ATTRIBUTES ObjectAttributes
;
3452 UNICODE_STRING SubKeyString
;
3459 Status
= MapDefaultKey (&KeyHandle
,
3461 if (!NT_SUCCESS(Status
))
3463 return RtlNtStatusToDosError (Status
);
3466 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3468 RtlInitUnicodeString (&SubKeyString
,
3470 InitializeObjectAttributes (&ObjectAttributes
,
3472 OBJ_CASE_INSENSITIVE
,
3475 Status
= NtOpenKey (&RealKey
,
3478 if (!NT_SUCCESS(Status
))
3480 return RtlNtStatusToDosError (Status
);
3482 CloseRealKey
= TRUE
;
3487 CloseRealKey
= FALSE
;
3490 ErrorCode
= RegSetValueExW (RealKey
,
3496 if (CloseRealKey
== TRUE
)
3505 /************************************************************************
3511 RegUnLoadKeyA (HKEY hKey
,
3514 UNICODE_STRING KeyName
;
3517 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3520 ErrorCode
= RegUnLoadKeyW (hKey
,
3523 RtlFreeUnicodeString (&KeyName
);
3529 /************************************************************************
3535 RegUnLoadKeyW (HKEY hKey
,
3538 OBJECT_ATTRIBUTES ObjectAttributes
;
3539 UNICODE_STRING KeyName
;
3543 if (hKey
== HKEY_PERFORMANCE_DATA
)
3545 return ERROR_INVALID_HANDLE
;
3548 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3549 if (!NT_SUCCESS(Status
))
3551 return RtlNtStatusToDosError (Status
);
3554 RtlInitUnicodeString (&KeyName
,
3557 InitializeObjectAttributes (&ObjectAttributes
,
3559 OBJ_CASE_INSENSITIVE
,
3563 Status
= NtUnloadKey (&ObjectAttributes
);
3565 if (!NT_SUCCESS(Status
))
3567 return RtlNtStatusToDosError (Status
);
3570 return ERROR_SUCCESS
;