#ifndef COMMON_H
#define COMMON_H

#include <ntifs.h>
#include <wdftypes.h>
#include "io.h"

#include "types/types.h"

/*
 * For numbers < 32, these are equivalent to 0ul < x.
 *
 * For an item to be printed, its bitwise AND'd with the set filter. If the result is non zero the
 * log will be printed.
 */
#define LOG_ERROR_LEVEL   1
#define LOG_WARNING_LEVEL 2
#define LOG_INFO_LEVEL    3
#define LOG_VERBOSE_LEVEL 4

#define DPFLTR_MASK 0x80000000

#define DEBUG_ERROR(fmt, ...) \
        DbgPrintEx(           \
            DPFLTR_DEFAULT_ID, LOG_ERROR_LEVEL, "donna-ac : [ERROR] ::: " fmt "\n", ##__VA_ARGS__)

#define DEBUG_WARNING(fmt, ...)                        \
        DbgPrintEx(DPFLTR_DEFAULT_ID,                  \
                   LOG_WARNING_LEVEL,                  \
                   "donna-ac : [WARNING] : " fmt "\n", \
                   ##__VA_ARGS__)

#define DEBUG_INFO(fmt, ...) \
        DbgPrintEx(          \
            DPFLTR_DEFAULT_ID, LOG_INFO_LEVEL, "donna-ac : [INFO] :::: " fmt "\n", ##__VA_ARGS__)

#define DEBUG_VERBOSE(fmt, ...)                        \
        DbgPrintEx(DPFLTR_DEFAULT_ID,                  \
                   LOG_VERBOSE_LEVEL,                  \
                   "donna-ac : [VERBOSE] : " fmt "\n", \
                   ##__VA_ARGS__)

#define STATIC static
#define INLINE inline

#define MAX_MODULE_PATH 256

/*
 * Interlocked intrinsics are only atomic with respect to other InterlockedXxx functions,
 * so all reads and writes to the THREAD_LIST->active flag must be with Interlocked instrinsics
 * to ensure atomicity.
 */
typedef struct _THREAD_LIST_HEAD
{
        SINGLE_LIST_ENTRY start;
        volatile BOOLEAN  active;
        KGUARDED_MUTEX    lock;
        LOOKASIDE_LIST_EX lookaside_list;

} THREAD_LIST_HEAD, *PTHREAD_LIST_HEAD;

typedef struct _PROCESS_LIST_HEAD
{
        SINGLE_LIST_ENTRY start;
        volatile BOOLEAN  active;
        KGUARDED_MUTEX    lock;
        LOOKASIDE_LIST_EX lookaside_list;

} PROCESS_LIST_HEAD, *PPROCESS_LIST_HEAD;

typedef struct _DRIVER_LIST_HEAD
{
        SINGLE_LIST_ENTRY start;
        volatile ULONG    count;
        volatile BOOLEAN  active;
        KGUARDED_MUTEX    lock;

} DRIVER_LIST_HEAD, *PDRIVER_LIST_HEAD;

typedef struct _THREAD_LIST_ENTRY
{
        SINGLE_LIST_ENTRY list;
        PKTHREAD          thread;
        PKPROCESS         owning_process;
        BOOLEAN           apc_queued;
        PKAPC             apc;

} THREAD_LIST_ENTRY, *PTHREAD_LIST_ENTRY;

typedef struct _PROCESS_LIST_ENTRY
{
        SINGLE_LIST_ENTRY list;
        PKPROCESS         process;
        PKPROCESS         parent;

} PROCESS_LIST_ENTRY, *PPROCESS_LIST_ENTRY;

/*
 * ioctl_flag consists of the first 16 bits of the Function part of the CTL code
 * cookie_value consists of a static 16 bit value generated by the user mode app on startup
 * which is then passed to the driver and stored.
 */
typedef union _SECURITY_COOKIE
{
        struct
        {
                UINT32 ioctl_flag : 16;
                UINT32 cookie_value : 16;
        } bits;

        UINT32 flags;

} SECURITY_COOKIE, *PSECURITY_COOKIE;

typedef struct _TIMER_OBJECT
{
        /*
         * state = 1: callback in progress
         * state = 0: no callback in progress (i.e safe to free and unregister)
         */
        volatile LONG state;

        KTIMER       timer;
        KDPC         dpc;
        PIO_WORKITEM work_item;

} TIMER_OBJECT, *PTIMER_OBJECT;

typedef enum _ENVIRONMENT_TYPE
{
        NativeWindows = 0,
        Vmware,
        VirtualBox

} ENVIRONMENT_TYPE;

typedef enum _PROCESSOR_TYPE
{
        Unknown = 0,
        GenuineIntel,
        AuthenticAmd

} PROCESSOR_TYPE;

#define VENDOR_STRING_MAX_LENGTH 256

#define DRIVER_PATH_MAX_LENGTH            512
#define MOTHERBOARD_SERIAL_CODE_LENGTH    64
#define DEVICE_DRIVE_0_SERIAL_CODE_LENGTH 64

#define MAX_REPORTS_PER_IRP 20

#define POOL_TAG_STRINGS 'strs'

#define IOCTL_STORAGE_QUERY_PROPERTY 0x002D1400

#define MAXIMUM_APC_CONTEXTS 10

typedef struct _SYSTEM_INFORMATION
{
        CHAR               motherboard_serial[MOTHERBOARD_SERIAL_CODE_LENGTH];
        CHAR               drive_0_serial[DEVICE_DRIVE_0_SERIAL_CODE_LENGTH];
        CHAR               vendor[VENDOR_STRING_MAX_LENGTH];
        BOOLEAN            virtualised_environment;
        ENVIRONMENT_TYPE   environment;
        PROCESSOR_TYPE     processor;
        RTL_OSVERSIONINFOW os_information;

} SYSTEM_INFORMATION, *PSYSTEM_INFORMATION;

typedef struct _OB_CALLBACKS_CONFIG
{
        PVOID          registration_handle;
        KGUARDED_MUTEX lock;

} OB_CALLBACKS_CONFIG, *POB_CALLBACKS_CONFIG;

typedef struct _DEFERRED_REPORT
{
        LIST_ENTRY list_entry;
        PVOID      buffer;
        UINT32     buffer_size;

} DEFERRED_REPORT, *PDEFERRED_REPORT;

typedef struct _DEFERRED_REPORTS_HEAD
{
        LIST_ENTRY     head;
        UINT32         count;
        KGUARDED_MUTEX lock;

} DEFERRED_REPORTS_HEAD, *PDEFERRED_REPORTS_HEAD;

typedef struct _IRP_QUEUE_HEAD
{
        LIST_ENTRY            queue;
        volatile UINT32       count;
        IO_CSQ                csq;
        KGUARDED_MUTEX        lock;
        DEFERRED_REPORTS_HEAD reports;

} IRP_QUEUE_HEAD, *PIRP_QUEUE_HEAD;

typedef struct _IRP_QUEUE_ENTRY
{
        SINGLE_LIST_ENTRY entry;
        PIRP              irp;

} IRP_QUEUE_ENTRY, *PIRP_QUEUE_ENTRY;

/*
 * This structure can change at anytime based on whether
 * the target process to protect is open / closed / changes etc.
 */

#define AES_128_KEY_SIZE 16

typedef struct _ACTIVE_SESSION
{
        BOOLEAN             is_session_active;
        PVOID               um_handle;
        PVOID               km_handle;
        PEPROCESS           process;
        OB_CALLBACKS_CONFIG callback_configuration;

        UINT32 session_cookie;
        CHAR   session_aes_key[AES_128_KEY_SIZE];

        KGUARDED_MUTEX lock;

} ACTIVE_SESSION, *PACTIVE_SESSION;

#define NMI_CONTEXT_POOL               '7331'
#define STACK_FRAMES_POOL              'loop'
#define INVALID_DRIVER_LIST_HEAD_POOL  'rwar'
#define INVALID_DRIVER_LIST_ENTRY_POOL 'gaah'
#define POOL_TAG_APC                   'apcc'
#define POOL_TAG_DPC                   'apcc'
#define SYSTEM_MODULES_POOL            'halb'
#define THREAD_DATA_POOL               'doof'
#define PROC_AFFINITY_POOL             'eeee'
#define TEMP_BUFFER_POOL               'ffff'
#define DRIVER_PATH_POOL_TAG           'path'
#define POOL_TAG_INTEGRITY             'intg'
#define POOL_TAG_MODULE_MEMORY_BUF     'lolo'
#define POOL_TAG_MODULE_MEMORY_BUF_2   'leeo'
#define POOL_TAG_HASH_OBJECT           'hobj'
#define POOL_TAG_RESULTING_HASH        'hash'
#define POOL_TAG_SAVE_EX_REGIONS       'sexc'
#define POOL_DUMP_BLOCK_TAG            'dump'
#define POOL_DEBUGGER_DATA_TAG         'data'
#define PROCESS_ADDRESS_LIST_TAG       'addr'
#define ANALYSE_PROCESS_TAG            'anls'
#define INVALID_PROCESS_REPORT_TAG     'invd'
#define QUEUE_POOL_TAG                 'qqqq'
#define REPORT_QUEUE_TEMP_BUFFER_TAG   'temp'
#define REPORT_POOL_TAG                'repo'
#define MODULES_REPORT_POOL_TAG        'modu'
#define POOL_TAG_LIST_ITEM             'tsil'
#define POOL_TAG_THREAD_LIST           'list'
#define POOL_TAG_PROCESS_LIST          'plis'
#define POOL_TAG_DRIVER_LIST           'drvl'
#define POOL_TAG_IRP_QUEUE             'irpp'
#define POOL_TAG_TIMER                 'time'

#define IA32_APERF_MSR 0x000000E8

#define ERROR                 -1
#define STACK_FRAME_POOL_SIZE 0x200
#define NUMBER_HASH_BUCKETS   37

#define KTHREAD_STACK_BASE_OFFSET    0x030
#define KTHREAD_STACK_LIMIT_OFFSET   0x038
#define KTHREAD_THREADLIST_OFFSET    0x2f8
#define KTHREAD_APC_STATE_OFFSET     0x098
#define KTHREAD_START_ADDRESS_OFFSET 0x450
#define KTHREAD_MISC_FLAGS_OFFSET    0x074
#define KTHREAD_WAIT_IRQL_OFFSET     0x186
#define KTHREAD_PREVIOUS_MODE_OFFSET 0x232
#define KTHREAD_STATE_OFFSET         0x184

#define KTHREAD_MISC_FLAGS_APC_QUEUEABLE 14
#define KTHREAD_MISC_FLAGS_ALERTABLE     4

#define EPROCESS_PEAK_VIRTUAL_SIZE_OFFSET 0x490
#define EPROCESS_VAD_ROOT_OFFSET          0x7d8
#define EPROCESS_OBJECT_TABLE_OFFSET      0x570
#define EPROCESS_IMAGE_NAME_OFFSET        0x5a8
#define EPROCESS_PEB_OFFSET               0x550
#define EPROCESS_SECTION_BASE_OFFSET      0x520
#define EPROCESS_IMAGE_FILE_NAME_OFFSET   0x5a8
#define EPROCESS_HANDLE_TABLE_OFFSET      0x570
#define EPROCESS_PLIST_ENTRY_OFFSET       0x448

#define KPROCESS_THREADLIST_OFFSET           0x030
#define KPROCESS_DIRECTORY_TABLE_BASE_OFFSET 0x028

#define OBJECT_HEADER_SIZE              0x30
#define OBJECT_HEADER_TYPE_INDEX_OFFSET 0x018

#define POOL_HEADER_BLOCK_SIZE_OFFSET 0x02
#define POOL_HEADER_TAG_OFFSET        0x04

#define KPROCESS_OFFSET_FROM_POOL_HEADER_SIZE_1 0x70
#define KPROCESS_OFFSET_FROM_POOL_HEADER_SIZE_2 0x80
#define KPROCESS_OFFSET_FROM_POOL_HEADER_SIZE_3 0x30
#define EPROCESS_SIZE                           0xa40

#define KPCRB_CURRENT_THREAD 0x8

#define IA32_GS_BASE              0xc0000101
#define KPRCB_OFFSET_FROM_GS_BASE 0x180

#define MODULE_VALIDATION_FAILURE_MAX_REPORT_COUNT 20

#define IMAGE_DIRECTORY_ENTRY_EXPORT         0
#define IMAGE_DIRECTORY_ENTRY_IMPORT         1
#define IMAGE_DIRECTORY_ENTRY_RESOURCE       2
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION      3
#define IMAGE_DIRECTORY_ENTRY_SECURITY       4
#define IMAGE_DIRECTORY_ENTRY_BASERELOC      5
#define IMAGE_DIRECTORY_ENTRY_DEBUG          6
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT      7
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR      8 /* (MIPS GP) */
#define IMAGE_DIRECTORY_ENTRY_TLS            9
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11
#define IMAGE_DIRECTORY_ENTRY_IAT            12 /* Import Address Table */
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14

/*
 * Generic macros that allow you to quickly determine whether
 *  or not a page table entry is present or may forward to a
 *  large page of data, rather than another page table (applies
 *  only to PDPTEs and PDEs)
 *
 * Some nice macros courtesy of:
 * https://www.unknowncheats.me/forum/general-programming-and-reversing/523359-introduction-physical-memory.html
 */
#define IS_LARGE_PAGE(x)   ((BOOLEAN)((x >> 7) & 1))
#define IS_PAGE_PRESENT(x) ((BOOLEAN)(x & 1))

#define PAGE_1GB_SHIFT     30
#define PAGE_1GB_OFFSET(x) (x & (~(MAXUINT64 << PAGE_1GB_SHIFT)))

#define PAGE_2MB_SHIFT     21
#define PAGE_2MB_OFFSET(x) (x & (~(MAXUINT64 << PAGE_2MB_SHIFT)))

#define PAGE_4KB_SHIFT     12
#define PAGE_4KB_OFFSET(x) (x & (~(MAXUINT64 << PAGE_4KB_SHIFT)))

typedef struct _KAFFINITY_EX
{
        USHORT    Count;
        USHORT    Size;
        ULONG     Reserved;
        ULONGLONG Bitmap[20];

} KAFFINITY_EX, *PKAFFINITY_EX;

typedef struct _OBJECT_DIRECTORY_ENTRY
{
        struct _OBJECT_DIRECTORY_ENTRY* ChainLink;
        PVOID                           Object;
        ULONG                           HashValue;

} OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY;

typedef struct _OBJECT_DIRECTORY
{
        POBJECT_DIRECTORY_ENTRY HashBuckets[NUMBER_HASH_BUCKETS];
        EX_PUSH_LOCK            Lock;
        struct _DEVICE_MAP*     DeviceMap;
        ULONG                   SessionId;
        PVOID                   NamespaceEntry;
        ULONG                   Flags;

} OBJECT_DIRECTORY, *POBJECT_DIRECTORY;

typedef struct _DEVICE_MAP
{
        struct _OBJECT_DIRECTORY* DosDevicesDirectory;
        struct _OBJECT_DIRECTORY* GlobalDosDevicesDirectory;
        ULONG                     ReferenceCount;
        ULONG                     DriveMap;
        UCHAR                     DriveType[32];

} DEVICE_MAP, *PDEVICE_MAP;

typedef struct _RTL_MODULE_EXTENDED_INFO
{
        PVOID  ImageBase;
        ULONG  ImageSize;
        USHORT FileNameOffset;
        CHAR   FullPathName[0x100];

} RTL_MODULE_EXTENDED_INFO, *PRTL_MODULE_EXTENDED_INFO;

/*
Thread Information Block: (GS register)

        SEH frame:						0x00
        Stack Base:						0x08
        Stack Limit:					0x10
        SubSystemTib:					0x18
        Fiber Data:						0x20
        Arbitrary Data:					0x28
        TEB:							0x30
        Environment Pointer:			0x38
        Process ID:						0x40
        Current Thread ID:				0x48
        Active RPC Handle:				0x50
        Thread Local Storage Array:		0x58
        PEB:							0x60
        Last error number:				0x68
        Count Owned Critical Sections:  0x6C
        CSR Client Thread:				0x70
        Win32 Thread Information:		0x78
        ...
*/

typedef struct _OBJECT_TYPE
{
        LIST_ENTRY     TypeList;
        UNICODE_STRING Name;
        PVOID          DefaultObject;
        UCHAR          Index;
        ULONG          TotalNumberOfObjects;
        ULONG          TotalNumberOfHandles;
        ULONG          HighWaterNumberOfObjects;
        ULONG          HighWaterNumberOfHandles;
        PVOID          TypeInfo; //_OBJECT_TYPE_INITIALIZER
        EX_PUSH_LOCK   TypeLock;
        ULONG          Key;
        LIST_ENTRY     CallbackList;

} OBJECT_TYPE, *POBJECT_TYPE;

typedef struct _PEB_LDR_DATA
{
        BYTE       Reserved1[8];
        PVOID      Reserved2[3];
        LIST_ENTRY InMemoryOrderModuleList;
} PEB_LDR_DATA, *PPEB_LDR_DATA;

typedef struct _LDR_DATA_TABLE_ENTRY
{
        PVOID          Reserved1[2];
        LIST_ENTRY     InMemoryOrderLinks;
        PVOID          Reserved2[2];
        PVOID          DllBase;
        PVOID          Reserved3[2];
        UNICODE_STRING FullDllName;
        BYTE           Reserved4[8];
        PVOID          Reserved5[3];
#pragma warning(push)
#pragma warning(disable : 4201) // we'll always use the Microsoft compiler
        union
        {
                ULONG CheckSum;
                PVOID Reserved6;
        } DUMMYUNIONNAME;
#pragma warning(pop)
        ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

typedef struct _PEB
{
        BYTE          Reserved1[2];
        BYTE          BeingDebugged;
        BYTE          Reserved2[1];
        PVOID         Reserved3[2];
        PPEB_LDR_DATA Ldr;
        PVOID         ProcessParameters;
        PVOID         Reserved4[3];
        PVOID         AtlThunkSListPtr;
        PVOID         Reserved5;
        ULONG         Reserved6;
        PVOID         Reserved7;
        ULONG         Reserved8;
        ULONG         AtlThunkSListPtr32;
        PVOID         Reserved9[45];
        BYTE          Reserved10[96];
        PVOID         PostProcessInitRoutine;
        BYTE          Reserved11[128];
        PVOID         Reserved12[1];
        ULONG         SessionId;
} PEB, *PPEB;

typedef struct _PEB32
{
        UCHAR InheritedAddressSpace;
        UCHAR ReadImageFileExecOptions;
        UCHAR BeingDebugged;
        UCHAR BitField;
        ULONG Mutant;
        ULONG ImageBaseAddress;
        ULONG Ldr;
        ULONG ProcessParameters;
        ULONG SubSystemData;
        ULONG ProcessHeap;
        ULONG FastPebLock;
        ULONG AtlThunkSListPtr;
        ULONG IFEOKey;
        ULONG CrossProcessFlags;
        ULONG UserSharedInfoPtr;
        ULONG SystemReserved;
        ULONG AtlThunkSListPtr32;
        ULONG ApiSetMap;
} PEB32, *PPEB32;

typedef struct _PEB_LDR_DATA32
{
        ULONG        Length;
        UCHAR        Initialized;
        ULONG        SsHandle;
        LIST_ENTRY32 InLoadOrderModuleList;
        LIST_ENTRY32 InMemoryOrderModuleList;
        LIST_ENTRY32 InInitializationOrderModuleList;
} PEB_LDR_DATA32, *PPEB_LDR_DATA32;

typedef struct _LDR_DATA_TABLE_ENTRY32
{
        LIST_ENTRY32     InLoadOrderLinks;
        LIST_ENTRY32     InMemoryOrderLinks;
        LIST_ENTRY32     InInitializationOrderLinks;
        ULONG            DllBase;
        ULONG            EntryPoint;
        ULONG            SizeOfImage;
        UNICODE_STRING32 FullDllName;
        UNICODE_STRING32 BaseDllName;
        ULONG            Flags;
        USHORT           LoadCount;
        USHORT           TlsIndex;
        LIST_ENTRY32     HashLinks;
        ULONG            TimeDateStamp;
} LDR_DATA_TABLE_ENTRY32, *PLDR_DATA_TABLE_ENTRY32;

typedef struct _HANDLE_TABLE_ENTRY_INFO
{
        ULONG AuditMask;
        ULONG MaxRelativeAccessMask;

} HANDLE_TABLE_ENTRY_INFO, *PHANDLE_TABLE_ENTRY_INFO;

typedef union _EXHANDLE
{
        struct
        {
                int TagBits : 2;
                int Index : 30;
        } u;
        void*     GenericHandleOverlay;
        ULONG_PTR Value;
} EXHANDLE, *PEXHANDLE;

#pragma warning(disable : 4214 4201)

#pragma pack(push, 1)
typedef struct _POOL_HEADER // Size=16
{
        union
        {
                struct
                {
                        unsigned long PreviousSize : 8; // Size=4 Offset=0 BitOffset=0 BitCount=8
                        unsigned long PoolIndex : 8;    // Size=4 Offset=0 BitOffset=8 BitCount=8
                        unsigned long BlockSize : 8;    // Size=4 Offset=0 BitOffset=16 BitCount=8
                        unsigned long PoolType : 8;     // Size=4 Offset=0 BitOffset=24 BitCount=8
                };
                unsigned long Ulong1; // Size=4 Offset=0
        };
        unsigned long PoolTag; // Size=4 Offset=4
        union
        {
                struct _EPROCESS* ProcessBilled; // Size=8 Offset=8
                struct
                {
                        unsigned short AllocatorBackTraceIndex; // Size=2 Offset=8
                        unsigned short PoolTagHash;             // Size=2 Offset=10
                };
        };
} POOL_HEADER, *PPOOL_HEADER;
#pragma pack(pop)

typedef struct _HANDLE_TABLE_ENTRY // Size=16
{
        union
        {
                ULONG_PTR                        VolatileLowValue; // Size=8 Offset=0
                ULONG_PTR                        LowValue;         // Size=8 Offset=0
                struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;        // Size=8 Offset=0
                struct
                {
                        ULONG_PTR Unlocked : 1;   // Size=8 Offset=0 BitOffset=0 BitCount=1
                        ULONG_PTR RefCnt : 16;    // Size=8 Offset=0 BitOffset=1 BitCount=16
                        ULONG_PTR Attributes : 3; // Size=8 Offset=0 BitOffset=17 BitCount=3
                        ULONG_PTR
                        ObjectPointerBits : 44; // Size=8 Offset=0 BitOffset=20 BitCount=44
                };
        };
        union
        {
                ULONG_PTR                   HighValue;           // Size=8 Offset=8
                struct _HANDLE_TABLE_ENTRY* NextFreeHandleEntry; // Size=8 Offset=8
                union _EXHANDLE             LeafHandleValue;     // Size=8 Offset=8
                struct
                {
                        ULONG GrantedAccessBits : 25; // Size=4 Offset=8 BitOffset=0 BitCount=25
                        ULONG NoRightsUpgrade : 1;    // Size=4 Offset=8 BitOffset=25 BitCount=1
                        ULONG Spare : 6;              // Size=4 Offset=8 BitOffset=26 BitCount=6
                };
        };
        ULONG TypeInfo; // Size=4 Offset=12
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

typedef struct _HANDLE_TABLE_FREE_LIST
{
        EX_PUSH_LOCK        FreeListLock;
        PHANDLE_TABLE_ENTRY FirstFreeHandleEntry;
        PHANDLE_TABLE_ENTRY LastFreeHandleEntry;
        LONG                HandleCount;
        ULONG               HighWaterMark;
} HANDLE_TABLE_FREE_LIST, *PHANDLE_TABLE_FREE_LIST;

typedef struct _HANDLE_TRACE_DB_ENTRY
{
        CLIENT_ID ClientId;
        PVOID     Handle;
        ULONG     Type;
        PVOID     StackTrace[16];

} HANDLE_TRACE_DB_ENTRY, *PHANDLE_TRACE_DB_ENTRY;

typedef struct _HANDLE_TRACE_DEBUG_INFO
{
        LONG                  RefCount;
        ULONG                 TableSize;
        ULONG                 BitMaskFlags;
        FAST_MUTEX            CloseCompactionLock;
        ULONG                 CurrentStackIndex;
        HANDLE_TRACE_DB_ENTRY TraceDb[1];

} HANDLE_TRACE_DEBUG_INFO, *PHANDLE_TRACE_DEBUG_INFO;

typedef struct _HANDLE_TABLE
{
        ULONG      NextHandleNeedingPool;
        LONG       ExtraInfoPages;
        ULONGLONG  TableCode;
        PEPROCESS  QuotaProcess;
        LIST_ENTRY HandleTableList;
        ULONG      UniqueProcessId;
        union
        {
                ULONG Flags;
                struct
                {
                        UCHAR StrictFIFO : 1;
                        UCHAR EnableHandleExceptions : 1;
                        UCHAR Rundown : 1;
                        UCHAR Duplicated : 1;
                        UCHAR RaiseUMExceptionOnInvalidHandleClose : 1;
                };
        };
        EX_PUSH_LOCK HandleContentionEvent;
        EX_PUSH_LOCK HandleTableLock;
        union
        {
                HANDLE_TABLE_FREE_LIST FreeLists[1];
                UCHAR                  ActualEntry[32];
        };

        struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo;

} HANDLE_TABLE, *PHANDLE_TABLE;

typedef BOOLEAN (*EX_ENUMERATE_HANDLE_ROUTINE)(IN PHANDLE_TABLE_ENTRY HandleTableEntry,
                                               IN HANDLE              Handle,
                                               IN PVOID               EnumParameter);

typedef struct _OBJECT_CREATE_INFORMATION
{
        ULONG                                Attributes;
        PVOID                                RootDirectory;
        CHAR                                 ProbeMode;
        ULONG                                PagedPoolCharge;
        ULONG                                NonPagedPoolCharge;
        ULONG                                SecurityDescriptorCharge;
        PVOID                                SecurityDescriptor;
        struct _SECURITY_QUALITY_OF_SERVICE* SecurityQos;
        struct _SECURITY_QUALITY_OF_SERVICE  SecurityQualityOfService;

} OBJECT_CREATE_INFORMATION, *POBJECT_CREATE_INFORMATION;

typedef struct _OBJECT_HEADER
{
        LONGLONG PointerCount;
        union
        {
                LONGLONG HandleCount;
                PVOID    NextToFree;
        };
        EX_PUSH_LOCK Lock;
        UCHAR        TypeIndex;
        union
        {
                UCHAR TraceFlags;
                struct
                {
                        UCHAR DbgRefTrace : 1;
                        UCHAR DbgTracePermanent : 1;
                };
        };
        UCHAR InfoMask;
        union
        {
                UCHAR Flags;
                struct
                {
                        UCHAR NewObject : 1;
                        UCHAR KernelObject : 1;
                        UCHAR KernelOnlyAccess : 1;
                        UCHAR ExclusiveObject : 1;
                        UCHAR PermanentObject : 1;
                        UCHAR DefaultSecurityQuota : 1;
                        UCHAR SingleHandleEntry : 1;
                        UCHAR DeletedInline : 1;
                };
        };
        ULONG Reserved;
        union
        {
                POBJECT_CREATE_INFORMATION ObjectCreateInfo;
                PVOID                      QuotaBlockCharged;
        };
        PVOID SecurityDescriptor;
        QUAD  Body;
} OBJECT_HEADER, *POBJECT_HEADER;

#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ    0x40000000
#define IMAGE_SCN_MEM_WRITE   0x80000000

#define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _IMAGE_SECTION_HEADER
{
        unsigned char Name[IMAGE_SIZEOF_SHORT_NAME];
        union
        {
                unsigned long PhysicalAddress;
                unsigned long VirtualSize;
        } Misc;
        unsigned long  VirtualAddress;
        unsigned long  SizeOfRawData;
        unsigned long  PointerToRawData;
        unsigned long  PointerToRelocations;
        unsigned long  PointerToLinenumbers;
        unsigned short NumberOfRelocations;
        unsigned short NumberOfLinenumbers;
        unsigned long  Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

typedef struct _IMAGE_FILE_HEADER
{
        unsigned short Machine;
        unsigned short NumberOfSections;
        unsigned long  TimeDateStamp;
        unsigned long  PointerToSymbolTable;
        unsigned long  NumberOfSymbols;
        unsigned short SizeOfOptionalHeader;
        unsigned short Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

typedef struct _IMAGE_DATA_DIRECTORY
{
        unsigned long VirtualAddress;
        unsigned long Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

typedef struct _IMAGE_OPTIONAL_HEADER64
{
        unsigned short       Magic;
        unsigned char        MajorLinkerVersion;
        unsigned char        MinorLinkerVersion;
        unsigned long        SizeOfCode;
        unsigned long        SizeOfInitializedData;
        unsigned long        SizeOfUninitializedData;
        unsigned long        AddressOfEntryPoint;
        unsigned long        BaseOfCode;
        ULONGLONG            ImageBase;
        unsigned long        SectionAlignment;
        unsigned long        FileAlignment;
        unsigned short       MajorOperatingSystemVersion;
        unsigned short       MinorOperatingSystemVersion;
        unsigned short       MajorImageVersion;
        unsigned short       MinorImageVersion;
        unsigned short       MajorSubsystemVersion;
        unsigned short       MinorSubsystemVersion;
        unsigned long        Win32VersionValue;
        unsigned long        SizeOfImage;
        unsigned long        SizeOfHeaders;
        unsigned long        CheckSum;
        unsigned short       Subsystem;
        unsigned short       DllCharacteristics;
        ULONGLONG            SizeOfStackReserve;
        ULONGLONG            SizeOfStackCommit;
        ULONGLONG            SizeOfHeapReserve;
        ULONGLONG            SizeOfHeapCommit;
        unsigned long        LoaderFlags;
        unsigned long        NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

typedef unsigned long  DWORD;
typedef unsigned short WORD;

typedef struct _IMAGE_OPTIONAL_HEADER32
{
        WORD                 Magic;
        BYTE                 MajorLinkerVersion;
        BYTE                 MinorLinkerVersion;
        DWORD                SizeOfCode;
        DWORD                SizeOfInitializedData;
        DWORD                SizeOfUninitializedData;
        DWORD                AddressOfEntryPoint;
        DWORD                BaseOfCode;
        DWORD                BaseOfData;
        DWORD                ImageBase;
        DWORD                SectionAlignment;
        DWORD                FileAlignment;
        WORD                 MajorOperatingSystemVersion;
        WORD                 MinorOperatingSystemVersion;
        WORD                 MajorImageVersion;
        WORD                 MinorImageVersion;
        WORD                 MajorSubsystemVersion;
        WORD                 MinorSubsystemVersion;
        DWORD                Win32VersionValue;
        DWORD                SizeOfImage;
        DWORD                SizeOfHeaders;
        DWORD                CheckSum;
        WORD                 Subsystem;
        WORD                 DllCharacteristics;
        DWORD                SizeOfStackReserve;
        DWORD                SizeOfStackCommit;
        DWORD                SizeOfHeapReserve;
        DWORD                SizeOfHeapCommit;
        DWORD                LoaderFlags;
        DWORD                NumberOfRvaAndSizes;
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

typedef struct _IMAGE_DOS_HEADER
{                                  // DOS .EXE header
        unsigned short e_magic;    // Magic number
        unsigned short e_cblp;     // Bytes on last page of file
        unsigned short e_cp;       // Pages in file
        unsigned short e_crlc;     // Relocations
        unsigned short e_cparhdr;  // Size of header in paragraphs
        unsigned short e_minalloc; // Minimum extra paragraphs needed
        unsigned short e_maxalloc; // Maximum extra paragraphs needed
        unsigned short e_ss;       // Initial (relative) SS value
        unsigned short e_sp;       // Initial SP value
        unsigned short e_csum;     // Checksum
        unsigned short e_ip;       // Initial IP value
        unsigned short e_cs;       // Initial (relative) CS value
        unsigned short e_lfarlc;   // File address of relocation table
        unsigned short e_ovno;     // Overlay number
        unsigned short e_res[4];   // Reserved words
        unsigned short e_oemid;    // OEM identifier (for e_oeminfo)
        unsigned short e_oeminfo;  // OEM information; e_oemid specific
        unsigned short e_res2[10]; // Reserved words
        LONG           e_lfanew;   // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

typedef struct _KLDR_DATA_TABLE_ENTRY
{
        LIST_ENTRY InLoadOrderLinks;
        PVOID      ExceptionTable;
        ULONG      ExceptionTableSize;
        // ULONG padding on IA64
        PVOID          GpValue;
        PVOID          NonPagedDebugInfo;
        PVOID          DllBase;
        PVOID          EntryPoint;
        ULONG          SizeOfImage;
        UNICODE_STRING FullDllName;
        UNICODE_STRING BaseDllName;
        ULONG          Flags;
        USHORT         LoadCount;
        USHORT         __Unused5;
        PVOID          SectionPointer;
        ULONG          CheckSum;
        // ULONG padding on IA64
        PVOID LoadedImports;
        PVOID PatchInformation;
} KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;

typedef struct _IMAGE_EXPORT_DIRECTORY
{
        DWORD Characteristics;
        DWORD TimeDateStamp;
        WORD  MajorVersion;
        WORD  MinorVersion;
        DWORD Name;
        DWORD Base;
        DWORD NumberOfFunctions;
        DWORD NumberOfNames;
        DWORD AddressOfFunctions;
        DWORD AddressOfNames;
        DWORD AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

typedef struct _LOCAL_NT_HEADER
{
        unsigned long           Signature;
        IMAGE_FILE_HEADER       FileHeader;
        IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} LOCAL_NT_HEADER, *PLOCAL_NT_HEADER;

#define IMAGE_FIRST_SECTION(ntheader)                                            \
        ((PIMAGE_SECTION_HEADER)((ULONG_PTR)(ntheader) +                         \
                                 FIELD_OFFSET(LOCAL_NT_HEADER, OptionalHeader) + \
                                 ((ntheader))->FileHeader.SizeOfOptionalHeader))

/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */

typedef struct _DBGKD_DEBUG_DATA_HEADER64
{
        LIST_ENTRY64 List;
        ULONG        OwnerTag;
        ULONG        Size;
} DBGKD_DEBUG_DATA_HEADER64, *PDBGKD_DEBUG_DATA_HEADER64;

typedef NTSTATUS(__stdcall* ZwQuerySystemInformation)(_In_ UINT32      SystemInformationClass,
                                                      _Inout_ PVOID    SystemInformation,
                                                      _In_ ULONG       SystemInformationLength,
                                                      _Out_opt_ PULONG ReturnLength);

#define SYSTEM_BIGPOOL_INFORMATION_ID 0x42

typedef struct _SYSTEM_BIGPOOL_ENTRY
{
        union
        {
                PVOID     VirtualAddress;
                ULONG_PTR NonPaged : 1;
        };
        SIZE_T SizeInBytes;
        union
        {
                UCHAR Tag[4];
                ULONG TagUlong;
        };
} SYSTEM_BIGPOOL_ENTRY, *PSYSTEM_BIGPOOL_ENTRY;

typedef struct _SYSTEM_BIGPOOL_INFORMATION
{
        ULONG Count;
        _Field_size_(Count) SYSTEM_BIGPOOL_ENTRY AllocatedInfo[1];
} SYSTEM_BIGPOOL_INFORMATION, *PSYSTEM_BIGPOOL_INFORMATION;

typedef struct _KDDEBUGGER_DATA64
{
        DBGKD_DEBUG_DATA_HEADER64 Header;
        ULONG64                   KernBase;
        ULONG64                   BreakpointWithStatus;
        ULONG64                   SavedContext;
        USHORT                    ThCallbackStack;
        USHORT                    NextCallback;
        USHORT                    FramePointer;
        USHORT                    PaeEnabled;
        ULONG64                   KiCallUserMode;
        ULONG64                   KeUserCallbackDispatcher;
        ULONG64                   PsLoadedModuleList;
        ULONG64                   PsActiveProcessHead;
        ULONG64                   PspCidTable;
        ULONG64                   ExpSystemResourcesList;
        ULONG64                   ExpPagedPoolDescriptor;
        ULONG64                   ExpNumberOfPagedPools;
        ULONG64                   KeTimeIncrement;
        ULONG64                   KeBugCheckCallbackListHead;
        ULONG64                   KiBugcheckData;
        ULONG64                   IopErrorLogListHead;
        ULONG64                   ObpRootDirectoryObject;
        ULONG64                   ObpTypeObjectType;
        ULONG64                   MmSystemCacheStart;
        ULONG64                   MmSystemCacheEnd;
        ULONG64                   MmSystemCacheWs;
        ULONG64                   MmPfnDatabase;
        ULONG64                   MmSystemPtesStart;
        ULONG64                   MmSystemPtesEnd;
        ULONG64                   MmSubsectionBase;
        ULONG64                   MmNumberOfPagingFiles;
        ULONG64                   MmLowestPhysicalPage;
        ULONG64                   MmHighestPhysicalPage;
        ULONG64                   MmNumberOfPhysicalPages;
        ULONG64                   MmMaximumNonPagedPoolInBytes;
        ULONG64                   MmNonPagedSystemStart;
        ULONG64                   MmNonPagedPoolStart;
        ULONG64                   MmNonPagedPoolEnd;
        ULONG64                   MmPagedPoolStart;
        ULONG64                   MmPagedPoolEnd;
        ULONG64                   MmPagedPoolInformation;
        ULONG64                   MmPageSize;
        ULONG64                   MmSizeOfPagedPoolInBytes;
        ULONG64                   MmTotalCommitLimit;
        ULONG64                   MmTotalCommittedPages;
        ULONG64                   MmSharedCommit;
        ULONG64                   MmDriverCommit;
        ULONG64                   MmProcessCommit;
        ULONG64                   MmPagedPoolCommit;
        ULONG64                   MmExtendedCommit;
        ULONG64                   MmZeroedPageListHead;
        ULONG64                   MmFreePageListHead;
        ULONG64                   MmStandbyPageListHead;
        ULONG64                   MmModifiedPageListHead;
        ULONG64                   MmModifiedNoWritePageListHead;
        ULONG64                   MmAvailablePages;
        ULONG64                   MmResidentAvailablePages;
        ULONG64                   PoolTrackTable;
        ULONG64                   NonPagedPoolDescriptor;
        ULONG64                   MmHighestUserAddress;
        ULONG64                   MmSystemRangeStart;
        ULONG64                   MmUserProbeAddress;
        ULONG64                   KdPrintCircularBuffer;
        ULONG64                   KdPrintCircularBufferEnd;
        ULONG64                   KdPrintWritePointer;
        ULONG64                   KdPrintRolloverCount;
        ULONG64                   MmLoadedUserImageList;
        ULONG64                   NtBuildLab;
        ULONG64                   KiNormalSystemCall;
        ULONG64                   KiProcessorBlock;
        ULONG64                   MmUnloadedDrivers;
        ULONG64                   MmLastUnloadedDriver;
        ULONG64                   MmTriageActionTaken;
        ULONG64                   MmSpecialPoolTag;
        ULONG64                   KernelVerifier;
        ULONG64                   MmVerifierData;
        ULONG64                   MmAllocatedNonPagedPool;
        ULONG64                   MmPeakCommitment;
        ULONG64                   MmTotalCommitLimitMaximum;
        ULONG64                   CmNtCSDVersion;
        ULONG64                   MmPhysicalMemoryBlock;
        ULONG64                   MmSessionBase;
        ULONG64                   MmSessionSize;
        ULONG64                   MmSystemParentTablePage;
        ULONG64                   MmVirtualTranslationBase;
        USHORT                    OffsetKThreadNextProcessor;
        USHORT                    OffsetKThreadTeb;
        USHORT                    OffsetKThreadKernelStack;
        USHORT                    OffsetKThreadInitialStack;
        USHORT                    OffsetKThreadApcProcess;
        USHORT                    OffsetKThreadState;
        USHORT                    OffsetKThreadBStore;
        USHORT                    OffsetKThreadBStoreLimit;
        USHORT                    SizeEProcess;
        USHORT                    OffsetEprocessPeb;
        USHORT                    OffsetEprocessParentCID;
        USHORT                    OffsetEprocessDirectoryTableBase;
        USHORT                    SizePrcb;
        USHORT                    OffsetPrcbDpcRoutine;
        USHORT                    OffsetPrcbCurrentThread;
        USHORT                    OffsetPrcbMhz;
        USHORT                    OffsetPrcbCpuType;
        USHORT                    OffsetPrcbVendorString;
        USHORT                    OffsetPrcbProcStateContext;
        USHORT                    OffsetPrcbNumber;
        USHORT                    SizeEThread;
        ULONG64                   KdPrintCircularBufferPtr;
        ULONG64                   KdPrintBufferSize;
        ULONG64                   KeLoaderBlock;
        USHORT                    SizePcr;
        USHORT                    OffsetPcrSelfPcr;
        USHORT                    OffsetPcrCurrentPrcb;
        USHORT                    OffsetPcrContainedPrcb;
        USHORT                    OffsetPcrInitialBStore;
        USHORT                    OffsetPcrBStoreLimit;
        USHORT                    OffsetPcrInitialStack;
        USHORT                    OffsetPcrStackLimit;
        USHORT                    OffsetPrcbPcrPage;
        USHORT                    OffsetPrcbProcStateSpecialReg;
        USHORT                    GdtR0Code;
        USHORT                    GdtR0Data;
        USHORT                    GdtR0Pcr;
        USHORT                    GdtR3Code;
        USHORT                    GdtR3Data;
        USHORT                    GdtR3Teb;
        USHORT                    GdtLdt;
        USHORT                    GdtTss;
        USHORT                    Gdt64R3CmCode;
        USHORT                    Gdt64R3CmTeb;
        ULONG64                   IopNumTriageDumpDataBlocks;
        ULONG64                   IopTriageDumpDataBlocks;
} KDDEBUGGER_DATA64, *PKDDEBUGGER_DATA64;

typedef struct _KDDEBUGGER_DATA_ADDITION64
{
        ULONG64 VfCrashDataBlock;
        ULONG64 MmBadPagesDetected;
        ULONG64 MmZeroedPageSingleBitErrorsDetected;
        ULONG64 EtwpDebuggerData;
        USHORT  OffsetPrcbContext;
        USHORT  OffsetPrcbMaxBreakpoints;
        USHORT  OffsetPrcbMaxWatchpoints;
        ULONG   OffsetKThreadStackLimit;
        ULONG   OffsetKThreadStackBase;
        ULONG   OffsetKThreadQueueListEntry;
        ULONG   OffsetEThreadIrpList;
        USHORT  OffsetPrcbIdleThread;
        USHORT  OffsetPrcbNormalDpcState;
        USHORT  OffsetPrcbDpcStack;
        USHORT  OffsetPrcbIsrStack;
        USHORT  SizeKDPC_STACK_FRAME;
        USHORT  OffsetKPriQueueThreadListHead;
        USHORT  OffsetKThreadWaitReason;
        USHORT  Padding;
        ULONG64 PteBase;
        ULONG64 RetpolineStubFunctionTable;
        ULONG   RetpolineStubFunctionTableSize;
        ULONG   RetpolineStubOffset;
        ULONG   RetpolineStubSize;
} KDDEBUGGER_DATA_ADDITION64, *PKDDEBUGGER_DATA_ADDITION64;

typedef struct _DUMP_HEADER
{
        ULONG                      Signature;
        ULONG                      ValidDump;
        ULONG                      MajorVersion;
        ULONG                      MinorVersion;
        ULONG_PTR                  DirectoryTableBase;
        ULONG_PTR                  PfnDataBase;
        PLIST_ENTRY                PsLoadedModuleList;
        PLIST_ENTRY                PsActiveProcessHead;
        ULONG                      MachineImageType;
        ULONG                      NumberProcessors;
        ULONG                      BugCheckCode;
        ULONG_PTR                  BugCheckParameter1;
        ULONG_PTR                  BugCheckParameter2;
        ULONG_PTR                  BugCheckParameter3;
        ULONG_PTR                  BugCheckParameter4;
        CHAR                       VersionUser[32];
        struct _KDDEBUGGER_DATA64* KdDebuggerDataBlock;
} DUMP_HEADER, *PDUMP_HEADER;

typedef union _VIRTUAL_MEMORY_ADDRESS
{
        struct
        {
                UINT64 PageIndex : 12; /* 0:11  */
                UINT64 PtIndex : 9;    /* 12:20 */
                UINT64 PdIndex : 9;    /* 21:29 */
                UINT64 PdptIndex : 9;  /* 30:38 */
                UINT64 Pml4Index : 9;  /* 39:47 */
                UINT64 Unused : 16;    /* 48:63 */

        } Bits;

        UINT64 BitAddress;

} VIRTUAL_ADDRESS, *PVIRTUAL_ADDRESS;

typedef union _PML4_ENTRY
{
        struct
        {
                UINT64 Present : 1;          /* 0     */
                UINT64 ReadWrite : 1;        /* 1     */
                UINT64 UserSupervisor : 1;   /* 2     */
                UINT64 PageWriteThrough : 1; /* 3     */
                UINT64 PageCacheDisable : 1; /* 4     */
                UINT64 Accessed : 1;         /* 5     */
                UINT64 _Ignored0 : 1;        /* 6     */
                UINT64 _Reserved0 : 1;       /* 7     */
                UINT64 _Ignored1 : 4;        /* 11:8  */
                UINT64 PhysicalAddress : 40; /* 51:12 */
                UINT64 _Ignored2 : 11;       /* 62:52 */
                UINT64 ExecuteDisable : 1;   /* 63    */
        } Bits;
        UINT64 BitAddress;
} PML4E;

typedef union _PDPT_ENTRY
{
        struct
        {
                UINT64 Present : 1;          /* 0     */
                UINT64 ReadWrite : 1;        /* 1     */
                UINT64 UserSupervisor : 1;   /* 2     */
                UINT64 PageWriteThrough : 1; /* 3     */
                UINT64 PageCacheDisable : 1; /* 4     */
                UINT64 Accessed : 1;         /* 5     */
                UINT64 _Ignored0 : 1;        /* 6     */
                UINT64 PageSize : 1;         /* 7     */
                UINT64 _Ignored1 : 4;        /* 11:8  */
                UINT64 PhysicalAddress : 40; /* 51:12 */
                UINT64 _Ignored2 : 11;       /* 62:52 */
                UINT64 ExecuteDisable : 1;   /* 63    */
        } Bits;
        UINT64 BitAddress;
} PDPTE;

typedef union _PD_ENTRY
{
        struct
        {
                UINT64 Present : 1;          /* 0     */
                UINT64 ReadWrite : 1;        /* 1     */
                UINT64 UserSupervisor : 1;   /* 2     */
                UINT64 PageWriteThrough : 1; /* 3     */
                UINT64 PageCacheDisable : 1; /* 4     */
                UINT64 Accessed : 1;         /* 5     */
                UINT64 _Ignored0 : 1;        /* 6     */
                UINT64 PageSize : 1;         /* 7     */
                UINT64 _Ignored1 : 4;        /* 11:8  */
                UINT64 PhysicalAddress : 38; /* 49:12 */
                UINT64 _Reserved0 : 2;       /* 51:50 */
                UINT64 _Ignored2 : 11;       /* 62:52 */
                UINT64 ExecuteDisable : 1;   /* 63    */
        } Bits;
        UINT64 BitAddress;
} PDE;

typedef union _PT_ENTRY
{
        struct
        {
                UINT64 Present : 1;            /* 0     */
                UINT64 ReadWrite : 1;          /* 1     */
                UINT64 UserSupervisor : 1;     /* 2     */
                UINT64 PageWriteThrough : 1;   /* 3     */
                UINT64 PageCacheDisable : 1;   /* 4     */
                UINT64 Accessed : 1;           /* 5     */
                UINT64 Dirty : 1;              /* 6     */
                UINT64 PageAttributeTable : 1; /* 7     */
                UINT64 Global : 1;             /* 8     */
                UINT64 _Ignored0 : 3;          /* 11:9  */
                UINT64 PhysicalAddress : 38;   /* 49:12 */
                UINT64 _Reserved0 : 2;         /* 51:50 */
                UINT64 _Ignored1 : 7;          /* 58:52 */
                UINT64 ProtectionKey : 4;      /* 62:59 */
                UINT64 ExecuteDisable : 1;     /* 63    */
        } Bits;
        UINT64 BitAddress;
} PTE;

typedef union _PDPT_ENTRY_LARGE
{
        struct
        {
                UINT64 Present : 1;            /* 0     */
                UINT64 ReadWrite : 1;          /* 1     */
                UINT64 UserSupervisor : 1;     /* 2     */
                UINT64 PageWriteThrough : 1;   /* 3     */
                UINT64 PageCacheDisable : 1;   /* 4     */
                UINT64 Accessed : 1;           /* 5     */
                UINT64 Dirty : 1;              /* 6     */
                UINT64 PageSize : 1;           /* 7     */
                UINT64 Global : 1;             /* 8     */
                UINT64 _Ignored0 : 3;          /* 11:9  */
                UINT64 PageAttributeTable : 1; /* 12    */
                UINT64 _Reserved0 : 17;        /* 29:13 */
                UINT64 PhysicalAddress : 22;   /* 51:30 */
                UINT64 _Ignored1 : 7;          /* 58:52 */
                UINT64 ProtectionKey : 4;      /* 62:59 */
                UINT64 ExecuteDisable : 1;     /* 63    */
        } Bits;
        UINT64 BitAddress;
} PDPTE_LARGE;

typedef union _PD_ENTRY_LARGE
{
        struct
        {
                UINT64 Present : 1;            /* 0     */
                UINT64 ReadWrite : 1;          /* 1     */
                UINT64 UserSupervisor : 1;     /* 2     */
                UINT64 PageWriteThrough : 1;   /* 3     */
                UINT64 PageCacheDisable : 1;   /* 4     */
                UINT64 Accessed : 1;           /* 5     */
                UINT64 Dirty : 1;              /* 6     */
                UINT64 PageSize : 1;           /* 7     */
                UINT64 Global : 1;             /* 8     */
                UINT64 _Ignored0 : 3;          /* 11:9  */
                UINT64 PageAttributeTalbe : 1; /* 12    */
                UINT64 _Reserved0 : 8;         /* 20:13 */
                UINT64 PhysicalAddress : 29;   /* 49:21 */
                UINT64 _Reserved1 : 2;         /* 51:50 */
                UINT64 _Ignored1 : 7;          /* 58:52 */
                UINT64 ProtectionKey : 4;      /* 62:59 */
                UINT64 ExecuteDisable : 1;     /* 63    */
        } Bits;
        UINT64 BitAddress;
} PDE_LARGE;

// typedef struct _KAPC_STATE
//{
//     LIST_ENTRY ApcListHead[ MaximumMode ];
//     struct _KPROCESS* Process;
//     union {
//         UCHAR InProgressFlags;
//         struct
//         {
//             BOOLEAN KernelApcInProgress : 1;
//             BOOLEAN SpecialApcInProgress : 1;
//         };
//     };
//
//     BOOLEAN KernelApcPending;
//     union {
//         BOOLEAN UserApcPendingAll;
//         struct
//         {
//             BOOLEAN SpecialUserApcPending : 1;
//             BOOLEAN UserApcPending : 1;
//         };
//     };
// } KAPC_STATE, * PKAPC_STATE, * PRKAPC_STATE;

typedef struct _RAW_SMBIOS_DATA
{
        BYTE   Used20CallingMethod;
        BYTE   SMBIOSMajorVersion;
        BYTE   SMBIOSMinorVersion;
        BYTE   DmiRevision;
        UINT32 Length;
        BYTE   SMBIOSTableData[1];
} RAW_SMBIOS_DATA, *PRAW_SMBIOS_DATA;

typedef struct _SMBIOS_TABLE_HEADER
{
        UCHAR  Type;
        UCHAR  Length;
        USHORT Handle;
        PCHAR  TableData;

} SMBIOS_TABLE_HEADER, *PSMBIOS_TABLE_HEADER;

typedef struct _RAW_SMBIOS_TABLE_01
{
        UCHAR  Type;
        UCHAR  Length;
        USHORT Handle;
        UCHAR  Manufacturer;
        UCHAR  ProductName;
        UCHAR  Version;
        UCHAR  SerialNumber;
        UCHAR  UUID[16];
        UCHAR  WakeUpType;
        UCHAR  SKUNumber;
        UCHAR  Family;

} RAW_SMBIOS_TABLE_01, *PRAW_SMBIOS_TABLE_01;

typedef struct _RAW_SMBIOS_TABLE_02
{
        UCHAR  Type;
        UCHAR  Length;
        USHORT Handle;
        BYTE   Manufacturer;
        BYTE   Product;
        BYTE   Version;
        BYTE   SerialNumber;
        BYTE   AssetTag;
        BYTE   FeatureFlags;
        BYTE   LocationInChassis;
        UINT16 ChassisHandle;
        BYTE   BoardType;
        BYTE   NumberOfContainedObjectHandles;
        BYTE   ContainedObjectHandles[256];

} RAW_SMBIOS_TABLE_02, *PRAW_SMBIOS_TABLE_02;

typedef struct _RTL_RELATIVE_NAME
{
        UNICODE_STRING RelativeName;
        HANDLE         ContainingDirectory;
        void*          CurDirRef;
} RTL_RELATIVE_NAME, *PRTL_RELATIVE_NAME;

typedef struct _STORAGE_DESCRIPTOR_HEADER
{
        ULONG Version;
        ULONG Size;
} STORAGE_DESCRIPTOR_HEADER, *PSTORAGE_DESCRIPTOR_HEADER;

typedef enum _STORAGE_BUS_TYPE
{
        BusTypeUnknown = 0x00,
        BusTypeScsi,
        BusTypeAtapi,
        BusTypeAta,
        BusType1394,
        BusTypeSsa,
        BusTypeFibre,
        BusTypeUsb,
        BusTypeRAID,
        BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE,
    *PSTORAGE_BUS_TYPE;

typedef enum _STORAGE_SET_TYPE
{
        PropertyStandardSet = 0, // Sets the descriptor
        PropertyExistsSet,       // Used to test whether the descriptor is supported
        PropertySetMaxDefined    // use to validate the value
} STORAGE_SET_TYPE,
    *PSTORAGE_SET_TYPE;

//
// define some initial property id's
//

typedef enum _STORAGE_QUERY_TYPE
{
        PropertyStandardQuery = 0, // Retrieves the descriptor
        PropertyExistsQuery,       // Used to test whether the descriptor is supported
        PropertyMaskQuery,         // Used to retrieve a mask of writeable fields in the descriptor
        PropertyQueryMaxDefined    // use to validate the value
} STORAGE_QUERY_TYPE,
    *PSTORAGE_QUERY_TYPE;

typedef enum _STORAGE_PROPERTY_ID
{
        StorageDeviceProperty = 0,
        StorageAdapterProperty,
        StorageDeviceIdProperty,
        StorageDeviceUniqueIdProperty, // See storduid.h for details
        StorageDeviceWriteCacheProperty,
        StorageMiniportProperty,
        StorageAccessAlignmentProperty,
        StorageDeviceSeekPenaltyProperty,
        StorageDeviceTrimProperty,
        StorageDeviceWriteAggregationProperty,
        StorageDeviceDeviceTelemetryProperty,
        StorageDeviceLBProvisioningProperty,
        StorageDevicePowerProperty,
        StorageDeviceCopyOffloadProperty,
        StorageDeviceResiliencyProperty,
        StorageDeviceMediumProductType,
        StorageAdapterRpmbProperty,
        StorageAdapterCryptoProperty,
        StorageDeviceIoCapabilityProperty = 48,
        StorageAdapterProtocolSpecificProperty,
        StorageDeviceProtocolSpecificProperty,
        StorageAdapterTemperatureProperty,
        StorageDeviceTemperatureProperty,
        StorageAdapterPhysicalTopologyProperty,
        StorageDevicePhysicalTopologyProperty,
        StorageDeviceAttributesProperty,
        StorageDeviceManagementStatus,
        StorageAdapterSerialNumberProperty,
        StorageDeviceLocationProperty,
        StorageDeviceNumaProperty,
        StorageDeviceZonedDeviceProperty,
        StorageDeviceUnsafeShutdownCount,
        StorageDeviceEnduranceProperty,
        StorageDeviceLedStateProperty,
        StorageDeviceSelfEncryptionProperty = 64,
        StorageFruIdProperty,
} STORAGE_PROPERTY_ID,
    *PSTORAGE_PROPERTY_ID;

typedef struct _STORAGE_PROPERTY_QUERY
{
        STORAGE_PROPERTY_ID PropertyId;
        STORAGE_QUERY_TYPE  QueryType;
        UCHAR               AdditionalParameters[1];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

typedef struct _STORAGE_DEVICE_DESCRIPTOR
{
        ULONG            Version;
        ULONG            Size;
        UCHAR            DeviceType;
        UCHAR            DeviceTypeModifier;
        BOOLEAN          RemovableMedia;
        BOOLEAN          CommandQueueing;
        ULONG            VendorIdOffset;
        ULONG            ProductIdOffset;
        ULONG            ProductRevisionOffset;
        ULONG            SerialNumberOffset;
        STORAGE_BUS_TYPE BusType;
        ULONG            RawPropertiesLength;
        UCHAR            RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;

NTKERNELAPI
BOOLEAN
ExEnumHandleTable(__in PHANDLE_TABLE               HandleTable,
                  __in EX_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
                  __in PVOID                       EnumParameter,
                  __out_opt PHANDLE                Handle);

NTKERNELAPI
POBJECT_TYPE
NTAPI
ObGetObjectType(_In_ PVOID Object);

typedef struct _EX_PUSH_LOCK_WAIT_BLOCK* PEX_PUSH_LOCK_WAIT_BLOCK;

NTKERNELAPI
VOID FASTCALL
ExfUnblockPushLock(_Inout_ PEX_PUSH_LOCK PushLock, _Inout_opt_ PEX_PUSH_LOCK_WAIT_BLOCK WaitBlock);

LPCSTR
NTSYSAPI
NTAPI
PsGetProcessImageFileName(PEPROCESS Process);

EXTERN_C
VOID
KeInitializeAffinityEx(PKAFFINITY_EX affinity);

EXTERN_C
VOID
KeAddProcessorAffinityEx(PKAFFINITY_EX affinity, INT num);

EXTERN_C
VOID
HalSendNMI(PKAFFINITY_EX affinity);

NTSTATUS
RtlQueryModuleInformation(ULONG* InformationLength, ULONG SizePerModule, PVOID InformationBuffer);

NTSTATUS
NTAPI
NtSetInformationProcess(_In_ HANDLE           ProcessHandle,
                        _In_ PROCESSINFOCLASS ProcessInformationClass,
                        _In_ PVOID            ProcessInformation,
                        _In_ ULONG            ProcessInformationLength);

NTSYSAPI
ULONG
NTAPI
KeCapturePersistentThreadState(__in PCONTEXT     Context,
                               __in_opt PKTHREAD Thread,
                               __in ULONG        BugCheckCode,
                               __in ULONG_PTR    BugCheckParameter1,
                               __in ULONG_PTR    BugCheckParameter2,
                               __in ULONG_PTR    BugCheckParameter3,
                               __in ULONG_PTR    BugCheckParameter4,
                               __in PDUMP_HEADER DumpHeader);

BOOLEAN NTAPI
RtlDosPathNameToRelativeNtPathName_U(_In_ PCWSTR                  DosFileName,
                                     _Out_ PUNICODE_STRING        NtFileName,
                                     _Out_opt_ PWSTR*             FilePath,
                                     _Out_opt_ PRTL_RELATIVE_NAME RelativeName);

typedef _Function_class_(KNORMAL_ROUTINE) _IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID NTAPI
                         KNORMAL_ROUTINE(_In_opt_ PVOID NormalContext,
                                         _In_opt_ PVOID SystemArgument1,
                                         _In_opt_ PVOID SystemArgument2);
typedef KNORMAL_ROUTINE* PKNORMAL_ROUTINE;

typedef _Function_class_(KRUNDOWN_ROUTINE) _IRQL_requires_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID NTAPI
                          KRUNDOWN_ROUTINE(_In_ PRKAPC Apc);
typedef KRUNDOWN_ROUTINE* PKRUNDOWN_ROUTINE;

typedef _Function_class_(KKERNEL_ROUTINE) _IRQL_requires_(APC_LEVEL)
_IRQL_requires_same_
VOID NTAPI
                         KKERNEL_ROUTINE(_In_ PRKAPC                                     Apc,
                                         _Inout_ _Deref_pre_maybenull_ PKNORMAL_ROUTINE* NormalRoutine,
                                         _Inout_ _Deref_pre_maybenull_ PVOID*            NormalContext,
                                         _Inout_ _Deref_pre_maybenull_ PVOID*            SystemArgument1,
                                         _Inout_ _Deref_pre_maybenull_ PVOID*            SystemArgument2);
typedef KKERNEL_ROUTINE* PKKERNEL_ROUTINE;

typedef enum _KAPC_ENVIRONMENT
{
        OriginalApcEnvironment,
        AttachedApcEnvironment,
        CurrentApcEnvironment,
        InsertApcEnvironment
} KAPC_ENVIRONMENT,
    *PKAPC_ENVIRONMENT;

NTKERNELAPI
VOID NTAPI
KeInitializeApc(_Out_ PRKAPC               Apc,
                _In_ PRKTHREAD             Thread,
                _In_ KAPC_ENVIRONMENT      Environment,
                _In_ PKKERNEL_ROUTINE      KernelRoutine,
                _In_opt_ PKRUNDOWN_ROUTINE RundownRoutine,
                _In_opt_ PKNORMAL_ROUTINE  NormalRoutine,
                _In_ KPROCESSOR_MODE       Mode,
                _In_opt_ PVOID             NormalContext);

NTSTATUS
NTAPI
MmCopyVirtualMemory(PEPROCESS       SourceProcess,
                    PVOID           SourceAddress,
                    PEPROCESS       TargetProcess,
                    PVOID           TargetAddress,
                    SIZE_T          BufferSize,
                    KPROCESSOR_MODE PreviousMode,
                    PSIZE_T         ReturnSize);

NTKERNELAPI
BOOLEAN
NTAPI
KeInsertQueueApc(_Inout_ PRKAPC Apc,
                 _In_opt_ PVOID SystemArgument1,
                 _In_opt_ PVOID SystemArgument2,
                 _In_ KPRIORITY Increment);

C_ASSERT(FIELD_OFFSET(DUMP_HEADER, Signature) == 0);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, ValidDump) == 4);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, MajorVersion) == 8);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, MinorVersion) == 0xc);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, DirectoryTableBase) == 0x10);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, PfnDataBase) == 0x18);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, PsLoadedModuleList) == 0x20);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, PsActiveProcessHead) == 0x28);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, MachineImageType) == 0x30);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, NumberProcessors) == 0x34);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, BugCheckCode) == 0x38);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, BugCheckParameter1) == 0x40);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, BugCheckParameter2) == 0x48);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, BugCheckParameter3) == 0x50);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, BugCheckParameter4) == 0x58);
C_ASSERT(FIELD_OFFSET(DUMP_HEADER, KdDebuggerDataBlock) == 0x80);

#ifndef _WIN64
#        define KDDEBUGGER_DATA_OFFSET 0x1068
#else
#        define KDDEBUGGER_DATA_OFFSET 0x2080
#endif

#ifndef _WIN64
#        define DUMP_BLOCK_SIZE 0x20000
#else
#        define DUMP_BLOCK_SIZE 0x40000
#endif

#define IA32_GS_BASE                 0xc0000101
#define KPCR_TSS_BASE_OFFSET         0x008
#define TSS_IST_OFFSET               0x01c
#define WINDOWS_USERMODE_MAX_ADDRESS 0x00007FFFFFFFFFFF

typedef struct _MACHINE_FRAME
{
        UINT64 rip;
        UINT64 cs;
        UINT64 eflags;
        UINT64 rsp;
        UINT64 ss;

} MACHINE_FRAME, *PMACHINE_FRAME;

NTKERNELAPI
_IRQL_requires_max_(APC_LEVEL)
_IRQL_requires_min_(PASSIVE_LEVEL)
_IRQL_requires_same_
VOID
KeGenericCallDpc(_In_ PKDEFERRED_ROUTINE Routine, _In_opt_ PVOID Context);

NTKERNELAPI
_IRQL_requires_(DISPATCH_LEVEL)
_IRQL_requires_same_
VOID
KeSignalCallDpcDone(_In_ PVOID SystemArgument1);

PEPROCESS
NTAPI
PsGetNextProcess(IN PEPROCESS OldProcess OPTIONAL);

PETHREAD
NTAPI
PsGetNextProcessThread(IN PEPROCESS Process, IN PETHREAD Thread OPTIONAL);

#define ABSOLUTE(wait) (wait)

#define RELATIVE(wait) (-(wait))

#define NANOSECONDS(nanos) (((signed __int64)(nanos)) / 100L)

#define MICROSECONDS(micros) (((signed __int64)(micros)) * NANOSECONDS(1000L))

#define MILLISECONDS(milli) (((signed __int64)(milli)) * MICROSECONDS(1000L))

#define SECONDS(seconds) (((signed __int64)(seconds)) * MILLISECONDS(1000L))

// https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
#define PROCESS_CREATE_PROCESS            0x0080
#define PROCESS_TERMINATE                 0x0001
#define PROCESS_CREATE_THREAD             0x0002
#define PROCESS_QUERY_INFORMATION         0x0400
#define PROCESS_QUERY_LIMITED_INFORMATION 0x1000
#define PROCESS_SET_INFORMATION           0x0200
#define PROCESS_SET_QUOTA                 0x0100
#define PROCESS_SUSPEND_RESUME            0x0800
#define PROCESS_VM_OPERATION              0x0008
#define PROCESS_VM_READ                   0x0010
#define PROCESS_VM_WRITE                  0x0020

#endif