示例#1
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();
}
示例#2
0
VOID
CmpDelayDerefKCBWorker(
    IN PVOID Parameter
    )

/*++

Routine Description:


Arguments:

    Parameter - not used.

Return Value:

    None.

--*/

{
    PCM_DELAY_DEREF_KCB_ITEM DelayItem;
    PCMHIVE                 CmHive = NULL;
    BOOLEAN                 DoUnloadCheck = FALSE;

    CM_PAGED_CODE();

    UNREFERENCED_PARAMETER (Parameter);

    ASSERT(CmpDelayDerefKCBWorkItemActive);

    BEGIN_LOCK_CHECKPOINT;
    CmpLockRegistry();

    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;

            }
        }

        //
        // now deref and free 
        //
        CmpDereferenceKeyControlBlock(DelayItem->Kcb);
        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();
    }
    //
    // signal that we have finished our work.
    //
    CmpDelayDerefKCBWorkItemActive = FALSE;
    UNLOCK_KCB_DELAY_DEREF_LIST();

    CmpUnlockRegistry();
    END_LOCK_CHECKPOINT;
}
示例#3
0
VOID
CmpDeleteKeyObject(
    IN  PVOID   Object
    )
/*++

Routine Description:

    This routine interfaces to the NT Object Manager.  It is invoked when
    the last reference to a particular Key object (or Key Root object)
    is destroyed.

    If the Key object going away holds the last reference to
    the extension it is associated with, that extension is destroyed.

Arguments:

    Object - supplies a pointer to a KeyRoot or Key, thus -> KEY_BODY.

Return Value:

    NONE.

--*/
{
    PCM_KEY_CONTROL_BLOCK   KeyControlBlock;
    PCM_KEY_BODY            KeyBody;
    PCMHIVE                 CmHive = NULL;
    BOOLEAN                 DoUnloadCheck = FALSE;

    CM_PAGED_CODE();

    CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"CmpDeleteKeyObject: Object = %p\n", Object));

    //
    // HandleClose callback
    //
    if ( CmAreCallbacksRegistered() ) {
        REG_KEY_HANDLE_CLOSE_INFORMATION  KeyHandleCloseInfo;
       
        KeyHandleCloseInfo.Object = Object;

        CmpCallCallBacks(RegNtPreKeyHandleClose,&KeyHandleCloseInfo,TRUE,RegNtPostKeyHandleClose,Object);
    }

    KeyBody = (PCM_KEY_BODY)Object;

    BEGIN_LOCK_CHECKPOINT;

    CmpLockRegistry();

    if (KeyBody->Type==KEY_BODY_TYPE) {
        KeyControlBlock = KeyBody->KeyControlBlock;

        //
        // the keybody should be initialized; when kcb is null, something went wrong
        // between the creation and the dereferenciation of the object
        //
        if( KeyControlBlock != NULL ) {
            //
            // Clean up any outstanding notifies attached to the KeyBody
            //
            CmpFlushNotify(KeyBody,FALSE);

            //
            // Remove our reference to the KeyControlBlock, clean it up, perform any
            // pend-till-final-close operations.
            //
            // NOTE: Delete notification is seen at the parent of the deleted key,
            //       not the deleted key itself.  If any notify was outstanding on
            //       this key, it was cleared away above us.  Only parent/ancestor
            //       keys will see the report.
            //
            //
            // The dereference will free the KeyControlBlock.  If the key was deleted, it
            // has already been removed from the hash table, and relevant notifications
            // posted then as well.  All we are doing is freeing the tombstone.
            //
            // If it was not deleted, we're both cutting the kcb out of
            // the kcb list/tree, AND freeing its storage.
            //

           
            //
            // Replace this with the definition so we avoid dropping and reacquiring the lock
            DelistKeyBodyFromKCB(KeyBody,FALSE);

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

                }
            }

            CmpDelayDerefKeyControlBlock(KeyControlBlock);

        }
    } else {
        //
        // This must be a predefined handle
        //  some sanity asserts
        //
        KeyControlBlock = KeyBody->KeyControlBlock;

        ASSERT( KeyBody->Type&REG_PREDEF_HANDLE_MASK);
        ASSERT( KeyControlBlock->Flags&KEY_PREDEF_HANDLE );

        if( KeyControlBlock != NULL ) {
            CmHive = (PCMHIVE)CONTAINING_RECORD(KeyControlBlock->KeyHive, CMHIVE, Hive);
            if( IsHiveFrozen(CmHive) ) {
                //
                // unload is pending for this hive; we shouldn't put the kcb in the delay
                // close table
                //
                DoUnloadCheck = TRUE;

            }
            CmpDereferenceKeyControlBlock(KeyControlBlock);
        }

    }

    //
    // if a handle inside a frozen hive has been closed, we may need to unload the hive
    //
    if( DoUnloadCheck == TRUE ) {
        CmpDoQueueLateUnloadWorker(CmHive);
    }

    CmpUnlockRegistry();
    END_LOCK_CHECKPOINT;

    // 
    // just a notification; disregard the return status
    //
    CmPostCallbackNotification(RegNtPostKeyHandleClose,NULL,STATUS_SUCCESS);
    return;
}