1 /* $Id: reg.c,v 1.33 2003/11/17 02:12:50 hyperion Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/reg/reg.c
6 * PURPOSE: Registry functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
13 /* INCLUDES *****************************************************************/
15 #define NTOS_MODE_USER
17 #include <ddk/ntddk.h>
18 #include <rosrtl/string.h>
19 #include <ntdll/rtl.h>
26 /* DEFINES ******************************************************************/
28 #define MAX_DEFAULT_HANDLES 6
29 #define REG_MAX_NAME_SIZE 256
30 #define REG_MAX_DATA_SIZE 2048
32 /* GLOBALS ******************************************************************/
34 static CRITICAL_SECTION HandleTableCS
;
35 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
36 static HANDLE ProcessHeap
;
38 /* PROTOTYPES ***************************************************************/
40 static NTSTATUS
MapDefaultKey (PHKEY ParentKey
, HKEY Key
);
41 static VOID
CloseDefaultKeys(VOID
);
43 static NTSTATUS
OpenClassesRootKey(PHANDLE KeyHandle
);
44 static NTSTATUS
OpenLocalMachineKey (PHANDLE KeyHandle
);
45 static NTSTATUS
OpenUsersKey (PHANDLE KeyHandle
);
46 static NTSTATUS
OpenCurrentConfigKey(PHANDLE KeyHandle
);
49 /* FUNCTIONS ****************************************************************/
51 /************************************************************************
52 * RegInitDefaultHandles
57 DPRINT("RegInitialize()\n");
59 ProcessHeap
= RtlGetProcessHeap();
60 RtlZeroMemory (DefaultHandleTable
,
61 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
62 RtlInitializeCriticalSection (&HandleTableCS
);
68 /************************************************************************
74 DPRINT("RegCleanup()\n");
77 RtlDeleteCriticalSection (&HandleTableCS
);
84 MapDefaultKey (PHKEY RealKey
,
89 NTSTATUS Status
= STATUS_SUCCESS
;
91 DPRINT("MapDefaultKey (Key %x)\n", Key
);
93 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
96 return STATUS_SUCCESS
;
99 /* Handle special cases here */
100 Index
= (ULONG
)Key
& 0x0FFFFFFF;
101 if (Index
>= MAX_DEFAULT_HANDLES
)
103 return STATUS_INVALID_PARAMETER
;
106 RtlEnterCriticalSection (&HandleTableCS
);
107 Handle
= &DefaultHandleTable
[Index
];
110 /* create/open the default handle */
113 case 0: /* HKEY_CLASSES_ROOT */
114 Status
= OpenClassesRootKey (Handle
);
117 case 1: /* HKEY_CURRENT_USER */
118 Status
= RtlOpenCurrentUser (MAXIMUM_ALLOWED
,
122 case 2: /* HKEY_LOCAL_MACHINE */
123 Status
= OpenLocalMachineKey (Handle
);
126 case 3: /* HKEY_USERS */
127 Status
= OpenUsersKey (Handle
);
130 case 4: /* HKEY_PERFORMANCE_DATA */
131 Status
= OpenPerformanceDataKey (Handle
);
134 case 5: /* HKEY_CURRENT_CONFIG */
135 Status
= OpenCurrentConfigKey (Handle
);
138 case 6: /* HKEY_DYN_DATA */
139 Status
= STATUS_NOT_IMPLEMENTED
;
143 DPRINT("MapDefaultHandle() no handle creator\n");
144 Status
= STATUS_INVALID_PARAMETER
;
147 RtlLeaveCriticalSection (&HandleTableCS
);
149 if (NT_SUCCESS(Status
))
151 *RealKey
= (HKEY
)*Handle
;
159 CloseDefaultKeys (VOID
)
163 RtlEnterCriticalSection (&HandleTableCS
);
164 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
166 if (DefaultHandleTable
[i
] != NULL
)
168 NtClose (DefaultHandleTable
[i
]);
169 DefaultHandleTable
[i
] = NULL
;
172 RtlLeaveCriticalSection (&HandleTableCS
);
177 OpenClassesRootKey (PHANDLE KeyHandle
)
179 OBJECT_ATTRIBUTES Attributes
;
180 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\Software\\CLASSES");
182 DPRINT("OpenClassesRootKey()\n");
184 InitializeObjectAttributes (&Attributes
,
186 OBJ_CASE_INSENSITIVE
,
189 return NtOpenKey (KeyHandle
,
196 OpenLocalMachineKey (PHANDLE KeyHandle
)
198 OBJECT_ATTRIBUTES Attributes
;
199 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine");
201 DPRINT("OpenLocalMachineKey()\n");
203 InitializeObjectAttributes (&Attributes
,
205 OBJ_CASE_INSENSITIVE
,
208 return NtOpenKey (KeyHandle
,
215 OpenUsersKey (PHANDLE KeyHandle
)
217 OBJECT_ATTRIBUTES Attributes
;
218 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\User");
220 DPRINT("OpenUsersKey()\n");
222 InitializeObjectAttributes (&Attributes
,
224 OBJ_CASE_INSENSITIVE
,
227 return NtOpenKey (KeyHandle
,
234 OpenCurrentConfigKey (PHANDLE KeyHandle
)
236 OBJECT_ATTRIBUTES Attributes
;
237 UNICODE_STRING KeyName
=
238 ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
240 DPRINT("OpenCurrentConfigKey()\n");
242 InitializeObjectAttributes (&Attributes
,
244 OBJ_CASE_INSENSITIVE
,
247 return NtOpenKey (KeyHandle
,
253 /************************************************************************
259 RegCloseKey (HKEY hKey
)
264 /* don't close null handle or a pseudo handle */
265 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
267 return ERROR_INVALID_HANDLE
;
270 Status
= NtClose (hKey
);
271 if (!NT_SUCCESS(Status
))
273 ErrorCode
= RtlNtStatusToDosError (Status
);
274 SetLastError (ErrorCode
);
278 return ERROR_SUCCESS
;
282 /************************************************************************
283 * RegConnectRegistryA
288 RegConnectRegistryA (LPCSTR lpMachineName
,
292 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
293 return ERROR_CALL_NOT_IMPLEMENTED
;
297 /************************************************************************
298 * RegConnectRegistryW
303 RegConnectRegistryW (LPCWSTR lpMachineName
,
307 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
308 return ERROR_CALL_NOT_IMPLEMENTED
;
312 /************************************************************************
318 RegCreateKeyExA (HKEY hKey
,
324 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
326 LPDWORD lpdwDisposition
)
328 UNICODE_STRING SubKeyString
;
329 UNICODE_STRING ClassString
;
330 OBJECT_ATTRIBUTES Attributes
;
335 DPRINT("RegCreateKeyExA() called\n");
337 /* get the real parent key */
338 Status
= MapDefaultKey (&ParentKey
,
340 if (!NT_SUCCESS(Status
))
342 ErrorCode
= RtlNtStatusToDosError (Status
);
343 SetLastError (ErrorCode
);
346 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
350 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
353 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
355 InitializeObjectAttributes (&Attributes
,
357 OBJ_CASE_INSENSITIVE
,
359 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
360 Status
= NtCreateKey (phkResult
,
364 (lpClass
== NULL
)? NULL
: &ClassString
,
366 (PULONG
)lpdwDisposition
);
367 RtlFreeUnicodeString (&SubKeyString
);
370 RtlFreeUnicodeString (&ClassString
);
372 DPRINT("Status %x\n", Status
);
373 if (!NT_SUCCESS(Status
))
375 ErrorCode
= RtlNtStatusToDosError (Status
);
376 SetLastError (ErrorCode
);
380 return ERROR_SUCCESS
;
384 /************************************************************************
390 RegCreateKeyExW(HKEY hKey
,
396 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
398 LPDWORD lpdwDisposition
)
400 UNICODE_STRING SubKeyString
;
401 UNICODE_STRING ClassString
;
402 OBJECT_ATTRIBUTES Attributes
;
407 DPRINT("RegCreateKeyExW() called\n");
409 /* get the real parent key */
410 Status
= MapDefaultKey (&ParentKey
,
412 if (!NT_SUCCESS(Status
))
414 ErrorCode
= RtlNtStatusToDosError(Status
);
415 SetLastError (ErrorCode
);
418 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
420 RtlInitUnicodeString (&ClassString
,
422 RtlInitUnicodeString (&SubKeyString
,
424 InitializeObjectAttributes (&Attributes
,
426 OBJ_CASE_INSENSITIVE
,
428 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
429 Status
= NtCreateKey (phkResult
,
433 (lpClass
== NULL
)? NULL
: &ClassString
,
435 (PULONG
)lpdwDisposition
);
436 DPRINT("Status %x\n", Status
);
437 if (!NT_SUCCESS(Status
))
439 ErrorCode
= RtlNtStatusToDosError (Status
);
440 SetLastError (ErrorCode
);
444 return ERROR_SUCCESS
;
448 /************************************************************************
454 RegCreateKeyA (HKEY hKey
,
458 return RegCreateKeyExA (hKey
,
470 /************************************************************************
476 RegCreateKeyW (HKEY hKey
,
480 return RegCreateKeyExW (hKey
,
492 /************************************************************************
498 RegDeleteKeyA (HKEY hKey
,
501 OBJECT_ATTRIBUTES ObjectAttributes
;
502 UNICODE_STRING SubKeyName
;
508 Status
= MapDefaultKey (&ParentKey
,
510 if (!NT_SUCCESS(Status
))
512 ErrorCode
= RtlNtStatusToDosError (Status
);
513 SetLastError (ErrorCode
);
517 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
519 InitializeObjectAttributes(&ObjectAttributes
,
521 OBJ_CASE_INSENSITIVE
,
525 Status
= NtOpenKey (&TargetKey
,
528 RtlFreeUnicodeString (&SubKeyName
);
529 if (!NT_SUCCESS(Status
))
531 ErrorCode
= RtlNtStatusToDosError (Status
);
532 SetLastError (ErrorCode
);
536 Status
= NtDeleteKey (TargetKey
);
538 if (!NT_SUCCESS(Status
))
540 ErrorCode
= RtlNtStatusToDosError(Status
);
541 SetLastError (ErrorCode
);
545 return ERROR_SUCCESS
;
549 /************************************************************************
555 RegDeleteKeyW (HKEY hKey
,
558 OBJECT_ATTRIBUTES ObjectAttributes
;
559 UNICODE_STRING SubKeyName
;
565 Status
= MapDefaultKey (&ParentKey
,
567 if (!NT_SUCCESS(Status
))
569 ErrorCode
= RtlNtStatusToDosError (Status
);
570 SetLastError (ErrorCode
);
574 RtlInitUnicodeString (&SubKeyName
,
576 InitializeObjectAttributes (&ObjectAttributes
,
578 OBJ_CASE_INSENSITIVE
,
581 Status
= NtOpenKey (&TargetKey
,
584 if (!NT_SUCCESS(Status
))
586 ErrorCode
= RtlNtStatusToDosError (Status
);
587 SetLastError (ErrorCode
);
591 Status
= NtDeleteKey (TargetKey
);
593 if (!NT_SUCCESS(Status
))
595 ErrorCode
= RtlNtStatusToDosError (Status
);
596 SetLastError (ErrorCode
);
600 return ERROR_SUCCESS
;
604 /************************************************************************
610 RegDeleteValueA (HKEY hKey
,
613 UNICODE_STRING ValueName
;
618 Status
= MapDefaultKey (&KeyHandle
,
620 if (!NT_SUCCESS(Status
))
622 ErrorCode
= RtlNtStatusToDosError (Status
);
623 SetLastError (ErrorCode
);
627 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
629 Status
= NtDeleteValueKey (KeyHandle
,
631 RtlFreeUnicodeString (&ValueName
);
632 if (!NT_SUCCESS(Status
))
634 ErrorCode
= RtlNtStatusToDosError (Status
);
635 SetLastError (ErrorCode
);
639 return ERROR_SUCCESS
;
643 /************************************************************************
649 RegDeleteValueW (HKEY hKey
,
652 UNICODE_STRING ValueName
;
657 Status
= MapDefaultKey (&KeyHandle
,
659 if (!NT_SUCCESS(Status
))
661 ErrorCode
= RtlNtStatusToDosError (Status
);
662 SetLastError (ErrorCode
);
666 RtlInitUnicodeString (&ValueName
,
667 (LPWSTR
)lpValueName
);
669 Status
= NtDeleteValueKey (KeyHandle
,
671 if (!NT_SUCCESS(Status
))
673 ErrorCode
= RtlNtStatusToDosError (Status
);
674 SetLastError (ErrorCode
);
678 return ERROR_SUCCESS
;
682 /************************************************************************
688 RegEnumKeyA (HKEY hKey
,
696 return RegEnumKeyExA (hKey
,
707 /************************************************************************
713 RegEnumKeyW (HKEY hKey
,
721 return RegEnumKeyExW (hKey
,
732 /************************************************************************
738 RegEnumKeyExA (HKEY hKey
,
745 PFILETIME lpftLastWriteTime
)
749 KEY_NODE_INFORMATION Node
;
750 KEY_BASIC_INFORMATION Basic
;
753 UNICODE_STRING StringU
;
755 LONG ErrorCode
= ERROR_SUCCESS
;
763 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
764 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
766 if ((lpClass
) && (!lpcbClass
))
768 SetLastError (ERROR_INVALID_PARAMETER
);
769 return ERROR_INVALID_PARAMETER
;
771 Status
= MapDefaultKey(&KeyHandle
,
773 if (!NT_SUCCESS(Status
))
775 ErrorCode
= RtlNtStatusToDosError (Status
);
776 SetLastError (ErrorCode
);
782 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
792 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
798 /* The class name should start at a dword boundary */
799 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
803 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
806 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
812 SetLastError (ERROR_OUTOFMEMORY
);
813 return ERROR_OUTOFMEMORY
;
816 Status
= NtEnumerateKey (KeyHandle
,
818 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
822 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
823 if (!NT_SUCCESS(Status
))
825 ErrorCode
= RtlNtStatusToDosError (Status
);
831 if (KeyInfo
->Basic
.NameLength
> NameLength
)
833 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
837 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
838 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
839 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
844 if (KeyInfo
->Node
.NameLength
> NameLength
||
845 KeyInfo
->Node
.ClassLength
> ClassLength
)
847 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
851 StringA
.Buffer
= lpClass
;
853 StringA
.MaximumLength
= *lpcbClass
;
854 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
855 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
856 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
857 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
858 lpClass
[StringA
.Length
] = 0;
859 *lpcbClass
= StringA
.Length
;
860 StringU
.Buffer
= KeyInfo
->Node
.Name
;
861 StringU
.Length
= KeyInfo
->Node
.NameLength
;
862 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
865 if (ErrorCode
== ERROR_SUCCESS
)
867 StringA
.Buffer
= lpName
;
869 StringA
.MaximumLength
= *lpcbName
;
870 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
871 lpName
[StringA
.Length
] = 0;
872 *lpcbName
= StringA
.Length
;
873 if (lpftLastWriteTime
!= NULL
)
877 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
878 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
882 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
883 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
889 DPRINT("Key Namea0 Length %d\n", StringU
.Length
);
890 DPRINT("Key Namea1 Length %d\n", NameLength
);
891 DPRINT("Key Namea Length %d\n", *lpcbName
);
892 DPRINT("Key Namea %s\n", lpName
);
894 RtlFreeHeap (ProcessHeap
,
898 if (ErrorCode
!= ERROR_SUCCESS
)
900 SetLastError(ErrorCode
);
907 /************************************************************************
913 RegEnumKeyExW (HKEY hKey
,
920 PFILETIME lpftLastWriteTime
)
924 KEY_NODE_INFORMATION Node
;
925 KEY_BASIC_INFORMATION Basic
;
933 LONG ErrorCode
= ERROR_SUCCESS
;
936 Status
= MapDefaultKey(&KeyHandle
,
938 if (!NT_SUCCESS(Status
))
940 ErrorCode
= RtlNtStatusToDosError (Status
);
941 SetLastError (ErrorCode
);
946 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
956 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
962 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
966 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
968 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
973 SetLastError (ERROR_OUTOFMEMORY
);
974 return ERROR_OUTOFMEMORY
;
977 Status
= NtEnumerateKey (KeyHandle
,
979 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
983 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
984 if (!NT_SUCCESS(Status
))
986 ErrorCode
= RtlNtStatusToDosError (Status
);
992 if (KeyInfo
->Basic
.NameLength
> NameLength
)
994 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
998 RtlCopyMemory (lpName
,
1000 KeyInfo
->Basic
.NameLength
);
1001 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1002 lpName
[*lpcbName
] = 0;
1007 if (KeyInfo
->Node
.NameLength
> NameLength
||
1008 KeyInfo
->Node
.ClassLength
> ClassLength
)
1010 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1014 RtlCopyMemory (lpName
,
1016 KeyInfo
->Node
.NameLength
);
1017 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1018 lpName
[*lpcbName
] = 0;
1019 RtlCopyMemory (lpClass
,
1020 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1021 KeyInfo
->Node
.ClassLength
);
1022 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1023 lpClass
[*lpcbClass
] = 0;
1026 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1028 if (lpClass
== NULL
)
1030 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1031 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1035 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1036 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1041 RtlFreeHeap (ProcessHeap
,
1045 if (ErrorCode
!= ERROR_SUCCESS
)
1047 SetLastError(ErrorCode
);
1053 /************************************************************************
1059 RegEnumValueA (HKEY hKey
,
1062 LPDWORD lpcbValueName
,
1070 KEY_VALUE_FULL_INFORMATION Full
;
1071 KEY_VALUE_BASIC_INFORMATION Basic
;
1081 UNICODE_STRING StringU
;
1082 ANSI_STRING StringA
;
1085 ErrorCode
= ERROR_SUCCESS
;
1087 Status
= MapDefaultKey (&KeyHandle
,
1089 if (!NT_SUCCESS(Status
))
1091 ErrorCode
= RtlNtStatusToDosError (Status
);
1092 SetLastError (ErrorCode
);
1096 if (*lpcbValueName
> 0)
1098 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1106 DataLength
= min (*lpcbData
* sizeof(WCHAR
), REG_MAX_DATA_SIZE
);
1107 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1111 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1114 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1117 if (ValueInfo
== NULL
)
1119 SetLastError(ERROR_OUTOFMEMORY
);
1120 return ERROR_OUTOFMEMORY
;
1123 Status
= NtEnumerateValueKey (KeyHandle
,
1125 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1130 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1131 if (!NT_SUCCESS(Status
))
1133 ErrorCode
= RtlNtStatusToDosError (Status
);
1139 IsStringType
= (ValueInfo
->Full
.Type
== REG_SZ
) ||
1140 (ValueInfo
->Full
.Type
== REG_MULTI_SZ
) ||
1141 (ValueInfo
->Full
.Type
== REG_EXPAND_SZ
);
1142 if (ValueInfo
->Full
.NameLength
> NameLength
||
1143 (!IsStringType
&& ValueInfo
->Full
.DataLength
> *lpcbData
) ||
1144 ValueInfo
->Full
.DataLength
> DataLength
)
1146 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1152 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
);
1153 StringU
.Length
= ValueInfo
->Full
.DataLength
;
1154 StringU
.MaximumLength
= DataLength
;
1155 StringA
.Buffer
= (PCHAR
)lpData
;
1157 StringA
.MaximumLength
= *lpcbData
;
1158 RtlUnicodeStringToAnsiString (&StringA
,
1161 *lpcbData
= StringA
.Length
;
1165 RtlCopyMemory(lpData
,
1166 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1167 ValueInfo
->Full
.DataLength
);
1168 *lpcbData
= ValueInfo
->Full
.DataLength
;
1170 StringU
.Buffer
= ValueInfo
->Full
.Name
;
1171 StringU
.Length
= ValueInfo
->Full
.NameLength
;
1172 StringU
.MaximumLength
= NameLength
;
1177 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1179 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1183 StringU
.Buffer
= ValueInfo
->Basic
.Name
;
1184 StringU
.Length
= ValueInfo
->Basic
.NameLength
;
1185 StringU
.MaximumLength
= NameLength
;
1188 if (ErrorCode
== ERROR_SUCCESS
)
1190 StringA
.Buffer
= (PCHAR
)lpValueName
;
1192 StringA
.MaximumLength
= *lpcbValueName
;
1193 RtlUnicodeStringToAnsiString (&StringA
,
1196 StringA
.Buffer
[StringA
.Length
] = 0;
1197 *lpcbValueName
= StringA
.Length
;
1200 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1204 RtlFreeHeap (ProcessHeap
,
1207 if (ErrorCode
!= ERROR_SUCCESS
)
1209 SetLastError(ErrorCode
);
1215 /************************************************************************
1221 RegEnumValueW (HKEY hKey
,
1224 LPDWORD lpcbValueName
,
1232 KEY_VALUE_FULL_INFORMATION Full
;
1233 KEY_VALUE_BASIC_INFORMATION Basic
;
1244 ErrorCode
= ERROR_SUCCESS
;
1246 Status
= MapDefaultKey (&KeyHandle
,
1248 if (!NT_SUCCESS(Status
))
1250 ErrorCode
= RtlNtStatusToDosError (Status
);
1251 SetLastError (ErrorCode
);
1255 if (*lpcbValueName
> 0)
1257 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1265 DataLength
= min(*lpcbData
, REG_MAX_DATA_SIZE
);
1266 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1270 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1272 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1275 if (ValueInfo
== NULL
)
1277 SetLastError (ERROR_OUTOFMEMORY
);
1278 return ERROR_OUTOFMEMORY
;
1280 Status
= NtEnumerateValueKey (KeyHandle
,
1282 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1287 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1288 if (!NT_SUCCESS(Status
))
1290 ErrorCode
= RtlNtStatusToDosError (Status
);
1296 if (ValueInfo
->Full
.DataLength
> DataLength
||
1297 ValueInfo
->Full
.NameLength
> NameLength
)
1299 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1303 RtlCopyMemory (lpValueName
,
1304 ValueInfo
->Full
.Name
,
1305 ValueInfo
->Full
.NameLength
);
1306 *lpcbValueName
= (DWORD
)(ValueInfo
->Full
.NameLength
/ sizeof(WCHAR
));
1307 lpValueName
[*lpcbValueName
] = 0;
1308 RtlCopyMemory (lpData
,
1309 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1310 ValueInfo
->Full
.DataLength
);
1311 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1316 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1318 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1322 RtlCopyMemory (lpValueName
,
1323 ValueInfo
->Basic
.Name
,
1324 ValueInfo
->Basic
.NameLength
);
1325 *lpcbValueName
= (DWORD
)(ValueInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1326 lpValueName
[*lpcbValueName
] = 0;
1329 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1331 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1334 RtlFreeHeap (ProcessHeap
,
1337 if (ErrorCode
!= ERROR_SUCCESS
)
1339 SetLastError(ErrorCode
);
1345 /************************************************************************
1351 RegFlushKey(HKEY hKey
)
1357 if (hKey
== HKEY_PERFORMANCE_DATA
)
1359 return ERROR_SUCCESS
;
1362 Status
= MapDefaultKey (&KeyHandle
,
1364 if (!NT_SUCCESS(Status
))
1366 ErrorCode
= RtlNtStatusToDosError (Status
);
1367 SetLastError (ErrorCode
);
1371 Status
= NtFlushKey (KeyHandle
);
1372 if (!NT_SUCCESS(Status
))
1374 ErrorCode
= RtlNtStatusToDosError (Status
);
1375 SetLastError (ErrorCode
);
1379 return ERROR_SUCCESS
;
1383 /************************************************************************
1389 RegGetKeySecurity (HKEY hKey
,
1390 SECURITY_INFORMATION SecurityInformation
,
1391 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1392 LPDWORD lpcbSecurityDescriptor
)
1399 if (hKey
= HKEY_PERFORMANCE_DATA
)
1401 return ERROR_INVALID_HANDLE
;
1404 Status
= MapDefaultKey (&KeyHandle
,
1406 if (!NT_SUCCESS(Status
))
1408 ErrorCode
= RtlNtStatusToDosError (Status
);
1409 SetLastError (ErrorCode
);
1413 Status
= NtQuerySecurityObject ()
1414 if (!NT_SUCCESS(Status
))
1416 ErrorCode
= RtlNtStatusToDosError (Status
);
1417 SetLastError (ErrorCode
);
1421 return ERROR_SUCCESS
;
1425 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1426 return ERROR_CALL_NOT_IMPLEMENTED
;
1430 /************************************************************************
1436 RegLoadKeyA (HKEY hKey
,
1440 UNICODE_STRING FileName
;
1441 UNICODE_STRING KeyName
;
1444 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1446 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1449 ErrorCode
= RegLoadKeyW (hKey
,
1453 RtlFreeUnicodeString (&FileName
);
1454 RtlFreeUnicodeString (&KeyName
);
1460 /************************************************************************
1466 RegLoadKeyW (HKEY hKey
,
1470 OBJECT_ATTRIBUTES FileObjectAttributes
;
1471 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1472 UNICODE_STRING FileName
;
1473 UNICODE_STRING KeyName
;
1478 if (hKey
== HKEY_PERFORMANCE_DATA
)
1480 return ERROR_INVALID_HANDLE
;
1483 Status
= MapDefaultKey (&KeyHandle
,
1485 if (!NT_SUCCESS(Status
))
1487 ErrorCode
= RtlNtStatusToDosError (Status
);
1488 SetLastError (ErrorCode
);
1492 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1497 SetLastError (ERROR_BAD_PATHNAME
);
1498 return ERROR_BAD_PATHNAME
;
1501 InitializeObjectAttributes (&FileObjectAttributes
,
1503 OBJ_CASE_INSENSITIVE
,
1507 RtlInitUnicodeString (&KeyName
,
1510 InitializeObjectAttributes (&KeyObjectAttributes
,
1512 OBJ_CASE_INSENSITIVE
,
1516 Status
= NtLoadKey (&KeyObjectAttributes
,
1517 &FileObjectAttributes
);
1519 RtlFreeUnicodeString (&FileName
);
1521 if (!NT_SUCCESS(Status
))
1523 ErrorCode
= RtlNtStatusToDosError (Status
);
1524 SetLastError (ErrorCode
);
1528 return ERROR_SUCCESS
;
1532 /************************************************************************
1533 * RegNotifyChangeKeyValue
1538 RegNotifyChangeKeyValue (HKEY hKey
,
1540 DWORD dwNotifyFilter
,
1544 IO_STATUS_BLOCK IoStatusBlock
;
1548 if (hKey
== HKEY_PERFORMANCE_DATA
)
1550 return ERROR_INVALID_HANDLE
;
1553 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1555 return ERROR_INVALID_PARAMETER
;
1558 Status
= MapDefaultKey (&KeyHandle
,
1560 if (!NT_SUCCESS(Status
))
1562 return RtlNtStatusToDosError (Status
);
1565 /* FIXME: Remote key handles must fail */
1567 Status
= NtNotifyChangeKey (KeyHandle
,
1577 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1579 return RtlNtStatusToDosError (Status
);
1582 return ERROR_SUCCESS
;
1587 /************************************************************************
1593 RegOpenKeyA (HKEY hKey
,
1597 OBJECT_ATTRIBUTES ObjectAttributes
;
1598 UNICODE_STRING SubKeyString
;
1603 Status
= MapDefaultKey (&KeyHandle
,
1605 if (!NT_SUCCESS(Status
))
1607 ErrorCode
= RtlNtStatusToDosError (Status
);
1608 SetLastError (ErrorCode
);
1612 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1614 InitializeObjectAttributes (&ObjectAttributes
,
1616 OBJ_CASE_INSENSITIVE
,
1619 Status
= NtOpenKey (phkResult
,
1622 RtlFreeUnicodeString (&SubKeyString
);
1623 if (!NT_SUCCESS(Status
))
1625 ErrorCode
= RtlNtStatusToDosError (Status
);
1626 SetLastError (ErrorCode
);
1630 return ERROR_SUCCESS
;
1634 /************************************************************************
1643 RegOpenKeyW (HKEY hKey
,
1647 OBJECT_ATTRIBUTES ObjectAttributes
;
1648 UNICODE_STRING SubKeyString
;
1653 Status
= MapDefaultKey (&KeyHandle
,
1655 if (!NT_SUCCESS(Status
))
1657 ErrorCode
= RtlNtStatusToDosError (Status
);
1658 SetLastError (ErrorCode
);
1662 RtlInitUnicodeString (&SubKeyString
,
1664 InitializeObjectAttributes (&ObjectAttributes
,
1666 OBJ_CASE_INSENSITIVE
,
1669 Status
= NtOpenKey (phkResult
,
1672 if (!NT_SUCCESS(Status
))
1674 ErrorCode
= RtlNtStatusToDosError (Status
);
1675 SetLastError(ErrorCode
);
1679 return ERROR_SUCCESS
;
1683 /************************************************************************
1689 RegOpenKeyExA (HKEY hKey
,
1695 OBJECT_ATTRIBUTES ObjectAttributes
;
1696 UNICODE_STRING SubKeyString
;
1701 Status
= MapDefaultKey (&KeyHandle
,
1703 if (!NT_SUCCESS(Status
))
1705 ErrorCode
= RtlNtStatusToDosError (Status
);
1706 SetLastError (ErrorCode
);
1710 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1712 InitializeObjectAttributes (&ObjectAttributes
,
1714 OBJ_CASE_INSENSITIVE
,
1717 Status
= NtOpenKey (phkResult
,
1720 RtlFreeUnicodeString (&SubKeyString
);
1721 if (!NT_SUCCESS(Status
))
1723 ErrorCode
= RtlNtStatusToDosError (Status
);
1724 SetLastError (ErrorCode
);
1728 return ERROR_SUCCESS
;
1732 /************************************************************************
1738 RegOpenKeyExW (HKEY hKey
,
1744 OBJECT_ATTRIBUTES ObjectAttributes
;
1745 UNICODE_STRING SubKeyString
;
1750 Status
= MapDefaultKey (&KeyHandle
,
1752 if (!NT_SUCCESS(Status
))
1754 ErrorCode
= RtlNtStatusToDosError (Status
);
1755 SetLastError (ErrorCode
);
1759 if (lpSubKey
!= NULL
)
1761 RtlInitUnicodeString (&SubKeyString
,
1766 RtlInitUnicodeString (&SubKeyString
,
1769 InitializeObjectAttributes (&ObjectAttributes
,
1771 OBJ_CASE_INSENSITIVE
,
1774 Status
= NtOpenKey (phkResult
,
1777 if (!NT_SUCCESS(Status
))
1779 ErrorCode
= RtlNtStatusToDosError (Status
);
1780 SetLastError (ErrorCode
);
1784 return ERROR_SUCCESS
;
1788 /************************************************************************
1794 RegQueryInfoKeyA (HKEY hKey
,
1799 LPDWORD lpcbMaxSubKeyLen
,
1800 LPDWORD lpcbMaxClassLen
,
1802 LPDWORD lpcbMaxValueNameLen
,
1803 LPDWORD lpcbMaxValueLen
,
1804 LPDWORD lpcbSecurityDescriptor
,
1805 PFILETIME lpftLastWriteTime
)
1807 WCHAR ClassName
[MAX_PATH
];
1808 UNICODE_STRING UnicodeString
;
1809 ANSI_STRING AnsiString
;
1812 RtlInitUnicodeString (&UnicodeString
,
1814 if (lpClass
!= NULL
)
1816 UnicodeString
.Buffer
= &ClassName
[0];
1817 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1818 AnsiString
.MaximumLength
= *lpcbClass
;
1821 ErrorCode
= RegQueryInfoKeyW (hKey
,
1822 UnicodeString
.Buffer
,
1829 lpcbMaxValueNameLen
,
1831 lpcbSecurityDescriptor
,
1833 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1835 AnsiString
.Buffer
= lpClass
;
1836 AnsiString
.Length
= 0;
1837 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1838 RtlUnicodeStringToAnsiString (&AnsiString
,
1841 *lpcbClass
= AnsiString
.Length
;
1842 lpClass
[AnsiString
.Length
] = 0;
1849 /************************************************************************
1855 RegQueryInfoKeyW (HKEY hKey
,
1860 LPDWORD lpcbMaxSubKeyLen
,
1861 LPDWORD lpcbMaxClassLen
,
1863 LPDWORD lpcbMaxValueNameLen
,
1864 LPDWORD lpcbMaxValueLen
,
1865 LPDWORD lpcbSecurityDescriptor
,
1866 PFILETIME lpftLastWriteTime
)
1868 KEY_FULL_INFORMATION FullInfoBuffer
;
1869 PKEY_FULL_INFORMATION FullInfo
;
1874 LONG ErrorCode
= ERROR_SUCCESS
;
1877 if ((lpClass
) && (!lpcbClass
))
1879 SetLastError(ERROR_INVALID_PARAMETER
);
1880 return ERROR_INVALID_PARAMETER
;
1883 Status
= MapDefaultKey (&KeyHandle
,
1885 if (!NT_SUCCESS(Status
))
1887 ErrorCode
= RtlNtStatusToDosError (Status
);
1888 SetLastError (ErrorCode
);
1892 if (lpClass
!= NULL
)
1896 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1902 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
1903 FullInfo
= RtlAllocateHeap (ProcessHeap
,
1906 if (FullInfo
== NULL
)
1908 SetLastError (ERROR_OUTOFMEMORY
);
1909 return ERROR_OUTOFMEMORY
;
1911 FullInfo
->ClassLength
= ClassLength
;
1915 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
1916 FullInfo
= &FullInfoBuffer
;
1917 FullInfo
->ClassLength
= 0;
1919 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
1921 Status
= NtQueryKey (KeyHandle
,
1926 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
1927 if (!NT_SUCCESS(Status
))
1929 ErrorCode
= RtlNtStatusToDosError (Status
);
1933 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
1934 if (lpcSubKeys
!= NULL
)
1936 *lpcSubKeys
= FullInfo
->SubKeys
;
1939 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
1940 if (lpcbMaxSubKeyLen
!= NULL
)
1942 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
1945 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
1946 if (lpcbMaxClassLen
!= NULL
)
1948 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
1951 DPRINT("Values %lu\n", FullInfo
->Values
);
1954 *lpcValues
= FullInfo
->Values
;
1957 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
1958 if (lpcbMaxValueNameLen
)
1960 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
1963 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
1964 if (lpcbMaxValueLen
)
1966 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
1969 if (lpcbSecurityDescriptor
)
1971 *lpcbSecurityDescriptor
= 0;
1975 if (lpftLastWriteTime
!= NULL
)
1977 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
1978 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
1981 if (lpClass
!= NULL
)
1983 if (FullInfo
->ClassLength
> ClassLength
)
1985 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1989 RtlCopyMemory (lpClass
,
1991 FullInfo
->ClassLength
);
1992 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
1993 lpClass
[*lpcbClass
] = 0;
1997 if (lpClass
!= NULL
)
1999 RtlFreeHeap (ProcessHeap
,
2003 if (ErrorCode
!= ERROR_SUCCESS
)
2005 SetLastError(ErrorCode
);
2012 /************************************************************************
2013 * RegQueryMultipleValuesA
2018 RegQueryMultipleValuesA (HKEY hKey
,
2025 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2026 return ERROR_CALL_NOT_IMPLEMENTED
;
2030 /************************************************************************
2031 * RegQueryMultipleValuesW
2036 RegQueryMultipleValuesW (HKEY hKey
,
2043 DWORD maxBytes
= *ldwTotsize
;
2045 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2047 if ( maxBytes
>= (1024*1024) )
2048 return ERROR_TRANSFER_TOO_LONG
;
2052 //TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2054 for(i
=0; i
< num_vals
; ++i
)
2056 val_list
[i
].ve_valuelen
=0;
2057 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
2058 if(status
!= ERROR_SUCCESS
)
2063 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2065 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
2066 bufptr
, &val_list
[i
].ve_valuelen
);
2067 if(status
!= ERROR_SUCCESS
)
2072 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2074 bufptr
+= val_list
[i
].ve_valuelen
;
2077 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2079 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2083 /************************************************************************
2089 RegQueryValueExW (HKEY hKey
,
2090 LPCWSTR lpValueName
,
2096 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2097 UNICODE_STRING ValueName
;
2099 LONG ErrorCode
= ERROR_SUCCESS
;
2104 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2105 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2107 Status
= MapDefaultKey (&KeyHandle
,
2109 if (!NT_SUCCESS(Status
))
2111 ErrorCode
= RtlNtStatusToDosError (Status
);
2112 SetLastError (ErrorCode
);
2116 if (lpData
!= NULL
&& lpcbData
== NULL
)
2118 SetLastError (ERROR_INVALID_PARAMETER
);
2119 return ERROR_INVALID_PARAMETER
;
2122 RtlInitUnicodeString (&ValueName
,
2124 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + *lpcbData
;
2125 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2128 if (ValueInfo
== NULL
)
2130 SetLastError(ERROR_OUTOFMEMORY
);
2131 return ERROR_OUTOFMEMORY
;
2134 Status
= NtQueryValueKey (hKey
,
2136 KeyValuePartialInformation
,
2140 DPRINT("Status 0x%X\n", Status
);
2141 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2143 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2144 ErrorCode
= ERROR_SUCCESS
;
2146 else if (!NT_SUCCESS(Status
))
2148 ErrorCode
= RtlNtStatusToDosError (Status
);
2149 SetLastError (ErrorCode
);
2155 *lpType
= ValueInfo
->Type
;
2157 RtlMoveMemory (lpData
,
2159 ValueInfo
->DataLength
);
2160 if ((ValueInfo
->Type
== REG_SZ
) ||
2161 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2162 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2164 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2167 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2169 if (NULL
!= lpcbData
)
2171 *lpcbData
= (DWORD
)ValueInfo
->DataLength
;
2173 RtlFreeHeap (ProcessHeap
,
2181 /************************************************************************
2196 UNICODE_STRING ValueName
;
2197 UNICODE_STRING ValueData
;
2198 ANSI_STRING AnsiString
;
2201 if ((lpData
) && (!lpcbData
))
2203 SetLastError(ERROR_INVALID_PARAMETER
);
2204 return ERROR_INVALID_PARAMETER
;
2209 ValueData
.Length
= ValueData
.MaximumLength
= *lpcbData
* sizeof(WCHAR
);
2210 ValueData
.Buffer
= RtlAllocateHeap(
2214 if (!ValueData
.Buffer
)
2216 SetLastError(ERROR_OUTOFMEMORY
);
2217 return ERROR_OUTOFMEMORY
;
2222 ValueData
.Buffer
= NULL
;
2225 RtlCreateUnicodeStringFromAsciiz(&ValueName
, (LPSTR
)lpValueName
);
2227 ErrorCode
= RegQueryValueExW(
2232 (LPBYTE
)ValueData
.Buffer
,
2233 (LPDWORD
)&ValueData
.Length
);
2235 if ((ErrorCode
== ERROR_SUCCESS
) && (ValueData
.Buffer
!= NULL
))
2237 if (lpType
&& ((*lpType
== REG_SZ
) || (*lpType
== REG_MULTI_SZ
) || (*lpType
== REG_EXPAND_SZ
)))
2239 RtlInitAnsiString(&AnsiString
, NULL
);
2240 AnsiString
.Buffer
= lpData
;
2241 AnsiString
.MaximumLength
= *lpcbData
;
2242 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2243 *lpcbData
= ValueData
.Length
/ sizeof(WCHAR
);
2245 RtlMoveMemory(lpData
, ValueData
.Buffer
, *lpcbData
);
2246 *lpcbData
= ValueData
.Length
;
2250 if (ValueData
.Buffer
)
2252 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2259 /************************************************************************
2265 RegQueryValueA (HKEY hKey
,
2270 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2271 UNICODE_STRING SubKeyName
;
2272 UNICODE_STRING Value
;
2273 ANSI_STRING AnsiString
;
2277 if (lpValue
!= NULL
&&
2280 SetLastError(ERROR_INVALID_PARAMETER
);
2281 return ERROR_INVALID_PARAMETER
;
2284 RtlInitUnicodeString (&SubKeyName
,
2286 RtlInitUnicodeString (&Value
,
2288 if (lpSubKey
!= NULL
&&
2289 strlen(lpSubKey
) != 0)
2291 RtlInitAnsiString (&AnsiString
,
2293 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2294 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2295 RtlAnsiStringToUnicodeString (&SubKeyName
,
2300 if (lpValue
!= NULL
)
2302 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2303 Value
.MaximumLength
= ValueSize
;
2304 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2307 if (Value
.Buffer
== NULL
)
2309 SetLastError(ERROR_OUTOFMEMORY
);
2310 return ERROR_OUTOFMEMORY
;
2318 ErrorCode
= RegQueryValueW (hKey
,
2319 (LPCWSTR
)SubKeyName
.Buffer
,
2322 if (ErrorCode
== ERROR_SUCCESS
)
2324 Value
.Length
= ValueSize
;
2325 RtlInitAnsiString (&AnsiString
,
2327 AnsiString
.Buffer
= lpValue
;
2328 AnsiString
.MaximumLength
= *lpcbValue
;
2329 RtlUnicodeStringToAnsiString (&AnsiString
,
2334 *lpcbValue
= ValueSize
;
2335 if (Value
.Buffer
!= NULL
)
2337 RtlFreeHeap (ProcessHeap
,
2346 /************************************************************************
2352 RegQueryValueW (HKEY hKey
,
2357 OBJECT_ATTRIBUTES ObjectAttributes
;
2358 UNICODE_STRING SubKeyString
;
2365 Status
= MapDefaultKey (&KeyHandle
,
2367 if (!NT_SUCCESS(Status
))
2369 ErrorCode
= RtlNtStatusToDosError (Status
);
2370 SetLastError (ErrorCode
);
2374 if (lpSubKey
!= NULL
&&
2375 wcslen(lpSubKey
) != 0)
2377 RtlInitUnicodeString (&SubKeyString
,
2379 InitializeObjectAttributes (&ObjectAttributes
,
2381 OBJ_CASE_INSENSITIVE
,
2384 Status
= NtOpenKey (&RealKey
,
2387 if (!NT_SUCCESS(Status
))
2389 ErrorCode
= RtlNtStatusToDosError (Status
);
2390 SetLastError (ErrorCode
);
2393 CloseRealKey
= TRUE
;
2398 CloseRealKey
= FALSE
;
2401 ErrorCode
= RegQueryValueExW (RealKey
,
2406 (LPDWORD
)lpcbValue
);
2416 /************************************************************************
2422 RegReplaceKeyA (HKEY hKey
,
2427 UNICODE_STRING lpSubKeyW
;
2428 UNICODE_STRING lpNewFileW
;
2429 UNICODE_STRING lpOldFileW
;
2432 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, (PCSZ
)lpSubKey
);
2433 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, (PCSZ
)lpOldFile
);
2434 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, (PCSZ
)lpNewFile
);
2435 ret
= RegReplaceKeyW( hKey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
2436 RtlFreeUnicodeString( &lpOldFileW
);
2437 RtlFreeUnicodeString( &lpNewFileW
);
2438 RtlFreeUnicodeString( &lpSubKeyW
);
2443 /************************************************************************
2449 RegReplaceKeyW (HKEY hKey
,
2455 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2456 return ERROR_CALL_NOT_IMPLEMENTED
;
2460 /************************************************************************
2466 RegRestoreKeyA (HKEY hKey
,
2470 UNICODE_STRING lpFileW
;
2473 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, (PCSZ
)lpFile
);
2474 ret
= RegRestoreKeyW( hKey
, lpFileW
.Buffer
, dwFlags
);
2475 RtlFreeUnicodeString( &lpFileW
);
2480 /************************************************************************
2486 RegRestoreKeyW (HKEY hKey
,
2491 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2492 return ERROR_CALL_NOT_IMPLEMENTED
;
2496 /************************************************************************
2502 RegSaveKeyA(HKEY hKey
,
2504 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2506 UNICODE_STRING FileName
;
2509 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2511 ErrorCode
= RegSaveKeyW (hKey
,
2513 lpSecurityAttributes
);
2514 RtlFreeUnicodeString (&FileName
);
2520 /************************************************************************
2526 RegSaveKeyW (HKEY hKey
,
2528 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2530 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2531 OBJECT_ATTRIBUTES ObjectAttributes
;
2532 UNICODE_STRING NtName
;
2533 IO_STATUS_BLOCK IoStatusBlock
;
2539 Status
= MapDefaultKey (&KeyHandle
,
2541 if (!NT_SUCCESS(Status
))
2543 ErrorCode
= RtlNtStatusToDosError (Status
);
2544 SetLastError (ErrorCode
);
2548 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2553 SetLastError (ERROR_INVALID_PARAMETER
);
2554 return ERROR_INVALID_PARAMETER
;
2557 if (lpSecurityAttributes
!= NULL
)
2559 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2562 InitializeObjectAttributes (&ObjectAttributes
,
2564 OBJ_CASE_INSENSITIVE
,
2566 SecurityDescriptor
);
2567 Status
= NtCreateFile (&FileHandle
,
2568 GENERIC_WRITE
| SYNCHRONIZE
,
2572 FILE_ATTRIBUTE_NORMAL
,
2575 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2578 RtlFreeUnicodeString (&NtName
);
2579 if (!NT_SUCCESS(Status
))
2581 ErrorCode
= RtlNtStatusToDosError (Status
);
2582 SetLastError (ErrorCode
);
2586 Status
= NtSaveKey (KeyHandle
,
2588 NtClose (FileHandle
);
2589 if (!NT_SUCCESS(Status
))
2591 ErrorCode
= RtlNtStatusToDosError (Status
);
2592 SetLastError (ErrorCode
);
2596 return ERROR_SUCCESS
;
2600 /************************************************************************
2606 RegSetKeySecurity (HKEY hKey
,
2607 SECURITY_INFORMATION SecurityInformation
,
2608 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
2614 if (hKey
== HKEY_PERFORMANCE_DATA
)
2615 return ERROR_INVALID_HANDLE
;
2617 Status
= MapDefaultKey (&KeyHandle
,
2619 if (!NT_SUCCESS(Status
))
2621 ErrorCode
= RtlNtStatusToDosError (Status
);
2622 SetLastError (ErrorCode
);
2626 Status
= NtSetSecurityObject (KeyHandle
,
2627 SecurityInformation
,
2628 pSecurityDescriptor
);
2629 if (!NT_SUCCESS(Status
))
2631 ErrorCode
= RtlNtStatusToDosError (Status
);
2632 SetLastError (ErrorCode
);
2636 return ERROR_SUCCESS
;
2640 /************************************************************************
2646 RegSetValueExA (HKEY hKey
,
2653 UNICODE_STRING ValueName
;
2655 ANSI_STRING AnsiString
;
2656 UNICODE_STRING Data
;
2663 SetLastError (ERROR_INVALID_PARAMETER
);
2664 return ERROR_INVALID_PARAMETER
;
2667 if (lpValueName
!= NULL
&&
2668 strlen(lpValueName
) != 0)
2670 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2671 (LPSTR
)lpValueName
);
2672 pValueName
= (LPWSTR
)ValueName
.Buffer
;
2679 if ((dwType
== REG_SZ
) ||
2680 (dwType
== REG_MULTI_SZ
) ||
2681 (dwType
== REG_EXPAND_SZ
))
2683 RtlInitAnsiString (&AnsiString
,
2685 AnsiString
.Buffer
= (LPSTR
)lpData
;
2686 AnsiString
.Length
= cbData
;
2687 AnsiString
.MaximumLength
= cbData
;
2688 RtlAnsiStringToUnicodeString (&Data
,
2691 pData
= (LPBYTE
)Data
.Buffer
;
2692 DataSize
= cbData
* sizeof(WCHAR
);
2696 RtlInitUnicodeString (&Data
,
2698 pData
= (LPBYTE
)lpData
;
2702 ErrorCode
= RegSetValueExW (hKey
,
2708 if (pValueName
!= NULL
)
2710 RtlFreeHeap (ProcessHeap
,
2715 if (Data
.Buffer
!= NULL
)
2717 RtlFreeHeap (ProcessHeap
,
2726 /************************************************************************
2732 RegSetValueExW (HKEY hKey
,
2733 LPCWSTR lpValueName
,
2739 UNICODE_STRING ValueName
;
2740 PUNICODE_STRING pValueName
;
2745 Status
= MapDefaultKey (&KeyHandle
,
2747 if (!NT_SUCCESS(Status
))
2749 ErrorCode
= RtlNtStatusToDosError (Status
);
2750 SetLastError (ErrorCode
);
2754 if (lpValueName
!= NULL
)
2756 RtlInitUnicodeString (&ValueName
,
2758 pValueName
= &ValueName
;
2765 Status
= NtSetValueKey (KeyHandle
,
2771 if (!NT_SUCCESS(Status
))
2773 ErrorCode
= RtlNtStatusToDosError (Status
);
2774 SetLastError (ErrorCode
);
2778 return ERROR_SUCCESS
;
2782 /************************************************************************
2788 RegSetValueA (HKEY hKey
,
2794 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2795 UNICODE_STRING SubKeyName
;
2796 UNICODE_STRING Data
;
2797 ANSI_STRING AnsiString
;
2803 SetLastError (ERROR_INVALID_PARAMETER
);
2804 return ERROR_INVALID_PARAMETER
;
2807 RtlInitUnicodeString (&SubKeyName
, NULL
);
2808 RtlInitUnicodeString (&Data
, NULL
);
2809 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
2811 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
2812 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2813 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2814 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
2817 DataSize
= cbData
* sizeof(WCHAR
);
2818 Data
.MaximumLength
= DataSize
;
2819 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2822 if (Data
.Buffer
== NULL
)
2824 SetLastError (ERROR_OUTOFMEMORY
);
2825 return ERROR_OUTOFMEMORY
;
2828 ErrorCode
= RegSetValueW (hKey
,
2829 (LPCWSTR
)SubKeyName
.Buffer
,
2833 RtlFreeHeap (ProcessHeap
,
2841 /************************************************************************
2847 RegSetValueW (HKEY hKey
,
2853 OBJECT_ATTRIBUTES ObjectAttributes
;
2854 UNICODE_STRING SubKeyString
;
2861 Status
= MapDefaultKey (&KeyHandle
,
2863 if (!NT_SUCCESS(Status
))
2865 ErrorCode
= RtlNtStatusToDosError (Status
);
2866 SetLastError (ErrorCode
);
2870 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
2872 RtlInitUnicodeString (&SubKeyString
,
2874 InitializeObjectAttributes (&ObjectAttributes
,
2876 OBJ_CASE_INSENSITIVE
,
2879 Status
= NtOpenKey (&RealKey
,
2882 if (!NT_SUCCESS(Status
))
2884 ErrorCode
= RtlNtStatusToDosError (Status
);
2885 SetLastError (ErrorCode
);
2888 CloseRealKey
= TRUE
;
2893 CloseRealKey
= FALSE
;
2896 ErrorCode
= RegSetValueExW (RealKey
,
2902 if (CloseRealKey
== TRUE
)
2911 /************************************************************************
2917 RegUnLoadKeyA (HKEY hKey
,
2920 UNICODE_STRING KeyName
;
2923 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
2926 ErrorCode
= RegUnLoadKeyW (hKey
,
2929 RtlFreeUnicodeString (&KeyName
);
2935 /************************************************************************
2941 RegUnLoadKeyW (HKEY hKey
,
2944 OBJECT_ATTRIBUTES ObjectAttributes
;
2945 UNICODE_STRING KeyName
;
2950 if (hKey
== HKEY_PERFORMANCE_DATA
)
2951 return ERROR_INVALID_HANDLE
;
2953 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2954 if (!NT_SUCCESS(Status
))
2956 ErrorCode
= RtlNtStatusToDosError (Status
);
2957 SetLastError (ErrorCode
);
2961 RtlInitUnicodeString (&KeyName
,
2964 InitializeObjectAttributes (&ObjectAttributes
,
2966 OBJ_CASE_INSENSITIVE
,
2970 Status
= NtUnloadKey (&ObjectAttributes
);
2972 if (!NT_SUCCESS(Status
))
2974 ErrorCode
= RtlNtStatusToDosError (Status
);
2975 SetLastError (ErrorCode
);
2979 return ERROR_SUCCESS
;