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(LPSTR lpMachineName,
293 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
294 return ERROR_CALL_NOT_IMPLEMENTED;
298 /************************************************************************
299 * RegConnectRegistryW
302 RegConnectRegistryW(LPWSTR 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;
503 Status = MapDefaultKey(&ParentKey,
505 if (!NT_SUCCESS(Status))
507 ErrorCode = RtlNtStatusToDosError(Status);
509 SetLastError (ErrorCode);
513 RtlInitAnsiString(&SubKeyStringA,
515 RtlAnsiStringToUnicodeString(&SubKeyStringW,
519 InitializeObjectAttributes (&ObjectAttributes,
521 OBJ_CASE_INSENSITIVE,
525 Status = NtOpenKey (&TargetKey,
529 RtlFreeUnicodeString (&SubKeyStringW);
531 if (!NT_SUCCESS(Status))
533 ErrorCode = RtlNtStatusToDosError(Status);
535 SetLastError (ErrorCode);
539 Status = NtDeleteKey(TargetKey);
543 if (!NT_SUCCESS(Status))
545 ErrorCode = RtlNtStatusToDosError(Status);
547 SetLastError (ErrorCode);
550 return ERROR_SUCCESS;
554 /************************************************************************
564 OBJECT_ATTRIBUTES ObjectAttributes;
565 UNICODE_STRING SubKeyString;
571 Status = MapDefaultKey(&ParentKey,
573 if (!NT_SUCCESS(Status))
575 ErrorCode = RtlNtStatusToDosError(Status);
577 SetLastError (ErrorCode);
581 RtlInitUnicodeString(&SubKeyString,
584 InitializeObjectAttributes (&ObjectAttributes,
586 OBJ_CASE_INSENSITIVE,
590 Status = NtOpenKey (&TargetKey,
593 if (!NT_SUCCESS(Status))
595 ErrorCode = RtlNtStatusToDosError(Status);
597 SetLastError (ErrorCode);
601 Status = NtDeleteKey(TargetKey);
605 if (!NT_SUCCESS(Status))
607 ErrorCode = RtlNtStatusToDosError(Status);
609 SetLastError (ErrorCode);
612 return ERROR_SUCCESS;
616 /************************************************************************
626 UNICODE_STRING ValueNameW;
627 ANSI_STRING ValueNameA;
632 Status = MapDefaultKey(&KeyHandle,
634 if (!NT_SUCCESS(Status))
636 ErrorCode = RtlNtStatusToDosError(Status);
638 SetLastError (ErrorCode);
642 RtlInitAnsiString(&ValueNameA,
644 RtlAnsiStringToUnicodeString(&ValueNameW,
648 Status = NtDeleteValueKey(KeyHandle,
651 RtlFreeUnicodeString (&ValueNameW);
653 if (!NT_SUCCESS(Status))
655 ErrorCode = RtlNtStatusToDosError(Status);
657 SetLastError (ErrorCode);
661 return ERROR_SUCCESS;
665 /************************************************************************
675 UNICODE_STRING ValueName;
680 Status = MapDefaultKey(&KeyHandle,
682 if (!NT_SUCCESS(Status))
684 ErrorCode = RtlNtStatusToDosError(Status);
686 SetLastError (ErrorCode);
690 RtlInitUnicodeString(&ValueName,
691 (LPWSTR)lpValueName);
693 Status = NtDeleteValueKey(KeyHandle,
695 if (!NT_SUCCESS(Status))
697 ErrorCode = RtlNtStatusToDosError(Status);
699 SetLastError (ErrorCode);
703 return ERROR_SUCCESS;
707 /************************************************************************
719 DWORD dwLength = cbName;
721 return RegEnumKeyExA(hKey,
732 /************************************************************************
745 PFILETIME lpftLastWriteTime
748 WCHAR Name[MAX_PATH+1];
749 UNICODE_STRING UnicodeStringName;
750 WCHAR Class[MAX_PATH+1];
751 UNICODE_STRING UnicodeStringClass;
752 ANSI_STRING AnsiString;
757 DPRINT("hKey 0x%x dwIndex %d lpName 0x%x *lpcbName %d lpClass 0x%x lpcbClass %d\n",
758 hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass);
760 if ((lpClass) && (!lpcbClass))
762 SetLastError(ERROR_INVALID_PARAMETER);
763 return ERROR_INVALID_PARAMETER;
766 RtlInitUnicodeString(&UnicodeStringName, NULL);
767 UnicodeStringName.Buffer = &Name[0];
768 UnicodeStringName.MaximumLength = sizeof(Name);
770 RtlInitUnicodeString(&UnicodeStringClass, NULL);
774 UnicodeStringClass.Buffer = &Class[0];
775 UnicodeStringClass.MaximumLength = sizeof(Class);
776 ClassLength = *lpcbClass;
783 NameLength = *lpcbName;
785 ErrorCode = RegEnumKeyExW(
788 UnicodeStringName.Buffer,
791 UnicodeStringClass.Buffer,
795 if (ErrorCode != ERROR_SUCCESS)
798 UnicodeStringName.Length = NameLength * sizeof(WCHAR);
799 UnicodeStringClass.Length = ClassLength * sizeof(WCHAR);
801 RtlInitAnsiString(&AnsiString, NULL);
802 AnsiString.Buffer = lpName;
803 AnsiString.MaximumLength = *lpcbName;
804 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringName, FALSE);
805 *lpcbName = AnsiString.Length;
807 DPRINT("Key Namea0 Length %d\n", UnicodeStringName.Length);
808 DPRINT("Key Namea1 Length %d\n", NameLength);
809 DPRINT("Key Namea Length %d\n", *lpcbName);
810 DPRINT("Key Namea %s\n", lpName);
814 RtlInitAnsiString(&AnsiString, NULL);
815 AnsiString.Buffer = lpClass;
816 AnsiString.MaximumLength = *lpcbClass;
817 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeStringClass, FALSE);
818 *lpcbClass = AnsiString.Length;
821 return ERROR_SUCCESS;
825 /************************************************************************
838 PFILETIME lpftLastWriteTime
841 PKEY_NODE_INFORMATION KeyInfo;
843 DWORD dwError = ERROR_SUCCESS;
848 Status = MapDefaultKey(&KeyHandle, hKey);
849 if (!NT_SUCCESS(Status))
851 dwError = RtlNtStatusToDosError(Status);
852 SetLastError (dwError);
856 BufferSize = sizeof (KEY_NODE_INFORMATION) + *lpcbName * sizeof(WCHAR);
858 BufferSize += *lpcbClass;
859 KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
861 /* We don't know the exact size of the data returned, so call
862 NtEnumerateKey() with a buffer size determined from parameters
863 to this function. If that call fails with a status code of
864 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
866 KeyInfo = RtlAllocateHeap(
872 SetLastError(ERROR_OUTOFMEMORY);
873 return ERROR_OUTOFMEMORY;
876 Status = NtEnumerateKey(
884 DPRINT("NtEnumerateKey() returned status 0x%X\n", Status);
886 if (Status == STATUS_BUFFER_OVERFLOW)
888 RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
889 BufferSize = ResultSize;
893 if (!NT_SUCCESS(Status))
895 dwError = RtlNtStatusToDosError(Status);
896 SetLastError(dwError);
901 if ((lpClass) && (*lpcbClass != 0) && (KeyInfo->ClassLength > *lpcbClass))
903 dwError = ERROR_MORE_DATA;
904 SetLastError(dwError);
908 RtlMoveMemory(lpName, KeyInfo->Name, KeyInfo->NameLength);
909 *lpcbName = (DWORD)(KeyInfo->NameLength / sizeof(WCHAR));
910 RegiTerminateWideString(lpName, *lpcbName);
914 RtlMoveMemory(lpClass,
915 (PVOID)((ULONG_PTR)KeyInfo->Name + KeyInfo->ClassOffset),
916 KeyInfo->ClassLength);
917 *lpcbClass = (DWORD)(KeyInfo->ClassLength / sizeof(WCHAR));
920 if (lpftLastWriteTime)
922 /* FIXME: Fill lpftLastWriteTime */
929 RtlFreeHeap (RtlGetProcessHeap(), 0, KeyInfo);
935 /************************************************************************
947 DWORD dwLength = cbName;
949 return RegEnumKeyExW(hKey,
960 /************************************************************************
969 LPDWORD lpcbValueName,
976 WCHAR ValueName[MAX_PATH+1];
977 UNICODE_STRING UnicodeString;
978 ANSI_STRING AnsiString;
980 DWORD ValueNameLength;
982 RtlInitUnicodeString(&UnicodeString, NULL);
983 UnicodeString.Buffer = &ValueName[0];
984 UnicodeString.MaximumLength = sizeof(ValueName);
986 ValueNameLength = *lpcbValueName;
988 ErrorCode = RegEnumValueW(
991 UnicodeString.Buffer,
998 if (ErrorCode != ERROR_SUCCESS)
1001 UnicodeString.Length = ValueNameLength * sizeof(WCHAR);
1003 RtlInitAnsiString(&AnsiString, NULL);
1004 AnsiString.Buffer = lpValueName;
1005 AnsiString.MaximumLength = *lpcbValueName;
1006 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1007 *lpcbValueName = AnsiString.Length;
1009 return ERROR_SUCCESS;
1013 /************************************************************************
1022 LPDWORD lpcbValueName,
1029 PKEY_VALUE_FULL_INFORMATION ValueInfo;
1031 DWORD dwError = ERROR_SUCCESS;
1036 Status = MapDefaultKey(&KeyHandle, hKey);
1037 if (!NT_SUCCESS(Status))
1039 dwError = RtlNtStatusToDosError(Status);
1040 SetLastError(dwError);
1044 BufferSize = sizeof (KEY_VALUE_FULL_INFORMATION) +
1045 *lpcbValueName * sizeof(WCHAR);
1047 BufferSize += *lpcbData;
1049 /* We don't know the exact size of the data returned, so call
1050 NtEnumerateValueKey() with a buffer size determined from parameters
1051 to this function. If that call fails with a status code of
1052 STATUS_BUFFER_OVERFLOW, allocate a new buffer and try again */
1054 ValueInfo = RtlAllocateHeap(
1055 RtlGetProcessHeap(),
1058 if (ValueInfo == NULL)
1060 SetLastError(ERROR_OUTOFMEMORY);
1061 return ERROR_OUTOFMEMORY;
1064 Status = NtEnumerateValueKey(
1067 KeyValueFullInformation,
1072 DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
1074 if (Status == STATUS_BUFFER_OVERFLOW)
1076 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
1077 BufferSize = ResultSize;
1081 if (!NT_SUCCESS(Status))
1083 dwError = RtlNtStatusToDosError(Status);
1084 SetLastError(dwError);
1089 if ((lpData) && (*lpcbData != 0) && (ValueInfo->DataLength > *lpcbData))
1091 dwError = ERROR_MORE_DATA;
1092 SetLastError(dwError);
1096 memcpy(lpValueName, ValueInfo->Name, ValueInfo->NameLength);
1097 *lpcbValueName = (DWORD)(ValueInfo->NameLength / sizeof(WCHAR));
1098 RegiTerminateWideString(lpValueName, *lpcbValueName);
1101 *lpType = ValueInfo->Type;
1106 (PVOID)((ULONG_PTR)ValueInfo->Name + ValueInfo->DataOffset),
1107 ValueInfo->DataLength);
1108 *lpcbData = (DWORD)ValueInfo->DataLength;
1115 RtlFreeHeap (RtlGetProcessHeap(), 0, ValueInfo);
1121 /************************************************************************
1125 RegFlushKey(HKEY hKey)
1131 if (hKey == HKEY_PERFORMANCE_DATA)
1132 return(ERROR_SUCCESS);
1134 Status = MapDefaultKey(&KeyHandle,
1136 if (!NT_SUCCESS(Status))
1138 ErrorCode = RtlNtStatusToDosError(Status);
1140 SetLastError(ErrorCode);
1144 Status = NtFlushKey(KeyHandle);
1145 if (!NT_SUCCESS(Status))
1147 ErrorCode = RtlNtStatusToDosError(Status);
1149 SetLastError(ErrorCode);
1153 return(ERROR_SUCCESS);
1157 /************************************************************************
1164 SECURITY_INFORMATION SecurityInformation,
1165 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1166 LPDWORD lpcbSecurityDescriptor
1170 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1171 return ERROR_CALL_NOT_IMPLEMENTED;
1175 /************************************************************************
1187 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1188 return ERROR_CALL_NOT_IMPLEMENTED;
1192 /************************************************************************
1203 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1204 return ERROR_CALL_NOT_IMPLEMENTED;
1208 /************************************************************************
1209 * RegNotifyChangeKeyValue
1213 RegNotifyChangeKeyValue(
1216 DWORD dwNotifyFilter,
1222 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1223 return ERROR_CALL_NOT_IMPLEMENTED;
1228 /************************************************************************
1232 RegOpenKeyA(HKEY hKey,
1236 OBJECT_ATTRIBUTES ObjectAttributes;
1237 UNICODE_STRING SubKeyString;
1242 Status = MapDefaultKey(&KeyHandle,
1244 if (!NT_SUCCESS(Status))
1246 ErrorCode = RtlNtStatusToDosError(Status);
1248 SetLastError(ErrorCode);
1252 RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
1255 InitializeObjectAttributes(&ObjectAttributes,
1257 OBJ_CASE_INSENSITIVE,
1261 Status = NtOpenKey(phkResult,
1265 RtlFreeUnicodeString(&SubKeyString);
1267 if (!NT_SUCCESS(Status))
1269 ErrorCode = RtlNtStatusToDosError(Status);
1271 SetLastError(ErrorCode);
1274 return(ERROR_SUCCESS);
1278 /************************************************************************
1293 UNICODE_STRING SubKeyString;
1294 OBJECT_ATTRIBUTES ObjectAttributes;
1298 errCode = MapDefaultKey(&KeyHandle,
1300 if (!NT_SUCCESS(errCode))
1302 ErrorCode = RtlNtStatusToDosError(errCode);
1304 SetLastError (ErrorCode);
1308 RtlInitUnicodeString(&SubKeyString,
1311 InitializeObjectAttributes(&ObjectAttributes,
1313 OBJ_CASE_INSENSITIVE,
1317 errCode = NtOpenKey(
1322 if ( !NT_SUCCESS(errCode) )
1324 ErrorCode = RtlNtStatusToDosError(errCode);
1326 SetLastError(ErrorCode);
1329 return ERROR_SUCCESS;
1333 /************************************************************************
1337 RegOpenKeyExA(HKEY hKey,
1343 OBJECT_ATTRIBUTES ObjectAttributes;
1344 UNICODE_STRING SubKeyString;
1349 Status = MapDefaultKey(&KeyHandle,
1351 if (!NT_SUCCESS(Status))
1353 ErrorCode = RtlNtStatusToDosError(Status);
1355 SetLastError(ErrorCode);
1359 RtlCreateUnicodeStringFromAsciiz(&SubKeyString,
1362 InitializeObjectAttributes(&ObjectAttributes,
1364 OBJ_CASE_INSENSITIVE,
1368 Status = NtOpenKey(phkResult,
1372 RtlFreeUnicodeString(&SubKeyString);
1374 if (!NT_SUCCESS(Status))
1376 ErrorCode = RtlNtStatusToDosError(Status);
1378 SetLastError(ErrorCode);
1382 return(ERROR_SUCCESS);
1386 /************************************************************************
1390 RegOpenKeyExW(HKEY hKey,
1396 OBJECT_ATTRIBUTES ObjectAttributes;
1397 UNICODE_STRING SubKeyString;
1402 Status = MapDefaultKey(&KeyHandle,
1404 if (!NT_SUCCESS(Status))
1406 ErrorCode = RtlNtStatusToDosError(Status);
1408 SetLastError (ErrorCode);
1412 RtlInitUnicodeString(&SubKeyString,
1415 InitializeObjectAttributes(&ObjectAttributes,
1417 OBJ_CASE_INSENSITIVE,
1421 Status = NtOpenKey(phkResult,
1424 if (!NT_SUCCESS(Status))
1426 ErrorCode = RtlNtStatusToDosError(Status);
1428 SetLastError(ErrorCode);
1431 return(ERROR_SUCCESS);
1435 /************************************************************************
1446 LPDWORD lpcbMaxSubKeyLen,
1447 LPDWORD lpcbMaxClassLen,
1449 LPDWORD lpcbMaxValueNameLen,
1450 LPDWORD lpcbMaxValueLen,
1451 LPDWORD lpcbSecurityDescriptor,
1452 PFILETIME lpftLastWriteTime
1455 WCHAR ClassName[MAX_PATH];
1456 UNICODE_STRING UnicodeString;
1457 ANSI_STRING AnsiString;
1460 RtlInitUnicodeString(&UnicodeString, NULL);
1464 UnicodeString.Buffer = &ClassName[0];
1465 UnicodeString.MaximumLength = sizeof(ClassName);
1468 ErrorCode = RegQueryInfoKeyW(
1470 UnicodeString.Buffer,
1477 lpcbMaxValueNameLen,
1479 lpcbSecurityDescriptor,
1482 if ((ErrorCode == ERROR_SUCCESS) && (lpClass))
1484 RtlInitAnsiString(&AnsiString, NULL);
1485 AnsiString.Buffer = lpClass;
1486 AnsiString.MaximumLength = *lpcbClass;
1487 RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
1488 *lpcbClass = AnsiString.Length;
1495 /************************************************************************
1506 LPDWORD lpcbMaxSubKeyLen,
1507 LPDWORD lpcbMaxClassLen,
1509 LPDWORD lpcbMaxValueNameLen,
1510 LPDWORD lpcbMaxValueLen,
1511 LPDWORD lpcbSecurityDescriptor,
1512 PFILETIME lpftLastWriteTime
1515 KEY_FULL_INFORMATION FullInfoBuffer;
1516 PKEY_FULL_INFORMATION FullInfo;
1523 if ((lpClass) && (!lpcbClass))
1525 SetLastError(ERROR_INVALID_PARAMETER);
1526 return ERROR_INVALID_PARAMETER;
1529 Status = MapDefaultKey(&KeyHandle, hKey);
1534 FullInfoSize = sizeof(KEY_FULL_INFORMATION) + *lpcbClass;
1535 FullInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullInfoSize);
1538 SetLastError(ERROR_OUTOFMEMORY);
1539 return ERROR_OUTOFMEMORY;
1542 FullInfo->ClassLength = *lpcbClass;
1546 FullInfoSize = sizeof(KEY_FULL_INFORMATION);
1547 FullInfo = &FullInfoBuffer;
1548 FullInfo->ClassLength = 1;
1551 FullInfo->ClassOffset = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
1553 Status = NtQueryKey(
1560 if (!NT_SUCCESS(Status))
1564 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1567 ErrorCode = RtlNtStatusToDosError(Status);
1568 SetLastError(ErrorCode);
1574 *lpcSubKeys = FullInfo->SubKeys;
1577 if (lpcbMaxSubKeyLen)
1579 *lpcbMaxSubKeyLen = FullInfo->MaxNameLen;
1582 if (lpcbMaxClassLen)
1584 *lpcbMaxClassLen = FullInfo->MaxClassLen;
1589 *lpcValues = FullInfo->Values;
1592 if (lpcbMaxValueNameLen)
1594 *lpcbMaxValueNameLen = FullInfo->MaxValueNameLen;
1597 if (lpcbMaxValueLen)
1599 *lpcbMaxValueLen = FullInfo->MaxValueDataLen;
1602 if (lpcbSecurityDescriptor)
1604 *lpcbSecurityDescriptor = 0;
1608 if (lpftLastWriteTime != NULL)
1610 lpftLastWriteTime->dwLowDateTime = FullInfo->LastWriteTime.u.LowPart;
1611 lpftLastWriteTime->dwHighDateTime = FullInfo->LastWriteTime.u.HighPart;
1616 wcsncpy(lpClass, FullInfo->Class, *lpcbClass);
1617 RtlFreeHeap(RtlGetProcessHeap(), 0, FullInfo);
1620 SetLastError(ERROR_SUCCESS);
1621 return ERROR_SUCCESS;
1625 /************************************************************************
1626 * RegQueryMultipleValuesA
1630 RegQueryMultipleValuesA(
1639 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1640 return ERROR_CALL_NOT_IMPLEMENTED;
1644 /************************************************************************
1645 * RegQueryMultipleValuesW
1649 RegQueryMultipleValuesW(
1658 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1659 return ERROR_CALL_NOT_IMPLEMENTED;
1663 /************************************************************************
1675 WCHAR SubKeyNameBuffer[MAX_PATH+1];
1676 UNICODE_STRING SubKeyName;
1677 UNICODE_STRING Value;
1678 ANSI_STRING AnsiString;
1682 if ((lpValue) && (!lpcbValue))
1684 SetLastError(ERROR_INVALID_PARAMETER);
1685 return ERROR_INVALID_PARAMETER;
1688 RtlInitUnicodeString(&SubKeyName, NULL);
1689 RtlInitUnicodeString(&Value, NULL);
1691 if ((lpSubKey) && (strlen(lpSubKey) != 0))
1693 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
1694 SubKeyName.Buffer = &SubKeyNameBuffer[0];
1695 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
1696 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
1701 ValueSize = *lpcbValue * sizeof(WCHAR);
1702 Value.MaximumLength = ValueSize;
1703 Value.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, ValueSize);
1706 SetLastError(ERROR_OUTOFMEMORY);
1707 return ERROR_OUTOFMEMORY;
1715 ErrorCode = RegQueryValueW(
1717 (LPCWSTR)SubKeyName.Buffer,
1721 if (ErrorCode == ERROR_SUCCESS)
1723 Value.Length = ValueSize;
1724 RtlInitAnsiString(&AnsiString, NULL);
1725 AnsiString.Buffer = lpValue;
1726 AnsiString.MaximumLength = *lpcbValue;
1727 RtlUnicodeStringToAnsiString(&AnsiString, &Value, FALSE);
1730 *lpcbValue = ValueSize;
1734 RtlFreeHeap(RtlGetProcessHeap(), 0, Value.Buffer);
1741 /************************************************************************
1755 WCHAR ValueNameBuffer[MAX_PATH+1];
1756 UNICODE_STRING ValueName;
1757 UNICODE_STRING ValueData;
1758 ANSI_STRING AnsiString;
1763 /* FIXME: HKEY_PERFORMANCE_DATA is special, see MS SDK */
1765 if ((lpData) && (!lpcbData))
1767 SetLastError(ERROR_INVALID_PARAMETER);
1768 return ERROR_INVALID_PARAMETER;
1771 RtlInitUnicodeString(&ValueData, NULL);
1775 ValueData.MaximumLength = *lpcbData * sizeof(WCHAR);
1776 ValueData.Buffer = RtlAllocateHeap(
1777 RtlGetProcessHeap(),
1779 ValueData.MaximumLength);
1780 if (!ValueData.Buffer)
1782 SetLastError(ERROR_OUTOFMEMORY);
1783 return ERROR_OUTOFMEMORY;
1787 RtlInitAnsiString(&AnsiString, (LPSTR)lpValueName);
1788 RtlInitUnicodeString(&ValueName, NULL);
1789 ValueName.Buffer = &ValueNameBuffer[0];
1790 ValueName.MaximumLength = sizeof(ValueNameBuffer);
1791 RtlAnsiStringToUnicodeString(&ValueName, &AnsiString, FALSE);
1795 ResultSize = *lpcbData;
1802 ErrorCode = RegQueryValueExW(
1807 (LPBYTE)ValueData.Buffer,
1810 if ((ErrorCode == ERROR_SUCCESS) && (ValueData.Buffer != NULL))
1817 if ((Type == REG_SZ) || (Type == REG_MULTI_SZ) || (Type == REG_EXPAND_SZ))
1819 ValueData.Length = ResultSize;
1820 RtlInitAnsiString(&AnsiString, NULL);
1821 AnsiString.Buffer = lpData;
1822 AnsiString.MaximumLength = *lpcbData;
1823 RtlUnicodeStringToAnsiString(&AnsiString, &ValueData, FALSE);
1827 RtlMoveMemory(lpData, ValueData.Buffer, ResultSize);
1833 *lpcbData = ResultSize;
1836 if (ValueData.Buffer)
1838 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueData.Buffer);
1845 /************************************************************************
1859 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
1860 UNICODE_STRING ValueName;
1862 DWORD dwError = ERROR_SUCCESS;
1867 DPRINT("hKey 0x%X lpValueName %S lpData 0x%X lpcbData %d\n",
1868 hKey, lpValueName, lpData, lpcbData ? *lpcbData : 0);
1870 Status = MapDefaultKey(&KeyHandle, hKey);
1871 if (!NT_SUCCESS(Status))
1873 dwError = RtlNtStatusToDosError(Status);
1874 SetLastError(dwError);
1878 if ((lpData) && (!lpcbData))
1880 SetLastError(ERROR_INVALID_PARAMETER);
1881 return ERROR_INVALID_PARAMETER;
1884 RtlInitUnicodeString (&ValueName,
1887 BufferSize = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + *lpcbData;
1888 ValueInfo = RtlAllocateHeap (RtlGetProcessHeap(),
1891 if (ValueInfo == NULL)
1893 SetLastError(ERROR_OUTOFMEMORY);
1894 return ERROR_OUTOFMEMORY;
1897 Status = NtQueryValueKey (hKey,
1899 KeyValuePartialInformation,
1904 DPRINT("Status 0x%X\n", Status);
1906 if (Status == STATUS_BUFFER_TOO_SMALL)
1908 /* Return ERROR_SUCCESS and the buffer space needed for a successful call */
1909 dwError = ERROR_SUCCESS;
1911 else if (!NT_SUCCESS(Status))
1913 dwError = RtlNtStatusToDosError(Status);
1914 SetLastError(dwError);
1920 *lpType = ValueInfo->Type;
1923 RtlMoveMemory(lpData, ValueInfo->Data, ValueInfo->DataLength);
1924 if ((ValueInfo->Type == REG_SZ) ||
1925 (ValueInfo->Type == REG_MULTI_SZ) ||
1926 (ValueInfo->Type == REG_EXPAND_SZ))
1928 ((PWSTR)lpData)[ValueInfo->DataLength / sizeof(WCHAR)] = 0;
1932 DPRINT("Type %d ResultSize %d\n", ValueInfo->Type, ResultSize);
1934 *lpcbData = (DWORD)ResultSize;
1936 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
1942 /************************************************************************
1955 UNICODE_STRING SubKeyString;
1956 OBJECT_ATTRIBUTES ObjectAttributes;
1962 errCode = MapDefaultKey(&KeyHandle, hKey);
1963 if (!NT_SUCCESS(errCode))
1965 ErrorCode = RtlNtStatusToDosError(errCode);
1966 SetLastError (ErrorCode);
1970 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
1973 RtlInitUnicodeString(&SubKeyString,
1976 InitializeObjectAttributes(&ObjectAttributes,
1978 OBJ_CASE_INSENSITIVE,
1982 errCode = NtOpenKey(
1987 if ( !NT_SUCCESS(errCode) )
1989 ErrorCode = RtlNtStatusToDosError(errCode);
1990 SetLastError(ErrorCode);
1993 CloseRealKey = TRUE;
1998 CloseRealKey = FALSE;
2001 ErrorCode = RegQueryValueExW(
2007 (LPDWORD)lpcbValue);
2018 /************************************************************************
2031 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2032 return ERROR_CALL_NOT_IMPLEMENTED;
2036 /************************************************************************
2049 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2050 return ERROR_CALL_NOT_IMPLEMENTED;
2054 /************************************************************************
2066 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2067 return ERROR_CALL_NOT_IMPLEMENTED;
2071 /************************************************************************
2083 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2084 return ERROR_CALL_NOT_IMPLEMENTED;
2088 /************************************************************************
2092 RegSaveKeyA(HKEY hKey,
2094 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2096 UNICODE_STRING FileName;
2099 RtlCreateUnicodeStringFromAsciiz(&FileName,
2101 ErrorCode = RegSaveKeyW(hKey,
2103 lpSecurityAttributes);
2104 RtlFreeUnicodeString(&FileName);
2110 /************************************************************************
2114 RegSaveKeyW(HKEY hKey,
2116 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
2118 PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
2119 OBJECT_ATTRIBUTES ObjectAttributes;
2120 UNICODE_STRING NtName;
2121 IO_STATUS_BLOCK IoStatusBlock;
2127 Status = MapDefaultKey(&KeyHandle,
2129 if (!NT_SUCCESS(Status))
2131 ErrorCode = RtlNtStatusToDosError(Status);
2132 SetLastError(ErrorCode);
2136 if (!RtlDosPathNameToNtPathName_U((LPWSTR)lpFile,
2141 SetLastError(ERROR_INVALID_PARAMETER);
2142 return(ERROR_INVALID_PARAMETER);
2145 if (lpSecurityAttributes != NULL)
2146 SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
2148 InitializeObjectAttributes(&ObjectAttributes,
2150 OBJ_CASE_INSENSITIVE,
2152 SecurityDescriptor);
2154 Status = NtCreateFile(&FileHandle,
2155 GENERIC_WRITE | SYNCHRONIZE,
2159 FILE_ATTRIBUTE_NORMAL,
2162 FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
2165 RtlFreeUnicodeString(&NtName);
2166 if (!NT_SUCCESS(Status))
2168 ErrorCode = RtlNtStatusToDosError(Status);
2169 SetLastError(ErrorCode);
2173 Status = NtSaveKey(KeyHandle,
2175 NtClose(FileHandle);
2176 if (!NT_SUCCESS(Status))
2178 ErrorCode = RtlNtStatusToDosError(Status);
2179 SetLastError(ErrorCode);
2183 return(ERROR_SUCCESS);
2187 /************************************************************************
2194 SECURITY_INFORMATION SecurityInformation, /* FIXME: ULONG? */
2195 PSECURITY_DESCRIPTOR pSecurityDescriptor
2199 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2200 return ERROR_CALL_NOT_IMPLEMENTED;
2204 /************************************************************************
2217 WCHAR SubKeyNameBuffer[MAX_PATH+1];
2218 UNICODE_STRING SubKeyName;
2219 UNICODE_STRING Data;
2220 ANSI_STRING AnsiString;
2226 SetLastError(ERROR_INVALID_PARAMETER);
2227 return ERROR_INVALID_PARAMETER;
2230 RtlInitUnicodeString(&SubKeyName, NULL);
2231 RtlInitUnicodeString(&Data, NULL);
2233 if ((lpSubKey) && (strlen(lpSubKey) != 0))
2235 RtlInitAnsiString(&AnsiString, (LPSTR)lpSubKey);
2236 SubKeyName.Buffer = &SubKeyNameBuffer[0];
2237 SubKeyName.MaximumLength = sizeof(SubKeyNameBuffer);
2238 RtlAnsiStringToUnicodeString(&SubKeyName, &AnsiString, FALSE);
2241 DataSize = cbData * sizeof(WCHAR);
2242 Data.MaximumLength = DataSize;
2243 Data.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DataSize);
2246 SetLastError(ERROR_OUTOFMEMORY);
2247 return ERROR_OUTOFMEMORY;
2250 ErrorCode = RegSetValueW(
2252 (LPCWSTR)SubKeyName.Buffer,
2257 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2263 /************************************************************************
2277 UNICODE_STRING ValueName;
2279 ANSI_STRING AnsiString;
2280 UNICODE_STRING Data;
2287 SetLastError(ERROR_INVALID_PARAMETER);
2288 return ERROR_INVALID_PARAMETER;
2291 if ((lpValueName) && (strlen(lpValueName) != 0))
2293 RtlCreateUnicodeStringFromAsciiz(&ValueName, (LPSTR)lpValueName);
2294 pValueName = (LPWSTR)ValueName.Buffer;
2301 if ((dwType == REG_SZ) || (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ))
2303 RtlInitAnsiString(&AnsiString, NULL);
2304 AnsiString.Buffer = (LPSTR)lpData;
2305 AnsiString.Length = cbData;
2306 AnsiString.MaximumLength = cbData;
2307 RtlAnsiStringToUnicodeString(&Data, &AnsiString, TRUE);
2308 pData = (LPBYTE)Data.Buffer;
2309 DataSize = cbData * sizeof(WCHAR);
2313 RtlInitUnicodeString(&Data, NULL);
2314 pData = (LPBYTE)lpData;
2318 ErrorCode = RegSetValueExW(
2328 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueName.Buffer);
2333 RtlFreeHeap(RtlGetProcessHeap(), 0, Data.Buffer);
2340 /************************************************************************
2347 LPCWSTR lpValueName,
2354 UNICODE_STRING ValueName;
2355 PUNICODE_STRING pValueName;
2360 Status = MapDefaultKey(&KeyHandle, hKey);
2361 if (!NT_SUCCESS(Status))
2363 ErrorCode = RtlNtStatusToDosError(Status);
2364 SetLastError(ErrorCode);
2370 RtlInitUnicodeString(&ValueName, lpValueName);
2371 pValueName = &ValueName;
2378 Status = NtSetValueKey(
2385 if (!NT_SUCCESS(Status))
2387 LONG ErrorCode = RtlNtStatusToDosError(Status);
2388 SetLastError (ErrorCode);
2392 return ERROR_SUCCESS;
2396 /************************************************************************
2410 UNICODE_STRING SubKeyString;
2411 OBJECT_ATTRIBUTES ObjectAttributes;
2417 errCode = MapDefaultKey(&KeyHandle, hKey);
2418 if (!NT_SUCCESS(errCode))
2420 ErrorCode = RtlNtStatusToDosError(errCode);
2421 SetLastError (ErrorCode);
2425 if ((lpSubKey) && (wcslen(lpSubKey) != 0))
2428 RtlInitUnicodeString(&SubKeyString,
2431 InitializeObjectAttributes(&ObjectAttributes,
2433 OBJ_CASE_INSENSITIVE,
2437 errCode = NtOpenKey(
2442 if ( !NT_SUCCESS(errCode) )
2444 ErrorCode = RtlNtStatusToDosError(errCode);
2445 SetLastError(ErrorCode);
2448 CloseRealKey = TRUE;
2453 CloseRealKey = FALSE;
2456 ErrorCode = RegSetValueExW(
2473 /************************************************************************
2484 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2485 return ERROR_CALL_NOT_IMPLEMENTED;
2489 /************************************************************************
2500 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2501 return ERROR_CALL_NOT_IMPLEMENTED;