标 题: 【分享】整理一份我对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, 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_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
文件系统过滤驱动sfilter
最新推荐文章于 2024-07-24 13:46:26 发布