1 /* $Id: reg.c,v 1.60 2004/10/10 10:10:52 hbirr 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 if (NULL
!= lpcbData
)
1449 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1453 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1455 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1459 RtlFreeHeap (ProcessHeap
,
1463 if (ErrorCode
!= ERROR_SUCCESS
)
1465 SetLastError (ErrorCode
);
1472 /************************************************************************
1478 RegFlushKey(HKEY hKey
)
1484 if (hKey
== HKEY_PERFORMANCE_DATA
)
1486 return ERROR_SUCCESS
;
1489 Status
= MapDefaultKey (&KeyHandle
,
1491 if (!NT_SUCCESS(Status
))
1493 ErrorCode
= RtlNtStatusToDosError (Status
);
1494 SetLastError (ErrorCode
);
1498 Status
= NtFlushKey (KeyHandle
);
1499 if (!NT_SUCCESS(Status
))
1501 ErrorCode
= RtlNtStatusToDosError (Status
);
1502 SetLastError (ErrorCode
);
1506 return ERROR_SUCCESS
;
1510 /************************************************************************
1516 RegGetKeySecurity(HKEY hKey
,
1517 SECURITY_INFORMATION SecurityInformation
,
1518 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1519 LPDWORD lpcbSecurityDescriptor
)
1525 if (hKey
== HKEY_PERFORMANCE_DATA
)
1527 SetLastError(ERROR_INVALID_HANDLE
);
1528 return ERROR_INVALID_HANDLE
;
1531 Status
= MapDefaultKey(&KeyHandle
,
1533 if (!NT_SUCCESS(Status
))
1535 DPRINT("MapDefaultKey() failed (Status %lx)\n", Status
);
1536 ErrorCode
= RtlNtStatusToDosError(Status
);
1537 SetLastError(ErrorCode
);
1541 Status
= NtQuerySecurityObject(KeyHandle
,
1542 SecurityInformation
,
1543 pSecurityDescriptor
,
1544 *lpcbSecurityDescriptor
,
1545 lpcbSecurityDescriptor
);
1546 if (!NT_SUCCESS(Status
))
1548 DPRINT("NtQuerySecurityObject() failed (Status %lx)\n", Status
);
1549 ErrorCode
= RtlNtStatusToDosError(Status
);
1550 SetLastError(ErrorCode
);
1554 return ERROR_SUCCESS
;
1558 /************************************************************************
1564 RegLoadKeyA (HKEY hKey
,
1568 UNICODE_STRING FileName
;
1569 UNICODE_STRING KeyName
;
1572 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1574 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1577 ErrorCode
= RegLoadKeyW (hKey
,
1581 RtlFreeUnicodeString (&FileName
);
1582 RtlFreeUnicodeString (&KeyName
);
1588 /************************************************************************
1594 RegLoadKeyW (HKEY hKey
,
1598 OBJECT_ATTRIBUTES FileObjectAttributes
;
1599 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1600 UNICODE_STRING FileName
;
1601 UNICODE_STRING KeyName
;
1606 if (hKey
== HKEY_PERFORMANCE_DATA
)
1608 SetLastError(ERROR_INVALID_HANDLE
);
1609 return ERROR_INVALID_HANDLE
;
1612 Status
= MapDefaultKey (&KeyHandle
,
1614 if (!NT_SUCCESS(Status
))
1616 ErrorCode
= RtlNtStatusToDosError (Status
);
1617 SetLastError (ErrorCode
);
1621 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1626 SetLastError (ERROR_BAD_PATHNAME
);
1627 return ERROR_BAD_PATHNAME
;
1630 InitializeObjectAttributes (&FileObjectAttributes
,
1632 OBJ_CASE_INSENSITIVE
,
1636 RtlInitUnicodeString (&KeyName
,
1639 InitializeObjectAttributes (&KeyObjectAttributes
,
1641 OBJ_CASE_INSENSITIVE
,
1645 Status
= NtLoadKey (&KeyObjectAttributes
,
1646 &FileObjectAttributes
);
1648 RtlFreeUnicodeString (&FileName
);
1650 if (!NT_SUCCESS(Status
))
1652 ErrorCode
= RtlNtStatusToDosError (Status
);
1653 SetLastError (ErrorCode
);
1657 return ERROR_SUCCESS
;
1661 /************************************************************************
1662 * RegNotifyChangeKeyValue
1667 RegNotifyChangeKeyValue (HKEY hKey
,
1669 DWORD dwNotifyFilter
,
1673 IO_STATUS_BLOCK IoStatusBlock
;
1677 if (hKey
== HKEY_PERFORMANCE_DATA
)
1679 return ERROR_INVALID_HANDLE
;
1682 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1684 return ERROR_INVALID_PARAMETER
;
1687 Status
= MapDefaultKey (&KeyHandle
,
1689 if (!NT_SUCCESS(Status
))
1691 return RtlNtStatusToDosError (Status
);
1694 /* FIXME: Remote key handles must fail */
1696 Status
= NtNotifyChangeKey (KeyHandle
,
1706 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1708 return RtlNtStatusToDosError (Status
);
1711 return ERROR_SUCCESS
;
1715 /************************************************************************
1721 RegOpenKeyA (HKEY hKey
,
1725 OBJECT_ATTRIBUTES ObjectAttributes
;
1726 UNICODE_STRING SubKeyString
;
1731 Status
= MapDefaultKey (&KeyHandle
,
1733 if (!NT_SUCCESS(Status
))
1735 ErrorCode
= RtlNtStatusToDosError (Status
);
1736 SetLastError (ErrorCode
);
1740 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1742 InitializeObjectAttributes (&ObjectAttributes
,
1744 OBJ_CASE_INSENSITIVE
,
1747 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1750 RtlFreeUnicodeString (&SubKeyString
);
1751 if (!NT_SUCCESS(Status
))
1753 ErrorCode
= RtlNtStatusToDosError (Status
);
1754 SetLastError (ErrorCode
);
1758 return ERROR_SUCCESS
;
1762 /************************************************************************
1771 RegOpenKeyW (HKEY hKey
,
1775 OBJECT_ATTRIBUTES ObjectAttributes
;
1776 UNICODE_STRING SubKeyString
;
1781 Status
= MapDefaultKey (&KeyHandle
,
1783 if (!NT_SUCCESS(Status
))
1785 ErrorCode
= RtlNtStatusToDosError (Status
);
1786 SetLastError (ErrorCode
);
1790 RtlInitUnicodeString (&SubKeyString
,
1792 InitializeObjectAttributes (&ObjectAttributes
,
1794 OBJ_CASE_INSENSITIVE
,
1797 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1800 if (!NT_SUCCESS(Status
))
1802 ErrorCode
= RtlNtStatusToDosError (Status
);
1803 SetLastError(ErrorCode
);
1807 return ERROR_SUCCESS
;
1811 /************************************************************************
1817 RegOpenKeyExA (HKEY hKey
,
1823 OBJECT_ATTRIBUTES ObjectAttributes
;
1824 UNICODE_STRING SubKeyString
;
1829 Status
= MapDefaultKey (&KeyHandle
,
1831 if (!NT_SUCCESS(Status
))
1833 ErrorCode
= RtlNtStatusToDosError (Status
);
1834 SetLastError (ErrorCode
);
1838 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1840 InitializeObjectAttributes (&ObjectAttributes
,
1842 OBJ_CASE_INSENSITIVE
,
1845 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1848 RtlFreeUnicodeString (&SubKeyString
);
1849 if (!NT_SUCCESS(Status
))
1851 ErrorCode
= RtlNtStatusToDosError (Status
);
1852 SetLastError (ErrorCode
);
1856 return ERROR_SUCCESS
;
1860 /************************************************************************
1866 RegOpenKeyExW (HKEY hKey
,
1872 OBJECT_ATTRIBUTES ObjectAttributes
;
1873 UNICODE_STRING SubKeyString
;
1878 Status
= MapDefaultKey (&KeyHandle
,
1880 if (!NT_SUCCESS(Status
))
1882 ErrorCode
= RtlNtStatusToDosError (Status
);
1883 SetLastError (ErrorCode
);
1887 if (lpSubKey
!= NULL
)
1889 RtlInitUnicodeString (&SubKeyString
,
1894 RtlInitUnicodeString (&SubKeyString
,
1897 InitializeObjectAttributes (&ObjectAttributes
,
1899 OBJ_CASE_INSENSITIVE
,
1902 Status
= NtOpenKey ((PHANDLE
)phkResult
,
1905 if (!NT_SUCCESS(Status
))
1907 ErrorCode
= RtlNtStatusToDosError (Status
);
1908 SetLastError (ErrorCode
);
1912 return ERROR_SUCCESS
;
1916 /************************************************************************
1922 RegQueryInfoKeyA (HKEY hKey
,
1927 LPDWORD lpcbMaxSubKeyLen
,
1928 LPDWORD lpcbMaxClassLen
,
1930 LPDWORD lpcbMaxValueNameLen
,
1931 LPDWORD lpcbMaxValueLen
,
1932 LPDWORD lpcbSecurityDescriptor
,
1933 PFILETIME lpftLastWriteTime
)
1935 WCHAR ClassName
[MAX_PATH
];
1936 UNICODE_STRING UnicodeString
;
1937 ANSI_STRING AnsiString
;
1940 RtlInitUnicodeString (&UnicodeString
,
1942 if (lpClass
!= NULL
)
1944 UnicodeString
.Buffer
= &ClassName
[0];
1945 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1946 AnsiString
.MaximumLength
= *lpcbClass
;
1949 ErrorCode
= RegQueryInfoKeyW (hKey
,
1950 UnicodeString
.Buffer
,
1957 lpcbMaxValueNameLen
,
1959 lpcbSecurityDescriptor
,
1961 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1963 AnsiString
.Buffer
= lpClass
;
1964 AnsiString
.Length
= 0;
1965 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1966 RtlUnicodeStringToAnsiString (&AnsiString
,
1969 *lpcbClass
= AnsiString
.Length
;
1970 lpClass
[AnsiString
.Length
] = 0;
1977 /************************************************************************
1983 RegQueryInfoKeyW (HKEY hKey
,
1988 LPDWORD lpcbMaxSubKeyLen
,
1989 LPDWORD lpcbMaxClassLen
,
1991 LPDWORD lpcbMaxValueNameLen
,
1992 LPDWORD lpcbMaxValueLen
,
1993 LPDWORD lpcbSecurityDescriptor
,
1994 PFILETIME lpftLastWriteTime
)
1996 KEY_FULL_INFORMATION FullInfoBuffer
;
1997 PKEY_FULL_INFORMATION FullInfo
;
1999 ULONG ClassLength
= 0;
2002 LONG ErrorCode
= ERROR_SUCCESS
;
2005 if ((lpClass
) && (!lpcbClass
))
2007 SetLastError(ERROR_INVALID_PARAMETER
);
2008 return ERROR_INVALID_PARAMETER
;
2011 Status
= MapDefaultKey (&KeyHandle
,
2013 if (!NT_SUCCESS(Status
))
2015 ErrorCode
= RtlNtStatusToDosError (Status
);
2016 SetLastError (ErrorCode
);
2020 if (lpClass
!= NULL
)
2024 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
2031 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
2032 FullInfo
= RtlAllocateHeap (ProcessHeap
,
2035 if (FullInfo
== NULL
)
2037 SetLastError (ERROR_OUTOFMEMORY
);
2038 return ERROR_OUTOFMEMORY
;
2041 FullInfo
->ClassLength
= ClassLength
;
2045 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
2046 FullInfo
= &FullInfoBuffer
;
2047 FullInfo
->ClassLength
= 0;
2049 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
2051 Status
= NtQueryKey (KeyHandle
,
2056 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
2057 if (!NT_SUCCESS(Status
))
2059 if (lpClass
!= NULL
)
2061 RtlFreeHeap (ProcessHeap
,
2066 ErrorCode
= RtlNtStatusToDosError (Status
);
2067 SetLastError (ErrorCode
);
2071 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
2072 if (lpcSubKeys
!= NULL
)
2074 *lpcSubKeys
= FullInfo
->SubKeys
;
2077 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
2078 if (lpcbMaxSubKeyLen
!= NULL
)
2080 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
2083 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
2084 if (lpcbMaxClassLen
!= NULL
)
2086 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
2089 DPRINT("Values %lu\n", FullInfo
->Values
);
2090 if (lpcValues
!= NULL
)
2092 *lpcValues
= FullInfo
->Values
;
2095 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
2096 if (lpcbMaxValueNameLen
!= NULL
)
2098 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
2101 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
2102 if (lpcbMaxValueLen
!= NULL
)
2104 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
2107 if (lpcbSecurityDescriptor
!= NULL
)
2109 Status
= NtQuerySecurityObject(KeyHandle
,
2110 OWNER_SECURITY_INFORMATION
|
2111 GROUP_SECURITY_INFORMATION
|
2112 DACL_SECURITY_INFORMATION
,
2115 lpcbSecurityDescriptor
);
2116 if (!NT_SUCCESS(Status
))
2118 if (lpClass
!= NULL
)
2120 RtlFreeHeap(ProcessHeap
,
2125 ErrorCode
= RtlNtStatusToDosError(Status
);
2126 SetLastError(ErrorCode
);
2131 if (lpftLastWriteTime
!= NULL
)
2133 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
2134 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
2137 if (lpClass
!= NULL
)
2139 if (FullInfo
->ClassLength
> ClassLength
)
2141 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
2145 RtlCopyMemory (lpClass
,
2147 FullInfo
->ClassLength
);
2148 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
2149 lpClass
[*lpcbClass
] = 0;
2152 RtlFreeHeap (ProcessHeap
,
2157 if (ErrorCode
!= ERROR_SUCCESS
)
2159 SetLastError (ErrorCode
);
2166 /************************************************************************
2167 * RegQueryMultipleValuesA
2172 RegQueryMultipleValuesA (HKEY hKey
,
2179 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2180 return ERROR_CALL_NOT_IMPLEMENTED
;
2184 /************************************************************************
2185 * RegQueryMultipleValuesW
2190 RegQueryMultipleValuesW (HKEY hKey
,
2197 DWORD maxBytes
= *ldwTotsize
;
2198 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2201 if (maxBytes
>= (1024*1024))
2202 return ERROR_TRANSFER_TOO_LONG
;
2206 DPRINT ("RegQueryMultipleValuesW(%p,%p,%ld,%p,%p=%ld)\n",
2207 hKey
, val_list
, num_vals
, lpValueBuf
, ldwTotsize
, *ldwTotsize
);
2209 for (i
= 0; i
< num_vals
; ++i
)
2211 val_list
[i
].ve_valuelen
= 0;
2212 ErrorCode
= RegQueryValueExW (hKey
,
2213 val_list
[i
].ve_valuename
,
2217 &val_list
[i
].ve_valuelen
);
2218 if (ErrorCode
!= ERROR_SUCCESS
)
2223 if (lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2225 ErrorCode
= RegQueryValueExW (hKey
,
2226 val_list
[i
].ve_valuename
,
2228 &val_list
[i
].ve_type
,
2230 &val_list
[i
].ve_valuelen
);
2231 if (ErrorCode
!= ERROR_SUCCESS
)
2236 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2238 bufptr
+= val_list
[i
].ve_valuelen
;
2241 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2244 return (lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
) ? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2248 /************************************************************************
2254 RegQueryValueExW (HKEY hKey
,
2255 LPCWSTR lpValueName
,
2261 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2262 UNICODE_STRING ValueName
;
2264 LONG ErrorCode
= ERROR_SUCCESS
;
2268 ULONG MaxCopy
= lpcbData
!= NULL
&& lpData
!= NULL
? *lpcbData
: 0;
2270 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2271 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2273 Status
= MapDefaultKey (&KeyHandle
,
2275 if (!NT_SUCCESS(Status
))
2277 ErrorCode
= RtlNtStatusToDosError (Status
);
2278 SetLastError (ErrorCode
);
2282 if (lpData
!= NULL
&& lpcbData
== NULL
)
2284 SetLastError (ERROR_INVALID_PARAMETER
);
2285 return ERROR_INVALID_PARAMETER
;
2288 RtlInitUnicodeString (&ValueName
,
2290 BufferSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + MaxCopy
;
2291 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2294 if (ValueInfo
== NULL
)
2296 SetLastError(ERROR_OUTOFMEMORY
);
2297 return ERROR_OUTOFMEMORY
;
2300 Status
= NtQueryValueKey (hKey
,
2302 KeyValuePartialInformation
,
2306 DPRINT("Status 0x%X\n", Status
);
2307 if (Status
== STATUS_BUFFER_OVERFLOW
)
2309 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2311 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2313 else if (!NT_SUCCESS(Status
))
2315 ErrorCode
= RtlNtStatusToDosError (Status
);
2316 SetLastError (ErrorCode
);
2318 if (lpcbData
!= NULL
)
2320 ResultSize
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) + *lpcbData
;
2326 *lpType
= ValueInfo
->Type
;
2329 if (NT_SUCCESS(Status
) && lpData
!= NULL
)
2331 RtlMoveMemory (lpData
,
2333 min(ValueInfo
->DataLength
, MaxCopy
));
2336 if ((ValueInfo
->Type
== REG_SZ
) ||
2337 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2338 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2340 if (lpData
!= NULL
&& MaxCopy
> ValueInfo
->DataLength
)
2342 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2345 if (lpcbData
!= NULL
)
2347 *lpcbData
= (ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]));
2348 DPRINT("(string) Returning Size: %lu\n", *lpcbData
);
2353 if (lpcbData
!= NULL
)
2355 *lpcbData
= ResultSize
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
2356 DPRINT("(other) Returning Size: %lu\n", *lpcbData
);
2360 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2362 RtlFreeHeap (ProcessHeap
,
2370 /************************************************************************
2376 RegQueryValueExA (HKEY hKey
,
2383 UNICODE_STRING ValueName
;
2384 UNICODE_STRING ValueData
;
2385 ANSI_STRING AnsiString
;
2390 if (lpData
!= NULL
&& lpcbData
== NULL
)
2392 SetLastError(ERROR_INVALID_PARAMETER
);
2393 return ERROR_INVALID_PARAMETER
;
2398 ValueData
.Length
= *lpcbData
* sizeof(WCHAR
);
2399 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2400 ValueData
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2402 ValueData
.MaximumLength
);
2403 if (!ValueData
.Buffer
)
2405 SetLastError(ERROR_OUTOFMEMORY
);
2406 return ERROR_OUTOFMEMORY
;
2411 ValueData
.Buffer
= NULL
;
2412 ValueData
.Length
= 0;
2413 ValueData
.MaximumLength
= 0;
2416 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2417 (LPSTR
)lpValueName
);
2419 if (NULL
!= lpcbData
)
2421 Length
= *lpcbData
* sizeof(WCHAR
);
2423 ErrorCode
= RegQueryValueExW (hKey
,
2427 (LPBYTE
)ValueData
.Buffer
,
2428 NULL
== lpcbData
? NULL
: &Length
);
2429 DPRINT("ErrorCode %lu\n", ErrorCode
);
2431 if (ErrorCode
== ERROR_SUCCESS
||
2432 ErrorCode
== ERROR_MORE_DATA
)
2439 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2441 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2443 RtlInitAnsiString(&AnsiString
, NULL
);
2444 AnsiString
.Buffer
= lpData
;
2445 AnsiString
.MaximumLength
= *lpcbData
;
2446 ValueData
.Length
= Length
;
2447 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2448 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2450 Length
= Length
/ sizeof(WCHAR
);
2452 else if (lpcbData
!= NULL
)
2454 Length
= min(*lpcbData
, Length
);
2455 if (ErrorCode
== ERROR_SUCCESS
&& ValueData
.Buffer
!= NULL
)
2457 RtlMoveMemory(lpData
, ValueData
.Buffer
, Length
);
2461 if (lpcbData
!= NULL
)
2467 if (ValueData
.Buffer
!= NULL
)
2469 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2476 /************************************************************************
2482 RegQueryValueA (HKEY hKey
,
2487 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2488 UNICODE_STRING SubKeyName
;
2489 UNICODE_STRING Value
;
2490 ANSI_STRING AnsiString
;
2494 if (lpValue
!= NULL
&&
2497 SetLastError(ERROR_INVALID_PARAMETER
);
2498 return ERROR_INVALID_PARAMETER
;
2501 RtlInitUnicodeString (&SubKeyName
,
2503 RtlInitUnicodeString (&Value
,
2505 if (lpSubKey
!= NULL
&&
2506 strlen(lpSubKey
) != 0)
2508 RtlInitAnsiString (&AnsiString
,
2510 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2511 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2512 RtlAnsiStringToUnicodeString (&SubKeyName
,
2517 if (lpValue
!= NULL
)
2519 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2520 Value
.MaximumLength
= ValueSize
;
2521 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2524 if (Value
.Buffer
== NULL
)
2526 SetLastError(ERROR_OUTOFMEMORY
);
2527 return ERROR_OUTOFMEMORY
;
2535 ErrorCode
= RegQueryValueW (hKey
,
2536 (LPCWSTR
)SubKeyName
.Buffer
,
2539 if (ErrorCode
== ERROR_SUCCESS
)
2541 Value
.Length
= ValueSize
;
2542 RtlInitAnsiString (&AnsiString
,
2544 AnsiString
.Buffer
= lpValue
;
2545 AnsiString
.MaximumLength
= *lpcbValue
;
2546 RtlUnicodeStringToAnsiString (&AnsiString
,
2551 *lpcbValue
= ValueSize
;
2552 if (Value
.Buffer
!= NULL
)
2554 RtlFreeHeap (ProcessHeap
,
2563 /************************************************************************
2569 RegQueryValueW (HKEY hKey
,
2574 OBJECT_ATTRIBUTES ObjectAttributes
;
2575 UNICODE_STRING SubKeyString
;
2582 Status
= MapDefaultKey (&KeyHandle
,
2584 if (!NT_SUCCESS(Status
))
2586 ErrorCode
= RtlNtStatusToDosError (Status
);
2587 SetLastError (ErrorCode
);
2591 if (lpSubKey
!= NULL
&&
2592 wcslen(lpSubKey
) != 0)
2594 RtlInitUnicodeString (&SubKeyString
,
2596 InitializeObjectAttributes (&ObjectAttributes
,
2598 OBJ_CASE_INSENSITIVE
,
2601 Status
= NtOpenKey (&RealKey
,
2604 if (!NT_SUCCESS(Status
))
2606 ErrorCode
= RtlNtStatusToDosError (Status
);
2607 SetLastError (ErrorCode
);
2610 CloseRealKey
= TRUE
;
2615 CloseRealKey
= FALSE
;
2618 ErrorCode
= RegQueryValueExW (RealKey
,
2623 (LPDWORD
)lpcbValue
);
2633 /************************************************************************
2639 RegReplaceKeyA (HKEY hKey
,
2644 UNICODE_STRING SubKey
;
2645 UNICODE_STRING NewFile
;
2646 UNICODE_STRING OldFile
;
2649 RtlCreateUnicodeStringFromAsciiz (&SubKey
,
2651 RtlCreateUnicodeStringFromAsciiz (&OldFile
,
2653 RtlCreateUnicodeStringFromAsciiz (&NewFile
,
2656 ErrorCode
= RegReplaceKeyW (hKey
,
2661 RtlFreeUnicodeString (&OldFile
);
2662 RtlFreeUnicodeString (&NewFile
);
2663 RtlFreeUnicodeString (&SubKey
);
2669 /************************************************************************
2675 RegReplaceKeyW (HKEY hKey
,
2680 OBJECT_ATTRIBUTES KeyObjectAttributes
;
2681 OBJECT_ATTRIBUTES NewObjectAttributes
;
2682 OBJECT_ATTRIBUTES OldObjectAttributes
;
2683 UNICODE_STRING SubKeyName
;
2684 UNICODE_STRING NewFileName
;
2685 UNICODE_STRING OldFileName
;
2686 BOOLEAN CloseRealKey
;
2687 HANDLE RealKeyHandle
;
2692 if (hKey
== HKEY_PERFORMANCE_DATA
)
2694 return ERROR_INVALID_HANDLE
;
2697 Status
= MapDefaultKey (&KeyHandle
,
2699 if (!NT_SUCCESS(Status
))
2701 ErrorCode
= RtlNtStatusToDosError (Status
);
2702 SetLastError (ErrorCode
);
2706 /* Open the real key */
2707 if (lpSubKey
!= NULL
&& *lpSubKey
!= (WCHAR
)0)
2709 RtlInitUnicodeString (&SubKeyName
,
2711 InitializeObjectAttributes (&KeyObjectAttributes
,
2713 OBJ_CASE_INSENSITIVE
,
2716 Status
= NtOpenKey (&RealKeyHandle
,
2718 &KeyObjectAttributes
);
2719 if (!NT_SUCCESS(Status
))
2721 ErrorCode
= RtlNtStatusToDosError (Status
);
2722 SetLastError (ErrorCode
);
2725 CloseRealKey
= TRUE
;
2729 RealKeyHandle
= KeyHandle
;
2730 CloseRealKey
= FALSE
;
2733 /* Convert new file name */
2734 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpNewFile
,
2741 NtClose (RealKeyHandle
);
2743 SetLastError (ERROR_INVALID_PARAMETER
);
2744 return ERROR_INVALID_PARAMETER
;
2747 InitializeObjectAttributes (&NewObjectAttributes
,
2749 OBJ_CASE_INSENSITIVE
,
2753 /* Convert old file name */
2754 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpOldFile
,
2759 RtlFreeUnicodeString (&NewFileName
);
2762 NtClose (RealKeyHandle
);
2764 SetLastError (ERROR_INVALID_PARAMETER
);
2765 return ERROR_INVALID_PARAMETER
;
2768 InitializeObjectAttributes (&OldObjectAttributes
,
2770 OBJ_CASE_INSENSITIVE
,
2774 Status
= NtReplaceKey (&NewObjectAttributes
,
2776 &OldObjectAttributes
);
2778 RtlFreeUnicodeString (&OldFileName
);
2779 RtlFreeUnicodeString (&NewFileName
);
2783 NtClose (RealKeyHandle
);
2786 if (!NT_SUCCESS(Status
))
2788 ErrorCode
= RtlNtStatusToDosError (Status
);
2789 SetLastError (ErrorCode
);
2793 return ERROR_SUCCESS
;
2797 /************************************************************************
2803 RegRestoreKeyA (HKEY hKey
,
2807 UNICODE_STRING FileName
;
2810 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2813 ErrorCode
= RegRestoreKeyW (hKey
,
2817 RtlFreeUnicodeString (&FileName
);
2823 /************************************************************************
2829 RegRestoreKeyW (HKEY hKey
,
2833 OBJECT_ATTRIBUTES ObjectAttributes
;
2834 IO_STATUS_BLOCK IoStatusBlock
;
2835 UNICODE_STRING FileName
;
2841 if (hKey
== HKEY_PERFORMANCE_DATA
)
2843 return ERROR_INVALID_HANDLE
;
2846 Status
= MapDefaultKey (&KeyHandle
,
2848 if (!NT_SUCCESS(Status
))
2850 ErrorCode
= RtlNtStatusToDosError (Status
);
2851 SetLastError (ErrorCode
);
2855 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2860 SetLastError (ERROR_INVALID_PARAMETER
);
2861 return ERROR_INVALID_PARAMETER
;
2864 InitializeObjectAttributes (&ObjectAttributes
,
2866 OBJ_CASE_INSENSITIVE
,
2870 Status
= NtOpenFile (&FileHandle
,
2875 FILE_SYNCHRONOUS_IO_NONALERT
);
2876 RtlFreeUnicodeString (&FileName
);
2877 if (!NT_SUCCESS(Status
))
2879 ErrorCode
= RtlNtStatusToDosError (Status
);
2880 SetLastError (ErrorCode
);
2884 Status
= NtRestoreKey (KeyHandle
,
2887 NtClose (FileHandle
);
2888 if (!NT_SUCCESS(Status
))
2890 ErrorCode
= RtlNtStatusToDosError (Status
);
2891 SetLastError (ErrorCode
);
2895 return ERROR_SUCCESS
;
2899 /************************************************************************
2905 RegSaveKeyA (HKEY hKey
,
2907 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2909 UNICODE_STRING FileName
;
2912 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2914 ErrorCode
= RegSaveKeyW (hKey
,
2916 lpSecurityAttributes
);
2917 RtlFreeUnicodeString (&FileName
);
2923 /************************************************************************
2929 RegSaveKeyW (HKEY hKey
,
2931 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2933 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2934 OBJECT_ATTRIBUTES ObjectAttributes
;
2935 UNICODE_STRING FileName
;
2936 IO_STATUS_BLOCK IoStatusBlock
;
2942 Status
= MapDefaultKey (&KeyHandle
,
2944 if (!NT_SUCCESS(Status
))
2946 ErrorCode
= RtlNtStatusToDosError (Status
);
2947 SetLastError (ErrorCode
);
2951 if (!RtlDosPathNameToNtPathName_U ((PWSTR
)lpFile
,
2956 SetLastError (ERROR_INVALID_PARAMETER
);
2957 return ERROR_INVALID_PARAMETER
;
2960 if (lpSecurityAttributes
!= NULL
)
2962 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2965 InitializeObjectAttributes (&ObjectAttributes
,
2967 OBJ_CASE_INSENSITIVE
,
2969 SecurityDescriptor
);
2970 Status
= NtCreateFile (&FileHandle
,
2971 GENERIC_WRITE
| SYNCHRONIZE
,
2975 FILE_ATTRIBUTE_NORMAL
,
2978 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2981 RtlFreeUnicodeString (&FileName
);
2982 if (!NT_SUCCESS(Status
))
2984 ErrorCode
= RtlNtStatusToDosError (Status
);
2985 SetLastError (ErrorCode
);
2989 Status
= NtSaveKey (KeyHandle
,
2991 NtClose (FileHandle
);
2992 if (!NT_SUCCESS(Status
))
2994 ErrorCode
= RtlNtStatusToDosError (Status
);
2995 SetLastError (ErrorCode
);
2999 return ERROR_SUCCESS
;
3003 /************************************************************************
3009 RegSetKeySecurity (HKEY hKey
,
3010 SECURITY_INFORMATION SecurityInformation
,
3011 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
3017 if (hKey
== HKEY_PERFORMANCE_DATA
)
3019 SetLastError(ERROR_INVALID_HANDLE
);
3020 return ERROR_INVALID_HANDLE
;
3023 Status
= MapDefaultKey (&KeyHandle
,
3025 if (!NT_SUCCESS(Status
))
3027 ErrorCode
= RtlNtStatusToDosError (Status
);
3028 SetLastError (ErrorCode
);
3032 Status
= NtSetSecurityObject (KeyHandle
,
3033 SecurityInformation
,
3034 pSecurityDescriptor
);
3035 if (!NT_SUCCESS(Status
))
3037 ErrorCode
= RtlNtStatusToDosError (Status
);
3038 SetLastError (ErrorCode
);
3042 return ERROR_SUCCESS
;
3046 /************************************************************************
3052 RegSetValueExA (HKEY hKey
,
3059 UNICODE_STRING ValueName
;
3061 ANSI_STRING AnsiString
;
3062 UNICODE_STRING Data
;
3069 SetLastError (ERROR_INVALID_PARAMETER
);
3070 return ERROR_INVALID_PARAMETER
;
3073 if (lpValueName
!= NULL
&&
3074 strlen(lpValueName
) != 0)
3076 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
3078 pValueName
= (LPWSTR
)ValueName
.Buffer
;
3085 if ((dwType
== REG_SZ
) ||
3086 (dwType
== REG_MULTI_SZ
) ||
3087 (dwType
== REG_EXPAND_SZ
))
3089 RtlInitAnsiString (&AnsiString
,
3091 AnsiString
.Buffer
= (PSTR
)lpData
;
3092 AnsiString
.Length
= cbData
;
3093 AnsiString
.MaximumLength
= cbData
;
3094 RtlAnsiStringToUnicodeString (&Data
,
3097 pData
= (LPBYTE
)Data
.Buffer
;
3098 DataSize
= cbData
* sizeof(WCHAR
);
3102 RtlInitUnicodeString (&Data
,
3104 pData
= (LPBYTE
)lpData
;
3108 ErrorCode
= RegSetValueExW (hKey
,
3114 if (pValueName
!= NULL
)
3116 RtlFreeHeap (ProcessHeap
,
3121 if (Data
.Buffer
!= NULL
)
3123 RtlFreeHeap (ProcessHeap
,
3132 /************************************************************************
3138 RegSetValueExW (HKEY hKey
,
3139 LPCWSTR lpValueName
,
3145 UNICODE_STRING ValueName
;
3146 PUNICODE_STRING pValueName
;
3151 Status
= MapDefaultKey (&KeyHandle
,
3153 if (!NT_SUCCESS(Status
))
3155 ErrorCode
= RtlNtStatusToDosError (Status
);
3156 SetLastError (ErrorCode
);
3160 if (lpValueName
!= NULL
)
3162 RtlInitUnicodeString (&ValueName
,
3167 RtlInitUnicodeString (&ValueName
, L
"");
3169 pValueName
= &ValueName
;
3171 Status
= NtSetValueKey (KeyHandle
,
3177 if (!NT_SUCCESS(Status
))
3179 ErrorCode
= RtlNtStatusToDosError (Status
);
3180 SetLastError (ErrorCode
);
3184 return ERROR_SUCCESS
;
3188 /************************************************************************
3194 RegSetValueA (HKEY hKey
,
3200 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
3201 UNICODE_STRING SubKeyName
;
3202 UNICODE_STRING Data
;
3203 ANSI_STRING AnsiString
;
3209 SetLastError (ERROR_INVALID_PARAMETER
);
3210 return ERROR_INVALID_PARAMETER
;
3213 RtlInitUnicodeString (&SubKeyName
, NULL
);
3214 RtlInitUnicodeString (&Data
, NULL
);
3215 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
3217 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
3218 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
3219 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
3220 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
3223 DataSize
= cbData
* sizeof(WCHAR
);
3224 Data
.MaximumLength
= DataSize
;
3225 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
3228 if (Data
.Buffer
== NULL
)
3230 SetLastError (ERROR_OUTOFMEMORY
);
3231 return ERROR_OUTOFMEMORY
;
3234 ErrorCode
= RegSetValueW (hKey
,
3235 (LPCWSTR
)SubKeyName
.Buffer
,
3240 RtlFreeHeap (ProcessHeap
,
3248 /************************************************************************
3254 RegSetValueW (HKEY hKey
,
3260 OBJECT_ATTRIBUTES ObjectAttributes
;
3261 UNICODE_STRING SubKeyString
;
3268 Status
= MapDefaultKey (&KeyHandle
,
3270 if (!NT_SUCCESS(Status
))
3272 ErrorCode
= RtlNtStatusToDosError (Status
);
3273 SetLastError (ErrorCode
);
3277 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
3279 RtlInitUnicodeString (&SubKeyString
,
3281 InitializeObjectAttributes (&ObjectAttributes
,
3283 OBJ_CASE_INSENSITIVE
,
3286 Status
= NtOpenKey (&RealKey
,
3289 if (!NT_SUCCESS(Status
))
3291 ErrorCode
= RtlNtStatusToDosError (Status
);
3292 SetLastError (ErrorCode
);
3295 CloseRealKey
= TRUE
;
3300 CloseRealKey
= FALSE
;
3303 ErrorCode
= RegSetValueExW (RealKey
,
3309 if (CloseRealKey
== TRUE
)
3318 /************************************************************************
3324 RegUnLoadKeyA (HKEY hKey
,
3327 UNICODE_STRING KeyName
;
3330 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
3333 ErrorCode
= RegUnLoadKeyW (hKey
,
3336 RtlFreeUnicodeString (&KeyName
);
3342 /************************************************************************
3348 RegUnLoadKeyW (HKEY hKey
,
3351 OBJECT_ATTRIBUTES ObjectAttributes
;
3352 UNICODE_STRING KeyName
;
3357 if (hKey
== HKEY_PERFORMANCE_DATA
)
3359 SetLastError(ERROR_INVALID_HANDLE
);
3360 return ERROR_INVALID_HANDLE
;
3363 Status
= MapDefaultKey (&KeyHandle
, hKey
);
3364 if (!NT_SUCCESS(Status
))
3366 ErrorCode
= RtlNtStatusToDosError (Status
);
3367 SetLastError (ErrorCode
);
3371 RtlInitUnicodeString (&KeyName
,
3374 InitializeObjectAttributes (&ObjectAttributes
,
3376 OBJ_CASE_INSENSITIVE
,
3380 Status
= NtUnloadKey (&ObjectAttributes
);
3382 if (!NT_SUCCESS(Status
))
3384 ErrorCode
= RtlNtStatusToDosError (Status
);
3385 SetLastError (ErrorCode
);
3389 return ERROR_SUCCESS
;