3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/ntfunc.c
6 * PURPOSE: Ntxxx function for registry access
8 * PROGRAMMERS: No programmer listed.
11 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
20 /* GLOBALS ******************************************************************/
22 extern POBJECT_TYPE CmiKeyType
;
23 extern PREGISTRY_HIVE CmiVolatileHive
;
24 extern LIST_ENTRY CmiKeyObjectListHead
;
26 static BOOLEAN CmiRegistryInitialized
= FALSE
;
28 LIST_ENTRY CmiCallbackHead
;
29 FAST_MUTEX CmiCallbackLock
;
31 /* FUNCTIONS ****************************************************************/
37 CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function
,
39 IN OUT PLARGE_INTEGER Cookie
)
41 PREGISTRY_CALLBACK Callback
;
45 ASSERT(Function
&& Cookie
);
47 Callback
= ExAllocatePoolWithTag(PagedPool
,
48 sizeof(REGISTRY_CALLBACK
),
49 TAG('C', 'M', 'c', 'b'));
52 /* initialize the callback */
53 ExInitializeRundownProtection(&Callback
->RundownRef
);
54 Callback
->Function
= Function
;
55 Callback
->Context
= Context
;
56 Callback
->PendingDelete
= FALSE
;
58 /* add it to the callback list and receive a cookie for the callback */
59 ExAcquireFastMutex(&CmiCallbackLock
);
60 /* FIXME - to receive a unique cookie we'll just return the pointer to the
62 Callback
->Cookie
.QuadPart
= (ULONG_PTR
)Callback
;
63 InsertTailList(&CmiCallbackHead
, &Callback
->ListEntry
);
65 ExReleaseFastMutex(&CmiCallbackLock
);
67 *Cookie
= Callback
->Cookie
;
68 return STATUS_SUCCESS
;
71 return STATUS_INSUFFICIENT_RESOURCES
;
79 CmUnRegisterCallback(IN LARGE_INTEGER Cookie
)
81 PLIST_ENTRY CurrentEntry
;
85 ExAcquireFastMutex(&CmiCallbackLock
);
87 for(CurrentEntry
= CmiCallbackHead
.Flink
;
88 CurrentEntry
!= &CmiCallbackHead
;
89 CurrentEntry
= CurrentEntry
->Flink
)
91 PREGISTRY_CALLBACK CurrentCallback
;
93 CurrentCallback
= CONTAINING_RECORD(CurrentEntry
, REGISTRY_CALLBACK
, ListEntry
);
94 if(CurrentCallback
->Cookie
.QuadPart
== Cookie
.QuadPart
)
96 if(!CurrentCallback
->PendingDelete
)
98 /* found the callback, don't unlink it from the list yet so we don't screw
100 CurrentCallback
->PendingDelete
= TRUE
;
101 ExReleaseFastMutex(&CmiCallbackLock
);
103 /* if the callback is currently executing, wait until it finished */
104 ExWaitForRundownProtectionRelease(&CurrentCallback
->RundownRef
);
106 /* time to unlink it. It's now safe because every attempt to acquire a
107 runtime protection on this callback will fail */
108 ExAcquireFastMutex(&CmiCallbackLock
);
109 RemoveEntryList(&CurrentCallback
->ListEntry
);
110 ExReleaseFastMutex(&CmiCallbackLock
);
112 /* free the callback */
113 ExFreePool(CurrentCallback
);
114 return STATUS_SUCCESS
;
118 /* pending delete, pretend like it already is deleted */
119 ExReleaseFastMutex(&CmiCallbackLock
);
120 return STATUS_UNSUCCESSFUL
;
125 ExReleaseFastMutex(&CmiCallbackLock
);
127 return STATUS_UNSUCCESSFUL
;
132 CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1
,
135 PLIST_ENTRY CurrentEntry
;
139 ExAcquireFastMutex(&CmiCallbackLock
);
141 for(CurrentEntry
= CmiCallbackHead
.Flink
;
142 CurrentEntry
!= &CmiCallbackHead
;
143 CurrentEntry
= CurrentEntry
->Flink
)
145 PREGISTRY_CALLBACK CurrentCallback
;
147 CurrentCallback
= CONTAINING_RECORD(CurrentEntry
, REGISTRY_CALLBACK
, ListEntry
);
148 if(!CurrentCallback
->PendingDelete
&&
149 ExAcquireRundownProtectionEx(&CurrentCallback
->RundownRef
, 1))
153 /* don't hold locks during the callbacks! */
154 ExReleaseFastMutex(&CmiCallbackLock
);
156 Status
= CurrentCallback
->Function(CurrentCallback
->Context
,
159 if(!NT_SUCCESS(Status
))
161 /* one callback returned failure, don't call any more callbacks */
165 ExAcquireFastMutex(&CmiCallbackLock
);
166 /* don't release the rundown protection before holding the callback lock
167 so the pointer to the next callback isn't cleared in case this callback
169 ExReleaseRundownProtectionEx(&CurrentCallback
->RundownRef
, 1);
173 ExReleaseFastMutex(&CmiCallbackLock
);
175 return STATUS_SUCCESS
;
180 NtCreateKey(OUT PHANDLE KeyHandle
,
181 IN ACCESS_MASK DesiredAccess
,
182 IN POBJECT_ATTRIBUTES ObjectAttributes
,
184 IN PUNICODE_STRING Class
,
185 IN ULONG CreateOptions
,
186 OUT PULONG Disposition
)
188 UNICODE_STRING RemainingPath
;
189 PKEY_OBJECT KeyObject
;
197 DPRINT("NtCreateKey (Name %wZ KeyHandle %x Root %x)\n",
198 ObjectAttributes
->ObjectName
,
200 ObjectAttributes
->RootDirectory
);
202 Status
= ObFindObject(ObjectAttributes
,
206 if (!NT_SUCCESS(Status
))
208 DPRINT("ObFindObject failed, Status: 0x%x\n", Status
);
212 DPRINT("RemainingPath %wZ\n", &RemainingPath
);
214 if (RemainingPath
.Length
== 0)
216 /* Fail if the key has been deleted */
217 if (((PKEY_OBJECT
) Object
)->Flags
& KO_MARKED_FOR_DELETE
)
219 ObDereferenceObject(Object
);
220 RtlFreeUnicodeString(&RemainingPath
);
221 DPRINT("Object marked for delete!\n");
222 return(STATUS_UNSUCCESSFUL
);
226 *Disposition
= REG_OPENED_EXISTING_KEY
;
228 Status
= ObCreateHandle(PsGetCurrentProcess(),
234 DPRINT("ObCreateHandle failed Status 0x%x\n", Status
);
235 ObDereferenceObject(Object
);
236 RtlFreeUnicodeString(&RemainingPath
);
240 /* If RemainingPath contains \ we must return error
241 because NtCreateKey doesn't create trees */
242 Start
= RemainingPath
.Buffer
;
246 for (i
= 1; i
< RemainingPath
.Length
/ sizeof(WCHAR
); i
++)
248 if (L
'\\' == RemainingPath
.Buffer
[i
])
250 ObDereferenceObject(Object
);
251 DPRINT1("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath
);
252 RtlFreeUnicodeString(&RemainingPath
);
253 return STATUS_OBJECT_NAME_NOT_FOUND
;
257 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
259 Status
= ObCreateObject(ExGetPreviousMode(),
268 if (!NT_SUCCESS(Status
))
270 DPRINT1("ObCreateObject() failed!\n");
274 Status
= ObInsertObject((PVOID
)KeyObject
,
280 if (!NT_SUCCESS(Status
))
282 ObDereferenceObject(KeyObject
);
283 RtlFreeUnicodeString(&RemainingPath
);
284 DPRINT1("ObInsertObject() failed!\n");
288 KeyObject
->ParentKey
= Object
;
290 if (CreateOptions
& REG_OPTION_VOLATILE
)
291 KeyObject
->RegistryHive
= CmiVolatileHive
;
293 KeyObject
->RegistryHive
= KeyObject
->ParentKey
->RegistryHive
;
295 KeyObject
->Flags
= 0;
296 KeyObject
->NumberOfSubKeys
= 0;
297 KeyObject
->SizeOfSubKeys
= 0;
298 KeyObject
->SubKeys
= NULL
;
300 /* Acquire hive lock */
301 KeEnterCriticalRegion();
302 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
304 InsertTailList(&CmiKeyObjectListHead
, &KeyObject
->ListEntry
);
306 /* add key to subkeys of parent if needed */
307 Status
= CmiAddSubKey(KeyObject
->RegistryHive
,
308 KeyObject
->ParentKey
,
314 if (!NT_SUCCESS(Status
))
316 DPRINT("CmiAddSubKey() failed (Status %lx)\n", Status
);
317 /* Release hive lock */
318 ExReleaseResourceLite(&CmiRegistryLock
);
319 KeLeaveCriticalRegion();
320 ObDereferenceObject(KeyObject
);
321 ObDereferenceObject(Object
);
322 RtlFreeUnicodeString(&RemainingPath
);
323 return STATUS_UNSUCCESSFUL
;
326 if (Start
== RemainingPath
.Buffer
)
328 KeyObject
->Name
= RemainingPath
;
332 RtlpCreateUnicodeString(&KeyObject
->Name
, Start
, NonPagedPool
);
333 RtlFreeUnicodeString(&RemainingPath
);
336 if (KeyObject
->RegistryHive
== KeyObject
->ParentKey
->RegistryHive
)
338 KeyObject
->KeyCell
->ParentKeyOffset
= KeyObject
->ParentKey
->KeyCellOffset
;
339 KeyObject
->KeyCell
->SecurityKeyOffset
= KeyObject
->ParentKey
->KeyCell
->SecurityKeyOffset
;
343 KeyObject
->KeyCell
->ParentKeyOffset
= -1;
344 KeyObject
->KeyCell
->SecurityKeyOffset
= -1;
345 /* This key must remain in memory unless it is deleted
346 or file is unloaded */
347 ObReferenceObjectByPointer(KeyObject
,
348 STANDARD_RIGHTS_REQUIRED
,
353 CmiAddKeyToList(KeyObject
->ParentKey
, KeyObject
);
355 VERIFY_KEY_OBJECT(KeyObject
);
357 /* Release hive lock */
358 ExReleaseResourceLite(&CmiRegistryLock
);
359 KeLeaveCriticalRegion();
362 ObDereferenceObject(Object
);
365 *Disposition
= REG_CREATED_NEW_KEY
;
374 NtDeleteKey(IN HANDLE KeyHandle
)
376 KPROCESSOR_MODE PreviousMode
;
377 PKEY_OBJECT KeyObject
;
382 DPRINT1("NtDeleteKey(KeyHandle %x) called\n", KeyHandle
);
384 PreviousMode
= ExGetPreviousMode();
386 /* Verify that the handle is valid and is a registry key */
387 Status
= ObReferenceObjectByHandle(KeyHandle
,
393 if (!NT_SUCCESS(Status
))
395 DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
399 /* Acquire hive lock */
400 KeEnterCriticalRegion();
401 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
403 VERIFY_KEY_OBJECT(KeyObject
);
405 /* Check for subkeys */
406 if (KeyObject
->NumberOfSubKeys
!= 0)
408 Status
= STATUS_CANNOT_DELETE
;
412 /* Set the marked for delete bit in the key object */
413 KeyObject
->Flags
|= KO_MARKED_FOR_DELETE
;
414 Status
= STATUS_SUCCESS
;
417 /* Release hive lock */
418 ExReleaseResourceLite(&CmiRegistryLock
);
419 KeLeaveCriticalRegion();
421 DPRINT1("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
423 /* Dereference the object */
424 ObDereferenceObject(KeyObject
);
425 /* Remove the keep-alive reference */
426 ObDereferenceObject(KeyObject
);
428 if (KeyObject
->RegistryHive
!= KeyObject
->ParentKey
->RegistryHive
)
429 ObDereferenceObject(KeyObject
);
431 DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID
)KeyObject
));
432 DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID
)KeyObject
));
436 * Hive-Synchronization will not be triggered here. This is done in
437 * CmiObjectDelete() (in regobj.c) after all key-related structures
438 * have been released.
446 NtEnumerateKey(IN HANDLE KeyHandle
,
448 IN KEY_INFORMATION_CLASS KeyInformationClass
,
449 OUT PVOID KeyInformation
,
451 OUT PULONG ResultLength
)
453 PKEY_OBJECT KeyObject
;
454 PKEY_OBJECT SubKeyObject
;
455 PREGISTRY_HIVE RegistryHive
;
456 PKEY_CELL KeyCell
, SubKeyCell
;
457 PHASH_TABLE_CELL HashTableBlock
;
458 PKEY_BASIC_INFORMATION BasicInformation
;
459 PKEY_NODE_INFORMATION NodeInformation
;
460 PKEY_FULL_INFORMATION FullInformation
;
461 PDATA_CELL ClassCell
;
462 ULONG NameSize
, ClassSize
;
467 DPRINT("KH %x I %d KIC %x KI %x L %d RL %x\n",
475 /* Verify that the handle is valid and is a registry key */
476 Status
= ObReferenceObjectByHandle(KeyHandle
,
477 KEY_ENUMERATE_SUB_KEYS
,
480 (PVOID
*) &KeyObject
,
482 if (!NT_SUCCESS(Status
))
484 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
488 /* Acquire hive lock */
489 KeEnterCriticalRegion();
490 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
492 VERIFY_KEY_OBJECT(KeyObject
);
494 /* Get pointer to KeyCell */
495 KeyCell
= KeyObject
->KeyCell
;
496 RegistryHive
= KeyObject
->RegistryHive
;
500 /* Check for hightest possible sub key index */
501 if (Index
>= KeyCell
->NumberOfSubKeys
+ KeyObject
->NumberOfSubKeys
)
503 ExReleaseResourceLite(&CmiRegistryLock
);
504 KeLeaveCriticalRegion();
505 ObDereferenceObject(KeyObject
);
506 DPRINT("No more volatile entries\n");
507 return STATUS_NO_MORE_ENTRIES
;
510 /* Get pointer to SubKey */
511 if (Index
>= KeyCell
->NumberOfSubKeys
)
513 PKEY_OBJECT CurKey
= NULL
;
517 /* Search for volatile or 'foreign' keys */
518 j
= KeyCell
->NumberOfSubKeys
;
519 for (i
= 0; i
< KeyObject
->NumberOfSubKeys
; i
++)
521 CurKey
= KeyObject
->SubKeys
[i
];
522 if (CurKey
->RegistryHive
!= RegistryHive
)
530 if (i
>= KeyObject
->NumberOfSubKeys
)
532 ExReleaseResourceLite(&CmiRegistryLock
);
533 KeLeaveCriticalRegion();
534 ObDereferenceObject(KeyObject
);
535 DPRINT("No more non-volatile entries\n");
536 return STATUS_NO_MORE_ENTRIES
;
539 SubKeyObject
= CurKey
;
540 SubKeyCell
= CurKey
->KeyCell
;
544 if (KeyCell
->HashTableOffset
== (BLOCK_OFFSET
)-1)
546 ExReleaseResourceLite(&CmiRegistryLock
);
547 KeLeaveCriticalRegion();
548 ObDereferenceObject(KeyObject
);
549 return STATUS_NO_MORE_ENTRIES
;
552 HashTableBlock
= CmiGetCell (RegistryHive
, KeyCell
->HashTableOffset
, NULL
);
553 if (HashTableBlock
== NULL
)
555 DPRINT("CmiGetBlock() failed\n");
556 ExReleaseResourceLite(&CmiRegistryLock
);
557 KeLeaveCriticalRegion();
558 ObDereferenceObject(KeyObject
);
559 return STATUS_UNSUCCESSFUL
;
562 SubKeyCell
= CmiGetKeyFromHashByIndex(RegistryHive
,
567 if (SubKeyCell
== NULL
)
569 ExReleaseResourceLite(&CmiRegistryLock
);
570 KeLeaveCriticalRegion();
571 ObDereferenceObject(KeyObject
);
572 DPRINT("No more entries\n");
573 return STATUS_NO_MORE_ENTRIES
;
576 Status
= STATUS_SUCCESS
;
577 switch (KeyInformationClass
)
579 case KeyBasicInformation
:
580 /* Check size of buffer */
581 if (SubKeyObject
!= NULL
)
583 NameSize
= SubKeyObject
->Name
.Length
;
587 NameSize
= SubKeyCell
->NameSize
;
588 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
590 NameSize
*= sizeof(WCHAR
);
594 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) + NameSize
;
597 * NOTE: It's perfetly valid to call NtEnumerateKey to get
598 * all the information but name. Actually the NT4 sound
599 * framework does that while querying parameters from registry.
600 * -- Filip Navara, 19/07/2004
602 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
604 Status
= STATUS_BUFFER_TOO_SMALL
;
608 /* Fill buffer with requested info */
609 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
610 BasicInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
611 BasicInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
612 BasicInformation
->TitleIndex
= Index
;
613 BasicInformation
->NameLength
= NameSize
;
615 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) < NameSize
)
617 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
618 Status
= STATUS_BUFFER_OVERFLOW
;
622 if (SubKeyObject
!= NULL
)
624 RtlCopyMemory(BasicInformation
->Name
,
625 SubKeyObject
->Name
.Buffer
,
630 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
632 CmiCopyPackedName(BasicInformation
->Name
,
634 NameSize
/ sizeof(WCHAR
));
638 RtlCopyMemory(BasicInformation
->Name
,
646 case KeyNodeInformation
:
647 /* Check size of buffer */
648 if (SubKeyObject
!= NULL
)
650 NameSize
= SubKeyObject
->Name
.Length
;
654 NameSize
= SubKeyCell
->NameSize
;
655 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
657 NameSize
*= sizeof(WCHAR
);
660 ClassSize
= SubKeyCell
->ClassSize
;
662 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
663 NameSize
+ ClassSize
;
665 if (Length
< FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]))
667 Status
= STATUS_BUFFER_TOO_SMALL
;
671 /* Fill buffer with requested info */
672 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
673 NodeInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
674 NodeInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
675 NodeInformation
->TitleIndex
= Index
;
676 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) + NameSize
;
677 NodeInformation
->ClassLength
= SubKeyCell
->ClassSize
;
678 NodeInformation
->NameLength
= NameSize
;
680 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
682 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
684 Status
= STATUS_BUFFER_OVERFLOW
;
687 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
688 NameSize
< ClassSize
)
690 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
692 Status
= STATUS_BUFFER_OVERFLOW
;
696 if (SubKeyObject
!= NULL
)
698 RtlCopyMemory(NodeInformation
->Name
,
699 SubKeyObject
->Name
.Buffer
,
704 if (SubKeyCell
->Flags
& REG_KEY_NAME_PACKED
)
706 CmiCopyPackedName(NodeInformation
->Name
,
708 NameSize
/ sizeof(WCHAR
));
712 RtlCopyMemory(NodeInformation
->Name
,
720 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
721 SubKeyCell
->ClassNameOffset
,
723 RtlCopyMemory (NodeInformation
->Name
+ SubKeyCell
->NameSize
,
730 case KeyFullInformation
:
731 ClassSize
= SubKeyCell
->ClassSize
;
733 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) +
736 /* Check size of buffer */
737 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]))
739 Status
= STATUS_BUFFER_TOO_SMALL
;
743 /* Fill buffer with requested info */
744 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
745 FullInformation
->LastWriteTime
.u
.LowPart
= SubKeyCell
->LastWriteTime
.u
.LowPart
;
746 FullInformation
->LastWriteTime
.u
.HighPart
= SubKeyCell
->LastWriteTime
.u
.HighPart
;
747 FullInformation
->TitleIndex
= Index
;
748 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) -
750 FullInformation
->ClassLength
= SubKeyCell
->ClassSize
;
751 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //SubKeyCell->NumberOfSubKeys;
752 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
753 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
754 FullInformation
->Values
= SubKeyCell
->NumberOfValues
;
755 FullInformation
->MaxValueNameLen
=
756 CmiGetMaxValueNameLength(RegistryHive
, SubKeyCell
);
757 FullInformation
->MaxValueDataLen
=
758 CmiGetMaxValueDataLength(RegistryHive
, SubKeyCell
);
760 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
762 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
763 Status
= STATUS_BUFFER_OVERFLOW
;
769 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
770 SubKeyCell
->ClassNameOffset
,
772 RtlCopyMemory (FullInformation
->Class
,
780 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
784 ExReleaseResourceLite(&CmiRegistryLock
);
785 KeLeaveCriticalRegion();
786 ObDereferenceObject(KeyObject
);
788 DPRINT("Returning status %x\n", Status
);
795 NtEnumerateValueKey(IN HANDLE KeyHandle
,
797 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
798 OUT PVOID KeyValueInformation
,
800 OUT PULONG ResultLength
)
803 PKEY_OBJECT KeyObject
;
804 PREGISTRY_HIVE RegistryHive
;
806 PVALUE_CELL ValueCell
;
808 ULONG NameSize
, DataSize
;
809 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
810 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
811 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
815 DPRINT("KH %x I %d KVIC %x KVI %x L %d RL %x\n",
818 KeyValueInformationClass
,
823 /* Verify that the handle is valid and is a registry key */
824 Status
= ObReferenceObjectByHandle(KeyHandle
,
828 (PVOID
*) &KeyObject
,
831 if (!NT_SUCCESS(Status
))
836 /* Acquire hive lock */
837 KeEnterCriticalRegion();
838 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
840 VERIFY_KEY_OBJECT(KeyObject
);
842 /* Get pointer to KeyCell */
843 KeyCell
= KeyObject
->KeyCell
;
844 RegistryHive
= KeyObject
->RegistryHive
;
846 /* Get Value block of interest */
847 Status
= CmiGetValueFromKeyByIndex(RegistryHive
,
852 if (!NT_SUCCESS(Status
))
854 ExReleaseResourceLite(&CmiRegistryLock
);
855 KeLeaveCriticalRegion();
856 ObDereferenceObject(KeyObject
);
860 if (ValueCell
!= NULL
)
862 switch (KeyValueInformationClass
)
864 case KeyValueBasicInformation
:
865 NameSize
= ValueCell
->NameSize
;
866 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
868 NameSize
*= sizeof(WCHAR
);
871 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) + NameSize
;
873 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
875 Status
= STATUS_BUFFER_TOO_SMALL
;
879 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
881 ValueBasicInformation
->TitleIndex
= 0;
882 ValueBasicInformation
->Type
= ValueCell
->DataType
;
883 ValueBasicInformation
->NameLength
= NameSize
;
885 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
888 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
889 Status
= STATUS_BUFFER_OVERFLOW
;
893 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
895 CmiCopyPackedName(ValueBasicInformation
->Name
,
897 NameSize
/ sizeof(WCHAR
));
901 RtlCopyMemory(ValueBasicInformation
->Name
,
908 case KeyValuePartialInformation
:
909 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
911 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
914 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
916 Status
= STATUS_BUFFER_TOO_SMALL
;
920 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
922 ValuePartialInformation
->TitleIndex
= 0;
923 ValuePartialInformation
->Type
= ValueCell
->DataType
;
924 ValuePartialInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
926 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
929 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
930 Status
= STATUS_BUFFER_OVERFLOW
;
934 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
936 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
937 RtlCopyMemory(ValuePartialInformation
->Data
,
943 RtlCopyMemory(ValuePartialInformation
->Data
,
944 &ValueCell
->DataOffset
,
950 case KeyValueFullInformation
:
951 NameSize
= ValueCell
->NameSize
;
952 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
954 NameSize
*= sizeof(WCHAR
);
956 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
958 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
959 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
961 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
963 Status
= STATUS_BUFFER_TOO_SMALL
;
967 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
969 ValueFullInformation
->TitleIndex
= 0;
970 ValueFullInformation
->Type
= ValueCell
->DataType
;
971 ValueFullInformation
->NameLength
= NameSize
;
972 ValueFullInformation
->DataOffset
=
973 (ULONG_PTR
)ValueFullInformation
->Name
-
974 (ULONG_PTR
)ValueFullInformation
+
975 ValueFullInformation
->NameLength
;
976 ValueFullInformation
->DataOffset
=
977 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
978 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
980 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
983 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
985 Status
= STATUS_BUFFER_OVERFLOW
;
988 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
989 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
991 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) - NameSize
, sizeof(PVOID
));
992 Status
= STATUS_BUFFER_OVERFLOW
;
996 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
998 CmiCopyPackedName(ValueFullInformation
->Name
,
1000 NameSize
/ sizeof(WCHAR
));
1004 RtlCopyMemory(ValueFullInformation
->Name
,
1009 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1011 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1012 RtlCopyMemory((PCHAR
) ValueFullInformation
1013 + ValueFullInformation
->DataOffset
,
1014 DataCell
->Data
, DataSize
);
1018 RtlCopyMemory((PCHAR
) ValueFullInformation
1019 + ValueFullInformation
->DataOffset
,
1020 &ValueCell
->DataOffset
, DataSize
);
1026 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1032 Status
= STATUS_UNSUCCESSFUL
;
1035 ExReleaseResourceLite(&CmiRegistryLock
);
1036 KeLeaveCriticalRegion();
1037 ObDereferenceObject(KeyObject
);
1044 NtFlushKey(IN HANDLE KeyHandle
)
1047 PKEY_OBJECT KeyObject
;
1048 PREGISTRY_HIVE RegistryHive
;
1049 KPROCESSOR_MODE PreviousMode
;
1053 DPRINT("NtFlushKey (KeyHandle %lx) called\n", KeyHandle
);
1055 PreviousMode
= ExGetPreviousMode();
1057 /* Verify that the handle is valid and is a registry key */
1058 Status
= ObReferenceObjectByHandle(KeyHandle
,
1062 (PVOID
*)&KeyObject
,
1064 if (!NT_SUCCESS(Status
))
1069 VERIFY_KEY_OBJECT(KeyObject
);
1071 RegistryHive
= KeyObject
->RegistryHive
;
1073 /* Acquire hive lock */
1074 KeEnterCriticalRegion();
1075 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1077 if (IsNoFileHive(RegistryHive
))
1079 Status
= STATUS_SUCCESS
;
1083 /* Flush non-volatile hive */
1084 Status
= CmiFlushRegistryHive(RegistryHive
);
1087 ExReleaseResourceLite(&CmiRegistryLock
);
1088 KeLeaveCriticalRegion();
1090 ObDereferenceObject(KeyObject
);
1092 return STATUS_SUCCESS
;
1097 NtOpenKey(OUT PHANDLE KeyHandle
,
1098 IN ACCESS_MASK DesiredAccess
,
1099 IN POBJECT_ATTRIBUTES ObjectAttributes
)
1101 UNICODE_STRING RemainingPath
;
1102 KPROCESSOR_MODE PreviousMode
;
1105 NTSTATUS Status
= STATUS_SUCCESS
;
1109 DPRINT("NtOpenKey(KH %x DA %x OA %x OA->ON '%wZ'\n",
1113 ObjectAttributes
? ObjectAttributes
->ObjectName
: NULL
);
1115 PreviousMode
= ExGetPreviousMode();
1117 if(PreviousMode
!= KernelMode
)
1121 ProbeForWrite(KeyHandle
,
1127 Status
= _SEH_GetExceptionCode();
1131 if(!NT_SUCCESS(Status
))
1137 RemainingPath
.Buffer
= NULL
;
1138 Status
= ObFindObject(ObjectAttributes
,
1142 if (!NT_SUCCESS(Status
))
1147 VERIFY_KEY_OBJECT((PKEY_OBJECT
) Object
);
1149 DPRINT("RemainingPath '%wZ'\n", &RemainingPath
);
1151 if ((RemainingPath
.Buffer
!= NULL
) && (RemainingPath
.Buffer
[0] != 0))
1153 ObDereferenceObject(Object
);
1154 RtlFreeUnicodeString(&RemainingPath
);
1155 return STATUS_OBJECT_NAME_NOT_FOUND
;
1158 RtlFreeUnicodeString(&RemainingPath
);
1160 /* Fail if the key has been deleted */
1161 if (((PKEY_OBJECT
)Object
)->Flags
& KO_MARKED_FOR_DELETE
)
1163 ObDereferenceObject(Object
);
1164 return(STATUS_UNSUCCESSFUL
);
1167 Status
= ObCreateHandle(PsGetCurrentProcess(),
1172 ObDereferenceObject(Object
);
1174 if (!NT_SUCCESS(Status
))
1185 Status
= _SEH_GetExceptionCode();
1194 NtQueryKey(IN HANDLE KeyHandle
,
1195 IN KEY_INFORMATION_CLASS KeyInformationClass
,
1196 OUT PVOID KeyInformation
,
1198 OUT PULONG ResultLength
)
1200 PKEY_BASIC_INFORMATION BasicInformation
;
1201 PKEY_NODE_INFORMATION NodeInformation
;
1202 PKEY_FULL_INFORMATION FullInformation
;
1203 PREGISTRY_HIVE RegistryHive
;
1204 PDATA_CELL ClassCell
;
1205 PKEY_OBJECT KeyObject
;
1207 ULONG NameSize
, ClassSize
;
1212 DPRINT("NtQueryKey(KH %x KIC %x KI %x L %d RL %x)\n",
1214 KeyInformationClass
,
1219 /* Verify that the handle is valid and is a registry key */
1220 Status
= ObReferenceObjectByHandle(KeyHandle
,
1224 (PVOID
*) &KeyObject
,
1226 if (!NT_SUCCESS(Status
))
1231 /* Acquire hive lock */
1232 KeEnterCriticalRegion();
1233 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
1235 VERIFY_KEY_OBJECT(KeyObject
);
1237 /* Get pointer to KeyCell */
1238 KeyCell
= KeyObject
->KeyCell
;
1239 RegistryHive
= KeyObject
->RegistryHive
;
1241 Status
= STATUS_SUCCESS
;
1242 switch (KeyInformationClass
)
1244 case KeyBasicInformation
:
1245 NameSize
= KeyObject
->Name
.Length
;
1247 *ResultLength
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1249 /* Check size of buffer */
1250 if (Length
< FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]))
1252 Status
= STATUS_BUFFER_TOO_SMALL
;
1256 /* Fill buffer with requested info */
1257 BasicInformation
= (PKEY_BASIC_INFORMATION
) KeyInformation
;
1258 BasicInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1259 BasicInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1260 BasicInformation
->TitleIndex
= 0;
1261 BasicInformation
->NameLength
= KeyObject
->Name
.Length
;
1263 if (Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]) <
1266 NameSize
= Length
- FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
[0]);
1267 Status
= STATUS_BUFFER_OVERFLOW
;
1271 RtlCopyMemory(BasicInformation
->Name
,
1272 KeyObject
->Name
.Buffer
,
1277 case KeyNodeInformation
:
1278 NameSize
= KeyObject
->Name
.Length
;
1279 ClassSize
= KeyCell
->ClassSize
;
1281 *ResultLength
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) +
1282 NameSize
+ ClassSize
;
1284 /* Check size of buffer */
1285 if (Length
< *ResultLength
)
1287 Status
= STATUS_BUFFER_TOO_SMALL
;
1291 /* Fill buffer with requested info */
1292 NodeInformation
= (PKEY_NODE_INFORMATION
) KeyInformation
;
1293 NodeInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1294 NodeInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1295 NodeInformation
->TitleIndex
= 0;
1296 NodeInformation
->ClassOffset
= sizeof(KEY_NODE_INFORMATION
) +
1297 KeyObject
->Name
.Length
;
1298 NodeInformation
->ClassLength
= KeyCell
->ClassSize
;
1299 NodeInformation
->NameLength
= KeyObject
->Name
.Length
;
1301 if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) < NameSize
)
1303 NameSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]);
1305 Status
= STATUS_BUFFER_OVERFLOW
;
1308 else if (Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1309 NameSize
< ClassSize
)
1311 ClassSize
= Length
- FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
[0]) -
1313 Status
= STATUS_BUFFER_OVERFLOW
;
1317 RtlCopyMemory(NodeInformation
->Name
,
1318 KeyObject
->Name
.Buffer
,
1323 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1324 KeyCell
->ClassNameOffset
,
1326 RtlCopyMemory (NodeInformation
->Name
+ KeyObject
->Name
.Length
,
1333 case KeyFullInformation
:
1334 ClassSize
= KeyCell
->ClassSize
;
1336 *ResultLength
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
) +
1339 /* Check size of buffer */
1340 if (Length
< FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
))
1342 Status
= STATUS_BUFFER_TOO_SMALL
;
1346 /* Fill buffer with requested info */
1347 FullInformation
= (PKEY_FULL_INFORMATION
) KeyInformation
;
1348 FullInformation
->LastWriteTime
.u
.LowPart
= KeyCell
->LastWriteTime
.u
.LowPart
;
1349 FullInformation
->LastWriteTime
.u
.HighPart
= KeyCell
->LastWriteTime
.u
.HighPart
;
1350 FullInformation
->TitleIndex
= 0;
1351 FullInformation
->ClassOffset
= sizeof(KEY_FULL_INFORMATION
) - sizeof(WCHAR
);
1352 FullInformation
->ClassLength
= KeyCell
->ClassSize
;
1353 FullInformation
->SubKeys
= CmiGetNumberOfSubKeys(KeyObject
); //KeyCell->NumberOfSubKeys;
1354 FullInformation
->MaxNameLen
= CmiGetMaxNameLength(KeyObject
);
1355 FullInformation
->MaxClassLen
= CmiGetMaxClassLength(KeyObject
);
1356 FullInformation
->Values
= KeyCell
->NumberOfValues
;
1357 FullInformation
->MaxValueNameLen
=
1358 CmiGetMaxValueNameLength(RegistryHive
, KeyCell
);
1359 FullInformation
->MaxValueDataLen
=
1360 CmiGetMaxValueDataLength(RegistryHive
, KeyCell
);
1362 if (Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]) < ClassSize
)
1364 ClassSize
= Length
- FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
[0]);
1365 Status
= STATUS_BUFFER_OVERFLOW
;
1371 ClassCell
= CmiGetCell (KeyObject
->RegistryHive
,
1372 KeyCell
->ClassNameOffset
,
1374 RtlCopyMemory (FullInformation
->Class
,
1375 ClassCell
->Data
, ClassSize
);
1381 DPRINT1("Not handling 0x%x\n", KeyInformationClass
);
1382 Status
= STATUS_INVALID_INFO_CLASS
;
1386 ExReleaseResourceLite(&CmiRegistryLock
);
1387 KeLeaveCriticalRegion();
1388 ObDereferenceObject(KeyObject
);
1395 NtQueryValueKey(IN HANDLE KeyHandle
,
1396 IN PUNICODE_STRING ValueName
,
1397 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
1398 OUT PVOID KeyValueInformation
,
1400 OUT PULONG ResultLength
)
1403 ULONG NameSize
, DataSize
;
1404 PKEY_OBJECT KeyObject
;
1405 PREGISTRY_HIVE RegistryHive
;
1407 PVALUE_CELL ValueCell
;
1408 PDATA_CELL DataCell
;
1409 PKEY_VALUE_BASIC_INFORMATION ValueBasicInformation
;
1410 PKEY_VALUE_PARTIAL_INFORMATION ValuePartialInformation
;
1411 PKEY_VALUE_FULL_INFORMATION ValueFullInformation
;
1415 DPRINT("NtQueryValueKey(KeyHandle %x ValueName %S Length %x)\n",
1416 KeyHandle
, ValueName
->Buffer
, Length
);
1418 /* Verify that the handle is valid and is a registry key */
1419 Status
= ObReferenceObjectByHandle(KeyHandle
,
1423 (PVOID
*)&KeyObject
,
1426 if (!NT_SUCCESS(Status
))
1428 DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status
);
1432 /* Acquire hive lock */
1433 KeEnterCriticalRegion();
1434 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
1436 VERIFY_KEY_OBJECT(KeyObject
);
1438 /* Get pointer to KeyCell */
1439 KeyCell
= KeyObject
->KeyCell
;
1440 RegistryHive
= KeyObject
->RegistryHive
;
1442 /* Get value cell by name */
1443 Status
= CmiScanKeyForValue(RegistryHive
,
1448 if (!NT_SUCCESS(Status
))
1450 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
1454 Status
= STATUS_SUCCESS
;
1455 switch (KeyValueInformationClass
)
1457 case KeyValueBasicInformation
:
1458 NameSize
= ValueCell
->NameSize
;
1459 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1461 NameSize
*= sizeof(WCHAR
);
1464 *ResultLength
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) +
1467 if (Length
< FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]))
1469 Status
= STATUS_BUFFER_TOO_SMALL
;
1473 ValueBasicInformation
= (PKEY_VALUE_BASIC_INFORMATION
)
1474 KeyValueInformation
;
1475 ValueBasicInformation
->TitleIndex
= 0;
1476 ValueBasicInformation
->Type
= ValueCell
->DataType
;
1477 ValueBasicInformation
->NameLength
= NameSize
;
1479 if (Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]) <
1482 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
[0]);
1483 Status
= STATUS_BUFFER_OVERFLOW
;
1487 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1489 CmiCopyPackedName(ValueBasicInformation
->Name
,
1491 NameSize
/ sizeof(WCHAR
));
1495 RtlCopyMemory(ValueBasicInformation
->Name
,
1502 case KeyValuePartialInformation
:
1503 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1505 *ResultLength
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) +
1508 if (Length
< FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]))
1510 Status
= STATUS_BUFFER_TOO_SMALL
;
1514 ValuePartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)
1515 KeyValueInformation
;
1516 ValuePartialInformation
->TitleIndex
= 0;
1517 ValuePartialInformation
->Type
= ValueCell
->DataType
;
1518 ValuePartialInformation
->DataLength
= DataSize
;
1520 if (Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]) <
1523 DataSize
= Length
- FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
1524 Status
= STATUS_BUFFER_OVERFLOW
;
1528 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1530 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1531 RtlCopyMemory(ValuePartialInformation
->Data
,
1537 RtlCopyMemory(ValuePartialInformation
->Data
,
1538 &ValueCell
->DataOffset
,
1544 case KeyValueFullInformation
:
1545 NameSize
= ValueCell
->NameSize
;
1546 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1548 NameSize
*= sizeof(WCHAR
);
1550 DataSize
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1552 *ResultLength
= ROUND_UP(FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1553 Name
[0]) + NameSize
, sizeof(PVOID
)) + DataSize
;
1555 if (Length
< FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]))
1557 Status
= STATUS_BUFFER_TOO_SMALL
;
1561 ValueFullInformation
= (PKEY_VALUE_FULL_INFORMATION
)
1562 KeyValueInformation
;
1563 ValueFullInformation
->TitleIndex
= 0;
1564 ValueFullInformation
->Type
= ValueCell
->DataType
;
1565 ValueFullInformation
->NameLength
= NameSize
;
1566 ValueFullInformation
->DataOffset
=
1567 (ULONG_PTR
)ValueFullInformation
->Name
-
1568 (ULONG_PTR
)ValueFullInformation
+
1569 ValueFullInformation
->NameLength
;
1570 ValueFullInformation
->DataOffset
=
1571 ROUND_UP(ValueFullInformation
->DataOffset
, sizeof(PVOID
));
1572 ValueFullInformation
->DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
1574 if (Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]) <
1577 NameSize
= Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
[0]);
1579 Status
= STATUS_BUFFER_OVERFLOW
;
1582 else if (ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1583 Name
[0]) - NameSize
, sizeof(PVOID
)) < DataSize
)
1585 DataSize
= ROUND_UP(Length
- FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
,
1586 Name
[0]) - NameSize
, sizeof(PVOID
));
1587 Status
= STATUS_BUFFER_OVERFLOW
;
1591 if (ValueCell
->Flags
& REG_VALUE_NAME_PACKED
)
1593 CmiCopyPackedName(ValueFullInformation
->Name
,
1595 NameSize
/ sizeof(WCHAR
));
1599 RtlCopyMemory(ValueFullInformation
->Name
,
1603 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
1605 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1606 RtlCopyMemory((PCHAR
) ValueFullInformation
1607 + ValueFullInformation
->DataOffset
,
1613 RtlCopyMemory((PCHAR
) ValueFullInformation
1614 + ValueFullInformation
->DataOffset
,
1615 &ValueCell
->DataOffset
,
1622 DPRINT1("Not handling 0x%x\n", KeyValueInformationClass
);
1623 Status
= STATUS_INVALID_INFO_CLASS
;
1628 ExReleaseResourceLite(&CmiRegistryLock
);
1629 KeLeaveCriticalRegion();
1630 ObDereferenceObject(KeyObject
);
1637 NtSetValueKey(IN HANDLE KeyHandle
,
1638 IN PUNICODE_STRING ValueName
,
1639 IN ULONG TitleIndex
,
1645 PKEY_OBJECT KeyObject
;
1646 PREGISTRY_HIVE RegistryHive
;
1648 PVALUE_CELL ValueCell
;
1649 BLOCK_OFFSET ValueCellOffset
;
1650 PDATA_CELL DataCell
;
1651 PDATA_CELL NewDataCell
;
1653 ULONG DesiredAccess
;
1657 DPRINT("NtSetValueKey(KeyHandle %x ValueName '%wZ' Type %d)\n",
1658 KeyHandle
, ValueName
, Type
);
1660 DesiredAccess
= KEY_SET_VALUE
;
1661 if (Type
== REG_LINK
)
1662 DesiredAccess
|= KEY_CREATE_LINK
;
1664 /* Verify that the handle is valid and is a registry key */
1665 Status
= ObReferenceObjectByHandle(KeyHandle
,
1669 (PVOID
*)&KeyObject
,
1671 if (!NT_SUCCESS(Status
))
1674 /* Acquire hive lock exclucively */
1675 KeEnterCriticalRegion();
1676 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1678 VERIFY_KEY_OBJECT(KeyObject
);
1680 /* Get pointer to key cell */
1681 KeyCell
= KeyObject
->KeyCell
;
1682 RegistryHive
= KeyObject
->RegistryHive
;
1683 Status
= CmiScanKeyForValue(RegistryHive
,
1688 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1690 DPRINT("Allocate new value cell\n");
1691 Status
= CmiAddValueToKey(RegistryHive
,
1693 KeyObject
->KeyCellOffset
,
1699 if (!NT_SUCCESS(Status
))
1701 DPRINT("Cannot add value. Status 0x%X\n", Status
);
1703 ExReleaseResourceLite(&CmiRegistryLock
);
1704 KeLeaveCriticalRegion();
1705 ObDereferenceObject(KeyObject
);
1709 DPRINT("DataSize %lu\n", DataSize
);
1710 DPRINT("ValueCell %p\n", ValueCell
);
1711 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1713 if (DataSize
<= sizeof(BLOCK_OFFSET
))
1715 /* If data size <= sizeof(BLOCK_OFFSET) then store data in the data offset */
1716 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1717 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1718 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1720 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1721 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1724 RtlCopyMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1725 ValueCell
->DataSize
= DataSize
| REG_DATA_IN_OFFSET
;
1726 ValueCell
->DataType
= Type
;
1727 RtlMoveMemory(&ValueCell
->DataOffset
, Data
, DataSize
);
1728 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1730 else if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1731 (DataSize
<= (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
)))
1733 /* If new data size is <= current then overwrite current data */
1734 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
,&pBin
);
1735 RtlZeroMemory(DataCell
->Data
, ValueCell
->DataSize
);
1736 RtlCopyMemory(DataCell
->Data
, Data
, DataSize
);
1737 ValueCell
->DataSize
= DataSize
;
1738 ValueCell
->DataType
= Type
;
1743 * New data size is larger than the current, destroy current
1744 * data block and allocate a new one.
1746 BLOCK_OFFSET NewOffset
;
1748 DPRINT("ValueCell->DataSize %lu\n", ValueCell
->DataSize
);
1750 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
) &&
1751 (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) != 0)
1753 DataCell
= CmiGetCell (RegistryHive
, ValueCell
->DataOffset
, NULL
);
1754 CmiDestroyCell(RegistryHive
, DataCell
, ValueCell
->DataOffset
);
1755 ValueCell
->DataSize
= 0;
1756 ValueCell
->DataType
= 0;
1757 ValueCell
->DataOffset
= (BLOCK_OFFSET
)-1;
1760 Status
= CmiAllocateCell (RegistryHive
,
1761 sizeof(CELL_HEADER
) + DataSize
,
1762 (PVOID
*)&NewDataCell
,
1764 if (!NT_SUCCESS(Status
))
1766 DPRINT("CmiAllocateBlock() failed (Status %lx)\n", Status
);
1768 ExReleaseResourceLite(&CmiRegistryLock
);
1769 KeLeaveCriticalRegion();
1770 ObDereferenceObject(KeyObject
);
1775 RtlCopyMemory(&NewDataCell
->Data
[0], Data
, DataSize
);
1776 ValueCell
->DataSize
= DataSize
& REG_DATA_SIZE_MASK
;
1777 ValueCell
->DataType
= Type
;
1778 ValueCell
->DataOffset
= NewOffset
;
1779 CmiMarkBlockDirty(RegistryHive
, ValueCell
->DataOffset
);
1780 CmiMarkBlockDirty(RegistryHive
, ValueCellOffset
);
1784 if ((Type
== REG_LINK
) &&
1785 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
1787 KeyCell
->Flags
|= REG_KEY_LINK_CELL
;
1790 KeQuerySystemTime (&KeyCell
->LastWriteTime
);
1791 CmiMarkBlockDirty (RegistryHive
, KeyObject
->KeyCellOffset
);
1793 ExReleaseResourceLite(&CmiRegistryLock
);
1794 KeLeaveCriticalRegion();
1795 ObDereferenceObject(KeyObject
);
1799 DPRINT("Return Status 0x%X\n", Status
);
1806 NtDeleteValueKey (IN HANDLE KeyHandle
,
1807 IN PUNICODE_STRING ValueName
)
1809 PKEY_OBJECT KeyObject
;
1814 /* Verify that the handle is valid and is a registry key */
1815 Status
= ObReferenceObjectByHandle(KeyHandle
,
1819 (PVOID
*)&KeyObject
,
1821 if (!NT_SUCCESS(Status
))
1826 /* Acquire hive lock */
1827 KeEnterCriticalRegion();
1828 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1830 VERIFY_KEY_OBJECT(KeyObject
);
1832 Status
= CmiDeleteValueFromKey(KeyObject
->RegistryHive
,
1834 KeyObject
->KeyCellOffset
,
1837 KeQuerySystemTime (&KeyObject
->KeyCell
->LastWriteTime
);
1838 CmiMarkBlockDirty (KeyObject
->RegistryHive
, KeyObject
->KeyCellOffset
);
1840 /* Release hive lock */
1841 ExReleaseResourceLite(&CmiRegistryLock
);
1842 KeLeaveCriticalRegion();
1844 ObDereferenceObject (KeyObject
);
1854 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1855 * KeyObjectAttributes->Name specifies the name of the key to load.
1858 NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1859 IN POBJECT_ATTRIBUTES FileObjectAttributes
)
1861 return NtLoadKey2 (KeyObjectAttributes
,
1862 FileObjectAttributes
,
1869 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
1870 * KeyObjectAttributes->Name specifies the name of the key to load.
1871 * Flags can be 0 or REG_NO_LAZY_FLUSH.
1874 NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
1875 IN POBJECT_ATTRIBUTES FileObjectAttributes
,
1878 POBJECT_NAME_INFORMATION NameInfo
;
1879 PUNICODE_STRING NamePointer
;
1887 DPRINT ("NtLoadKey2() called\n");
1890 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
1891 return STATUS_PRIVILEGE_NOT_HELD
;
1894 if (FileObjectAttributes
->RootDirectory
!= NULL
)
1897 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1898 Buffer
= ExAllocatePool (NonPagedPool
,
1901 return STATUS_INSUFFICIENT_RESOURCES
;
1903 Status
= ZwQueryObject (FileObjectAttributes
->RootDirectory
,
1904 ObjectNameInformation
,
1908 if (!NT_SUCCESS(Status
))
1910 DPRINT1 ("NtQueryObject() failed (Status %lx)\n", Status
);
1911 ExFreePool (Buffer
);
1915 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1916 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1917 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1919 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1920 if (FileObjectAttributes
->ObjectName
->Buffer
[0] != L
'\\')
1922 RtlAppendUnicodeToString (&NameInfo
->Name
,
1924 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1925 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1927 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1928 FileObjectAttributes
->ObjectName
);
1930 DPRINT ("ObjectPath: '%wZ' Length %hu\n",
1931 &NameInfo
->Name
, NameInfo
->Name
.Length
);
1932 NamePointer
= &NameInfo
->Name
;
1936 if (FileObjectAttributes
->ObjectName
->Buffer
[0] == L
'\\')
1939 NamePointer
= FileObjectAttributes
->ObjectName
;
1944 sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
);
1945 Buffer
= ExAllocatePool (NonPagedPool
,
1948 return STATUS_INSUFFICIENT_RESOURCES
;
1950 NameInfo
= (POBJECT_NAME_INFORMATION
)Buffer
;
1951 NameInfo
->Name
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
1952 NameInfo
->Name
.Length
= 0;
1953 NameInfo
->Name
.Buffer
= (PWSTR
)((ULONG_PTR
)Buffer
+ sizeof(OBJECT_NAME_INFORMATION
));
1954 NameInfo
->Name
.Buffer
[0] = 0;
1956 RtlAppendUnicodeToString (&NameInfo
->Name
,
1958 RtlAppendUnicodeStringToString (&NameInfo
->Name
,
1959 FileObjectAttributes
->ObjectName
);
1961 NamePointer
= &NameInfo
->Name
;
1965 DPRINT ("Full name: '%wZ'\n", NamePointer
);
1967 /* Acquire hive lock */
1968 KeEnterCriticalRegion();
1969 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
1971 Status
= CmiLoadHive (KeyObjectAttributes
,
1974 if (!NT_SUCCESS (Status
))
1976 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
1979 /* Release hive lock */
1980 ExReleaseResourceLite(&CmiRegistryLock
);
1981 KeLeaveCriticalRegion();
1984 ExFreePool (Buffer
);
1991 NtNotifyChangeKey (IN HANDLE KeyHandle
,
1993 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
1994 IN PVOID ApcContext OPTIONAL
,
1995 OUT PIO_STATUS_BLOCK IoStatusBlock
,
1996 IN ULONG CompletionFilter
,
1997 IN BOOLEAN WatchSubtree
,
2000 IN BOOLEAN Asynchronous
)
2003 return(STATUS_NOT_IMPLEMENTED
);
2008 NtQueryMultipleValueKey (IN HANDLE KeyHandle
,
2009 IN OUT PKEY_VALUE_ENTRY ValueList
,
2010 IN ULONG NumberOfValues
,
2012 IN OUT PULONG Length
,
2013 OUT PULONG ReturnLength
)
2015 PREGISTRY_HIVE RegistryHive
;
2016 PVALUE_CELL ValueCell
;
2017 PKEY_OBJECT KeyObject
;
2018 PDATA_CELL DataCell
;
2019 ULONG BufferLength
= 0;
2027 /* Verify that the handle is valid and is a registry key */
2028 Status
= ObReferenceObjectByHandle(KeyHandle
,
2032 (PVOID
*) &KeyObject
,
2034 if (!NT_SUCCESS(Status
))
2036 DPRINT("ObReferenceObjectByHandle() failed with status %x\n", Status
);
2040 /* Acquire hive lock */
2041 KeEnterCriticalRegion();
2042 ExAcquireResourceSharedLite(&CmiRegistryLock
, TRUE
);
2044 VERIFY_KEY_OBJECT(KeyObject
);
2046 /* Get pointer to KeyCell */
2047 KeyCell
= KeyObject
->KeyCell
;
2048 RegistryHive
= KeyObject
->RegistryHive
;
2050 DataPtr
= (PUCHAR
) Buffer
;
2052 for (i
= 0; i
< NumberOfValues
; i
++)
2054 DPRINT("ValueName: '%wZ'\n", ValueList
[i
].ValueName
);
2056 /* Get Value block of interest */
2057 Status
= CmiScanKeyForValue(RegistryHive
,
2059 ValueList
[i
].ValueName
,
2063 if (!NT_SUCCESS(Status
))
2065 DPRINT("CmiScanKeyForValue() failed with status %x\n", Status
);
2068 else if (ValueCell
== NULL
)
2070 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
2074 BufferLength
= ROUND_UP(BufferLength
, sizeof(PVOID
));
2076 if (BufferLength
+ (ValueCell
->DataSize
& REG_DATA_SIZE_MASK
) <= *Length
)
2078 DataPtr
= (PUCHAR
)ROUND_UP((ULONG_PTR
)DataPtr
, sizeof(PVOID
));
2080 ValueList
[i
].Type
= ValueCell
->DataType
;
2081 ValueList
[i
].DataLength
= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
2082 ValueList
[i
].DataOffset
= (ULONG_PTR
)DataPtr
- (ULONG_PTR
)Buffer
;
2084 if (!(ValueCell
->DataSize
& REG_DATA_IN_OFFSET
))
2086 DataCell
= CmiGetCell (RegistryHive
,
2087 ValueCell
->DataOffset
,
2089 RtlCopyMemory(DataPtr
,
2091 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
2095 RtlCopyMemory(DataPtr
,
2096 &ValueCell
->DataOffset
,
2097 ValueCell
->DataSize
& REG_DATA_SIZE_MASK
);
2100 DataPtr
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
2104 Status
= STATUS_BUFFER_TOO_SMALL
;
2107 BufferLength
+= ValueCell
->DataSize
& REG_DATA_SIZE_MASK
;
2110 if (NT_SUCCESS(Status
))
2111 *Length
= BufferLength
;
2113 *ReturnLength
= BufferLength
;
2115 /* Release hive lock */
2116 ExReleaseResourceLite(&CmiRegistryLock
);
2117 KeLeaveCriticalRegion();
2119 ObDereferenceObject(KeyObject
);
2121 DPRINT("Return Status 0x%X\n", Status
);
2128 NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes
,
2130 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
2133 return(STATUS_NOT_IMPLEMENTED
);
2138 NtRestoreKey (IN HANDLE KeyHandle
,
2139 IN HANDLE FileHandle
,
2140 IN ULONG RestoreFlags
)
2143 return(STATUS_NOT_IMPLEMENTED
);
2148 NtSaveKey (IN HANDLE KeyHandle
,
2149 IN HANDLE FileHandle
)
2151 PREGISTRY_HIVE TempHive
;
2152 PKEY_OBJECT KeyObject
;
2157 DPRINT ("NtSaveKey() called\n");
2160 if (!SeSinglePrivilegeCheck (SeBackupPrivilege
, KeGetPreviousMode ()))
2161 return STATUS_PRIVILEGE_NOT_HELD
;
2164 Status
= ObReferenceObjectByHandle (KeyHandle
,
2167 KeGetPreviousMode(),
2168 (PVOID
*)&KeyObject
,
2170 if (!NT_SUCCESS(Status
))
2172 DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status
);
2176 /* Acquire hive lock exclucively */
2177 KeEnterCriticalRegion();
2178 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2180 /* Refuse to save a volatile key */
2181 if (KeyObject
->RegistryHive
== CmiVolatileHive
)
2183 DPRINT1 ("Cannot save a volatile key\n");
2184 ExReleaseResourceLite(&CmiRegistryLock
);
2185 KeLeaveCriticalRegion();
2186 ObDereferenceObject (KeyObject
);
2187 return STATUS_ACCESS_DENIED
;
2190 Status
= CmiCreateTempHive(&TempHive
);
2191 if (!NT_SUCCESS(Status
))
2193 DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status
);
2194 ExReleaseResourceLite(&CmiRegistryLock
);
2195 KeLeaveCriticalRegion();
2196 ObDereferenceObject (KeyObject
);
2200 Status
= CmiCopyKey (TempHive
,
2202 KeyObject
->RegistryHive
,
2203 KeyObject
->KeyCell
);
2204 if (!NT_SUCCESS(Status
))
2206 DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status
);
2207 CmiRemoveRegistryHive (TempHive
);
2208 ExReleaseResourceLite(&CmiRegistryLock
);
2209 KeLeaveCriticalRegion();
2210 ObDereferenceObject (KeyObject
);
2214 Status
= CmiSaveTempHive (TempHive
,
2216 if (!NT_SUCCESS(Status
))
2218 DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status
);
2221 CmiRemoveRegistryHive (TempHive
);
2223 /* Release hive lock */
2224 ExReleaseResourceLite(&CmiRegistryLock
);
2225 KeLeaveCriticalRegion();
2227 ObDereferenceObject (KeyObject
);
2229 DPRINT ("NtSaveKey() done\n");
2231 return STATUS_SUCCESS
;
2240 IN HANDLE KeyHandle
,
2241 IN HANDLE FileHandle
,
2242 IN ULONG Flags
// REG_STANDARD_FORMAT, etc..
2246 return STATUS_NOT_IMPLEMENTED
;
2251 NtSetInformationKey (IN HANDLE KeyHandle
,
2252 IN KEY_SET_INFORMATION_CLASS KeyInformationClass
,
2253 IN PVOID KeyInformation
,
2254 IN ULONG KeyInformationLength
)
2256 PKEY_OBJECT KeyObject
;
2261 if (KeyInformationClass
!= KeyWriteTimeInformation
)
2262 return STATUS_INVALID_INFO_CLASS
;
2264 if (KeyInformationLength
!= sizeof (KEY_WRITE_TIME_INFORMATION
))
2265 return STATUS_INFO_LENGTH_MISMATCH
;
2267 /* Verify that the handle is valid and is a registry key */
2268 Status
= ObReferenceObjectByHandle (KeyHandle
,
2272 (PVOID
*)&KeyObject
,
2274 if (!NT_SUCCESS (Status
))
2276 DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status
);
2280 /* Acquire hive lock */
2281 KeEnterCriticalRegion();
2282 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2284 VERIFY_KEY_OBJECT(KeyObject
);
2286 KeyObject
->KeyCell
->LastWriteTime
.QuadPart
=
2287 ((PKEY_WRITE_TIME_INFORMATION
)KeyInformation
)->LastWriteTime
.QuadPart
;
2289 CmiMarkBlockDirty (KeyObject
->RegistryHive
,
2290 KeyObject
->KeyCellOffset
);
2292 /* Release hive lock */
2293 ExReleaseResourceLite(&CmiRegistryLock
);
2294 KeLeaveCriticalRegion();
2296 ObDereferenceObject (KeyObject
);
2300 DPRINT ("NtSaveKey() done\n");
2302 return STATUS_SUCCESS
;
2308 * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
2309 * KeyObjectAttributes->Name specifies the name of the key to unload.
2312 NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes
)
2314 PREGISTRY_HIVE RegistryHive
;
2319 DPRINT ("NtUnloadKey() called\n");
2322 if (!SeSinglePrivilegeCheck (SeRestorePrivilege
, KeGetPreviousMode ()))
2323 return STATUS_PRIVILEGE_NOT_HELD
;
2326 /* Acquire registry lock exclusively */
2327 KeEnterCriticalRegion();
2328 ExAcquireResourceExclusiveLite(&CmiRegistryLock
, TRUE
);
2330 Status
= CmiDisconnectHive (KeyObjectAttributes
,
2332 if (!NT_SUCCESS (Status
))
2334 DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status
);
2335 ExReleaseResourceLite (&CmiRegistryLock
);
2336 KeLeaveCriticalRegion();
2340 DPRINT ("RegistryHive %p\n", RegistryHive
);
2344 if (!IsNoFileHive (RegistryHive
))
2345 CmiFlushRegistryHive (RegistryHive
);
2348 CmiRemoveRegistryHive (RegistryHive
);
2350 /* Release registry lock */
2351 ExReleaseResourceLite (&CmiRegistryLock
);
2352 KeLeaveCriticalRegion();
2354 DPRINT ("NtUnloadKey() done\n");
2356 return STATUS_SUCCESS
;
2361 NtInitializeRegistry (IN BOOLEAN SetUpBoot
)
2367 if (CmiRegistryInitialized
== TRUE
)
2368 return STATUS_ACCESS_DENIED
;
2370 /* Save boot log file */
2371 IopSaveBootLogToFile();
2373 Status
= CmiInitHives (SetUpBoot
);
2375 CmiRegistryInitialized
= TRUE
;