I was working on a mouse and a keyboard filter driver and decided to look at Microsoft’s examples and noticed that their ‘MouFilter_EvtIoInternalDeviceControl’ function (same with the keyboard version) had a description that said, “This routine is the dispatch routine for internal device control requests.”. After more investigating it seems like this function runs at Dispatch Level if this is true, I wonder why they would have ‘#pragma alloc_text (PAGE, MouFilter_EvtIoInternalDeviceControl)’ and ‘PAGED_CODE()’ located inside the function because I thought functions running at Dispatch Level can never be paged out without causing a fault.
My second question pertains to the same function where I have been advised to add a SpinLock to the Device Extension and then acquire that lock inside of ‘case IOCTL_INTERNAL_MOUSE_DISCONNECT:’ and then release it before breaking out. I was advised that this was good to do in order to mitigate other threads from trying to run the ‘IOCTL_INTERNAL_MOUSE_CONNECT’ case while ‘IOCTL_INTERNAL_MOUSE_DISCONNECT’ is being ran from a separate thread. This seems very unlikely to be an issue, but I don’t see what being a little extra carful could harm.
‘IOCTL_INTERNAL_MOUSE_CONNECT’ and DISCONNECT will not run concurrently with the current implementation. It has been this way for 25+ years. If you feel safer synchronizing the two, go for it.
@Doron_Holan said:
‘IOCTL_INTERNAL_MOUSE_CONNECT’ and DISCONNECT will not run concurrently with the current implementation. It has been this way for 25+ years. If you feel safer synchronizing the two, go for it.
@Cyclone said:
I was working on a mouse and a keyboard filter driver and decided to look at Microsoft’s examples and noticed that their ‘MouFilter_EvtIoInternalDeviceControl’ function (same with the keyboard version) had a description that said, “This routine is the dispatch routine for internal device control requests.”. After more investigating it seems like this function runs at Dispatch Level if this is true, I wonder why they would have ‘#pragma alloc_text (PAGE, MouFilter_EvtIoInternalDeviceControl)’ and ‘PAGED_CODE()’ located inside the function because I thought functions running at Dispatch Level can never be paged out without causing a fault.
The word “dispatch” is very overloaded in Windows…In the underlying Windows Driver Model (WDM) the I/O Manager dispatches I/O requests to drivers by calling their “I/O Dispatch Entry Points”. WDF abstracts the Dispatch Entry Points using WDFIOQUEUEs and their associated “I/O Event Processing Callbacks”. So, in this case, the “MouFilter_EvtIoInternalDeviceControl Event Processing Callback” is an abstraction of what would have originally been an “IRP_MJ_INTERNAL_DEVICE_CONTROL Dispatch Entry Point” (or “Dispatch Routine”).
Going back to the IRQL question: The I/O Dispatch Entry Points can run at IRQL <= DISPATCH_LEVEL* depending on the stack and who is sending the I/O requests. If you’re writing a filter you can’t know a priori at what IRQL(s) your Dispatch Entry Points (and therefore I/O Event Processing Callbacks) will run as you don’t control the I/O rules of the stack. Presumably whoever wrote the sample “knows” that the Internal IOCTL requests in the mouse stack are always processes at < DISPATCH_LEVEL and therefore it’s safe to put this in a pageable code section. Note that the WDFQUEUEs also have an ExecutionLevel option that allows you to force your callbacks to run at PASSIVE_LEVEL, though that’s often a bad idea in a filter unless you REALLY know the rules and behavior of the stack.
*The “dispatch” in DISPATCH_LEVEL is referring to the Thread Dispatcher, which is a different use of the word and not directly related to the I/O Dispatch Entry Points (except that they can possibly run at DISPATCH_LEVEL…Head hurt yet? ?)