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; }
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; }