KMDF established its own dispatch routines that intercept all IRPs that are sent to the driver. Figure 1 shows the overall flow of I/O through the KMDF library and driver.
When an IRP arrives, KMDF directs it to one of the following components for processing:
I/O request handler, which handles requests that involve device I/O.
Plug and Play/power request handler, which handles Plug and Play and power request (IRP_MJ_PNP and IRP_MJ_POWER requests) and notifies other components of changes in device status.
WMI handler, which handles WMI and event-tracing request (IRP_MJ_SYSTEM_CONTROL requests).
Each component takes one or more of the following actions for each request:
Raises one or more events to the driver.
Forwards the request to another internal handler or I/O target for further processing.
Completes the request based on its own action.
Completes the request as a result of a driver call.
If the request has not been
processed when it reaches the end of frameworks processing, KMDF takes
an action that is appropriate for the type of driver. For function and
bus drivers, KMDF completes the request with the status STATUS_INVALID_DEVICE_REQUEST. For filter drivers, KMDF automatically forwards the request to the default I/O target (the next lower driver). The next sections describe how each of the three components processes I/O requests.
1. I/O Request Handler
The I/O request handler
dispatches I/O requests to the driver, manages I/O cancellation and
completion, and works with the Plug and Play/power handler to ensure
that the device state is compatible with performing device I/O.
Depending on the type of I/O
request, the I/O request handler either queues the request or invokes an
event callback that the driver registered for the request.
1.1. Create, Cleanup, and Close Requests
To handle create events, a
driver can either configure a queue to receive the events or can supply
an event callback that is invoked immediately. The driver’s options are
the following:
To be called immediately, the driver supplies an EvtDeviceFileCreate callback and registers it from the EvtDriverDeviceAdd callback by calling WdfDeviceInitSetFileObjectConfig.
To configure a queue to receive the requests, the driver calls WdfDeviceConfigureRequestDispatching and specifies WdfRequestTypeCreate. If the queue is not manual, the driver must register an EvtIoDefault callback, which is called when a create request arrives.
Queuing takes precedence over the EvtDeviceFileCreate callback—that is, if the driver both registers for EvtDeviceFileCreate
events and configures a queue to receive such requests, KMDF queues the
requests and does not invoke the callback. KMDF does not queue create
requests to a default queue; the driver must explicitly configure a
queue to receive them.
In a bus or function driver, if a create request arrives for which the driver has neither registered an EvtDeviceFileCreate
callback function nor configured a queue to receive create requests,
KMDF opens a file object to represent the device and completes the
request with STATUS_SUCCESS.
Therefore, any bus or function driver that does not accept create or
open requests from user mode application—and thus does not register a
device interface—must register an EvtDeviceFileCreate
callback that explicitly fails such requests. Supplying a callback to
fail create requests ensures that a rogue user mode application cannot
gain access to the device.
If
a filter driver does not handle create requests, KMDF by default
forwards all create, cleanup, and close requests to the default I/O
target (the next lower driver). Filter drivers that handle create
requests should perform whatever filtering tasks are required and then
forward such requests to the default I/O target. If the filter driver
completes a create request for a file object, it should set AutoForwardCleanupClose to WdfFalse
in the file object configuration so that KMDF completes cleanup and
close requests for the file object instead of forwarding them.
To handle file cleanup and close requests, a driver registers the EvtFileCleanup and EvtFileClose
event callbacks. If a bus or function driver does not register such a
callback, KMDF closes the file object and completes the request with STATUS_SUCCESS.
In a filter driver that does not register cleanup and close callbacks,
KMDF forwards these requests to the default I/O target unless the driver
has explicitly set AutoForwardCleanupClose to WdfFalse in the file object configuration.
1.2. Read, Write, Device I/O Control, and Internal Device I/O Control Requests
For read, write, device I/O
control, and internal device I/O control requests, the driver creates
one or more queues and configures each queue to receive one or more
types of I/O requests. When such a request arrives, the I/O request
handler does the following:
Determines
whether the driver has configured a queue for this type of request. If
not, the handler fails a read, write, device I/O control, or internal
device I/O control request if this is a function or bus driver. If this
is a filter driver, the handler passes such a request to the default I/O
target.
Determines whether the queue is accepting requests and the device is powered on. If both are true, the handler creates a WDFREQUEST
object to represent the request and adds it to the queue. If the queue
is not accepting requests, the handler fails the request.
If the device is not in the DO state, notifies the Plug and Play/power handler to power up the device.
Queues the request.
Figure 2
shows the flow of a read, write, device I/O control, or internal device
I/O control request through the I/O request handler to the driver.