ƽʱæٷ⡣ڹʱߵĺܶͬ¶ͣйWindowsļϵͳ⡣кܶȥѧϰWDKṩMiniFilterܣʹMiniFilterƷǣ˵MiniFilterѧsFilterѶȺܴ󲻺ѧԭ򣬵õĴ𰸶˵ʹMiniFilter̲عĶIRPĴҲعЩᷳľ󶨣sFilterҪĶIRPĴҪľİ󶨣ҪFastIo˺ܶ˲ԸȥʹsFilter

 ˵ǣsFilterļĸ֪ܶʶǺõġǲؿ֮۵sFilterãMiniFilterá

 ϻ˵ˣܽһ¶sFilterĴ⡣ Ұһ磬ұѴȫճڴд˺ܶע͡ȻˣܶණвοһЩǰˡ

ͷļsFilter.hĴעˡ뿴


#include "ntifs.h"
#include "ntdddisk.h"

#pragma warning(error:4100)        //ʹ(βδʱ)
#pragma warning(error:4101)        //ֲʱ

//==============================  ============================
#ifndef Add2Ptr
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))          //﷨: PVOID  Add2Ptr(PUCHAR p,PUCHAR i);  :  ַ
#endif
//================ (OS汾Win2000ʱ¶δ) ===================
#if WINVER == 0x0500

#ifndef FlagOn  //FlagOnδ#define,һ
#define FlagOn(_F,_SF)  ((_F) & (_SF))                  //﷨: FiagOn(a,b);  : a&b(abλ)
#endif

#ifndef BooleanFlagOn
#define BooleanFlagOn(F,SF)  ((BOOLEAN)(((F) & (SF)) != 0))  //﷨: BooleanFlagOn(a,b); : a&b !=0
#endif

#ifndef SetFlag
#define SetFlag(_F,_SF)  ((_F) |= (_SF))                  //﷨: SetFlag(a,b);  : a |= b(abλ,a)
#endif

#ifndef ClearFlag  
#define ClearFlag(_F,_SF)  ((_F) &= ~(_SF))              //﷨: ClearFlag(a,b);  : a &= ~b(abǰλ,a)
#endif

#ifndef min
#define min(a,b)  (((a) < (b)) ? (a) : (b))                //﷨: min(a,b); : abеС
#endif

#ifndef max
#define max(a,b)  (((a) > (b)) ? (a) : (b))                //﷨: max(a,b); : abеĴ
#endif

#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) )        //ɿ,ExFreePoolWithTagһ궨,ʵϾExFreePool

#endif


//=================== (WinXPOSʱ¶δ) ====================
#if WINVER >= 0x0501

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  NTSTATUS (*PSF_GET_DISK_DEVICE_OBJECT) ( IN PDEVICE_OBJECT FileSystemDeviceObject, OUT PDEVICE_OBJECT *DiskDeviceObject );
typedef  NTSTATUS (*PSF_GET_VERSION) ( IN OUT PRTL_OSVERSIONINFOW VersionInformation );

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  PDEVICE_OBJECT (*PSF_GET_ATTACHED_DEVICE_REFERENCE) ( IN PDEVICE_OBJECT DeviceObject );

#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))

typedef struct _SF_DYNAMIC_FUNCTION_POINTERS {
    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 = {0};  //ýṹʼΪ0

ULONG gSfOsMajorVersion = 0;        //ϵͳ汾
ULONG gSfOsMinorVersion = 0;        //ϵͳ汾

#endif


#define MAX_DEVNAME_LENGTH 64        //峣ֵ
#define DEVOBJ_LIST_SIZE 64
#define SFLT_POOL_TAG   'tlFS'        //ڴǩ
ULONG SfDebug = 0;

#define DELAY_ONE_MICROSECOND   (-10)
#define DELAY_ONE_MILLISECOND   (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND        (DELAY_ONE_MILLISECOND*1000)


// 궨: IS_MY_DEVICE_OBJECT(ָ豸ָ); : (ָNULL)(豸DriverObjectgSFilterDriverObject)(豸DeviceExtensionNULL)
#define IS_MY_DEVICE_OBJECT(_devObj)  (((_devObj) != NULL) && ((_devObj)->DriverObject == gSFilterDriverObject) && ((_devObj)->DeviceExtension != NULL))


// 궨: ǲҵ"豸"
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj)  (((_devObj) == gSFilterControlDeviceObject) ? (ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && ((_devObj)->DeviceExtension == NULL)), TRUE) : FALSE)


// 궨: ǲҪ"豸"
#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))


// 궨: 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))


// 궨: 
#define SF_LOG_PRINT( _dbgLevel, _string )  (FlagOn(SfDebug,(_dbgLevel)) ? DbgPrint _string : ((void)0))

#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

#define GET_DEVICE_TYPE_NAME( _type ) ((((_type) > 0) && ((_type) < (sizeof(DeviceTypeNames) / sizeof(PCHAR)))) ? DeviceTypeNames[ (_type) ] : "[Unknown]")



typedef struct _SFILTER_DEVICE_EXTENSION {
  PDEVICE_OBJECT AttachedToDeviceObject;          //󶨵ļϵͳ豸
  PDEVICE_OBJECT StorageStackDeviceObject;        //ļϵͳ豸صʵ豸() 
  UNICODE_STRING DeviceName;                //һ,̾,Ϊ󶨵Ŀ豸
  WCHAR DeviceNameBuffer[MAX_DEVNAME_LENGTH];        //ִĻ
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;

typedef struct _FSCTRL_COMPLETION_CONTEXT {
  WORK_QUEUE_ITEM WorkItem;                        
  PDEVICE_OBJECT DeviceObject;                      
  PIRP Irp;                                    
  PDEVICE_OBJECT NewDeviceObject;                    
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;

typedef struct _GET_NAME_CONTROL {
  PCHAR allocatedBuffer;                            
  CHAR smallBuffer[256];                            
} GET_NAME_CONTROL, *PGET_NAME_CONTROL;



// 

NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath );

#if DBG && WINVER >= 0x0501  //԰汾OSWinXPʱú,򲻱
VOID  DriverUnload( IN PDRIVER_OBJECT DriverObject );                  //жغ
#endif

#if WINVER >= 0x0501        //ʱOSWinXPʱ,,򲻱
VOID  SfLoadDynamicFunctions ();                  
VOID  SfGetCurrentVersion ();                                                  
#endif

PUNICODE_STRING  SfGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl );
VOID  SfGetFileNameCleanup( IN OUT PGET_NAME_CONTROL NameControl );
NTSTATUS  SfPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
NTSTATUS  SfCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp  );
NTSTATUS  SfCreateCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context );
NTSTATUS  SfCleanupClose( 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 );
NTSTATUS  SfFsControlMountVolumeComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT NewDeviceObject );
NTSTATUS  SfFsControlLoadFileSystem( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
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 );
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 );
VOID  SfFsControlLoadFileSystemCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context );
VOID  SfFsControlMountVolumeCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context );
VOID  SfFastIoDetachDevice( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice );

#if WINVER >= 0x0501
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

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 );
NTSTATUS  SfAttachToMountedDevice( IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT SFilterDeviceObject );
VOID  SfFsNotification( IN PDEVICE_OBJECT DeviceObject, IN BOOLEAN FsActive );
VOID  SfDetachFromFileSystemDevice( IN PDEVICE_OBJECT DeviceObject );
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 );
VOID  SfReadDriverParameters( IN PUNICODE_STRING RegistryPath );
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 );
NTSTATUS  SfIsShadowCopyVolume( IN PDEVICE_OBJECT StorageStackDeviceObject, OUT PBOOLEAN IsShadowCopy );

/////////////////////////////////////////////////////////////////////////////////////
////////
sFilter.cĳˡ
ϣܹע⼸Եĵط
(1) ShadowCopyVolume---ҲǾӰ
(2) FastIo
(3) ļϵͳ豸İ󶨡
(4) ļϵͳ豸İ󶨡
(5) SfCreateһСϸڡ

ҿд<<Windowsں˰ȫ>>Ȿ顣Ȿĵ7½sFilterⱾûаWindowsҪһϵͳ˵ľӰ

sFilter.cд£



#include "sfilter.h"


//ָÿڴҳ
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)

#if DBG && WINVER >= 0x0501
#pragma alloc_text(PAGE, DriverUnload)
#endif

#pragma alloc_text(INIT, SfReadDriverParameters)
#pragma alloc_text(PAGE, SfFsNotification)
#pragma alloc_text(PAGE, SfCreate)
#pragma alloc_text(PAGE, SfCleanupClose)
#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, 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

#endif


PDRIVER_OBJECT gSFilterDriverObject = NULL;        ///Oɲ
PDEVICE_OBJECT gSFilterControlDeviceObject = NULL;    //ɱɵĿ豸
FAST_MUTEX gSfilterAttachLock;              //һٻṹ()



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



NTSTATUS  DriverEntry(IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath )
{
    PFAST_IO_DISPATCH fastIoDispatch;  //FAST_IO_DISPATCHṹ
    UNICODE_STRING nameString;      //ִṹ
    NTSTATUS status;          //״̬
    ULONG i;

#if WINVER >= 0x0501    //,OS汾WinXP,,򲻱
    SfLoadDynamicFunctions();                              
    SfGetCurrentVersion();                                  
#endif                                        

    SfReadDriverParameters( RegistryPath );                        
    gSFilterDriverObject = DriverObject;  //I/O󱣴浽ȫֱgSFilterDriverObject


#if DBG && WINVER >= 0x0501          //OS汾xpchecked,Щ,򲻱
    if (NULL != gSfDynamicFunctions.EnumerateDeviceObjectList)
  {
    gSFilterDriverObject->DriverUnload = DriverUnload;        //עжغ
  }
#endif                                              

  ExInitializeFastMutex( &gSfilterAttachLock );        //ʼ"FastMutex(ٻ)",Ժֻܻ߳



  //豸
  RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters\\SFilter" );    //ļϵͳ豸

  //豸
    status = IoCreateDevice( DriverObject,
                0,                        //û 豸չ 
                &nameString,                  //豸:   FileSystem\\Filters\\SFilter
                FILE_DEVICE_DISK_FILE_SYSTEM,          //豸: ļϵͳ
                FILE_DEVICE_SECURE_OPEN,            //豸: Է͵CDOĴаȫ
                FALSE,                      //һûģʽʹõ豸
                &gSFilterControlDeviceObject );          //ɵ"豸"

  if (status == STATUS_OBJECT_PATH_NOT_FOUND)                //жǷ δҵ·
  {
    RtlInitUnicodeString( &nameString, L"\\FileSystem\\SFilterCDO" );    //´ 豸 
    status = IoCreateDevice( DriverObject, 0,
                &nameString,                      //豸: FileSystem\\SFilterCDO
                FILE_DEVICE_DISK_FILE_SYSTEM,
                FILE_DEVICE_SECURE_OPEN,
                FALSE,
                &gSFilterControlDeviceObject );              //ɵ 豸 
  }
  if (!NT_SUCCESS( status ))                              //жIoCreateDeviceǷɹ
  {
    KdPrint(( "SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status ));
    return status;    //󷵻(CDOʧ)
  }


  //עĬǲ
  for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)                
  {
    DriverObject->MajorFunction[i] = SfPassThrough;                
  }
  //עǲ
    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] = SfCleanupClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;



  fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,        //ӷǷҳз
                      sizeof( FAST_IO_DISPATCH ),  //Ҫֽ
                      SFLT_POOL_TAG );      //ָһ4ֽڵıǩ(ǰѺ궨:'tlFS')
    
  if (!fastIoDispatch)    //ڴʧ
  {
    IoDeleteDevice( gSFilterControlDeviceObject );            //ɾ洴CDO
    return STATUS_INSUFFICIENT_RESOURCES;                //һstatus(Դ)
  }
    RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );      
    DriverObject->FastIoDispatch = fastIoDispatch;              //FastIoɱ浽FastIoDispatch
    fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );    //FastIoɱĳ

    fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;    //FastIoɺ,21
    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;


//--------------------------------עfsFilterص-------------------------------

#if WINVER >= 0x0501  //OS汾ΪWinXP,δ,򲻱
  {
    FS_FILTER_CALLBACKS fsFilterCallbacks;
    if (NULL != gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)
    {
      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 );
                return status;
      }
    }
  }
#endif            


    status = IoRegisterFsRegistrationChange( DriverObject, SfFsNotification );
    if (!NT_SUCCESS( status ))
  {
    KdPrint(( "SFilter!DriverEntry: Error registering FS change notification, status=%08x\n", status ));

    DriverObject->FastIoDispatch = NULL;          //עָfastIoָΪNULL
    ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG );    //ͷŷfastIoڴ
    IoDeleteDevice( gSFilterControlDeviceObject );      //ɾ洴CDO
    return status;                      //󷵻
  }

    {
    
    PDEVICE_OBJECT rawDeviceObject;
    PFILE_OBJECT fileObject;
    RtlInitUnicodeString( &nameString, L"\\Device\\RawDisk" );

  
    /*
    IoGetDeviceObjectPointerĹ:
    ²豸²豸ָ롣ú˶²豸Լ²豸Ӧļá
    ж֮ǰ²豸ûû²жػᱻֹͣ˱Ҫ²豸á
    ǳһ㲻ֱӶ²豸ü١ֻҪٶļþͿԼļ豸á
    ʵϣIoGetDeviceObjectPointerصĲ²豸ָ룬Ǹ豸ջж豸ָ롣


    IoGetDeviceObjectPointerĵñ IRQL=PASSIVE_LEVELļС
    */

        status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject );
    if (NT_SUCCESS( status ))
    {
      SfFsNotification( rawDeviceObject, TRUE );
      ObDereferenceObject( fileObject ); //ٶļ
    }

    RtlInitUnicodeString( &nameString, L"\\Device\\RawCdRom" );
        status = IoGetDeviceObjectPointer( &nameString, FILE_READ_ATTRIBUTES, &fileObject, &rawDeviceObject );
    if (NT_SUCCESS( status ))
    {
      SfFsNotification( rawDeviceObject, TRUE );
      ObDereferenceObject( fileObject );//ٶļ
    }
  }

  ClearFlag( gSFilterControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  return STATUS_SUCCESS;
}



// жغ 
#if DBG && WINVER >= 0x0501
VOID  DriverUnload( IN PDRIVER_OBJECT DriverObject )
{
  PSFILTER_DEVICE_EXTENSION devExt;
  PFAST_IO_DISPATCH fastIoDispatch;
  NTSTATUS status;
  ULONG numDevices;
  ULONG i;
  LARGE_INTEGER interval;

  PDEVICE_OBJECT devList[DEVOBJ_LIST_SIZE];
  ASSERT(DriverObject == gSFilterDriverObject);
  SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES, ("SFilter!DriverUnload:                        Unloading driver (%p)\n", DriverObject) );
  IoUnregisterFsRegistrationChange( DriverObject, SfFsNotification );
  for (;;)
  {
    ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList );
        status = (gSfDynamicFunctions.EnumerateDeviceObjectList)( DriverObject, devList, sizeof(devList), &numDevices);
    if (numDevices <= 0)
    {
      break;
    }

    numDevices = min( numDevices, DEVOBJ_LIST_SIZE );
    for (i=0; i < numDevices; i++)
    {
      devExt = devList[i]->DeviceExtension;
      if (NULL != devExt)
      {
        IoDetachDevice( devExt->AttachedToDeviceObject );
      }
    }

    interval.QuadPart = (5 * DELAY_ONE_SECOND);          //delay 5 seconds
    KeDelayExecutionThread( KernelMode, FALSE, &interval );
    for (i=0; i < numDevices; i++)
    {
      if (NULL != devList[i]->DeviceExtension)
      {
        SfCleanupMountedDevice( devList[i] );
      }
      else
      {
        ASSERT(devList[i] == gSFilterControlDeviceObject);
        gSFilterControlDeviceObject = NULL;
      }

      IoDeleteDevice( devList[i] );
            ObDereferenceObject( devList[i] );
        }
    }

  fastIoDispatch = DriverObject->FastIoDispatch;
  DriverObject->FastIoDispatch = NULL;
  ExFreePool( fastIoDispatch );
}
#endif



// SfLoadDynamicFunctions(WindowsXPϵͳ±ú)
#if WINVER >= 0x0501
VOID  SfLoadDynamicFunctions()
{

  /*
  ̬Щں˺ʹö̬νǣڵͰ汾WindowsϵͳϣγȻԼسɹ
  */

    UNICODE_STRING functionName;
    RtlZeroMemory( &gSfDynamicFunctions, sizeof( gSfDynamicFunctions ) );    //gSfDynamicFunctionsṹ0

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



//SfGetCurrentVersion(WinXP±ú)
#if WINVER >= 0x0501
VOID  SfGetCurrentVersion()
{
    if (NULL != gSfDynamicFunctions.GetVersion)
  {
    RTL_OSVERSIONINFOW versionInfo;
    NTSTATUS status;
    
    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 )
{

 /*
   SfFsNotification
   һ豸󣬲ӵָļϵͳ豸(File System CDO)Ķջϡ豸з͸ļϵͳ
   Ǿܹһؾ󣬾ͿԸӵµľ豸豸ջϡ
  
   SfFsNotificationԺǵĹ豸ܹյ͵ļϵͳCDO󣬼յIRP_MJ_FILE_SYSTEM_CONTROL˵
   ļϵͳ豸Ѿ󶨣Զ̬ؾĹˡôԺĹҪɶԾļذˡ
  
   
   ˵:
  
   DeviceObject:   ָļϵͳĿ豸(CDO) File System CDO
   FsActive:       ֵΪTRUEʾļϵͳļֵΪFALSEʾļϵͳжء
  
  */

    UNICODE_STRING name;          //ṹ
    WCHAR nameBuffer[MAX_DEVNAME_LENGTH];  //ַ,64

    PAGED_CODE();

  RtlInitEmptyUnicodeString( &name, nameBuffer, sizeof(nameBuffer) );    //ʼname(ԱBuffer->nameBuffer,Length=0,MaximumLength=64)
  SfGetObjectName( DeviceObject, &name );                        
  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)) );

  if (FsActive)
  {
    SfAttachToFileSystemDevice( DeviceObject, &name );  //ɶļϵͳ豸İ
  }
  else
  {
    SfDetachFromFileSystemDevice( DeviceObject );
  }
}



NTSTATUS  SfPassThrough( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
  ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  IoSkipCurrentIrpStackLocation( Irp );
  return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
}



VOID  SfDisplayCreateFileName( IN PIRP Irp )
{
  PIO_STACK_LOCATION irpSp;
  PUNICODE_STRING name;
  GET_NAME_CONTROL nameControl;
  
  irpSp = IoGetCurrentIrpStackLocation( Irp );
  name = SfGetFileName( irpSp->FileObject, Irp->IoStatus.Status, &nameControl );
  if (irpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID)
  {
    SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
                      ("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ (FID)\n", 
                       Irp->IoStatus.Status,
                       Irp->IoStatus.Information,
                       name) );
  }
  else
  {
    SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
                      ("SFilter!SfDisplayCreateFileName: Opened %08x:%08x %wZ\n", 
                       Irp->IoStatus.Status,
                       Irp->IoStatus.Information,
                       name) );
  }
  
  SfGetFileNameCleanup( &nameControl );
}



NTSTATUS  SfCreate( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    NTSTATUS status;

    PAGED_CODE();
  

   /*
   sFilterĴУifдĺ:CreateFileRing3´򿪴˿豸ӵʱʧ
   */
   
  if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
  {
    Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return STATUS_INVALID_DEVICE_REQUEST;
  }
  
  /*
  ˣҪif޸ĳʽ:

  if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) 
  {
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = FILE_OPENED;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return STATUS_SUCCESS;
  }
  */


  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  
  if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION | SFDEBUG_GET_CREATE_NAMES| SFDEBUG_DISPLAY_CREATE_NAMES ))
  {
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
  }
  else
  {
    //ʼ¼̡
    KEVENT waitEvent;
    KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
    IoCopyCurrentIrpStackLocationToNext( Irp );
    IoSetCompletionRoutine( Irp,
                SfCreateCompletion,
                &waitEvent,
                TRUE,
                TRUE,
                TRUE );
    status = IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
    if (STATUS_PENDING == status)//״̬ 
    {
      NTSTATUS localStatus = KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);
      ASSERT(STATUS_SUCCESS == localStatus);
    }
    
    ASSERT(KeReadStateEvent(&waitEvent) || !NT_SUCCESS(Irp->IoStatus.Status));
    if (FlagOn(SfDebug, (SFDEBUG_GET_CREATE_NAMES|SFDEBUG_DISPLAY_CREATE_NAMES)))
    {
      SfDisplayCreateFileName( Irp );
    }
    status = Irp->IoStatus.Status;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return status;
  }
}



NTSTATUS  SfCreateCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
    PKEVENT event = Context;

    UNREFERENCED_PARAMETER( DeviceObject );
    UNREFERENCED_PARAMETER( Irp );

    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));

    KeSetEvent(event, IO_NO_INCREMENT, FALSE);

    return STATUS_MORE_PROCESSING_REQUIRED;
}



NTSTATUS  SfCleanupClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    PAGED_CODE();
    ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
}



NTSTATUS  SfFsControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
  /*
  ˵:
  
  DeviceObject:    Ǵ豸Ǳ󶨵ļϵͳ豸ջϡ
  
  */

    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
    PAGED_CODE();
    ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    switch (irpSp->MinorFunction) {

        case IRP_MN_MOUNT_VOLUME:

            return SfFsControlMountVolume( DeviceObject, Irp );

        case IRP_MN_LOAD_FILE_SYSTEM:

            return SfFsControlLoadFileSystem( DeviceObject, Irp );

        case IRP_MN_USER_FS_REQUEST:
        {
            switch (irpSp->Parameters.FileSystemControl.FsControlCode) {

                case FSCTL_DISMOUNT_VOLUME:
                {
                    PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;

                    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                                  ("SFilter!SfFsControl:                         Dismounting volume         %p \"%wZ\"\n",
                                   devExt->AttachedToDeviceObject,
                                   &devExt->DeviceName) );
                    break;
                }
            }
            break;
        }
    }        

    IoSkipCurrentIrpStackLocation( Irp );
    return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDeviceObject, Irp );
}



NTSTATUS  SfFsControlCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{
    UNREFERENCED_PARAMETER( DeviceObject );
    UNREFERENCED_PARAMETER( Irp );

    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    ASSERT(Context != NULL);

#if WINVER >= 0x0501
    if (IS_WINDOWSXP_OR_LATER())
  {
    KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
  }
  else
  {
#endif
    if (KeGetCurrentIrql() > PASSIVE_LEVEL)
    {
      ExQueueWorkItem( (PWORK_QUEUE_ITEM) Context, DelayedWorkQueue );
    }
    else
    {
      PWORK_QUEUE_ITEM workItem = Context;
      (workItem->WorkerRoutine)(workItem->Parameter);
    }

#if WINVER >= 0x0501
    }
#endif

    return STATUS_MORE_PROCESSING_REQUIRED;
}




NTSTATUS  SfFsControlMountVolume( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    /*
  ˵:

  DeviceObject:    Ǵ豸󶨵ļϵͳCDO豸ջϡ
  Irp:             Ƿ͸ļϵͳCDOĹһ¾Ĺ
  
  */
  
  PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );

    PDEVICE_OBJECT storageStackDeviceObject;


  // newDeviceObjectǽҪ󶨵ļϵͳľ豸ϡ˵newDeviceObjectҪ󶨵¹ؾ豸ϡ
    PDEVICE_OBJECT newDeviceObject;

    PSFILTER_DEVICE_EXTENSION newDevExt;
    NTSTATUS status;
    BOOLEAN isShadowCopyVolume;
    PFSCTRL_COMPLETION_CONTEXT completionContext;
    

    PAGED_CODE();

    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    ASSERT(IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType));


  /*
   ڰIRP͵ļϵͳ֮ǰʱVpb->RealDeviceǣҪصĴ豸
   storageStackDeviceObjectȱVPBֵΪIRP·ײ󣬿ܻı䡣
   */
    storageStackDeviceObject = irpSp->Parameters.MountVolume.Vpb->RealDevice;


    status = SfIsShadowCopyVolume ( storageStackDeviceObject, &isShadowCopyVolume );

    if (NT_SUCCESS(status) && 
        isShadowCopyVolume &&
        !FlagOn(SfDebug,SFDEBUG_ATTACH_TO_SHADOW_COPIES)) 
  {

        UNICODE_STRING shadowDeviceName;
        WCHAR shadowNameBuffer[MAX_DEVNAME_LENGTH];

    RtlInitEmptyUnicodeString( &shadowDeviceName, shadowNameBuffer, sizeof(shadowNameBuffer) );
        SfGetObjectName( storageStackDeviceObject, &shadowDeviceName );
        SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                      ("SFilter!SfFsControlMountVolume               Not attaching to Volume    %p \"%wZ\", shadow copy volume\n", 
                       storageStackDeviceObject,
                       &shadowDeviceName) );

    //󶨾Ӱһ
    IoSkipCurrentIrpStackLocation( Irp );
        return IoCallDriver( devExt->AttachedToDeviceObject, Irp );
    }

  status = IoCreateDevice( gSFilterDriverObject,
                             sizeof( SFILTER_DEVICE_EXTENSION ),
                             NULL,
                             DeviceObject->DeviceType,
                             0,
                             FALSE,
                             &newDeviceObject );


  
  /*IRP͵ļϵͳУôļϵͳͲյĹ*/
    if (!NT_SUCCESS( status ))
  {
    KdPrint(( "SFilter!SfFsControlMountVolume: Error creating volume device object, status=%08x\n", status ));

        Irp->IoStatus.Information = 0;
        Irp->IoStatus.Status = status;
        IoCompleteRequest( Irp, IO_NO_INCREMENT );

        return status;
    }


  //д豸չĿǣɺ׵storageStackDeviceObject
  newDevExt = newDeviceObject->DeviceExtension;
    newDevExt->StorageStackDeviceObject = storageStackDeviceObject;
    RtlInitEmptyUnicodeString( &newDevExt->DeviceName, newDevExt->DeviceNameBuffer, sizeof(newDevExt->DeviceNameBuffer) );
    SfGetObjectName( storageStackDeviceObject, &newDevExt->DeviceName );

#if WINVER >= 0x0501

    if (IS_WINDOWSXP_OR_LATER())
  {
    
    //¼󣬰СĿǣ֪ͨǰ̣ļϵͳѾ˵ǰĹء
    KEVENT waitEvent;
    KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
        IoCopyCurrentIrpStackLocationToNext ( Irp );
        IoSetCompletionRoutine( Irp,
                                SfFsControlCompletion,
                                &waitEvent,     //context parameter
                                TRUE,
                                TRUE,
                                TRUE );
        status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
      if (STATUS_PENDING == status) 
    {

      //ȴײɣȻͻ̡
        status = KeWaitForSingleObject( &waitEvent,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL );
          ASSERT( STATUS_SUCCESS == status );
      }
        ASSERT(KeReadStateEvent(&waitEvent) ||
               !NT_SUCCESS(Irp->IoStatus.Status));

    
    //ִе˵ĹѾɣҪʼ󶨾ˡȵɺ¼֮󶨾
        status = SfFsControlMountVolumeComplete( DeviceObject, Irp, newDeviceObject );

    }
  else
  {
#endif
    completionContext = ExAllocatePoolWithTag( NonPagedPool, sizeof( FSCTRL_COMPLETION_CONTEXT ), SFLT_POOL_TAG );
        if (completionContext == NULL)
    {
      IoSkipCurrentIrpStackLocation( Irp );
      status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
    }
    else
    {
      //ʼһָһдִеĺSfFsControlMountVolumeCompleteWorker뵽ĳ߳ȥִС
      ExInitializeWorkItem( &completionContext->WorkItem, SfFsControlMountVolumeCompleteWorker,  completionContext );
            completionContext->DeviceObject = DeviceObject;
            completionContext->Irp = Irp;
            completionContext->NewDeviceObject = newDeviceObject;
            IoCopyCurrentIrpStackLocationToNext( Irp );
            IoSetCompletionRoutine( Irp,
                                    SfFsControlCompletion,
                                    &completionContext->WorkItem, //context parameter
                                    TRUE,
                                    TRUE,
                                    TRUE );
            status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
        }
#if WINVER >= 0x0501        
    }
#endif

    return status;
}


VOID  SfFsControlMountVolumeCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context )
{
    ASSERT( Context != NULL );

    SfFsControlMountVolumeComplete( Context->DeviceObject,
                                    Context->Irp,
                                    Context->NewDeviceObject );

    ExFreePoolWithTag( Context, SFLT_POOL_TAG );
}



NTSTATUS  SfFsControlMountVolumeComplete( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_OBJECT NewDeviceObject )
{
  /*
  ˵:

  DeviceObject:        ǰ󶨵ļϵͳ豸豸ջϣһ豸
  Irp:                 Ƿ͸ļϵͳCDOĹһ¾Ĺ
    NewDeviceObject:     ´Ĺ豸ڰ󶨵ļϵͳľ豸豸ջϡ

  */

    PVPB vpb;
    PSFILTER_DEVICE_EXTENSION newDevExt;
    PIO_STACK_LOCATION irpSp;
    PDEVICE_OBJECT attachedDeviceObject;
    NTSTATUS status;

    PAGED_CODE();

    newDevExt = NewDeviceObject->DeviceExtension;
    irpSp = IoGetCurrentIrpStackLocation( Irp );

   /*
  * ȡǱVPBʱͿͨ豸õVPB
  * VPB->DeviceObject  ļϵͳľ豸
  * VPB->RealDevice    豸
  */
    vpb = newDevExt->StorageStackDeviceObject->Vpb;
    if (vpb != irpSp->Parameters.MountVolume.Vpb)
  {
    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                      ("SFilter!SfFsControlMountVolume:              VPB in IRP stack changed   %p IRPVPB=%p VPB=%p\n",
                       vpb->DeviceObject,
                       irpSp->Parameters.MountVolume.Vpb,
                       vpb) );
    }

    if (NT_SUCCESS( Irp->IoStatus.Status ))
  {
    ExAcquireFastMutex( &gSfilterAttachLock );
    if (!SfIsAttachedToDevice( vpb->DeviceObject, &attachedDeviceObject ))
    {
      
     /*
          * SfAttachToMountedDevice壺ǴĹ豸NewDeviceObject󶨵ļϵͳVPB->DeviceObject豸ջϡ          
      */
      status = SfAttachToMountedDevice( vpb->DeviceObject, NewDeviceObject );

      if (!NT_SUCCESS( status ))
      {
        SfCleanupMountedDevice( NewDeviceObject );
        IoDeleteDevice( NewDeviceObject );
      }

      ASSERT( NULL == attachedDeviceObject );
    }
    else
    {
      SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                          ("SFilter!SfFsControlMountVolume               Mount volume failure for   %p \"%wZ\", already attached\n", 
                           ((PSFILTER_DEVICE_EXTENSION)attachedDeviceObject->DeviceExtension)->AttachedToDeviceObject,
                           &newDevExt->DeviceName) );

      SfCleanupMountedDevice( NewDeviceObject );
            IoDeleteDevice( NewDeviceObject );
      ObDereferenceObject( attachedDeviceObject );
        }

    ExReleaseFastMutex( &gSfilterAttachLock );
  }
  else
  {
    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                      ("SFilter!SfFsControlMountVolume:              Mount volume failure for   %p \"%wZ\", status=%08x\n", 
                       DeviceObject,
                       &newDevExt->DeviceName, 
                       Irp->IoStatus.Status) );
    SfCleanupMountedDevice( NewDeviceObject );
    IoDeleteDevice( NewDeviceObject );
  }

  status = Irp->IoStatus.Status;
  IoCompleteRequest( Irp, IO_NO_INCREMENT );
  return status;
}



NTSTATUS  SfFsControlLoadFileSystem( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    NTSTATUS status;
    PFSCTRL_COMPLETION_CONTEXT completionContext;

    PAGED_CODE();shu

  SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                  ("SFilter!SfFscontrolLoadFileSystem:           Loading File System, Detaching from \"%wZ\"\n", 
                   &devExt->DeviceName) );

#if WINVER >= 0x0501
    if (IS_WINDOWSXP_OR_LATER()) 
  {

        KEVENT waitEvent;
        
        KeInitializeEvent( &waitEvent, 
                           NotificationEvent, 
                           FALSE );

        IoCopyCurrentIrpStackLocationToNext( Irp );
        
        IoSetCompletionRoutine( Irp,
                                SfFsControlCompletion,
                                &waitEvent,     //context parameter
                                TRUE,
                                TRUE,
                                TRUE );

        status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );

    if (STATUS_PENDING == status) 
    {

        status = KeWaitForSingleObject( &waitEvent,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL );
          ASSERT( STATUS_SUCCESS == status );
      }

    ASSERT(KeReadStateEvent(&waitEvent) ||
               !NT_SUCCESS(Irp->IoStatus.Status));

        status = SfFsControlLoadFileSystemComplete( DeviceObject, Irp );

    } else {
#endif    
    
        completionContext = ExAllocatePoolWithTag( NonPagedPool, 
                                                   sizeof( FSCTRL_COMPLETION_CONTEXT ),
                                                   SFLT_POOL_TAG );

        if (completionContext == NULL) {

            IoSkipCurrentIrpStackLocation( Irp );
            status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );

        } else {

            ExInitializeWorkItem( &completionContext->WorkItem,
                                  SfFsControlLoadFileSystemCompleteWorker,
                                  completionContext );
            completionContext->DeviceObject = DeviceObject;
            completionContext->Irp = Irp;
            completionContext->NewDeviceObject = NULL;
              
            IoCopyCurrentIrpStackLocationToNext( Irp );

            IoSetCompletionRoutine(
                Irp,
                SfFsControlCompletion,
                completionContext,
                TRUE,
                TRUE,
                TRUE );

            IoDetachDevice( devExt->AttachedToDeviceObject );
            status = IoCallDriver( devExt->AttachedToDeviceObject, Irp );
        }
#if WINVER >= 0x0501        
    }
#endif   
    
    return status;
}



VOID  SfFsControlLoadFileSystemCompleteWorker( IN PFSCTRL_COMPLETION_CONTEXT Context )
{
    ASSERT( NULL != Context );
    SfFsControlLoadFileSystemComplete( Context->DeviceObject, Context->Irp );
    ExFreePoolWithTag( Context, SFLT_POOL_TAG );
}


NTSTATUS  SfFsControlLoadFileSystemComplete ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    PSFILTER_DEVICE_EXTENSION devExt;
    NTSTATUS status;

    PAGED_CODE();

    devExt = DeviceObject->DeviceExtension;
    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                  ("SFilter!SfFsControlLoadFileSystem:           Detaching from recognizer  %p \"%wZ\", status=%08x\n", 
                   DeviceObject,
                   &devExt->DeviceName,
                   Irp->IoStatus.Status) );
    if (!NT_SUCCESS( Irp->IoStatus.Status ) && (Irp->IoStatus.Status != STATUS_IMAGE_ALREADY_LOADED))
  {
    SfAttachDeviceToDeviceStack( DeviceObject, devExt->AttachedToDeviceObject, &devExt->AttachedToDeviceObject );
        ASSERT(devExt->AttachedToDeviceObject != NULL);
    }
  else
  {
    SfCleanupMountedDevice( DeviceObject );
        IoDeleteDevice( DeviceObject );
    }

  status = Irp->IoStatus.Status;
    IoCompleteRequest( Irp, IO_NO_INCREMENT );
    return status;
}



/*****************************************************************************************************************************************************
                                 µĴFastIO Ĵ:

ǵҪ󶨵ļϵͳϱߣļϵͳ˴IRP֮⣬ҪνFastIo
FastIoCache Managerһûirp󡣳Dispatch Functions֮⣬㻹ΪDriverObject дһFast Io Functions
ļϵͳַ̺ͨfastio̶ʱпܱáõĹȻӦͬʱ׽ӿڡ

ڽлIRPΪĽӿڵǰ, IO᳢ʹFAST IO ӿٸIO


FastIO ٵġͬġҡon cached filesIOFastIOʱ账ֱûbufferϵͳндģ
ͨļϵͳʹ洢ջ(storage driver stack)
ʵϴ洢ʹFastIOơҪѾϵͳ棬FastIOƵĶд̾Ϳɡϵͳһȱҳжϣ
ᵼϵͳӦIRPûĶдָͨݲϵͳʱFastIO᷵FALSE
һֱȵȱҳжӦݶصϵͳС(FastIOFALSEô߱ԼӦIrpĴ)


ļϵͳĿ豸CDOһҪIO豸(FiDO)ҪвʶIrpݵԼ²
һҪע⣬ڵϵĹ豸ṩ FastIoDetachDevice 

******************************************************************************************************************************************************/ 
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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoCheckIfPossible ))
    {
      return (fastIoDispatch->FastIoCheckIfPossible)(
                        FileObject,
                        FileOffset,
                        Length,
                        Wait,
                        LockKey,
                        CheckForReadOperation,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension) {

        ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoRead ))
    {
      return (fastIoDispatch->FastIoRead)(
                        FileObject,
                        FileOffset,
                        Length,
                        Wait,
                        LockKey,
                        Buffer,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();
    
    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWrite ))
    {
      return (fastIoDispatch->FastIoWrite)(
                        FileObject,
                        FileOffset,
                        Length,
                        Wait,
                        LockKey,
                        Buffer,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
BOOLEAN  SfFastIoQueryBasicInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_BASIC_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryBasicInfo ))
    {
      return (fastIoDispatch->FastIoQueryBasicInfo)(
                        FileObject,
                        Wait,
                        Buffer,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
BOOLEAN  SfFastIoQueryStandardInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_STANDARD_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryStandardInfo ))
    {
      return (fastIoDispatch->FastIoQueryStandardInfo)(
                        FileObject,
                        Wait,
                        Buffer,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoLock ))
    {
      return (fastIoDispatch->FastIoLock)(
                        FileObject,
                        FileOffset,
                        Length,
                        ProcessId,
                        Key,
                        FailImmediately,
                        ExclusiveLock,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockSingle ))
    {
      return (fastIoDispatch->FastIoUnlockSingle)(
                        FileObject,
                        FileOffset,
                        Length,
                        ProcessId,
                        Key,
                        IoStatus,
                        nextDeviceObject );
    }
  }
  return FALSE;
}
BOOLEAN  SfFastIoUnlockAll( IN PFILE_OBJECT FileObject, PEPROCESS ProcessId, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        if (nextDeviceObject)
    {
      fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
      if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAll ))
      {
        return (fastIoDispatch->FastIoUnlockAll)(
                            FileObject,
                            ProcessId,
                            IoStatus,
                            nextDeviceObject );
            }
        }
    }
    return FALSE;
}
BOOLEAN  SfFastIoUnlockAllByKey( IN PFILE_OBJECT FileObject, PVOID ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoUnlockAllByKey ))
    {
      return (fastIoDispatch->FastIoUnlockAllByKey)(
                        FileObject,
                        ProcessId,
                        Key,
                        IoStatus,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoDeviceControl ))
    {
      return (fastIoDispatch->FastIoDeviceControl)(
                        FileObject,
                        Wait,
                        InputBuffer,
                        InputBufferLength,
                        OutputBuffer,
                        OutputBufferLength,
                        IoControlCode,
                        IoStatus,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


VOID  SfFastIoDetachDevice( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice )
{
    PSFILTER_DEVICE_EXTENSION devExt;

    PAGED_CODE();

    ASSERT(IS_MY_DEVICE_OBJECT( SourceDevice ));
    devExt = SourceDevice->DeviceExtension;
    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                  ("SFilter!SfFastIoDetachDevice:                Detaching from volume      %p \"%wZ\"\n",
                   TargetDevice, &devExt->DeviceName) );
    SfCleanupMountedDevice( SourceDevice );
    IoDetachDevice( TargetDevice );
    IoDeleteDevice( SourceDevice );
}


BOOLEAN  SfFastIoQueryNetworkOpenInfo( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, OUT PFILE_NETWORK_OPEN_INFORMATION Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryNetworkOpenInfo ))
    {
      return (fastIoDispatch->FastIoQueryNetworkOpenInfo)(
                        FileObject,
                        Wait,
                        Buffer,
                        IoStatus,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlRead ))
    {
      return (fastIoDispatch->MdlRead)(
                        FileObject,
                        FileOffset,
                        Length,
                        LockKey,
                        MdlChain,
                        IoStatus,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


BOOLEAN  SfFastIoMdlReadComplete( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadComplete ))
    {
      return (fastIoDispatch->MdlReadComplete)( FileObject, MdlChain, nextDeviceObject );
        }
    }
    return FALSE;
}


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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, PrepareMdlWrite ))
    {
      return (fastIoDispatch->PrepareMdlWrite)(
                        FileObject,
                        FileOffset,
                        Length,
                        LockKey,
                        MdlChain,
                        IoStatus,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


BOOLEAN  SfFastIoMdlWriteComplete( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteComplete ))
    {
      return (fastIoDispatch->MdlWriteComplete)(
                        FileObject,
                        FileOffset,
                        MdlChain,
                        nextDeviceObject );
        }
    }
    return FALSE;
}


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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoReadCompressed ))
    {
      return (fastIoDispatch->FastIoReadCompressed)(
                        FileObject,
                        FileOffset,
                        Length,
                        LockKey,
                        Buffer,
                        MdlChain,
                        IoStatus,
                        CompressedDataInfo,
                        CompressedDataInfoLength,
                        nextDeviceObject );
    }
  }
  return FALSE;
}



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 )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);
        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
    if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoWriteCompressed ))
    {
      return (fastIoDispatch->FastIoWriteCompressed)(
                        FileObject,
                        FileOffset,
                        Length,
                        LockKey,
                        Buffer,
                        MdlChain,
                        IoStatus,
                        CompressedDataInfo,
                        CompressedDataInfoLength,
                        nextDeviceObject );
        }
    }
    return FALSE;
}



BOOLEAN  SfFastIoMdlReadCompleteCompressed( IN PFILE_OBJECT FileObject, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    ASSERT(nextDeviceObject);
    fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
    if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlReadCompleteCompressed ))
    {
      return (fastIoDispatch->MdlReadCompleteCompressed)(
                        FileObject,
                        MdlChain,
                        nextDeviceObject );
        }
    }
    return FALSE;
}



BOOLEAN  SfFastIoMdlWriteCompleteCompressed( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PMDL MdlChain, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;

    if (DeviceObject->DeviceExtension) {

        ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
        nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
        ASSERT(nextDeviceObject);

        fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;

        if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, MdlWriteCompleteCompressed )) {

            return (fastIoDispatch->MdlWriteCompleteCompressed)(
                        FileObject,
                        FileOffset,
                        MdlChain,
                        nextDeviceObject );
        }
    }
    return FALSE;
}



BOOLEAN  SfFastIoQueryOpen( IN PIRP Irp, OUT PFILE_NETWORK_OPEN_INFORMATION NetworkInformation, IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT nextDeviceObject;
    PFAST_IO_DISPATCH fastIoDispatch;
    BOOLEAN result;

    PAGED_CODE();

    if (DeviceObject->DeviceExtension)
  {
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
    nextDeviceObject = ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->AttachedToDeviceObject;
    ASSERT(nextDeviceObject);
    fastIoDispatch = nextDeviceObject->DriverObject->FastIoDispatch;
    if (VALID_FAST_IO_DISPATCH_HANDLER( fastIoDispatch, FastIoQueryOpen ))
    {
      PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
      irpSp->DeviceObject = nextDeviceObject;
      result = (fastIoDispatch->FastIoQueryOpen)(
                        Irp,
                        NetworkInformation,
                        nextDeviceObject );

            irpSp->DeviceObject = DeviceObject;
            return result;
        }
    }
    return FALSE;
}



#if WINVER >= 0x0501
//========================== FSFilter ص ===========================
NTSTATUS  SfPreFsFilterPassThrough( IN PFS_FILTER_CALLBACK_DATA Data, OUT PVOID *CompletionContext )
{
    UNREFERENCED_PARAMETER( Data );
    UNREFERENCED_PARAMETER( CompletionContext );

    ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );

    return STATUS_SUCCESS;
}


VOID  SfPostFsFilterPassThrough ( IN PFS_FILTER_CALLBACK_DATA Data, IN NTSTATUS OperationStatus, IN PVOID CompletionContext )
{
    UNREFERENCED_PARAMETER( Data );
    UNREFERENCED_PARAMETER( OperationStatus );
    UNREFERENCED_PARAMETER( CompletionContext );

    ASSERT( IS_MY_DEVICE_OBJECT( Data->DeviceObject ) );
}
#endif



NTSTATUS  SfAttachDeviceToDeviceStack( IN PDEVICE_OBJECT SourceDevice, IN PDEVICE_OBJECT TargetDevice, IN OUT PDEVICE_OBJECT *AttachedToDeviceObject )
{
  /*
  ˵:

  SourceDevice:         ǵߴ豸󡣱ʹIoCreateDevice豸
  TargetDevice:         ָ豸
  AttachedToDeviceObject:     洢IoAttachDeviceToDeviceStackķֵ

  */

    PAGED_CODE();

#if WINVER >= 0x0501

    if (IS_WINDOWSXP_OR_LATER())
  {
    ASSERT( NULL != gSfDynamicFunctions.AttachDeviceToDeviceStackSafe );
    return (gSfDynamicFunctions.AttachDeviceToDeviceStackSafe)( SourceDevice, TargetDevice, AttachedToDeviceObject );
  }
  else
  {
    ASSERT( NULL == gSfDynamicFunctions.AttachDeviceToDeviceStackSafe );
#endif

        *AttachedToDeviceObject = TargetDevice;
        *AttachedToDeviceObject = IoAttachDeviceToDeviceStack( SourceDevice, TargetDevice );

        if (*AttachedToDeviceObject == NULL)
    {
      return STATUS_NO_SUCH_DEVICE;
        }

        return STATUS_SUCCESS;

#if WINVER >= 0x0501
    }
#endif
}



NTSTATUS  SfAttachToFileSystemDevice( IN PDEVICE_OBJECT DeviceObject, IN PUNICODE_STRING DeviceName )
{
  /*
   SfAttachToFileSystemDeviceɶļϵͳ豸İ󶨡

   ˵:
   DeviceObject:   ָļϵͳĿ豸(CDO) File System CDO

  */

    PDEVICE_OBJECT newDeviceObject;      //豸
    PSFILTER_DEVICE_EXTENSION devExt;    //ļϵͳ豸չ
    NTSTATUS status;            //״̬
    UNICODE_STRING fsrecName;                            
    UNICODE_STRING fsName;          //ļϵͳ
    WCHAR tempNameBuffer[MAX_DEVNAME_LENGTH];//ʱ(ִ)

    PAGED_CODE();

    if (!IS_DESIRED_DEVICE_TYPE(DeviceObject->DeviceType))  //Ը豸ǲҪĵ豸
  {
    return STATUS_SUCCESS;
  }
  

  /*
   * Windowsı׼ļϵͳʶ϶ \FileSystem\Fs_Rec ɵġֱжֿԽһ⡣
   * ҲһǵҪļϵͳʶ\FileSystem\Fs_Rec档ֻ˵һ\FileSystem\Fs_Rec档
   */
  RtlInitEmptyUnicodeString( &fsName, tempNameBuffer, sizeof(tempNameBuffer) );
  
  if (!FlagOn(SfDebug,SFDEBUG_ATTACH_TO_FSRECOGNIZER))
  {
    RtlInitUnicodeString( &fsrecName, L"\\FileSystem\\Fs_Rec" );
    SfGetObjectName( DeviceObject->DriverObject, &fsName );

    if (RtlCompareUnicodeString( &fsName, &fsrecName, TRUE ) == 0)
    {  
      //ֱͨWindowsı׼ļϵͳʶǣôسɹҲǷˡ
      //дļϵͳʶûбжϵļϵͳĹжӦĴ
      return STATUS_SUCCESS;
    }
  }

  
  
  //ǹĵļϵͳҲ΢ļϵͳʶ豸һ豸豸
    status = IoCreateDevice( gSFilterDriverObject,
                             sizeof( SFILTER_DEVICE_EXTENSION ),
                             NULL,
                             DeviceObject->DeviceType,
                             0,
                             FALSE,
                             &newDeviceObject );

    if (!NT_SUCCESS( status ))
  {
    return status;
  }

    if ( FlagOn( DeviceObject->Flags, DO_BUFFERED_IO ))
  {
    SetFlag( newDeviceObject->Flags, DO_BUFFERED_IO );                
  }

    if ( FlagOn( DeviceObject->Flags, DO_DIRECT_IO ))
  {
    SetFlag( newDeviceObject->Flags, DO_DIRECT_IO );                  
  }

    if ( FlagOn( DeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN ) )
  {
    SetFlag( newDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN );    
    }

  devExt = newDeviceObject->DeviceExtension;

  
  /*
    SfAttachDeviceToDeviceStack豸󶨵File System CDO豸ջ档ǵnewDeviceObjectͿԽյ͵
    File System CDOIRP_MJ_FILE_SYSTEM_CONTROLˡ Ժ󣬳Ϳȥ󶨾ˡ
    ʹSfAttachDeviceToDeviceStackа󶨡1󶨵2󶨺ص豸洢ڲ3С
   */
  status = SfAttachDeviceToDeviceStack( newDeviceObject, DeviceObject,  &devExt->AttachedToDeviceObject );
  if (!NT_SUCCESS( status ))
  {
    goto ErrorCleanupDevice;
  }

  RtlInitEmptyUnicodeString( &devExt->DeviceName, devExt->DeviceNameBuffer, sizeof(devExt->DeviceNameBuffer) );
    RtlCopyUnicodeString( &devExt->DeviceName, DeviceName );        //Save Name
    ClearFlag( newDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                  ("SFilter!SfAttachToFileSystemDevice:          Attaching to file system   %p \"%wZ\" (%s)\n",
                   DeviceObject,
                   &devExt->DeviceName,
                   GET_DEVICE_TYPE_NAME(newDeviceObject->DeviceType)) );
 
#if WINVER >= 0x0501

    if (IS_WINDOWSXP_OR_LATER())
  {
    ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList &&
                NULL != gSfDynamicFunctions.GetDiskDeviceObject &&
                NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef &&
                NULL != gSfDynamicFunctions.GetLowerDeviceObject );

    
    /* 
    SpyEnumerateFileSystemVolumesöٸļϵͳµĵǰڵй˵豸Ұǡ
        ĿģΪʱأǼعʱļϵͳѾ˾豸
    ǣùӺأʱܰѾڻոչļϵͳ豸
    */
    status = SfEnumerateFileSystemVolumes( DeviceObject, &fsName );
    if (!NT_SUCCESS( status ))
    {
      IoDetachDevice( devExt->AttachedToDeviceObject );
      goto ErrorCleanupDevice;
    }
  }

#endif

    return STATUS_SUCCESS;

    ErrorCleanupDevice:
    SfCleanupMountedDevice( newDeviceObject );
    IoDeleteDevice( newDeviceObject );

    return status;
}



VOID  SfDetachFromFileSystemDevice( IN PDEVICE_OBJECT DeviceObject )
{
    PDEVICE_OBJECT ourAttachedDevice;
    PSFILTER_DEVICE_EXTENSION devExt;

    PAGED_CODE();

  ourAttachedDevice = DeviceObject->AttachedDevice;
  while (NULL != ourAttachedDevice)
  {
    if (IS_MY_DEVICE_OBJECT( ourAttachedDevice ))
    {
      devExt = ourAttachedDevice->DeviceExtension;
      SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                          ("SFilter!SfDetachFromFileSystemDevice:        Detaching from file system %p \"%wZ\" (%s)\n",
                           devExt->AttachedToDeviceObject,
                           &devExt->DeviceName,
                           GET_DEVICE_TYPE_NAME(ourAttachedDevice->DeviceType)) );
      
      SfCleanupMountedDevice( ourAttachedDevice );
            IoDetachDevice( DeviceObject );
            IoDeleteDevice( ourAttachedDevice );

            return;
        }
    
    DeviceObject = ourAttachedDevice;
        ourAttachedDevice = ourAttachedDevice->AttachedDevice;
    }
}



#if WINVER >= 0x0501
NTSTATUS  SfEnumerateFileSystemVolumes( IN PDEVICE_OBJECT FSDeviceObject, IN PUNICODE_STRING Name ) 
{
  /*
  ˵:
   
    FSDeviceObject:    ָļϵͳĿ豸(CDO) File System CDO
  Name:         ļϵͳ

  */

    PDEVICE_OBJECT newDeviceObject;
    PSFILTER_DEVICE_EXTENSION newDevExt;
    PDEVICE_OBJECT *devList;
    PDEVICE_OBJECT storageStackDeviceObject;
    NTSTATUS status;
    ULONG numDevices;
    ULONG i;
    BOOLEAN isShadowCopyVolume;

    PAGED_CODE();
  
  /*
   * IoEnumerateDeviceObjectListöµ豸б2Ρ
   * 1εã ȡ豸бе豸
   * 2ε:  ݵ1εĽnumDevicesֵ豸Ĵſռ䣬Ӷõ豸devList
   */
  status = (gSfDynamicFunctions.EnumerateDeviceObjectList)(
                    FSDeviceObject->DriverObject,
                    NULL,
                    0,
                    &numDevices);
  
  if (!NT_SUCCESS( status ))
  {
    ASSERT(STATUS_BUFFER_TOO_SMALL == status);
    numDevices += 8;  //Ϊ֪豸ڴռд洢8ֽڡ

    
    devList = ExAllocatePoolWithTag( NonPagedPool, (numDevices * sizeof(PDEVICE_OBJECT)), SFLT_POOL_TAG );
    if (NULL == devList)
    {
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    ASSERT( NULL != gSfDynamicFunctions.EnumerateDeviceObjectList );
    status = (gSfDynamicFunctions.EnumerateDeviceObjectList)(
                        FSDeviceObject->DriverObject,
                        devList,
                        (numDevices * sizeof(PDEVICE_OBJECT)),
                        &numDevices);
    
    if (!NT_SUCCESS( status ))
    {
      ExFreePool( devList );
      return status;
    }
    
    //α豸
    for (i=0; i < numDevices; i++)
    {
      storageStackDeviceObject = NULL;
      try {
         
        //豸ļϵͳCDOǲ͵ģѾ󶨵
        if ((devList[i] == FSDeviceObject) || (devList[i]->DeviceType != FSDeviceObject->DeviceType) || SfIsAttachedToDevice( devList[i], NULL ))
        {
          leave;
        }
        
        SfGetBaseDeviceObjectName( devList[i], Name );
        if (Name->Length > 0)
        {
          leave;
        }


        /*
         IoGetDiskDeviceObjectȡһļϵͳ豸йصĴ豸ֻѾӵһ豸ļϵͳ豸
         */
        ASSERT( NULL != gSfDynamicFunctions.GetDiskDeviceObject );
                status = (gSfDynamicFunctions.GetDiskDeviceObject)( devList[i], &storageStackDeviceObject );

                if (!NT_SUCCESS( status ))
        {
          leave;
        }
        
        status = SfIsShadowCopyVolume ( storageStackDeviceObject, &isShadowCopyVolume );

                if (NT_SUCCESS(status) &&
                    isShadowCopyVolume &&
                    !FlagOn(SfDebug,SFDEBUG_ATTACH_TO_SHADOW_COPIES)) 
        {

                    UNICODE_STRING shadowDeviceName;
                    WCHAR shadowNameBuffer[MAX_DEVNAME_LENGTH];

          RtlInitEmptyUnicodeString( &shadowDeviceName, shadowNameBuffer, sizeof(shadowNameBuffer) );
          SfGetObjectName( storageStackDeviceObject, &shadowDeviceName );

                    SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                                  ("SFilter!SfEnumerateFileSystemVolumes         Not attaching to Volume    %p \"%wZ\", shadow copy volume\n", 
                                   storageStackDeviceObject,
                                   &shadowDeviceName) );
          
          leave;
        }
        

        // һ豸󣬴µ豸׼󶨡
        status = IoCreateDevice( gSFilterDriverObject,
                                         sizeof( SFILTER_DEVICE_EXTENSION ),
                                         NULL,
                                         devList[i]->DeviceType,
                                         0,
                                         FALSE,
                                         &newDeviceObject );
        if (!NT_SUCCESS( status ))
        {
          leave;
        }
        
        newDevExt = newDeviceObject->DeviceExtension;
                newDevExt->StorageStackDeviceObject = storageStackDeviceObject;
        RtlInitEmptyUnicodeString( &newDevExt->DeviceName, newDevExt->DeviceNameBuffer,sizeof(newDevExt->DeviceNameBuffer) );
        SfGetObjectName( storageStackDeviceObject, &newDevExt->DeviceName );
      

        /*
         ڰʱٲ£豸Ƿ񱻰󶨹һû󶨣ִİ󶨹ֱ̣ӷء
        */
        ExAcquireFastMutex( &gSfilterAttachLock );
        if (!SfIsAttachedToDevice( devList[i], NULL ))
        {
          status = SfAttachToMountedDevice( devList[i], newDeviceObject );
          if (!NT_SUCCESS( status ))
          {
            SfCleanupMountedDevice( newDeviceObject );
            IoDeleteDevice( newDeviceObject );
          }
        }
        else
        {
          SfCleanupMountedDevice( newDeviceObject );
          IoDeleteDevice( newDeviceObject );
        }
        
        ExReleaseFastMutex( &gSfilterAttachLock );
      }
      
      finally {
        
      /*
       豸ļɺIoGetDiskDeviceObjectӵġɹ󶨺󣬾ͼٸ豸ļ
       һɹ󶨵devList[i]I/Oȷ豸ջ²豸һֱڣһֱļϵͳջж
      */
        if (storageStackDeviceObject != NULL)
        {
          ObDereferenceObject( storageStackDeviceObject );
        }
        
        
        //豸ļɺIoEnumerateDeviceObjectListӵġ
        ObDereferenceObject( devList[i] );
            }
        }
    
    status = STATUS_SUCCESS;
    ExFreePool( devList );
  }
  
  return status;
}
#endif



NTSTATUS  SfAttachToMountedDevice( IN PDEVICE_OBJECT DeviceObject, IN PDEVICE_OBJECT SFilterDeviceObject )
{
  /*
  SfAttachToMountedDeviceĹ: ɰһļϵͳ豸Ĳ
  
  ˵:
  SFilterDeviceObject:  ʹIoCreateDevice豸

  */

    PSFILTER_DEVICE_EXTENSION newDevExt = SFilterDeviceObject->DeviceExtension;
    NTSTATUS status;
    ULONG i;

    PAGED_CODE();
  ASSERT(IS_MY_DEVICE_OBJECT( SFilterDeviceObject ));
#if WINVER >= 0x0501
  ASSERT(!SfIsAttachedToDevice ( DeviceObject, NULL ));
#endif
  
  if (FlagOn( DeviceObject->Flags, DO_BUFFERED_IO ))
  {
    SetFlag( SFilterDeviceObject->Flags, DO_BUFFERED_IO );
  }
  
  if (FlagOn( DeviceObject->Flags, DO_DIRECT_IO ))
  {
    SetFlag( SFilterDeviceObject->Flags, DO_DIRECT_IO );
  }
  
  for (i=0; i < 8; i++)
  {
    LARGE_INTEGER interval;

    //SfAttachDeviceToDeviceStack  İ
    status = SfAttachDeviceToDeviceStack( SFilterDeviceObject, DeviceObject, &newDevExt->AttachedToDeviceObject );
    if (NT_SUCCESS(status))
    {
      ClearFlag( SFilterDeviceObject->Flags, DO_DEVICE_INITIALIZING );
      SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
                          ("SFilter!SfAttachToMountedDevice:             Attaching to volume        %p \"%wZ\"\n", 
                           newDevExt->AttachedToDeviceObject,
                           &newDevExt->DeviceName) );
      return STATUS_SUCCESS;
    }

    interval.QuadPart = (500 * DELAY_ONE_MILLISECOND);      //delay 1/2 second
        KeDelayExecutionThread( KernelMode, FALSE, &interval );
    }

    return status;
}



VOID  SfCleanupMountedDevice( IN PDEVICE_OBJECT DeviceObject )
{        

    UNREFERENCED_PARAMETER( DeviceObject );
    ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
}



VOID  SfGetObjectName( IN PVOID Object, IN OUT PUNICODE_STRING Name )
{
    NTSTATUS status;
    CHAR nibuf[512];                              //շصĶ
    POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)nibuf;    //nameInfoŵָUNICODE_STRINGṹָ
    ULONG retLength;                              //"ʵʷصĶ"
  
  status = ObQueryNameString( Object, nameInfo, sizeof(nibuf), &retLength);  //ض
  Name->Length = 0;
  if (NT_SUCCESS( status ))
  {
    RtlCopyUnicodeString( Name, &nameInfo->Name );
  }
}



#if WINVER >= 0x0501

VOID  SfGetBaseDeviceObjectName( IN PDEVICE_OBJECT DeviceObject, IN OUT PUNICODE_STRING Name )
{
  ASSERT( NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef );
  DeviceObject = (gSfDynamicFunctions.GetDeviceAttachmentBaseRef)( DeviceObject );
  SfGetObjectName( DeviceObject, Name );
  ObDereferenceObject( DeviceObject );
}
#endif



PUNICODE_STRING  SfGetFileName( IN PFILE_OBJECT FileObject, IN NTSTATUS CreateStatus, IN OUT PGET_NAME_CONTROL NameControl )
{
    POBJECT_NAME_INFORMATION nameInfo;
    NTSTATUS status;
    ULONG size;
    ULONG bufferSize;

  NameControl->allocatedBuffer = NULL;
  nameInfo = (POBJECT_NAME_INFORMATION)NameControl->smallBuffer;
  bufferSize = sizeof(NameControl->smallBuffer);
  status = ObQueryNameString( (NT_SUCCESS( CreateStatus ) ? (PVOID)FileObject :  (PVOID)FileObject->DeviceObject), nameInfo, bufferSize, &size );
  if (status == STATUS_BUFFER_OVERFLOW)
  {
    bufferSize = size + sizeof(WCHAR);
    NameControl->allocatedBuffer = ExAllocatePoolWithTag( NonPagedPool, bufferSize, SFLT_POOL_TAG );
    if (NULL == NameControl->allocatedBuffer)
    {
      RtlInitEmptyUnicodeString(
                (PUNICODE_STRING)&NameControl->smallBuffer,
                (PWCHAR)(NameControl->smallBuffer + sizeof(UNICODE_STRING)),
                (USHORT)(sizeof(NameControl->smallBuffer) - sizeof(UNICODE_STRING)) );

            return (PUNICODE_STRING)&NameControl->smallBuffer;
        }
    
    nameInfo = (POBJECT_NAME_INFORMATION)NameControl->allocatedBuffer;
    status = ObQueryNameString(
                      FileObject,
                      nameInfo,
                      bufferSize,
                      &size );
    }
  
  if (NT_SUCCESS( status ) && !NT_SUCCESS( CreateStatus ))
  {
    ULONG newSize;
        PCHAR newBuffer;
        POBJECT_NAME_INFORMATION newNameInfo;
    newSize = size + FileObject->FileName.Length;
    if (NULL != FileObject->RelatedFileObject)
    {
      newSize += FileObject->RelatedFileObject->FileName.Length + sizeof(WCHAR);
    }
    
    if (newSize > bufferSize)
    {
      newBuffer = ExAllocatePoolWithTag( NonPagedPool, newSize, SFLT_POOL_TAG );
      if (NULL == newBuffer)
      {
        RtlInitEmptyUnicodeString(
                    (PUNICODE_STRING)&NameControl->smallBuffer,
                    (PWCHAR)(NameControl->smallBuffer + sizeof(UNICODE_STRING)),
                    (USHORT)(sizeof(NameControl->smallBuffer) - sizeof(UNICODE_STRING)) );

                return (PUNICODE_STRING)&NameControl->smallBuffer;
            }
      
      newNameInfo = (POBJECT_NAME_INFORMATION)newBuffer;
      
      RtlInitEmptyUnicodeString(
                &newNameInfo->Name,
                (PWCHAR)(newBuffer + sizeof(OBJECT_NAME_INFORMATION)),
                (USHORT)(newSize - sizeof(OBJECT_NAME_INFORMATION)) );

            RtlCopyUnicodeString( &newNameInfo->Name, &nameInfo->Name );
      if (NULL != NameControl->allocatedBuffer) 
      {
        ExFreePool( NameControl->allocatedBuffer );
      }
      
      NameControl->allocatedBuffer = newBuffer;
            bufferSize = newSize;
            nameInfo = newNameInfo;
    }
    else
    {
      nameInfo->Name.MaximumLength = (USHORT)(bufferSize - sizeof(OBJECT_NAME_INFORMATION));
    }
    
    if (NULL != FileObject->RelatedFileObject)
    {
      RtlAppendUnicodeStringToString( &nameInfo->Name, &FileObject->RelatedFileObject->FileName );
      RtlAppendUnicodeToString( &nameInfo->Name, L"\\" );
    }
    
    RtlAppendUnicodeStringToString( &nameInfo->Name, &FileObject->FileName );
    ASSERT(nameInfo->Name.Length <= nameInfo->Name.MaximumLength);
  }
  
  return &nameInfo->Name;
}



VOID SfGetFileNameCleanup( IN OUT PGET_NAME_CONTROL NameControl )
{

    if (NULL != NameControl->allocatedBuffer) {

        ExFreePool( NameControl->allocatedBuffer);
        NameControl->allocatedBuffer = NULL;
    }
}



BOOLEAN  SfIsAttachedToDevice( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{

    PAGED_CODE();

#if WINVER >= 0x0501
    if (IS_WINDOWSXP_OR_LATER())
  {
    ASSERT( NULL != gSfDynamicFunctions.GetLowerDeviceObject && NULL != gSfDynamicFunctions.GetDeviceAttachmentBaseRef );
    return SfIsAttachedToDeviceWXPAndLater( DeviceObject, AttachedDeviceObject );
    }
  else
  {
#endif
    return SfIsAttachedToDeviceW2K( DeviceObject, AttachedDeviceObject );
#if WINVER >= 0x0501
  }
#endif    
}



BOOLEAN  SfIsAttachedToDeviceW2K( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{
    PDEVICE_OBJECT currentDevice;
    PAGED_CODE();

    for (currentDevice = DeviceObject;  currentDevice != NULL;  currentDevice = currentDevice->AttachedDevice)
  {
    if (IS_MY_DEVICE_OBJECT( currentDevice ))
    {
      if (ARGUMENT_PRESENT(AttachedDeviceObject))
      {
        ObReferenceObject( currentDevice );
        *AttachedDeviceObject = currentDevice;
      }
      return TRUE;
    }
  }
  
  if (ARGUMENT_PRESENT(AttachedDeviceObject))
  {
    *AttachedDeviceObject = NULL;
  }
  return FALSE;
}



#if WINVER >= 0x0501
BOOLEAN  SfIsAttachedToDeviceWXPAndLater( PDEVICE_OBJECT DeviceObject, PDEVICE_OBJECT *AttachedDeviceObject OPTIONAL )
{
    PDEVICE_OBJECT currentDevObj;
    PDEVICE_OBJECT nextDevObj;

    PAGED_CODE();

    ASSERT( NULL != gSfDynamicFunctions.GetAttachedDeviceReference );
    currentDevObj = (gSfDynamicFunctions.GetAttachedDeviceReference)( DeviceObject );
  
  do {
    
    if (IS_MY_DEVICE_OBJECT( currentDevObj ))
    {
      if (ARGUMENT_PRESENT(AttachedDeviceObject))
      {
        *AttachedDeviceObject = currentDevObj;
      }
      else
      {
        ObDereferenceObject( currentDevObj );
      }
      return TRUE;
    }

    ASSERT( NULL != gSfDynamicFunctions.GetLowerDeviceObject );
    nextDevObj = (gSfDynamicFunctions.GetLowerDeviceObject)( currentDevObj );
        ObDereferenceObject( currentDevObj );
    currentDevObj = nextDevObj;
  } while (NULL != currentDevObj);
  
  if (ARGUMENT_PRESENT(AttachedDeviceObject))
  {
    *AttachedDeviceObject = NULL;
  }
  
  return FALSE;
}
#endif



VOID  SfReadDriverParameters( IN PUNICODE_STRING RegistryPath )
{
    OBJECT_ATTRIBUTES attributes;
    HANDLE driverRegKey;
    NTSTATUS status;
    ULONG resultLength;
    UNICODE_STRING valueName;
    UCHAR buffer[sizeof( KEY_VALUE_PARTIAL_INFORMATION ) + sizeof( LONG )];

    PAGED_CODE();
  
  if (0 == SfDebug)
  {
    InitializeObjectAttributes( &attributes,
                                    RegistryPath,
                                    OBJ_CASE_INSENSITIVE,
                                    NULL,
                                    NULL );
    
    status = ZwOpenKey( &driverRegKey, KEY_READ, &attributes );
    if (!NT_SUCCESS( status ))
    {
      return;
    }
    
    RtlInitUnicodeString( &valueName, L"DebugFlags" );
    status = ZwQueryValueKey( driverRegKey,
                                  &valueName,
                                  KeyValuePartialInformation,
                                  buffer,
                                  sizeof(buffer),
                                  &resultLength );
    if (NT_SUCCESS( status ))
    {
      SfDebug = *((PLONG) &(((PKEY_VALUE_PARTIAL_INFORMATION) buffer)->Data));
    }
    
    ZwClose(driverRegKey);
  }
}




NTSTATUS  SfIsShadowCopyVolume( IN PDEVICE_OBJECT StorageStackDeviceObject, OUT PBOOLEAN IsShadowCopy )
{

/*******************************************************************************************************************************************
SfIsShadowCopyVolume( )Ҫǣ漰 Ӱġ

Ӱ(Volume Shadow Copy ServiceVSS)һֱݺͻָļһֻʱļļ
ͨʹþӰǿضϽݿʱ㣬ڽĳһʱ̰ݻָκһʱ״̬
һǻָΪԭɵݶʧûش洢дϢļǲСɾļ⡣
VSSղɾݾԼָʱ㿽ǼȿԻָգҲȡ裬߻ʹVSSݹָļļС

VSSǶӦóбݵģVSSԶ߼(Ӳ̷)пա
VSSWindowsµĿռRequestor, Write,ProviderɣҪVolsnap.sysʵ֣ӵļϵͳ֮䣬ͬʱCOM
ˣǵھϵblockдǺ͸ϵͳӦSQLEXCHANGEADȵȡӶʹڲػҲֹͣӦõ£ա
VSS㷺ӦõWindowsıݴС

VSS ķǣͨṩҪʵ֮ͨѶ֤ݵĸ߶ʵͻ̵ָļ㡣
(1)ʱݸӰӦó򣬱籸ݻ洢Ӧó
(2)дǸ֪ͨݱдVSSӰսĵطVSSľӰƹл漰һЩӦó
(3)ṩڱ¶ӲľӰĻơ洢ӲӦ̶ΪǵĴ洢бдṩ


VSSΨһȱǣ
ҪΪÿһӰĴ̿ռ䣬Ǳĳ洢ЩΪVSSʹָݣЩռõĿռҪСö࣬ǿЧش洢Щ


йVSSĸ˵ȥMicrosoftվ

http://technet.microsoft.com/en-us/library/ee923636.aspx

 *********************************************************************************************************************************************/
    PAGED_CODE();

    *IsShadowCopy = FALSE;

#if WINVER >= 0x0501
    if (IS_WINDOWS2000())
  {
#endif
    UNREFERENCED_PARAMETER( StorageStackDeviceObject );
    return STATUS_SUCCESS;
#if WINVER >= 0x0501
  }
  
  if (IS_WINDOWSXP())
  {
    UNICODE_STRING volSnapDriverName;
    WCHAR buffer[MAX_DEVNAME_LENGTH];
    PUNICODE_STRING storageDriverName;
    ULONG returnedLength;
    NTSTATUS status;
    
    if (FILE_DEVICE_DISK != StorageStackDeviceObject->DeviceType)
    {
      return STATUS_SUCCESS;
    }
    
    storageDriverName = (PUNICODE_STRING) buffer;
    RtlInitEmptyUnicodeString( storageDriverName, Add2Ptr( storageDriverName, sizeof( UNICODE_STRING ) ), sizeof( buffer ) - sizeof( UNICODE_STRING ) );
    status = ObQueryNameString( StorageStackDeviceObject, (POBJECT_NAME_INFORMATION)storageDriverName, storageDriverName->MaximumLength, &returnedLength );
    if (!NT_SUCCESS( status ))
    {
      return status;
    }
    
    RtlInitUnicodeString( &volSnapDriverName, L"\\Driver\\VolSnap" );
    if (RtlEqualUnicodeString( storageDriverName, &volSnapDriverName, TRUE ))
    {
      *IsShadowCopy = TRUE;
    }
    else
    {
      NOTHING;
    }
    
    return STATUS_SUCCESS;
  }
  else
  {
    PIRP irp;
    KEVENT event;
    IO_STATUS_BLOCK iosb;
    NTSTATUS status;
    if (FILE_DEVICE_VIRTUAL_DISK != StorageStackDeviceObject->DeviceType)
    {
      return STATUS_SUCCESS;
    }
    
    KeInitializeEvent( &event, NotificationEvent, FALSE );

     /*
    *Microsoft WDKٷĵ IOCTL_DISK_IS_WRITABLE͵ģ
    *Determines whether a disk is writable.
    *The Status field can be set to STATUS_SUCCESS, or possibly to STATUS_INSUFFICIENT_RESOURCES, STATUS_IO_DEVICE_ERROR, or STATUS_MEDIA_WRITE_PROTECTED.
    *
    *IOCTL_DISK_IS_WRITABLEûҲûġ
    */
    irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_IS_WRITABLE,
                                             StorageStackDeviceObject,
                                             NULL,
                                             0,
                                             NULL,
                                             0,
                                             FALSE,
                                             &event,
                                             &iosb );
    if (irp == NULL)
    {
      return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    status = IoCallDriver( StorageStackDeviceObject, irp );
    if (status == STATUS_PENDING)
    {
      (VOID)KeWaitForSingleObject( &event,
                                         Executive,
                                         KernelMode,
                                         FALSE,
                                         NULL );
      status = iosb.Status;
    }

    if (STATUS_MEDIA_WRITE_PROTECTED == status)
    {
      *IsShadowCopy = TRUE;
      status = STATUS_SUCCESS;
    }

    return status;
  }
#endif
}

Ĵȫͨ
WDK7600.16385.1˳ͨġ 




ϣܹע⼸Եĵط
 (1) ShadowCopyVolume---ҲǾӰ
 (2) FastIo
 (3) ļϵͳ豸İ󶨡
 (4) ļϵͳ豸İ󶨡
 (5) SfCreateһСϸڡ 