Minifilter - File Name Support

The Filter Manager provides library routinesthat retrieve the name of the object in the current operation through lookingat the operation parameters or querying the file system.  For improved efficiency, the Filter Manageralso caches the names as they are retrieved so that the cost of generating afile name can be amortized among all minifilters interested in that name.

过滤管理器提供类库函数通过当前操作的参数或者查询文件系统获取对象的名称。为了提供效率,文件过滤管理器还会缓存这些名称,所有的minifilter驱动都可以较快的获取缓存的名称。

The Filter Manager name APIs return names in FLT_FILE_NAME_INFORMATION structures so as to avoid data copies when a minifilter requests aname.  These structures are referencecounted and possibly shared by multiple minifilters requesting names.  Only the Filter Manager APIs should everchange the data in these structures.  Thereis more information about these structures in the following sections.

过滤管理器将返回的名称保存在一个FLT_FILE_NAME_INFORMATION结构体中以避免数据拷贝,这些数据结构是引用计数的,可能被其他的minifilter驱动共享。只有过滤管理器Api可以更改这些数据结构的数据。接下来会有更多的关于此数据结构的介绍。


To retrieve a file name for the CallbackData->Iopb->TargetFileObject for the current operation, the minifilter should call the followingroutine:

获取CallbackData->Iopb->TargetFileObject对象的文件名,minifilter驱动应该调用以下函数:

NTSTATUS

FLTAPI

FltGetFileNameInformation(

    IN PFLT_CALLBACK_DATA CallbackData,

    IN FLT_FILE_NAME_FORMAT NameFormat,

    IN FLT_FILE_NAME_QUERY_METHOD QueryMethod,

    OUT PFLT_FILE_NAME_INFORMATION*FileNameInformation

    );

The CallbackData is the FLT_CALLBACK_DATA structure for the operation on the FileObject for which theminifilter wants to query the name.

CallbackData是minifilter要查询当前文件对象文件名称的结构体FLT_CALLBACK_DATA对象

The NameFormat is one of thefollowing three formats:

·         FLT_FILE_NAME_NORMALIZED_FORMAT:  A name requested in thisformat contains the full path for the name, including the volume name.  All short names in the path have beenexpanded to their long name.  Any streamname component will have any trailing “:$DATA” removed.  If this is the name for a directory otherthan the root directory, the final ‘\’ in the path will be removed.

·         FLT_FILE_NAME_OPENED_FORMAT:  A name requested in thisformat contains a full path for the name, including the volume name, but thename is in the same format that the caller used to open this object.  Therefore, it could include short names forany of the components in the path.

·         FLT_FILE_NAME_SHORT_FORMAT:  A name requested in thisformat contains the short name (DOS name) for only the final component of thename.  The full path for this object isnot returned.

NameFormat可以是以下的值:

·         FLT_FILE_NAME_NORMALIZED_FORMAT:  查询此格式的名称包含完全的路径,包括卷名称。所有的短名被扩展成长名。Any stream name component willhave any trailing “:$DATA” removed.如果是一个目录名称并且不是根目录,最后的反斜杠将被删除。

·         FLT_FILE_NAME_OPENED_FORMAT:  查询此格式的名称包含完全的路径,包括卷名称。但是其格式与用户打开对象所使用的格式相同,所以,对路径中任何的组件来说它可能包含短名。

·         FLT_FILE_NAME_SHORT_FORMAT:  查询此格式的名称包含最后组件的短名(DOS名),完整的路径不被返回。

 

The QueryMethod is one of thefollowing:

·         FLT_FILE_NAME_QUERY_DEFAULT:  When looking for a name,the Filter Manager will look in the cache first to find the name, then, ifpossible, query the file system to retrieve the name requested.

·         FLT_FILE_NAME_QUERY_CACHE_ONLY:  When looking to fulfill aname request, the Filter Manager will only look in the name cache to find thename.  If the name is not found, STATUS_FLT_NAME_CACHE_MISS will be returned.

·         FLT_FILE_NAME_QUERY_FILE_SYSTEM_ONLY:  When looking to fulfill aname request, the Filter Manager will not look in the name cache and query the filesystem for the name if possible.

QueryMethod可以是以下值:

·         FLT_FILE_NAME_QUERY_DEFAULT:  查询名称时,过滤管理器先查询缓存再查询文件系统。

·         FLT_FILE_NAME_QUERY_CACHE_ONLY:  查询名称时,过滤管理器只查询缓存,若没有找到,返回STATUS_FLT_NAME_CACHE_MISS。

·         FLT_FILE_NAME_QUERY_FILE_SYSTEM_ONLY: 查询名称时,只查询文件系统。

 

The name is returned in the final parameter, FileNameInformation.  This structure is a set ofUnicode strings that share the same buffer. The various Unicode strings denote varying sections of the name.

对象名称被返回在最后的参数FileNameInformation中。这个结构体是一组Unicode字符串集合,并且共享一片缓冲区,不同的字符串代表名称的不同部分。

typedefstruct _FLT_FILE_NAME_INFORMATION {

    USHORT Size;

    FLT_FILE_NAME_FORMAT Format;

    FLT_FILE_NAME_PARSED_FLAGS NamesParsed;

    UNICODE_STRING Name;

    UNICODE_STRING Volume;

    UNICODE_STRING Share;

    UNICODE_STRING Extension;

    UNICODE_STRING Stream;

    UNICODE_STRING FinalComponent;

    UNICODE_STRING ParentDir;

} FLT_FILE_NAME_INFORMATION,*PFLT_FILE_NAME_INFORMATION;

When a file name information structure isreturned from FltGetFileNameInformation(), the Name, Volume, and Share (for remote file names) will beparsed.  If a minifilter needs the othernames parsed, it should call FltParseFileNameInformation().

文件名称信息在函数FltGetFileNameInformation返回后,Name、Volume及Share(远程文件名)将被解析,如果minifilter驱动要解析其它的文件名,调用FltParseFileNameInformation。

A minifilter can call FltGetFileNameInformation() at any point during its IO processing when it is executing an IRQLless than DPC.  If the minifilter isrequesting to query the name at a time when it is possible for the name queryto cause the system to deadlock (e.g., while processing paging IO), the callwill fail if the name is not found in the cache or the caller requested to onlyquery the file system.

当IRQL低于DPC时,minifilter驱动可以在IO处理的任何时间调用FltGetFileNameInformation。当minifilter查询文件名时可能引起系统死锁时(例如处于pagingIO),如果名字没有在缓存中找到或者调用者要求只查询文件系统时,调用将会失败。

A minifilter can use FltGetFileNameInformationUnsafe() to query a name for a file object if it does not have a callbackdata to describe the current operation targeting this file object and thefilter knows that this is a safe time to potentially query the file system toget a name.  This routine cannot detectthat a file system query could potentially deadlock the system and return afailure status as FltGetFileNameInformation() can.

?????????????????????????????????????

When a minifilter is finished using the name, itshould be released by calling:

当minifilter驱动使用完名称后,它应当调用FltReleaseFileNameInformation释放名称。

FLTAPI

FltReleaseFileNameInformation(

    IN PFLT_FILE_NAME_INFORMATIONFileNameInformation

    );

FilterManager’s name cache is designed to be efficient enough for minifilters toquery the name during the operations it needs to process.  The name cache manages the invalidation ofnames due to file or directory renames. Minifilters are isolated from the complex logic necessary to maintain aname cache, but minifilters still need to be aware that names can beinvalidated by renames in the system. When a rename occurs, the Filter Manager purges any affected cachedentries, but minifilters may have outstanding references to the now stale filename information structure.  When all thereferences are released the stale file name information structure will befreed.  If a minifilter queries a name onan object that has been renamed, the new name will be returned if possible.

过滤管理器的名字缓存被设计用来供minifilter驱动高效的查询名称,名字缓存管理者由于文件或文件夹重命名导致的名字失效。Minifilter驱动与名字缓存的复杂逻辑隔离,但是minifilter驱动需要知道由于重命名导致的名字失效。重命名发生后,过滤管理器清除所有被影响的缓存项,但是minifilter驱动可能依然有过时的文件名称引用。当所有的过时名称引用释放后,过时名称的结构将被释放。如果一个minifilter驱动查询一个已经重命名的文件对象,新的名字将被返回。

The Filter Manager also provides an API to helpminifilters retrieve the destination name for rename and hardlink creationoperations:

过滤管理器还提供了API帮助minifilter驱动获取重命名和创建硬链接的目标文件名。

NTSTATUS
FltGetDestinationFileNameInformation (
    IN PFLT_INSTANCE Instance,
    IN PFILE_OBJECT FileObject,
    IN HANDLE RootDirectory OPTIONAL,
    IN PWSTR FileName,
    IN ULONG FileNameLength,
    IN FLT_FILE_NAME_FORMAT NameFormat,
    IN FLT_FILE_NAME_QUERY_METHOD QueryMethod,
    OUT PFLT_FILE_NAME_INFORMATION *RetFileNameInformation
    );

This API should be used during a minifilters pre-operation callback for IRP_MJ_SET_INFORMATION, FileSetNameInformation or FileSetLinkInformation.  The caller specifies the parameters from the operation, and the Filter Manager will return a FLT_FILE_NAME_INFORMATION structure that contains the destination name for the operation in the format requested.  Just as with FltGetFileNameInformation(), the minifilter must call FltReleaseFileNameInformation() when it is finished using the name returned.

这个API应该在 IRP_MJ_SET_INFORMATION, FileSetNameInformation or FileSetLinkInformation pre-operation回调函数中调用,调用者指定操作的参数,过滤管理器返回指定格式的文件名在结构体FLT_FILE_NAME_INFORMATION中。和FltGetFileNameInformation()一样,调用者必须调用FltReleaseFileNameInformation()在使用完名字后。

Name tunneling is another aspect of file names where filter commonly make mistakes.  The Filter Manager provides the following API to detect and retrieve a new name when needed due to name tunneling:

Name tunneling是另外一个驱动经常犯错误的方面,过滤管理器提供了以下API由于Name tunneling检测、获取新的名字。

NTSTATUS

FltGetTunneledName (

    IN PFLT_CALLBACK_DATA CallbackData,

    IN PFLT_FILE_NAME_INFORMATIONFileNameInformation,

    OUT PFLT_FILE_NAME_INFORMATION*RetTunneledFileNameInformation

    );

Name tunneling will only affect a minifilter that is working with names in normalized format.  If a minifilter needs a normalized name in its pre-operation callback for CREATE, rename or hardlink creation operations, it should call FltGetTunneledName() in its post-operation callback to validate that the name provided in the pre-operation callback was not affected by name tunneling in the file system.  If name tunneling did occur, a new file name information structure is returned in RetTunneledFileNameInformation.  The minifilter should use this name for its name processing and call FltReleaseFileName() on this structure when complete.

Name tunneling仅仅影响使用正常格式文件名的minifilter驱动,如果minifilter驱动需要在创建、重命名、创建硬链接的pre-operation的回调函数中获取普通文件名,那么它应该在它的post-operation回调函数中调用FltGetTunneledName()验证在pre-operation回调函数中获取的文件名没有被文件系统的name-tuneling影响。如果发生了name-tuneling,新的名字将在结构体RetTunneledFileNameInformation中返回,minifilter驱动应该使用这个名字并且最后调用FltReleaseFileName()释放它。


以下段落摘自楚狂人的微文件系统过滤驱动开发指南

长文件名出现之后,旧的16位应用程序随时可能破坏掉长文件名。为此出现了所谓的命名隧道概念。现在假设一个16位的程序比如文字处理程序把当前版本的文挡维护在一个临时文件中。当用户修改这个文件,原始的文件就被删除了,临时文件被改为原来的文件名。
如果原始文件有一个长文件名,但是临时文件仅仅有短文件名,那么当旧的文件被删除,名字也跟着丢失了。因此当命名隧道起作用的时候,文件系统记住了每个被删除的文件名一段时间(比如15秒),如果一个短文件名的文件生成了,刚好和被记忆的长文件名配套,那么短文件名自动改名为长文件名。这就是命名隧道概念。
想自己尝试一下:首先,在一个空文件夹中生成一个文件 longfilename.然后删除它。在生成一个文件longfi~1,然后输入dir /x,这时你发现,longfilename又出现了!)


我说说我的理解,如果创建了一个短名文件,minifilter获取普通文件名时此短名被扩展成长名。而由于name tunneling,最终创建了一个被缓存的长文件名,此长文件名与短名扩展成的长文件名并不相同,所以获取的短名扩展成的长名无效。

我读了下《window internal》中关于tunneling的说明,大概表述的是为了与之前的应用兼容,例如MS Dos使用safe save方法的程序(将改动的文件存放在一临时文件,然后删除原始文件,最后将临时文件改名),被重命名的文件信息需要与原始文件一致,否则创建时间会不断变化,所以文件的元信息需要在一段时间内被缓存(一般15s)。当文件删除时,它的长名、短名、创建时间等元信息被缓存,当一个新文件被创建时,文件系统搜索缓存是否有隧道数据应被还原。

默认情况下,数据被缓存15s,可以使用注册表 HKLM\SYSTEM\CurrentControlSet\Control\FileSystem下的值MaximumTunnelEntryAgeInSeconds修改此默认时间,改为0则表示禁用name tunneling。

使用FltGetFileNameInformation在pre-create中获取短名、post-close、paging I/O path以及当前线程域TopLevelIrp非空时,函数返回STATUS_FLT_INVALID_NAME_REQUEST。


(待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值