1 /* $Id: reg.c,v 1.54 2004/08/15 17:03:14 chorns Exp $
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)
13 /* INCLUDES *****************************************************************/
19 /* DEFINES ******************************************************************/
21 #define MAX_DEFAULT_HANDLES 6
22 #define REG_MAX_NAME_SIZE 256
23 #define REG_MAX_DATA_SIZE 2048
25 /* GLOBALS ******************************************************************/
27 static CRITICAL_SECTION HandleTableCS
;
28 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
29 static HANDLE ProcessHeap
;
31 /* PROTOTYPES ***************************************************************/
33 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
34 static VOID
CloseDefaultKeys(VOID
);
36 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
37 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
38 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
39 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
42 /* FUNCTIONS ****************************************************************/
44 /************************************************************************
45 * RegInitDefaultHandles
50 DPRINT("RegInitialize()\n");
52 ProcessHeap
= RtlGetProcessHeap();
53 RtlZeroMemory (DefaultHandleTable
,
54 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
55 RtlInitializeCriticalSection (&HandleTableCS
);
61 /************************************************************************
67 DPRINT("RegCleanup()\n");
70 RtlDeleteCriticalSection (&HandleTableCS
);
77 MapDefaultKey (PHANDLE RealKey
,
82 NTSTATUS Status
= STATUS_SUCCESS
;
84 DPRINT("MapDefaultKey (Key %x)\n", Key
);
86 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
88 *RealKey
= (HANDLE
)Key
;
89 return STATUS_SUCCESS
;
92 /* Handle special cases here */
93 Index
= (ULONG
)Key
& 0x0FFFFFFF;
94 if (Index
>= MAX_DEFAULT_HANDLES
)
96 return STATUS_INVALID_PARAMETER
;
99 RtlEnterCriticalSection (&HandleTableCS
);
100 Handle
= &DefaultHandleTable
[Index
];
103 /* create/open the default handle */
106 case 0: /* HKEY_CLASSES_ROOT */
107 Status
= OpenClassesRootKey (Handle
);
110 case 1: /* HKEY_CURRENT_USER */
111 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
115 case 2: /* HKEY_LOCAL_MACHINE */
116 Status
= OpenLocalMachineKey (Handle
);
119 case 3: /* HKEY_USERS */
120 Status
= OpenUsersKey (Handle
);
123 case 4: /* HKEY_PERFORMANCE_DATA */
124 Status
= OpenPerformanceDataKey (Handle
);
127 case 5: /* HKEY_CURRENT_CONFIG */
128 Status
= OpenCurrentConfigKey (Handle
);
131 case 6: /* HKEY_DYN_DATA */
132 Status
= STATUS_NOT_IMPLEMENTED
;
136 DPRINT("MapDefaultHandle() no handle creator\n");
137 Status
= STATUS_INVALID_PARAMETER
;
140 RtlLeaveCriticalSection (&HandleTableCS
);
142 if (NT_SUCCESS(Status
))
152 CloseDefaultKeys (VOID
)
156 RtlEnterCriticalSection (&HandleTableCS
);
157 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
159 if (DefaultHandleTable
[i
] != NULL
)
161 NtClose (DefaultHandleTable
[i
]);
162 DefaultHandleTable
[i
] = NULL
;
165 RtlLeaveCriticalSection (&HandleTableCS
);
170 OpenClassesRootKey (PHANDLE KeyHandle
)
172 OBJECT_ATTRIBUTES Attributes
;
173 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\Software\\CLASSES");
175 DPRINT("OpenClassesRootKey()\n");
177 InitializeObjectAttributes (&Attributes
,
179 OBJ_CASE_INSENSITIVE
,
182 return NtOpenKey (KeyHandle
,
189 OpenLocalMachineKey (PHANDLE KeyHandle
)
191 OBJECT_ATTRIBUTES Attributes
;
192 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine");
195 DPRINT("OpenLocalMachineKey()\n");
197 InitializeObjectAttributes (&Attributes
,
199 OBJ_CASE_INSENSITIVE
,
202 Status
= NtOpenKey (KeyHandle
,
206 DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
212 OpenUsersKey (PHANDLE KeyHandle
)
214 OBJECT_ATTRIBUTES Attributes
;
215 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\User");
217 DPRINT("OpenUsersKey()\n");
219 InitializeObjectAttributes (&Attributes
,
221 OBJ_CASE_INSENSITIVE
,
224 return NtOpenKey (KeyHandle
,
231 OpenCurrentConfigKey (PHANDLE KeyHandle
)
233 OBJECT_ATTRIBUTES Attributes
;
234 UNICODE_STRING KeyName
=
235 ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
237 DPRINT("OpenCurrentConfigKey()\n");
239 InitializeObjectAttributes (&Attributes
,
241 OBJ_CASE_INSENSITIVE
,
244 return NtOpenKey (KeyHandle
,
250 /************************************************************************
256 RegCloseKey (HKEY hKey
)
261 /* don't close null handle or a pseudo handle */
262 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
264 return ERROR_INVALID_HANDLE
;
267 Status
= NtClose (hKey
);
268 if (!NT_SUCCESS(Status
))
270 ErrorCode
= RtlNtStatusToDosError (Status
);
271 SetLastError (ErrorCode
);
275 return ERROR_SUCCESS
;
279 /************************************************************************
280 * RegConnectRegistryA
285 RegConnectRegistryA (LPCSTR lpMachineName
,
289 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
290 return ERROR_CALL_NOT_IMPLEMENTED
;
294 /************************************************************************
295 * RegConnectRegistryW
300 RegConnectRegistryW (LPCWSTR lpMachineName
,
304 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
305 return ERROR_CALL_NOT_IMPLEMENTED
;
309 /************************************************************************
312 * Create key and all necessary intermediate keys
315 CreateNestedKey(PHKEY KeyHandle
,
316 POBJECT_ATTRIBUTES ObjectAttributes
,
317 PUNICODE_STRING ClassString
,
320 DWORD
*lpdwDisposition
)
322 OBJECT_ATTRIBUTES LocalObjectAttributes
;
323 UNICODE_STRING LocalKeyName
;
326 ULONG FullNameLength
;
329 HANDLE LocalKeyHandle
;
331 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
337 (PULONG
)lpdwDisposition
);
338 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
339 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
342 /* Copy object attributes */
343 RtlCopyMemory (&LocalObjectAttributes
,
345 sizeof(OBJECT_ATTRIBUTES
));
346 RtlCreateUnicodeString (&LocalKeyName
,
347 ObjectAttributes
->ObjectName
->Buffer
);
348 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
349 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
351 /* Remove the last part of the key name and try to create the key again. */
352 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
354 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
355 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
357 Status
= STATUS_UNSUCCESSFUL
;
361 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
363 Status
= NtCreateKey (&LocalKeyHandle
,
365 &LocalObjectAttributes
,
370 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
373 if (!NT_SUCCESS(Status
))
375 RtlFreeUnicodeString (&LocalKeyName
);
379 /* Add removed parts of the key name and create them too. */
380 Length
= wcslen (LocalKeyName
.Buffer
);
383 NtClose (LocalKeyHandle
);
385 LocalKeyName
.Buffer
[Length
] = L
'\\';
386 Length
= wcslen (LocalKeyName
.Buffer
);
387 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
389 if (Length
== FullNameLength
)
391 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
397 (PULONG
)lpdwDisposition
);
400 Status
= NtCreateKey (&LocalKeyHandle
,
402 &LocalObjectAttributes
,
407 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
408 if (!NT_SUCCESS(Status
))
412 RtlFreeUnicodeString (&LocalKeyName
);
418 /************************************************************************
424 RegCreateKeyExA (HKEY hKey
,
430 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
432 LPDWORD lpdwDisposition
)
434 UNICODE_STRING SubKeyString
;
435 UNICODE_STRING ClassString
;
436 OBJECT_ATTRIBUTES Attributes
;
441 DPRINT("RegCreateKeyExA() called\n");
443 /* get the real parent key */
444 Status
= MapDefaultKey (&ParentKey
,
446 if (!NT_SUCCESS(Status
))
448 ErrorCode
= RtlNtStatusToDosError (Status
);
449 SetLastError (ErrorCode
);
452 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
456 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
459 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
461 InitializeObjectAttributes (&Attributes
,
463 OBJ_CASE_INSENSITIVE
,
465 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
466 Status
= CreateNestedKey(phkResult
,
468 (lpClass
== NULL
)? NULL
: &ClassString
,
472 RtlFreeUnicodeString (&SubKeyString
);
475 RtlFreeUnicodeString (&ClassString
);
477 DPRINT("Status %x\n", Status
);
478 if (!NT_SUCCESS(Status
))
480 ErrorCode
= RtlNtStatusToDosError (Status
);
481 SetLastError (ErrorCode
);
485 return ERROR_SUCCESS
;
489 /************************************************************************
495 RegCreateKeyExW (HKEY hKey
,
501 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
503 LPDWORD lpdwDisposition
)
505 UNICODE_STRING SubKeyString
;
506 UNICODE_STRING ClassString
;
507 OBJECT_ATTRIBUTES Attributes
;
512 DPRINT("RegCreateKeyExW() called\n");
514 /* get the real parent key */
515 Status
= MapDefaultKey (&ParentKey
,
517 if (!NT_SUCCESS(Status
))
519 ErrorCode
= RtlNtStatusToDosError(Status
);
520 SetLastError (ErrorCode
);
523 DPRINT("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 DPRINT("Status %x\n", Status
);
541 if (!NT_SUCCESS(Status
))
543 ErrorCode
= RtlNtStatusToDosError (Status
);
544 SetLastError (ErrorCode
);
548 return ERROR_SUCCESS
;
552 /************************************************************************
558 RegCreateKeyA (HKEY hKey
,
562 return RegCreateKeyExA (hKey
,
574 /************************************************************************
580 RegCreateKeyW (HKEY hKey
,
584 return RegCreateKeyExW (hKey
,
596 /************************************************************************
602 RegDeleteKeyA (HKEY hKey
,
605 OBJECT_ATTRIBUTES ObjectAttributes
;
606 UNICODE_STRING SubKeyName
;
612 Status
= MapDefaultKey (&ParentKey
,
614 if (!NT_SUCCESS(Status
))
616 ErrorCode
= RtlNtStatusToDosError (Status
);
617 SetLastError (ErrorCode
);
621 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
623 InitializeObjectAttributes(&ObjectAttributes
,
625 OBJ_CASE_INSENSITIVE
,
629 Status
= NtOpenKey (&TargetKey
,
632 RtlFreeUnicodeString (&SubKeyName
);
633 if (!NT_SUCCESS(Status
))
635 ErrorCode
= RtlNtStatusToDosError (Status
);
636 SetLastError (ErrorCode
);
640 Status
= NtDeleteKey (TargetKey
);
642 if (!NT_SUCCESS(Status
))
644 ErrorCode
= RtlNtStatusToDosError(Status
);
645 SetLastError (ErrorCode
);
649 return ERROR_SUCCESS
;
653 /************************************************************************
659 RegDeleteKeyW (HKEY hKey
,
662 OBJECT_ATTRIBUTES ObjectAttributes
;
663 UNICODE_STRING SubKeyName
;
669 Status
= MapDefaultKey (&ParentKey
,
671 if (!NT_SUCCESS(Status
))
673 ErrorCode
= RtlNtStatusToDosError (Status
);
674 SetLastError (ErrorCode
);
678 RtlInitUnicodeString (&SubKeyName
,
680 InitializeObjectAttributes (&ObjectAttributes
,
682 OBJ_CASE_INSENSITIVE
,
685 Status
= NtOpenKey (&TargetKey
,
688 if (!NT_SUCCESS(Status
))
690 ErrorCode
= RtlNtStatusToDosError (Status
);
691 SetLastError (ErrorCode
);
695 Status
= NtDeleteKey (TargetKey
);
697 if (!NT_SUCCESS(Status
))
699 ErrorCode
= RtlNtStatusToDosError (Status
);
700 SetLastError (ErrorCode
);
704 return ERROR_SUCCESS
;
708 /************************************************************************
714 RegDeleteValueA (HKEY hKey
,
717 UNICODE_STRING ValueName
;
722 Status
= MapDefaultKey (&KeyHandle
,
724 if (!NT_SUCCESS(Status
))
726 ErrorCode
= RtlNtStatusToDosError (Status
);
727 SetLastError (ErrorCode
);
731 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
733 Status
= NtDeleteValueKey (KeyHandle
,
735 RtlFreeUnicodeString (&ValueName
);
736 if (!NT_SUCCESS(Status
))
738 ErrorCode
= RtlNtStatusToDosError (Status
);
739 SetLastError (ErrorCode
);
743 return ERROR_SUCCESS
;
747 /************************************************************************
753 RegDeleteValueW (HKEY hKey
,
756 UNICODE_STRING ValueName
;
761 Status
= MapDefaultKey (&KeyHandle
,
763 if (!NT_SUCCESS(Status
))
765 ErrorCode
= RtlNtStatusToDosError (Status
);
766 SetLastError (ErrorCode
);
770 RtlInitUnicodeString (&ValueName
,
771 (LPWSTR
)lpValueName
);
773 Status
= NtDeleteValueKey (KeyHandle
,
775 if (!NT_SUCCESS(Status
))
777 ErrorCode
= RtlNtStatusToDosError (Status
);
778 SetLastError (ErrorCode
);
782 return ERROR_SUCCESS
;
786 /************************************************************************
792 RegEnumKeyA (HKEY hKey
,
800 return RegEnumKeyExA (hKey
,
811 /************************************************************************
817 RegEnumKeyW (HKEY hKey
,
825 return RegEnumKeyExW (hKey
,
836 /************************************************************************
842 RegEnumKeyExA (HKEY hKey
,
849 PFILETIME lpftLastWriteTime
)
853 KEY_NODE_INFORMATION Node
;
854 KEY_BASIC_INFORMATION Basic
;
857 UNICODE_STRING StringU
;
859 LONG ErrorCode
= ERROR_SUCCESS
;
861 DWORD ClassLength
= 0;
867 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
868 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
870 if ((lpClass
) && (!lpcbClass
))
872 SetLastError (ERROR_INVALID_PARAMETER
);
873 return ERROR_INVALID_PARAMETER
;
876 Status
= MapDefaultKey(&KeyHandle
,
878 if (!NT_SUCCESS(Status
))
880 ErrorCode
= RtlNtStatusToDosError (Status
);
881 SetLastError (ErrorCode
);
887 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
898 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
905 /* The class name should start at a dword boundary */
906 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
910 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
913 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
918 SetLastError (ERROR_OUTOFMEMORY
);
919 return ERROR_OUTOFMEMORY
;
922 Status
= NtEnumerateKey (KeyHandle
,
924 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
928 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
929 if (!NT_SUCCESS(Status
))
931 ErrorCode
= RtlNtStatusToDosError (Status
);
937 if (KeyInfo
->Basic
.NameLength
> NameLength
)
939 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
943 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
944 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
945 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
950 if (KeyInfo
->Node
.NameLength
> NameLength
||
951 KeyInfo
->Node
.ClassLength
> ClassLength
)
953 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
957 StringA
.Buffer
= lpClass
;
959 StringA
.MaximumLength
= *lpcbClass
;
960 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
961 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
962 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
963 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
964 lpClass
[StringA
.Length
] = 0;
965 *lpcbClass
= StringA
.Length
;
966 StringU
.Buffer
= KeyInfo
->Node
.Name
;
967 StringU
.Length
= KeyInfo
->Node
.NameLength
;
968 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
972 if (ErrorCode
== ERROR_SUCCESS
)
974 StringA
.Buffer
= lpName
;
976 StringA
.MaximumLength
= *lpcbName
;
977 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
978 lpName
[StringA
.Length
] = 0;
979 *lpcbName
= StringA
.Length
;
980 if (lpftLastWriteTime
!= NULL
)
984 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
985 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
989 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
990 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
996 DPRINT("Key Namea0 Length %d\n", StringU
.Length
);
997 DPRINT("Key Namea1 Length %d\n", NameLength
);
998 DPRINT("Key Namea Length %d\n", *lpcbName
);
999 DPRINT("Key Namea %s\n", lpName
);
1001 RtlFreeHeap (ProcessHeap
,
1005 if (ErrorCode
!= ERROR_SUCCESS
)
1007 SetLastError(ErrorCode
);
1014 /************************************************************************
1020 RegEnumKeyExW (HKEY hKey
,
1027 PFILETIME lpftLastWriteTime
)
1031 KEY_NODE_INFORMATION Node
;
1032 KEY_BASIC_INFORMATION Basic
;
1038 ULONG ClassLength
= 0;
1040 LONG ErrorCode
= ERROR_SUCCESS
;
1043 Status
= MapDefaultKey(&KeyHandle
,
1045 if (!NT_SUCCESS(Status
))
1047 ErrorCode
= RtlNtStatusToDosError (Status
);
1048 SetLastError (ErrorCode
);
1054 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1065 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1072 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1076 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1079 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1082 if (KeyInfo
== NULL
)
1084 SetLastError (ERROR_OUTOFMEMORY
);
1085 return ERROR_OUTOFMEMORY
;
1088 Status
= NtEnumerateKey (KeyHandle
,
1090 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1094 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
1095 if (!NT_SUCCESS(Status
))
1097 ErrorCode
= RtlNtStatusToDosError (Status
);
1101 if (lpClass
== NULL
)
1103 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1105 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1109 RtlCopyMemory (lpName
,
1110 KeyInfo
->Basic
.Name
,
1111 KeyInfo
->Basic
.NameLength
);
1112 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1113 lpName
[*lpcbName
] = 0;
1118 if (KeyInfo
->Node
.NameLength
> NameLength
||
1119 KeyInfo
->Node
.ClassLength
> ClassLength
)
1121 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1125 RtlCopyMemory (lpName
,
1127 KeyInfo
->Node
.NameLength
);
1128 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1129 lpName
[*lpcbName
] = 0;
1130 RtlCopyMemory (lpClass
,
1131 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1132 KeyInfo
->Node
.ClassLength
);
1133 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1134 lpClass
[*lpcbClass
] = 0;
1138 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1140 if (lpClass
== NULL
)
1142 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1143 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1147 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1148 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1153 RtlFreeHeap (ProcessHeap
,
1157 if (ErrorCode
!= ERROR_SUCCESS
)
1159 SetLastError(ErrorCode
);
1166 /************************************************************************
1172 RegEnumValueA (HKEY hKey
,
1175 LPDWORD lpcbValueName
,
1183 KEY_VALUE_FULL_INFORMATION Full
;
1184 KEY_VALUE_BASIC_INFORMATION Basic
;
1189 ULONG DataLength
= 0;
1194 UNICODE_STRING StringU
;
1195 ANSI_STRING StringA
;
1198 ErrorCode
= ERROR_SUCCESS
;
1200 Status
= MapDefaultKey (&KeyHandle
,
1202 if (!NT_SUCCESS(Status
))
1204 ErrorCode
= RtlNtStatusToDosError (Status
);
1205 SetLastError (ErrorCode
);
1209 if (*lpcbValueName
> 0)
1211 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1220 DataLength
= min (*lpcbData
* sizeof(WCHAR
), REG_MAX_DATA_SIZE
);
1221 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1225 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1228 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1231 if (ValueInfo
== NULL
)
1233 SetLastError(ERROR_OUTOFMEMORY
);
1234 return ERROR_OUTOFMEMORY
;
1237 Status
= NtEnumerateValueKey (KeyHandle
,
1239 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1244 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1245 if (!NT_SUCCESS(Status
))
1247 ErrorCode
= RtlNtStatusToDosError (Status
);
1253 IsStringType
= (ValueInfo
->Full
.Type
== REG_SZ
) ||
1254 (ValueInfo
->Full
.Type
== REG_MULTI_SZ
) ||
1255 (ValueInfo
->Full
.Type
== REG_EXPAND_SZ
);
1256 if (ValueInfo
->Full
.NameLength
> NameLength
||
1257 (!IsStringType
&& ValueInfo
->Full
.DataLength
> *lpcbData
) ||
1258 ValueInfo
->Full
.DataLength
> DataLength
)
1260 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1266 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
);
1267 StringU
.Length
= ValueInfo
->Full
.DataLength
;
1268 StringU
.MaximumLength
= DataLength
;
1269 StringA
.Buffer
= (PCHAR
)lpData
;
1271 StringA
.MaximumLength
= *lpcbData
;
1272 RtlUnicodeStringToAnsiString (&StringA
,
1275 *lpcbData
= StringA
.Length
;
1279 RtlCopyMemory (lpData
,
1280 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1281 ValueInfo
->Full
.DataLength
);
1282 *lpcbData
= ValueInfo
->Full
.DataLength
;
1285 StringU
.Buffer
= ValueInfo
->Full
.Name
;
1286 StringU
.Length
= ValueInfo
->Full
.NameLength
;
1287 StringU
.MaximumLength
= NameLength
;
1292 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1294 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1298 StringU
.Buffer
= ValueInfo
->Basic
.Name
;
1299 StringU
.Length
= ValueInfo
->Basic
.NameLength
;
1300 StringU
.MaximumLength
= NameLength
;
1304 if (ErrorCode
== ERROR_SUCCESS
)
1306 StringA
.Buffer
= (PCHAR
)lpValueName
;
1308 StringA
.MaximumLength
= *lpcbValueName
;
1309 RtlUnicodeStringToAnsiString (&StringA
,
1312 StringA
.Buffer
[StringA
.Length
] = 0;
1313 *lpcbValueName
= StringA
.Length
;
1316 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1321 RtlFreeHeap (ProcessHeap
,
1324 if (ErrorCode
!= ERROR_SUCCESS
)
1326 SetLastError(ErrorCode
);
1333 /************************************************************************
1339 RegEnumValueW (HKEY hKey
,
1342 LPDWORD lpcbValueName
,
1350 KEY_VALUE_FULL_INFORMATION Full
;
1351 KEY_VALUE_BASIC_INFORMATION Basic
;
1356 ULONG DataLength
= 0;
1362 ErrorCode
= ERROR_SUCCESS
;
1364 Status
= MapDefaultKey (&KeyHandle
,
1366 if (!NT_SUCCESS(Status
))
1368 ErrorCode
= RtlNtStatusToDosError (Status
);
1369 SetLastError (ErrorCode
);
1373 if (*lpcbValueName
> 0)
1375 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1384 DataLength
= min(*lpcbData
, REG_MAX_DATA_SIZE
);
1385 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1389 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1391 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1394 if (ValueInfo
== NULL
)
1396 SetLastError (ERROR_OUTOFMEMORY
);
1397 return ERROR_OUTOFMEMORY
;
1399 Status
= NtEnumerateValueKey (KeyHandle
,
1401 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1406 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1407 if (!NT_SUCCESS(Status
))
1409 ErrorCode
= RtlNtStatusToDosError (Status
);
1415 if (ValueInfo
->Full
.DataLength
> DataLength
||
1416 ValueInfo
->Full
.NameLength
> NameLength
)
1418 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1422 RtlCopyMemory (lpValueName
,
1423 ValueInfo
->Full
.Name
,
1424 ValueInfo
->Full
.NameLength
);
1425 *lpcbValueName
= (DWORD
)(ValueInfo
->Full
.NameLength
/ sizeof(WCHAR
));
1426 lpValueName
[*lpcbValueName
] = 0;
1427 RtlCopyMemory (lpData
,
1428 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1429 ValueInfo
->Full
.DataLength
);
1430 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1435 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1437 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1441 RtlCopyMemory (lpValueName
,
1442 ValueInfo
->Basic
.Name
,
1443 ValueInfo
->Basic
.NameLength
);
1444 *lpcbValueName
= (DWORD
)(ValueInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1445 lpValueName
[*lpcbValueName
] = 0;
1447 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1450 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1452 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1456 RtlFreeHeap (ProcessHeap
,
1460 if (ErrorCode
!= ERROR_SUCCESS
)
1462 SetLastError (ErrorCode
);
1469 /************************************************************************
1475 RegFlushKey(HKEY hKey
)
1481 if (hKey
== HKEY_PERFORMANCE_DATA
)
1483 return ERROR_SUCCESS
;
1486 Status
= MapDefaultKey (&KeyHandle
,
1488 if (!NT_SUCCESS(Status
))
1490 ErrorCode
= RtlNtStatusToDosError (Status
);
1491 SetLastError (ErrorCode
);
1495 Status
= NtFlushKey (KeyHandle
);
1496 if (!NT_SUCCESS(Status
))
1498 ErrorCode
= RtlNtStatusToDosError (Status
);
1499 SetLastError (ErrorCode
);
1503 return ERROR_SUCCESS
;
1507 /************************************************************************
1513 RegGetKeySecurity (HKEY hKey
,
1514 SECURITY_INFORMATION SecurityInformation
,
1515 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1516 LPDWORD lpcbSecurityDescriptor
)
1523 if (hKey
= HKEY_PERFORMANCE_DATA
)
1525 return ERROR_INVALID_HANDLE
;
1528 Status
= MapDefaultKey (&KeyHandle
,
1530 if (!NT_SUCCESS(Status
))
1532 ErrorCode
= RtlNtStatusToDosError (Status
);
1533 SetLastError (ErrorCode
);
1537 Status
= NtQuerySecurityObject ()
1538 if (!NT_SUCCESS(Status
))
1540 ErrorCode
= RtlNtStatusToDosError (Status
);
1541 SetLastError (ErrorCode
);
1545 return ERROR_SUCCESS
;
1549 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1550 return ERROR_CALL_NOT_IMPLEMENTED
;
1554 /************************************************************************
1560 RegLoadKeyA (HKEY hKey
,
1564 UNICODE_STRING FileName
;
1565 UNICODE_STRING KeyName
;
1568 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1570 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1573 ErrorCode
= RegLoadKeyW (hKey
,
1577 RtlFreeUnicodeString (&FileName
);
1578 RtlFreeUnicodeString (&KeyName
);
1584 /************************************************************************
1590 RegLoadKeyW (HKEY hKey
,
1594 OBJECT_ATTRIBUTES FileObjectAttributes
;
1595 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1596 UNICODE_STRING FileName
;
1597 UNICODE_STRING KeyName
;
1602 if (hKey
== HKEY_PERFORMANCE_DATA
)
1604 return ERROR_INVALID_HANDLE
;
1607 Status
= MapDefaultKey (&KeyHandle
,
1609 if (!NT_SUCCESS(Status
))
1611 ErrorCode
= RtlNtStatusToDosError (Status
);
1612 SetLastError (ErrorCode
);
1616 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1621 SetLastError (ERROR_BAD_PATHNAME
);
1622 return ERROR_BAD_PATHNAME
;
1625 InitializeObjectAttributes (&FileObjectAttributes
,
1627 OBJ_CASE_INSENSITIVE
,
1631 RtlInitUnicodeString (&KeyName
,
1634 InitializeObjectAttributes (&KeyObjectAttributes
,
1636 OBJ_CASE_INSENSITIVE
,
1640 Status
= NtLoadKey (&KeyObjectAttributes
,
1641 &FileObjectAttributes
);
1643 RtlFreeUnicodeString (&FileName
);
1645 if (!NT_SUCCESS(Status
))
1647 ErrorCode
= RtlNtStatusToDosError (Status
);
1648 SetLastError (ErrorCode
);
1652 return ERROR_SUCCESS
;
1656 /************************************************************************
1657 * RegNotifyChangeKeyValue
1662 RegNotifyChangeKeyValue (HKEY hKey
,
1664 DWORD dwNotifyFilter
,
1668 IO_STATUS_BLOCK IoStatusBlock
;
1672 if (hKey
== HKEY_PERFORMANCE_DATA
)
1674 return ERROR_INVALID_HANDLE
;
1677 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1679 return ERROR_INVALID_PARAMETER
;
1682 Status
= MapDefaultKey (&KeyHandle
,
1684 if (!NT_SUCCESS(Status
))
1686 return RtlNtStatusToDosError (Status
);
1689 /* FIXME: Remote key handles must fail */
1691 Status
= NtNotifyChangeKey (KeyHandle
,
1701 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1703 return RtlNtStatusToDosError (Status
);
1706 return ERROR_SUCCESS
;
1710 /************************************************************************
1716 RegOpenKeyA (HKEY hKey
,
1720 OBJECT_ATTRIBUTES ObjectAttributes
;
1721 UNICODE_STRING SubKeyString
;
1726 Status
= MapDefaultKey (&KeyHandle
,
1728 if (!NT_SUCCESS(Status
))
1730 ErrorCode
= RtlNtStatusToDosError (Status
);
1731 SetLastError (ErrorCode
);
1735 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1737 InitializeObjectAttributes (&ObjectAttributes
,
1739 OBJ_CASE_INSENSITIVE
,
1742 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1745 RtlFreeUnicodeString (&SubKeyString
);
1746 if (!NT_SUCCESS(Status
))
1748 ErrorCode
= RtlNtStatusToDosError (Status
);
1749 SetLastError (ErrorCode
);
1753 return ERROR_SUCCESS
;
1757 /************************************************************************
1766 RegOpenKeyW (HKEY hKey
,
1770 OBJECT_ATTRIBUTES ObjectAttributes
;
1771 UNICODE_STRING SubKeyString
;
1776 Status
= MapDefaultKey (&KeyHandle
,
1778 if (!NT_SUCCESS(Status
))
1780 ErrorCode
= RtlNtStatusToDosError (Status
);
1781 SetLastError (ErrorCode
);
1785 RtlInitUnicodeString (&SubKeyString
,
1787 InitializeObjectAttributes (&ObjectAttributes
,
1789 OBJ_CASE_INSENSITIVE
,
1792 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1795 if (!NT_SUCCESS(Status
))
1797 ErrorCode
= RtlNtStatusToDosError (Status
);
1798 SetLastError(ErrorCode
);
1802 return ERROR_SUCCESS
;
1806 /************************************************************************
1812 RegOpenKeyExA (HKEY hKey
,
1818 OBJECT_ATTRIBUTES ObjectAttributes
;
1819 UNICODE_STRING SubKeyString
;
1824 Status
= MapDefaultKey (&KeyHandle
,
1826 if (!NT_SUCCESS(Status
))
1828 ErrorCode
= RtlNtStatusToDosError (Status
);
1829 SetLastError (ErrorCode
);
1833 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1835 InitializeObjectAttributes (&ObjectAttributes
,
1837 OBJ_CASE_INSENSITIVE
,
1840 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1843 RtlFreeUnicodeString (&SubKeyString
);
1844 if (!NT_SUCCESS(Status
))
1846 ErrorCode
= RtlNtStatusToDosError (Status
);
1847 SetLastError (ErrorCode
);
1851 return ERROR_SUCCESS
;
1855 /************************************************************************
1861 RegOpenKeyExW (HKEY hKey
,
1867 OBJECT_ATTRIBUTES ObjectAttributes
;
1868 UNICODE_STRING SubKeyString
;
1873 Status
= MapDefaultKey (&KeyHandle
,
1875 if (!NT_SUCCESS(Status
))
1877 ErrorCode
= RtlNtStatusToDosError (Status
);
1878 SetLastError (ErrorCode
);
1882 if (lpSubKey
!= NULL
)
1884 RtlInitUnicodeString (&SubKeyString
,
1889 RtlInitUnicodeString (&SubKeyString
,
1892 InitializeObjectAttributes (&ObjectAttributes
,
1894 OBJ_CASE_INSENSITIVE
,
1897 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1900 if (!NT_SUCCESS(Status
))
1902 ErrorCode
= RtlNtStatusToDosError (Status
);
1903 SetLastError (ErrorCode
);
1907 return ERROR_SUCCESS
;
1911 /************************************************************************
1917 RegQueryInfoKeyA (HKEY hKey
,
1922 LPDWORD lpcbMaxSubKeyLen
,
1923 LPDWORD lpcbMaxClassLen
,
1925 LPDWORD lpcbMaxValueNameLen
,
1926 LPDWORD lpcbMaxValueLen
,
1927 LPDWORD lpcbSecurityDescriptor
,
1928 PFILETIME lpftLastWriteTime
)
1930 WCHAR ClassName
[MAX_PATH
];
1931 UNICODE_STRING UnicodeString
;
1932 ANSI_STRING AnsiString
;
1935 RtlInitUnicodeString (&UnicodeString
,
1937 if (lpClass
!= NULL
)
1939 UnicodeString
.Buffer
= &ClassName
[0];
1940 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1941 AnsiString
.MaximumLength
= *lpcbClass
;
1944 ErrorCode
= RegQueryInfoKeyW (hKey
,
1945 UnicodeString
.Buffer
,
1952 lpcbMaxValueNameLen
,
1954 lpcbSecurityDescriptor
,
1956 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1958 AnsiString
.Buffer
= lpClass
;
1959 AnsiString
.Length
= 0;
1960 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1961 RtlUnicodeStringToAnsiString (&AnsiString
,
1964 *lpcbClass
= AnsiString
.Length
;
1965 lpClass
[AnsiString
.Length
] = 0;
1972 /************************************************************************
1978 RegQueryInfoKeyW (HKEY hKey
,
1983 LPDWORD lpcbMaxSubKeyLen
,
1984 LPDWORD lpcbMaxClassLen
,
1986 LPDWORD lpcbMaxValueNameLen
,
1987 LPDWORD lpcbMaxValueLen
,
1988 LPDWORD lpcbSecurityDescriptor
,
1989 PFILETIME lpftLastWriteTime
)
1991 KEY_FULL_INFORMATION FullInfoBuffer
;
1992 PKEY_FULL_INFORMATION FullInfo
;
1994 ULONG ClassLength
= 0;
1997 LONG ErrorCode
= ERROR_SUCCESS
;
2000 if ((lpClass
) && (!lpcbClass
))
2002 SetLastError(ERROR_INVALID_PARAMETER
);
2003 return ERROR_INVALID_PARAMETER
;
2006 Status
= MapDefaultKey (&KeyHandle
,
2008 if (!NT_SUCCESS(Status
))
2010 ErrorCode
= RtlNtStatusToDosError (Status
);
2011 SetLastError (ErrorCode
);
2015 if (lpClass
!= NULL
)
2019 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2026 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2027 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2030 if (FullInfo
== NULL
)
2032 SetLastError (ERROR_OUTOFMEMORY
);
2033 return ERROR_OUTOFMEMORY
;
2036 FullInfo
->ClassLength
= ClassLength
;
2040 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2041 FullInfo
= &FullInfoBuffer
;
2042 FullInfo
->ClassLength
= 0;
2044 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2046 Status
= NtQueryKey (KeyHandle
,
2051 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
2052 if (!NT_SUCCESS(Status
))
2054 if (lpClass
!= NULL
)
2056 RtlFreeHeap (ProcessHeap
,
2061 ErrorCode
= RtlNtStatusToDosError (Status
);
2062 SetLastError (ErrorCode
);
2066 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
2067 if (lpcSubKeys
!= NULL
)
2069 *lpcSubKeys
= FullInfo
->SubKeys
;
2072 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2073 if (lpcbMaxSubKeyLen
!= NULL
)
2075 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2078 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2079 if (lpcbMaxClassLen
!= NULL
)
2081 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2084 DPRINT("Values %lu\n", FullInfo
->Values
);
2085 if (lpcValues
!= NULL
)
2087 *lpcValues
= FullInfo
->Values
;
2090 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2091 if (lpcbMaxValueNameLen
!= NULL
)
2093 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2096 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2097 if (lpcbMaxValueLen
!= NULL
)
2099 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2102 if (lpcbSecurityDescriptor
!= NULL
)
2105 *lpcbSecurityDescriptor
= 0;
2108 if (lpftLastWriteTime
!= NULL
)
2110 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2111 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2114 if (lpClass
!= NULL
)
2116 if (FullInfo
->ClassLength
> ClassLength
)
2118 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2122 RtlCopyMemory (lpClass
,
2124 FullInfo
->ClassLength
);
2125 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2126 lpClass
[*lpcbClass
] = 0;
2129 RtlFreeHeap (ProcessHeap
,
2134 if (ErrorCode
!= ERROR_SUCCESS
)
2136 SetLastError (ErrorCode
);
2143 /************************************************************************
2144 * RegQueryMultipleValuesA
2149 RegQueryMultipleValuesA (HKEY hKey
,
2156 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2157 return ERROR_CALL_NOT_IMPLEMENTED
;
2161 /************************************************************************
2162 * RegQueryMultipleValuesW
2167 RegQueryMultipleValuesW (HKEY hKey
,
2174 DWORD maxBytes
= *ldwTotsize
;
2175 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2178 if (maxBytes
>= (1024*1024))
2179 return ERROR_TRANSFER_TOO_LONG
;
2183 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2184 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2186 for (i
= 0; i
< num_vals
; ++i
)
2188 val_list
[i
].ve_valuelen
= 0;
2189 ErrorCode
= RegQueryValueExW (hKey
,
2190 val_list
[i
].ve_valuename
,
2194 &val_list
[i
].ve_valuelen
);
2195 if (ErrorCode
!= ERROR_SUCCESS
)
2200 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2202 ErrorCode
= RegQueryValueExW (hKey
,
2203 val_list
[i
].ve_valuename
,
2205 &val_list
[i
].ve_type
,
2207 &val_list
[i
].ve_valuelen
);
2208 if (ErrorCode
!= ERROR_SUCCESS
)
2213 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2215 bufptr
+= val_list
[i
].ve_valuelen
;
2218 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2221 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2225 /************************************************************************
2231 RegQueryValueExW (HKEY hKey
,
2232 LPCWSTR lpValueName
,
2238 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2239 UNICODE_STRING ValueName
;
2241 LONG ErrorCode
= ERROR_SUCCESS
;
2245 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2247 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2248 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2250 Status
= MapDefaultKey (&KeyHandle
,
2252 if (!NT_SUCCESS(Status
))
2254 ErrorCode
= RtlNtStatusToDosError (Status
);
2255 SetLastError (ErrorCode
);
2259 if (lpData
!= NULL
&& lpcbData
== NULL
)
2261 SetLastError (ERROR_INVALID_PARAMETER
);
2262 return ERROR_INVALID_PARAMETER
;
2265 RtlInitUnicodeString (&ValueName
,
2267 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + MaxCopy
;
2268 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2271 if (ValueInfo
== NULL
)
2273 SetLastError(ERROR_OUTOFMEMORY
);
2274 return ERROR_OUTOFMEMORY
;
2277 Status
= NtQueryValueKey (hKey
,
2279 KeyValuePartialInformation
,
2283 DPRINT("Status 0x%X\n", Status
);
2284 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2286 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2288 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2290 else if (!NT_SUCCESS(Status
))
2292 ErrorCode
= RtlNtStatusToDosError (Status
);
2293 SetLastError (ErrorCode
);
2295 if (lpcbData
!= NULL
)
2297 ResultSize
= sizeof(*ValueInfo
) + *lpcbData
;
2303 *lpType
= ValueInfo
->Type
;
2306 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2308 RtlMoveMemory (lpData
,
2310 min(ValueInfo
->DataLength
, MaxCopy
));
2313 if ((ValueInfo
->Type
== REG_SZ
) ||
2314 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2315 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2317 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2319 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2322 if (lpcbData
!= NULL
)
2324 *lpcbData
= (ResultSize
- sizeof(*ValueInfo
));
2325 DPRINT("(string) Returning Size: %lu\n", *lpcbData
);
2330 if (lpcbData
!= NULL
)
2332 *lpcbData
= ResultSize
- sizeof(*ValueInfo
);
2333 DPRINT("(other) Returning Size: %lu\n", *lpcbData
);
2337 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2339 RtlFreeHeap (ProcessHeap
,
2347 /************************************************************************
2353 RegQueryValueExA (HKEY hKey
,
2360 UNICODE_STRING ValueName
;
2361 UNICODE_STRING ValueData
;
2362 ANSI_STRING AnsiString
;
2367 if (lpData
!= NULL
&& lpcbData
== NULL
)
2369 SetLastError(ERROR_INVALID_PARAMETER
);
2370 return ERROR_INVALID_PARAMETER
;
2375 ValueData
.Length
= *lpcbData
* sizeof(WCHAR
);
2376 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2377 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2379 ValueData
.MaximumLength
);
2380 if (!ValueData
.Buffer
)
2382 SetLastError(ERROR_OUTOFMEMORY
);
2383 return ERROR_OUTOFMEMORY
;
2388 ValueData
.Buffer
= NULL
;
2389 ValueData
.Length
= 0;
2390 ValueData
.MaximumLength
= 0;
2393 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2394 (LPSTR
)lpValueName
);
2396 if (NULL
!= lpcbData
)
2398 Length
= *lpcbData
* sizeof(WCHAR
);
2400 ErrorCode
= RegQueryValueExW (hKey
,
2404 (LPBYTE
)ValueData
.Buffer
,
2405 NULL
== lpcbData
? NULL
: &Length
);
2406 DPRINT("ErrorCode %lu\n", ErrorCode
);
2408 if (ErrorCode
== ERROR_SUCCESS
||
2409 ErrorCode
== ERROR_MORE_DATA
)
2416 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2418 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2420 RtlInitAnsiString(&AnsiString
, NULL
);
2421 AnsiString
.Buffer
= lpData
;
2422 AnsiString
.MaximumLength
= *lpcbData
;
2423 ValueData
.Length
= Length
;
2424 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2425 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2427 Length
= Length
/ sizeof(WCHAR
);
2429 else if (lpcbData
!= NULL
)
2431 Length
= min(*lpcbData
, Length
);
2432 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2434 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2438 if (lpcbData
!= NULL
)
2444 if (ValueData
.Buffer
!= NULL
)
2446 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2453 /************************************************************************
2459 RegQueryValueA (HKEY hKey
,
2464 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2465 UNICODE_STRING SubKeyName
;
2466 UNICODE_STRING Value
;
2467 ANSI_STRING AnsiString
;
2471 if (lpValue
!= NULL
&&
2474 SetLastError(ERROR_INVALID_PARAMETER
);
2475 return ERROR_INVALID_PARAMETER
;
2478 RtlInitUnicodeString (&SubKeyName
,
2480 RtlInitUnicodeString (&Value
,
2482 if (lpSubKey
!= NULL
&&
2483 strlen(lpSubKey
) != 0)
2485 RtlInitAnsiString (&AnsiString
,
2487 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2488 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2489 RtlAnsiStringToUnicodeString (&SubKeyName
,
2494 if (lpValue
!= NULL
)
2496 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2497 Value
.MaximumLength
= ValueSize
;
2498 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2501 if (Value
.Buffer
== NULL
)
2503 SetLastError(ERROR_OUTOFMEMORY
);
2504 return ERROR_OUTOFMEMORY
;
2512 ErrorCode
= RegQueryValueW (hKey
,
2513 (LPCWSTR
)SubKeyName
.Buffer
,
2516 if (ErrorCode
== ERROR_SUCCESS
)
2518 Value
.Length
= ValueSize
;
2519 RtlInitAnsiString (&AnsiString
,
2521 AnsiString
.Buffer
= lpValue
;
2522 AnsiString
.MaximumLength
= *lpcbValue
;
2523 RtlUnicodeStringToAnsiString (&AnsiString
,
2528 *lpcbValue
= ValueSize
;
2529 if (Value
.Buffer
!= NULL
)
2531 RtlFreeHeap (ProcessHeap
,
2540 /************************************************************************
2546 RegQueryValueW (HKEY hKey
,
2551 OBJECT_ATTRIBUTES ObjectAttributes
;
2552 UNICODE_STRING SubKeyString
;
2559 Status
= MapDefaultKey (&KeyHandle
,
2561 if (!NT_SUCCESS(Status
))
2563 ErrorCode
= RtlNtStatusToDosError (Status
);
2564 SetLastError (ErrorCode
);
2568 if (lpSubKey
!= NULL
&&
2569 wcslen(lpSubKey
) != 0)
2571 RtlInitUnicodeString (&SubKeyString
,
2573 InitializeObjectAttributes (&ObjectAttributes
,
2575 OBJ_CASE_INSENSITIVE
,
2578 Status
= NtOpenKey (&RealKey
,
2581 if (!NT_SUCCESS(Status
))
2583 ErrorCode
= RtlNtStatusToDosError (Status
);
2584 SetLastError (ErrorCode
);
2587 CloseRealKey
= TRUE
;
2592 CloseRealKey
= FALSE
;
2595 ErrorCode
= RegQueryValueExW (RealKey
,
2600 (LPDWORD
)lpcbValue
);
2610 /************************************************************************
2616 RegReplaceKeyA (HKEY hKey
,
2621 UNICODE_STRING SubKey
;
2622 UNICODE_STRING NewFile
;
2623 UNICODE_STRING OldFile
;
2626 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
2628 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
2630 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
2633 ErrorCode
= RegReplaceKeyW (hKey
,
2638 RtlFreeUnicodeString (&OldFile
);
2639 RtlFreeUnicodeString (&NewFile
);
2640 RtlFreeUnicodeString (&SubKey
);
2646 /************************************************************************
2652 RegReplaceKeyW (HKEY hKey
,
2657 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2658 OBJECT_ATTRIBUTES NewObjectAttributes
;
2659 OBJECT_ATTRIBUTES OldObjectAttributes
;
2660 UNICODE_STRING SubKeyName
;
2661 UNICODE_STRING NewFileName
;
2662 UNICODE_STRING OldFileName
;
2663 BOOLEAN CloseRealKey
;
2664 HANDLE RealKeyHandle
;
2669 if (hKey
== HKEY_PERFORMANCE_DATA
)
2671 return ERROR_INVALID_HANDLE
;
2674 Status
= MapDefaultKey (&KeyHandle
,
2676 if (!NT_SUCCESS(Status
))
2678 ErrorCode
= RtlNtStatusToDosError (Status
);
2679 SetLastError (ErrorCode
);
2683 /* Open the real key */
2684 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
2686 RtlInitUnicodeString (&SubKeyName
,
2688 InitializeObjectAttributes (&KeyObjectAttributes
,
2690 OBJ_CASE_INSENSITIVE
,
2693 Status
= NtOpenKey (&RealKeyHandle
,
2695 &KeyObjectAttributes
);
2696 if (!NT_SUCCESS(Status
))
2698 ErrorCode
= RtlNtStatusToDosError (Status
);
2699 SetLastError (ErrorCode
);
2702 CloseRealKey
= TRUE
;
2706 RealKeyHandle
= KeyHandle
;
2707 CloseRealKey
= FALSE
;
2710 /* Convert new file name */
2711 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
2718 NtClose (RealKeyHandle
);
2720 SetLastError (ERROR_INVALID_PARAMETER
);
2721 return ERROR_INVALID_PARAMETER
;
2724 InitializeObjectAttributes (&NewObjectAttributes
,
2726 OBJ_CASE_INSENSITIVE
,
2730 /* Convert old file name */
2731 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
2736 RtlFreeUnicodeString (&NewFileName
);
2739 NtClose (RealKeyHandle
);
2741 SetLastError (ERROR_INVALID_PARAMETER
);
2742 return ERROR_INVALID_PARAMETER
;
2745 InitializeObjectAttributes (&OldObjectAttributes
,
2747 OBJ_CASE_INSENSITIVE
,
2751 Status
= NtReplaceKey (&NewObjectAttributes
,
2753 &OldObjectAttributes
);
2755 RtlFreeUnicodeString (&OldFileName
);
2756 RtlFreeUnicodeString (&NewFileName
);
2760 NtClose (RealKeyHandle
);
2763 if (!NT_SUCCESS(Status
))
2765 ErrorCode
= RtlNtStatusToDosError (Status
);
2766 SetLastError (ErrorCode
);
2770 return ERROR_SUCCESS
;
2774 /************************************************************************
2780 RegRestoreKeyA (HKEY hKey
,
2784 UNICODE_STRING FileName
;
2787 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2790 ErrorCode
= RegRestoreKeyW (hKey
,
2794 RtlFreeUnicodeString (&FileName
);
2800 /************************************************************************
2806 RegRestoreKeyW (HKEY hKey
,
2810 OBJECT_ATTRIBUTES ObjectAttributes
;
2811 IO_STATUS_BLOCK IoStatusBlock
;
2812 UNICODE_STRING FileName
;
2818 if (hKey
== HKEY_PERFORMANCE_DATA
)
2820 return ERROR_INVALID_HANDLE
;
2823 Status
= MapDefaultKey (&KeyHandle
,
2825 if (!NT_SUCCESS(Status
))
2827 ErrorCode
= RtlNtStatusToDosError (Status
);
2828 SetLastError (ErrorCode
);
2832 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2837 SetLastError (ERROR_INVALID_PARAMETER
);
2838 return ERROR_INVALID_PARAMETER
;
2841 InitializeObjectAttributes (&ObjectAttributes
,
2843 OBJ_CASE_INSENSITIVE
,
2847 Status
= NtOpenFile (&FileHandle
,
2852 FILE_SYNCHRONOUS_IO_NONALERT
);
2853 RtlFreeUnicodeString (&FileName
);
2854 if (!NT_SUCCESS(Status
))
2856 ErrorCode
= RtlNtStatusToDosError (Status
);
2857 SetLastError (ErrorCode
);
2861 Status
= NtRestoreKey (KeyHandle
,
2864 NtClose (FileHandle
);
2865 if (!NT_SUCCESS(Status
))
2867 ErrorCode
= RtlNtStatusToDosError (Status
);
2868 SetLastError (ErrorCode
);
2872 return ERROR_SUCCESS
;
2876 /************************************************************************
2882 RegSaveKeyA (HKEY hKey
,
2884 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2886 UNICODE_STRING FileName
;
2889 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2891 ErrorCode
= RegSaveKeyW (hKey
,
2893 lpSecurityAttributes
);
2894 RtlFreeUnicodeString (&FileName
);
2900 /************************************************************************
2906 RegSaveKeyW (HKEY hKey
,
2908 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2910 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2911 OBJECT_ATTRIBUTES ObjectAttributes
;
2912 UNICODE_STRING FileName
;
2913 IO_STATUS_BLOCK IoStatusBlock
;
2919 Status
= MapDefaultKey (&KeyHandle
,
2921 if (!NT_SUCCESS(Status
))
2923 ErrorCode
= RtlNtStatusToDosError (Status
);
2924 SetLastError (ErrorCode
);
2928 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
2933 SetLastError (ERROR_INVALID_PARAMETER
);
2934 return ERROR_INVALID_PARAMETER
;
2937 if (lpSecurityAttributes
!= NULL
)
2939 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2942 InitializeObjectAttributes (&ObjectAttributes
,
2944 OBJ_CASE_INSENSITIVE
,
2946 SecurityDescriptor
);
2947 Status
= NtCreateFile (&FileHandle
,
2948 GENERIC_WRITE
| SYNCHRONIZE
,
2952 FILE_ATTRIBUTE_NORMAL
,
2955 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2958 RtlFreeUnicodeString (&FileName
);
2959 if (!NT_SUCCESS(Status
))
2961 ErrorCode
= RtlNtStatusToDosError (Status
);
2962 SetLastError (ErrorCode
);
2966 Status
= NtSaveKey (KeyHandle
,
2968 NtClose (FileHandle
);
2969 if (!NT_SUCCESS(Status
))
2971 ErrorCode
= RtlNtStatusToDosError (Status
);
2972 SetLastError (ErrorCode
);
2976 return ERROR_SUCCESS
;
2980 /************************************************************************
2986 RegSetKeySecurity (HKEY hKey
,
2987 SECURITY_INFORMATION SecurityInformation
,
2988 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
2994 if (hKey
== HKEY_PERFORMANCE_DATA
)
2996 return ERROR_INVALID_HANDLE
;
2999 Status
= MapDefaultKey (&KeyHandle
,
3001 if (!NT_SUCCESS(Status
))
3003 ErrorCode
= RtlNtStatusToDosError (Status
);
3004 SetLastError (ErrorCode
);
3008 Status
= NtSetSecurityObject (KeyHandle
,
3009 SecurityInformation
,
3010 pSecurityDescriptor
);
3011 if (!NT_SUCCESS(Status
))
3013 ErrorCode
= RtlNtStatusToDosError (Status
);
3014 SetLastError (ErrorCode
);
3018 return ERROR_SUCCESS
;
3022 /************************************************************************
3028 RegSetValueExA (HKEY hKey
,
3035 UNICODE_STRING ValueName
;
3037 ANSI_STRING AnsiString
;
3038 UNICODE_STRING Data
;
3045 SetLastError (ERROR_INVALID_PARAMETER
);
3046 return ERROR_INVALID_PARAMETER
;
3049 if (lpValueName
!= NULL
&&
3050 strlen(lpValueName
) != 0)
3052 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3054 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3061 if ((dwType
== REG_SZ
) ||
3062 (dwType
== REG_MULTI_SZ
) ||
3063 (dwType
== REG_EXPAND_SZ
))
3065 RtlInitAnsiString (&AnsiString
,
3067 AnsiString
.Buffer
= (PSTR
)lpData
;
3068 AnsiString
.Length
= cbData
;
3069 AnsiString
.MaximumLength
= cbData
;
3070 RtlAnsiStringToUnicodeString (&Data
,
3073 pData
= (LPBYTE
)Data
.Buffer
;
3074 DataSize
= cbData
* sizeof(WCHAR
);
3078 RtlInitUnicodeString (&Data
,
3080 pData
= (LPBYTE
)lpData
;
3084 ErrorCode
= RegSetValueExW (hKey
,
3090 if (pValueName
!= NULL
)
3092 RtlFreeHeap (ProcessHeap
,
3097 if (Data
.Buffer
!= NULL
)
3099 RtlFreeHeap (ProcessHeap
,
3108 /************************************************************************
3114 RegSetValueExW (HKEY hKey
,
3115 LPCWSTR lpValueName
,
3121 UNICODE_STRING ValueName
;
3122 PUNICODE_STRING pValueName
;
3127 Status
= MapDefaultKey (&KeyHandle
,
3129 if (!NT_SUCCESS(Status
))
3131 ErrorCode
= RtlNtStatusToDosError (Status
);
3132 SetLastError (ErrorCode
);
3136 if (lpValueName
!= NULL
)
3138 RtlInitUnicodeString (&ValueName
,
3143 RtlInitUnicodeString (&ValueName
, L
"");
3145 pValueName
= &ValueName
;
3147 Status
= NtSetValueKey (KeyHandle
,
3153 if (!NT_SUCCESS(Status
))
3155 ErrorCode
= RtlNtStatusToDosError (Status
);
3156 SetLastError (ErrorCode
);
3160 return ERROR_SUCCESS
;
3164 /************************************************************************
3170 RegSetValueA (HKEY hKey
,
3176 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3177 UNICODE_STRING SubKeyName
;
3178 UNICODE_STRING Data
;
3179 ANSI_STRING AnsiString
;
3185 SetLastError (ERROR_INVALID_PARAMETER
);
3186 return ERROR_INVALID_PARAMETER
;
3189 RtlInitUnicodeString (&SubKeyName
, NULL
);
3190 RtlInitUnicodeString (&Data
, NULL
);
3191 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
3193 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
3194 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3195 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3196 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
3199 DataSize
= cbData
* sizeof(WCHAR
);
3200 Data
.MaximumLength
= DataSize
;
3201 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3204 if (Data
.Buffer
== NULL
)
3206 SetLastError (ERROR_OUTOFMEMORY
);
3207 return ERROR_OUTOFMEMORY
;
3210 ErrorCode
= RegSetValueW (hKey
,
3211 (LPCWSTR
)SubKeyName
.Buffer
,
3216 RtlFreeHeap (ProcessHeap
,
3224 /************************************************************************
3230 RegSetValueW (HKEY hKey
,
3236 OBJECT_ATTRIBUTES ObjectAttributes
;
3237 UNICODE_STRING SubKeyString
;
3244 Status
= MapDefaultKey (&KeyHandle
,
3246 if (!NT_SUCCESS(Status
))
3248 ErrorCode
= RtlNtStatusToDosError (Status
);
3249 SetLastError (ErrorCode
);
3253 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3255 RtlInitUnicodeString (&SubKeyString
,
3257 InitializeObjectAttributes (&ObjectAttributes
,
3259 OBJ_CASE_INSENSITIVE
,
3262 Status
= NtOpenKey (&RealKey
,
3265 if (!NT_SUCCESS(Status
))
3267 ErrorCode
= RtlNtStatusToDosError (Status
);
3268 SetLastError (ErrorCode
);
3271 CloseRealKey
= TRUE
;
3276 CloseRealKey
= FALSE
;
3279 ErrorCode
= RegSetValueExW (RealKey
,
3285 if (CloseRealKey
== TRUE
)
3294 /************************************************************************
3300 RegUnLoadKeyA (HKEY hKey
,
3303 UNICODE_STRING KeyName
;
3306 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3309 ErrorCode
= RegUnLoadKeyW (hKey
,
3312 RtlFreeUnicodeString (&KeyName
);
3318 /************************************************************************
3324 RegUnLoadKeyW (HKEY hKey
,
3327 OBJECT_ATTRIBUTES ObjectAttributes
;
3328 UNICODE_STRING KeyName
;
3333 if (hKey
== HKEY_PERFORMANCE_DATA
)
3334 return ERROR_INVALID_HANDLE
;
3336 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3337 if (!NT_SUCCESS(Status
))
3339 ErrorCode
= RtlNtStatusToDosError (Status
);
3340 SetLastError (ErrorCode
);
3344 RtlInitUnicodeString (&KeyName
,
3347 InitializeObjectAttributes (&ObjectAttributes
,
3349 OBJ_CASE_INSENSITIVE
,
3353 Status
= NtUnloadKey (&ObjectAttributes
);
3355 if (!NT_SUCCESS(Status
))
3357 ErrorCode
= RtlNtStatusToDosError (Status
);
3358 SetLastError (ErrorCode
);
3362 return ERROR_SUCCESS
;