Minifilter中 Filter Initiated I/O(过滤器自产生I/O)

来源:互联网 发布:淘宝招商条件 编辑:程序博客网 时间:2024/05/22 00:54

下面的话摘自《Filter Driver Developer Guide》:

Certain minifilters need to perform I/O of theirown.  This I/O is only seen byminifilters below the current minifilter in the minifilter stack of theVolume.  For instance, an anti-virusminifilter may wish to read a file before an open has completed.  In the new minifilter model, a minifilter willbe able to generate I/O in one of two ways: using general routines similar totoday's routines, and using simplified routines that provide an interfacesimilar to the ZwXxx routines.

The general routines that the system provides tominifilters for I/O generation are:

NTSTATUS

FLTAPI

FltAllocateCallbackData (

    INPFLT_INSTANCE Instance,

    INPFILE_OBJECT FileObject OPTIONAL,

    OUTPFLT_CALLBACK_DATA *RetNewCallbackData

    );

 

VOID

FLTAPI

FltPerformSynchronousIo(

    IN PFLT_CALLBACK_DATA CallbackData

    );

 

NTSTATUS

FLTAPI

FltPerformAsynchronousIo(

    IN PFLT_CALLBACK_DATA CallbackData,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACKCallbackRoutine,

    IN PVOID CallbackContext

    );

Using the general routines, a minifilter cancall FltAllocateCallbackData() to allocate a CallbackData for the operation, and then fill in the appropriate parameters inthe CallbackData for the desired operation. The minifilter then calls FltPerformSynchronousIo() or FltPerformAsynchronousIo() to actually initiate the I/O. The instance parameter should always be for the current instance doingthe I/O operation.

In addition Filter Manager exports some commonutility routines. Examples:

NTSTATUS

FLTAPI

FltCreateFile(

    IN PFLT_FILTER Filter,

    IN PFLT_INSTANCE Instance OPTIONAL,

    OUT PHANDLE   FileHandle,

    IN ACCESS_MASK DesiredAccess,

    INPOBJECT_ATTRIBUTES ObjectAttributes,

    OUT PIO_STATUS_BLOCK IoStatusBlock,

    IN PLARGE_INTEGER AllocationSize OPTIONAL,

    IN ULONG FileAttributes,

    IN ULONG ShareAccess,

    IN ULONG CreateDisposition,

    IN ULONG CreateOptions,

    IN PVOID EaBuffer OPTIONAL,

    IN ULONG EaLength,

    IN ULONG Flags

    );

If InstanceHandle is omitted,the CREATE will be sent to the top of the stack (so the minifilter initiatingthe operation will itself see the I/O recursively.) This is discouraged unlessabsolutely necessary as it can cause deadlocks and stack overflows ifminifilters misuse it.

If InstanceHandle is provided(this should always be your own instance), then the create is initiated withthe minifilter just below the caller of this API, by passing all legacyminifilters above the Filter Manager and minifilters above the caller.

The FileHandle returned by this API can be usedin all Zw* calls that accept a file handle as a parameter. If the Instanceparameter is non-NULL in a call to FltCreateFile(), it isguaranteed that all future I/O (via the Zw APIs, FltClose() etc.), on this handle will only be seen by the instances below the InitiatingInstance.

FltReadFile() and FltWriteFile() are support routines to allow minifilters to generate IOs that areonly seen by instances below them when they have only the FileObject torepresent the file.  These routines areanalogous to “rolling an IRP” in the legacy filter model.

IMPORTANTNOTE: Filters need NOT use FltReadFile()/FltWriteFile() to initiate I/O on the handle returned by FltCreateFile().  For handles created via FltCreateFile(), the normal Zw*() APIs will be targeted to the correct instancerelative to the InitiatingInstance specified.

NTSTATUS

FLTAPI

FltReadFile (

    INPFLT_INSTANCE InitiatingInstance,

    INPFILE_OBJECT FileObject,

    INPLARGE_INTEGER ByteOffset OPTIONAL,

    IN ULONGLength,

    OUT PVOIDBuffer,

    IN FLT_IO_OPERATION_FLAGS Flags,

    OUT PULONGBytesRead OPTIONAL,

    INPFLT_COMPLETED_ASYNC_IO_CALLBACK CallbackRoutine OPTIONAL,

    IN PVOIDCallbackContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltWriteFile(

    IN PFLT_INSTANCE InitiatingInstance,

    IN PFILE_OBJECT FileObject,

    IN PLARGE_INTEGER ByteOffset OPTIONAL,

    IN ULONG Length,

    IN PVOID Buffer,

    IN FLT_IO_OPERATION_FLAGS Flags,

    OUT PULONG BytesWritten OPTIONAL,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACKCallbackRoutine OPTIONAL,

    IN PVOID CallbackContext OPTIONAL

    );

By default, all minifilter-initiated I/O is sentto the next attached instance for the given volume, bypassing any instancesattached above the minifilter initiating the I/O.

Minifilter initiated I/O can be synchronous or asynchronous.  When the I/O is asynchronous, the minifilterprovides a callback routine that the system will call when the I/O iscompleted.


楚狂人楚大侠在《Windows文件系统过滤驱动开发教程(第二版)》中对这部分内容做了翻译,如下:

某些微过滤器需要执行他们自己的I/O请求。 在卷的微过滤器栈中, 只有此过滤器以下的过滤器才能收到这些I/O请求。 比如,一个防毒软件,可能希望在打开一个文件之前先读一下这个文件。在新的微过滤模式下,一个微过滤器有两种方法生成自己的请求:使用生成例程,类似现在的其他例程。此外就是使用旧的ZwXxx例程。 
 
主要的I/O生成例程如下: 

NTSTATUS

FLTAPI

FltAllocateCallbackData (

    INPFLT_INSTANCE Instance,

    INPFILE_OBJECT FileObject OPTIONAL,

    OUTPFLT_CALLBACK_DATA *RetNewCallbackData

    );

 

VOID

FLTAPI

FltPerformSynchronousIo(

    IN PFLT_CALLBACK_DATA CallbackData

    );

 

NTSTATUS

FLTAPI

FltPerformAsynchronousIo(

    IN PFLT_CALLBACK_DATA CallbackData,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACKCallbackRoutine,

    IN PVOID CallbackContext

    );

要使用这些例程,一个微过滤器可以首先调用FltAllocateCallbackData来分配一个 CallbackData.然后对应于不同的操作填写合适的参数。之后即可调用FltPerformSynchronousIo()或者是FltPerformAsynchronousIo()来实际发起I/O请求。参数Instance必须总是微过滤器发起此请求的实例。(译者注:不能由A实例分配而B实例来发起请求)。 
 
此外过滤管理器导出了一些常用的实用例程,比如: 

NTSTATUS

FLTAPI

FltCreateFile(

    IN PFLT_FILTER Filter,

    IN PFLT_INSTANCE Instance OPTIONAL,

    OUT PHANDLE   FileHandle,

    IN ACCESS_MASK DesiredAccess,

    INPOBJECT_ATTRIBUTES ObjectAttributes,

    OUT PIO_STATUS_BLOCK IoStatusBlock,

    IN PLARGE_INTEGER AllocationSize OPTIONAL,

    IN ULONG FileAttributes,

    IN ULONG ShareAccess,

    IN ULONG CreateDisposition,

    IN ULONG CreateOptions,

    IN PVOID EaBuffer OPTIONAL,

    IN ULONG EaLength,

    IN ULONG Flags

    );

 
如果Instance参数被忽略(译者注:指定为空.),那么CREATE请求会被发送到微过滤器栈的顶端(这导致本微过滤器会回环的看到自己发送的请求。)除非绝对必要,这是不明智的。如果被滥用,很容易导致死锁和栈溢出. 
 
如果指定了这个参数(应该总是你自己当前的instance),那么仅仅向下发起此请求。所有的前面的调用此api的微过滤器之上的微过滤器(包括自己)都不会收到此请求. 
 
FileHandle参数返回一个供Zw*系列函数调用的文件句柄.如果先前指定的Instance不为空,那么保证关于这个文件句柄的其他未来的I/O操作(通过Zw接口,FltClose(),等),都只能被这个发起Instance下面的Instance看到。 
 
FltReadFile()和FltWriteFile()发起的I/O读写请求也只有下层实例才能看见。 用于我们只有FileObject而没有文件句柄的时候。这些例程类似以前旧的过滤模型中自己发送IRP的读写方式. 
 
重要提示:过滤器不需要使用FltReadFile()/FltwriteFile()来对一个FltCreateFile返回的文件句柄发起一个I/O请求.对于这种情况,使用Zw*()接口就可以发送到合适的实例上去。 
 

NTSTATUS

FLTAPI

FltReadFile (

    INPFLT_INSTANCE InitiatingInstance,

    INPFILE_OBJECT FileObject,

    INPLARGE_INTEGER ByteOffset OPTIONAL,

    IN ULONGLength,

    OUT PVOIDBuffer,

    IN FLT_IO_OPERATION_FLAGS Flags,

    OUT PULONGBytesRead OPTIONAL,

    INPFLT_COMPLETED_ASYNC_IO_CALLBACK CallbackRoutine OPTIONAL,

    IN PVOIDCallbackContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltWriteFile(

    IN PFLT_INSTANCE InitiatingInstance,

    IN PFILE_OBJECT FileObject,

    IN PLARGE_INTEGER ByteOffset OPTIONAL,

    IN ULONG Length,

    IN PVOID Buffer,

    IN FLT_IO_OPERATION_FLAGS Flags,

    OUT PULONG BytesWritten OPTIONAL,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACKCallbackRoutine OPTIONAL,

    IN PVOID CallbackContext OPTIONAL

    );

微过滤器发出I/O可能为同步也可能为异步.当I/O被指定为异步,微过滤器提供一个回调例程.当系统完成了I/O请求回调例程会被调用.