예제 #1
0
VOID
NTAPI
CmpDereferenceKeyControlBlockWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
                                      IN BOOLEAN LockHeldExclusively)
{
    CMTRACE(CM_REFERENCE_DEBUG,
            "%s - Dereferencing KCB: %p\n", __FUNCTION__, Kcb);

    /* Sanity check */
    ASSERT_KCB_VALID(Kcb);

    /* Check if this is the last reference */
    if ((InterlockedDecrement((PLONG)&Kcb->RefCount) & 0xFFFF) == 0)
    {
        /* Sanity check */
        ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
               (CmpTestRegistryLockExclusive() == TRUE));

        /* Check if we should do a direct delete */
        if (((CmpHoldLazyFlush) &&
                !(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) &&
                !(Kcb->Flags & KEY_SYM_LINK)) ||
                (Kcb->ExtFlags & CM_KCB_NO_DELAY_CLOSE) ||
                (Kcb->Delete))
        {
            /* Clean up the KCB*/
            CmpCleanUpKcbCacheWithLock(Kcb, LockHeldExclusively);
        }
        else
        {
            /* Otherwise, use delayed close */
            CmpAddToDelayedClose(Kcb, LockHeldExclusively);
        }
    }
}
예제 #2
0
VOID
NTAPI
EnlistKeyBodyWithKCB(IN PCM_KEY_BODY KeyBody,
                     IN ULONG Flags)
{
    ULONG i;

    /* Sanity check */
    ASSERT(KeyBody->KeyControlBlock != NULL);

    /* Initialize the list entry */
    InitializeListHead(&KeyBody->KeyBodyList);

    /* Check if we can use the parent KCB array */
    for (i = 0; i < 4; i++)
    {
        /* Add it into the list */
        if (!InterlockedCompareExchangePointer((PVOID*)&KeyBody->KeyControlBlock->
                                               KeyBodyArray[i],
                                               KeyBody,
                                               NULL))
        {
            /* Added */
            return;
        }
    }

    /* Array full, check if we need to unlock the KCB */
    if (Flags & CMP_ENLIST_KCB_LOCKED_SHARED)
    {
        /* It's shared, so release the KCB shared lock */
        CmpReleaseKcbLock(KeyBody->KeyControlBlock);
        ASSERT(!(Flags & CMP_ENLIST_KCB_LOCKED_EXCLUSIVE));
    }

    /* Check if we need to lock the KCB */
    if (!(Flags & CMP_ENLIST_KCB_LOCKED_EXCLUSIVE))
    {
        /* Acquire the lock */
        CmpAcquireKcbLockExclusive(KeyBody->KeyControlBlock);
    }

    /* Make sure we have the exclusive lock */
    ASSERT((CmpIsKcbLockedExclusive(KeyBody->KeyControlBlock) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* do the insert */
    InsertTailList(&KeyBody->KeyControlBlock->KeyBodyListHead,
                   &KeyBody->KeyBodyList);

    /* Check if we did a manual lock */
    if (!(Flags & (CMP_ENLIST_KCB_LOCKED_SHARED |
                   CMP_ENLIST_KCB_LOCKED_EXCLUSIVE)))
    {
        /* Release the lock */
        CmpReleaseKcbLock(KeyBody->KeyControlBlock);
    }
}
예제 #3
0
VOID
NTAPI
CmpCleanUpSubKeyInfo(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    PCM_KEY_NODE KeyNode;

    /* Sanity check */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Check if there's any cached subkey */
    if (Kcb->ExtFlags & (CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT))
    {
        /* Check if there's a hint */
        if (Kcb->ExtFlags & (CM_KCB_SUBKEY_HINT))
        {
            /* Kill it */
            CmpFree(Kcb->IndexHint, 0);
        }

        /* Remove subkey flags */
        Kcb->ExtFlags &= ~(CM_KCB_NO_SUBKEY | CM_KCB_SUBKEY_ONE | CM_KCB_SUBKEY_HINT);
    }

    /* Check if there's no linked cell */
    if (Kcb->KeyCell == HCELL_NIL)
    {
        /* Make sure it's a delete */
        ASSERT(Kcb->Delete);
        KeyNode = NULL;
    }
    else
    {
        /* Get the key node */
        KeyNode = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive, Kcb->KeyCell);
    }

    /* Check if we got the node */
    if (!KeyNode)
    {
        /* We didn't, mark the cached data invalid */
        Kcb->ExtFlags |= CM_KCB_INVALID_CACHED_INFO;
    }
    else
    {
        /* We have a keynode, update subkey counts */
        Kcb->ExtFlags &= ~CM_KCB_INVALID_CACHED_INFO;
        Kcb->SubKeyCount = KeyNode->SubKeyCounts[Stable] +
                           KeyNode->SubKeyCounts[Volatile];

        /* Release the cell */
        HvReleaseCell(Kcb->KeyHive, Kcb->KeyCell);
    }
}
예제 #4
0
VOID
NTAPI
CmpRemoveKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    /* Make sure that the registry and KCB are utterly locked */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Remove the key hash */
    CmpRemoveKeyHash(&Kcb->KeyHash);
}
예제 #5
0
VOID
NTAPI
CmpCleanUpKcbValueCache(IN PCM_KEY_CONTROL_BLOCK Kcb)
{
    PULONG_PTR CachedList;
    ULONG i;

    /* Sanity check */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Check if the value list is cached */
    if (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))
    {
        /* Get the cache list */
        CachedList = (PULONG_PTR)CMP_GET_CACHED_DATA(Kcb->ValueCache.ValueList);
        for (i = 0; i < Kcb->ValueCache.Count; i++)
        {
            /* Check if this cell is cached */
            if (CMP_IS_CELL_CACHED(CachedList[i]))
            {
                /* Free it */
                CmpFree((PVOID)CMP_GET_CACHED_CELL(CachedList[i]), 0);
            }
        }

        /* Now free the list */
        CmpFree((PVOID)CMP_GET_CACHED_CELL(Kcb->ValueCache.ValueList), 0);
        Kcb->ValueCache.ValueList = HCELL_NIL;
    }
    else if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)
    {
        /* This is a sym link, check if there's only one reference left */
        if ((Kcb->ValueCache.RealKcb->RefCount == 1) &&
                !(Kcb->ValueCache.RealKcb->Delete))
        {
            /* Disable delay close for the KCB */
            Kcb->ValueCache.RealKcb->ExtFlags |= CM_KCB_NO_DELAY_CLOSE;
        }

        /* Dereference the KCB */
        CmpDelayDerefKeyControlBlock(Kcb->ValueCache.RealKcb);
        Kcb->ExtFlags &= ~CM_KCB_SYM_LINK_FOUND;
    }
}
예제 #6
0
VOID
NTAPI
CmpCleanUpKcbCacheWithLock(IN PCM_KEY_CONTROL_BLOCK Kcb,
                           IN BOOLEAN LockHeldExclusively)
{
    PCM_KEY_CONTROL_BLOCK Parent;
    PAGED_CODE();

    /* Sanity checks */
    ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));
    ASSERT(Kcb->RefCount == 0);

    /* Cleanup the value cache */
    CmpCleanUpKcbValueCache(Kcb);

    /* Dereference the NCB */
    CmpDereferenceNameControlBlockWithLock(Kcb->NameBlock);

    /* Check if we have an index hint block and free it */
    if (Kcb->ExtFlags & CM_KCB_SUBKEY_HINT) CmpFree(Kcb->IndexHint, 0);

    /* Check if we were already deleted */
    Parent = Kcb->ParentKcb;
    if (!Kcb->Delete) CmpRemoveKeyControlBlock(Kcb);

    /* Set invalid KCB signature */
    Kcb->Signature = CM_KCB_INVALID_SIGNATURE;

    /* Free the KCB as well */
    CmpFreeKeyControlBlock(Kcb);

    /* Check if we have a parent */
    if (Parent)
    {
        /* Dereference the parent */
        LockHeldExclusively ?
        CmpDereferenceKeyControlBlockWithLock(Parent,LockHeldExclusively) :
        CmpDelayDerefKeyControlBlock(Parent);
    }
}
예제 #7
0
VOID
NTAPI
DelistKeyBodyFromKCB(IN PCM_KEY_BODY KeyBody,
                     IN BOOLEAN LockHeld)
{
    ULONG i;

    /* Sanity check */
    ASSERT(KeyBody->KeyControlBlock != NULL);

    /* Check if we can use the parent KCB array */
    for (i = 0; i < 4; i++)
    {
        /* Add it into the list */
        if (InterlockedCompareExchangePointer((VOID*)&KeyBody->KeyControlBlock->
                                              KeyBodyArray[i],
                                              NULL,
                                              KeyBody) == KeyBody)
        {
            /* Removed */
            return;
        }
    }

    /* Sanity checks */
    ASSERT(IsListEmpty(&KeyBody->KeyControlBlock->KeyBodyListHead) == FALSE);
    ASSERT(IsListEmpty(&KeyBody->KeyBodyList) == FALSE);

    /* Lock the KCB */
    if (!LockHeld) CmpAcquireKcbLockExclusive(KeyBody->KeyControlBlock);
    ASSERT((CmpIsKcbLockedExclusive(KeyBody->KeyControlBlock) == TRUE) ||
           (CmpTestRegistryLockExclusive() == TRUE));

    /* Remove the entry */
    RemoveEntryList(&KeyBody->KeyBodyList);

    /* Unlock it it if we did a manual lock */
    if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock);
}
예제 #8
0
VOID    
CmpRunDownDelayDerefKCBEngine(  PCM_KEY_CONTROL_BLOCK KeyControlBlock,
                                BOOLEAN               RegLockHeldEx)
{
    PCM_DELAY_DEREF_KCB_ITEM    DelayItem;
    ULONG                       NewIndex;
    ULONG                       Index1 = CmpHashTableSize;
    ULONG                       Index2 = CmpHashTableSize;
    PCMHIVE                     CmHive = NULL;
    BOOLEAN                     DoUnloadCheck = FALSE;

    CM_PAGED_CODE();

    ASSERT_CM_LOCK_OWNED();

    ASSERT( (KeyControlBlock && CmpIsKCBLockedExclusive(KeyControlBlock)) || (CmpTestRegistryLockExclusive() == TRUE) );

    if( KeyControlBlock ) {
        Index1 = GET_HASH_INDEX(KeyControlBlock->ConvKey);
        if( KeyControlBlock->ParentKcb ) {
            Index2 = GET_HASH_INDEX(KeyControlBlock->ParentKcb->ConvKey);
        }
    }
    LOCK_KCB_DELAY_DEREF_LIST();
    while( !CmpIsListEmpty(&CmpDelayDerefKCBListHead) ) {
        //
        // pull it out of the list
        //
        DelayItem = (PCM_DELAY_DEREF_KCB_ITEM)RemoveHeadList(&CmpDelayDerefKCBListHead);
        UNLOCK_KCB_DELAY_DEREF_LIST();

        DelayItem = CONTAINING_RECORD(  DelayItem,
                                        CM_DELAY_DEREF_KCB_ITEM,
                                        ListEntry);
        CmpClearListEntry(&(DelayItem->ListEntry));

        //
        // take additional precaution in the case the hive has been unloaded and this is the root
        //
        DoUnloadCheck = FALSE;
        if( !DelayItem->Kcb->Delete ) {
            CmHive = (PCMHIVE)CONTAINING_RECORD(DelayItem->Kcb->KeyHive, CMHIVE, Hive);
            if( IsHiveFrozen(CmHive) ) {
                //
                // unload is pending for this hive;
                //
                DoUnloadCheck = TRUE;

            }
        }

        NewIndex = GET_HASH_INDEX(DelayItem->Kcb->ConvKey);
        //
        // now deref and free 
        //
        if( (NewIndex == Index1) || (NewIndex == Index2) ) {
            //
            // we already hold the lock
            //
            ASSERT_KCB_LOCKED_EXCLUSIVE(DelayItem->Kcb);
            CmpDereferenceKeyControlBlockWithLock(DelayItem->Kcb,RegLockHeldEx);
        } else {
            //
            // we can't afford to force acquire; try to acquire and if it fails bail out
            //
            if( CmpKCBLockForceAcquireAllowed(Index1,Index2,NewIndex) ) {
                CmpLockHashEntryByIndexExclusive(NewIndex);
            } else if( CmpTryToLockHashEntryByIndexExclusive(NewIndex) == FALSE ) {
                //
                // add the item back to the list and bail out
                //
                ASSERT( CmpTestRegistryLockExclusive() == FALSE );
                LOCK_KCB_DELAY_DEREF_LIST();
                InsertHeadList(&CmpDelayDerefKCBListHead,&(DelayItem->ListEntry));
                UNLOCK_KCB_DELAY_DEREF_LIST();
                return;
            }
            ASSERT_KCB_LOCKED_EXCLUSIVE(DelayItem->Kcb);
            CmpDereferenceKeyControlBlockWithLock(DelayItem->Kcb,RegLockHeldEx);
            CmpUnlockHashEntryByIndex(NewIndex);
        }
        CmpDelayDerefKCBFreeEntry(DelayItem);

        //
        // if we dropped a reference inside a frozen hive, we may need to unload the hive
        //
        if( DoUnloadCheck == TRUE ) {
            CmpDoQueueLateUnloadWorker(CmHive);
        }

        LOCK_KCB_DELAY_DEREF_LIST();
    }
    UNLOCK_KCB_DELAY_DEREF_LIST();
}
예제 #9
0
VOID
CmpAddToDelayedClose(
    IN PCM_KEY_CONTROL_BLOCK    kcb,
    IN BOOLEAN                  RegLockHeldEx
    )
/*++

Routine Description:

    Adds a kcb to the delayed close table

Arguments:

    kcb - the kcb in question

Note: 
    
    kcb lock/resource should be acquired exclusively when this function is called

Return Value:

    NONE.

--*/
{
    PCM_DELAYED_CLOSE_ENTRY     DelayedEntry = NULL;

    CM_PAGED_CODE();

    ASSERT( (CmpIsKCBLockedExclusive(kcb) == TRUE) || // this kcb is owned exclusive
            (CmpTestRegistryLockExclusive() == TRUE) ); // or the entire registry is locked exclusive


    // Already on delayed close, don't try to put on again
    if (kcb->DelayedCloseIndex != CmpDelayedCloseSize) { // see if we really need this
        ASSERT( FALSE );
        return;
    }

    ASSERT(kcb->RefCount == 0);

    //
    // now materialize a new entry for this kcb
    //
    ASSERT_KEYBODY_LIST_EMPTY(kcb);
    DelayedEntry = CmpDelayCloseAllocNewEntry();
    if( !DelayedEntry ) {
        //
        // this is bad luck; we need to free the kcb in place
        //
        CmpCleanUpKcbCacheWithLock(kcb,RegLockHeldEx);
        return;
    }
#if DBG
    if( kcb->InDelayClose != 0 ) {
        ASSERT( FALSE );
    }
    {
        LONG                        OldRefCount;
        LONG                        NewRefCount;

        OldRefCount = *(PLONG)&kcb->InDelayClose; //get entire dword
        ASSERT( OldRefCount == 0 );
        NewRefCount = 1;
        if( InterlockedCompareExchange((PLONG)&kcb->InDelayClose,NewRefCount,OldRefCount)
                != OldRefCount ) {
    
            ASSERT( FALSE );
        }
    }
#endif //DBG
    //
    // populate the entry and insert it into the LRU list (at the top).
    //
    kcb->DelayedCloseIndex = 0; // see if we really need this
    kcb->DelayCloseEntry = (PVOID)DelayedEntry;    // need this for removing it back from here
    DelayedEntry->KeyControlBlock = kcb;
    InterlockedIncrement((PLONG)&CmpDelayedCloseElements);

    LOCK_DELAY_CLOSE();
    InsertHeadList(
        &CmpDelayedLRUListHead,
        &(DelayedEntry->DelayedLRUList)
        );
    //
    // check if limit hit and arm timer if not already armed
    //
    if( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (!CmpDelayCloseWorkItemActive) ) {
        CmpArmDelayedCloseTimer();
    } 
    UNLOCK_DELAY_CLOSE();
    //
    // we're done here
    //

}
예제 #10
0
VOID
CmpRemoveFromDelayedClose(
    IN PCM_KEY_CONTROL_BLOCK kcb
    )
/*++

Routine Description:

    Removes a KCB from the delayed close table;

Arguments:

    kcb - the kcb in question

Note: 
    
    kcb lock/resource should be acquired exclusively when this function is called

Return Value:

    NONE.

--*/
{
    PCM_DELAYED_CLOSE_ENTRY     DelayedEntry;

    CM_PAGED_CODE();


    ASSERT( (CmpIsKCBLockedExclusive(kcb) == TRUE) || // this kcb is owned exclusive
            (CmpTestRegistryLockExclusive() == TRUE) ); // or the entire registry is locked exclusive

    // not on delay close; don't try to remove it.
    if (kcb->DelayedCloseIndex == CmpDelayedCloseSize) { // see if we really need this
        ASSERT( FALSE );
        return;
    }

    DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)kcb->DelayCloseEntry;
    if( DelayedEntry != NULL ) {
        LOCK_DELAY_CLOSE();
        CmpRemoveEntryList(&(DelayedEntry->DelayedLRUList));
        UNLOCK_DELAY_CLOSE();

        //
        // give back the entry
        //
        CmpDelayCloseFreeEntry(DelayedEntry);
        InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
#if DBG
        if( kcb->InDelayClose == 0 ) {
            ASSERT( FALSE );
        }
        {
            LONG                        OldRefCount;
            LONG                        NewRefCount;

            OldRefCount = *(PLONG)&kcb->InDelayClose; //get entire dword
            ASSERT( OldRefCount == 1 );
            NewRefCount = 0;
            if( InterlockedCompareExchange((PLONG)&kcb->InDelayClose,NewRefCount,OldRefCount)
                    != OldRefCount ) {
    
                ASSERT( FALSE );
            }
        }
#endif //DBG
    }

    //
    // easy enough huh ?
    //
    kcb->DelayedCloseIndex = CmpDelayedCloseSize; // see if we really need this
    kcb->DelayCloseEntry = NULL;
}