0

Just want to understand APCs better. To queue a user mode APC, we can use the QueueUserAPC function. So how to queue a special/normal kernel mode APC? Thanks.

1 Answers1

1

APC must be allocated only from non-paged pool because APC can be inserted (by KeInsertQueueAPC) in thread list at DPC level - so if you for example allocate KAPC from paged pool, insert it, and then somebody try insert another APC at DPC level - your paged APC data can be assigned (when inserted to linked list) and as result BSOD

for initialize KAPC use KeInitializeApc. if for free APC need exactly call ExFreePool and nothing more you can use 0 as RundownRoutine. otherwise you must provide own RundownRoutine for correct cleanup. KernelRoutine always must be set, and because almost always it point to some function in your driver - driver must not be unloaded until APC will be not executed. usual need call ObfReferenceObject for driver object before insert APC by KeInsertQueueAPC and ObfDereferenceObject after KernelRoutine or RundownRoutine will be executed (or KeInsertQueueAPC return false). but you can not "normal way" call ObfDereferenceObject - this is senseless (if driver hold on last reference - will be crash when ObfDereferenceObject return to your driver code. you need assembly written proxy from KernelRoutine and RundownRoutine which call they c/c++ implementation and on exit do jmp (but not call !!) instruction to ObfDereferenceObject and stack must be special rebuild for after ObfDereferenceObject call ret - code will be returned to kernel code, which call your driver callback routine (kernel or rundown) - so skip driver code execute after ObfDereferenceObject

for more details - read Inside NT's Asynchronous Procedure Call - despite this is already very old article - nothing changed from this time and in latest win 10 - all the same

RbMm
  • 31,280
  • 3
  • 35
  • 56