#pragma once // ke_apc.h - kernel APC infrastructure // // Kernel APCs are per-thread callbacks that run in the target thread's // context when that thread reaches PASSIVE_LEVEL and APC delivery is enabled. // They are the first APC layer; user APCs will build on this once trap-frame // return-to-user delivery exists. #include #include #include #include struct THREAD; typedef struct THREAD THREAD; typedef struct KTRAP_FRAME KTRAP_FRAME; typedef struct KAPC KAPC; typedef void (*PKKERNEL_ROUTINE)(KAPC* apc, void** normalRoutine, void** normalContext, void** systemArgument1, void** systemArgument2); typedef void (*PKNORMAL_ROUTINE)(void* normalContext, void* systemArgument1, void* systemArgument2); typedef void (*PKRUNDOWN_ROUTINE)(KAPC* apc); typedef struct KUSER_APC KUSER_APC; typedef struct SYS_USER_APC_FRAME_K { uint64_t Magic; uint64_t OriginalRip; uint64_t OriginalRsp; uint64_t OriginalRflags; uint64_t OriginalRax; uint64_t Routine; uint64_t NormalContext; uint64_t SystemArgument1; uint64_t SystemArgument2; } SYS_USER_APC_FRAME_K; #define SYS_USER_APC_FRAME_MAGIC 0x3143504152555355ULL /* "USURAPC1" little-ish */ struct KUSER_APC { LIST_ENTRY Link; void* Routine; void* NormalContext; void* SystemArgument1; void* SystemArgument2; }; struct KAPC { LIST_ENTRY Link; THREAD* Thread; PKKERNEL_ROUTINE KernelRoutine; PKNORMAL_ROUTINE NormalRoutine; PKRUNDOWN_ROUTINE RundownRoutine; void* NormalContext; void* SystemArgument1; void* SystemArgument2; volatile long Inserted; }; void KiInitializeApcState(THREAD* thread); __declspec(dllexport) void KeInitializeApc(KAPC* apc, THREAD* thread, PKKERNEL_ROUTINE kernelRoutine, PKNORMAL_ROUTINE normalRoutine, void* normalContext); __declspec(dllexport) void KeSetApcRundownRoutine(KAPC* apc, PKRUNDOWN_ROUTINE rundownRoutine); __declspec(dllexport) bool KeInsertQueueApc(KAPC* apc, void* systemArgument1, void* systemArgument2); __declspec(dllexport) void KeEnterCriticalRegion(void); __declspec(dllexport) void KeLeaveCriticalRegion(void); __declspec(dllexport) bool KeAreKernelApcsDisabled(void); // Internal dispatcher hook. Called when a thread returns to PASSIVE_LEVEL, // after context switches, and after waits complete. void KiDeliverKernelApcs(void); __declspec(dllexport) KSTATUS KeSetUserApcDispatcher(void* dispatcher); __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread, void* routine, void* normalContext, void* systemArgument1, void* systemArgument2); __declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* frame); void KiRundownApcState(THREAD* thread); // Called from KiExitTrapFrame before committing the editable user return state. void KiCheckForUserApcDelivery(KTRAP_FRAME* frame);