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 *****************************************************************/
11 #define NTOS_MODE_KERNEL
14 #include <internal/ob.h>
17 #include <internal/se.h>
18 #include <internal/registry.h>
21 #include <internal/debug.h>
26 /* GLOBALS ******************************************************************/
28 extern POBJECT_TYPE CmiKeyType;
29 extern PREGISTRY_HIVE CmiVolatileHive;
31 static BOOLEAN CmiRegistryInitialized = FALSE;
34 /* FUNCTIONS ****************************************************************/
37 NtCreateKey(OUT PHANDLE KeyHandle,
38 IN ACCESS_MASK DesiredAccess,
39 IN POBJECT_ATTRIBUTES ObjectAttributes,
41 IN PUNICODE_STRING Class,
42 IN ULONG CreateOptions,
43 OUT PULONG Disposition)
45 UNICODE_STRING RemainingPath;
46 PKEY_OBJECT KeyObject;
52 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
53 ObjectAttributes->ObjectName,
55 ObjectAttributes->RootDirectory);
57 Status = ObFindObject(ObjectAttributes,
61 if (!NT_SUCCESS(Status))
66 DPRINT("RemainingPath %wZ\n", &RemainingPath);
68 if ((RemainingPath.Buffer == NULL) || (RemainingPath.Buffer[0] == 0))
70 /* Fail if the key has been deleted */
71 if (((PKEY_OBJECT) Object)->Flags & KO_MARKED_FOR_DELETE)
73 ObDereferenceObject(Object);
74 return(STATUS_UNSUCCESSFUL);
78 *Disposition = REG_OPENED_EXISTING_KEY;
80 Status = ObCreateHandle(PsGetCurrentProcess(),
86 DPRINT("Status %x\n", Status);
87 ObDereferenceObject(Object);
91 /* If RemainingPath contains \ we must return error
92 because NtCreateKey don't create trees */
93 Start = RemainingPath.Buffer;
97 End = wcschr(Start, L'\\');
100 ObDereferenceObject(Object);
101 return STATUS_OBJECT_NAME_NOT_FOUND;
104 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath.Buffer, Object);
106 Status = ObRosCreateObject(KeyHandle,
111 if (!NT_SUCCESS(Status))
116 KeyObject->ParentKey = Object;
118 if (CreateOptions & REG_OPTION_VOLATILE)
119 KeyObject->RegistryHive = CmiVolatileHive;
121 KeyObject->RegistryHive = KeyObject->ParentKey->RegistryHive;
123 KeyObject->Flags = 0;
124 KeyObject->NumberOfSubKeys = 0;
125 KeyObject->SizeOfSubKeys = 0;
126 KeyObject->SubKeys = NULL;
128 /* Acquire hive lock */
129 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
131 /* add key to subkeys of parent if needed */
132 Status = CmiAddSubKey(KeyObject->RegistryHive,
133 KeyObject->ParentKey,
139 if (!NT_SUCCESS(Status))
141 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status);
142 /* Release hive lock */
143 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
144 ObDereferenceObject(KeyObject);
145 ObDereferenceObject(Object);
146 return STATUS_UNSUCCESSFUL;
149 RtlCreateUnicodeString(&KeyObject->Name,
152 if (KeyObject->RegistryHive == KeyObject->ParentKey->RegistryHive)
154 KeyObject->KeyCell->ParentKeyOffset = KeyObject->ParentKey->BlockOffset;
155 KeyObject->KeyCell->SecurityKeyOffset = KeyObject->ParentKey->KeyCell->SecurityKeyOffset;
159 KeyObject->KeyCell->ParentKeyOffset = -1;
160 KeyObject->KeyCell->SecurityKeyOffset = -1;
161 /* This key must remain in memory unless it is deleted
162 or file is unloaded */
163 ObReferenceObjectByPointer(KeyObject,
164 STANDARD_RIGHTS_REQUIRED,
169 CmiAddKeyToList(KeyObject->ParentKey, KeyObject);
171 VERIFY_KEY_OBJECT(KeyObject);
173 /* Release hive lock */
174 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
176 ObDereferenceObject(KeyObject);
177 ObDereferenceObject(Object);
180 *Disposition = REG_CREATED_NEW_KEY;
189 NtDeleteKey(IN HANDLE KeyHandle)
191 PKEY_OBJECT KeyObject;
194 DPRINT("KeyHandle %x\n", KeyHandle);
196 /* Verify that the handle is valid and is a registry key */
197 Status = ObReferenceObjectByHandle(KeyHandle,
203 if (!NT_SUCCESS(Status))
208 /* Acquire hive lock */
209 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
211 VERIFY_KEY_OBJECT(KeyObject);
213 /* Check for subkeys */
214 if (KeyObject->NumberOfSubKeys != 0)
216 Status = STATUS_CANNOT_DELETE;
220 /* Set the marked for delete bit in the key object */
221 KeyObject->Flags |= KO_MARKED_FOR_DELETE;
222 Status = STATUS_SUCCESS;
225 /* Release hive lock */
226 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
228 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
230 /* Dereference the object */
231 ObDereferenceObject(KeyObject);
232 if(KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
233 ObDereferenceObject(KeyObject);
235 DPRINT("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.
249 NtEnumerateKey(IN HANDLE KeyHandle,
251 IN KEY_INFORMATION_CLASS KeyInformationClass,
252 OUT PVOID KeyInformation,
254 OUT PULONG ResultLength)
256 PKEY_OBJECT KeyObject;
257 PREGISTRY_HIVE RegistryHive;
258 PKEY_CELL KeyCell, SubKeyCell;
259 PHASH_TABLE_CELL HashTableBlock;
260 PKEY_BASIC_INFORMATION BasicInformation;
261 PKEY_NODE_INFORMATION NodeInformation;
262 PKEY_FULL_INFORMATION FullInformation;
263 PDATA_CELL ClassData;
267 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
275 /* Verify that the handle is valid and is a registry key */
276 Status = ObReferenceObjectByHandle(KeyHandle,
277 KEY_ENUMERATE_SUB_KEYS,
280 (PVOID *) &KeyObject,
282 if (!NT_SUCCESS(Status))
284 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
288 /* Acquire hive lock */
289 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
291 VERIFY_KEY_OBJECT(KeyObject);
293 /* Get pointer to KeyCell */
294 KeyCell = KeyObject->KeyCell;
295 RegistryHive = KeyObject->RegistryHive;
297 /* Get pointer to SubKey */
298 if (Index >= KeyCell->NumberOfSubKeys)
300 if (RegistryHive == CmiVolatileHive)
302 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
303 ObDereferenceObject(KeyObject);
304 DPRINT("No more volatile entries\n");
305 return(STATUS_NO_MORE_ENTRIES);
310 PKEY_OBJECT CurKey = NULL;
312 /* Search volatile keys */
313 for (i = 0; i < KeyObject->NumberOfSubKeys; i++)
315 CurKey = KeyObject->SubKeys[i];
316 if (CurKey->RegistryHive == CmiVolatileHive)
318 if (Index-- == KeyCell->NumberOfSubKeys)
322 if (Index >= KeyCell->NumberOfSubKeys)
324 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
325 ObDereferenceObject(KeyObject);
326 DPRINT("No more non-volatile entries\n");
327 return(STATUS_NO_MORE_ENTRIES);
329 SubKeyCell = CurKey->KeyCell;
334 if (KeyCell->HashTableOffset == (BLOCK_OFFSET)-1)
336 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
337 ObDereferenceObject(KeyObject);
338 return(STATUS_NO_MORE_ENTRIES);
341 HashTableBlock = CmiGetBlock(RegistryHive, KeyCell->HashTableOffset, NULL);
342 if (HashTableBlock == NULL)
344 DPRINT("CmiGetBlock() failed\n");
345 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
346 ObDereferenceObject(KeyObject);
347 return STATUS_UNSUCCESSFUL;
349 SubKeyCell = CmiGetKeyFromHashByIndex(RegistryHive,
354 if (SubKeyCell == NULL)
356 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
357 ObDereferenceObject(KeyObject);
358 DPRINT("No more entries\n");
359 return(STATUS_NO_MORE_ENTRIES);
362 Status = STATUS_SUCCESS;
363 switch (KeyInformationClass)
365 case KeyBasicInformation:
366 /* Check size of buffer */
367 NameSize = SubKeyCell->NameSize;
368 if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
370 NameSize *= sizeof(WCHAR);
372 *ResultLength = sizeof(KEY_BASIC_INFORMATION) + NameSize;
374 if (Length < *ResultLength)
376 Status = STATUS_BUFFER_OVERFLOW;
380 /* Fill buffer with requested info */
381 BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
382 BasicInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
383 BasicInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
384 BasicInformation->TitleIndex = Index;
385 BasicInformation->NameLength = NameSize;
387 if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
389 CmiCopyPackedName(BasicInformation->Name,
391 SubKeyCell->NameSize);
395 RtlCopyMemory(BasicInformation->Name,
397 SubKeyCell->NameSize);
402 case KeyNodeInformation:
403 /* Check size of buffer */
404 if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
406 NameSize = SubKeyCell->NameSize * sizeof(WCHAR);
410 NameSize = SubKeyCell->NameSize;
412 *ResultLength = sizeof(KEY_NODE_INFORMATION) +
413 NameSize + SubKeyCell->ClassSize;
415 if (Length < *ResultLength)
417 Status = STATUS_BUFFER_OVERFLOW;
421 /* Fill buffer with requested info */
422 NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
423 NodeInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
424 NodeInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
425 NodeInformation->TitleIndex = Index;
426 NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) + NameSize;
427 NodeInformation->ClassLength = SubKeyCell->ClassSize;
428 NodeInformation->NameLength = NameSize;
430 if (SubKeyCell->Flags & REG_KEY_NAME_PACKED)
432 CmiCopyPackedName(NodeInformation->Name,
434 SubKeyCell->NameSize);
438 RtlCopyMemory(NodeInformation->Name,
440 SubKeyCell->NameSize);
443 if (SubKeyCell->ClassSize != 0)
445 ClassData=CmiGetBlock(KeyObject->RegistryHive,
446 SubKeyCell->ClassNameOffset,
448 wcsncpy(NodeInformation->Name + SubKeyCell->NameSize,
449 (PWCHAR)ClassData->Data,
450 SubKeyCell->ClassSize);
455 case KeyFullInformation:
456 /* Check size of buffer */
457 *ResultLength = sizeof(KEY_FULL_INFORMATION) +
458 SubKeyCell->ClassSize;
460 if (Length < *ResultLength)
462 Status = STATUS_BUFFER_OVERFLOW;
466 /* Fill buffer with requested info */
467 FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
468 FullInformation->LastWriteTime.u.LowPart = SubKeyCell->LastWriteTime.u.LowPart;
469 FullInformation->LastWriteTime.u.HighPart = SubKeyCell->LastWriteTime.u.HighPart;
470 FullInformation->TitleIndex = Index;
471 FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) -
473 FullInformation->ClassLength = SubKeyCell->ClassSize;
474 FullInformation->SubKeys = SubKeyCell->NumberOfSubKeys;
475 FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
476 FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
477 FullInformation->Values = SubKeyCell->NumberOfValues;
478 FullInformation->MaxValueNameLen =
479 CmiGetMaxValueNameLength(RegistryHive, SubKeyCell);
480 FullInformation->MaxValueDataLen =
481 CmiGetMaxValueDataLength(RegistryHive, SubKeyCell);
482 if (SubKeyCell->ClassSize != 0)
484 ClassData = CmiGetBlock(KeyObject->RegistryHive,
485 SubKeyCell->ClassNameOffset,
487 wcsncpy(FullInformation->Class,
488 (PWCHAR)ClassData->Data,
489 SubKeyCell->ClassSize);
495 DPRINT1("Not handling 0x%x\n", KeyInformationClass);
499 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
500 ObDereferenceObject(KeyObject);
502 DPRINT("Returning status %x\n", Status);
509 NtEnumerateValueKey(IN HANDLE KeyHandle,
511 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
512 OUT PVOID KeyValueInformation,
514 OUT PULONG ResultLength)
517 PKEY_OBJECT KeyObject;
518 PREGISTRY_HIVE RegistryHive;
520 PVALUE_CELL ValueCell;
523 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
524 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
525 PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
527 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
530 KeyValueInformationClass,
535 /* Verify that the handle is valid and is a registry key */
536 Status = ObReferenceObjectByHandle(KeyHandle,
540 (PVOID *) &KeyObject,
543 if (!NT_SUCCESS(Status))
548 /* Acquire hive lock */
549 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
551 VERIFY_KEY_OBJECT(KeyObject);
553 /* Get pointer to KeyCell */
554 KeyCell = KeyObject->KeyCell;
555 RegistryHive = KeyObject->RegistryHive;
557 /* Get Value block of interest */
558 Status = CmiGetValueFromKeyByIndex(RegistryHive,
563 if (!NT_SUCCESS(Status))
565 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
566 ObDereferenceObject(KeyObject);
570 if (ValueCell != NULL)
572 switch (KeyValueInformationClass)
574 case KeyValueBasicInformation:
575 NameSize = ValueCell->NameSize;
576 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
578 NameSize *= sizeof(WCHAR);
580 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameSize;
581 if (Length < *ResultLength)
583 Status = STATUS_BUFFER_OVERFLOW;
587 ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
589 ValueBasicInformation->TitleIndex = 0;
590 ValueBasicInformation->Type = ValueCell->DataType;
591 ValueBasicInformation->NameLength = NameSize;
592 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
594 CmiCopyPackedName(ValueBasicInformation->Name,
596 ValueCell->NameSize);
600 RtlCopyMemory(ValueBasicInformation->Name,
607 case KeyValuePartialInformation:
608 *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
609 (ValueCell->DataSize & LONG_MAX);
610 if (Length < *ResultLength)
612 Status = STATUS_BUFFER_OVERFLOW;
616 ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
618 ValuePartialInformation->TitleIndex = 0;
619 ValuePartialInformation->Type = ValueCell->DataType;
620 ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
621 if(ValueCell->DataSize >0)
623 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
624 RtlCopyMemory(ValuePartialInformation->Data,
626 ValueCell->DataSize & LONG_MAX);
630 RtlCopyMemory(ValuePartialInformation->Data,
631 &ValueCell->DataOffset,
632 ValueCell->DataSize & LONG_MAX);
634 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
638 case KeyValueFullInformation:
639 NameSize = ValueCell->NameSize;
640 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
642 NameSize *= sizeof(WCHAR);
644 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
645 NameSize + (ValueCell->DataSize & LONG_MAX);
646 if (Length < *ResultLength)
648 Status = STATUS_BUFFER_OVERFLOW;
652 ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
654 ValueFullInformation->TitleIndex = 0;
655 ValueFullInformation->Type = ValueCell->DataType;
656 ValueFullInformation->NameLength = NameSize;
657 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
659 CmiCopyPackedName(ValueFullInformation->Name,
661 ValueCell->NameSize);
665 RtlCopyMemory(ValueFullInformation->Name,
667 ValueCell->NameSize);
669 ValueFullInformation->DataOffset =
670 (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
671 ValueFullInformation->NameLength;
672 ValueFullInformation->DataOffset =
673 (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
674 ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
675 if (ValueCell->DataSize > 0)
677 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
678 RtlCopyMemory((PCHAR) ValueFullInformation
679 + ValueFullInformation->DataOffset,
681 ValueCell->DataSize & LONG_MAX);
685 RtlCopyMemory((PCHAR) ValueFullInformation
686 + ValueFullInformation->DataOffset,
687 &ValueCell->DataOffset,
688 ValueCell->DataSize & LONG_MAX);
694 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass);
700 Status = STATUS_UNSUCCESSFUL;
703 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
704 ObDereferenceObject(KeyObject);
711 NtFlushKey(IN HANDLE KeyHandle)
714 PKEY_OBJECT KeyObject;
715 PREGISTRY_HIVE RegistryHive;
717 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle);
719 /* Verify that the handle is valid and is a registry key */
720 Status = ObReferenceObjectByHandle(KeyHandle,
726 if (!NT_SUCCESS(Status))
731 VERIFY_KEY_OBJECT(KeyObject);
733 RegistryHive = KeyObject->RegistryHive;
735 /* Acquire hive lock */
736 ExAcquireResourceExclusiveLite(&RegistryHive->HiveResource,
739 if (IsNoFileHive(RegistryHive))
741 Status = STATUS_SUCCESS;
745 /* Flush non-volatile hive */
746 Status = CmiFlushRegistryHive(RegistryHive);
749 ExReleaseResourceLite(&RegistryHive->HiveResource);
751 ObDereferenceObject(KeyObject);
753 return STATUS_SUCCESS;
758 NtOpenKey(OUT PHANDLE KeyHandle,
759 IN ACCESS_MASK DesiredAccess,
760 IN POBJECT_ATTRIBUTES ObjectAttributes)
762 UNICODE_STRING RemainingPath;
766 DPRINT("NtOpenFile(KH %x DA %x OA %x OA->ON '%wZ'\n",
770 ObjectAttributes ? ObjectAttributes->ObjectName : NULL);
772 RemainingPath.Buffer = NULL;
773 Status = ObFindObject(ObjectAttributes,
777 if (!NT_SUCCESS(Status))
782 VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
784 DPRINT("RemainingPath '%wZ'\n", &RemainingPath);
786 if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
788 ObDereferenceObject(Object);
789 return(STATUS_UNSUCCESSFUL);
792 /* Fail if the key has been deleted */
793 if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
795 ObDereferenceObject(Object);
796 return(STATUS_UNSUCCESSFUL);
799 Status = ObCreateHandle(PsGetCurrentProcess(),
804 ObDereferenceObject(Object);
806 if (!NT_SUCCESS(Status))
811 return(STATUS_SUCCESS);
816 NtQueryKey(IN HANDLE KeyHandle,
817 IN KEY_INFORMATION_CLASS KeyInformationClass,
818 OUT PVOID KeyInformation,
820 OUT PULONG ResultLength)
822 PKEY_BASIC_INFORMATION BasicInformation;
823 PKEY_NODE_INFORMATION NodeInformation;
824 PKEY_FULL_INFORMATION FullInformation;
825 PREGISTRY_HIVE RegistryHive;
826 PDATA_CELL ClassData;
827 PKEY_OBJECT KeyObject;
831 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
838 /* Verify that the handle is valid and is a registry key */
839 Status = ObReferenceObjectByHandle(KeyHandle,
843 (PVOID *) &KeyObject,
845 if (!NT_SUCCESS(Status))
850 /* Acquire hive lock */
851 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
853 VERIFY_KEY_OBJECT(KeyObject);
855 /* Get pointer to KeyCell */
856 KeyCell = KeyObject->KeyCell;
857 RegistryHive = KeyObject->RegistryHive;
859 Status = STATUS_SUCCESS;
860 switch (KeyInformationClass)
862 case KeyBasicInformation:
863 /* Check size of buffer */
864 *ResultLength = sizeof(KEY_BASIC_INFORMATION) +
865 KeyObject->Name.Length;
867 if (Length < *ResultLength)
869 Status = STATUS_BUFFER_OVERFLOW;
873 /* Fill buffer with requested info */
874 BasicInformation = (PKEY_BASIC_INFORMATION) KeyInformation;
875 BasicInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.u.LowPart;
876 BasicInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
877 BasicInformation->TitleIndex = 0;
878 BasicInformation->NameLength = KeyObject->Name.Length;
880 if (KeyCell->Flags & REG_KEY_NAME_PACKED)
882 CmiCopyPackedName(BasicInformation->Name,
888 RtlCopyMemory(BasicInformation->Name,
895 case KeyNodeInformation:
896 /* Check size of buffer */
897 *ResultLength = sizeof(KEY_NODE_INFORMATION) +
898 KeyObject->Name.Length + KeyCell->ClassSize;
900 if (Length < *ResultLength)
902 Status = STATUS_BUFFER_OVERFLOW;
906 /* Fill buffer with requested info */
907 NodeInformation = (PKEY_NODE_INFORMATION) KeyInformation;
908 NodeInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.u.LowPart;
909 NodeInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
910 NodeInformation->TitleIndex = 0;
911 NodeInformation->ClassOffset = sizeof(KEY_NODE_INFORMATION) +
912 KeyObject->Name.Length;
913 NodeInformation->ClassLength = KeyCell->ClassSize;
914 NodeInformation->NameLength = KeyObject->Name.Length;
916 if (KeyCell->Flags & REG_KEY_NAME_PACKED)
918 CmiCopyPackedName(NodeInformation->Name,
924 RtlCopyMemory(NodeInformation->Name,
929 if (KeyCell->ClassSize != 0)
931 ClassData = CmiGetBlock(KeyObject->RegistryHive,
932 KeyCell->ClassNameOffset,
934 wcsncpy(NodeInformation->Name + KeyObject->Name.Length,
935 (PWCHAR)ClassData->Data,
941 case KeyFullInformation:
942 /* Check size of buffer */
943 *ResultLength = sizeof(KEY_FULL_INFORMATION) +
946 if (Length < *ResultLength)
948 Status = STATUS_BUFFER_OVERFLOW;
952 /* Fill buffer with requested info */
953 FullInformation = (PKEY_FULL_INFORMATION) KeyInformation;
954 FullInformation->LastWriteTime.u.LowPart = KeyCell->LastWriteTime.u.LowPart;
955 FullInformation->LastWriteTime.u.HighPart = KeyCell->LastWriteTime.u.HighPart;
956 FullInformation->TitleIndex = 0;
957 FullInformation->ClassOffset = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR);
958 FullInformation->ClassLength = KeyCell->ClassSize;
959 FullInformation->SubKeys = KeyCell->NumberOfSubKeys;
960 FullInformation->MaxNameLen = CmiGetMaxNameLength(KeyObject);
961 FullInformation->MaxClassLen = CmiGetMaxClassLength(KeyObject);
962 FullInformation->Values = KeyCell->NumberOfValues;
963 FullInformation->MaxValueNameLen =
964 CmiGetMaxValueNameLength(RegistryHive, KeyCell);
965 FullInformation->MaxValueDataLen =
966 CmiGetMaxValueDataLength(RegistryHive, KeyCell);
967 if (KeyCell->ClassSize != 0)
969 ClassData=CmiGetBlock(KeyObject->RegistryHive,
970 KeyCell->ClassNameOffset,
972 wcsncpy(FullInformation->Class,
973 (PWCHAR)ClassData->Data,
979 DPRINT1("Not handling 0x%x\n", KeyInformationClass);
983 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
984 ObDereferenceObject(KeyObject);
991 NtQueryValueKey(IN HANDLE KeyHandle,
992 IN PUNICODE_STRING ValueName,
993 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
994 OUT PVOID KeyValueInformation,
996 OUT PULONG ResultLength)
1000 PKEY_OBJECT KeyObject;
1001 PREGISTRY_HIVE RegistryHive;
1003 PVALUE_CELL ValueCell;
1004 PDATA_CELL DataCell;
1005 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation;
1006 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation;
1007 PKEY_VALUE_FULL_INFORMATION ValueFullInformation;
1009 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1010 KeyHandle, ValueName->Buffer, Length);
1012 /* Verify that the handle is valid and is a registry key */
1013 Status = ObReferenceObjectByHandle(KeyHandle,
1017 (PVOID *)&KeyObject,
1020 if (!NT_SUCCESS(Status))
1022 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
1026 /* Acquire hive lock */
1027 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1029 VERIFY_KEY_OBJECT(KeyObject);
1031 /* Get pointer to KeyCell */
1032 KeyCell = KeyObject->KeyCell;
1033 RegistryHive = KeyObject->RegistryHive;
1035 /* Get Value block of interest */
1036 Status = CmiScanKeyForValue(RegistryHive,
1041 if (!NT_SUCCESS(Status))
1043 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
1044 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1045 ObDereferenceObject(KeyObject);
1048 else if (ValueCell != NULL)
1050 switch (KeyValueInformationClass)
1052 case KeyValueBasicInformation:
1053 NameSize = ValueCell->NameSize;
1054 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1056 NameSize *= sizeof(WCHAR);
1058 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameSize;
1059 if (Length < *ResultLength)
1061 Status = STATUS_BUFFER_TOO_SMALL;
1065 ValueBasicInformation = (PKEY_VALUE_BASIC_INFORMATION)
1066 KeyValueInformation;
1067 ValueBasicInformation->TitleIndex = 0;
1068 ValueBasicInformation->Type = ValueCell->DataType;
1069 ValueBasicInformation->NameLength = NameSize;
1070 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1072 CmiCopyPackedName(ValueBasicInformation->Name,
1074 ValueCell->NameSize);
1078 RtlCopyMemory(ValueBasicInformation->Name,
1080 ValueCell->NameSize * sizeof(WCHAR));
1085 case KeyValuePartialInformation:
1086 *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION)
1087 + (ValueCell->DataSize & LONG_MAX);
1088 if (Length < *ResultLength)
1090 Status = STATUS_BUFFER_TOO_SMALL;
1094 ValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)
1095 KeyValueInformation;
1096 ValuePartialInformation->TitleIndex = 0;
1097 ValuePartialInformation->Type = ValueCell->DataType;
1098 ValuePartialInformation->DataLength = ValueCell->DataSize & LONG_MAX;
1099 if (ValueCell->DataSize > 0)
1101 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
1102 RtlCopyMemory(ValuePartialInformation->Data,
1104 ValueCell->DataSize & LONG_MAX);
1108 RtlCopyMemory(ValuePartialInformation->Data,
1109 &ValueCell->DataOffset,
1110 ValueCell->DataSize & LONG_MAX);
1115 case KeyValueFullInformation:
1116 NameSize = ValueCell->NameSize;
1117 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1119 NameSize *= sizeof(WCHAR);
1121 *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION) +
1122 NameSize + (ValueCell->DataSize & LONG_MAX);
1123 if (Length < *ResultLength)
1125 Status = STATUS_BUFFER_TOO_SMALL;
1129 ValueFullInformation = (PKEY_VALUE_FULL_INFORMATION)
1130 KeyValueInformation;
1131 ValueFullInformation->TitleIndex = 0;
1132 ValueFullInformation->Type = ValueCell->DataType;
1133 ValueFullInformation->NameLength = NameSize;
1134 if (ValueCell->Flags & REG_VALUE_NAME_PACKED)
1136 CmiCopyPackedName(ValueFullInformation->Name,
1138 ValueCell->NameSize);
1142 RtlCopyMemory(ValueFullInformation->Name,
1144 ValueCell->NameSize);
1146 ValueFullInformation->DataOffset =
1147 (ULONG)ValueFullInformation->Name - (ULONG)ValueFullInformation +
1148 ValueFullInformation->NameLength;
1149 ValueFullInformation->DataOffset =
1150 (ValueFullInformation->DataOffset + 3) & 0xfffffffc;
1151 ValueFullInformation->DataLength = ValueCell->DataSize & LONG_MAX;
1152 if (ValueCell->DataSize > 0)
1154 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL);
1155 RtlCopyMemory((PCHAR) ValueFullInformation
1156 + ValueFullInformation->DataOffset,
1158 ValueCell->DataSize & LONG_MAX);
1162 RtlCopyMemory((PCHAR) ValueFullInformation
1163 + ValueFullInformation->DataOffset,
1164 &ValueCell->DataOffset,
1165 ValueCell->DataSize & LONG_MAX);
1170 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass);
1176 Status = STATUS_OBJECT_NAME_NOT_FOUND;
1179 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1180 ObDereferenceObject(KeyObject);
1187 NtSetValueKey(IN HANDLE KeyHandle,
1188 IN PUNICODE_STRING ValueName,
1189 IN ULONG TitleIndex,
1195 PKEY_OBJECT KeyObject;
1196 PREGISTRY_HIVE RegistryHive;
1198 PVALUE_CELL ValueCell;
1199 BLOCK_OFFSET VBOffset;
1200 PDATA_CELL DataCell;
1201 PDATA_CELL NewDataCell;
1203 ULONG DesiredAccess;
1205 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1206 KeyHandle, ValueName, Type);
1208 DesiredAccess = KEY_SET_VALUE;
1209 if (Type == REG_LINK)
1210 DesiredAccess |= KEY_CREATE_LINK;
1212 /* Verify that the handle is valid and is a registry key */
1213 Status = ObReferenceObjectByHandle(KeyHandle,
1217 (PVOID *)&KeyObject,
1219 if (!NT_SUCCESS(Status))
1222 /* Acquire hive lock exclucively */
1223 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1225 VERIFY_KEY_OBJECT(KeyObject);
1227 /* Get pointer to key cell */
1228 KeyCell = KeyObject->KeyCell;
1229 RegistryHive = KeyObject->RegistryHive;
1230 Status = CmiScanKeyForValue(RegistryHive,
1235 if (!NT_SUCCESS(Status))
1237 DPRINT("Value not found. Status 0x%X\n", Status);
1239 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1240 ObDereferenceObject(KeyObject);
1244 if (ValueCell == NULL)
1246 DPRINT("Allocate new value cell\n");
1247 Status = CmiAddValueToKey(RegistryHive,
1252 if (NT_SUCCESS(Status))
1254 CmiMarkBlockDirty(RegistryHive, VBOffset);
1258 if (!NT_SUCCESS(Status))
1260 DPRINT("Cannot add value. Status 0x%X\n", Status);
1262 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1263 ObDereferenceObject(KeyObject);
1267 DPRINT("DataSize %lu\n", DataSize);
1268 DPRINT("ValueCell %p\n", ValueCell);
1269 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1273 /* If datasize <= 4 then write in valueblock directly */
1274 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1275 if ((ValueCell->DataSize >= 0) &&
1276 (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
1278 CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
1281 RtlCopyMemory(&ValueCell->DataOffset, Data, DataSize);
1282 ValueCell->DataSize = DataSize | 0x80000000;
1283 ValueCell->DataType = Type;
1284 RtlMoveMemory(&ValueCell->DataOffset, Data, DataSize);
1285 CmiMarkBlockDirty(RegistryHive, VBOffset);
1287 else if (DataSize <= (ULONG) (ValueCell->DataSize & 0x7fffffff))
1289 /* If new data size is <= current then overwrite current data */
1290 DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset,&pBin);
1291 RtlZeroMemory(DataCell->Data, ValueCell->DataSize);
1292 RtlCopyMemory(DataCell->Data, Data, DataSize);
1293 ValueCell->DataSize = DataSize;
1294 ValueCell->DataType = Type;
1296 /* Update time of heap */
1297 if (!IsNoFileHive(RegistryHive))
1299 NtQuerySystemTime(&pBin->DateModified);
1301 CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
1306 * New data size is larger than the current, destroy current
1307 * data block and allocate a new one.
1309 BLOCK_OFFSET NewOffset;
1311 DPRINT("ValueCell->DataSize %lu\n", ValueCell->DataSize);
1313 if ((ValueCell->DataSize >= 0) &&
1314 (DataCell = CmiGetBlock(RegistryHive, ValueCell->DataOffset, NULL)))
1316 CmiDestroyBlock(RegistryHive, DataCell, ValueCell->DataOffset);
1317 ValueCell->DataSize = 0;
1318 ValueCell->DataType = 0;
1319 ValueCell->DataOffset = 0xffffffff;
1322 Status = CmiAllocateBlock(RegistryHive,
1323 (PVOID *)&NewDataCell,
1326 if (!NT_SUCCESS(Status))
1328 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status);
1330 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1331 ObDereferenceObject(KeyObject);
1336 RtlCopyMemory(&NewDataCell->Data[0], Data, DataSize);
1337 ValueCell->DataSize = DataSize;
1338 ValueCell->DataType = Type;
1339 ValueCell->DataOffset = NewOffset;
1340 CmiMarkBlockDirty(RegistryHive, ValueCell->DataOffset);
1344 if ((_wcsicmp(ValueName->Buffer, L"SymbolicLinkValue") == 0) &&
1347 KeyCell->Flags |= REG_KEY_LINK_CELL;
1348 CmiMarkBlockDirty(RegistryHive, KeyObject->BlockOffset);
1351 /* Update time of heap */
1352 if (!IsNoFileHive(RegistryHive) && CmiGetBlock(RegistryHive, VBOffset, &pBin))
1354 NtQuerySystemTime(&pBin->DateModified);
1357 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1358 ObDereferenceObject(KeyObject);
1362 DPRINT("Return Status 0x%X\n", Status);
1369 NtDeleteValueKey (IN HANDLE KeyHandle,
1370 IN PUNICODE_STRING ValueName)
1372 PKEY_OBJECT KeyObject;
1375 /* Verify that the handle is valid and is a registry key */
1376 Status = ObReferenceObjectByHandle(KeyHandle,
1380 (PVOID *)&KeyObject,
1382 if (!NT_SUCCESS(Status))
1387 /* Acquire hive lock */
1388 ExAcquireResourceExclusiveLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1390 VERIFY_KEY_OBJECT(KeyObject);
1392 Status = CmiDeleteValueFromKey(KeyObject->RegistryHive,
1394 KeyObject->BlockOffset,
1397 /* Release hive lock */
1398 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1400 ObDereferenceObject(KeyObject);
1410 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1411 * KeyObjectAttributes->Name specifies the name of the key to load.
1414 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
1415 IN POBJECT_ATTRIBUTES FileObjectAttributes)
1417 return NtLoadKey2 (KeyObjectAttributes,
1418 FileObjectAttributes,
1425 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1426 * KeyObjectAttributes->Name specifies the name of the key to load.
1427 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1430 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
1431 IN POBJECT_ATTRIBUTES FileObjectAttributes,
1434 POBJECT_NAME_INFORMATION NameInfo;
1435 PUNICODE_STRING NamePointer;
1441 DPRINT ("NtLoadKey2() called\n");
1444 if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
1445 return STATUS_PRIVILEGE_NOT_HELD;
1448 if (FileObjectAttributes->RootDirectory != NULL)
1451 sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
1452 Buffer = ExAllocatePool (NonPagedPool,
1455 return STATUS_INSUFFICIENT_RESOURCES;
1457 Status = NtQueryObject (FileObjectAttributes->RootDirectory,
1458 ObjectNameInformation,
1462 if (!NT_SUCCESS(Status))
1464 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status);
1465 ExFreePool (Buffer);
1469 NameInfo = (POBJECT_NAME_INFORMATION)Buffer;
1470 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1471 &NameInfo->Name, NameInfo->Name.Length);
1473 NameInfo->Name.MaximumLength = MAX_PATH * sizeof(WCHAR);
1474 if (FileObjectAttributes->ObjectName->Buffer[0] != L'\\')
1476 RtlAppendUnicodeToString (&NameInfo->Name,
1478 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1479 &NameInfo->Name, NameInfo->Name.Length);
1481 RtlAppendUnicodeStringToString (&NameInfo->Name,
1482 FileObjectAttributes->ObjectName);
1484 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1485 &NameInfo->Name, NameInfo->Name.Length);
1486 NamePointer = &NameInfo->Name;
1490 if (FileObjectAttributes->ObjectName->Buffer[0] == L'\\')
1493 NamePointer = FileObjectAttributes->ObjectName;
1498 sizeof(OBJECT_NAME_INFORMATION) + MAX_PATH * sizeof(WCHAR);
1499 Buffer = ExAllocatePool (NonPagedPool,
1502 return STATUS_INSUFFICIENT_RESOURCES;
1504 NameInfo = (POBJECT_NAME_INFORMATION)Buffer;
1505 NameInfo->Name.MaximumLength = MAX_PATH * sizeof(WCHAR);
1506 NameInfo->Name.Length = 0;
1507 NameInfo->Name.Buffer = (PWSTR)((ULONG_PTR)Buffer + sizeof(OBJECT_NAME_INFORMATION));
1508 NameInfo->Name.Buffer[0] = 0;
1510 RtlAppendUnicodeToString (&NameInfo->Name,
1512 RtlAppendUnicodeStringToString (&NameInfo->Name,
1513 FileObjectAttributes->ObjectName);
1515 NamePointer = &NameInfo->Name;
1519 DPRINT ("Full name: '%wZ'\n", NamePointer);
1521 Status = CmiLoadHive (KeyObjectAttributes,
1524 if (!NT_SUCCESS (Status))
1526 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status);
1530 ExFreePool (Buffer);
1537 NtNotifyChangeKey (IN HANDLE KeyHandle,
1539 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
1540 IN PVOID ApcContext OPTIONAL,
1541 OUT PIO_STATUS_BLOCK IoStatusBlock,
1542 IN ULONG CompletionFilter,
1543 IN BOOLEAN Asynchroneous,
1544 OUT PVOID ChangeBuffer,
1546 IN BOOLEAN WatchSubtree)
1549 return(STATUS_NOT_IMPLEMENTED);
1554 NtQueryMultipleValueKey (IN HANDLE KeyHandle,
1555 IN OUT PKEY_VALUE_ENTRY ValueList,
1556 IN ULONG NumberOfValues,
1558 IN OUT PULONG Length,
1559 OUT PULONG ReturnLength)
1561 PREGISTRY_HIVE RegistryHive;
1562 PVALUE_CELL ValueCell;
1563 PKEY_OBJECT KeyObject;
1564 PDATA_CELL DataCell;
1565 ULONG BufferLength = 0;
1571 /* Verify that the handle is valid and is a registry key */
1572 Status = ObReferenceObjectByHandle(KeyHandle,
1576 (PVOID *) &KeyObject,
1578 if (!NT_SUCCESS(Status))
1580 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status);
1584 /* Acquire hive lock */
1585 ExAcquireResourceSharedLite(&KeyObject->RegistryHive->HiveResource, TRUE);
1587 VERIFY_KEY_OBJECT(KeyObject);
1589 /* Get pointer to KeyCell */
1590 KeyCell = KeyObject->KeyCell;
1591 RegistryHive = KeyObject->RegistryHive;
1593 DataPtr = (PUCHAR) Buffer;
1595 for (i = 0; i < NumberOfValues; i++)
1597 DPRINT("ValueName: '%wZ'\n", ValueList[i].ValueName);
1599 /* Get Value block of interest */
1600 Status = CmiScanKeyForValue(RegistryHive,
1602 ValueList[i].ValueName,
1606 if (!NT_SUCCESS(Status))
1608 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status);
1611 else if (ValueCell == NULL)
1613 Status = STATUS_OBJECT_NAME_NOT_FOUND;
1617 BufferLength = (BufferLength + 3) & 0xfffffffc;
1619 if (BufferLength + (ValueCell->DataSize & LONG_MAX) <= *Length)
1621 DataPtr = (PUCHAR)(((ULONG)DataPtr + 3) & 0xfffffffc);
1623 ValueList[i].Type = ValueCell->DataType;
1624 ValueList[i].DataLength = ValueCell->DataSize & LONG_MAX;
1625 ValueList[i].DataOffset = (ULONG) DataPtr - (ULONG) Buffer;
1627 if (ValueCell->DataSize > 0)
1629 DataCell = CmiGetBlock(RegistryHive,
1630 ValueCell->DataOffset,
1632 RtlCopyMemory(DataPtr,
1634 ValueCell->DataSize & LONG_MAX);
1638 RtlCopyMemory(DataPtr,
1639 &ValueCell->DataOffset,
1640 ValueCell->DataSize & LONG_MAX);
1643 DataPtr += ValueCell->DataSize & LONG_MAX;
1647 Status = STATUS_BUFFER_TOO_SMALL;
1650 BufferLength += ValueCell->DataSize & LONG_MAX;
1653 if (NT_SUCCESS(Status))
1654 *Length = BufferLength;
1656 *ReturnLength = BufferLength;
1658 /* Release hive lock */
1659 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1661 ObDereferenceObject(KeyObject);
1663 DPRINT("Return Status 0x%X\n", Status);
1670 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes,
1672 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
1675 return(STATUS_NOT_IMPLEMENTED);
1680 NtRestoreKey (IN HANDLE KeyHandle,
1681 IN HANDLE FileHandle,
1682 IN ULONG RestoreFlags)
1685 return(STATUS_NOT_IMPLEMENTED);
1690 NtSaveKey (IN HANDLE KeyHandle,
1691 IN HANDLE FileHandle)
1693 PREGISTRY_HIVE TempHive;
1694 PKEY_OBJECT KeyObject;
1697 DPRINT ("NtSaveKey() called\n");
1700 if (!SeSinglePrivilegeCheck (SeBackupPrivilege, KeGetPreviousMode ()))
1701 return STATUS_PRIVILEGE_NOT_HELD;
1704 Status = ObReferenceObjectByHandle (KeyHandle,
1707 KeGetPreviousMode(),
1708 (PVOID *)&KeyObject,
1710 if (!NT_SUCCESS(Status))
1712 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status);
1716 /* Acquire hive lock exclucively */
1717 ExAcquireResourceExclusiveLite (&KeyObject->RegistryHive->HiveResource,
1720 /* Refuse to save a volatile key */
1721 if (KeyObject->RegistryHive == CmiVolatileHive)
1723 DPRINT1 ("Cannot save a volatile key\n");
1724 ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
1725 ObDereferenceObject (KeyObject);
1726 return STATUS_ACCESS_DENIED;
1729 Status = CmiCreateTempHive(&TempHive);
1730 if (!NT_SUCCESS(Status))
1732 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status);
1733 ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
1734 ObDereferenceObject (KeyObject);
1738 Status = CmiCopyKey (TempHive,
1740 KeyObject->RegistryHive,
1741 KeyObject->KeyCell);
1742 if (!NT_SUCCESS(Status))
1744 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status);
1745 CmiRemoveRegistryHive (TempHive);
1746 ExReleaseResourceLite (&KeyObject->RegistryHive->HiveResource);
1747 ObDereferenceObject (KeyObject);
1751 Status = CmiSaveTempHive (TempHive,
1753 if (!NT_SUCCESS(Status))
1755 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status);
1758 CmiRemoveRegistryHive (TempHive);
1760 /* Release hive lock */
1761 ExReleaseResourceLite(&KeyObject->RegistryHive->HiveResource);
1763 ObDereferenceObject (KeyObject);
1765 DPRINT ("NtSaveKey() done\n");
1767 return STATUS_SUCCESS;
1772 NtSetInformationKey (IN HANDLE KeyHandle,
1773 IN CINT KeyInformationClass,
1774 IN PVOID KeyInformation,
1775 IN ULONG KeyInformationLength)
1778 return(STATUS_NOT_IMPLEMENTED);
1784 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1785 * KeyObjectAttributes->Name specifies the name of the key to unload.
1788 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes)
1790 PREGISTRY_HIVE RegistryHive;
1793 DPRINT ("NtUnloadKey() called\n");
1796 if (!SeSinglePrivilegeCheck (SeRestorePrivilege, KeGetPreviousMode ()))
1797 return STATUS_PRIVILEGE_NOT_HELD;
1800 Status = CmiDisconnectHive (KeyObjectAttributes,
1802 if (!NT_SUCCESS (Status))
1804 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status);
1808 DPRINT ("RegistryHive %p\n", RegistryHive);
1810 /* Acquire hive list lock exclusively */
1811 ExAcquireResourceExclusiveLite (&CmiHiveListLock,
1816 if (!IsNoFileHive (RegistryHive))
1817 CmiFlushRegistryHive (RegistryHive);
1820 /* Release hive list lock */
1821 ExReleaseResourceLite (&CmiHiveListLock);
1823 CmiRemoveRegistryHive (RegistryHive);
1825 DPRINT ("NtUnloadKey() done\n");
1827 return STATUS_SUCCESS;
1832 NtInitializeRegistry (IN BOOLEAN SetUpBoot)
1836 if (CmiRegistryInitialized == TRUE)
1837 return STATUS_ACCESS_DENIED;
1839 /* FIXME: save boot log file */
1841 Status = CmiInitHives (SetUpBoot);
1843 CmiRegistryInitialized = TRUE;