我平时很忙,很少发表主题。我在工作的时候,我身边的很多同事都不停地问我有关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 );
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 );
RtlInitUnicodeString( &functionName, L"IoAttachDeviceToDeviceStackSafe" );
gSfDynamicFunctions.AttachDeviceToDeviceStackSafe = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"IoEnumerateDeviceObjectList" );
gSfDynamicFunctions.EnumerateDeviceObjectList = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"IoGetLowerDeviceObject" );
gSfDynamicFunctions.GetLowerDeviceObject = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"IoGetDeviceAttachmentBaseRef" );
gSfDynamicFunctions.GetDeviceAttachmentBaseRef = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"IoGetDiskDeviceObject" );
gSfDynamicFunctions.GetDiskDeviceObject = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"IoGetAttachedDeviceReference" );
gSfDynamicFunctions.GetAttachedDeviceReference = MmGetSystemRoutineAddress( &functionName );
RtlInitUnicodeString( &functionName, L"RtlGetVersion" );
gSfDynamicFunctions.GetVersion = MmGetSystemRoutineAddress( &functionName );
}
#endif //SfGetCurrentVersion函数(仅WinXP下编译该函数)
#if WINVER >= 0x0501
VOID SfGetCurrentVersion()
{
if (NULL != gSfDynamicFunctions.GetVersion)
{
RTL_OSVERSIONINFOW versionInfo;
NTSTATUS status;
versionInfo.dwOSVersionInfoSize = sizeof( RTL_OSVERSIONINFOW );
status = (gSfDynamicFunctions.GetVersion)( &versionInfo );
ASSERT( NT_SUCCESS( status ) );
gSfOsMajorVersion = versionInfo.dwMajorVersion;
gSfOsMinorVersion = versionInfo.dwMinorVersion;
}
else
{
PsGetVersion( &gSfOsMajorVersion, &gSfOsMinorVersion, NULL, NULL );
}
}
#endif VOID SfFsNotification( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FsActive )
{
/*
SfFsNotification函数:
它创建一个设备对象,并将它附加到指定的文件系统控制设备对象(File System CDO)的对象栈上。这就允许这个设备对象过滤所有发送给文件系统的请求。
这样,我们就能够获得一个挂载卷的请求,就可以附加到这个新的卷设备对象的设备对象栈上。
当SfFsNotification函数调用完毕以后,我们的过滤驱动设备对象就能够接收到发送到文件系统CDO的请求,即接收到IRP_MJ_FILE_SYSTEM_CONTROL,或者说,
文件系统控制设备已经被绑定,可以动态监控卷的挂载了。那么以后的工作就是要完成对卷的监控绑定了。
参数说明:
DeviceObject: 它指向文件系统的控制设备对象(CDO)。即 被激活或则撤消的File System CDO
FsActive: 值为TRUE,表示文件系统的激活。值为FALSE,表示文件系统的卸载。
*/
UNICODE_STRING name; //定义结构变量
WCHAR nameBuffer[MAX_DEVNAME_LENGTH]; //定义宽字符缓冲区,长度64
PAGED_CODE();
RtlInitEmptyUnicodeString( &name, nameBuffer, sizeof(nameBuffer) ); //初始化name(成员Buffer->nameBuffer,Length=0,MaximumLength=64)
SfGetObjectName( DeviceObject, &name );
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsNotification: %s %p \"%wZ\" (%s)\n",
(FsActive) ? "Activating file system " : "Deactivating file system",
DeviceObject,
&name,
GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) );
if (FsActive)
{
SfAttachToFileSystemDevice( DeviceObject, &name ); //用于完成对文件系统控制设备的绑定
}
else
{
SfDetachFromFileSystemDevice( DeviceObject );
}
} NTSTATUS SfPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
} VOID SfDisplayCreateFileName( IN PIRP Irp )
{
PIO_STACK_LOCATION irpSp;
PUNICODE_STRING name;
GET_NAME_CONTROL nameControl;
irpSp = IoGetCurrentIrpStackLocation( Irp );
name = SfGetFileName( irpSp->FileObject, Irp->IoStatus.Status, &nameControl );
if (irpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID)
{
SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ (FID)\n",
Irp->IoStatus.Status,
Irp->IoStatus.Information,
name) );
}
else
{
SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ\n",
Irp->IoStatus.Status,
Irp->IoStatus.Information,
name) );
}
SfGetFileNameCleanup( &nameControl );
} NTSTATUS SfCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
NTSTATUS status;
PAGED_CODE();
/*
在sFilter的代码中,下面的这个if语句体这样写的后果是:我们用CreateFile函数在Ring3下打开此控制设备符号链接的时候会失败
*/
if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
{
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_INVALID_DEVICE_REQUEST;
}
/*
因此,需要把上面的这个if语句体修改成如下形式:
if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
*/ ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION | SFDEBUG_GET_CREATE_NAMES| SFDEBUG_DISPLAY_CREATE_NAMES ))
{
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
}
else
{
//初始化事件对象,设置完成例程。
KEVENT waitEvent;
KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
SfCreateCompletion,
&waitEvent,
TRUE,
TRUE,
TRUE );
status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
if (STATUS_PENDING == status)//若状态是 挂起
{
NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
ASSERT(STATUS_SUCCESS == localStatus);
}
ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status));
if (FlagOn(SfDebug, (SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES)))
{
SfDisplayCreateFileName( Irp );
}
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
}
} NTSTATUS SfCreateCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
PKEVENT event = Context;
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Irp );
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
KeSetEvent(event, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
} NTSTATUS SfCleanupClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PAGED_CODE();
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
} NTSTATUS SfFsControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
/*
参数说明:
DeviceObject: 我们创建的设备对象。它是被绑定到文件系统控制设备对象栈上。
*/
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
PAGED_CODE();
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
switch (irpSp->MinorFunction) {
case IRP_MN_MOUNT_VOLUME:
return SfFsControlMountVolume( DeviceObject, Irp );
case IRP_MN_LOAD_FILE_SYSTEM:
return SfFsControlLoadFileSystem( DeviceObject, Irp );
case IRP_MN_USER_FS_REQUEST:
{
switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
case FSCTL_DISMOUNT_VOLUME:
{
PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControl: Dismounting volume %p \"%wZ\"\n",
devExt->AttachedToDeviceObject,
&devExt->DeviceName) );
break;
}
}
break;
}
}
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
} NTSTATUS SfFsControlCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( Irp );
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
ASSERT(Context != NULL);
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
}
else
{
#endif
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
{
ExQueueWorkItem( (PWORK_QUEUE_ITEM) Context, DelayedWorkQueue );
}
else
{
PWORK_QUEUE_ITEM workItem = Context;
(workItem->WorkerRoutine)(workItem->Parameter);
}
#if WINVER >= 0x0501
}
#endif
return STATUS_MORE_PROCESSING_REQUIRED;
} NTSTATUS SfFsControlMountVolume( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
/*
参数说明:
DeviceObject: 它是我们创建的设备对象。它被绑定到文件系统CDO的设备栈上。
Irp: 它是发送给文件系统CDO的挂载请求。它是一个新卷的挂载请求。
*/
PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
PDEVICE_OBJECT storageStackDeviceObject; // newDeviceObject是将要绑定到文件系统的卷设备对象上。或者说,这个newDeviceObject要被绑定到新挂载卷的设备卷上。
PDEVICE_OBJECT newDeviceObject;
PSFILTER_DEVICE_EXTENSION newDevExt;
NTSTATUS status;
BOOLEAN isShadowCopyVolume;
PFSCTRL_COMPLETION_CONTEXT completionContext;
PAGED_CODE();
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
ASSERT(IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType)); /*
在把IRP发送到文件系统之前,当挂载请求到来时,Vpb->RealDevice保存的是:将要被挂载的磁盘设备对象。
storageStackDeviceObject事先保存了VPB的值,这是因为:当IRP下发给底层驱动后,可能会改变。
*/
storageStackDeviceObject = irpSp->Parameters.MountVolume.Vpb->RealDevice; status = SfIsShadowCopyVolume ( storageStackDeviceObject, &isShadowCopyVolume );
if (NT_SUCCESS(status) &&
isShadowCopyVolume &&
!FlagOn(SfDebug,SFDEBUG_ATTACH_TO_SHADOW_COPIES))
{
UNICODE_STRING shadowDeviceName;
WCHAR shadowNameBuffer[MAX_DEVNAME_LENGTH];
RtlInitEmptyUnicodeString( &shadowDeviceName, shadowNameBuffer, sizeof(shadowNameBuffer) );
SfGetObjectName( storageStackDeviceObject, &shadowDeviceName );
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControlMountVolume Not attaching to Volume %p \"%wZ\", shadow copy volume\n",
storageStackDeviceObject,
&shadowDeviceName) );
//如果不打算绑定卷影则跳到下一层驱动
IoSkipCurrentIrpStackLocation( Irp );
return IoCallDriver( devExt->AttachedToDeviceObject, Irp );
}
status = IoCreateDevice( gSFilterDriverObject,
sizeof( SFILTER_DEVICE_EXTENSION ),
NULL,
DeviceObject->DeviceType,
0,
FALSE,
&newDeviceObject );
/*如果不把IRP发送到文件系统中,那么文件系统就不会收到这个卷的挂载请求。*/
if (!NT_SUCCESS( status ))
{
KdPrint(( "SFilter!SfFsControlMountVolume: Error creating volume device object, status=%08x\n", status ));
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
} //填写设备扩展,这样目的是:可以让完成函数更容易到storageStackDeviceObject
newDevExt = newDeviceObject->DeviceExtension;
newDevExt->StorageStackDeviceObject = storageStackDeviceObject;
RtlInitEmptyUnicodeString( &newDevExt->DeviceName, newDevExt->DeviceNameBuffer, sizeof(newDevExt->DeviceNameBuffer) );
SfGetObjectName( storageStackDeviceObject, &newDevExt->DeviceName );
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
//在这里设置了事件对象,把它用在完成例程中。这样做的目的是:通知当前例程,文件系统已经完成了当前卷的挂载。
KEVENT waitEvent;
KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
IoCopyCurrentIrpStackLocationToNext ( Irp );
IoSetCompletionRoutine( Irp,
SfFsControlCompletion,
&waitEvent, //context parameter
TRUE,
TRUE,
TRUE );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
if (STATUS_PENDING == status)
{
//等待更底层的驱动完成,然后就会调用完成例程。
status = KeWaitForSingleObject( &waitEvent,
Executive,
KernelMode,
FALSE,
NULL );
ASSERT( STATUS_SUCCESS == status );
}
ASSERT(KeReadStateEvent(&waitEvent) ||
!NT_SUCCESS(Irp->IoStatus.Status));
//执行到了这里,说明卷的挂载已经完成,要开始绑定卷了。等到完成函数设置了事件之后,再来绑定卷。
status = SfFsControlMountVolumeComplete( DeviceObject, Irp, newDeviceObject );
}
else
{
#endif
completionContext = ExAllocatePoolWithTag( NonPagedPool, sizeof( FSCTRL_COMPLETION_CONTEXT ), SFLT_POOL_TAG );
if (completionContext == NULL)
{
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
}
else
{
//初始化一个工作任务。指定一个有待执行的函数SfFsControlMountVolumeCompleteWorker,把这个函数插入到某个线程中去执行。
ExInitializeWorkItem( &completionContext->WorkItem, SfFsControlMountVolumeCompleteWorker, completionContext );
completionContext->DeviceObject = DeviceObject;
completionContext->Irp = Irp;
completionContext->NewDeviceObject = newDeviceObject;
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
SfFsControlCompletion,
&completionContext->WorkItem, //context parameter
TRUE,
TRUE,
TRUE );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
}
#if WINVER >= 0x0501
}
#endif
return status;
} VOID SfFsControlMountVolumeCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context )
{
ASSERT( Context != NULL );
SfFsControlMountVolumeComplete( Context->DeviceObject,
Context->Irp,
Context->NewDeviceObject );
ExFreePoolWithTag( Context, SFLT_POOL_TAG );
} NTSTATUS SfFsControlMountVolumeComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT NewDeviceObject )
{
/*
参数说明:
DeviceObject: 它是绑定到文件系统控制设备对象的设备栈上,它是一个过滤设备对象。
Irp: 它是发送给文件系统CDO的挂载请求。它是一个新卷的挂载请求。
NewDeviceObject: 它是新创建的过滤设备对象,用于绑定到文件系统的卷设备对象的设备栈上。
*/
PVPB vpb;
PSFILTER_DEVICE_EXTENSION newDevExt;
PIO_STACK_LOCATION irpSp;
PDEVICE_OBJECT attachedDeviceObject;
NTSTATUS status;
PAGED_CODE();
newDevExt = NewDeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation( Irp );
/*
* 获取我们保存的VPB,这个时候就可以通过该设备对象得到VPB
* VPB->DeviceObject是 文件系统创建的卷设备对象
* VPB->RealDevice是 磁盘驱动创建的物理设备对象
*/
vpb = newDevExt->StorageStackDeviceObject->Vpb;
if (vpb != irpSp->Parameters.MountVolume.Vpb)
{
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControlMountVolume: VPB in IRP stack changed %p IRPVPB=%p VPB=%p\n",
vpb->DeviceObject,
irpSp->Parameters.MountVolume.Vpb,
vpb) );
}
if (NT_SUCCESS( Irp->IoStatus.Status ))
{
ExAcquireFastMutex( &gSfilterAttachLock );
if (!SfIsAttachedToDevice( vpb->DeviceObject, &attachedDeviceObject ))
{
/*
* SfAttachToMountedDevice的意义:将我们创建的过滤设备对象NewDeviceObject绑定到文件系统创建的VPB->DeviceObject的设备对象栈上。
*/
status = SfAttachToMountedDevice( vpb->DeviceObject, NewDeviceObject );
if (!NT_SUCCESS( status ))
{
SfCleanupMountedDevice( NewDeviceObject );
IoDeleteDevice( NewDeviceObject );
}
ASSERT( NULL == attachedDeviceObject );
}
else
{
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControlMountVolume Mount volume failure for %p \"%wZ\", already attached\n",
((PSFILTER_DEVICE_EXTENSION)attachedDeviceObject->DeviceExtension)->AttachedToDeviceObject,
&newDevExt->DeviceName) );
SfCleanupMountedDevice( NewDeviceObject );
IoDeleteDevice( NewDeviceObject );
ObDereferenceObject( attachedDeviceObject );
}
ExReleaseFastMutex( &gSfilterAttachLock );
}
else
{
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControlMountVolume: Mount volume failure for %p \"%wZ\", status=%08x\n",
DeviceObject,
&newDevExt->DeviceName,
Irp->IoStatus.Status) );
SfCleanupMountedDevice( NewDeviceObject );
IoDeleteDevice( NewDeviceObject );
}
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
} NTSTATUS SfFsControlLoadFileSystem( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
NTSTATUS status;
PFSCTRL_COMPLETION_CONTEXT completionContext;
PAGED_CODE();shu
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFscontrolLoadFileSystem: Loading File System, Detaching from \"%wZ\"\n",
&devExt->DeviceName) );
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
KEVENT waitEvent;
KeInitializeEvent( &waitEvent,
NotificationEvent,
FALSE );
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp,
SfFsControlCompletion,
&waitEvent, //context parameter
TRUE,
TRUE,
TRUE );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
if (STATUS_PENDING == status)
{
status = KeWaitForSingleObject( &waitEvent,
Executive,
KernelMode,
FALSE,
NULL );
ASSERT( STATUS_SUCCESS == status );
}
ASSERT(KeReadStateEvent(&waitEvent) ||
!NT_SUCCESS(Irp->IoStatus.Status));
status = SfFsControlLoadFileSystemComplete( DeviceObject, Irp );
} else {
#endif
completionContext = ExAllocatePoolWithTag( NonPagedPool,
sizeof( FSCTRL_COMPLETION_CONTEXT ),
SFLT_POOL_TAG );
if (completionContext == NULL) {
IoSkipCurrentIrpStackLocation( Irp );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
} else {
ExInitializeWorkItem( &completionContext->WorkItem,
SfFsControlLoadFileSystemCompleteWorker,
completionContext );
completionContext->DeviceObject = DeviceObject;
completionContext->Irp = Irp;
completionContext->NewDeviceObject = NULL;
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine(
Irp,
SfFsControlCompletion,
completionContext,
TRUE,
TRUE,
TRUE );
IoDetachDevice( devExt->AttachedToDeviceObject );
status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
}
#if WINVER >= 0x0501
}
#endif
return status;
} VOID SfFsControlLoadFileSystemCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context )
{
ASSERT( NULL != Context );
SfFsControlLoadFileSystemComplete( Context->DeviceObject, Context->Irp );
ExFreePoolWithTag( Context, SFLT_POOL_TAG );
} NTSTATUS SfFsControlLoadFileSystemComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
PSFILTER_DEVICE_EXTENSION devExt;
NTSTATUS status;
PAGED_CODE();
devExt = DeviceObject->DeviceExtension;
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFsControlLoadFileSystem: Detaching from recognizer %p \"%wZ\", status=%08x\n",
DeviceObject,
&devExt->DeviceName,
Irp->IoStatus.Status) );
if (!NT_SUCCESS( Irp->IoStatus.Status ) && (Irp->IoStatus.Status != STATUS_IMAGE_ALREADY_LOADED))
{
SfAttachDeviceToDeviceStack( DeviceObject, devExt->AttachedToDeviceObject, &devExt->AttachedToDeviceObject );
ASSERT(devExt->AttachedToDeviceObject != NULL);
}
else
{
SfCleanupMountedDevice( DeviceObject );
IoDeleteDevice( DeviceObject );
}
status = Irp->IoStatus.Status;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status;
} /*****************************************************************************************************************************************************
以下的代码是FastIO 的处理函数:
由于我们的驱动将要绑定到文件系统驱动的上边,文件系统除了处理正常的IRP之外,还要处理所谓的FastIo
FastIo是Cache Manager调用所引发的一种没有irp的请求。除了正常的Dispatch Functions之外,你还得为DriverObject 编写另一组Fast Io Functions。
文件系统的普通分发例程和fastio例程都随时有可能被调用。做好的过滤驱动显然应该同时过滤这两套接口。
在进行基于IRP为基础的接口调用前, IO管理器会尝试使用FAST IO 接口来加速各种IO操作。 FastIO 的设计是用来处理快速的、同步的、并且“on cached files”的IO操作。当进行FastIO操作时,所需处理的数据是直接在用户buffer和系统缓存中进行传输的,
而不是通过文件系统和存储器驱动栈(storage driver stack)。
事实上存储器驱动并不使用FastIO机制。当需要处理的数据已经存在于系统缓存,则采用FastIO机制的读写操作立刻就可以完成。否则,系统会产生一个缺页中断,
这会导致系统发送相应的IRP包来完成用户所需的读写操作。通常发生这种情况(指:所需的数据不在系统缓存的情况的时候,FastIO函数会返回FALSE,
或者一直等到缺页中端响应函数把所需的数据都加载到系统缓存中。(如果FastIO处理函数返回FALSE,那么调用者必须自己创建相应Irp来完成所需的处理。) 文件系统过滤驱动程序的控制设备对象(CDO)并不一定需要处理IO操作。过滤器设备对象(FiDO)则需要将所有不能识别的Irp包都传递到自己下层的驱动程序。
另外有一点需要注意,挂在到卷上的过滤器设备对象必须提供 FastIoDetachDevice 函数。
******************************************************************************************************************************************************/
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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible ))
{
return (fastIoDispatch->FastIoCheckIfPossible)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
CheckForReadOperation,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension) {
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead ))
{
return (fastIoDispatch->FastIoRead)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
Buffer,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWrite ))
{
return (fastIoDispatch->FastIoWrite)(
FileObject,
FileOffset,
Length,
Wait,
LockKey,
Buffer,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
BOOLEAN SfFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryBasicInfo ))
{
return (fastIoDispatch->FastIoQueryBasicInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
BOOLEAN SfFastIoQueryStandardInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryStandardInfo ))
{
return (fastIoDispatch->FastIoQueryStandardInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoLock ))
{
return (fastIoDispatch->FastIoLock)(
FileObject,
FileOffset,
Length,
ProcessId,
Key,
FailImmediately,
ExclusiveLock,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockSingle ))
{
return (fastIoDispatch->FastIoUnlockSingle)(
FileObject,
FileOffset,
Length,
ProcessId,
Key,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
}
BOOLEAN SfFastIoUnlockAll( IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
if (nextDeviceObject)
{
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAll ))
{
return (fastIoDispatch->FastIoUnlockAll)(
FileObject,
ProcessId,
IoStatus,
nextDeviceObject );
}
}
}
return FALSE;
}
BOOLEAN SfFastIoUnlockAllByKey( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAllByKey ))
{
return (fastIoDispatch->FastIoUnlockAllByKey)(
FileObject,
ProcessId,
Key,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
} 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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoDeviceControl ))
{
return (fastIoDispatch->FastIoDeviceControl)(
FileObject,
Wait,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength,
IoControlCode,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
} VOID SfFastIoDetachDevice( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice )
{
PSFILTER_DEVICE_EXTENSION devExt;
PAGED_CODE();
ASSERT(IS_MY_DEVICE_OBJECT( SourceDevice ));
devExt = SourceDevice->DeviceExtension;
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfFastIoDetachDevice: Detaching from volume %p \"%wZ\"\n",
TargetDevice, &devExt->DeviceName) );
SfCleanupMountedDevice( SourceDevice );
IoDetachDevice( TargetDevice );
IoDeleteDevice( SourceDevice );
} BOOLEAN SfFastIoQueryNetworkOpenInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryNetworkOpenInfo ))
{
return (fastIoDispatch->FastIoQueryNetworkOpenInfo)(
FileObject,
Wait,
Buffer,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
} 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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlRead ))
{
return (fastIoDispatch->MdlRead)(
FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
} BOOLEAN SfFastIoMdlReadComplete( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadComplete ))
{
return (fastIoDispatch->MdlReadComplete)( FileObject, MdlChain, nextDeviceObject );
}
}
return FALSE;
} 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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, PrepareMdlWrite ))
{
return (fastIoDispatch->PrepareMdlWrite)(
FileObject,
FileOffset,
Length,
LockKey,
MdlChain,
IoStatus,
nextDeviceObject );
}
}
return FALSE;
} BOOLEAN SfFastIoMdlWriteComplete( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteComplete ))
{
return (fastIoDispatch->MdlWriteComplete)(
FileObject,
FileOffset,
MdlChain,
nextDeviceObject );
}
}
return FALSE;
} 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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoReadCompressed ))
{
return (fastIoDispatch->FastIoReadCompressed)(
FileObject,
FileOffset,
Length,
LockKey,
Buffer,
MdlChain,
IoStatus,
CompressedDataInfo,
CompressedDataInfoLength,
nextDeviceObject );
}
}
return FALSE;
} 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 )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWriteCompressed ))
{
return (fastIoDispatch->FastIoWriteCompressed)(
FileObject,
FileOffset,
Length,
LockKey,
Buffer,
MdlChain,
IoStatus,
CompressedDataInfo,
CompressedDataInfoLength,
nextDeviceObject );
}
}
return FALSE;
} BOOLEAN SfFastIoMdlReadCompleteCompressed( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadCompleteCompressed ))
{
return (fastIoDispatch->MdlReadCompleteCompressed)(
FileObject,
MdlChain,
nextDeviceObject );
}
}
return FALSE;
} BOOLEAN SfFastIoMdlWriteCompleteCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
if (DeviceObject->DeviceExtension) {
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteCompleteCompressed )) {
return (fastIoDispatch->MdlWriteCompleteCompressed)(
FileObject,
FileOffset,
MdlChain,
nextDeviceObject );
}
}
return FALSE;
} BOOLEAN SfFastIoQueryOpen( IN PIRP Irp, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT nextDeviceObject;
PFAST_IO_DISPATCH fastIoDispatch;
BOOLEAN result;
PAGED_CODE();
if (DeviceObject->DeviceExtension)
{
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
ASSERT(nextDeviceObject);
fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryOpen ))
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
irpSp->DeviceObject = nextDeviceObject;
result = (fastIoDispatch->FastIoQueryOpen)(
Irp,
NetworkInformation,
nextDeviceObject );
irpSp->DeviceObject = DeviceObject;
return result;
}
}
return FALSE;
} #if WINVER >= 0x0501
//========================== FSFilter 回调函数 ===========================
NTSTATUS SfPreFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, OUT PVOID *CompletionContext )
{
UNREFERENCED_PARAMETER( Data );
UNREFERENCED_PARAMETER( CompletionContext );
ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );
return STATUS_SUCCESS;
} VOID SfPostFsFilterPassThrough ( IN PFS_FILTER_CALLBACK_DATA Data, IN NTSTATUS OperationStatus, IN PVOID CompletionContext )
{
UNREFERENCED_PARAMETER( Data );
UNREFERENCED_PARAMETER( OperationStatus );
UNREFERENCED_PARAMETER( CompletionContext );
ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );
}
#endif NTSTATUS SfAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice, IN OUT PDEVICE_OBJECT *AttachedToDeviceObject )
{
/*
参数说明:
SourceDevice: 它是调用者创建的设备对象。比如调用者使用IoCreateDevice函数来创建设备对象。
TargetDevice: 它指向其它驱动程序的设备对象。
AttachedToDeviceObject: 它用来存储IoAttachDeviceToDeviceStack函数的返回值。
*/
PAGED_CODE();
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
ASSERT( NULL != gSfDynamicFunctions.AttachDeviceToDeviceStackSafe );
return (gSfDynamicFunctions.AttachDeviceToDeviceStackSafe)( SourceDevice, TargetDevice, AttachedToDeviceObject );
}
else
{
ASSERT( NULL == gSfDynamicFunctions.AttachDeviceToDeviceStackSafe );
#endif
*AttachedToDeviceObject = TargetDevice;
*AttachedToDeviceObject = IoAttachDeviceToDeviceStack( SourceDevice, TargetDevice );
if (*AttachedToDeviceObject == NULL)
{
return STATUS_NO_SUCH_DEVICE;
}
return STATUS_SUCCESS;
#if WINVER >= 0x0501
}
#endif
} NTSTATUS SfAttachToFileSystemDevice( IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING DeviceName )
{
/*
SfAttachToFileSystemDevice函数用来完成对文件系统控制设备的绑定。
参数说明:
DeviceObject: 它指向文件系统的控制设备对象(CDO)。即 被激活或则撤消的File System CDO
*/
PDEVICE_OBJECT newDeviceObject; //新设备对象
PSFILTER_DEVICE_EXTENSION devExt; //文件系统过滤驱动定义的设备扩展
NTSTATUS status; //状态码
UNICODE_STRING fsrecName;
UNICODE_STRING fsName; //文件系统名
WCHAR tempNameBuffer[MAX_DEVNAME_LENGTH];//临时缓冲区(存放名字串)
PAGED_CODE();
if (!IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType)) //测试给定设备是不是所需要关心的设备
{
return STATUS_SUCCESS;
}
/*
* Windows的标准文件系统识别器基本上都是由驱动 \FileSystem\Fs_Rec 生成的。所以直接判断驱动的名字可以解决一部分问题。
* 也不一定非得要把文件系统识别器生成在驱动\FileSystem\Fs_Rec下面。只是说,一般情况下是在\FileSystem\Fs_Rec下面。
*/
RtlInitEmptyUnicodeString( &fsName, tempNameBuffer, sizeof(tempNameBuffer) );
if (!FlagOn(SfDebug,SFDEBUG_ATTACH_TO_FSRECOGNIZER))
{
RtlInitUnicodeString( &fsrecName, L"\\FileSystem\\Fs_Rec" );
SfGetObjectName( DeviceObject->DriverObject, &fsName );
if (RtlCompareUnicodeString( &fsName, &fsrecName, TRUE ) == 0)
{
//通过驱动的名字来分辨出部分Windows的标准文件系统识别器。如果是,那么返回成功,也就是放弃绑定了。
//如果,有错过的文件系统识别器没有被判断到,文件系统控制请求的过滤驱动中有对应的处理。
return STATUS_SUCCESS;
}
}
//是我们关心的文件系统,且不是微软的文件系统识别器的设备,创建一个设备绑定这个设备对象。
status = IoCreateDevice( gSFilterDriverObject,
sizeof( SFILTER_DEVICE_EXTENSION ),
NULL,
DeviceObject->DeviceType,
0,
FALSE,
&newDeviceObject );
if (!NT_SUCCESS( status ))
{
return status;
}
if ( FlagOn( DeviceObject->Flags, DO_BUFFERED_IO ))
{
SetFlag( newDeviceObject->Flags, DO_BUFFERED_IO );
}
if ( FlagOn( DeviceObject->Flags, DO_DIRECT_IO ))
{
SetFlag( newDeviceObject->Flags, DO_DIRECT_IO );
}
if ( FlagOn( DeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN ) )
{
SetFlag( newDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN );
}
devExt = newDeviceObject->DeviceExtension;
/*
调用SfAttachDeviceToDeviceStack函数将过滤设备对象绑定到File System CDO的设备栈上面。这样,我们的newDeviceObject就可以接收到发送到
File System CDO的IRP_MJ_FILE_SYSTEM_CONTROL请求了。 以后,程序就可以去绑定卷了。
使用SfAttachDeviceToDeviceStack函数来进行绑定。参数1绑定到参数2,绑定函数返回的设备存储在参数3中。
*/
status = SfAttachDeviceToDeviceStack( newDeviceObject, DeviceObject, &devExt->AttachedToDeviceObject );
if (!NT_SUCCESS( status ))
{
goto ErrorCleanupDevice;
}
RtlInitEmptyUnicodeString( &devExt->DeviceName, devExt->DeviceNameBuffer, sizeof(devExt->DeviceNameBuffer) );
RtlCopyUnicodeString( &devExt->DeviceName, DeviceName ); //Save Name
ClearFlag( newDeviceObject->Flags, DO_DEVICE_INITIALIZING );
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfAttachToFileSystemDevice: Attaching to file system %p \"%wZ\" (%s)\n",
DeviceObject,
&devExt->DeviceName,
GET_DEVICE_TYPE_NAME(newDeviceObject->DeviceType)) );
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList &&
NULL != gSfDynamicFunctions.GetDiskDeviceObject &&
NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef &&
NULL != gSfDynamicFunctions.GetLowerDeviceObject );
/*
函数SpyEnumerateFileSystemVolumes枚举给定的文件系统下的当前存在的所有挂载了的设备,并且绑定他们。
这样做的目的,是因为过滤驱动可能随时被加载,但是加载过滤驱动的时候,文件系统已经挂载了卷设备。
既是:让过滤驱动加后载,随时都能绑定已经存在或刚刚挂载上来的文件系统卷设备。
*/
status = SfEnumerateFileSystemVolumes( DeviceObject, &fsName );
if (!NT_SUCCESS( status ))
{
IoDetachDevice( devExt->AttachedToDeviceObject );
goto ErrorCleanupDevice;
}
}
#endif
return STATUS_SUCCESS;
ErrorCleanupDevice:
SfCleanupMountedDevice( newDeviceObject );
IoDeleteDevice( newDeviceObject );
return status;
} VOID SfDetachFromFileSystemDevice( IN PDEVICE_OBJECT DeviceObject )
{
PDEVICE_OBJECT ourAttachedDevice;
PSFILTER_DEVICE_EXTENSION devExt;
PAGED_CODE();
ourAttachedDevice = DeviceObject->AttachedDevice;
while (NULL != ourAttachedDevice)
{
if (IS_MY_DEVICE_OBJECT( ourAttachedDevice ))
{
devExt = ourAttachedDevice->DeviceExtension;
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfDetachFromFileSystemDevice: Detaching from file system %p \"%wZ\" (%s)\n",
devExt->AttachedToDeviceObject,
&devExt->DeviceName,
GET_DEVICE_TYPE_NAME(ourAttachedDevice->DeviceType)) );
SfCleanupMountedDevice( ourAttachedDevice );
IoDetachDevice( DeviceObject );
IoDeleteDevice( ourAttachedDevice );
return;
}
DeviceObject = ourAttachedDevice;
ourAttachedDevice = ourAttachedDevice->AttachedDevice;
}
} #if WINVER >= 0x0501
NTSTATUS SfEnumerateFileSystemVolumes( IN PDEVICE_OBJECT FSDeviceObject, IN PUNICODE_STRING Name )
{
/*
参数说明:
FSDeviceObject: 它指向文件系统的控制设备对象(CDO)。即 被激活或则撤消的File System CDO
Name: 它是文件系统的名字
*/
PDEVICE_OBJECT newDeviceObject;
PSFILTER_DEVICE_EXTENSION newDevExt;
PDEVICE_OBJECT *devList;
PDEVICE_OBJECT storageStackDeviceObject;
NTSTATUS status;
ULONG numDevices;
ULONG i;
BOOLEAN isShadowCopyVolume;
PAGED_CODE();
/*
* IoEnumerateDeviceObjectList函数枚举这个驱动下的设备对象列表。这个函数将被调用2次。
* 第1次调用: 获取设备列表中的设备对象的数量。
* 第2次调用: 根据第1次的结果numDevices值来开辟设备对象的存放空间,从而得到设备链devList。
*/
status = (gSfDynamicFunctions.EnumerateDeviceObjectList)(
FSDeviceObject->DriverObject,
NULL,
0,
&numDevices);
if (!NT_SUCCESS( status ))
{
ASSERT(STATUS_BUFFER_TOO_SMALL == status);
numDevices += 8; //为已知的设备开辟内存空间进行存储。额外增加8字节。
devList = ExAllocatePoolWithTag( NonPagedPool, (numDevices * sizeof(PDEVICE_OBJECT)), SFLT_POOL_TAG );
if (NULL == devList)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList );
status = (gSfDynamicFunctions.EnumerateDeviceObjectList)(
FSDeviceObject->DriverObject,
devList,
(numDevices * sizeof(PDEVICE_OBJECT)),
&numDevices);
if (!NT_SUCCESS( status ))
{
ExFreePool( devList );
return status;
}
//依次遍历各个设备对象
for (i=0; i < numDevices; i++)
{
storageStackDeviceObject = NULL;
try {
//如果设备对象是文件系统CDO,或者是不符合类型的,或者是已经绑定的
if ((devList[i] == FSDeviceObject) || (devList[i]->DeviceType != FSDeviceObject->DeviceType) || SfIsAttachedToDevice( devList[i], NULL ))
{
leave;
}
SfGetBaseDeviceObjectName( devList[i], Name );
if (Name->Length > 0)
{
leave;
} /*
调用IoGetDiskDeviceObject函数来获取一个与文件系统设备对象有关的磁盘设备对象。只绑定已经拥有一个磁盘设备对象的文件系统设备对象。
*/
ASSERT( NULL != gSfDynamicFunctions.GetDiskDeviceObject );
status = (gSfDynamicFunctions.GetDiskDeviceObject)( devList[i], &storageStackDeviceObject );
if (!NT_SUCCESS( status ))
{
leave;
}
status = SfIsShadowCopyVolume ( storageStackDeviceObject, &isShadowCopyVolume );
if (NT_SUCCESS(status) &&
isShadowCopyVolume &&
!FlagOn(SfDebug,SFDEBUG_ATTACH_TO_SHADOW_COPIES))
{
UNICODE_STRING shadowDeviceName;
WCHAR shadowNameBuffer[MAX_DEVNAME_LENGTH];
RtlInitEmptyUnicodeString( &shadowDeviceName, shadowNameBuffer, sizeof(shadowNameBuffer) );
SfGetObjectName( storageStackDeviceObject, &shadowDeviceName );
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfEnumerateFileSystemVolumes Not attaching to Volume %p \"%wZ\", shadow copy volume\n",
storageStackDeviceObject,
&shadowDeviceName) );
leave;
}
// 是一个磁盘设备对象,创建新的设备对象,准备绑定。
status = IoCreateDevice( gSFilterDriverObject,
sizeof( SFILTER_DEVICE_EXTENSION ),
NULL,
devList[i]->DeviceType,
0,
FALSE,
&newDeviceObject );
if (!NT_SUCCESS( status ))
{
leave;
}
newDevExt = newDeviceObject->DeviceExtension;
newDevExt->StorageStackDeviceObject = storageStackDeviceObject;
RtlInitEmptyUnicodeString( &newDevExt->DeviceName, newDevExt->DeviceNameBuffer,sizeof(newDevExt->DeviceNameBuffer) );
SfGetObjectName( storageStackDeviceObject, &newDevExt->DeviceName );
/*
在绑定最后的时候,再测试下,该设备是否被绑定过。这里加了一个锁。如果没被绑定,则执行下面的绑定过程,否则,直接返回。
*/
ExAcquireFastMutex( &gSfilterAttachLock );
if (!SfIsAttachedToDevice( devList[i], NULL ))
{
status = SfAttachToMountedDevice( devList[i], newDeviceObject );
if (!NT_SUCCESS( status ))
{
SfCleanupMountedDevice( newDeviceObject );
IoDeleteDevice( newDeviceObject );
}
}
else
{
SfCleanupMountedDevice( newDeviceObject );
IoDeleteDevice( newDeviceObject );
}
ExReleaseFastMutex( &gSfilterAttachLock );
}
finally {
/*
减少设备对象的计数,这个计数是由函数IoGetDiskDeviceObject增加的。成功绑定后,就减少该设备对象的计数。
一旦成功绑定到devList[i],I/O管理器会确定设备栈的下层设备,会一直存在,一直到这个文件系统栈被卸掉。
*/
if (storageStackDeviceObject != NULL)
{
ObDereferenceObject( storageStackDeviceObject );
}
//减少设备对象的计数,这个计数是由函数IoEnumerateDeviceObjectList增加的。
ObDereferenceObject( devList[i] );
}
}
status = STATUS_SUCCESS;
ExFreePool( devList );
}
return status;
}
#endif NTSTATUS SfAttachToMountedDevice( IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT SFilterDeviceObject )
{
/*
SfAttachToMountedDevice函数的功能: 完成绑定一个文件系统卷设备的操作。
参数说明:
SFilterDeviceObject: 它是我们使用IoCreateDevice函数来创建的设备对象。
*/
PSFILTER_DEVICE_EXTENSION newDevExt = SFilterDeviceObject->DeviceExtension;
NTSTATUS status;
ULONG i;
PAGED_CODE();
ASSERT(IS_MY_DEVICE_OBJECT( SFilterDeviceObject ));
#if WINVER >= 0x0501
ASSERT(!SfIsAttachedToDevice ( DeviceObject, NULL ));
#endif
if (FlagOn( DeviceObject->Flags, DO_BUFFERED_IO ))
{
SetFlag( SFilterDeviceObject->Flags, DO_BUFFERED_IO );
}
if (FlagOn( DeviceObject->Flags, DO_DIRECT_IO ))
{
SetFlag( SFilterDeviceObject->Flags, DO_DIRECT_IO );
}
for (i=0; i < 8; i++)
{
LARGE_INTEGER interval;
//调用SfAttachDeviceToDeviceStack函数进行 卷的绑定
status = SfAttachDeviceToDeviceStack( SFilterDeviceObject, DeviceObject, &newDevExt->AttachedToDeviceObject );
if (NT_SUCCESS(status))
{
ClearFlag( SFilterDeviceObject->Flags, DO_DEVICE_INITIALIZING );
SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!SfAttachToMountedDevice: Attaching to volume %p \"%wZ\"\n",
newDevExt->AttachedToDeviceObject,
&newDevExt->DeviceName) );
return STATUS_SUCCESS;
}
interval.QuadPart = (500 * DELAY_ONE_MILLISECOND); //delay 1/2 second
KeDelayExecutionThread( KernelMode, FALSE, &interval );
}
return status;
} VOID SfCleanupMountedDevice( IN PDEVICE_OBJECT DeviceObject )
{
UNREFERENCED_PARAMETER( DeviceObject );
ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
} VOID SfGetObjectName( IN PVOID Object, IN OUT PUNICODE_STRING Name )
{
NTSTATUS status;
CHAR nibuf[512]; //接收返回的对象名
POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)nibuf; //nameInfo存放的是指向UNICODE_STRING结构变量的指针
ULONG retLength; //接收"实际返回的对象名长度"
status = ObQueryNameString( Object, nameInfo, sizeof(nibuf), &retLength); //返回对象名
Name->Length = 0;
if (NT_SUCCESS( status ))
{
RtlCopyUnicodeString( Name, &nameInfo->Name );
}
} #if WINVER >= 0x0501
VOID SfGetBaseDeviceObjectName( IN PDEVICE_OBJECT DeviceObject, IN OUT PUNICODE_STRING Name )
{
ASSERT( NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef );
DeviceObject = (gSfDynamicFunctions.GetDeviceAttachmentBaseRef)( DeviceObject );
SfGetObjectName( DeviceObject, Name );
ObDereferenceObject( DeviceObject );
}
#endif PUNICODE_STRING SfGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl )
{
POBJECT_NAME_INFORMATION nameInfo;
NTSTATUS status;
ULONG size;
ULONG bufferSize;
NameControl->allocatedBuffer = NULL;
nameInfo = (POBJECT_NAME_INFORMATION)NameControl->smallBuffer;
bufferSize = sizeof(NameControl->smallBuffer);
status = ObQueryNameString( (NT_SUCCESS( CreateStatus ) ? (PVOID)FileObject : (PVOID)FileObject->DeviceObject), nameInfo, bufferSize, &size );
if (status == STATUS_BUFFER_OVERFLOW)
{
bufferSize = size + sizeof(WCHAR);
NameControl->allocatedBuffer = ExAllocatePoolWithTag( NonPagedPool, bufferSize, SFLT_POOL_TAG );
if (NULL == NameControl->allocatedBuffer)
{
RtlInitEmptyUnicodeString(
(PUNICODE_STRING)&NameControl->smallBuffer,
(PWCHAR)(NameControl->smallBuffer + sizeof(UNICODE_STRING)),
(USHORT)(sizeof(NameControl->smallBuffer) - sizeof(UNICODE_STRING)) );
return (PUNICODE_STRING)&NameControl->smallBuffer;
}
nameInfo = (POBJECT_NAME_INFORMATION)NameControl->allocatedBuffer;
status = ObQueryNameString(
FileObject,
nameInfo,
bufferSize,
&size );
}
if (NT_SUCCESS( status ) && !NT_SUCCESS( CreateStatus ))
{
ULONG newSize;
PCHAR newBuffer;
POBJECT_NAME_INFORMATION newNameInfo;
newSize = size + FileObject->FileName.Length;
if (NULL != FileObject->RelatedFileObject)
{
newSize += FileObject->RelatedFileObject->FileName.Length + sizeof(WCHAR);
}
if (newSize > bufferSize)
{
newBuffer = ExAllocatePoolWithTag( NonPagedPool, newSize, SFLT_POOL_TAG );
if (NULL == newBuffer)
{
RtlInitEmptyUnicodeString(
(PUNICODE_STRING)&NameControl->smallBuffer,
(PWCHAR)(NameControl->smallBuffer + sizeof(UNICODE_STRING)),
(USHORT)(sizeof(NameControl->smallBuffer) - sizeof(UNICODE_STRING)) );
return (PUNICODE_STRING)&NameControl->smallBuffer;
}
newNameInfo = (POBJECT_NAME_INFORMATION)newBuffer;
RtlInitEmptyUnicodeString(
&newNameInfo->Name,
(PWCHAR)(newBuffer + sizeof(OBJECT_NAME_INFORMATION)),
(USHORT)(newSize - sizeof(OBJECT_NAME_INFORMATION)) );
RtlCopyUnicodeString( &newNameInfo->Name, &nameInfo->Name );
if (NULL != NameControl->allocatedBuffer)
{
ExFreePool( NameControl->allocatedBuffer );
}
NameControl->allocatedBuffer = newBuffer;
bufferSize = newSize;
nameInfo = newNameInfo;
}
else
{
nameInfo->Name.MaximumLength = (USHORT)(bufferSize - sizeof(OBJECT_NAME_INFORMATION));
}
if (NULL != FileObject->RelatedFileObject)
{
RtlAppendUnicodeStringToString( &nameInfo->Name, &FileObject->RelatedFileObject->FileName );
RtlAppendUnicodeToString( &nameInfo->Name, L"\\" );
}
RtlAppendUnicodeStringToString( &nameInfo->Name, &FileObject->FileName );
ASSERT(nameInfo->Name.Length <= nameInfo->Name.MaximumLength);
}
return &nameInfo->Name;
} VOID SfGetFileNameCleanup( IN OUT PGET_NAME_CONTROL NameControl )
{
if (NULL != NameControl->allocatedBuffer) {
ExFreePool( NameControl->allocatedBuffer);
NameControl->allocatedBuffer = NULL;
}
} BOOLEAN SfIsAttachedToDevice( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{
PAGED_CODE();
#if WINVER >= 0x0501
if (IS_WINDOWSXP_OR_LATER())
{
ASSERT( NULL != gSfDynamicFunctions.GetLowerDeviceObject && NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef );
return SfIsAttachedToDeviceWXPAndLater( DeviceObject, AttachedDeviceObject );
}
else
{
#endif
return SfIsAttachedToDeviceW2K( DeviceObject, AttachedDeviceObject );
#if WINVER >= 0x0501
}
#endif
} BOOLEAN SfIsAttachedToDeviceW2K( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{
PDEVICE_OBJECT currentDevice;
PAGED_CODE();
for (currentDevice = DeviceObject; currentDevice != NULL; currentDevice = currentDevice->AttachedDevice)
{
if (IS_MY_DEVICE_OBJECT( currentDevice ))
{
if (ARGUMENT_PRESENT(AttachedDeviceObject))
{
ObReferenceObject( currentDevice );
*AttachedDeviceObject = currentDevice;
}
return TRUE;
}
}
if (ARGUMENT_PRESENT(AttachedDeviceObject))
{
*AttachedDeviceObject = NULL;
}
return FALSE;
} #if WINVER >= 0x0501
BOOLEAN SfIsAttachedToDeviceWXPAndLater( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{
PDEVICE_OBJECT currentDevObj;
PDEVICE_OBJECT nextDevObj;
PAGED_CODE();
ASSERT( NULL != gSfDynamicFunctions.GetAttachedDeviceReference );
currentDevObj = (gSfDynamicFunctions.GetAttachedDeviceReference)( DeviceObject );
do {
if (IS_MY_DEVICE_OBJECT( currentDevObj ))
{
if (ARGUMENT_PRESENT(AttachedDeviceObject))
{
*AttachedDeviceObject = currentDevObj;
}
else
{
ObDereferenceObject( currentDevObj );
}
return TRUE;
}
ASSERT( NULL != gSfDynamicFunctions.GetLowerDeviceObject );
nextDevObj = (gSfDynamicFunctions.GetLowerDeviceObject)( currentDevObj );
ObDereferenceObject( currentDevObj );
currentDevObj = nextDevObj;
} while (NULL != currentDevObj);
if (ARGUMENT_PRESENT(AttachedDeviceObject))
{
*AttachedDeviceObject = NULL;
}
return FALSE;
}
#endif VOID SfReadDriverParameters( IN PUNICODE_STRING RegistryPath )
{
OBJECT_ATTRIBUTES attributes;
HANDLE driverRegKey;
NTSTATUS status;
ULONG resultLength;
UNICODE_STRING valueName;
UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];
PAGED_CODE();
if (0 == SfDebug)
{
InitializeObjectAttributes( &attributes,
RegistryPath,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
status = ZwOpenKey( &driverRegKey, KEY_READ, &attributes );
if (!NT_SUCCESS( status ))
{
return;
}
RtlInitUnicodeString( &valueName, L"DebugFlags" );
status = ZwQueryValueKey( driverRegKey,
&valueName,
KeyValuePartialInformation,
buffer,
sizeof(buffer),
&resultLength );
if (NT_SUCCESS( status ))
{
SfDebug = *((PLONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data));
}
ZwClose(driverRegKey);
}
} NTSTATUS SfIsShadowCopyVolume( IN PDEVICE_OBJECT StorageStackDeviceObject, OUT PBOOLEAN IsShadowCopy )
{
/*******************************************************************************************************************************************
SfIsShadowCopyVolume( )函数的主要功能是:涉及到 卷影拷贝服务的。
卷影拷贝服务(Volume Shadow Copy Service,VSS)是一种备份和恢复的技术。它是一种基于时间点来备份文件拷贝的技术。
通过使用卷影拷贝服务,我们可以在特定卷上建立数据拷贝时间点,并在将来的某一时刻把数据恢复到任何一个你曾创建的时间点的状态。
最常见的请求一般是恢复人为原因造成的数据丢失。用户不经意地存储了有错误信息的文件,或者是不小心删除文件,或是其他的数据意外。
备份VSS快照产生干净的数据镜像以及恢复时间点拷贝的能力。我们既可以恢复整个快照,也可以取所需,或者还可以使用VSS备份工具来恢复单独的文件和文件夹。
VSS不是对应用程序进行备份的,VSS可以对逻辑卷(硬盘分区)进行快照。
VSS是Windows下的快照技术,由Requestor, Write,和Provider组成;主要由驱动程序Volsnap.sys实现,被加到卷管理驱动和文件系统驱动之间,同时集成了COM技术。
因此,它不再是单单在卷级上的block进行处理,而是和各种系统应用相关联,比如SQL,EXCHANGE,AD等等。从而使得在不关机,也不停止应用的情况下,做快照。
VSS被广泛的应用到Windows的备份处理中。
VSS 解决问题的方法是,通过提供以下三个重要实体之间的通讯来保证备份的高度真实和恢复过程的简便。
(1)请求程序:它是用来请求时间点数据副本或卷影副本的应用程序,比如备份或存储管理应用程序。
(2)写入程序:它们负责数据通知和数据保护。写入程序是VSS区别于其它卷影副本或快照解决方案的地方。在VSS的卷影复制过程中会涉及一些应用程序。
(3)提供程序:它用于暴露基于硬件或软件的卷影副本的机制。许多存储硬件供应商都会为它们的存储阵列编写提供程序。 VSS服务唯一的缺点是:
我们需要为每一个卷影留出更多的磁盘空间,我们必须在某处存储这些拷贝。因为VSS使用指针数据,这些拷贝占用的空间要比想像的小得多,我们可以有效地存储这些拷贝。 有关VSS的更多说明,可以去浏览Microsoft的下述网站
http://technet.microsoft.com/en-us/library/ee923636.aspx
*********************************************************************************************************************************************/
PAGED_CODE();
*IsShadowCopy = FALSE;
#if WINVER >= 0x0501
if (IS_WINDOWS2000())
{
#endif
UNREFERENCED_PARAMETER( StorageStackDeviceObject );
return STATUS_SUCCESS;
#if WINVER >= 0x0501
}
if (IS_WINDOWSXP())
{
UNICODE_STRING volSnapDriverName;
WCHAR buffer[MAX_DEVNAME_LENGTH];
PUNICODE_STRING storageDriverName;
ULONG returnedLength;
NTSTATUS status;
if (FILE_DEVICE_DISK != StorageStackDeviceObject->DeviceType)
{
return STATUS_SUCCESS;
}
storageDriverName = (PUNICODE_STRING) buffer;
RtlInitEmptyUnicodeString( storageDriverName, Add2Ptr( storageDriverName, sizeof( UNICODE_STRING ) ), sizeof( buffer ) - sizeof( UNICODE_STRING ) );
status = ObQueryNameString( StorageStackDeviceObject, (POBJECT_NAME_INFORMATION)storageDriverName, storageDriverName->MaximumLength, &returnedLength );
if (!NT_SUCCESS( status ))
{
return status;
}
RtlInitUnicodeString( &volSnapDriverName, L"\\Driver\\VolSnap" );
if (RtlEqualUnicodeString( storageDriverName, &volSnapDriverName, TRUE ))
{
*IsShadowCopy = TRUE;
}
else
{
NOTHING;
}
return STATUS_SUCCESS;
}
else
{
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
if (FILE_DEVICE_VIRTUAL_DISK != StorageStackDeviceObject->DeviceType)
{
return STATUS_SUCCESS;
}
KeInitializeEvent( &event, NotificationEvent, FALSE );
/*
*Microsoft WDK官方文档对 IOCTL_DISK_IS_WRITABLE是这样解释的:
*Determines whether a disk is writable.
*The Status field can be set to STATUS_SUCCESS, or possibly to STATUS_INSUFFICIENT_RESOURCES, STATUS_IO_DEVICE_ERROR, or STATUS_MEDIA_WRITE_PROTECTED.
*
*IOCTL_DISK_IS_WRITABLE是没有输入也没有输出的。
*/
irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_IS_WRITABLE,
StorageStackDeviceObject,
NULL,
0,
NULL,
0,
FALSE,
&event,
&iosb );
if (irp == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver( StorageStackDeviceObject, irp );
if (status == STATUS_PENDING)
{
(VOID)KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
NULL );
status = iosb.Status;
}
if (STATUS_MEDIA_WRITE_PROTECTED == status)
{
*IsShadowCopy = TRUE;
status = STATUS_SUCCESS;
}
return status;
}
#endif
}
上面的代码可以全部复制下来,并编译通过。
我是在WDK7600.16385.1环境下顺利编译通过的。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课