前面寫了安裝功能驅動,過濾驅動,本篇談談調整過濾驅動的位置。裝置棧上總線驅動和功能驅動的數量比較固定,但過濾驅動就不一樣了,可以不斷的往裝置棧上疊加。如果僅僅像壘書本一樣,往現有堆棧頂添加過濾驅動使得裝置棧的深度不斷增加,倒也簡單。但如果要調整一下過濾驅動的位置,比如從最頂端移到較低的位置,那該怎麼做?本篇的寫作目的就是回答這個疑問。
仍然以toaster的過濾驅動為例(不要質問我為什麼老拿它開刀,因為其他的我也不會
)。我為toaster添加了2個類下層過濾驅動:将clslower.sys一式兩份,取名為clslower.sys和clslower1.sys。同時修改clafilter用以添加這對雙胞胎:
下列為clslower.sys的inf檔案clslower.inf
[Version]
signature = "$Windows NT$"
[SourceDisksNames]
1 = %ClasFilt.MediaDesc%
[SourceDisksFiles]
clslower.sys = 1
[DestinationDirs]
DefaultDestDir = 12 ; DIRID_DRIVERS
[DefaultInstall.NT]
CopyFiles = @clslower.sys
AddReg = ClassFilter_AddReg
[ClassFilter_AddReg]
HKLM, System\CurrentControlSet\Control\Class\{b85b7c50-6a01-11d2-b841-00c04fad5171}, LowerFilters, 0x00010008, clasfilt0
[DefaultInstall.NT.Services]
AddService = clasfilt0, , clasfilt_Service_Inst
[clasfilt_Service_Inst]
DisplayName = %ClasFilt.SvcDesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_IGNORE%
ServiceBinary = %12%\clslower.sys
[Strings]
ClasFilt.SvcDesc = "Lower Class 0 Filter Driver"
ClasFilt.MediaDesc = "Class Filter 0 Driver Disc"
SERVICE_KERNEL_DRIVER = 1
SERVICE_DEMAND_START = 3
SERVICE_ERROR_IGNORE = 0
REG_EXPAND_SZ = 0x00020000
REG_DWORD = 0x00010001
<pre name="code" class="cpp">下列為clslower1.sys的inf檔案clslower1.inf
[Version]
signature = "$Windows NT$"
[SourceDisksNames]
1 = %ClasFilt.MediaDesc%
[SourceDisksFiles]
clslower1.sys = 1
[DestinationDirs]
DefaultDestDir = 12 ; DIRID_DRIVERS
[DefaultInstall.NT]
CopyFiles = @clslower1.sys
AddReg = ClassFilter_AddReg
[ClassFilter_AddReg]
HKLM, System\CurrentControlSet\Control\Class\{b85b7c50-6a01-11d2-b841-00c04fad5171}, LowerFilters, 0x00010008, clasfilt
[DefaultInstall.NT.Services]
AddService = clasfilt, , clasfilt_Service_Inst
[clasfilt_Service_Inst]
DisplayName = %ClasFilt.SvcDesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_IGNORE%
ServiceBinary = %12%\clslower1.sys
[Strings]
ClasFilt.SvcDesc = "Lower Class Filter Driver"
ClasFilt.MediaDesc = "Class Filter Driver Disc"
SERVICE_KERNEL_DRIVER = 1
SERVICE_DEMAND_START = 3
SERVICE_ERROR_IGNORE = 0
REG_EXPAND_SZ = 0x00020000
REG_DWORD = 0x00010001
右鍵安裝這兩個類過濾驅動後,可以看到如下結果:

系統資料庫LowerFilter項顯示toaster類裝置有兩個類下層驅動;裝置管理器大概也是從系統資料庫讀取資訊,是以有同樣的值。用windbg檢視toaster裝置棧:
kd> !drvobj toaster ;參看toaster驅動對象資訊
Driver object (fffffa80051dbe70) is for:
\Driver\toaster
Driver Extension List: (id , addr)
Device Object list:
fffffa8005a56bb0 fffffa80051dccc0
kd> !devstack fffffa8005a56bb0 ;toaster裝置對象的裝置棧資訊
!DevObj !DrvObj !DevExt ObjectName
> fffffa8005a56bb0 \Driver\toaster fffffa8005a56d00 -->toaster功能裝置
fffffa80059ce8c0 \Driver\clasfilt0 fffffa80059cea10 -->類過濾驅動
fffffa8003e7a460 \Driver\clasfilt fffffa8003e7a5b0 -->類過濾驅動
fffffa8003dfb080 \Driver\busenum fffffa8003dfb1d0 000000b6
!DevNode fffffa8004b2e9d0 :
DeviceInst is "{B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster\1&79f5d87&0&01"
ServiceName is "toaster"
windbg羅列了toaster裝置棧的堆疊情況,從結果來看classfilter0堆疊在clasfilter之上。如果你看過前一篇文章,可能記得
删除驅動時會調用GetFilters,GetFilters通過GetDeviceRegistryProperty函數從系統資料庫中獲得過濾驅動的資訊,傳回的結果是一個字元串數組。對于這裡的情況,字元串數組的内容應該包括clasfilt和clasfilt0兩個字元串。移除驅動的時候,是把其中一個字元串從字元串數組中移除,然後再調用SetDeviceRegistryProperty把結果寫回系統資料庫。受此啟發,你可能會想到,可以直接在系統資料庫中調整兩個字元串的位置,到達調整驅動位置的目的。為此,我們來驗證這個猜想的正确性。
驗證的步驟如下:首先停用裝置然後修改系統資料庫LowerFilter,最後啟用裝置用windbg檢視裝置棧:
kd> !drvobj toaster
Driver object (fffffa80051dbe70) is for:
\Driver\toaster
Driver Extension List: (id , addr)
Device Object list:
fffffa8005a12cc0 fffffa80051dccc0
kd> !devstack fffffa8005a12cc0
!DevObj !DrvObj !DevExt ObjectName
> fffffa8005a12cc0 \Driver\toaster fffffa8005a12e10
<span style="color:#ff0000;"> fffffa8003fc7600 \Driver\clasfilt fffffa8003fc7750
fffffa800408b040 \Driver\clasfilt0 fffffa800408b190 </span>
fffffa8003dfb080 \Driver\busenum fffffa8003dfb1d0 000000b6
!DevNode fffffa8004b2e9d0 :
DeviceInst is "{B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster\1&79f5d87&0&01"
ServiceName is "toaster"