Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
Windows 7

Windows 7 Kernel Mode Drivers Overview and Operations : KMDF I/O Model (part 2)

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
12/15/2011 5:56:08 PM

2. I/O Queues

A WDFQueue object represents a queue that presents requests from KMDF to the driver. A WDFQUEUE is more than just a list of pending requests; however, it tracks requests that are active in the driver, supports request cancellation, manages the concurrency of requests, and can optionally synchronize calls to the driver’s I/O event callback functions.

A driver typically creates one or more queues, each of which can accept one or more types of requests. The driver configures the queues when it creates them. For each queue, the driver can specify

  • The types of requests that are placed in the queue.

  • The event callback functions that are registered to handle I/O requests from the queue.

  • The power management options for the queue.

  • The dispatch method for the queue, which determines the number of requests that are serviced at a given time.

  • Whether the queue accepts requests that have a zero-length buffer.

A driver can have any number of queues, and they can all be configured differently. For example, a driver might have a parallel queue for read requests and a sequential queue for write requests.

While a request is in a queue and has not yet been presented to the driver, the queue is considered the “owner” of the request. After the request has been dispatched to the driver, it is “owned” by the driver and is considered an in-flight request internally, and each WDFQUEUE object keeps track of which requests it owns and which requests are pending. A driver can forward a request from one queue to another by calling a method on the request object.

2.1. Queues and Power Management

KMDF provides rich control of queues. The framework can manage the queues for the driver, or the driver can manage queues on its own. Power management is configurable on a per-queue basis. A driver can use both power-managed and non-power-managed queues and can sort requests based on the requirements for its power model.

By default, queues for FDOs and PDOs are power managed, which means that the state of the queue can trigger power-management activities. Such queues have several advantages:

  • If an I/O request arrives while the system is in the working state (SO) but the device is not, KMDF notifies the Plug and Play/power handler so that it can restore device power.

  • When a queue becomes empty, KMDF notifies the Plug and Play/power handler so that it can track device usage through its idle timer.

  • If the device power state begins to change while the driver “owns” an I/O request, KMDF can notify the driver through the EvtIoStop callback. The driver must complete, cancel, or acknowledge all the I/O requests that it owns before the device can leave the working state.

For power-managed queues, KMDF pauses the delivery of requests when the device leaves the working state (DO) and resumes delivery when the device returns to the working state. Although delivery stops while the queue is paused, queuing does not. If KMDF receives a request while the queue is paused, KMDF adds the request to the queue for delivery after the queue resumes. If an I/O request arrives while the device is idle and the system is in the working state, KMDF returns the device to the working state so that it can handle the request. If an I/O request arrives while the system is transitioning to a sleep state, however, KMDF does not return the device to the working state until the system returns to the working state.

For requests to be delivered, both the driver and the device power state must allow processing. The driver can pause delivery manually by calling WdfIoQueueStopWdfIoQueueStart. and resume delivery by calling

If a queue is not power managed, the state of the queue has no effect on power management, and conversely, KMDF delivers requests to the driver any time the system is in the working state, regardless of the power state of the device. KMDF does not start an idle timer when the queue becomes empty, and it does not power up a sleeping device when I/O arrives for the queue.

Drivers should use non-power-managed queues to hold requests that the driver can handle even while its device is not in the working state.

2.2. Dispatch Type

A queue’s dispatch type determines how and when I/O requests are delivered to the driver and, as a result, whether multiple I/O requests from a queue are active in the driver at one time. Drivers can control the concurrency of in-flight requests by configuring the dispatching method for their queues. KMDF supports three dispatch types:

  • Sequential— A queue that is configured for sequential dispatching delivers I/O requests to the driver one at a time. The queue does not deliver another request to the driver until the previous request has been completed. (Sequential dispatching is similar to the start-I/O technique in WDM.)

  • Parallel— A queue that is configured for parallel dispatching delivers I/O requests to the driver as soon as possible, whether or not another request is already active in the driver.

  • Manual— A queue that is configured for manual dispatching does not deliver I/O requests to the driver. Instead, the driver retrieves requests at its own pace by calling a method on the queue.

The dispatch type controls only the number of requests that are active within a driver at one time. It has no effect on whether the queue’s I/O event callbacks are invoked sequentially or concurrently; instead, the concurrency of callbacks is controlled by the synchronization scope of the device object. Even if the synchronization scope for a parallel queue does not allow concurrent callbacks, the queue nevertheless might have many in-flight requests.

All I/O requests that a driver receives from a queue are inherently asynchronous. The driver can complete the request within the event callback or sometime later, after returning from the callback.

3. I/O Request Objects

The WDFREQUEST object is the KMDF representation of an IRP. When an I/O request arrives, the I/O handler creates a WDFREQUEST object, queues the object, and eventually passes the object to the driver in its I/O callback function.

The properties of the WDFREQUEST object represent the fields of the IRP. The object also contains additional information. Like all other KMDF objects, the WDFREQUEST object has a reference count and can have its own object context area. When the driver completes the I/O request that the object represents, KMDF automatically frees the object and any child resources such as associated memory buffers or memory descriptor lists (MDLs). After the driver has called WdfRequestComplete, the driver must not attempt to access the handle to the WDFREQUEST object or any of its child resources. A driver can create its own WDFREQUEST objects to request I/O from another device or to split an I/O request into multiple, smaller requests before completing it.

4. Retrieving Buffers from I/O Requests

The WDFMEMORY object encapsulates the I/O buffers that are supplied for an I/O request. To enable device drivers to handle complicated requests with widely scattered buffers, any number of WDFMEMORY objects may be associated with a WDFREQUEST.

The WDFMEMORY object represents a buffer that the framework manages. The object can be used to copy memory to and from the driver and the buffer represented by the WDFMEMORY handle. In addition, the driver can use the underlying buffer pointer and its length for complex access, such as casting to a known data structure.

Like other KMDF objects, WDFMEMORY objects have reference counts and persist until all references to them have been removed. The buffer that underlies the WDFMEMORY object, however, might not be “owned” by the object itself. For example, if the issuer of the I/O request allocated the buffer or if the driver called WdfMemoryCreatePreallocated to assign an existing buffer to the object, the WDFMEMORY object does not “own” the buffer. In this case, the buffer pointer becomes invalid when the associated I/O request has been completed, even if the WDFMEMORY object still exists.

Each WDFMEMORY object contains the length of the buffer that it represents. KMDF methods that copy data to and from the buffer validate the length of every transfer to prevent buffer over- and underruns, which can result in corrupt data or security breaches.

Depending on the type of I/O that the device and driver support, the underlying buffer might be any of the following:

  • For buffered I/O, a system-allocated buffer from the nonpaged pool.

  • For direct I/O, a system-allocated MDL that points to the physical pages for DMA.

  • For neither buffered nor direct I/O, an unmapped and unverified user mode memory address.

The WDFMEMORY object supports methods that return each type of buffer from the object and methods to read and write the buffers. For device I/O control requests (IOCTLs), KMDF provides methods to probe and lock user mode buffers. The driver must be running in the context of the process that sent the I/O request to probe and lock a user mode buffer, so KMDF also defines a callback that drivers can register to be called in the context of the sending component.

Each WDFMEMORY object also controls access to the buffer and allows the driver to write only to buffers that support I/O from the device to the buffer. A buffer that is used to receive data from the device (as in a read request) is writable. The WDFMEMORY object does not allow write access to a buffer that only supplies data (as in a write request).

5. I/O Targets

Drivers send I/O requests by creating or reusing an I/O request object, creating an I/O target, and sending the request to the target. Drivers can send requests either synchronously or asynchronously. A driver can specify a time-out value for either type of request.

An I/O target represents a device object to which an I/O request is directed. If a driver cannot complete an I/O request by itself, it typically forwards the request to an I/O target. An I/O target can be a KMDF driver, a WDM driver, or any other Kernel Mode Driver.

Before a driver forwards an existing I/O request or sends a new request, it must create a WDFIOTARGET object to represent either a local or remote target for the I/O request. The local I/O target is the next lower driver in the device stack and is the default target or a filter or FDO device object. A remote I/O target is any other driver that might be the target of an I/O request. A driver might use a remote I/O target if it requires data from another device to complete an I/O request. A function driver might also use a remote I/O target to send a device I/O control request to its bus driver. In this case, the I/O request originates with the function driver itself, rather than originating with some other process.

The WDFIOTARGET object formats I/O requests to send to other drivers, handles changes in device state, and defines callbacks through which a driver can request notification about target device removal. A driver can call methods on the WDFIOTARGET to

  • Open a device object or device stack by name.

  • Format read, write, and device I/O control requests to send to the target. Some types of targets, such as WDFUSBDEVICE and WDFUSBPIPE, can format bus-specific requests in addition to the standard request types.

  • Send read, write, and device I/O control requests synchronously or asynchronously.

  • Determine the Plug and Play state of the target.

Internally, KMDF calls IoCallDriver to send the request. It takes out a reference on the WDFREQUEST object to prevent the freeing of associated resources while the request is pending for the target device object.

The WDFIOTARGET object racks queued and sent requests and can cancel them when the state of the target device or of the issuing driver changes. From the driver’s perspective, the I/O target object behaves like a cancel-safe queue that retains forwarded requests until KMDF can deliver them. KMDF does not free the WDFIOTARGET object until all the I/O requests that have been sent to it are complete.

By default, KMDF sends a request only when the target is in the proper state to receive it. However, a driver can also request that KMDF ignore the state of the target and send the request anyway. If the target device has been stopped (but not removed), KMDF queues the request to send later after the target device resumes. If the issuing driver specifies a time-out value, the timer starts when the request is added to the queue.

If the device that is associated with a remote I/O target is removed, KMDF stops and closes the I/O target object, but does not notify the driver unless the driver has registered an EvtIoTargetXxx callback. If the driver must perform any special processing of I/O requests that it sent to the I/O target, it should register one or more such callbacks. When the removal of the target device is queried, canceled, or completed, KMDF calls the corresponding functions and then processes the target state changes on its own.

For local I/O targets, no such callbacks are defined. Because the driver and the target device are in the same device stack, the driver is notified of device removal requests through its Plug and Play and power management callbacks.

6. Creating Buffers for I/O Requests

Drivers that issue I/O requests must supply buffers for the results of those requests. The buffers in a synchronous request can be allocated from any type of memory, such as the nonpaged pool or an MDL, as well as a WDFMEMORY object. Asynchronous requests must use WDFMEMORY object so that KMDF can ensure that the buffers persist until the I/O request has completed back to the issuing driver.

If the driver uses a WDFMEMORY object, the I/O target object takes out a reference on the WDFMEMORY object when it formats the object to send to the I/O target. The target object retains this reference until one of the following occurs:

  • The request has been completed.

  • The driver reformats the WDFREQUEST object.

  • The driver calls WdfRequestReuse to send a request to another target.

A driver can retrieve a WDFMEMORY object from an incoming WDFREQUEST and reuse it later in a new request to a different target. However, if the driver has not yet completed the original request, the original I/O target still has a reference on the WDFMEMORY object. To avoid a bug check, the driver must call WdfRequestReuse in its I/O completion routine before it completes the original request.

7. Canceled and Suspended Requests

Windows I/O is inherently asynchronous. The system can request that a driver stop processing an I/O request at any time for many reasons, of which these are the most common:

  • The thread or process that issued the request cancels it or exits.

  • A system Plug and Play or power event such as hibernation occurs.

  • The device is being, or has been, removed.

The actions that a driver takes to stop processing an I/O request depend on the reason for suspension or cancellation. In general, the driver can either cancel the request or complete it with an error. In some situations, the system might request that a driver suspend (temporarily pause) processing; the system notifies the driver later when to resume processing.

To provide a good user experience, drivers should provide callbacks to handle cancellation and suspension of any I/O request that might take a long time to complete or that might not complete, such as a request for asynchronous input.

7.1. Request Cancellation

How KMDF proceeds to cancel an I/O request depends on whether the request has already been delivered to the target driver:

  • If the request has never been delivered—either because KMDF has not yet queued it or because it is still in a queue—KMDF cancels or suspends it automatically. If the original IRP has been canceled, KMDF completes the request with a cancellation status.

  • If the request has been delivered and then requeued, KMDF notifies the driver of cancellation only if the driver has registered an EvtIoCanceledOnQueue callback for the queue.

After a request has been delivered, it cannot be canceled unless the driver that owns it explicitly marks it cancelable by calling the WdfRequestMarkCancelableEvtRequestCancel) for the request. method on the request and registering a cancellation callback (

A driver should mark a request cancelable and register an I/O cancellation callback if either of the following is true:

  • The request involves a long-term operation.

  • The request might never succeed; for example, the request is waiting for synchronous input.

In the EvtRequestCancel callback, the driver must perform any tasks that are required to cancel the request, such as stopping any device I/O operations that are in progress and canceling any related requests that it has already forwarded to an I/O target. Eventually, the driver must complete the request with the status STATUS_CANCELLED.

Requests that are marked cancelable cannot be forwarded to another queue. Before requeuing a request, the driver must first make it noncancelable by calling WdfRequestUnmarkCancelable. After the request has been added to the new queue, KMDF once again considers it cancelable until that queue dispatches it to the driver.

If the driver does not mark a request cancelable, it can call WdfRequestIsCanceled to determine whether the I/O manager or original requester has attempted to cancel the request. A driver that processes data on a periodic basis might use this approach. For example, a driver involved in image processing might complete a transfer request in small chunks and poll for cancellation after processing each chunk. In this case, the driver supports cancellation of the I/O request, but only after each discrete chunk of processing is complete. If the driver determines that the request has been canceled, it performs any required cleanup and completes the request with the status STATUS_CANCELLED.

7.2. Request Suspension

When the system transitions to a sleep state—typically because the user has requested hibernation or closed the lid on a laptop—a driver can complete, requeue, or continue to hold any in-flight requests. KMDF notifies the driver of the impending power change by calling the EvtIoStop callback for each in-flight request. Each call includes flags that indicate the reason for stopping the queue and whether the I/O request is currently cancelable.

Depending on the value of the flags, the driver can complete the request, requeue the request, acknowledge the event but continue to hold the request, or ignore the event if the current request will complete in a timely manner. If the queue is stopping because the device is being removed (either by an orderly removal or a surprise removal), the driver must complete the request immediately.

Drivers should handle EvtIoStop events for any request that might take a long time to complete or that might not complete, such as a request for asynchronous input. Handling EvtIoStop provides a good user experience for laptops and other power-managed systems.

8. Completing I/O Requests

To complete an I/O request, a driver calls WdfRequestComplete. In response, KMDF completes the underlying IRP and then deletes the WDFREQUEST object and any child objects. If the driver has set an EvtCleanupCallback for the WDFREQUEST object, KMDF invokes the callback before completing the underlying IRP, so that the IRP itself is still valid when the callback runs.

After WdfRequestComplete returns, the WDFREQUEST object’s handle is invalid and its resources have been released. The driver must not attempt to access the handle or any of its resources, such as parameters and memory buffers that were passed in the request.

If the request was dispatched from a sequential queue, the driver’s call to complete the IRP might cause KMDF to deliver the next request in the queue. (If the queue is configured for parallel dispatching, KMDF can deliver another request at any time.) If the driver holds any locks while it calls WdfRequestComplete, it must ensure that its event callbacks for the queue do not use the same locks because a deadlock might occur. In practice, this is difficult to ensure, so the best practice is not to call WdfRequestComplete while holding a lock.

9. Self-Managed I/O

Although the I/O support that is built into KMDF is recommended for most drivers, some drivers have I/O paths that do not pass through queues or are not subject to power management. KMDF provides self-managed I/O features for this purpose. For example, the PCIDRV sample uses self-managed I/O callbacks to start and stop a watchdog timer DPC.

The self-managed I/O callbacks correspond directly to WDM Plug and Play and power management state changes. These routines are called with a handle to the device object and no other parameters. If a driver registers these callbacks, KMDF calls them at the designated times so that the driver can perform whatever actions it requires.

10. Accessing IRPs and WDM Structures

KMDF includes a mechanism nicknamed “the great escape” through which a driver can access the underlying WDM structures and the I/O request packet as it was delivered from the operating system. Although this mechanism exposes the driver to all the complexity of the WDM model, it can often be useful in converting a WDM driver to KMDF, such as processing for some types of IRPs. Such drivers can use KMDF for most features but can rely on the “great escape” to gain access to the WDM features that they require.

To use the “great escape,” a driver calls WdfDeviceInitAssignWdmIrpPreprocessCallback to register an EvtDeviceWdmIrpPreprocess event callback function for an IRP major function code. When KMDF receives an IRP with that function code, it invokes the callback. The driver must then handle the request just as a WDM driver would, by using I/O manager functions such as IoCallDriver to forward the request and IoCompleteRequest to complete it. The Serial driver sample shows how to use this feature.

In addition to the “great escape,” KMDF provides methods with which a driver can access the WDM objects that the KMDF objects represent. For example, a driver can access the IRP that underlies a WDFREQUEST object, the WDM device object that underlies a WDFDEVICE object, and so forth.

Other -----------------
- Windows 7 Kernel Mode Drivers Overview and Operations : KMDF Object Model
- Windows 7 Kernel Mode Drivers Overview and Operations (part 2) - Device Objects and Driver Roles
- Windows 7 Kernel Mode Drivers Overview and Operations (part 1)
- Microsoft Power Point 2010 : Inserting a Diagram & Editing SmartArt Text
- Microsoft Power Point 2010 : Understanding SmartArt Types and Their Uses
- Visual Studio 2010 : Taking Command from Control Central
- Visual Studio 2010 : Designing Windows Forms
- Troubleshooting and Recovering from Disaster : Using System Restore to Repair Windows
- Microsoft Visio 2010 : Editing Existing Hyperlinks & Adding Multiple Hyperlinks
- Microsoft Visio 2010 : Setting the Hyperlink Base
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
Windows Vista
Windows 7
Windows Azure
Windows Server