2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmapi.c
5 * PURPOSE: Configuration Manager - Internal Registry APIs
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 CmpSetValueKeyNew(IN PHHIVE Hive
,
21 IN PCM_KEY_NODE Parent
,
22 IN PUNICODE_STRING ValueName
,
31 HCELL_INDEX ValueCell
;
34 /* Check if we already have a value list */
35 if (Parent
->ValueList
.Count
)
37 /* Then make sure it's valid and dirty it */
38 ASSERT(Parent
->ValueList
.List
!= HCELL_NIL
);
39 HvMarkCellDirty(Hive
, Parent
->ValueList
.List
);
42 /* Allocate avalue cell */
43 ValueCell
= HvAllocateCell(Hive
,
44 FIELD_OFFSET(CM_KEY_VALUE
, Name
) +
45 CmpNameSize(Hive
, ValueName
),
47 if (ValueCell
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
49 /* Get the actual data for it */
50 CellData
= HvGetCell(Hive
, ValueCell
);
51 if (!CellData
) ASSERT(FALSE
);
53 /* Now we can release it, make sure it's also dirty */
54 HvReleaseCell(Hive
, ValueCell
);
55 ASSERT(HvIsCellDirty(Hive
, ValueCell
));
57 /* Set it up and copy the name */
58 CellData
->u
.KeyValue
.Signature
= CM_KEY_VALUE_SIGNATURE
;
59 CellData
->u
.KeyValue
.Flags
= 0;
60 CellData
->u
.KeyValue
.Type
= Type
;
61 CellData
->u
.KeyValue
.NameLength
= CmpCopyName(Hive
,
62 CellData
->u
.KeyValue
.Name
,
64 if (CellData
->u
.KeyValue
.NameLength
< ValueName
->Length
)
66 /* This is a compressed name */
67 CellData
->u
.KeyValue
.Flags
= VALUE_COMP_NAME
;
70 /* Check if this is a normal key */
71 if (DataSize
> CM_KEY_VALUE_SMALL
)
73 /* Build a data cell for it */
74 Status
= CmpSetValueDataNew(Hive
,
79 &CellData
->u
.KeyValue
.Data
);
80 if (!NT_SUCCESS(Status
))
82 /* We failed, free the cell */
83 HvFreeCell(Hive
, ValueCell
);
87 /* Otherwise, set the data length, and make sure the data is dirty */
88 CellData
->u
.KeyValue
.DataLength
= DataSize
;
89 ASSERT(HvIsCellDirty(Hive
, CellData
->u
.KeyValue
.Data
));
93 /* This is a small key, set the data directly inside */
94 CellData
->u
.KeyValue
.DataLength
= DataSize
+ CM_KEY_VALUE_SPECIAL_SIZE
;
95 CellData
->u
.KeyValue
.Data
= SmallData
;
98 /* Add this value cell to the child list */
99 Status
= CmpAddValueToList(Hive
,
105 /* If we failed, free the entire cell, including the data */
106 if (!NT_SUCCESS(Status
)) CmpFreeValue(Hive
, ValueCell
);
114 CmpSetValueKeyExisting(IN PHHIVE Hive
,
115 IN HCELL_INDEX OldChild
,
116 IN PCM_KEY_VALUE Value
,
120 IN ULONG StorageType
,
123 HCELL_INDEX DataCell
, NewCell
;
126 BOOLEAN WasSmall
, IsSmall
;
128 /* Mark the old child cell dirty */
129 HvMarkCellDirty(Hive
, OldChild
);
131 /* See if this is a small or normal key */
132 WasSmall
= CmpIsKeyValueSmall(&Length
, Value
->DataLength
);
134 /* See if our new data can fit in a small key */
135 IsSmall
= (DataSize
<= CM_KEY_VALUE_SMALL
) ? TRUE
: FALSE
;
137 /* Big keys are unsupported */
138 ASSERT_VALUE_BIG(Hive
, Length
);
139 ASSERT_VALUE_BIG(Hive
, DataSize
);
141 /* Mark the old value dirty */
142 CmpMarkValueDataDirty(Hive
, Value
);
144 /* Check if we have a small key */
147 /* Check if we had a normal key with some data in it */
148 if (!(WasSmall
) && (Length
> 0))
150 /* Free the previous data */
151 CmpFreeValueData(Hive
, Value
->Data
, Length
);
154 /* Write our data directly */
155 Value
->DataLength
= DataSize
+ CM_KEY_VALUE_SPECIAL_SIZE
;
156 Value
->Data
= TempData
;
158 return STATUS_SUCCESS
;
162 /* We have a normal key. Was the old cell also normal and had data? */
163 if (!(WasSmall
) && (Length
> 0))
165 /* Get the current data cell and actual data inside it */
166 DataCell
= Value
->Data
;
167 ASSERT(DataCell
!= HCELL_NIL
);
168 CellData
= HvGetCell(Hive
, DataCell
);
169 if (!CellData
) return STATUS_INSUFFICIENT_RESOURCES
;
171 /* Immediately release the cell */
172 HvReleaseCell(Hive
, DataCell
);
174 /* Make sure that the data cell actually has a size */
175 ASSERT(HvGetCellSize(Hive
, CellData
) > 0);
177 /* Check if the previous data cell could fit our new data */
178 if (DataSize
<= (ULONG
)(HvGetCellSize(Hive
, CellData
)))
185 /* Otherwise, re-allocate the current data cell */
186 NewCell
= HvReallocateCell(Hive
, DataCell
, DataSize
);
187 if (NewCell
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
192 /* This was a small key, or a key with no data, allocate a cell */
193 NewCell
= HvAllocateCell(Hive
, DataSize
, StorageType
);
194 if (NewCell
== HCELL_NIL
) return STATUS_INSUFFICIENT_RESOURCES
;
197 /* Now get the actual data for our data cell */
198 CellData
= HvGetCell(Hive
, NewCell
);
199 if (!CellData
) ASSERT(FALSE
);
201 /* Release it immediately */
202 HvReleaseCell(Hive
, NewCell
);
204 /* Copy our data into the data cell's buffer, and set up the value */
205 RtlCopyMemory(CellData
, Data
, DataSize
);
206 Value
->Data
= NewCell
;
207 Value
->DataLength
= DataSize
;
211 ASSERT(HvIsCellDirty(Hive
, NewCell
));
212 return STATUS_SUCCESS
;
218 CmSetValueKey(IN PKEY_OBJECT KeyObject
,
219 IN PUNICODE_STRING ValueName
,
226 PCM_KEY_VALUE Value
= NULL
;
227 HCELL_INDEX CurrentChild
, Cell
;
229 BOOLEAN Found
, Result
;
230 ULONG Count
, ChildIndex
, SmallData
, Storage
;
232 /* Acquire hive lock exclusively */
233 KeEnterCriticalRegion();
234 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
236 /* Get pointer to key cell */
237 Parent
= KeyObject
->KeyCell
;
238 Hive
= &KeyObject
->RegistryHive
->Hive
;
239 Cell
= KeyObject
->KeyCellOffset
;
241 /* Prepare to scan the key node */
242 Count
= Parent
->ValueList
.Count
;
246 /* Try to find the existing name */
247 Result
= CmpFindNameInList(Hive
,
255 Status
= STATUS_INSUFFICIENT_RESOURCES
;
259 /* Check if we found something */
260 if (CurrentChild
!= HCELL_NIL
)
263 Value
= (PCM_KEY_VALUE
)HvGetCell(Hive
, CurrentChild
);
267 Status
= STATUS_INSUFFICIENT_RESOURCES
;
271 /* Remember that we found it */
277 /* No child list, we'll need to add it */
281 /* Mark the cell dirty */
282 HvMarkCellDirty(Hive
, Cell
);
284 /* Get the storage type */
285 Storage
= HvGetCellType(Cell
);
287 /* Check if this is small data */
289 if ((DataLength
<= CM_KEY_VALUE_SMALL
) && (DataLength
> 0))
292 RtlCopyMemory(&SmallData
, Data
, DataLength
);
295 /* Check if we didn't find a matching key */
298 /* Call the internal routine */
299 Status
= CmpSetValueKeyNew(Hive
,
311 /* Call the internal routine */
312 Status
= CmpSetValueKeyExisting(Hive
,
323 if ((Type
== REG_LINK
) &&
324 (_wcsicmp(ValueName
->Buffer
, L
"SymbolicLinkValue") == 0))
326 Parent
->Flags
|= KEY_SYM_LINK
;
329 /* Check for success */
331 if (NT_SUCCESS(Status
))
333 /* Save the write time */
334 KeQuerySystemTime(&Parent
->LastWriteTime
);
337 /* Release the lock */
338 ExReleaseResourceLite(&CmpRegistryLock
);
339 KeLeaveCriticalRegion();
345 CmDeleteValueKey(IN PKEY_OBJECT KeyObject
,
346 IN UNICODE_STRING ValueName
)
348 NTSTATUS Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
351 HCELL_INDEX ChildCell
, Cell
;
352 PCHILD_LIST ChildList
;
353 PCM_KEY_VALUE Value
= NULL
;
357 /* Acquire hive lock */
358 KeEnterCriticalRegion();
359 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
361 /* Get the hive and the cell index */
362 Hive
= &KeyObject
->RegistryHive
->Hive
;
363 Cell
= KeyObject
->KeyCellOffset
;
365 /* Get the parent key node */
366 Parent
= (PCM_KEY_NODE
)HvGetCell(Hive
, Cell
);
370 Status
= STATUS_INSUFFICIENT_RESOURCES
;
374 /* Get the value list and check if it has any entries */
375 ChildList
= &Parent
->ValueList
;
376 if (ChildList
->Count
)
378 /* Try to find this value */
379 Result
= CmpFindNameInList(Hive
,
387 Status
= STATUS_INSUFFICIENT_RESOURCES
;
391 /* Value not found, return error */
392 if (ChildCell
== HCELL_NIL
) goto Quickie
;
394 /* We found the value, mark all relevant cells dirty */
395 HvMarkCellDirty(Hive
, Cell
);
396 HvMarkCellDirty(Hive
, Parent
->ValueList
.List
);
397 HvMarkCellDirty(Hive
, ChildCell
);
399 /* Get the key value */
400 Value
= (PCM_KEY_VALUE
)HvGetCell(Hive
,ChildCell
);
401 if (!Value
) ASSERT(FALSE
);
403 /* Mark it and all related data as dirty */
404 CmpMarkValueDataDirty(Hive
, Value
);
407 ASSERT(HvIsCellDirty(Hive
, Parent
->ValueList
.List
));
408 ASSERT(HvIsCellDirty(Hive
, ChildCell
));
410 /* Remove the value from the child list */
411 Status
= CmpRemoveValueFromList(Hive
, ChildIndex
, ChildList
);
412 if(!NT_SUCCESS(Status
)) goto Quickie
;
414 /* Remove the value and its data itself */
415 if (!CmpFreeValue(Hive
, ChildCell
))
417 /* Failed to free the value, fail */
418 Status
= STATUS_INSUFFICIENT_RESOURCES
;
422 /* Set the last write time */
423 KeQuerySystemTime(&Parent
->LastWriteTime
);
426 ASSERT(HvIsCellDirty(Hive
, Cell
));
428 /* Check if the value list is empty now */
429 if (!Parent
->ValueList
.Count
)
431 /* Then clear key node data */
432 Parent
->MaxValueNameLen
= 0;
433 Parent
->MaxValueDataLen
= 0;
436 /* Change default Status to success */
437 Status
= STATUS_SUCCESS
;
441 /* Release the parent cell, if any */
442 if (Parent
) HvReleaseCell(Hive
, Cell
);
444 /* Check if we had a value */
447 /* Release the child cell */
448 ASSERT(ChildCell
!= HCELL_NIL
);
449 HvReleaseCell(Hive
, ChildCell
);
452 /* Release hive lock */
453 ExReleaseResourceLite(&CmpRegistryLock
);
454 KeLeaveCriticalRegion();
460 CmQueryValueKey(IN PKEY_OBJECT KeyObject
,
461 IN UNICODE_STRING ValueName
,
462 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
463 IN PVOID KeyValueInformation
,
465 IN PULONG ResultLength
)
468 PCM_KEY_VALUE ValueData
;
470 BOOLEAN ValueCached
= FALSE
;
471 PCM_CACHED_VALUE
*CachedValue
;
472 HCELL_INDEX CellToRelease
;
473 VALUE_SEARCH_RETURN_TYPE Result
;
477 /* Acquire hive lock */
478 KeEnterCriticalRegion();
479 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
482 Hive
= &KeyObject
->RegistryHive
->Hive
;
484 /* Find the key value */
485 Result
= CmpFindValueByNameFromCache(KeyObject
,
492 if (Result
== SearchSuccess
)
495 ASSERT(ValueData
!= NULL
);
497 /* Query the information requested */
498 Result
= CmpQueryKeyValueData(KeyObject
,
502 KeyValueInformationClass
,
510 /* Failed to find the value */
511 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
514 /* If we have a cell to release, do so */
515 if (CellToRelease
!= HCELL_NIL
) HvReleaseCell(Hive
, CellToRelease
);
517 /* Release hive lock */
518 ExReleaseResourceLite(&CmpRegistryLock
);
519 KeLeaveCriticalRegion();
525 CmEnumerateValueKey(IN PKEY_OBJECT KeyObject
,
527 IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass
,
528 IN PVOID KeyValueInformation
,
530 IN PULONG ResultLength
)
535 HCELL_INDEX CellToRelease
= HCELL_NIL
, CellToRelease2
= HCELL_NIL
;
536 VALUE_SEARCH_RETURN_TYPE Result
;
537 BOOLEAN IndexIsCached
, ValueIsCached
= FALSE
;
539 PCM_CACHED_VALUE
*CachedValue
;
540 PCM_KEY_VALUE ValueData
;
543 /* Acquire hive lock */
544 KeEnterCriticalRegion();
545 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
547 /* Get the hive and parent */
548 Hive
= &KeyObject
->RegistryHive
->Hive
;
549 Parent
= (PCM_KEY_NODE
)HvGetCell(Hive
, KeyObject
->KeyCellOffset
);
553 Status
= STATUS_INSUFFICIENT_RESOURCES
;
557 /* Make sure the index is valid */
558 //if (Index >= KeyObject->ValueCache.Count)
559 if (Index
>= KeyObject
->KeyCell
->ValueList
.Count
)
561 /* Release the cell and fail */
562 HvReleaseCell(Hive
, KeyObject
->KeyCellOffset
);
563 Status
= STATUS_NO_MORE_ENTRIES
;
567 /* Find the value list */
568 Result
= CmpGetValueListFromCache(KeyObject
,
572 if (Result
!= SearchSuccess
)
575 ASSERT(CellData
== NULL
);
577 /* Release the cell and fail */
578 Status
= STATUS_INSUFFICIENT_RESOURCES
;
582 /* Now get the key value */
583 Result
= CmpGetValueKeyFromCache(KeyObject
,
591 if (Result
!= SearchSuccess
)
594 ASSERT(CellToRelease2
== HCELL_NIL
);
596 /* Release the cells and fail */
597 Status
= STATUS_INSUFFICIENT_RESOURCES
;
601 /* Query the information requested */
602 Result
= CmpQueryKeyValueData(KeyObject
,
606 KeyValueInformationClass
,
613 /* If we have a cell to release, do so */
614 if (CellToRelease
!= HCELL_NIL
) HvReleaseCell(Hive
, CellToRelease
);
616 /* Release the parent cell */
617 HvReleaseCell(Hive
, KeyObject
->KeyCellOffset
);
619 /* If we have a cell to release, do so */
620 if (CellToRelease2
!= HCELL_NIL
) HvReleaseCell(Hive
, CellToRelease2
);
622 /* Release hive lock */
623 ExReleaseResourceLite(&CmpRegistryLock
);
624 KeLeaveCriticalRegion();
630 CmpQueryKeyData(IN PHHIVE Hive
,
631 IN PCM_KEY_NODE Node
,
632 IN KEY_INFORMATION_CLASS KeyInformationClass
,
633 IN OUT PVOID KeyInformation
,
635 IN OUT PULONG ResultLength
)
638 ULONG Size
, SizeLeft
, MinimumSize
;
639 PKEY_INFORMATION Info
= (PKEY_INFORMATION
)KeyInformation
;
642 /* Check if the value is compressed */
643 if (Node
->Flags
& KEY_COMP_NAME
)
645 /* Get the compressed name size */
646 NameLength
= CmpCompressedNameSize(Node
->Name
, Node
->NameLength
);
650 /* Get the real size */
651 NameLength
= Node
->NameLength
;
654 /* Check what kind of information is being requested */
655 switch (KeyInformationClass
)
657 /* Basic information */
658 case KeyBasicInformation
:
660 /* This is the size we need */
661 Size
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
) + NameLength
;
663 /* And this is the minimum we can work with */
664 MinimumSize
= FIELD_OFFSET(KEY_BASIC_INFORMATION
, Name
);
666 /* Let the caller know and assume success */
667 *ResultLength
= Size
;
668 Status
= STATUS_SUCCESS
;
670 /* Check if the bufer we got is too small */
671 if (Length
< MinimumSize
)
673 /* Let the caller know and fail */
674 Status
= STATUS_BUFFER_TOO_SMALL
;
678 /* Copy the basic information */
679 Info
->KeyBasicInformation
.LastWriteTime
= Node
->LastWriteTime
;
680 Info
->KeyBasicInformation
.TitleIndex
= 0;
681 Info
->KeyBasicInformation
.NameLength
= NameLength
;
683 /* Only the name is left */
684 SizeLeft
= Length
- MinimumSize
;
687 /* Check if we don't have enough space for the name */
690 /* Truncate the name we'll return, and tell the caller */
692 Status
= STATUS_BUFFER_OVERFLOW
;
695 /* Check if this is a compressed key */
696 if (Node
->Flags
& KEY_COMP_NAME
)
698 /* Copy the compressed name */
699 CmpCopyCompressedName(Info
->KeyBasicInformation
.Name
,
706 /* Otherwise, copy the raw name */
707 RtlCopyMemory(Info
->KeyBasicInformation
.Name
,
713 /* Node information */
714 case KeyNodeInformation
:
716 /* Calculate the size we need */
717 Size
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
) +
721 /* And the minimum size we can support */
722 MinimumSize
= FIELD_OFFSET(KEY_NODE_INFORMATION
, Name
);
724 /* Return the size to the caller and assume succes */
725 *ResultLength
= Size
;
726 Status
= STATUS_SUCCESS
;
728 /* Check if the caller's buffer is too small */
729 if (Length
< MinimumSize
)
731 /* Let them know, and fail */
732 Status
= STATUS_BUFFER_TOO_SMALL
;
736 /* Copy the basic information */
737 Info
->KeyNodeInformation
.LastWriteTime
= Node
->LastWriteTime
;
738 Info
->KeyNodeInformation
.TitleIndex
= 0;
739 Info
->KeyNodeInformation
.ClassLength
= Node
->ClassLength
;
740 Info
->KeyNodeInformation
.NameLength
= NameLength
;
742 /* Now the name is left */
743 SizeLeft
= Length
- MinimumSize
;
746 /* Check if the name can fit entirely */
749 /* It can't, we'll have to truncate. Tell the caller */
751 Status
= STATUS_BUFFER_OVERFLOW
;
754 /* Check if the key node name is compressed */
755 if (Node
->Flags
& KEY_COMP_NAME
)
757 /* Copy the compressed name */
758 CmpCopyCompressedName(Info
->KeyNodeInformation
.Name
,
765 /* It isn't, so copy the raw name */
766 RtlCopyMemory(Info
->KeyNodeInformation
.Name
,
771 /* Check if the node has a class */
772 if (Node
->ClassLength
> 0)
774 /* It does. We don't support these yet */
775 ASSERTMSG("Classes not supported\n", FALSE
);
779 /* It doesn't, so set offset to -1, not 0! */
780 Info
->KeyNodeInformation
.ClassOffset
= 0xFFFFFFFF;
784 /* Full information requsted */
785 case KeyFullInformation
:
787 /* This is the size we need */
788 Size
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
) +
791 /* This is what we can work with */
792 MinimumSize
= FIELD_OFFSET(KEY_FULL_INFORMATION
, Class
);
794 /* Return it to caller and assume success */
795 *ResultLength
= Size
;
796 Status
= STATUS_SUCCESS
;
798 /* Check if the caller's buffer is to small */
799 if (Length
< MinimumSize
)
801 /* Let them know and fail */
802 Status
= STATUS_BUFFER_TOO_SMALL
;
806 /* Now copy all the basic information */
807 Info
->KeyFullInformation
.LastWriteTime
= Node
->LastWriteTime
;
808 Info
->KeyFullInformation
.TitleIndex
= 0;
809 Info
->KeyFullInformation
.ClassLength
= Node
->ClassLength
;
810 Info
->KeyFullInformation
.SubKeys
= Node
->SubKeyCounts
[HvStable
] +
811 Node
->SubKeyCounts
[HvVolatile
];
812 Info
->KeyFullInformation
.Values
= Node
->ValueList
.Count
;
813 Info
->KeyFullInformation
.MaxNameLen
= CmiGetMaxNameLength(Hive
, Node
);
814 Info
->KeyFullInformation
.MaxClassLen
= CmiGetMaxClassLength(Hive
, Node
);
815 Info
->KeyFullInformation
.MaxValueNameLen
= CmiGetMaxValueNameLength(Hive
, Node
);
816 Info
->KeyFullInformation
.MaxValueDataLen
= CmiGetMaxValueDataLength(Hive
, Node
);
817 DPRINT("%d %d %d %d\n",
818 CmiGetMaxNameLength(Hive
, Node
),
819 CmiGetMaxValueDataLength(Hive
, Node
),
820 CmiGetMaxValueNameLength(Hive
, Node
),
821 CmiGetMaxClassLength(Hive
, Node
));
822 //Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
823 //Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
824 //Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
825 //Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
827 /* Check if we have a class */
828 if (Node
->ClassLength
> 0)
830 /* We do, but we currently don't support this */
831 ASSERTMSG("Classes not supported\n", FALSE
);
835 /* We don't have a class, so set offset to -1, not 0! */
836 Info
->KeyNodeInformation
.ClassOffset
= 0xFFFFFFFF;
840 /* Any other class that got sent here is invalid! */
843 /* Set failure code */
844 Status
= STATUS_INVALID_PARAMETER
;
854 CmQueryKey(IN PKEY_OBJECT KeyObject
,
855 IN KEY_INFORMATION_CLASS KeyInformationClass
,
856 IN PVOID KeyInformation
,
858 IN PULONG ResultLength
)
864 /* Acquire hive lock */
865 KeEnterCriticalRegion();
866 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
868 /* Get the hive and parent */
869 Hive
= &KeyObject
->RegistryHive
->Hive
;
870 Parent
= (PCM_KEY_NODE
)HvGetCell(Hive
, KeyObject
->KeyCellOffset
);
874 Status
= STATUS_INSUFFICIENT_RESOURCES
;
878 /* Check what class we got */
879 switch (KeyInformationClass
)
881 /* Typical information */
882 case KeyFullInformation
:
883 case KeyBasicInformation
:
884 case KeyNodeInformation
:
886 /* Call the internal API */
887 Status
= CmpQueryKeyData(Hive
,
895 /* Unsupported classes for now */
896 case KeyNameInformation
:
897 case KeyCachedInformation
:
898 case KeyFlagsInformation
:
900 /* Print message and fail */
901 DPRINT1("Unsupported class: %d!\n", KeyInformationClass
);
902 Status
= STATUS_NOT_IMPLEMENTED
;
905 /* Illegal classes */
908 /* Print message and fail */
909 DPRINT1("Unsupported class: %d!\n", KeyInformationClass
);
910 Status
= STATUS_INVALID_INFO_CLASS
;
915 /* Release hive lock */
916 ExReleaseResourceLite(&CmpRegistryLock
);
917 KeLeaveCriticalRegion();
923 CmEnumerateKey(IN PKEY_OBJECT KeyObject
,
925 IN KEY_INFORMATION_CLASS KeyInformationClass
,
926 IN PVOID KeyInformation
,
928 IN PULONG ResultLength
)
932 PCM_KEY_NODE Parent
, Child
;
933 HCELL_INDEX ChildCell
;
935 /* Acquire hive lock */
936 KeEnterCriticalRegion();
937 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
939 /* Get the hive and parent */
940 Hive
= &KeyObject
->RegistryHive
->Hive
;
941 Parent
= (PCM_KEY_NODE
)HvGetCell(Hive
, KeyObject
->KeyCellOffset
);
945 Status
= STATUS_INSUFFICIENT_RESOURCES
;
949 /* Get the child cell */
950 ChildCell
= CmpFindSubKeyByNumber(Hive
, Parent
, Index
);
952 /* Release the parent cell */
953 HvReleaseCell(Hive
, KeyObject
->KeyCellOffset
);
955 /* Check if we found the child */
956 if (ChildCell
== HCELL_NIL
)
958 /* We didn't, fail */
959 Status
= STATUS_NO_MORE_ENTRIES
;
963 /* Now get the actual child node */
964 Child
= (PCM_KEY_NODE
)HvGetCell(Hive
, ChildCell
);
968 Status
= STATUS_INSUFFICIENT_RESOURCES
;
972 /* Query the data requested */
973 Status
= CmpQueryKeyData(Hive
,
981 /* Release hive lock */
982 ExReleaseResourceLite(&CmpRegistryLock
);
983 KeLeaveCriticalRegion();