/* * Native definition support * * This file is part of System Informer. */ #ifndef _PHNT_NTDEF_H #define _PHNT_NTDEF_H #ifndef _NTDEF_ #define _NTDEF_ // This header file provides basic NT types not included in Win32. If you have included winnt.h // (perhaps indirectly), you must use this file instead of ntdef.h. #ifndef NOTHING #define NOTHING #endif // // Basic types // /** * The QUAD structure is a union used for 64-bit values or double precision. * * This structure is used to represent a 64-bit integer or a double value. * The field `UseThisFieldToCopy` is intended for copying the structure, * while `DoNotUseThisField` should not be used directly. */ typedef struct _QUAD { union { __int64 UseThisFieldToCopy; double DoNotUseThisField; }; } QUAD, *PQUAD; /** * The QUAD_PTR structure is a utility structure for pointer-sized fields. * * This structure is not part of NT, but is useful. */ typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _QUAD_PTR { ULONG_PTR DoNotUseThisField1; ULONG_PTR DoNotUseThisField2; } QUAD_PTR, *PQUAD_PTR; /** * The LOGICAL type is an unsigned long used by the NT API for boolean logic. */ typedef ULONG LOGICAL; typedef ULONG *PLOGICAL; /** * The NTSTATUS type is a signed long used for NT API status codes. * * Functions returning NTSTATUS indicate success or error conditions. */ typedef _Return_type_success_(return >= 0) LONG NTSTATUS; typedef NTSTATUS *PNTSTATUS; // // Cardinal types // typedef char CCHAR; typedef short CSHORT; typedef ULONG CLONG; typedef CCHAR *PCCHAR; typedef CSHORT *PCSHORT; typedef CLONG *PCLONG; /** * The PCSZ type is a pointer to a constant string. */ typedef PCSTR PCSZ; /** * The PPVOID type is a pointer to a pointer to void. */ typedef PVOID* PPVOID; /** * The PCVOID type is a pointer to a constant void. */ typedef CONST VOID *PCVOID; // // Specific // /** * The KIRQL type is an unsigned char used by the NT API for kernel IRQL (Interrupt Request Level). */ typedef UCHAR KIRQL, *PKIRQL; /** * The KPRIORITY type is a signed long used by the NT API for kernel priority values. */ typedef LONG KPRIORITY, *PKPRIORITY; /** * The RTL_ATOM type is an unsigned short used by the NT API for Atom values. */ typedef USHORT RTL_ATOM, *PRTL_ATOM; /** * The PHYSICAL_ADDRESS type is a LARGE_INTEGER representing a physical address. */ typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; /** * The LARGE_INTEGER_128 structure represents a 128-bit signed integer. */ typedef struct _LARGE_INTEGER_128 { LONGLONG QuadPart[2]; } LARGE_INTEGER_128, *PLARGE_INTEGER_128; /** * The ULARGE_INTEGER_128 structure represents a 128-bit unsigned integer. */ typedef struct _ULARGE_INTEGER_128 { ULONGLONG QuadPart[2]; } ULARGE_INTEGER_128, *PULARGE_INTEGER_128; // // Limits // #define MINCHAR 0x80 // winnt #define MAXCHAR 0x7f // winnt #define MINSHORT 0x8000 // winnt #define MAXSHORT 0x7fff // winnt #define MINLONG 0x80000000 // winnt #define MAXLONG 0x7fffffff // winnt #define MAXUCHAR 0xff // winnt #define MAXUSHORT 0xffff // winnt #define MAXULONG 0xffffffff // winnt // // NT status macros // #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #define NT_INFORMATION(Status) ((((ULONG)(Status)) >> 30) == 1) #define NT_WARNING(Status) ((((ULONG)(Status)) >> 30) == 2) #define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3) #define NT_CUSTOMER_SHIFT 29 #define NT_CUSTOMER(Status) ((((ULONG)(Status)) >> NT_CUSTOMER_SHIFT) & 1) #define NT_FACILITY_MASK 0xfff #define NT_FACILITY_SHIFT 16 #define NT_FACILITY(Status) ((((ULONG)(Status)) >> NT_FACILITY_SHIFT) & NT_FACILITY_MASK) #define NT_NTWIN32(Status) (NT_FACILITY(Status) == FACILITY_NTWIN32) #define WIN32_FROM_NTSTATUS(Status) (((ULONG)(Status)) & 0xffff) // // Functions // #if defined(_WIN64) #define FASTCALL #else #define FASTCALL __fastcall #endif #if defined(_WIN64) #define POINTER_ALIGNMENT DECLSPEC_ALIGN(8) #else #define POINTER_ALIGNMENT #endif #if defined(_WIN64) || defined(_M_ALPHA) #define MAX_NATURAL_ALIGNMENT sizeof(ULONGLONG) #define MEMORY_ALLOCATION_ALIGNMENT 16 #else #define MAX_NATURAL_ALIGNMENT sizeof(DWORD) #define MEMORY_ALLOCATION_ALIGNMENT 8 #endif #ifndef DECLSPEC_NOALIAS #if _MSC_VER < 1900 #define DECLSPEC_NOALIAS #else #define DECLSPEC_NOALIAS __declspec(noalias) #endif #endif #ifndef DECLSPEC_IMPORT #define DECLSPEC_IMPORT __declspec(dllimport) #endif #ifndef DECLSPEC_EXPORT #define DECLSPEC_EXPORT __declspec(dllexport) #endif // // Synchronization enumerations // /** * Event types used with kernel synchronization objects. */ typedef enum _EVENT_TYPE { NotificationEvent, SynchronizationEvent } EVENT_TYPE; /** * Timer types used by kernel timer objects. */ typedef enum _TIMER_TYPE { NotificationTimer, SynchronizationTimer } TIMER_TYPE; /** * Wait operation types for kernel wait routines. */ typedef enum _WAIT_TYPE { WaitAll, WaitAny, WaitNotification, WaitDequeue, WaitDpc, } WAIT_TYPE; // // Strings // /** * The ANSI_STRING structure defines a counted string used for ANSI strings. * * \sa https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-string */ typedef struct _STRING { USHORT Length; USHORT MaximumLength; _Field_size_bytes_part_opt_(MaximumLength, Length) PCHAR Buffer; } STRING, *PSTRING, ANSI_STRING, *PANSI_STRING, OEM_STRING, *POEM_STRING; typedef STRING UTF8_STRING; typedef PSTRING PUTF8_STRING; typedef const STRING *PCSTRING; typedef const ANSI_STRING *PCANSI_STRING; typedef const OEM_STRING *PCOEM_STRING; typedef const STRING *PCUTF8_STRING; /** * The UNICODE_STRING structure defines a counted string used for Unicode strings. * * \sa https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string */ typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; _Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer; } UNICODE_STRING, *PUNICODE_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; #ifdef __cplusplus extern "C++" { template char _RTL_CONSTANT_STRING_type_check(const char (&s)[N]); template char _RTL_CONSTANT_STRING_type_check(const WCHAR (&s)[N]); // __typeof would be desirable here instead of sizeof. template class _RTL_CONSTANT_STRING_remove_const_template_class; template <> class _RTL_CONSTANT_STRING_remove_const_template_class {public: typedef char T; }; template <> class _RTL_CONSTANT_STRING_remove_const_template_class {public: typedef WCHAR T; }; #define _RTL_CONSTANT_STRING_remove_const_macro(s) \ (const_cast<_RTL_CONSTANT_STRING_remove_const_template_class::T*>(s)) } #else char _RTL_CONSTANT_STRING_type_check(const void *s); #define _RTL_CONSTANT_STRING_remove_const_macro(s) (s) #endif #define RTL_CONSTANT_STRING(s) \ { \ sizeof( s ) - sizeof( (s)[0] ), \ sizeof( s ) / (sizeof(_RTL_CONSTANT_STRING_type_check(s))), \ _RTL_CONSTANT_STRING_remove_const_macro(s) \ } #define DECLARE_CONST_UNICODE_STRING(_var, _str) \ const WCHAR _var ## _buffer[] = _str; \ const UNICODE_STRING _var = { sizeof(_str) - sizeof(WCHAR), sizeof(_str), (PWCH) _var ## _buffer } #define DECLARE_GLOBAL_CONST_UNICODE_STRING(_var, _str) \ extern const DECLSPEC_SELECTANY UNICODE_STRING _var = RTL_CONSTANT_STRING(_str) #define DECLARE_UNICODE_STRING_SIZE(_var, _size) \ WCHAR _var ## _buffer[_size]; \ UNICODE_STRING _var = { 0, (_size) * sizeof(WCHAR) , _var ## _buffer } // // Balanced tree node // #ifndef RTL_BALANCED_NODE_RESERVED_PARENT_MASK #define RTL_BALANCED_NODE_RESERVED_PARENT_MASK 3 #endif typedef struct _RTL_BALANCED_NODE { union { struct _RTL_BALANCED_NODE *Children[2]; struct { struct _RTL_BALANCED_NODE *Left; struct _RTL_BALANCED_NODE *Right; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; union { UCHAR Red : 1; UCHAR Balance : 2; ULONG_PTR ParentValue; } DUMMYUNIONNAME2; } RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; #ifndef RTL_BALANCED_NODE_GET_PARENT_POINTER #define RTL_BALANCED_NODE_GET_PARENT_POINTER(Node) \ ((PRTL_BALANCED_NODE)((Node)->ParentValue & ~RTL_BALANCED_NODE_RESERVED_PARENT_MASK)) #endif // // Portability // typedef struct _SINGLE_LIST_ENTRY32 { ULONG Next; } SINGLE_LIST_ENTRY32, *PSINGLE_LIST_ENTRY32; /** * The STRING32 structure is a 32-bit thunked representation of the `STRING` structure. * * \remarks Used for marshaling between 32-bit and 64-bit contexts. */ typedef struct _STRING32 { USHORT Length; USHORT MaximumLength; ULONG Buffer; } STRING32, *PSTRING32; typedef STRING32 UNICODE_STRING32, *PUNICODE_STRING32; typedef STRING32 ANSI_STRING32, *PANSI_STRING32; typedef const STRING32 *PCUNICODE_STRING32; typedef const STRING32 *PCANSI_STRING32; /** * The STRING64 structure is a 64-bit thunked representation of the `STRING` structure. * * \remarks Used for marshaling between 64-bit and 32-bit contexts. */ typedef struct _STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } STRING64, *PSTRING64; typedef STRING64 UNICODE_STRING64, *PUNICODE_STRING64; typedef STRING64 ANSI_STRING64, *PANSI_STRING64; typedef const STRING64 *PCUNICODE_STRING64; typedef const STRING64 *PCANSI_STRING64; // // Object attributes // /** * Protects the object from being closed by certain APIs (platform specific). */ #define OBJ_PROTECT_CLOSE 0x00000001L /** * This handle can be inherited by child processes of the current process. */ #define OBJ_INHERIT 0x00000002L /** * Request auditing when the object is closed. */ #define OBJ_AUDIT_OBJECT_CLOSE 0x00000004L /** * Prevents automatic rights upgrade on the object. */ #define OBJ_NO_RIGHTS_UPGRADE 0x00000008L /** * This flag only applies to objects that are named within the object manager. * By default such objects are deleted when all open handles to them are closed. * If this flag is specified, the object is not deleted when all open handles are closed. * The NtMakeTemporaryObject function can be used to delete permanent objects. */ #define OBJ_PERMANENT 0x00000010L /** * OBJ_EXCLUSIVE 0x00000020L * * Only a single handle can be open for this object. */ #define OBJ_EXCLUSIVE 0x00000020L /** * If this flag is specified, a case-insensitive comparison is used when matching the name * pointed to by the ObjectName member against the names of existing objects. * Otherwise, object names are compared using the default system settings. */ #define OBJ_CASE_INSENSITIVE 0x00000040L /** * If this flag is specified, by using the object handle, to a routine that creates objects * and if that object already exists, the routine should open that object. * Otherwise, the routine creating the object returns an NTSTATUS code of STATUS_OBJECT_NAME_COLLISION. */ #define OBJ_OPENIF 0x00000080L /** * If an object handle, with this flag set, is passed to a routine that opens objects * and if the object is a symbolic link object, the routine should open the symbolic link * object itself, rather than the object that the symbolic link refers to (which is the default behavior). */ #define OBJ_OPENLINK 0x00000100L /** * The handle is created in system process context and can only be accessed from kernel mode. */ #define OBJ_KERNEL_HANDLE 0x00000200L /** * The routine opening the handle should enforce all access checks for the object, * even if the handle is being opened in kernel mode. */ #define OBJ_FORCE_ACCESS_CHECK 0x00000400L /** * Separate device maps exists for each user in the system, and each user can manage * their own device maps. If this flag is set, the process user's device map is used * during impersonation instead of the impersonated user's device map. */ #define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x00000800L /** * If this flag is set, no reparse points will be followed when parsing the name of the associated object. * If any reparses are encountered the attempt will fail and return an STATUS_REPARSE_POINT_ENCOUNTERED result. * This can be used to determine if there are any reparse points in the object's path, in security scenarios. */ #define OBJ_DONT_REPARSE 0x00001000L /** * Mask of valid object attribute flags. */ #define OBJ_VALID_ATTRIBUTES 0x00001FF2L /** * The OBJECT_ATTRIBUTES structure specifies attributes that can be applied * to objects or object handles by routines that create objects and/or return handles to objects. * * \sa https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes */ typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PCUNICODE_STRING ObjectName; ULONG Attributes; PSECURITY_DESCRIPTOR SecurityDescriptor; PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; typedef const OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES; /** * The InitializeObjectAttributes macro initializes the opaque OBJECT_ATTRIBUTES structure, * which specifies the properties of an object handle to routines that open handles. * * \param p A pointer to the OBJECT_ATTRIBUTES structure to initialize. * \param n A pointer to a Unicode string that contains a fully qualified object name, or a relative path name for which a handle is to be opened. * \param a Specifies one or more of the OBJ_* attributes flags. * \param r A handle to the root object directory for the path name specified in the ObjectName parameter * \param s A pointer to a security descriptor to apply to an object when it is created or NULL to accept the default security for the object. * \sa https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_object_attributes */ #define InitializeObjectAttributes(p, n, a, r, s) { \ (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = NULL; \ } #define InitializeObjectAttributesEx(p, n, a, r, s, q) { \ (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ (p)->RootDirectory = r; \ (p)->Attributes = a; \ (p)->ObjectName = n; \ (p)->SecurityDescriptor = s; \ (p)->SecurityQualityOfService = q; \ } #define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) { sizeof(OBJECT_ATTRIBUTES), NULL, n, a, NULL, NULL } #define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) #define OBJ_NAME_PATH_SEPARATOR ((WCHAR)L'\\') #define OBJ_NAME_ALTPATH_SEPARATOR ((WCHAR)L'/') // // Portability // /** * The OBJECT_ATTRIBUTES64 structure is a 64-bit thunked representation of OBJECT_ATTRIBUTES. * \remarks Used for marshaling between 64-bit and 32-bit contexts. */ typedef struct _OBJECT_ATTRIBUTES64 { ULONG Length; ULONG64 RootDirectory; ULONG64 ObjectName; ULONG Attributes; ULONG64 SecurityDescriptor; ULONG64 SecurityQualityOfService; } OBJECT_ATTRIBUTES64, *POBJECT_ATTRIBUTES64; typedef const OBJECT_ATTRIBUTES64 *PCOBJECT_ATTRIBUTES64; /** * The OBJECT_ATTRIBUTES32 structure is a 32-bit thunked representation of OBJECT_ATTRIBUTES. * \remarks Used for marshaling between 32-bit and 64-bit contexts. */ typedef struct _OBJECT_ATTRIBUTES32 { ULONG Length; ULONG RootDirectory; ULONG ObjectName; ULONG Attributes; ULONG SecurityDescriptor; ULONG SecurityQualityOfService; } OBJECT_ATTRIBUTES32, *POBJECT_ATTRIBUTES32; typedef const OBJECT_ATTRIBUTES32 *PCOBJECT_ATTRIBUTES32; // // Product types // /** * The NT_PRODUCT_TYPE enum identifies the Windows product family for the operating system. */ typedef enum _NT_PRODUCT_TYPE { NtProductWinNt = 1, NtProductLanManNt, NtProductServer } NT_PRODUCT_TYPE, *PNT_PRODUCT_TYPE; /** * The SUITE_TYPE enum represents the installed Windows product suite or feature set. */ typedef enum _SUITE_TYPE { SmallBusiness, Enterprise, BackOffice, CommunicationServer, TerminalServer, SmallBusinessRestricted, EmbeddedNT, DataCenter, SingleUserTS, Personal, Blade, EmbeddedRestricted, SecurityAppliance, StorageServer, ComputeServer, WHServer, PhoneNT, MaxSuiteType } SUITE_TYPE; // // Specific // /** * The CLIENT_ID structure contains identifiers of a process and a thread. * * \sa https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsts/a11e7129-685b-4535-8d37-21d4596ac057 */ typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, *PCLIENT_ID; /** * The CLIENT_ID32 structure is a 32-bit version of CLIENT_ID. * \remarks Used for marshaling between 32-bit and 64-bit contexts. */ typedef struct _CLIENT_ID32 { ULONG UniqueProcess; ULONG UniqueThread; } CLIENT_ID32, *PCLIENT_ID32; /** * The CLIENT_ID64 structure is a 64-bit version of CLIENT_ID. * \remarks Used for marshaling between 64-bit and 32-bit contexts. */ typedef struct _CLIENT_ID64 { ULONGLONG UniqueProcess; ULONGLONG UniqueThread; } CLIENT_ID64, *PCLIENT_ID64; /** * The KSYSTEM_TIME structure represents interrupt time, system time, and time zone bias. */ typedef struct _KSYSTEM_TIME { ULONG LowPart; LONG High1Time; LONG High2Time; } KSYSTEM_TIME, *PKSYSTEM_TIME; #if defined(__INTELLISENSE__) || defined(DOXYGEN) #ifndef AFFINITY_MASK /** * The AFFINITY_MASK macro creates a single-bit affinity mask from an index. * * \param n Zero-based bit index. * \return A `KAFFINITY` mask with only bit @p n set. * \remarks Shifting by a value >= bit-width of `KAFFINITY` is undefined behavior. */ #define AFFINITY_MASK(n) ((KAFFINITY)1 << (n)) #endif #ifndef FlagOn /** * The FlagOn macro tests whether any bits in a subset are set in a flag value. * * \param _F The flag value to test. * \param _SF The subset of flags to test for. * \return Non-zero if any bits in @p _SF are set in @p _F; otherwise zero. * \remarks This returns the raw AND result (not normalized to BOOLEAN). */ #define FlagOn(_F, _SF) ((_F) & (_SF)) #endif #ifndef BooleanFlagOn /** * The BooleanFlagOn macro tests whether any bits in a subset are set and returns a BOOLEAN. * * \param F The flag value to test. * \param SF The subset of flags to test for. * \return `TRUE` if any bits in @p SF are set in @p F; otherwise `FALSE`. * \remarks The result is explicitly converted to `BOOLEAN`. */ #define BooleanFlagOn(F, SF) ((BOOLEAN)(((F) & (SF)) != 0)) #endif #ifndef SetFlag /** * The SetFlag macro sets bits in a flag value (in-place). * * \param _F The flag lvalue to modify. * \param _SF The bits to set in @p _F. * \remarks This macro modifies @p _F by OR-ing it with @p _SF. */ #define SetFlag(_F, _SF) ((_F) |= (_SF)) #endif #ifndef ClearFlag /** * The ClearFlag macro clears bits in a flag value (in-place). * * \param _F The flag lvalue to modify. * \param _SF The bits to clear from @p _F. * \remarks This macro modifies @p _F by AND-ing it with the complement of @p _SF. */ #define ClearFlag(_F, _SF) ((_F) &= ~(_SF)) #endif #ifndef Add2Ptr /** * The Add2Ptr macro adds a byte offset to a pointer. * * \param P The base pointer. * \param I The byte offset to add. * \return A pointer equal to @p P advanced by @p I bytes. * \remarks The addition is performed using `PUCHAR` arithmetic and cast to `PVOID`. */ #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I))) #endif #ifndef PtrOffset /** * The PtrOffset macro computes the byte offset between two pointers. * * \param B The base pointer. * \param O The other pointer. * \return The byte offset from @p B to @p O, cast to `ULONG`. * \remarks If the true offset does not fit in `ULONG`, truncation may occur. */ #define PtrOffset(B,O) ((ULONG)((ULONG_PTR)(O) - (ULONG_PTR)(B))) #endif #ifndef ALIGN_DOWN_BY /** * The ALIGN_DOWN_BY macro aligns a value down to a specified alignment boundary. * * \param Length The value to align. * \param Alignment The alignment boundary in bytes (typically a power of two). * \return @p Length rounded down to the nearest multiple of @p Alignment. * \remarks Non power-of-two alignments may produce unexpected results. */ #define ALIGN_DOWN_BY(Length, Alignment) ((ULONG_PTR)(Length) & ~((ULONG_PTR)(Alignment) - 1)) #endif #ifndef ALIGN_UP_BY /** * The ALIGN_UP_BY macro aligns a value up to a specified alignment boundary. * * \param Length The value to align. * \param Alignment The alignment boundary in bytes (typically a power of two). * \return @p Length rounded up to the nearest multiple of @p Alignment. * \remarks This uses ALIGN_DOWN_BY after adding (@p Alignment - 1). */ #define ALIGN_UP_BY(Length, Alignment) (ALIGN_DOWN_BY(((ULONG_PTR)(Length) + (Alignment) - 1), Alignment)) #endif #ifndef ALIGN_DOWN_POINTER_BY /** * The ALIGN_DOWN_POINTER_BY macro aligns a pointer down to a specified alignment boundary. * * \param Address The pointer to align. * \param Alignment The alignment boundary in bytes (typically a power of two). * \return A pointer at or below @p Address aligned down to @p Alignment. * \remarks The pointer is treated as an integer (`ULONG_PTR`) for masking. */ #define ALIGN_DOWN_POINTER_BY(Address, Alignment) ((PVOID)ALIGN_DOWN_BY(Address, Alignment)) #endif #ifndef ALIGN_UP_POINTER_BY /** * The ALIGN_UP_POINTER_BY macro aligns a pointer up to a specified alignment boundary. * * \param Address The pointer to align. * \param Alignment The alignment boundary in bytes (typically a power of two). * \return A pointer at or above @p Address aligned up to @p Alignment. * \remarks This is a pointer wrapper over ALIGN_UP_BY. */ #define ALIGN_UP_POINTER_BY(Address, Alignment) ((PVOID)ALIGN_UP_BY(Address, Alignment)) #endif #ifndef ALIGN_DOWN /** * The ALIGN_DOWN macro aligns a value down using sizeof(Type) as the boundary. * * \param Length The value to align. * \param Type The type whose size is used as the alignment boundary. * \return @p Length rounded down to the nearest multiple of sizeof(@p Type). * \remarks This is a convenience wrapper over ALIGN_DOWN_BY. */ #define ALIGN_DOWN(Length, Type) ALIGN_DOWN_BY(Length, sizeof(Type)) #endif #ifndef ALIGN_UP /** * The ALIGN_UP macro aligns a value up using sizeof(Type) as the boundary. * * \param Length The value to align. * \param Type The type whose size is used as the alignment boundary. * \return @p Length rounded up to the nearest multiple of sizeof(@p Type). * \remarks This is a convenience wrapper over ALIGN_UP_BY. */ #define ALIGN_UP(Length, Type) ALIGN_UP_BY(Length, sizeof(Type)) #endif #ifndef ALIGN_DOWN_POINTER /** * The ALIGN_DOWN_POINTER macro aligns a pointer down using sizeof(Type) as the boundary. * * \param Address The pointer to align. * \param Type The type whose size is used as the alignment boundary. * \return A pointer at or below @p Address aligned down to sizeof(@p Type). * \remarks This is a convenience wrapper over ALIGN_DOWN_POINTER_BY. */ #define ALIGN_DOWN_POINTER(Address, Type) ALIGN_DOWN_POINTER_BY(Address, sizeof(Type)) #endif #ifndef ALIGN_UP_POINTER /** * The ALIGN_UP_POINTER macro aligns a pointer up using sizeof(Type) as the boundary. * * \param Address The pointer to align. * \param Type The type whose size is used as the alignment boundary. * \return A pointer at or above @p Address aligned up to sizeof(@p Type). * \remarks This is a convenience wrapper over ALIGN_UP_POINTER_BY. */ #define ALIGN_UP_POINTER(Address, Type) ALIGN_UP_POINTER_BY(Address, sizeof(Type)) #endif #ifndef IS_ALIGNED /** * The IS_ALIGNED macro tests whether an address is aligned to a given boundary. * * \param Address The address/pointer value to test. * \param Alignment The alignment boundary in bytes (typically a power of two). * \return Non-zero if @p Address is aligned to @p Alignment; otherwise zero. * \remarks The test checks that the low bits masked by (@p Alignment - 1) are zero. */ #define IS_ALIGNED(Address, Alignment) ((((ULONG_PTR)(Address)) & ((Alignment) - 1)) == 0) #endif #ifndef PAGE_SIZE /** * The PAGE_SIZE macro defines the assumed system page size in bytes. * * \return The page size in bytes (default 0x1000). * \remarks This assumes 4 KiB pages. */ #define PAGE_SIZE 0x1000 #endif #ifndef PAGE_MASK /** * The PAGE_MASK macro defines the mask for offsets within a page. * * \return The page offset mask (default 0xFFF). * \remarks This is typically PAGE_SIZE - 1 for power-of-two page sizes. */ #define PAGE_MASK 0xFFF #endif #ifndef PAGE_SHIFT /** * The PAGE_SHIFT macro defines the bit shift corresponding to PAGE_SIZE. * * \return The shift value (default 0xC, i.e., 12). * \remarks For 4 KiB pages, PAGE_SHIFT is 12 because 2^12 = 4096. */ #define PAGE_SHIFT 0xC #endif #ifndef BYTE_OFFSET /** * The BYTE_OFFSET macro returns the byte offset of an address within its page. * * \param Address The address/pointer value. * \return The offset in bytes within the containing page. * \remarks This masks the address with PAGE_MASK. */ #define BYTE_OFFSET(Address) ((SIZE_T)((ULONG_PTR)(Address) & PAGE_MASK)) #endif #ifndef PAGE_ALIGN /** * The PAGE_ALIGN macro aligns an address down to the base of its page. * * \param Address The address/pointer value. * \return The page-aligned base address containing @p Address. * \remarks This clears the low bits specified by PAGE_MASK. */ #define PAGE_ALIGN(Address) ((PVOID)((ULONG_PTR)(Address) & ~PAGE_MASK)) #endif #ifndef PAGE_OFFSET /** * The PAGE_OFFSET macro returns the offset of a pointer within its page. * * \param p The pointer value. * \return The offset in bytes within the page (0..PAGE_MASK). * \remarks This is equivalent to (PAGE_MASK & (ULONG_PTR)p). */ #define PAGE_OFFSET(p) ((PAGE_MASK) & (ULONG_PTR)(p)) #endif #ifndef PAGE_TAILSIZE /** * The PAGE_TAILSIZE macro returns the number of bytes from a pointer to the end of its page. * * \param p The pointer value. * \return The remaining bytes in the page starting at @p p. * \remarks This is computed as PAGE_SIZE - PAGE_OFFSET(p). */ #define PAGE_TAILSIZE(p) (PAGE_SIZE - PAGE_OFFSET(p)) #endif #else #ifndef AFFINITY_MASK #define AFFINITY_MASK(n) ((KAFFINITY)1 << (n)) #endif #ifndef FlagOn #define FlagOn(_F, _SF) ((_F) & (_SF)) #endif #ifndef BooleanFlagOn #define BooleanFlagOn(F, SF) ((BOOLEAN)(((F) & (SF)) != 0)) #endif #ifndef SetFlag #define SetFlag(_F, _SF) ((_F) |= (_SF)) #endif #ifndef ClearFlag #define ClearFlag(_F, _SF) ((_F) &= ~(_SF)) #endif #ifndef Add2Ptr #define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I))) #endif #ifndef PtrOffset #define PtrOffset(B,O) ((ULONG)((ULONG_PTR)(O) - (ULONG_PTR)(B))) #endif #ifndef ALIGN_DOWN_BY #define ALIGN_DOWN_BY(Length, Alignment) ((ULONG_PTR)(Length) & ~((ULONG_PTR)(Alignment) - 1)) #endif #ifndef ALIGN_UP_BY #define ALIGN_UP_BY(Length, Alignment) (ALIGN_DOWN_BY(((ULONG_PTR)(Length) + (Alignment) - 1), Alignment)) #endif #ifndef ALIGN_DOWN_POINTER_BY #define ALIGN_DOWN_POINTER_BY(Address, Alignment) ((PVOID)ALIGN_DOWN_BY(Address, Alignment)) #endif #ifndef ALIGN_UP_POINTER_BY #define ALIGN_UP_POINTER_BY(Address, Alignment) ((PVOID)ALIGN_UP_BY(Address, Alignment)) #endif #ifndef ALIGN_DOWN #define ALIGN_DOWN(Length, Type) ALIGN_DOWN_BY(Length, sizeof(Type)) #endif #ifndef ALIGN_UP #define ALIGN_UP(Length, Type) ALIGN_UP_BY(Length, sizeof(Type)) #endif #ifndef ALIGN_DOWN_POINTER #define ALIGN_DOWN_POINTER(Address, Type) ALIGN_DOWN_POINTER_BY(Address, sizeof(Type)) #endif #ifndef ALIGN_UP_POINTER #define ALIGN_UP_POINTER(Address, Type) ALIGN_UP_POINTER_BY(Address, sizeof(Type)) #endif #ifndef IS_ALIGNED #define IS_ALIGNED(Address, Alignment) ((((ULONG_PTR)(Address)) & ((Alignment) - 1)) == 0) #endif #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 #endif #ifndef PAGE_MASK #define PAGE_MASK 0xFFF #endif #ifndef PAGE_SHIFT #define PAGE_SHIFT 0xC #endif #ifndef BYTE_OFFSET #define BYTE_OFFSET(Address) ((SIZE_T)((ULONG_PTR)(Address) & PAGE_MASK)) #endif #ifndef PAGE_ALIGN #define PAGE_ALIGN(Address) ((PVOID)((ULONG_PTR)(Address) & ~PAGE_MASK)) #endif #ifndef PAGE_OFFSET #define PAGE_OFFSET(p) ((PAGE_MASK) & (ULONG_PTR)(p)) #endif #ifndef PAGE_TAILSIZE #define PAGE_TAILSIZE(p) (PAGE_SIZE - PAGE_OFFSET(p)) #endif #ifndef ADDRESS_AND_SIZE_TO_SPAN_PAGES #define ADDRESS_AND_SIZE_TO_SPAN_PAGES(Address, Size) ((BYTE_OFFSET(Address) + ((SIZE_T)(Size)) + PAGE_MASK) >> PAGE_SHIFT) #endif #ifndef ROUND_TO_SIZE #define ROUND_TO_SIZE(Size, Alignment) ((((ULONG_PTR)(Size)) + ((Alignment) - 1)) & ~(ULONG_PTR)((Alignment) - 1)) #endif #ifndef ROUND_TO_PAGES #define ROUND_TO_PAGES(Size) (((ULONG_PTR)(Size) + PAGE_MASK) & ~PAGE_MASK) #endif #ifndef BYTES_TO_PAGES #define BYTES_TO_PAGES(Size) (((Size) >> PAGE_SHIFT) + (((Size) & PAGE_MASK) != 0)) #endif #endif // defined(__INTELLISENSE__) || defined(DOXYGEN) #ifdef _DEBUG #ifndef ASSERT #define ASSERT( exp ) \ ((!(exp)) ? \ (RtlAssert( (PVOID)#exp, (PVOID)__FILE__, __LINE__, NULL ),FALSE) : \ TRUE) #endif #ifndef ASSERTMSG #define ASSERTMSG( msg, exp ) \ ((!(exp)) ? \ (RtlAssert( (PVOID)#exp, (PVOID)__FILE__, __LINE__, (PSTR)msg ),FALSE) : \ TRUE) #endif #ifndef RTL_SOFT_ASSERT #define RTL_SOFT_ASSERT(_exp) \ ((!(_exp)) ? \ (DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n", __FILE__, __LINE__, #_exp),FALSE) : \ TRUE) #endif #ifndef RTL_SOFT_ASSERTMSG #define RTL_SOFT_ASSERTMSG(_msg, _exp) \ ((!(_exp)) ? \ (DbgPrint("%s(%d): Soft assertion failed\n Expression: %s\n Message: %s\n", __FILE__, __LINE__, #_exp, (_msg)),FALSE) : \ TRUE) #endif #ifndef RTL_VERIFY #define RTL_VERIFY ASSERT #endif #ifndef RTL_VERIFYMSG #define RTL_VERIFYMSG ASSERTMSG #endif #ifndef RTL_SOFT_VERIFY #define RTL_SOFT_VERIFY RTL_SOFT_ASSERT #endif #ifndef RTL_SOFT_VERIFYMSG #define RTL_SOFT_VERIFYMSG RTL_SOFT_ASSERTMSG #endif #else // _DEBUG #ifndef ASSERT #define ASSERT( exp ) ((void) 0) #endif #ifndef ASSERTMSG #define ASSERTMSG( msg, exp ) ((void) 0) #endif #ifndef RTL_SOFT_ASSERT #define RTL_SOFT_ASSERT(_exp) ((void) 0) #endif #ifndef RTL_SOFT_ASSERTMSG #define RTL_SOFT_ASSERTMSG(_msg, _exp) ((void) 0) #endif #ifndef RTL_VERIFY #define RTL_VERIFY( exp ) ((exp) ? TRUE : FALSE) #endif #ifndef RTL_VERIFYMSG #define RTL_VERIFYMSG( msg, exp ) ((exp) ? TRUE : FALSE) #endif #ifndef RTL_SOFT_VERIFY #define RTL_SOFT_VERIFY(_exp) ((_exp) ? TRUE : FALSE) #endif #ifndef RTL_SOFT_VERIFYMSG #define RTL_SOFT_VERIFYMSG(msg, _exp) ((_exp) ? TRUE : FALSE) #endif #endif // _DEBUG #ifndef RTL_ASSERT #define RTL_ASSERT ASSERT #endif #ifndef RTL_ASSERTMSG #define RTL_ASSERTMSG ASSERTMSG #endif #ifndef NT_ANALYSIS_ASSUME #if defined(_PREFAST_) #define NT_ANALYSIS_ASSUME(_exp) _Analysis_assume_(_exp) #else // _PREFAST_ #ifdef _DEBUG #define NT_ANALYSIS_ASSUME(_exp) ((void) 0) #else // _DEBUG #define NT_ANALYSIS_ASSUME(_exp) __noop(_exp) #endif // _DEBUG #endif // _PREFAST_ #endif // NT_ANALYSIS_ASSUME #ifndef NT_ASSERT_ACTION #define NT_ASSERT_ACTION(_exp) \ ((!(_exp)) ? \ (__annotation(L"Debug", L"AssertFail", L## #_exp), \ DbgRaiseAssertionFailure(), FALSE) : \ TRUE) #endif #ifndef NT_ASSERTMSG_ACTION #define NT_ASSERTMSG_ACTION(_msg, _exp) \ ((!(_exp)) ? \ (__annotation(L"Debug", L"AssertFail", L##_msg), \ DbgRaiseAssertionFailure(), FALSE) : \ TRUE) #endif #ifndef NT_ASSERTMSGW_ACTION #define NT_ASSERTMSGW_ACTION(_msg, _exp) \ ((!(_exp)) ? \ (__annotation(L"Debug", L"AssertFail", _msg), \ DbgRaiseAssertionFailure(), FALSE) : \ TRUE) #endif #ifdef _DEBUG #ifndef NT_ASSERT_ASSUME #define NT_ASSERT_ASSUME(_exp) \ (NT_ANALYSIS_ASSUME(_exp), NT_ASSERT_ACTION(_exp)) #endif #ifndef NT_ASSERTMSG_ASSUME #define NT_ASSERTMSG_ASSUME(_msg, _exp) \ (NT_ANALYSIS_ASSUME(_exp), NT_ASSERTMSG_ACTION(_msg, _exp)) #endif #ifdef NT_ASSERTMSGW_ASSUME #define NT_ASSERTMSGW_ASSUME(_msg, _exp) \ (NT_ANALYSIS_ASSUME(_exp), NT_ASSERTMSGW_ACTION(_msg, _exp)) #endif #ifndef NT_ASSERT_NOASSUME #define NT_ASSERT_NOASSUME NT_ASSERT_ASSUME #endif #ifndef NT_ASSERTMSG_NOASSUME #define NT_ASSERTMSG_NOASSUME NT_ASSERTMSG_ASSUME #endif #ifndef NT_ASSERTMSGW_NOASSUME #define NT_ASSERTMSGW_NOASSUME NT_ASSERTMSGW_ASSUME #endif #ifndef NT_VERIFY #define NT_VERIFY NT_ASSERT #endif #ifndef NT_VERIFYMSG #define NT_VERIFYMSG NT_ASSERTMSG #endif #ifndef NT_VERIFYMSGW #define NT_VERIFYMSGW NT_ASSERTMSGW #endif #else // _DEBUG #ifndef NT_ASSERT_ASSUME #define NT_ASSERT_ASSUME(_exp) (NT_ANALYSIS_ASSUME(_exp), 0) #endif #ifndef NT_ASSERTMSG_ASSUME #define NT_ASSERTMSG_ASSUME(_msg, _exp) (NT_ANALYSIS_ASSUME(_exp), 0) #endif #ifndef NT_ASSERTMSGW_ASSUME #define NT_ASSERTMSGW_ASSUME(_msg, _exp) (NT_ANALYSIS_ASSUME(_exp), 0) #endif #ifndef NT_ASSERT_NOASSUME #define NT_ASSERT_NOASSUME(_exp) ((void) 0) #endif #ifndef NT_ASSERTMSG_NOASSUME #define NT_ASSERTMSG_NOASSUME(_msg, _exp) ((void) 0) #endif #ifndef NT_ASSERTMSGW_NOASSUME #define NT_ASSERTMSGW_NOASSUME(_msg, _exp) ((void) 0) #endif #ifndef NT_VERIFY #define NT_VERIFY(_exp) (NT_ANALYSIS_ASSUME(_exp), ((_exp) ? TRUE : FALSE)) #endif #ifndef NT_VERIFYMSG #define NT_VERIFYMSG(_msg, _exp ) (NT_ANALYSIS_ASSUME(_exp), ((_exp) ? TRUE : FALSE)) #endif #ifndef NT_VERIFYMSGW #define NT_VERIFYMSGW(_msg, _exp) (NT_ANALYSIS_ASSUME(_exp), ((_exp) ? TRUE : FALSE)) #endif #endif // _DEBUG #ifndef NT_FRE_ASSERT #define NT_FRE_ASSERT(_exp) (NT_ANALYSIS_ASSUME(_exp), NT_ASSERT_ACTION(_exp)) #endif #ifndef NT_FRE_ASSERTMSG #define NT_FRE_ASSERTMSG(_msg, _exp) (NT_ANALYSIS_ASSUME(_exp), NT_ASSERTMSG_ACTION(_msg, _exp)) #endif #ifndef NT_FRE_ASSERTMSGW #define NT_FRE_ASSERTMSGW(_msg, _exp) (NT_ANALYSIS_ASSUME(_exp), NT_ASSERTMSGW_ACTION(_msg, _exp)) #endif #ifdef NT_ASSERT_ALWAYS_ASSUMES #ifndef NT_ASSERT #define NT_ASSERT NT_ASSERT_ASSUME #endif #ifndef NT_ASSERTMSG #define NT_ASSERTMSG NT_ASSERTMSG_ASSUME #endif #ifndef NT_ASSERTMSGW #define NT_ASSERTMSGW NT_ASSERTMSGW_ASSUME #endif #else // NT_ASSERT_ALWAYS_ASSUMES #ifndef NT_ASSERT #define NT_ASSERT NT_ASSERT_NOASSUME #endif #ifndef NT_ASSERTMSG #define NT_ASSERTMSG NT_ASSERTMSG_NOASSUME #endif #ifndef NT_ASSERTMSGW #define NT_ASSERTMSGW NT_ASSERTMSGW_NOASSUME #endif #endif // NT_ASSERT_ALWAYS_ASSUMES #endif // _NTDEF_ #endif // _PHNT_NTDEF_H