Last reviewed and updated: 11 May 2020
The concept of “arbitrary thread context” or “arbitrary process and thread context” is often confusing to new Windows driver developers. OSR’s Peter Viscarola clarifies this concept in this video:
Here’s what Peter had to say:
I’m going to describe what we mean when we say that a particular callback or function is called in an “arbitrary process and thread context.” And I’m going to contrast this with what we mean when we talk about a “specific process and thread context.”
When we ask what context something runs in, what we’re really asking is what is the current thread as established by the Windows Dispatcher (the Windows scheduler). Knowing what thread also tells us what process. And knowing what process tells us things like the virtual memory setup, the default security token, the default priorities, etc. for that process.
With that definition, what we mean specifically when we say that a routine or a callback executes in an arbitrary process and thread context? What we mean is that we can’t predict in advance the context that that callback will be executing in. In other words, we don’t know which thread will be the currently scheduled thread when that callback is called.
Understanding arbitrary process and thread context is important because most of the entry points in a KMDF driver are in fact called in this context. If you have a driver that handles interrupts, when your device interrupts your interrupt service routine executes in the context of whatever process and thread happens to be running at the time when the interrupt occurs. This is also the case for kernel timers. When that timer fires, you can’t predict in advance what process and thread will be running when that timer fires. And your timer callback in your driver will be called in the context of whatever thread and process happens to be running at that time. Thus, we say that these routines (interrupts and kernel timer callbacks) execute in an arbitrary process and thread context. This is also the case with your EvtIoXxx Event Processing Callbacks. When you get a read and you get a write, you can’t predict in advance what that context will be.
Contrast this arbitrary process and thread context with the concept of specific process and thread context. When we say a routine runs in a specific process and thread context what we’re saying is we can predict in advance what thread and process will be running when that callback is called. This is the case, for example, the callbacks like EvtFileCleanup, which is always called at IRQL PASSIVE_LEVEL, and in the context of the requesting process (the process that closed the handle). It’s the same for the EvtIoInCallerContext Event Processing Callback. EvtIoInCallerContext is always called in the context of the requesting process and thread (the process and thread that issued the IO request).
So… that’s the difference between arbitrary and specific process and thread context. When you hear people talk about arbitrary thread context, all they’re saying is that you can’t know for certain the context in which the callback will take place.