コード例 #1
0
ファイル: cmdelete.c プロジェクト: BaoYu0721/WRK-1.2
VOID
CmpDoQueueLateUnloadWorker(IN PCMHIVE CmHive)
{
    PWORK_QUEUE_ITEM    WorkItem;

    CM_PAGED_CODE();

    ASSERT( CmHive->RootKcb != NULL );

    //
    // NB: Hive lock has higher precedence; We don't need the kcb lock as we are only checking the refcount
    //
    CmLockHive(CmHive);

    if( (CmHive->RootKcb->RefCount == 1) && (CmHive->UnloadWorkItem == NULL) ) {
        //
        // the only reference on the rookcb is the one that we artificially created
        // queue a work item to late unload the hive
        //
        WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
        if( InterlockedCompareExchangePointer(&(CmHive->UnloadWorkItem),WorkItem,NULL) == NULL ) {
            ExInitializeWorkItem(CmHive->UnloadWorkItem,
                                 CmpLateUnloadHiveWorker,
                                 CmHive);
            ExQueueWorkItem(CmHive->UnloadWorkItem, DelayedWorkQueue);
        } else {
            ExFreePool(WorkItem);
        }

    }

    CmUnlockHive(CmHive);
}
コード例 #2
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
VOID
CmpArmDelayedCloseTimer( )

/*++

Routine Description:

    Arms timer for DelayClose worker procession

    NB: this routine should be called with CmpDelayedCloseTableLock held. 
        If not --> change CmpDelayCloseWorkItemActive to a ULONG and do an InterlockedCompareExchange on it 
        before setting the timer

Arguments:


Note: 
    

Return Value:

    NONE.

--*/
{
    LARGE_INTEGER DueTime;

    CM_PAGED_CODE();
    
    CmpDelayCloseWorkItemActive = TRUE;

    //
    // queue a timer for 5 secs later to do the actual delay close
    //

    DueTime.QuadPart = Int32x32To64(CmpDelayCloseIntervalInSeconds,
                                    - SECOND_MULT);
    //
    // Indicate relative time
    //

    KeSetTimer(&CmpDelayCloseTimer,
               DueTime,
               &CmpDelayCloseDpc);

}
コード例 #3
0
ファイル: cmalloc.c プロジェクト: AlexiaChen/wrk_study
VOID
CmpDestroyCmPrivateDelayAlloc( )

/*++

Routine Description:

    Frees memory used by the CmPrivate pool allocation module

Arguments:


Return Value:


--*/

{
    CM_PAGED_CODE();
}
コード例 #4
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
VOID
CmpDelayDerefKeyControlBlock( PCM_KEY_CONTROL_BLOCK   KeyControlBlock )
/*++

Routine Description:

    Adds kcb to a list to be deref in a workitem

Arguments:

    kcb - the kcb in question

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

Return Value:

    NONE.

--*/
{
    PCM_DELAY_DEREF_KCB_ITEM    DelayItem;
    LONG                        OldRefCount;
    LONG                        NewRefCount;

    CM_PAGED_CODE();

    //
    // try the fast path first; we only need to take the work item approach when we drop to 0
    //
    OldRefCount = *(PLONG)&KeyControlBlock->RefCount; //get entire dword
    NewRefCount = OldRefCount - 1;
    if( (NewRefCount & 0xffff) > 0  &&
        InterlockedCompareExchange((PLONG)&KeyControlBlock->RefCount,NewRefCount,OldRefCount)
            == OldRefCount ) {
    
        LogKCBReference(KeyControlBlock,2);
        return;
    }

    DelayItem = CmpDelayDerefKCBAllocNewEntry();
    if( DelayItem == NULL ) {
        //
        // nothing to do here ; we'll leak a reference on this kcb
        //
        return;
    }

    DelayItem->Kcb = KeyControlBlock;
    LOCK_KCB_DELAY_DEREF_LIST();
    InsertTailList( &CmpDelayDerefKCBListHead,&(DelayItem->ListEntry));
    //
    // if worker is not already up; queue it
    //
    if( !CmpDelayDerefKCBWorkItemActive ) {
        LARGE_INTEGER DueTime;

        CmpDelayDerefKCBWorkItemActive = TRUE;
            
        //
        // queue a timer for 5 secs later to do the actual delay close
        //

        DueTime.QuadPart = Int32x32To64(CmpDelayDerefKCBIntervalInSeconds,
                                        - SECOND_MULT);
        //
        // Indicate relative time
        //

        KeSetTimer(&CmpDelayDerefKCBTimer,
                   DueTime,
                   &CmpDelayDerefKCBDpc);
    } 
    UNLOCK_KCB_DELAY_DEREF_LIST();
}
コード例 #5
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
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;
}
コード例 #6
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
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();
}
コード例 #7
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
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
    //

}
コード例 #8
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
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;
}
コード例 #9
0
ファイル: cmdelay.c プロジェクト: AlexiaChen/wrk_study
VOID
CmpDelayCloseWorker(
    IN PVOID Parameter
    )

/*++

Routine Description:
    
      The fun part. We need to walk the cache and look for kcbs with refcount == 0
      Get the oldest one and kick it out of cache.

Arguments:

    Parameter - not used.

Return Value:

    None.

--*/

{
    PCM_DELAYED_CLOSE_ENTRY     DelayedEntry;
    ULONG                       ConvKey;
    ULONG                       MaxIterations = MAX_DELAY_WORKER_ITERATIONS;

    CM_PAGED_CODE();

    UNREFERENCED_PARAMETER (Parameter);

    ASSERT(CmpDelayCloseWorkItemActive);

    BEGIN_LOCK_CHECKPOINT;
    CmpLockRegistry();
    
    //
    // process kick out every entry with RefCount == 0 && DelayCloseIndex == 0
    // ignore the others; we only do this while there is excess of delay - close kcbs
    //
    LOCK_DELAY_CLOSE();
    while( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (MaxIterations--) ) {
        ASSERT( !CmpIsListEmpty(&CmpDelayedLRUListHead) );
        //
        // We first need to get the hash entry and attempt to lock it.
        //
        DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
        DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                            CM_DELAYED_CLOSE_ENTRY,
                                            DelayedLRUList);
        ConvKey = DelayedEntry->KeyControlBlock->ConvKey;
        UNLOCK_DELAY_CLOSE();
        //
        // now lock the hash then recheck if the entry is still first on the list
        //
        CmpLockHashEntryExclusive(ConvKey);
        LOCK_DELAY_CLOSE();
        if( CmpDelayedCloseElements <= CmpDelayedCloseSize ) {
            //
            // just bail out; no need to kick them out
            //
            CmpUnlockHashEntry(ConvKey);
            break;
        }
        DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
        DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                            CM_DELAYED_CLOSE_ENTRY,
                                            DelayedLRUList);
        if( ConvKey == DelayedEntry->KeyControlBlock->ConvKey ) {
            //
            // same hash entry; proceed
            // pull it out of the list
            //
            DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)RemoveTailList(&CmpDelayedLRUListHead);
    
            DelayedEntry = CONTAINING_RECORD(   DelayedEntry,
                                                CM_DELAYED_CLOSE_ENTRY,
                                                DelayedLRUList);
            CmpClearListEntry(&(DelayedEntry->DelayedLRUList));

            if( (DelayedEntry->KeyControlBlock->RefCount == 0) && (DelayedEntry->KeyControlBlock->DelayedCloseIndex == 0) ){
                //
                // free this kcb and the entry
                //
                UNLOCK_DELAY_CLOSE();
                DelayedEntry->KeyControlBlock->DelayCloseEntry = NULL;
                CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock,FALSE);
                CmpDelayCloseFreeEntry(DelayedEntry);
                InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
            } else {
                //
                // put it back at the top
                //
                InsertHeadList( &CmpDelayedLRUListHead,
                                &(DelayedEntry->DelayedLRUList)
                            );
                UNLOCK_DELAY_CLOSE();
            }
        } else {
            UNLOCK_DELAY_CLOSE();
        }
        CmpUnlockHashEntry(ConvKey);

        LOCK_DELAY_CLOSE();
    }
    if( CmpDelayedCloseElements > CmpDelayedCloseSize ) {
        //
        // iteration run was too short, there are more elements to process, queue ourselves for later
        //
        CmpArmDelayedCloseTimer();
    } else {
        //
        // signal that we have finished our work.
        //
        CmpDelayCloseWorkItemActive = FALSE;
    }
    UNLOCK_DELAY_CLOSE();


    CmpUnlockRegistry();
    END_LOCK_CHECKPOINT;
}
コード例 #10
0
ファイル: cmalloc.c プロジェクト: AlexiaChen/wrk_study
VOID
CmpFreeDelayItem( PVOID Item )

/*++

Routine Description:

    Frees a kcb; if it's allocated from our own pool put it back in the free list.
    If it's allocated from general pool, just free it.

Arguments:

    kcb to free

Return Value:


--*/
{
    USHORT			j;
	PCM_ALLOC_PAGE	AllocPage;
    PCM_DELAY_ALLOC DelayItem = (PCM_DELAY_ALLOC)Item;

    CM_PAGED_CODE();

	LOCK_DELAY_ALLOC_BUCKET();

    //
    // add kcb to freelist
    //
    InsertTailList(
        &CmpFreeDelayItemsListHead,
        &(DelayItem->ListEntry)
        );

	//
	// get the page
	//
    AllocPage = (PCM_ALLOC_PAGE)DELAY_ALLOC_TO_ALLOC_PAGE( DelayItem );

    //
	// not all are free
	//
	ASSERT( AllocPage->FreeCount != CM_DELAYS_PER_PAGE);

	AllocPage->FreeCount++;

    if( AllocPage->FreeCount == CM_DELAYS_PER_PAGE ) {
        //
        // entire page is free; let it go
        //
        //
        // first; iterate through the free item list and remove all items inside this page
        //
        for(j=0;j<CM_DELAYS_PER_PAGE;j++) {
            DelayItem = (PCM_DELAY_ALLOC)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_DELAY_ALLOC_ENTRY_SIZE);
            CmpRemoveEntryList(&(DelayItem->ListEntry));
        }
        ExFreePoolWithTag(AllocPage, CM_ALLOCATE_TAG|PROTECTED_POOL);
    }

	UNLOCK_DELAY_ALLOC_BUCKET();
}
コード例 #11
0
ファイル: cmalloc.c プロジェクト: AlexiaChen/wrk_study
PVOID
CmpAllocateDelayItem( )

/*++

Routine Description:

    Allocates a delay item from our own pool; 

Arguments:


Return Value:

    The  new item

--*/

{
    USHORT                  j;
    PCM_DELAY_ALLOC         DelayItem = NULL;
	PCM_ALLOC_PAGE			AllocPage;

    CM_PAGED_CODE();
    
    
	LOCK_DELAY_ALLOC_BUCKET();

SearchFreeItem:
    //
    // try to find a free one
    //
    if( CmpIsListEmpty(&CmpFreeDelayItemsListHead) == FALSE ) {
        //
        // found one
        //
        DelayItem = (PCM_DELAY_ALLOC)RemoveHeadList(&CmpFreeDelayItemsListHead);
        DelayItem = CONTAINING_RECORD(  DelayItem,
                                        CM_DELAY_ALLOC,
                                        ListEntry);

        CmpClearListEntry(&(DelayItem->ListEntry));

        AllocPage = (PCM_ALLOC_PAGE)DELAY_ALLOC_TO_ALLOC_PAGE( DelayItem );

        ASSERT( AllocPage->FreeCount != 0 );

        AllocPage->FreeCount--;
        
		UNLOCK_DELAY_ALLOC_BUCKET();
        return DelayItem;
    }

    //
    // we need to allocate a new page as we ran out of free items
    //
            
    //
    // allocate a new page and insert all kcbs in the freelist
    //
    AllocPage = (PCM_ALLOC_PAGE)ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, CM_ALLOCATE_TAG|PROTECTED_POOL);
    if( AllocPage == NULL ) {
        //
        // bad luck
        //
		UNLOCK_DELAY_ALLOC_BUCKET();
        return NULL;
    }

	//
	// set up the page
	//
    AllocPage->FreeCount = CM_DELAYS_PER_PAGE;

    //
    // now the dirty job; insert all items inside the page in the free list
    //
    for(j=0;j<CM_DELAYS_PER_PAGE;j++) {
        DelayItem = (PCM_DELAY_ALLOC)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_DELAY_ALLOC_ENTRY_SIZE);

        InsertTailList(
            &CmpFreeDelayItemsListHead,
            &(DelayItem->ListEntry)
            );
        DelayItem->Kcb = NULL;
    }
            
    //
    // this time will find one for sure
    //
    goto SearchFreeItem;
}
コード例 #12
0
ファイル: cmdelete.c プロジェクト: BaoYu0721/WRK-1.2
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;
}
コード例 #13
0
ファイル: cmdelete.c プロジェクト: BaoYu0721/WRK-1.2
VOID
CmpLateUnloadHiveWorker(
    IN PVOID Hive
    )
/*++

Routine Description:

    "Late" unloads the hive; If nothing goes badly wrong (i.e. insufficient resources),
    this function should succeed

Arguments:

    CmHive - the frozen hive to be unloaded

Return Value:

    NONE.

--*/
{
    NTSTATUS                Status;
    HCELL_INDEX             Cell;
    PCM_KEY_CONTROL_BLOCK   RootKcb;
    PCMHIVE                 CmHive;

    CM_PAGED_CODE();

    //
    // first, load the registry exclusive
    //
    CmpLockRegistryExclusive();

    //
    // hive is the parameter to this worker; make sure we free the work item
    // allocated by CmpDeleteKeyObject
    //
    CmHive = (PCMHIVE)Hive;

    ASSERT( CmHive->UnloadWorkItem != NULL );
    ExFreePool( CmHive->UnloadWorkItem );

    //
    // if this attempt doesn't succeed, mark that we can try another
    //
    CmHive->UnloadWorkItem = NULL;

    ASSERT( !(CmHive->Hive.HiveFlags & HIVE_IS_UNLOADING) );
    if( CmHive->Frozen == FALSE )  {
        //
        // another thread mounted the exact same hive in the exact same place, hence unfreezing the hive
        // we've done the cleanup part (free the workitem) nothing more to do.
        // or hive is already in process of being unloaded
        //
        ASSERT( CmHive->RootKcb == NULL );
        CmpUnlockRegistry();
        return;
    }
    //
    // this is just about the only possible way the hive can get corrupted in between
    //
    if( HvShutdownComplete == TRUE ) {
        // too late to do anything
        CmpUnlockRegistry();
        return;
    }

    //
    // hive should be frozen, otherwise we wouldn't get here
    //
    ASSERT( CmHive->Frozen == TRUE );

    RootKcb = CmHive->RootKcb;
    //
    // root kcb must be valid and has only our "artificial" refcount on it
    //
    ASSERT( RootKcb != NULL );

    if( RootKcb->RefCount > 1 ) {
        //
        // somebody else must've gotten in between dropping/reacquiring the reglock
        // and opened a handle inside this hive; bad luck, we can't unload
        //
        CmpUnlockRegistry();
        return;
    }

    ASSERT_KCB(RootKcb);

    Cell = RootKcb->KeyCell;
    Status = CmUnloadKey(RootKcb,0,CM_UNLOAD_REG_LOCKED_EX);
    ASSERT( (Status != STATUS_CANNOT_DELETE) && (Status != STATUS_INVALID_PARAMETER) );

    if(NT_SUCCESS(Status)) {
        // CmUnloadKey already released the lock
        CmpLockRegistry();
        CmpDereferenceKeyControlBlock(RootKcb);
    } 
    CmpUnlockRegistry();
}
コード例 #14
0
ファイル: cmsubs2.c プロジェクト: BaoYu0721/WRK-1.2
NTSTATUS
CmpQueryKeyDataFromCache(
    PCM_KEY_CONTROL_BLOCK   Kcb,
    KEY_INFORMATION_CLASS   KeyInformationClass,
    PVOID                   KeyInformation,
    ULONG                   Length,
    PULONG                  ResultLength
    )
/*++

Routine Description:

    Do the actual copy of data for a key into caller's buffer.

    If KeyInformation is not long enough to hold all requested data,
    STATUS_BUFFER_OVERFLOW will be returned, and ResultLength will be
    set to the number of bytes actually required.

    Works only for the information cached into kcb. I.e. KeyBasicInformation
    and KeyCachedInfo


Arguments:

    Kcb - Supplies pointer to the kcb to be queried

    KeyInformationClass - Specifies the type of information returned in
        Buffer.  One of the following types:

        KeyBasicInformation - return last write time, title index, and name.
            (see KEY_BASIC_INFORMATION structure)

        KeyCachedInformation - return last write time, title index, name ....
            (see KEY_CACHED_INFORMATION structure)

    KeyInformation -Supplies pointer to buffer to receive the data.

    Length - Length of KeyInformation in bytes.

    ResultLength - Number of bytes actually written into KeyInformation.

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS            status;
    PKEY_INFORMATION    pbuffer;
    ULONG               requiredlength;
    USHORT              NameLength;
    PCM_KEY_NODE        Node; // this is to be used only in case of cache incoherency

    CM_PAGED_CODE();

    //
    // we cannot afford to return the kcb NameBlock as the key name
    // for KeyBasicInformation as there are lots of callers expecting
    // the name to be case-sensitive; KeyCachedInformation is new
    // and used only by the Win32 layer, which is not case sensitive
    // Note: future clients of KeyCachedInformation must be made aware 
    // that name is NOT case-sensitive
    //
    ASSERT( KeyInformationClass == KeyCachedInformation );

    // 
    // we are going to need the nameblock; if it is NULL, bail out
    //
    if( Kcb->NameBlock == NULL ) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    pbuffer = (PKEY_INFORMATION)KeyInformation;
    
    if (Kcb->NameBlock->Compressed) {
        NameLength = CmpCompressedNameSize(Kcb->NameBlock->Name,Kcb->NameBlock->NameLength);
    } else {
        NameLength = Kcb->NameBlock->NameLength;
    }
    
    // Assume success
    status = STATUS_SUCCESS;

    switch (KeyInformationClass) {

    case KeyCachedInformation:

        //
        // LastWriteTime, TitleIndex, 
        // SubKeys, MaxNameLen, Values, MaxValueNameLen,
        // MaxValueDataLen, Name
        //
        requiredlength = sizeof(KEY_CACHED_INFORMATION);

        *ResultLength = requiredlength;

        if (Length < requiredlength) {

            status = STATUS_BUFFER_TOO_SMALL;

        } else {

            pbuffer->KeyCachedInformation.LastWriteTime = Kcb->KcbLastWriteTime;

            pbuffer->KeyCachedInformation.TitleIndex = 0;

            pbuffer->KeyCachedInformation.NameLength = NameLength;

            pbuffer->KeyCachedInformation.Values = Kcb->ValueCache.Count;
            
            pbuffer->KeyCachedInformation.MaxNameLen = Kcb->KcbMaxNameLen;
            
            pbuffer->KeyCachedInformation.MaxValueNameLen = Kcb->KcbMaxValueNameLen;
            
            pbuffer->KeyCachedInformation.MaxValueDataLen = Kcb->KcbMaxValueDataLen;

            if( !(Kcb->ExtFlags & CM_KCB_INVALID_CACHED_INFO) ) {
                // there is some cached info
                if( Kcb->ExtFlags & CM_KCB_NO_SUBKEY ) {
                    pbuffer->KeyCachedInformation.SubKeys = 0;
                } else if( Kcb->ExtFlags & CM_KCB_SUBKEY_ONE ) {
                    pbuffer->KeyCachedInformation.SubKeys = 1;
                } else if( Kcb->ExtFlags & CM_KCB_SUBKEY_HINT ) {
                    pbuffer->KeyCachedInformation.SubKeys = Kcb->IndexHint->Count;
                } else {
                    pbuffer->KeyCachedInformation.SubKeys = Kcb->SubKeyCount;
                }
            } else {
                //
                // kcb cache is not coherent; get the info from knode
                // 
                CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Kcb cache incoherency detected, kcb = %p\n",Kcb));

                Node = (PCM_KEY_NODE)HvGetCell(Kcb->KeyHive,Kcb->KeyCell);
                if( Node == NULL ) {
                    //
                    // couldn't map view for this cell
                    //
                    status = STATUS_INSUFFICIENT_RESOURCES;
                    break;
                }

                pbuffer->KeyCachedInformation.SubKeys = Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile];
                HvReleaseCell(Kcb->KeyHive,Kcb->KeyCell);

            }

        }

        break;

    default:
        status = STATUS_INVALID_PARAMETER;
        break;
    }

    return status;
}