Flylib.com

Books Software

 
 
 

The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition) - page 57

< BACK    NEXT  >
[oR]

Summary

This completes the implementation of an initial Windows 2000 device driver. Granted, this Minimal driver is kernel-mode only. Converting it to a WDM driver must wait until chapter 9. Nevertheless, tools to build and install a driver are now ready to go. Additionally, the beginning structure of the kernel-mode device driver is forming.

The next chapter discusses the Dispatch routines necessary to make the driver useful. Read, Write, and I/O Control functions are implemented. Coding shown in the next chapter builds upon the minimal driver built in this chapter.

< BACK    NEXT >
< BACK    NEXT >
[oR]

Chapter 7. Driver Dispatch Routines

CHAPTER OBJECTIVES

  • Announcing Driver Dispatch Routines

  • Writing Driver Dispatch Routines

  • Processing Read and Write Requests

  • Code Example: A Loopback Device

  • Extending the Dispatch Interface

  • Testing Driver Dispatch Routines

  • Summary

Getting a driver to load is the first step, but ultimately the job of a driver is to respond to I/O requests -from user -mode applications or from other parts of the system. Windows 2000 drivers process these requests by implementing Dispatch routines. The I/O Manager in response to a request calls these routines. This chapter describes the basic Dispatch routines and explains the overall process of handling I/O requests.

< BACK    NEXT >
< BACK    NEXT >
[oR]

Announcing Driver Dispatch Routines

Before a driver can process I/O requests , it must announce what kinds of operations it supports. This section describes the I/O Manager's dispatching mechanism and explains how to enable receipt of appropriate I/O function codes. It also presents guidelines for deciding which function codes should be supported for different device types.

I/O Request Dispatching Mechanism

Windows 2000 I/O operations are packet-driven. When an I/O request is initiated, the I/O Manager first builds an IRP work-order to keep track of the request. Among other things, it stores a function code in the MajorField field of the IRP's I/O stack location to uniquely identify the type of request.

The MajorField code is used by the I/O Manager to index the Driver object's MajorFunction table. The table contains a function pointer to a Dispatch routine specific to the I/O request. If a driver does not support the requested operation, the MajorFunction table entry points to an entry within the I/O Manager, _IopInvalidDeviceRequest, which returns an error to the original caller. Thus, it is the responsibility of the driver author to provide Dispatch routines for each I/O function code that it supports. Figure 7.1 illustrates this process.

Figure 7.1. Dispatch routine selection.
graphics/07fig01.gif

Enabling Specific Function Codes

To enable specific I/O function codes, a driver must first "announce" the Dispatch routine that responds to such a request. The announcement mechanism is simply the work performed by DriverEntry that stores the Dispatch routine function address into the appropriate slot of the MajorFunction table of the driver object. The I/O function code is the index used for the table. The following code fragment illustrates the process of announcement.

NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDO,
                         IN PUNICODE_STRING pRegPath ) {
         :
    pDO->MajorFunction[ IRP_MJ_CREATE ] = DispCreate;
    pDO->MajorFunction[ IRP_MJ_CLOSE ] = DispClose;
    pDO->MajorFunction[ IRP_MJ_CLEANUP ] = DispCleanup;
    pDO->MajorFunction[ IRP_MJ_READ ]= DispRead;
    pDO->MajorFunction[ IRP_MJ_WRITE ] = DispWrite;
        :
    return STATUS_SUCCESS;
}

Notice that each I/O function code (table index) is identified by a unique symbol of the form IRP_MJ_XXX, defined by the NTDDK.h (and WDM.h) include file. Of course, these symbolic constants should always be used in lieu of hard-coded constants.

The announcement technique also allows for a single routine to be used to handle multiple request types. DriverEntry would place the common Dispatch routine address in multiple table slots. Since the IRP workorder contains the requested code, the common function could dispatch internally as appropriate.

Finally, it should be noted that function codes drivers do not support should be left untouched by DriverEntry. The I/O Manager fills the entire MajorFunction table of the Driver object with pointers to _IopInvalidDeviceRequest before calling DriverEntry.

Deciding Which Function Codes to Support

All drivers must support the function code IRP_MJ_CREATE since this code is generated in response to the Win32 CreateFile call. Without support for this code, Win32 applications would have no way to obtain a handle to the device. Similarly, the IRP_MJ_CLOSE must also be supported to handle the Win32 CloseHandle call. Incidentally, the CloseHandle call is made automatically by the system for all handles left open at the time of application termination.

The other function codes that a driver should support depend on the nature of the device it controls. Table 7.1 associates I/O function codes with the Win32 calls that generate them. When writing layered drivers, the higher driver must support a superset of the lower driver(s) since the user request dispatches through the higher driver first.

Table 7.1. IRP Function Codes
IRP MajorFunction Codes  
Function Code Description
IRP_MJ_CREATE Request for a handle
  CreateFile
IRP_MJ_CLEANUP Cancel pending IRPs on handle close
  CloseHandle
IRP_MJ_CLOSE Close the handle
  CloseHandle
IRP_MJ_READ Get data from device
  ReadFile
IRP_MJ_WRITE Send data to device
  WriteFile
IRP_MJ_DEVICE_CONTROL Control operation
  DeviceIoControl
IRP_MJ_INTERNAL_DEVICE_CONTROL Control operation available only to kernel-mode clients (no Win32 call)
IRP_MJ_QUERY_INFORMATION Get length of file
  GetFileSize
IRP_MJ_SET_INFORMATION Set length of file
  SetFileSize
IRP_MJ_FLUSH_BUFFERS Write or discard buffers
  FlushFileBuffers
  FlushConsoleInputBuffer
  PurgeComm
IRP_MJ_SHUTDOWN System shutting down
  InitiateSystemShutdown
< BACK    NEXT >