📄 sfilter.c
字号:
/*++
Copyright (c) 1989-2004 Microsoft Corporation
Module Name:
sfilter.c
Abstract:
This module contains the code that implements the general purpose sample
file system filter driver.
As of the Windows XP SP1 IFS Kit version of this sample and later, this
sample can be built for each build environment released with the IFS Kit
with no additional modifications. To provide this capability, additional
compile-time logic was added -- see the '#if WINVER' locations. Comments
tagged with the 'VERSION NOTE' header have also been added as appropriate to
describe how the logic must change between versions.
If this sample is built in the Windows XP environment or later, it will run
on Windows 2000 or later. This is done by dynamically loading the routines
that are only available on Windows XP or later and making run-time decisions
to determine what code to execute. Comments tagged with 'MULTIVERISON NOTE'
mark the locations where such logic has been added.
Environment:
Kernel mode
--*/
// 修复涉及后视列表的Win2K兼容性
// Fixes Win2K compatibility regarding lookaside lists.
//
#ifndef _WIN2K_COMPAT_SLIST_USAGE
#define _WIN2K_COMPAT_SLIST_USAGE
#endif
#include "ntifs.h"
#include "ntdddisk.h"
#include "namelookup.h"
// 在代码中开启这些警告
// Enable these warnings in the code.
//
#pragma warning(error:4100) // Unreferenced formal parameter 未被引用的正式参数
#pragma warning(error:4101) // Unreferenced local variable 未被引用的局部参数
/////////////////////////////////////////////////////////////////////////////
//
// Macro and Structure Definitions
//
/////////////////////////////////////////////////////////////////////////////
//
// VERSION NOTE:
// 下面的宏在Windows XP及以后OS中的NTIFS.H中被定义,如果我们在Windows 2000环境下编译加上这些定义
// The following useful macros are defined in NTIFS.H in Windows XP and later.
// We will define them locally if we are building for the Windows 2000
// environment.
//
#if WINVER == 0x0500
// 用于测试、设置、清除标志
// These macros are used to test, set and clear flags respectively
//
// 打开标志
#ifndef FlagOn
#define FlagOn(_F,_SF) ((_F) & (_SF))
#endif
// 测试标志是否打开
#ifndef BooleanFlagOn
#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0))
#endif
// 设置标志
#ifndef SetFlag
#define SetFlag(_F,_SF) ((_F) |= (_SF))
#endif
// 清除标志
#ifndef ClearFlag
#define ClearFlag(_F,_SF) ((_F) &= ~(_SF))
#endif
#define RtlInitEmptyUnicodeString(_ucStr,_buf,_bufSize) \
((_ucStr)->Buffer = (_buf), \
(_ucStr)->Length = 0, \
(_ucStr)->MaximumLength = (USHORT)(_bufSize))
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
//
// We want ASSERT defined as an expression, which was fixed after Windows 2000
//
#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) )
#endif /* WINVER == 0x0500 */
#ifndef Add2Ptr
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
#endif
// 在堆栈上的局部名字的缓冲尺寸
// Buffer size for local names on the stack
//
#define MAX_DEVNAME_LENGTH 64
// 限制的最大路径长度
//
#define MAX_PATH 512
// 系统加密信息目录
//
// 加密位尺寸,设置加密位共128*8个位,即128字节
#define ENCRYPT_BIT_SIZE (128 * 8)
#define SF_ENCRYPT_INFO_DIR L"System Encrypt Information"
#define SF_ENCRYPT_INFOR_DIR_LENGTH 26
// 规则文件的文件名
//
#define RULE_FILE_NAME L"\\SystemRoot\\xefs_c.dat"
#if DBG
#define DEBUG_VOLUME L'C'
#endif
#define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof(s), s }
/*
typedef struct _FILE_OBJECT {
CSHORT Type;
CSHORT Size;
PDEVICE_OBJECT DeviceObject;
PVPB Vpb;
PVOID FsContext;
PVOID FsContext2;
PSECTION_OBJECT_POINTERS SectionObjectPointer;
PVOID PrivateCacheMap;
NTSTATUS FinalStatus;
struct _FILE_OBJECT *RelatedFileObject;
BOOLEAN LockOperation;
BOOLEAN DeletePending;
BOOLEAN ReadAccess;
BOOLEAN WriteAccess;
BOOLEAN DeleteAccess;
BOOLEAN SharedRead;
BOOLEAN SharedWrite;
BOOLEAN SharedDelete;
ULONG Flags;
UNICODE_STRING FileName;
LARGE_INTEGER CurrentByteOffset;
ULONG Waiters;
ULONG Busy;
PVOID LastLock;
KEVENT Lock;
KEVENT Event;
PIO_COMPLETION_CONTEXT CompletionContext;
} FILE_OBJECT;
typedef struct _FILE_OBJECT *PFILE_OBJECT; // ntndis
*/
typedef struct _FILE_CONTEXT
{
PVOID FsContext;
ULONG RefCount;
// 是否读时解密
BOOLEAN DecryptOnRead;
// 是否写时加密
BOOLEAN EncryptOnWrite;
BOOLEAN EncryptFlagExist; // if encrypt flag file exists, then the file is encrypted
// 如果加密标志存在,那么文件被加密
// 需要加密
BOOLEAN NeedEncrypt;
KEVENT Event;
WCHAR Name[MAX_PATH];
//转换成字节数,表明从最终形成'\??\i:\System Encrypt Information\System Volume Information'的文件中读入的加密位的字节长度
UCHAR EncryptExtData[ENCRYPT_BIT_SIZE / sizeof(UCHAR)];
} FILE_CONTEXT, *PFILE_CONTEXT;
// 我们驱动的设备扩展。注意相同的扩展用于下面类型的设备对象
// - 我们附着的文件系统设备对象
// - 我们附着的被安装的卷设备对象
// Device extension definition for our driver. Note that the same extension
// is used for the following types of device objects:
// - File system device object we attach to
// - Mounted volume device objects we attach to
//
typedef struct _SFILTER_DEVICE_EXTENSION {
// NL_DEVICE_EXTENSION_HEADER包含所有由名字查找库需要的字段。
// 它正好包含SFilter需要的用于它的设备扩展的所有字段
// NL_DEVICE_EXTENSION_HEADER contains all the fields that are needed by
// the name lookup library. It happens to contain all fields SFilter needs
// for its device extension.
//
NL_DEVICE_EXTENSION_HEADER NLExtHeader;
// 这个设备的局部标志
// Local flags for this device
//
ULONG Flags;
RTL_GENERIC_TABLE FsCtxTable;
FAST_MUTEX FsCtxTableMutex;
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;
typedef struct _POST_CREATE_WORKER_CONTEXT
{
WORK_QUEUE_ITEM WorkItem;
KEVENT Event;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PFILE_CONTEXT FileContext;
BOOLEAN NewElement;
} POST_CREATE_WORKER_CONTEXT, *PPOST_CREATE_WORKER_CONTEXT;
typedef struct _READ_WRITE_COMPLETION_CONTEXT
{
PMDL OldMdl;
PVOID OldUserBuffer;
PVOID OldSystemBuffer;
PVOID OldBuffer;
PVOID MyBuffer;
ULONG Length;
} READ_WRITE_COMPLETION_CONTEXT, *PREAD_WRITE_COMPLETION_CONTEXT;
typedef struct _POST_SET_INFORMATION_WORKER_CONTEXT
{
WORK_QUEUE_ITEM WorkItem;
KEVENT Event;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PFILE_CONTEXT FileContext;
PWCHAR FileName;
PWCHAR TargetFileName;
BOOLEAN Delete;
} POST_SET_INFORMATION_WORKER_CONTEXT, *PPOST_SET_INFORMATION_WORKER_CONTEXT;
typedef CSHORT NODE_TYPE_CODE;
typedef NODE_TYPE_CODE *PNODE_TYPE_CODE;
// 如果设置,禁止在这个卷上的所有特定的调试选项
// If set, disable all special debug options on this volume
//
#define SFDEVFL_DISABLE_VOLUME 0x00000001
//fs node type
#define FAT_NTC_FCB 0x0502
#define FAT_NTC_DCB 0x0503
#define FAT_NTC_ROOT_DCB 0x0504
#define NTFS_NTC_DCB 0x0703
#define NTFS_NTC_ROOT_DCB 0x0704
#define NTFS_NTC_FCB 0x0705
#ifndef NodeType
//
// So all records start with
//
// typedef struct _RECORD_NAME {
// NODE_TYPE_CODE NodeTypeCode;
// NODE_BYTE_SIZE NodeByteSize;
// :
// } RECORD_NAME;
// typedef RECORD_NAME *PRECORD_NAME;
//
#define NodeType(Ptr) (*((PNODE_TYPE_CODE)(Ptr)))
#endif
// 这个结构含有我们需要为FSCTRLs传递到完成处理的信息
// This structure contains the information we need to pass to the completion
// processing for FSCTRLs.
//
typedef struct _FSCTRL_COMPLETION_CONTEXT {
// 如果这个完成处理需要在一个工作线程中完成,用我们的上下文和工作例程初始化的workitem
// The workitem that will be initialized with our context and
// worker routine if this completion processing needs to be completed
// in a worker thread.
//
WORK_QUEUE_ITEM WorkItem;
//
// The device object to which this device is currently directed.
//
PDEVICE_OBJECT DeviceObject;
// 这个FSCTRL操作的IRP
// The IRP for this FSCTRL operation.
//
PIRP Irp;
// 对于卷安装操作,我们已经分配且部分初始化的我们将附着到被成功安装的卷的新设备对象
// For mount operations, the new device object that we have allocated
// and partially initialized that we will attach to the mounted volume
// if the mount is successful.
//
PDEVICE_OBJECT NewDeviceObject;
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;
#define POLICY_NONE 0x0
#define POLICY_ENCRYPT 0x1
#define POLICY_END 0xFFFFFFFF
typedef struct _RULE
{
// 规则策略码
ULONG Policy;
// 匹配规则,可以含有通配符 * ?
WCHAR Pattern[MAX_PATH];
} RULE, *PRULE;
// 用于测试是否我们设备对象的宏
// Macro to test if this is my device object
//
#define IS_MY_DEVICE_OBJECT(_devObj) \
(((_devObj) != NULL) && \
((_devObj)->DriverObject == gSFilterDriverObject) && \
((_devObj)->DeviceExtension != NULL))
// 用于测试是否我们的控制设备对象的宏
// Macro to test if this is my control device object
//
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
(((_devObj) == gSFilterControlDeviceObject) ? \
(ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && \
((_devObj)->DeviceExtension == NULL)), TRUE) : \
FALSE)
// 测试我们想附着到的设备类型的宏
// Macro to test for device types we want to attach to
//
#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处理例程有效的宏
// Macro to test if FAST_IO_DISPATCH handling routine is valid
//
#define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \
(((_FastIoDispatchPtr) != NULL) && \
(((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
(FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \
((_FastIoDispatchPtr)->_FieldName != NULL))
#if WINVER >= 0x0501
//
// MULTIVERSION NOTE:
// 动态输入函数的原型的函数指针
// If built in the Windows XP environment or later, we will dynamically import
// the function pointers for routines that were not supported on Windows 2000
// so that we can build a driver that will run, with modified logic, on
// Windows 2000 or later.
//
// Below are the prototypes for the function pointers that we need to
// dynamically import because not all OS versions support these routines.
//
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
);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -