Writing Preoperation Callback Routines

A file system minifilter driver uses one or more preoperation callback routines to filter I/O operations. Preoperation callback routines are similar to the dispatch routines that are used in legacy file system filter drivers.

A minifilter driver registers a preoperation callback routine for a particular type of I/O operation by storing the callback routine's entry point in the OperationRegistration member of the FLT_REGISTRATION structure. The minifilter driver passes this member as a parameter to FltRegisterFilter in its DriverEntry routine.

Minifilter drivers receive only those types of I/O operations for which they have registered a preoperation or postoperation callback routine. A minifilter driver can register a preoperation callback routine for a given type of I/O operation without registering a postoperation callback routine, and vice versa.

The following table shows the preoperation callback routine implementation for a specific usage scenario and its return value.

Usage Scenario Implementation Value Returned
The routine is not relevant for the operation and does not require the final status of the operation or it has no postoperation callback. Pass the I/O operation through without calling the minifilter's postoperation callback on completion. FLT_PREOP_SUCCESS_NO_CALLBACK
The routine requires the final status of the operation. Pass the operation through, requiring the minifilter to call the postoperation callback routine. FLT_PREOP_SUCCESS_WITH_CALLBACK
The minifilter must complete or continue processing this operation in the future. Put the operation into a pending state. Use FltCompletePendedPreOperation to complete the operation later. FLT_PREOP_PENDING
The postoperation processing must occur in the context of the same thread that the dispatch routine was called. This ensures consistent IRQL and maintains your local variable state. Synchronize the operation with the postoperation. FLT_PREOP_SYNCHRONIZE
The preoperation callback routine needs to complete the operation. Stop processing for the operation and assign final NTSTATUS value. FLT_PREOP_COMPLETE

Every preoperation callback routine is defined as follows:

    OUT PVOID *CompletionContext 

Like a dispatch routine, a preoperation callback routine can be called at IRQL = PASSIVE_LEVEL or at IRQL = APC_LEVEL. Typically it is called at IRQL = PASSIVE_LEVEL, in the context of the thread that originated the I/O request. For fast I/O and file system filter (FsFilter) operations, the preoperation callback routine is always called at IRQL = PASSIVE_LEVEL. However, for an IRP-based operation, a minifilter driver's preoperation callback routine can be called in the context of a system worker thread if a higher filter or minifilter driver pends the operation for processing by the worker thread.

Context objects cannot be retrieved in postoperation routines at IRQL > APC_LEVEL. Instead, either get the context object during a preoperation routine and pass it to the postoperation routine or perform postoperation processing at IRQL <= APC_LEVEL. For more information about contexts, see Managing Contexts.

When the filter manager calls a minifilter driver's preoperation callback routine for a given I/O operation, the minifilter driver temporarily controls the I/O operation. The minifilter driver retains this control until it does one of the following:

  • Returns a status value other than FLT_PREOP_PENDING from the preoperation callback routine.

  • Calls FltCompletePendedPreOperation from a work routine that has processed an operation that was pended in the preoperation callback routine.

This section includes:

Passing an I/O Operation Down the Minifilter Instance Stack

Completing an I/O Operation in a Preoperation Callback Routine

Disallowing a Fast I/O Operation in a Preoperation Callback Routine

Pending an I/O Operation in a Preoperation Callback Routine