一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

文件系統(tǒng)minifilter新架構(gòu)開發(fā)指南

 夢(mèng)中家園 2013-04-12

微過濾器驅(qū)動(dòng)開發(fā)指南

 

 

 

0.譯者序

 

對(duì)我來說,中文永遠(yuǎn)是最美,最簡(jiǎn)潔,最精確和最高雅的文字。

 

本 文翻譯僅僅用做交流學(xué)習(xí)。我不打算保留任何版權(quán)或者承擔(dān)任何責(zé)任。不要引用到贏利出版物中給您帶來版權(quán)官司。本文的翻譯者是楚狂人,如果有任何問題,你可 以通過郵箱http://shoufuban.net/mailto:MFC_Tan_Wen@163.com,或者是QQ16191935,或者是MSN http://shoufuban.net/mailto:walled_river@hotmail.com與我交流。

 

我翻譯此文出于對(duì)文件系統(tǒng)技術(shù)的興趣。這就是新的文件系統(tǒng)過濾接口。其實(shí)也不算什么新的東西,微軟開發(fā)了另一個(gè)“舊模型的”過 濾驅(qū)動(dòng),稱之為過濾管理器(Filter Manager)。從而提供了一系列新的接口來讓你開發(fā)新的過濾器。確實(shí)這套接口變簡(jiǎn)單清晰了。你至少避免了包含無數(shù)個(gè)信息的IRP,避免了請(qǐng)求在各個(gè)部 件中循環(huán)的發(fā)來發(fā)去,一個(gè)分發(fā)例程中處理無數(shù)中情況,一不小心系統(tǒng)崩潰。我不知道花了多少時(shí)間才弄明白一個(gè)簡(jiǎn)單的緩沖讀請(qǐng)求從用戶到過濾到文件系統(tǒng)和緩沖 管理器,虛擬內(nèi)存管理器之間的關(guān)系!現(xiàn)在你也許不需要再管他們了,僅僅做好自己的過濾工作就可以。

 

這套接口強(qiáng)大嗎?能實(shí)現(xiàn)你想要的功能嗎?你很快就發(fā)現(xiàn)你沒有研究過sfilter就看不懂Minifilter,或者是還得從sfilter開始做起更靈活一點(diǎn)。微軟就是這樣,拿僵硬而且也不簡(jiǎn)單的東西來“簡(jiǎn)化”強(qiáng)大靈活但是設(shè)計(jì)上一團(tuán)糟的東西,對(duì)于你來說是兩者都必須學(xué)習(xí),最后你的腦子被微軟塞得滿滿的,不過沒關(guān)系,我們已經(jīng)習(xí)慣了.

 

此文的原文是《Filter Driver Development Guide》,出自微軟的網(wǎng)站。我在以下這個(gè)地址下載得到此文:

http://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/FilterDriverDeveloperGuide.doc

我盡量在翻譯中使文章保持原貌。如果您認(rèn)為此文無法理解,建議您首先閱讀舊的文件過濾驅(qū)動(dòng)的相關(guān)資料。我認(rèn)為必須有文件系統(tǒng)和windows驅(qū)動(dòng)的相關(guān)知識(shí),才能閱讀此文。

 

我未必總是使用規(guī)范的名詞,但我總是使用最容易理解的名詞。一些常用的可能不翻譯,比如IRP,MDL,有驅(qū)動(dòng)開發(fā)經(jīng)驗(yàn)的人應(yīng)該可以理解。另一些可能采用中文(英文)的方式。

 

一些解釋如下:

例程(Routine):我不懂得例程和函數(shù)有什么不同。我認(rèn)為例程就是函數(shù)。稱為Routine而不是Function可能是為了避免其他c程序員理解得太容易。

接口(Api):編程開發(fā)接口,一個(gè)提供給你調(diào)用的函數(shù)。

流(Stream):如果你寫過文件系統(tǒng)驅(qū)動(dòng),那么你一定知道FileObject,對(duì)你來說一個(gè)流就是一個(gè)FileObject。

文件(File):一個(gè)文件可能有多個(gè)流,因?yàn)榭赡芏啻未蜷_,多個(gè)FileObject可能對(duì)應(yīng)一個(gè)文件。

域(Field):一個(gè)數(shù)據(jù)結(jié)構(gòu)中的一個(gè)數(shù)據(jù)成員。喜歡數(shù)據(jù)庫(kù)的人可能稱為字段。喜歡面向?qū)ο蟮姆Q為數(shù)據(jù)成員。

透明(transparence):看不見,意味著也不需要管。不過請(qǐng)注意透明的反意詞絕對(duì)不是不透明(opacity)。

不透明(opacity):不知道的。比如空指針。因?yàn)榭罩羔樦赶虻氖鞘裁矗瑥目罩羔槺旧硎橇私獠坏降?。所以稱為不透明的指針。

回調(diào)(Callback)函數(shù):一個(gè)由系統(tǒng)調(diào)用而且原則上你不能自己調(diào)的函數(shù)。

預(yù)操作(pre-operation)回調(diào):如果打算過濾一個(gè)操作,那么這個(gè)回調(diào)出現(xiàn)在操作完成之前。

后操作(post-operation)回調(diào):如果打算過濾一個(gè)操作,那么這個(gè)回調(diào)出現(xiàn)在操作完成之后。

 

1.概述

 

這個(gè)文檔用于I/O管理器和基本文件系統(tǒng)之間的過濾驅(qū)動(dòng)。文件系統(tǒng)可能是本地或者網(wǎng)絡(luò)的。這個(gè)文檔不涉及文件系統(tǒng)和存儲(chǔ)設(shè)備之間的過濾驅(qū)動(dòng),比如FtDisk和DMIO.

 

我們將主要討論一種新的文件系統(tǒng)過濾驅(qū)動(dòng)模型,所謂的微過濾器(minfiter).

 

以前的文件系統(tǒng)過濾基于一個(gè)例子sfilter.使用IRP和設(shè)備對(duì)象進(jìn)行過濾。我們現(xiàn)在稱之為“舊過濾模型”

 

新的架構(gòu)中一個(gè)關(guān)鍵的組件其實(shí)是一個(gè)舊過濾模型的文件系統(tǒng)過濾驅(qū)動(dòng),被稱為“過濾管理器(Filter Manger)”.在未來,微軟發(fā)行的操作系統(tǒng)將默認(rèn)安裝這個(gè)驅(qū)動(dòng)。(譯者注:現(xiàn)在,你得手工安裝。)這個(gè)驅(qū)動(dòng)通過提供一些庫(kù)供微過濾器調(diào)用來管理所有的微過濾器。必要的頭文件,庫(kù)和二進(jìn)制代碼都在微過濾器IFSKit中。

 

為何要開發(fā)一個(gè)微文件系統(tǒng)過濾驅(qū)動(dòng)?

 .通過更少的工作量,得到更簡(jiǎn)單的,更可靠的過濾驅(qū)動(dòng).

 .動(dòng)態(tài)加載和卸載,綁定和解除綁定.

 .在過濾棧中,綁定到一個(gè)合理確定的位置。

 .上下文管理。快捷,干凈,可靠的上下文管理,用于文件對(duì)象,流,文件,實(shí)例和卷.

 .一組有用的調(diào)用.包括根據(jù)文件名尋找,高效存取,和用戶態(tài)程序之間的通信,以及io排隊(duì).

 .支持非回環(huán)I/O.這樣,一個(gè)微過濾器發(fā)起的I/O請(qǐng)求可以輕松的只讓棧中更下面的微過濾器以及文件系統(tǒng)看到了。

 .僅僅過濾感興趣的操作。不象舊過濾模型那樣必須掛接每個(gè)操作入口以便把操作傳遞到下層.

 

2.術(shù)語(yǔ)

 

在過濾管理器架構(gòu)中,定義了一些新的對(duì)象。為了搞清這些,這里將列出一些定義:

 

過濾器:在文件系統(tǒng)上執(zhí)行一些過濾操作的一種驅(qū)動(dòng).

 

卷:在本地文件系統(tǒng),這個(gè)對(duì)象指文件系統(tǒng)所管理的邏輯卷.對(duì)于網(wǎng)絡(luò)重定向文件系統(tǒng),指所有網(wǎng)絡(luò)請(qǐng)求被重定向的目的。卷直接對(duì)應(yīng)文件系統(tǒng)(無論本地或者網(wǎng)絡(luò))舊過濾模型中的設(shè)備對(duì)象(DEVICE_OBJECT).

 

實(shí)例:一 個(gè)過濾器在一個(gè)卷上唯一的某層上生成的一個(gè)實(shí)例化對(duì)象。過濾管理器把所有的IO請(qǐng)求發(fā)到卷上的實(shí)例棧上。一個(gè)微過濾器在一個(gè)卷上可能不止一個(gè)實(shí)例.規(guī)范的 例子是FileSpy.有時(shí)候把FileSpy的兩個(gè)實(shí)例分別綁定在另一個(gè)過濾器的上邊和下邊。此時(shí)每個(gè)實(shí)例有一個(gè)私有的上下文.這個(gè)上下文包含IO操作 的日志.可以用來比較一個(gè)過濾器上下的IO操作有什么不同。

 

文件:文件系統(tǒng)保存在一個(gè)磁盤上的可能包含若干個(gè)流的有名字的數(shù)據(jù)對(duì)象.

流:指一個(gè)文件中的物理數(shù)據(jù)流.

 

文件對(duì)象(FileObject):用來描述一個(gè)用戶對(duì)一個(gè)文件中的一個(gè)物理數(shù)據(jù)流的一次打開。

 

回調(diào)數(shù)據(jù)(CallbackData):過濾管理器中的一種數(shù)據(jù)結(jié)構(gòu),包含了一個(gè)操作中的所有信息。對(duì)應(yīng)于舊過濾模型中的IRP.

 

3.微過濾器安裝

 

微過濾器可以通過一個(gè)INF文件安裝。INF文件指出了這個(gè)微過濾器所支持的實(shí)例.實(shí)例的具體說明在第5節(jié).每個(gè)實(shí)例有一組標(biāo)志,還有一個(gè)唯一的數(shù)值固定了它在過濾棧中的位置。

 

INF 文件中有一個(gè)表標(biāo)明了每個(gè)實(shí)例的層級(jí).這用來給文件系統(tǒng)過濾的開發(fā)商裝載他們的微過濾器.有標(biāo)記標(biāo)明了這個(gè)微過濾器是否需要"自動(dòng)的綁定".如果是,那么 每個(gè)新的卷出現(xiàn)的時(shí)候,微過濾器都回收到一個(gè)通知.它可以在此綁定他們.綁定的時(shí)候,inf文件中的層級(jí)決定了綁定到什么層次上。

 

在微過濾器運(yùn)行時(shí),文件系統(tǒng)過濾開發(fā)商也可以在某個(gè)指定的層級(jí)上動(dòng)態(tài)的生成一個(gè)實(shí)例,這可以使用FilterAttachAtAltitude()調(diào)用.這對(duì)于開發(fā)者來說可以用來進(jìn)行測(cè)試和排除bug.

 

4.微過濾器注冊(cè)

 

微過濾器是內(nèi)核驅(qū)動(dòng)。因此它必須導(dǎo)出一個(gè)名為DriverEntry的函數(shù)。在驅(qū)動(dòng)加載的時(shí)候這個(gè)函數(shù)第一個(gè)被調(diào)用.很多微過濾器在DriverEntry()中調(diào)用FltRegisterFilter().

 

FilterRegisterFilter ()需要傳入一個(gè)參數(shù)。是一個(gè)FLT_REGISTRATION結(jié)構(gòu).包含了:一個(gè)卸載例程.實(shí)例通知回調(diào),一組上下文回調(diào)指針,一組文件系統(tǒng)操作回調(diào)指 針.一般情況下,微過濾過器只捕獲一部分操作,因此文件系統(tǒng)操作回調(diào)指針可能并不多。

 

對(duì)于某一種操作,微過濾器可以指定一些附加的標(biāo)記來指明它是否在所有的情況下都收到它們.比如,如果FLTFL_OPERATION_REGISTRATION_SKIP_PAGING_IO被指定了,微過濾器就不會(huì)收到任何此類IRP的paging I/O操作。

 

同樣的,如果FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO被指定了,那么只有這類操作的非緩沖請(qǐng)求能看見.(比如說,指定了IRP_MJ_READ類操作,那么所有的緩沖讀就都不會(huì)被微過濾器捕獲了。

 

5.開始過濾

 

當(dāng)一個(gè)微過濾器注冊(cè)自己,它就應(yīng)該在某個(gè)時(shí)間調(diào)用函數(shù)FltStartFiltering()來開始過濾。并不一定要在DriverEntry中調(diào)用。不過大多數(shù)微過濾器可能是這樣做的。

 

這個(gè)函數(shù)將激發(fā)必要的通知,導(dǎo)致微過濾器綁定到卷上然后開始過濾I/O操作。為此,過濾管理器會(huì)通過微過濾器的inf文件遍歷它注冊(cè)過的所有的實(shí)例。

 

每個(gè)示例都有一個(gè)層級(jí)。一個(gè)層級(jí)是一個(gè)唯一的字符串,(如"100.123456"),這個(gè)定義了微過濾器的這個(gè)實(shí)例在棧上的位置。商業(yè)版本的微過濾器層級(jí)將由微軟公司來分配。

 

層級(jí)的數(shù)字越高,這個(gè)微過濾器綁定在棧上的位置就越高。一些示例層級(jí)提供給開發(fā)者用來實(shí)現(xiàn)微過濾器。這些是僅有的不會(huì)被分配的層級(jí)。層級(jí)有兩個(gè)作用:一是確定兩個(gè)微過濾器之間的順序關(guān)系,尤其是有時(shí)得實(shí)現(xiàn)一些不用去考慮個(gè)別微過濾器什么時(shí)候加載的功能。

 

比 如說,一個(gè)加密解密過濾器必須安裝在一個(gè)防病毒的過濾的下邊。否則,防病毒過濾器無法從已經(jīng)加密的內(nèi)容中發(fā)現(xiàn)病毒。另外就是提供了一個(gè)最小的測(cè)試矩陣,用 來測(cè)試這些過濾驅(qū)動(dòng)的互容性。如果這些驅(qū)動(dòng)實(shí)例都是按一個(gè)指定的順序在棧中的,那么測(cè)試的時(shí)候就不用再考慮排列各種不同的順序了。

 

在inf 文件中,一個(gè)實(shí)例和一個(gè)標(biāo)記聯(lián)系在一起。如果第1個(gè)位標(biāo)記了,那么微過濾器不會(huì)在卷出現(xiàn)在系統(tǒng)中的時(shí)候得到通知。這樣的實(shí)例應(yīng)該通過過濾管理器編程接口來 手工的綁定。如果第2位被設(shè)置了,即使手工的發(fā)送了一個(gè)綁定請(qǐng)求,微過濾器也不會(huì)收到通知來要求綁定一個(gè)實(shí)例到一個(gè)卷。

 

6.實(shí)例的通知

 

當(dāng)一個(gè)實(shí)例生成的時(shí)候,一組回調(diào)函數(shù)提供來通知微過濾器。通過這些回調(diào),微過濾器可以決定它的實(shí)例在什么時(shí)候綁定到卷上和從卷上解除了綁定。

 

6.1. 安裝一個(gè)實(shí)例

 

回調(diào)例程InstatanceSetupCallback()在下列情況下被調(diào)用:

.當(dāng)一個(gè)微過濾器加載的時(shí)候,每個(gè)存在的卷都會(huì)導(dǎo)致這個(gè)調(diào)用。

.當(dāng)一個(gè)新的卷被mount.

.當(dāng)FltAttachVolume被調(diào)用(內(nèi)核模式)

.當(dāng)FltAttachVolumeAtAltitude()被調(diào)用(內(nèi)核模式)

.當(dāng)FilterAttach()被調(diào)用(用戶模式)

.當(dāng)FilterAttachAtAltitude()被調(diào)用(用戶模式)

 

在這個(gè)過程中,微過濾器決定是否在這個(gè)卷上生成實(shí)例。這個(gè)回調(diào)的原型如下:

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

);

FltObjects結(jié)構(gòu)喊有指向微過濾器,卷,和實(shí)例的指針。這個(gè)實(shí)例指將要在InstanceSetupCallback()函數(shù)中生成的實(shí)例。Flags標(biāo)記是什么操作導(dǎo)致激發(fā)了InstanceSetupCallback():

FLTFL_INSTANCE_SETUP_AUTOMATIC_ATTACHMENT:  這是一個(gè)微過濾器注冊(cè)的時(shí)候,一個(gè)自動(dòng)的綁定通知。過濾管理器為每個(gè)剛加載的微過濾器枚舉所有的卷。如果是一個(gè)使用者明確的指定一個(gè)實(shí)例綁定到某一個(gè)卷,不會(huì)設(shè)置有這個(gè)標(biāo)記。

FLTFL_INSTANCE_SETUP_MANUAL_ATTACHMENT:  通過調(diào)用FilterAttach()(用戶態(tài)),或者是FilterAttachVolumeAtAltitude()(用戶態(tài)),或者是FltAttachVolume()(內(nèi)核態(tài))所發(fā)起的一個(gè)手工的請(qǐng)求。

FLTFL_INSTANCE_SETUP_NEWLY_MOUNTED_VOLUME:  文件系統(tǒng)剛剛掛載(mount)了一個(gè)卷,所以呼叫InstanceSetupCallback()來通知微過濾器,如果它愿意可以生成實(shí)例來綁定這個(gè)卷。

 

在InstanceSetupCallback()中,微過濾器同時(shí)得到了卷設(shè)備類型(VolumeDeviceType)和卷文件系統(tǒng)類型(VolumeFilesytemType),用以判斷這個(gè)卷是否過濾器所感興趣的。同時(shí),微過濾器可以調(diào)用FltGetVolumeProperties()來獲取卷屬性。通過FltSetInstanceContext()在實(shí)例上設(shè)置上下文。當(dāng)然這是需要綁定的時(shí)候。它甚至可以在卷上打開或者關(guān)閉文件。

 

如果這個(gè)回調(diào)返回了成功,那么這個(gè)實(shí)例將綁定到卷上。如果返回了一個(gè)警告或者錯(cuò)誤,那么不會(huì)綁定。

如果微過濾器沒有指定InstanceSetup回調(diào),那么,系統(tǒng)將認(rèn)為用戶總是返回了STATUS_SUCCESS,實(shí)例總是會(huì)生成并綁定。

 

6.2. 控制實(shí)例的銷毀

 

InstanceQueryTeardown()回調(diào)僅僅在一個(gè)手工解除綁定的請(qǐng)求下被調(diào)用。以下操作可能導(dǎo)致:

FltDetachVolume() (內(nèi)核模式)

FilterDetach()    (用戶模式)

 

如果一個(gè)微過濾器沒有提供這個(gè)回調(diào),那么手工解除綁定是不被支持的。但是,卷的解掛載(dismount)和微過濾器的卸載還是允許的。

 

如果這個(gè)回調(diào)返回成功,那么過濾管理器開始銷毀給出的實(shí)例。最后實(shí)例的InstanceTeardownStart()和InstanceTeardownComplete()會(huì)被調(diào)用。如果返回了錯(cuò)誤或者警告,手工解除綁定會(huì)失敗。推薦的錯(cuò)誤代碼有: STATUS_FLT_DO_NOT_DETACH,不過實(shí)際上你可以返回任何錯(cuò)誤代碼。

InstanceQueryTeardown()回調(diào)的原型是:

typedef NTSTATUS

(*PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK) (

    IN PCFLT_RELATED_OBJECTS FltObjects,

    IN FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags

    );

和InstanceSetupCallback()類似,F(xiàn)ltObject指出了與這個(gè)銷毀操作有關(guān)的微過濾器,卷和實(shí)例。

 

6.3. 實(shí)例解綁定的同步

 

如果InstanceTeardownStart()的時(shí)候已經(jīng)決定要解除綁定,那么這個(gè)例程中必須做以下的事情:

(1)重設(shè)所有的未決的I/O操作(包括預(yù)操作和后操作)

(2)保證不會(huì)有新的I/O操作進(jìn)入未決。

(3)對(duì)剛剛到達(dá)的操作開始最少的工作。

同時(shí),應(yīng)該做以下操作:

(1)關(guān)閉所有打開的文件。

(2)取消所有本過濾器發(fā)起的I/O請(qǐng)求。

(3)停止將新的工作任務(wù)排隊(duì)。

 

然后微過濾器把控制權(quán)交還過濾管理器來繼續(xù)它的銷毀過程。當(dāng)所有與這個(gè)實(shí)例相關(guān)的操作都排除干凈或者完成了,InstanceTeardownComplete()會(huì)被調(diào)用。管理器保證此時(shí)所有此實(shí)例的存在的操作回調(diào)都完成了。這時(shí)微過濾器必須關(guān)閉所有這個(gè)實(shí)例打開的文件。

這兩個(gè)回調(diào)的原型如下:

typedef VOID

(*PFLT_INSTANCE_TEARDOWN_CALLBACK) (

    IN PCFLT_RELATED_OBJECTS FltObjects,

IN FLT_INSTANCE_TEARDOWN_FLAGS Reason

);

FltObjets中有微過濾器,卷和實(shí)例。Resson參數(shù)指明這次銷毀的原因,可能是以下一些標(biāo)記的組合:

FLTFL_INSTANCE_TEARDOWN_MANUAL:  這次銷毀操作是一個(gè)手工的請(qǐng)求。(FilterDetach()或者 FltDetachVolume()).

FLTFL_INSTANCE_TEARDOWN_FILTER_UNLOAD:  這次銷毀操作是因?yàn)槲⑦^濾器執(zhí)行卸載或者是選擇了把卸載請(qǐng)求失敗掉導(dǎo)致的。

FLTFL_INSTANCE_TEARDOWN_MANDATORY_FILTER_UNLOAD:  這次銷毀操作是一次強(qiáng)制卸載導(dǎo)致的。這種情況下不能把卸載請(qǐng)求失敗掉。

FLTFL_INSTANCE_TEARDOWN_VOLUME_DISMOUNT: 這次銷毀是一個(gè)卷被解掛載的結(jié)果。FLTFL_INSTANCE_TEARDOWN_INTERNAL_ERROR:  這次銷毀是因?yàn)榘惭b實(shí)例的時(shí)候的一個(gè)內(nèi)部錯(cuò)誤導(dǎo)致的,比如內(nèi)存不足。

 

請(qǐng)注意沒有返回值。InstanceTeardownStart()和InstanceTeardownComplete()都不能失敗。過濾管理器保證這些例程都運(yùn)行在Passive IRQL.

 

7.回調(diào)支持

 

7.1 回調(diào)數(shù)據(jù)(Callback data)

 

回調(diào)數(shù)據(jù)(Callback data)是過濾管理器用來描述I/O操作的新結(jié)構(gòu)。類似舊過濾模型下的IRP.微過濾器通過這個(gè)結(jié)構(gòu)和過濾管理器交互。不同的是,回調(diào)數(shù)據(jù)不像IRP那樣管理一個(gè)棧結(jié)構(gòu)?;卣{(diào)數(shù)據(jù)的管理都通過已經(jīng)明確定義的過濾管理器接口。并且返回狀態(tài)值給過濾管理器即可。

FLT_CALLBACK_DATA類型包含了微過濾器描述一個(gè)I/O操作所需要的所有的信息。下面繼續(xù)詳細(xì)講解這個(gè)結(jié)構(gòu)中的各個(gè)域來說明其中包含的信息:

Flags:提供這個(gè)操作的一些信息。一個(gè)或多個(gè)下面的標(biāo)記可能被設(shè)置在Flags中:

FLTFL_CALLBACK_DATA_IRP_OPERATION: 這個(gè)回調(diào)數(shù)據(jù)描述一個(gè)IRP操作。

FLTFL_CALLBACK_DATA_FAST_IO_OPERATION:這個(gè)回調(diào)數(shù)據(jù)描述一個(gè)FastIO操作。

FLTFL_CALLBACK_DATA_FS_FILTER_OPERATION:這個(gè)回調(diào)描述一個(gè)文件系統(tǒng)過濾器操作。

FLTFL_CALLBACK_DATA_SYSTEM_BUFFER:這個(gè)操作所用的緩沖是一個(gè)系統(tǒng)分配的緩沖。

FLTFL_CALLBACK_DATA_GENERATED_IO:這個(gè)操作是由一個(gè)微過濾器發(fā)起的。

FLTFL_CALLBACK_DATA_REISSUED_IO:這個(gè)操作被一個(gè)當(dāng)前實(shí)例之上的過濾器所重新發(fā)回給文件系統(tǒng)。

FLTFL_CALLBACK_DATA_DRAINING_IO:只有設(shè)置了后操作(Post-operation)回調(diào)的情況下,表明這是一個(gè)快速“排出”的I/O操作以便微過濾器的卸載。

FLTFL_CALLBACK_DATA_POST_OPERATION:只有設(shè)置了后操作(Post-operation)回調(diào)的情況下,表明著個(gè)I/O正在后操作中。

FLTFL_CALLBACK_DATA_DIRTY: 當(dāng)一個(gè)微過濾器已經(jīng)改變了這個(gè)操作的一個(gè)或者多個(gè)可變參數(shù)的時(shí)候,設(shè)置這個(gè)參數(shù)。這個(gè)標(biāo)記僅僅在Pre-operation過程中設(shè)置。微過濾器必須用 FLT_SET_CALLBACK_DATA_DIRTY()和FLT_CLEAR_CALLBACK_DATA_DIRTY()來操作這個(gè)標(biāo)記。

Thread: 發(fā)出這個(gè)操作的線程的地址。

Iopb:       指向這個(gè)操作的可變參數(shù)的指針。這個(gè)結(jié)構(gòu)在后邊詳敘。

IoStatus:IO_STATUS_BLOCK結(jié)構(gòu)返回操作最后的狀態(tài)。如果一個(gè)微過濾器打算結(jié)束這個(gè)操作,那么必須先設(shè)置這個(gè)域,然后才能結(jié)束這個(gè)請(qǐng)求。對(duì)于傳遞給文件系統(tǒng)去的請(qǐng)求,在后操作過程(Post-operation)中有操作最終的狀態(tài)。

TagData:僅僅在Create操作的后操作回調(diào)中有效。當(dāng)一個(gè)操作的目標(biāo)文件有一個(gè)重解析點(diǎn)(Reparse point)的時(shí)候設(shè)置這個(gè)位。

QueueLinks:一個(gè)鏈表入口結(jié)構(gòu)。有時(shí)要把回調(diào)數(shù)據(jù)(Callback Data)放入工作隊(duì)列中使用這個(gè)。

QueueContext[2]:一組空指針結(jié)構(gòu),用來傳入附加的上下文到工作隊(duì)列處理過程中。

FilterContext[4]:一組空指針結(jié)構(gòu),當(dāng)回調(diào)數(shù)據(jù)進(jìn)入了隊(duì)列,微過濾器可以做任意使用。不依賴于過濾管理器的內(nèi)部結(jié)構(gòu)。

RequestorMode:這個(gè)操作的者的請(qǐng)求模式。

 

Iopb 域所指的是一個(gè)FLT_IO_PARAMETER_BLOCK結(jié)構(gòu)。包含了回調(diào)數(shù)據(jù)中可以修改的部分。對(duì)比IRP來說,這里相當(dāng)于IRP的當(dāng)前??臻g (current stack location)。微過濾器必須訪問這個(gè)結(jié)構(gòu)來得到每次預(yù)操作(pre-operation)和后操作(post-operation)回調(diào)的I/O參 數(shù)。下面是一些更詳細(xì)的細(xì)節(jié):

IrpFlags:IRP中描述這個(gè)操作的一些標(biāo)記。

MajorFunction:IRP主功能號(hào)。

MinorFunction:IRP輔功能號(hào)。

OperationFlags:即IO_STACK_LOCATION.Flags.

TargetFileObject:這個(gè)操作所影響到的目標(biāo)文件。

TargetInstance:管理這個(gè)操作的實(shí)例。

Parameters:FLT_PARAMETERS是一個(gè)共用體。描述主功能號(hào)和輔功能號(hào)所指定的操作的具體參數(shù)。

 

除了在預(yù)操作回調(diào)中不能修改主功能號(hào)之外,微過濾器可以修改這個(gè)結(jié)構(gòu)中其他的任何參數(shù)。如果參數(shù)改變,微過濾器應(yīng)該調(diào)用FLT_SET_CALLBACK_DIRTY()來注明這個(gè)改變。更多詳細(xì)的信息將在第8節(jié)中講述。

 

微 過濾器在同一個(gè)I/O操作的預(yù)回調(diào)和后回調(diào)中,總是會(huì)看到參數(shù)是一樣的。即使下面的過濾器可能已經(jīng)修改了這些參數(shù)。這是由過濾管理器保證的。但是雖然 FLT_IO_PARAMTER_BLOCK的內(nèi)容是一樣的,在預(yù)操作和后操作中,這個(gè)結(jié)構(gòu)的地址可能不一樣。因此微過濾器不應(yīng)該依賴這個(gè)地址。

 

回調(diào)數(shù)據(jù)結(jié)構(gòu)包含IO_STATUS_BLOCK來記錄這個(gè)操作的狀態(tài)。過濾管理器會(huì)“尊重”這些改變而不會(huì)標(biāo)記這些數(shù)據(jù)為臟(Dirty)。微過濾器如果打算在預(yù)操作回調(diào)中結(jié)束這個(gè)操作或者是后操作回調(diào)中撤消這個(gè)操作,都必須先設(shè)置這個(gè)IO_STATUS_BLOCK。

 

7.2 預(yù)操作回調(diào)(Pre-Operation Callbacks)

 

所有的預(yù)操作回調(diào)原型都是這樣:

typedef FLT_PREOP_CALLBACK_STATUS

(*PFLT_PRE_OPERATION_CALLBACK) (

    IN OUT PFLT_CALLBACK_DATA Data,

    IN PCFLT_RELATED_OBJECTS FltObjects,

    OUT PVOID *CompletionContext

);

所有的預(yù)操作回調(diào)都返回一個(gè)FLT_PRE_OPERATION_CALLBACK_STATUS.這個(gè)變量是如下定義的:

FLT_PREOP_SUCCESS_WITH_CALLBACK:這個(gè)操作成功了而且微過濾器需要后操作回調(diào)。

FLT_PREOP_SUCCESS_NO_CALLBACK:   操作成功了,但是不需要后操作回調(diào)。

FLT_PREOP_PENDING:     微過濾器將在未來某個(gè)時(shí)候結(jié)束這個(gè)操作(通過調(diào)用FltCompletePendedOperation())。微過濾器在返回這個(gè)值之前不需要做其他特殊的操作(比如IoMarkIrpPending())。如果這個(gè)狀態(tài)返回了,這個(gè)I/O操作被過濾管理器掛起(棧中的下層驅(qū)動(dòng)都不會(huì)收到預(yù)操作回調(diào)),直到FltCompletePendedPreOperation()被調(diào)用。

FLT_PREOP_COMPLETE:         微 過濾結(jié)束了操作。這個(gè)微過濾器設(shè)置了Data->IoStatus.Status中的I/O狀態(tài)。這個(gè)過濾器以下的微過濾器,舊模型過濾器和文件系 統(tǒng)都不會(huì)看見這個(gè)I/O請(qǐng)求。而之上的微過濾器回看到這個(gè)請(qǐng)求以合適的狀態(tài)完成。對(duì)于CLEANUP和CLOSE操作來說,微過濾器以一個(gè)失敗狀態(tài)結(jié)束這 個(gè)操作是不允許的。因?yàn)檫@些操作不能失敗。

FLT_PREOP_SYNCHRONIZE:      僅 僅在非CREATE操作有效。(CREATE操作是自動(dòng)同步的)。若返回此值微過濾器必須有一個(gè)后操作回調(diào)。這表明這個(gè)微過濾器希望這個(gè)操作在同一個(gè)線程 里完成。也就是說后操作調(diào)出現(xiàn)的時(shí)候和預(yù)操作調(diào)用在同一個(gè)線程上下文里。這是由過濾管理器所保證的。不管下層的過濾器以及文件系統(tǒng)是掛起還是忽略這個(gè) I/O操作。這個(gè)狀態(tài)必須小心使用。因?yàn)檫^濾管理器必須同步整個(gè)I/O,這可能影響整個(gè)系統(tǒng)的性能。

FLT_PREOP_DISALLOW_FAST_IO: 這個(gè)狀態(tài)僅僅在舊模型下返回BOOLEAN的fastI/O的操作的情況下有效。這個(gè)狀態(tài)表明不接受fastI/O請(qǐng)求,請(qǐng)發(fā)送IRP重試。

 

在預(yù)操作返回之前,過濾器可能修改I/O操作的參數(shù)。而且能修改的參數(shù)都集中在Data->Iopb中。當(dāng)一個(gè)微過濾器修改了任何一個(gè)參數(shù),它必須調(diào)用FLT_SET_CALLBACK_DATA_DIRTY(),否則,修改不會(huì)被承認(rèn),可能導(dǎo)致未知的錯(cuò)誤。

 

對(duì)此還有兩個(gè)例外。如果修改的是IoStatus,沒有必要設(shè)置Dirty就會(huì)被過濾管理器所承認(rèn)。

另 一個(gè)例外是IRP_MJ_CREATE的后操作過程。如果一個(gè)碰到重解析點(diǎn)(reparse point),Data->TagData會(huì)指想一個(gè)重解析數(shù)據(jù)緩沖。如果微過濾器打算修改這個(gè)緩沖,它可以釋放了這個(gè)緩沖然后重新分配一個(gè)(不能 為空)。此時(shí)不用調(diào)用FLT_SET_CALLBACK_DATA_DIRTY().

 

7.3 后操作回調(diào)(Post-Operation Callbacks)

 

所有的后操作都有同樣的原型:

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

);

Data->Flags中都設(shè)置了FLTFL_CALL_DATA_POST_OPERATION.

如果一個(gè)微過濾器在預(yù)操作回調(diào)中返回FLT_PREOP_SUCCESS_WITH_CALLBACK了,它肯定能收到這個(gè)同樣操作的完成回調(diào)也就是后操作回調(diào)。后操作回調(diào)返回的類型為FLT_POSTOP_CALLBACK_STATUS.這個(gè)值是:

FLT_POSTOP_FINISHED_PROCESSING – 微過濾器已經(jīng)完成了這個(gè)操作控制權(quán)應(yīng)該還給請(qǐng)求的發(fā)起者.

FLT_POSTOP_STATUS_MORE_PROCESSING_REQUIRED – 微過濾器還沒有完成這個(gè)請(qǐng)求,而且回在后邊完成它,使用FltCompletePendedPostOperation().

與舊模型過濾驅(qū)動(dòng)的完成例程不同,這個(gè)后操作回調(diào)執(zhí)行在DPC中斷級(jí)上。如果一個(gè)微過濾器需要完成一些在DPC上完成不了的工作,可以調(diào)用FltDoCompletionProcessingWhenSafe()。有必要的情況下(我們?cè)贒PC中斷級(jí)時(shí)),會(huì)把工作插入一個(gè)工作線程。除非這個(gè)請(qǐng)求是不能被排隊(duì)的(比如一個(gè)頁(yè)面交換請(qǐng)求(paging I/O)).

 

對(duì)于打算在后操作回調(diào)中取消一個(gè)文件打開的微過濾器,F(xiàn)ltCancelFileOpen()調(diào)用可以對(duì)指定的FileObject來一個(gè)清理和關(guān)閉的功能。微過濾器必須必須填寫合適的錯(cuò)誤代碼,并且在后操作回調(diào)中返回FLT_POSTOP_FINISHED_PROCESSING.

 

當(dāng)一個(gè)實(shí)例被卸除的時(shí)候,過濾管理器可能調(diào)用候后操作回調(diào),但是此時(shí)操作還未真的完成。這時(shí),標(biāo)志FLTFL_POST_OPERATION_DRAINING會(huì)設(shè)置。此時(shí)提供了盡量少的信息。所以微過濾器應(yīng)該清理所有的從預(yù)操作中傳來的操作上下文,并返回FLT_POSTOP_FINISHED_PROCESSING.

 

操作的IRP_MJ(主功能碼)中增加了一些附加的新數(shù)值來表示FastI/O中的一些沒有IRP與之對(duì)應(yīng)的操作。目的是把IRP操作和FastI/O操作可以采用同樣的處理方式。這樣通過一些標(biāo)記就可以區(qū)分IRP操作,微過濾相關(guān)操作和FastI/O操作,而不用注冊(cè)一些類似的回調(diào)函數(shù)了(比如讀,寫,鎖定等操作的回調(diào)函數(shù))。

 

有以下這些操作主功能碼:

所有原有的IRP_MJ。

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

 

關(guān)于主功能號(hào)的一些要注意的地方:

(1)IRP_MJ_CREATE的預(yù)操作回調(diào)中不能獲得或者設(shè)置文件,流,或者流句柄這樣的上下文。因?yàn)樵陬A(yù)操作中,文件或者流還沒有決定是否生成。

(2)IRP_MJ_CLOSE 的后操作中不能同樣不能設(shè)置或者或者文件,流或者流句柄這樣的上下問。因?yàn)樵谶@個(gè)操作中,一些與之相關(guān)的系統(tǒng)內(nèi)部結(jié)構(gòu)可能已經(jīng)釋放了。

(3)IRP_MJ_CLEANUP和IRP_MJ_CLOSE 是永遠(yuǎn)不能失敗的。他們可以掛起,傳遞或者成功結(jié)束。但是不能返回FLT_PREOP_COMPLETE并填一個(gè)錯(cuò)誤碼在IoStatus塊中。

 

后操作回調(diào)不能失敗,因?yàn)檫@個(gè)操作已經(jīng)發(fā)生了。如果希望在后操作回調(diào)中讓一個(gè)操作失敗,那么你必須撤消已經(jīng)成功的操作。比如IRP_MG_CREATE操作,過濾管理器提供了FltCancelFileOpen()來銷毀已經(jīng)打開的文件對(duì)象。但是過濾器還是有責(zé)任來重新整理由于Create操作而被覆蓋掉的原來的文件的內(nèi)容。

 

在后操作中對(duì)操作參數(shù)做的任何改變都不會(huì)被過濾管理器所承認(rèn)。

 

8.操作回調(diào)數(shù)據(jù)參數(shù)

 

8.1 I/O參數(shù)塊(I/O Parameter Block)

 

就像前面所提及的,回調(diào)數(shù)據(jù)(Callback Data)包含了兩個(gè)關(guān)于I/O的重要的數(shù)據(jù)結(jié)構(gòu):

1)I/O狀態(tài)塊(I/O Status Block):         Data->IoStatus用來返回它自己所結(jié)束的操作的狀態(tài)(或者在后操作回調(diào)中可以讀取下層驅(qū)動(dòng)所完成的操作的狀態(tài))。

2)I/O參數(shù)塊(I/O Parameter Block):   Data->Iopb指向這個(gè)I/O操作中專為本微過濾器使用的數(shù)據(jù)。

本節(jié)深入討論讀取和改變這些參數(shù)的問題。

 

Iopb中的主功能號(hào)和輔功能號(hào)表示IRP/FastIo/FsFilter-主/輔功能,主功能號(hào)不能由過濾器修改。過濾管理器不支持。

TargetFileObject表示I/O操作的目標(biāo),流的文件對(duì)象。微過濾器可以修改它(必須調(diào)用FLT_SET_CALLBACK_DATA_DIRTY()),而且被過濾管理器承認(rèn)。

TargetInstance參數(shù)與I/O從一個(gè)實(shí)例向另一個(gè)實(shí)例傳遞的意義不同,是表示當(dāng)前的實(shí)例。過濾器可以改變這個(gè)指針。但是僅僅能是同一個(gè)層級(jí),但綁定在其他的卷上的實(shí)例。同時(shí),也必須調(diào)用FLT_SET_CALLBACK_DATA_DIRTY()。

 

微 過濾器是不能修改TargetInstance指向同一個(gè)卷上的另一個(gè)實(shí)例的。舉個(gè)例子來說,一個(gè)微過濾器在一個(gè)卷C:上有兩個(gè)實(shí)例。一個(gè)在層級(jí)200稱 為實(shí)例C200,,另一個(gè)在層級(jí)100,稱為實(shí)例C100,同時(shí)在D:上還有一個(gè)層級(jí)200的實(shí)例,稱為實(shí)例D:200。現(xiàn)在假設(shè)在實(shí)例C200上 IRP_MJ_READ的預(yù)操作回調(diào)被調(diào)用了,微過濾器可以把TrageInstance修改為實(shí)例D:200,但是不能修改為實(shí)例C:100。

 

這組織了任何微過濾器同一個(gè)卷的棧中非法的(不按固定順序的)傳遞操作。

I/O參數(shù)塊中含有一些與具體操作相關(guān)的參數(shù)。微過濾器必須用與操作配套的共用體結(jié)構(gòu)來訪問他們。對(duì)于IOCTL和FSCTL,具體的控制碼也有不同的共用體結(jié)構(gòu)。微過濾器必須檢查具體的控制碼來使用正確的共用體。

 

8.2 使用緩沖/MDL

 

在IRP 的世界中,緩沖采用多種機(jī)制傳遞到驅(qū)動(dòng)中。比如支持基本I/O的設(shè)備對(duì)象,緩沖是通過Irp->UserBuffer傳入的,這對(duì)文件系統(tǒng)是最常見 的。有些設(shè)備只支持緩沖I/O,那么I/O管理器傳入的緩沖區(qū)Irp->AssociatedIrp.SystemBuffer.對(duì)于支持直接 I/O的設(shè)備,緩沖是通過Irp->MdlAddress,一個(gè)被鎖定的MDL。

 

但是可能有例外。一些IRP的??臻g的緩沖參數(shù)直接傳入??赡苤赶蚝诵膬?nèi)存或者是原始的用戶空間內(nèi)存。和設(shè)備對(duì)象對(duì)I/O操作的要求無關(guān)。這些緩沖不能傳到硬件,因?yàn)樗麄儫o視設(shè)備對(duì)象所支持的I/O類型。

 

也有一些IRP總是緩沖I/O,比如IRP_MJ_QUERY/SET_INFORMATION.

 

對(duì)于微過濾器,緩沖總是通過適當(dāng)?shù)牟僮飨嚓P(guān)的共用體傳入。沒有一個(gè)通用的方法可以獲得緩沖/MDL的地址來源。這種設(shè)計(jì)是為了減少棧空間之間緩沖導(dǎo)致的沖突。

 

在回調(diào)數(shù)據(jù)中,如果操作是緩沖型的,那么標(biāo)記 FLTFL_CALLBACK_DATA_SYSTEM_BUFFER會(huì)被設(shè)置。如果是這樣的,那么緩沖區(qū)在非分頁(yè)的核心內(nèi)存中。

 

如 果這個(gè)標(biāo)記沒有設(shè)置,那么只能說明不是緩沖型。微過濾器有方法做進(jìn)一步區(qū)分(見下一節(jié))。緩沖還是可能來源于某個(gè)核心內(nèi)存池。但是只要這個(gè)標(biāo)記沒有設(shè)置, 過濾器就應(yīng)該假設(shè)內(nèi)存在原始用戶空間中。這種情況下,如果緩沖并不是傳入的用戶緩沖,那么總是需要一個(gè)MDL來鎖定一些頁(yè)面,而且調(diào)用者必須獲得一個(gè)系統(tǒng) 空間地址來訪問這些頁(yè)面。這是一條規(guī)則,將在下節(jié)詳敘之。

 

最 后,對(duì)于某些微過濾器希望能夠定位緩沖/長(zhǎng)度/MDL來做一些最通用的操作的時(shí)候,F(xiàn)ltDecodeParameters()提供用來做一個(gè)快速的查找 并返回一個(gè)指向參數(shù)結(jié)構(gòu)中的緩沖/長(zhǎng)度/MDL。對(duì)于沒有緩沖空間的操作,返回STATUS_INVALID_PARMETER.

 

NTSTATUS

FLTAPI

FltDecodeParameters(

    IN PFLT_CALLBACK_DATA CallbackData,

    OUT PMDL **MdlAddressPointer OPTIONAL,

    OUT PVOID  **Buffer OPTIONAL,

    OUT PULONG *Length OPTIONAL,

    OUT LOCK_OPERATION *DesiredAcces OPTIONAL

    );

 

DesiredAccess表示微過濾器可以使用的訪問緩沖的方式。比如對(duì)于IRP_MJ_READ,可能指定IpWriteAccess,意味著這個(gè)緩沖區(qū)是可寫的。對(duì)于IRP_MJ_WRITE,一般指定IoReadAccess表示微過濾器可以讀取這個(gè)緩沖區(qū)但是不能修改它。這樣一個(gè)應(yīng)用使用一個(gè)僅僅有只讀權(quán)限的頁(yè)面來發(fā)起一個(gè)寫請(qǐng)求也是合法的了。

 

對(duì)于希望緩沖空間被鎖定的過濾器,應(yīng)該了解:如果FLTFL_CALLBACK_DATA_SYSTEM_BUFFER表示設(shè)置了,那么可以假設(shè)這個(gè)緩沖區(qū)已經(jīng)被鎖定,可以安全的訪問。

 

如果沒有設(shè)置則可以調(diào)用FltLockUserBuffer()來鎖定頁(yè)面。這個(gè)調(diào)用可以保證頁(yè)面被合適的方法鎖定。如果成功了,它會(huì)設(shè)置與操作相關(guān)的參數(shù)部分的MdlAddress域?yàn)橛脕砻枋鲞@些頁(yè)面的MDL.

 

8.3 交換緩沖

 

一 些微過濾器為了某些操作必須交換緩沖??紤]一個(gè)微過濾器實(shí)現(xiàn)加密算法,對(duì)一個(gè)非緩沖(non-cached)IRP_MJ_READ,它一般會(huì)希望把緩沖 中的數(shù)據(jù)解密。同樣的在寫的時(shí)候,它希望把內(nèi)容加密??紤]以下情況:內(nèi)容無法在這個(gè)空間中加密。因?yàn)閷?duì)于IRP_MJ_WRITE,這個(gè)微過濾器可能只有 IoreadAccess權(quán)限。

 

因此微過濾器必須以他自己的有讀寫權(quán)限的緩沖區(qū)取代原來的緩沖區(qū)。加密了原緩沖區(qū)中的內(nèi)容后寫入新緩沖區(qū)后,再繼續(xù)傳遞I/O請(qǐng)求。

 

為此,過濾管理器支持緩沖轉(zhuǎn)換。有以下一些游戲規(guī)則必須遵守:

1.   改變了緩沖區(qū)的微過濾器必須有對(duì)應(yīng)的后操作回調(diào)。這樣緩沖能被過濾管理器自動(dòng)的轉(zhuǎn)換回來。

2.   如果改變的是一個(gè)標(biāo)記有FLTFL_CALLBACK_DATA_SYSTEM_BUFFER標(biāo)記的緩沖,必須保證新的緩沖是非分頁(yè)內(nèi)存。(也就是比如來自非分頁(yè)內(nèi)存池或者鎖定的內(nèi)存)。

3.   如果以上的標(biāo)記沒有設(shè)置,那么微過濾器必須按設(shè)備對(duì)象的要求來確定緩沖類型(可以在卷屬性中查看DeviceObjectFlags等標(biāo)記)。比如如果是支持直接I/O的,那么必須提供MDL等等。

4.   如果微過濾器使用非分頁(yè)池中的緩沖來給一個(gè)沒有設(shè)置FLTFL_CALLBACK_DATA_SYSTEM_BUFFER的操作,那么它也必須用MuBuildMdlForNonpagedPool()并把地址填寫到MdlAddress域中。這是因?yàn)檫@么一來,下面的任何過濾器或者文件系統(tǒng)都不用再嘗試去鎖定非分頁(yè)池(可以在構(gòu)建的時(shí)候使用斷言,但是對(duì)效率不利),如果提供了一個(gè)MDL,過濾器和文件系統(tǒng)總是可以通過MDL訪問緩沖(可以獲得一個(gè)系統(tǒng)內(nèi)存地址來訪問它)。

5.   替換一個(gè)緩沖的時(shí)候,微過濾器也必須換掉MDL(就是說緩沖和MDL要保持同步了)。對(duì)于通常的直接I/O異常,可以把MDL留空。

6.   微過濾器不應(yīng)該釋放舊的MDL和緩沖空間。

7.   不要嘗試在后操作回調(diào)中替換掉舊的緩沖和MDL.過濾管理器自動(dòng)執(zhí)行這些操作。實(shí)際上微過濾器在后操作回調(diào)中的Iopb中見到緩沖空間和MDL是舊的(譯者注:替換前的)。微過濾器必須自己在上下文中記錄新的緩沖區(qū)。

8.   微過濾器應(yīng)該釋放自己分配的(和替換過的)緩沖。無論如何,如果有的話,過濾管理器會(huì)自動(dòng)釋放新緩沖的MDL。

9.   微過濾器不希望過濾管理器自動(dòng)釋放交換過的緩沖MDL可以調(diào)用FltRetainSwappedBufferMdl()。

10. 過濾器如果希望訪問交換過的緩沖的MDL可以在后操作回調(diào)中使用FltGetSwappedBufferMdl()。既然一個(gè)更下層的過濾器或文件系統(tǒng)交換了新的緩沖空間進(jìn)來,那么有可能生成了一個(gè)MDL。在后操作回調(diào)中微過濾器交換緩沖之前,過濾管理器保存了所有這樣的的MDL。這個(gè)調(diào)用可以用來訪問這些MDL.

 

 

9.上下文(Context)支持

 

所有的過濾器都必須在他們所操作的各種對(duì)象中記錄一些他們自己的狀態(tài)。讓微過濾器在這些對(duì)象中擁有他們的上下文是過濾管理器的一個(gè)重要特點(diǎn)。

 

一個(gè)上下文是使用FltAllocateContext()分配一的一片動(dòng)態(tài)內(nèi)存區(qū)。這個(gè)調(diào)用傳入需要的內(nèi)存空間的大小并返回一個(gè)內(nèi)存空間指針。系統(tǒng)會(huì)綁定一個(gè)內(nèi)部的數(shù)據(jù)頭用來跟蹤這個(gè)指針?biāo)鶎?duì)應(yīng)的上下文。

 

以下種類的對(duì)象支持上下文:

 

卷 - 一個(gè)已經(jīng)掛載的設(shè)備。

實(shí)例 - 一個(gè)微過濾器對(duì)對(duì)一個(gè)卷的一次綁定。一個(gè)微過濾器可能對(duì)一個(gè)卷綁定多次。如果一個(gè)微過濾器對(duì)一個(gè)卷只能綁定一次,那么推薦用卷上下文來代替實(shí)例上下文,這樣效率高多了。

文件 - 指關(guān)于一個(gè)文件的所有打開的流。一般這些上下文是不支持的。

流 - 文件上的一個(gè)單獨(dú)的數(shù)據(jù)流。

流句柄 - 一個(gè)文件的一次打開,比如一個(gè)文件對(duì)象。

 

9.1 上下文注冊(cè)

 

注冊(cè)的時(shí)候,微過濾器定義它所想使用的上下文的類型,大小以及一個(gè)用來清理上下文的例程。微過濾器用一組FLT_CONTEXT_REGISTRATION結(jié)構(gòu)來確定這些參數(shù).

 

下面解釋FLT_CONTEXT_REGISTRATION的細(xì)節(jié):

 

ContextType:  注冊(cè)的上下問的類型。

Flag:         表 示這個(gè)上下文的一些特殊處理信息。當(dāng)前的定義有:FLT_CONTEXT_REGISTRATION_NO_EXACT_SIZE_MATCH:默認(rèn)的情 況下,過濾管理器會(huì)比較一個(gè)給定的上下文的請(qǐng)求的長(zhǎng)度和分配上下文的時(shí)候指定的數(shù)據(jù)長(zhǎng)度。如果指定了這個(gè)標(biāo)記,如果請(qǐng)求分配的內(nèi)存大小少于等于注冊(cè)的時(shí)候 所指定的長(zhǎng)度,過濾權(quán)利氣回使用特殊指定的分配例程。當(dāng)注冊(cè)時(shí)候指定的大小為FLT_VARIABLE_SIZED_CONTEXT或者分配和釋放例程都 已經(jīng)指定了的時(shí)候,這個(gè)標(biāo)記被忽略。

CleanupContext:    當(dāng)過濾管理器決定應(yīng)該清理這個(gè)上下問的時(shí)候這個(gè)例程被調(diào)用。如果在上下文被釋放之前沒有什么需要清理的,這個(gè)可以設(shè)置為NULL.

Size:         這個(gè)上下文的字節(jié)大小。這用來允許過濾管理器使用內(nèi)存池技術(shù)(如旁視列表)來讓分配和釋放更加有效率。如果使用了自己的分配和釋放例程,這個(gè)域被忽略。

PoolTag: 分配內(nèi)存的“池”上下文。這是使用ExAllocatePoolWithTag的時(shí)候用的。如果使用自己的分配和釋放例程,這個(gè)域被忽略。

Allocate: 如果打算使用自己的分配例程,設(shè)置這個(gè)指針。如果打算依賴過濾管理器的內(nèi)存池技術(shù),那么這個(gè)應(yīng)該設(shè)置為NULL.

Free:         如果想使用自己的釋放例程,那么這個(gè)必須設(shè)置為非空。

 

如果一個(gè)微過濾器有相同類型的上下文但是長(zhǎng)度不一,它可以為同類型的上下文注冊(cè)不同的FLT_CONTEXT_REGISTRATION結(jié)構(gòu)來利用過濾管理器的內(nèi)存池技術(shù)。

 

9.2 上下文生成接口

 

下面是FltAllocateContext()的函數(shù)原型:

NTSTATUS

FLTAPI

FltAllocateContext (

    IN PFLT_FILTER Filter,

    IN FLT_CONTEXT_TYPE ContextType,

    IN SIZE_T ContextSize,

    IN POOL_TYPE PoolType,

    OUT PFLT_CONTEXT *ReturnedContext

);

ContextType可以是以下的情況:FLT_VOLUME_CONTEXT , FLT_INSTANCE_CONTEXT, FLT_FILE_CONTEXT, FLT_STREAM_CONTEXT, 或者是FLT_STREAMHANDLE_CONTEXT.

 

下面是一組用來把一個(gè)上下文綁定到一個(gè)對(duì)象上的例程。請(qǐng)注意上下文的類型和對(duì)象類型必須是配套的。

 

NTSTATUS

FLTAPI

FltSetVolumeContext (

    IN PFLT_VOLUME Volume,

    IN FLT_SET_CONTEXT_OPERATION Operation,

    IN PFLT_CONTEXT NewContext,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltSetInstanceContext (

    IN PFLT_INSTANCE Instance,

    IN FLT_SET_CONTEXT_OPERATION Operation,

    IN PFLT_CONTEXT NewContext,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltSetFileContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    IN FLT_SET_CONTEXT_OPERATION Operation,

    IN PFLT_CONTEXT NewContext,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltSetStreamContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    IN FLT_SET_CONTEXT_OPERATION Operation,

    IN PFLT_CONTEXT NewContext,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltSetStreamHandleContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    IN FLT_SET_CONTEXT_OPERATION Operation,

    IN PFLT_CONTEXT NewContext,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

);

設(shè)置一個(gè)上下文的時(shí)候有兩種類型的操作可能發(fā)生。 它們是:

 

FLT_SET_CONTEXT_KEEP_IF_EXISTS:如果沒有存在的上下文,那么將設(shè)置新的上下問。如果有存在的,那么新的上下文將不會(huì)設(shè)置上去,而且會(huì)返回一個(gè)錯(cuò)誤代碼。如果OldContext參數(shù)定義了,那么已經(jīng)存在的上下文會(huì)返回。如果有,調(diào)用者必須釋放返回的上下文。如果新的上下文沒設(shè)置上去,那么調(diào)用者必須負(fù)責(zé)釋放它。

 

FLT_SET_CONTEXT_REPLACE_IF_EXISTS: 即使舊的上下文存在,新的也回釋放上去。如果OldContext定義了,那么被取代的上下文會(huì)返回。調(diào)用者必須自己釋放它。如果沒有定義,則舊的上下文會(huì)被自動(dòng)釋放。

 

當(dāng)相關(guān)設(shè)備對(duì)象被系統(tǒng)釋放,過濾管理器會(huì)在合適的時(shí)機(jī)調(diào)用微過濾器來清理上下文。微過濾器可能希望某個(gè)時(shí)候自己刪除一個(gè)對(duì)象上的上下文。為此,微過濾器可以調(diào)用以下的一個(gè)例程來刪除上下文。當(dāng)然前提是它擁有這個(gè)上下文的指針。

 

VOID

FLTAPI

FltDeleteContext (

    IN PFLT_CONTEXT Context

    );

 

如果沒有指針呢?它必須通過指定對(duì)象來刪除上下文??梢允褂靡韵逻@些例程中的某個(gè):

 

NTSTATUS

FLTAPI

FltDeleteVolumeContext (

    IN PFLT_FILTER Filter,

    IN PFLT_VOLUME Volume,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltDeleteInstanceContext (

    IN PFLT_INSTANCE Instance,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltDeleteFileContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltDeleteStreamContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

    );

 

NTSTATUS

FLTAPI

FltDeleteStreamHandleContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *OldContext OPTIONAL

);

 

如果OldContext參數(shù)為空,那么過濾管理器會(huì)釋放對(duì)這個(gè)上下文的所有的引用。否則,上下文會(huì)通過OldContext返回。微過濾器必須自己調(diào)用FltReleaseContext來釋放它。

 

9.3 上下文獲?。≧etrieval)接口

 

下面的例程用來獲取某個(gè)設(shè)備的相關(guān)上下文。使用完畢,調(diào)用者必須釋放返回的上下文,釋放使用FltReleaseContext().上下文不能在DPC中斷級(jí)獲取。所以如果一個(gè)后操作回調(diào)中希望得到一個(gè)上下文,那么必須從預(yù)操作中獲得并傳入。

 

NTSTATUS

FLTAPI

FltGetVolumeContext (

    IN PFLT_FILTER Filter,

    IN PFLT_VOLUME Volume,

    OUT PFLT_CONTEXT *Context

    );

 

NTSTATUS

FLTAPI

FltGetInstanceContext (

    IN PFLT_INSTANCE Instance,

    OUT PFLT_CONTEXT *Context

    );

 

NTSTATUS

FLTAPI

FltGetFileContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *Context

    );

 

NTSTATUS

FLTAPI

FltGetStreamContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *Context

    );

 

NTSTATUS

FLTAPI

FltGetStreamHandleContext (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    OUT PFLT_CONTEXT *Context

);

 

當(dāng)使用完畢,下面的一些例程用來釋放獲得的上下文。一般推薦不要在操作之間傳遞這些上下文指針。上下文的獲取非常有效率,是專門設(shè)計(jì)用來在每個(gè)操作要使用的時(shí)候?qū)iT來獲取上下文的。

 

VOID

FLTAPI

FltReleaseContext (

    IN PFLT_CONTEXT Context

);

 

類似實(shí)例通知例程,每個(gè)操作的回調(diào)例程都收到一個(gè)FLT_RELATED_OBJECTS結(jié)構(gòu)。這個(gè)結(jié)構(gòu)包含所有這個(gè)操作相關(guān)的所有已知的的對(duì)象。為了簡(jiǎn)化上下文的獲取,有一個(gè)類似的FLT_RELATED_CONTEXT可以一次獲取。這個(gè)結(jié)構(gòu)如下:

 

typedef struct _FLT_RELATED_CONTEXTS {

 

    PFLT_CONTEXT VolumeContext;

    PFLT_CONTEXT InstanceContext;

    PFLT_CONTEXT FileContext;

    PFLT_CONTEXT StreamContext;

    PFLT_CONTEXT StreamHandleContext;

 

} FLT_RELATED_CONTEXTS, *PFLT_RELATED_CONTEXTS;

 

接 下來兩個(gè)例程用來依次獲得多個(gè)例程,此外也有一次性釋放。對(duì)于FltGetContexts()調(diào)用者指定(在DesiredContext參數(shù)中)需要 的上下文。在內(nèi)部,一次獲得多個(gè)上下文比一個(gè)一個(gè)的獲得它們效率高。當(dāng)然,對(duì)于不需要的上下文最好是不要去獲取它。FLT_ALL_CONTEXTS可以 用來得到所有可用的上下文。

 

VOID
FltGetContexts (
    IN PFLT_RELATED_OBJECTS FltObjects,
    IN FLT_CONTEXT_TYPE DesiredContexts,
    OUT PFLT_RELATED_CONTEXTS Contexts
    );

VOID
FltReleaseContexts (
    IN OUT PFLT_RELATED_CONTEXTS Contexts
    );

 

9.4 上下文釋放接口

 

當(dāng)過濾管理器決定了一個(gè)上下文要被釋放的時(shí)候,微過濾器的相關(guān)回調(diào)會(huì)被調(diào)用。這個(gè)回調(diào)例程應(yīng)該清理任何上下文(包括清理分配的內(nèi)存,釋放資源等等)。通過返回,過濾管理器會(huì)釋放傳入的上下文結(jié)構(gòu)。

 

每個(gè)類型的上下文都要有一個(gè)對(duì)應(yīng)的清理例程。這些例程定義如下:

 

typedef VOID

(*PFLT_CONTEXT_CLEANUP_CALLBACK) (

    IN PFLT_CONTEXT Context,

    IN FLT_CONTEXT_TYPE ContextType

);

同一個(gè)清理例程可以注冊(cè)給多個(gè)不同類型的上下文。

 

10.與用戶態(tài)的通信

 

10.1 過濾器通信端口對(duì)象

為了實(shí)現(xiàn)安全的和支持多種不同類型通信方法,一個(gè)新的對(duì)象被引入:微過濾器通信端口(以下簡(jiǎn)稱通信端口或者端口)。專門設(shè)計(jì)用來給核心態(tài)-用戶態(tài)通信或者反過來。核心-核心通信現(xiàn)在不在支持。一個(gè)端口是一個(gè)有名字的NT對(duì)象。而且有一個(gè)安全的描述符號(hào)。

 

過濾管理器生成了一個(gè)新的對(duì)象類型,F(xiàn)ilterConnectionPort來實(shí)現(xiàn)這個(gè)。過濾管理器在它的DriverEntry中生成這個(gè)新的對(duì)象類型,趕在了任何微過濾器加載之前。

 

只有核心模式的驅(qū)動(dòng)才能生成一個(gè)通信端口,使用以下的調(diào)用:

NTSTATUS

FltCreateCommunicationPort(

    IN PFLT_FILTER Filter,

    OUT PHANDLE PortHandle,

    IN POBJECT_ATTRIBUTES ObjectAttributes,

    IN PVOID ServerPortCookie OPTIONAL,

    IN PFLT_CONNECT_NOTIFY ConnectNotifyCallback,

    IN PFLT_DISCONNECT_NOTIFY DisconnectNotifyCallback,

    IN PFLT_MESSAGE_NOTIFY MessageNotifyCallback,

    IN ULONG MaxConnections

);

Filter是微過濾器的過濾器句柄。成功生成之后,端口的句柄在PortHandle參數(shù)中返回。

和其他的NT對(duì)象一樣,ObjectAttributes參數(shù)定義了OBJECT_ATTRIBUTES結(jié)構(gòu)來初始化要生成的端口對(duì)象的名字,對(duì)象屬性和安全描述符等。

 

請(qǐng)注意屬性中OBJ_KERNEL_HANDLE標(biāo)記必須設(shè)置。因?yàn)橥ㄐ哦丝谥荒苁呛诵膶?duì)象。

 

ServerPortCookie是一個(gè)上下文。微過濾器可以通過這個(gè)和端口聯(lián)系在一起。這個(gè)上下文對(duì)過濾管理器是不透明的。所有的連接,中斷通知,都會(huì)同過這個(gè)上下文才能傳遞給微過濾器。有些過濾器可能要生成一組通信端口,又想功用一個(gè)同志例程。那么可以通過這個(gè)上下文中保存的數(shù)據(jù)進(jìn)行區(qū)分。

 

調(diào)用者還可以注冊(cè)一些回調(diào)函數(shù):

 

ConnectNotifyCallback():    當(dāng) 一個(gè)用戶態(tài)進(jìn)程嘗試打開一個(gè)端口的時(shí)候,這個(gè)例程被調(diào)用。過濾器可以選擇把這個(gè)請(qǐng)求失敗掉。通知例程回手到一個(gè)關(guān)于此連接的句柄。每一個(gè)連接有唯一的一個(gè) 句柄。ServerPortCookie 也會(huì)傳入。微過可以填寫ConnectionCookie為一個(gè)上下文。這個(gè)上下文會(huì)傳到所有的用戶態(tài)傳來的消息以及連接中斷例程中。

 

DisconnectNotifyCallback(): 當(dāng)一個(gè)端口被用戶態(tài)關(guān)閉的時(shí)候會(huì)調(diào)用這個(gè)回調(diào)。(也就是打開計(jì)數(shù)到0的時(shí)候)。

 

MessageNotifyCallback():    任何時(shí)候手到一個(gè)消息都會(huì)調(diào)用這個(gè)。

 

MaxConnections指出了這個(gè)通信端口上允許的最大向外連接數(shù)。這沒有默認(rèn)值,必須設(shè)置得大于0。

 

并 不能保證所有的對(duì)象名會(huì)生成在根名字空間。有可能過濾管理器把它們映射在/FileSystem/Filters目錄下。不過即使如此,對(duì)微過濾器和用戶 態(tài)應(yīng)用程序來說,這是透明的。當(dāng)引用了一個(gè)通信斷口的名字,那么所有的足見都應(yīng)該使用同樣的名字。例子Sacnner Minifiter中展示了這是怎么做的。

 

對(duì)應(yīng)于新的對(duì)象類型,新的訪問方式也被引入了。有新的訪問方式如下:

FLT_PORT_CONNECT

FLT_PORT_ALL_ACCESS

這是一些訪問類型。調(diào)用者可以設(shè)置這些來給使用者權(quán)限。用于構(gòu)造安全描述符的時(shí)候,使用InitializeObjectAttributes()。

 

設(shè)置了FLT_PORT_CONNECT,那么我們的應(yīng)用程序足可以連接這個(gè)端口并發(fā)送和接受消息。

 

微過濾器生成一個(gè)端口之后,端口就會(huì)開始偵聽可能的連接。直到你使用ZwClose()將它關(guān)閉為止。

 

10.2 從用戶態(tài)連接到通信端口

 

微過濾器的通信端口模型和舊模型的過濾器一樣,是不對(duì)稱的。核心態(tài)端生成,用戶態(tài)端連接。有一個(gè)接口用來給用戶態(tài)應(yīng)用打開一個(gè)端口。當(dāng)端口建立,ConnectNotify()例程被調(diào)用來通知微過濾器。

 

用戶態(tài)下連接一個(gè)端口的編程接口原型如下:

HRESULT

FilterConnectCommunicationPort(

    IN LPWSTR lpPortName,

    IN DWORD dwOptions,

    IN LPVOID lpContext,

    IN WORD wSizeOfContext,

    IN LPSECURITY_ATTRIBUTES lpSecurityAttributes,

    OUT HANDLE *hPort

);

 

lpPortName是一個(gè)寬字符格式的字符串,指出要連接的端口的名字。這個(gè)名字應(yīng)該和微過濾器生成這個(gè)端口的時(shí)候一樣。名字可以以”/”開頭表示在根路徑中。過濾管理器會(huì)在合適的路徑下打開他們并管理很多微過濾器通信端口。

 

dwOptions現(xiàn)在沒有使用。

LpContext是一個(gè)指針。指向一個(gè)不透明的參數(shù)塊。這個(gè)參數(shù)會(huì)被傳入到ConnectNotify()中。比如可以用來鑒別請(qǐng)求生成端口的應(yīng)用程序的版本。wSizeOfContext指出這個(gè)上下文的字節(jié)數(shù)。

 

LpSecurtityAttributes指出給用戶端的安全權(quán)限。如果這個(gè)句柄是繼承得到的。

 

如果這個(gè)調(diào)用不成功,合適的HRESULT會(huì)返回。

 

返回得到的句柄可以被管理或者被復(fù)制。這要通過一些編程接口。它也可以和一個(gè)I/O完成端口綁定。

 

當(dāng)這個(gè)接口被調(diào)用,一個(gè)新的核心態(tài)的無名端口對(duì)象就生成了(類型是FilterCommunicationPort).這個(gè)對(duì)象用來表示這個(gè)連接。微過濾器的ConnectNotify()例程被調(diào)用,從而得到通知。而且也得到連接端口的句柄,用來從核心態(tài)發(fā)送消息。

 

如果調(diào)用者沒有訪問這個(gè)服務(wù)端口的權(quán)限,或者已經(jīng)達(dá)到了最大連接數(shù),那么調(diào)用會(huì)失敗。

 

10.3 中斷與通信端口的連接

 

當(dāng)用戶態(tài)程序調(diào)用CloseHandle()或者核心態(tài)調(diào)用ZwClose()來關(guān)閉連接句柄的時(shí)候,連接會(huì)中斷。

 

只有用戶態(tài)調(diào)用CloseHandle()的時(shí)候,微端口的DisconnectNotify()例程才會(huì)調(diào)用。

 

理想情況下,微過濾器應(yīng)該總是在連接結(jié)束的時(shí)候,在DisconnectNotify()中關(guān)閉連接。如果一個(gè)微過濾器在其他地方關(guān)閉句柄,那么它必須用一些同步方法確保不會(huì)在DisconnectNotify()中關(guān)閉再次關(guān)閉它。

 

當(dāng)一個(gè)連接在核心態(tài)或者用戶態(tài)被中斷了,以下情況發(fā)生:

 

1.  所有用戶態(tài)的等待(通過FilterGetMessage)被清理掉,而且以STATUS_FLT_PORT_DISCONNECTED結(jié)束掉(被解釋為win32錯(cuò)誤碼ERROR_DISCONNECTED)。

2. 所有核心的被阻塞的發(fā)送例程會(huì)以STATUS_FLT_PORT_DISCONNECTED結(jié)束阻塞。

3. 因?yàn)槎丝谧儫o效了,所以不可能有其他的等待或者阻塞的情況出現(xiàn)。

 

微過濾器總是可以對(duì)服務(wù)端口的句柄調(diào)用ZwClose()來關(guān)閉服務(wù)端口。這并不會(huì)使已經(jīng)建立的連接中斷,但是會(huì)阻止新連接的建立。

 

10.4 卸載

 

微過濾器總是必須在FltUnregisterFilter()調(diào)用之前,在FilterUnload例程或者更早關(guān)閉服務(wù)端口。否則系統(tǒng)可能在卸載例程中被掛起。

 

即使在有一些連接打開的情況下(比如用戶態(tài)一放已經(jīng)打開了一些連接句柄),微過濾器也應(yīng)該允許被卸載。這種情況下,過濾管理器會(huì)嘗試強(qiáng)行終止這些連接。過濾管理器會(huì)調(diào)用DisconnectNotify()例程。微過濾器應(yīng)該在這里關(guān)閉這些連接句柄以避免句柄的泄漏。

 

11.文件名處理

 

通過查找操作的參數(shù)或者詢問文件系統(tǒng),過濾管理器能得到對(duì)象的名字。因而過濾管理器提供一組調(diào)用來方便獲取對(duì)象名。為了更高的效率,過濾管理器也暫存一些對(duì)象名。當(dāng)很多過濾器經(jīng)常查一個(gè)名字的時(shí)候,暫存這個(gè)名字所付出的代價(jià)是很值得的。

 

查詢對(duì)象名的時(shí)候,過濾管理器返回一個(gè)FLT_FILE_NAME_INFORAMTION結(jié)構(gòu)來避免數(shù)據(jù)拷貝。這些結(jié)構(gòu)被根據(jù)過濾器的請(qǐng)求次數(shù)計(jì)數(shù)。只有通過過濾管理器的編程接口才能改變這些結(jié)構(gòu)中的數(shù)據(jù)。下面有這些結(jié)構(gòu)的詳細(xì)信息。

 

11.1 從操作獲得一個(gè)文件名

 

可以在當(dāng)前操作的CallbackData->Iopb->TargetFileObject中得到文件名。這需要調(diào)用下面的例程:

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

);

 

CallbackData是這個(gè)操作的FLT_CALLBACK_DATA結(jié)構(gòu)?,F(xiàn)在假設(shè)過濾器想從這個(gè)操作中得到文件名。

 

名字的格式是以下三種:

FLT_FILE_NAME_NORMALIZED_FORMAT:請(qǐng)求全路徑名字,包括卷名。所有的短名被擴(kuò)展成長(zhǎng)名。任何流名足見回去掉后邊的“:$DATA”.如果這是一個(gè)目錄名,且不是根目錄,最后的“/”會(huì)被去掉。

FLT_FILE_NAME_OPENED_FORMAT:     包含全路徑,包括卷名。但是這個(gè)名字和打開這個(gè)對(duì)象所用的名字相同。因此可能在路徑中包含一些短名。

FLT_FILE_NAME_SHORT_FORMAT: 僅僅含有路徑中最后一個(gè)元素的短名(Dos名),不會(huì)返回全路徑。

 

QueryMethod應(yīng)該是以下之一:

FLT_FILE_NAME_QUERY_DEFAULT:     搜索一個(gè)名字的時(shí)候,管理器會(huì)首先找暫存的名字。然后再詢問文件系統(tǒng)。

FLT_FILE_NAME_QUERY_CACHE_ONLY:  僅僅在暫存中找。如果失敗,返回STATUS_FLT_NAME_CACHE_MISS.

FLT_FILE_NAME_QUERY_FILE_SYSTEM_ONLY:僅僅詢問文件系統(tǒng),不會(huì)從暫存中去尋找這個(gè)名字。

 

名字在最后一個(gè)參數(shù)中返回,F(xiàn)ileNameInformation.這個(gè)結(jié)構(gòu)是一組共享緩沖的Unicode字符串。不同的字符串表明不名字中不同的部分.

 

typedef struct _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;

 

當(dāng)一個(gè)文件名信息結(jié)構(gòu)從FltGetFileNameInforamtion()返回,name,Volume,Share(用于遠(yuǎn)程文件)會(huì)被解析出來。如果一個(gè)微過濾器需要其他的名字信息,它應(yīng)該調(diào)用FltParseFileNameInformation().

 

運(yùn) 行在DPC或者更低級(jí)的中斷級(jí)別的時(shí)候,微過濾器可以在IO過程中任何地方調(diào)用FltGetFileNameInformation().當(dāng)它在一個(gè)可能 導(dǎo)致死鎖的情況下請(qǐng)求(比如處理分頁(yè)交換的時(shí)候),如果在暫存中沒有找到名字或者指定了必須從文件系統(tǒng)讀取那么調(diào)用會(huì)失敗。

 

即 使沒有回調(diào)數(shù)據(jù)(Callback Data)存在,僅僅知道文件對(duì)象(FileObject)的時(shí)候,微過濾器也可以調(diào)用FltGetFileNameInformationUnsafe ()來獲得一個(gè)文件名。不過過濾器必須知道當(dāng)前向文件系統(tǒng)詢問這個(gè)名字是安全的。這個(gè)調(diào)用不能像FltGetFileNameInformation() 那樣檢查是否導(dǎo)致死活。微過濾器必須自己保證它。

 

當(dāng)一個(gè)名字使用完畢,應(yīng)該調(diào)用以下的例程來釋放:

 

FLTAPI

FltReleaseFileNameInformation (

    IN PFLT_FILE_NAME_INFORMATION FileNameInformation

);

 

過 濾管理器的名字暫存對(duì)微過濾查找對(duì)象的名字來說效率足夠了。名字暫存機(jī)制也管理了由于重新命名而無效的名字。維護(hù)一個(gè)名字暫存空間的復(fù)雜邏輯對(duì)微過濾器們 而言是透明的。但是微過濾器對(duì)于無效的名字并不是完全不需要關(guān)系。當(dāng)一個(gè)重命名發(fā)生了,過濾管理器清理所有的受影響的暫存文件名。但是微過濾器可能引用過 一個(gè)過時(shí)的文件名。當(dāng)這些引用全部被釋放的時(shí)候,過時(shí)的文件名信息結(jié)構(gòu)才會(huì)被真的釋放掉。如果一個(gè)微過濾器請(qǐng)求詢問一個(gè)已經(jīng)被重新命名的對(duì)象,將盡可能的 返回新的名字。

 

11.2 文件名的附加支持

 

過濾管理器也提供了一個(gè)編程接口來幫助微過濾器獲得一個(gè)改名或生成硬連接的操作的目的名:

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

    );

 

這個(gè)接口只能在IRP_MJ_SET_INFORMATION的預(yù)操作回調(diào)中調(diào)用,包括FileSetNameInformation和FileSetLinkInformation。 調(diào)用者從這個(gè)操作中獲得參數(shù),這個(gè)調(diào)用會(huì)返回一個(gè)FLT_FILE_NAME_INFORMTION結(jié)構(gòu),包含了目標(biāo)文件名在其中。與使用 FltGetFileNameInformation()相同,這個(gè)調(diào)用返回的名字使用完畢之后,應(yīng)該調(diào)用 FltReleaseFileNameInformation()來釋放。

 

命名隧道(Name Tunneling)是過濾器的另一個(gè)困繞之處。過濾管理器提供了一個(gè)編程接口來獲得一個(gè)命名管道需要的新名字:

NTSTATUS

FltGetTunneledName (

    IN PFLT_CALLBACK_DATA CallbackData,

    IN PFLT_FILE_NAME_INFORMATION FileNameInformation,

    OUT PFLT_FILE_NAME_INFORMATION *RetTunneledFileNameInformation

    );

 

命名隧道僅僅影響獲取文件名采用通常格式的微過濾器。如果一個(gè)微過濾器在它的一個(gè)預(yù)操作需要一個(gè)通常格式的文件名,這個(gè)預(yù)操作回調(diào)的來源是CREATE,改名,或生成硬連接的話,它應(yīng)該在后操作回調(diào)中調(diào)用FltGetTunneledName()來確認(rèn)這個(gè)名字是否被操作系統(tǒng)命名隧道所改過。如果命名隧道確實(shí)出現(xiàn)了,那么RetTunneledFileNameInformation中回返回一個(gè)新的文件名字信息結(jié)構(gòu)。微過濾器必須用這個(gè)新的名字,并且處理完畢后必須用FltReleaseFileName()來釋放它。

 

(譯者注:什么是命名隧道(Name Tunneling)

 

長(zhǎng)文件名出現(xiàn)之后,舊的16位應(yīng)用程序隨時(shí)可能破壞掉長(zhǎng)文件名。為此出現(xiàn)了所謂的命名隧道概念。現(xiàn)在假設(shè)一個(gè)16位的程序比如文字處理程序把當(dāng)前版本的文擋維護(hù)在一個(gè)臨時(shí)文件中。當(dāng)用戶修改這個(gè)文件,原始的文件就被刪除了,臨時(shí)文件被改為原來的文件名。

 

如 果原始文件有一個(gè)長(zhǎng)文件名,但是臨時(shí)文件僅僅有短文件名,那么當(dāng)舊的文件被刪除,名字也跟著丟失了。因此當(dāng)命名隧道起作用的時(shí)候,文件系統(tǒng)記住了每個(gè)被刪 除的文件名一段時(shí)間(比如15秒),如果一個(gè)短文件名的文件生成了,剛好和被記憶的長(zhǎng)文件名配套,那么短文件名自動(dòng)改名為長(zhǎng)文件名。這就是命名隧道概念。

 

想自己嘗試一下:首先,在一個(gè)空文件夾中生成一個(gè)文件 longfilename.然后刪除它。在生成一個(gè)文件longfi~1,然后輸入dir /x,這時(shí)你發(fā)現(xiàn),longfilename又出現(xiàn)了?。?/P>

 

11.3 名字提供接口

 

如 果一個(gè)過濾器打算提供一個(gè)途徑來改變名字空間,他必須注冊(cè)三個(gè)附加的回調(diào)給過濾管理器。這些回調(diào)允許過濾器作為名字的提供者。過濾器將有責(zé)任對(duì)上層發(fā)來的 FltGetFilenameInformation或者FltGetDestinationFileName返回 FLT_FILE_NAME_INFORMATION結(jié)構(gòu),并填寫其中名字的內(nèi)容。而且這樣的微過濾器還可以告知過濾管理器,他們所返回的名字要不要被暫 存。

 

作 為一個(gè)名字提供者,過濾器必須可以返回一個(gè)指定的文件對(duì)象(file object)的開放格式的名字。如果確定了通常名字格式,過濾管理器將重新遍歷這個(gè)名字的所有部分并調(diào)用名字提供者的徽調(diào)來展開這些部分為一個(gè)通常格式 的文件名。在展開一個(gè)路徑的所有部分的過程中,過濾器的名字通常化例程可能被調(diào)用不止一次。因此這個(gè)過程中允許過濾器傳入一個(gè)上下文。所有的過程結(jié)束后, 如果調(diào)用返回了,過濾器會(huì)被要求清理這個(gè)上下文。

 

當(dāng)一個(gè)過濾器作為名字提供者必須提供一個(gè)名字的時(shí)候,它的PFLT_GENERATE_FILE_NAME例程會(huì)被調(diào)用。你能在參數(shù)中得到文件對(duì)象,過濾器的實(shí)例,同時(shí)回調(diào)數(shù)據(jù)描述發(fā)生的操作。此外還有名字請(qǐng)求選項(xiàng)。那么過濾器必須在這中間生成名字:

 

typedef NTSTATUS

(*PFLT_GENERATE_FILE_NAME) (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject,

    IN PFLT_CALLBACK_DATA CallbackData OPTIONAL,

    IN ULONG NameOptions,

    OUT PBOOLEAN CacheFileNameInformation,

    OUT PFLT_NAME_CONTROL FileName

    );

 

typedef NTSTATUS

(*PFLT_NORMALIZE_NAME_COMPONENT) (

    IN PFLT_INSTANCE Instance,

    IN CONST PUNICODE_STRING ParentDirectory,

    IN USHORT VolumeNameLength,

    IN CONST PUNICODE_STRING Component,

    IN OUT PFILE_NAMES_INFORMATION ExpandComponentName,

    IN ULONG ExpandComponentNameLength,

    IN OUT PVOID *NormalizationContext

    );

 

typedef VOID

(*PFLT_NORMALIZE_CONTEXT_CLEANUP) (

    IN PVOID *NormalizationContext

    );

 

如果一個(gè)過濾器希望讓所有自己提供的名字的暫存失效,他可以調(diào)用以下的接口。在此之前它可能已經(jīng)提供了一些FLT_FILE_NAME_INFORMATION結(jié)構(gòu),而且其他過濾器可能剛好還在使用。那么這些FLT_FILE_NAME_INFORMATION結(jié)構(gòu)只有當(dāng)引用數(shù)降到0(已經(jīng)沒有人使用了),才會(huì)自己釋放掉。

 

NTSTATUS

FltPurgeFileNameInformationCache (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject OPTIONAL

    );

 

為了確保這樣一個(gè)過濾可以卸載,過濾管理器有責(zé)任管理這些過濾器提供的文件名的暫存和釋放。

 

一些FltGetFileNameInformation()調(diào)用FltGetDestinationFileName()調(diào)用基于一些過濾器提供的名字。過濾管理器將負(fù)責(zé)初始化這些FLT_FILE_NAME_INFORMATION結(jié)構(gòu)。

 

為 了提高效率,過濾管理器往名字提供者的PFLT_GENERATE_FILE_NAME回調(diào)傳入一個(gè)緩沖區(qū)。這個(gè)緩沖是一個(gè) FLT_NAME_CONTROL所包裝的UNICODE_STRING.這個(gè)結(jié)構(gòu)中包含一些公有的或者私有的信息。在一個(gè)過濾器試圖填充這個(gè)緩沖之前, 應(yīng)該先檢查緩沖是否足夠的大:

 

NTSTATUS

FltCheckAndGrowNameControl (

    IN OUT PFLT_NAME_CONTROL NameCtrl,

    IN USHORT NewSize

    );

如果這個(gè)調(diào)用返回STATUS_SUCCESS,說明FLT_NAME_CONTROL結(jié)構(gòu)足夠容納從名字提供者返回的名字了。

 

12.過濾器自產(chǎn)生I/O

 

某 些微過濾器需要執(zhí)行他們自己的I/O請(qǐng)求。在卷的微過濾器棧中,只有此過濾器以下的過濾器才能收到這些I/O請(qǐng)求。比如,一個(gè)防毒軟件,可能希望在打開一 個(gè)文件之前先讀一下這個(gè)文件。在新的微過濾模式下,一個(gè)微過濾器有兩種方法生成自己的請(qǐng)求:使用生成例程,類似現(xiàn)在的其他例程。此外就是使用舊的 ZwXxx例程。

 

主要的I/O生成例程如下:

 

NTSTATUS

FLTAPI

FltAllocateCallbackData (

    IN PFLT_INSTANCE Instance,

    IN PFILE_OBJECT FileObject OPTIONAL,

OUT PFLT_CALLBACK_DATA *RetNewCallbackData

);

 

VOID

FLTAPI

FltPerformSynchronousIo (

    IN PFLT_CALLBACK_DATA CallbackData

    );

 

NTSTATUS

FLTAPI

FltPerformAsynchronousIo (

    IN PFLT_CALLBACK_DATA CallbackData,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACK CallbackRoutine,

    IN PVOID CallbackContext

    );

 

要使用這些例程,一個(gè)微過濾器可以首先調(diào)用FltAllocateCallbackData來分配一個(gè) CallbackData.然 后對(duì)應(yīng)于不同的操作填寫合適的參數(shù)。之后即可調(diào)用FltPerformSynchronousIo()或者是 FltPerformAsynchronousIo()來實(shí)際發(fā)起I/O請(qǐng)求。參數(shù)Instance必須總是微過濾器發(fā)起此請(qǐng)求的實(shí)例。(譯者注:不能由 A實(shí)例分配而B實(shí)例來發(fā)起請(qǐng)求)。

 

此外過濾管理器導(dǎo)出了一些常用的實(shí)用例程,比如:

 

NTSTATUS

FLTAPI

FltCreateFile (

    IN PFLT_FILTER Filter,

    IN PFLT_INSTANCE Instance OPTIONAL,

    OUT PHANDLE   FileHandle,

    IN ACCESS_MASK DesiredAccess,

    IN POBJECT_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參數(shù)被忽略(譯者注:指定為空.),那么CREATE請(qǐng)求會(huì)被發(fā)送到微過濾器棧的頂端(這導(dǎo)致本微過濾器會(huì)回環(huán)的看到自己發(fā)送的請(qǐng)求。)除非絕對(duì)必要,這是不明智的。如果被濫用,很容易導(dǎo)致死鎖和棧溢出.

 

如果指定了這個(gè)參數(shù)(應(yīng)該總是你自己當(dāng)前的instance),那么僅僅向下發(fā)起此請(qǐng)求。所有的前面的調(diào)用此api的微過濾器之上的微過濾器(包括自己)都不會(huì)收到此請(qǐng)求.

 

FileHandle參數(shù)返回一個(gè)供Zw*系列函數(shù)調(diào)用的文件句柄.如果先前指定的Instance不為空,那么保證關(guān)于這個(gè)文件句柄的其他未來的I/O操作(通過Zw接口,FltClose(),等),都只能被這個(gè)發(fā)起Instance下面的Instance看到。

 

FltReadFile()和FltWriteFile()發(fā)起的I/O讀寫請(qǐng)求也只有下層實(shí)例才能看見。用于我們只有FileObject而沒有文件句柄的時(shí)候。這些例程類似以前舊的過濾模型中自己發(fā)送IRP的讀寫方式.

 

重要提示:過濾器不需要使用FltReadFile()/FltwriteFile()來對(duì)一個(gè)FltCreateFile返回的文件句柄發(fā)起一個(gè)I/O請(qǐng)求.對(duì)于這種情況,使用Zw*()接口就可以發(fā)送到合適的實(shí)例上去。

 

NTSTATUS

FLTAPI

FltReadFile (

    IN PFLT_INSTANCE InitiatingInstance,

    IN PFILE_OBJECT FileObject,

    IN PLARGE_INTEGER ByteOffset OPTIONAL,

    IN ULONG Length,

    OUT PVOID Buffer,

    IN FLT_IO_OPERATION_FLAGS Flags,

    OUT PULONG BytesRead OPTIONAL,

    IN PFLT_COMPLETED_ASYNC_IO_CALLBACK CallbackRoutine OPTIONAL,

    IN PVOID CallbackContext 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_CALLBACK CallbackRoutine OPTIONAL,

    IN PVOID CallbackContext OPTIONAL

);

 

微過濾器發(fā)出I/O可能為同步也可能為異步.當(dāng)I/O被指定為異步,微過濾器提供一個(gè)回調(diào)例程.當(dāng)系統(tǒng)完成了I/O請(qǐng)求回調(diào)例程會(huì)被調(diào)用.

 

13 卸載/注銷/解除綁定的規(guī)則

 

解除綁定意味著一個(gè)微過濾實(shí)例將被銷毀.這個(gè)微過濾器不在會(huì)因?yàn)槿魏螌?duì)卷的操作而被調(diào)用(當(dāng)然除非還有別的實(shí)例綁定在這個(gè)卷上).

 

卸載一個(gè)微過濾器意味著它的代碼將不在存在于內(nèi)存中。這往往在系統(tǒng)關(guān)閉的時(shí)候發(fā)生?;蛘呤且粋€(gè)新版本的微過濾器在不關(guān)閉系統(tǒng)的情況下安裝了(譯者注:那么這時(shí)舊版本的微過濾器被卸載了。)

 

一 個(gè)微過濾器可以自己把自己從一個(gè)卷解除綁定(調(diào)用FltDetachVolume),不過更通常的情況是在用戶界面上解除的。一個(gè)微過濾器即使是有未完成 的I/O請(qǐng)求的時(shí)候,依然可以解除綁定.此時(shí),微過濾器的完成例程會(huì)被調(diào)用,而且所有的未完成的I/O操作都帶有標(biāo)記 FLT_COMPLETION_DETACHED.當(dāng)這些操作以后實(shí)際完成時(shí),微過濾器就不會(huì)再收到這些完成回調(diào)了。

 

當(dāng)一個(gè)微過濾器實(shí)例被解除綁定的時(shí)候,系統(tǒng)回調(diào)用這個(gè)微過濾器的所有的沒有清除的上下文的釋放例程,包括文件,流,流文件對(duì)象等和這個(gè)實(shí)例相關(guān)的對(duì)象。

 

14. 支持例程

 

除了已經(jīng)討論過的接口之外,過濾管理器提供了一組支持例程來幫助微過濾器完成他需要的工作。這里列出一部分附加的例程。請(qǐng)查閱過濾管理器IFS文檔來獲得這些例程的更多信息:

對(duì)象,名字轉(zhuǎn)換:

FltGetFilterFromName()

FltGetVolumeFromName()

FltGetVolumeInstanceFromName()

卷,實(shí)例,設(shè)備對(duì)象轉(zhuǎn)換歷程:

FltGetVolumeFromInstance(), FltGetFilterFromInstance()

FltGetVolumeFromDeviceObject()

FltGetDeviceObject()

FltGetDiskDeviceObject()

獲取對(duì)象信息例程:

FltGetVolumeProperties()

FltIsVolumeWriteable

FltQueryVolumeInformation(), FltSetVolumeInformation()

FltGetInstanceInformation()

FltGetFilterInformation()

枚舉例程:

FltEnumerateFilters()

FltEnumerateVolumes()

FltEnumerateInstances()

FltEnumerateFilterInformation()

FltEnumerateInstanceInformationByFilter()

FltEnumerateInstanceInformationByVolume()

FltEnumerateVolumeInformation()

Oplock例程:

FltInitializeOplock()

FltUninitializeOplock()

FltOplockFsctrl()

FltCheckOplock()

FltOplockIsFastIoPossible()

FltCurrentBatchOplock()

目錄改變通知例程:

   (譯者注:目錄改變通知在文件系統(tǒng)中的意義是當(dāng)目錄改變后,通知操作系統(tǒng),使操作系統(tǒng)可以在界面上做出一些改變,比如顯示的目錄結(jié)構(gòu)變化等等,專門有一種IRP可以干這個(gè)事情。)    FltNotifyFilterChangeDirectory()

其他: FltGetRequestorProcess(), FltGetRequestorProcessId()

 

15.構(gòu)建一個(gè)微過濾器

 

構(gòu)建一個(gè)微過濾器應(yīng)用所需要的所有的東西都可以在過濾管理器IFS開發(fā)包中找到。這包括:

1.用來構(gòu)建一個(gè)微過濾器和一個(gè)使用了過濾管理器接口的用戶態(tài)應(yīng)用程序的完整的構(gòu)建環(huán)境。

2.所有的在一臺(tái)機(jī)器上安裝過濾管理器組件用于開發(fā)的安裝包。當(dāng)然如果以后的windows版本內(nèi)部包含了過濾管理器組件,那么就沒有必要了。

3.微過濾器示例的代碼。

所有的微過濾器包含頭文件FltKernel.h,而且連接FltMgr.lib.而應(yīng)用程序應(yīng)該包含頭文件FltUser.h,并連接庫(kù)FltLib.lib。

本文來自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/celestialwy/archive/2006/04/27/694044.aspx

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    精品日韩视频在线观看| 在线视频免费看你懂的| 日韩精品视频香蕉视频| 亚洲高清亚洲欧美一区二区| 国产精品免费视频专区| 91人妻人人做人碰人人九色| 国语对白刺激高潮在线视频| 成人精品视频在线观看不卡| 麻豆印象传媒在线观看| 欧美人妻免费一区二区三区| 视频一区二区黄色线观看| 熟女中文字幕一区二区三区| 精品人妻一区二区三区在线看| 日韩成人h视频在线观看 | 国产一区二区三区丝袜不卡 | 成人免费观看视频免费| 91超频在线视频中文字幕| 亚洲日本加勒比在线播放 | 亚洲天堂久久精品成人| 日韩成人免费性生活视频| 人妻内射在线二区一区| 亚洲综合激情另类专区老铁性| 五月天六月激情联盟网| 神马午夜福利一区二区| 午夜福利黄片免费观看| 黑人巨大精品欧美一区二区区 | 在线观看免费无遮挡大尺度视频 | 日韩在线欧美一区二区| 国产精品一区二区丝袜| 91插插插外国一区二区婷婷| 一二区中文字幕在线观看| 亚洲第一区二区三区女厕偷拍| 麻豆精品视频一二三区| 欧美成人黄色一级视频| 91亚洲人人在字幕国产| 福利一区二区视频在线| 亚洲精品欧美精品一区三区| 久久精品国产亚洲av麻豆尤物 | 免费高清欧美一区二区视频| 日韩国产精品激情一区| 黄片在线免费观看全集|