Author: fireball Date: Wed Dec 5 00:39:15 2007 New Revision: 31009
URL: http://svn.reactos.org/svn/reactos?rev=31009&view=rev Log: - Finish correct definition of CM_KEY_NODE. - Fix broken CmpTestRegistryLock functions, they could return FALSE even if the lock was held. - Enable some extra assertions. - Update KCB flags as well when updating keynode flags in CmpDoCreate. - Update KCB Last write time as well when updating keynode lastwritetime in CmpDoCreate. - Do CmpDoOpen with the registry lock held, and tell CmpCreateKeycontrolBlock to lock the KCB exclusively. - Enable link-node create code to set the ChildHiveRefernece values. This is used to "escape" the current Hive when a KEY_HIVE_EXIT node is detected (an internal symlink) and required for new parsing semantics. - Implement CmpHandleExitNode to test how "escaping" from an exit node into a link hive works (it does). - Plug that function into the new parse routine for testing purposes. - Enable CmpDoOpen path in the new parse routine, only used for link node creation for now.
Modified: trunk/reactos/lib/cmlib/cmdata.h trunk/reactos/ntoskrnl/config/cmparse.c trunk/reactos/ntoskrnl/config/cmsysini.c
Modified: trunk/reactos/lib/cmlib/cmdata.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/cmlib/cmdata.h?rev=3100... ============================================================================== --- trunk/reactos/lib/cmlib/cmdata.h (original) +++ trunk/reactos/lib/cmlib/cmdata.h Wed Dec 5 00:39:15 2007 @@ -103,7 +103,7 @@ HCELL_INDEX SubKeyLists[HTYPE_COUNT]; CHILD_LIST ValueList; }; - //CM_KEY_REFERENCE ChildHiveReference; + CM_KEY_REFERENCE ChildHiveReference; }; HCELL_INDEX Security; HCELL_INDEX Class;
Modified: trunk/reactos/ntoskrnl/config/cmparse.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmparse.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmparse.c (original) +++ trunk/reactos/ntoskrnl/config/cmparse.c Wed Dec 5 00:39:15 2007 @@ -379,11 +379,12 @@ ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell); ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive); ASSERT(KeyBody->KeyControlBlock->ParentKcb == ParentKcb); - //ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen); + ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
/* Update the timestamp */ KeQuerySystemTime(&TimeStamp); KeyNode->LastWriteTime = TimeStamp; + KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
/* Check if we need to update name maximum */ if (KeyNode->MaxNameLen < Name->Length) @@ -413,6 +414,7 @@
/* Update the flags */ CellData->u.KeyNode.Flags |= KEY_SYM_LINK; + KeyBody->KeyControlBlock->Flags = CellData->u.KeyNode.Flags; HvReleaseCell(Hive, KeyCell); } } @@ -448,6 +450,9 @@ /* It is, don't touch it */ return STATUS_OBJECT_NAME_NOT_FOUND; } + + /* Do this in the registry lock */ + CmpLockRegistry();
/* If we have a KCB, make sure it's locked */ //ASSERT(CmpIsKcbLockedExclusive(*CachedKcb)); @@ -457,13 +462,16 @@ Cell, Node, *CachedKcb, - CMP_LOCK_HASHES_FOR_KCB, + 0, KeyName); if (!Kcb) return STATUS_INSUFFICIENT_RESOURCES;
/* Make sure it's also locked, and set the pointer */ //ASSERT(CmpIsKcbLockedExclusive(Kcb)); *CachedKcb = Kcb; + + /* Release the registry lock */ + CmpUnlockRegistry();
/* Allocate the key object */ Status = ObCreateObject(AccessMode, @@ -671,8 +679,8 @@ KeyNode->ClassLength = 0;
/* Reference the root node */ - //KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive; - //KeyNode->ChildHiveReference.KeyCell = ChildCell; + KeyNode->ChildHiveReference.KeyHive = Context->ChildHive.KeyHive; + KeyNode->ChildHiveReference.KeyCell = ChildCell; HvReleaseCell(Hive, LinkCell);
/* Get the parent node */ @@ -698,7 +706,7 @@ /* Sanity checks */ ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell); ASSERT(KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive); - //ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen); + ASSERT(KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen);
/* Update the timestamp */ KeQuerySystemTime(&TimeStamp); @@ -725,6 +733,42 @@ ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock); ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock); return Status; +} + +VOID +NTAPI +CmpHandleExitNode(IN OUT PHHIVE *Hive, + IN OUT HCELL_INDEX *Cell, + IN OUT PCM_KEY_NODE *KeyNode, + IN OUT PHHIVE *ReleaseHive, + IN OUT HCELL_INDEX *ReleaseCell) +{ + /* Check if we have anything to release */ + if (*ReleaseCell != HCELL_NIL) + { + /* Release it */ + ASSERT(*ReleaseHive != NULL); + HvReleaseCell((*ReleaseHive), *ReleaseCell); + } + + /* Get the link references */ + *Hive = (*KeyNode)->ChildHiveReference.KeyHive; + *Cell = (*KeyNode)->ChildHiveReference.KeyCell; + + /* Get the new node */ + *KeyNode = (PCM_KEY_NODE)HvGetCell((*Hive), *Cell); + if (*KeyNode) + { + /* Set the new release values */ + *ReleaseCell = *Cell; + *ReleaseHive = *Hive; + } + else + { + /* Nothing to release */ + *ReleaseCell = HCELL_NIL; + *ReleaseHive = NULL; + } }
NTSTATUS @@ -775,11 +819,13 @@ IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *Object) { - NTSTATUS Status = STATUS_UNSUCCESSFUL; + NTSTATUS Status; PCM_KEY_CONTROL_BLOCK Kcb, ParentKcb; PHHIVE Hive = NULL; PCM_KEY_NODE Node = NULL; HCELL_INDEX Cell = HCELL_NIL, NextCell; + PHHIVE HiveToRelease = NULL; + HCELL_INDEX CellToRelease = HCELL_NIL; UNICODE_STRING Current, NextName; PCM_PARSE_CONTEXT ParseContext = Context; ULONG TotalRemainingSubkeys = 0, MatchRemainSubkeyLevel = 0, TotalSubkeys = 0; @@ -852,7 +898,7 @@ DPRINT1("Node Parse: %p\n", Node);
/* Start parsing */ - Status = STATUS_SUCCESS; + Status = STATUS_NOT_IMPLEMENTED; while (TRUE) { /* Get the next component */ @@ -865,7 +911,7 @@ { /* Find the subkey */ NextCell = CmpFindSubKeyByName(Hive, Node, &NextName); - DPRINT1("NextCell Parse: %lx\n", NextCell); + DPRINT1("NextCell Parse: %lx %wZ\n", NextCell, &NextName); if (NextCell != HCELL_NIL) { /* Get the new node */ @@ -877,17 +923,57 @@ /* Check if this was the last key */ if (Last) { - /* Shouldn't happen yet */ - DPRINT1("Unhandled: Open of last key\n"); + /* Is this an exit node */ + if (Node->Flags & KEY_HIVE_EXIT) + { + /* Handle it */ + DPRINT1("Exit node\n"); + CmpHandleExitNode(&Hive, + &Cell, + &Node, + &HiveToRelease, + &CellToRelease); + DPRINT1("Node Parse: %p\n", Node); + if (!Node) ASSERT(FALSE); + } + + /* Do the open */ + Status = CmpDoOpen(Hive, + Cell, + Node, + AccessState, + AccessMode, + Attributes, + ParseContext, + 0, + &Kcb, + &NextName, + Object); + if (Status == STATUS_REPARSE) + { + /* Not implemented */ + DPRINT1("Parsing sym link\n"); + while (TRUE); + } + + /* We are done */ + DPRINT1("Open of last key\n"); break; }
- /* Get hive and cell from reference */ - //Hive = Node->ChildHiveReference.KeyHive; - //Cell = Node->ChildHiveReference.KeyCell; - Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell); - DPRINT1("Node Parse: %p\n", Node); - if (!Node) ASSERT(FALSE); + /* Is this an exit node */ + if (Node->Flags & KEY_HIVE_EXIT) + { + /* Handle it */ + DPRINT1("Exit node: %lx\n", Node->Flags); + CmpHandleExitNode(&Hive, + &Cell, + &Node, + &HiveToRelease, + &CellToRelease); + DPRINT1("Node Parse: %p\n", Node); + if (!Node) ASSERT(FALSE); + }
/* Create a KCB for this key */ Kcb = CmpCreateKeyControlBlock(Hive, @@ -959,5 +1045,5 @@
/* Unlock the registry */ CmpUnlockRegistry(); - return STATUS_NOT_IMPLEMENTED; + return Status; }
Modified: trunk/reactos/ntoskrnl/config/cmsysini.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cmsysini.c?... ============================================================================== --- trunk/reactos/ntoskrnl/config/cmsysini.c (original) +++ trunk/reactos/ntoskrnl/config/cmsysini.c Wed Dec 5 00:39:15 2007 @@ -1580,7 +1580,7 @@ CmpTestRegistryLock(VOID) { /* Test the lock */ - return (BOOLEAN)ExIsResourceAcquiredSharedLite(&CmpRegistryLock); + return !ExIsResourceAcquiredSharedLite(&CmpRegistryLock) ? FALSE : TRUE; }
BOOLEAN @@ -1588,7 +1588,7 @@ CmpTestRegistryLockExclusive(VOID) { /* Test the lock */ - return ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock); + return !ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) ? FALSE : TRUE; }
VOID