An NT driver’s Dispatch routine must check its own I/O stack location of the IRP to determine what to do if any of the following conditions hold:
To determine which operation is requested and what parameters to use, if the particular IRP_MJ_XXX has any, the Dispatch routine calls IoGetCurrentIrpStackLocation to get a pointer to its own I/O stack location in the input IRP.
Higher-level NT drivers’ Dispatch routines always call IoGetCurrentIrpStackLocation and also call IoGetNextIrpStackLocation to get a pointer to the next-lower driver’s I/O stack location in the IRPs that they set up for the next-lower driver, as mentioned in Chapter 4.
The Dispatch(Internal)DeviceControl routine of a device driver, or possibly of its closely coupled class driver(s), must determine which I/O control code is set in the driver’s I/O stack location at Parameters.DeviceIoControl.IoControlCode for each request. Such a driver’s Dispatch(Internal)DeviceControl routine frequently features a switch statement, as described later in Section 6.3.4.
In most cases, the Dispatch(Internal)DeviceControl routine of a higher-level NT driver simply passes an IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL request on to the next-lower driver, after setting up its stack location in the IRP. However, NT SCSI class drivers must check for certain IOCTL_SCSI_XXX control codes in order to set up the SCSI port driver’s I/O stack location correctly before they pass on these requests. For more information about these requirements for SCSI class drivers, see Appendix A.