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;