6.3.4.1 DispatchDeviceControl in Lowest-Level Drivers
-
An IRP_MJ_DEVICE_CONTROL request for a lowest-level NT driver either requires
the driver to change the state of its device or to provide information about
the state of its device. Because most kinds of NT drivers are required to
handle a number of I/O control codes, their DispatchDeviceControl routines
usually contain a switch statement somewhat like the following:
-
: :
switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_DeviceType_XXX:
case IOCTL_DeviceType_YYY:
if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
(sizeof(IOCTL_XXXYYY_STRUCTURE))) {
status = STATUS_BUFFER_TOO_SMALL;
break;
} else {
IoMarkIrpPending(Irp);
: : // pass IRP on for further processing
case ...
: :
As this code fragment shows, a DispatchDeviceControl routine also checks
parameters, sometimes on each I/O control code that the driver must support,
sometimes on groups of these IOCTL_XXX.
Consider these
implementation guidelines for device drivers’ DispatchDeviceControl routines:
-
As for any IRP and driver Dispatch routine, DispatchDeviceControl must check
the parameters for validity and complete IRPs with parameter errors
immediately, as described in Section
6.2.3.
-
Switching first on any I/O control codes for which the DispatchDeviceControl
routine can satisfy and complete the IRP improves performance because the
driver can return control faster.
For better performance, every NT device driver should satisfy any device
control request that it can, without queueing the IRP to other driver
routines, in its DispatchDeviceControl routine.
-
Switching later on I/O control codes that specify infrequently requested
operations also can improve the driver’s performance in processing
IRP_MJ_DEVICE_CONTROL_REQUESTS.
-
Grouping cases of I/O control codes as possible when testing for valid
parameters is economical both in term of driver performance/size and in code
maintenance. As the preceding code fragment suggests, I/O control codes that
use a common structure are natural candidates for such a case group.
For those IRPs that the DispatchDeviceControl routine can complete, it should
call IoCompleteRequest with a PriorityBoost of IO_NO_INCREMENT.
The DispatchDeviceControl routine must call IoMarkIrpPending with each
request that it queues for further processing on the device and it must return
STATUS_PENDING.