📄 sfilter.c
字号:
/*++
Copyright (c) 1989-1993 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 // Add content(增加内容)
#define _WIN2K_COMPAT_SLIST_USAGE
#endif
#include "ntifs.h"
#include "ntdddisk.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
// Add content(增加内容)******
// 限制的最大路径长度 + 系统加密信息目录
#define MAX_PATH 512
// 加密位尺寸,设置加密位共128*8个位,即128字节
#define ENCRYPT_BIT_SIZE (128 * 8)
#define SF_ENCRYPT_POSTFIX L".$encrypt$"
#define SF_ENCRYPT_POSTFIX_LENGTH 10
// 规则文件的文件名
#define RULE_FILE_NAME L"\\SystemRoot\\xefs.dat"
#if DBG
#define DEBUG_VOLUME L'D' // L'G'
#endif
/*
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_HDR
{
PVOID FsContext;
} FILE_CONTEXT_HDR, *PFILE_CONTEXT_HDR;
typedef struct _FILE_CONTEXT
{
FILE_CONTEXT_HDR;
ULONG RefCount;
BOOLEAN DecryptOnRead; // 是否读时解密
BOOLEAN EncryptOnWrite; // 是否写时加密
BOOLEAN EncryptFlagExist; // 如果加密标志存在,那么文件被加密,if encrypt flag file exists, then the file is encrypted
BOOLEAN NeedEncrypt; // 需要加密
BOOLEAN DeleteOnClose;
KEVENT Event;
WCHAR Name[MAX_PATH]; // 转换成字节数,// 表明从最终形成'\??\i:\System Encrypt Information\System Volume Information'的文件中读入的加密位的字节长度
UCHAR EncryptExtData[ENCRYPT_BIT_SIZE / sizeof(UCHAR)];
} FILE_CONTEXT, *PFILE_CONTEXT;
// Add content(增加内容)******
//
// 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
{
//
// Pointer to the file system device object we are attached to
//
PDEVICE_OBJECT AttachedToDeviceObject;
//
// Pointer to the real (disk) device object that is associated with
// the file system device object we are attached to
//
PDEVICE_OBJECT StorageStackDeviceObject;
//
// Name for this device. If attached to a Volume Device Object it is the
// name of the physical disk drive. If attached to a Control Device
// Object it is the name of the Control Device Object.
//
UNICODE_STRING DeviceName;
//
// Buffer used to hold the above unicode strings
//
WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];
WCHAR DriveLetter; // Add content(增加内容)
RTL_GENERIC_TABLE FsCtxTable; // Add content(增加内容)
FAST_MUTEX FsCtxTableMutex; // Add content(增加内容)
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;
//
// 这个结构含有我们需要为FSCTRLs传递到完成处理的信息
// This structure contains the information we need to pass to the completion
// processing for FSCTRLs.
//
typedef struct _FSCTRL_COMPLETION_CONTEXT
{
//
// The workitem that will be initialized with our context and
// worker routine if this completion processing needs to be completed
// in a worker thread.
// 如果这个完成处理需要在一个工作线程中完成,用我们的上下文和工作例程初始化的workitem
//
WORK_QUEUE_ITEM WorkItem;
//
// The device object to which this device is currently directed.
//
PDEVICE_OBJECT DeviceObject;
//
// The IRP for this FSCTRL operation.
// 这个FSCTRL操作的IRP
//
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;
typedef struct _POST_CREATE_WORKER_CONTEXT // Add content(增加内容)
{
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 // Add content(增加内容)
{
PMDL OldMdl;
PVOID OldUserBuffer;
PVOID OldSystemBuffer;
PMDL MdlForUserBuffer;
PVOID OldBuffer;
PVOID MyBuffer;
ULONG Length;
} READ_WRITE_COMPLETION_CONTEXT, *PREAD_WRITE_COMPLETION_CONTEXT;
typedef struct _POST_SET_INFORMATION_WORKER_CONTEXT // Add content(增加内容)
{
WORK_QUEUE_ITEM WorkItem;
KEVENT Event;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject;
PFILE_CONTEXT FileContext;
PWCHAR FileName;
PWCHAR TargetFileName;
} POST_SET_INFORMATION_WORKER_CONTEXT, *PPOST_SET_INFORMATION_WORKER_CONTEXT;
#define POLICY_NONE 0x0 // Add content(增加内容)
#define POLICY_ENCRYPT 0x1
#define POLICY_END 0xFFFFFFFF
typedef struct _RULE // Add content(增加内容)
{
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))
//
// Macro to test if FAST_IO_DISPATCH handling routine is valid
// 测试是否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))
#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
);
typedef
NTSTATUS
(* PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE)(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject
);
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
NTSTATUS
(* PSF_GET_DISK_DEVICE_OBJECT)(
IN PDEVICE_OBJECT FileSystemDeviceObject,
OUT PDEVICE_OBJECT *DiskDeviceObject
);
typedef
PDEVICE_OBJECT
(* PSF_GET_ATTACHED_DEVICE_REFERENCE)(
IN PDEVICE_OBJECT DeviceObject
);
typedef
NTSTATUS
(* PSF_GET_VERSION)(
IN OUT PRTL_OSVERSIONINFOW VersionInformation
);
typedef struct _SF_DYNAMIC_FUNCTION_POINTERS
{
//
// The following routines should all be available on Windows XP (5.1) and later.
// 下面这些例程应该在Windows XP (5.1)及以后的操作系统可用
//
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -