How to Handle Requests that the Frameworks Do Not Support


Neither UMDF nor KMDF supports every possible type of I/O request. For example, the frameworks do not support file-system requests such as IRP_MJ_FILE_SYSTEM_CONTROL. Instead, the frameworks support the I/O request types that drivers most commonly receive.

Chapter 8, "I/O Flow and Dispatching," provides a complete list of supported request types.

Default Handling of Unsupported Requests

UMDF and KMDF differ in their default handling of unsupported requests.

 UMDF  For a UMDF driver, when the reflector receives an IRP of an unsupported type, it passes the IRP down to the next-lower driver in the kernel-mode device stack. UMDF drivers do not have access to requests that the framework does not support.

 KMDF  When KMDF receives a request of an unsupported type, its default action depends on the device object that was the target of the request. For an FDO or PDO, the framework completes the IRP with the status STATUS_INVALID_DEVICE_REQUEST. For a filter DO, the framework passes the IRP to the next-lower driver.

However, a KMDF driver can override this default by registering a callback function to be invoked when an unsupported IRP arrives. The callback function can then process the IRP.

How to Process Unsupported Requests in KMDF Drivers

KMDF defines a WDM IRP preprocessing event callback through which the driver can receive any WDM IRP. To handle such IRPs:

  • In the EvtDriverDeviceAdd callback, call WdfDeviceInitAssignWdmIrpPreprocessCallback for each WDM IRP type that the driver supports.

    In the call, specify the name of the EvtDeviceWdmIrpPreprocess callback function and the major IRP function code and any minor function codes that the callback function handles. The driver must register the callback function before it creates the device object.

  • In the EvtDeviceWdmIrpPreprocess callback, perform whatever tasks the driver requires to handle the IRP, by using the WDM functions as needed.

Each call to WdfDeviceInitAssignWdmIrpPreprocessCallback registers a preprocessing callback for a single major IRP type. A driver can call this method as many times as necessary to register callbacks for multiple types of IRP. A single callback function can preprocess more than one type of IRP.

The framework does not synchronize the call to EvtDeviceWdmIrpPreprocess with the Plug and Play or power state of the device object, so the driver has no guarantee that its hardware is available. Furthermore, the framework does not count the IRP in its tally of current I/O requests for the device object. Consequently, if the device is removed or the device object is being destroyed, the framework does not wait for the IRP to complete. The driver must manage this synchronization on its own.

When the EvtDeviceWdmIrpPreprocess function has finished processing the IRP, the EvtDeviceWdmIrpPreprocess function does one of the following:

  • Calls IoCompleteRequest to complete the IRP.

  • Sets up the next I/O stack location by calling either IoSkipCurrentIrpStackLocation or IoCopyCurrentIrpStackLocationToNext and calls IoCallDriver to pass the IRP to the next lower driver, just as a WDM driver would.

  • Calls WdfDeviceWdmDispatchPreprocessedIrp to pass the IRP to the framework to handle in its usual way.

For a filter DO, the framework passes the IRP to the next lower driver; for any other device object, the framework fails the IRP as described in "Default Handling of Unsupported Requests" earlier in this chapter.

If the driver or the framework passes the IRP down the device stack but the driver requires access to the IRP after lower drivers have completed it-that is, the driver post-processes the IRP-EvtDeviceWdmIrpPreprocess must call IoSetCompletionRoutine or IoSetCompletionRoutineEx for the IRP before passing it to the next-lower driver. The IoCompletion routine post-processes the IRP.

The EvtDeviceWdmIrpPreprocess callback, the call to IoSetCompletionRoutine or IoSetCompletionRoutineEx, and the IoCompletion routine itself must all follow the usual WDM rules for handling IRPs.

Example: Establishing the Preprocess Callback Function in EvtDriverDeviceAdd

The Serial sample shows how to implement and use the EvtDeviceWdmPreprocessIrp callback to handle and complete IRP_MJ_FLUSH_BUFFERS, IRP_MJ_QUERY_INFORMATION, and IRP_MJ_SET_INFORMATION requests. Listing 14-3, excerpted from the Kmdf\Serial\Pnp.c file, shows how a driver's EvtDriverDeviceAdd callback registers the EvtDeviceWdmIrpPreprocess callback function for the IRP_MJ_FLUSH_BUFFERS request.

Listing 14-3: How to register the EvtDeviceWdmPreprocessIrp callback

image from book
 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(              DeviceInit,              SerialFlush,              IRP_MJ_FLUSH_BUFFERS,              NULL, // pointer to minor function table              0); // number of entries in the table 
image from book

The sample registers the callback as part of device initialization, before it creates the device object. The call to WdfDeviceInitAssignWdmIrpPreprocessCallback takes the following five parameters:

  • The PWDFDEVICEINIT pointer that was passed to the EvtDriverDeviceAdd function (DeviceInit).

  • A pointer to the EvtDeviceWdmIrpPreprocess callback to register (SerialFlush).

  • The major IRP code for which to invoke the callback (IRP_MJ_FLUSH_BUFFERS).

  • A pointer to an array of minor function codes for which to invoke the callback-NULL because IRP_MJ_FLUSH_BUFFERS does not have minor function codes.

  • A ULONG value that indicates the number of entries in the array (0).

Whenever an IRP_MJ_FLUSH_BUFFERS request arrives for the device object, the framework invokes the driver's SerialFlush callback function.

Example: Processing in the EvtDeviceWdmPreprocessIrp Callback Function

Listing 14-4, which is excerpted from the Kmdf\Serial\Flush.c file, shows the EvtDeviceWdmPreprocessIrp callback function that was registered in the previous example. The function is called with a handle to the WDFDEVICE object and a pointer to the WDM IRP.

Listing 14-4: How to handle a WDM IRP in an EvtDeviceWdmPreprocessIrp callback

image from book
 NTSTATUS SerialFlush(     IN WDFDEVICE Device,     IN PIRP Irp   ) {     PSERIAL_DEVICE_EXTENSION extension;     extension = SerialGetDeviceExtension(Device);     WdfIoQueueStopSynchronously(extension->WriteQueue);     // Flush is done - restart the queue     WdfIoQueueStart(extension->WriteQueue);     Irp->IoStatus.Information = 0L;     Irp->IoStatus.Status = STATUS_SUCCESS;     IoCompleteRequest(Irp, IO_NO_INCREMENT);     return STATUS_SUCCESS; } 
image from book

This example handles the IRP_MJ_FLUSH_BUFFERS request. This request has no parameters, so the driver immediately begins processing. For this device stack, a flush buffers request indicates a request to flush the write queue. To do so, the driver calls WdfIoQueueStopSynchronously, which returns when all the requests in the queue have been completed or canceled. It then restarts the queue and completes the IRP.

To complete the IRP, the driver writes the NTSTATUS value directly into the IoStatus.Status field and the number of bytes transferred into the IoStatus.Information field of the IRP. It then calls the I/O manager's IoCompleteRequest function to complete the IRP. Because the framework has not created a WDFREQUEST object to represent the request, the driver cannot use the WdfRequestComplete method. For the same reason, if the driver did not complete the request but instead forwarded the request down the device stack, the driver could not use an I/O target.

If your driver handles IRPs outside the framework, as this example shows, it must follow all the usual WDM rules and use WDM functions to manipulate the IRP and any other WDM data structures.

 Tip  See "Kernel-Mode Driver Architecture Design Guide" in the WDK documentation for a deep discussion of the principles and guidelines for handling IRPs in WDF drivers-online at http://go.microsoft.com/fwlink/?LinkId=79288.




Developing Drivers with the Microsoft Windows Driver Foundation
Developing Drivers with the Windows Driver Foundation (Pro Developer)
ISBN: 0735623740
EAN: 2147483647
Year: 2007
Pages: 224

Similar book on Amazon
Windows Internals, Part 1: Covering Windows Server 2008 R2 and Windows 7
Windows Internals, Part 1: Covering Windows Server 2008 R2 and Windows 7
Windowsu00ae Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (Pro Developer)
Windowsu00ae Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (Pro Developer)
Advanced Windows Debugging
Advanced Windows Debugging
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net