Example: Passing the IRP Down Without Setting a Completion Routine

Note

For optimal reliability and performance, use file system minifilter drivers with Filter Manager support instead of legacy file system filter drivers. To port your legacy driver to a minifilter driver, see Guidelines for Porting Legacy Filter Drivers.

To pass the IRP down to lower-level drivers without setting a completion routine, a dispatch routine must do the following actions:

  • Call IoSkipCurrentIrpStackLocation to remove the current IRP stack location, so that the I/O Manager doesn't look for a completion routine there when it performs completion processing on the IRP.
  • Call IoCallDriver to pass the IRP down to the next lower-level driver.

This technique is illustrated in the following code examples:

IoSkipCurrentIrpStackLocation ( Irp ); 
return IoCallDriver ( NextLowerDriverDeviceObject, Irp ); 

Or, equivalently:

IoSkipCurrentIrpStackLocation ( Irp ); 
status = IoCallDriver ( NextLowerDriverDeviceObject, Irp ); 
/* log or debugprint the status value here */
return status; 

In these examples, the first parameter in the call to IoCallDriver is a pointer to the next-lower-level filter driver's device object. The second parameter is a pointer to the IRP.

Advantages of This Approach

Calling IoSkipCurrentIrpStackLocation is simple and efficient and should be used in all cases where the driver passes the IRP down the driver stack without registering a completion routine.

Disadvantages of This Approach

After IoCallDriver is called, the IRP pointer that was passed to IoCallDriver is no longer valid and can't safely be dereferenced. If the driver needs to perform further processing or cleanup after lower-level drivers have processed the IRP, it must set a completion routine before sending the IRP down the driver stack. For more information about writing and setting completion routines, see Using Completion Routines.

If you call IoSkipCurrentIrpStackLocation for an IRP, you can't set a completion routine for it.