C/C++ 实现文件透明加解密

               

  

 今日遇见一个开超市的朋友,真没想到在高校开超市一个月可以达到月净利润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

软件名称:SEFS透明加密内核 V 2.0.0.1软件版本:2.0.0.1建议分类:系统安全/文件加密软件大小:371K安装平台:Win2000 sp4+urp / xp sp2 / 2003 sp1 / vista软件语言:简体中文/繁体中文/英文软件授权:共享软件软件主页:http://www.sefs.net支持邮箱:admin@sefs.net软件下载:http://www.sefs.net/setup.rar国内首家采用MS全新 MiniFilter架构的SEFS透明加密内核 V 2.0.0.1发布1、简述 SEFS透明加密开发内核是基于MS最新的IFS文件过滤驱动(MiniFilter)开发的透明加密平台。加密标识内置于文件本身、可支持PKCS7电子 信封、加密算法可在内核态。也可在应用层,支持MS CSP 标准,可实现对加密硬件如USBKEY的支持。加、解密操作均受保护 的内存区域完成,高效安全。不会产生临时文件,同时配套保护驱动可防止进程注入、内存Dump、和截屏操作,全程保护您的 机密资料。2、特点   1、强制加密:客户端指定规则或匹配规则产生的任意文件均强制加密。所有的“文件另存”均为加密。不管是 怎么样的文件名称。SEFS是智能识别应用程序的行为.  2、文件加密标记识别采用指纹智能识别技术,加密标记植于文件本身,支持电子信封模式(PKCS7)和支持   身份/身份组机制.方便交流和传输。  3、SEFS平台工作于文件系统驱动层面,可以支持内存映射文件的方式.而非一些基于API Hook方式的加密系   统绝对无法支持内存映射文件。例如最常见的notepad(记事本)/另外可执行文件的加载执行均是通过内存   映射文件的方式.  4、进程识别基于特征值,而非简单的基于进程名称判断。可防止进程改名、加壳等形式的攻击。  5、非授权进程无法读取密文。网络间受控文件的传输为密文。FoxMail、OutLook或Ftp客户端等网络软件无法发送 明文。(假设其为非授权进程的话) 6、完美解决明文缓存问题,即便是密文正在被打开,也不能非法夺取明文 7、使用全新的MiniFilter架构,同杀毒软件有较好的兼容性,同时在性能和稳定性方面,较老的IFS过滤驱动 有着明显的提升。 8、支持应用层的加、解密算法和引擎。可兼容MS CSP 、PKCS11 等标准,从而实现硬件的加解密。满足不同的安全级别的要求。3、安装环境 客户端:Win2000 sp4 + URP /XP sp2/2003 sp1 / Vista Win2000需要Update Rollup Pack (URP) 下载:http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=B54730CF-8850-4531-B52B-BF28B324C6624、支持的软件: 1. 办公类: Microsoft Office 2000/XP/2003 、 Adobe acrobat7 、NotePad、 WordPad。 2. 图像类: Photoshop 、 CorelDraw12 、 Mspaint画图等 3. 设计类: AutoCAD 2004 、圆方BtoCAD、等 4. ...................SEFS--透明加密内核=============================================商业授权:sales@sefs.netBug 报告:bug@sefs.net
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值