2729 lines
60 KiB
C
2729 lines
60 KiB
C
/*++ 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_ */
|