1. 程式人生 > >C/C++ 實現檔案透明加解密

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.// // 動態輸入函式的原型的函式指標

typedefNTSTATUS(* PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS)( IN PDRIVER_OBJECT DriverObject, IN PFS_FILTER_CALLBACKS Callbacks );

typedefNTSTATUS(* PSF_ENUMERATE_DEVICE_OBJECT_LIST)( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT *DeviceObjectList, IN ULONG DeviceObjectListSize, OUT PULONG ActualNumberDeviceObjects );

typedefNTSTATUS(* 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 );

typedefPDEVICE_OBJECT(* PSF_GET_DEVICE_ATTACHMENT_BASE_REF)( IN PDEVICE_OBJECT DeviceObject );

typedefNTSTATUS(* PSF_GET_DISK_DEVICE_OBJECT)( IN PDEVICE_OBJECT FileSystemDeviceObject, OUT PDEVICE_OBJECT *DiskDeviceObject );

typedefPDEVICE_OBJECT(* PSF_GET_ATTACHED_DEVICE_REFERENCE)( IN PDEVICE_OBJECT DeviceObject );

typedefNTSTATUS(* 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_STRINGSfGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl );

VOIDSfGetFileNameCleanup( 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 __cdeclswprintf(wchar_t *, const wchar_t *, ...); // Add content(增加內容)

// // Define driver entry routine.//

NTSTATUSDriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );

#if DBG && WINVER >= 0x0501VOIDDriverUnload( 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 >= 0x0501VOIDSfLoadDynamicFunctions( );

VOIDSfGetCurrentVersion( );#endif

NTSTATUSSfPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUSSfCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

// 缺少sfCreateCompletion(...)

NTSTATUSSfCleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

// 將 SfCleanupClose(...)分成SfCleanup(...)和SfClose(...).

NTSTATUSSfClose( 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 );

NTSTATUSSfFsControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUSSfFsControlMountVolume ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

VOIDSfFsControlMountVolumeCompleteWorker ( IN PFSCTRL_COMPLETION_CONTEXT Context );

NTSTATUSSfFsControlMountVolumeComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT NewDeviceObject );

NTSTATUSSfFsControlLoadFileSystem ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

VOIDSfFsControlLoadFileSystemCompleteWorker ( IN PFSCTRL_COMPLETION_CONTEXT Context );

NTSTATUSSfFsControlLoadFileSystemComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );

NTSTATUSSfFsControlCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );

BOOLEANSfFastIoCheckIfPossible( 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 );

BOOLEANSfFastIoRead( 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 );

BOOLEANSfFastIoWrite( 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 );

BOOLEANSfFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoQueryStandardInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoLock( 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 );

BOOLEANSfFastIoUnlockSingle( 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 );

BOOLEANSfFastIoUnlockAll( IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoUnlockAllByKey( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoDeviceControl( 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 );

VOIDSfFastIoDetachDevice( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice );

BOOLEANSfFastIoQueryNetworkOpenInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoMdlRead( 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 );

BOOLEANSfFastIoMdlReadComplete( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoPrepareMdlWrite( 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 );

BOOLEANSfFastIoMdlWriteComplete( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoReadCompressed( 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 );

BOOLEANSfFastIoWriteCompressed( 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 );

BOOLEANSfFastIoMdlReadCompleteCompressed( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoMdlWriteCompleteCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject );

BOOLEANSfFastIoQueryOpen( IN PIRP Irp, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, IN PDEVICE_OBJECT DeviceObject );

#if WINVER >= 0x0501 /* See comment in DriverEntry */NTSTATUSSfPreFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, OUT PVOID *CompletionContext );

VOIDSfPostFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, IN NTSTATUS OperationStatus, IN PVOID CompletionContext );#endif

VOIDSfFsNotification( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FsActive );

NTSTATUSSfAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice, IN OUT PDEVICE_OBJECT *AttachedToDeviceObject );

NTSTATUSSfAttachToFileSystemDevice( IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING DeviceName );

VOIDSfDetachFromFileSystemDevice( IN PDEVICE_OBJECT DeviceObject );

NTSTATUSSfAttachToMountedDevice( IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT SFilterDeviceObject );

VOIDSfCleanupMountedDevice( IN PDEVICE_OBJECT DeviceObject );

#if WINVER >= 0x0501NTSTATUSSfEnumerateFileSystemVolumes( IN PDEVICE_OBJECT FSDeviceObject, IN PUNICODE_STRING FSName );#endif

VOIDSfGetObjectName( IN PVOID Object, IN OUT PUNICODE_STRING Name );

VOIDSfGetBaseDeviceObjectName( IN PDEVICE_OBJECT DeviceObject, IN OUT PUNICODE_STRING DeviceName );

BOOLEANSfIsAttachedToDevice( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL );

BOOLEANSfIsAttachedToDeviceW2K( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL );

BOOLEANSfIsAttachedToDeviceWXPAndLater( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL );

VOIDSfReadDriverParameters( IN PUNICODE_STRING RegistryPath );

VOID  // Add content(增加內容)SfDriverReinitialization(    IN PDRIVER_OBJECT DriverObject,    IN PVOID Context,    IN ULONG Count    );

NTSTATUSSfIsShadowCopyVolume ( 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// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /

NTSTATUSDriverEntry( 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 >= 0x0501VOIDDriverUnload( 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 >= 0x0501VOIDSfLoadDynamicFunctions ( )/*++

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);}

VOIDSfGetCurrentVersion ( )/*++

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

VOIDSfFsNotification( 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// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // /

NTSTATUSSfPassThrough( 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請