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:

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.