1 /* $Id: reg.c,v 1.41 2003/12/28 23:22:30 arty 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
,
197 OpenLocalMachineKey (PHANDLE KeyHandle
)
199 OBJECT_ATTRIBUTES Attributes
;
200 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\Machine");
203 DPRINT("OpenLocalMachineKey()\n");
205 InitializeObjectAttributes (&Attributes
,
207 OBJ_CASE_INSENSITIVE
,
210 Status
= NtOpenKey (KeyHandle
,
214 DPRINT("NtOpenKey(%wZ) => %08x\n", &KeyName
, Status
);
221 OpenUsersKey (PHANDLE KeyHandle
)
223 OBJECT_ATTRIBUTES Attributes
;
224 UNICODE_STRING KeyName
= ROS_STRING_INITIALIZER(L
"\\Registry\\User");
226 DPRINT("OpenUsersKey()\n");
228 InitializeObjectAttributes (&Attributes
,
230 OBJ_CASE_INSENSITIVE
,
233 return NtOpenKey (KeyHandle
,
240 OpenCurrentConfigKey (PHANDLE KeyHandle
)
242 OBJECT_ATTRIBUTES Attributes
;
243 UNICODE_STRING KeyName
=
244 ROS_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
246 DPRINT("OpenCurrentConfigKey()\n");
248 InitializeObjectAttributes (&Attributes
,
250 OBJ_CASE_INSENSITIVE
,
253 return NtOpenKey (KeyHandle
,
259 /************************************************************************
265 RegCloseKey (HKEY hKey
)
270 /* don't close null handle or a pseudo handle */
271 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
273 return ERROR_INVALID_HANDLE
;
276 Status
= NtClose (hKey
);
277 if (!NT_SUCCESS(Status
))
279 ErrorCode
= RtlNtStatusToDosError (Status
);
280 SetLastError (ErrorCode
);
284 return ERROR_SUCCESS
;
288 /************************************************************************
289 * RegConnectRegistryA
294 RegConnectRegistryA (LPCSTR lpMachineName
,
298 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
299 return ERROR_CALL_NOT_IMPLEMENTED
;
303 /************************************************************************
304 * RegConnectRegistryW
309 RegConnectRegistryW (LPCWSTR lpMachineName
,
313 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
314 return ERROR_CALL_NOT_IMPLEMENTED
;
318 /************************************************************************
324 RegCreateKeyExA (HKEY hKey
,
330 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
332 LPDWORD lpdwDisposition
)
334 UNICODE_STRING SubKeyString
;
335 UNICODE_STRING ClassString
;
336 OBJECT_ATTRIBUTES Attributes
;
341 DPRINT("RegCreateKeyExA() called\n");
343 /* get the real parent key */
344 Status
= MapDefaultKey (&ParentKey
,
346 if (!NT_SUCCESS(Status
))
348 ErrorCode
= RtlNtStatusToDosError (Status
);
349 SetLastError (ErrorCode
);
352 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
356 RtlCreateUnicodeStringFromAsciiz (&ClassString
,
359 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
361 InitializeObjectAttributes (&Attributes
,
363 OBJ_CASE_INSENSITIVE
,
365 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
366 Status
= NtCreateKey (phkResult
,
370 (lpClass
== NULL
)? NULL
: &ClassString
,
372 (PULONG
)lpdwDisposition
);
373 RtlFreeUnicodeString (&SubKeyString
);
376 RtlFreeUnicodeString (&ClassString
);
378 DPRINT("Status %x\n", Status
);
379 if (!NT_SUCCESS(Status
))
381 ErrorCode
= RtlNtStatusToDosError (Status
);
382 SetLastError (ErrorCode
);
386 return ERROR_SUCCESS
;
390 /************************************************************************
396 RegCreateKeyExW(HKEY hKey
,
402 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
404 LPDWORD lpdwDisposition
)
406 UNICODE_STRING SubKeyString
;
407 UNICODE_STRING ClassString
;
408 OBJECT_ATTRIBUTES Attributes
;
413 DPRINT("RegCreateKeyExW() called\n");
415 /* get the real parent key */
416 Status
= MapDefaultKey (&ParentKey
,
418 if (!NT_SUCCESS(Status
))
420 ErrorCode
= RtlNtStatusToDosError(Status
);
421 SetLastError (ErrorCode
);
424 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
426 RtlInitUnicodeString (&ClassString
,
428 RtlInitUnicodeString (&SubKeyString
,
430 InitializeObjectAttributes (&Attributes
,
432 OBJ_CASE_INSENSITIVE
,
434 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
435 Status
= NtCreateKey (phkResult
,
439 (lpClass
== NULL
)? NULL
: &ClassString
,
441 (PULONG
)lpdwDisposition
);
442 DPRINT("Status %x\n", Status
);
443 if (!NT_SUCCESS(Status
))
445 ErrorCode
= RtlNtStatusToDosError (Status
);
446 SetLastError (ErrorCode
);
450 return ERROR_SUCCESS
;
454 /************************************************************************
460 RegCreateKeyA (HKEY hKey
,
464 return RegCreateKeyExA (hKey
,
476 /************************************************************************
482 RegCreateKeyW (HKEY hKey
,
486 return RegCreateKeyExW (hKey
,
498 /************************************************************************
504 RegDeleteKeyA (HKEY hKey
,
507 OBJECT_ATTRIBUTES ObjectAttributes
;
508 UNICODE_STRING SubKeyName
;
514 Status
= MapDefaultKey (&ParentKey
,
516 if (!NT_SUCCESS(Status
))
518 ErrorCode
= RtlNtStatusToDosError (Status
);
519 SetLastError (ErrorCode
);
523 RtlCreateUnicodeStringFromAsciiz (&SubKeyName
,
525 InitializeObjectAttributes(&ObjectAttributes
,
527 OBJ_CASE_INSENSITIVE
,
531 Status
= NtOpenKey (&TargetKey
,
534 RtlFreeUnicodeString (&SubKeyName
);
535 if (!NT_SUCCESS(Status
))
537 ErrorCode
= RtlNtStatusToDosError (Status
);
538 SetLastError (ErrorCode
);
542 Status
= NtDeleteKey (TargetKey
);
544 if (!NT_SUCCESS(Status
))
546 ErrorCode
= RtlNtStatusToDosError(Status
);
547 SetLastError (ErrorCode
);
551 return ERROR_SUCCESS
;
555 /************************************************************************
561 RegDeleteKeyW (HKEY hKey
,
564 OBJECT_ATTRIBUTES ObjectAttributes
;
565 UNICODE_STRING SubKeyName
;
571 Status
= MapDefaultKey (&ParentKey
,
573 if (!NT_SUCCESS(Status
))
575 ErrorCode
= RtlNtStatusToDosError (Status
);
576 SetLastError (ErrorCode
);
580 RtlInitUnicodeString (&SubKeyName
,
582 InitializeObjectAttributes (&ObjectAttributes
,
584 OBJ_CASE_INSENSITIVE
,
587 Status
= NtOpenKey (&TargetKey
,
590 if (!NT_SUCCESS(Status
))
592 ErrorCode
= RtlNtStatusToDosError (Status
);
593 SetLastError (ErrorCode
);
597 Status
= NtDeleteKey (TargetKey
);
599 if (!NT_SUCCESS(Status
))
601 ErrorCode
= RtlNtStatusToDosError (Status
);
602 SetLastError (ErrorCode
);
606 return ERROR_SUCCESS
;
610 /************************************************************************
616 RegDeleteValueA (HKEY hKey
,
619 UNICODE_STRING ValueName
;
624 Status
= MapDefaultKey (&KeyHandle
,
626 if (!NT_SUCCESS(Status
))
628 ErrorCode
= RtlNtStatusToDosError (Status
);
629 SetLastError (ErrorCode
);
633 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
635 Status
= NtDeleteValueKey (KeyHandle
,
637 RtlFreeUnicodeString (&ValueName
);
638 if (!NT_SUCCESS(Status
))
640 ErrorCode
= RtlNtStatusToDosError (Status
);
641 SetLastError (ErrorCode
);
645 return ERROR_SUCCESS
;
649 /************************************************************************
655 RegDeleteValueW (HKEY hKey
,
658 UNICODE_STRING ValueName
;
663 Status
= MapDefaultKey (&KeyHandle
,
665 if (!NT_SUCCESS(Status
))
667 ErrorCode
= RtlNtStatusToDosError (Status
);
668 SetLastError (ErrorCode
);
672 RtlInitUnicodeString (&ValueName
,
673 (LPWSTR
)lpValueName
);
675 Status
= NtDeleteValueKey (KeyHandle
,
677 if (!NT_SUCCESS(Status
))
679 ErrorCode
= RtlNtStatusToDosError (Status
);
680 SetLastError (ErrorCode
);
684 return ERROR_SUCCESS
;
688 /************************************************************************
694 RegEnumKeyA (HKEY hKey
,
702 return RegEnumKeyExA (hKey
,
713 /************************************************************************
719 RegEnumKeyW (HKEY hKey
,
727 return RegEnumKeyExW (hKey
,
738 /************************************************************************
744 RegEnumKeyExA (HKEY hKey
,
751 PFILETIME lpftLastWriteTime
)
755 KEY_NODE_INFORMATION Node
;
756 KEY_BASIC_INFORMATION Basic
;
759 UNICODE_STRING StringU
;
761 LONG ErrorCode
= ERROR_SUCCESS
;
769 DPRINT("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
770 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
? *lpcbClass
: 0);
772 if ((lpClass
) && (!lpcbClass
))
774 SetLastError (ERROR_INVALID_PARAMETER
);
775 return ERROR_INVALID_PARAMETER
;
777 Status
= MapDefaultKey(&KeyHandle
,
779 if (!NT_SUCCESS(Status
))
781 ErrorCode
= RtlNtStatusToDosError (Status
);
782 SetLastError (ErrorCode
);
788 NameLength
= min (*lpcbName
- 1 , REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
798 ClassLength
= min (*lpcbClass
-1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
804 /* The class name should start at a dword boundary */
805 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
809 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
812 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
818 SetLastError (ERROR_OUTOFMEMORY
);
819 return ERROR_OUTOFMEMORY
;
822 Status
= NtEnumerateKey (KeyHandle
,
824 lpClass
== NULL
? KeyBasicInformation
: KeyNodeInformation
,
828 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
829 if (!NT_SUCCESS(Status
))
831 ErrorCode
= RtlNtStatusToDosError (Status
);
837 if (KeyInfo
->Basic
.NameLength
> NameLength
)
839 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
843 StringU
.Buffer
= KeyInfo
->Basic
.Name
;
844 StringU
.Length
= KeyInfo
->Basic
.NameLength
;
845 StringU
.MaximumLength
= KeyInfo
->Basic
.NameLength
;
850 if (KeyInfo
->Node
.NameLength
> NameLength
||
851 KeyInfo
->Node
.ClassLength
> ClassLength
)
853 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
857 StringA
.Buffer
= lpClass
;
859 StringA
.MaximumLength
= *lpcbClass
;
860 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
);
861 StringU
.Length
= KeyInfo
->Node
.ClassLength
;
862 StringU
.MaximumLength
= KeyInfo
->Node
.ClassLength
;
863 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
864 lpClass
[StringA
.Length
] = 0;
865 *lpcbClass
= StringA
.Length
;
866 StringU
.Buffer
= KeyInfo
->Node
.Name
;
867 StringU
.Length
= KeyInfo
->Node
.NameLength
;
868 StringU
.MaximumLength
= KeyInfo
->Node
.NameLength
;
871 if (ErrorCode
== ERROR_SUCCESS
)
873 StringA
.Buffer
= lpName
;
875 StringA
.MaximumLength
= *lpcbName
;
876 RtlUnicodeStringToAnsiString (&StringA
, &StringU
, FALSE
);
877 lpName
[StringA
.Length
] = 0;
878 *lpcbName
= StringA
.Length
;
879 if (lpftLastWriteTime
!= NULL
)
883 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
884 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
888 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
889 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
895 DPRINT("Key Namea0 Length %d\n", StringU
.Length
);
896 DPRINT("Key Namea1 Length %d\n", NameLength
);
897 DPRINT("Key Namea Length %d\n", *lpcbName
);
898 DPRINT("Key Namea %s\n", lpName
);
900 RtlFreeHeap (ProcessHeap
,
904 if (ErrorCode
!= ERROR_SUCCESS
)
906 SetLastError(ErrorCode
);
913 /************************************************************************
919 RegEnumKeyExW (HKEY hKey
,
926 PFILETIME lpftLastWriteTime
)
930 KEY_NODE_INFORMATION Node
;
931 KEY_BASIC_INFORMATION Basic
;
939 LONG ErrorCode
= ERROR_SUCCESS
;
942 Status
= MapDefaultKey(&KeyHandle
,
944 if (!NT_SUCCESS(Status
))
946 ErrorCode
= RtlNtStatusToDosError (Status
);
947 SetLastError (ErrorCode
);
952 NameLength
= min (*lpcbName
- 1, REG_MAX_NAME_SIZE
) * sizeof (WCHAR
);
962 ClassLength
= min (*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
968 BufferSize
= ((sizeof(KEY_NODE_INFORMATION
) + NameLength
+ 3) & ~3) + ClassLength
;
972 BufferSize
= sizeof(KEY_BASIC_INFORMATION
) + NameLength
;
974 KeyInfo
= RtlAllocateHeap (ProcessHeap
,
979 SetLastError (ERROR_OUTOFMEMORY
);
980 return ERROR_OUTOFMEMORY
;
983 Status
= NtEnumerateKey (KeyHandle
,
985 lpClass
? KeyNodeInformation
: KeyBasicInformation
,
989 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
990 if (!NT_SUCCESS(Status
))
992 ErrorCode
= RtlNtStatusToDosError (Status
);
998 if (KeyInfo
->Basic
.NameLength
> NameLength
)
1000 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1004 RtlCopyMemory (lpName
,
1005 KeyInfo
->Basic
.Name
,
1006 KeyInfo
->Basic
.NameLength
);
1007 *lpcbName
= (DWORD
)(KeyInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1008 lpName
[*lpcbName
] = 0;
1013 if (KeyInfo
->Node
.NameLength
> NameLength
||
1014 KeyInfo
->Node
.ClassLength
> ClassLength
)
1016 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1020 RtlCopyMemory (lpName
,
1022 KeyInfo
->Node
.NameLength
);
1023 *lpcbName
= KeyInfo
->Node
.NameLength
/ sizeof(WCHAR
);
1024 lpName
[*lpcbName
] = 0;
1025 RtlCopyMemory (lpClass
,
1026 (PVOID
)((ULONG_PTR
)KeyInfo
->Node
.Name
+ KeyInfo
->Node
.ClassOffset
),
1027 KeyInfo
->Node
.ClassLength
);
1028 *lpcbClass
= (DWORD
)(KeyInfo
->Node
.ClassLength
/ sizeof(WCHAR
));
1029 lpClass
[*lpcbClass
] = 0;
1032 if (ErrorCode
== ERROR_SUCCESS
&& lpftLastWriteTime
!= NULL
)
1034 if (lpClass
== NULL
)
1036 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.LowPart
;
1037 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Basic
.LastWriteTime
.u
.HighPart
;
1041 lpftLastWriteTime
->dwLowDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.LowPart
;
1042 lpftLastWriteTime
->dwHighDateTime
= KeyInfo
->Node
.LastWriteTime
.u
.HighPart
;
1047 RtlFreeHeap (ProcessHeap
,
1051 if (ErrorCode
!= ERROR_SUCCESS
)
1053 SetLastError(ErrorCode
);
1059 /************************************************************************
1065 RegEnumValueA (HKEY hKey
,
1068 LPDWORD lpcbValueName
,
1076 KEY_VALUE_FULL_INFORMATION Full
;
1077 KEY_VALUE_BASIC_INFORMATION Basic
;
1087 UNICODE_STRING StringU
;
1088 ANSI_STRING StringA
;
1091 ErrorCode
= ERROR_SUCCESS
;
1093 Status
= MapDefaultKey (&KeyHandle
,
1095 if (!NT_SUCCESS(Status
))
1097 ErrorCode
= RtlNtStatusToDosError (Status
);
1098 SetLastError (ErrorCode
);
1102 if (*lpcbValueName
> 0)
1104 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1112 DataLength
= min (*lpcbData
* sizeof(WCHAR
), REG_MAX_DATA_SIZE
);
1113 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1117 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1120 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1123 if (ValueInfo
== NULL
)
1125 SetLastError(ERROR_OUTOFMEMORY
);
1126 return ERROR_OUTOFMEMORY
;
1129 Status
= NtEnumerateValueKey (KeyHandle
,
1131 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1136 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1137 if (!NT_SUCCESS(Status
))
1139 ErrorCode
= RtlNtStatusToDosError (Status
);
1145 IsStringType
= (ValueInfo
->Full
.Type
== REG_SZ
) ||
1146 (ValueInfo
->Full
.Type
== REG_MULTI_SZ
) ||
1147 (ValueInfo
->Full
.Type
== REG_EXPAND_SZ
);
1148 if (ValueInfo
->Full
.NameLength
> NameLength
||
1149 (!IsStringType
&& ValueInfo
->Full
.DataLength
> *lpcbData
) ||
1150 ValueInfo
->Full
.DataLength
> DataLength
)
1152 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1158 StringU
.Buffer
= (PWCHAR
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
);
1159 StringU
.Length
= ValueInfo
->Full
.DataLength
;
1160 StringU
.MaximumLength
= DataLength
;
1161 StringA
.Buffer
= (PCHAR
)lpData
;
1163 StringA
.MaximumLength
= *lpcbData
;
1164 RtlUnicodeStringToAnsiString (&StringA
,
1167 *lpcbData
= StringA
.Length
;
1171 RtlCopyMemory(lpData
,
1172 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1173 ValueInfo
->Full
.DataLength
);
1174 *lpcbData
= ValueInfo
->Full
.DataLength
;
1176 StringU
.Buffer
= ValueInfo
->Full
.Name
;
1177 StringU
.Length
= ValueInfo
->Full
.NameLength
;
1178 StringU
.MaximumLength
= NameLength
;
1183 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1185 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1189 StringU
.Buffer
= ValueInfo
->Basic
.Name
;
1190 StringU
.Length
= ValueInfo
->Basic
.NameLength
;
1191 StringU
.MaximumLength
= NameLength
;
1194 if (ErrorCode
== ERROR_SUCCESS
)
1196 StringA
.Buffer
= (PCHAR
)lpValueName
;
1198 StringA
.MaximumLength
= *lpcbValueName
;
1199 RtlUnicodeStringToAnsiString (&StringA
,
1202 StringA
.Buffer
[StringA
.Length
] = 0;
1203 *lpcbValueName
= StringA
.Length
;
1206 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1210 RtlFreeHeap (ProcessHeap
,
1213 if (ErrorCode
!= ERROR_SUCCESS
)
1215 SetLastError(ErrorCode
);
1221 /************************************************************************
1227 RegEnumValueW (HKEY hKey
,
1230 LPDWORD lpcbValueName
,
1238 KEY_VALUE_FULL_INFORMATION Full
;
1239 KEY_VALUE_BASIC_INFORMATION Basic
;
1250 ErrorCode
= ERROR_SUCCESS
;
1252 Status
= MapDefaultKey (&KeyHandle
,
1254 if (!NT_SUCCESS(Status
))
1256 ErrorCode
= RtlNtStatusToDosError (Status
);
1257 SetLastError (ErrorCode
);
1261 if (*lpcbValueName
> 0)
1263 NameLength
= min (*lpcbValueName
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1271 DataLength
= min(*lpcbData
, REG_MAX_DATA_SIZE
);
1272 BufferSize
= ((sizeof(KEY_VALUE_FULL_INFORMATION
) + NameLength
+ 3) & ~3) + DataLength
;
1276 BufferSize
= sizeof(KEY_VALUE_BASIC_INFORMATION
) + NameLength
;
1278 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
1281 if (ValueInfo
== NULL
)
1283 SetLastError (ERROR_OUTOFMEMORY
);
1284 return ERROR_OUTOFMEMORY
;
1286 Status
= NtEnumerateValueKey (KeyHandle
,
1288 lpData
? KeyValueFullInformation
: KeyValueBasicInformation
,
1293 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1294 if (!NT_SUCCESS(Status
))
1296 ErrorCode
= RtlNtStatusToDosError (Status
);
1302 if (ValueInfo
->Full
.DataLength
> DataLength
||
1303 ValueInfo
->Full
.NameLength
> NameLength
)
1305 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1309 RtlCopyMemory (lpValueName
,
1310 ValueInfo
->Full
.Name
,
1311 ValueInfo
->Full
.NameLength
);
1312 *lpcbValueName
= (DWORD
)(ValueInfo
->Full
.NameLength
/ sizeof(WCHAR
));
1313 lpValueName
[*lpcbValueName
] = 0;
1314 RtlCopyMemory (lpData
,
1315 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->Full
.DataOffset
),
1316 ValueInfo
->Full
.DataLength
);
1317 *lpcbData
= (DWORD
)ValueInfo
->Full
.DataLength
;
1322 if (ValueInfo
->Basic
.NameLength
> NameLength
)
1324 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1328 RtlCopyMemory (lpValueName
,
1329 ValueInfo
->Basic
.Name
,
1330 ValueInfo
->Basic
.NameLength
);
1331 *lpcbValueName
= (DWORD
)(ValueInfo
->Basic
.NameLength
/ sizeof(WCHAR
));
1332 lpValueName
[*lpcbValueName
] = 0;
1335 if (ErrorCode
== ERROR_SUCCESS
&& lpType
!= NULL
)
1337 *lpType
= lpData
? ValueInfo
->Full
.Type
: ValueInfo
->Basic
.Type
;
1340 RtlFreeHeap (ProcessHeap
,
1343 if (ErrorCode
!= ERROR_SUCCESS
)
1345 SetLastError(ErrorCode
);
1351 /************************************************************************
1357 RegFlushKey(HKEY hKey
)
1363 if (hKey
== HKEY_PERFORMANCE_DATA
)
1365 return ERROR_SUCCESS
;
1368 Status
= MapDefaultKey (&KeyHandle
,
1370 if (!NT_SUCCESS(Status
))
1372 ErrorCode
= RtlNtStatusToDosError (Status
);
1373 SetLastError (ErrorCode
);
1377 Status
= NtFlushKey (KeyHandle
);
1378 if (!NT_SUCCESS(Status
))
1380 ErrorCode
= RtlNtStatusToDosError (Status
);
1381 SetLastError (ErrorCode
);
1385 return ERROR_SUCCESS
;
1389 /************************************************************************
1395 RegGetKeySecurity (HKEY hKey
,
1396 SECURITY_INFORMATION SecurityInformation
,
1397 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1398 LPDWORD lpcbSecurityDescriptor
)
1405 if (hKey
= HKEY_PERFORMANCE_DATA
)
1407 return ERROR_INVALID_HANDLE
;
1410 Status
= MapDefaultKey (&KeyHandle
,
1412 if (!NT_SUCCESS(Status
))
1414 ErrorCode
= RtlNtStatusToDosError (Status
);
1415 SetLastError (ErrorCode
);
1419 Status
= NtQuerySecurityObject ()
1420 if (!NT_SUCCESS(Status
))
1422 ErrorCode
= RtlNtStatusToDosError (Status
);
1423 SetLastError (ErrorCode
);
1427 return ERROR_SUCCESS
;
1431 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1432 return ERROR_CALL_NOT_IMPLEMENTED
;
1436 /************************************************************************
1442 RegLoadKeyA (HKEY hKey
,
1446 UNICODE_STRING FileName
;
1447 UNICODE_STRING KeyName
;
1450 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
1452 RtlCreateUnicodeStringFromAsciiz (&FileName
,
1455 ErrorCode
= RegLoadKeyW (hKey
,
1459 RtlFreeUnicodeString (&FileName
);
1460 RtlFreeUnicodeString (&KeyName
);
1466 /************************************************************************
1472 RegLoadKeyW (HKEY hKey
,
1476 OBJECT_ATTRIBUTES FileObjectAttributes
;
1477 OBJECT_ATTRIBUTES KeyObjectAttributes
;
1478 UNICODE_STRING FileName
;
1479 UNICODE_STRING KeyName
;
1484 if (hKey
== HKEY_PERFORMANCE_DATA
)
1486 return ERROR_INVALID_HANDLE
;
1489 Status
= MapDefaultKey (&KeyHandle
,
1491 if (!NT_SUCCESS(Status
))
1493 ErrorCode
= RtlNtStatusToDosError (Status
);
1494 SetLastError (ErrorCode
);
1498 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
1503 SetLastError (ERROR_BAD_PATHNAME
);
1504 return ERROR_BAD_PATHNAME
;
1507 InitializeObjectAttributes (&FileObjectAttributes
,
1509 OBJ_CASE_INSENSITIVE
,
1513 RtlInitUnicodeString (&KeyName
,
1516 InitializeObjectAttributes (&KeyObjectAttributes
,
1518 OBJ_CASE_INSENSITIVE
,
1522 Status
= NtLoadKey (&KeyObjectAttributes
,
1523 &FileObjectAttributes
);
1525 RtlFreeUnicodeString (&FileName
);
1527 if (!NT_SUCCESS(Status
))
1529 ErrorCode
= RtlNtStatusToDosError (Status
);
1530 SetLastError (ErrorCode
);
1534 return ERROR_SUCCESS
;
1538 /************************************************************************
1539 * RegNotifyChangeKeyValue
1544 RegNotifyChangeKeyValue (HKEY hKey
,
1546 DWORD dwNotifyFilter
,
1550 IO_STATUS_BLOCK IoStatusBlock
;
1554 if (hKey
== HKEY_PERFORMANCE_DATA
)
1556 return ERROR_INVALID_HANDLE
;
1559 if (fAsynchronous
== TRUE
&& hEvent
== NULL
)
1561 return ERROR_INVALID_PARAMETER
;
1564 Status
= MapDefaultKey (&KeyHandle
,
1566 if (!NT_SUCCESS(Status
))
1568 return RtlNtStatusToDosError (Status
);
1571 /* FIXME: Remote key handles must fail */
1573 Status
= NtNotifyChangeKey (KeyHandle
,
1583 if (!NT_SUCCESS(Status
) && Status
!= STATUS_TIMEOUT
)
1585 return RtlNtStatusToDosError (Status
);
1588 return ERROR_SUCCESS
;
1593 /************************************************************************
1599 RegOpenKeyA (HKEY hKey
,
1603 OBJECT_ATTRIBUTES ObjectAttributes
;
1604 UNICODE_STRING SubKeyString
;
1609 Status
= MapDefaultKey (&KeyHandle
,
1611 if (!NT_SUCCESS(Status
))
1613 ErrorCode
= RtlNtStatusToDosError (Status
);
1614 SetLastError (ErrorCode
);
1618 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1620 InitializeObjectAttributes (&ObjectAttributes
,
1622 OBJ_CASE_INSENSITIVE
,
1625 Status
= NtOpenKey (phkResult
,
1628 RtlFreeUnicodeString (&SubKeyString
);
1629 if (!NT_SUCCESS(Status
))
1631 ErrorCode
= RtlNtStatusToDosError (Status
);
1632 SetLastError (ErrorCode
);
1636 return ERROR_SUCCESS
;
1640 /************************************************************************
1649 RegOpenKeyW (HKEY hKey
,
1653 OBJECT_ATTRIBUTES ObjectAttributes
;
1654 UNICODE_STRING SubKeyString
;
1659 Status
= MapDefaultKey (&KeyHandle
,
1661 if (!NT_SUCCESS(Status
))
1663 ErrorCode
= RtlNtStatusToDosError (Status
);
1664 SetLastError (ErrorCode
);
1668 RtlInitUnicodeString (&SubKeyString
,
1670 InitializeObjectAttributes (&ObjectAttributes
,
1672 OBJ_CASE_INSENSITIVE
,
1675 Status
= NtOpenKey (phkResult
,
1678 if (!NT_SUCCESS(Status
))
1680 ErrorCode
= RtlNtStatusToDosError (Status
);
1681 SetLastError(ErrorCode
);
1685 return ERROR_SUCCESS
;
1689 /************************************************************************
1695 RegOpenKeyExA (HKEY hKey
,
1701 OBJECT_ATTRIBUTES ObjectAttributes
;
1702 UNICODE_STRING SubKeyString
;
1707 Status
= MapDefaultKey (&KeyHandle
,
1709 if (!NT_SUCCESS(Status
))
1711 ErrorCode
= RtlNtStatusToDosError (Status
);
1712 SetLastError (ErrorCode
);
1716 RtlCreateUnicodeStringFromAsciiz (&SubKeyString
,
1718 InitializeObjectAttributes (&ObjectAttributes
,
1720 OBJ_CASE_INSENSITIVE
,
1723 Status
= NtOpenKey (phkResult
,
1726 RtlFreeUnicodeString (&SubKeyString
);
1727 if (!NT_SUCCESS(Status
))
1729 ErrorCode
= RtlNtStatusToDosError (Status
);
1730 SetLastError (ErrorCode
);
1734 return ERROR_SUCCESS
;
1738 /************************************************************************
1744 RegOpenKeyExW (HKEY hKey
,
1750 OBJECT_ATTRIBUTES ObjectAttributes
;
1751 UNICODE_STRING SubKeyString
;
1756 Status
= MapDefaultKey (&KeyHandle
,
1758 if (!NT_SUCCESS(Status
))
1760 ErrorCode
= RtlNtStatusToDosError (Status
);
1761 SetLastError (ErrorCode
);
1765 if (lpSubKey
!= NULL
)
1767 RtlInitUnicodeString (&SubKeyString
,
1772 RtlInitUnicodeString (&SubKeyString
,
1775 InitializeObjectAttributes (&ObjectAttributes
,
1777 OBJ_CASE_INSENSITIVE
,
1780 Status
= NtOpenKey (phkResult
,
1783 if (!NT_SUCCESS(Status
))
1785 ErrorCode
= RtlNtStatusToDosError (Status
);
1786 SetLastError (ErrorCode
);
1790 return ERROR_SUCCESS
;
1794 /************************************************************************
1800 RegQueryInfoKeyA (HKEY hKey
,
1805 LPDWORD lpcbMaxSubKeyLen
,
1806 LPDWORD lpcbMaxClassLen
,
1808 LPDWORD lpcbMaxValueNameLen
,
1809 LPDWORD lpcbMaxValueLen
,
1810 LPDWORD lpcbSecurityDescriptor
,
1811 PFILETIME lpftLastWriteTime
)
1813 WCHAR ClassName
[MAX_PATH
];
1814 UNICODE_STRING UnicodeString
;
1815 ANSI_STRING AnsiString
;
1818 RtlInitUnicodeString (&UnicodeString
,
1820 if (lpClass
!= NULL
)
1822 UnicodeString
.Buffer
= &ClassName
[0];
1823 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1824 AnsiString
.MaximumLength
= *lpcbClass
;
1827 ErrorCode
= RegQueryInfoKeyW (hKey
,
1828 UnicodeString
.Buffer
,
1835 lpcbMaxValueNameLen
,
1837 lpcbSecurityDescriptor
,
1839 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
!= NULL
))
1841 AnsiString
.Buffer
= lpClass
;
1842 AnsiString
.Length
= 0;
1843 UnicodeString
.Length
= *lpcbClass
* sizeof(WCHAR
);
1844 RtlUnicodeStringToAnsiString (&AnsiString
,
1847 *lpcbClass
= AnsiString
.Length
;
1848 lpClass
[AnsiString
.Length
] = 0;
1855 /************************************************************************
1861 RegQueryInfoKeyW (HKEY hKey
,
1866 LPDWORD lpcbMaxSubKeyLen
,
1867 LPDWORD lpcbMaxClassLen
,
1869 LPDWORD lpcbMaxValueNameLen
,
1870 LPDWORD lpcbMaxValueLen
,
1871 LPDWORD lpcbSecurityDescriptor
,
1872 PFILETIME lpftLastWriteTime
)
1874 KEY_FULL_INFORMATION FullInfoBuffer
;
1875 PKEY_FULL_INFORMATION FullInfo
;
1880 LONG ErrorCode
= ERROR_SUCCESS
;
1883 if ((lpClass
) && (!lpcbClass
))
1885 SetLastError(ERROR_INVALID_PARAMETER
);
1886 return ERROR_INVALID_PARAMETER
;
1889 Status
= MapDefaultKey (&KeyHandle
,
1891 if (!NT_SUCCESS(Status
))
1893 ErrorCode
= RtlNtStatusToDosError (Status
);
1894 SetLastError (ErrorCode
);
1898 if (lpClass
!= NULL
)
1902 ClassLength
= min(*lpcbClass
- 1, REG_MAX_NAME_SIZE
) * sizeof(WCHAR
);
1908 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + ((ClassLength
+ 3) & ~3);
1909 FullInfo
= RtlAllocateHeap (ProcessHeap
,
1912 if (FullInfo
== NULL
)
1914 SetLastError (ERROR_OUTOFMEMORY
);
1915 return ERROR_OUTOFMEMORY
;
1917 FullInfo
->ClassLength
= ClassLength
;
1921 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
1922 FullInfo
= &FullInfoBuffer
;
1923 FullInfo
->ClassLength
= 0;
1925 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
1927 Status
= NtQueryKey (KeyHandle
,
1932 DPRINT("NtQueryKey() returned status 0x%X\n", Status
);
1933 if (!NT_SUCCESS(Status
))
1935 ErrorCode
= RtlNtStatusToDosError (Status
);
1939 DPRINT("SubKeys %d\n", FullInfo
->SubKeys
);
1940 if (lpcSubKeys
!= NULL
)
1942 *lpcSubKeys
= FullInfo
->SubKeys
;
1945 DPRINT("MaxNameLen %lu\n", FullInfo
->MaxNameLen
);
1946 if (lpcbMaxSubKeyLen
!= NULL
)
1948 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
/ sizeof(WCHAR
) + 1;
1951 DPRINT("MaxClassLen %lu\n", FullInfo
->MaxClassLen
);
1952 if (lpcbMaxClassLen
!= NULL
)
1954 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
/ sizeof(WCHAR
) + 1;
1957 DPRINT("Values %lu\n", FullInfo
->Values
);
1960 *lpcValues
= FullInfo
->Values
;
1963 DPRINT("MaxValueNameLen %lu\n", FullInfo
->MaxValueNameLen
);
1964 if (lpcbMaxValueNameLen
)
1966 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
/ sizeof(WCHAR
) + 1;
1969 DPRINT("MaxValueDataLen %lu\n", FullInfo
->MaxValueDataLen
);
1970 if (lpcbMaxValueLen
)
1972 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
1975 if (lpcbSecurityDescriptor
)
1977 *lpcbSecurityDescriptor
= 0;
1981 if (lpftLastWriteTime
!= NULL
)
1983 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
1984 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
1987 if (lpClass
!= NULL
)
1989 if (FullInfo
->ClassLength
> ClassLength
)
1991 ErrorCode
= ERROR_BUFFER_OVERFLOW
;
1995 RtlCopyMemory (lpClass
,
1997 FullInfo
->ClassLength
);
1998 *lpcbClass
= FullInfo
->ClassLength
/ sizeof(WCHAR
);
1999 lpClass
[*lpcbClass
] = 0;
2003 if (lpClass
!= NULL
)
2005 RtlFreeHeap (ProcessHeap
,
2009 if (ErrorCode
!= ERROR_SUCCESS
)
2011 SetLastError(ErrorCode
);
2018 /************************************************************************
2019 * RegQueryMultipleValuesA
2024 RegQueryMultipleValuesA (HKEY hKey
,
2031 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2032 return ERROR_CALL_NOT_IMPLEMENTED
;
2036 /************************************************************************
2037 * RegQueryMultipleValuesW
2042 RegQueryMultipleValuesW (HKEY hKey
,
2049 DWORD maxBytes
= *ldwTotsize
;
2051 LPSTR bufptr
= (LPSTR
)lpValueBuf
;
2053 if ( maxBytes
>= (1024*1024) )
2054 return ERROR_TRANSFER_TOO_LONG
;
2058 //TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hKey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
2060 for(i
=0; i
< num_vals
; ++i
)
2062 val_list
[i
].ve_valuelen
=0;
2063 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, NULL
, NULL
, &val_list
[i
].ve_valuelen
);
2064 if(status
!= ERROR_SUCCESS
)
2069 if(lpValueBuf
!= NULL
&& *ldwTotsize
+ val_list
[i
].ve_valuelen
<= maxBytes
)
2071 status
= RegQueryValueExW(hKey
, val_list
[i
].ve_valuename
, NULL
, &val_list
[i
].ve_type
,
2072 bufptr
, &val_list
[i
].ve_valuelen
);
2073 if(status
!= ERROR_SUCCESS
)
2078 val_list
[i
].ve_valueptr
= (DWORD_PTR
)bufptr
;
2080 bufptr
+= val_list
[i
].ve_valuelen
;
2083 *ldwTotsize
+= val_list
[i
].ve_valuelen
;
2085 return lpValueBuf
!= NULL
&& *ldwTotsize
<= maxBytes
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
2089 /************************************************************************
2095 RegQueryValueExW (HKEY hKey
,
2096 LPCWSTR lpValueName
,
2102 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
2103 UNICODE_STRING ValueName
;
2105 LONG ErrorCode
= ERROR_SUCCESS
;
2109 ULONG MaxCopy
= lpcbData
? *lpcbData
: 0;
2111 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
2112 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
2114 Status
= MapDefaultKey (&KeyHandle
,
2116 if (!NT_SUCCESS(Status
))
2118 ErrorCode
= RtlNtStatusToDosError (Status
);
2119 SetLastError (ErrorCode
);
2123 if (lpData
!= NULL
&& lpcbData
== NULL
)
2125 SetLastError (ERROR_INVALID_PARAMETER
);
2126 return ERROR_INVALID_PARAMETER
;
2129 RtlInitUnicodeString (&ValueName
,
2131 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + MaxCopy
;
2132 ValueInfo
= RtlAllocateHeap (ProcessHeap
,
2135 if (ValueInfo
== NULL
)
2137 SetLastError(ERROR_OUTOFMEMORY
);
2138 return ERROR_OUTOFMEMORY
;
2141 Status
= NtQueryValueKey (hKey
,
2143 KeyValuePartialInformation
,
2147 DPRINT("Status 0x%X\n", Status
);
2148 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2150 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
2152 ErrorCode
= lpData
? ERROR_MORE_DATA
: ERROR_SUCCESS
;
2154 else if (!NT_SUCCESS(Status
))
2156 ErrorCode
= RtlNtStatusToDosError (Status
);
2157 SetLastError (ErrorCode
);
2163 *lpType
= ValueInfo
->Type
;
2166 if (NT_SUCCESS(Status
))
2167 RtlMoveMemory (lpData
,
2169 min(ValueInfo
->DataLength
,MaxCopy
));
2171 if ((ValueInfo
->Type
== REG_SZ
) ||
2172 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
2173 (ValueInfo
->Type
== REG_EXPAND_SZ
))
2175 if (MaxCopy
> ValueInfo
->DataLength
/ sizeof(WCHAR
))
2176 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
2179 *lpcbData
= (ResultSize
- sizeof(*ValueInfo
)) / sizeof(WCHAR
);
2180 DPRINT("(string) Returning Size: %d\n", *lpcbData
);
2185 *lpcbData
= ResultSize
- sizeof(*ValueInfo
);
2186 DPRINT("(other) Returning Size: %d\n", *lpcbData
);
2189 DPRINT("Type %d Size %d\n", ValueInfo
->Type
, ValueInfo
->DataLength
);
2191 RtlFreeHeap (ProcessHeap
,
2199 /************************************************************************
2214 UNICODE_STRING ValueName
;
2215 UNICODE_STRING ValueData
;
2216 ANSI_STRING AnsiString
;
2221 if ((lpData
) && (!lpcbData
))
2223 SetLastError(ERROR_INVALID_PARAMETER
);
2224 return ERROR_INVALID_PARAMETER
;
2229 ValueData
.Length
= *lpcbData
* sizeof(WCHAR
);
2230 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2231 ValueData
.Buffer
= RtlAllocateHeap(
2234 ValueData
.MaximumLength
);
2235 if (!ValueData
.Buffer
)
2237 SetLastError(ERROR_OUTOFMEMORY
);
2238 return ERROR_OUTOFMEMORY
;
2243 ValueData
.Buffer
= NULL
;
2244 ValueData
.Length
= 0;
2245 ValueData
.MaximumLength
= 0;
2248 RtlCreateUnicodeStringFromAsciiz(&ValueName
, (LPSTR
)lpValueName
);
2250 /* Convert length from USHORT to DWORD */
2251 Length
= ValueData
.Length
/ sizeof(WCHAR
);
2252 ErrorCode
= RegQueryValueExW
2257 (LPBYTE
)ValueData
.Buffer
,
2259 if (lpType
) *lpType
= Type
;
2260 if ((ErrorCode
== ERROR_SUCCESS
) && (ValueData
.Buffer
!= NULL
))
2262 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
2264 RtlInitAnsiString(&AnsiString
, NULL
);
2265 AnsiString
.Buffer
= lpData
;
2266 AnsiString
.MaximumLength
= *lpcbData
;
2267 ValueData
.Length
= Length
* sizeof(WCHAR
);
2268 ValueData
.MaximumLength
= ValueData
.Length
+ sizeof(WCHAR
);
2269 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
2271 RtlMoveMemory(lpData
, ValueData
.Buffer
,
2272 min(*lpcbData
,Length
));
2278 if (ValueData
.Buffer
)
2280 RtlFreeHeap(ProcessHeap
, 0, ValueData
.Buffer
);
2287 /************************************************************************
2293 RegQueryValueA (HKEY hKey
,
2298 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2299 UNICODE_STRING SubKeyName
;
2300 UNICODE_STRING Value
;
2301 ANSI_STRING AnsiString
;
2305 if (lpValue
!= NULL
&&
2308 SetLastError(ERROR_INVALID_PARAMETER
);
2309 return ERROR_INVALID_PARAMETER
;
2312 RtlInitUnicodeString (&SubKeyName
,
2314 RtlInitUnicodeString (&Value
,
2316 if (lpSubKey
!= NULL
&&
2317 strlen(lpSubKey
) != 0)
2319 RtlInitAnsiString (&AnsiString
,
2321 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2322 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2323 RtlAnsiStringToUnicodeString (&SubKeyName
,
2328 if (lpValue
!= NULL
)
2330 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
2331 Value
.MaximumLength
= ValueSize
;
2332 Value
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2335 if (Value
.Buffer
== NULL
)
2337 SetLastError(ERROR_OUTOFMEMORY
);
2338 return ERROR_OUTOFMEMORY
;
2346 ErrorCode
= RegQueryValueW (hKey
,
2347 (LPCWSTR
)SubKeyName
.Buffer
,
2350 if (ErrorCode
== ERROR_SUCCESS
)
2352 Value
.Length
= ValueSize
;
2353 RtlInitAnsiString (&AnsiString
,
2355 AnsiString
.Buffer
= lpValue
;
2356 AnsiString
.MaximumLength
= *lpcbValue
;
2357 RtlUnicodeStringToAnsiString (&AnsiString
,
2362 *lpcbValue
= ValueSize
;
2363 if (Value
.Buffer
!= NULL
)
2365 RtlFreeHeap (ProcessHeap
,
2374 /************************************************************************
2380 RegQueryValueW (HKEY hKey
,
2385 OBJECT_ATTRIBUTES ObjectAttributes
;
2386 UNICODE_STRING SubKeyString
;
2393 Status
= MapDefaultKey (&KeyHandle
,
2395 if (!NT_SUCCESS(Status
))
2397 ErrorCode
= RtlNtStatusToDosError (Status
);
2398 SetLastError (ErrorCode
);
2402 if (lpSubKey
!= NULL
&&
2403 wcslen(lpSubKey
) != 0)
2405 RtlInitUnicodeString (&SubKeyString
,
2407 InitializeObjectAttributes (&ObjectAttributes
,
2409 OBJ_CASE_INSENSITIVE
,
2412 Status
= NtOpenKey (&RealKey
,
2415 if (!NT_SUCCESS(Status
))
2417 ErrorCode
= RtlNtStatusToDosError (Status
);
2418 SetLastError (ErrorCode
);
2421 CloseRealKey
= TRUE
;
2426 CloseRealKey
= FALSE
;
2429 ErrorCode
= RegQueryValueExW (RealKey
,
2434 (LPDWORD
)lpcbValue
);
2444 /************************************************************************
2450 RegReplaceKeyA (HKEY hKey
,
2455 UNICODE_STRING lpSubKeyW
;
2456 UNICODE_STRING lpNewFileW
;
2457 UNICODE_STRING lpOldFileW
;
2460 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW
, (PCSZ
)lpSubKey
);
2461 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW
, (PCSZ
)lpOldFile
);
2462 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW
, (PCSZ
)lpNewFile
);
2463 ret
= RegReplaceKeyW( hKey
, lpSubKeyW
.Buffer
, lpNewFileW
.Buffer
, lpOldFileW
.Buffer
);
2464 RtlFreeUnicodeString( &lpOldFileW
);
2465 RtlFreeUnicodeString( &lpNewFileW
);
2466 RtlFreeUnicodeString( &lpSubKeyW
);
2471 /************************************************************************
2477 RegReplaceKeyW (HKEY hKey
,
2483 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2484 return ERROR_CALL_NOT_IMPLEMENTED
;
2488 /************************************************************************
2494 RegRestoreKeyA (HKEY hKey
,
2498 UNICODE_STRING lpFileW
;
2501 RtlCreateUnicodeStringFromAsciiz( &lpFileW
, (PCSZ
)lpFile
);
2502 ret
= RegRestoreKeyW( hKey
, lpFileW
.Buffer
, dwFlags
);
2503 RtlFreeUnicodeString( &lpFileW
);
2508 /************************************************************************
2514 RegRestoreKeyW (HKEY hKey
,
2519 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2520 return ERROR_CALL_NOT_IMPLEMENTED
;
2524 /************************************************************************
2530 RegSaveKeyA(HKEY hKey
,
2532 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2534 UNICODE_STRING FileName
;
2537 RtlCreateUnicodeStringFromAsciiz (&FileName
,
2539 ErrorCode
= RegSaveKeyW (hKey
,
2541 lpSecurityAttributes
);
2542 RtlFreeUnicodeString (&FileName
);
2548 /************************************************************************
2554 RegSaveKeyW (HKEY hKey
,
2556 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2558 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2559 OBJECT_ATTRIBUTES ObjectAttributes
;
2560 UNICODE_STRING NtName
;
2561 IO_STATUS_BLOCK IoStatusBlock
;
2567 Status
= MapDefaultKey (&KeyHandle
,
2569 if (!NT_SUCCESS(Status
))
2571 ErrorCode
= RtlNtStatusToDosError (Status
);
2572 SetLastError (ErrorCode
);
2576 if (!RtlDosPathNameToNtPathName_U ((LPWSTR
)lpFile
,
2581 SetLastError (ERROR_INVALID_PARAMETER
);
2582 return ERROR_INVALID_PARAMETER
;
2585 if (lpSecurityAttributes
!= NULL
)
2587 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2590 InitializeObjectAttributes (&ObjectAttributes
,
2592 OBJ_CASE_INSENSITIVE
,
2594 SecurityDescriptor
);
2595 Status
= NtCreateFile (&FileHandle
,
2596 GENERIC_WRITE
| SYNCHRONIZE
,
2600 FILE_ATTRIBUTE_NORMAL
,
2603 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2606 RtlFreeUnicodeString (&NtName
);
2607 if (!NT_SUCCESS(Status
))
2609 ErrorCode
= RtlNtStatusToDosError (Status
);
2610 SetLastError (ErrorCode
);
2614 Status
= NtSaveKey (KeyHandle
,
2616 NtClose (FileHandle
);
2617 if (!NT_SUCCESS(Status
))
2619 ErrorCode
= RtlNtStatusToDosError (Status
);
2620 SetLastError (ErrorCode
);
2624 return ERROR_SUCCESS
;
2628 /************************************************************************
2634 RegSetKeySecurity (HKEY hKey
,
2635 SECURITY_INFORMATION SecurityInformation
,
2636 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
2642 if (hKey
== HKEY_PERFORMANCE_DATA
)
2643 return ERROR_INVALID_HANDLE
;
2645 Status
= MapDefaultKey (&KeyHandle
,
2647 if (!NT_SUCCESS(Status
))
2649 ErrorCode
= RtlNtStatusToDosError (Status
);
2650 SetLastError (ErrorCode
);
2654 Status
= NtSetSecurityObject (KeyHandle
,
2655 SecurityInformation
,
2656 pSecurityDescriptor
);
2657 if (!NT_SUCCESS(Status
))
2659 ErrorCode
= RtlNtStatusToDosError (Status
);
2660 SetLastError (ErrorCode
);
2664 return ERROR_SUCCESS
;
2668 /************************************************************************
2674 RegSetValueExA (HKEY hKey
,
2681 UNICODE_STRING ValueName
;
2683 ANSI_STRING AnsiString
;
2684 UNICODE_STRING Data
;
2691 SetLastError (ERROR_INVALID_PARAMETER
);
2692 return ERROR_INVALID_PARAMETER
;
2695 if (lpValueName
!= NULL
&&
2696 strlen(lpValueName
) != 0)
2698 RtlCreateUnicodeStringFromAsciiz (&ValueName
,
2699 (LPSTR
)lpValueName
);
2700 pValueName
= (LPWSTR
)ValueName
.Buffer
;
2707 if ((dwType
== REG_SZ
) ||
2708 (dwType
== REG_MULTI_SZ
) ||
2709 (dwType
== REG_EXPAND_SZ
))
2711 RtlInitAnsiString (&AnsiString
,
2713 AnsiString
.Buffer
= (LPSTR
)lpData
;
2714 AnsiString
.Length
= cbData
;
2715 AnsiString
.MaximumLength
= cbData
;
2716 RtlAnsiStringToUnicodeString (&Data
,
2719 pData
= (LPBYTE
)Data
.Buffer
;
2720 DataSize
= cbData
* sizeof(WCHAR
);
2724 RtlInitUnicodeString (&Data
,
2726 pData
= (LPBYTE
)lpData
;
2730 ErrorCode
= RegSetValueExW (hKey
,
2736 if (pValueName
!= NULL
)
2738 RtlFreeHeap (ProcessHeap
,
2743 if (Data
.Buffer
!= NULL
)
2745 RtlFreeHeap (ProcessHeap
,
2754 /************************************************************************
2760 RegSetValueExW (HKEY hKey
,
2761 LPCWSTR lpValueName
,
2767 UNICODE_STRING ValueName
;
2768 PUNICODE_STRING pValueName
;
2773 Status
= MapDefaultKey (&KeyHandle
,
2775 if (!NT_SUCCESS(Status
))
2777 ErrorCode
= RtlNtStatusToDosError (Status
);
2778 SetLastError (ErrorCode
);
2782 if (lpValueName
!= NULL
)
2784 RtlInitUnicodeString (&ValueName
,
2789 RtlInitUnicodeString (&ValueName
, L
"");
2791 pValueName
= &ValueName
;
2793 Status
= NtSetValueKey (KeyHandle
,
2799 if (!NT_SUCCESS(Status
))
2801 ErrorCode
= RtlNtStatusToDosError (Status
);
2802 SetLastError (ErrorCode
);
2806 return ERROR_SUCCESS
;
2810 /************************************************************************
2816 RegSetValueA (HKEY hKey
,
2822 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2823 UNICODE_STRING SubKeyName
;
2824 UNICODE_STRING Data
;
2825 ANSI_STRING AnsiString
;
2831 SetLastError (ERROR_INVALID_PARAMETER
);
2832 return ERROR_INVALID_PARAMETER
;
2835 RtlInitUnicodeString (&SubKeyName
, NULL
);
2836 RtlInitUnicodeString (&Data
, NULL
);
2837 if (lpSubKey
!= NULL
&& (strlen(lpSubKey
) != 0))
2839 RtlInitAnsiString (&AnsiString
, (LPSTR
)lpSubKey
);
2840 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2841 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2842 RtlAnsiStringToUnicodeString (&SubKeyName
, &AnsiString
, FALSE
);
2845 DataSize
= cbData
* sizeof(WCHAR
);
2846 Data
.MaximumLength
= DataSize
;
2847 Data
.Buffer
= RtlAllocateHeap (ProcessHeap
,
2850 if (Data
.Buffer
== NULL
)
2852 SetLastError (ERROR_OUTOFMEMORY
);
2853 return ERROR_OUTOFMEMORY
;
2856 ErrorCode
= RegSetValueW (hKey
,
2857 (LPCWSTR
)SubKeyName
.Buffer
,
2861 RtlFreeHeap (ProcessHeap
,
2869 /************************************************************************
2875 RegSetValueW (HKEY hKey
,
2881 OBJECT_ATTRIBUTES ObjectAttributes
;
2882 UNICODE_STRING SubKeyString
;
2889 Status
= MapDefaultKey (&KeyHandle
,
2891 if (!NT_SUCCESS(Status
))
2893 ErrorCode
= RtlNtStatusToDosError (Status
);
2894 SetLastError (ErrorCode
);
2898 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
2900 RtlInitUnicodeString (&SubKeyString
,
2902 InitializeObjectAttributes (&ObjectAttributes
,
2904 OBJ_CASE_INSENSITIVE
,
2907 Status
= NtOpenKey (&RealKey
,
2910 if (!NT_SUCCESS(Status
))
2912 ErrorCode
= RtlNtStatusToDosError (Status
);
2913 SetLastError (ErrorCode
);
2916 CloseRealKey
= TRUE
;
2921 CloseRealKey
= FALSE
;
2924 ErrorCode
= RegSetValueExW (RealKey
,
2930 if (CloseRealKey
== TRUE
)
2939 /************************************************************************
2945 RegUnLoadKeyA (HKEY hKey
,
2948 UNICODE_STRING KeyName
;
2951 RtlCreateUnicodeStringFromAsciiz (&KeyName
,
2954 ErrorCode
= RegUnLoadKeyW (hKey
,
2957 RtlFreeUnicodeString (&KeyName
);
2963 /************************************************************************
2969 RegUnLoadKeyW (HKEY hKey
,
2972 OBJECT_ATTRIBUTES ObjectAttributes
;
2973 UNICODE_STRING KeyName
;
2978 if (hKey
== HKEY_PERFORMANCE_DATA
)
2979 return ERROR_INVALID_HANDLE
;
2981 Status
= MapDefaultKey (&KeyHandle
, hKey
);
2982 if (!NT_SUCCESS(Status
))
2984 ErrorCode
= RtlNtStatusToDosError (Status
);
2985 SetLastError (ErrorCode
);
2989 RtlInitUnicodeString (&KeyName
,
2992 InitializeObjectAttributes (&ObjectAttributes
,
2994 OBJ_CASE_INSENSITIVE
,
2998 Status
= NtUnloadKey (&ObjectAttributes
);
3000 if (!NT_SUCCESS(Status
))
3002 ErrorCode
= RtlNtStatusToDosError (Status
);
3003 SetLastError (ErrorCode
);
3007 return ERROR_SUCCESS
;