File system filter drivers use completion routines that are similar to those used by device drivers. A completion routine performs completion processing on an IRP. Any driver routine that passes an IRP down to the next-lower-level driver can optionally register a completion routine for the IRP by calling IoSetCompletionRoutine before calling IoCallDriver.
Every IRP completion routine is defined as follows:
NTSTATUS (*PIO_COMPLETION_ROUTINE) ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
Completion routines are called at IRQL <= DISPATCH_LEVEL, in an arbitrary thread context.
Because they can be called at IRQL DISPATCH_LEVEL, completion routines cannot call kernel-mode routines that must be called at a lower IRQL, such as IoDeleteDevice. For the same reason, any data structures that are used in a completion routine must be allocated from nonpaged pool.
This section discusses the following topics: