1 /* $Id: reg.c,v 1.18 2002/11/02 13:55:06 robd 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)
12 #include <ddk/ntddk.h>
13 #include <ntdll/rtl.h>
20 #define CHECK_STATUS \
22 if (!NT_SUCCESS(Status)) \
24 LONG _ErrorCode = RtlNtStatusToDosError(Status); \
25 SetLastError(_ErrorCode); \
30 /* GLOBALS *******************************************************************/
32 #define MAX_DEFAULT_HANDLES 6
34 static CRITICAL_SECTION HandleTableCS
;
35 static HANDLE DefaultHandleTable
[MAX_DEFAULT_HANDLES
];
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 inline RegiTerminateWideString(LPWSTR String
, DWORD Length
)
53 LPWSTR AfterString
= String
+ Length
;
57 /************************************************************************
58 * RegInitDefaultHandles
64 DPRINT("RegInitialize()\n");
66 RtlZeroMemory (DefaultHandleTable
,
67 MAX_DEFAULT_HANDLES
* sizeof(HANDLE
));
69 RtlInitializeCriticalSection(&HandleTableCS
);
74 /************************************************************************
80 DPRINT("RegCleanup()\n");
83 RtlDeleteCriticalSection(&HandleTableCS
);
89 MapDefaultKey(PHKEY RealKey
,
94 NTSTATUS Status
= STATUS_SUCCESS
;
96 DPRINT("MapDefaultKey (Key %x)\n", Key
);
98 if (((ULONG
)Key
& 0xF0000000) != 0x80000000)
101 return STATUS_SUCCESS
;
104 /* Handle special cases here */
105 Index
= (ULONG
)Key
& 0x0FFFFFFF;
107 if (Index
>= MAX_DEFAULT_HANDLES
)
108 return STATUS_INVALID_PARAMETER
;
110 RtlEnterCriticalSection(&HandleTableCS
);
112 Handle
= &DefaultHandleTable
[Index
];
115 /* create/open the default handle */
118 case 0: /* HKEY_CLASSES_ROOT */
119 Status
= OpenClassesRootKey(Handle
);
122 case 1: /* HKEY_CURRENT_USER */
123 Status
= RtlOpenCurrentUser(KEY_ALL_ACCESS
,
127 case 2: /* HKEY_LOCAL_MACHINE */
128 Status
= OpenLocalMachineKey(Handle
);
131 case 3: /* HKEY_USERS */
132 Status
= OpenUsersKey(Handle
);
135 case 4: /* HKEY_PERFORMANCE_DATA */
136 Status
= OpenPerformanceDataKey(Handle
);
139 case 5: /* HKEY_CURRENT_CONFIG */
140 Status
= OpenCurrentConfigKey(Handle
);
144 DPRINT("MapDefaultHandle() no handle creator\n");
145 Status
= STATUS_INVALID_PARAMETER
;
149 RtlLeaveCriticalSection(&HandleTableCS
);
151 if (NT_SUCCESS(Status
))
153 *RealKey
= (HKEY
)*Handle
;
161 CloseDefaultKeys(VOID
)
165 RtlEnterCriticalSection(&HandleTableCS
);
167 for (i
= 0; i
< MAX_DEFAULT_HANDLES
; i
++)
169 if (DefaultHandleTable
[i
] != NULL
)
171 NtClose (DefaultHandleTable
[i
]);
172 DefaultHandleTable
[i
] = NULL
;
176 RtlLeaveCriticalSection(&HandleTableCS
);
181 OpenClassesRootKey(PHANDLE KeyHandle
)
183 OBJECT_ATTRIBUTES Attributes
;
184 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine\\Software\\CLASSES");
186 DPRINT("OpenClassesRootKey()\n");
188 InitializeObjectAttributes(&Attributes
,
190 OBJ_CASE_INSENSITIVE
,
194 return(NtOpenKey(KeyHandle
,
201 OpenLocalMachineKey(PHANDLE KeyHandle
)
203 OBJECT_ATTRIBUTES Attributes
;
204 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine");
206 DPRINT("OpenLocalMachineKey()\n");
208 InitializeObjectAttributes(&Attributes
,
210 OBJ_CASE_INSENSITIVE
,
214 return(NtOpenKey(KeyHandle
,
221 OpenUsersKey(PHANDLE KeyHandle
)
223 OBJECT_ATTRIBUTES Attributes
;
224 UNICODE_STRING KeyName
= UNICODE_STRING_INITIALIZER(L
"\\Registry\\User");
226 DPRINT("OpenUsersKey()\n");
228 InitializeObjectAttributes(&Attributes
,
230 OBJ_CASE_INSENSITIVE
,
234 return(NtOpenKey(KeyHandle
,
241 OpenCurrentConfigKey(PHANDLE KeyHandle
)
243 OBJECT_ATTRIBUTES Attributes
;
244 UNICODE_STRING KeyName
=
245 UNICODE_STRING_INITIALIZER(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current");
247 DPRINT("OpenCurrentConfigKey()\n");
249 InitializeObjectAttributes(&Attributes
,
251 OBJ_CASE_INSENSITIVE
,
255 return(NtOpenKey(KeyHandle
,
260 /************************************************************************
264 RegCloseKey(HKEY hKey
)
268 /* don't close null handle or a pseudo handle */
269 if ((!hKey
) || (((ULONG
)hKey
& 0xF0000000) == 0x80000000))
270 return ERROR_INVALID_HANDLE
;
272 Status
= NtClose (hKey
);
273 if (!NT_SUCCESS(Status
))
275 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
277 SetLastError (ErrorCode
);
281 return ERROR_SUCCESS
;
285 /************************************************************************
286 * RegConnectRegistryA
289 RegConnectRegistryA(LPCSTR lpMachineName
,
293 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
294 return ERROR_CALL_NOT_IMPLEMENTED
;
298 /************************************************************************
299 * RegConnectRegistryW
302 RegConnectRegistryW(LPCWSTR lpMachineName
,
306 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
307 return ERROR_CALL_NOT_IMPLEMENTED
;
311 /************************************************************************
315 RegCreateKeyA(HKEY hKey
,
319 return(RegCreateKeyExA(hKey
,
331 /************************************************************************
335 RegCreateKeyW(HKEY hKey
,
339 return(RegCreateKeyExW(hKey
,
351 /************************************************************************
355 RegCreateKeyExA(HKEY hKey
,
361 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
363 LPDWORD lpdwDisposition
)
365 UNICODE_STRING SubKeyString
;
366 UNICODE_STRING ClassString
;
367 OBJECT_ATTRIBUTES Attributes
;
371 DPRINT("RegCreateKeyExW() called\n");
373 /* get the real parent key */
374 Status
= MapDefaultKey(&ParentKey
,
376 if (!NT_SUCCESS(Status
))
378 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
380 SetLastError(ErrorCode
);
384 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
387 RtlCreateUnicodeStringFromAsciiz(&ClassString
,
389 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
392 InitializeObjectAttributes(&Attributes
,
394 OBJ_CASE_INSENSITIVE
,
396 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
398 Status
= NtCreateKey(phkResult
,
402 (lpClass
== NULL
)? NULL
: &ClassString
,
404 (PULONG
)lpdwDisposition
);
406 RtlFreeUnicodeString(&SubKeyString
);
408 RtlFreeUnicodeString(&ClassString
);
410 DPRINT("Status %x\n", Status
);
411 if (!NT_SUCCESS(Status
))
413 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
415 SetLastError (ErrorCode
);
419 return(ERROR_SUCCESS
);
423 /************************************************************************
427 RegCreateKeyExW(HKEY hKey
,
433 LPSECURITY_ATTRIBUTES lpSecurityAttributes
,
435 LPDWORD lpdwDisposition
)
437 UNICODE_STRING SubKeyString
;
438 UNICODE_STRING ClassString
;
439 OBJECT_ATTRIBUTES Attributes
;
443 DPRINT("RegCreateKeyExW() called\n");
445 /* get the real parent key */
446 Status
= MapDefaultKey (&ParentKey
, hKey
);
447 if (!NT_SUCCESS(Status
))
449 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
451 SetLastError (ErrorCode
);
455 DPRINT("ParentKey %x\n", (ULONG
)ParentKey
);
456 RtlInitUnicodeString (&ClassString
, lpClass
);
457 RtlInitUnicodeString (&SubKeyString
, lpSubKey
);
459 InitializeObjectAttributes (&Attributes
,
461 OBJ_CASE_INSENSITIVE
,
463 (PSECURITY_DESCRIPTOR
)lpSecurityAttributes
);
465 Status
= NtCreateKey (phkResult
,
469 (lpClass
== NULL
)? NULL
: &ClassString
,
471 (PULONG
)lpdwDisposition
);
472 DPRINT("Status %x\n", Status
);
473 if (!NT_SUCCESS(Status
))
475 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
477 SetLastError (ErrorCode
);
481 return ERROR_SUCCESS
;
485 /************************************************************************
495 OBJECT_ATTRIBUTES ObjectAttributes
;
496 UNICODE_STRING SubKeyStringW
;
497 ANSI_STRING SubKeyStringA
;
504 Status
= MapDefaultKey(&ParentKey
,
506 if (!NT_SUCCESS(Status
))
508 ErrorCode
= RtlNtStatusToDosError(Status
);
510 SetLastError (ErrorCode
);
514 RtlInitAnsiString(&SubKeyStringA
,
516 RtlAnsiStringToUnicodeString(&SubKeyStringW
,
520 InitializeObjectAttributes (&ObjectAttributes
,
522 OBJ_CASE_INSENSITIVE
,
526 Status
= NtOpenKey (&TargetKey
,
530 RtlFreeUnicodeString (&SubKeyStringW
);
532 if (!NT_SUCCESS(Status
))
534 ErrorCode
= RtlNtStatusToDosError(Status
);
536 SetLastError (ErrorCode
);
540 Status
= NtDeleteKey(TargetKey
);
544 if (!NT_SUCCESS(Status
))
546 ErrorCode
= RtlNtStatusToDosError(Status
);
548 SetLastError (ErrorCode
);
551 return ERROR_SUCCESS
;
555 /************************************************************************
565 OBJECT_ATTRIBUTES ObjectAttributes
;
566 UNICODE_STRING SubKeyString
;
572 Status
= MapDefaultKey(&ParentKey
,
574 if (!NT_SUCCESS(Status
))
576 ErrorCode
= RtlNtStatusToDosError(Status
);
578 SetLastError (ErrorCode
);
582 RtlInitUnicodeString(&SubKeyString
,
585 InitializeObjectAttributes (&ObjectAttributes
,
587 OBJ_CASE_INSENSITIVE
,
591 Status
= NtOpenKey (&TargetKey
,
594 if (!NT_SUCCESS(Status
))
596 ErrorCode
= RtlNtStatusToDosError(Status
);
598 SetLastError (ErrorCode
);
602 Status
= NtDeleteKey(TargetKey
);
606 if (!NT_SUCCESS(Status
))
608 ErrorCode
= RtlNtStatusToDosError(Status
);
610 SetLastError (ErrorCode
);
613 return ERROR_SUCCESS
;
617 /************************************************************************
627 UNICODE_STRING ValueNameW
;
628 ANSI_STRING ValueNameA
;
633 Status
= MapDefaultKey(&KeyHandle
,
635 if (!NT_SUCCESS(Status
))
637 ErrorCode
= RtlNtStatusToDosError(Status
);
639 SetLastError (ErrorCode
);
643 RtlInitAnsiString(&ValueNameA
,
645 RtlAnsiStringToUnicodeString(&ValueNameW
,
649 Status
= NtDeleteValueKey(KeyHandle
,
652 RtlFreeUnicodeString (&ValueNameW
);
654 if (!NT_SUCCESS(Status
))
656 ErrorCode
= RtlNtStatusToDosError(Status
);
658 SetLastError (ErrorCode
);
662 return ERROR_SUCCESS
;
666 /************************************************************************
676 UNICODE_STRING ValueName
;
681 Status
= MapDefaultKey(&KeyHandle
,
683 if (!NT_SUCCESS(Status
))
685 ErrorCode
= RtlNtStatusToDosError(Status
);
687 SetLastError (ErrorCode
);
691 RtlInitUnicodeString(&ValueName
,
692 (LPWSTR
)lpValueName
);
694 Status
= NtDeleteValueKey(KeyHandle
,
696 if (!NT_SUCCESS(Status
))
698 ErrorCode
= RtlNtStatusToDosError(Status
);
700 SetLastError (ErrorCode
);
704 return ERROR_SUCCESS
;
708 /************************************************************************
720 DWORD dwLength
= cbName
;
722 return RegEnumKeyExA(hKey
,
733 /************************************************************************
746 PFILETIME lpftLastWriteTime
749 WCHAR Name
[MAX_PATH
+1];
750 UNICODE_STRING UnicodeStringName
;
751 WCHAR Class
[MAX_PATH
+1];
752 UNICODE_STRING UnicodeStringClass
;
753 ANSI_STRING AnsiString
;
758 DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n",
759 hKey
, dwIndex
, lpName
, *lpcbName
, lpClass
, lpcbClass
);
761 if ((lpClass
) && (!lpcbClass
))
763 SetLastError(ERROR_INVALID_PARAMETER
);
764 return ERROR_INVALID_PARAMETER
;
767 RtlInitUnicodeString(&UnicodeStringName
, NULL
);
768 UnicodeStringName
.Buffer
= &Name
[0];
769 UnicodeStringName
.MaximumLength
= sizeof(Name
);
771 RtlInitUnicodeString(&UnicodeStringClass
, NULL
);
775 UnicodeStringClass
.Buffer
= &Class
[0];
776 UnicodeStringClass
.MaximumLength
= sizeof(Class
);
777 ClassLength
= *lpcbClass
;
784 NameLength
= *lpcbName
;
786 ErrorCode
= RegEnumKeyExW(
789 UnicodeStringName
.Buffer
,
792 UnicodeStringClass
.Buffer
,
796 if (ErrorCode
!= ERROR_SUCCESS
)
799 UnicodeStringName
.Length
= NameLength
* sizeof(WCHAR
);
800 UnicodeStringClass
.Length
= ClassLength
* sizeof(WCHAR
);
802 RtlInitAnsiString(&AnsiString
, NULL
);
803 AnsiString
.Buffer
= lpName
;
804 AnsiString
.MaximumLength
= *lpcbName
;
805 RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeStringName
, FALSE
);
806 *lpcbName
= AnsiString
.Length
;
808 DPRINT("Key Namea0 Length %d\n", UnicodeStringName
.Length
);
809 DPRINT("Key Namea1 Length %d\n", NameLength
);
810 DPRINT("Key Namea Length %d\n", *lpcbName
);
811 DPRINT("Key Namea %s\n", lpName
);
815 RtlInitAnsiString(&AnsiString
, NULL
);
816 AnsiString
.Buffer
= lpClass
;
817 AnsiString
.MaximumLength
= *lpcbClass
;
818 RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeStringClass
, FALSE
);
819 *lpcbClass
= AnsiString
.Length
;
822 return ERROR_SUCCESS
;
826 /************************************************************************
839 PFILETIME lpftLastWriteTime
842 PKEY_NODE_INFORMATION KeyInfo
;
844 DWORD dwError
= ERROR_SUCCESS
;
849 Status
= MapDefaultKey(&KeyHandle
, hKey
);
850 if (!NT_SUCCESS(Status
))
852 dwError
= RtlNtStatusToDosError(Status
);
853 SetLastError (dwError
);
857 BufferSize
= sizeof (KEY_NODE_INFORMATION
) + *lpcbName
* sizeof(WCHAR
);
859 BufferSize
+= *lpcbClass
;
862 // I think this is a memory leak, always allocated again below ???
864 // KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
867 /* We don't know the exact size of the data returned, so call
868 NtEnumerateKey() with a buffer size determined from parameters
869 to this function. If that call fails with a status code of
870 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
872 KeyInfo
= RtlAllocateHeap(
878 SetLastError(ERROR_OUTOFMEMORY
);
879 return ERROR_OUTOFMEMORY
;
882 Status
= NtEnumerateKey(
890 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status
);
892 if (Status
== STATUS_BUFFER_OVERFLOW
)
894 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo
);
895 BufferSize
= ResultSize
;
899 if (!NT_SUCCESS(Status
))
901 dwError
= RtlNtStatusToDosError(Status
);
902 SetLastError(dwError
);
907 if ((lpClass
) && (*lpcbClass
!= 0) && (KeyInfo
->ClassLength
> *lpcbClass
))
909 dwError
= ERROR_MORE_DATA
;
910 SetLastError(dwError
);
914 RtlMoveMemory(lpName
, KeyInfo
->Name
, KeyInfo
->NameLength
);
915 *lpcbName
= (DWORD
)(KeyInfo
->NameLength
/ sizeof(WCHAR
));
916 RegiTerminateWideString(lpName
, *lpcbName
);
920 RtlMoveMemory(lpClass
,
921 (PVOID
)((ULONG_PTR
)KeyInfo
->Name
+ KeyInfo
->ClassOffset
),
922 KeyInfo
->ClassLength
);
923 *lpcbClass
= (DWORD
)(KeyInfo
->ClassLength
/ sizeof(WCHAR
));
926 if (lpftLastWriteTime
)
928 /* FIXME: Fill lpftLastWriteTime */
935 RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo
);
941 /************************************************************************
953 DWORD dwLength
= cbName
;
955 return RegEnumKeyExW(hKey
,
966 /************************************************************************
975 LPDWORD lpcbValueName
,
982 WCHAR ValueName
[MAX_PATH
+1];
983 UNICODE_STRING UnicodeString
;
984 ANSI_STRING AnsiString
;
986 DWORD ValueNameLength
;
988 RtlInitUnicodeString(&UnicodeString
, NULL
);
989 UnicodeString
.Buffer
= &ValueName
[0];
990 UnicodeString
.MaximumLength
= sizeof(ValueName
);
992 ValueNameLength
= *lpcbValueName
;
994 ErrorCode
= RegEnumValueW(
997 UnicodeString
.Buffer
,
1004 if (ErrorCode
!= ERROR_SUCCESS
)
1007 UnicodeString
.Length
= ValueNameLength
* sizeof(WCHAR
);
1009 RtlInitAnsiString(&AnsiString
, NULL
);
1010 AnsiString
.Buffer
= lpValueName
;
1011 AnsiString
.MaximumLength
= *lpcbValueName
;
1012 RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
1013 *lpcbValueName
= AnsiString
.Length
;
1015 return ERROR_SUCCESS
;
1019 /************************************************************************
1028 LPDWORD lpcbValueName
,
1035 PKEY_VALUE_FULL_INFORMATION ValueInfo
;
1037 DWORD dwError
= ERROR_SUCCESS
;
1042 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1043 if (!NT_SUCCESS(Status
))
1045 dwError
= RtlNtStatusToDosError(Status
);
1046 SetLastError(dwError
);
1050 BufferSize
= sizeof (KEY_VALUE_FULL_INFORMATION
) +
1051 *lpcbValueName
* sizeof(WCHAR
);
1053 BufferSize
+= *lpcbData
;
1055 /* We don't know the exact size of the data returned, so call
1056 NtEnumerateValueKey() with a buffer size determined from parameters
1057 to this function. If that call fails with a status code of
1058 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
1060 ValueInfo
= RtlAllocateHeap(
1061 RtlGetProcessHeap(),
1064 if (ValueInfo
== NULL
)
1066 SetLastError(ERROR_OUTOFMEMORY
);
1067 return ERROR_OUTOFMEMORY
;
1070 Status
= NtEnumerateValueKey(
1073 KeyValueFullInformation
,
1078 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status
);
1080 if (Status
== STATUS_BUFFER_OVERFLOW
)
1082 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
1083 BufferSize
= ResultSize
;
1087 if (!NT_SUCCESS(Status
))
1089 dwError
= RtlNtStatusToDosError(Status
);
1090 SetLastError(dwError
);
1095 if ((lpData
) && (*lpcbData
!= 0) && (ValueInfo
->DataLength
> *lpcbData
))
1097 dwError
= ERROR_MORE_DATA
;
1098 SetLastError(dwError
);
1102 memcpy(lpValueName
, ValueInfo
->Name
, ValueInfo
->NameLength
);
1103 *lpcbValueName
= (DWORD
)(ValueInfo
->NameLength
/ sizeof(WCHAR
));
1104 RegiTerminateWideString(lpValueName
, *lpcbValueName
);
1107 *lpType
= ValueInfo
->Type
;
1112 (PVOID
)((ULONG_PTR
)ValueInfo
+ ValueInfo
->DataOffset
),
1113 ValueInfo
->DataLength
);
1114 *lpcbData
= (DWORD
)ValueInfo
->DataLength
;
1121 RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo
);
1127 /************************************************************************
1131 RegFlushKey(HKEY hKey
)
1137 if (hKey
== HKEY_PERFORMANCE_DATA
)
1138 return(ERROR_SUCCESS
);
1140 Status
= MapDefaultKey(&KeyHandle
,
1142 if (!NT_SUCCESS(Status
))
1144 ErrorCode
= RtlNtStatusToDosError(Status
);
1146 SetLastError(ErrorCode
);
1150 Status
= NtFlushKey(KeyHandle
);
1151 if (!NT_SUCCESS(Status
))
1153 ErrorCode
= RtlNtStatusToDosError(Status
);
1155 SetLastError(ErrorCode
);
1159 return(ERROR_SUCCESS
);
1163 /************************************************************************
1170 SECURITY_INFORMATION SecurityInformation
,
1171 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1172 LPDWORD lpcbSecurityDescriptor
1176 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1177 return ERROR_CALL_NOT_IMPLEMENTED
;
1181 /************************************************************************
1193 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1194 return ERROR_CALL_NOT_IMPLEMENTED
;
1198 /************************************************************************
1209 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1210 return ERROR_CALL_NOT_IMPLEMENTED
;
1214 /************************************************************************
1215 * RegNotifyChangeKeyValue
1219 RegNotifyChangeKeyValue(
1222 DWORD dwNotifyFilter
,
1228 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1229 return ERROR_CALL_NOT_IMPLEMENTED
;
1234 /************************************************************************
1238 RegOpenKeyA(HKEY hKey
,
1242 OBJECT_ATTRIBUTES ObjectAttributes
;
1243 UNICODE_STRING SubKeyString
;
1248 Status
= MapDefaultKey(&KeyHandle
,
1250 if (!NT_SUCCESS(Status
))
1252 ErrorCode
= RtlNtStatusToDosError(Status
);
1254 SetLastError(ErrorCode
);
1258 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
1261 InitializeObjectAttributes(&ObjectAttributes
,
1263 OBJ_CASE_INSENSITIVE
,
1267 Status
= NtOpenKey(phkResult
,
1271 RtlFreeUnicodeString(&SubKeyString
);
1273 if (!NT_SUCCESS(Status
))
1275 ErrorCode
= RtlNtStatusToDosError(Status
);
1277 SetLastError(ErrorCode
);
1280 return(ERROR_SUCCESS
);
1284 /************************************************************************
1299 UNICODE_STRING SubKeyString
;
1300 OBJECT_ATTRIBUTES ObjectAttributes
;
1304 errCode
= MapDefaultKey(&KeyHandle
,
1306 if (!NT_SUCCESS(errCode
))
1308 ErrorCode
= RtlNtStatusToDosError(errCode
);
1310 SetLastError (ErrorCode
);
1314 RtlInitUnicodeString(&SubKeyString
,
1317 InitializeObjectAttributes(&ObjectAttributes
,
1319 OBJ_CASE_INSENSITIVE
,
1323 errCode
= NtOpenKey(
1328 if ( !NT_SUCCESS(errCode
) )
1330 ErrorCode
= RtlNtStatusToDosError(errCode
);
1332 SetLastError(ErrorCode
);
1335 return ERROR_SUCCESS
;
1339 /************************************************************************
1343 RegOpenKeyExA(HKEY hKey
,
1349 OBJECT_ATTRIBUTES ObjectAttributes
;
1350 UNICODE_STRING SubKeyString
;
1355 Status
= MapDefaultKey(&KeyHandle
,
1357 if (!NT_SUCCESS(Status
))
1359 ErrorCode
= RtlNtStatusToDosError(Status
);
1361 SetLastError(ErrorCode
);
1365 RtlCreateUnicodeStringFromAsciiz(&SubKeyString
,
1368 InitializeObjectAttributes(&ObjectAttributes
,
1370 OBJ_CASE_INSENSITIVE
,
1374 Status
= NtOpenKey(phkResult
,
1378 RtlFreeUnicodeString(&SubKeyString
);
1380 if (!NT_SUCCESS(Status
))
1382 ErrorCode
= RtlNtStatusToDosError(Status
);
1384 SetLastError(ErrorCode
);
1388 return(ERROR_SUCCESS
);
1392 /************************************************************************
1396 RegOpenKeyExW(HKEY hKey
,
1402 OBJECT_ATTRIBUTES ObjectAttributes
;
1403 UNICODE_STRING SubKeyString
;
1408 Status
= MapDefaultKey(&KeyHandle
,
1410 if (!NT_SUCCESS(Status
))
1412 ErrorCode
= RtlNtStatusToDosError(Status
);
1414 SetLastError (ErrorCode
);
1418 RtlInitUnicodeString(&SubKeyString
,
1421 InitializeObjectAttributes(&ObjectAttributes
,
1423 OBJ_CASE_INSENSITIVE
,
1427 Status
= NtOpenKey(phkResult
,
1430 if (!NT_SUCCESS(Status
))
1432 ErrorCode
= RtlNtStatusToDosError(Status
);
1434 SetLastError(ErrorCode
);
1437 return(ERROR_SUCCESS
);
1441 /************************************************************************
1452 LPDWORD lpcbMaxSubKeyLen
,
1453 LPDWORD lpcbMaxClassLen
,
1455 LPDWORD lpcbMaxValueNameLen
,
1456 LPDWORD lpcbMaxValueLen
,
1457 LPDWORD lpcbSecurityDescriptor
,
1458 PFILETIME lpftLastWriteTime
1461 WCHAR ClassName
[MAX_PATH
];
1462 UNICODE_STRING UnicodeString
;
1463 ANSI_STRING AnsiString
;
1466 RtlInitUnicodeString(&UnicodeString
, NULL
);
1470 UnicodeString
.Buffer
= &ClassName
[0];
1471 UnicodeString
.MaximumLength
= sizeof(ClassName
);
1474 ErrorCode
= RegQueryInfoKeyW(
1476 UnicodeString
.Buffer
,
1483 lpcbMaxValueNameLen
,
1485 lpcbSecurityDescriptor
,
1488 if ((ErrorCode
== ERROR_SUCCESS
) && (lpClass
))
1490 RtlInitAnsiString(&AnsiString
, NULL
);
1491 AnsiString
.Buffer
= lpClass
;
1492 AnsiString
.MaximumLength
= *lpcbClass
;
1493 RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
1494 *lpcbClass
= AnsiString
.Length
;
1501 /************************************************************************
1512 LPDWORD lpcbMaxSubKeyLen
,
1513 LPDWORD lpcbMaxClassLen
,
1515 LPDWORD lpcbMaxValueNameLen
,
1516 LPDWORD lpcbMaxValueLen
,
1517 LPDWORD lpcbSecurityDescriptor
,
1518 PFILETIME lpftLastWriteTime
1521 KEY_FULL_INFORMATION FullInfoBuffer
;
1522 PKEY_FULL_INFORMATION FullInfo
;
1529 if ((lpClass
) && (!lpcbClass
))
1531 SetLastError(ERROR_INVALID_PARAMETER
);
1532 return ERROR_INVALID_PARAMETER
;
1535 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1540 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
) + *lpcbClass
;
1541 FullInfo
= RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize
);
1544 SetLastError(ERROR_OUTOFMEMORY
);
1545 return ERROR_OUTOFMEMORY
;
1548 FullInfo
->ClassLength
= *lpcbClass
;
1552 FullInfoSize
= sizeof(KEY_FULL_INFORMATION
);
1553 FullInfo
= &FullInfoBuffer
;
1554 FullInfo
->ClassLength
= 1;
1557 FullInfo
->ClassOffset
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
1559 Status
= NtQueryKey(
1566 if (!NT_SUCCESS(Status
))
1570 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo
);
1573 ErrorCode
= RtlNtStatusToDosError(Status
);
1574 SetLastError(ErrorCode
);
1580 *lpcSubKeys
= FullInfo
->SubKeys
;
1583 if (lpcbMaxSubKeyLen
)
1585 *lpcbMaxSubKeyLen
= FullInfo
->MaxNameLen
;
1588 if (lpcbMaxClassLen
)
1590 *lpcbMaxClassLen
= FullInfo
->MaxClassLen
;
1595 *lpcValues
= FullInfo
->Values
;
1598 if (lpcbMaxValueNameLen
)
1600 *lpcbMaxValueNameLen
= FullInfo
->MaxValueNameLen
;
1603 if (lpcbMaxValueLen
)
1605 *lpcbMaxValueLen
= FullInfo
->MaxValueDataLen
;
1608 if (lpcbSecurityDescriptor
)
1610 *lpcbSecurityDescriptor
= 0;
1614 if (lpftLastWriteTime
!= NULL
)
1616 lpftLastWriteTime
->dwLowDateTime
= FullInfo
->LastWriteTime
.u
.LowPart
;
1617 lpftLastWriteTime
->dwHighDateTime
= FullInfo
->LastWriteTime
.u
.HighPart
;
1622 wcsncpy(lpClass
, FullInfo
->Class
, *lpcbClass
);
1623 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo
);
1626 SetLastError(ERROR_SUCCESS
);
1627 return ERROR_SUCCESS
;
1631 /************************************************************************
1632 * RegQueryMultipleValuesA
1636 RegQueryMultipleValuesA(
1645 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1646 return ERROR_CALL_NOT_IMPLEMENTED
;
1650 /************************************************************************
1651 * RegQueryMultipleValuesW
1655 RegQueryMultipleValuesW(
1664 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1665 return ERROR_CALL_NOT_IMPLEMENTED
;
1669 /************************************************************************
1681 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
1682 UNICODE_STRING SubKeyName
;
1683 UNICODE_STRING Value
;
1684 ANSI_STRING AnsiString
;
1688 if ((lpValue
) && (!lpcbValue
))
1690 SetLastError(ERROR_INVALID_PARAMETER
);
1691 return ERROR_INVALID_PARAMETER
;
1694 RtlInitUnicodeString(&SubKeyName
, NULL
);
1695 RtlInitUnicodeString(&Value
, NULL
);
1697 if ((lpSubKey
) && (strlen(lpSubKey
) != 0))
1699 RtlInitAnsiString(&AnsiString
, (LPSTR
)lpSubKey
);
1700 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
1701 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
1702 RtlAnsiStringToUnicodeString(&SubKeyName
, &AnsiString
, FALSE
);
1707 ValueSize
= *lpcbValue
* sizeof(WCHAR
);
1708 Value
.MaximumLength
= ValueSize
;
1709 Value
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize
);
1712 SetLastError(ERROR_OUTOFMEMORY
);
1713 return ERROR_OUTOFMEMORY
;
1721 ErrorCode
= RegQueryValueW(
1723 (LPCWSTR
)SubKeyName
.Buffer
,
1727 if (ErrorCode
== ERROR_SUCCESS
)
1729 Value
.Length
= ValueSize
;
1730 RtlInitAnsiString(&AnsiString
, NULL
);
1731 AnsiString
.Buffer
= lpValue
;
1732 AnsiString
.MaximumLength
= *lpcbValue
;
1733 RtlUnicodeStringToAnsiString(&AnsiString
, &Value
, FALSE
);
1736 *lpcbValue
= ValueSize
;
1740 RtlFreeHeap(RtlGetProcessHeap(), 0, Value
.Buffer
);
1747 /************************************************************************
1761 WCHAR ValueNameBuffer
[MAX_PATH
+1];
1762 UNICODE_STRING ValueName
;
1763 UNICODE_STRING ValueData
;
1764 ANSI_STRING AnsiString
;
1769 /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
1771 if ((lpData
) && (!lpcbData
))
1773 SetLastError(ERROR_INVALID_PARAMETER
);
1774 return ERROR_INVALID_PARAMETER
;
1777 RtlInitUnicodeString(&ValueData
, NULL
);
1781 ValueData
.MaximumLength
= *lpcbData
* sizeof(WCHAR
);
1782 ValueData
.Buffer
= RtlAllocateHeap(
1783 RtlGetProcessHeap(),
1785 ValueData
.MaximumLength
);
1786 if (!ValueData
.Buffer
)
1788 SetLastError(ERROR_OUTOFMEMORY
);
1789 return ERROR_OUTOFMEMORY
;
1793 RtlInitAnsiString(&AnsiString
, (LPSTR
)lpValueName
);
1794 RtlInitUnicodeString(&ValueName
, NULL
);
1795 ValueName
.Buffer
= &ValueNameBuffer
[0];
1796 ValueName
.MaximumLength
= sizeof(ValueNameBuffer
);
1797 RtlAnsiStringToUnicodeString(&ValueName
, &AnsiString
, FALSE
);
1801 ResultSize
= *lpcbData
;
1808 ErrorCode
= RegQueryValueExW(
1813 (LPBYTE
)ValueData
.Buffer
,
1816 if ((ErrorCode
== ERROR_SUCCESS
) && (ValueData
.Buffer
!= NULL
))
1823 if ((Type
== REG_SZ
) || (Type
== REG_MULTI_SZ
) || (Type
== REG_EXPAND_SZ
))
1825 ValueData
.Length
= ResultSize
;
1826 RtlInitAnsiString(&AnsiString
, NULL
);
1827 AnsiString
.Buffer
= lpData
;
1828 AnsiString
.MaximumLength
= *lpcbData
;
1829 RtlUnicodeStringToAnsiString(&AnsiString
, &ValueData
, FALSE
);
1833 RtlMoveMemory(lpData
, ValueData
.Buffer
, ResultSize
);
1839 *lpcbData
= ResultSize
;
1842 if (ValueData
.Buffer
)
1844 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData
.Buffer
);
1851 /************************************************************************
1858 LPCWSTR lpValueName
,
1865 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
1866 UNICODE_STRING ValueName
;
1868 DWORD dwError
= ERROR_SUCCESS
;
1873 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
1874 hKey
, lpValueName
, lpData
, lpcbData
? *lpcbData
: 0);
1876 Status
= MapDefaultKey(&KeyHandle
, hKey
);
1877 if (!NT_SUCCESS(Status
))
1879 dwError
= RtlNtStatusToDosError(Status
);
1880 SetLastError(dwError
);
1884 if ((lpData
) && (!lpcbData
))
1886 SetLastError(ERROR_INVALID_PARAMETER
);
1887 return ERROR_INVALID_PARAMETER
;
1890 RtlInitUnicodeString (&ValueName
,
1893 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + *lpcbData
;
1894 ValueInfo
= RtlAllocateHeap (RtlGetProcessHeap(),
1897 if (ValueInfo
== NULL
)
1899 SetLastError(ERROR_OUTOFMEMORY
);
1900 return ERROR_OUTOFMEMORY
;
1903 Status
= NtQueryValueKey (hKey
,
1905 KeyValuePartialInformation
,
1910 DPRINT("Status 0x%X\n", Status
);
1912 if (Status
== STATUS_BUFFER_TOO_SMALL
)
1914 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
1915 dwError
= ERROR_SUCCESS
;
1917 else if (!NT_SUCCESS(Status
))
1919 dwError
= RtlNtStatusToDosError(Status
);
1920 SetLastError(dwError
);
1926 *lpType
= ValueInfo
->Type
;
1929 RtlMoveMemory(lpData
, ValueInfo
->Data
, ValueInfo
->DataLength
);
1930 if ((ValueInfo
->Type
== REG_SZ
) ||
1931 (ValueInfo
->Type
== REG_MULTI_SZ
) ||
1932 (ValueInfo
->Type
== REG_EXPAND_SZ
))
1934 ((PWSTR
)lpData
)[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = 0;
1938 DPRINT("Type %d ResultSize %d\n", ValueInfo
->Type
, ResultSize
);
1940 *lpcbData
= (DWORD
)ResultSize
;
1942 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo
);
1948 /************************************************************************
1961 UNICODE_STRING SubKeyString
;
1962 OBJECT_ATTRIBUTES ObjectAttributes
;
1968 errCode
= MapDefaultKey(&KeyHandle
, hKey
);
1969 if (!NT_SUCCESS(errCode
))
1971 ErrorCode
= RtlNtStatusToDosError(errCode
);
1972 SetLastError (ErrorCode
);
1976 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
1979 RtlInitUnicodeString(&SubKeyString
,
1982 InitializeObjectAttributes(&ObjectAttributes
,
1984 OBJ_CASE_INSENSITIVE
,
1988 errCode
= NtOpenKey(
1993 if ( !NT_SUCCESS(errCode
) )
1995 ErrorCode
= RtlNtStatusToDosError(errCode
);
1996 SetLastError(ErrorCode
);
1999 CloseRealKey
= TRUE
;
2004 CloseRealKey
= FALSE
;
2007 ErrorCode
= RegQueryValueExW(
2013 (LPDWORD
)lpcbValue
);
2024 /************************************************************************
2037 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2038 return ERROR_CALL_NOT_IMPLEMENTED
;
2042 /************************************************************************
2055 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2056 return ERROR_CALL_NOT_IMPLEMENTED
;
2060 /************************************************************************
2072 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2073 return ERROR_CALL_NOT_IMPLEMENTED
;
2077 /************************************************************************
2089 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2090 return ERROR_CALL_NOT_IMPLEMENTED
;
2094 /************************************************************************
2098 RegSaveKeyA(HKEY hKey
,
2100 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2102 UNICODE_STRING FileName
;
2105 RtlCreateUnicodeStringFromAsciiz(&FileName
,
2107 ErrorCode
= RegSaveKeyW(hKey
,
2109 lpSecurityAttributes
);
2110 RtlFreeUnicodeString(&FileName
);
2116 /************************************************************************
2120 RegSaveKeyW(HKEY hKey
,
2122 LPSECURITY_ATTRIBUTES lpSecurityAttributes
)
2124 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
2125 OBJECT_ATTRIBUTES ObjectAttributes
;
2126 UNICODE_STRING NtName
;
2127 IO_STATUS_BLOCK IoStatusBlock
;
2133 Status
= MapDefaultKey(&KeyHandle
,
2135 if (!NT_SUCCESS(Status
))
2137 ErrorCode
= RtlNtStatusToDosError(Status
);
2138 SetLastError(ErrorCode
);
2142 if (!RtlDosPathNameToNtPathName_U((LPWSTR
)lpFile
,
2147 SetLastError(ERROR_INVALID_PARAMETER
);
2148 return(ERROR_INVALID_PARAMETER
);
2151 if (lpSecurityAttributes
!= NULL
)
2152 SecurityDescriptor
= lpSecurityAttributes
->lpSecurityDescriptor
;
2154 InitializeObjectAttributes(&ObjectAttributes
,
2156 OBJ_CASE_INSENSITIVE
,
2158 SecurityDescriptor
);
2160 Status
= NtCreateFile(&FileHandle
,
2161 GENERIC_WRITE
| SYNCHRONIZE
,
2165 FILE_ATTRIBUTE_NORMAL
,
2168 FILE_OPEN_FOR_BACKUP_INTENT
| FILE_SYNCHRONOUS_IO_NONALERT
,
2171 RtlFreeUnicodeString(&NtName
);
2172 if (!NT_SUCCESS(Status
))
2174 ErrorCode
= RtlNtStatusToDosError(Status
);
2175 SetLastError(ErrorCode
);
2179 Status
= NtSaveKey(KeyHandle
,
2181 NtClose(FileHandle
);
2182 if (!NT_SUCCESS(Status
))
2184 ErrorCode
= RtlNtStatusToDosError(Status
);
2185 SetLastError(ErrorCode
);
2189 return(ERROR_SUCCESS
);
2193 /************************************************************************
2200 SECURITY_INFORMATION SecurityInformation
, /* FIXME: ULONG? */
2201 PSECURITY_DESCRIPTOR pSecurityDescriptor
2205 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2206 return ERROR_CALL_NOT_IMPLEMENTED
;
2210 /************************************************************************
2223 WCHAR SubKeyNameBuffer
[MAX_PATH
+1];
2224 UNICODE_STRING SubKeyName
;
2225 UNICODE_STRING Data
;
2226 ANSI_STRING AnsiString
;
2232 SetLastError(ERROR_INVALID_PARAMETER
);
2233 return ERROR_INVALID_PARAMETER
;
2236 RtlInitUnicodeString(&SubKeyName
, NULL
);
2237 RtlInitUnicodeString(&Data
, NULL
);
2239 if ((lpSubKey
) && (strlen(lpSubKey
) != 0))
2241 RtlInitAnsiString(&AnsiString
, (LPSTR
)lpSubKey
);
2242 SubKeyName
.Buffer
= &SubKeyNameBuffer
[0];
2243 SubKeyName
.MaximumLength
= sizeof(SubKeyNameBuffer
);
2244 RtlAnsiStringToUnicodeString(&SubKeyName
, &AnsiString
, FALSE
);
2247 DataSize
= cbData
* sizeof(WCHAR
);
2248 Data
.MaximumLength
= DataSize
;
2249 Data
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize
);
2252 SetLastError(ERROR_OUTOFMEMORY
);
2253 return ERROR_OUTOFMEMORY
;
2256 ErrorCode
= RegSetValueW(
2258 (LPCWSTR
)SubKeyName
.Buffer
,
2263 RtlFreeHeap(RtlGetProcessHeap(), 0, Data
.Buffer
);
2269 /************************************************************************
2283 UNICODE_STRING ValueName
;
2285 ANSI_STRING AnsiString
;
2286 UNICODE_STRING Data
;
2293 SetLastError(ERROR_INVALID_PARAMETER
);
2294 return ERROR_INVALID_PARAMETER
;
2297 if ((lpValueName
) && (strlen(lpValueName
) != 0))
2299 RtlCreateUnicodeStringFromAsciiz(&ValueName
, (LPSTR
)lpValueName
);
2300 pValueName
= (LPWSTR
)ValueName
.Buffer
;
2307 if ((dwType
== REG_SZ
) || (dwType
== REG_MULTI_SZ
) || (dwType
== REG_EXPAND_SZ
))
2309 RtlInitAnsiString(&AnsiString
, NULL
);
2310 AnsiString
.Buffer
= (LPSTR
)lpData
;
2311 AnsiString
.Length
= cbData
;
2312 AnsiString
.MaximumLength
= cbData
;
2313 RtlAnsiStringToUnicodeString(&Data
, &AnsiString
, TRUE
);
2314 pData
= (LPBYTE
)Data
.Buffer
;
2315 DataSize
= cbData
* sizeof(WCHAR
);
2319 RtlInitUnicodeString(&Data
, NULL
);
2320 pData
= (LPBYTE
)lpData
;
2324 ErrorCode
= RegSetValueExW(
2334 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName
.Buffer
);
2339 RtlFreeHeap(RtlGetProcessHeap(), 0, Data
.Buffer
);
2346 /************************************************************************
2353 LPCWSTR lpValueName
,
2360 UNICODE_STRING ValueName
;
2361 PUNICODE_STRING pValueName
;
2366 Status
= MapDefaultKey(&KeyHandle
, hKey
);
2367 if (!NT_SUCCESS(Status
))
2369 ErrorCode
= RtlNtStatusToDosError(Status
);
2370 SetLastError(ErrorCode
);
2376 RtlInitUnicodeString(&ValueName
, lpValueName
);
2377 pValueName
= &ValueName
;
2384 Status
= NtSetValueKey(
2391 if (!NT_SUCCESS(Status
))
2393 LONG ErrorCode
= RtlNtStatusToDosError(Status
);
2394 SetLastError (ErrorCode
);
2398 return ERROR_SUCCESS
;
2402 /************************************************************************
2416 UNICODE_STRING SubKeyString
;
2417 OBJECT_ATTRIBUTES ObjectAttributes
;
2423 errCode
= MapDefaultKey(&KeyHandle
, hKey
);
2424 if (!NT_SUCCESS(errCode
))
2426 ErrorCode
= RtlNtStatusToDosError(errCode
);
2427 SetLastError (ErrorCode
);
2431 if ((lpSubKey
) && (wcslen(lpSubKey
) != 0))
2434 RtlInitUnicodeString(&SubKeyString
,
2437 InitializeObjectAttributes(&ObjectAttributes
,
2439 OBJ_CASE_INSENSITIVE
,
2443 errCode
= NtOpenKey(
2448 if ( !NT_SUCCESS(errCode
) )
2450 ErrorCode
= RtlNtStatusToDosError(errCode
);
2451 SetLastError(ErrorCode
);
2454 CloseRealKey
= TRUE
;
2459 CloseRealKey
= FALSE
;
2462 ErrorCode
= RegSetValueExW(
2479 /************************************************************************
2490 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2491 return ERROR_CALL_NOT_IMPLEMENTED
;
2495 /************************************************************************
2506 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2507 return ERROR_CALL_NOT_IMPLEMENTED
;