DOC

Filter Driver Development Guide

By Derek Chavez,2014-04-11 22:06
12 views 0
Filter Driver Development Guide

    FILE SYSTEM FILTER MANAGER

    Filter Driver

    Development Guide

Version 1.0a

    Summary

    This specification includes, but is not limited to, the following topic areas:

    ; Description of the new 'File System Filter Manager' architecture and interfaces ; Aspects of the Windows 'Memory Manager', 'I/O Manager', and 'Cache Manager' interfaces that affect the

    development of file system filters using the new File System Filter Manager architecture. Disclaimer

    The information contained in this document represents the current view of Microsoft Corporation on the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication. This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation. Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property. Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, email address, logo, person, place or event is intended or should be inferred. ? 2004 Microsoft Corporation. All rights reserved. Microsoft, Windows, and Windows NT are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners.

    Page 1 of 28

Table Of Contents

    1. Overview ................................................................................................................................... 3 2. Terms ........................................................................................................................................ 3 3. Minifilter Installation ................................................................................................................ 4 4. Minifilter Registration ............................................................................................................... 4 5. Initiating filtering ..................................................................................................................... 4 6. Instance Notification Support ................................................................................................... 5

    6.1. Setting up an Instance ..................................................................................................... 5

    6.2. Controlling Instance Teardown .......................................................................................... 6

    6.3. Synchronizing Instance Detach .......................................................................................... 6 7. Callback Support ....................................................................................................................... 7

    7.1. Callback data .................................................................................................................. 7

    7.2. Pre-Operation Callbacks ................................................................................................... 8

    7.3. Post-Operation Callbacks .................................................................................................. 9 8. Manipulating Callback Data Parameters .................................................................................. 11

    8.1. I/O Parameter Block ....................................................................................................... 11

    8.2. Accessing buffer/MDL ...................................................................................................... 12

    8.3. Swapping buffers ............................................................................................................ 12 9. Context Support ...................................................................................................................... 13

    9.1. Context Registration ....................................................................................................... 14

    9.2. Context Creation APIs ..................................................................................................... 14

    9.3. Context Retrieval APIs ..................................................................................................... 17

    9.4. Context Freeing APIs ....................................................................................................... 18 10. User Mode Communication ...................................................................................................... 19

    10.1. Filter Communication Port Object...................................................................................... 19

    10.2. Connecting to Communication Port from User Mode ............................................................ 20

    10.3. Disconnecting from the Communication Port ...................................................................... 21

    10.4. Unload issues ................................................................................................................. 21 11. File Name Support ................................................................................................................... 21

    11.1. Retrieving a File Name during an Operation ....................................................................... 21

    11.2. Additional Support for File Names ..................................................................................... 23

    11.3. Interfaces for Name Providing Filters ................................................................................. 23 12. Filter Initiated I/O .................................................................................................................. 25 13. Rules for Unload/Unregister/Detach ...................................................................................... 27 14. Support Routines .................................................................................................................... 27 15. Building a Minifilter ................................................................................................................. 28

    Page 2 of 28

1. Overview

    This document pertains to filter drivers between the I/O manager and the base filesystem, which can be local or remote. It does not pertain to filter drivers that sit between the filesystem and the storage driver(s), such as FtDisk or DMIO.

    We will refer to a file system filter driver written using the new model as a mini file system filter driver/minifilter.

    The existing file system filters based on the sfilter sample using IRP and device-object based filtering will be

    referred to as 'legacy filters'.

    One of the key components of the new architecture is a legacy file system filter which is called 'Filter Manager'. In future Windows operating system releases, this driver will be installed by default on the system. This driver manages the minifilters by providing export libraries to which the minifilters link. The necessary header files, libraries and binaries are available in the Minifilter IFSKit.

    Why write a mini file system filter driver?

    ; Simpler, get a more reliable filter driver with less development effort.

    ; Dynamic load and unload, attach and detach.

    ; Attach at a well-defined location in the filter stack.

    ; Context management: fast, clean, reliable contexts for file objects, streams, files, instances, and volumes ; A host of utility routines including support for looking up names and caching them for efficient access,

    communication between minifilters and user mode services, and IO queuing.

    ; Support non-recursive I/O so minifilter generated I/O can easily be seen only by lower minifilters and the

    file system.

    ; Filter only operations of interest to minifilter unlike the legacy model where a filter has to hook every

    entry point to pass through operation.

    2. Terms

    In the Filter Manager architecture, some new objects are defined. For clarity these objects will be defined up front.

    Filter: A driver that performs some type of filtering operation on the file system.

    Volume: For local file systems, the object that represents logical volume the file system manages. For network redirectors, this represents the object to which all network requests are directed. The volume maps directly to the file system (local or remote) DEVICE_OBJECT in the legacy filter model. Instance: An instantiation of a filter on a volume at a unique altitude. The Filter Manager manages presenting IOs to each instance in the stack of instances attached to a volume. There may be more than one instance of a given minifilter for a given volume. The canonical example is a filter like FileSpy. It would be helpful to attach FileSpy both above and below another filter on the same volume with each instance maintaining a private context. This context could contain the log of IOs seen by the instance for later comparison of the IO as seen above and below the filter.

    File: A named object of data that could be composed of multiple streams that is stored on a disk by the file system.

    Stream: Represents a physical stream of data in a file.

    FileObject: Represents a user‘s open of a physical stream of data in a file.

    CallbackData: The Filter Manager structure that encapsulates all the information about an operation. This is equivalent to an IRP in the legacy filter model.

    Page 3 of 28

3. Minifilter Installation

    Minifilters will be installed via an INF file. The INF file indicates what instances the minifilter supports. Instances are defined in Section 5. Each instance is also accompanied by an altitude value which indicates its absolute position in a minifilter stack and a set of flags.

    The list of instances with their altitudes in the INF is the preferred means for file system filter vendors to ship their minifilters. The flags indicate if the minifilter needs 'automatic attachment'. If this is the case, for every volume in the system (and for new ones as they arrive), the minifilter gets a notification that it can respond to and attach. The altitude in the INF file determines the altitude to which the minifilter attaches if it chooses to do so.

    A file system filter vendor may also create an instance dynamically at a specified altitude at any time when the minifilter is running via the FilterAttachAtAltitude() function. This is provided as an override and

    a potential debugging and testing aid.

    4. Minifilter Registration

    Mini file system filter drivers are kernel-mode drivers. As such, they must export a function called DriverEntry(), which will be the first function invoked when the driver is loaded. Most minifilters will call FltRegisterFilter() in their DriverEntry().

    FltRegisterFilter() takes as a parameter a FLT_REGISTRATION structure, which contains an unload

    routine, instance notification callbacks, a list of context callback function pointers and a list of file system operation callback pointers. In the most common case, where the minifilter hooks just a few operations, this list can be very short.

    The minifilter also can specify additional flags for each operation that controls whether it receives the callbacks in all cases. For instance, if FLTFL_OPERATION_REGISTRATION_SKIP_PAGING_IO is supplied,

    the minifilter will not receive any paging I/O operations for that particular IRP major code. Similarly, if FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO is specified, only the non-cached I/O

    path will be seen for that operation (i.e., if it is supplied for IRP_MJ_READ, all cached read paths will be

    skipped by that minifilter).

    5. Initiating filtering

    Once a minifilter registers itself, it should initiate filtering at some point by calling the function FltStartFiltering(). It is not necessary to call it from DriverEntry(), though most filters will

    probably prefer to.

    This function will kick-off the necessary notifications that will result in the minifilter attaching to the appropriate volumes and start filtering I/O.

    For this the Filter Manager walks through the list of instances that are registered by the minifilter via its INF.

    Each instance specifies an "altitude". An altitude is an infinite precision string (e.g., "100.123456") that defines where it will be attached in a stack of minifilter instances. Altitudes for commercially released minifilter drivers will be assigned by Microsoft.

    The larger the altitude in numeric value, the higher the instance is attached in the minifilter stack for a volume. Several sample altitudes are provided for developers to use while implementing minifilters and these are the only altitudes an unsigned driver may use. There are two purposes for altitudes. The first is to enforce relative minifilter ordering when it is necessary for proper functioning regardless of when the individual drivers load. For instance, an encryption filter and an antivirus filter must attach with the antivirus filter on top, otherwise the antivirus filter could not scan the clear text for viruses. The second purpose is to provide a smaller test matrix for minifilter interoperability testing. Each minifilter instance will have a well-specified altitude, therefore, when testing the interoperability between one or more minifilters, there is exactly one well-defined configuration to test.

    An INF instance specification also has associated flags. If bit 1 is set, the minifilter will not be automatically notified when volumes appear in the system so that it can attach its instance. An instance with this flag set

    Page 4 of 28

    in its specification would be manually attached via a Filter Manager API. If bit 2 is set, the minifilter will not be asked to attach this instance to a volume when a manual attachment request is made. 6. Instance Notification Support

    A set of callbacks are provided to notify a minifilter when an instance is being created or torn down. Through these callbacks, the minifilter can control when instances are attached and detached from volumes. 6.1. Setting up an Instance

    The InstanceSetupCallback() routine gets called for the following reasons:

    ; When a minifilter is loaded it is called for each volume that currently exists in the system. ; When a new volume is mounted.

    ; When FltAttachVolume() is called (kernel mode).

    ; When FltAttachVolumeAtAltitude() is called (kernel mode).

    ; When FilterAttach() is called (user mode).

    ; When FilterAttachAtAltitude() is called (user mode).

    It is during the processing of the InstanceSetupCallback() that the minifilter decides whether or not the instance should be created on the volume specified. This callback has the following signature: typedef NTSTATUS

    (*PFLT_INSTANCE_SETUP_CALLBACK) (

     IN PCFLT_RELATED_OBJECTS FltObjects,

     IN FLT_INSTANCE_SETUP_FLAGS Flags,

     IN DEVICE_TYPE VolumeDeviceType,

     IN FLT_FILESYSTEM_TYPE VolumeFilesystemType

     );

    The FltObjects structure contains pointers to the minifilter, volume and instance that define the instance being created by this InstanceSetupCallback(). The Flags explain what operation triggered this

    InstanceSetupCallback():

    ; FLTFL_INSTANCE_SETUP_AUTOMATIC_ATTACHMENT: This is an automatic attachment that is

    occurring because the minifilter has just registered; therefore the Filter Manager is enumerating all

    existing volumes in the systems for the newly loaded minifilter. This flag is not set when a user

    explicitly request an instance to attach to a volume.

    ; FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT: A manual attachment request has been issued

    via the FilterAttach() (user-mode), FilterAttachVolumeAtAltitude() (user-mode),

    FltAttachVolume() (kernel-mode), or FltAttachVolumeAtAltitude() (kernel-mode) call.

    ; FLTFL_INSTANCE_SETUP_NEWLY_MOUNTED_VOLUME: The file system has just mounted this

    volume, therefore it is calling the InstanceSetupCallback() for the minifilter to create an

    instance on the volume if desired.

    During the InstanceSetupCallback(), the minifilter also receives the VolumeDeviceType and the VolumeFilesystemType to help the minifilter decide whether or not it is interested in attaching to this volume. From the InstanceSetupCallback(), a minifilter can query the volume properties by calling FltGetVolumeProperties() and set a context using FltSetInstanceContext() on this instance if it

    plans to attach this instance to the volume. It can also open and close files on the volume. If the minifilter returns a success code from the instance setup callback, the instance will be attached to the given volume. If the minifilter returns a warning or an error code, the instance will not be attached to the

    volume.

    If a minifilter does not register an InstanceSetup() routine, the system will treat this as if the user

    returned STATUS_SUCCESS and allow the instance to be created on the volume.

    Page 5 of 28

6.2. Controlling Instance Teardown

    The InstanceQueryTeardown() callback is called only when a manual detach request is made. The following operations cause manual detach requests:

    ; FltDetachVolume() (kernel-mode)

    ; FilterDetach() (user-model)

    If a minifilter does not provide this callback than manual detach is not supported. However, volume dismounts and minifilter unloads will still be allowed.

    If this callback is defined and a success code is returned, Filter Manager will start tearing down the given

    instance. Eventually the instance's InstanceTeardownStart() and InstanceTeardownComplete()

    routines will be called. If the minifilter returns a warning/error status, the manual detach will fail. The

    recommended error code is STATUS_FLT_DO_NOT_DETACH but any failure status may be returned.

    The signature for the InstanceQueryTeardown() callback is as follows:

    typedef NTSTATUS

    (*PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK) (

     IN PCFLT_RELATED_OBJECTS FltObjects,

     IN FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags

     );

    As in the InstanceSetupCallback(), the FltObjects specify the minifilter, volume and instance to which this InstanceQueryTeardown() operation is related.

    6.3. Synchronizing Instance Detach

    Once the decision to detach has been made the InstanceTeardownStart() callback is called. This routine must do the following things:

    ; Restart any pended I/O operations (both pre & post operations)

    ; Guarantee no new I/O operations will be pended

    ; Start doing minimal work on new operations as they arrive.

    This routine may also do the following work:

    ; Close opened files

    ; Cancel filter initiated I/O‘s

    ; Stop queuing new work items

    The minifilter then returns control back to the Filter Manager to continue its teardown processing. After all operations in which this instance participated have drained or completed, the InstanceTeardownComplete() callback is called to allow the minifilter to do the final cleanup for the teardown of this instance. When InstanceTeardownComplete() is called, the Filter Manager guarantees that all existing operation callbacks have been completed for this instance. At this time, the minifilter must

    close any files it still has open that are associated with this instance. The InstanceTeardownStart() and InstanceTeardownComplete() callbacks have the same signature: typedef VOID

    (*PFLT_INSTANCE_TEARDOWN_CALLBACK) (

     IN PCFLT_RELATED_OBJECTS FltObjects,

     IN FLT_INSTANCE_TEARDOWN_FLAGS Reason

     );

    The FltObjects parameter describes the minifilter, volume and instance of interest for the callback. The Reason parameter describes the reason for this teardown callback and may be a combination of the following

    flag values:

    ; FLTFL_INSTANCE_TEARDOWN_MANUAL: This teardown operation is the result of a manual request

    to detach this instance (FilterDetach() or FltDetachVolume()).

    Page 6 of 28

    ; FLTFL_INSTANCE_TEARDOWN_FILTER_UNLOAD: This teardown operation is the result of the

    minifilter being unloaded and the minifilter could have chosen to fail the unload request.

    ; FLTFL_INSTANCE_TEARDOWN_MANDATORY_FILTER_UNLOAD: This teardown operation is the

    result of the minifilter being unloaded and the minifilter could not have chosen to fail the unload

    request.

    ; FLTFL_INSTANCE_TEARDOWN_VOLUME_DISMOUNT: This teardown request is the result of the

    volume being dismounted.

    ; FLTFL_INSTANCE_TEARDOWN_INTERNAL_ERROR: This teardown request is the result of some

    error that occurred while trying to setup the instance, like insufficient memory. Notice that there is no return value the InstanceTeardownStart() and

    InstanceTeardownComplete() cannot be failed. The Filter Manager guarantees that these callbacks will be called at passive IRQL.

    7. Callback Support

    7.1. Callback data

    The callback data structure is the new I/O packet descriptor for the Filter Manager, and it is analogous to the IRP in the legacy model. Minifilters talk to Filter Manager and each other via this structure. Unlike an IRP however, minifilters do not manage stack locations but instead indicate how the callback data should be managed via well-defined Filter Manager interfaces and return status values to the Filter Manager. The FLT_CALLBACK_DATA type describes all the information provided to a minifilter to describe an I/O. The following description goes through each field in this structure to describe the information it contains. Flags: Provides information about this operation. One or more of the following flags could be set in a

    callback data structure:

    ; FLTFL_CALLBACK_DATA_IRP_OPERATION: This callback data structure represents an IRP

    operation.

    ; FLTFL_CALLBACK_DATA_FAST_IO_OPERATION: This callback data structure represents a FAST IO

    operation.

    ; FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION: This callback data structure represents an

    FsFilter operation.

    ; FLTFL_CALLBACK_DATA_SYSTEM_BUFFER: The buffer for the operation described by this callback

    data is a system allocated buffer.

    ; FLTFL_CALLBACK_DATA_GENERATED_IO: This callback data represents an operation that was

    generated by another minifilter.

    ; FLTFL_CALLBACK_DATA_REISSUED_IO: This callback data represents an operation that has been

    sent back down to the file system by a minifilter instance above the current instance in the stack.

    ; FLTFL_CALLBACK_DATA_DRAINING_IO: Only set for a post-operation callback, this callback data

    represents an IO operation that is being drained so that the minifilter can unload.

    ; FLTFL_CALLBACK_DATA_POST_OPERATION: Only set for a post-operation callback, this callback

    data is currently in the post-operation processing for this I/O.

    ; FLTFL_CALLABACK_DATA_DIRTY: This is set after a minifilter has changed one or more of the

    changeable parameters for this operation. This flag is only set during pre-operation processing.

    Minifilters should use FLT_SET_CALLBACK_DATA_DIRTY() and

    FLT_CLEAR_CALLBACK_DATA_DIRTY() to manipulate this flag.

    Thread: The address of the thread which initiated this operation.

    Iopb: Pointer to the changeable parameters for this operation. This structure is described in more detail

    later in this document.

    Page 7 of 28

    IoStatus: The IO_STATUS_BLOCK which will receive the final status for this operation. If a minifilter wants

    to complete an operation, the status should be set in this field before completing the operation. For

    operations that are passed through to the file system, this field contains the final status of the operation

    during post-operation processing.

    TagData: This field is only valid in post-callback processing for CREATE operations when the target file of

    the operation has a reparse point set on it.

    QueueLinks: The list entry structure used to add this callback data structure to a work queue if needed. QueueContext[2]: An array of PVOID structures to allow additional context to be passed to the work queue

    processing routine.

    FilterContext[4]: An array of PVOID structures that can be used as desired by a minifilter if this callback

    data has been queued in a manner that does not rely on the queuing infrastructure provided by the Filter

    Manager.

    RequestorMode: The requestor mode of the caller who initiated this IO operation.

    The FLT_IO_PARAMETER_BLOCK is the structure pointed to by the Iopb field of the callback data structure

    and contains the changeable portion of the callback data structure. To extend the IRP analogy, this is like the ―current stack location‖ of the IRP. Minifilters should access this structure to retrieve I/O parameters in both pre- and post-callbacks. The following is a more detailed description of the fields this structure contains. IrpFlags: The flags from the IRP which describe this operation. These flags begin with the IRP_ prefix. MajorFunction: The IRP_MJ function which describes this operation.

    MinorFunction: The IRP_MN function which describes this operation.

    OperationFlags: The flag values in the IO_STACK_LOCATION.Flags field in the legacy filter model. These

    flags being with the SL_ prefix.

    TargetFileObject: The file object which represents the file stream which this operation affects. TargetInstance: The instance to which this IO is directed.

    Parameters: The FLT_PARAMETERS union describes parameters specific to the operation specified in the

    MajorFunction and MinorFunction fields.

    Minifilters may change any of the parameters in the FLT_IO_PARAMETER_BLOCK except the

    MajorFunction in the pre-callbacks. If parameters have been changed, the minifilter should call FLT_SET_CALLBACK_DIRTY() to indicate this change. More information regarding changing the

    parameters of an operation are in Section 8.

    Minifilters will see the same parameters in both their pre- and post-callback routines for the same I/O even

    though they or other minifilters below may have changed the parameters. This is guaranteed by the Filter Manager. Although the contents of the FLT_IO_PARAMETER_BLOCK will be the same in the pre- and post-

    callback routines for the same I/O, the address to the FLT_IO_PARAMETER_BLOCK may not be the same,

    therefore minifilters should not rely on this.

    The callback data structure also contains the IO_STATUS_BLOCK that describes the status of the operation. A minifilter can change this value and it will be honored by the Filter Manager without marking the callback data dirty. The minifilter should set the status for the operation if it is completing the operation in its pre-operation callback or undoing the operation in the post-operation callback.

    7.2. Pre-Operation Callbacks

    All pre-operation callbacks have the same signature:

    typedef FLT_PREOP_CALLBACK_STATUS

    (*PFLT_PRE_OPERATION_CALLBACK) (

     IN OUT PFLT_CALLBACK_DATA Data,

     IN PCFLT_RELATED_OBJECTS FltObjects,

     OUT PVOID *CompletionContext

     );

    Page 8 of 28

All pre-operation callbacks return an FLT_PRE_OPERATION_CALLBACK_STATUS. The values are defined as

    follows:

    ; FLT_PREOP_SUCCESS_WITH_CALLBACK: The operation succeeded and the minifilter wants to have its

    post-operation callback called.

    ; FLT_PREOP_SUCCESS_NO_CALLBACK: The operation succeeded, but the minifilter does not want to

    have its post-operation callback called.

    ; FLT_PREOP_PENDING: The minifilter driver will complete the operation (by calling

    FltCompletePendedPreOperation()) sometime in the future. There is no need for the minifilter to

    call any special preparation routine before returning this status, like IoMarkIrpPending() in the

    legacy filter model. If this status is returned, all further processing on the I/O is suspended by the Filter

    Manager (i.e. no pre-callbacks of lower drivers are called etc.) until

    FltCompletePendedPreOperation() is called.

    ; FLT_PREOP_COMPLETE: The minifilter completed the operation. The minifilter sets the I/O status of the

    operation in Data->IoStatus.Status. Minifilters attached below this minifilter, legacy filters, and the

    base file system will not see this I/O. Minifilters attached above this minifilter will see the operation

    complete with the appropriate status. For CLEANUP and CLOSE operations, it is incorrect for a minifilter

    to complete these operations with a failure status since these operations cannot fail. ; FLT_PREOP_SYNCHRONIZE: This status is valid only for non-create operations (creates are automatically

    synchronized). A minifilter MUST have a post-callback for the operation when this status is returned.

    This indicates that the minifilter wants this I/O to be completed in the same thread context as the pre-

    operation process. The post-callback will be called after the I/O is completed in this thread context.

    Filter Manager guarantees this regardless of whether a lower filter/file system may pend the I/O or

    abort completion processing etc. This status should be used with care because it requires Filter Manager

    tosynchronizes the entire I/O and this has negative performance impacts on the systems overall

    throughput.

    ; FLT_PREOP_DISALLOW_FAST_IO: This status is valid only for fast I/O operations that return BOOLEAN

    in the legacy model. This status indicates to I/O to retry the operation using the IRP path instead. Filters may change the parameters for the I/O before returning from the pre-operation callback. However the only parameters that may be changed are in the Data->Iopb structure (FLT_IO_PARAMETER_BLOCK).

    When a minifilter changes any of the parameters in this structure, it needs to issue FLT_SET_CALLBACK_DATA_DIRTY() on the passed in CallbackData, or the changes will not be honored,

    and unpredictable failures may occur.

    There are a couple exceptions to this. If a minifilter is completing the operation or changing the operations status, it may set the IoStatus appropriately in the callback data structure and it is not necessary to mark the callback data dirty for this change to be honored by the Filter Manager.

    Another exception is during the post-operation processing of IRP_MJ_CREATE operations. When a reparse point is encountered, the Data->TagData will point to the reparse data buffer. If a minifilter wishes to change this buffer in any way, it can free the existing buffer and replace Data->TagData with a new buffer

    (or NULL) without calling FLT_SET_CALLBACK_DATA_DIRTY().

    7.3. Post-Operation Callbacks

    All post-operation callbacks have the same signature:

    typedef FLT_POSTOP_CALLBACK_STATUS

    (*PFLT_POST_OPERATION_CALLBACK) (

     IN OUT PFLT_CALLBACK_DATA Data,

     IN PCFLT_RELATED_OBJECTS FltObjects,

     IN PVOID CompletionContext,

     IN FLT_POST_OPERATION_FLAGS Flags

     );

    The flag FLTFL_CALLBACK_DATA_POST_OPERATION is set in the Data->Flags field for post-operation

    callbacks.

    Page 9 of 28

If a minifilter returns FLT_PREOP_SUCCESS_WITH_CALLBACK from its pre-operation callback, it is

    guaranteed to receive exactly one completion callback per pre-operation callback. Post operations can return a status of type FLT_POSTOP_CALLBACK_STATUS. The values are:

    ; FLT_POSTOP_FINISHED_PROCESSING The minifilter has completed its processing of the request and

    control should be returned to whoever initiated the I/O.

    ; FLT_POSTOP_STATUS_MORE_PROCESSING_REQUIRED The minifilter has not completed its

    processing of the request, and will later complete the request using

    FltCompletePendedPostOperation().

    Like completion routines in the legacy filter model, post-operation callback routines can be called at DPC. If a minifilter needs to do work once the operation is completed but this work cannot be performed at DPC, the minifilter can call FltDoCompletionProcessingWhenSafe(). This routine will queue this work to a

    worker thread only if it is necessary (i.e., we are at DPC_LEVEL) and it is safe to do so. This call can fail if the completion processing must be queued to a worker thread, but this is an I/O that cannot be queued (e.g., paging I/Os).

    For filters who want to cancel an opened file in the post-operation callback, FltCancelFileOpen() is

    provided which does a cleanup and close on the specified FileObject on behalf of the minifilter. The minifilter should fill in an appropriate error status code and return FLT_POSTOP_FINISHED_PROCESSING from its

    post-operation callback.

    When an instance is being torn down, the Filter Manager may call the post-operation callback before it is actually completed by the lower filters or file system. In this case, the flag

    FLTFL_POST_OPERATION_DRAINING will be set when the post-operation is called. Minimal information about the operation will be provided, so at this time, the minifilter should cleanup any operation context passed in from its pre-operation and return FLT_POSTOP_FINISHED_PROCESSING.

    The operations defined are based on the IRP_MJ codes with the addition of some new codes to represent Fast I/O operations that have no IRP equivalents. The goal is to present IRP-based and Fast I/O operations in a consistent manner to the minifilter. There will be a flag in the callback data so that it can determine the difference between an Irp-based, FsFilter based, or Fast I/O based operation, but it will not have to register separate callbacks for operations that are similar (i.e., Reads, Writes, and Locking operations). The operations for which pre- and post-operation callbacks can be provided are:

    ; All the existing IRP_MJ codes from IRP_MJ_CREATE to IRP_MJ_PNP

    ; IRP_MJ_FAST_IO_CHECK_IF_POSSIBLE

    ; IRP_MJ_NETWORK_QUERY_OPEN

    ; IRP_MJ_MDL_READ

    ; IRP_MJ_MDL_READ_COMPLETE

    ; IRP_MJ_PREPARE_MDL_WRITE

    ; IRP_MJ_MDL_WRITE_COMPLETE

    ; IRP_MJ_VOLUME_MOUNT

    ; IRP_MJ_VOLUME_DISMOUNT

    ; IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION

    ; IRP_MJ_RELEASE_FOR_SECTION_SYNCHRONIZATION

    ; IRP_MJ_ACQUIRE_FOR_MOD_WRITE

    ; IRP_MJ_RELEASE_FOR_MOD_WRITE

    ; IRP_MJ_ACQUIRE_FOR_CC_FLUSH

    ; IRP_MJ_RELEASE_FOR_CC_FLUSH

    A few special notes for some of the IRP_MJ codes:

    Page 10 of 28

Report this document

For any questions or suggestions please email
cust-service@docsford.com