AMD's CodeXL driver implements DPCs by declaring a local KDPC variable, initializing it, queueing it, creating an event, and waiting for the deferred routine to post to the event. The data passed to the deferred routine is also in a local variable.
I assume this is safe, because AMD's product is out there. But it doesn't follow the documented requirement that it be in a device/controller extension or somewhere allocated from a nonpaged pool.
Is the kernel stack in nonpaged memory, too?
I made the mistake recently of creating my KDPC on the stack, but not waiting for the deferred routine to finish, so that the KDPC would have quickly been overwritten. This resulted in a bugcheck. So I'm putting my KDPC in the device extension.
But that raises the question of reusing the KDPC, and synchronizing usage between threads. Assuming that I've handled the issue of access by different threads, I need to know how long a thread that is using the KDPC needs hold onto it, after queueing it.
Even when the device is only being used by one user File, there may be multiple IRPs coming from different user threads at the same time.