2020-09-30 17:12:29 +02:00

2729 lines
60 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++ BUILD Version: 0007 // Increment this if a change has global effects
Copyright (c) 1989 Microsoft Corporation
Module Name:
ex.h
Abstract:
Public executive data structures and procedure prototypes.
Author:
Mark Lucovsky (markl) 23-Feb-1989
Revision History:
--*/
#ifndef _EX_
#define _EX_
//
// Define caller count hash table structures and function prototypes.
//
#define CALL_HASH_TABLE_SIZE 64
typedef struct _CALL_HASH_ENTRY {
LIST_ENTRY ListEntry;
PVOID CallersAddress;
PVOID CallersCaller;
ULONG CallCount;
} CALL_HASH_ENTRY, *PCALL_HASH_ENTRY;
typedef struct _CALL_PERFORMANCE_DATA {
KSPIN_LOCK SpinLock;
LIST_ENTRY HashTable[CALL_HASH_TABLE_SIZE];
} CALL_PERFORMANCE_DATA, *PCALL_PERFORMANCE_DATA;
VOID
ExInitializeCallData(
IN PCALL_PERFORMANCE_DATA CallData
);
VOID
ExRecordCallerInHashTable(
IN PCALL_PERFORMANCE_DATA CallData,
IN PVOID CallersAddress,
IN PVOID CallersCaller
);
#define RECORD_CALL_DATA(Table) \
{ \
PVOID CallersAddress; \
PVOID CallersCaller; \
RtlGetCallersAddress(&CallersAddress, &CallersCaller); \
ExRecordCallerInHashTable((Table), CallersAddress, CallersCaller); \
}
//
// Define executive event pair object structure.
//
typedef struct _EEVENT_PAIR {
KEVENT_PAIR KernelEventPair;
} EEVENT_PAIR, *PEEVENT_PAIR;
//
// empty struct def so we can forward reference ETHREAD
//
struct _ETHREAD;
//
// System Initialization procedure for EX subcomponent of NTOS (in exinit.c)
//
NTKERNELAPI
BOOLEAN
ExInitSystem(
VOID
);
NTKERNELAPI
VOID
ExInitSystemPhase2(
VOID
);
ULONG
ExComputeTickCountMultiplier (
IN ULONG TimeIncrement
);
// begin_ntddk begin_nthal begin_ntifs
//
// Pool Allocation routines (in pool.c)
//
typedef enum _POOL_TYPE {
NonPagedPool,
PagedPool,
NonPagedPoolMustSucceed,
DontUseThisType,
NonPagedPoolCacheAligned,
PagedPoolCacheAligned,
NonPagedPoolCacheAlignedMustS,
MaxPoolType
} POOL_TYPE;
// end_ntddk end_nthal end_ntifs
//
// The following two defintions control the raising of excpetions on quota
// and allocation failures.
//
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 8
#define POOL_RAISE_IF_ALLOCATION_FAILURE 16 // ntifs
VOID
InitializePool(
IN POOL_TYPE PoolType,
IN ULONG Threshold
);
// begin_ntddk begin_nthal begin_ntifs
NTKERNELAPI
PVOID
ExAllocatePool(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes
);
NTKERNELAPI
PVOID
ExAllocatePoolWithQuota(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes
);
NTKERNELAPI
PVOID
ExAllocatePoolWithTag(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag
);
#ifndef POOL_TAGGING
#define ExAllocatePoolWithTag(a,b,c) ExAllocatePool(a,b)
#endif //POOL_TAGGING
NTKERNELAPI
PVOID
ExAllocatePoolWithQuotaTag(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag
);
#ifndef POOL_TAGGING
#define ExAllocatePoolWithQuotaTag(a,b,c) ExAllocatePoolWithQuota(a,b)
#endif //POOL_TAGGING
NTKERNELAPI
VOID
NTAPI
ExFreePool(
IN PVOID P
);
// end_ntddk end_nthal end_ntifs
//
// If high order bit in Pool tag is set, then must use ExFreePoolWithTag to free
//
#define PROTECTED_POOL 0x80000000
NTKERNELAPI
VOID
ExFreePoolWithTag(
IN PVOID P,
IN ULONG Tag
);
#ifndef POOL_TAGGING
#define ExFreePoolWithTag(a,b) ExFreePool(a)
#endif //POOL_TAGGING
NTKERNELAPI
KIRQL
ExLockPool(
IN POOL_TYPE PoolType
);
NTKERNELAPI
VOID
ExUnlockPool(
IN POOL_TYPE PoolType,
IN KIRQL LockHandle
);
NTKERNELAPI // ntifs
ULONG // ntifs
ExQueryPoolBlockSize ( // ntifs
IN PVOID PoolBlock, // ntifs
OUT PBOOLEAN QuotaCharged // ntifs
); // ntifs
NTKERNELAPI
VOID
ExQueryPoolUsage(
OUT PULONG PagedPoolPages,
OUT PULONG NonPagedPoolPages,
OUT PULONG PagedPoolAllocs,
OUT PULONG PagedPoolFrees,
OUT PULONG PagedPoolLookasideHits,
OUT PULONG NonPagedPoolAllocs,
OUT PULONG NonPagedPoolFrees,
OUT PULONG NonPagedPoolLookasideHits
);
VOID
ExReturnPoolQuota (
IN PVOID P
);
#if DBG
NTKERNELAPI
NTSTATUS
ExSnapShotPool(
IN POOL_TYPE PoolType,
IN PSYSTEM_POOL_INFORMATION PoolInformation,
IN ULONG Length,
OUT PULONG ReturnLength OPTIONAL
);
#endif // DBG
// begin_ntifs begin_ntddk begin_nthal
//
// Routines to support fast mutexes.
//
typedef struct _FAST_MUTEX {
LONG Count;
PKTHREAD Owner;
ULONG Contention;
KEVENT Event;
ULONG OldIrql;
} FAST_MUTEX, *PFAST_MUTEX;
#if DBG
#define ExInitializeFastMutex(_FastMutex) \
(_FastMutex)->Count = 1; \
(_FastMutex)->Owner = NULL; \
(_FastMutex)->Contention = 0; \
KeInitializeEvent(&(_FastMutex)->Event, \
SynchronizationEvent, \
FALSE);
#else
#define ExInitializeFastMutex(_FastMutex) \
(_FastMutex)->Count = 1; \
(_FastMutex)->Contention = 0; \
KeInitializeEvent(&(_FastMutex)->Event, \
SynchronizationEvent, \
FALSE);
#endif // DBG
NTKERNELAPI
VOID
FASTCALL
ExAcquireFastMutexUnsafe (
IN PFAST_MUTEX FastMutex
);
NTKERNELAPI
VOID
FASTCALL
ExReleaseFastMutexUnsafe (
IN PFAST_MUTEX FastMutex
);
#if defined(_MIPS_) || defined(_ALPHA_) || defined(_PPC_) || (defined(_X86_) && defined(_NTHAL_))
NTKERNELAPI
VOID
FASTCALL
ExAcquireFastMutex (
IN PFAST_MUTEX FastMutex
);
NTKERNELAPI
VOID
FASTCALL
ExReleaseFastMutex (
IN PFAST_MUTEX FastMutex
);
NTKERNELAPI
BOOLEAN
FASTCALL
ExTryToAcquireFastMutex (
IN PFAST_MUTEX FastMutex
);
#elif defined(_X86_) && !defined(_NTHAL_)
__declspec(dllimport)
VOID
FASTCALL
ExAcquireFastMutex (
IN PFAST_MUTEX FastMutex
);
__declspec(dllimport)
VOID
FASTCALL
ExReleaseFastMutex (
IN PFAST_MUTEX FastMutex
);
__declspec(dllimport)
BOOLEAN
FASTCALL
ExTryToAcquireFastMutex (
IN PFAST_MUTEX FastMutex
);
#elif
#error "Target architecture not defined"
#endif
// end_ntifs end_ntddk end_nthal
//
// Interlocked support routine definitions.
//
// begin_ntddk begin_nthal begin_ntifs
//
NTKERNELAPI
VOID
FASTCALL
ExInterlockedAddLargeStatistic (
IN PLARGE_INTEGER Addend,
IN ULONG Increment
);
NTKERNELAPI
LARGE_INTEGER
ExInterlockedAddLargeInteger (
IN PLARGE_INTEGER Addend,
IN LARGE_INTEGER Increment,
IN PKSPIN_LOCK Lock
);
#if defined(NT_UP) && !defined(_NTHAL_) && !defined(_NTDDK_) && !defined(_NTIFS_)
#undef ExInterlockedAddUlong
#define ExInterlockedAddUlong(x, y, z) InterlockedExchangeAdd((PLONG)(x), (LONG)(y))
#else
NTKERNELAPI
ULONG
FASTCALL
ExInterlockedAddUlong (
IN PULONG Addend,
IN ULONG Increment,
IN PKSPIN_LOCK Lock
);
#endif
#if defined(_ALPHA_) || defined(_MIPS_)
#define ExInterlockedCompareExchange64(Destination, Exchange, Comperand, Lock) \
ExpInterlockedCompareExchange64(Destination, Exchange, Comperand)
NTKERNELAPI
ULONGLONG
ExpInterlockedCompareExchange64 (
IN PULONGLONG Destination,
IN PULONGLONG Exchange,
IN PULONGLONG Comperand
);
#else
NTKERNELAPI
ULONGLONG
FASTCALL
ExInterlockedCompareExchange64 (
IN PULONGLONG Destination,
IN PULONGLONG Exchange,
IN PULONGLONG Comperand,
IN PKSPIN_LOCK Lock
);
#endif
NTKERNELAPI
PLIST_ENTRY
FASTCALL
ExInterlockedInsertHeadList (
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY ListEntry,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
PLIST_ENTRY
FASTCALL
ExInterlockedInsertTailList (
IN PLIST_ENTRY ListHead,
IN PLIST_ENTRY ListEntry,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
PLIST_ENTRY
FASTCALL
ExInterlockedRemoveHeadList (
IN PLIST_ENTRY ListHead,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
PSINGLE_LIST_ENTRY
FASTCALL
ExInterlockedPopEntryList (
IN PSINGLE_LIST_ENTRY ListHead,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
PSINGLE_LIST_ENTRY
FASTCALL
ExInterlockedPushEntryList (
IN PSINGLE_LIST_ENTRY ListHead,
IN PSINGLE_LIST_ENTRY ListEntry,
IN PKSPIN_LOCK Lock
);
//
// Define interlocked sequenced listhead functions.
//
// A sequenced interlocked list is a singly linked list with a header that
// contains the current depth and a sequence number. Each time an entry is
// inserted or removed from the list the depth is updated and the sequence
// number is incremented. This enables MIPS, Alpha, and Pentium and later
// machines to insert and remove from the list without the use of spinlocks.
// The PowerPc, however, must use a spinlock to synchronize access to the
// list.
//
// N.B. A spinlock must be specified with SLIST operations. However, it may
// not actually be used.
//
/*++
VOID
ExInitializeSListHead (
IN PSLIST_HEADER SListHead
)
Routine Description:
This function initializes a sequenced singly linked listhead.
Arguments:
SListHead - Supplies a pointer to a sequenced singly linked listhead.
Return Value:
None.
--*/
#define ExInitializeSListHead(_listhead_) \
(_listhead_)->Next.Next = NULL; \
(_listhead_)->Depth = 0; \
(_listhead_)->Sequence = 0
/*++
USHORT
ExQueryDepthSListHead (
IN PSLIST_HEADERT SListHead
)
Routine Description:
This function queries the current number of entries contained in a
sequenced single linked list.
Arguments:
SListHead - Supplies a pointer to the sequenced listhead which is
be queried.
Return Value:
The current number of entries in the sequenced singly linked list is
returned as the function value.
--*/
#define ExQueryDepthSList(_listhead_) (_listhead_)->Depth
#if defined(_MIPS_) || defined(_ALPHA_)
#define ExInterlockedPopEntrySList(Head, Lock) \
ExpInterlockedPopEntrySList(Head)
#define ExInterlockedPushEntrySList(Head, Entry, Lock) \
ExpInterlockedPushEntrySList(Head, Entry)
#define ExQueryDepthSList(_listhead_) (_listhead_)->Depth
NTKERNELAPI
PSINGLE_LIST_ENTRY
ExpInterlockedPopEntrySList (
IN PSLIST_HEADER ListHead
);
NTKERNELAPI
PSINGLE_LIST_ENTRY
ExpInterlockedPushEntrySList (
IN PSLIST_HEADER ListHead,
IN PSINGLE_LIST_ENTRY ListEntry
);
#else
NTKERNELAPI
PSINGLE_LIST_ENTRY
FASTCALL
ExInterlockedPopEntrySList (
IN PSLIST_HEADER ListHead,
IN PKSPIN_LOCK Lock
);
NTKERNELAPI
PSINGLE_LIST_ENTRY
FASTCALL
ExInterlockedPushEntrySList (
IN PSLIST_HEADER ListHead,
IN PSINGLE_LIST_ENTRY ListEntry,
IN PKSPIN_LOCK Lock
);
#endif
//
// Define interlocked lookaside list structure and allocation functions.
//
VOID
ExAdjustLookasideDepth (
VOID
);
typedef
PVOID
(*PALLOCATE_FUNCTION) (
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN ULONG Tag
);
typedef
VOID
(*PFREE_FUNCTION) (
IN PVOID Buffer
);
typedef struct _GENERAL_LOOKASIDE {
SLIST_HEADER ListHead;
USHORT Depth;
USHORT MaximumDepth;
ULONG TotalAllocates;
ULONG AllocateMisses;
ULONG TotalFrees;
ULONG FreeMisses;
POOL_TYPE Type;
ULONG Tag;
ULONG Size;
PALLOCATE_FUNCTION Allocate;
PFREE_FUNCTION Free;
LIST_ENTRY ListEntry;
ULONG LastTotalAllocates;
ULONG LastAllocateMisses;
ULONG Future[2];
} GENERAL_LOOKASIDE, *PGENERAL_LOOKASIDE;
typedef struct _NPAGED_LOOKASIDE_LIST {
GENERAL_LOOKASIDE L;
KSPIN_LOCK Lock;
} NPAGED_LOOKASIDE_LIST, *PNPAGED_LOOKASIDE_LIST;
NTKERNELAPI
VOID
ExInitializeNPagedLookasideList (
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN ULONG Size,
IN ULONG Tag,
IN USHORT Depth
);
NTKERNELAPI
VOID
ExDeleteNPagedLookasideList (
IN PNPAGED_LOOKASIDE_LIST Lookaside
);
__inline
PVOID
ExAllocateFromNPagedLookasideList(
IN PNPAGED_LOOKASIDE_LIST Lookaside
)
/*++
Routine Description:
This function removes (pops) the first entry from the specified
nonpaged lookaside list.
Arguments:
Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
Return Value:
If an entry is removed from the specified lookaside list, then the
address of the entry is returned as the function value. Otherwise,
NULL is returned.
--*/
{
PVOID Entry;
Lookaside->L.TotalAllocates += 1;
Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead, &Lookaside->Lock);
if (Entry == NULL) {
Lookaside->L.AllocateMisses += 1;
Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
Lookaside->L.Size,
Lookaside->L.Tag);
}
return Entry;
}
__inline
VOID
ExFreeToNPagedLookasideList(
IN PNPAGED_LOOKASIDE_LIST Lookaside,
IN PVOID Entry
)
/*++
Routine Description:
This function inserts (pushes) the specified entry into the specified
nonpaged lookaside list.
Arguments:
Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
Entry - Supples a pointer to the entry that is inserted in the
lookaside list.
Return Value:
None.
--*/
{
Lookaside->L.TotalFrees += 1;
if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
Lookaside->L.FreeMisses += 1;
(Lookaside->L.Free)(Entry);
} else {
ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
(PSINGLE_LIST_ENTRY)Entry,
&Lookaside->Lock);
}
return;
}
typedef struct _PAGED_LOOKASIDE_LIST {
GENERAL_LOOKASIDE L;
FAST_MUTEX Lock;
} PAGED_LOOKASIDE_LIST, *PPAGED_LOOKASIDE_LIST;
NTKERNELAPI
VOID
ExInitializePagedLookasideList (
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PALLOCATE_FUNCTION Allocate,
IN PFREE_FUNCTION Free,
IN ULONG Flags,
IN ULONG Size,
IN ULONG Tag,
IN USHORT Depth
);
NTKERNELAPI
VOID
ExDeletePagedLookasideList (
IN PPAGED_LOOKASIDE_LIST Lookaside
);
#if defined(_X86_) || defined(_PPC_)
NTKERNELAPI
PVOID
ExAllocateFromPagedLookasideList(
IN PPAGED_LOOKASIDE_LIST Lookaside
);
NTKERNELAPI
VOID
ExFreeToPagedLookasideList(
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PVOID Entry
);
#else
__inline
PVOID
ExAllocateFromPagedLookasideList(
IN PPAGED_LOOKASIDE_LIST Lookaside
)
/*++
Routine Description:
This function removes (pops) the first entry from the specified
paged lookaside list.
Arguments:
Lookaside - Supplies a pointer to a paged lookaside list structure.
Return Value:
If an entry is removed from the specified lookaside list, then the
address of the entry is returned as the function value. Otherwise,
NULL is returned.
--*/
{
PVOID Entry;
Lookaside->L.TotalAllocates += 1;
Entry = ExInterlockedPopEntrySList(&Lookaside->L.ListHead, NULL);
if (Entry == NULL) {
Lookaside->L.AllocateMisses += 1;
Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
Lookaside->L.Size,
Lookaside->L.Tag);
}
return Entry;
}
__inline
VOID
ExFreeToPagedLookasideList(
IN PPAGED_LOOKASIDE_LIST Lookaside,
IN PVOID Entry
)
/*++
Routine Description:
This function inserts (pushes) the specified entry into the specified
paged lookaside list.
Arguments:
Lookaside - Supplies a pointer to a nonpaged lookaside list structure.
Entry - Supples a pointer to the entry that is inserted in the
lookaside list.
Return Value:
None.
--*/
{
Lookaside->L.TotalFrees += 1;
if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
Lookaside->L.FreeMisses += 1;
(Lookaside->L.Free)(Entry);
} else {
ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
(PSINGLE_LIST_ENTRY)Entry,
NULL);
}
return;
}
#endif
// end_ntddk end_nthal end_ntifs
extern LIST_ENTRY ExNPagedLookasideListHead;
extern KSPIN_LOCK ExNPagedLookasideLock;
extern LIST_ENTRY ExPagedLookasideListHead;
extern KSPIN_LOCK ExPagedLookasideLock;
#if i386 && !FPO
NTSTATUS
ExQuerySystemBackTraceInformation(
OUT PRTL_PROCESS_BACKTRACES BackTraceInformation,
IN ULONG BackTraceInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
NTKERNELAPI
USHORT
ExGetPoolBackTraceIndex(
IN PVOID P
);
#endif // i386 && !FPO
NTKERNELAPI
PVOID
ExLockUserBuffer(
IN PVOID Buffer,
IN ULONG Length,
OUT PVOID *LockVariable
);
NTKERNELAPI
VOID
ExUnlockUserBuffer(
IN PVOID LockVariable
);
// begin_ntifs
//
// Probe function definitions
//
// Probe for read funstions.
//
//++
//
// VOID
// ProbeForRead(
// IN PVOID Address,
// IN ULONG Length,
// IN ULONG Alignment
// )
//
//--
#define ProbeForRead(Address, Length, Alignment) \
ASSERT(((Alignment) == 1) || ((Alignment) == 2) || \
((Alignment) == 4) || ((Alignment) == 8)); \
\
if ((Length) != 0) { \
if (((ULONG)(Address) & ((Alignment) - 1)) != 0) { \
ExRaiseDatatypeMisalignment(); \
\
} else if ((((ULONG)(Address) + (Length)) < (ULONG)(Address)) || \
(((ULONG)(Address) + (Length)) > (ULONG)MM_USER_PROBE_ADDRESS)) { \
ExRaiseAccessViolation(); \
} \
}
// end_ntifs
//++
//
// BOOLEAN
// ProbeAndReadBoolean(
// IN PBOOLEAN Address
// )
//
//--
#define ProbeAndReadBoolean(Address) \
(((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS) : (*(volatile BOOLEAN *)(Address)))
//++
//
// CHAR
// ProbeAndReadChar(
// IN PCHAR Address
// )
//
//--
#define ProbeAndReadChar(Address) \
(((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile CHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile CHAR *)(Address)))
//++
//
// UCHAR
// ProbeAndReadUchar(
// IN PUCHAR Address
// )
//
//--
#define ProbeAndReadUchar(Address) \
(((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS) : (*(volatile UCHAR *)(Address)))
//++
//
// SHORT
// ProbeAndReadShort(
// IN PSHORT Address
// )
//
//--
#define ProbeAndReadShort(Address) \
(((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile SHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile SHORT *)(Address)))
//++
//
// USHORT
// ProbeAndReadUshort(
// IN PUSHORT Address
// )
//
//--
#define ProbeAndReadUshort(Address) \
(((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile USHORT * const)MM_USER_PROBE_ADDRESS) : (*(volatile USHORT *)(Address)))
//++
//
// HANDLE
// ProbeAndReadHandle(
// IN PHANDLE Address
// )
//
//--
#define ProbeAndReadHandle(Address) \
(((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS) : (*(volatile HANDLE *)(Address)))
//++
//
// LONG
// ProbeAndReadLong(
// IN PLONG Address
// )
//
//--
#define ProbeAndReadLong(Address) \
(((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile LONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile LONG *)(Address)))
//++
//
// ULONG
// ProbeAndReadUlong(
// IN PULONG Address
// )
//
//--
#define ProbeAndReadUlong(Address) \
(((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile ULONG * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULONG *)(Address)))
//++
//
// QUAD
// ProbeAndReadQuad(
// IN PQUAD Address
// )
//
//--
#define ProbeAndReadQuad(Address) \
(((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile QUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile QUAD *)(Address)))
//++
//
// UQUAD
// ProbeAndReadUquad(
// IN PUQUAD Address
// )
//
//--
#define ProbeAndReadUquad(Address) \
(((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile UQUAD * const)MM_USER_PROBE_ADDRESS) : (*(volatile UQUAD *)(Address)))
//++
//
// LARGE_INTEGER
// ProbeAndReadLargeInteger(
// IN PLARGE_INTEGER Source
// )
//
//--
#define ProbeAndReadLargeInteger(Source) \
(((Source) >= (LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile LARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile LARGE_INTEGER *)(Source)))
//++
//
// ULARGE_INTEGER
// ProbeAndReadUlargeInteger(
// IN PULARGE_INTEGER Source
// )
//
//--
#define ProbeAndReadUlargeInteger(Source) \
(((Source) >= (ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile ULARGE_INTEGER * const)MM_USER_PROBE_ADDRESS) : (*(volatile ULARGE_INTEGER *)(Source)))
//++
//
// UNICODE_STRING
// ProbeAndReadUnicodeString(
// IN PUNICODE_STRING Source
// )
//
//--
#define ProbeAndReadUnicodeString(Source) \
(((Source) >= (UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) ? \
(*(volatile UNICODE_STRING * const)MM_USER_PROBE_ADDRESS) : (*(volatile UNICODE_STRING *)(Source)))
//++
//
// <STRUCTURE>
// ProbeAndReadStructure(
// IN P<STRUCTURE> Source
// <STRUCTURE>
// )
//
//--
#define ProbeAndReadStructure(Source,STRUCTURE) \
(((Source) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) ? \
(*(STRUCTURE * const)MM_USER_PROBE_ADDRESS) : (*(STRUCTURE *)(Source)))
//
// Probe for write functions definitions.
//
//++
//
// VOID
// ProbeForWriteBoolean(
// IN PBOOLEAN Address
// )
//
//--
#define ProbeForWriteBoolean(Address) { \
if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \
*(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile BOOLEAN *)(Address) = *(volatile BOOLEAN *)(Address); \
}
//++
//
// VOID
// ProbeForWriteChar(
// IN PCHAR Address
// )
//
//--
#define ProbeForWriteChar(Address) { \
if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \
*(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile CHAR *)(Address) = *(volatile CHAR *)(Address); \
}
//++
//
// VOID
// ProbeForWriteUchar(
// IN PUCHAR Address
// )
//
//--
#define ProbeForWriteUchar(Address) { \
if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \
*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile UCHAR *)(Address) = *(volatile UCHAR *)(Address); \
}
//++
//
// VOID
// ProbeForWriteIoStatus(
// IN PIO_STATUS_BLOCK Address
// )
//
//--
#define ProbeForWriteIoStatus(Address) { \
if ((Address) >= (IO_STATUS_BLOCK * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile IO_STATUS_BLOCK *)(Address) = *(volatile IO_STATUS_BLOCK *)(Address); \
}
//++
//
// VOID
// ProbeForWriteShort(
// IN PSHORT Address
// )
//
//--
#define ProbeForWriteShort(Address) { \
if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \
*(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile SHORT *)(Address) = *(volatile SHORT *)(Address); \
}
//++
//
// VOID
// ProbeForWriteUshort(
// IN PUSHORT Address
// )
//
//--
#define ProbeForWriteUshort(Address) { \
if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \
*(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile USHORT *)(Address) = *(volatile USHORT *)(Address); \
}
//++
//
// VOID
// ProbeForWriteHandle(
// IN PHANDLE Address
// )
//
//--
#define ProbeForWriteHandle(Address) { \
if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile HANDLE *)(Address) = *(volatile HANDLE *)(Address); \
}
//++
//
// VOID
// ProbeAndZeroHandle(
// IN PHANDLE Address
// )
//
//--
#define ProbeAndZeroHandle(Address) { \
if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile HANDLE *)(Address) = 0; \
}
//++
//
// VOID
// ProbeAndNullPointer(
// IN PVOID Address
// )
//
//--
#define ProbeAndNullPointer(Address) { \
if ((PVOID *)(Address) >= (PVOID * const)MM_USER_PROBE_ADDRESS) { \
*(volatile PVOID * const)MM_USER_PROBE_ADDRESS = NULL; \
} \
\
*(volatile PVOID *)(Address) = NULL; \
}
//++
//
// VOID
// ProbeForWriteLong(
// IN PLONG Address
// )
//
//--
#define ProbeForWriteLong(Address) { \
if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \
*(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile LONG *)(Address) = *(volatile LONG *)(Address); \
}
//++
//
// VOID
// ProbeForWriteUlong(
// IN PULONG Address
// )
//
//--
#define ProbeForWriteUlong(Address) { \
if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile ULONG *)(Address) = *(volatile ULONG *)(Address); \
}
//++
//
// VOID
// ProbeForWriteQuad(
// IN PQUAD Address
// )
//
//--
#define ProbeForWriteQuad(Address) { \
if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
*(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile QUAD *)(Address) = *(volatile QUAD *)(Address); \
}
//++
//
// VOID
// ProbeForWriteUquad(
// IN PUQUAD Address
// )
//
//--
#define ProbeForWriteUquad(Address) { \
if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(volatile UQUAD *)(Address) = *(volatile UQUAD *)(Address); \
}
//
// Probe and write functions definitions.
//
//++
//
// VOID
// ProbeAndWriteBoolean(
// IN PBOOLEAN Address,
// IN BOOLEAN Value
// )
//
//--
#define ProbeAndWriteBoolean(Address, Value) { \
if ((Address) >= (BOOLEAN * const)MM_USER_PROBE_ADDRESS) { \
*(volatile BOOLEAN * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteChar(
// IN PCHAR Address,
// IN CHAR Value
// )
//
//--
#define ProbeAndWriteChar(Address, Value) { \
if ((Address) >= (CHAR * const)MM_USER_PROBE_ADDRESS) { \
*(volatile CHAR * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteUchar(
// IN PUCHAR Address,
// IN UCHAR Value
// )
//
//--
#define ProbeAndWriteUchar(Address, Value) { \
if ((Address) >= (UCHAR * const)MM_USER_PROBE_ADDRESS) { \
*(volatile UCHAR * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteShort(
// IN PSHORT Address,
// IN SHORT Value
// )
//
//--
#define ProbeAndWriteShort(Address, Value) { \
if ((Address) >= (SHORT * const)MM_USER_PROBE_ADDRESS) { \
*(volatile SHORT * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteUshort(
// IN PUSHORT Address,
// IN USHORT Value
// )
//
//--
#define ProbeAndWriteUshort(Address, Value) { \
if ((Address) >= (USHORT * const)MM_USER_PROBE_ADDRESS) { \
*(volatile USHORT * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteHandle(
// IN PHANDLE Address,
// IN HANDLE Value
// )
//
//--
#define ProbeAndWriteHandle(Address, Value) { \
if ((Address) >= (HANDLE * const)MM_USER_PROBE_ADDRESS) { \
*(volatile HANDLE * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteLong(
// IN PLONG Address,
// IN LONG Value
// )
//
//--
#define ProbeAndWriteLong(Address, Value) { \
if ((Address) >= (LONG * const)MM_USER_PROBE_ADDRESS) { \
*(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteUlong(
// IN PULONG Address,
// IN ULONG Value
// )
//
//--
#define ProbeAndWriteUlong(Address, Value) { \
if ((Address) >= (ULONG * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteQuad(
// IN PQUAD Address,
// IN QUAD Value
// )
//
//--
#define ProbeAndWriteQuad(Address, Value) { \
if ((Address) >= (QUAD * const)MM_USER_PROBE_ADDRESS) { \
*(volatile LONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteUquad(
// IN PUQUAD Address,
// IN UQUAD Value
// )
//
//--
#define ProbeAndWriteUquad(Address, Value) { \
if ((Address) >= (UQUAD * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
//++
//
// VOID
// ProbeAndWriteSturcture(
// IN P<STRUCTURE> Address,
// IN <STRUCTURE> Value,
// <STRUCTURE>
// )
//
//--
#define ProbeAndWriteStructure(Address, Value,STRUCTURE) { \
if ((STRUCTURE * const)(Address) >= (STRUCTURE * const)MM_USER_PROBE_ADDRESS) { \
*(volatile ULONG * const)MM_USER_PROBE_ADDRESS = 0; \
} \
\
*(Address) = (Value); \
}
// begin_ntifs
//
// Common probe for write functions.
//
NTKERNELAPI
VOID
NTAPI
ProbeForWrite (
IN PVOID Address,
IN ULONG Length,
IN ULONG Alignment
);
// end_ntifs
//
// Timer Rundown
//
NTKERNELAPI
VOID
ExTimerRundown (
VOID
);
// begin_ntddk begin_nthal begin_ntifs
//
// Worker Thread
//
typedef enum _WORK_QUEUE_TYPE {
CriticalWorkQueue,
DelayedWorkQueue,
HyperCriticalWorkQueue,
MaximumWorkQueue
} WORK_QUEUE_TYPE;
typedef
VOID
(*PWORKER_THREAD_ROUTINE)(
IN PVOID Parameter
);
typedef struct _WORK_QUEUE_ITEM {
LIST_ENTRY List;
PWORKER_THREAD_ROUTINE WorkerRoutine;
PVOID Parameter;
} WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM;
#define ExInitializeWorkItem(Item, Routine, Context) \
(Item)->WorkerRoutine = (Routine); \
(Item)->Parameter = (Context); \
(Item)->List.Flink = NULL;
NTKERNELAPI
VOID
ExQueueWorkItem(
IN PWORK_QUEUE_ITEM WorkItem,
IN WORK_QUEUE_TYPE QueueType
);
NTKERNELAPI
BOOLEAN
ExIsProcessorFeaturePresent(
ULONG ProcessorFeature
);
// end_ntddk end_nthal end_ntifs
extern KQUEUE ExWorkerQueue[];
// begin_ntddk begin_nthal begin_ntifs
//
// Zone Allocation
//
typedef struct _ZONE_SEGMENT_HEADER {
SINGLE_LIST_ENTRY SegmentList;
PVOID Reserved;
} ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER;
typedef struct _ZONE_HEADER {
SINGLE_LIST_ENTRY FreeList;
SINGLE_LIST_ENTRY SegmentList;
ULONG BlockSize;
ULONG TotalSegmentSize;
} ZONE_HEADER, *PZONE_HEADER;
NTKERNELAPI
NTSTATUS
ExInitializeZone(
IN PZONE_HEADER Zone,
IN ULONG BlockSize,
IN PVOID InitialSegment,
IN ULONG InitialSegmentSize
);
NTKERNELAPI
NTSTATUS
ExExtendZone(
IN PZONE_HEADER Zone,
IN PVOID Segment,
IN ULONG SegmentSize
);
NTKERNELAPI
NTSTATUS
ExInterlockedExtendZone(
IN PZONE_HEADER Zone,
IN PVOID Segment,
IN ULONG SegmentSize,
IN PKSPIN_LOCK Lock
);
//++
//
// PVOID
// ExAllocateFromZone(
// IN PZONE_HEADER Zone
// )
//
// Routine Description:
//
// This routine removes an entry from the zone and returns a pointer to it.
//
// Arguments:
//
// Zone - Pointer to the zone header controlling the storage from which the
// entry is to be allocated.
//
// Return Value:
//
// The function value is a pointer to the storage allocated from the zone.
//
//--
#define ExAllocateFromZone(Zone) \
(PVOID)((Zone)->FreeList.Next); \
if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next
//++
//
// PVOID
// ExFreeToZone(
// IN PZONE_HEADER Zone,
// IN PVOID Block
// )
//
// Routine Description:
//
// This routine places the specified block of storage back onto the free
// list in the specified zone.
//
// Arguments:
//
// Zone - Pointer to the zone header controlling the storage to which the
// entry is to be inserted.
//
// Block - Pointer to the block of storage to be freed back to the zone.
//
// Return Value:
//
// Pointer to previous block of storage that was at the head of the free
// list. NULL implies the zone went from no available free blocks to
// at least one free block.
//
//--
#define ExFreeToZone(Zone,Block) \
( ((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next, \
(Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)), \
((PSINGLE_LIST_ENTRY)(Block))->Next \
)
//++
//
// BOOLEAN
// ExIsFullZone(
// IN PZONE_HEADER Zone
// )
//
// Routine Description:
//
// This routine determines if the specified zone is full or not. A zone
// is considered full if the free list is empty.
//
// Arguments:
//
// Zone - Pointer to the zone header to be tested.
//
// Return Value:
//
// TRUE if the zone is full and FALSE otherwise.
//
//--
#define ExIsFullZone(Zone) \
( (Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY)NULL )
//++
//
// PVOID
// ExInterlockedAllocateFromZone(
// IN PZONE_HEADER Zone,
// IN PKSPIN_LOCK Lock
// )
//
// Routine Description:
//
// This routine removes an entry from the zone and returns a pointer to it.
// The removal is performed with the specified lock owned for the sequence
// to make it MP-safe.
//
// Arguments:
//
// Zone - Pointer to the zone header controlling the storage from which the
// entry is to be allocated.
//
// Lock - Pointer to the spin lock which should be obtained before removing
// the entry from the allocation list. The lock is released before
// returning to the caller.
//
// Return Value:
//
// The function value is a pointer to the storage allocated from the zone.
//
//--
#define ExInterlockedAllocateFromZone(Zone,Lock) \
(PVOID) ExInterlockedPopEntryList( &(Zone)->FreeList, Lock )
//++
//
// PVOID
// ExInterlockedFreeToZone(
// IN PZONE_HEADER Zone,
// IN PVOID Block,
// IN PKSPIN_LOCK Lock
// )
//
// Routine Description:
//
// This routine places the specified block of storage back onto the free
// list in the specified zone. The insertion is performed with the lock
// owned for the sequence to make it MP-safe.
//
// Arguments:
//
// Zone - Pointer to the zone header controlling the storage to which the
// entry is to be inserted.
//
// Block - Pointer to the block of storage to be freed back to the zone.
//
// Lock - Pointer to the spin lock which should be obtained before inserting
// the entry onto the free list. The lock is released before returning
// to the caller.
//
// Return Value:
//
// Pointer to previous block of storage that was at the head of the free
// list. NULL implies the zone went from no available free blocks to
// at least one free block.
//
//--
#define ExInterlockedFreeToZone(Zone,Block,Lock) \
ExInterlockedPushEntryList( &(Zone)->FreeList, ((PSINGLE_LIST_ENTRY) (Block)), Lock )
//++
//
// BOOLEAN
// ExIsObjectInFirstZoneSegment(
// IN PZONE_HEADER Zone,
// IN PVOID Object
// )
//
// Routine Description:
//
// This routine determines if the specified pointer lives in the zone.
//
// Arguments:
//
// Zone - Pointer to the zone header controlling the storage to which the
// object may belong.
//
// Object - Pointer to the object in question.
//
// Return Value:
//
// TRUE if the Object came from the first segment of zone.
//
//--
#define ExIsObjectInFirstZoneSegment(Zone,Object) ((BOOLEAN) \
(((PUCHAR)(Object) >= (PUCHAR)(Zone)->SegmentList.Next) && \
((PUCHAR)(Object) < (PUCHAR)(Zone)->SegmentList.Next + \
(Zone)->TotalSegmentSize)) \
)
// end_ntddk end_nthal end_ntifs
// begin_ntifs begin_ntddk
//
// Define executive resource data structures.
//
typedef ULONG ERESOURCE_THREAD;
typedef ERESOURCE_THREAD *PERESOURCE_THREAD;
typedef struct _OWNER_ENTRY {
ERESOURCE_THREAD OwnerThread;
SHORT OwnerCount;
USHORT TableSize;
} OWNER_ENTRY, *POWNER_ENTRY;
typedef struct _ERESOURCE {
LIST_ENTRY SystemResourcesList;
POWNER_ENTRY OwnerTable;
SHORT ActiveCount;
USHORT Flag;
PKSEMAPHORE SharedWaiters;
PKEVENT ExclusiveWaiters;
OWNER_ENTRY OwnerThreads[2];
ULONG ContentionCount;
USHORT NumberOfSharedWaiters;
USHORT NumberOfExclusiveWaiters;
union {
PVOID Address;
ULONG CreatorBackTraceIndex;
};
KSPIN_LOCK SpinLock;
} ERESOURCE, *PERESOURCE;
//
// Values for ERESOURCE.Flag
//
#define ResourceNeverExclusive 0x10
#define ResourceReleaseByOtherThread 0x20
#define ResourceOwnedExclusive 0x80
#define RESOURCE_HASH_TABLE_SIZE 64
typedef struct _RESOURCE_HASH_ENTRY {
LIST_ENTRY ListEntry;
PVOID Address;
ULONG ContentionCount;
ULONG Number;
} RESOURCE_HASH_ENTRY, *PRESOURCE_HASH_ENTRY;
typedef struct _RESOURCE_PERFORMANCE_DATA {
ULONG ActiveResourceCount;
ULONG TotalResourceCount;
ULONG ExclusiveAcquire;
ULONG SharedFirstLevel;
ULONG SharedSecondLevel;
ULONG StarveFirstLevel;
ULONG StarveSecondLevel;
ULONG WaitForExclusive;
ULONG OwnerTableExpands;
ULONG MaximumTableExpand;
LIST_ENTRY HashTable[RESOURCE_HASH_TABLE_SIZE];
} RESOURCE_PERFORMANCE_DATA, *PRESOURCE_PERFORMANCE_DATA;
//
// Define executive resource function prototypes.
//
NTKERNELAPI
NTSTATUS
ExInitializeResourceLite(
IN PERESOURCE Resource
);
NTKERNELAPI
NTSTATUS
ExReinitializeResourceLite(
IN PERESOURCE Resource
);
NTKERNELAPI
BOOLEAN
ExAcquireResourceSharedLite(
IN PERESOURCE Resource,
IN BOOLEAN Wait
);
NTKERNELAPI
BOOLEAN
ExAcquireResourceExclusiveLite(
IN PERESOURCE Resource,
IN BOOLEAN Wait
);
NTKERNELAPI
BOOLEAN
ExAcquireSharedStarveExclusive(
IN PERESOURCE Resource,
IN BOOLEAN Wait
);
NTKERNELAPI
BOOLEAN
ExAcquireSharedWaitForExclusive(
IN PERESOURCE Resource,
IN BOOLEAN Wait
);
NTKERNELAPI
BOOLEAN
ExTryToAcquireResourceExclusiveLite(
IN PERESOURCE Resource
);
//
// VOID
// ExReleaseResource(
// IN PERESOURCE Resource
// );
//
#define ExReleaseResource(R) (ExReleaseResourceLite(R))
NTKERNELAPI
VOID
FASTCALL
ExReleaseResourceLite(
IN PERESOURCE Resource
);
NTKERNELAPI
VOID
ExReleaseResourceForThreadLite(
IN PERESOURCE Resource,
IN ERESOURCE_THREAD ResourceThreadId
);
NTKERNELAPI
VOID
ExSetResourceOwnerPointer(
IN PERESOURCE Resource,
IN PVOID OwnerPointer
);
NTKERNELAPI
VOID
ExConvertExclusiveToSharedLite(
IN PERESOURCE Resource
);
NTKERNELAPI
NTSTATUS
ExDeleteResourceLite (
IN PERESOURCE Resource
);
NTKERNELAPI
ULONG
ExGetExclusiveWaiterCount (
IN PERESOURCE Resource
);
NTKERNELAPI
ULONG
ExGetSharedWaiterCount (
IN PERESOURCE Resource
);
// end_ntddk
NTKERNELAPI
VOID
ExDisableResourceBoostLite (
IN PERESOURCE Resource
);
// begin_ntddk
//
// ERESOURCE_THREAD
// ExGetCurrentResourceThread(
// );
//
#define ExGetCurrentResourceThread() ((ULONG)PsGetCurrentThread())
NTKERNELAPI
BOOLEAN
ExIsResourceAcquiredExclusiveLite (
IN PERESOURCE Resource
);
NTKERNELAPI
USHORT
ExIsResourceAcquiredSharedLite (
IN PERESOURCE Resource
);
//
// ntddk.h stole the entry points we wanted, so fix them up here.
//
#define ExInitializeResource ExInitializeResourceLite
#define ExAcquireResourceShared ExAcquireResourceSharedLite
#define ExAcquireResourceExclusive ExAcquireResourceExclusiveLite
#define ExReleaseResourceForThread ExReleaseResourceForThreadLite
#define ExConvertExclusiveToShared ExConvertExclusiveToSharedLite
#define ExDeleteResource ExDeleteResourceLite
#define ExIsResourceAcquiredExclusive ExIsResourceAcquiredExclusiveLite
#define ExIsResourceAcquiredShared ExIsResourceAcquiredSharedLite
// end_ntddk
#define ExDisableResourceBoost ExDisableResourceBoostLite
// end_ntifs
#if DEVL
NTKERNELAPI
NTSTATUS
ExQuerySystemLockInformation(
OUT struct _RTL_PROCESS_LOCKS *LockInformation,
IN ULONG LockInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
#endif // DEVL
//
// Shared resource function definitions (in resource.c).
//
// This definition here matches the ntddk one defined above. It allows
// the resource package to deal with these antiquated objects.
//
typedef struct _NTDDK_ERESOURCE {
//
// First 8 bytes are used to align the next part of the structure
// onto 16 bytes. (typical case)
//
LIST_ENTRY SystemResourcesList;
//
// Next 128 bits of this structure are field which we know
// we will hit to obtain this resource either shared or exclusive
//
PERESOURCE_THREAD OwnerThreads;
PUCHAR OwnerCounts;
USHORT TableSize;
USHORT ActiveCount;
USHORT Flag;
USHORT TableRover; // (0 - 128 bits)
//
// Next 128 bits contain the initial counters and at least the
// first initial thread (which is also highly updated)
//
UCHAR InitialOwnerCounts[4];
ERESOURCE_THREAD InitialOwnerThreads[4];
ULONG Spare1;
//
// The rest is what ever was left. The spinlock is in with
// a part of the stucture we normally don't touch in the
// hot paths (read or write)
//
ULONG ContentionCount;
USHORT NumberOfExclusiveWaiters;
USHORT NumberOfSharedWaiters;
KSEMAPHORE SharedWaiters;
KEVENT ExclusiveWaiters;
KSPIN_LOCK SpinLock;
USHORT CreatorBackTraceIndex;
USHORT Spare2;
} NTDDK_ERESOURCE;
typedef NTDDK_ERESOURCE *PNTDDK_ERESOURCE;
//
// These are routines that were unfortunately exported to ntddk.h
//
// They live in ntos\ex\DdkResrc.c
//
//
// NTKERNELAPI
// NTSTATUS
// ExInitializeResource(
// IN PNTDDK_ERESOURCE Resource
// );
//
// NTKERNELAPI
// BOOLEAN
// ExAcquireResourceExclusive(
// IN PNTDDK_ERESOURCE Resource,
// IN BOOLEAN Wait
// );
//
// NTKERNELAPI
// VOID
// ExReleaseResourceForThread(
// IN PNTDDK_ERESOURCE Resource,
// IN ERESOURCE_THREAD ResourceThreadId
// );
//
// NTKERNELAPI
// NTSTATUS
// ExDeleteResource (
// IN PNTDDK_ERESOURCE Resource
// );
//
//
// Macros to convert between handles and handle table indexes.
//
#define HANDLE_TO_INDEX(h) ((ULONG)(h))
#define INDEX_TO_HANDLE(i) ((HANDLE)(i))
//
// Define handle entry structure.
//
typedef struct _HANDLE_ENTRY {
union {
LIST_ENTRY ListEntry;
struct {
PVOID Object;
ULONG Attributes;
};
};
} HANDLE_ENTRY, *PHANDLE_ENTRY;
#define ExIsEntryFree(base, bound, p) ((p)->Object >= (PVOID)(base) && (p)->Object < (PVOID)(bound))
#define ExIsEntryUsed(base, bound, p) ((p)->Object < (PVOID)(base) || (p)->Object >= (PVOID)(bound))
//
// Define handle table descriptor structure.
//
struct _EPROCESS;
typedef union _HANDLE_SYNCH {
struct {
USHORT NumberOfSharedWaiters;
USHORT NumberOfExclusiveWaiters;
ULONG OwnerCount;
} u;
ULONGLONG Value;
}HANDLE_SYNCH, *PHANDLE_SYNCH;
typedef struct _HANDLE_TABLE {
HANDLE_SYNCH State;
KSPIN_LOCK SpinLock;
PHANDLE_ENTRY TableEntries;
PHANDLE_ENTRY TableBound;
ULONG HandleCount;
struct _EPROCESS *QuotaProcess;
HANDLE UniqueProcessId;
USHORT CountToGrowBy;
BOOLEAN LifoOrder;
UCHAR Spare1;
LIST_ENTRY ListEntry;
KEVENT ExclusiveWaiters;
KSEMAPHORE SharedWaiters;
} HANDLE_TABLE, *PHANDLE_TABLE;
//
// Routines for handle manipulation.
//
typedef
BOOLEAN
(*PEX_CHANGE_HANDLE_ROUTINE) (
IN OUT PHANDLE_ENTRY HandleEntry,
IN ULONG Parameter
);
NTKERNELAPI
BOOLEAN
ExChangeHandle(
IN PHANDLE_TABLE HandleTable,
IN HANDLE Handle,
IN PEX_CHANGE_HANDLE_ROUTINE ChangeRoutine,
IN ULONG Parameter
);
NTKERNELAPI
HANDLE
ExCreateHandle(
IN PHANDLE_TABLE HandleTable,
IN PHANDLE_ENTRY HandleEntry
);
NTKERNELAPI
PHANDLE_TABLE
ExCreateHandleTable(
IN struct _EPROCESS *Process OPTIONAL,
IN ULONG CountEntries,
IN ULONG CountToGrowBy
);
NTKERNELAPI
BOOLEAN
ExDestroyHandle(
IN PHANDLE_TABLE HandleTable,
IN HANDLE Handle,
IN BOOLEAN TableLocked
);
typedef VOID (*EX_DESTROY_HANDLE_ROUTINE)(
IN HANDLE Handle,
IN PHANDLE_ENTRY HandleEntry
);
NTKERNELAPI
VOID
ExDestroyHandleTable(
IN PHANDLE_TABLE HandleTable,
IN EX_DESTROY_HANDLE_ROUTINE DestroyHandleProcedure
);
NTKERNELAPI
VOID
ExRemoveHandleTable(
IN PHANDLE_TABLE HandleTable
);
typedef BOOLEAN (*EX_DUPLICATE_HANDLE_ROUTINE)(
IN struct _EPROCESS *Process OPTIONAL,
IN PHANDLE_ENTRY HandleEntry
);
NTKERNELAPI
PHANDLE_TABLE
ExDupHandleTable(
IN struct _EPROCESS *Process OPTIONAL,
IN PHANDLE_TABLE OldHandleTable,
IN EX_DUPLICATE_HANDLE_ROUTINE DupHandleProcedure OPTIONAL
);
typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)(
IN PHANDLE_ENTRY HandleEntry,
IN HANDLE Handle,
IN PVOID EnumParameter
);
NTKERNELAPI
BOOLEAN
ExEnumHandleTable(
IN PHANDLE_TABLE HandleTable,
IN EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
IN PVOID EnumParameter,
OUT PHANDLE Handle OPTIONAL
);
NTKERNELAPI
VOID
FASTCALL
ExAcquireHandleTableExclusive (
IN PHANDLE_TABLE HandleTable
);
NTKERNELAPI
VOID
FASTCALL
ExAcquireHandleTableShared (
IN PHANDLE_TABLE HandleTable
);
NTKERNELAPI
VOID
FASTCALL
ExReleaseHandleTableExclusive (
IN PHANDLE_TABLE HandleTable
);
NTKERNELAPI
VOID
FASTCALL
ExReleaseHandleTableShared (
IN PHANDLE_TABLE HandleTable
);
#define ExLockHandleTableExclusive(_T) \
KeEnterCriticalRegion(); \
ExAcquireHandleTableExclusive(_T)
#define ExLockHandleTableShared(_T) \
KeEnterCriticalRegion(); \
ExAcquireHandleTableShared(_T)
#define ExUnlockHandleTableExclusive(_T) \
ExReleaseHandleTableExclusive(_T); \
KeLeaveCriticalRegion()
#define ExUnlockHandleTableShared(_T) \
ExReleaseHandleTableShared(_T); \
KeLeaveCriticalRegion()
NTKERNELAPI
PHANDLE_ENTRY
ExMapHandleToPointer(
IN PHANDLE_TABLE HandleTable,
IN HANDLE Handle,
IN BOOLEAN Shared
);
NTKERNELAPI
VOID
ExInitializeHandleTablePackage(
VOID
);
#define ExSetHandleTableOwner(t, id) (t)->UniqueProcessId = (id)
#define ExSetHandleTableOrder(t, order) (t)->LifoOrder = (order)
typedef NTSTATUS (*PEX_SNAPSHOT_HANDLE_ENTRY)(
IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo,
IN HANDLE UniqueProcessId,
IN PHANDLE_ENTRY HandleEntry,
IN HANDLE Handle,
IN ULONG Length,
IN OUT PULONG RequiredLength
);
NTKERNELAPI
NTSTATUS
ExSnapShotHandleTables(
IN PEX_SNAPSHOT_HANDLE_ENTRY SnapShotHandleEntry,
IN OUT PSYSTEM_HANDLE_INFORMATION HandleInformation,
IN ULONG Length,
IN OUT PULONG RequiredLength
);
//
// Locally Unique Identifier Services
//
NTKERNELAPI
BOOLEAN
ExLuidInitialization (
VOID
);
//
// VOID
// ExAllocateLocallyUniqueId (
// PLUID Luid
// )
//
//*++
//
// Routine Description:
//
// This function returns an LUID value that is unique since the system
// was last rebooted. It is unique only on the system it is generated on
// and not network wide.
//
// N.B. A LUID is a 64-bit value and for all practical purposes will
// never carry in the lifetime of a single boot of the system.
// At an increment rate of 1ns, the value would carry to zero in
// approximately 126 years.
//
// Arguments:
//
// Luid - Supplies a pointer to a variable that receives the allocated
// locally uniquie Id.
//
// Return Value:
//
// The allocated LUID value.
//
// --*/
extern LARGE_INTEGER ExpLuid;
extern LARGE_INTEGER ExpLuidIncrement;
extern KSPIN_LOCK ExpLuidLock;
#define ExAllocateLocallyUniqueId(Luid) \
{ \
LARGE_INTEGER _TempLi; \
\
_TempLi = ExInterlockedExchangeAddLargeInteger(&ExpLuid, \
ExpLuidIncrement, \
&ExpLuidLock); \
(Luid)->LowPart = _TempLi.LowPart; \
(Luid)->HighPart = _TempLi.HighPart; \
}
// begin_ntddk begin_ntifs
//
// Get previous mode
//
NTKERNELAPI
KPROCESSOR_MODE
ExGetPreviousMode(
VOID
);
// end_ntddk end_ntifs
//
// Raise exception from kernel mode.
//
NTKERNELAPI
VOID
NTAPI
ExRaiseException (
PEXCEPTION_RECORD ExceptionRecord
);
// begin_ntddk begin_ntifs
//
// Raise status from kernel mode.
//
NTKERNELAPI
VOID
NTAPI
ExRaiseStatus (
IN NTSTATUS Status
);
NTKERNELAPI
VOID
ExRaiseDatatypeMisalignment (
VOID
);
NTKERNELAPI
VOID
ExRaiseAccessViolation (
VOID
);
// end_ntddk end_ntifs
extern BOOLEAN ExReadyForErrors;
NTKERNELAPI
NTSTATUS
ExRaiseHardError(
IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN ULONG UnicodeStringParameterMask,
IN PULONG Parameters,
IN ULONG ValidResponseOptions,
OUT PULONG Response
);
int
ExSystemExceptionFilter(
VOID
);
//
// The following are global counters used by the EX component to indicate
// the amount of EventPair transactions being performed in the system.
//
extern ULONG EvPrSetHigh;
extern ULONG EvPrSetLow;
//
// Debug event logging facility
//
#define EX_DEBUG_LOG_FORMAT_NONE (UCHAR)0
#define EX_DEBUG_LOG_FORMAT_ULONG (UCHAR)1
#define EX_DEBUG_LOG_FORMAT_PSZ (UCHAR)2
#define EX_DEBUG_LOG_FORMAT_PWSZ (UCHAR)3
#define EX_DEBUG_LOG_FORMAT_STRING (UCHAR)4
#define EX_DEBUG_LOG_FORMAT_USTRING (UCHAR)5
#define EX_DEBUG_LOG_FORMAT_OBJECT (UCHAR)6
#define EX_DEBUG_LOG_FORMAT_HANDLE (UCHAR)7
#define EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES 4
#define EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES 4
typedef struct _EX_DEBUG_LOG_TAG {
UCHAR Format[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ];
PCHAR Name;
} EX_DEBUG_LOG_TAG, *PEX_DEBUG_LOG_TAG;
typedef struct _EX_DEBUG_LOG_EVENT {
USHORT ThreadId;
USHORT ProcessId;
ULONG Time : 24;
ULONG Tag : 8;
ULONG BackTrace[ EX_DEBUG_LOG_NUMBER_OF_BACK_TRACES ];
ULONG Data[ EX_DEBUG_LOG_NUMBER_OF_DATA_VALUES ];
} EX_DEBUG_LOG_EVENT, *PEX_DEBUG_LOG_EVENT;
typedef struct _EX_DEBUG_LOG {
KSPIN_LOCK Lock;
ULONG NumberOfTags;
ULONG MaximumNumberOfTags;
PEX_DEBUG_LOG_TAG Tags;
ULONG CountOfEventsLogged;
PEX_DEBUG_LOG_EVENT First;
PEX_DEBUG_LOG_EVENT Last;
PEX_DEBUG_LOG_EVENT Next;
} EX_DEBUG_LOG, *PEX_DEBUG_LOG;
NTKERNELAPI
PEX_DEBUG_LOG
ExCreateDebugLog(
IN UCHAR MaximumNumberOfTags,
IN ULONG MaximumNumberOfEvents
);
NTKERNELAPI
UCHAR
ExCreateDebugLogTag(
IN PEX_DEBUG_LOG Log,
IN PCHAR Name,
IN UCHAR Format1,
IN UCHAR Format2,
IN UCHAR Format3,
IN UCHAR Format4
);
NTKERNELAPI
VOID
ExDebugLogEvent(
IN PEX_DEBUG_LOG Log,
IN UCHAR Tag,
IN ULONG Data1,
IN ULONG Data2,
IN ULONG Data3,
IN ULONG Data4
);
NTKERNELAPI
BOOLEAN
ExRefreshTimeZoneInformation(
IN PLARGE_INTEGER CurrentUniversalTime
);
// begin_ntddk begin_ntifs
//
// Subtract time zone bias from system time to get local time.
//
NTKERNELAPI
VOID
ExSystemTimeToLocalTime (
IN PLARGE_INTEGER SystemTime,
OUT PLARGE_INTEGER LocalTime
);
//
// Add time zone bias to local time to get system time.
//
NTKERNELAPI
VOID
ExLocalTimeToSystemTime (
IN PLARGE_INTEGER LocalTime,
OUT PLARGE_INTEGER SystemTime
);
// end_ntddk end_ntifs
NTKERNELAPI
VOID
ExInitializeTimeRefresh(
VOID
);
// begin_ntddk begin_nthal begin_ntminiport
NTKERNELAPI
VOID
ExPostSystemEvent(
IN SYSTEM_EVENT_ID EventID,
IN PVOID EventData OPTIONAL,
IN ULONG EventDataLength
);
// end_ntddk end_nthal end_ntminiport
// begin_ntddk begin_ntifs begin_nthal begin_ntminiport
//
// Define the type for Callback function.
//
typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT;
typedef VOID (*PCALLBACK_FUNCTION ) (
IN PVOID CallbackContext,
IN PVOID Argument1,
IN PVOID Argument2
);
NTKERNELAPI
NTSTATUS
ExCreateCallback (
OUT PCALLBACK_OBJECT *CallbackObject,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN BOOLEAN Create,
IN BOOLEAN AllowMultipleCallbacks
);
NTKERNELAPI
PVOID
ExRegisterCallback (
IN PCALLBACK_OBJECT CallbackObject,
IN PCALLBACK_FUNCTION CallbackFunction,
IN PVOID CallbackContext
);
NTKERNELAPI
VOID
ExUnregisterCallback (
IN PVOID CallbackRegistration
);
NTKERNELAPI
VOID
ExNotifyCallback (
IN PVOID CallbackObject,
IN PVOID Argument1,
IN PVOID Argument2
);
// end_ntddk end_ntifs end_nthal end_ntminiport
//
// The current bias from GMT to LocalTime
//
extern LARGE_INTEGER ExpTimeZoneBias;
extern LONG ExpLastTimeZoneBias;
extern LONG ExpAltTimeZoneBias;
extern ULONG ExpCurrentTimeZoneId;
extern ULONG ExpRealTimeIsUniversal;
extern ULONG ExCriticalWorkerThreads;
extern ULONG ExDelayedWorkerThreads;
extern ULONG ExpTickCountMultiplier;
//
// The lock handle for PAGELK section, initialized in init\init.c
//
extern PVOID ExPageLockHandle;
#ifdef _PNP_POWER_
//
// Global executive callbacks
//
extern PCALLBACK_OBJECT ExCbSetSystemInformation;
extern PCALLBACK_OBJECT ExCbSetSystemTime;
extern PCALLBACK_OBJECT ExCbSuspendHibernateSystem;
#endif // _PNP_POWER_
typedef
PVOID
(*PKWIN32_GLOBALATOMTABLE_CALLOUT) ( void );
extern PKWIN32_GLOBALATOMTABLE_CALLOUT ExGlobalAtomTableCallout;
#if DBG
PRTL_EVENT_ID_INFO
ExDefineEventId(
IN PRTL_EVENT_ID_INFO EventId
);
#endif // DBG
#endif /* _EX_ */