📄 ex.h
字号:
* the specified descriptor.
*
* @param RunRef
* Pointer to a rundown reference descriptor.
*
* @return TRUE if access to the protected structure was granted, FALSE otherwise.
*
* @remarks This is the internal macro for system use only.In case the rundown
* was active, then the slow-path will be called through the exported
* function.
*
*--*/
VOID
FORCEINLINE
_ExReleaseRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
ULONG_PTR Value, NewValue;
/* Get the current value and mask the active bit */
Value = RunRef->Count &~ EX_RUNDOWN_ACTIVE;
/* Remove a reference */
NewValue = Value - EX_RUNDOWN_COUNT_INC;
/* Change the value */
NewValue = ExpChangeRundown(RunRef, NewValue, Value);
/* Check if the rundown was active */
if (NewValue != Value)
{
/* Rundown was active, use long path */
ExfReleaseRundownProtection(RunRef);
}
else
{
/* Sanity check */
ASSERT((Value >= EX_RUNDOWN_COUNT_INC) || (KeNumberProcessors > 1));
}
}
/*++
* @name ExInitializeRundownProtection
* INTERNAL MACRO
*
* The ExInitializeRundownProtection routine initializes a rundown
* protection descriptor.
*
* @param RunRef
* Pointer to a rundown reference descriptor.
*
* @return None.
*
* @remarks This is the internal macro for system use only.
*
*--*/
VOID
FORCEINLINE
_ExInitializeRundownProtection(IN PEX_RUNDOWN_REF RunRef)
{
/* Set the count to zero */
RunRef->Count = 0;
}
/*++
* @name ExWaitForRundownProtectionRelease
* INTERNAL MACRO
*
* The ExWaitForRundownProtectionRelease routine waits until the specified
* rundown descriptor has been released.
*
* @param RunRef
* Pointer to a rundown reference descriptor.
*
* @return None.
*
* @remarks This is the internal macro for system use only. If a wait is actually
* necessary, then the slow path is taken through the exported function.
*
*--*/
VOID
FORCEINLINE
_ExWaitForRundownProtectionRelease(IN PEX_RUNDOWN_REF RunRef)
{
ULONG_PTR Value;
/* Set the active bit */
Value = ExpChangeRundown(RunRef, EX_RUNDOWN_ACTIVE, 0);
if ((Value) && (Value != EX_RUNDOWN_ACTIVE))
{
/* If the the rundown wasn't already active, then take the long path */
ExfWaitForRundownProtectionRelease(RunRef);
}
}
/*++
* @name ExRundownCompleted
* INTERNAL MACRO
*
* The ExRundownCompleted routine completes the rundown of the specified
* descriptor by setting the active bit.
*
* @param RunRef
* Pointer to a rundown reference descriptor.
*
* @return None.
*
* @remarks This is the internal macro for system use only.
*
*--*/
VOID
FORCEINLINE
_ExRundownCompleted(IN PEX_RUNDOWN_REF RunRef)
{
/* Sanity check */
ASSERT((RunRef->Count & EX_RUNDOWN_ACTIVE) != 0);
/* Mark the counter as active */
ExpSetRundown(&RunRef->Count, EX_RUNDOWN_ACTIVE);
}
/* PUSHLOCKS *****************************************************************/
/* FIXME: VERIFY THESE! */
VOID
FASTCALL
ExBlockPushLock(
IN PEX_PUSH_LOCK PushLock,
IN PVOID WaitBlock
);
VOID
FASTCALL
ExfUnblockPushLock(
IN PEX_PUSH_LOCK PushLock,
IN PVOID CurrentWaitBlock
);
VOID
FASTCALL
ExWaitForUnblockPushLock(
IN PEX_PUSH_LOCK PushLock,
IN PVOID WaitBlock
);
/*++
* @name ExInitializePushLock
* INTERNAL MACRO
*
* The ExInitializePushLock macro initializes a PushLock.
*
* @params PushLock
* Pointer to the pushlock which is to be initialized.
*
* @return None.
*
* @remarks None.
*
*--*/
VOID
FORCEINLINE
ExInitializePushLock(IN PULONG_PTR PushLock)
{
/* Set the value to 0 */
*PushLock = 0;
}
/*++
* @name ExAcquirePushLockExclusive
* INTERNAL MACRO
*
* The ExAcquirePushLockExclusive macro exclusively acquires a PushLock.
*
* @params PushLock
* Pointer to the pushlock which is to be acquired.
*
* @return None.
*
* @remarks The function attempts the quickest route to acquire the lock, which is
* to simply set the lock bit.
* However, if the pushlock is already shared, the slower path is taken.
*
* Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
* This macro should usually be paired up with KeAcquireCriticalRegion.
*
*--*/
VOID
FORCEINLINE
ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
{
/* Try acquiring the lock */
if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
{
/* Someone changed it, use the slow path */
// DbgPrint("%s - Contention!\n", __FUNCTION__);
ExfAcquirePushLockExclusive(PushLock);
}
/* Sanity check */
ASSERT(PushLock->Locked);
}
/*++
* @name ExAcquirePushLockShared
* INTERNAL MACRO
*
* The ExAcquirePushLockShared macro acquires a shared PushLock.
*
* @params PushLock
* Pointer to the pushlock which is to be acquired.
*
* @return None.
*
* @remarks The function attempts the quickest route to acquire the lock, which is
* to simply set the lock bit and set the share count to one.
* However, if the pushlock is already shared, the slower path is taken.
*
* Callers of ExAcquirePushLockShared must be running at IRQL <= APC_LEVEL.
* This macro should usually be paired up with KeAcquireCriticalRegion.
*
*--*/
VOID
FORCEINLINE
ExAcquirePushLockShared(PEX_PUSH_LOCK PushLock)
{
EX_PUSH_LOCK NewValue;
/* Try acquiring the lock */
NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
{
/* Someone changed it, use the slow path */
// DbgPrint("%s - Contention!\n", __FUNCTION__);
ExfAcquirePushLockShared(PushLock);
}
/* Sanity checks */
ASSERT(PushLock->Locked);
ASSERT(PushLock->Waiting || PushLock->Shared > 0);
}
/*++
* @name ExConvertPushLockSharedToExclusive
* INTERNAL MACRO
*
* The ExConvertPushLockSharedToExclusive macro converts an exclusive
* pushlock to a shared pushlock.
*
* @params PushLock
* Pointer to the pushlock which is to be converted.
*
* @return FALSE if conversion failed, TRUE otherwise.
*
* @remarks The function attempts the quickest route to convert the lock, which is
* to simply set the lock bit and remove any other bits.
*
*--*/
BOOLEAN
FORCEINLINE
ExConvertPushLockSharedToExclusive(IN PEX_PUSH_LOCK PushLock)
{
EX_PUSH_LOCK OldValue;
/* Set the expected old value */
OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
/* Try converting the lock */
if (ExpChangePushlock(PushLock, EX_PUSH_LOCK_LOCK, OldValue.Value) !=
OldValue.Ptr)
{
/* Conversion failed */
return FALSE;
}
/* Sanity check */
ASSERT(PushLock->Locked);
return TRUE;
}
/*++
* @name ExWaitOnPushLock
* INTERNAL MACRO
*
* The ExWaitOnPushLock macro acquires and instantly releases a pushlock.
*
* @params PushLock
* Pointer to a pushlock.
*
* @return None.
*
* @remarks The function attempts to get any exclusive waiters out of their slow
* path by forcing an instant acquire/release operation.
*
* Callers of ExWaitOnPushLock must be running at IRQL <= APC_LEVEL.
*
*--*/
VOID
FORCEINLINE
ExWaitOnPushLock(PEX_PUSH_LOCK PushLock)
{
/* Check if we're locked */
if (PushLock->Locked)
{
/* Acquire the lock */
ExfAcquirePushLockExclusive(PushLock);
ASSERT(PushLock->Locked);
/* Release it */
ExfReleasePushLockExclusive(PushLock);
}
}
/*++
* @name ExReleasePushLockShared
* INTERNAL MACRO
*
* The ExReleasePushLockShared macro releases a previously acquired PushLock.
*
* @params PushLock
* Pointer to a previously acquired pushlock.
*
* @return None.
*
* @remarks The function attempts the quickest route to release the lock, which is
* to simply decrease the share count and remove the lock bit.
* However, if the pushlock is being waited on then the long path is taken.
*
* Callers of ExReleasePushLockShared must be running at IRQL <= APC_LEVEL.
* This macro should usually be paired up with KeLeaveCriticalRegion.
*
*--*/
VOID
FORCEINLINE
ExReleasePushLockShared(PEX_PUSH_LOCK PushLock)
{
EX_PUSH_LOCK OldValue;
/* Sanity checks */
ASSERT(PushLock->Locked);
ASSERT(PushLock->Waiting || PushLock->Shared > 0);
/* Try to clear the pushlock */
OldValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
if (ExpChangePushlock(PushLock, 0, OldValue.Ptr) != OldValue.Ptr)
{
/* There are still other people waiting on it */
DbgPrint("%s - Contention!\n", __FUNCTION__);
ExfReleasePushLockShared(PushLock);
}
}
/*++
* @name ExReleasePushLockExclusive
* INTERNAL MACRO
*
* The ExReleasePushLockExclusive macro releases a previously
* exclusively acquired PushLock.
*
* @params PushLock
* Pointer to a previously acquired pushlock.
*
* @return None.
*
* @remarks The function attempts the quickest route to release the lock, which is
* to simply clear the locked bit.
* However, if the pushlock is being waited on, the slow path is taken
* in an attempt to wake up the lock.
*
* Callers of ExReleasePushLockExclusive must be running at IRQL <= APC_LEVEL.
* This macro should usually be paired up with KeLeaveCriticalRegion.
*
*--*/
VOID
FORCEINLINE
ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock)
{
EX_PUSH_LOCK OldValue;
/* Sanity checks */
ASSERT(PushLock->Locked);
ASSERT(PushLock->Waiting || PushLock->Shared == 0);
/* Unlock the pushlock */
OldValue.Value = InterlockedExchangeAddSizeT((PLONG)PushLock,
-(LONG)EX_PUSH_LOCK_LOCK);
/* Sanity checks */
ASSERT(OldValue.Locked);
ASSERT(OldValue.Waiting || OldValue.Shared == 0);
/* Check if anyone is waiting on it and it's not already waking*/
if ((OldValue.Waiting) && !(OldValue.Waking))
{
/* Wake it up */
DbgPrint("%s - Contention!\n", __FUNCTION__);
ExfTryToWakePushLock(PushLock);
}
}
/*++
* @name ExReleasePushLock
* INTERNAL MACRO
*
* The ExReleasePushLock macro releases a previously acquired PushLock.
*
* @params PushLock
* Pointer to a previously acquired pushlock.
*
* @return None.
*
* @remarks The function attempts the quickest route to release the lock, which is
* to simply clear all the fields and decrease the share count if required.
* However, if the pushlock is being waited on then the long path is taken.
*
* Callers of ExReleasePushLock must be running at IRQL <= APC_LEVEL.
* This macro should usually be paired up with KeLeaveCriticalRegion.
*
*--*/
VOID
FORCEINLINE
ExReleasePushLock(PEX_PUSH_LOCK PushLock)
{
EX_PUSH_LOCK OldValue = *PushLock;
EX_PUSH_LOCK NewValue;
/* Sanity checks */
ASSERT(OldValue.Locked);
/* Check if the pushlock is shared */
if (OldValue.Shared > 1)
{
/* Decrease the share count */
NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
}
else
{
/* Clear the pushlock entirely */
NewValue.Value = 0;
}
/* Check if nobody is waiting on us and try clearing the lock here */
if ((OldValue.Waiting) ||
(ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
OldValue.Ptr))
{
/* We have waiters, use the long path */
// DbgPrint("%s - Contention!\n", __FUNCTION__);
ExfReleasePushLock(PushLock);
}
}
/* OTHER FUNCTIONS **********************************************************/
LONGLONG
FASTCALL
ExfpInterlockedExchange64(
LONGLONG volatile * Destination,
PLONGLONG Exchange
);
NTSTATUS
ExpSetTimeZoneInformation(PTIME_ZONE_INFORMATION TimeZoneInformation);
BOOLEAN
NTAPI
ExAcquireTimeRefreshLock(BOOLEAN Wait);
VOID
NTAPI
ExReleaseTimeRefreshLock(VOID);
VOID
NTAPI
ExUpdateSystemTimeFromCmos(IN BOOLEAN UpdateInterruptTime,
IN ULONG MaxSepInSeconds);
NTSTATUS
NTAPI
ExpAllocateLocallyUniqueId(OUT LUID *LocallyUniqueId);
VOID
NTAPI
ExTimerRundown(VOID);
VOID
NTAPI
HeadlessInit(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
VOID
NTAPI
XIPInit(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
#define InterlockedDecrementUL(Addend) \
(ULONG)InterlockedDecrement((PLONG)(Addend))
#define InterlockedIncrementUL(Addend) \
(ULONG)InterlockedIncrement((PLONG)(Addend))
#define InterlockedExchangeUL(Target, Value) \
(ULONG)InterlockedExchange((PLONG)(Target), (LONG)(Value))
#define InterlockedExchangeAddUL(Addend, Value) \
(ULONG)InterlockedExchangeAdd((PLONG)(Addend), (LONG)(Value))
#define InterlockedCompareExchangeUL(Destination, Exchange, Comperand) \
(ULONG)InterlockedCompareExchange((PLONG)(Destination), (LONG)(Exchange), (LONG)(Comperand))
#define ExfInterlockedCompareExchange64UL(Destination, Exchange, Comperand) \
(ULONGLONG)ExfInterlockedCompareExchange64((PLONGLONG)(Destination), (PLONGLONG)(Exchange), (PLONGLONG)(Comperand))
#define ExfpInterlockedExchange64UL(Target, Value) \
(ULONGLONG)ExfpInterlockedExchange64((PLONGLONG)(Target), (PLONGLONG)(Value))
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_EXECUTIVE_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -