?? 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
--*/
// 修復(fù)涉及后視列表的Win2K兼容性
// Fixes Win2K compatibility regarding lookaside lists.
//
#ifndef _WIN2K_COMPAT_SLIST_USAGE // Add content(增加內(nèi)容)
#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 未被引用的正式參數(shù)
#pragma warning(error:4101) // Unreferenced local variable 未被引用的局部參數(shù)
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// Macro and Structure Definitions
//
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /
//
// VERSION NOTE:
//
// 下面的宏在Windows XP及以后OS中的NTIFS.H中被定義,如果我們在Windows 2000環(huán)境下編譯加上這些定義
// 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
//
// 用于測試、設(shè)置、清除標志
// 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
// 設(shè)置標志
#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(增加內(nèi)容)******
// 限制的最大路徑長度 + 系統(tǒng)加密信息目錄
#define MAX_PATH 512
// 加密位尺寸,設(shè)置加密位共128*8個位,即128字節(jié)
#define ENCRYPT_BIT_SIZE (128 * 8)
#define SF_ENCRYPT_POSTFIX L".$encrypt$"
#define SF_ENCRYPT_POSTFIX_LENGTH 10
// 規(guī)則文件的文件名
#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]; // 轉(zhuǎn)換成字節(jié)數(shù),// 表明從最終形成'\??\i:\System Encrypt Information\System Volume Information'的文件中讀入的加密位的字節(jié)長度
UCHAR EncryptExtData[ENCRYPT_BIT_SIZE / sizeof(UCHAR)];
} FILE_CONTEXT, *PFILE_CONTEXT;
// Add content(增加內(nèi)容)******
//
// 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
//
// 我們驅(qū)動的設(shè)備擴展。注意相同的擴展用于下面類型的設(shè)備對象
// - 我們附著的文件系統(tǒng)設(shè)備對象
// - 我們附著的被安裝的卷設(shè)備對象
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(增加內(nèi)容)
RTL_GENERIC_TABLE FsCtxTable; // Add content(增加內(nèi)容)
FAST_MUTEX FsCtxTableMutex; // Add content(增加內(nèi)容)
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;
//
// 這個結(jié)構(gòu)含有我們需要為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.
// 對于卷安裝操作,我們已經(jīng)分配且部分初始化的我們將附著到被成功安裝的卷的新設(shè)備對象
//
PDEVICE_OBJECT NewDeviceObject;
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;
typedef struct _POST_CREATE_WORKER_CONTEXT // Add content(增加內(nèi)容)
{
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(增加內(nèi)容)
{
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(增加內(nèi)容)
{
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(增加內(nèi)容)
#define POLICY_ENCRYPT 0x1
#define POLICY_END 0xFFFFFFFF
typedef struct _RULE // Add content(增加內(nèi)容)
{
ULONG Policy; // 規(guī)則策略碼
WCHAR Pattern[MAX_PATH]; // 匹配規(guī)則,可以含有通配符 * ?
} RULE, *PRULE;
//
// Macro to test if this is my device object
// 用于測試是否我們設(shè)備對象的宏
//
#define IS_MY_DEVICE_OBJECT(_devObj) \
(((_devObj) != NULL) && \
((_devObj)->DriverObject == gSFilterDriverObject) && \
((_devObj)->DeviceExtension != NULL))
//
// Macro to test if this is my control device object
// 用于測試是否我們的控制設(shè)備對象的宏
//
#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
// 測試我們想附著到的設(shè)備類型的宏
//
#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.
//
// 動態(tài)輸入函數(shù)的原型的函數(shù)指針
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.
// 下面這些例程應(yīng)該在Windows XP (5.1)及以后的操作系統(tǒng)可用
//
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;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -