When to Check the Driver's I/O Stack Location
A major I/O function code is set in the driver's I/O stack location for each incoming IRP.
A driver's dispatch routine must check the driver's I/O stack location for the IRP to determine what to do if any of the following conditions hold:
The dispatch routine handles more than one major I/O function code.
The dispatch routine must handle a set of minor function codes for certain major function codes. IRPs with minor function codes include IRP_MJ_PNP and IRP_MJ_POWER, as well as certain IRPs that the SCSI port driver and file system drivers must handle.
The dispatch routine of a device driver or of a closely coupled higher-level driver handles IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL requests, which have an associated set of I/O control codes.
To get a pointer to a driver's I/O stack location, its dispatch routine calls IoGetCurrentIrpStackLocation.
Higher-level drivers' dispatch routines always call IoGetCurrentIrpStackLocation and also call IoGetNextIrpStackLocation to get a pointer to the next-lower driver's I/O stack location for IRPs that they set up for the next-lower driver, when passing IRPs down the driver stack.
The DispatchDeviceControl routine or DispatchInternalDeviceControl 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. The I/O control code is contained in the driver's I/O stack location.
In most cases, the DispatchDeviceControl or DispatchInternalDeviceControl routine of a higher-level 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, SCSI class drivers must check for certain SCSI Port I/O control codes so that they can set up the SCSI port driver's I/O stack location correctly before passing on these requests.