文件系统过滤驱动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)§ + (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, FILELINE, 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_MICROSECOND1000)

#define DELAY_ONE_SECOND        (DELAY_ONE_MILLISECOND1000)





// 宏定义: 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 );

NTSTATUS  SfFsControlMountVolume( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUS  SfFsControlMountVolumeComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT NewDeviceObject );

NTSTATUS  SfFsControlLoadFileSystem( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUS  SfFsControlLoadFileSystemComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUS  SfFsControlCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );

BOOLEAN  SfFastIoCheckIfPossible( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN BOOLEAN CheckForReadOperation, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoRead(IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoQueryStandardInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoLock( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoUnlockSingle( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoUnlockAll( IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoUnlockAllByKey( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoDeviceControl( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoQueryNetworkOpenInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoMdlRead( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoMdlReadComplete( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoPrepareMdlWrite( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoMdlWriteComplete( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoReadCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, OUT PVOID Buffer, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, OUT struct _COMPRESSED_DATA_INFO *CompressedDataInfo, IN ULONG CompressedDataInfoLength, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoWriteCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN ULONG LockKey, IN PVOID Buffer, OUT PMDL *MdlChain, OUT PIO_STATUS_BLOCK IoStatus, IN struct _COMPRESSED_DATA_INFO *CompressedDataInfo, IN ULONG CompressedDataInfoLength, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoMdlReadCompleteCompressed( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoMdlWriteCompleteCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEAN  SfFastIoQueryOpen( IN PIRP Irp, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, IN PDEVICE_OBJECT DeviceObject );

VOID  SfFsControlLoadFileSystemCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context );

VOID  SfFsControlMountVolumeCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context );

VOID  SfFastIoDetachDevice( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice );



#if WINVER >= 0x0501

NTSTATUS  SfPreFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, OUT PVOID CompletionContext );

VOID  SfPostFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, IN NTSTATUS OperationStatus, IN PVOID CompletionContext );

#endif



NTSTATUS  SfAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice, IN OUT PDEVICE_OBJECT AttachedToDeviceObject );

NTSTATUS  SfAttachToFileSystemDevice( IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING DeviceName );

NTSTATUS  SfAttachToMountedDevice( IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT SFilterDeviceObject );

VOID  SfFsNotification( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FsActive );

VOID  SfDetachFromFileSystemDevice( IN PDEVICE_OBJECT DeviceObject );

VOID  SfCleanupMountedDevice( IN PDEVICE_OBJECT DeviceObject );



#if WINVER >= 0x0501

NTSTATUS  SfEnumerateFileSystemVolumes( IN PDEVICE_OBJECT FSDeviceObject, IN PUNICODE_STRING FSName );

#endif



VOID  SfGetObjectName( IN PVOID Object, IN OUT PUNICODE_STRING Name );

VOID  SfGetBaseDeviceObjectName( IN PDEVICE_OBJECT DeviceObject, IN OUT PUNICODE_STRING DeviceName );

VOID  SfReadDriverParameters( IN PUNICODE_STRING RegistryPath );

BOOLEAN  SfIsAttachedToDevice( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT AttachedDeviceObject OPTIONAL );

BOOLEAN  SfIsAttachedToDeviceW2K( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT AttachedDeviceObject OPTIONAL );

BOOLEAN  SfIsAttachedToDeviceWXPAndLater( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT AttachedDeviceObject OPTIONAL );

NTSTATUS  SfIsShadowCopyVolume( IN PDEVICE_OBJECT StorageStackDeviceObject, OUT PBOOLEAN IsShadowCopy );



/



接下来是sFilter.c的程序代码了。

我希望大家能够注意几个忽略的地方:

(1) ShadowCopyVolume—也就是卷影。

(2) FastIo函数。

(3) 文件系统控制设备对象的绑定。

(4) 文件系统卷设备的绑定。

(5) SfCreate函数的一个小细节。



我看过楚狂人写的<<寒江独钓Windows内核安全编程>>这本书。这本书的第7章讲了sFilter,但是这本书没有把Windows很重要一个系统服务说清楚。就是我上面所的卷影。



sFilter.c的所有代码如下:







#include “sfilter.h”





//指定每个函数的内存页面属性

#ifdef ALLOC_PRAGMA

#pragma alloc_text(INIT, DriverEntry)



#if DBG && WINVER >= 0x0501

#pragma alloc_text(PAGE, DriverUnload)

#endif



#pragma alloc_text(INIT, SfReadDriverParameters)

#pragma alloc_text(PAGE, SfFsNotification)

#pragma alloc_text(PAGE, SfCreate)

#pragma alloc_text(PAGE, SfCleanupClose)

#pragma alloc_text(PAGE, SfFsControl)

#pragma alloc_text(PAGE, SfFsControlMountVolume)

#pragma alloc_text(PAGE, SfFsControlMountVolumeComplete)

#pragma alloc_text(PAGE, SfFsControlLoadFileSystem)

#pragma alloc_text(PAGE, SfFsControlLoadFileSystemComplete)

#pragma alloc_text(PAGE, SfFastIoCheckIfPossible)

#pragma alloc_text(PAGE, SfFastIoRead)

#pragma alloc_text(PAGE, SfFastIoWrite)

#pragma alloc_text(PAGE, SfFastIoQueryBasicInfo)

#pragma alloc_text(PAGE, SfFastIoQueryStandardInfo)

#pragma alloc_text(PAGE, SfFastIoLock)

#pragma alloc_text(PAGE, SfFastIoUnlockSingle)

#pragma alloc_text(PAGE, SfFastIoUnlockAll)

#pragma alloc_text(PAGE, SfFastIoUnlockAllByKey)

#pragma alloc_text(PAGE, SfFastIoDeviceControl)

#pragma alloc_text(PAGE, SfFastIoDetachDevice)

#pragma alloc_text(PAGE, SfFastIoQueryNetworkOpenInfo)

#pragma alloc_text(PAGE, SfFastIoMdlRead)

#pragma alloc_text(PAGE, SfFastIoPrepareMdlWrite)

#pragma alloc_text(PAGE, SfFastIoMdlWriteComplete)

#pragma alloc_text(PAGE, SfFastIoReadCompressed)

#pragma alloc_text(PAGE, SfFastIoWriteCompressed)

#pragma alloc_text(PAGE, SfFastIoQueryOpen)

#pragma alloc_text(PAGE, SfAttachDeviceToDeviceStack)

#pragma alloc_text(PAGE, SfAttachToFileSystemDevice)

#pragma alloc_text(PAGE, SfDetachFromFileSystemDevice)

#pragma alloc_text(PAGE, SfAttachToMountedDevice)

#pragma alloc_text(PAGE, SfIsAttachedToDevice)

#pragma alloc_text(PAGE, SfIsAttachedToDeviceW2K)

#pragma alloc_text(PAGE, SfIsShadowCopyVolume)



#if WINVER >= 0x0501

#pragma alloc_text(INIT, SfLoadDynamicFunctions)

#pragma alloc_text(INIT, SfGetCurrentVersion)

#pragma alloc_text(PAGE, SfEnumerateFileSystemVolumes)

#pragma alloc_text(PAGE, SfIsAttachedToDeviceWXPAndLater)

#endif



#endif





PDRIVER_OBJECT gSFilterDriverObject = NULL;        //保存由/O管理器生成并传入的驱动对象

PDEVICE_OBJECT gSFilterControlDeviceObject = NULL;    //保存由本过滤驱动生成的控制设备对象

FAST_MUTEX gSfilterAttachLock;              //定义一个快速互斥结构变量(对象)







static const PCHAR DeviceTypeNames[] = {

    “”,

    “BEEP”,

    “CD_ROM”,

    “CD_ROM_FILE_SYSTEM”,

    “CONTROLLER”,

    “DATALINK”,

    “DFS”,

    “DISK”,

    “DISK_FILE_SYSTEM”,

    “FILE_SYSTEM”,

    “INPORT_PORT”,

    “KEYBOARD”,

    “MAILSLOT”,

    “MIDI_IN”,

    “MIDI_OUT”,

    “MOUSE”,

    “MULTI_UNC_PROVIDER”,

    “NAMED_PIPE”,

    “NETWORK”,

    “NETWORK_BROWSER”,

    “NETWORK_FILE_SYSTEM”,

    “NULL”,

    “PARALLEL_PORT”,

    “PHYSICAL_NETCARD”,

    “PRINTER”,

    “SCANNER”,

    “SERIAL_MOUSE_PORT”,

    “SERIAL_PORT”,

    “SCREEN”,

    “SOUND”,

    “STREAMS”,

    “TAPE”,

    “TAPE_FILE_SYSTEM”,

    “TRANSPORT”,

    “UNKNOWN”,

    “VIDEO”,

    “VIRTUAL_DISK”,

    “WAVE_IN”,

    “WAVE_OUT”,

    “8042_PORT”,

    “NETWORK_REDIRECTOR”,

    “BATTERY”,

    “BUS_EXTENDER”,

    “MODEM”,

    “VDM”,

    “MASS_STORAGE”,

    “SMB”,

    “KS”,

    “CHANGER”,

    “SMARTCARD”,

    “ACPI”,

    “DVD”,

    “FULLSCREEN_VIDEO”,

    “DFS_FILE_SYSTEM”,

    “DFS_VOLUME”,

    “SERENUM”,

    “TERMSRV”,

    “KSEC”

};







NTSTATUS  DriverEntry(IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath )

{

    PFAST_IO_DISPATCH fastIoDispatch;  //定义FAST_IO_DISPATCH结构变量

    UNICODE_STRING nameString;      //定义名字串结构变量

    NTSTATUS status;          //状态码

    ULONG i;



#if WINVER >= 0x0501    //条件编译,如果OS版本是WinXP以上,编译这两句,否则不编译

    SfLoadDynamicFunctions();                              

    SfGetCurrentVersion();                                  

#endif                                        



    SfReadDriverParameters( RegistryPath );                        

    gSFilterDriverObject = DriverObject;  //将I/O管理器传入的驱动对象保存到全局变量gSFilterDriverObject中





#if DBG && WINVER >= 0x0501          //若OS版本是xp以上且生成checked版,编译这些语句,否则不编译

    if (NULL != gSfDynamicFunctions.EnumerateDeviceObjectList)

  {

    gSFilterDriverObject->DriverUnload = DriverUnload;        //注册驱动卸载函数

  }

#endif                                              



  ExInitializeFastMutex( &gSfilterAttachLock );        //初始化"FastMutex(快速互斥)“对象,以后多线程只能互斥访问它







  //创建控制设备名称

  RtlInitUnicodeString( &nameString, L”\FileSystem\Filters\SFilter" );    //用来创建文件系统控制设备对象



  //创建控制设备对象

    status = IoCreateDevice( DriverObject,

                0,                        //没有 设备扩展 

                &nameString,                  //设备名:   FileSystem\Filters\SFilter

                FILE_DEVICE_DISK_FILE_SYSTEM,          //设备类型: 磁盘文件系统

                FILE_DEVICE_SECURE_OPEN,            //设备特征: 对发送到CDO的打开请求进行安全检查

                FALSE,                      //生成一个在用户模式下使用的设备

                &gSFilterControlDeviceObject );          //接收生成的"控制设备对象"



  if (status == STATUS_OBJECT_PATH_NOT_FOUND)                //判断是否 未找到路径

  {

    RtlInitUnicodeString( &nameString, L"\FileSystem\SFilterCDO" );    //重新创建 控制设备名称 

    status = IoCreateDevice( DriverObject, 0,

                &nameString,                      //设备名: FileSystem\SFilterCDO

                FILE_DEVICE_DISK_FILE_SYSTEM,

                FILE_DEVICE_SECURE_OPEN,

                FALSE,

                &gSFilterControlDeviceObject );              //接收生成的 控制设备对象 

  }

  if (!NT_SUCCESS( status ))                              //判断IoCreateDevice调用是否成功

  {

    KdPrint(( “SFilter!DriverEntry: Error creating control device object “%wZ”, status=%08x\n”, &nameString, status ));

    return status;    //错误返回(创建CDO失败)

  }





  //注册默认派遣函数

  for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)                

  {

    DriverObject->MajorFunction[i] = SfPassThrough;                

  }

  //注册具体派遣函数

    DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate;

    DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate;

    DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate;

    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;

    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose;

    DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;







  fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,        //从非分页池中分配

                      sizeof( FAST_IO_DISPATCH ),  //要分配的字节数

                      SFLT_POOL_TAG );      //指定一个4字节的标签(前面已宏定义:‘tlFS’)

    

  if (!fastIoDispatch)    //内存分配失败

  {

    IoDeleteDevice( gSFilterControlDeviceObject );            //删除上面创建的CDO

    return STATUS_INSUFFICIENT_RESOURCES;                //返回一个错误status码(资源不足)

  }

    RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );      

    DriverObject->FastIoDispatch = fastIoDispatch;              //将FastIo分派表保存到驱动对象的FastIoDispatch域

    fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );    //设置FastIo分派表的长度域



    fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;    //设置FastIo分派函数,共21个

    fastIoDispatch->FastIoRead = SfFastIoRead;

    fastIoDispatch->FastIoWrite = SfFastIoWrite;

    fastIoDispatch->FastIoQueryBasicInfo = SfFastIoQueryBasicInfo;

    fastIoDispatch->FastIoQueryStandardInfo = SfFastIoQueryStandardInfo;

    fastIoDispatch->FastIoLock = SfFastIoLock;

    fastIoDispatch->FastIoUnlockSingle = SfFastIoUnlockSingle;

    fastIoDispatch->FastIoUnlockAll = SfFastIoUnlockAll;

    fastIoDispatch->FastIoUnlockAllByKey = SfFastIoUnlockAllByKey;

    fastIoDispatch->FastIoDeviceControl = SfFastIoDeviceControl;

    fastIoDispatch->FastIoDetachDevice = SfFastIoDetachDevice;

    fastIoDispatch->FastIoQueryNetworkOpenInfo = SfFastIoQueryNetworkOpenInfo;

    fastIoDispatch->MdlRead = SfFastIoMdlRead;

    fastIoDispatch->MdlReadComplete = SfFastIoMdlReadComplete;

    fastIoDispatch->PrepareMdlWrite = SfFastIoPrepareMdlWrite;

    fastIoDispatch->MdlWriteComplete = SfFastIoMdlWriteComplete;

    fastIoDispatch->FastIoReadCompressed = SfFastIoReadCompressed;

    fastIoDispatch->FastIoWriteCompressed = SfFastIoWriteCompressed;

    fastIoDispatch->MdlReadCompleteCompressed = SfFastIoMdlReadCompleteCompressed;

    fastIoDispatch->MdlWriteCompleteCompressed = SfFastIoMdlWriteCompleteCompressed;

    fastIoDispatch->FastIoQueryOpen = SfFastIoQueryOpen;





//--------------------------------注册fsFilter回调函数-------------------------------



#if WINVER >= 0x0501  //如果OS版本为WinXP以上,编译这段代码,否则不编译

  {

    FS_FILTER_CALLBACKS fsFilterCallbacks;

    if (NULL != gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)

    {

      fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );

            fsFilterCallbacks.PreAcquireForSectionSynchronization = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostAcquireForSectionSynchronization = SfPostFsFilterPassThrough;

            fsFilterCallbacks.PreReleaseForSectionSynchronization = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostReleaseForSectionSynchronization = SfPostFsFilterPassThrough;

            fsFilterCallbacks.PreAcquireForCcFlush = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostAcquireForCcFlush = SfPostFsFilterPassThrough;

            fsFilterCallbacks.PreReleaseForCcFlush = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostReleaseForCcFlush = SfPostFsFilterPassThrough;

            fsFilterCallbacks.PreAcquireForModifiedPageWriter = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostAcquireForModifiedPageWriter = SfPostFsFilterPassThrough;

            fsFilterCallbacks.PreReleaseForModifiedPageWriter = SfPreFsFilterPassThrough;

            fsFilterCallbacks.PostReleaseForModifiedPageWriter = SfPostFsFilterPassThrough;



            status = (gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)( DriverObject, &fsFilterCallbacks );

            if (!NT_SUCCESS( status ))

      {

        DriverObject->FastIoDispatch = NULL;

                ExFreePool( fastIoDispatch );

                IoDeleteDevice( gSFilterControlDeviceObject );

                return status;

      }

    }

  }

#endif            





    status = IoRegisterFsRegistrationChange( DriverObject, SfFsNotification );

    if (!NT_SUCCESS( status ))

  {

    KdPrint(( “SFilter!DriverEntry: Error registering FS change notification, status=%08x\n”, status ));



    DriverObject->FastIoDispatch = NULL;          //注销指向fastIo函数组的指针为NULL

    ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG );    //释放分配给fastIo函数组的内存

    IoDeleteDevice( gSFilterControlDeviceObject );      //删除上面创建的CDO

    return status;                      //错误返回

  }



    {

    

    PDEVICE_OBJECT rawDeviceObject;

    PFILE_OBJECT fileObject;

    RtlInitUnicodeString( &nameString, L"\Device\RawDisk" );



  

    /

    IoGetDeviceObjectPointer函数的功能是:

    它从下层的设备对象名称来获得下层设备指针。该函数造成了对下层设备对象以及下层设备对象所对应的文件对象的引用。

    如果本层驱动在卸载之前对下层的设备对象的引用还没有消除,则下层驱动的卸载会被停止。因此必须要消除对下层设备对象的引用。

    但是程序一般不会直接对下层设备对象的引用减少。因此只要减少对文件对象的引用就可以减少文件对象和设备对象两个对象的引用。

    事实上,IoGetDeviceObjectPointer返回的并不是下层设备对象的指针,而是该设备堆栈中顶层的设备对象的指针。





    IoGetDeviceObjectPointer函数的调用必须在 IRQL=PASSIVE_LEVEL的级别上运行。

    /



        status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject );

    if (NT_SUCCESS( status ))

    {

      SfFsNotification( rawDeviceObject, TRUE );

      ObDereferenceObject( fileObject ); //这里减少对文件对象的引用

    }



    RtlInitUnicodeString( &nameString, L"\Device\RawCdRom" );

        status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject );

    if (NT_SUCCESS( status ))

    {

      SfFsNotification( rawDeviceObject, TRUE );

      ObDereferenceObject( fileObject );//这里减少对文件对象的引用

    }

  }



  ClearFlag( gSFilterControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );

  return STATUS_SUCCESS;

}







// 驱动卸载函数 

#if DBG && WINVER >= 0x0501

VOID  DriverUnload( IN PDRIVER_OBJECT DriverObject )

{

  PSFILTER_DEVICE_EXTENSION devExt;

  PFAST_IO_DISPATCH fastIoDispatch;

  NTSTATUS status;

  ULONG numDevices;

  ULONG i;

  LARGE_INTEGER interval;



  PDEVICE_OBJECT devList[DEVOBJ_LIST_SIZE];

  ASSERT(DriverObject == gSFilterDriverObject);

  SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES, (“SFilter!DriverUnload:                        Unloading driver (%p)\n”, DriverObject) );

  IoUnregisterFsRegistrationChange( DriverObject, SfFsNotification );

  for (;😉

  {

    ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList );

        status = (gSfDynamicFunctions.EnumerateDeviceObjectList)( DriverObject, devList, sizeof(devList), &numDevices);

    if (numDevices <= 0)

    {

      break;

    }



    numDevices = min( numDevices, DEVOBJ_LIST_SIZE );

    for (i=0; i < numDevices; i++)

    {

      devExt = devList[i]->DeviceExtension;

      if (NULL != devExt)

      {

        IoDetachDevice( devExt->AttachedToDeviceObject );

      }

    }



    interval.QuadPart = (5  DELAY_ONE_SECOND);          //delay 5 seconds

    KeDelayExecutionThread( KernelMode, FALSE, &interval );

    for (i=0; i < numDevices; i++)

    {

      if (NULL != devList[i]->DeviceExtension)

      {

        SfCleanupMountedDevice( devList[i] );

      }

      else

      {

        ASSERT(devList[i] == gSFilterControlDeviceObject);

        gSFilterControlDeviceObject = NULL;

      }



      IoDeleteDevice( devList[i] );

            ObDereferenceObject( devList[i] );

        }

    }



  fastIoDispatch = DriverObject->FastIoDispatch;

  DriverObject->FastIoDispatch = NULL;

  ExFreePool( fastIoDispatch );

}

#endif







// SfLoadDynamicFunctions函数(仅在WindowsXP系统下编译该函数)

#if WINVER >= 0x0501

VOID  SfLoadDynamicFunctions()

{



  /

  动态加载下面的这些内核函数。使用动态加载所谓理由是:在低版本的Windows操作系统上,这段程序依然可以加载成功。

  /



    UNICODE_STRING functionName;

    RtlZeroMemory( &gSfDynamicFunctions, sizeof( gSfDynamicFunctions ) );    //将gSfDynamicFunctions结构变量清0



    RtlInitUnicodeString( &functionName, L"FsRtlRegisterFileSystemFilterCallbacks" );

    gSfDynamicFunctions.RegisterFileSystemFilterCallbacks = MmGetSystemRoutineAddress( &functionName );

<br style="color:rgb(19,37,60); font-family:宋体,verdana,geneva,lucida,‘lucida grande’,arial,helvet

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值