1 /* $Id: reg.c,v 1.51 2004/07/17 16:09:07 navaraf 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 *****************************************************************/
15 #define NTOS_MODE_USER
17 #include <ddk/ntddk.h>
18 #include <rosrtl/string.h>
19 #include <ntdll/rtl.h>
26 /* DEFINES ******************************************************************/
28 #define MAX_DEFAULT_HANDLES 6
29 #define REG_MAX_NAME_SIZE 256
30 #define REG_MAX_DATA_SIZE 2048
32 /* GLOBALS ******************************************************************/
34 static CRITICAL_SECTION HandleTableCS
;
35 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
36 static HANDLE ProcessHeap
;
38 /* PROTOTYPES ***************************************************************/
40 static NTSTATUS
MapDefaultKey (PHANDLE ParentKey
, HKEY Key
);
41 static VOID
CloseDefaultKeys(VOID
);
43 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
44 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
45 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
46 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
49 /* FUNCTIONS ****************************************************************/
51 /************************************************************************
52 * RegInitDefaultHandles
57 DPRINT("RegInitialize()\n");
59 ProcessHeap
= RtlGetProcessHeap();
60 RtlZeroMemory (DefaultHandleTable
,
61 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
62 RtlInitializeCriticalSection (&HandleTableCS
);
68 /************************************************************************
74 DPRINT("RegCleanup()\n");
77 RtlDeleteCriticalSection (&HandleTableCS
);
84 MapDefaultKey (PHANDLE RealKey
,
89 NTSTATUS Status
= STATUS_SUCCESS
;
91 DPRINT("MapDefaultKey (Key %x)\n", Key
);
93 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
95 *RealKey
= (HANDLE
)Key
;
96 return STATUS_SUCCESS
;
99 /* Handle special cases here */
100 Index
= (ULONG
)Key
& 0x0FFFFFFF;
101 if (Index
>= MAX_DEFAULT_HANDLES
)
103 return STATUS_INVALID_PARAMETER
;
106 RtlEnterCriticalSection (&HandleTableCS
);
107 Handle
= &DefaultHandleTable
[Index
];
110 /* create/open the default handle */
113 case 0: /* HKEY_CLASSES_ROOT */
114 Status
= OpenClassesRootKey (Handle
);
117 case 1: /* HKEY_CURRENT_USER */
118 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
122 case 2: /* HKEY_LOCAL_MACHINE */
123 Status
= OpenLocalMachineKey (Handle
);
126 case 3: /* HKEY_USERS */
127 Status
= OpenUsersKey (Handle
);
130 case 4: /* HKEY_PERFORMANCE_DATA */
131 Status
= OpenPerformanceDataKey (Handle
);
134 case 5: /* HKEY_CURRENT_CONFIG */
135 Status
= OpenCurrentConfigKey (Handle
);
138 case 6: /* HKEY_DYN_DATA */
139 Status
= STATUS_NOT_IMPLEMENTED
;
143 DPRINT("MapDefaultHandle() no handle creator\n");
144 Status
= STATUS_INVALID_PARAMETER
;
147 RtlLeaveCriticalSection (&HandleTableCS
);
149 if (NT_SUCCESS(Status
))
159 CloseDefaultKeys (VOID
)
163 RtlEnterCriticalSection (&HandleTableCS
);
164 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
166 if (DefaultHandleTable
[i
] != NULL
)
168 NtClose (DefaultHandleTable
[i
]);
169 DefaultHandleTable
[i
] = NULL
;
172 RtlLeaveCriticalSection (&HandleTableCS
);
177 OpenClassesRootKey (PHANDLE KeyHandle
)
179 OBJECT_ATTRIBUTES Attributes
;
180 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\Software\\CLASSES");
182 DPRINT("OpenClassesRootKey()\n");
184 InitializeObjectAttributes (&Attributes
,
186 OBJ_CASE_INSENSITIVE
,
189 return NtOpenKey (KeyHandle
,
196 OpenLocalMachineKey (PHANDLE KeyHandle
)
198 OBJECT_ATTRIBUTES Attributes
;
199 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine");
202 DPRINT("OpenLocalMachineKey()\n");
204 InitializeObjectAttributes (&Attributes
,
206 OBJ_CASE_INSENSITIVE
,
209 Status
= NtOpenKey (KeyHandle
,
213 DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
219 OpenUsersKey (PHANDLE KeyHandle
)
221 OBJECT_ATTRIBUTES Attributes
;
222 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\User");
224 DPRINT("OpenUsersKey()\n");
226 InitializeObjectAttributes (&Attributes
,
228 OBJ_CASE_INSENSITIVE
,
231 return NtOpenKey (KeyHandle
,
238 OpenCurrentConfigKey (PHANDLE KeyHandle
)
240 OBJECT_ATTRIBUTES Attributes
;
241 UNICODE_STRING KeyName
=
242 ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
244 DPRINT("OpenCurrentConfigKey()\n");
246 InitializeObjectAttributes (&Attributes
,
248 OBJ_CASE_INSENSITIVE
,
251 return NtOpenKey (KeyHandle
,
257 /************************************************************************
263 RegCloseKey (HKEY hKey
)
268 /* don't close null handle or a pseudo handle */
269 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
271 return ERROR_INVALID_HANDLE
;
274 Status
= NtClose (hKey
);
275 if (!NT_SUCCESS(Status
))
277 ErrorCode
= RtlNtStatusToDosError (Status
);
278 SetLastError (ErrorCode
);
282 return ERROR_SUCCESS
;
286 /************************************************************************
287 * RegConnectRegistryA
292 RegConnectRegistryA (LPCSTR lpMachineName
,
296 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
297 return ERROR_CALL_NOT_IMPLEMENTED
;
301 /************************************************************************
302 * RegConnectRegistryW
307 RegConnectRegistryW (LPCWSTR lpMachineName
,
311 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
312 return ERROR_CALL_NOT_IMPLEMENTED
;
316 /************************************************************************
319 * Create key and all necessary intermediate keys
322 CreateNestedKey(PHKEY KeyHandle
,
323 POBJECT_ATTRIBUTES ObjectAttributes
,
324 PUNICODE_STRING ClassString
,
327 DWORD
*lpdwDisposition
)
329 OBJECT_ATTRIBUTES LocalObjectAttributes
;
330 UNICODE_STRING LocalKeyName
;
333 ULONG FullNameLength
;
336 HANDLE LocalKeyHandle
;
338 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
344 (PULONG
)lpdwDisposition
);
345 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", ObjectAttributes
->ObjectName
, Status
);
346 if (Status
!= STATUS_OBJECT_NAME_NOT_FOUND
)
349 /* Copy object attributes */
350 RtlCopyMemory (&LocalObjectAttributes
,
352 sizeof(OBJECT_ATTRIBUTES
));
353 RtlCreateUnicodeString (&LocalKeyName
,
354 ObjectAttributes
->ObjectName
->Buffer
);
355 LocalObjectAttributes
.ObjectName
= &LocalKeyName
;
356 FullNameLength
= LocalKeyName
.Length
/ sizeof(WCHAR
);
358 /* Remove the last part of the key name and try to create the key again. */
359 while (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
361 Ptr
= wcsrchr (LocalKeyName
.Buffer
, '\\');
362 if (Ptr
== NULL
|| Ptr
== LocalKeyName
.Buffer
)
364 Status
= STATUS_UNSUCCESSFUL
;
368 LocalKeyName
.Length
= wcslen (LocalKeyName
.Buffer
) * sizeof(WCHAR
);
370 Status
= NtCreateKey (&LocalKeyHandle
,
372 &LocalObjectAttributes
,
377 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
380 if (!NT_SUCCESS(Status
))
382 RtlFreeUnicodeString (&LocalKeyName
);
386 /* Add removed parts of the key name and create them too. */
387 Length
= wcslen (LocalKeyName
.Buffer
);
390 NtClose (LocalKeyHandle
);
392 LocalKeyName
.Buffer
[Length
] = L
'\\';
393 Length
= wcslen (LocalKeyName
.Buffer
);
394 LocalKeyName
.Length
= Length
* sizeof(WCHAR
);
396 if (Length
== FullNameLength
)
398 Status
= NtCreateKey((PHANDLE
) KeyHandle
,
404 (PULONG
)lpdwDisposition
);
407 Status
= NtCreateKey (&LocalKeyHandle
,
409 &LocalObjectAttributes
,
414 DPRINT("NtCreateKey(%wZ) called (Status %lx)\n", &LocalKeyName
, Status
);
415 if (!NT_SUCCESS(Status
))
419 RtlFreeUnicodeString (&LocalKeyName
);
425 /************************************************************************
431 RegCreateKeyExA (HKEY hKey
,
437 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
439 LPDWORD lpdwDisposition
)
441 UNICODE_STRING SubKeyString
;
442 UNICODE_STRING ClassString
;
443 OBJECT_ATTRIBUTES Attributes
;
448 DPRINT("RegCreateKeyExA() called\n");
450 /* get the real parent key */
451 Status
= MapDefaultKey (&ParentKey
,
453 if (!NT_SUCCESS(Status
))
455 ErrorCode
= RtlNtStatusToDosError (Status
);
456 SetLastError (ErrorCode
);
459 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
463 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
466 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
468 InitializeObjectAttributes (&Attributes
,
470 OBJ_CASE_INSENSITIVE
,
472 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
473 Status
= CreateNestedKey(phkResult
,
475 (lpClass
== NULL
)? NULL
: &ClassString
,
479 RtlFreeUnicodeString (&SubKeyString
);
482 RtlFreeUnicodeString (&ClassString
);
484 DPRINT("Status %x\n", Status
);
485 if (!NT_SUCCESS(Status
))
487 ErrorCode
= RtlNtStatusToDosError (Status
);
488 SetLastError (ErrorCode
);
492 return ERROR_SUCCESS
;
496 /************************************************************************
502 RegCreateKeyExW (HKEY hKey
,
508 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
510 LPDWORD lpdwDisposition
)
512 UNICODE_STRING SubKeyString
;
513 UNICODE_STRING ClassString
;
514 OBJECT_ATTRIBUTES Attributes
;
519 DPRINT("RegCreateKeyExW() called\n");
521 /* get the real parent key */
522 Status
= MapDefaultKey (&ParentKey
,
524 if (!NT_SUCCESS(Status
))
526 ErrorCode
= RtlNtStatusToDosError(Status
);
527 SetLastError (ErrorCode
);
530 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
532 RtlInitUnicodeString (&ClassString
,
534 RtlInitUnicodeString (&SubKeyString
,
536 InitializeObjectAttributes (&Attributes
,
538 OBJ_CASE_INSENSITIVE
,
540 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
541 Status
= CreateNestedKey(phkResult
,
543 (lpClass
== NULL
)? NULL
: &ClassString
,
547 DPRINT("Status %x\n", Status
);
548 if (!NT_SUCCESS(Status
))
550 ErrorCode
= RtlNtStatusToDosError (Status
);
551 SetLastError (ErrorCode
);
555 return ERROR_SUCCESS
;
559 /************************************************************************
565 RegCreateKeyA (HKEY hKey
,
569 return RegCreateKeyExA (hKey
,
581 /************************************************************************
587 RegCreateKeyW (HKEY hKey
,
591 return RegCreateKeyExW (hKey
,
603 /************************************************************************
609 RegDeleteKeyA (HKEY hKey
,
612 OBJECT_ATTRIBUTES ObjectAttributes
;
613 UNICODE_STRING SubKeyName
;
619 Status
= MapDefaultKey (&ParentKey
,
621 if (!NT_SUCCESS(Status
))
623 ErrorCode
= RtlNtStatusToDosError (Status
);
624 SetLastError (ErrorCode
);
628 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
630 InitializeObjectAttributes(&ObjectAttributes
,
632 OBJ_CASE_INSENSITIVE
,
636 Status
= NtOpenKey (&TargetKey
,
639 RtlFreeUnicodeString (&SubKeyName
);
640 if (!NT_SUCCESS(Status
))
642 ErrorCode
= RtlNtStatusToDosError (Status
);
643 SetLastError (ErrorCode
);
647 Status
= NtDeleteKey (TargetKey
);
649 if (!NT_SUCCESS(Status
))
651 ErrorCode
= RtlNtStatusToDosError(Status
);
652 SetLastError (ErrorCode
);
656 return ERROR_SUCCESS
;
660 /************************************************************************
666 RegDeleteKeyW (HKEY hKey
,
669 OBJECT_ATTRIBUTES ObjectAttributes
;
670 UNICODE_STRING SubKeyName
;
676 Status
= MapDefaultKey (&ParentKey
,
678 if (!NT_SUCCESS(Status
))
680 ErrorCode
= RtlNtStatusToDosError (Status
);
681 SetLastError (ErrorCode
);
685 RtlInitUnicodeString (&SubKeyName
,
687 InitializeObjectAttributes (&ObjectAttributes
,
689 OBJ_CASE_INSENSITIVE
,
692 Status
= NtOpenKey (&TargetKey
,
695 if (!NT_SUCCESS(Status
))
697 ErrorCode
= RtlNtStatusToDosError (Status
);
698 SetLastError (ErrorCode
);
702 Status
= NtDeleteKey (TargetKey
);
704 if (!NT_SUCCESS(Status
))
706 ErrorCode
= RtlNtStatusToDosError (Status
);
707 SetLastError (ErrorCode
);
711 return ERROR_SUCCESS
;
715 /************************************************************************
721 RegDeleteValueA (HKEY hKey
,
724 UNICODE_STRING ValueName
;
729 Status
= MapDefaultKey (&KeyHandle
,
731 if (!NT_SUCCESS(Status
))
733 ErrorCode
= RtlNtStatusToDosError (Status
);
734 SetLastError (ErrorCode
);
738 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
740 Status
= NtDeleteValueKey (KeyHandle
,
742 RtlFreeUnicodeString (&ValueName
);
743 if (!NT_SUCCESS(Status
))
745 ErrorCode
= RtlNtStatusToDosError (Status
);
746 SetLastError (ErrorCode
);
750 return ERROR_SUCCESS
;
754 /************************************************************************
760 RegDeleteValueW (HKEY hKey
,
763 UNICODE_STRING ValueName
;
768 Status
= MapDefaultKey (&KeyHandle
,
770 if (!NT_SUCCESS(Status
))
772 ErrorCode
= RtlNtStatusToDosError (Status
);
773 SetLastError (ErrorCode
);
777 RtlInitUnicodeString (&ValueName
,
778 (LPWSTR
)lpValueName
);
780 Status
= NtDeleteValueKey (KeyHandle
,
782 if (!NT_SUCCESS(Status
))
784 ErrorCode
= RtlNtStatusToDosError (Status
);
785 SetLastError (ErrorCode
);
789 return ERROR_SUCCESS
;
793 /************************************************************************
799 RegEnumKeyA (HKEY hKey
,
807 return RegEnumKeyExA (hKey
,
818 /************************************************************************
824 RegEnumKeyW (HKEY hKey
,
832 return RegEnumKeyExW (hKey
,
843 /************************************************************************
849 RegEnumKeyExA (HKEY hKey
,
856 PFILETIME lpftLastWriteTime
)
860 KEY_NODE_INFORMATION Node
;
861 KEY_BASIC_INFORMATION Basic
;
864 UNICODE_STRING StringU
;
866 LONG ErrorCode
= ERROR_SUCCESS
;
868 DWORD ClassLength
= 0;
874 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
875 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
877 if ((lpClass
) && (!lpcbClass
))
879 SetLastError (ERROR_INVALID_PARAMETER
);
880 return ERROR_INVALID_PARAMETER
;
883 Status
= MapDefaultKey(&KeyHandle
,
885 if (!NT_SUCCESS(Status
))
887 ErrorCode
= RtlNtStatusToDosError (Status
);
888 SetLastError (ErrorCode
);
894 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
905 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
912 /* The class name should start at a dword boundary */
913 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
917 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
920 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
925 SetLastError (ERROR_OUTOFMEMORY
);
926 return ERROR_OUTOFMEMORY
;
929 Status
= NtEnumerateKey (KeyHandle
,
931 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
935 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
936 if (!NT_SUCCESS(Status
))
938 ErrorCode
= RtlNtStatusToDosError (Status
);
944 if (KeyInfo
->Basic
.NameLength
> NameLength
)
946 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
950 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
951 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
952 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
957 if (KeyInfo
->Node
.NameLength
> NameLength
||
958 KeyInfo
->Node
.ClassLength
> ClassLength
)
960 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
964 StringA
.Buffer
= lpClass
;
966 StringA
.MaximumLength
= *lpcbClass
;
967 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
968 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
969 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
970 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
971 lpClass
[StringA
.Length
] = 0;
972 *lpcbClass
= StringA
.Length
;
973 StringU
.Buffer
= KeyInfo
->Node
.Name
;
974 StringU
.Length
= KeyInfo
->Node
.NameLength
;
975 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
979 if (ErrorCode
== ERROR_SUCCESS
)
981 StringA
.Buffer
= lpName
;
983 StringA
.MaximumLength
= *lpcbName
;
984 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
985 lpName
[StringA
.Length
] = 0;
986 *lpcbName
= StringA
.Length
;
987 if (lpftLastWriteTime
!= NULL
)
991 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
992 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
996 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
997 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1003 DPRINT("Key Namea0 Length %d\n", StringU
.Length
);
1004 DPRINT("Key Namea1 Length %d\n", NameLength
);
1005 DPRINT("Key Namea Length %d\n", *lpcbName
);
1006 DPRINT("Key Namea %s\n", lpName
);
1008 RtlFreeHeap (ProcessHeap
,
1012 if (ErrorCode
!= ERROR_SUCCESS
)
1014 SetLastError(ErrorCode
);
1021 /************************************************************************
1027 RegEnumKeyExW (HKEY hKey
,
1034 PFILETIME lpftLastWriteTime
)
1038 KEY_NODE_INFORMATION Node
;
1039 KEY_BASIC_INFORMATION Basic
;
1045 ULONG ClassLength
= 0;
1047 LONG ErrorCode
= ERROR_SUCCESS
;
1050 Status
= MapDefaultKey(&KeyHandle
,
1052 if (!NT_SUCCESS(Status
))
1054 ErrorCode
= RtlNtStatusToDosError (Status
);
1055 SetLastError (ErrorCode
);
1061 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
1072 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1079 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
1083 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
1086 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
1089 if (KeyInfo
== NULL
)
1091 SetLastError (ERROR_OUTOFMEMORY
);
1092 return ERROR_OUTOFMEMORY
;
1095 Status
= NtEnumerateKey (KeyHandle
,
1097 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
1101 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
1102 if (!NT_SUCCESS(Status
))
1104 ErrorCode
= RtlNtStatusToDosError (Status
);
1108 if (lpClass
== NULL
)
1110 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1112 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1116 RtlCopyMemory (lpName
,
1117 KeyInfo
->Basic
.Name
,
1118 KeyInfo
->Basic
.NameLength
);
1119 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1120 lpName
[*lpcbName
] = 0;
1125 if (KeyInfo
->Node
.NameLength
> NameLength
||
1126 KeyInfo
->Node
.ClassLength
> ClassLength
)
1128 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1132 RtlCopyMemory (lpName
,
1134 KeyInfo
->Node
.NameLength
);
1135 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1136 lpName
[*lpcbName
] = 0;
1137 RtlCopyMemory (lpClass
,
1138 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1139 KeyInfo
->Node
.ClassLength
);
1140 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1141 lpClass
[*lpcbClass
] = 0;
1145 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1147 if (lpClass
== NULL
)
1149 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1150 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1154 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1155 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1160 RtlFreeHeap (ProcessHeap
,
1164 if (ErrorCode
!= ERROR_SUCCESS
)
1166 SetLastError(ErrorCode
);
1173 /************************************************************************
1179 RegEnumValueA (HKEY hKey
,
1182 LPDWORD lpcbValueName
,
1190 KEY_VALUE_FULL_INFORMATION Full
;
1191 KEY_VALUE_BASIC_INFORMATION Basic
;
1196 ULONG DataLength
= 0;
1201 UNICODE_STRING StringU
;
1202 ANSI_STRING StringA
;
1205 ErrorCode
= ERROR_SUCCESS
;
1207 Status
= MapDefaultKey (&KeyHandle
,
1209 if (!NT_SUCCESS(Status
))
1211 ErrorCode
= RtlNtStatusToDosError (Status
);
1212 SetLastError (ErrorCode
);
1216 if (*lpcbValueName
> 0)
1218 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1227 DataLength
= min (*lpcbData
* sizeof(WCHAR
), REG_MAX_DATA_SIZE
);
1228 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1232 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1235 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1238 if (ValueInfo
== NULL
)
1240 SetLastError(ERROR_OUTOFMEMORY
);
1241 return ERROR_OUTOFMEMORY
;
1244 Status
= NtEnumerateValueKey (KeyHandle
,
1246 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1251 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1252 if (!NT_SUCCESS(Status
))
1254 ErrorCode
= RtlNtStatusToDosError (Status
);
1260 IsStringType
= (ValueInfo
->Full
.Type
== REG_SZ
) ||
1261 (ValueInfo
->Full
.Type
== REG_MULTI_SZ
) ||
1262 (ValueInfo
->Full
.Type
== REG_EXPAND_SZ
);
1263 if (ValueInfo
->Full
.NameLength
> NameLength
||
1264 (!IsStringType
&& ValueInfo
->Full
.DataLength
> *lpcbData
) ||
1265 ValueInfo
->Full
.DataLength
> DataLength
)
1267 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1273 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
);
1274 StringU
.Length
= ValueInfo
->Full
.DataLength
;
1275 StringU
.MaximumLength
= DataLength
;
1276 StringA
.Buffer
= (PCHAR
)lpData
;
1278 StringA
.MaximumLength
= *lpcbData
;
1279 RtlUnicodeStringToAnsiString (&StringA
,
1282 *lpcbData
= StringA
.Length
;
1286 RtlCopyMemory (lpData
,
1287 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1288 ValueInfo
->Full
.DataLength
);
1289 *lpcbData
= ValueInfo
->Full
.DataLength
;
1292 StringU
.Buffer
= ValueInfo
->Full
.Name
;
1293 StringU
.Length
= ValueInfo
->Full
.NameLength
;
1294 StringU
.MaximumLength
= NameLength
;
1299 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1301 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1305 StringU
.Buffer
= ValueInfo
->Basic
.Name
;
1306 StringU
.Length
= ValueInfo
->Basic
.NameLength
;
1307 StringU
.MaximumLength
= NameLength
;
1311 if (ErrorCode
== ERROR_SUCCESS
)
1313 StringA
.Buffer
= (PCHAR
)lpValueName
;
1315 StringA
.MaximumLength
= *lpcbValueName
;
1316 RtlUnicodeStringToAnsiString (&StringA
,
1319 StringA
.Buffer
[StringA
.Length
] = 0;
1320 *lpcbValueName
= StringA
.Length
;
1323 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1328 RtlFreeHeap (ProcessHeap
,
1331 if (ErrorCode
!= ERROR_SUCCESS
)
1333 SetLastError(ErrorCode
);
1340 /************************************************************************
1346 RegEnumValueW (HKEY hKey
,
1349 LPDWORD lpcbValueName
,
1357 KEY_VALUE_FULL_INFORMATION Full
;
1358 KEY_VALUE_BASIC_INFORMATION Basic
;
1363 ULONG DataLength
= 0;
1369 ErrorCode
= ERROR_SUCCESS
;
1371 Status
= MapDefaultKey (&KeyHandle
,
1373 if (!NT_SUCCESS(Status
))
1375 ErrorCode
= RtlNtStatusToDosError (Status
);
1376 SetLastError (ErrorCode
);
1380 if (*lpcbValueName
> 0)
1382 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1391 DataLength
= min(*lpcbData
, REG_MAX_DATA_SIZE
);
1392 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1396 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1398 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1401 if (ValueInfo
== NULL
)
1403 SetLastError (ERROR_OUTOFMEMORY
);
1404 return ERROR_OUTOFMEMORY
;
1406 Status
= NtEnumerateValueKey (KeyHandle
,
1408 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1413 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1414 if (!NT_SUCCESS(Status
))
1416 ErrorCode
= RtlNtStatusToDosError (Status
);
1422 if (ValueInfo
->Full
.DataLength
> DataLength
||
1423 ValueInfo
->Full
.NameLength
> NameLength
)
1425 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1429 RtlCopyMemory (lpValueName
,
1430 ValueInfo
->Full
.Name
,
1431 ValueInfo
->Full
.NameLength
);
1432 *lpcbValueName
= (DWORD
)(ValueInfo
->Full
.NameLength
/ sizeof(WCHAR
));
1433 lpValueName
[*lpcbValueName
] = 0;
1434 RtlCopyMemory (lpData
,
1435 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1436 ValueInfo
->Full
.DataLength
);
1437 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1442 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1444 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1448 RtlCopyMemory (lpValueName
,
1449 ValueInfo
->Basic
.Name
,
1450 ValueInfo
->Basic
.NameLength
);
1451 *lpcbValueName
= (DWORD
)(ValueInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1452 lpValueName
[*lpcbValueName
] = 0;
1456 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1458 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1462 RtlFreeHeap (ProcessHeap
,
1466 if (ErrorCode
!= ERROR_SUCCESS
)
1468 SetLastError (ErrorCode
);
1475 /************************************************************************
1481 RegFlushKey(HKEY hKey
)
1487 if (hKey
== HKEY_PERFORMANCE_DATA
)
1489 return ERROR_SUCCESS
;
1492 Status
= MapDefaultKey (&KeyHandle
,
1494 if (!NT_SUCCESS(Status
))
1496 ErrorCode
= RtlNtStatusToDosError (Status
);
1497 SetLastError (ErrorCode
);
1501 Status
= NtFlushKey (KeyHandle
);
1502 if (!NT_SUCCESS(Status
))
1504 ErrorCode
= RtlNtStatusToDosError (Status
);
1505 SetLastError (ErrorCode
);
1509 return ERROR_SUCCESS
;
1513 /************************************************************************
1519 RegGetKeySecurity (HKEY hKey
,
1520 SECURITY_INFORMATION SecurityInformation
,
1521 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1522 LPDWORD lpcbSecurityDescriptor
)
1529 if (hKey
= HKEY_PERFORMANCE_DATA
)
1531 return ERROR_INVALID_HANDLE
;
1534 Status
= MapDefaultKey (&KeyHandle
,
1536 if (!NT_SUCCESS(Status
))
1538 ErrorCode
= RtlNtStatusToDosError (Status
);
1539 SetLastError (ErrorCode
);
1543 Status
= NtQuerySecurityObject ()
1544 if (!NT_SUCCESS(Status
))
1546 ErrorCode
= RtlNtStatusToDosError (Status
);
1547 SetLastError (ErrorCode
);
1551 return ERROR_SUCCESS
;
1555 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1556 return ERROR_CALL_NOT_IMPLEMENTED
;
1560 /************************************************************************
1566 RegLoadKeyA (HKEY hKey
,
1570 UNICODE_STRING FileName
;
1571 UNICODE_STRING KeyName
;
1574 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1576 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1579 ErrorCode
= RegLoadKeyW (hKey
,
1583 RtlFreeUnicodeString (&FileName
);
1584 RtlFreeUnicodeString (&KeyName
);
1590 /************************************************************************
1596 RegLoadKeyW (HKEY hKey
,
1600 OBJECT_ATTRIBUTES FileObjectAttributes
;
1601 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1602 UNICODE_STRING FileName
;
1603 UNICODE_STRING KeyName
;
1608 if (hKey
== HKEY_PERFORMANCE_DATA
)
1610 return ERROR_INVALID_HANDLE
;
1613 Status
= MapDefaultKey (&KeyHandle
,
1615 if (!NT_SUCCESS(Status
))
1617 ErrorCode
= RtlNtStatusToDosError (Status
);
1618 SetLastError (ErrorCode
);
1622 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1627 SetLastError (ERROR_BAD_PATHNAME
);
1628 return ERROR_BAD_PATHNAME
;
1631 InitializeObjectAttributes (&FileObjectAttributes
,
1633 OBJ_CASE_INSENSITIVE
,
1637 RtlInitUnicodeString (&KeyName
,
1640 InitializeObjectAttributes (&KeyObjectAttributes
,
1642 OBJ_CASE_INSENSITIVE
,
1646 Status
= NtLoadKey (&KeyObjectAttributes
,
1647 &FileObjectAttributes
);
1649 RtlFreeUnicodeString (&FileName
);
1651 if (!NT_SUCCESS(Status
))
1653 ErrorCode
= RtlNtStatusToDosError (Status
);
1654 SetLastError (ErrorCode
);
1658 return ERROR_SUCCESS
;
1662 /************************************************************************
1663 * RegNotifyChangeKeyValue
1668 RegNotifyChangeKeyValue (HKEY hKey
,
1670 DWORD dwNotifyFilter
,
1674 IO_STATUS_BLOCK IoStatusBlock
;
1678 if (hKey
== HKEY_PERFORMANCE_DATA
)
1680 return ERROR_INVALID_HANDLE
;
1683 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1685 return ERROR_INVALID_PARAMETER
;
1688 Status
= MapDefaultKey (&KeyHandle
,
1690 if (!NT_SUCCESS(Status
))
1692 return RtlNtStatusToDosError (Status
);
1695 /* FIXME: Remote key handles must fail */
1697 Status
= NtNotifyChangeKey (KeyHandle
,
1707 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1709 return RtlNtStatusToDosError (Status
);
1712 return ERROR_SUCCESS
;
1716 /************************************************************************
1722 RegOpenKeyA (HKEY hKey
,
1726 OBJECT_ATTRIBUTES ObjectAttributes
;
1727 UNICODE_STRING SubKeyString
;
1732 Status
= MapDefaultKey (&KeyHandle
,
1734 if (!NT_SUCCESS(Status
))
1736 ErrorCode
= RtlNtStatusToDosError (Status
);
1737 SetLastError (ErrorCode
);
1741 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1743 InitializeObjectAttributes (&ObjectAttributes
,
1745 OBJ_CASE_INSENSITIVE
,
1748 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1751 RtlFreeUnicodeString (&SubKeyString
);
1752 if (!NT_SUCCESS(Status
))
1754 ErrorCode
= RtlNtStatusToDosError (Status
);
1755 SetLastError (ErrorCode
);
1759 return ERROR_SUCCESS
;
1763 /************************************************************************
1772 RegOpenKeyW (HKEY hKey
,
1776 OBJECT_ATTRIBUTES ObjectAttributes
;
1777 UNICODE_STRING SubKeyString
;
1782 Status
= MapDefaultKey (&KeyHandle
,
1784 if (!NT_SUCCESS(Status
))
1786 ErrorCode
= RtlNtStatusToDosError (Status
);
1787 SetLastError (ErrorCode
);
1791 RtlInitUnicodeString (&SubKeyString
,
1793 InitializeObjectAttributes (&ObjectAttributes
,
1795 OBJ_CASE_INSENSITIVE
,
1798 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1801 if (!NT_SUCCESS(Status
))
1803 ErrorCode
= RtlNtStatusToDosError (Status
);
1804 SetLastError(ErrorCode
);
1808 return ERROR_SUCCESS
;
1812 /************************************************************************
1818 RegOpenKeyExA (HKEY hKey
,
1824 OBJECT_ATTRIBUTES ObjectAttributes
;
1825 UNICODE_STRING SubKeyString
;
1830 Status
= MapDefaultKey (&KeyHandle
,
1832 if (!NT_SUCCESS(Status
))
1834 ErrorCode
= RtlNtStatusToDosError (Status
);
1835 SetLastError (ErrorCode
);
1839 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1841 InitializeObjectAttributes (&ObjectAttributes
,
1843 OBJ_CASE_INSENSITIVE
,
1846 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1849 RtlFreeUnicodeString (&SubKeyString
);
1850 if (!NT_SUCCESS(Status
))
1852 ErrorCode
= RtlNtStatusToDosError (Status
);
1853 SetLastError (ErrorCode
);
1857 return ERROR_SUCCESS
;
1861 /************************************************************************
1867 RegOpenKeyExW (HKEY hKey
,
1873 OBJECT_ATTRIBUTES ObjectAttributes
;
1874 UNICODE_STRING SubKeyString
;
1879 Status
= MapDefaultKey (&KeyHandle
,
1881 if (!NT_SUCCESS(Status
))
1883 ErrorCode
= RtlNtStatusToDosError (Status
);
1884 SetLastError (ErrorCode
);
1888 if (lpSubKey
!= NULL
)
1890 RtlInitUnicodeString (&SubKeyString
,
1895 RtlInitUnicodeString (&SubKeyString
,
1898 InitializeObjectAttributes (&ObjectAttributes
,
1900 OBJ_CASE_INSENSITIVE
,
1903 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1906 if (!NT_SUCCESS(Status
))
1908 ErrorCode
= RtlNtStatusToDosError (Status
);
1909 SetLastError (ErrorCode
);
1913 return ERROR_SUCCESS
;
1917 /************************************************************************
1923 RegQueryInfoKeyA (HKEY hKey
,
1928 LPDWORD lpcbMaxSubKeyLen
,
1929 LPDWORD lpcbMaxClassLen
,
1931 LPDWORD lpcbMaxValueNameLen
,
1932 LPDWORD lpcbMaxValueLen
,
1933 LPDWORD lpcbSecurityDescriptor
,
1934 PFILETIME lpftLastWriteTime
)
1936 WCHAR ClassName
[MAX_PATH
];
1937 UNICODE_STRING UnicodeString
;
1938 ANSI_STRING AnsiString
;
1941 RtlInitUnicodeString (&UnicodeString
,
1943 if (lpClass
!= NULL
)
1945 UnicodeString
.Buffer
= &ClassName
[0];
1946 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1947 AnsiString
.MaximumLength
= *lpcbClass
;
1950 ErrorCode
= RegQueryInfoKeyW (hKey
,
1951 UnicodeString
.Buffer
,
1958 lpcbMaxValueNameLen
,
1960 lpcbSecurityDescriptor
,
1962 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1964 AnsiString
.Buffer
= lpClass
;
1965 AnsiString
.Length
= 0;
1966 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1967 RtlUnicodeStringToAnsiString (&AnsiString
,
1970 *lpcbClass
= AnsiString
.Length
;
1971 lpClass
[AnsiString
.Length
] = 0;
1978 /************************************************************************
1984 RegQueryInfoKeyW (HKEY hKey
,
1989 LPDWORD lpcbMaxSubKeyLen
,
1990 LPDWORD lpcbMaxClassLen
,
1992 LPDWORD lpcbMaxValueNameLen
,
1993 LPDWORD lpcbMaxValueLen
,
1994 LPDWORD lpcbSecurityDescriptor
,
1995 PFILETIME lpftLastWriteTime
)
1997 KEY_FULL_INFORMATION FullInfoBuffer
;
1998 PKEY_FULL_INFORMATION FullInfo
;
2000 ULONG ClassLength
= 0;
2003 LONG ErrorCode
= ERROR_SUCCESS
;
2006 if ((lpClass
) && (!lpcbClass
))
2008 SetLastError(ERROR_INVALID_PARAMETER
);
2009 return ERROR_INVALID_PARAMETER
;
2012 Status
= MapDefaultKey (&KeyHandle
,
2014 if (!NT_SUCCESS(Status
))
2016 ErrorCode
= RtlNtStatusToDosError (Status
);
2017 SetLastError (ErrorCode
);
2021 if (lpClass
!= NULL
)
2025 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2032 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2033 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2036 if (FullInfo
== NULL
)
2038 SetLastError (ERROR_OUTOFMEMORY
);
2039 return ERROR_OUTOFMEMORY
;
2042 FullInfo
->ClassLength
= ClassLength
;
2046 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2047 FullInfo
= &FullInfoBuffer
;
2048 FullInfo
->ClassLength
= 0;
2050 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2052 Status
= NtQueryKey (KeyHandle
,
2057 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
2058 if (!NT_SUCCESS(Status
))
2060 if (lpClass
!= NULL
)
2062 RtlFreeHeap (ProcessHeap
,
2067 ErrorCode
= RtlNtStatusToDosError (Status
);
2068 SetLastError (ErrorCode
);
2072 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
2073 if (lpcSubKeys
!= NULL
)
2075 *lpcSubKeys
= FullInfo
->SubKeys
;
2078 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2079 if (lpcbMaxSubKeyLen
!= NULL
)
2081 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2084 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2085 if (lpcbMaxClassLen
!= NULL
)
2087 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2090 DPRINT("Values %lu\n", FullInfo
->Values
);
2091 if (lpcValues
!= NULL
)
2093 *lpcValues
= FullInfo
->Values
;
2096 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2097 if (lpcbMaxValueNameLen
!= NULL
)
2099 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2102 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2103 if (lpcbMaxValueLen
!= NULL
)
2105 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2108 if (lpcbSecurityDescriptor
!= NULL
)
2111 *lpcbSecurityDescriptor
= 0;
2114 if (lpftLastWriteTime
!= NULL
)
2116 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2117 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2120 if (lpClass
!= NULL
)
2122 if (FullInfo
->ClassLength
> ClassLength
)
2124 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2128 RtlCopyMemory (lpClass
,
2130 FullInfo
->ClassLength
);
2131 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2132 lpClass
[*lpcbClass
] = 0;
2135 RtlFreeHeap (ProcessHeap
,
2140 if (ErrorCode
!= ERROR_SUCCESS
)
2142 SetLastError (ErrorCode
);
2149 /************************************************************************
2150 * RegQueryMultipleValuesA
2155 RegQueryMultipleValuesA (HKEY hKey
,
2162 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2163 return ERROR_CALL_NOT_IMPLEMENTED
;
2167 /************************************************************************
2168 * RegQueryMultipleValuesW
2173 RegQueryMultipleValuesW (HKEY hKey
,
2180 DWORD maxBytes
= *ldwTotsize
;
2181 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2184 if (maxBytes
>= (1024*1024))
2185 return ERROR_TRANSFER_TOO_LONG
;
2189 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2190 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2192 for (i
= 0; i
< num_vals
; ++i
)
2194 val_list
[i
].ve_valuelen
= 0;
2195 ErrorCode
= RegQueryValueExW (hKey
,
2196 val_list
[i
].ve_valuename
,
2200 &val_list
[i
].ve_valuelen
);
2201 if (ErrorCode
!= ERROR_SUCCESS
)
2206 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2208 ErrorCode
= RegQueryValueExW (hKey
,
2209 val_list
[i
].ve_valuename
,
2211 &val_list
[i
].ve_type
,
2213 &val_list
[i
].ve_valuelen
);
2214 if (ErrorCode
!= ERROR_SUCCESS
)
2219 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2221 bufptr
+= val_list
[i
].ve_valuelen
;
2224 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2227 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2231 /************************************************************************
2237 RegQueryValueExW (HKEY hKey
,
2238 LPCWSTR lpValueName
,
2244 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2245 UNICODE_STRING ValueName
;
2247 LONG ErrorCode
= ERROR_SUCCESS
;
2251 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2253 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2254 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2256 Status
= MapDefaultKey (&KeyHandle
,
2258 if (!NT_SUCCESS(Status
))
2260 ErrorCode
= RtlNtStatusToDosError (Status
);
2261 SetLastError (ErrorCode
);
2265 if (lpData
!= NULL
&& lpcbData
== NULL
)
2267 SetLastError (ERROR_INVALID_PARAMETER
);
2268 return ERROR_INVALID_PARAMETER
;
2271 RtlInitUnicodeString (&ValueName
,
2273 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + MaxCopy
;
2274 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2277 if (ValueInfo
== NULL
)
2279 SetLastError(ERROR_OUTOFMEMORY
);
2280 return ERROR_OUTOFMEMORY
;
2283 Status
= NtQueryValueKey (hKey
,
2285 KeyValuePartialInformation
,
2289 DPRINT("Status 0x%X\n", Status
);
2290 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2292 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2294 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2296 else if (!NT_SUCCESS(Status
))
2298 ErrorCode
= RtlNtStatusToDosError (Status
);
2299 SetLastError (ErrorCode
);
2301 if (lpcbData
!= NULL
)
2303 ResultSize
= sizeof(*ValueInfo
) + *lpcbData
;
2309 *lpType
= ValueInfo
->Type
;
2312 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2314 RtlMoveMemory (lpData
,
2316 min(ValueInfo
->DataLength
, MaxCopy
));
2319 if ((ValueInfo
->Type
== REG_SZ
) ||
2320 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2321 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2323 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2325 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2328 if (lpcbData
!= NULL
)
2330 *lpcbData
= (ResultSize
- sizeof(*ValueInfo
));
2331 DPRINT("(string) Returning Size: %lu\n", *lpcbData
);
2336 if (lpcbData
!= NULL
)
2338 *lpcbData
= ResultSize
- sizeof(*ValueInfo
);
2339 DPRINT("(other) Returning Size: %lu\n", *lpcbData
);
2343 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2345 RtlFreeHeap (ProcessHeap
,
2353 /************************************************************************
2359 RegQueryValueExA (HKEY hKey
,
2366 UNICODE_STRING ValueName
;
2367 UNICODE_STRING ValueData
;
2368 ANSI_STRING AnsiString
;
2373 if (lpData
!= NULL
&& lpcbData
== NULL
)
2375 SetLastError(ERROR_INVALID_PARAMETER
);
2376 return ERROR_INVALID_PARAMETER
;
2381 ValueData
.Length
= *lpcbData
* sizeof(WCHAR
);
2382 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2383 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2385 ValueData
.MaximumLength
);
2386 if (!ValueData
.Buffer
)
2388 SetLastError(ERROR_OUTOFMEMORY
);
2389 return ERROR_OUTOFMEMORY
;
2394 ValueData
.Buffer
= NULL
;
2395 ValueData
.Length
= 0;
2396 ValueData
.MaximumLength
= 0;
2399 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2400 (LPSTR
)lpValueName
);
2402 if (NULL
!= lpcbData
)
2404 Length
= *lpcbData
* sizeof(WCHAR
);
2406 ErrorCode
= RegQueryValueExW (hKey
,
2410 (LPBYTE
)ValueData
.Buffer
,
2411 NULL
== lpcbData
? NULL
: &Length
);
2412 DPRINT("ErrorCode %lu\n", ErrorCode
);
2414 if (ErrorCode
== ERROR_SUCCESS
||
2415 ErrorCode
== ERROR_MORE_DATA
)
2422 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2424 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2426 RtlInitAnsiString(&AnsiString
, NULL
);
2427 AnsiString
.Buffer
= lpData
;
2428 AnsiString
.MaximumLength
= *lpcbData
;
2429 ValueData
.Length
= Length
;
2430 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2431 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2433 Length
= Length
/ sizeof(WCHAR
);
2435 else if (lpcbData
!= NULL
)
2437 Length
= min(*lpcbData
, Length
);
2438 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2440 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2444 if (lpcbData
!= NULL
)
2450 if (ValueData
.Buffer
!= NULL
)
2452 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2459 /************************************************************************
2465 RegQueryValueA (HKEY hKey
,
2470 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2471 UNICODE_STRING SubKeyName
;
2472 UNICODE_STRING Value
;
2473 ANSI_STRING AnsiString
;
2477 if (lpValue
!= NULL
&&
2480 SetLastError(ERROR_INVALID_PARAMETER
);
2481 return ERROR_INVALID_PARAMETER
;
2484 RtlInitUnicodeString (&SubKeyName
,
2486 RtlInitUnicodeString (&Value
,
2488 if (lpSubKey
!= NULL
&&
2489 strlen(lpSubKey
) != 0)
2491 RtlInitAnsiString (&AnsiString
,
2493 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2494 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2495 RtlAnsiStringToUnicodeString (&SubKeyName
,
2500 if (lpValue
!= NULL
)
2502 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2503 Value
.MaximumLength
= ValueSize
;
2504 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2507 if (Value
.Buffer
== NULL
)
2509 SetLastError(ERROR_OUTOFMEMORY
);
2510 return ERROR_OUTOFMEMORY
;
2518 ErrorCode
= RegQueryValueW (hKey
,
2519 (LPCWSTR
)SubKeyName
.Buffer
,
2522 if (ErrorCode
== ERROR_SUCCESS
)
2524 Value
.Length
= ValueSize
;
2525 RtlInitAnsiString (&AnsiString
,
2527 AnsiString
.Buffer
= lpValue
;
2528 AnsiString
.MaximumLength
= *lpcbValue
;
2529 RtlUnicodeStringToAnsiString (&AnsiString
,
2534 *lpcbValue
= ValueSize
;
2535 if (Value
.Buffer
!= NULL
)
2537 RtlFreeHeap (ProcessHeap
,
2546 /************************************************************************
2552 RegQueryValueW (HKEY hKey
,
2557 OBJECT_ATTRIBUTES ObjectAttributes
;
2558 UNICODE_STRING SubKeyString
;
2565 Status
= MapDefaultKey (&KeyHandle
,
2567 if (!NT_SUCCESS(Status
))
2569 ErrorCode
= RtlNtStatusToDosError (Status
);
2570 SetLastError (ErrorCode
);
2574 if (lpSubKey
!= NULL
&&
2575 wcslen(lpSubKey
) != 0)
2577 RtlInitUnicodeString (&SubKeyString
,
2579 InitializeObjectAttributes (&ObjectAttributes
,
2581 OBJ_CASE_INSENSITIVE
,
2584 Status
= NtOpenKey (&RealKey
,
2587 if (!NT_SUCCESS(Status
))
2589 ErrorCode
= RtlNtStatusToDosError (Status
);
2590 SetLastError (ErrorCode
);
2593 CloseRealKey
= TRUE
;
2598 CloseRealKey
= FALSE
;
2601 ErrorCode
= RegQueryValueExW (RealKey
,
2606 (LPDWORD
)lpcbValue
);
2616 /************************************************************************
2622 RegReplaceKeyA (HKEY hKey
,
2627 UNICODE_STRING SubKey
;
2628 UNICODE_STRING NewFile
;
2629 UNICODE_STRING OldFile
;
2632 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
2634 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
2636 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
2639 ErrorCode
= RegReplaceKeyW (hKey
,
2644 RtlFreeUnicodeString (&OldFile
);
2645 RtlFreeUnicodeString (&NewFile
);
2646 RtlFreeUnicodeString (&SubKey
);
2652 /************************************************************************
2658 RegReplaceKeyW (HKEY hKey
,
2663 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2664 OBJECT_ATTRIBUTES NewObjectAttributes
;
2665 OBJECT_ATTRIBUTES OldObjectAttributes
;
2666 UNICODE_STRING SubKeyName
;
2667 UNICODE_STRING NewFileName
;
2668 UNICODE_STRING OldFileName
;
2669 BOOLEAN CloseRealKey
;
2670 HANDLE RealKeyHandle
;
2675 if (hKey
== HKEY_PERFORMANCE_DATA
)
2677 return ERROR_INVALID_HANDLE
;
2680 Status
= MapDefaultKey (&KeyHandle
,
2682 if (!NT_SUCCESS(Status
))
2684 ErrorCode
= RtlNtStatusToDosError (Status
);
2685 SetLastError (ErrorCode
);
2689 /* Open the real key */
2690 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
2692 RtlInitUnicodeString (&SubKeyName
,
2694 InitializeObjectAttributes (&KeyObjectAttributes
,
2696 OBJ_CASE_INSENSITIVE
,
2699 Status
= NtOpenKey (&RealKeyHandle
,
2701 &KeyObjectAttributes
);
2702 if (!NT_SUCCESS(Status
))
2704 ErrorCode
= RtlNtStatusToDosError (Status
);
2705 SetLastError (ErrorCode
);
2708 CloseRealKey
= TRUE
;
2712 RealKeyHandle
= KeyHandle
;
2713 CloseRealKey
= FALSE
;
2716 /* Convert new file name */
2717 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
2724 NtClose (RealKeyHandle
);
2726 SetLastError (ERROR_INVALID_PARAMETER
);
2727 return ERROR_INVALID_PARAMETER
;
2730 InitializeObjectAttributes (&NewObjectAttributes
,
2732 OBJ_CASE_INSENSITIVE
,
2736 /* Convert old file name */
2737 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
2742 RtlFreeUnicodeString (&NewFileName
);
2745 NtClose (RealKeyHandle
);
2747 SetLastError (ERROR_INVALID_PARAMETER
);
2748 return ERROR_INVALID_PARAMETER
;
2751 InitializeObjectAttributes (&OldObjectAttributes
,
2753 OBJ_CASE_INSENSITIVE
,
2757 Status
= NtReplaceKey (&NewObjectAttributes
,
2759 &OldObjectAttributes
);
2761 RtlFreeUnicodeString (&OldFileName
);
2762 RtlFreeUnicodeString (&NewFileName
);
2766 NtClose (RealKeyHandle
);
2769 if (!NT_SUCCESS(Status
))
2771 ErrorCode
= RtlNtStatusToDosError (Status
);
2772 SetLastError (ErrorCode
);
2776 return ERROR_SUCCESS
;
2780 /************************************************************************
2786 RegRestoreKeyA (HKEY hKey
,
2790 UNICODE_STRING FileName
;
2793 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2796 ErrorCode
= RegRestoreKeyW (hKey
,
2800 RtlFreeUnicodeString (&FileName
);
2806 /************************************************************************
2812 RegRestoreKeyW (HKEY hKey
,
2816 OBJECT_ATTRIBUTES ObjectAttributes
;
2817 IO_STATUS_BLOCK IoStatusBlock
;
2818 UNICODE_STRING FileName
;
2824 if (hKey
== HKEY_PERFORMANCE_DATA
)
2826 return ERROR_INVALID_HANDLE
;
2829 Status
= MapDefaultKey (&KeyHandle
,
2831 if (!NT_SUCCESS(Status
))
2833 ErrorCode
= RtlNtStatusToDosError (Status
);
2834 SetLastError (ErrorCode
);
2838 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2843 SetLastError (ERROR_INVALID_PARAMETER
);
2844 return ERROR_INVALID_PARAMETER
;
2847 InitializeObjectAttributes (&ObjectAttributes
,
2849 OBJ_CASE_INSENSITIVE
,
2853 Status
= NtOpenFile (&FileHandle
,
2858 FILE_SYNCHRONOUS_IO_NONALERT
);
2859 RtlFreeUnicodeString (&FileName
);
2860 if (!NT_SUCCESS(Status
))
2862 ErrorCode
= RtlNtStatusToDosError (Status
);
2863 SetLastError (ErrorCode
);
2867 Status
= NtRestoreKey (KeyHandle
,
2870 NtClose (FileHandle
);
2871 if (!NT_SUCCESS(Status
))
2873 ErrorCode
= RtlNtStatusToDosError (Status
);
2874 SetLastError (ErrorCode
);
2878 return ERROR_SUCCESS
;
2882 /************************************************************************
2888 RegSaveKeyA (HKEY hKey
,
2890 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2892 UNICODE_STRING FileName
;
2895 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2897 ErrorCode
= RegSaveKeyW (hKey
,
2899 lpSecurityAttributes
);
2900 RtlFreeUnicodeString (&FileName
);
2906 /************************************************************************
2912 RegSaveKeyW (HKEY hKey
,
2914 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2916 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2917 OBJECT_ATTRIBUTES ObjectAttributes
;
2918 UNICODE_STRING FileName
;
2919 IO_STATUS_BLOCK IoStatusBlock
;
2925 Status
= MapDefaultKey (&KeyHandle
,
2927 if (!NT_SUCCESS(Status
))
2929 ErrorCode
= RtlNtStatusToDosError (Status
);
2930 SetLastError (ErrorCode
);
2934 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
2939 SetLastError (ERROR_INVALID_PARAMETER
);
2940 return ERROR_INVALID_PARAMETER
;
2943 if (lpSecurityAttributes
!= NULL
)
2945 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2948 InitializeObjectAttributes (&ObjectAttributes
,
2950 OBJ_CASE_INSENSITIVE
,
2952 SecurityDescriptor
);
2953 Status
= NtCreateFile (&FileHandle
,
2954 GENERIC_WRITE
| SYNCHRONIZE
,
2958 FILE_ATTRIBUTE_NORMAL
,
2961 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2964 RtlFreeUnicodeString (&FileName
);
2965 if (!NT_SUCCESS(Status
))
2967 ErrorCode
= RtlNtStatusToDosError (Status
);
2968 SetLastError (ErrorCode
);
2972 Status
= NtSaveKey (KeyHandle
,
2974 NtClose (FileHandle
);
2975 if (!NT_SUCCESS(Status
))
2977 ErrorCode
= RtlNtStatusToDosError (Status
);
2978 SetLastError (ErrorCode
);
2982 return ERROR_SUCCESS
;
2986 /************************************************************************
2992 RegSetKeySecurity (HKEY hKey
,
2993 SECURITY_INFORMATION SecurityInformation
,
2994 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3000 if (hKey
== HKEY_PERFORMANCE_DATA
)
3002 return ERROR_INVALID_HANDLE
;
3005 Status
= MapDefaultKey (&KeyHandle
,
3007 if (!NT_SUCCESS(Status
))
3009 ErrorCode
= RtlNtStatusToDosError (Status
);
3010 SetLastError (ErrorCode
);
3014 Status
= NtSetSecurityObject (KeyHandle
,
3015 SecurityInformation
,
3016 pSecurityDescriptor
);
3017 if (!NT_SUCCESS(Status
))
3019 ErrorCode
= RtlNtStatusToDosError (Status
);
3020 SetLastError (ErrorCode
);
3024 return ERROR_SUCCESS
;
3028 /************************************************************************
3034 RegSetValueExA (HKEY hKey
,
3041 UNICODE_STRING ValueName
;
3043 ANSI_STRING AnsiString
;
3044 UNICODE_STRING Data
;
3051 SetLastError (ERROR_INVALID_PARAMETER
);
3052 return ERROR_INVALID_PARAMETER
;
3055 if (lpValueName
!= NULL
&&
3056 strlen(lpValueName
) != 0)
3058 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3060 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3067 if ((dwType
== REG_SZ
) ||
3068 (dwType
== REG_MULTI_SZ
) ||
3069 (dwType
== REG_EXPAND_SZ
))
3071 RtlInitAnsiString (&AnsiString
,
3073 AnsiString
.Buffer
= (PSTR
)lpData
;
3074 AnsiString
.Length
= cbData
;
3075 AnsiString
.MaximumLength
= cbData
;
3076 RtlAnsiStringToUnicodeString (&Data
,
3079 pData
= (LPBYTE
)Data
.Buffer
;
3080 DataSize
= cbData
* sizeof(WCHAR
);
3084 RtlInitUnicodeString (&Data
,
3086 pData
= (LPBYTE
)lpData
;
3090 ErrorCode
= RegSetValueExW (hKey
,
3096 if (pValueName
!= NULL
)
3098 RtlFreeHeap (ProcessHeap
,
3103 if (Data
.Buffer
!= NULL
)
3105 RtlFreeHeap (ProcessHeap
,
3114 /************************************************************************
3120 RegSetValueExW (HKEY hKey
,
3121 LPCWSTR lpValueName
,
3127 UNICODE_STRING ValueName
;
3128 PUNICODE_STRING pValueName
;
3133 Status
= MapDefaultKey (&KeyHandle
,
3135 if (!NT_SUCCESS(Status
))
3137 ErrorCode
= RtlNtStatusToDosError (Status
);
3138 SetLastError (ErrorCode
);
3142 if (lpValueName
!= NULL
)
3144 RtlInitUnicodeString (&ValueName
,
3149 RtlInitUnicodeString (&ValueName
, L
"");
3151 pValueName
= &ValueName
;
3153 Status
= NtSetValueKey (KeyHandle
,
3159 if (!NT_SUCCESS(Status
))
3161 ErrorCode
= RtlNtStatusToDosError (Status
);
3162 SetLastError (ErrorCode
);
3166 return ERROR_SUCCESS
;
3170 /************************************************************************
3176 RegSetValueA (HKEY hKey
,
3182 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3183 UNICODE_STRING SubKeyName
;
3184 UNICODE_STRING Data
;
3185 ANSI_STRING AnsiString
;
3191 SetLastError (ERROR_INVALID_PARAMETER
);
3192 return ERROR_INVALID_PARAMETER
;
3195 RtlInitUnicodeString (&SubKeyName
, NULL
);
3196 RtlInitUnicodeString (&Data
, NULL
);
3197 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
3199 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
3200 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3201 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3202 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
3205 DataSize
= cbData
* sizeof(WCHAR
);
3206 Data
.MaximumLength
= DataSize
;
3207 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3210 if (Data
.Buffer
== NULL
)
3212 SetLastError (ERROR_OUTOFMEMORY
);
3213 return ERROR_OUTOFMEMORY
;
3216 ErrorCode
= RegSetValueW (hKey
,
3217 (LPCWSTR
)SubKeyName
.Buffer
,
3222 RtlFreeHeap (ProcessHeap
,
3230 /************************************************************************
3236 RegSetValueW (HKEY hKey
,
3242 OBJECT_ATTRIBUTES ObjectAttributes
;
3243 UNICODE_STRING SubKeyString
;
3250 Status
= MapDefaultKey (&KeyHandle
,
3252 if (!NT_SUCCESS(Status
))
3254 ErrorCode
= RtlNtStatusToDosError (Status
);
3255 SetLastError (ErrorCode
);
3259 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3261 RtlInitUnicodeString (&SubKeyString
,
3263 InitializeObjectAttributes (&ObjectAttributes
,
3265 OBJ_CASE_INSENSITIVE
,
3268 Status
= NtOpenKey (&RealKey
,
3271 if (!NT_SUCCESS(Status
))
3273 ErrorCode
= RtlNtStatusToDosError (Status
);
3274 SetLastError (ErrorCode
);
3277 CloseRealKey
= TRUE
;
3282 CloseRealKey
= FALSE
;
3285 ErrorCode
= RegSetValueExW (RealKey
,
3291 if (CloseRealKey
== TRUE
)
3300 /************************************************************************
3306 RegUnLoadKeyA (HKEY hKey
,
3309 UNICODE_STRING KeyName
;
3312 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3315 ErrorCode
= RegUnLoadKeyW (hKey
,
3318 RtlFreeUnicodeString (&KeyName
);
3324 /************************************************************************
3330 RegUnLoadKeyW (HKEY hKey
,
3333 OBJECT_ATTRIBUTES ObjectAttributes
;
3334 UNICODE_STRING KeyName
;
3339 if (hKey
== HKEY_PERFORMANCE_DATA
)
3340 return ERROR_INVALID_HANDLE
;
3342 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3343 if (!NT_SUCCESS(Status
))
3345 ErrorCode
= RtlNtStatusToDosError (Status
);
3346 SetLastError (ErrorCode
);
3350 RtlInitUnicodeString (&KeyName
,
3353 InitializeObjectAttributes (&ObjectAttributes
,
3355 OBJ_CASE_INSENSITIVE
,
3359 Status
= NtUnloadKey (&ObjectAttributes
);
3361 if (!NT_SUCCESS(Status
))
3363 ErrorCode
= RtlNtStatusToDosError (Status
);
3364 SetLastError (ErrorCode
);
3368 return ERROR_SUCCESS
;