4.2 TDI Driver Dispatch Routines

All TDI requests are handled by the Windows NT I/O Manager. Such requests are formatted as IRPs either by the I/O Manager or explictly by a client and submitted to the transport driver by calling IoCallDriver. Completed IRPs are returned to the caller when the transport driver calls IoCompleteRequest or TdiCompleteRequest. Any kernel-mode TDI client can set its IoCompletion routine an IRP before it calls IoCallDriver.

There are five IRP_MJ_XXX codes used to send I/O requests to TDI transport drivers. These transports handle incoming IRPs in which the MajorFunctionCode is one of the following:

IRP_MJ_CREATE

Opens a transport address, connection endpoint, or control channel in the underlying transport.

This request originates in a client's call to ZwCreateFile.

IRP_MJ_INTERNAL_DEVICE_CONTROL

Specifies kernel-mode client requests (TDI IOCTLs), for which internal transport functions handle operations other than opening and closing file objects.

This request usually originates in a client's call to a TdiBuildXxx macro followed by its call to IoCallDriver.

IRP_MJ_DEVICE_CONTROL

Specifies user-mode-visible IOCTL requests issued by a transport-dedicated application. Except for any transport-defined "private" IOCTLs, such requests usually are forwarded to the same internal driver functions that handle internal-device control requests.

This request originates in a call by a transport-dedicated user-mode application to DeviceIoControl.

IRP_MJ_CLEANUP

Closes an open address, connection endpoint, or control channel when the Windows NT executive is closing the last handle for the corresponding file object.

This request originates in a client's call ZwClose.

IRP_MJ_CLOSE

Closes an address, connection endpoint, or control channel if the executive is removing its last reference to the file object handle.

This request follows an IRP_MJ_CLEANUP request on the same file object.

The entry points in the TDI driver are one or more Dispatch routines that handle these IRP_MJ_XXX requests. Because a TDI client communicates with the driver only through IRPs, the driver has one or more TdiDispatchXxx routines that determine what operation to carry out and, usually, pass the client requests to appropriate internal driver functions for further processing.

A TDI transport driver exports all its TdiDispatchXxx entry points by setting them in the driver object passed in to its DriverEntry routine. The I/O Manager calls a TdiDispatchXxx routine whenever a client makes an I/O request. A transport driver can have a separate TdiDispatchXxx to handle each of the possible IRP_MJ_XXX opcodes, a single TdiDispatch routine that processes IRPs with all possible IRP_MJ_XXX opcodes, or a number of TdiDispatchXxx that handle discrete subsets of the IRP_MJ_XXX opcodes.

Since all Dispatch entry points are exported by address in the driver object, not by name, a TDI transport driver writer can name these routines anything. In this TDI documentation, TdiDispatchXxx routines have the following metanames, each describing their basic functionality, to correspond with the preceding IRP_MJ_XXX:

IRP_MJ_CREATE

TdiDispatchCreate

IRP_MJ_DEVICE_INTERNAL_CONTROL

TdiDispatchInternalDeviceControl

IRP_MJ_DEVICE_CONTROL

TdiDispatchDeviceControl

IRP_MJ_CLEANUP

TdiDispatchCleanup

IRP_MJ_CLOSE

TdiDispatchClose