1. 程式人生 > >整理一份我對Windows檔案系統過濾驅動的sFilter工程程式碼的詳細說明(精華僑)

整理一份我對Windows檔案系統過濾驅動的sFilter工程程式碼的詳細說明(精華僑)

標 題: 【分享】整理一份我對Windows檔案系統過濾驅動的sFilter工程程式碼的詳細說明
作 者: tianhz
時 間: 2012-06-19,18:32:07
鏈 接: http://bbs.pediy.com/showthread.php?t=152338

我平時很忙,很少發表主題。我在工作的時候,我身邊的很多同事都不停地問我有關Windows檔案系統過濾驅動的問題。他們中有很多人去學習了WDK提供的MiniFilter框架,並使用MiniFilter框架來開發過濾驅動產品。我問他們,他們總是說:MiniFilter簡單易學,sFilter難度很大不好學。我深究其根本原因,得到的答案都是說:使用MiniFilter框架來程式設計不必關心對IRP的處理,也不必關心那些令人厭煩的卷繫結,而sFilter需要關心對IRP的處理,還要關心卷的繫結,還要關心FastIo。因此很多人不願意去使用sFilter來開發驅動程式。


 我想說的是:sFilter是檔案過濾驅動的根本,很多知識還是很有用的。我們不必口舌之爭來辯論到底是sFilter好,還是MiniFilter好。

 廢話不多說了,我想總結一下對sFilter的程式碼理解。 我按照一貫作風,我必須把程式碼全部粘貼出來,我在程式碼裡面寫了很多的註釋。當然了,很多東西都有參考一些前輩的了。

首先是標頭檔案sFilter.h的程式碼註解了。大家請看:


#include "ntifs.h"
#include "ntdddisk.h"

#pragma warning(error:4100)        //使能這兩個錯誤碼(當形參錯誤時發出警告)

#pragma warning(error:4101)        //當局部變數錯誤時發出警告

//============================== 條件編譯 ============================
#ifndef Add2Ptr
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))          //語法: PVOID  Add2Ptr(PUCHAR p,PUCHAR i);  含義:  連線兩個字串
#endif
//================ 條件編譯(當OS版本是Win2000時編譯下段程式碼) ===================

#if WINVER == 0x0500

#ifndef FlagOn  //當FlagOn未被#define定義過,編譯下一句
#define FlagOn(_F,_SF)  ((_F) & (_SF))                  //語法: FiagOn(a,b);  含義: a&b(a和b按位與操作)
#endif

#ifndef BooleanFlagOn
#define BooleanFlagOn(F,SF)  ((BOOLEAN)(((F) & (SF)) != 0))  //語法: BooleanFlagOn(a,b); 含義: a&b !=0
#endif

#ifndef SetFlag
#define SetFlag(_F,_SF)  ((_F) |= (_SF))                  //語法: SetFlag(a,b);  含義: a |= b(a和b按位或操作,結果存入a)
#endif

#ifndef ClearFlag  
#define ClearFlag(_F,_SF)  ((_F) &= ~(_SF))              //語法: ClearFlag(a,b);  含義: a &= ~b(a和b非按位與操作,結果存入a)
#endif

#ifndef min
#define min(a,b)  (((a) < (b)) ? (a) : (b))                //語法: min(a,b); 含義: 返回a和b中的小者
#endif

#ifndef max
#define max(a,b)  (((a) > (b)) ? (a) : (b))                //語法: max(a,b); 含義: 返回a和b中的大者
#endif

#ifdef ASSERT
#undef ASSERT
#if DBG
#define ASSERT( exp ) ((!(exp)) ? (RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : TRUE)
#else
#define ASSERT( exp ) ((void) 0)
#endif
#endif        

#define ExFreePoolWithTag( a, b )  ExFreePool( (a) )        //可看出,ExFreePoolWithTag是一個巨集定義,實際上就是ExFreePool函式

#endif


//=================== 條件編譯(WinXP及以上OS時編譯下段程式碼) ====================
#if WINVER >= 0x0501

typedef  NTSTATUS (*PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS) ( IN PDRIVER_OBJECT DriverObject, IN PFS_FILTER_CALLBACKS Callbacks );
typedef  NTSTATUS (*PSF_ENUMERATE_DEVICE_OBJECT_LIST) ( IN  PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT *DeviceObjectList, IN ULONG DeviceObjectListSize, OUT PULONG ActualNumberDeviceObjects );
typedef  NTSTATUS (*PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE) ( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice, OUT PDEVICE_OBJECT *AttachedToDeviceObject );
typedef  NTSTATUS (*PSF_GET_DISK_DEVICE_OBJECT) ( IN PDEVICE_OBJECT FileSystemDeviceObject, OUT PDEVICE_OBJECT *DiskDeviceObject );
typedef  NTSTATUS (*PSF_GET_VERSION) ( IN OUT PRTL_OSVERSIONINFOW VersionInformation );

typedef  PDEVICE_OBJECT (*PSF_GET_LOWER_DEVICE_OBJECT) ( IN PDEVICE_OBJECT  DeviceObject );
typedef  PDEVICE_OBJECT (*PSF_GET_DEVICE_ATTACHMENT_BASE_REF) ( IN PDEVICE_OBJECT DeviceObject );
typedef  PDEVICE_OBJECT (*PSF_GET_ATTACHED_DEVICE_REFERENCE) ( IN PDEVICE_OBJECT DeviceObject );

#define IS_WINDOWS2000() ((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 0))
#define IS_WINDOWSXP() ((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 1))
#define IS_WINDOWSXP_OR_LATER() (((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 1)) || (gSfOsMajorVersion > 5))
#define IS_WINDOWSSRV2003_OR_LATER() (((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 2)) || (gSfOsMajorVersion > 5))

typedef struct _SF_DYNAMIC_FUNCTION_POINTERS {
    PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS RegisterFileSystemFilterCallbacks;  
    PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE AttachDeviceToDeviceStackSafe;      
    PSF_ENUMERATE_DEVICE_OBJECT_LIST EnumerateDeviceObjectList;              
    PSF_GET_LOWER_DEVICE_OBJECT GetLowerDeviceObject;                    
    PSF_GET_DEVICE_ATTACHMENT_BASE_REF GetDeviceAttachmentBaseRef;          
    PSF_GET_DISK_DEVICE_OBJECT GetDiskDeviceObject;                        
    PSF_GET_ATTACHED_DEVICE_REFERENCE GetAttachedDeviceReference;            
    PSF_GET_VERSION GetVersion;                                        
} SF_DYNAMIC_FUNCTION_POINTERS, *PSF_DYNAMIC_FUNCTION_POINTERS;

SF_DYNAMIC_FUNCTION_POINTERS gSfDynamicFunctions = {0};  //定義該結構變數並初始化為0

ULONG gSfOsMajorVersion = 0;        //作業系統主版本號
ULONG gSfOsMinorVersion = 0;        //作業系統副版本號

#endif


#define MAX_DEVNAME_LENGTH 64        //定義常量值
#define DEVOBJ_LIST_SIZE 64
#define SFLT_POOL_TAG   'tlFS'        //記憶體塊標籤
ULONG SfDebug = 0;

#define DELAY_ONE_MICROSECOND   (-10)
#define DELAY_ONE_MILLISECOND   (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND        (DELAY_ONE_MILLISECOND*1000)


// 巨集定義: IS_MY_DEVICE_OBJECT(指向裝置物件的指標); 意義: (指標≠NULL)且(裝置物件的DriverObject是gSFilterDriverObject)且(裝置物件的DeviceExtension≠NULL)
#define IS_MY_DEVICE_OBJECT(_devObj)  (((_devObj) != NULL) && ((_devObj)->DriverObject == gSFilterDriverObject) && ((_devObj)->DeviceExtension != NULL))


// 巨集定義: 測試是不是我的"控制裝置物件"
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj)  (((_devObj) == gSFilterControlDeviceObject) ? (ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && ((_devObj)->DeviceExtension == NULL)), TRUE) : FALSE)


// 巨集定義: 測試是不是所需要的"裝置型別"
#define IS_DESIRED_DEVICE_TYPE(_type)  (((_type) == FILE_DEVICE_DISK_FILE_SYSTEM) || ((_type) == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || ((_type) == FILE_DEVICE_NETWORK_FILE_SYSTEM))


// 巨集定義: 測試FAST_IO_DISPATCH中的處理函式合法
#define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName)  (((_FastIoDispatchPtr) != NULL) && (((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= (FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && ((_FastIoDispatchPtr)->_FieldName != NULL))


// 巨集定義: 
#define SF_LOG_PRINT( _dbgLevel, _string )  (FlagOn(SfDebug,(_dbgLevel)) ? DbgPrint _string : ((void)0))

#define SFDEBUG_DISPLAY_ATTACHMENT_NAMES  0x00000001    //display names of device objects we attach to
#define SFDEBUG_DISPLAY_CREATE_NAMES  0x00000002        //get and display names during create
#define SFDEBUG_GET_CREATE_NAMES  0x00000004          //get name (don't display) during create
#define SFDEBUG_DO_CREATE_COMPLETION  0x00000008      //do create completion routine, don't get names
#define SFDEBUG_ATTACH_TO_FSRECOGNIZER  0x00000010      //do attach to FSRecognizer device objects
#define SFDEBUG_ATTACH_TO_SHADOW_COPIES  0x00000020    //do attach to ShadowCopy Volume device objects -- they are only around on Windows XP and later

#define GET_DEVICE_TYPE_NAME( _type ) ((((_type) > 0) && ((_type) < (sizeof(DeviceTypeNames) / sizeof(PCHAR)))) ? DeviceTypeNames[ (_type) ] : "[Unknown]")



typedef struct _SFILTER_DEVICE_EXTENSION {
  PDEVICE_OBJECT AttachedToDeviceObject;          //繫結的檔案系統裝置
  PDEVICE_OBJECT StorageStackDeviceObject;        //與檔案系統裝置相關的真實裝置(磁碟) 
  UNICODE_STRING DeviceName;                //如果綁定了一個卷,這是物理磁碟卷名;否則,為繫結的控制裝置名。
  WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];        //用來儲存名字串的緩衝區
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;

typedef struct _FSCTRL_COMPLETION_CONTEXT {
  WORK_QUEUE_ITEM WorkItem;                        
  PDEVICE_OBJECT DeviceObject;                      
  PIRP Irp;                                    
  PDEVICE_OBJECT NewDeviceObject;                    
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;

typedef struct _GET_NAME_CONTROL {
  PCHAR allocatedBuffer;                            
  CHAR smallBuffer[256];                            
} GET_NAME_CONTROL, *PGET_NAME_CONTROL;



//函式宣告 

NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );

#if DBG && WINVER >= 0x0501  //如果編譯除錯版本且OS是WinXP時編譯該函式,否則不編譯
VOID  DriverUnload( IN PDRIVER_OBJECT DriverObject );                  //驅動解除安裝函式
#endif

#if WINVER >= 0x0501        //如果編譯時的OS是WinXP時,編譯這兩個函式,否則不編譯
VOID  SfLoadDynamicFunctions ();                  
VOID  SfGetCurrentVersion ();                                                  
#endif

PUNICODE_STRING  SfGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl );
VOID  SfGetFileNameCleanup( IN OUT PGET_NAME_CONTROL NameControl );
NTSTATUS  SfPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS  SfCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp  );
NTSTATUS  SfCreateCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS  SfCleanupClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS  SfFsControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

相關推薦

整理Windows檔案系統過濾驅動sFilter工程程式碼詳細說明(華僑)

標 題: 【分享】整理一份我對Windows檔案系統過濾驅動的sFilter工程程式碼的詳細說明 作 者: tianhz 時 間: 2012-06-19,18:32:07 鏈 接: http://bbs.pediy.com/showthread.php?t=1523

Windows檔案系統過濾驅動中開啟檔案時如何避免重入

呼叫下面的函式可以避免在打開回調中開啟新的檔案的時候引起重入 NTSTATUS IoCreateFileSpecifyDeviceObjectHint( __out PHANDLE FileHandle, __in ACCESS_MASK Desir

檔案系統過濾驅動開發()—Win32底層開發小組

    宣告:本文無太多新意,只是介紹下學習經驗,大神級人物(如總監大人)請略過,謝謝合作>_<     吐槽一下:學驅動算起來也是從上學期9月份開始吧,之前在家買了<Windows驅動開發技術詳解>這本書,搭了個環境之後,其實也沒碰很多,編了個經典的Hello,World!之後就無

一個簡單的檔案系統過濾驅動框架

 很多人認為檔案系統過濾驅動很複雜,其實也有一定道理,因為需要有很多細節需要考慮到,這是一個簡單的檔案系統過濾驅動,拋去了大部分細節,留下了一個簡單的框架,其實這樣檔案系統過濾驅動就變得蠻簡單的,很多介面可以不用實現,只要知道大致流程,其它都將會很清晰。#define DBG

那葉輕靈輕咬銀牙旋即其腳尖一點不論牧塵

c11 ace caf adb 12c deb ntb ftl dbf http://baobao.baidu.com/article/b635e48a0628a03114f528e1a301166c.html?2017_10_04=ftf5=v9 http://baoba

gulp常用配置檔案,構建前端工作流

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

未來的看法

我似乎沒有認真的思考過未來的事情,因為我覺得所有的事情都是要一步一步來走的,我現在只走到了未來的前一步,我還沒有走向未來,所以一直以來也沒有思考過。 認識自己活著認清自己真的很難,喜歡什麼?或者不喜歡什麼?在意什麼?或者不在意什麼?人真的很複雜,複雜到不想過多的去考量。如果

java單繼承和多繼承的理解。

今天終於重拾書本,感覺好久好久沒有認真看過書了樣。好了不說廢話了。 偶是菜鳥,可能理解有誤。高手們指點指點哦。 今天看那書上說:java是但繼承,並不支援多繼承,後來又講到java支援多繼承,是在介面的基礎上實現多繼承。 總的來說還是不支援多繼承,要通過其他方式來彌補jav

整理拖拽排序自動儲存的程式碼,後臺是php

<style>     .tuozhuaitr{         cursor: pointer;     } </style> <table wid

tmpfs:種基於記憶體的檔案系統

tmpfs是一種基於記憶體的檔案系統, tmpfs有時候使用rm(實體記憶體),有時候使用swap(磁碟一塊區域)。根據實際情況進行分配。 rm:實體記憶體。real memery的簡稱? 真實記憶體就是電腦主機板上那塊記憶體條,叫做真實記憶體不為過。 swap:交換分割槽。是硬碟上一塊區域

本科計算機專業的認識

    新的一年開始了,我大學的所有課程也剛剛結束不久,想一寫篇文章談一談我對計算機專業的認識。博主學的專業是“電腦科學與技術”,今年大四,三年半的校園生活使我對計算機專業的認知一次又一次的改變;由於沒有一個好的“引路人”,自己總是摸索著前進,走了不少的彎路。剛上大學的時候

微軟正在Windows 10系統進行改造

微軟正在對Windows 10系統進行改造,至少視覺效果上看起來更加舒爽。 據外媒給出的報道稱,微軟悄然向Insider成員釋出了Windows 10 Mail和Calendar應用更新,其版本號是Version 16005.11029.20090.0,主要更新內容也是視覺上的改變。 從微軟公佈的

tmpfs臨時檔案系統,是種基於記憶體的檔案系統

在Linux系統記憶體中的虛擬磁碟對映,可以理解為使用實體記憶體當做磁碟,利用這種檔案系統,可以有效提高在高併發場景下的磁碟讀寫,但是重啟後資料會丟失。 1、檢視tmpfs路徑 (系統預設開啟,大小約為實體記憶體一半) 2、檢視實體記憶體利用情況  (-m  代表按照M統計) 3、調

Hadoop 《》,HDFS 分散式檔案系統

Hadoop-HDFS 儲存模型:位元組 -檔案線性切割成塊(Block):偏移量 offset -block分散儲存在叢集結點中 -單一檔案block大小一致,檔案與檔案可以不一致 -block可以設定副本數,副本無序分散在不同結點中 >副本數不要超過結點數量 -檔案上傳可以

檔案系統Minifilter驅動()

檔案系統Minifilter驅動 宣告: 本系列文章源於WDK,所有權利歸原作者所有,翻譯的目的只為交流和學習。 說明: 所有preoperation及postoperation均簡寫為pre-oper和post-oper 所有檔案系統過濾驅動均簡寫為FS

Windows檔案系統許可權

NTFS (New Technology File System),是 WindowsNT 環境的檔案系統。新技術檔案系統是Windows NT家族(如,Windows 2000、Windows XP、Windows Vista、Windows 7和 wi

gulp的配置檔案

參考: gulpfile.js如下: /** * Created by admin on 2016/12/3. */ /** * 元件安裝 * npm install gulp gulp-notify gulp-livereload gulp-sass

FAT12檔案系統的理解

於淵老師實驗用了兩個檔案系統,一個是前幾章用的FAT12檔案格式,還有一個是後面他自己設計的一個簡單的orange‘s檔案系統。     對於檔案系統的作用,我想可以分成兩個方面去理解。一個是像我們這次實驗用到的檔案系統,非常簡單直接,是直接屬於核心的一部分用來和磁碟驅動打

dubbo的理解

一:什麼是dubbo? dubbo是阿里巴巴的一種開源分散式服務框架,是面向服務的,顧名思義就是提供服務。我們通常將一些專案中相同的邏輯抽離出來,封裝成通用的service,然後根據不同的邏輯功能部署到不同的伺服器上,然後我們在內網可以遠端呼叫伺服器上的service提供的

無法刪除 NTFS 盤上的文件或文件夾(Windows文件的各種情況有比較詳細的描述)

將在 binding 新的 資源管理器 操作權限 損壞 windows 導致 port 簡介 本文介紹您可能無法刪除 NTFS 文件系統卷上的文件或文件夾的原因,以及如何分析造成此問題的不同原因從而解決此問題。