今日遇见一个开超市的朋友,真没想到在高校开超市一个月可以达到月净利润50K,相比起我们程序员的工资,真是不可同日而语,这个世道啊,真是做程序员不如经商开超市,
我们高科技的从业者,真是造原子弹不如卖茶叶蛋。
请见代码详细注释
// 修复涉及后视列表的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'H' // 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;
PSF_GET_ATTACHED_DEVICE_REFERENCE GetAttachedDeviceReference;
PSF_GET_VERSION GetVersion;
} SF_DYNAMIC_FUNCTION_POINTERS, *PSF_DYNAMIC_FUNCTION_POINTERS;
SF_DYNAMIC_FUNCTION_POINTERS gSfDynamicFunctions = {NULL};
//
// MULTIVERSION NOTE: For this version of the driver, we need to know the
// current OS version while we are running to make decisions regarding what
// logic to use when the logic cannot be the same for all platforms. We
// will look up the OS version in DriverEntry and store the values
// in these global variables.
//
// 在DriverEntry中查找OS版本且存储值在这些全局变量中
ULONG gSfOsMajorVersion = 0;
ULONG gSfOsMinorVersion = 0;
//
// Here is what the major and minor versions should be for the various OS versions:
// 这里是各种OS对应的主次版本号
//
// OS Name MajorVersion MinorVersion
// ---------------------------------------------------------------------
// Windows 2000 5 0
// Windows XP 5 1
// Windows Server 2003 5 2
//
#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))
#endif
//
// TAG identifying memory SFilter allocates
// 标识SFilter分配内存的标记
//
#define SFLT_POOL_TAG 'tlFS'
//
// This structure and these routines are used to retrieve the name of a file
// object. To prevent allocating memory every time we get a name this
// structure contains a small buffer (which should handle 90+% of all names).
// If we do overflow this buffer we will allocate a buffer big enough
// for the name.
//
typedef struct _GET_NAME_CONTROL
{
PCHAR allocatedBuffer;
CHAR smallBuffer[256];
} GET_NAME_CONTROL, *PGET_NAME_CONTROL;
PUNICODE_STRING
SfGetFileName(
IN PFILE_OBJECT FileObject,
IN NTSTATUS CreateStatus,
IN OUT PGET_NAME_CONTROL NameControl
);
VOID
SfGetFileNameCleanup(
IN OUT PGET_NAME_CONTROL NameControl
);
//
// Macros for SFilter DbgPrint levels.
// 用于SFilter DbgPrint级的宏
//
#define SF_LOG_PRINT(_dbgLevel, _string) /
(FlagOn(SfDebug,(_dbgLevel)) ? /
DbgPrint _string : /
((void)0))
//
// Delay values for KeDelayExecutionThread()
// (Values are negative to represent relative time)
// 用于KeDelayExecutionThread()的延迟值,(负值代表相对时间)
//
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Global variables
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Holds pointer to the driver object for this driver
// 保持用于这个驱动的驱动对象的指针
//
PDRIVER_OBJECT gSFilterDriverObject = NULL;
//
// Holds pointer to the device object that represents this driver and is used
// by external programs to access this driver. This is also known as the
// "control device object".
// 保持代表这个驱动的且由外部程序使用存取这个驱动的设备对象的指针。
// 这也就是所谓的"control device object"
//
PDEVICE_OBJECT gSFilterControlDeviceObject = NULL;
//
// This lock is used to synchronize our attaching to a given device object.
// This lock fixes a race condition where we could accidently attach to the
// same device object more then once. This race condition only occurs if
// a volume is being mounted at the same time as this filter is being loaded.
// This problem will never occur if this filter is loaded at boot time before
// any file systems are loaded.
//
// This lock is used to atomically test if we are already attached to a given
// device object and if not, do the attach.
//
// 用于同步我们的附着到给定设备对象的锁
// 这个锁修正我们可能偶然附着到相同设备对象多次的竞争条件。这个竞争条件仅发生在
// 卷被安装的同时这个过滤器被载入。
// 这个问题当这个过滤器在任何文件系统被载入前就在启动时被载入的情况下不会发生
// 这个锁被用于自动测试是否我们已经附着到给定的设备对象且如果没有,执行附着。
FAST_MUTEX gSfilterAttachLock;
// Add content(增加内容)******
PAGED_LOOKASIDE_LIST gFileNameLookAsideList;
PAGED_LOOKASIDE_LIST gFsCtxLookAsideList;
NPAGED_LOOKASIDE_LIST gReadWriteCompletionCtxLookAsideList;
PRULE gRules = NULL;
ERESOURCE gRulesResource;
HANDLE gRuleFileHandle = NULL;
UCHAR gKey[128] = {0};
#define FSCTX_GENERIC_TABLE_POOL_SIZE sizeof(FILE_CONTEXT) + 32
// Add content(增加内容)******
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Debug Definitions
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// DEBUG display flags
//
/*
#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
ULONG SfDebug = 0;
*/
// 显示我们附着到的设备对象的名字
// Display names of device objects we attach to.
//
#define SFDEBUG_DISPLAY_ATTACHMENT_NAMES 0x00000001 // display names of device objects we attach to
// 得到文件名(在创建期间)且显示他们(创建完成)
// Get file names (during create) and display them (create completion).
//
#define SFDEBUG_DISPLAY_CREATE_NAMES 0x00000002 // get and display names during create
// 得到文件名但不显示他们(在创建期间)
// Get file names but don't display them (during create).
//
#define SFDEBUG_GET_CREATE_NAMES 0x00000004 // get name (don't display) during create
// 执行创建完成例程,忽略名字显示
// Do create completion routine, regardless of name display.
//
#define SFDEBUG_DO_CREATE_COMPLETION 0x00000008 // do create completion routine, don't get names
// 执行附着到FSRecognizer设备对象
// Do attach to FSRecognizer device objects.
//
#define SFDEBUG_ATTACH_TO_FSRECOGNIZER 0x00000010 // do attach to FSRecognizer device objects
// 执行附着到ShadowCopy卷设备对象--他们仅在Windows XP及以后OS发生
// Do attach to ShadowCopy Volume device objects -- they are only around on
// Windows XP and later.
//
#define SFDEBUG_ATTACH_TO_SHADOW_COPIES 0x00000020 // do attach to ShadowCopy Volume device objects -- they are only around on Windows XP and later
// 执行得到和使用DOS设备名字用于文件名的显示
// Do get and use DOS device names for file name display.
//
//#define SFDEBUG_GET_DOS_NAMES 0x00000040
// 在清除/关闭时间显示信息
// Display information at cleanup/close time
//
//#define SFDEBUG_DISPLAY_CLEANUPCLOSE_NAMES 0x00000080
// 保持调试状态的全局变量
// Global which holds debug state
//
ULONG SfDebug = 0;
//
// Given a device type, return a valid name
// 给出一个设备类型,返回一个有效名字
//
#define GET_DEVICE_TYPE_NAME(_type) /
((((_type) > 0) && ((_type) < (sizeof(DeviceTypeNames) / sizeof(PCHAR)))) ? /
DeviceTypeNames[ (_type) ] : /
"[Unknown]")
//
// Known device type names
// 已知设备类名称
//
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"
};
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Function Prototypes
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
int __cdecl
swprintf(wchar_t *, const wchar_t *, ...); // Add content(增加内容)
//
// Define driver entry routine.
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
#if DBG && WINVER >= 0x0501
VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
);
#endif
//
// Define the local routines used by this driver module. This includes a
// a sample of how to filter a create file operation, and then invoke an I/O
// completion routine when the file has successfully been created/opened.
//
// 定义由这个驱动模块使用的局部例程。这包括一个如何过滤一个创建文件操作的例子,
// 且然后当文件已经成功被创建/打开时调用一个I/O完成例程
#if WINVER >= 0x0501
VOID
SfLoadDynamicFunctions(
);
VOID
SfGetCurrentVersion(
);
#endif
NTSTATUS
SfPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
SfCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
// 缺少sfCreateCompletion(...)
NTSTATUS
SfCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
// 将 SfCleanupClose(...)分成SfCleanup(...)和SfClose(...).
NTSTATUS
SfClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS // Add content(增加内容)
SfRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS // Add content(增加内容)
SfReadCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS // Add content(增加内容)
SfWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS // Add content(增加内容)
SfWriteCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
NTSTATUS // Add content(增加内容)
SfDirectoryControl (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS // Add content(增加内容)
SfSetInformation (
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
);
VOID
SfFsControlMountVolumeCompleteWorker (
IN PFSCTRL_COMPLETION_CONTEXT Context
);
NTSTATUS
SfFsControlMountVolumeComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PDEVICE_OBJECT NewDeviceObject
);
NTSTATUS
SfFsControlLoadFileSystem (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
SfFsControlLoadFileSystemCompleteWorker (
IN PFSCTRL_COMPLETION_CONTEXT Context
);
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
);
VOID
SfFastIoDetachDevice(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice
);
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
);
#if WINVER >= 0x0501 /* See comment in DriverEntry */
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
VOID
SfFsNotification(
IN PDEVICE_OBJECT DeviceObject,
IN BOOLEAN FsActive
);
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
);
VOID
SfDetachFromFileSystemDevice(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
SfAttachToMountedDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT SFilterDeviceObject
);
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
);
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
);
VOID
SfReadDriverParameters(
IN PUNICODE_STRING RegistryPath
);
VOID // Add content(增加内容)
SfDriverReinitialization(
IN PDRIVER_OBJECT DriverObject,
IN PVOID Context,
IN ULONG Count
);
NTSTATUS
SfIsShadowCopyVolume (
IN PDEVICE_OBJECT StorageStackDeviceObject,
OUT PBOOLEAN IsShadowCopy
);
BOOLEAN // Add content(增加内容)
SfDissectFileName(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT PWSTR FileName
);
RTL_GENERIC_COMPARE_RESULTS // Add content(增加内容)
SfGenericCompareRoutine(
IN PRTL_GENERIC_TABLE Table,
IN PVOID FirstStruct,
IN PVOID SecondStruct
);
PVOID // Add content(增加内容)
SfGenericAllocateRoutine(
IN PRTL_GENERIC_TABLE Table,
IN CLONG ByteSize
);
VOID // Add content(增加内容)
SfGenericFreeRoutine(
IN PRTL_GENERIC_TABLE Table,
IN PVOID Buffer
);
NTSTATUS // Add content(增加内容)
SfIsEncryptFlagExist(
IN PDEVICE_OBJECT DeviceObject,
IN PCWSTR FileName,
OUT PBOOLEAN Encrypted,
OUT PVOID Data,
IN ULONG DataLength
);
NTSTATUS // Add content(增加内容)
SfIsFileNeedEncrypt(
IN PDEVICE_OBJECT DeviceObject,
IN PCWSTR FileName,
OUT PBOOLEAN NeedEncrypt
);
NTSTATUS // Add content(增加内容)
SfSetFileEncrypted(
IN PDEVICE_OBJECT DeviceObject,
IN PCWSTR FileName,
IN BOOLEAN IsEncrypted,
IN PVOID Data,
IN ULONG DataLength
);
NTSTATUS // Add content(增加内容)
SfUpdateFileByFileObject(
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject
);
NTSTATUS // Add content(增加内容)
SfIssueReadWriteIrpSynchronously(
IN PDEVICE_OBJECT DeviceObject,
IN PFILE_OBJECT FileObject,
IN ULONG MajorFunction,
IN PIO_STATUS_BLOCK IoStatus,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset,
IN ULONG IrpFlags
);
NTSTATUS // Add content(增加内容)
SfIssueCleanupIrpSynchronously(
IN PDEVICE_OBJECT NextDeviceObject,
IN PIRP Irp,
IN PFILE_OBJECT FileObject
);
NTSTATUS // Add content(增加内容)
SfCreateFile(
IN PCWSTR FileName,
IN ULONG FileAttributes,
IN BOOLEAN IsFile
);
NTSTATUS // Add content(增加内容)
SfRenameFile(
IN PWSTR SrcFileName,
IN PWSTR DstFileName
);
NTSTATUS // Add content(增加内容)
SfForwardIrpSyncronously(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS // Add content(增加内容)
SfLoadRules(
OUT PHANDLE FileHandle
);
ULONG // Add content(增加内容)
SfMatchRules(
IN PCWSTR FileName
);
BOOLEAN // Add content(增加内容)
SfMatchWithPattern(
IN PCWSTR Pattern,
IN PCWSTR Name
);
BOOLEAN // Add content(增加内容)
SfMatchOkay(
IN PCWSTR Pattern
);
BOOLEAN // Add content(增加内容)
SfIsObjectFile(
IN PFILE_OBJECT FileObject
);
NTSTATUS // Add content(增加内容)
SfQuerySymbolicLink(
IN PUNICODE_STRING SymbolicLinkName,
OUT PUNICODE_STRING LinkTarget
);
NTSTATUS // Add content(增加内容)
SfVolumeDeviceNameToDosName(
IN PUNICODE_STRING VolumeDeviceName,
OUT PUNICODE_STRING DosName
);
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Assign text sections for each routine.
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#if DBG && WINVER >= 0x0501
#pragma alloc_text(PAGE, DriverUnload)
#endif
#pragma alloc_text(PAGE, SfFsNotification)
#pragma alloc_text(PAGE, SfCreate)
#pragma alloc_text(PAGE, SfCleanup) // Add content(增加内容)
#pragma alloc_text(PAGE, SfClose)
#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, SfReadDriverParameters) // 缺少
#pragma alloc_text(PAGE, SfDriverReinitialization) // Add content(增加内容)
#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
#pragma alloc_text(PAGE, SfQuerySymbolicLink) // Add content(增加内容)
#pragma alloc_text(PAGE, SfVolumeDeviceNameToDosName) // Add content(增加内容)
#endif
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Functions
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
// 创建设备对象且登记它监视所有的活动文件系统
This is the initialization routine for the SFILTER file system filter
driver. This routine creates the device object that represents this
driver in the system and registers it for watching all file systems that
register or unregister themselves as active file systems.
Arguments:
DriverObject - Pointer to driver object created by the system.
Return Value:
The function value is the final status from the initialization operation.
--*/
{
PFAST_IO_DISPATCH FastIoDispatch;
UNICODE_STRING NameString;
NTSTATUS Status;
ULONG i;
UNREFERENCED_PARAMETER(RegistryPath);
#if WINVER >= 0x0501
//
// Try to load the dynamic functions that may be available for our use.
// 试图载入动态函数
//
SfLoadDynamicFunctions();
//
// Now get the current OS version that we will use to determine what logic
// paths to take when this driver is built to run on various OS version.
// 得到OS版本
//
SfGetCurrentVersion();
#endif
//
// Save our Driver Object, set our UNLOAD routine
// 保存我们的驱动对象,设置我们的UNLOAD例程
//
gSFilterDriverObject = DriverObject;
#if DBG && WINVER >= 0x0501
//
// MULTIVERSION NOTE:
//
// We can only support unload for testing environments if we can enumerate
// the outstanding device objects that our driver has.
// 如果我们可以枚举我们驱动拥有的显著的设备对象,仅支持测试环境的卸载
//
//
// Unload is useful for development purposes. It is not recommended for
// production versions
// 卸载只用于开发环境
//
if (NULL != gSfDynamicFunctions.EnumerateDeviceObjectList)
gSFilterDriverObject->DriverUnload = DriverUnload;
#endif
// 初始化一个资源变量,可被用于同步一线程集合,
// 在释放资源占用内存前调用ExDeleteResourceLite
//
Status = ExInitializeResourceLite(&gRulesResource);
if (!NT_SUCCESS(Status))
{
KdPrint(("SFilter!DriverEntry: ExInitializeResourceLite failed, Status=%08x/n", Status));
return Status;
}
//
// Setup other global variables
// 设置其它全局变量
//
ExInitializeFastMutex(&gSfilterAttachLock);
ExInitializePagedLookasideList(
&gFsCtxLookAsideList,
NULL,
NULL,
0,
FSCTX_GENERIC_TABLE_POOL_SIZE,
SFLT_POOL_TAG,
0
);
ExInitializePagedLookasideList(
&gFileNameLookAsideList,
NULL,
NULL,
0,
MAX_PATH * sizeof(WCHAR),
SFLT_POOL_TAG,
0
);
ExInitializeNPagedLookasideList(
&gReadWriteCompletionCtxLookAsideList,
NULL,
NULL,
0,
sizeof(READ_WRITE_COMPLETION_CONTEXT),
SFLT_POOL_TAG,
0
);
//
// Create the Control Device Object (CDO). This object represents this
// driver. Note that it does not have a device extension.
// 创建控制设备对象,这个对象代表这个驱动。注意它没有设备扩展。
//
RtlInitUnicodeString(&NameString, L"//FileSystem//Filters//SFilterCDO");
Status = IoCreateDevice(
DriverObject,
0, // has no device extension
&NameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gSFilterControlDeviceObject
);
if (Status == STATUS_OBJECT_PATH_NOT_FOUND)
{
//
// This must be a version of the OS that doesn't have the Filters
// path in its namespace. This was added in Windows XP.
//
// We will try just putting our control device object in the /FileSystem
// portion of the object name space.
// XP以前的版本名字空间中未加入Filters路径,所以将我们的控制设备对象放入
// 对象名字空间的/FileSystem部分
//
RtlInitUnicodeString(&NameString, L"//FileSystem//SFilterCDO");
Status = IoCreateDevice(
DriverObject,
0, // has no device extension
&NameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gSFilterControlDeviceObject
);
if (!NT_SUCCESS(Status))
{
KdPrint(("SFilter!DriverEntry: Error creating control device object /"%wZ/", Status=%08x/n", &NameString, Status));
ExDeleteResourceLite(&gRulesResource);
return Status;
}
}
else if (!NT_SUCCESS(Status))
{
KdPrint(("SFilter!DriverEntry: Error creating control device object /"%wZ/", Status=%08x/n", &NameString, Status));
ExDeleteResourceLite(&gRulesResource);
return Status;
}
//
// Initialize the driver object with this device driver's entry points.
//
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = SfPassThrough;
}
//
// We will use SfCreate for all the create operations
//
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] = SfCleanup;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfClose;
DriverObject->MajorFunction[IRP_MJ_READ] = SfRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = SfWrite;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = SfDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = SfSetInformation;
//
// Allocate fast I/O data structure and fill it in.
// 分配快速I/O数据结构且填入它
//
// NOTE: The following FastIo Routines are not supported:
// AcquireFileForNtCreateSection
// ReleaseFileForNtCreateSection
// AcquireForModWrite
// ReleaseForModWrite
// AcquireForCcFlush
// ReleaseForCcFlush
//
// For historical reasons these FastIO's have never been sent to filters
// by the NT I/O system. Instead, they are sent directly to the base
// file system. On Windows XP and later OS releases, you can use the new
// system routine "FsRtlRegisterFileSystemFilterCallbacks" if you need to
// intercept these callbacks (see below).
// 由于历史的原因,这些快速IO不发送到过滤驱动,而是直接发送到基础文件系统。
// 在WINXP及以后版本,如果你想拦截这些回调,你可以使用新的系
// 统例程FsRtlRegisterFileSystemFilterCallbacks
//
FastIoDispatch = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_IO_DISPATCH), SFLT_POOL_TAG);
if (!FastIoDispatch)
{
IoDeleteDevice(gSFilterControlDeviceObject);
ExDeleteResourceLite(&gRulesResource);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(FastIoDispatch, sizeof(FAST_IO_DISPATCH));
FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;
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;
DriverObject->FastIoDispatch = FastIoDispatch;
//
// VERSION NOTE:
//
// There are 6 FastIO routines for which file system filters are bypassed as
// the requests are passed directly to the base file system. These 6 routines
// are AcquireFileForNtCreateSection, ReleaseFileForNtCreateSection,
// AcquireForModWrite, ReleaseForModWrite, AcquireForCcFlush, and
// ReleaseForCcFlush.
//
// In Windows XP and later, the FsFilter callbacks were introduced to allow
// filters to safely hook these operations. See the IFS Kit documentation for
// more details on how these new interfaces work.
//
// MULTIVERSION NOTE:
//
// If built for Windows XP or later, this driver is built to run on
// multiple versions. When this is the case, we will test
// for the presence of FsFilter callbacks registration API. If we have it,
// then we will register for those callbacks, otherwise, we will not.
//
#if WINVER >= 0x0501
{
FS_FILTER_CALLBACKS FsFilterCallbacks;
if (NULL != gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)
{
//
// Setup the callbacks for the operations we receive through
// the FsFilter interface.
// 为我们通过FsFilter接口接收的操作设置回调
//
// NOTE: You only need to register for those routines you really need
// to handle. SFilter is registering for all routines simply to
// give an example of how it is done.
//
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);
ExDeleteResourceLite(&gRulesResource);
return Status;
}
}
}
#endif
//
// The registered callback routine "SfFsNotification" will be called
// whenever a new file systems is loaded or when any file system is
// unloaded.
// 当一个新的文件系统被装入或者当任何文件系统被卸载时,注册的回调函数
// SfFsNotification将被调用
//
// VERSION NOTE:
//
// On Windows XP and later this will also enumerate all existing file
// systems (except the RAW file systems). On Windows 2000 this does not
// enumerate the file systems that were loaded before this filter was
// loaded.
//
Status = IoRegisterFsRegistrationChange(DriverObject, SfFsNotification);
if (!NT_SUCCESS(Status))
{
KdPrint(("SFilter!DriverEntry: Error registering FS change notification, Status=%08x/n", Status));
DriverObject->FastIoDispatch = NULL;
ExFreePool(FastIoDispatch);
IoDeleteDevice(gSFilterControlDeviceObject);
ExDeleteResourceLite(&gRulesResource);
return Status;
}
//
// Attempt to attach to the appropriate RAW file system device objects
// since they are not enumerated by IoRegisterFsRegistrationChange.
// 试图附着到合适的RAW文件系统设备对象,因为他们没有被IoRegisterFsRegistrationChange枚举
//
{
PDEVICE_OBJECT RawDeviceObject;
PFILE_OBJECT FileObject;
//
// Attach to RawDisk device
// 附着到RawDisk设备
//
RtlInitUnicodeString(&NameString, L"//Device//RawDisk");
Status = IoGetDeviceObjectPointer(
&NameString,
FILE_READ_ATTRIBUTES,
&FileObject,
&RawDeviceObject
);
if (NT_SUCCESS(Status))
{
SfFsNotification(RawDeviceObject, TRUE);
ObDereferenceObject(FileObject);
}
//
// Attach to the RawCdRom device
// 附着到RawCdRom设备
//
RtlInitUnicodeString(&NameString, L"//Device//RawCdRom");
Status = IoGetDeviceObjectPointer(
&NameString,
FILE_READ_ATTRIBUTES,
&FileObject,
&RawDeviceObject
);
if (NT_SUCCESS(Status))
{
SfFsNotification(RawDeviceObject, TRUE);
ObDereferenceObject(FileObject);
}
}
//
// Clear the initializing flag on the control device object since we
// have now successfully initialized everything.
// 清除控制设备对象上的初始化标志,因为我们现在成功完成初始化
//
ClearFlag(gSFilterControlDeviceObject->Flags, DO_DEVICE_INITIALIZING);
IoRegisterDriverReinitialization(DriverObject, SfDriverReinitialization, NULL);
return STATUS_SUCCESS;
}
#if DBG && WINVER >= 0x0501
VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine is called when a driver can be unloaded. This performs all of
the necessary cleanup for unloading the driver from memory. Note that an
error can NOT be returned from this routine.
// 执行所有从内存中卸载驱动必要的清除操作,注意错误不能从这个例程返回
When a request is made to unload a driver the IO System will cache that
information and not actually call this routine until the following states
have occurred:
- All device objects which belong to this filter are at the top of their
respective attachment chains.
- All handle counts for all device objects which belong to this filter have
gone to zero.
// 当发出卸载一个驱动请求,IO系统将缓冲那个信息且不真正调用这个例程直到下面状态发生:
- 所有属于这个过滤的设备对象在他们各自附着链的顶部
- 所有设备对象的句柄计数已经成为0
WARNING: Microsoft does not officially support the unloading of File
System Filter Drivers. This is an example of how to unload
your driver if you would like to use it during development.
This should not be made available in production code.
Arguments:
DriverObject - Driver object for this module
Return Value:
None.
--*/
{
PSFILTER_DEVICE_EXTENSION DevExt;
PFAST_IO_DISPATCH FastIoDispatch;
NTSTATUS Status;
ULONG NumDevices;
ULONG i;
LARGE_INTEGER Interval;
# define DEVOBJ_LIST_SIZE 64
PDEVICE_OBJECT DevList[DEVOBJ_LIST_SIZE];
ASSERT(DriverObject == gSFilterDriverObject);
//
// Log we are unloading
// 我们卸载时做日志
//
SF_LOG_PRINT(SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
("SFilter!DriverUnload: Unloading driver (%p)/n",
DriverObject));
//
// Don't get anymore file system change notifications
// 不得到任何文件系统改变通知
//
IoUnregisterFsRegistrationChange(DriverObject, SfFsNotification);
//
// This is the loop that will go through all of the devices we are attached
// to and detach from them. Since we don't know how many there are and
// we don't want to allocate memory (because we can't return an error)
// we will free them in chunks using a local array on the stack.
// 这是遍历我们附着到的所有设备且断开他们的循环。因为我们不知道有多少且
// 我们不想分配内存(因为我们不能返回错误)。
// 我们将使用堆栈上的本地数组按块释放他们
//
for (;;)
{
//
// Get what device objects we can for this driver. Quit if there
// are not any more. Note that this routine should always be
// defined since this routine is only compiled for Windows XP and
// later.
// 为这个驱动得到设备对象。如果没有了,就退出。注意这个例程应该被定义
// 因为这个例程仅为Windows XP及以后的OS编译。
//
ASSERT(NULL != gSfDynamicFunctions.EnumerateDeviceObjectList);
Status = (gSfDynamicFunctions.EnumerateDeviceObjectList)(
DriverObject,
DevList,
sizeof(DevList),
&NumDevices
);
if (NumDevices <= 0)
break;
NumDevices = min(NumDevices, DEVOBJ_LIST_SIZE);
//
// First go through the list and detach each of the devices.
// Our control device object does not have a DeviceExtension and
// is not attached to anything so don't detach it.
// 首先遍历列表且断开每个设备。我们的控制设备对象没有DeviceExtension
// 且未附着到任何事情,因此不断开它。
//
for (i=0; i < NumDevices; i++)
{
DevExt = DevList[i]->DeviceExtension;
if (NULL != DevExt)
IoDetachDevice(DevExt->AttachedToDeviceObject);
}
//
// The IO Manager does not currently add a reference count to a device
// object for each outstanding IRP. This means there is no way to
// know if there are any outstanding IRPs on the given device.
// We are going to wait for a reasonable amount of time for pending
// irps to complete.
// IO Manager当前不为每个未处理的IRPs增加设备对象的引用计数。这意味着无法知道
// 给定设备是否存在未处理的IRPs.我们将等待合理的时间完成这些IRPs。
// 象opLocks和目录改变通知的重负荷系统,可能发生问题
//
// WARNING: This does not work 100% of the time and the driver may be
// unloaded before all IRPs are completed. This can easily
// occur under stress situations and if a long lived IRP is
// pending (like oplocks and directory change notifications).
// The system will fault when this Irp actually completes.
// This is a sample of how to do this during testing. This
// is not recommended for production code.
//
Interval.QuadPart = (5 * DELAY_ONE_SECOND); // delay 5 seconds
KeDelayExecutionThread(KernelMode, FALSE, &Interval);
//
// Now go back through the list and delete the device objects.
// 现在回到且遍历列表且删除设备对象
//
for (i=0; i < NumDevices; i++)
{
//
// See if this is our control device object. If not then cleanup
// the device extension. If so then clear the global pointer
// that references it.
// 看是否我们的控制设备对象。如果不是那么清除设备扩展。如果是清除引用它的全局指针。
//
if (NULL != DevList[i]->DeviceExtension)
SfCleanupMountedDevice(DevList[i]);
else
{
ASSERT(DevList[i] == gSFilterControlDeviceObject);
gSFilterControlDeviceObject = NULL;
}
//
// Delete the device object, remove reference counts added by
// IoEnumerateDeviceObjectList. Note that the delete does
// not actually occur until the reference count goes to zero.
// 删除设备对象,删除由IoEnumerateDeviceObjectList增加的引用计数。
// 注意删除直到引用计数降到0时才真正发生
//
IoDeleteDevice(DevList[i]);
ObDereferenceObject(DevList[i]);
}
}
//
// Free our FastIO table
// 释放我们的FastIO表
//
FastIoDispatch = DriverObject->FastIoDispatch;
DriverObject->FastIoDispatch = NULL;
ExFreePool(FastIoDispatch);
ExDeletePagedLookasideList(&gFsCtxLookAsideList);
ExDeletePagedLookasideList(&gFileNameLookAsideList);
ExDeleteNPagedLookasideList(&gReadWriteCompletionCtxLookAsideList);
ZwClose(gRuleFileHandle);
ExDeleteResourceLite(&gRulesResource);
if (gRules)
ExFreePoolWithTag(gRules, SFLT_POOL_TAG);
}
#endif
#if WINVER >= 0x0501
VOID
SfLoadDynamicFunctions (
)
/*++
Routine Description:
// 试图载入不是所有操作系统都支持的例程的函数指针。
// 这些函数指针然后被存储于全局结构SpyDynamicFunctions中
This routine tries to load the function pointers for the routines that
are not supported on all versions of the OS. These function pointers are
then stored in the global structure SpyDynamicFunctions.
This support allows for one driver to be built that will run on all
versions of the OS Windows 2000 and greater. Note that on Windows 2000,
the functionality may be limited.
Arguments:
None.
Return Value:
None.
--*/
{
UNICODE_STRING FunctionName;
RtlZeroMemory(&gSfDynamicFunctions, sizeof(gSfDynamicFunctions));
//
// For each routine that we would want to use, lookup its address in the
// kernel or hal. If it is not present, that field in our global
// SpyDynamicFunctions structure will be set to NULL.
// 对于每个我们想使用的例程,在kernel或HAL中查找他的地址。
// 如果不存在,在我们的SpyDynamicFunctions结构中的那个字段将被设置为NULL。
//
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);
}
VOID
SfGetCurrentVersion (
)
/*++
Routine Description:
// 基于可用的正确的例程读当前的OS版本
This routine reads the current OS version using the correct routine based
on what routine is available.
Arguments:
None.
Return Value:
None.
--*/
{
if (NULL != gSfDynamicFunctions.GetVersion)
{
RTL_OSVERSIONINFOW VersionInfo;
NTSTATUS Status;
//
// VERSION NOTE: RtlGetVersion does a bit more than we need, but
// we are using it if it is available to show how to use it. It
// is available on Windows XP and later. RtlGetVersion and
// RtlVerifyVersionInfo (both documented in the IFS Kit docs) allow
// you to make correct choices when you need to change logic based
// on the current OS executing your code.
// RtlGetVersion执行多于我们需要的事情,但如果可用我们使用它以显示如何使用它。
// RtlGetVersion和RtlVerifyVersionInfo允许我们当基于当前OS执行你的代码时执行正确的选择
//
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
)
/*++
Routine Description:
// 当一个文件系统或者被登记或者取消登记自己作为一个活动文件系统时被调用
This routine is invoked whenever a file system has either registered or
unregistered itself as an active file system.
For the former case, this routine creates a device object and attaches it
to the specified file system's device object. This allows this driver
to filter all requests to that file system. Specifically we are looking
for MOUNT requests so we can attach to newly mounted volumes.
// 对于前者,这个历程创建一个设备对象且附着它到指定文件系统的设备对象。
// 这允许这个驱动过滤到那个文件系统的所有请求。尤其是我们查找MOUNT请求,
// 因而我们可以附着到新安装的卷上
For the latter case, this file system's device object is located,
detached, and deleted. This removes this file system as a filter for
the specified file system.
// 对于后者,这个文件系统的设备对象被定位,断开且删除。
// 这删除这个文件系统作为特定文件系统的过滤器
Arguments:
// 文件系统设备对象的指针
DeviceObject - Pointer to the file system's device object.
// 布尔值指示是否文件系统已经登记(TRUE)或者取消登记(FALSE)自己作为一个活动的文件系统
FsActive - Boolean indicating whether the file system has registered
(TRUE) or unregistered (FALSE) itself as an active file system.
Return Value:
None.
--*/
{
UNICODE_STRING Name;
WCHAR NameBuffer[MAX_DEVNAME_LENGTH];
PAGED_CODE();
//
// Init local Name buffer
//
RtlInitEmptyUnicodeString(&Name, NameBuffer, sizeof(NameBuffer));
SfGetObjectName(DeviceObject, &Name);
//
// Display the names of all the file system we are notified of
// 显示我们被通知的所有文件系统的名字
//
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))
);
//
// Handle attaching/detaching from the given file system.
// 处理附着/断开给定文件系统
//
if (FsActive)
SfAttachToFileSystemDevice(DeviceObject, &Name);
else
SfDetachFromFileSystemDevice(DeviceObject);
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// IRP Handling Routines
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
NTSTATUS
SfPassThrough(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the main dispatch routine for the general purpose file
system driver. It simply passes requests onto the next driver in the
stack, which is presumably a disk file system.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
Note:
A note to file system filter implementers:
This routine actually "passes" through the request by taking this
driver out of the IRP stack. If the driver would like to pass the
I/O request through, but then also see the result, then rather than
taking itself out of the loop it could keep itself in by copying the
caller's parameters to the next stack location and then set its own
completion routine.
这个例程通过将这个驱动取出IRP堆栈而真正传递请求,如果驱动想传递I/O请求,
但是想看到结果,那么就不是将自己取出而是通过拷贝调用者的参数到下层堆栈的
方式保持自己处于堆栈中,且然后设置它自己的完成例程。
Hence, instead of calling: // 因此,不用
IoSkipCurrentIrpStackLocation(Irp);
You could instead call: // 而是使用
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
This example actually NULLs out the caller's I/O completion routine, but
this driver could set its own completion routine so that it would be
notified when the request was completed (see SfCreate for an example of
this).
这个例子真正将调用者的I/O完成例程置NULL,但这个驱动可以设置他自己的完成例程
因此当请求完成时它将被通知。
--*/
{
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
//
// Get this driver out of the driver stack and get to the next driver as
// quickly as possible.
// 将这个驱动取出驱动堆栈且尽快到下层驱动
//
IoSkipCurrentIrpStackLocation(Irp);
//
// Call the appropriate file system driver with the request.
// 按请求调用合适的文件系统驱动
//
return IoCallDriver(((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp);
}
NTSTATUS
SfCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
// 这个函数处理创建/打开操作。它简单地建立一个I/O完成例程在操作成功时被调用
This function filters create/open operations. It simply establishes an
I/O completion routine to be invoked if the operation was successful.
Arguments:
DeviceObject - Pointer to the target device object of the create/open.
Irp - Pointer to the I/O Request Packet that represents the operation.
Return Value:
The function value is the status of the call to the file system's entry
point.
--*/
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
PFILE_OBJECT RelatedFileObject = FileObject->RelatedFileObject;
PWSTR FileName = NULL;
PFILE_CONTEXT FileCtxPtr = NULL;
BOOLEAN DeleteOnClose = (BOOLEAN) (IrpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE);
BOOLEAN IsEncryptFlagExist = FALSE;
BOOLEAN IsNeedEncrypt = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS LocalStatus = STATUS_SUCCESS;
PAGED_CODE();
//
// If this is for our control device object, don't allow it to be opened.
// 如果这是我们的控制设备对象,不允许它被打开
//
if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
{
//
// Sfilter doesn't allow for any communication through its control
// device object, therefore it fails all requests to open a handle
// to its control device object.
//
// See the FileSpy sample for an example of how to allow creates to
// the filter's control device object and manage communication via
// that handle.
// Sfilter不允许通过它的控制设备对象进行任何通讯,因此它失败打开他的控制设备对象的句柄
// 的任何请求,看FileSpy例子知道如何允许过滤控制设备对象的创建及通过句柄管理通讯
//
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
//
// We only care about volume filter device object
// 我们仅关心卷过滤设备对象
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
if (DevExt->DriveLetter == L'/0') {
UNICODE_STRING DosName;
Status = SfVolumeDeviceNameToDosName(&DevExt->DeviceName, &DosName);
if (NT_SUCCESS(Status)) {
DevExt->DriveLetter = DosName.Buffer[0];
ExFreePool(DosName.Buffer);
if ((DevExt->DriveLetter >= L'a') && (DevExt->DriveLetter <= L'z')) {
DevExt->DriveLetter += L'A' - L'a';
}
} else {
KdPrint(("sfilter!SfCreate: SfVolumeDeviceNameToDosName(%x) failed(%x)/n",
DevExt->StorageStackDeviceObject, Status));
}
}
//
// Open Volume Device directly
// 直接打开卷设备
//
if ((FileObject->FileName.Length == 0) && !RelatedFileObject)
{
// 打开卷设备时,卷设备对象肯定没有打开,所以必须FileObject->FileName.Length == 0
// 且RelatedFileObject == NULL。
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
do
{
// KdPrint(("sfilter!SfCreate: Entering.../n"));
//
// If the file is opened by id, then we can't get file name directly,
// But if this case happened, the FsContext must be in GenericTable already.
// So we just update the RefCount, that's enough
//
if (!(IrpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID))
{
FileName = ExAllocateFromPagedLookasideList(&gFileNameLookAsideList);
if (!FileName)
{
KdPrint(("sfilter!SfCreate: ExAllocatePoolWithTag failed/n"));
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
if (!SfDissectFileName(DeviceObject, Irp, FileName))
{
KdPrint(("sfilter!SfCreate: SfDissectFileName failed/n"));
Status = STATUS_INVALID_PARAMETER;
break;
}
if (wcslen(FileName) >= SF_ENCRYPT_POSTFIX_LENGTH)
{
if (_wcsnicmp(&FileName[wcslen(FileName) - SF_ENCRYPT_POSTFIX_LENGTH],
SF_ENCRYPT_POSTFIX, SF_ENCRYPT_POSTFIX_LENGTH) == 0)
{
//
// We deny all create request to our encrypt falg file except kernel mode
//
if (KernelMode == Irp->RequestorMode)
{
ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
else
{
Status = STATUS_SUCCESS;
break;
}
}
}
}
FileCtxPtr = ExAllocatePoolWithTag(PagedPool, sizeof(FILE_CONTEXT), SFLT_POOL_TAG);
if (FileCtxPtr == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
Status = SfForwardIrpSyncronously(DevExt->AttachedToDeviceObject, Irp);
if (NT_SUCCESS(Status) && (STATUS_REPARSE != Status) && SfIsObjectFile(FileObject))
{
PFILE_CONTEXT FileCtxPtr2 = NULL;
BOOLEAN NewElement = FALSE;
FileCtxPtr->FsContext = FileObject->FsContext;
ExAcquireFastMutex(&DevExt->FsCtxTableMutex);
FileCtxPtr2 = RtlLookupElementGenericTable(&DevExt->FsCtxTable, FileCtxPtr);
if (FileCtxPtr2)
++FileCtxPtr2->RefCount;
else
{
FileCtxPtr2 = RtlInsertElementGenericTable(
&DevExt->FsCtxTable,
FileCtxPtr,
sizeof(FILE_CONTEXT),
&NewElement
);
FileCtxPtr2->RefCount = 1;
ASSERT(FileName);
wcscpy(FileCtxPtr2->Name, FileName);
KeInitializeEvent(&FileCtxPtr2->Event, SynchronizationEvent, TRUE);
}
FileCtxPtr2->DeleteOnClose = DeleteOnClose;
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
IsEncryptFlagExist = FALSE;
IsNeedEncrypt = FALSE;
LocalStatus = STATUS_SUCCESS;
KdPrint(("sfilter!SfCreate: FileName = %ws/n", FileCtxPtr2->Name));
//
// we need handle file synchronously
//
KeWaitForSingleObject(&FileCtxPtr2->Event, Executive, KernelMode, FALSE, NULL);
LocalStatus = SfIsEncryptFlagExist(DeviceObject, FileCtxPtr2->Name, &IsEncryptFlagExist,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (!NT_SUCCESS(LocalStatus))
KdPrint(("sfilter!SfPostCreateWorker: SfIsEncryptFlagExist failed, return %x/n", LocalStatus));
LocalStatus = SfIsFileNeedEncrypt(DeviceObject, FileCtxPtr2->Name, &IsNeedEncrypt);
if (!NT_SUCCESS(LocalStatus))
KdPrint(("sfilter!SfPostCreateWorker: SfIsFileNeedEncrypt failed, return %x/n", LocalStatus));
FileCtxPtr2->EncryptFlagExist = IsEncryptFlagExist;
FileCtxPtr2->NeedEncrypt = IsNeedEncrypt;
KdPrint(("sfilter!SfCreate: IsEncryptFlagExist = %d, IsNeedEncrypt = %d, NewElement = %d/n",
IsEncryptFlagExist, IsNeedEncrypt, NewElement));
if (NewElement && ((!IsNeedEncrypt && IsEncryptFlagExist) || (IsNeedEncrypt && !IsEncryptFlagExist)))
{
if (!IsNeedEncrypt && IsEncryptFlagExist)
{
if (NewElement)
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = FALSE;
KdPrint(("sfilter!SfPostCreateWorker: Decrypt %ws/n", FileCtxPtr2->Name));
LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject);
if (NT_SUCCESS(LocalStatus))
{
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, FALSE, NULL, 0);
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = FALSE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, FALSE) failed, return %x/n", FileCtxPtr2->Name, LocalStatus));
}
else
{
KdPrint(("sfilter!SfPostCreateWorker: SfUpdateFileByFileObject failed, return %x/n", LocalStatus));
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
}
}
else
{
if (NewElement)
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = TRUE;
KdPrint(("sfilter!SfPostCreateWorker: Encrypt %ws/n", FileCtxPtr2->Name));
LocalStatus = SfUpdateFileByFileObject(DeviceObject, FileObject);
if (NT_SUCCESS(LocalStatus))
{
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, TRUE,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = TRUE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x/n", FileCtxPtr2->Name, LocalStatus));
}
else
{
KdPrint(("sfilter!SfPostCreateWorker: SfUpdateFileByFileObject failed, return %x/n", LocalStatus));
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
}
}
}
else
{
if (FileCtxPtr2->NeedEncrypt)
{
FileCtxPtr2->DecryptOnRead = TRUE;
FileCtxPtr2->EncryptOnWrite = TRUE;
if (!FileCtxPtr2->EncryptFlagExist)
{
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, TRUE,
FileCtxPtr2->EncryptExtData, sizeof(FileCtxPtr2->EncryptExtData));
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = TRUE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x/n", FileCtxPtr2->Name, LocalStatus));
}
}
else
{
FileCtxPtr2->DecryptOnRead = FALSE;
FileCtxPtr2->EncryptOnWrite = FALSE;
if (FileCtxPtr2->EncryptFlagExist)
{
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr2->Name, FALSE,
NULL, 0);
if (NT_SUCCESS(LocalStatus))
FileCtxPtr2->EncryptFlagExist = FALSE;
else
KdPrint(("sfilter!SfPostCreateWorker: SfSetFileEncrypted(%ws, TRUE) failed, return %x/n", FileCtxPtr2->Name, LocalStatus));
}
}
}
KeSetEvent(&FileCtxPtr2->Event, IO_NO_INCREMENT, FALSE);
}
} while (FALSE);
// 释放名字控制结构
// Release the name control structure if we have
if (FileName)
ExFreeToPagedLookasideList(&gFileNameLookAsideList, FileName);
if (FileCtxPtr)
ExFreePool(FileCtxPtr);
// 保存状态且继续处理IRP
// Save the status and continue processing the IRP
// KdPrint(("sfilter!SfCreate: Exiting.../n"));
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
SfCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
当一个清除或者关闭请求被处理时被调用。注意:这个例程不真正执行东西,它与SfPassThrough相同
它仅登记作为清除处理器以使调试更加容易(你可以在这里设置断点从而代替在通用的PassThrough设置断点)
This routine is invoked whenever a cleanup or a close request is to be
processed. NOTE: This routine doesn't actually do anything, it is the same
as SfPassThrough. It is only registered as the cleanup handler to ease in
debugging (You can set a Breakpoint here instead of in the generic PassThrough.
Arguments:
DeviceObject - Pointer to the device object for this driver.
Irp - Pointer to the request packet representing the I/O request.
Return Value:
The function value is the status of the operation.
Note:
See notes for SfPassThrough for this routine.
--*/
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FILE_CONTEXT_HDR FileCtxHdr;
PFILE_CONTEXT FileCtxPtr = NULL;
BOOLEAN DeletePending = FileObject->DeletePending;
BOOLEAN DeleteOnClose = FALSE;
NTSTATUS Status;
PAGED_CODE();
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
//
// We only care about volume filter device object
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
FileCtxHdr.FsContext = FileObject->FsContext;
ExAcquireFastMutex(&DevExt->FsCtxTableMutex);
FileCtxPtr = RtlLookupElementGenericTable(&DevExt->FsCtxTable, &FileCtxHdr);
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
if (!FileCtxPtr)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
KeWaitForSingleObject(&FileCtxPtr->Event, Executive, KernelMode, FALSE, NULL);
Status = SfForwardIrpSyncronously(DevExt->AttachedToDeviceObject, Irp);
if (!NT_SUCCESS(Status))
{
KeSetEvent(&FileCtxPtr->Event, IO_NO_INCREMENT, FALSE);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
DeleteOnClose = FileCtxPtr->DeleteOnClose;
FileCtxPtr->DeleteOnClose = FALSE;
if (DeletePending || DeleteOnClose)
{
if (FileCtxPtr->EncryptFlagExist)
{
NTSTATUS LocalStatus;
LocalStatus = SfSetFileEncrypted(DeviceObject, FileCtxPtr->Name, FALSE, NULL, 0);
if (NT_SUCCESS(LocalStatus))
{
FileCtxPtr->EncryptFlagExist = FALSE;
}
else
{
KdPrint(("sfilter!SfClose: SfSetFileEncrypted failed, return %x/n", LocalStatus));
}
}
}
KeSetEvent(&FileCtxPtr->Event, IO_NO_INCREMENT, FALSE);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
SfClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
FILE_CONTEXT_HDR FileCtxHdr;
PFILE_CONTEXT FileCtxPtr = NULL;
PAGED_CODE();
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
//
// We only care about volume filter device object
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
if (((FileObject->Flags & FO_STREAM_FILE) == FO_STREAM_FILE) ||
(FileObject->SectionObjectPointer &&
(CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer) == FileObject)))
{
}
else
{
FileCtxHdr.FsContext = FileObject->FsContext;
ExAcquireFastMutex(&DevExt->FsCtxTableMutex);
FileCtxPtr = RtlLookupElementGenericTable(&DevExt->FsCtxTable, &FileCtxHdr);
if (FileCtxPtr)
{
if (FileCtxPtr->RefCount > 0)
--FileCtxPtr->RefCount;
if ((0 == FileCtxPtr->RefCount) &&
(!FileObject->SectionObjectPointer ||
(!FileObject->SectionObjectPointer->DataSectionObject &&
!FileObject->SectionObjectPointer->ImageSectionObject)))
{
RtlDeleteElementGenericTable(&DevExt->FsCtxTable, &FileCtxHdr);
}
}
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
NTSTATUS
SfRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PFILE_OBJECT FileObject = IrpSp->FileObject;
PREAD_WRITE_COMPLETION_CONTEXT CompletionCtx = NULL;
PVOID OldBuffer = NULL;
PMDL Mdl = NULL;
PVOID MyBuffer = NULL;
ULONG Length = 0;
FILE_CONTEXT_HDR FileCtxHdr;
PFILE_CONTEXT FileCtxPtr = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
//
// Sfilter doesn't allow handles to its control device object to be created,
// therefore, no other operation should be able to come through.
//
ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject));
ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
//
// We only care about volume filter device object
//
if (!DevExt->StorageStackDeviceObject)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#if DBG
if (DevExt->DriveLetter != DEBUG_VOLUME)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
#endif
if (!(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO)))
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp);
}
ExAcquireFastMutex(&DevExt->FsCtxTableMutex);
FileCtxHdr.FsContext = FileObject->FsContext;
FileCtxPtr = RtlLookupElementGenericTable(&DevExt->FsCtxTable, &FileCtxHdr);
ExReleaseFastMutex(&DevExt->FsCtxTableMutex);
if (!FileCtxPtr || !FileCtxPtr->DecryptOnRead)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DevExt->AttachedToDeviceObject, Irp)
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow