> After some time, the 2nd thread finishes its work and calls ExitProcess.
Note that internally ExitProcess is just a) calling the DllMain routines and b) TerminateProcess.
The latter call enters the kernel and sends the “exit special APC” to all threads in the process.
After receiving this APC, the thread will exit. This “receive the APC” situation occurs:
a) for a thread running in user mode - immediately
b) for a thread running in kernel mode - on next return to user mode
c) for a thread waiting for a non-overlapped IO operation (inside Read/WriteFile/DeviceIoControl) - the thread is awaken by this special APC, and goes on trying to cancel the request. If cancellation fails, then the thread waits for the IRP to complete its normal way with a huge timeout (minute or so). In case of timeout, the hard error is raised, with event logging and baloon/message box UI.
d) for a thread waiting in the driver with KernelMode/Alertable=FALSE, the APC is not delivered till the wait will be satisfied.
Then, when the thread receives the APC, its exit procedure starts.
The exit procedure tries to cancel all overlapped IO IRPs still pending off this thread, then waits for them for some large time (minute or so), then, when no IRPs are left - the thread is really destroyed. On timeout, the same occurs but with a dialog box/maybe event logging.
The process is actually killed (with MJ_CLEANUP sent to all handles) when the last thread in it exits.
So note that, if you have a thread blocked by KeWaitForSingleObject in kernel mode, this can really make an “unkillable” process which will not die till this wait will be satisfied. Avoid doing such things, pend the IRP instead and provide the cancel routine for it.
–
Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com