Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
19046 lines (15496 sloc) 533 KB
/*++ BUILD Version: 0185 // Increment this if a change has global effects
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
ntddk.h
Abstract:
This module defines the NT types, constants, and functions that are
exposed to device drivers.
Revision History:
--*/
#ifndef _NTDDK_
#define _NTDDK_
#if !defined(_NTHAL_) && !defined(_NTIFS_)
#define _NTDDK_INCLUDED_
#define _DDK_DRIVER_
#endif
#ifndef RC_INVOKED
#if _MSC_VER < 1300
#error Compiler version not supported by Windows DDK
#endif
#endif // RC_INVOKED
#define NT_INCLUDED
#define _CTYPE_DISABLE_MACROS
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable:4115) // named type definition in parentheses
#pragma warning(disable:4201) // nameless struct/union
#pragma warning(disable:4214) // bit field types other than int
#pragma warning(disable:4625) // copy constructor was implicitly defined as deleted
#pragma warning(disable:4626) // assignment operator was implicitly defined as deleted
#pragma warning(disable:4668) // #if not_defined treated as #if 0
#pragma warning(disable:4820) // padding added
#include <wdm.h>
#include <excpt.h>
#include <ntdef.h>
#include <ntstatus.h>
#include <bugcodes.h>
#include <ntiologc.h>
#ifdef __cplusplus
extern "C" {
#endif
//
// Define types that are not exported.
//
typedef struct _BUS_HANDLER *PBUS_HANDLER;
typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT;
typedef struct _DEVICE_HANDLER_OBJECT *PDEVICE_HANDLER_OBJECT;
#if defined(_NTHAL_INCLUDED_)
typedef struct _KPROCESS *PEPROCESS;
typedef struct _ETHREAD *PETHREAD;
typedef struct _KAFFINITY_EX *PKAFFINITY_EX;
#elif defined(_NTIFS_INCLUDED_)
typedef struct _KPROCESS *PEPROCESS;
typedef struct _KTHREAD *PETHREAD;
#else
typedef struct _EPROCESS *PEPROCESS;
typedef struct _ETHREAD *PETHREAD;
#endif
typedef struct _EJOB *PEJOB;
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
typedef struct _EJOB *PESILO;
typedef struct _SILO_MONITOR *PSILO_MONITOR;
#endif
typedef struct _IO_TIMER *PIO_TIMER;
typedef struct _KINTERRUPT *PKINTERRUPT;
typedef struct _KTHREAD *PKTHREAD, *PRKTHREAD;
typedef struct _OBJECT_TYPE *POBJECT_TYPE;
typedef struct _PEB *PPEB;
typedef struct _IMAGE_NT_HEADERS *PIMAGE_NT_HEADERS32;
typedef struct _IMAGE_NT_HEADERS64 *PIMAGE_NT_HEADERS64;
#ifdef _WIN64
typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS;
#else
typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS;
#endif
#define PsGetCurrentProcess IoGetCurrentProcess
#if (NTDDI_VERSION >= NTDDI_VISTA)
#if defined(_X86_) || defined(_AMD64_)
extern NTSYSAPI volatile CCHAR KeNumberProcessors;
#else
extern NTSYSAPI CCHAR KeNumberProcessors;
#endif
#elif (NTDDI_VERSION >= NTDDI_WINXP)
extern NTSYSAPI CCHAR KeNumberProcessors;
#else
extern PCCHAR KeNumberProcessors;
#endif
extern POBJECT_TYPE *PsProcessType;
extern POBJECT_TYPE *PsThreadType;
extern POBJECT_TYPE *PsJobType;
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
extern POBJECT_TYPE *PsSiloContextPagedType;
extern POBJECT_TYPE *PsSiloContextNonPagedType;
#endif
#include <mce.h>
#ifndef FAR
#define FAR
#endif
#ifdef _X86_
//
// Some intrinsics have a redundant __cdecl calling-convention specifier when
// not compiled with /clr:pure.
//
#if defined(_M_CEE_PURE)
#define CDECL_NON_WVMPURE
#else
#define CDECL_NON_WVMPURE __cdecl
#endif
//
// Disable these two pragmas that evaluate to "sti" "cli" on x86 so that driver
// writers to not leave them inadvertantly in their code.
//
#if !defined(MIDL_PASS)
#if !defined(RC_INVOKED)
#if _MSC_VER >= 1200
#pragma warning(push)
#endif // _MSC_VER >= 1200
//#pragma warning(disable:4164) // disable C4164 warning so that apps that
// build with /Od don't get weird errors !
#if _MSC_VER >= 1200
#pragma warning( pop )
#else
#pragma warning( default:4164 ) // reenable C4164 warning
#endif // _MSC_VER >= 1200
#endif // !defined(MIDL_PASS)
#endif // !defined(RC_INVOKED)
//
// Size of kernel mode stack.
//
#define KERNEL_STACK_SIZE 12288
//
// Define size of large kernel mode stack for callbacks.
//
#define KERNEL_LARGE_STACK_SIZE 61440
//
// Define number of pages to initialize in a large kernel stack.
//
#define KERNEL_LARGE_STACK_COMMIT 12288
#ifdef _X86_
#if !defined(MIDL_PASS) && defined(_M_IX86)
#if !defined(_M_CEE_PURE) && !defined(_M_HYBRID_X86_ARM64)
#pragma prefast(push)
#pragma warning(push)
#pragma prefast(disable: 6001 28113, "The barrier variable is accessed only to create a side effect.")
#pragma warning(disable: 4793)
FORCEINLINE
VOID
MemoryBarrier (
VOID
)
{
LONG Barrier;
InterlockedOr(&Barrier, 0);
return;
}
#pragma warning(pop)
#pragma prefast(pop)
#endif /* !_M_CEE_PURE || !_M_HYBRID_X86_ARM64*/
#if !defined(_M_HYBRID_X86_ARM64)
//
// Define constants for use with _mm_prefetch.
//
#define _MM_HINT_T0 1
#define _MM_HINT_T1 2
#define _MM_HINT_T2 3
#define _MM_HINT_NTA 0
VOID
_mm_prefetch (
_In_ CHAR CONST *a,
_In_ int sel
);
#pragma intrinsic(_mm_prefetch)
//
// PreFetchCacheLine level defines.
//
#define PF_TEMPORAL_LEVEL_1 _MM_HINT_T0
#define PF_TEMPORAL_LEVEL_2 _MM_HINT_T1
#define PF_TEMPORAL_LEVEL_3 _MM_HINT_T2
#define PF_NON_TEMPORAL_LEVEL_ALL _MM_HINT_NTA
#define PreFetchCacheLine(l, a) _mm_prefetch((CHAR CONST *) a, l)
#define PrefetchForWrite(p)
#define ReadForWriteAccess(p) (*(p))
#if !defined(_MANAGED)
//
// Define function to read the value of a performance counter.
//
#define ReadPMC __readpmc
ULONG64
__readpmc (
_In_ ULONG Counter
);
#pragma intrinsic(__readpmc)
//
// Define function to read the value of the time stamp counter
//
#define ReadTimeStampCounter() __rdtsc()
ULONG64
__rdtsc (
VOID
);
#pragma intrinsic(__rdtsc)
#endif // !defined(_MANAGED)
#endif // !defined(_M_HYBRID_X86_ARM64)
#endif // !defined(MIDL_PASS) && defined(_M_IX86)
//
// Define the size of the 80387 save area, which is in the context frame.
//
#define SIZE_OF_80387_REGISTERS 80
//
// The following flags control the contents of the CONTEXT structure.
//
#if !defined(RC_INVOKED)
#define CONTEXT_i386 0x00010000L // this assumes that i386 and
#define CONTEXT_i486 0x00010000L // i486 have identical context records
#define CONTEXT_CONTROL (CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP
#define CONTEXT_INTEGER (CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI
#define CONTEXT_SEGMENTS (CONTEXT_i386 | 0x00000004L) // DS, ES, FS, GS
#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 0x00000008L) // 387 state
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x00000010L) // DB 0-3,6,7
#define CONTEXT_EXTENDED_REGISTERS (CONTEXT_i386 | 0x00000020L) // cpu specific extensions
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER |\
CONTEXT_SEGMENTS)
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | \
CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | \
CONTEXT_EXTENDED_REGISTERS)
#define CONTEXT_XSTATE (CONTEXT_i386 | 0x00000040L)
#define CONTEXT_EXCEPTION_ACTIVE 0x08000000L
#define CONTEXT_SERVICE_ACTIVE 0x10000000L
#define CONTEXT_EXCEPTION_REQUEST 0x40000000L
#define CONTEXT_EXCEPTION_REPORTING 0x80000000L
#endif // !defined(RC_INVOKED)
typedef struct _FLOATING_SAVE_AREA {
ULONG ControlWord;
ULONG StatusWord;
ULONG TagWord;
ULONG ErrorOffset;
ULONG ErrorSelector;
ULONG DataOffset;
ULONG DataSelector;
UCHAR RegisterArea[SIZE_OF_80387_REGISTERS];
ULONG Spare0;
} FLOATING_SAVE_AREA;
typedef FLOATING_SAVE_AREA *PFLOATING_SAVE_AREA;
#include "pshpack4.h"
//
// Context Frame
//
// This frame has a several purposes: 1) it is used as an argument to
// NtContinue, 2) is is used to constuct a call frame for APC delivery,
// and 3) it is used in the user level thread creation routines.
//
// The layout of the record conforms to a standard call frame.
//
typedef struct _CONTEXT {
//
// The flags values within this flag control the contents of
// a CONTEXT record.
//
// If the context record is used as an input parameter, then
// for each portion of the context record controlled by a flag
// whose value is set, it is assumed that that portion of the
// context record contains valid context. If the context record
// is being used to modify a threads context, then only that
// portion of the threads context will be modified.
//
// If the context record is used as an IN OUT parameter to capture
// the context of a thread, then only those portions of the thread's
// context corresponding to set flags will be returned.
//
// The context record is never used as an OUT only parameter.
//
ULONG ContextFlags;
//
// This section is specified/returned if CONTEXT_DEBUG_REGISTERS is
// set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT
// included in CONTEXT_FULL.
//
ULONG Dr0;
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_FLOATING_POINT.
//
FLOATING_SAVE_AREA FloatSave;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_SEGMENTS.
//
ULONG SegGs;
ULONG SegFs;
ULONG SegEs;
ULONG SegDs;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_INTEGER.
//
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Edx;
ULONG Ecx;
ULONG Eax;
//
// This section is specified/returned if the
// ContextFlags word contians the flag CONTEXT_CONTROL.
//
ULONG Ebp;
ULONG Eip;
ULONG SegCs; // MUST BE SANITIZED
ULONG EFlags; // MUST BE SANITIZED
ULONG Esp;
ULONG SegSs;
//
// This section is specified/returned if the ContextFlags word
// contains the flag CONTEXT_EXTENDED_REGISTERS.
// The format and contexts are processor specific
//
UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
} CONTEXT;
typedef CONTEXT *PCONTEXT;
#include "poppack.h"
#endif //_X86_
#endif // _X86_
#ifdef _AMD64_
//
// Size of kernel mode stack.
//
#define KERNEL_STACK_SIZE 0x6000
//
// Define size of large kernel mode stack for callbacks.
//
#define KERNEL_LARGE_STACK_SIZE 0x12000
//
// Define number of pages to initialize in a large kernel stack.
//
#define KERNEL_LARGE_STACK_COMMIT KERNEL_STACK_SIZE
//
// Define the size of the stack used for processing an MCA exception.
//
#define KERNEL_MCA_EXCEPTION_STACK_SIZE 0x2000
//
// The following values specify the type of access in the first parameter
// of the exception record whan the exception code specifies an access
// violation.
//
#define EXCEPTION_READ_FAULT 0 // exception caused by a read
#define EXCEPTION_WRITE_FAULT 1 // exception caused by a write
#define EXCEPTION_EXECUTE_FAULT 8 // exception caused by an instruction fetch
//
// The following flags control the contents of the CONTEXT structure.
//
#if !defined(RC_INVOKED)
#define CONTEXT_AMD64 0x00100000L
#define CONTEXT_CONTROL (CONTEXT_AMD64 | 0x00000001L)
#define CONTEXT_INTEGER (CONTEXT_AMD64 | 0x00000002L)
#define CONTEXT_SEGMENTS (CONTEXT_AMD64 | 0x00000004L)
#define CONTEXT_FLOATING_POINT (CONTEXT_AMD64 | 0x00000008L)
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x00000010L)
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | \
CONTEXT_FLOATING_POINT)
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | \
CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | \
CONTEXT_DEBUG_REGISTERS)
#define CONTEXT_XSTATE (CONTEXT_AMD64 | 0x00000040L)
#if defined(XBOX_SYSTEMOS)
#define CONTEXT_KERNEL_DEBUGGER 0x04000000L
#endif
#define CONTEXT_EXCEPTION_ACTIVE 0x08000000L
#define CONTEXT_SERVICE_ACTIVE 0x10000000L
#define CONTEXT_EXCEPTION_REQUEST 0x40000000L
#define CONTEXT_EXCEPTION_REPORTING 0x80000000L
#endif // !defined(RC_INVOKED)
//
// Define initial MxCsr and FpCsr control.
//
#define INITIAL_MXCSR 0x1f80 // initial MXCSR value
#define INITIAL_FPCSR 0x027f // initial FPCSR value
//
// Context Frame
//
// This frame has a several purposes: 1) it is used as an argument to
// NtContinue, 2) it is used to constuct a call frame for APC delivery,
// and 3) it is used in the user level thread creation routines.
//
//
// The flags field within this record controls the contents of a CONTEXT
// record.
//
// If the context record is used as an input parameter, then for each
// portion of the context record controlled by a flag whose value is
// set, it is assumed that that portion of the context record contains
// valid context. If the context record is being used to modify a threads
// context, then only that portion of the threads context is modified.
//
// If the context record is used as an output parameter to capture the
// context of a thread, then only those portions of the thread's context
// corresponding to set flags will be returned.
//
// CONTEXT_CONTROL specifies SegSs, Rsp, SegCs, Rip, and EFlags.
//
// CONTEXT_INTEGER specifies Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, and R8-R15.
//
// CONTEXT_SEGMENTS specifies SegDs, SegEs, SegFs, and SegGs.
//
// CONTEXT_FLOATING_POINT specifies Xmm0-Xmm15.
//
// CONTEXT_DEBUG_REGISTERS specifies Dr0-Dr3 and Dr6-Dr7.
//
typedef struct DECLSPEC_ALIGN(16) _CONTEXT {
//
// Register parameter home addresses.
//
// N.B. These fields are for convience - they could be used to extend the
// context record in the future.
//
ULONG64 P1Home;
ULONG64 P2Home;
ULONG64 P3Home;
ULONG64 P4Home;
ULONG64 P5Home;
ULONG64 P6Home;
//
// Control flags.
//
ULONG ContextFlags;
ULONG MxCsr;
//
// Segment Registers and processor flags.
//
USHORT SegCs;
USHORT SegDs;
USHORT SegEs;
USHORT SegFs;
USHORT SegGs;
USHORT SegSs;
ULONG EFlags;
//
// Debug registers
//
ULONG64 Dr0;
ULONG64 Dr1;
ULONG64 Dr2;
ULONG64 Dr3;
ULONG64 Dr6;
ULONG64 Dr7;
//
// Integer registers.
//
ULONG64 Rax;
ULONG64 Rcx;
ULONG64 Rdx;
ULONG64 Rbx;
ULONG64 Rsp;
ULONG64 Rbp;
ULONG64 Rsi;
ULONG64 Rdi;
ULONG64 R8;
ULONG64 R9;
ULONG64 R10;
ULONG64 R11;
ULONG64 R12;
ULONG64 R13;
ULONG64 R14;
ULONG64 R15;
//
// Program counter.
//
ULONG64 Rip;
//
// Floating point state.
//
union {
XMM_SAVE_AREA32 FltSave;
struct {
M128A Header[2];
M128A Legacy[8];
M128A Xmm0;
M128A Xmm1;
M128A Xmm2;
M128A Xmm3;
M128A Xmm4;
M128A Xmm5;
M128A Xmm6;
M128A Xmm7;
M128A Xmm8;
M128A Xmm9;
M128A Xmm10;
M128A Xmm11;
M128A Xmm12;
M128A Xmm13;
M128A Xmm14;
M128A Xmm15;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
//
// Vector registers.
//
M128A VectorRegister[26];
ULONG64 VectorControl;
//
// Special debug control registers.
//
ULONG64 DebugControl;
ULONG64 LastBranchToRip;
ULONG64 LastBranchFromRip;
ULONG64 LastExceptionToRip;
ULONG64 LastExceptionFromRip;
} CONTEXT, *PCONTEXT;
#endif // _AMD64_
#ifdef _ARM_
//
// Size of kernel mode stack.
//
#define KERNEL_STACK_SIZE 0x3000
//
// Define size of large kernel mode stack for callbacks.
//
#define KERNEL_LARGE_STACK_SIZE 0xF000
//
// Define number of pages to initialize in a large kernel stack.
//
#define KERNEL_LARGE_STACK_COMMIT KERNEL_STACK_SIZE
//
// Define the size of the stack used for processing an MCA exception.
//
#define KERNEL_MCA_EXCEPTION_STACK_SIZE 0x2000
//
// The following values specify the type of access in the first parameter
// of the exception record whan the exception code specifies an access
// violation.
//
#define EXCEPTION_READ_FAULT 0 // exception caused by a read
#define EXCEPTION_WRITE_FAULT 1 // exception caused by a write
#define EXCEPTION_EXECUTE_FAULT 8 // exception caused by an instruction fetch
//
// The following flags control the contents of the CONTEXT structure.
//
#if !defined(RC_INVOKED)
#define CONTEXT_ARM 0x00200000L
#define CONTEXT_CONTROL (CONTEXT_ARM | 0x1L)
#define CONTEXT_INTEGER (CONTEXT_ARM | 0x2L)
#define CONTEXT_FLOATING_POINT (CONTEXT_ARM | 0x4L)
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM | 0x8L)
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS)
#define CONTEXT_EXCEPTION_ACTIVE 0x8000000L
#define CONTEXT_SERVICE_ACTIVE 0x10000000L
#define CONTEXT_EXCEPTION_REQUEST 0x40000000L
#define CONTEXT_EXCEPTION_REPORTING 0x80000000L
//
// This flag is set by the unwinder if it has unwound to a call
// site, and cleared whenever it unwinds through a trap frame.
// It is used by language-specific exception handlers to help
// differentiate exception scopes during dispatching.
//
#define CONTEXT_UNWOUND_TO_CALL 0x20000000
#endif // !defined(RC_INVOKED)
//
// Define initial Cpsr/Fpscr value
//
#define INITIAL_CPSR 0x10
#define INITIAL_FPSCR 0
//
// Specify the number of breakpoints and watchpoints that the OS
// will track. Architecturally, ARM supports up to 16. In practice,
// however, almost no one implements more than 4 of each.
//
#define ARM_MAX_BREAKPOINTS 8
#define ARM_MAX_WATCHPOINTS 1
//
// Context Frame
//
// This frame has a several purposes: 1) it is used as an argument to
// NtContinue, 2) it is used to constuct a call frame for APC delivery,
// and 3) it is used in the user level thread creation routines.
//
//
// The flags field within this record controls the contents of a CONTEXT
// record.
//
// If the context record is used as an input parameter, then for each
// portion of the context record controlled by a flag whose value is
// set, it is assumed that that portion of the context record contains
// valid context. If the context record is being used to modify a threads
// context, then only that portion of the threads context is modified.
//
// If the context record is used as an output parameter to capture the
// context of a thread, then only those portions of the thread's context
// corresponding to set flags will be returned.
//
// CONTEXT_CONTROL specifies Sp, Lr, Pc, and Cpsr
//
// CONTEXT_INTEGER specifies R0-R12
//
// CONTEXT_FLOATING_POINT specifies Q0-Q15 / D0-D31 / S0-S31
//
// CONTEXT_DEBUG_REGISTERS specifies up to 16 of DBGBVR, DBGBCR, DBGWVR,
// DBGWCR.
//
typedef struct _NEON128 {
ULONGLONG Low;
LONGLONG High;
} NEON128, *PNEON128;
typedef struct DECLSPEC_ALIGN(8) _CONTEXT {
//
// Control flags.
//
ULONG ContextFlags;
//
// Integer registers
//
ULONG R0;
ULONG R1;
ULONG R2;
ULONG R3;
ULONG R4;
ULONG R5;
ULONG R6;
ULONG R7;
ULONG R8;
ULONG R9;
ULONG R10;
ULONG R11;
ULONG R12;
//
// Control Registers
//
ULONG Sp;
ULONG Lr;
ULONG Pc;
ULONG Cpsr;
//
// Floating Point/NEON Registers
//
ULONG Fpscr;
ULONG Padding;
union {
NEON128 Q[16];
ULONGLONG D[32];
ULONG S[32];
} DUMMYUNIONNAME;
//
// Debug registers
//
ULONG Bvr[ARM_MAX_BREAKPOINTS];
ULONG Bcr[ARM_MAX_BREAKPOINTS];
ULONG Wvr[ARM_MAX_WATCHPOINTS];
ULONG Wcr[ARM_MAX_WATCHPOINTS];
ULONG Padding2[2];
} CONTEXT, *PCONTEXT;
#endif // _ARM_
#if defined(_ARM64_) || defined(_CHPE_X86_ARM64_)
#if defined(_ARM64_)
//
// Size of kernel mode stack.
//
// ARM64_WORKITEM: temporally bump up the kernel stack size until optimized build is ready.
#define KERNEL_STACK_SIZE 0x8000
//
// Define size of large kernel mode stack for callbacks.
//
#define KERNEL_LARGE_STACK_SIZE 0x12000
//
// Define number of pages to initialize in a large kernel stack.
//
#define KERNEL_LARGE_STACK_COMMIT KERNEL_STACK_SIZE
//
// Define the size of the stack used for processing an MCA exception.
//
#define KERNEL_MCA_EXCEPTION_STACK_SIZE 0x2000
#endif // defined(_ARM64_)
//
// The following values specify the type of access in the first parameter
// of the exception record whan the exception code specifies an access
// violation.
//
#define EXCEPTION_READ_FAULT 0 // exception caused by a read
#define EXCEPTION_WRITE_FAULT 1 // exception caused by a write
#define EXCEPTION_EXECUTE_FAULT 8 // exception caused by an instruction fetch
//
// Define initial Cpsr/Fpscr value
//
#define INITIAL_CPSR 0x10
#define INITIAL_FPSCR 0
#endif // defined(_ARM64_) || defined(_CHPE_X86_ARM64_)
//
// The following flags control the contents of the CONTEXT structure.
//
#if !defined(RC_INVOKED)
#define CONTEXT_ARM64 0x00400000L
#define CONTEXT_ARM64_CONTROL (CONTEXT_ARM64 | 0x1L)
#define CONTEXT_ARM64_INTEGER (CONTEXT_ARM64 | 0x2L)
#define CONTEXT_ARM64_FLOATING_POINT (CONTEXT_ARM64 | 0x4L)
#define CONTEXT_ARM64_DEBUG_REGISTERS (CONTEXT_ARM64 | 0x8L)
#define CONTEXT_ARM64_X18 (CONTEXT_ARM64 | 0x10L)
//
// CONTEXT_ARM64_X18 is not part of CONTEXT_ARM64_FULL because in NT user-mode
// threads, x18 contains a pointer to the TEB and should generally not be set
// without intending to.
//
#define CONTEXT_ARM64_FULL (CONTEXT_ARM64_CONTROL | CONTEXT_ARM64_INTEGER | CONTEXT_ARM64_FLOATING_POINT)
#define CONTEXT_ARM64_ALL (CONTEXT_ARM64_CONTROL | CONTEXT_ARM64_INTEGER | CONTEXT_ARM64_FLOATING_POINT | CONTEXT_ARM64_DEBUG_REGISTERS | CONTEXT_ARM64_X18)
#if defined(_ARM64_)
#define CONTEXT_CONTROL CONTEXT_ARM64_CONTROL
#define CONTEXT_INTEGER CONTEXT_ARM64_INTEGER
#define CONTEXT_FLOATING_POINT CONTEXT_ARM64_FLOATING_POINT
#define CONTEXT_DEBUG_REGISTERS CONTEXT_ARM64_DEBUG_REGISTERS
#define CONTEXT_FULL CONTEXT_ARM64_FULL
#define CONTEXT_ALL CONTEXT_ARM64_ALL
#define CONTEXT_EXCEPTION_ACTIVE 0x08000000L
#define CONTEXT_SERVICE_ACTIVE 0x10000000L
#define CONTEXT_EXCEPTION_REQUEST 0x40000000L
#define CONTEXT_EXCEPTION_REPORTING 0x80000000L
#endif
#if defined(_ARM64_) || defined(_CHPE_X86_ARM64_) || defined(_X86_)
//
// This flag is set by the unwinder if it has unwound to a call
// site, and cleared whenever it unwinds through a trap frame.
// It is used by language-specific exception handlers to help
// differentiate exception scopes during dispatching.
//
#define CONTEXT_UNWOUND_TO_CALL 0x20000000
#define CONTEXT_RET_TO_GUEST 0x04000000
#endif
#endif // !defined(RC_INVOKED)
//
// Specify the number of breakpoints and watchpoints that the OS
// will track. Architecturally, ARM64 supports up to 16. In practice,
// however, almost no one implements more than 4 of each.
//
#define ARM64_MAX_BREAKPOINTS 8
#define ARM64_MAX_WATCHPOINTS 2
//
// Context Frame
//
// This frame has a several purposes: 1) it is used as an argument to
// NtContinue, 2) it is used to constuct a call frame for APC delivery,
// and 3) it is used in the user level thread creation routines.
//
//
// The flags field within this record controls the contents of a CONTEXT
// record.
//
// If the context record is used as an input parameter, then for each
// portion of the context record controlled by a flag whose value is
// set, it is assumed that that portion of the context record contains
// valid context. If the context record is being used to modify a threads
// context, then only that portion of the threads context is modified.
//
// If the context record is used as an output parameter to capture the
// context of a thread, then only those portions of the thread's context
// corresponding to set flags will be returned.
//
// CONTEXT_CONTROL specifies FP, LR, SP, PC, and CPSR
//
// CONTEXT_INTEGER specifies X0-X28
//
// CONTEXT_FLOATING_POINT specifies Fpcr, Fpsr and Q0-Q31 / D0-D31 / S0-S31
//
// CONTEXT_DEBUG_REGISTERS specifies up to 16 of DBGBVR, DBGBCR, DBGWVR,
// DBGWCR.
//
typedef union _ARM64_NT_NEON128 {
struct {
ULONGLONG Low;
LONGLONG High;
} DUMMYSTRUCTNAME;
double D[2];
float S[4];
USHORT H[8];
UCHAR B[16];
} ARM64_NT_NEON128, *PARM64_NT_NEON128;
#if defined(_ARM64_)
typedef ARM64_NT_NEON128 NEON128, *PNEON128;
#endif
#if defined(_ARM64_)
#pragma push_macro("_ARM64_NT_CONTEXT")
#undef _ARM64_NT_CONTEXT
#define _ARM64_NT_CONTEXT _CONTEXT
#pragma push_macro("ARM64_NT_NEON128")
#undef ARM64_NT_NEON128
#define ARM64_NT_NEON128 NEON128
#endif
typedef struct DECLSPEC_ALIGN(16) _ARM64_NT_CONTEXT {
//
// Control flags.
//
/* +0x000 */ ULONG ContextFlags;
//
// Integer registers
//
/* +0x004 */ ULONG Cpsr; // NZVF + DAIF + CurrentEL + SPSel
/* +0x008 */ union {
struct {
ULONG64 X0;
ULONG64 X1;
ULONG64 X2;
ULONG64 X3;
ULONG64 X4;
ULONG64 X5;
ULONG64 X6;
ULONG64 X7;
ULONG64 X8;
ULONG64 X9;
ULONG64 X10;
ULONG64 X11;
ULONG64 X12;
ULONG64 X13;
ULONG64 X14;
ULONG64 X15;
ULONG64 X16;
ULONG64 X17;
ULONG64 X18;
ULONG64 X19;
ULONG64 X20;
ULONG64 X21;
ULONG64 X22;
ULONG64 X23;
ULONG64 X24;
ULONG64 X25;
ULONG64 X26;
ULONG64 X27;
ULONG64 X28;
/* +0x0f0 */ ULONG64 Fp;
/* +0x0f8 */ ULONG64 Lr;
} DUMMYSTRUCTNAME;
ULONG64 X[31];
} DUMMYUNIONNAME;
/* +0x100 */ ULONG64 Sp;
/* +0x108 */ ULONG64 Pc;
//
// Floating Point/NEON Registers
//
/* +0x110 */ ARM64_NT_NEON128 V[32];
/* +0x310 */ ULONG Fpcr;
/* +0x314 */ ULONG Fpsr;
//
// Debug registers
//
/* +0x318 */ ULONG Bcr[ARM64_MAX_BREAKPOINTS];
/* +0x338 */ ULONG64 Bvr[ARM64_MAX_BREAKPOINTS];
/* +0x378 */ ULONG Wcr[ARM64_MAX_WATCHPOINTS];
/* +0x380 */ ULONG64 Wvr[ARM64_MAX_WATCHPOINTS];
/* +0x390 */
} ARM64_NT_CONTEXT, *PARM64_NT_CONTEXT;
#if defined(_ARM64_)
#undef ARM64_NT_NEON128
#pragma pop_macro("ARM64_NT_NEON128")
#undef _ARM64_NT_CONTEXT
#pragma pop_macro("_ARM64_NT_CONTEXT")
typedef ARM64_NT_CONTEXT CONTEXT, *PCONTEXT;
#endif
//
// Well known SID definitions for lookup.
//
typedef enum {
WinNullSid = 0,
WinWorldSid = 1,
WinLocalSid = 2,
WinCreatorOwnerSid = 3,
WinCreatorGroupSid = 4,
WinCreatorOwnerServerSid = 5,
WinCreatorGroupServerSid = 6,
WinNtAuthoritySid = 7,
WinDialupSid = 8,
WinNetworkSid = 9,
WinBatchSid = 10,
WinInteractiveSid = 11,
WinServiceSid = 12,
WinAnonymousSid = 13,
WinProxySid = 14,
WinEnterpriseControllersSid = 15,
WinSelfSid = 16,
WinAuthenticatedUserSid = 17,
WinRestrictedCodeSid = 18,
WinTerminalServerSid = 19,
WinRemoteLogonIdSid = 20,
WinLogonIdsSid = 21,
WinLocalSystemSid = 22,
WinLocalServiceSid = 23,
WinNetworkServiceSid = 24,
WinBuiltinDomainSid = 25,
WinBuiltinAdministratorsSid = 26,
WinBuiltinUsersSid = 27,
WinBuiltinGuestsSid = 28,
WinBuiltinPowerUsersSid = 29,
WinBuiltinAccountOperatorsSid = 30,
WinBuiltinSystemOperatorsSid = 31,
WinBuiltinPrintOperatorsSid = 32,
WinBuiltinBackupOperatorsSid = 33,
WinBuiltinReplicatorSid = 34,
WinBuiltinPreWindows2000CompatibleAccessSid = 35,
WinBuiltinRemoteDesktopUsersSid = 36,
WinBuiltinNetworkConfigurationOperatorsSid = 37,
WinAccountAdministratorSid = 38,
WinAccountGuestSid = 39,
WinAccountKrbtgtSid = 40,
WinAccountDomainAdminsSid = 41,
WinAccountDomainUsersSid = 42,
WinAccountDomainGuestsSid = 43,
WinAccountComputersSid = 44,
WinAccountControllersSid = 45,
WinAccountCertAdminsSid = 46,
WinAccountSchemaAdminsSid = 47,
WinAccountEnterpriseAdminsSid = 48,
WinAccountPolicyAdminsSid = 49,
WinAccountRasAndIasServersSid = 50,
WinNTLMAuthenticationSid = 51,
WinDigestAuthenticationSid = 52,
WinSChannelAuthenticationSid = 53,
WinThisOrganizationSid = 54,
WinOtherOrganizationSid = 55,
WinBuiltinIncomingForestTrustBuildersSid = 56,
WinBuiltinPerfMonitoringUsersSid = 57,
WinBuiltinPerfLoggingUsersSid = 58,
WinBuiltinAuthorizationAccessSid = 59,
WinBuiltinTerminalServerLicenseServersSid = 60,
WinBuiltinDCOMUsersSid = 61,
WinBuiltinIUsersSid = 62,
WinIUserSid = 63,
WinBuiltinCryptoOperatorsSid = 64,
WinUntrustedLabelSid = 65,
WinLowLabelSid = 66,
WinMediumLabelSid = 67,
WinHighLabelSid = 68,
WinSystemLabelSid = 69,
WinWriteRestrictedCodeSid = 70,
WinCreatorOwnerRightsSid = 71,
WinCacheablePrincipalsGroupSid = 72,
WinNonCacheablePrincipalsGroupSid = 73,
WinEnterpriseReadonlyControllersSid = 74,
WinAccountReadonlyControllersSid = 75,
WinBuiltinEventLogReadersGroup = 76,
WinNewEnterpriseReadonlyControllersSid = 77,
WinBuiltinCertSvcDComAccessGroup = 78,
WinMediumPlusLabelSid = 79,
WinLocalLogonSid = 80,
WinConsoleLogonSid = 81,
WinThisOrganizationCertificateSid = 82,
WinApplicationPackageAuthoritySid = 83,
WinBuiltinAnyPackageSid = 84,
WinCapabilityInternetClientSid = 85,
WinCapabilityInternetClientServerSid = 86,
WinCapabilityPrivateNetworkClientServerSid = 87,
WinCapabilityPicturesLibrarySid = 88,
WinCapabilityVideosLibrarySid = 89,
WinCapabilityMusicLibrarySid = 90,
WinCapabilityDocumentsLibrarySid = 91,
WinCapabilitySharedUserCertificatesSid = 92,
WinCapabilityEnterpriseAuthenticationSid = 93,
WinCapabilityRemovableStorageSid = 94,
WinBuiltinRDSRemoteAccessServersSid = 95,
WinBuiltinRDSEndpointServersSid = 96,
WinBuiltinRDSManagementServersSid = 97,
WinUserModeDriversSid = 98,
WinBuiltinHyperVAdminsSid = 99,
WinAccountCloneableControllersSid = 100,
WinBuiltinAccessControlAssistanceOperatorsSid = 101,
WinBuiltinRemoteManagementUsersSid = 102,
WinAuthenticationAuthorityAssertedSid = 103,
WinAuthenticationServiceAssertedSid = 104,
WinLocalAccountSid = 105,
WinLocalAccountAndAdministratorSid = 106,
WinAccountProtectedUsersSid = 107,
WinCapabilityAppointmentsSid = 108,
WinCapabilityContactsSid = 109,
WinAccountDefaultSystemManagedSid = 110,
WinBuiltinDefaultSystemManagedGroupSid = 111,
WinBuiltinStorageReplicaAdminsSid = 112,
WinAccountKeyAdminsSid = 113,
WinAccountEnterpriseKeyAdminsSid = 114,
WinAuthenticationKeyTrustSid = 115,
WinAuthenticationKeyPropertyMFASid = 116,
WinAuthenticationKeyPropertyAttestationSid = 117,
WinAuthenticationFreshKeyAuthSid = 118,
WinBuiltinDeviceOwnersSid = 119,
} WELL_KNOWN_SID_TYPE;
//
// Unsolicited Input is obsolete and unused.
//
#define SE_UNSOLICITED_INPUT_PRIVILEGE (6L)
//
// Base signing levels.
//
typedef UCHAR SE_SIGNING_LEVEL, *PSE_SIGNING_LEVEL;
#define SE_SIGNING_LEVEL_UNCHECKED 0x00000000
#define SE_SIGNING_LEVEL_UNSIGNED 0x00000001
#define SE_SIGNING_LEVEL_ENTERPRISE 0x00000002
#define SE_SIGNING_LEVEL_CUSTOM_1 0x00000003
#define SE_SIGNING_LEVEL_DEVELOPER SE_SIGNING_LEVEL_CUSTOM_1
#define SE_SIGNING_LEVEL_AUTHENTICODE 0x00000004
#define SE_SIGNING_LEVEL_CUSTOM_2 0x00000005
#define SE_SIGNING_LEVEL_STORE 0x00000006
#define SE_SIGNING_LEVEL_CUSTOM_3 0x00000007
#define SE_SIGNING_LEVEL_ANTIMALWARE SE_SIGNING_LEVEL_CUSTOM_3
#define SE_SIGNING_LEVEL_MICROSOFT 0x00000008
#define SE_SIGNING_LEVEL_CUSTOM_4 0x00000009
#define SE_SIGNING_LEVEL_CUSTOM_5 0x0000000A
#define SE_SIGNING_LEVEL_DYNAMIC_CODEGEN 0x0000000B
#define SE_SIGNING_LEVEL_WINDOWS 0x0000000C
#define SE_SIGNING_LEVEL_CUSTOM_7 0x0000000D
#define SE_SIGNING_LEVEL_WINDOWS_TCB 0x0000000E
#define SE_SIGNING_LEVEL_CUSTOM_6 0x0000000F
//
// Image signature types.
//
typedef enum _SE_IMAGE_SIGNATURE_TYPE
{
SeImageSignatureNone = 0,
SeImageSignatureEmbedded,
SeImageSignatureCache,
SeImageSignatureCatalogCached,
SeImageSignatureCatalogNotCached,
SeImageSignatureCatalogHint,
SeImageSignaturePackageCatalog,
} SE_IMAGE_SIGNATURE_TYPE, *PSE_IMAGE_SIGNATURE_TYPE;
#ifndef _NTLSA_IFS_
//
// All of this stuff (between the Ifndef _NTLSA_AUDIT_ and its endif) were not
// present in NTIFS prior to Windows Server 2003 SP1. All of the definitions however
// exist down to windows 2000 (except for the few exceptions noted in the code).
//
#ifndef _NTLSA_AUDIT_
#define _NTLSA_AUDIT_
/////////////////////////////////////////////////////////////////////////
// //
// Data types related to Auditing //
// //
/////////////////////////////////////////////////////////////////////////
//
// The following enumerated type is used between the reference monitor and
// LSA in the generation of audit messages. It is used to indicate the
// type of data being passed as a parameter from the reference monitor
// to LSA. LSA is responsible for transforming the specified data type
// into a set of unicode strings that are added to the event record in
// the audit log.
//
typedef enum _SE_ADT_PARAMETER_TYPE {
SeAdtParmTypeNone = 0, //Produces 1 parameter
//Received value:
//
// None.
//
//Results in:
//
// a unicode string containing "-".
//
//Note: This is typically used to
// indicate that a parameter value
// was not available.
//
SeAdtParmTypeString, //Produces 1 parameter.
//Received Value:
//
// Unicode String (variable length)
//
//Results in:
//
// No transformation. The string
// entered into the event record as
// received.
//
// The Address value of the audit info
// should be a pointer to a UNICODE_STRING
// structure.
SeAdtParmTypeFileSpec, //Produces 1 parameter.
//Received value:
//
// Unicode string containing a file or
// directory name.
//
//Results in:
//
// Unicode string with the prefix of the
// file's path replaced by a drive letter
// if possible.
//
SeAdtParmTypeUlong, //Produces 1 parameter
//Received value:
//
// Ulong
//
//Results in:
//
// Unicode string representation of
// unsigned integer value.
SeAdtParmTypeSid, //Produces 1 parameter.
//Received value:
//
// SID (variable length)
//
//Results in:
//
// String representation of SID
//
SeAdtParmTypeLogonId, //Produces 4 parameters.
//Received Value:
//
// LUID (fixed length)
//
//Results in:
//
// param 1: Sid string
// param 2: Username string
// param 3: domain name string
// param 4: Logon ID (Luid) string
SeAdtParmTypeNoLogonId, //Produces 3 parameters.
//Received value:
//
// None.
//
//Results in:
//
// param 1: "-"
// param 2: "-"
// param 3: "-"
// param 4: "-"
//
//Note:
//
// This type is used when a logon ID
// is needed, but one is not available
// to pass. For example, if an
// impersonation logon ID is expected
// but the subject is not impersonating
// anyone.
//
SeAdtParmTypeAccessMask, //Produces 1 parameter with formatting.
//Received value:
//
// ACCESS_MASK followed by
// a Unicode string. The unicode
// string contains the name of the
// type of object the access mask
// applies to. The event's source
// further qualifies the object type.
//
//Results in:
//
// formatted unicode string built to
// take advantage of the specified
// source's parameter message file.
//
//Note:
//
// An access mask containing three
// access types for a Widget object
// type (defined by the Foozle source)
// might end up looking like:
//
// %%1062\n\t\t%1066\n\t\t%%601
//
// The %%numbers are signals to the
// event viewer to perform parameter
// substitution before display.
//
SeAdtParmTypePrivs, //Produces 1 parameter with formatting.
//Received value:
//
//Results in:
//
// formatted unicode string similar to
// that for access types. Each priv
// will be formatted to be displayed
// on its own line. E.g.,
//
// %%642\n\t\t%%651\n\t\t%%655
//
SeAdtParmTypeObjectTypes, //Produces 10 parameters with formatting.
//Received value:
//
// Produces a list a stringized GUIDS along
// with information similar to that for
// an access mask.
SeAdtParmTypeHexUlong, //Produces 1 parameter
//Received value:
//
// Ulong
//
//Results in:
//
// Unicode string representation of
// unsigned integer value in hexadecimal.
// In W2k this value did not exist, it was ParmTypeLUID
SeAdtParmTypePtr, //Produces 1 parameter
//Received value:
//
// pointer
//
//Results in:
//
// Unicode string representation of
// unsigned integer value in hexadecimal.
//
// Everything below exists only in Windows XP and greater
//
SeAdtParmTypeTime, //Produces 2 parameters
//Received value:
//
// LARGE_INTEGER
//
//Results in:
//
// Unicode string representation of
// date and time.
//
SeAdtParmTypeGuid, //Produces 1 parameter
//Received value:
//
// GUID pointer
//
//Results in:
//
// Unicode string representation of GUID
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
//
//
// Everything below exists only in Windows Server 2003 and Greater
//
SeAdtParmTypeLuid, //
//Produces 1 parameter
//Received value:
//
// LUID
//
//Results in:
//
// Hex LUID
//
SeAdtParmTypeHexInt64, //Produces 1 parameter
//Received value:
//
// 64 bit integer
//
//Results in:
//
// Unicode string representation of
// unsigned integer value in hexadecimal.
SeAdtParmTypeStringList, //Produces 1 parameter
//Received value:
//
// ptr to LSAP_ADT_STRING_LIST
//
//Results in:
//
// Unicode string representation of
// concatenation of the strings in the list
SeAdtParmTypeSidList, //Produces 1 parameter
//Received value:
//
// ptr to LSAP_ADT_SID_LIST
//
//Results in:
//
// Unicode string representation of
// concatenation of the SIDs in the list
SeAdtParmTypeDuration, //Produces 1 parameters
//Received value:
//
// LARGE_INTEGER
//
//Results in:
//
// Unicode string representation of
// a duration.
SeAdtParmTypeUserAccountControl,//Produces 3 parameters
//Received value:
//
// old and new UserAccountControl values
//
//Results in:
//
// Unicode string representations of
// the flags in UserAccountControl.
// 1 - old value in hex
// 2 - new value in hex
// 3 - difference as strings
SeAdtParmTypeNoUac, //Produces 3 parameters
//Received value:
//
// none
//
//Results in:
//
// Three dashes ('-') as unicode strings.
SeAdtParmTypeMessage, //Produces 1 Parameter
//Received value:
//
// ULONG (MessageNo from msobjs.mc)
//
//Results in:
//
// Unicode string representation of
// %%MessageNo which the event viewer
// will replace with the message string
// from msobjs.mc
SeAdtParmTypeDateTime, //Produces 1 Parameter
//Received value:
//
// LARGE_INTEGER
//
//Results in:
//
// Unicode string representation of
// date and time (in _one_ string).
SeAdtParmTypeSockAddr, // Produces 2 parameters
//
// Received value:
//
// pointer to SOCKADDR_IN/SOCKADDR_IN6
// structure
//
// Results in:
//
// param 1: IP address string
// param 2: Port number string
//
//
// Everything below this exists only in Windows Server 2008 and greater
//
SeAdtParmTypeSD, // Produces 1 parameters
//
// Received value:
//
// pointer to SECURITY_DESCRIPTOR
// structure. This HAS to appear in pairs.
// The first parameter will represent the
// old SD and the second parameter will
// represent the New SD
//
// Results in:
//
// SDDL string representation of SD
//
SeAdtParmTypeLogonHours, // Produces 1 parameters
//
// Received value:
//
// pointer to LOGON_HOURS
// structure
//
// Results in:
//
// String representation of allowed logon hours
//
SeAdtParmTypeLogonIdNoSid, //Produces 3 parameters.
//Received Value:
//
// LUID (fixed length)
//
//Results in:
//
// param 1: Username string
// param 2: domain name string
// param 3: Logon ID (Luid) string
SeAdtParmTypeUlongNoConv, // Produces 1 parameter.
// Received Value:
// Ulong
//
//Results in:
// Not converted to string
//
SeAdtParmTypeSockAddrNoPort, // Produces 1 parameter
//
// Received value:
//
// pointer to SOCKADDR_IN/SOCKADDR_IN6
// structure
//
// Results in:
//
// param 1: IPv4/IPv6 address string
//
//
// Everything below this exists only in Windows Server 2008 and greater
//
SeAdtParmTypeAccessReason, // Produces 1 parameters
//
// Received value:
//
// pointer to SE_ADT_ACCESS_REASON structure
//
// Results in:
//
// String representation of the access reason.
//
//
// Everything below this exists only in Windows Server 2012 and greater
//
SeAdtParmTypeStagingReason, // Produces 1 parameters
//
// Received value:
//
// pointer to SE_ADT_ACCESS_REASON structure
//
// Results in:
//
// String representation of Staging policy's
// access reason.
//
SeAdtParmTypeResourceAttribute, // Produces 1 parameters
//
// Received value:
//
// pointer to SECURITY_DESCRIPTOR
// structure
//
// Results in:
//
// SDDL string representation of the
// Resource Attribute ACEs in the SD
//
SeAdtParmTypeClaims, // Produces 1 parameters
//
// Received value:
//
// pointer to the structure -
// CLAIM_SECURITY_ATTRIBUTES_INFORMATION
// structure
//
// Results in:
//
// Claims information as attributes, value
// pairs
//
SeAdtParmTypeLogonIdAsSid, // Produces 4 parameters.
// Received Value:
//
// SID (variable length)
//
//Results in:
//
// param 1: Sid string (based on SID and not derived from the LUID)
// param 2: -
// param 3: -
// param 4: -
SeAdtParmTypeMultiSzString, //Produces 1 parameter
//Received value:
//
// PZZWSTR string
//
//Results in:
//
// Unicode string with each null replaced with /r/n
SeAdtParmTypeLogonIdEx, //Produces 4 parameters.
//Received Value:
//
// LUID (fixed length)
//
//Results in:
//
// param 1: Sid string
// param 2: Username string
// param 3: domain name string
// param 4: Logon ID (Luid) string
} SE_ADT_PARAMETER_TYPE, *PSE_ADT_PARAMETER_TYPE;
#ifndef GUID_DEFINED
#include <guiddef.h>
#endif /* GUID_DEFINED */
typedef struct _SE_ADT_OBJECT_TYPE {
GUID ObjectType;
USHORT Flags;
#define SE_ADT_OBJECT_ONLY 0x1
USHORT Level;
ACCESS_MASK AccessMask;
} SE_ADT_OBJECT_TYPE, *PSE_ADT_OBJECT_TYPE;
typedef struct _SE_ADT_PARAMETER_ARRAY_ENTRY {
SE_ADT_PARAMETER_TYPE Type;
ULONG Length;
ULONG_PTR Data[2];
PVOID Address;
} SE_ADT_PARAMETER_ARRAY_ENTRY, *PSE_ADT_PARAMETER_ARRAY_ENTRY;
typedef struct _SE_ADT_ACCESS_REASON{
ACCESS_MASK AccessMask;
ULONG AccessReasons[32];
ULONG ObjectTypeIndex;
ULONG AccessGranted;
PSECURITY_DESCRIPTOR SecurityDescriptor; // multple SDs may be stored here in self-relative way.
} SE_ADT_ACCESS_REASON, *PSE_ADT_ACCESS_REASON;
typedef struct _SE_ADT_CLAIMS {
ULONG Length;
PCLAIMS_BLOB Claims; // one claim blob will be stored here in self-relative way
} SE_ADT_CLAIMS, *PSE_ADT_CLAIMS;
//
// Structure that will be passed between the Reference Monitor and LSA
// to transmit auditing information.
//
#define SE_MAX_AUDIT_PARAMETERS 32
#define SE_MAX_GENERIC_AUDIT_PARAMETERS 28
typedef struct _SE_ADT_PARAMETER_ARRAY {
ULONG CategoryId;
ULONG AuditId;
ULONG ParameterCount;
ULONG Length;
USHORT FlatSubCategoryId;
USHORT Type;
ULONG Flags;
SE_ADT_PARAMETER_ARRAY_ENTRY Parameters[ SE_MAX_AUDIT_PARAMETERS ];
} SE_ADT_PARAMETER_ARRAY, *PSE_ADT_PARAMETER_ARRAY;
typedef struct _SE_ADT_PARAMETER_ARRAY_EX {
ULONG CategoryId;
ULONG AuditId;
ULONG Version;
ULONG ParameterCount;
ULONG Length;
USHORT FlatSubCategoryId;
USHORT Type;
ULONG Flags;
SE_ADT_PARAMETER_ARRAY_ENTRY Parameters[ SE_MAX_AUDIT_PARAMETERS ];
} SE_ADT_PARAMETER_ARRAY_EX, *PSE_ADT_PARAMETER_ARRAY_EX;
#define SE_ADT_PARAMETERS_SELF_RELATIVE 0x00000001
#define SE_ADT_PARAMETERS_SEND_TO_LSA 0x00000002
#define SE_ADT_PARAMETER_EXTENSIBLE_AUDIT 0x00000004
#define SE_ADT_PARAMETER_GENERIC_AUDIT 0x00000008
#define SE_ADT_PARAMETER_WRITE_SYNCHRONOUS 0x00000010
//
// This macro only existed in Windows Server 2008 and after
//
#define LSAP_SE_ADT_PARAMETER_ARRAY_TRUE_SIZE(AuditParameters) \
( sizeof(SE_ADT_PARAMETER_ARRAY) - \
sizeof(SE_ADT_PARAMETER_ARRAY_ENTRY) * \
(SE_MAX_AUDIT_PARAMETERS - AuditParameters->ParameterCount) )
#endif // _NTLSA_AUDIT_
#endif // _NTLSA_IFS_
#ifndef _RTL_RUN_ONCE_DEF
#define _RTL_RUN_ONCE_DEF
//
// Run once
//
#define RTL_RUN_ONCE_INIT {0} // Static initializer
//
// Run once flags
//
#define RTL_RUN_ONCE_CHECK_ONLY 0x00000001UL
#define RTL_RUN_ONCE_ASYNC 0x00000002UL
#define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL
//
// The context stored in the run once structure must leave the following number
// of low order bits unused.
//
#define RTL_RUN_ONCE_CTX_RESERVED_BITS 2
typedef union _RTL_RUN_ONCE {
PVOID Ptr;
} RTL_RUN_ONCE, *PRTL_RUN_ONCE;
typedef
_Function_class_(RTL_RUN_ONCE_INIT_FN)
_IRQL_requires_same_
ULONG /* LOGICAL */
NTAPI
RTL_RUN_ONCE_INIT_FN (
_Inout_ PRTL_RUN_ONCE RunOnce,
_Inout_opt_ PVOID Parameter,
_Inout_opt_ PVOID *Context
);
typedef RTL_RUN_ONCE_INIT_FN *PRTL_RUN_ONCE_INIT_FN;
#endif // _RTL_RUN_ONCE_DEF
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
_IRQL_requires_max_(APC_LEVEL)
NTSYSAPI
VOID
NTAPI
RtlRunOnceInitialize (
_Out_ PRTL_RUN_ONCE RunOnce
);
_IRQL_requires_max_(APC_LEVEL)
_Maybe_raises_SEH_exception_
NTSYSAPI
NTSTATUS
NTAPI
RtlRunOnceExecuteOnce (
_Inout_ PRTL_RUN_ONCE RunOnce,
_In_ __callback PRTL_RUN_ONCE_INIT_FN InitFn,
_Inout_opt_ PVOID Parameter,
_Outptr_opt_result_maybenull_ PVOID *Context
);
_IRQL_requires_max_(APC_LEVEL)
_Must_inspect_result_
NTSYSAPI
NTSTATUS
NTAPI
RtlRunOnceBeginInitialize (
_Inout_ PRTL_RUN_ONCE RunOnce,
_In_ ULONG Flags,
_Outptr_opt_result_maybenull_ PVOID *Context
);
_IRQL_requires_max_(APC_LEVEL)
NTSYSAPI
NTSTATUS
NTAPI
RtlRunOnceComplete (
_Inout_ PRTL_RUN_ONCE RunOnce,
_In_ ULONG Flags,
_In_opt_ PVOID Context
);
#endif // NTDDI_VERSION >= NTDDI_LONGHORN
//
// This enumerated type is used as the function return value of the function
// that is used to search the tree for a key. FoundNode indicates that the
// function found the key. Insert as left indicates that the key was not found
// and the node should be inserted as the left child of the parent. Insert as
// right indicates that the key was not found and the node should be inserted
// as the right child of the parent.
//
typedef enum _TABLE_SEARCH_RESULT{
TableEmptyTree,
TableFoundNode,
TableInsertAsLeft,
TableInsertAsRight
} TABLE_SEARCH_RESULT;
//
// The results of a compare can be less than, equal, or greater than.
//
typedef enum _RTL_GENERIC_COMPARE_RESULTS {
GenericLessThan,
GenericGreaterThan,
GenericEqual
} RTL_GENERIC_COMPARE_RESULTS;
//
// Define the Avl version of the generic table package. Note a generic table
// should really be an opaque type. We provide routines to manipulate the structure.
//
// A generic table is package for inserting, deleting, and looking up elements
// in a table (e.g., in a symbol table). To use this package the user
// defines the structure of the elements stored in the table, provides a
// comparison function, a memory allocation function, and a memory
// deallocation function.
//
// Note: the user compare function must impose a complete ordering among
// all of the elements, and the table does not allow for duplicate entries.
//
//
// Add an empty typedef so that functions can reference the
// a pointer to the generic table struct before it is declared.
//
struct _RTL_AVL_TABLE;
//
// The comparison function takes as input pointers to elements containing
// user defined structures and returns the results of comparing the two
// elements.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_AVL_COMPARE_ROUTINE)
RTL_GENERIC_COMPARE_RESULTS
NTAPI
RTL_AVL_COMPARE_ROUTINE (
_In_ struct _RTL_AVL_TABLE *Table,
_In_ PVOID FirstStruct,
_In_ PVOID SecondStruct
);
typedef RTL_AVL_COMPARE_ROUTINE *PRTL_AVL_COMPARE_ROUTINE;
//
// The allocation function is called by the generic table package whenever
// it needs to allocate memory for the table.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_AVL_ALLOCATE_ROUTINE)
__drv_allocatesMem(Mem)
PVOID
NTAPI
RTL_AVL_ALLOCATE_ROUTINE (
_In_ struct _RTL_AVL_TABLE *Table,
_In_ CLONG ByteSize
);
typedef RTL_AVL_ALLOCATE_ROUTINE *PRTL_AVL_ALLOCATE_ROUTINE;
//
// The deallocation function is called by the generic table package whenever
// it needs to deallocate memory from the table that was allocated by calling
// the user supplied allocation function.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_AVL_FREE_ROUTINE)
VOID
NTAPI
RTL_AVL_FREE_ROUTINE (
_In_ struct _RTL_AVL_TABLE *Table,
_In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer
);
typedef RTL_AVL_FREE_ROUTINE *PRTL_AVL_FREE_ROUTINE;
//
// The match function takes as input the user data to be matched and a pointer
// to some match data, which was passed along with the function pointer. It
// returns TRUE for a match and FALSE for no match.
//
// RTL_AVL_MATCH_FUNCTION returns
// STATUS_SUCCESS if the IndexRow matches
// STATUS_NO_MATCH if the IndexRow does not match, but the enumeration should
// continue
// STATUS_NO_MORE_MATCHES if the IndexRow does not match, and the enumeration
// should terminate
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_AVL_MATCH_FUNCTION)
NTSTATUS
NTAPI
RTL_AVL_MATCH_FUNCTION (
_In_ struct _RTL_AVL_TABLE *Table,
_In_ PVOID UserData,
_In_ PVOID MatchData
);
typedef RTL_AVL_MATCH_FUNCTION *PRTL_AVL_MATCH_FUNCTION;
//
// Define the balanced tree links and Balance field. (No Rank field
// defined at this time.)
//
// Callers should treat this structure as opaque!
//
// The root of a balanced binary tree is not a real node in the tree
// but rather points to a real node which is the root. It is always
// in the table below, and its fields are used as follows:
//
// Parent Pointer to self, to allow for detection of the root.
// LeftChild NULL
// RightChild Pointer to real root
// Balance Undefined, however it is set to a convenient value
// (depending on the algorithm) prior to rebalancing
// in insert and delete routines.
//
typedef struct _RTL_BALANCED_LINKS {
struct _RTL_BALANCED_LINKS *Parent;
struct _RTL_BALANCED_LINKS *LeftChild;
struct _RTL_BALANCED_LINKS *RightChild;
CHAR Balance;
UCHAR Reserved[3];
} RTL_BALANCED_LINKS;
typedef RTL_BALANCED_LINKS *PRTL_BALANCED_LINKS;
//
// To use the generic table package the user declares a variable of type
// GENERIC_TABLE and then uses the routines described below to initialize
// the table and to manipulate the table. Note that the generic table
// should really be an opaque type.
//
typedef struct _RTL_AVL_TABLE {
RTL_BALANCED_LINKS BalancedRoot;
PVOID OrderedPointer;
ULONG WhichOrderedElement;
ULONG NumberGenericTableElements;
ULONG DepthOfTree;
PRTL_BALANCED_LINKS RestartKey;
ULONG DeleteCount;
PRTL_AVL_COMPARE_ROUTINE CompareRoutine;
PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine;
PRTL_AVL_FREE_ROUTINE FreeRoutine;
PVOID TableContext;
} RTL_AVL_TABLE;
typedef RTL_AVL_TABLE *PRTL_AVL_TABLE;
//
// The procedure InitializeGenericTable takes as input an uninitialized
// generic table variable and pointers to the three user supplied routines.
// This must be called for every individual generic table variable before
// it can be used.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
VOID
NTAPI
RtlInitializeGenericTableAvl (
_Out_ PRTL_AVL_TABLE Table,
_In_ PRTL_AVL_COMPARE_ROUTINE CompareRoutine,
_In_ PRTL_AVL_ALLOCATE_ROUTINE AllocateRoutine,
_In_ PRTL_AVL_FREE_ROUTINE FreeRoutine,
_In_opt_ PVOID TableContext
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function InsertElementGenericTable will insert a new element
// in a table. It does this by allocating space for the new element
// (this includes AVL links), inserting the element in the table, and
// then returning to the user a pointer to the new element. If an element
// with the same key already exists in the table the return value is a pointer
// to the old element. The optional output parameter NewElement is used
// to indicate if the element previously existed in the table. Note: the user
// supplied Buffer is only used for searching the table, upon insertion its
// contents are copied to the newly created element. This means that
// pointer to the input buffer will not point to the new element.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
PVOID
NTAPI
RtlInsertElementGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_reads_bytes_(BufferSize) PVOID Buffer,
_In_ CLONG BufferSize,
_Out_opt_ PBOOLEAN NewElement
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function InsertElementGenericTableFull will insert a new element
// in a table. It does this by allocating space for the new element
// (this includes AVL links), inserting the element in the table, and
// then returning to the user a pointer to the new element. If an element
// with the same key already exists in the table the return value is a pointer
// to the old element. The optional output parameter NewElement is used
// to indicate if the element previously existed in the table. Note: the user
// supplied Buffer is only used for searching the table, upon insertion its
// contents are copied to the newly created element. This means that
// pointer to the input buffer will not point to the new element.
// This routine is passed the NodeOrParent and SearchResult from a
// previous RtlLookupElementGenericTableFull.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
PVOID
NTAPI
RtlInsertElementGenericTableFullAvl (
_In_ PRTL_AVL_TABLE Table,
_In_reads_bytes_(BufferSize) PVOID Buffer,
_In_ CLONG BufferSize,
_Out_opt_ PBOOLEAN NewElement,
_In_ PVOID NodeOrParent,
_In_ TABLE_SEARCH_RESULT SearchResult
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function DeleteElementGenericTable will find and delete an element
// from a generic table. If the element is located and deleted the return
// value is TRUE, otherwise if the element is not located the return value
// is FALSE. The user supplied input buffer is only used as a key in
// locating the element in the table.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
BOOLEAN
NTAPI
RtlDeleteElementGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ PVOID Buffer
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function DeleteElementGenericTableAvxEx deletes the element specified
// by the NodeOrParent pointer. This element user data pointer must have first
// been obtained with RtlLookupElementGenericTableFull.
//
#if (NTDDI_VERSION >= NTDDI_WIN8)
NTSYSAPI
VOID
NTAPI
RtlDeleteElementGenericTableAvlEx (
_In_ PRTL_AVL_TABLE Table,
_In_ PVOID NodeOrParent
);
#endif // NTDDI_VERSION >= NTDDI_WIN8
//
// The function LookupElementGenericTable will find an element in a generic
// table. If the element is located the return value is a pointer to
// the user defined structure associated with the element, otherwise if
// the element is not located the return value is NULL. The user supplied
// input buffer is only used as a key in locating the element in the table.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlLookupElementGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ PVOID Buffer
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function LookupElementGenericTableFull will find an element in a generic
// table. If the element is located the return value is a pointer to
// the user defined structure associated with the element. If the element is not
// located then a pointer to the parent for the insert location is returned. The
// user must look at the SearchResult value to determine which is being returned.
// The user can use the SearchResult and parent for a subsequent FullInsertElement
// call to optimize the insert.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
PVOID
NTAPI
RtlLookupElementGenericTableFullAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ PVOID Buffer,
_Out_ PVOID *NodeOrParent,
_Out_ TABLE_SEARCH_RESULT *SearchResult
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function EnumerateGenericTable will return to the caller one-by-one
// the elements of of a table. The return value is a pointer to the user
// defined structure associated with the element. The input parameter
// Restart indicates if the enumeration should start from the beginning
// or should return the next element. If the are no more new elements to
// return the return value is NULL. As an example of its use, to enumerate
// all of the elements in a table the user would write:
//
// for (ptr = EnumerateGenericTable(Table, TRUE);
// ptr != NULL;
// ptr = EnumerateGenericTable(Table, FALSE)) {
// :
// }
//
// NOTE: This routine does not modify the structure of the tree, but saves
// the last node returned in the generic table itself, and for this
// reason requires exclusive access to the table for the duration of
// the enumeration.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlEnumerateGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ BOOLEAN Restart
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function EnumerateGenericTableWithoutSplaying will return to the
// caller one-by-one the elements of of a table. The return value is a
// pointer to the user defined structure associated with the element.
// The input parameter RestartKey indicates if the enumeration should
// start from the beginning or should return the next element. If the
// are no more new elements to return the return value is NULL. As an
// example of its use, to enumerate all of the elements in a table the
// user would write:
//
// RestartKey = NULL;
// for (ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey);
// ptr != NULL;
// ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey)) {
// :
// }
//
// If RestartKey is NULL, the package will start from the least entry in the
// table, otherwise it will start from the last entry returned.
//
// NOTE: This routine does not modify either the structure of the tree
// or the generic table itself, but must insure that no deletes
// occur for the duration of the enumeration, typically by having
// at least shared access to the table for the duration.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlEnumerateGenericTableWithoutSplayingAvl (
_In_ PRTL_AVL_TABLE Table,
_Inout_ PVOID *RestartKey
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// RtlLookupFirstMatchingElementGenericTableAvl will return the left-most
// element in the tree matching the data in Buffer. If, for example, the tree
// contains filenames there may exist several that differ only in case. A case-
// blind searcher can use this routine to position himself in the tree at the
// first match, and use an enumeration routine (such as RtlEnumerateGenericTableWithoutSplayingAvl
// to return each subsequent match.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlLookupFirstMatchingElementGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ PVOID Buffer,
_Out_ PVOID *RestartKey
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function EnumerateGenericTableLikeADirectory will return to the
// caller one-by-one the elements of of a table. The return value is a
// pointer to the user defined structure associated with the element.
// The input parameter RestartKey indicates if the enumeration should
// start from the beginning or should return the next element. If the
// are no more new elements to return the return value is NULL. As an
// example of its use, to enumerate all of the elements in a table the
// user would write:
//
// RestartKey = NULL;
// for (ptr = EnumerateGenericTableLikeADirectory(Table, &RestartKey, ...);
// ptr != NULL;
// ptr = EnumerateGenericTableLikeADirectory(Table, &RestartKey, ...)) {
// :
// }
//
// If RestartKey is NULL, the package will start from the least entry in the
// table, otherwise it will start from the last entry returned.
//
// NOTE: This routine does not modify either the structure of the tree
// or the generic table itself. The table must only be acquired
// shared for the duration of this call, and all synchronization
// may optionally be dropped between calls. Enumeration is always
// correctly resumed in the most efficient manner possible via the
// IN OUT parameters provided.
//
// ****** Explain NextFlag. Directory enumeration resumes from a key
// requires more thought. Also need the match pattern and IgnoreCase.
// Should some structure be introduced to carry it all?
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlEnumerateGenericTableLikeADirectory (
_In_ PRTL_AVL_TABLE Table,
_In_opt_ PRTL_AVL_MATCH_FUNCTION MatchFunction,
_In_opt_ PVOID MatchData,
_In_ ULONG NextFlag,
_Inout_ PVOID *RestartKey,
_Inout_ PULONG DeleteCount,
_In_ PVOID Buffer
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function GetElementGenericTable will return the i'th element
// inserted in the generic table. I = 0 implies the first element,
// I = (RtlNumberGenericTableElements(Table)-1) will return the last element
// inserted into the generic table. The type of I is ULONG. Values
// of I > than (NumberGenericTableElements(Table)-1) will return NULL. If
// an arbitrary element is deleted from the generic table it will cause
// all elements inserted after the deleted element to "move up".
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlGetElementGenericTableAvl (
_In_ PRTL_AVL_TABLE Table,
_In_ ULONG I
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function NumberGenericTableElements returns a ULONG value
// which is the number of generic table elements currently inserted
// in the generic table.
#if (NTDDI_VERSION >= NTDDI_WINXP)
NTSYSAPI
ULONG
NTAPI
RtlNumberGenericTableElementsAvl (
_In_ PRTL_AVL_TABLE Table
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// The function IsGenericTableEmpty will return to the caller TRUE if
// the input table is empty (i.e., does not contain any elements) and
// FALSE otherwise.
//
//
// Generic extensions for using generic structures with the avl libraries.
//
#if (NTDDI_VERSION >= NTDDI_WINXP)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlIsGenericTableEmptyAvl (
_In_ PRTL_AVL_TABLE Table
);
#endif // NTDDI_VERSION >= NTDDI_WINXP
//
// As an aid to allowing existing generic table users to do (in most
// cases) a single-line edit to switch over to Avl table use, we
// have the following defines and inline routine definitions which
// redirect calls and types. Note that the type override (performed
// by #define below) will not work in the unexpected event that someone
// has used a pointer or type specifier in their own #define, since
// #define processing is one pass and does not nest. The __inline
// declarations below do not have this limitation, however.
//
// To switch to using Avl tables, add the following line before your
// includes:
//
// #define RTL_USE_AVL_TABLES 0
//
#ifdef RTL_USE_AVL_TABLES
#undef PRTL_GENERIC_COMPARE_ROUTINE
#undef RTL_GENERIC_COMPARE_ROUTINE
#undef PRTL_GENERIC_ALLOCATE_ROUTINE
#undef RTL_GENERIC_ALLOCATE_ROUTINE
#undef PRTL_GENERIC_FREE_ROUTINE
#undef RTL_GENERIC_FREE_ROUTINE
#undef RTL_GENERIC_TABLE
#undef PRTL_GENERIC_TABLE
#define PRTL_GENERIC_COMPARE_ROUTINE PRTL_AVL_COMPARE_ROUTINE
#define RTL_GENERIC_COMPARE_ROUTINE RTL_AVL_COMPARE_ROUTINE
#define PRTL_GENERIC_ALLOCATE_ROUTINE PRTL_AVL_ALLOCATE_ROUTINE
#define RTL_GENERIC_ALLOCATE_ROUTINE RTL_AVL_ALLOCATE_ROUTINE
#define PRTL_GENERIC_FREE_ROUTINE PRTL_AVL_FREE_ROUTINE
#define RTL_GENERIC_FREE_ROUTINE RTL_AVL_FREE_ROUTINE
#define RTL_GENERIC_TABLE RTL_AVL_TABLE
#define PRTL_GENERIC_TABLE PRTL_AVL_TABLE
#define RtlInitializeGenericTable RtlInitializeGenericTableAvl
#define RtlInsertElementGenericTable RtlInsertElementGenericTableAvl
#define RtlInsertElementGenericTableFull RtlInsertElementGenericTableFullAvl
#define RtlDeleteElementGenericTable RtlDeleteElementGenericTableAvl
#define RtlLookupElementGenericTable RtlLookupElementGenericTableAvl
#define RtlLookupElementGenericTableFull RtlLookupElementGenericTableFullAvl
#define RtlEnumerateGenericTable RtlEnumerateGenericTableAvl
#define RtlEnumerateGenericTableWithoutSplaying RtlEnumerateGenericTableWithoutSplayingAvl
#define RtlGetElementGenericTable RtlGetElementGenericTableAvl
#define RtlNumberGenericTableElements RtlNumberGenericTableElementsAvl
#define RtlIsGenericTableEmpty RtlIsGenericTableEmptyAvl
#endif // RTL_USE_AVL_TABLES
//
// Define the splay links and the associated manipuliation macros and
// routines. Note that the splay_links should be an opaque type.
// Routine are provided to traverse and manipulate the structure.
//
typedef struct _RTL_SPLAY_LINKS {
struct _RTL_SPLAY_LINKS *Parent;
struct _RTL_SPLAY_LINKS *LeftChild;
struct _RTL_SPLAY_LINKS *RightChild;
} RTL_SPLAY_LINKS;
typedef RTL_SPLAY_LINKS *PRTL_SPLAY_LINKS;
#if !defined(MIDL_PASS) && !defined(SORTPP_PASS)
FORCEINLINE
VOID
RtlInitializeSplayLinks (
_Out_ PRTL_SPLAY_LINKS Links
)
//++
//
// The procedure InitializeSplayLinks takes as input a pointer to
// splay link and initializes its substructure. All splay link nodes must
// be initialized before they are used in the different splay routines and
// macros.
//
//--
{
Links->Parent = Links;
Links->LeftChild = NULL;
Links->RightChild = NULL;
}
#endif // !defined(MIDL_PASS) && !defined(SORTPP_PASS)
//
// The macro function Parent takes as input a pointer to a splay link in a
// tree and returns a pointer to the splay link of the parent of the input
// node. If the input node is the root of the tree the return value is
// equal to the input value.
//
// PRTL_SPLAY_LINKS
// RtlParent (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlParent(Links) ( \
(PRTL_SPLAY_LINKS)(Links)->Parent \
)
//
// The macro function LeftChild takes as input a pointer to a splay link in
// a tree and returns a pointer to the splay link of the left child of the
// input node. If the left child does not exist, the return value is NULL.
//
// PRTL_SPLAY_LINKS
// RtlLeftChild (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlLeftChild(Links) ( \
(PRTL_SPLAY_LINKS)(Links)->LeftChild \
)
//
// The macro function RightChild takes as input a pointer to a splay link
// in a tree and returns a pointer to the splay link of the right child of
// the input node. If the right child does not exist, the return value is
// NULL.
//
// PRTL_SPLAY_LINKS
// RtlRightChild (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlRightChild(Links) ( \
(PRTL_SPLAY_LINKS)(Links)->RightChild \
)
//
// The macro function IsRoot takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the root of the tree,
// otherwise it returns FALSE.
//
// BOOLEAN
// RtlIsRoot (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlIsRoot(Links) ( \
(RtlParent(Links) == (PRTL_SPLAY_LINKS)(Links)) \
)
//
// The macro function IsLeftChild takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the left child of its
// parent, otherwise it returns FALSE.
//
// BOOLEAN
// RtlIsLeftChild (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlIsLeftChild(Links) ( \
(RtlLeftChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) \
)
//
// The macro function IsRightChild takes as input a pointer to a splay link
// in a tree and returns TRUE if the input node is the right child of its
// parent, otherwise it returns FALSE.
//
// BOOLEAN
// RtlIsRightChild (
// PRTL_SPLAY_LINKS Links
// );
//
#define RtlIsRightChild(Links) ( \
(RtlRightChild(RtlParent(Links)) == (PRTL_SPLAY_LINKS)(Links)) \
)
#if !defined(MIDL_PASS) && !defined(SORTPP_PASS)
FORCEINLINE
VOID
RtlInsertAsLeftChild (
_Inout_ PRTL_SPLAY_LINKS ParentLinks,
_Inout_ PRTL_SPLAY_LINKS ChildLinks
)
//++
//
// The procedure InsertAsLeftChild takes as input a pointer to a splay
// link in a tree and a pointer to a node not in a tree. It inserts the
// second node as the left child of the first node. The first node must not
// already have a left child, and the second node must not already have a
// parent.
//
//--
{
ParentLinks->LeftChild = ChildLinks;
ChildLinks->Parent = ParentLinks;
}
FORCEINLINE
VOID
RtlInsertAsRightChild (
_Inout_ PRTL_SPLAY_LINKS ParentLinks,
_Inout_ PRTL_SPLAY_LINKS ChildLinks
)
//++
//
// The procedure InsertAsRightChild takes as input a pointer to a splay
// link in a tree and a pointer to a node not in a tree. It inserts the
// second node as the right child of the first node. The first node must not
// already have a right child, and the second node must not already have a
// parent.
//
//--
{
ParentLinks->RightChild = ChildLinks;
ChildLinks->Parent = ParentLinks;
}
#endif // !defined(MIDL_PASS) && !defined(SORTPP_PASS)
//
// The Splay function takes as input a pointer to a splay link in a tree
// and splays the tree. Its function return value is a pointer to the
// root of the splayed tree.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSplay (
_Inout_ PRTL_SPLAY_LINKS Links
);
#endif
//
// The Delete function takes as input a pointer to a splay link in a tree
// and deletes that node from the tree. Its function return value is a
// pointer to the root of the tree. If the tree is now empty, the return
// value is NULL.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlDelete (
_In_ PRTL_SPLAY_LINKS Links
);
#endif
//
// The DeleteNoSplay function takes as input a pointer to a splay link in a tree,
// the caller's pointer to the root of the tree and deletes that node from the
// tree. Upon return the caller's pointer to the root node will correctly point
// at the root of the tree.
//
// It operationally differs from RtlDelete only in that it will not splay the tree.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
VOID
NTAPI
RtlDeleteNoSplay (
_In_ PRTL_SPLAY_LINKS Links,
_Inout_ PRTL_SPLAY_LINKS *Root
);
#endif
//
// The SubtreeSuccessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the successor of the input node of
// the substree rooted at the input node. If there is not a successor, the
// return value is NULL.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSubtreeSuccessor (
_In_ PRTL_SPLAY_LINKS Links
);
#endif
//
// The SubtreePredecessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the predecessor of the input node of
// the substree rooted at the input node. If there is not a predecessor,
// the return value is NULL.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlSubtreePredecessor (
_In_ PRTL_SPLAY_LINKS Links
);
#endif
//
// The RealSuccessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the successor of the input node within
// the entire tree. If there is not a successor, the return value is NULL.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlRealSuccessor (
_In_ PRTL_SPLAY_LINKS Links
);
#endif
//
// The RealPredecessor function takes as input a pointer to a splay link
// in a tree and returns a pointer to the predecessor of the input node
// within the entire tree. If there is not a predecessor, the return value
// is NULL.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PRTL_SPLAY_LINKS
NTAPI
RtlRealPredecessor (
_In_ PRTL_SPLAY_LINKS Links
);
#endif
//
// Define the generic table package. Note a generic table should really
// be an opaque type. We provide routines to manipulate the structure.
//
// A generic table is package for inserting, deleting, and looking up elements
// in a table (e.g., in a symbol table). To use this package the user
// defines the structure of the elements stored in the table, provides a
// comparison function, a memory allocation function, and a memory
// deallocation function.
//
// Note: the user compare function must impose a complete ordering among
// all of the elements, and the table does not allow for duplicate entries.
//
//
// Do not do the following defines if using Avl
//
#ifndef RTL_USE_AVL_TABLES
//
// Add an empty typedef so that functions can reference the
// a pointer to the generic table struct before it is declared.
//
struct _RTL_GENERIC_TABLE;
//
// The comparison function takes as input pointers to elements containing
// user defined structures and returns the results of comparing the two
// elements.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_GENERIC_COMPARE_ROUTINE)
RTL_GENERIC_COMPARE_RESULTS
NTAPI
RTL_GENERIC_COMPARE_ROUTINE (
_In_ struct _RTL_GENERIC_TABLE *Table,
_In_ PVOID FirstStruct,
_In_ PVOID SecondStruct
);
typedef RTL_GENERIC_COMPARE_ROUTINE *PRTL_GENERIC_COMPARE_ROUTINE;
//
// The allocation function is called by the generic table package whenever
// it needs to allocate memory for the table.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_GENERIC_ALLOCATE_ROUTINE)
__drv_allocatesMem(Mem)
PVOID
NTAPI
RTL_GENERIC_ALLOCATE_ROUTINE (
_In_ struct _RTL_GENERIC_TABLE *Table,
_In_ CLONG ByteSize
);
typedef RTL_GENERIC_ALLOCATE_ROUTINE *PRTL_GENERIC_ALLOCATE_ROUTINE;
//
// The deallocation function is called by the generic table package whenever
// it needs to deallocate memory from the table that was allocated by calling
// the user supplied allocation function.
//
typedef
_IRQL_requires_same_
_Function_class_(RTL_GENERIC_FREE_ROUTINE)
VOID
NTAPI
RTL_GENERIC_FREE_ROUTINE (
_In_ struct _RTL_GENERIC_TABLE *Table,
_In_ __drv_freesMem(Mem) _Post_invalid_ PVOID Buffer
);
typedef RTL_GENERIC_FREE_ROUTINE *PRTL_GENERIC_FREE_ROUTINE;
//
// To use the generic table package the user declares a variable of type
// GENERIC_TABLE and then uses the routines described below to initialize
// the table and to manipulate the table. Note that the generic table
// should really be an opaque type.
//
typedef struct _RTL_GENERIC_TABLE {
PRTL_SPLAY_LINKS TableRoot;
LIST_ENTRY InsertOrderList;
PLIST_ENTRY OrderedPointer;
ULONG WhichOrderedElement;
ULONG NumberGenericTableElements;
PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine;
PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine;
PRTL_GENERIC_FREE_ROUTINE FreeRoutine;
PVOID TableContext;
} RTL_GENERIC_TABLE;
typedef RTL_GENERIC_TABLE *PRTL_GENERIC_TABLE;
//
// The procedure InitializeGenericTable takes as input an uninitialized
// generic table variable and pointers to the three user supplied routines.
// This must be called for every individual generic table variable before
// it can be used.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
VOID
NTAPI
RtlInitializeGenericTable (
_Out_ PRTL_GENERIC_TABLE Table,
_In_ PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine,
_In_ PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine,
_In_ PRTL_GENERIC_FREE_ROUTINE FreeRoutine,
_In_opt_ PVOID TableContext
);
#endif
//
// The function InsertElementGenericTable will insert a new element
// in a table. It does this by allocating space for the new element
// (this includes splay links), inserting the element in the table, and
// then returning to the user a pointer to the new element. If an element
// with the same key already exists in the table the return value is a pointer
// to the old element. The optional output parameter NewElement is used
// to indicate if the element previously existed in the table. Note: the user
// supplied Buffer is only used for searching the table, upon insertion its
// contents are copied to the newly created element. This means that
// pointer to the input buffer will not point to the new element.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
PVOID
NTAPI
RtlInsertElementGenericTable (
_In_ PRTL_GENERIC_TABLE Table,
_In_reads_bytes_(BufferSize) PVOID Buffer,
_In_ CLONG BufferSize,
_Out_opt_ PBOOLEAN NewElement
);
#endif
//
// The function InsertElementGenericTableFull will insert a new element
// in a table. It does this by allocating space for the new element
// (this includes splay links), inserting the element in the table, and
// then returning to the user a pointer to the new element. If an element
// with the same key already exists in the table the return value is a pointer
// to the old element. The optional output parameter NewElement is used
// to indicate if the element previously existed in the table. Note: the user
// supplied Buffer is only used for searching the table, upon insertion its
// contents are copied to the newly created element. This means that
// pointer to the input buffer will not point to the new element.
// This routine is passed the NodeOrParent and SearchResult from a
// previous RtlLookupElementGenericTableFull.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
PVOID
NTAPI
RtlInsertElementGenericTableFull (
_In_ PRTL_GENERIC_TABLE Table,
_In_reads_bytes_(BufferSize) PVOID Buffer,
_In_ CLONG BufferSize,
_Out_opt_ PBOOLEAN NewElement,
_In_ PVOID NodeOrParent,
_In_ TABLE_SEARCH_RESULT SearchResult
);
#endif
//
// The function DeleteElementGenericTable will find and delete an element
// from a generic table. If the element is located and deleted the return
// value is TRUE, otherwise if the element is not located the return value
// is FALSE. The user supplied input buffer is only used as a key in
// locating the element in the table.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
BOOLEAN
NTAPI
RtlDeleteElementGenericTable (
_In_ PRTL_GENERIC_TABLE Table,
_In_ PVOID Buffer
);
#endif
//
// The function LookupElementGenericTable will find an element in a generic
// table. If the element is located the return value is a pointer to
// the user defined structure associated with the element, otherwise if
// the element is not located the return value is NULL. The user supplied
// input buffer is only used as a key in locating the element in the table.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlLookupElementGenericTable (
_In_ PRTL_GENERIC_TABLE Table,
_In_ PVOID Buffer
);
#endif
//
// The function LookupElementGenericTableFull will find an element in a generic
// table. If the element is located the return value is a pointer to
// the user defined structure associated with the element. If the element is not
// located then a pointer to the parent for the insert location is returned. The
// user must look at the SearchResult value to determine which is being returned.
// The user can use the SearchResult and parent for a subsequent FullInsertElement
// call to optimize the insert.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
PVOID
NTAPI
RtlLookupElementGenericTableFull (
_In_ PRTL_GENERIC_TABLE Table,
_In_ PVOID Buffer,
_Out_ PVOID *NodeOrParent,
_Out_ TABLE_SEARCH_RESULT *SearchResult
);
#endif
//
// The function EnumerateGenericTable will return to the caller one-by-one
// the elements of of a table. The return value is a pointer to the user
// defined structure associated with the element. The input parameter
// Restart indicates if the enumeration should start from the beginning
// or should return the next element. If the are no more new elements to
// return the return value is NULL. As an example of its use, to enumerate
// all of the elements in a table the user would write:
//
// for (ptr = EnumerateGenericTable(Table, TRUE);
// ptr != NULL;
// ptr = EnumerateGenericTable(Table, FALSE)) {
// :
// }
//
//
// PLEASE NOTE:
//
// If you enumerate a GenericTable using RtlEnumerateGenericTable, you
// will flatten the table, turning it into a sorted linked list.
// To enumerate the table without perturbing the splay links, use
// RtlEnumerateGenericTableWithoutSplaying
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlEnumerateGenericTable (
_In_ PRTL_GENERIC_TABLE Table,
_In_ BOOLEAN Restart
);
#endif
//
// The function EnumerateGenericTableWithoutSplaying will return to the
// caller one-by-one the elements of of a table. The return value is a
// pointer to the user defined structure associated with the element.
// The input parameter RestartKey indicates if the enumeration should
// start from the beginning or should return the next element. If the
// are no more new elements to return the return value is NULL. As an
// example of its use, to enumerate all of the elements in a table the
// user would write:
//
// RestartKey = NULL;
// for (ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey);
// ptr != NULL;
// ptr = EnumerateGenericTableWithoutSplaying(Table, &RestartKey)) {
// :
// }
//
// If RestartKey is NULL, the package will start from the least entry in the
// table, otherwise it will start from the last entry returned.
//
//
// Note that unlike RtlEnumerateGenericTable, this routine will NOT perturb
// the splay order of the tree.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlEnumerateGenericTableWithoutSplaying (
_In_ PRTL_GENERIC_TABLE Table,
_Inout_ PVOID *RestartKey
);
#endif
//
// The function GetElementGenericTable will return the i'th element
// inserted in the generic table. I = 0 implies the first element,
// I = (RtlNumberGenericTableElements(Table)-1) will return the last element
// inserted into the generic table. The type of I is ULONG. Values
// of I > than (NumberGenericTableElements(Table)-1) will return NULL. If
// an arbitrary element is deleted from the generic table it will cause
// all elements inserted after the deleted element to "move up".
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
PVOID
NTAPI
RtlGetElementGenericTable(
_In_ PRTL_GENERIC_TABLE Table,
_In_ ULONG I
);
#endif
//
// The function NumberGenericTableElements returns a ULONG value
// which is the number of generic table elements currently inserted
// in the generic table.
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
ULONG
NTAPI
RtlNumberGenericTableElements(
_In_ PRTL_GENERIC_TABLE Table
);
#endif
//
// The function IsGenericTableEmpty will return to the caller TRUE if
// the input table is empty (i.e., does not contain any elements) and
// FALSE otherwise.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlIsGenericTableEmpty (
_In_ PRTL_GENERIC_TABLE Table
);
#endif
#endif // RTL_USE_AVL_TABLES
//
// The hash table header structure can either be allocated
// by the caller, or by the hash table creation function itself.
// This flag indicates what was done at creation time.
//
#define RTL_HASH_ALLOCATED_HEADER 0x00000001
//
// The RTL_HASH_RESERVED_SIGNATURE is the signature used internally for
// enumerators. A caller can never assign this signature to
// valid entries.
//
#define RTL_HASH_RESERVED_SIGNATURE 0
typedef struct _RTL_DYNAMIC_HASH_TABLE_ENTRY {
LIST_ENTRY Linkage;
ULONG_PTR Signature;
} RTL_DYNAMIC_HASH_TABLE_ENTRY, *PRTL_DYNAMIC_HASH_TABLE_ENTRY;
//
// Some components want to see the actual signature and can use
// this macro to encapsulate that operation.
//
#define HASH_ENTRY_KEY(x) ((x)->Signature)
//
// Brief background on each of the parameters and their
// justification:
// 1. ChainHead stores the pointer to a bucket. This is needed since
// our hash chains are doubly-linked circular lists, and there is
// is no way to determine whether we've reached the end of the
// chain unless we store the pointer to the bucket itself. This
// is particularly used in walking the sub-list of entries returned
// by a lookup. We need to know when the sub-list has been
// completely returned.
// 2. PrevLinkage stores a pointer to the entry before the entry
// under consideration. The reason for storing the previous entry
// instead of the entry itself is for cases where a lookup fails
// and PrevLinkage actually stores the entry that would have been
// the previous entry, had the looked up entry existed. This can
// then be used to actually insert the entry at that place.
// 3. Signature is used primarily as a safety check in insertion.
// This field must match the Signature of the entry being inserted.
//
typedef struct _RTL_DYNAMIC_HASH_TABLE_CONTEXT {
PLIST_ENTRY ChainHead;
PLIST_ENTRY PrevLinkage;
ULONG_PTR Signature;
} RTL_DYNAMIC_HASH_TABLE_CONTEXT, *PRTL_DYNAMIC_HASH_TABLE_CONTEXT;
typedef struct _RTL_DYNAMIC_HASH_TABLE_ENUMERATOR {
union {
RTL_DYNAMIC_HASH_TABLE_ENTRY HashEntry;
PLIST_ENTRY CurEntry;
};
PLIST_ENTRY ChainHead;
ULONG BucketIndex;
} RTL_DYNAMIC_HASH_TABLE_ENUMERATOR, *PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR;
typedef struct _RTL_DYNAMIC_HASH_TABLE {
// Entries initialized at creation
ULONG Flags;
ULONG Shift;
// Entries used in bucket computation.
ULONG TableSize;
ULONG Pivot;
ULONG DivisorMask;
// Counters
ULONG NumEntries;
ULONG NonEmptyBuckets;
ULONG NumEnumerators;
// The directory. This field is for internal use only.
PVOID Directory;
} RTL_DYNAMIC_HASH_TABLE, *PRTL_DYNAMIC_HASH_TABLE;
//
// Inline functions first.
//
#if !defined(MIDL_PASS) && !defined(SORTPP_PASS)
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
VOID
RtlInitHashTableContext(
_Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
)
{
Context->ChainHead = NULL;
Context->PrevLinkage = NULL;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
VOID
RtlInitHashTableContextFromEnumerator(
_Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context,
_In_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
)
{
Context->ChainHead = Enumerator->ChainHead;
Context->PrevLinkage = Enumerator->HashEntry.Linkage.Blink;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
void
RtlReleaseHashTableContext(
_Inout_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
)
{
UNREFERENCED_PARAMETER(Context);
return;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
ULONG
RtlTotalBucketsHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
)
{
return HashTable->TableSize;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
ULONG
RtlNonEmptyBucketsHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
)
{
return HashTable->NonEmptyBuckets;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
ULONG
RtlEmptyBucketsHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
)
{
return HashTable->TableSize - HashTable->NonEmptyBuckets;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
ULONG
RtlTotalEntriesHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
)
{
return HashTable->NumEntries;
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
FORCEINLINE
ULONG
RtlActiveEnumeratorsHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
)
{
return HashTable->NumEnumerators;
}
#endif
#endif // !defined(MIDL_PASS) && !defined(SORTPP_PASS)
//
// Almost all the hash functions take in a Context.
// If a valid context is passed in, it will be used
// in executing the operation if possible. If a
// blank context is passed in, it will be initialized
// appropriately.
//
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
_Success_(return != 0)
NTSYSAPI
BOOLEAN
NTAPI
RtlCreateHashTable(
_Inout_ _When_(NULL == *HashTable, _At_(*HashTable, __drv_allocatesMem(Mem)))
PRTL_DYNAMIC_HASH_TABLE *HashTable,
_In_ ULONG Shift,
_Reserved_ ULONG Flags
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN8)
_Must_inspect_result_
_Success_(return != 0)
NTSYSAPI
BOOLEAN
NTAPI
RtlCreateHashTableEx(
_Inout_ _When_(NULL == *HashTable, _At_(*HashTable, __drv_allocatesMem(Mem)))
PRTL_DYNAMIC_HASH_TABLE *HashTable,
_In_ ULONG InitialSize,
_In_ ULONG Shift,
_Reserved_ ULONG Flags
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
VOID
NTAPI
RtlDeleteHashTable(
_In_ _When_((HashTable->Flags & RTL_HASH_ALLOCATED_HEADER), __drv_freesMem(Mem) _Post_invalid_)
PRTL_DYNAMIC_HASH_TABLE HashTable
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlInsertEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_In_ __drv_aliasesMem PRTL_DYNAMIC_HASH_TABLE_ENTRY Entry,
_In_ ULONG_PTR Signature,
_Inout_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlRemoveEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_In_ PRTL_DYNAMIC_HASH_TABLE_ENTRY Entry,
_Inout_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
NTSYSAPI
PRTL_DYNAMIC_HASH_TABLE_ENTRY
NTAPI
RtlLookupEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_In_ ULONG_PTR Signature,
_Out_opt_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
NTSYSAPI
PRTL_DYNAMIC_HASH_TABLE_ENTRY
NTAPI
RtlGetNextEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_In_ PRTL_DYNAMIC_HASH_TABLE_CONTEXT Context
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlInitEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Out_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
NTSYSAPI
PRTL_DYNAMIC_HASH_TABLE_ENTRY
NTAPI
RtlEnumerateEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
VOID
NTAPI
RtlEndEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlInitWeakEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Out_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
_Must_inspect_result_
NTSYSAPI
PRTL_DYNAMIC_HASH_TABLE_ENTRY
NTAPI
RtlWeaklyEnumerateEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
VOID
NTAPI
RtlEndWeakEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
NTSYSAPI
BOOLEAN
NTAPI
RtlInitStrongEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Out_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
_Must_inspect_result_
NTSYSAPI
PRTL_DYNAMIC_HASH_TABLE_ENTRY
NTAPI
RtlStronglyEnumerateEntryHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
NTSYSAPI
VOID
NTAPI
RtlEndStrongEnumerationHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable,
_Inout_ PRTL_DYNAMIC_HASH_TABLE_ENUMERATOR Enumerator
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlExpandHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN7)
NTSYSAPI
BOOLEAN
NTAPI
RtlContractHashTable(
_In_ PRTL_DYNAMIC_HASH_TABLE HashTable
);
#endif
#if defined (_MSC_VER) && ( _MSC_VER >= 900 )
PVOID
_ReturnAddress (
VOID
);
#pragma intrinsic(_ReturnAddress)
#endif
#if (defined(_M_AMD64) || defined(_M_IA64)) && !defined(_REALLY_GET_CALLERS_CALLER_)
#define RtlGetCallersAddress(CallersAddress, CallersCaller) \
*CallersAddress = (PVOID)_ReturnAddress(); \
*CallersCaller = NULL;
#else
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
VOID
NTAPI
RtlGetCallersAddress(
_Out_ PVOID *CallersAddress,
_Out_ PVOID *CallersCaller
);
#endif
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
//
// Reserve byte 1 of the RtlWalkFrameChain flags for
// specifying a number of frames to skip.
//
#define RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT 8
////@[comment("MVI_tracked")]
NTSYSAPI
ULONG
NTAPI
RtlWalkFrameChain (
_Out_writes_(Count - (Flags >> RTL_STACK_WALKING_MODE_FRAMES_TO_SKIP_SHIFT)) PVOID *Callers,
_In_ ULONG Count,
_In_ ULONG Flags
);
#endif
#if !defined(MIDL_PASS)
#if (NTDDI_VERSION >= NTDDI_WIN7)
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
ULONG64
NTAPI
RtlGetEnabledExtendedFeatures(
_In_ ULONG64 FeatureMask
);
#endif
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
NTSTATUS
NTAPI
RtlCharToInteger (
_In_z_ PCSZ String,
_In_opt_ ULONG Base,
_Out_ PULONG Value
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
NTSYSAPI
VOID
NTAPI
RtlCopyString(
_Out_ PSTRING DestinationString,
_In_opt_ const STRING * SourceString
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
CHAR
NTAPI
RtlUpperChar (
_In_ CHAR Character
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
LONG
NTAPI
RtlCompareString(
_In_ const STRING * String1,
_In_ const STRING * String2,
_In_ BOOLEAN CaseInSensitive
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlEqualString(
_In_ const STRING * String1,
_In_ const STRING * String2,
_In_ BOOLEAN CaseInSensitive
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
VOID
NTAPI
RtlUpperString(
_Inout_ PSTRING DestinationString,
_In_ const STRING * SourceString
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlPrefixUnicodeString(
_In_ PCUNICODE_STRING String1,
_In_ PCUNICODE_STRING String2,
_In_ BOOLEAN CaseInSensitive
);
#endif
#if (NTDDI_VERSION >= NTDDI_THRESHOLD)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlSuffixUnicodeString(
_In_ PCUNICODE_STRING String1,
_In_ PCUNICODE_STRING String2,
_In_ BOOLEAN CaseInSensitive
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(PASSIVE_LEVEL)
_When_(AllocateDestinationString, _Must_inspect_result_)
NTSYSAPI
NTSTATUS
NTAPI
RtlUpcaseUnicodeString(
_When_(AllocateDestinationString, _Out_ _At_(DestinationString->Buffer, __drv_allocatesMem(Mem)))
_When_(!AllocateDestinationString, _Inout_)
PUNICODE_STRING DestinationString,
_In_ PCUNICODE_STRING SourceString,
_In_ BOOLEAN AllocateDestinationString
);
#endif
#if !defined(MIDL_PASS)
#if defined(_AMD64_) || defined(_ARM_) || defined(_ARM64_) || defined(_IA64_) || defined(_CHPE_X86_ARM64_)
//
// Large Integer divide - 64-bits / 64-bits -> 64-bits
//
DECLSPEC_DEPRECATED_DDK // Use native __int64 math
__drv_preferredFunction("compiler support for 64 bit", "Obsolete")
__inline
LARGE_INTEGER
NTAPI_INLINE
RtlLargeIntegerDivide (
_In_ LARGE_INTEGER Dividend,
_In_ LARGE_INTEGER Divisor,
_Out_opt_ PLARGE_INTEGER Remainder
)
{
LARGE_INTEGER Quotient;
Quotient.QuadPart = Dividend.QuadPart / Divisor.QuadPart;
if (ARGUMENT_PRESENT(Remainder)) {
Remainder->QuadPart = Dividend.QuadPart % Divisor.QuadPart;
}
return Quotient;
}
#else
//
// Large Integer divide - 64-bits / 64-bits -> 64-bits
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
DECLSPEC_DEPRECATED_DDK // Use native __int64 math
__drv_preferredFunction("compiler support for 64 bit", "Obsolete")
NTSYSAPI
LARGE_INTEGER
NTAPI
RtlLargeIntegerDivide (
_In_ LARGE_INTEGER Dividend,
_In_ LARGE_INTEGER Divisor,
_Out_opt_ PLARGE_INTEGER Remainder
);
#endif
#endif // defined(_AMD64_) || defined(_ARM_) || defined(_ARM64_) || defined(_IA64_)
#endif // !defined(MIDL_PASS)
#if (NTDDI_VERSION >= NTDDI_RS4)
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
NTSTATUS
NTAPI
RtlQueryRegistryValueWithFallback(
_In_opt_ HANDLE PrimaryHandle,
_In_opt_ HANDLE FallbackHandle,
_In_ PUNICODE_STRING ValueName,
_In_ ULONG ValueLength,
_Out_opt_ PULONG ValueType,
_Out_writes_bytes_to_(ValueLength, *ResultLength) PVOID ValueData,
_Out_range_(<= , ValueLength) PULONG ResultLength
);
#endif
//
// BOOLEAN
// RtlEqualLuid(
// PLUID L1,
// PLUID L2
// );
#define RtlEqualLuid(L1, L2) (((L1)->LowPart == (L2)->LowPart) && \
((L1)->HighPart == (L2)->HighPart))
//
// BOOLEAN
// RtlIsZeroLuid(
// PLUID L1
// );
//
#define RtlIsZeroLuid(L1) ((BOOLEAN) (((L1)->LowPart | (L1)->HighPart) == 0))
#if !defined(MIDL_PASS)
FORCEINLINE
LUID
NTAPI_INLINE
RtlConvertLongToLuid(
_In_ LONG Long
)
{
LUID TempLuid;
LARGE_INTEGER TempLi;
TempLi.QuadPart = Long;
TempLuid.LowPart = TempLi.u.LowPart;
TempLuid.HighPart = TempLi.u.HighPart;
return(TempLuid);
}
FORCEINLINE
LUID
NTAPI_INLINE
RtlConvertUlongToLuid(
_In_ ULONG Ulong
)
{
LUID TempLuid;
TempLuid.LowPart = Ulong;
TempLuid.HighPart = 0;
return(TempLuid);
}
#endif
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_IRQL_requires_max_(APC_LEVEL)
NTSYSAPI
VOID
NTAPI
RtlMapGenericMask(
_Inout_ PACCESS_MASK AccessMask,
_In_ PGENERIC_MAPPING GenericMapping
);
#endif
//
// Routine for converting from a volume device object to a DOS name.
//
#if (NTDDI_VERSION >= NTDDI_WIN2K)
_When_(NTDDI_VERSION >= NTDDI_WINXP,
__drv_preferredFunction("IoVolumeDeviceToDosName",
"Obsolete on WINXP and above"))
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSYSAPI
NTSTATUS
NTAPI
RtlVolumeDeviceToDosName(
_In_ PVOID VolumeDeviceObject,
_Out_ PUNICODE_STRING DosName
);
#endif
//
NTSYSAPI
ULONG
NTAPI
DbgPrompt (
_In_z_ PCCH Prompt,
_Out_writes_bytes_(Length) PCH Response,
_In_ ULONG Length
);
//
#if (NTDDI_VERSION >= NTDDI_VISTA)
NTSYSAPI
BOOLEAN
NTAPI
RtlGetProductInfo(
_In_ ULONG OSMajorVersion,
_In_ ULONG OSMinorVersion,
_In_ ULONG SpMajorVersion,
_In_ ULONG SpMinorVersion,
_Out_ PULONG ReturnedProductType
);
#endif
#if (NTDDI_VERSION >= NTDDI_WIN8) && !defined(MIDL_PASS)
NTSYSAPI
NTSTATUS
NTAPI
RtlIsUntrustedObject (
_In_opt_ HANDLE Handle,
_In_opt_ PVOID Object,
_Out_ PBOOLEAN UntrustedObject
);
#endif // (NTDDI_VERSION >= NTDDI_WIN8) && !defined(MIDL_PASS)
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
NTSYSAPI
ULONG
NTAPI
RtlGetActiveConsoleId(
VOID
);
#endif // NTDDI_VERSION >= NTDDI_RS1
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
NTSYSAPI
ULONGLONG
NTAPI
RtlGetConsoleSessionForegroundProcessId(
VOID
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
NTSYSAPI
ULONG
NTAPI
RtlGetSuiteMask(
VOID
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlIsMultiSessionSku (
VOID
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
#if (NTDDI_VERSION >= NTDDI_WIN10_RS4)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlIsStateSeparationEnabled (
VOID
);
typedef enum _STATE_LOCATION_TYPE {
LocationTypeRegistry = 0,
LocationTypeFileSystem = 1,
LocationTypeMaximum = 2
} STATE_LOCATION_TYPE;
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
NTSTATUS
NTAPI
RtlGetPersistedStateLocation (
_In_ PCWSTR SourceID,
_In_opt_ PCWSTR CustomValue,
_In_opt_ PCWSTR DefaultPath,
_In_ STATE_LOCATION_TYPE StateLocationType,
_Out_writes_bytes_to_opt_(BufferLengthIn, *BufferLengthOut)
PWCHAR TargetPath,
_In_ ULONG BufferLengthIn,
_Out_opt_ PULONG BufferLengthOut
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS3
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
BOOLEAN
NTAPI
RtlIsMultiUsersInSessionSku (
VOID
);
#endif // NTDDI_VERSION >= NTDDI_WIN10_RS1
#if (NTDDI_VERSION >= NTDDI_WIN10_RS1)
NTSYSAPI
BOOLEAN
NTAPI
RtlGetNtProductType(
_Out_ PNT_PRODUCT_TYPE NtProductType
);