1 /* $Id: reg.c,v 1.31 2003/10/14 18:18:27 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 <ntdll/rtl.h>
25 /* DEFINES ******************************************************************/
27 #define MAX_DEFAULT_HANDLES 6
28 #define REG_MAX_NAME_SIZE 256
29 #define REG_MAX_DATA_SIZE 2048
31 /* GLOBALS ******************************************************************/
33 static CRITICAL_SECTION HandleTableCS
;
34 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
35 static HANDLE ProcessHeap
;
37 /* PROTOTYPES ***************************************************************/
39 static NTSTATUS
MapDefaultKey (PHKEY ParentKey
, HKEY Key
);
40 static VOID
CloseDefaultKeys(VOID
);
42 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
43 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
44 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
45 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
48 /* FUNCTIONS ****************************************************************/
50 /************************************************************************
51 * RegInitDefaultHandles
56 DPRINT("RegInitialize()\n");
58 ProcessHeap
= RtlGetProcessHeap();
59 RtlZeroMemory (DefaultHandleTable
,
60 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
61 RtlInitializeCriticalSection (&HandleTableCS
);
67 /************************************************************************
73 DPRINT("RegCleanup()\n");
76 RtlDeleteCriticalSection (&HandleTableCS
);
83 MapDefaultKey (PHKEY RealKey
,
88 NTSTATUS Status
= STATUS_SUCCESS
;
90 DPRINT("MapDefaultKey (Key %x)\n", Key
);
92 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
95 return STATUS_SUCCESS
;
98 /* Handle special cases here */
99 Index
= (ULONG
)Key
& 0x0FFFFFFF;
100 if (Index
>= MAX_DEFAULT_HANDLES
)
102 return STATUS_INVALID_PARAMETER
;
105 RtlEnterCriticalSection (&HandleTableCS
);
106 Handle
= &DefaultHandleTable
[Index
];
109 /* create/open the default handle */
112 case 0: /* HKEY_CLASSES_ROOT */
113 Status
= OpenClassesRootKey (Handle
);
116 case 1: /* HKEY_CURRENT_USER */
117 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
121 case 2: /* HKEY_LOCAL_MACHINE */
122 Status
= OpenLocalMachineKey (Handle
);
125 case 3: /* HKEY_USERS */
126 Status
= OpenUsersKey (Handle
);
129 case 4: /* HKEY_PERFORMANCE_DATA */
130 Status
= OpenPerformanceDataKey (Handle
);
133 case 5: /* HKEY_CURRENT_CONFIG */
134 Status
= OpenCurrentConfigKey (Handle
);
137 case 6: /* HKEY_DYN_DATA */
138 Status
= STATUS_NOT_IMPLEMENTED
;
142 DPRINT("MapDefaultHandle() no handle creator\n");
143 Status
= STATUS_INVALID_PARAMETER
;
146 RtlLeaveCriticalSection (&HandleTableCS
);
148 if (NT_SUCCESS(Status
))
150 *RealKey
= (HKEY
)*Handle
;
158 CloseDefaultKeys (VOID
)
162 RtlEnterCriticalSection (&HandleTableCS
);
163 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
165 if (DefaultHandleTable
[i
] != NULL
)
167 NtClose (DefaultHandleTable
[i
]);
168 DefaultHandleTable
[i
] = NULL
;
171 RtlLeaveCriticalSection (&HandleTableCS
);
176 OpenClassesRootKey (PHANDLE KeyHandle
)
178 OBJECT_ATTRIBUTES Attributes
;
179 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine\\Software\\CLASSES");
181 DPRINT("OpenClassesRootKey()\n");
183 InitializeObjectAttributes (&Attributes
,
185 OBJ_CASE_INSENSITIVE
,
188 return NtOpenKey (KeyHandle
,
195 OpenLocalMachineKey (PHANDLE KeyHandle
)
197 OBJECT_ATTRIBUTES Attributes
;
198 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine");
200 DPRINT("OpenLocalMachineKey()\n");
202 InitializeObjectAttributes (&Attributes
,
204 OBJ_CASE_INSENSITIVE
,
207 return NtOpenKey (KeyHandle
,
214 OpenUsersKey (PHANDLE KeyHandle
)
216 OBJECT_ATTRIBUTES Attributes
;
217 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\User");
219 DPRINT("OpenUsersKey()\n");
221 InitializeObjectAttributes (&Attributes
,
223 OBJ_CASE_INSENSITIVE
,
226 return NtOpenKey (KeyHandle
,
233 OpenCurrentConfigKey (PHANDLE KeyHandle
)
235 OBJECT_ATTRIBUTES Attributes
;
236 UNICODE_STRING KeyName
=
237 UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
239 DPRINT("OpenCurrentConfigKey()\n");
241 InitializeObjectAttributes (&Attributes
,
243 OBJ_CASE_INSENSITIVE
,
246 return NtOpenKey (KeyHandle
,
252 /************************************************************************
258 RegCloseKey (HKEY hKey
)
263 /* don't close null handle or a pseudo handle */
264 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
266 return ERROR_INVALID_HANDLE
;
269 Status
= NtClose (hKey
);
270 if (!NT_SUCCESS(Status
))
272 ErrorCode
= RtlNtStatusToDosError (Status
);
273 SetLastError (ErrorCode
);
277 return ERROR_SUCCESS
;
281 /************************************************************************
282 * RegConnectRegistryA
287 RegConnectRegistryA (LPCSTR lpMachineName
,
291 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
292 return ERROR_CALL_NOT_IMPLEMENTED
;
296 /************************************************************************
297 * RegConnectRegistryW
302 RegConnectRegistryW (LPCWSTR lpMachineName
,
306 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
307 return ERROR_CALL_NOT_IMPLEMENTED
;
311 /************************************************************************
317 RegCreateKeyExA (HKEY hKey
,
323 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
325 LPDWORD lpdwDisposition
)
327 UNICODE_STRING SubKeyString
;
328 UNICODE_STRING ClassString
;
329 OBJECT_ATTRIBUTES Attributes
;
334 DPRINT("RegCreateKeyExA() called\n");
336 /* get the real parent key */
337 Status
= MapDefaultKey (&ParentKey
,
339 if (!NT_SUCCESS(Status
))
341 ErrorCode
= RtlNtStatusToDosError (Status
);
342 SetLastError (ErrorCode
);
345 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
349 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
352 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
354 InitializeObjectAttributes (&Attributes
,
356 OBJ_CASE_INSENSITIVE
,
358 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
359 Status
= NtCreateKey (phkResult
,
363 (lpClass
== NULL
)? NULL
: &ClassString
,
365 (PULONG
)lpdwDisposition
);
366 RtlFreeUnicodeString (&SubKeyString
);
369 RtlFreeUnicodeString (&ClassString
);
371 DPRINT("Status %x\n", Status
);
372 if (!NT_SUCCESS(Status
))
374 ErrorCode
= RtlNtStatusToDosError (Status
);
375 SetLastError (ErrorCode
);
379 return ERROR_SUCCESS
;
383 /************************************************************************
389 RegCreateKeyExW(HKEY hKey
,
395 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
397 LPDWORD lpdwDisposition
)
399 UNICODE_STRING SubKeyString
;
400 UNICODE_STRING ClassString
;
401 OBJECT_ATTRIBUTES Attributes
;
406 DPRINT("RegCreateKeyExW() called\n");
408 /* get the real parent key */
409 Status
= MapDefaultKey (&ParentKey
,
411 if (!NT_SUCCESS(Status
))
413 ErrorCode
= RtlNtStatusToDosError(Status
);
414 SetLastError (ErrorCode
);
417 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
419 RtlInitUnicodeString (&ClassString
,
421 RtlInitUnicodeString (&SubKeyString
,
423 InitializeObjectAttributes (&Attributes
,
425 OBJ_CASE_INSENSITIVE
,
427 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
428 Status
= NtCreateKey (phkResult
,
432 (lpClass
== NULL
)? NULL
: &ClassString
,
434 (PULONG
)lpdwDisposition
);
435 DPRINT("Status %x\n", Status
);
436 if (!NT_SUCCESS(Status
))
438 ErrorCode
= RtlNtStatusToDosError (Status
);
439 SetLastError (ErrorCode
);
443 return ERROR_SUCCESS
;
447 /************************************************************************
453 RegCreateKeyA (HKEY hKey
,
457 return RegCreateKeyExA (hKey
,
469 /************************************************************************
475 RegCreateKeyW (HKEY hKey
,
479 return RegCreateKeyExW (hKey
,
491 /************************************************************************
497 RegDeleteKeyA (HKEY hKey
,
500 OBJECT_ATTRIBUTES ObjectAttributes
;
501 UNICODE_STRING SubKeyName
;
507 Status
= MapDefaultKey (&ParentKey
,
509 if (!NT_SUCCESS(Status
))
511 ErrorCode
= RtlNtStatusToDosError (Status
);
512 SetLastError (ErrorCode
);
516 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
518 InitializeObjectAttributes(&ObjectAttributes
,
520 OBJ_CASE_INSENSITIVE
,
524 Status
= NtOpenKey (&TargetKey
,
527 RtlFreeUnicodeString (&SubKeyName
);
528 if (!NT_SUCCESS(Status
))
530 ErrorCode
= RtlNtStatusToDosError (Status
);
531 SetLastError (ErrorCode
);
535 Status
= NtDeleteKey (TargetKey
);
537 if (!NT_SUCCESS(Status
))
539 ErrorCode
= RtlNtStatusToDosError(Status
);
540 SetLastError (ErrorCode
);
544 return ERROR_SUCCESS
;
548 /************************************************************************
554 RegDeleteKeyW (HKEY hKey
,
557 OBJECT_ATTRIBUTES ObjectAttributes
;
558 UNICODE_STRING SubKeyName
;
564 Status
= MapDefaultKey (&ParentKey
,
566 if (!NT_SUCCESS(Status
))
568 ErrorCode
= RtlNtStatusToDosError (Status
);
569 SetLastError (ErrorCode
);
573 RtlInitUnicodeString (&SubKeyName
,
575 InitializeObjectAttributes (&ObjectAttributes
,
577 OBJ_CASE_INSENSITIVE
,
580 Status
= NtOpenKey (&TargetKey
,
583 if (!NT_SUCCESS(Status
))
585 ErrorCode
= RtlNtStatusToDosError (Status
);
586 SetLastError (ErrorCode
);
590 Status
= NtDeleteKey (TargetKey
);
592 if (!NT_SUCCESS(Status
))
594 ErrorCode
= RtlNtStatusToDosError (Status
);
595 SetLastError (ErrorCode
);
599 return ERROR_SUCCESS
;
603 /************************************************************************
609 RegDeleteValueA (HKEY hKey
,
612 UNICODE_STRING ValueName
;
617 Status
= MapDefaultKey (&KeyHandle
,
619 if (!NT_SUCCESS(Status
))
621 ErrorCode
= RtlNtStatusToDosError (Status
);
622 SetLastError (ErrorCode
);
626 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
628 Status
= NtDeleteValueKey (KeyHandle
,
630 RtlFreeUnicodeString (&ValueName
);
631 if (!NT_SUCCESS(Status
))
633 ErrorCode
= RtlNtStatusToDosError (Status
);
634 SetLastError (ErrorCode
);
638 return ERROR_SUCCESS
;
642 /************************************************************************
648 RegDeleteValueW (HKEY hKey
,
651 UNICODE_STRING ValueName
;
656 Status
= MapDefaultKey (&KeyHandle
,
658 if (!NT_SUCCESS(Status
))
660 ErrorCode
= RtlNtStatusToDosError (Status
);
661 SetLastError (ErrorCode
);
665 RtlInitUnicodeString (&ValueName
,
666 (LPWSTR
)lpValueName
);
668 Status
= NtDeleteValueKey (KeyHandle
,
670 if (!NT_SUCCESS(Status
))
672 ErrorCode
= RtlNtStatusToDosError (Status
);
673 SetLastError (ErrorCode
);
677 return ERROR_SUCCESS
;
681 /************************************************************************
687 RegEnumKeyA (HKEY hKey
,
695 return RegEnumKeyExA (hKey
,
706 /************************************************************************
712 RegEnumKeyW (HKEY hKey
,
720 return RegEnumKeyExW (hKey
,
731 /************************************************************************
737 RegEnumKeyExA (HKEY hKey
,
744 PFILETIME lpftLastWriteTime
)
748 KEY_NODE_INFORMATION Node
;
749 KEY_BASIC_INFORMATION Basic
;
752 UNICODE_STRING StringU
;
754 LONG ErrorCode
= ERROR_SUCCESS
;
762 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
763 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
765 if ((lpClass
) && (!lpcbClass
))
767 SetLastError (ERROR_INVALID_PARAMETER
);
768 return ERROR_INVALID_PARAMETER
;
770 Status
= MapDefaultKey(&KeyHandle
,
772 if (!NT_SUCCESS(Status
))
774 ErrorCode
= RtlNtStatusToDosError (Status
);
775 SetLastError (ErrorCode
);
781 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
791 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
797 /* The class name should start at a dword boundary */
798 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
802 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
805 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
811 SetLastError (ERROR_OUTOFMEMORY
);
812 return ERROR_OUTOFMEMORY
;
815 Status
= NtEnumerateKey (KeyHandle
,
817 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
821 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
822 if (!NT_SUCCESS(Status
))
824 ErrorCode
= RtlNtStatusToDosError (Status
);
830 if (KeyInfo
->Basic
.NameLength
> NameLength
)
832 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
836 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
837 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
838 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
843 if (KeyInfo
->Node
.NameLength
> NameLength
||
844 KeyInfo
->Node
.ClassLength
> ClassLength
)
846 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
850 StringA
.Buffer
= lpClass
;
852 StringA
.MaximumLength
= *lpcbClass
;
853 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
854 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
855 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
856 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
857 lpClass
[StringA
.Length
] = 0;
858 *lpcbClass
= StringA
.Length
;
859 StringU
.Buffer
= KeyInfo
->Node
.Name
;
860 StringU
.Length
= KeyInfo
->Node
.NameLength
;
861 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
864 if (ErrorCode
== ERROR_SUCCESS
)
866 StringA
.Buffer
= lpName
;
868 StringA
.MaximumLength
= *lpcbName
;
869 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
870 lpName
[StringA
.Length
] = 0;
871 *lpcbName
= StringA
.Length
;
872 if (lpftLastWriteTime
!= NULL
)
876 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
877 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
881 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
882 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
888 DPRINT("Key Namea0 Length %d\n", StringU
.Length
);
889 DPRINT("Key Namea1 Length %d\n", NameLength
);
890 DPRINT("Key Namea Length %d\n", *lpcbName
);
891 DPRINT("Key Namea %s\n", lpName
);
893 RtlFreeHeap (ProcessHeap
,
897 if (ErrorCode
!= ERROR_SUCCESS
)
899 SetLastError(ErrorCode
);
906 /************************************************************************
912 RegEnumKeyExW (HKEY hKey
,
919 PFILETIME lpftLastWriteTime
)
923 KEY_NODE_INFORMATION Node
;
924 KEY_BASIC_INFORMATION Basic
;
932 LONG ErrorCode
= ERROR_SUCCESS
;
935 Status
= MapDefaultKey(&KeyHandle
,
937 if (!NT_SUCCESS(Status
))
939 ErrorCode
= RtlNtStatusToDosError (Status
);
940 SetLastError (ErrorCode
);
945 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
955 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
961 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
965 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
967 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
972 SetLastError (ERROR_OUTOFMEMORY
);
973 return ERROR_OUTOFMEMORY
;
976 Status
= NtEnumerateKey (KeyHandle
,
978 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
982 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
983 if (!NT_SUCCESS(Status
))
985 ErrorCode
= RtlNtStatusToDosError (Status
);
991 if (KeyInfo
->Basic
.NameLength
> NameLength
)
993 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
997 RtlCopyMemory (lpName
,
999 KeyInfo
->Basic
.NameLength
);
1000 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1001 lpName
[*lpcbName
] = 0;
1006 if (KeyInfo
->Node
.NameLength
> NameLength
||
1007 KeyInfo
->Node
.ClassLength
> ClassLength
)
1009 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1013 RtlCopyMemory (lpName
,
1015 KeyInfo
->Node
.NameLength
);
1016 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1017 lpName
[*lpcbName
] = 0;
1018 RtlCopyMemory (lpClass
,
1019 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1020 KeyInfo
->Node
.ClassLength
);
1021 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1022 lpClass
[*lpcbClass
] = 0;
1025 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1027 if (lpClass
== NULL
)
1029 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1030 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1034 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1035 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1040 RtlFreeHeap (ProcessHeap
,
1044 if (ErrorCode
!= ERROR_SUCCESS
)
1046 SetLastError(ErrorCode
);
1052 /************************************************************************
1058 RegEnumValueA (HKEY hKey
,
1061 LPDWORD lpcbValueName
,
1069 KEY_VALUE_FULL_INFORMATION Full
;
1070 KEY_VALUE_BASIC_INFORMATION Basic
;
1080 UNICODE_STRING StringU
;
1081 ANSI_STRING StringA
;
1084 ErrorCode
= ERROR_SUCCESS
;
1086 Status
= MapDefaultKey (&KeyHandle
,
1088 if (!NT_SUCCESS(Status
))
1090 ErrorCode
= RtlNtStatusToDosError (Status
);
1091 SetLastError (ErrorCode
);
1095 if (*lpcbValueName
> 0)
1097 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1105 DataLength
= min (*lpcbData
* sizeof(WCHAR
), REG_MAX_DATA_SIZE
);
1106 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1110 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1113 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1116 if (ValueInfo
== NULL
)
1118 SetLastError(ERROR_OUTOFMEMORY
);
1119 return ERROR_OUTOFMEMORY
;
1122 Status
= NtEnumerateValueKey (KeyHandle
,
1124 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1129 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1130 if (!NT_SUCCESS(Status
))
1132 ErrorCode
= RtlNtStatusToDosError (Status
);
1138 IsStringType
= (ValueInfo
->Full
.Type
== REG_SZ
) ||
1139 (ValueInfo
->Full
.Type
== REG_MULTI_SZ
) ||
1140 (ValueInfo
->Full
.Type
== REG_EXPAND_SZ
);
1141 if (ValueInfo
->Full
.NameLength
> NameLength
||
1142 (!IsStringType
&& ValueInfo
->Full
.DataLength
> *lpcbData
) ||
1143 ValueInfo
->Full
.DataLength
> DataLength
)
1145 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1151 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
);
1152 StringU
.Length
= ValueInfo
->Full
.DataLength
;
1153 StringU
.MaximumLength
= DataLength
;
1154 StringA
.Buffer
= (PCHAR
)lpData
;
1156 StringA
.MaximumLength
= *lpcbData
;
1157 RtlUnicodeStringToAnsiString (&StringA
,
1160 *lpcbData
= StringA
.Length
;
1164 RtlCopyMemory(lpData
,
1165 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1166 ValueInfo
->Full
.DataLength
);
1167 *lpcbData
= ValueInfo
->Full
.DataLength
;
1169 StringU
.Buffer
= ValueInfo
->Full
.Name
;
1170 StringU
.Length
= ValueInfo
->Full
.NameLength
;
1171 StringU
.MaximumLength
= NameLength
;
1176 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1178 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1182 StringU
.Buffer
= ValueInfo
->Basic
.Name
;
1183 StringU
.Length
= ValueInfo
->Basic
.NameLength
;
1184 StringU
.MaximumLength
= NameLength
;
1187 if (ErrorCode
== ERROR_SUCCESS
)
1189 StringA
.Buffer
= (PCHAR
)lpValueName
;
1191 StringA
.MaximumLength
= *lpcbValueName
;
1192 RtlUnicodeStringToAnsiString (&StringA
,
1195 StringA
.Buffer
[StringA
.Length
] = 0;
1196 *lpcbValueName
= StringA
.Length
;
1199 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1203 RtlFreeHeap (ProcessHeap
,
1206 if (ErrorCode
!= ERROR_SUCCESS
)
1208 SetLastError(ErrorCode
);
1214 /************************************************************************
1220 RegEnumValueW (HKEY hKey
,
1223 LPDWORD lpcbValueName
,
1231 KEY_VALUE_FULL_INFORMATION Full
;
1232 KEY_VALUE_BASIC_INFORMATION Basic
;
1243 ErrorCode
= ERROR_SUCCESS
;
1245 Status
= MapDefaultKey (&KeyHandle
,
1247 if (!NT_SUCCESS(Status
))
1249 ErrorCode
= RtlNtStatusToDosError (Status
);
1250 SetLastError (ErrorCode
);
1254 if (*lpcbValueName
> 0)
1256 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1264 DataLength
= min(*lpcbData
, REG_MAX_DATA_SIZE
);
1265 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1269 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1271 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1274 if (ValueInfo
== NULL
)
1276 SetLastError (ERROR_OUTOFMEMORY
);
1277 return ERROR_OUTOFMEMORY
;
1279 Status
= NtEnumerateValueKey (KeyHandle
,
1281 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1286 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1287 if (!NT_SUCCESS(Status
))
1289 ErrorCode
= RtlNtStatusToDosError (Status
);
1295 if (ValueInfo
->Full
.DataLength
> DataLength
||
1296 ValueInfo
->Full
.NameLength
> NameLength
)
1298 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1302 RtlCopyMemory (lpValueName
,
1303 ValueInfo
->Full
.Name
,
1304 ValueInfo
->Full
.NameLength
);
1305 *lpcbValueName
= (DWORD
)(ValueInfo
->Full
.NameLength
/ sizeof(WCHAR
));
1306 lpValueName
[*lpcbValueName
] = 0;
1307 RtlCopyMemory (lpData
,
1308 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1309 ValueInfo
->Full
.DataLength
);
1310 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1315 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1317 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1321 RtlCopyMemory (lpValueName
,
1322 ValueInfo
->Basic
.Name
,
1323 ValueInfo
->Basic
.NameLength
);
1324 *lpcbValueName
= (DWORD
)(ValueInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1325 lpValueName
[*lpcbValueName
] = 0;
1328 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1330 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1333 RtlFreeHeap (ProcessHeap
,
1336 if (ErrorCode
!= ERROR_SUCCESS
)
1338 SetLastError(ErrorCode
);
1344 /************************************************************************
1350 RegFlushKey(HKEY hKey
)
1356 if (hKey
== HKEY_PERFORMANCE_DATA
)
1358 return ERROR_SUCCESS
;
1361 Status
= MapDefaultKey (&KeyHandle
,
1363 if (!NT_SUCCESS(Status
))
1365 ErrorCode
= RtlNtStatusToDosError (Status
);
1366 SetLastError (ErrorCode
);
1370 Status
= NtFlushKey (KeyHandle
);
1371 if (!NT_SUCCESS(Status
))
1373 ErrorCode
= RtlNtStatusToDosError (Status
);
1374 SetLastError (ErrorCode
);
1378 return ERROR_SUCCESS
;
1382 /************************************************************************
1388 RegGetKeySecurity (HKEY hKey
,
1389 SECURITY_INFORMATION SecurityInformation
,
1390 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1391 LPDWORD lpcbSecurityDescriptor
)
1398 if (hKey
= HKEY_PERFORMANCE_DATA
)
1400 return ERROR_INVALID_HANDLE
;
1403 Status
= MapDefaultKey (&KeyHandle
,
1405 if (!NT_SUCCESS(Status
))
1407 ErrorCode
= RtlNtStatusToDosError (Status
);
1408 SetLastError (ErrorCode
);
1412 Status
= NtQuerySecurityObject ()
1413 if (!NT_SUCCESS(Status
))
1415 ErrorCode
= RtlNtStatusToDosError (Status
);
1416 SetLastError (ErrorCode
);
1420 return ERROR_SUCCESS
;
1424 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1425 return ERROR_CALL_NOT_IMPLEMENTED
;
1429 /************************************************************************
1435 RegLoadKeyA (HKEY hKey
,
1439 UNICODE_STRING FileName
;
1440 UNICODE_STRING KeyName
;
1443 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1445 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1448 ErrorCode
= RegLoadKeyW (hKey
,
1452 RtlFreeUnicodeString (&FileName
);
1453 RtlFreeUnicodeString (&KeyName
);
1459 /************************************************************************
1465 RegLoadKeyW (HKEY hKey
,
1469 OBJECT_ATTRIBUTES FileObjectAttributes
;
1470 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1471 UNICODE_STRING FileName
;
1472 UNICODE_STRING KeyName
;
1477 if (hKey
== HKEY_PERFORMANCE_DATA
)
1479 return ERROR_INVALID_HANDLE
;
1482 Status
= MapDefaultKey (&KeyHandle
,
1484 if (!NT_SUCCESS(Status
))
1486 ErrorCode
= RtlNtStatusToDosError (Status
);
1487 SetLastError (ErrorCode
);
1491 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1496 SetLastError (ERROR_BAD_PATHNAME
);
1497 return ERROR_BAD_PATHNAME
;
1500 InitializeObjectAttributes (&FileObjectAttributes
,
1502 OBJ_CASE_INSENSITIVE
,
1506 RtlInitUnicodeString (&KeyName
,
1509 InitializeObjectAttributes (&KeyObjectAttributes
,
1511 OBJ_CASE_INSENSITIVE
,
1515 Status
= NtLoadKey (&KeyObjectAttributes
,
1516 &FileObjectAttributes
);
1518 RtlFreeUnicodeString (&FileName
);
1520 if (!NT_SUCCESS(Status
))
1522 ErrorCode
= RtlNtStatusToDosError (Status
);
1523 SetLastError (ErrorCode
);
1527 return ERROR_SUCCESS
;
1531 /************************************************************************
1532 * RegNotifyChangeKeyValue
1537 RegNotifyChangeKeyValue (HKEY hKey
,
1539 DWORD dwNotifyFilter
,
1543 IO_STATUS_BLOCK IoStatusBlock
;
1547 if (hKey
== HKEY_PERFORMANCE_DATA
)
1549 return ERROR_INVALID_HANDLE
;
1552 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1554 return ERROR_INVALID_PARAMETER
;
1557 Status
= MapDefaultKey (&KeyHandle
,
1559 if (!NT_SUCCESS(Status
))
1561 return RtlNtStatusToDosError (Status
);
1564 /* FIXME: Remote key handles must fail */
1566 Status
= NtNotifyChangeKey (KeyHandle
,
1576 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1578 return RtlNtStatusToDosError (Status
);
1581 return ERROR_SUCCESS
;
1586 /************************************************************************
1592 RegOpenKeyA (HKEY hKey
,
1596 OBJECT_ATTRIBUTES ObjectAttributes
;
1597 UNICODE_STRING SubKeyString
;
1602 Status
= MapDefaultKey (&KeyHandle
,
1604 if (!NT_SUCCESS(Status
))
1606 ErrorCode
= RtlNtStatusToDosError (Status
);
1607 SetLastError (ErrorCode
);
1611 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1613 InitializeObjectAttributes (&ObjectAttributes
,
1615 OBJ_CASE_INSENSITIVE
,
1618 Status
= NtOpenKey (phkResult
,
1621 RtlFreeUnicodeString (&SubKeyString
);
1622 if (!NT_SUCCESS(Status
))
1624 ErrorCode
= RtlNtStatusToDosError (Status
);
1625 SetLastError (ErrorCode
);
1629 return ERROR_SUCCESS
;
1633 /************************************************************************
1642 RegOpenKeyW (HKEY hKey
,
1646 OBJECT_ATTRIBUTES ObjectAttributes
;
1647 UNICODE_STRING SubKeyString
;
1652 Status
= MapDefaultKey (&KeyHandle
,
1654 if (!NT_SUCCESS(Status
))
1656 ErrorCode
= RtlNtStatusToDosError (Status
);
1657 SetLastError (ErrorCode
);
1661 RtlInitUnicodeString (&SubKeyString
,
1663 InitializeObjectAttributes (&ObjectAttributes
,
1665 OBJ_CASE_INSENSITIVE
,
1668 Status
= NtOpenKey (phkResult
,
1671 if (!NT_SUCCESS(Status
))
1673 ErrorCode
= RtlNtStatusToDosError (Status
);
1674 SetLastError(ErrorCode
);
1678 return ERROR_SUCCESS
;
1682 /************************************************************************
1688 RegOpenKeyExA (HKEY hKey
,
1694 OBJECT_ATTRIBUTES ObjectAttributes
;
1695 UNICODE_STRING SubKeyString
;
1700 Status
= MapDefaultKey (&KeyHandle
,
1702 if (!NT_SUCCESS(Status
))
1704 ErrorCode
= RtlNtStatusToDosError (Status
);
1705 SetLastError (ErrorCode
);
1709 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1711 InitializeObjectAttributes (&ObjectAttributes
,
1713 OBJ_CASE_INSENSITIVE
,
1716 Status
= NtOpenKey (phkResult
,
1719 RtlFreeUnicodeString (&SubKeyString
);
1720 if (!NT_SUCCESS(Status
))
1722 ErrorCode
= RtlNtStatusToDosError (Status
);
1723 SetLastError (ErrorCode
);
1727 return ERROR_SUCCESS
;
1731 /************************************************************************
1737 RegOpenKeyExW (HKEY hKey
,
1743 OBJECT_ATTRIBUTES ObjectAttributes
;
1744 UNICODE_STRING SubKeyString
;
1749 Status
= MapDefaultKey (&KeyHandle
,
1751 if (!NT_SUCCESS(Status
))
1753 ErrorCode
= RtlNtStatusToDosError (Status
);
1754 SetLastError (ErrorCode
);
1758 if (lpSubKey
!= NULL
)
1760 RtlInitUnicodeString (&SubKeyString
,
1765 RtlInitUnicodeString (&SubKeyString
,
1768 InitializeObjectAttributes (&ObjectAttributes
,
1770 OBJ_CASE_INSENSITIVE
,
1773 Status
= NtOpenKey (phkResult
,
1776 if (!NT_SUCCESS(Status
))
1778 ErrorCode
= RtlNtStatusToDosError (Status
);
1779 SetLastError (ErrorCode
);
1783 return ERROR_SUCCESS
;
1787 /************************************************************************
1793 RegQueryInfoKeyA (HKEY hKey
,
1798 LPDWORD lpcbMaxSubKeyLen
,
1799 LPDWORD lpcbMaxClassLen
,
1801 LPDWORD lpcbMaxValueNameLen
,
1802 LPDWORD lpcbMaxValueLen
,
1803 LPDWORD lpcbSecurityDescriptor
,
1804 PFILETIME lpftLastWriteTime
)
1806 WCHAR ClassName
[MAX_PATH
];
1807 UNICODE_STRING UnicodeString
;
1808 ANSI_STRING AnsiString
;
1811 RtlInitUnicodeString (&UnicodeString
,
1813 if (lpClass
!= NULL
)
1815 UnicodeString
.Buffer
= &ClassName
[0];
1816 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1817 AnsiString
.MaximumLength
= *lpcbClass
;
1820 ErrorCode
= RegQueryInfoKeyW (hKey
,
1821 UnicodeString
.Buffer
,
1828 lpcbMaxValueNameLen
,
1830 lpcbSecurityDescriptor
,
1832 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1834 AnsiString
.Buffer
= lpClass
;
1835 AnsiString
.Length
= 0;
1836 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1837 RtlUnicodeStringToAnsiString (&AnsiString
,
1840 *lpcbClass
= AnsiString
.Length
;
1841 lpClass
[AnsiString
.Length
] = 0;
1848 /************************************************************************
1854 RegQueryInfoKeyW (HKEY hKey
,
1859 LPDWORD lpcbMaxSubKeyLen
,
1860 LPDWORD lpcbMaxClassLen
,
1862 LPDWORD lpcbMaxValueNameLen
,
1863 LPDWORD lpcbMaxValueLen
,
1864 LPDWORD lpcbSecurityDescriptor
,
1865 PFILETIME lpftLastWriteTime
)
1867 KEY_FULL_INFORMATION FullInfoBuffer
;
1868 PKEY_FULL_INFORMATION FullInfo
;
1873 LONG ErrorCode
= ERROR_SUCCESS
;
1876 if ((lpClass
) && (!lpcbClass
))
1878 SetLastError(ERROR_INVALID_PARAMETER
);
1879 return ERROR_INVALID_PARAMETER
;
1882 Status
= MapDefaultKey (&KeyHandle
,
1884 if (!NT_SUCCESS(Status
))
1886 ErrorCode
= RtlNtStatusToDosError (Status
);
1887 SetLastError (ErrorCode
);
1891 if (lpClass
!= NULL
)
1895 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1901 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
1902 FullInfo
= RtlAllocateHeap (ProcessHeap
,
1905 if (FullInfo
== NULL
)
1907 SetLastError (ERROR_OUTOFMEMORY
);
1908 return ERROR_OUTOFMEMORY
;
1910 FullInfo
->ClassLength
= ClassLength
;
1914 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
1915 FullInfo
= &FullInfoBuffer
;
1916 FullInfo
->ClassLength
= 0;
1918 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
1920 Status
= NtQueryKey (KeyHandle
,
1925 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
1926 if (!NT_SUCCESS(Status
))
1928 ErrorCode
= RtlNtStatusToDosError (Status
);
1932 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
1933 if (lpcSubKeys
!= NULL
)
1935 *lpcSubKeys
= FullInfo
->SubKeys
;
1938 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
1939 if (lpcbMaxSubKeyLen
!= NULL
)
1941 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
1944 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
1945 if (lpcbMaxClassLen
!= NULL
)
1947 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
1950 DPRINT("Values %lu\n", FullInfo
->Values
);
1953 *lpcValues
= FullInfo
->Values
;
1956 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
1957 if (lpcbMaxValueNameLen
)
1959 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
1962 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
1963 if (lpcbMaxValueLen
)
1965 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
1968 if (lpcbSecurityDescriptor
)
1970 *lpcbSecurityDescriptor
= 0;
1974 if (lpftLastWriteTime
!= NULL
)
1976 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
1977 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
1980 if (lpClass
!= NULL
)
1982 if (FullInfo
->ClassLength
> ClassLength
)
1984 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1988 RtlCopyMemory (lpClass
,
1990 FullInfo
->ClassLength
);
1991 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
1992 lpClass
[*lpcbClass
] = 0;
1996 if (lpClass
!= NULL
)
1998 RtlFreeHeap (ProcessHeap
,
2002 if (ErrorCode
!= ERROR_SUCCESS
)
2004 SetLastError(ErrorCode
);
2011 /************************************************************************
2012 * RegQueryMultipleValuesA
2017 RegQueryMultipleValuesA (HKEY hKey
,
2024 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2025 return ERROR_CALL_NOT_IMPLEMENTED
;
2029 /************************************************************************
2030 * RegQueryMultipleValuesW
2035 RegQueryMultipleValuesW (HKEY hKey
,
2042 DWORD maxBytes
= *ldwTotsize
;
2044 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2046 if ( maxBytes
>= (1024*1024) )
2047 return ERROR_TRANSFER_TOO_LONG
;
2051 //TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2053 for(i
=0; i
< num_vals
; ++i
)
2055 val_list
[i
].ve_valuelen
=0;
2056 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
2057 if(status
!= ERROR_SUCCESS
)
2062 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2064 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
2065 bufptr
, &val_list
[i
].ve_valuelen
);
2066 if(status
!= ERROR_SUCCESS
)
2071 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2073 bufptr
+= val_list
[i
].ve_valuelen
;
2076 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2078 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2082 /************************************************************************
2088 RegQueryValueExW (HKEY hKey
,
2089 LPCWSTR lpValueName
,
2095 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2096 UNICODE_STRING ValueName
;
2098 LONG ErrorCode
= ERROR_SUCCESS
;
2103 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2104 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2106 Status
= MapDefaultKey (&KeyHandle
,
2108 if (!NT_SUCCESS(Status
))
2110 ErrorCode
= RtlNtStatusToDosError (Status
);
2111 SetLastError (ErrorCode
);
2115 if (lpData
!= NULL
&& lpcbData
== NULL
)
2117 SetLastError (ERROR_INVALID_PARAMETER
);
2118 return ERROR_INVALID_PARAMETER
;
2121 RtlInitUnicodeString (&ValueName
,
2123 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + *lpcbData
;
2124 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2127 if (ValueInfo
== NULL
)
2129 SetLastError(ERROR_OUTOFMEMORY
);
2130 return ERROR_OUTOFMEMORY
;
2133 Status
= NtQueryValueKey (hKey
,
2135 KeyValuePartialInformation
,
2139 DPRINT("Status 0x%X\n", Status
);
2140 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2142 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2143 ErrorCode
= ERROR_SUCCESS
;
2145 else if (!NT_SUCCESS(Status
))
2147 ErrorCode
= RtlNtStatusToDosError (Status
);
2148 SetLastError (ErrorCode
);
2154 *lpType
= ValueInfo
->Type
;
2156 RtlMoveMemory (lpData
,
2158 ValueInfo
->DataLength
);
2159 if ((ValueInfo
->Type
== REG_SZ
) ||
2160 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2161 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2163 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2166 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2168 if (NULL
!= lpcbData
)
2170 *lpcbData
= (DWORD
)ValueInfo
->DataLength
;
2172 RtlFreeHeap (ProcessHeap
,
2180 /************************************************************************
2195 UNICODE_STRING ValueName
;
2196 UNICODE_STRING ValueData
;
2197 ANSI_STRING AnsiString
;
2200 if ((lpData
) && (!lpcbData
))
2202 SetLastError(ERROR_INVALID_PARAMETER
);
2203 return ERROR_INVALID_PARAMETER
;
2208 ValueData
.Length
= ValueData
.MaximumLength
= *lpcbData
* sizeof(WCHAR
);
2209 ValueData
.Buffer
= RtlAllocateHeap(
2213 if (!ValueData
.Buffer
)
2215 SetLastError(ERROR_OUTOFMEMORY
);
2216 return ERROR_OUTOFMEMORY
;
2221 ValueData
.Buffer
= NULL
;
2224 RtlCreateUnicodeStringFromAsciiz(&ValueName
, (LPSTR
)lpValueName
);
2226 ErrorCode
= RegQueryValueExW(
2231 (LPBYTE
)ValueData
.Buffer
,
2232 (LPDWORD
)&ValueData
.Length
);
2234 if ((ErrorCode
== ERROR_SUCCESS
) && (ValueData
.Buffer
!= NULL
))
2236 if (lpType
&& ((*lpType
== REG_SZ
) || (*lpType
== REG_MULTI_SZ
) || (*lpType
== REG_EXPAND_SZ
)))
2238 RtlInitAnsiString(&AnsiString
, NULL
);
2239 AnsiString
.Buffer
= lpData
;
2240 AnsiString
.MaximumLength
= *lpcbData
;
2241 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2242 *lpcbData
= ValueData
.Length
/ sizeof(WCHAR
);
2244 RtlMoveMemory(lpData
, ValueData
.Buffer
, *lpcbData
);
2245 *lpcbData
= ValueData
.Length
;
2249 if (ValueData
.Buffer
)
2251 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2258 /************************************************************************
2264 RegQueryValueA (HKEY hKey
,
2269 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2270 UNICODE_STRING SubKeyName
;
2271 UNICODE_STRING Value
;
2272 ANSI_STRING AnsiString
;
2276 if (lpValue
!= NULL
&&
2279 SetLastError(ERROR_INVALID_PARAMETER
);
2280 return ERROR_INVALID_PARAMETER
;
2283 RtlInitUnicodeString (&SubKeyName
,
2285 RtlInitUnicodeString (&Value
,
2287 if (lpSubKey
!= NULL
&&
2288 strlen(lpSubKey
) != 0)
2290 RtlInitAnsiString (&AnsiString
,
2292 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2293 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2294 RtlAnsiStringToUnicodeString (&SubKeyName
,
2299 if (lpValue
!= NULL
)
2301 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2302 Value
.MaximumLength
= ValueSize
;
2303 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2306 if (Value
.Buffer
== NULL
)
2308 SetLastError(ERROR_OUTOFMEMORY
);
2309 return ERROR_OUTOFMEMORY
;
2317 ErrorCode
= RegQueryValueW (hKey
,
2318 (LPCWSTR
)SubKeyName
.Buffer
,
2321 if (ErrorCode
== ERROR_SUCCESS
)
2323 Value
.Length
= ValueSize
;
2324 RtlInitAnsiString (&AnsiString
,
2326 AnsiString
.Buffer
= lpValue
;
2327 AnsiString
.MaximumLength
= *lpcbValue
;
2328 RtlUnicodeStringToAnsiString (&AnsiString
,
2333 *lpcbValue
= ValueSize
;
2334 if (Value
.Buffer
!= NULL
)
2336 RtlFreeHeap (ProcessHeap
,
2345 /************************************************************************
2351 RegQueryValueW (HKEY hKey
,
2356 OBJECT_ATTRIBUTES ObjectAttributes
;
2357 UNICODE_STRING SubKeyString
;
2364 Status
= MapDefaultKey (&KeyHandle
,
2366 if (!NT_SUCCESS(Status
))
2368 ErrorCode
= RtlNtStatusToDosError (Status
);
2369 SetLastError (ErrorCode
);
2373 if (lpSubKey
!= NULL
&&
2374 wcslen(lpSubKey
) != 0)
2376 RtlInitUnicodeString (&SubKeyString
,
2378 InitializeObjectAttributes (&ObjectAttributes
,
2380 OBJ_CASE_INSENSITIVE
,
2383 Status
= NtOpenKey (&RealKey
,
2386 if (!NT_SUCCESS(Status
))
2388 ErrorCode
= RtlNtStatusToDosError (Status
);
2389 SetLastError (ErrorCode
);
2392 CloseRealKey
= TRUE
;
2397 CloseRealKey
= FALSE
;
2400 ErrorCode
= RegQueryValueExW (RealKey
,
2405 (LPDWORD
)lpcbValue
);
2415 /************************************************************************
2421 RegReplaceKeyA (HKEY hKey
,
2426 UNICODE_STRING lpSubKeyW
;
2427 UNICODE_STRING lpNewFileW
;
2428 UNICODE_STRING lpOldFileW
;
2431 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, (PCSZ
)lpSubKey
);
2432 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, (PCSZ
)lpOldFile
);
2433 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, (PCSZ
)lpNewFile
);
2434 ret
= RegReplaceKeyW( hKey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
2435 RtlFreeUnicodeString( &lpOldFileW
);
2436 RtlFreeUnicodeString( &lpNewFileW
);
2437 RtlFreeUnicodeString( &lpSubKeyW
);
2442 /************************************************************************
2448 RegReplaceKeyW (HKEY hKey
,
2454 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2455 return ERROR_CALL_NOT_IMPLEMENTED
;
2459 /************************************************************************
2465 RegRestoreKeyA (HKEY hKey
,
2469 UNICODE_STRING lpFileW
;
2472 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, (PCSZ
)lpFile
);
2473 ret
= RegRestoreKeyW( hKey
, lpFileW
.Buffer
, dwFlags
);
2474 RtlFreeUnicodeString( &lpFileW
);
2479 /************************************************************************
2485 RegRestoreKeyW (HKEY hKey
,
2490 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2491 return ERROR_CALL_NOT_IMPLEMENTED
;
2495 /************************************************************************
2501 RegSaveKeyA(HKEY hKey
,
2503 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2505 UNICODE_STRING FileName
;
2508 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2510 ErrorCode
= RegSaveKeyW (hKey
,
2512 lpSecurityAttributes
);
2513 RtlFreeUnicodeString (&FileName
);
2519 /************************************************************************
2525 RegSaveKeyW (HKEY hKey
,
2527 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2529 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2530 OBJECT_ATTRIBUTES ObjectAttributes
;
2531 UNICODE_STRING NtName
;
2532 IO_STATUS_BLOCK IoStatusBlock
;
2538 Status
= MapDefaultKey (&KeyHandle
,
2540 if (!NT_SUCCESS(Status
))
2542 ErrorCode
= RtlNtStatusToDosError (Status
);
2543 SetLastError (ErrorCode
);
2547 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2552 SetLastError (ERROR_INVALID_PARAMETER
);
2553 return ERROR_INVALID_PARAMETER
;
2556 if (lpSecurityAttributes
!= NULL
)
2558 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2561 InitializeObjectAttributes (&ObjectAttributes
,
2563 OBJ_CASE_INSENSITIVE
,
2565 SecurityDescriptor
);
2566 Status
= NtCreateFile (&FileHandle
,
2567 GENERIC_WRITE
| SYNCHRONIZE
,
2571 FILE_ATTRIBUTE_NORMAL
,
2574 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2577 RtlFreeUnicodeString (&NtName
);
2578 if (!NT_SUCCESS(Status
))
2580 ErrorCode
= RtlNtStatusToDosError (Status
);
2581 SetLastError (ErrorCode
);
2585 Status
= NtSaveKey (KeyHandle
,
2587 NtClose (FileHandle
);
2588 if (!NT_SUCCESS(Status
))
2590 ErrorCode
= RtlNtStatusToDosError (Status
);
2591 SetLastError (ErrorCode
);
2595 return ERROR_SUCCESS
;
2599 /************************************************************************
2605 RegSetKeySecurity (HKEY hKey
,
2606 SECURITY_INFORMATION SecurityInformation
,
2607 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
2613 if (hKey
== HKEY_PERFORMANCE_DATA
)
2614 return ERROR_INVALID_HANDLE
;
2616 Status
= MapDefaultKey (&KeyHandle
,
2618 if (!NT_SUCCESS(Status
))
2620 ErrorCode
= RtlNtStatusToDosError (Status
);
2621 SetLastError (ErrorCode
);
2625 Status
= NtSetSecurityObject (KeyHandle
,
2626 SecurityInformation
,
2627 pSecurityDescriptor
);
2628 if (!NT_SUCCESS(Status
))
2630 ErrorCode
= RtlNtStatusToDosError (Status
);
2631 SetLastError (ErrorCode
);
2635 return ERROR_SUCCESS
;
2639 /************************************************************************
2645 RegSetValueExA (HKEY hKey
,
2652 UNICODE_STRING ValueName
;
2654 ANSI_STRING AnsiString
;
2655 UNICODE_STRING Data
;
2662 SetLastError (ERROR_INVALID_PARAMETER
);
2663 return ERROR_INVALID_PARAMETER
;
2666 if (lpValueName
!= NULL
&&
2667 strlen(lpValueName
) != 0)
2669 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2670 (LPSTR
)lpValueName
);
2671 pValueName
= (LPWSTR
)ValueName
.Buffer
;
2678 if ((dwType
== REG_SZ
) ||
2679 (dwType
== REG_MULTI_SZ
) ||
2680 (dwType
== REG_EXPAND_SZ
))
2682 RtlInitAnsiString (&AnsiString
,
2684 AnsiString
.Buffer
= (LPSTR
)lpData
;
2685 AnsiString
.Length
= cbData
;
2686 AnsiString
.MaximumLength
= cbData
;
2687 RtlAnsiStringToUnicodeString (&Data
,
2690 pData
= (LPBYTE
)Data
.Buffer
;
2691 DataSize
= cbData
* sizeof(WCHAR
);
2695 RtlInitUnicodeString (&Data
,
2697 pData
= (LPBYTE
)lpData
;
2701 ErrorCode
= RegSetValueExW (hKey
,
2707 if (pValueName
!= NULL
)
2709 RtlFreeHeap (ProcessHeap
,
2714 if (Data
.Buffer
!= NULL
)
2716 RtlFreeHeap (ProcessHeap
,
2725 /************************************************************************
2731 RegSetValueExW (HKEY hKey
,
2732 LPCWSTR lpValueName
,
2738 UNICODE_STRING ValueName
;
2739 PUNICODE_STRING pValueName
;
2744 Status
= MapDefaultKey (&KeyHandle
,
2746 if (!NT_SUCCESS(Status
))
2748 ErrorCode
= RtlNtStatusToDosError (Status
);
2749 SetLastError (ErrorCode
);
2753 if (lpValueName
!= NULL
)
2755 RtlInitUnicodeString (&ValueName
,
2757 pValueName
= &ValueName
;
2764 Status
= NtSetValueKey (KeyHandle
,
2770 if (!NT_SUCCESS(Status
))
2772 ErrorCode
= RtlNtStatusToDosError (Status
);
2773 SetLastError (ErrorCode
);
2777 return ERROR_SUCCESS
;
2781 /************************************************************************
2787 RegSetValueA (HKEY hKey
,
2793 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2794 UNICODE_STRING SubKeyName
;
2795 UNICODE_STRING Data
;
2796 ANSI_STRING AnsiString
;
2802 SetLastError (ERROR_INVALID_PARAMETER
);
2803 return ERROR_INVALID_PARAMETER
;
2806 RtlInitUnicodeString (&SubKeyName
, NULL
);
2807 RtlInitUnicodeString (&Data
, NULL
);
2808 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
2810 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
2811 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2812 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2813 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
2816 DataSize
= cbData
* sizeof(WCHAR
);
2817 Data
.MaximumLength
= DataSize
;
2818 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2821 if (Data
.Buffer
== NULL
)
2823 SetLastError (ERROR_OUTOFMEMORY
);
2824 return ERROR_OUTOFMEMORY
;
2827 ErrorCode
= RegSetValueW (hKey
,
2828 (LPCWSTR
)SubKeyName
.Buffer
,
2832 RtlFreeHeap (ProcessHeap
,
2840 /************************************************************************
2846 RegSetValueW (HKEY hKey
,
2852 OBJECT_ATTRIBUTES ObjectAttributes
;
2853 UNICODE_STRING SubKeyString
;
2860 Status
= MapDefaultKey (&KeyHandle
,
2862 if (!NT_SUCCESS(Status
))
2864 ErrorCode
= RtlNtStatusToDosError (Status
);
2865 SetLastError (ErrorCode
);
2869 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
2871 RtlInitUnicodeString (&SubKeyString
,
2873 InitializeObjectAttributes (&ObjectAttributes
,
2875 OBJ_CASE_INSENSITIVE
,
2878 Status
= NtOpenKey (&RealKey
,
2881 if (!NT_SUCCESS(Status
))
2883 ErrorCode
= RtlNtStatusToDosError (Status
);
2884 SetLastError (ErrorCode
);
2887 CloseRealKey
= TRUE
;
2892 CloseRealKey
= FALSE
;
2895 ErrorCode
= RegSetValueExW (RealKey
,
2901 if (CloseRealKey
== TRUE
)
2910 /************************************************************************
2916 RegUnLoadKeyA (HKEY hKey
,
2919 UNICODE_STRING KeyName
;
2922 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
2925 ErrorCode
= RegUnLoadKeyW (hKey
,
2928 RtlFreeUnicodeString (&KeyName
);
2934 /************************************************************************
2940 RegUnLoadKeyW (HKEY hKey
,
2943 OBJECT_ATTRIBUTES ObjectAttributes
;
2944 UNICODE_STRING KeyName
;
2949 if (hKey
== HKEY_PERFORMANCE_DATA
)
2950 return ERROR_INVALID_HANDLE
;
2952 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2953 if (!NT_SUCCESS(Status
))
2955 ErrorCode
= RtlNtStatusToDosError (Status
);
2956 SetLastError (ErrorCode
);
2960 RtlInitUnicodeString (&KeyName
,
2963 InitializeObjectAttributes (&ObjectAttributes
,
2965 OBJ_CASE_INSENSITIVE
,
2969 Status
= NtUnloadKey (&ObjectAttributes
);
2971 if (!NT_SUCCESS(Status
))
2973 ErrorCode
= RtlNtStatusToDosError (Status
);
2974 SetLastError (ErrorCode
);
2978 return ERROR_SUCCESS
;