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:
typedef FLT_PREOP_CALLBACK_STATUS (*PFLT_PRE_OPERATION_CALLBACK) ( IN OUT PFLT_CALLBACK_DATA Data, IN PCFLT_RELATED_OBJECTS FltObjects, 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: