2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/ntfunc.c
5 * PURPOSE: Ntxxx function for registry access
9 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
19 #include <internal/pool.h>
20 #include <internal/registry.h>
23 #include <internal/debug.h>
29 /* GLOBALS ******************************************************************/
31 extern POBJECT_TYPE CmiKeyType;
32 extern PREGISTRY_HIVE CmiVolatileHive;
34 static BOOLEAN CmiRegistryInitialized = FALSE;
37 /* FUNCTIONS ****************************************************************/
40 NtCreateKey(OUT PHANDLE KeyHandle,
41 IN ACCESS_MASK DesiredAccess,
42 IN POBJECT_ATTRIBUTES ObjectAttributes,
44 IN PUNICODE_STRING Class,
45 IN ULONG CreateOptions,
46 OUT PULONG Disposition)
48 UNICODE_STRING RemainingPath;
49 PKEY_OBJECT KeyObject;
54 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
55 ObjectAttributes->ObjectName,
57 ObjectAttributes->RootDirectory);
59 /* FIXME: check for standard handle prefix and adjust objectAttributes accordingly */
61 Status = ObFindObject(ObjectAttributes,
65 if (!NT_SUCCESS(Status))
70 DPRINT("RemainingPath %wZ\n", &RemainingPath);
72 if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
74 /* Fail if the key has been deleted */
75 if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
77 ObDereferenceObject(Object);
78 return(STATUS_UNSUCCESSFUL);
82 *Disposition = REG_OPENED_EXISTING_KEY;
84 Status = ObCreateHandle(PsGetCurrentProcess(),
90 DPRINT("Status %x\n", Status);
91 ObDereferenceObject(Object);
95 /* If RemainingPath contains \ we must return error
96 because NtCreateKey don't create trees */
97 if (RemainingPath.Buffer[0] == '\\')
98 End = wcschr(RemainingPath.Buffer + 1, '\\');
100 End = wcschr(RemainingPath.Buffer, '\\');
104 ObDereferenceObject(Object);
105 return STATUS_UNSUCCESSFUL;
108 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object);
110 Status = ObCreateObject(KeyHandle,
115 if (!NT_SUCCESS(Status))
120 KeyObject->ParentKey = Object;
122 if (CreateOptions & REG_OPTION_VOLATILE)
123 KeyObject->RegistryHive = CmiVolatileHive;
125 KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive;
127 KeyObject->Flags = 0;
128 KeyObject->NumberOfSubKeys = 0;
129 KeyObject->SizeOfSubKeys = 0;
130 KeyObject->SubKeys = NULL;
132 /* Acquire hive lock */
133 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
135 /* add key to subkeys of parent if needed */
136 Status = CmiAddSubKey(KeyObject->RegistryHive,
137 KeyObject->ParentKey,
139 RemainingPath.Buffer,
140 RemainingPath.Length,
144 if (!NT_SUCCESS(Status))
146 /* Release hive lock */
147 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
148 ObDereferenceObject(KeyObject);
149 ObDereferenceObject(Object);
150 return STATUS_UNSUCCESSFUL;
153 KeyObject->Name = KeyObject->KeyCell->Name;
154 KeyObject->NameSize = KeyObject->KeyCell->NameSize;
156 if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
158 KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset;
159 KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
163 KeyObject->KeyCell->ParentKeyOffset = -1;
164 KeyObject->KeyCell->SecurityKeyOffset = -1;
165 /* This key must remain in memory unless it is deleted
166 or file is unloaded */
167 ObReferenceObjectByPointer(KeyObject,
168 STANDARD_RIGHTS_REQUIRED,
173 CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
175 VERIFY_KEY_OBJECT(KeyObject);
177 /* Release hive lock */
178 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
180 ObDereferenceObject(KeyObject);
181 ObDereferenceObject(Object);
184 *Disposition = REG_CREATED_NEW_KEY;
193 NtDeleteKey(IN HANDLE KeyHandle)
195 PKEY_OBJECT KeyObject;
198 DPRINT("KeyHandle %x\n", KeyHandle);
200 /* Verify that the handle is valid and is a registry key */
202 Status = ObReferenceObjectByHandle(KeyHandle,
208 if (!NT_SUCCESS(Status))
215 /* Acquire hive lock */
216 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
219 VERIFY_KEY_OBJECT(KeyObject);
221 /* Set the marked for delete bit in the key object */
222 KeyObject->Flags |= KO_MARKED_FOR_DELETE;
225 /* Release hive lock */
226 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
228 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
230 /* Dereference the object */
231 ObDereferenceObject(KeyObject);
232 if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
233 ObDereferenceObject(KeyObject);
235 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
239 * Hive-Synchronization will not be triggered here. This is done in
240 * CmiObjectDelete() (in regobj.c) after all key-related structures
241 * have been released.
244 return(STATUS_SUCCESS);
252 IN KEY_INFORMATION_CLASS KeyInformationClass,
253 OUT PVOID KeyInformation,
255 OUT PULONG ResultLength
259 PKEY_OBJECT KeyObject;
260 PREGISTRY_HIVE RegistryHive;
261 PKEY_CELL KeyCell, SubKeyCell;
262 PHASH_TABLE_CELL HashTableBlock;
263 PKEY_BASIC_INFORMATION BasicInformation;
264 PKEY_NODE_INFORMATION NodeInformation;
265 PKEY_FULL_INFORMATION FullInformation;
266 PDATA_CELL pClassData;
268 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
276 /* Verify that the handle is valid and is a registry key */
277 Status = ObReferenceObjectByHandle(KeyHandle,
278 KEY_ENUMERATE_SUB_KEYS,
281 (PVOID *) &KeyObject,
283 if (!NT_SUCCESS(Status))
285 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
289 /* Acquire hive lock */
290 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
292 VERIFY_KEY_OBJECT(KeyObject);
294 /* Get pointer to KeyCell */
295 KeyCell = KeyObject->KeyCell;
296 RegistryHive = KeyObject->RegistryHive;
298 /* Get pointer to SubKey */
299 if (Index >= KeyCell->NumberOfSubKeys)
301 if (RegistryHive == CmiVolatileHive)
303 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
304 ObDereferenceObject(KeyObject);
305 DPRINT("No more volatile entries\n");
306 return(STATUS_NO_MORE_ENTRIES);
311 PKEY_OBJECT CurKey = NULL;
313 /* Search volatile keys */
314 for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
316 CurKey = KeyObject->SubKeys[i];
317 if (CurKey->RegistryHive == CmiVolatileHive)
319 if (Index-- == KeyObject->NumberOfSubKeys)
323 if (Index >= KeyCell->NumberOfSubKeys)
325 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
326 ObDereferenceObject(KeyObject);
327 DPRINT("No more non-volatile entries\n");
328 return(STATUS_NO_MORE_ENTRIES);
330 SubKeyCell = CurKey->KeyCell;
335 HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
336 SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
341 if (SubKeyCell == NULL)
343 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
344 ObDereferenceObject(KeyObject);
345 DPRINT("No more entries\n");
346 return(STATUS_NO_MORE_ENTRIES);
349 Status = STATUS_SUCCESS;
350 switch (KeyInformationClass)
352 case KeyBasicInformation:
353 /* Check size of buffer */
354 *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
355 (SubKeyCell->NameSize ) * sizeof(WCHAR);
356 if (Length < *ResultLength)
358 Status = STATUS_BUFFER_OVERFLOW;
362 /* Fill buffer with requested info */
363 BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
364 BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime;
365 BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime;
366 BasicInformation->TitleIndex = Index;
367 BasicInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR);
368 mbstowcs(BasicInformation->Name,
370 SubKeyCell->NameSize * 2);
371 // BasicInformation->Name[SubKeyCell->NameSize] = 0;
375 case KeyNodeInformation:
376 /* Check size of buffer */
377 *ResultLength = sizeof(KEY_NODE_INFORMATION) +
378 SubKeyCell->NameSize * sizeof(WCHAR) +
379 SubKeyCell->ClassSize;
380 if (Length < *ResultLength)
382 Status = STATUS_BUFFER_OVERFLOW;
386 /* Fill buffer with requested info */
387 NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
388 NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime;
389 NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime;
390 NodeInformation->TitleIndex = Index;
391 NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
392 SubKeyCell->NameSize * sizeof(WCHAR);
393 NodeInformation->ClassLength = SubKeyCell->ClassSize;
394 NodeInformation->NameLength = SubKeyCell->NameSize * sizeof(WCHAR);
395 mbstowcs(NodeInformation->Name,
397 SubKeyCell->NameSize * 2);
398 // NodeInformation->Name[SubKeyCell->NameSize] = 0;
399 if (SubKeyCell->ClassSize != 0)
401 pClassData=CmiGetBlock(KeyObject->RegistryHive,
402 SubKeyCell->ClassNameOffset,
404 wcsncpy(NodeInformation->Name + SubKeyCell->NameSize ,
405 (PWCHAR) pClassData->Data,
406 SubKeyCell->ClassSize);
407 CmiReleaseBlock(RegistryHive, pClassData);
412 case KeyFullInformation:
413 /* check size of buffer */
414 *ResultLength = sizeof(KEY_FULL_INFORMATION) +
415 SubKeyCell->ClassSize;
416 if (Length < *ResultLength)
418 Status = STATUS_BUFFER_OVERFLOW;
422 /* fill buffer with requested info */
423 FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
424 FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.dwLowDateTime;
425 FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.dwHighDateTime;
426 FullInformation->TitleIndex = Index;
427 FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
429 FullInformation->ClassLength = SubKeyCell->ClassSize;
430 FullInformation->SubKeys = SubKeyCell->NumberOfSubKeys;
431 FullInformation->MaxNameLen =
432 CmiGetMaxNameLength(RegistryHive, SubKeyCell);
433 FullInformation->MaxClassLen =
434 CmiGetMaxClassLength(RegistryHive, SubKeyCell);
435 FullInformation->Values = SubKeyCell->NumberOfValues;
436 FullInformation->MaxValueNameLen =
437 CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
438 FullInformation->MaxValueDataLen =
439 CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
440 if (SubKeyCell->ClassSize != 0)
442 pClassData = CmiGetBlock(KeyObject->RegistryHive,
443 SubKeyCell->ClassNameOffset,
445 wcsncpy(FullInformation->Class,
446 (PWCHAR) pClassData->Data,
447 SubKeyCell->ClassSize);
448 CmiReleaseBlock(RegistryHive, pClassData);
453 CmiReleaseBlock(RegistryHive, SubKeyCell);
455 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
456 ObDereferenceObject(KeyObject);
458 DPRINT("Returning status %x\n", Status);
465 NtEnumerateValueKey(IN HANDLE KeyHandle,
467 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
468 OUT PVOID KeyValueInformation,
470 OUT PULONG ResultLength)
473 PKEY_OBJECT KeyObject;
474 PREGISTRY_HIVE RegistryHive;
476 PVALUE_CELL ValueCell;
478 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
479 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
480 PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
482 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
485 KeyValueInformationClass,
490 /* Verify that the handle is valid and is a registry key */
491 Status = ObReferenceObjectByHandle(KeyHandle,
495 (PVOID *) &KeyObject,
498 if (!NT_SUCCESS(Status))
503 /* Acquire hive lock */
504 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
506 VERIFY_KEY_OBJECT(KeyObject);
508 /* Get pointer to KeyCell */
509 KeyCell = KeyObject->KeyCell;
510 RegistryHive = KeyObject->RegistryHive;
512 /* Get Value block of interest */
513 Status = CmiGetValueFromKeyByIndex(RegistryHive,
518 if (!NT_SUCCESS(Status))
520 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
521 ObDereferenceObject(KeyObject);
525 if (ValueCell != NULL)
527 switch (KeyValueInformationClass)
529 case KeyValueBasicInformation:
530 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
532 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
533 (ValueCell->NameSize + 1) * sizeof(WCHAR);
537 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
538 ValueCell->NameSize + sizeof(WCHAR);
540 if (Length < *ResultLength)
542 Status = STATUS_BUFFER_OVERFLOW;
546 ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
548 ValueBasicInformation->TitleIndex = 0;
549 ValueBasicInformation->Type = ValueCell->DataType;
550 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
552 ValueBasicInformation->NameLength =
553 (ValueCell->NameSize + 1) * sizeof(WCHAR);
554 CmiCopyPackedName(ValueBasicInformation->Name,
556 ValueCell->NameSize);
557 ValueBasicInformation->Name[ValueCell->NameSize] = 0;
561 ValueBasicInformation->NameLength =
562 ValueCell->NameSize + sizeof(WCHAR);
563 RtlCopyMemory(ValueBasicInformation->Name,
565 ValueCell->NameSize * sizeof(WCHAR));
566 ValueBasicInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
571 case KeyValuePartialInformation:
572 *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
573 (ValueCell->DataSize & LONG_MAX);
574 if (Length < *ResultLength)
576 Status = STATUS_BUFFER_OVERFLOW;
580 ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
582 ValuePartialInformation->TitleIndex = 0;
583 ValuePartialInformation->Type = ValueCell->DataType;
584 ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
585 if(ValueCell->DataSize >0)
587 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
588 RtlCopyMemory(ValuePartialInformation->Data,
590 ValueCell->DataSize & LONG_MAX);
591 CmiReleaseBlock(RegistryHive, DataCell);
595 RtlCopyMemory(ValuePartialInformation->Data,
596 &ValueCell->DataOffset,
597 ValueCell->DataSize & LONG_MAX);
599 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
603 case KeyValueFullInformation:
604 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
606 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
607 (ValueCell->NameSize + 1) * sizeof(WCHAR) +
608 (ValueCell->DataSize & LONG_MAX);
612 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
613 ValueCell->NameSize + sizeof(WCHAR) +
614 (ValueCell->DataSize & LONG_MAX);
616 if (Length < *ResultLength)
618 Status = STATUS_BUFFER_OVERFLOW;
622 ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
624 ValueFullInformation->TitleIndex = 0;
625 ValueFullInformation->Type = ValueCell->DataType;
626 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
628 ValueFullInformation->NameLength =
629 (ValueCell->NameSize + 1) * sizeof(WCHAR);
631 CmiCopyPackedName(ValueFullInformation->Name,
633 ValueCell->NameSize);
634 ValueFullInformation->Name[ValueCell->NameSize] = 0;
638 ValueFullInformation->NameLength =
639 ValueCell->NameSize + sizeof(WCHAR);
640 RtlCopyMemory(ValueFullInformation->Name,
642 ValueCell->NameSize);
643 ValueFullInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
645 ValueFullInformation->DataOffset =
646 (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
647 ValueFullInformation->NameLength;
648 ValueFullInformation->DataOffset =
649 (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
650 ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
651 if (ValueCell->DataSize > 0)
653 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
654 RtlCopyMemory((PCHAR) ValueFullInformation
655 + ValueFullInformation->DataOffset,
657 ValueCell->DataSize & LONG_MAX);
658 CmiReleaseBlock(RegistryHive, DataCell);
662 RtlCopyMemory((PCHAR) ValueFullInformation
663 + ValueFullInformation->DataOffset,
664 &ValueCell->DataOffset,
665 ValueCell->DataSize & LONG_MAX);
673 Status = STATUS_UNSUCCESSFUL;
676 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
677 ObDereferenceObject(KeyObject);
684 NtFlushKey(IN HANDLE KeyHandle)
687 PKEY_OBJECT KeyObject;
688 PREGISTRY_HIVE RegistryHive;
690 WCHAR LogName[MAX_PATH];
691 UNICODE_STRING TmpFileName;
693 // HANDLE FileHandleLog;
694 OBJECT_ATTRIBUTES ObjectAttributes;
695 LARGE_INTEGER fileOffset;
700 DPRINT("KeyHandle %x\n", KeyHandle);
702 /* Verify that the handle is valid and is a registry key */
703 Status = ObReferenceObjectByHandle(KeyHandle,
709 if (!NT_SUCCESS(Status))
714 VERIFY_KEY_OBJECT(KeyObject);
716 RegistryHive = KeyObject->RegistryHive;
718 /* Acquire hive lock */
719 ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
722 if (IsPermanentHive(RegistryHive))
724 /* Flush non-volatile hive */
725 Status = CmiFlushRegistryHive(RegistryHive);
729 Status = STATUS_SUCCESS;
734 /* Then write changed blocks in .log */
735 wcscpy(LogName,RegistryHive->Filename.Buffer);
736 wcscat(LogName,L".log");
737 RtlInitUnicodeString (&TmpFileName, LogName);
738 InitializeObjectAttributes(&ObjectAttributes,
744 /* BEGIN FIXME : actually (26 November 200) vfatfs.sys can't create new files
745 so we can't create log file
746 Status = ZwCreateFile(&FileHandleLog,
751 FILE_ATTRIBUTE_NORMAL,
758 if (!NT_SUCCESS(Status))
760 ObDereferenceObject(KeyObject);
764 Status = ZwWriteFile(FileHandleLog,
769 RegistryHive->HiveHeader,
774 if (!NT_SUCCESS(Status))
776 ZwClose(FileHandleLog);
777 ObDereferenceObject(KeyObject);
781 for (i = 0; i < RegistryHive->BlockListSize ; i++)
783 if ( RegistryHive->BlockList[i]->DateModified.dwHighDateTime
784 > RegistryHive->HiveHeader->DateModified.dwHighDateTime
785 || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
786 == RegistryHive->HiveHeader->DateModified.dwHighDateTime
787 && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
788 > RegistryHive->HiveHeader->DateModified.dwLowDateTime
792 Status = ZwWriteFile(FileHandleLog,
797 RegistryHive->BlockList[i],
798 RegistryHive->BlockList[i]->BlockSize ,
802 if (!NT_SUCCESS(Status))
804 ZwClose(FileHandleLog);
805 ObDereferenceObject(KeyObject);
809 ZwClose(FileHandleLog);
812 /* Update header of RegistryHive with Version >VersionOld */
813 /* this allow recover if system crash while updating hove file */
814 InitializeObjectAttributes(&ObjectAttributes,
815 &RegistryHive->Filename,
820 Status = NtOpenFile(&FileHandle,
825 FILE_SYNCHRONOUS_IO_NONALERT);
826 if (!NT_SUCCESS(Status))
828 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
829 ObDereferenceObject(KeyObject);
833 RegistryHive->HiveHeader->Version++;
835 Status = ZwWriteFile(FileHandle,
840 RegistryHive->HiveHeader,
844 if (!NT_SUCCESS(Status))
847 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
848 ObDereferenceObject(KeyObject);
852 /* Update changed blocks in file */
853 fileOffset.u.HighPart = 0;
854 for (i = 0; i < RegistryHive->BlockListSize ; i++)
856 if (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
857 > RegistryHive->HiveHeader->DateModified.dwHighDateTime
858 || (RegistryHive->BlockList[i]->DateModified.dwHighDateTime
859 == RegistryHive->HiveHeader->DateModified.dwHighDateTime
860 && RegistryHive->BlockList[i]->DateModified.dwLowDateTime
861 > RegistryHive->HiveHeader->DateModified.dwLowDateTime))
863 fileOffset.u.LowPart = RegistryHive->BlockList[i]->BlockOffset+4096;
864 Status = NtWriteFile(FileHandle,
869 RegistryHive->BlockList[i],
870 RegistryHive->BlockList[i]->BlockSize,
873 if (!NT_SUCCESS(Status))
876 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
877 ObDereferenceObject(KeyObject);
883 /* Change version in header */
884 RegistryHive->HiveHeader->VersionOld = RegistryHive->HiveHeader->Version;
885 ZwQuerySystemTime((PTIME) &RegistryHive->HiveHeader->DateModified);
887 /* Calculate checksum */
888 RegistryHive->HiveHeader->Checksum = 0;
889 pEntDword = (DWORD *) RegistryHive->HiveHeader;
890 for (i = 0; i < 127 ; i++)
892 RegistryHive->HiveHeader->Checksum ^= pEntDword[i];
895 /* Write new header */
896 fileOffset.u.LowPart = 0;
897 Status = ZwWriteFile(FileHandle,
902 RegistryHive->HiveHeader,
907 if (!NT_SUCCESS(Status))
910 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
911 ObDereferenceObject(KeyObject);
918 ExReleaseResourceLite(&RegistryHive->HiveResource);
920 ObDereferenceObject(KeyObject);
922 return STATUS_SUCCESS;
927 NtOpenKey(OUT PHANDLE KeyHandle,
928 IN ACCESS_MASK DesiredAccess,
929 IN POBJECT_ATTRIBUTES ObjectAttributes)
931 UNICODE_STRING RemainingPath;
935 DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
939 ObjectAttributes ? ObjectAttributes->ObjectName : NULL);
941 RemainingPath.Buffer = NULL;
942 Status = ObFindObject(ObjectAttributes,
946 if (!NT_SUCCESS(Status))
951 VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
953 DPRINT("RemainingPath '%wZ'\n", &RemainingPath);
955 if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
957 ObDereferenceObject(Object);
958 return(STATUS_UNSUCCESSFUL);
961 /* Fail if the key has been deleted */
962 if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
964 ObDereferenceObject(Object);
965 return(STATUS_UNSUCCESSFUL);
968 Status = ObCreateHandle(PsGetCurrentProcess(),
973 ObDereferenceObject(Object);
975 if (!NT_SUCCESS(Status))
980 return(STATUS_SUCCESS);
985 NtQueryKey(IN HANDLE KeyHandle,
986 IN KEY_INFORMATION_CLASS KeyInformationClass,
987 OUT PVOID KeyInformation,
989 OUT PULONG ResultLength)
991 PKEY_BASIC_INFORMATION BasicInformation;
992 PKEY_NODE_INFORMATION NodeInformation;
993 PKEY_FULL_INFORMATION FullInformation;
994 PREGISTRY_HIVE RegistryHive;
995 PDATA_CELL pClassData;
996 PKEY_OBJECT KeyObject;
1000 DPRINT("KH %x KIC %x KI %x L %d RL %x\n",
1002 KeyInformationClass,
1007 /* Verify that the handle is valid and is a registry key */
1008 Status = ObReferenceObjectByHandle(KeyHandle,
1012 (PVOID *) &KeyObject,
1014 if (!NT_SUCCESS(Status))
1021 /* Acquire hive lock */
1022 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1025 VERIFY_KEY_OBJECT(KeyObject);
1027 /* Get pointer to KeyCell */
1028 KeyCell = KeyObject->KeyCell;
1029 RegistryHive = KeyObject->RegistryHive;
1031 Status = STATUS_SUCCESS;
1032 switch (KeyInformationClass)
1034 case KeyBasicInformation:
1036 /* Check size of buffer */
1037 if (Length < sizeof(KEY_BASIC_INFORMATION) +
1038 KeyObject->NameSize * sizeof(WCHAR))
1040 Status = STATUS_BUFFER_OVERFLOW;
1044 /* Fill buffer with requested info */
1045 BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
1046 BasicInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime;
1047 BasicInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime;
1048 BasicInformation->TitleIndex = 0;
1049 BasicInformation->NameLength = (KeyObject->NameSize) * sizeof(WCHAR);
1050 mbstowcs(BasicInformation->Name,
1052 KeyObject->NameSize*sizeof(WCHAR));
1053 *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
1054 KeyObject->NameSize * sizeof(WCHAR);
1059 case KeyNodeInformation:
1060 /* Check size of buffer */
1061 if (Length < sizeof(KEY_NODE_INFORMATION)
1062 + KeyObject->NameSize * sizeof(WCHAR)
1063 + KeyCell->ClassSize)
1065 Status = STATUS_BUFFER_OVERFLOW;
1069 /* Fill buffer with requested info */
1070 NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
1071 NodeInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime;
1072 NodeInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime;
1073 NodeInformation->TitleIndex = 0;
1074 NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
1075 KeyObject->NameSize * sizeof(WCHAR);
1076 NodeInformation->ClassLength = KeyCell->ClassSize;
1077 NodeInformation->NameLength = KeyObject->NameSize * sizeof(WCHAR);
1078 mbstowcs(NodeInformation->Name,
1080 KeyObject->NameSize * sizeof(WCHAR));
1082 if (KeyCell->ClassSize != 0)
1084 pClassData = CmiGetBlock(KeyObject->RegistryHive,
1085 KeyCell->ClassNameOffset,
1087 wcsncpy(NodeInformation->Name + KeyObject->NameSize * sizeof(WCHAR),
1088 (PWCHAR)pClassData->Data,
1089 KeyCell->ClassSize);
1090 CmiReleaseBlock(RegistryHive, pClassData);
1092 *ResultLength = sizeof(KEY_NODE_INFORMATION)
1093 + KeyObject->NameSize * sizeof(WCHAR)
1094 + KeyCell->ClassSize;
1098 case KeyFullInformation:
1099 /* Check size of buffer */
1100 if (Length < sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize)
1102 Status = STATUS_BUFFER_OVERFLOW;
1106 /* Fill buffer with requested info */
1107 FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
1108 FullInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.dwLowDateTime;
1109 FullInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.dwHighDateTime;
1110 FullInformation->TitleIndex = 0;
1111 FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR);
1112 FullInformation->ClassLength = KeyCell->ClassSize;
1113 FullInformation->SubKeys = KeyCell->NumberOfSubKeys;
1114 FullInformation->MaxNameLen =
1115 CmiGetMaxNameLength(RegistryHive, KeyCell);
1116 FullInformation->MaxClassLen =
1117 CmiGetMaxClassLength(RegistryHive, KeyCell);
1118 FullInformation->Values = KeyCell->NumberOfValues;
1119 FullInformation->MaxValueNameLen =
1120 CmiGetMaxValueNameLength(RegistryHive, KeyCell);
1121 FullInformation->MaxValueDataLen =
1122 CmiGetMaxValueDataLength(RegistryHive, KeyCell);
1123 if (KeyCell->ClassSize != 0)
1125 pClassData=CmiGetBlock(KeyObject->RegistryHive,
1126 KeyCell->ClassNameOffset,
1128 wcsncpy(FullInformation->Class,
1129 (PWCHAR)pClassData->Data,
1130 KeyCell->ClassSize);
1131 CmiReleaseBlock(RegistryHive, pClassData);
1133 *ResultLength = sizeof(KEY_FULL_INFORMATION) + KeyCell->ClassSize;
1139 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1141 ObDereferenceObject(KeyObject);
1149 NtQueryValueKey(IN HANDLE KeyHandle,
1150 IN PUNICODE_STRING ValueName,
1151 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
1152 OUT PVOID KeyValueInformation,
1154 OUT PULONG ResultLength)
1157 PKEY_OBJECT KeyObject;
1158 PREGISTRY_HIVE RegistryHive;
1160 PVALUE_CELL ValueCell;
1161 PDATA_CELL DataCell;
1162 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
1163 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
1164 PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
1166 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1167 KeyHandle, ValueName->Buffer, Length);
1169 /* Verify that the handle is valid and is a registry key */
1170 Status = ObReferenceObjectByHandle(KeyHandle,
1174 (PVOID *)&KeyObject,
1177 if (!NT_SUCCESS(Status))
1179 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
1183 /* Acquire hive lock */
1184 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1186 VERIFY_KEY_OBJECT(KeyObject);
1188 /* Get pointer to KeyCell */
1189 KeyCell = KeyObject->KeyCell;
1190 RegistryHive = KeyObject->RegistryHive;
1192 /* Get Value block of interest */
1193 Status = CmiScanKeyForValue(RegistryHive,
1198 if (!NT_SUCCESS(Status))
1200 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
1201 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1202 ObDereferenceObject(KeyObject);
1205 else if (ValueCell != NULL)
1207 switch (KeyValueInformationClass)
1209 case KeyValueBasicInformation:
1210 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1212 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
1213 (ValueCell->NameSize + 1) * sizeof(WCHAR);
1217 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) +
1218 ValueCell->NameSize + sizeof(WCHAR);
1220 if (Length < *ResultLength)
1222 Status = STATUS_BUFFER_TOO_SMALL;
1226 ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
1227 KeyValueInformation;
1228 ValueBasicInformation->TitleIndex = 0;
1229 ValueBasicInformation->Type = ValueCell->DataType;
1230 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1232 ValueBasicInformation->NameLength =
1233 (ValueCell->NameSize + 1) * sizeof(WCHAR);
1234 CmiCopyPackedName(ValueBasicInformation->Name,
1236 ValueCell->NameSize);
1237 ValueBasicInformation->Name[ValueCell->NameSize] = 0;
1241 ValueBasicInformation->NameLength =
1242 ValueCell->NameSize + sizeof(WCHAR);
1243 RtlCopyMemory(ValueBasicInformation->Name,
1245 ValueCell->NameSize * sizeof(WCHAR));
1246 ValueBasicInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
1251 case KeyValuePartialInformation:
1252 *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
1253 + (ValueCell->DataSize & LONG_MAX);
1254 if (Length < *ResultLength)
1256 Status = STATUS_BUFFER_TOO_SMALL;
1260 ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
1261 KeyValueInformation;
1262 ValuePartialInformation->TitleIndex = 0;
1263 ValuePartialInformation->Type = ValueCell->DataType;
1264 ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
1265 if (ValueCell->DataSize > 0)
1267 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
1268 RtlCopyMemory(ValuePartialInformation->Data,
1270 ValueCell->DataSize & LONG_MAX);
1271 CmiReleaseBlock(RegistryHive, DataCell);
1275 RtlCopyMemory(ValuePartialInformation->Data,
1276 &ValueCell->DataOffset,
1277 ValueCell->DataSize & LONG_MAX);
1282 case KeyValueFullInformation:
1283 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1285 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
1286 (ValueCell->NameSize + 1) * sizeof(WCHAR) +
1287 (ValueCell->DataSize & LONG_MAX);
1291 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
1292 ValueCell->NameSize + sizeof(WCHAR) +
1293 (ValueCell->DataSize & LONG_MAX);
1295 if (Length < *ResultLength)
1297 Status = STATUS_BUFFER_TOO_SMALL;
1301 ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
1302 KeyValueInformation;
1303 ValueFullInformation->TitleIndex = 0;
1304 ValueFullInformation->Type = ValueCell->DataType;
1305 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1307 ValueFullInformation->NameLength =
1308 (ValueCell->NameSize + 1) * sizeof(WCHAR);
1309 CmiCopyPackedName(ValueFullInformation->Name,
1311 ValueCell->NameSize);
1312 ValueFullInformation->Name[ValueCell->NameSize] = 0;
1316 ValueFullInformation->NameLength =
1317 ValueCell->NameSize + sizeof(WCHAR);
1318 RtlCopyMemory(ValueFullInformation->Name,
1320 ValueCell->NameSize);
1321 ValueFullInformation->Name[ValueCell->NameSize / sizeof(WCHAR)] = 0;
1323 ValueFullInformation->DataOffset =
1324 (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
1325 ValueFullInformation->NameLength;
1326 ValueFullInformation->DataOffset =
1327 (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
1328 ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
1329 if (ValueCell->DataSize > 0)
1331 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
1332 RtlCopyMemory((PCHAR) ValueFullInformation
1333 + ValueFullInformation->DataOffset,
1335 ValueCell->DataSize & LONG_MAX);
1336 CmiReleaseBlock(RegistryHive, DataCell);
1340 RtlCopyMemory((PCHAR) ValueFullInformation
1341 + ValueFullInformation->DataOffset,
1342 &ValueCell->DataOffset,
1343 ValueCell->DataSize & LONG_MAX);
1351 Status = STATUS_OBJECT_NAME_NOT_FOUND;
1354 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1355 ObDereferenceObject(KeyObject);
1362 NtSetValueKey(IN HANDLE KeyHandle,
1363 IN PUNICODE_STRING ValueName,
1364 IN ULONG TitleIndex,
1370 PKEY_OBJECT KeyObject;
1371 PREGISTRY_HIVE RegistryHive;
1373 PVALUE_CELL ValueCell;
1374 BLOCK_OFFSET VBOffset;
1375 PDATA_CELL DataCell;
1376 PDATA_CELL NewDataCell;
1378 ULONG DesiredAccess;
1380 DPRINT("NtSetValueKey(KeyHandle %x ValueName %S Type %d)\n",
1381 KeyHandle, ValueName? ValueName->Buffer : NULL, Type);
1383 DesiredAccess = KEY_SET_VALUE;
1384 if (Type == REG_LINK)
1385 DesiredAccess |= KEY_CREATE_LINK;
1387 /* Verify that the handle is valid and is a registry key */
1388 Status = ObReferenceObjectByHandle(KeyHandle,
1392 (PVOID *)&KeyObject,
1394 if (!NT_SUCCESS(Status))
1397 /* Acquire hive lock exclucively */
1398 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1400 VERIFY_KEY_OBJECT(KeyObject);
1402 /* Get pointer to key cell */
1403 KeyCell = KeyObject->KeyCell;
1404 RegistryHive = KeyObject->RegistryHive;
1405 Status = CmiScanKeyForValue(RegistryHive,
1410 if (!NT_SUCCESS(Status))
1412 DPRINT1("Value not found. Status 0x%X\n", Status);
1414 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1415 ObDereferenceObject(KeyObject);
1419 if (ValueCell == NULL)
1421 DPRINT("Allocate new value cell\n");
1422 Status = CmiAddValueToKey(RegistryHive,
1427 if (NT_SUCCESS(Status))
1429 CmiMarkBlockDirty(RegistryHive, VBOffset);
1433 if (!NT_SUCCESS(Status))
1435 DPRINT1("Cannot add value. Status 0x%X\n", Status);
1437 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1438 ObDereferenceObject(KeyObject);
1442 DPRINT("DataSize %lu\n", DataSize);
1443 DPRINT("ValueCell %p\n", ValueCell);
1444 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1448 /* If datasize <= 4 then write in valueblock directly */
1449 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1450 if ((ValueCell->DataSize >= 0) &&
1451 (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
1453 CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
1456 RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
1457 ValueCell->DataSize = DataSize | 0x80000000;
1458 ValueCell->DataType = Type;
1459 RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
1460 CmiMarkBlockDirty(RegistryHive, VBOffset);
1462 else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff))
1464 /* If new data size is <= current then overwrite current data */
1465 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
1466 RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
1467 RtlCopyMemory(DataCell->Data, Data, DataSize);
1468 ValueCell->DataSize = DataSize;
1469 ValueCell->DataType = Type;
1470 CmiReleaseBlock(RegistryHive, DataCell);
1472 /* Update time of heap */
1473 if (IsPermanentHive(RegistryHive))
1475 ZwQuerySystemTime((PTIME) &pBin->DateModified);
1477 CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
1482 * New data size is larger than the current, destroy current
1483 * data block and allocate a new one.
1485 BLOCK_OFFSET NewOffset;
1487 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1489 if ((ValueCell->DataSize >= 0) &&
1490 (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
1492 CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
1493 ValueCell->DataSize = 0;
1494 ValueCell->DataType = 0;
1495 ValueCell->DataOffset = 0xffffffff;
1498 Status = CmiAllocateBlock(RegistryHive,
1499 (PVOID *)&NewDataCell,
1502 if (!NT_SUCCESS(Status))
1504 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
1506 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1507 ObDereferenceObject(KeyObject);
1512 RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
1513 ValueCell->DataSize = DataSize;
1514 ValueCell->DataType = Type;
1515 CmiReleaseBlock(RegistryHive, NewDataCell);
1516 ValueCell->DataOffset = NewOffset;
1517 CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
1521 if ((_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0) &&
1524 KeyCell->Type = REG_LINK_KEY_CELL_TYPE;
1525 CmiMarkBlockDirty(RegistryHive, KeyObject->BlockOffset);
1528 /* Update time of heap */
1529 if (IsPermanentHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
1531 ZwQuerySystemTime((PTIME) &pBin->DateModified);
1534 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1535 ObDereferenceObject(KeyObject);
1539 DPRINT("Return Status 0x%X\n", Status);
1546 NtDeleteValueKey(IN HANDLE KeyHandle,
1547 IN PUNICODE_STRING ValueName)
1549 PKEY_OBJECT KeyObject;
1552 /* Verify that the handle is valid and is a registry key */
1553 Status = ObReferenceObjectByHandle(KeyHandle,
1557 (PVOID *)&KeyObject,
1559 if (!NT_SUCCESS(Status))
1564 /* Acquire hive lock */
1565 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1567 VERIFY_KEY_OBJECT(KeyObject);
1569 Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
1571 KeyObject->BlockOffset,
1574 /* Release hive lock */
1575 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1577 ObDereferenceObject(KeyObject);
1586 NtLoadKey(PHANDLE KeyHandle,
1587 POBJECT_ATTRIBUTES ObjectAttributes)
1589 return NtLoadKey2(KeyHandle, ObjectAttributes, 0);
1594 NtLoadKey2(IN PHANDLE KeyHandle,
1595 IN POBJECT_ATTRIBUTES ObjectAttributes,
1604 IN HANDLE KeyHandle,
1606 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1607 IN PVOID ApcContext OPTIONAL,
1608 OUT PIO_STATUS_BLOCK IoStatusBlock,
1609 IN ULONG CompletionFilter,
1610 IN BOOLEAN Asynchroneous,
1611 OUT PVOID ChangeBuffer,
1613 IN BOOLEAN WatchSubtree)
1620 NtQueryMultipleValueKey(IN HANDLE KeyHandle,
1621 IN OUT PKEY_VALUE_ENTRY ValueList,
1622 IN ULONG NumberOfValues,
1624 IN OUT PULONG Length,
1625 OUT PULONG ReturnLength)
1627 PREGISTRY_HIVE RegistryHive;
1628 PVALUE_CELL ValueCell;
1629 PKEY_OBJECT KeyObject;
1630 PDATA_CELL DataCell;
1631 ULONG BufferLength = 0;
1637 /* Verify that the handle is valid and is a registry key */
1638 Status = ObReferenceObjectByHandle(KeyHandle,
1642 (PVOID *) &KeyObject,
1644 if (!NT_SUCCESS(Status))
1646 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
1650 /* Acquire hive lock */
1651 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1653 VERIFY_KEY_OBJECT(KeyObject);
1655 /* Get pointer to KeyCell */
1656 KeyCell = KeyObject->KeyCell;
1657 RegistryHive = KeyObject->RegistryHive;
1659 DataPtr = (PUCHAR) Buffer;
1661 for (i = 0; i < NumberOfValues; i++)
1663 DPRINT("ValueName: '%wZ'\n", ValueList[i].ValueName);
1665 /* Get Value block of interest */
1666 Status = CmiScanKeyForValue(RegistryHive,
1668 ValueList[i].ValueName,
1672 if (!NT_SUCCESS(Status))
1674 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
1677 else if (ValueCell == NULL)
1679 Status = STATUS_OBJECT_NAME_NOT_FOUND;
1683 BufferLength = (BufferLength + 3) & 0xfffffffc;
1685 if (BufferLength + (ValueCell->DataSize & LONG_MAX) <= *Length)
1687 DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc);
1689 ValueList[i].Type = ValueCell->DataType;
1690 ValueList[i].DataLength = ValueCell->DataSize & LONG_MAX;
1691 ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer;
1693 if (ValueCell->DataSize > 0)
1695 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
1696 RtlCopyMemory(DataPtr, DataCell->Data, ValueCell->DataSize & LONG_MAX);
1697 CmiReleaseBlock(RegistryHive, DataCell);
1701 RtlCopyMemory(DataPtr,
1702 &ValueCell->DataOffset,
1703 ValueCell->DataSize & LONG_MAX);
1706 DataPtr += ValueCell->DataSize & LONG_MAX;
1710 Status = STATUS_BUFFER_TOO_SMALL;
1713 BufferLength += ValueCell->DataSize & LONG_MAX;
1716 if (NT_SUCCESS(Status))
1717 *Length = BufferLength;
1719 *ReturnLength = BufferLength;
1721 /* Release hive lock */
1722 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1724 ObDereferenceObject(KeyObject);
1726 DPRINT("Return Status 0x%X\n", Status);
1734 IN POBJECT_ATTRIBUTES ObjectAttributes,
1736 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
1745 IN HANDLE KeyHandle,
1746 IN HANDLE FileHandle,
1747 IN ULONG RestoreFlags
1756 IN HANDLE KeyHandle,
1757 IN HANDLE FileHandle)
1764 NtSetInformationKey(
1765 IN HANDLE KeyHandle,
1766 IN CINT KeyInformationClass,
1767 IN PVOID KeyInformation,
1768 IN ULONG KeyInformationLength)
1775 NtUnloadKey(IN HANDLE KeyHandle)
1782 NtInitializeRegistry(IN BOOLEAN SetUpBoot)
1784 NTSTATUS Status = STATUS_ACCESS_DENIED;
1786 if (CmiRegistryInitialized == FALSE)
1788 /* FIXME: save boot log file */
1790 Status = CmiInitHives(SetUpBoot);
1792 CmiRegistryInitialized = TRUE;