Processing I/O Operations

The filter manager simplifies processing I/O operations for minifilter drivers. Unlike a legacy filter driver, which must correctly pass all I/O requests to the next-lower driver and correctly handle pending requests, synchronization, and I/O completion whether the legacy filter driver does any work related to the request, a minifilter driver registers only for the I/O operations it must handle.

For a given I/O operation, the filter manager calls only minifilter drivers that have registered a preoperation callback routine for that operation. The filter manager also handles certain IRP maintenance tasks on behalf of the minifilter driver, such as copying parameters to the next stack location and propagating the IRP PendingReturned flag.

In its preoperation callback routine, a minifilter driver does whatever processing is needed for the I/O operation and indicates what should be done to the IRP by returning the appropriate value from its preoperation callback routine. For example, to forward an IRP to the next-lower driver without a completion routine, the minifilter driver returns FLT_PREOP_SUCCESS_NO_CALLBACK; to do the same with a completion routine (the minifilter driver's postoperation callback routine for the I/O operation), the minifilter driver returns FLT_PREOP_SUCCESS_WITH_CALLBACK.

In its preoperation callback routine, the minifilter driver can queue the operation to a worker thread if needed by calling FltQueueDeferredIoWorkItem. After doing so, the minifilter driver returns FLT_PREOP_PENDING from its preoperation callback routine to indicate that the I/O operation is pending, and the minifilter driver is responsible for completing or resuming processing of the request. To resume processing, the minifilter driver calls FltCompletePendedPreOperation from the worker thread.

If the minifilter driver needs to maintain its own per-instance cancel-safe queue of outstanding I/O operations to be processed, it can set up such a queue by calling FltCbdqInitialize in its InstanceSetupCallback routine and calling FltCbdqInsertIo in its preoperation callback routine as needed to insert I/O operations into the queue.

The filter manager calls a minifilter driver's postoperation callback routine for an I/O operation when lower filter drivers (legacy filters and minifilter drivers) have finished completion processing.

In its postoperation callback routine, the minifilter driver can call FltDoCompletionProcessingWhenSafe to ensure that completion processing is performed at safe IRQL. Or it can queue the completion processing of the operation to a worker thread if needed by calling FltQueueDeferredIoWorkItem. After doing so, the minifilter driver returns FLT_POSTOP_MORE_PROCESSING_REQUIRED from its postoperation callback routine to halt the filter manager's completion processing for the I/O operation. To resume completion processing, the minifilter driver calls FltCompletePendedPostOperation from the worker thread.

The filter manager provides support for queuing of "generic" work items - work items that are associated with a minifilter driver or minifilter driver instance rather than an I/O operation. A minifilter driver can insert a work item into a system work queue by calling FltQueueGenericWorkItem. This routine is similar to routines such as ExQueueWorkItem; for example, work items (allocated by calling FltAllocateGenericWorkItem) can be reused. However, FltQueueGenericWorkItem is safer for minifilter drivers to use, because the filter manager does not allow the minifilter driver or minifilter driver instance to unload while outstanding work items are still being processed.

The filter manager also provides support for opportunistic lock (oplock) operations. For oplock operations, a minifilter driver can use such filter manager routines as FltInitializeOplock and FltOplockFsctrl, which are equivalent to the FsRtlInitializeOplock and FsRtlOplockFsctrl routines that are used by file systems and legacy filter drivers.

Filter Manager Routines for Processing I/O Operations

The filter manager provides the following support routines for pending I/O in preoperation and postoperation callback routines:

FltCompletePendedPostOperation

FltCompletePendedPreOperation

FltDoCompletionProcessingWhenSafe

The following routines are used for queuing work items in preoperation and postoperation callback routines:

FltAllocateDeferredIoWorkItem

FltAllocateGenericWorkItem

FltFreeDeferredIoWorkItem

FltFreeGenericWorkItem

FltQueueDeferredIoWorkItem

FltQueueGenericWorkItem

The following routines provide cancel-safe queue support:

FltCbdqDisable

FltCbdqEnable

FltCbdqInitialize

FltCbdqInsertIo

FltCbdqRemoveIo

FltCbdqRemoveNextIo

The following routines provide oplock support:

FltCheckOplock

FltCurrentBatchOplock

FltInitializeOplock

FltOplockFsctrl

FltOplockIsFastIoPossible

FltUninitializeOplock

Minifilter Driver Callback Routines for Processing I/O Operations

The following callback routines are stored in the FLT_OPERATION_REGISTRATION structure for each type of I/O operation that the minifilter driver handles:

Callback Routine Name Callback Routine Type

PostOperation

PFLT_POST_OPERATION_CALLBACK

PreOperation

PFLT_PRE_OPERATION_CALLBACK