Exemple #1
0
NTKERNELAPI
VOID
FASTCALL
ObInitializeFastReference (
    IN PEX_FAST_REF FastRef,
    IN PVOID Object
    )
/*++

Routine Description:

    Initialize a fast reference structure.

Arguments:

    FastRef - Rundown block to be initialized

Return Value:

    None

--*/
{
    //
    // If an object was given then bias the object reference by the cache size.
    //
    if (Object != NULL) {
        ObReferenceObjectEx (Object, ExFastRefGetAdditionalReferenceCount ());
    }
    ExFastRefInitialize (FastRef, Object);
}
Exemple #2
0
NTKERNELAPI
PVOID
FASTCALL
ObFastReferenceObject (
    IN PEX_FAST_REF FastRef
    )
/*++

Routine Description:

    This routine attempts a fast reference of an object in a fast ref
    structure.

Arguments:

    FastRef - Rundown block to be used for the reference

Return Value:

    PVOID - Object that was referenced or NULL if we failed

--*/
{
    EX_FAST_REF OldRef;
    PVOID Object;
    ULONG RefsToAdd, Unused;
    //
    // Attempt the fast reference
    //
    OldRef = ExFastReference (FastRef);

    Object = ExFastRefGetObject (OldRef);
    //
    // We fail if there wasn't an object or if it has no cached references
    // left. Both of these cases had the cached reference count zero.
    //
    Unused = ExFastRefGetUnusedReferences (OldRef);

    if (Unused <= 1) {
        if (Unused == 0) {
            return NULL;
        }
        //
        // If we took the counter to zero then attempt to make life easier for
        // the next referencer by resetting the counter to its max. Since we now
        // have a reference to the object we can do this.
        //
        RefsToAdd = ExFastRefGetAdditionalReferenceCount ();
        ObReferenceObjectEx (Object, RefsToAdd);

        //
        // Try to add the added references to the cache. If we fail then just
        // release them.
        //
        if (!ExFastRefAddAdditionalReferenceCounts (FastRef, Object, RefsToAdd)) {
            ObDereferenceObjectEx (Object, RefsToAdd);
        }
    }
    return Object;
}
Exemple #3
0
NTKERNELAPI
PVOID
FASTCALL
ObFastReplaceObject (
    IN PEX_FAST_REF FastRef,
    IN PVOID Object
    )
/*++

Routine Description:

    This routine does a swap of the object. This must be called while holding
    a lock.

Arguments:

    FastRef - Rundown block to be used to do the swap.

Return Value:

    PVOID - Object that was in the block before the swap..

--*/
{
    EX_FAST_REF OldRef;
    PVOID OldObject;
    ULONG RefsToReturn;

    //
    // If we have been given an object then bias it by the correct amount.
    //
    if (Object != NULL) {
        ObReferenceObjectEx (Object, ExFastRefGetAdditionalReferenceCount ());
    }
    //
    // Do the swap
    //
    OldRef = ExFastRefSwapObject (FastRef, Object);
    OldObject = ExFastRefGetObject (OldRef);
    //
    // If there was an original object then we need to work out how many
    // cached references there were (if any) and return them.
    //
    if (OldObject != NULL) {
        RefsToReturn = ExFastRefGetUnusedReferences (OldRef);
        if (RefsToReturn > 0) {
            ObDereferenceObjectEx (OldObject, RefsToReturn);
        }
    }
    return OldObject;
}
Exemple #4
0
PEX_CALLBACK_ROUTINE_BLOCK
ExReferenceCallBackBlock (
    IN OUT PEX_CALLBACK CallBack
    )
/*++

Routine Description:

    This function takes a reference on the call back block inside the
    callback structure.

Arguments:

    CallBack - Call back to obtain the call back block from

Return Value:

    PEX_CALLBACK_ROUTINE_BLOCK - Referenced structure or NULL if these wasn't one

--*/
{
    EX_FAST_REF OldRef;
    PEX_CALLBACK_ROUTINE_BLOCK CallBackBlock;

    //
    // Get a reference to the callback block if we can.
    //
    OldRef = ExFastReference (&CallBack->RoutineBlock);

    //
    // If there is no callback then return
    //
    if (ExFastRefObjectNull (OldRef)) {
        return NULL;
    }
    //
    // If we didn't get a reference then use a lock to get one.
    //
    if (!ExFastRefCanBeReferenced (OldRef)) {
        PKTHREAD CurrentThread;
        CurrentThread = KeGetCurrentThread ();

        KeEnterCriticalRegionThread (CurrentThread);

        ExAcquirePushLockExclusive (&ExpCallBackFlush);

        CallBackBlock = ExFastRefGetObject (CallBack->RoutineBlock);
        if (CallBackBlock && !ExAcquireRundownProtection (&CallBackBlock->RundownProtect)) {
            CallBackBlock = NULL;
        }

        ExReleasePushLockExclusive (&ExpCallBackFlush);

        KeLeaveCriticalRegionThread (CurrentThread);

        if (CallBackBlock == NULL) {
            return NULL;
        }

    } else {
        CallBackBlock = ExFastRefGetObject (OldRef);

        //
        // If we just removed the last reference then attempt fix it up.
        //
        if (ExFastRefIsLastReference (OldRef) && !ExpCallBackReturnRefs) {
            ULONG RefsToAdd;

            RefsToAdd = ExFastRefGetAdditionalReferenceCount ();

            //
            // If we can't add the references then just give up
            //
            if (ExAcquireRundownProtectionEx (&CallBackBlock->RundownProtect,
                                              RefsToAdd)) {
                //
                // Repopulate the cached refs. If this fails we just give them back.
                //
                if (!ExFastRefAddAdditionalReferenceCounts (&CallBack->RoutineBlock,
                                                            CallBackBlock,
                                                            RefsToAdd)) {
                    ExReleaseRundownProtectionEx (&CallBackBlock->RundownProtect,
                                                  RefsToAdd);
                }
            }
        }
    }

    return CallBackBlock;
}
Exemple #5
0
BOOLEAN
ExCompareExchangeCallBack (
    IN OUT PEX_CALLBACK CallBack,
    IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock,
    IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock
    )
/*++

Routine Description:

    This function assigns, removes or swaps a low overhead callback function.

Arguments:

    CallBack - Callback structure to be modified

    NewBlock - New block to be installed in the callback

    OldBlock - The old block that must be there now to be replaced

Return Value:

    BOOLEAN - TRUE: The swap occured, FALSE: The swap failed

--*/
{
    EX_FAST_REF OldRef;
    PEX_CALLBACK_ROUTINE_BLOCK ReplacedBlock;

    if (NewBlock != NULL) {
        //
        // Add the additional references to the routine block
        //
        if (!ExAcquireRundownProtectionEx (&NewBlock->RundownProtect,
                                           ExFastRefGetAdditionalReferenceCount () + 1)) {
            ASSERTMSG ("Callback block is already undergoing rundown", FALSE);
            return FALSE;
        }
    }

    //
    // Attempt to replace the existing object and balance all the reference counts
    //
    OldRef = ExFastRefCompareSwapObject (&CallBack->RoutineBlock,
                                         NewBlock,
                                         OldBlock);

    ReplacedBlock = ExFastRefGetObject (OldRef);

    //
    // See if the swap occured. If it didn't undo the original references we added.
    // If it did then release remaining references on the original
    //
    if (ReplacedBlock == OldBlock) {
        PKTHREAD CurrentThread;
        //
        // We need to flush out any slow referencers at this point. We do this by
        // acquiring and releasing a lock.
        //
        if (ReplacedBlock != NULL) {
            CurrentThread = KeGetCurrentThread ();

            KeEnterCriticalRegionThread (CurrentThread);

            ExAcquireReleasePushLockExclusive (&ExpCallBackFlush);

            KeLeaveCriticalRegionThread (CurrentThread);

            ExReleaseRundownProtectionEx (&ReplacedBlock->RundownProtect,
                                          ExFastRefGetUnusedReferences (OldRef) + 1);

        }
        return TRUE;
    } else {
        //
        // The swap failed. Remove the addition references if we had added any.
        //
        if (NewBlock != NULL) {
            ExReleaseRundownProtectionEx (&NewBlock->RundownProtect,
                                          ExFastRefGetAdditionalReferenceCount () + 1);
        }
        return FALSE;
    }
}