?? sfilter.c
字號:
/*++
Copyright (c) 1989-2004 Microsoft Corporation
Module Name:
sfilter.c
Abstract:
This module contains the code that implements the general purpose sample
file system filter driver.
As of the Windows XP SP1 IFS Kit version of this sample and later, this
sample can be built for each build environment released with the IFS Kit
with no additional modifications. To provide this capability, additional
compile-time logic was added -- see the '#if WINVER' locations. Comments
tagged with the 'VERSION NOTE' header have also been added as appropriate to
describe how the logic must change between versions.
If this sample is built in the Windows XP environment or later, it will run
on Windows 2000 or later. This is done by dynamically loading the routines
that are only available on Windows XP or later and making run-time decisions
to determine what code to execute. Comments tagged with 'MULTIVERISON NOTE'
mark the locations where such logic has been added.
Environment:
Kernel mode
--*/
//
// Fixes Win2K compatibility regarding lookaside lists.
//
#ifndef _WIN2K_COMPAT_SLIST_USAGE
#define _WIN2K_COMPAT_SLIST_USAGE
#endif
#include "ntifs.h"
#include "ntdddisk.h"
#include "namelookup.h"
#include <dontuse.h>
//
// Enable these warnings in the code.
//
#pragma warning(error:4100) // Unreferenced formal parameter
#pragma warning(error:4101) // Unreferenced local variable
/////////////////////////////////////////////////////////////////////////////
//
// Macro and Structure Definitions
//
/////////////////////////////////////////////////////////////////////////////
//
// VERSION NOTE:
//
// The following useful macros are defined in NTIFS.H in Windows XP and later.
// We will define them locally if we are building for the Windows 2000
// environment.
//
#if WINVER == 0x0500
//
// These macros are used to test, set and clear flags respectively
//
#ifndef FlagOn
#define FlagOn(_F,_SF) ((_F) & (_SF))
#endif
#ifndef BooleanFlagOn
#define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0))
#endif
#ifndef SetFlag
#define SetFlag(_F,_SF) ((_F) |= (_SF))
#endif
#ifndef ClearFlag
#define ClearFlag(_F,_SF) ((_F) &= ~(_SF))
#endif
#define RtlInitEmptyUnicodeString(_ucStr,_buf,_bufSize) \
((_ucStr)->Buffer = (_buf), \
(_ucStr)->Length = 0, \
(_ucStr)->MaximumLength = (USHORT)(_bufSize))
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
//
// We want ASSERT defined as an expression, which was fixed after Windows 2000
//
#ifdef ASSERT
#undef ASSERT
#if DBG
#define ASSERT( exp ) \
((!(exp)) ? \
(RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \
TRUE)
#else
#define ASSERT( exp ) ((void) 0)
#endif
#endif
#define ExFreePoolWithTag( a, b ) ExFreePool( (a) )
#endif /* WINVER == 0x0500 */
#ifndef Add2Ptr
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
#endif
//
// Buffer size for local names on the stack
//
#define MAX_DEVNAME_LENGTH 64
#define CONSTANT_UNICODE_STRING(s) { sizeof( s ) - sizeof( WCHAR ), sizeof(s), s }
//
// Device extension definition for our driver. Note that the same extension
// is used for the following types of device objects:
// - File system device object we attach to
// - Mounted volume device objects we attach to
//
typedef struct _SFILTER_DEVICE_EXTENSION {
//
// NL_DEVICE_EXTENSION_HEADER contains all the fields that are needed by
// the name lookup library. It happens to contain all fields SFilter needs
// for its device extension.
//
NL_DEVICE_EXTENSION_HEADER NLExtHeader;
//
// Local flags for this device
//
ULONG Flags;
} SFILTER_DEVICE_EXTENSION, *PSFILTER_DEVICE_EXTENSION;
//
// If set, disable all special debug options on this volume
//
#define SFDEVFL_DISABLE_VOLUME 0x00000001
//
// This structure contains the information we need to pass to the completion
// processing for FSCTRLs.
//
typedef struct _FSCTRL_COMPLETION_CONTEXT {
//
// The workitem that will be initialized with our context and
// worker routine if this completion processing needs to be completed
// in a worker thread.
//
WORK_QUEUE_ITEM WorkItem;
//
// The device object to which this device is currently directed.
//
PDEVICE_OBJECT DeviceObject;
//
// The IRP for this FSCTRL operation.
//
PIRP Irp;
//
// For mount operations, the new device object that we have allocated
// and partially initialized that we will attach to the mounted volume
// if the mount is successful.
//
PDEVICE_OBJECT NewDeviceObject;
} FSCTRL_COMPLETION_CONTEXT, *PFSCTRL_COMPLETION_CONTEXT;
//
// Macro to test if this is my device object
//
#define IS_MY_DEVICE_OBJECT(_devObj) \
(((_devObj) != NULL) && \
((_devObj)->DriverObject == gSFilterDriverObject) && \
((_devObj)->DeviceExtension != NULL))
//
// Macro to test if this is my control device object
//
#define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
(((_devObj) == gSFilterControlDeviceObject) ? \
(ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && \
((_devObj)->DeviceExtension == NULL)), TRUE) : \
FALSE)
//
// Macro to test for device types we want to attach to
//
#define IS_DESIRED_DEVICE_TYPE(_type) \
(((_type) == FILE_DEVICE_DISK_FILE_SYSTEM) || \
((_type) == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || \
((_type) == FILE_DEVICE_NETWORK_FILE_SYSTEM))
//
// Macro to test if FAST_IO_DISPATCH handling routine is valid
//
#define VALID_FAST_IO_DISPATCH_HANDLER(_FastIoDispatchPtr, _FieldName) \
(((_FastIoDispatchPtr) != NULL) && \
(((_FastIoDispatchPtr)->SizeOfFastIoDispatch) >= \
(FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && \
((_FastIoDispatchPtr)->_FieldName != NULL))
#if WINVER >= 0x0501
//
// MULTIVERSION NOTE:
//
// If built in the Windows XP environment or later, we will dynamically import
// the function pointers for routines that were not supported on Windows 2000
// so that we can build a driver that will run, with modified logic, on
// Windows 2000 or later.
//
// Below are the prototypes for the function pointers that we need to
// dynamically import because not all OS versions support these routines.
//
typedef
NTSTATUS
(*PSF_REGISTER_FILE_SYSTEM_FILTER_CALLBACKS) (
IN PDRIVER_OBJECT DriverObject,
IN PFS_FILTER_CALLBACKS Callbacks
);
typedef
NTSTATUS
(*PSF_ENUMERATE_DEVICE_OBJECT_LIST) (
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT *DeviceObjectList,
IN ULONG DeviceObjectListSize,
OUT PULONG ActualNumberDeviceObjects
);
typedef
NTSTATUS
(*PSF_ATTACH_DEVICE_TO_DEVICE_STACK_SAFE) (
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject
);
typedef
PDEVICE_OBJECT
(*PSF_GET_LOWER_DEVICE_OBJECT) (
IN PDEVICE_OBJECT DeviceObject
);
typedef
PDEVICE_OBJECT
(*PSF_GET_DEVICE_ATTACHMENT_BASE_REF) (
IN PDEVICE_OBJECT DeviceObject
);
typedef
NTSTATUS
(*PSF_GET_DISK_DEVICE_OBJECT) (
IN PDEVICE_OBJECT FileSystemDeviceObject,
OUT PDEVICE_OBJECT *DiskDeviceObject
);
typedef
PDEVICE_OBJECT
(*PSF_GET_ATTACHED_DEVICE_REFERENCE) (
IN PDEVICE_OBJECT DeviceObject
);
typedef
NTSTATUS
(*PSF_GET_VERSION) (
IN OUT PRTL_OSVERSIONINFOW VersionInformation
);
typedef struct _SF_DYNAMIC_FUNCTION_POINTERS {
//
// The following routines should all be available on Windows XP (5.1) and
// later.
//
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};
//
// MULTIVERSION NOTE: For this version of the driver, we need to know the
// current OS version while we are running to make decisions regarding what
// logic to use when the logic cannot be the same for all platforms. We
// will look up the OS version in DriverEntry and store the values
// in these global variables.
//
ULONG gSfOsMajorVersion = 0;
ULONG gSfOsMinorVersion = 0;
//
// Here is what the major and minor versions should be for the various
// OS versions:
//
// OS Name MajorVersion MinorVersion
// ---------------------------------------------------------------------
// Windows 2000 5 0
// Windows XP 5 1
// Windows Server 2003 5 2
//
#define IS_WINDOWS2000() \
((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 0))
#define IS_WINDOWSXP() \
((gSfOsMajorVersion == 5) && (gSfOsMinorVersion == 1))
#define IS_WINDOWSXP_OR_LATER() \
(((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 1)) || \
(gSfOsMajorVersion > 5))
#define IS_WINDOWSSRV2003_OR_LATER() \
(((gSfOsMajorVersion == 5) && (gSfOsMinorVersion >= 2)) || \
(gSfOsMajorVersion > 5))
#endif
//
// Tags identifying memory SFilter allocates
//
#define SFLT_POOL_TAG_FASTIO 'ifFS'
#define SFLT_POOL_TAG_MOUNTVOL 'vmFS'
#define SFLT_POOL_TAG_LOADFS 'flFS'
#define SFLT_POOL_TAG_ENUMFSVOL 'neFS'
#define SFLT_POOL_TAG_DOSNAME 'ndFS'
#define SFLT_POOL_TAG_NAME_BUFFER 'bnFS'
#define SFLT_POOL_TAG_BIGNAMEBUFFER 'nbFS'
#define SFLT_POOL_TAG_DEVNAME 'nvFS'
//
// Macros for SFilter DbgPrint levels.
//
#define SF_LOG_PRINT( _dbgLevel, _string ) \
(FlagOn(SfDebug,(_dbgLevel)) ? \
DbgPrint _string : \
((void)0))
//
// Delay values for KeDelayExecutionThread()
// (Values are negative to represent relative time)
//
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
/////////////////////////////////////////////////////////////////////////////
//
// Global variables
//
/////////////////////////////////////////////////////////////////////////////
//
// Lookaside list for various name buffers.
//
PAGED_LOOKASIDE_LIST gSfNameBufferLookasideList;
//
// Since we always use this list to allocate NAME_CONTROLs, we will use that
// for the size of the lookaside list.
//
#define SFILTER_LOOKASIDE_SIZE sizeof( NAME_CONTROL )
//
// Holds pointer to the driver object for this driver
//
PDRIVER_OBJECT gSFilterDriverObject = NULL;
//
// Holds pointer to the device object that represents this driver and is used
// by external programs to access this driver. This is also known as the
// "control device object".
//
PDEVICE_OBJECT gSFilterControlDeviceObject = NULL;
//
// This lock is used to synchronize our attaching to a given device object.
// This lock fixes a race condition where we could accidently attach to the
// same device object more then once. This race condition only occurs if
// a volume is being mounted at the same time as this filter is being loaded.
// This problem will never occur if this filter is loaded at boot time before
// any file systems are loaded.
//
// This lock is used to atomically test if we are already attached to a given
// device object and if not, do the attach.
//
FAST_MUTEX gSfilterAttachLock;
UNICODE_STRING gInsufficientResourcesUnicode = CONSTANT_UNICODE_STRING(L"[-= Insufficient Resources =-]");
/////////////////////////////////////////////////////////////////////////////
//
// Debug Definitions
//
/////////////////////////////////////////////////////////////////////////////
//
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -