本文主要是介绍读源码笔记--文件过滤驱动FileSpy第1篇 -- DriverEntry,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今天只读FileSpy的DriverEntry,位于源文件:filespy.c。
//
// 全局变量.
//
ULONG gFileSpyDebugLevel = DEFAULT_FILESPY_DEBUG_LEVEL;
#if WINVER >= 0x0501
ULONG gFileSpyAttachMode = FILESPY_ATTACH_ALL_VOLUMES;
#else
ULONG gFileSpyAttachMode = FILESPY_ATTACH_ON_DEMAND;
#endif
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)
{
UNICODE_STRING nameString;
NTSTATUS status;
PFAST_IO_DISPATCH fastIoDispatch;
ULONG i;
UNICODE_STRING linkString;
#if WINVER >= 0x0501
//第一步,获取动态函数。
//目的只有一个,兼容Windows的之前的版本。原因是:有些Windows后面版本出现的函数,在出现之前的Windows操作系统中是没有。
//如果直接使用该函数,在该函数出现之前的Windows操作系统中,将直接导致驱动加载失败。
//这里面包括如下动态加载的函数:
// 1.FsRtlRegisterFileSystemFilterCallbacks:注册一些通知回调函数,当下层文件驱动执行某些操作的时候调用。2K SP4和XP以后可用。
// 2.IoAttachDeviceToDeviceStackSafe:绑定目标设备对象。2K SP4和XP以后可用。
// 3.IoEnumerateDeviceObjectList:枚举驱动的设备对象链。2K SP4和XP以后可用。
// 4.IoGetLowerDeviceObject:获取当前驱动的下一层的设备对象。2K SP4和XP以后可用。
// 5.IoGetDeviceAttachmentBaseRef:获取文件系统驱动或设备驱动栈底的设备对象。2K SP4和XP以后可用。
// 6.IoGetDiskDeviceObject:获取与给定文件系统卷设备相关的磁盘设备对象。2K SP4和XP以后可用。
// 7.IoGetAttachedDeviceReference:获取驱动栈顶的设备对象,并将该设备对象的引用计数增1。2K 和XP以后可用。
// 8.RtlGetVersion:获取操作系统版本。
SpyLoadDynamicFunctions();
// 获取操作系统版本,调用的是RtlGetVersion或PsGetVersion。
SpyGetCurrentVersion();
#endif
// 从注册表中获取FileSpy指定的参数。
// 根据RegistryPath在注册表中的路径,
// 1.查询“MaxRecords”
// 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gMaxRecordsToAllocate中
// 2.查询“MaxNames”
// 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gMaxNamesToAllocate中
// 3.查询“DebugFlags”
// 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gFileSpyDebugLevel中
// 4.查询“AttachMode”
// 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gFileSpyAttachMode中
SpyReadDriverParameters( RegistryPath );
// #ifndef FlagOn
// #define FlagOn(_F,_SF) ((_F) & (_SF))
// #endif
if (FlagOn(gFileSpyDebugLevel, SPYDEBUG_BREAK_ON_DRIVER_ENTRY)) {
DbgBreakPoint();
}
//
// 将DriverEntry的参数:DriverObject,保存到全局变量:gFileSpyDriverObject
//
gFileSpyDriverObject = DriverObject;
//
// 初始化一个Lookaside的内存池。
//
ExInitializePagedLookasideList( &gFileSpyNameBufferLookasideList,
NULL,
NULL,
0,
FILESPY_LOOKASIDE_SIZE,
FILESPY_NAME_BUFFER_TAG,
0 );
#if DBG && WINVER >= 0x0501
//
// 判断操作系统版本,设置卸载例程。
//
if (IS_WINDOWSXP_OR_LATER()) {
ASSERT( NULL != gSpyDynamicFunctions.EnumerateDeviceObjectList );
gFileSpyDriverObject->DriverUnload = DriverUnload;
}
#endif
//
// 初始化名称,并调用IoCreateDevice创建设备。
// 这里的#define FILESPY_FULLDEVICE_NAME1 L"\\FileSystem\\Filters\\FileSpy"
// 因为是CDO,所以不需要设备拓展。
//
RtlInitUnicodeString( &nameString, FILESPY_FULLDEVICE_NAME1 );
status = IoCreateDevice( DriverObject,
0, // has no device extension
&nameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gControlDeviceObject);
if (STATUS_OBJECT_PATH_NOT_FOUND == status) {
//
// 如果第一次创建失败,错误代码为:STATUS_OBJECT_PATH_NOT_FOUND,说明不存在这个路径。再次创建,路径为:
// #define FILESPY_FULLDEVICE_NAME2 L"\\FileSystem\\FileSpyCDO"
// 因为这是一个我们自己使用的CDO,所以不需要设备拓展。该设备,主要用来与我们自己的应用层通信使用 和
// 修改整个驱动的内部配置的。
//
RtlInitUnicodeString( &nameString, FILESPY_FULLDEVICE_NAME2 );
status = IoCreateDevice( DriverObject,
0, // has no device extension
&nameString,
FILE_DEVICE_DISK_FILE_SYSTEM,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&gControlDeviceObject);
if (!NT_SUCCESS( status )) {
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!DriverEntry: Error creating FileSpy control device \"%wZ\", error: %x\n",
&nameString,
status) );
return status;
}
} else if (!NT_SUCCESS( status )) {
//
// 调用失败,直接返回。
//
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!DriverEntry: Error creating FileSpy control device \"%wZ\", error: %x\n",
&nameString,
status) );
return status;
}
//
// 创建符号链接,如果失败,删除符号链接,再创建一次,如果再次失败,删除设备,返回。
//
RtlInitUnicodeString( &linkString, FILESPY_DOSDEVICE_NAME );
status = IoCreateSymbolicLink( &linkString, &nameString );
if (!NT_SUCCESS(status)) {
//
// Remove the existing symbol link and try and create it again.
// If this fails then quit.
//
IoDeleteSymbolicLink( &linkString );
status = IoCreateSymbolicLink( &linkString, &nameString );
if (!NT_SUCCESS(status)) {
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!DriverEntry: IoCreateSymbolicLink failed\n") );
IoDeleteDevice(gControlDeviceObject);
return status;
}
}
//
// 初始化派遣例程,这里只设置IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJ_FILE_SYSTEM_CONTROL。
// IRP_MJ_FILE_SYSTEM_CONTROL,是文件系统控制设备对象(CDO),在一个新的存储介质被系统发现并在文件系统中生成一个卷的
// 这个过程开始时,收到的一个IRP,这个时候的次功能号为IRP_MN_MOUNT。只要过滤驱动生成了一个设备,并且绑定了文件系统的控制
// 设备对象(CDO),过滤驱动就一定能得到这样一个IRP。
//
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
DriverObject->MajorFunction[i] = SpyDispatch;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = SpyCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SpyClose;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SpyFsControl;
//
// 设置FAST I/O的派遣例程。每个驱动对象都有FAST I/O派遣例程,只是多数设备驱动是不调用这写快速I/O分发函数的。但是文件系统必须
// 要设置,如果不设置上层依然会调用FAST I/O这些例程,而且会导致蓝屏。它是独立于普通IRP的另外的接口。
// 最简单的FAST I/O分发函数的写法是:直接返回FALSE就可以了。
//
// FLAST I/O 的例程空间需要自己开辟。该空间的释放,在DriverUnload里面。
//
fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,
sizeof( FAST_IO_DISPATCH ),
FILESPY_POOL_TAG );
if (!fastIoDispatch) {
IoDeleteDevice( gControlDeviceObject );
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );
fastIoDispatch->FastIoCheckIfPossible = SpyFastIoCheckIfPossible;
fastIoDispatch->FastIoRead = SpyFastIoRead;
fastIoDispatch->FastIoWrite = SpyFastIoWrite;
fastIoDispatch->FastIoQueryBasicInfo = SpyFastIoQueryBasicInfo;
fastIoDispatch->FastIoQueryStandardInfo = SpyFastIoQueryStandardInfo;
fastIoDispatch->FastIoLock = SpyFastIoLock;
fastIoDispatch->FastIoUnlockSingle = SpyFastIoUnlockSingle;
fastIoDispatch->FastIoUnlockAll = SpyFastIoUnlockAll;
fastIoDispatch->FastIoUnlockAllByKey = SpyFastIoUnlockAllByKey;
fastIoDispatch->FastIoDeviceControl = SpyFastIoDeviceControl;
fastIoDispatch->FastIoDetachDevice = SpyFastIoDetachDevice;
fastIoDispatch->FastIoQueryNetworkOpenInfo = SpyFastIoQueryNetworkOpenInfo;
fastIoDispatch->MdlRead = SpyFastIoMdlRead;
fastIoDispatch->MdlReadComplete = SpyFastIoMdlReadComplete;
fastIoDispatch->PrepareMdlWrite = SpyFastIoPrepareMdlWrite;
fastIoDispatch->MdlWriteComplete = SpyFastIoMdlWriteComplete;
fastIoDispatch->FastIoReadCompressed = SpyFastIoReadCompressed;
fastIoDispatch->FastIoWriteCompressed = SpyFastIoWriteCompressed;
fastIoDispatch->MdlReadCompleteCompressed = SpyFastIoMdlReadCompleteCompressed;
fastIoDispatch->MdlWriteCompleteCompressed = SpyFastIoMdlWriteCompleteCompressed;
fastIoDispatch->FastIoQueryOpen = SpyFastIoQueryOpen;
DriverObject->FastIoDispatch = fastIoDispatch;
//
// 设置通知回调。FsRtlRegisterFileSystemFilterCallbacks函数注册需通知回调函数,这些回调函数将在文件系统的相关操作之前被调用
//
#if WINVER >= 0x0501
{
FS_FILTER_CALLBACKS fsFilterCallbacks;
if (IS_WINDOWSXP_OR_LATER()) {
ASSERT( NULL != gSpyDynamicFunctions.RegisterFileSystemFilterCallbacks );
//
// This version of the OS exports
// FsRtlRegisterFileSystemFilterCallbacks, therefore it must
// support the FsFilter callbacks interface. We will register to
// receive callbacks for these operations.
//
//
// Setup the callbacks for the operations we receive through
// the FsFilter interface.
//
fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );
fsFilterCallbacks.PreAcquireForSectionSynchronization = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForSectionSynchronization = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForSectionSynchronization = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForSectionSynchronization = SpyPostFsFilterOperation;
fsFilterCallbacks.PreAcquireForCcFlush = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForCcFlush = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForCcFlush = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForCcFlush = SpyPostFsFilterOperation;
fsFilterCallbacks.PreAcquireForModifiedPageWriter = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForModifiedPageWriter = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForModifiedPageWriter = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForModifiedPageWriter = SpyPostFsFilterOperation;
status = (gSpyDynamicFunctions.RegisterFileSystemFilterCallbacks)( DriverObject,
&fsFilterCallbacks );
if (!NT_SUCCESS( status )) {
DriverObject->FastIoDispatch = NULL;
ExFreePoolWithTag( fastIoDispatch, FILESPY_POOL_TAG );
IoDeleteDevice( gControlDeviceObject );
return status;
}
}
}
#endif
//
// 初始化全局变量。链表,锁等
//
ExInitializeFastMutex( &gSpyDeviceExtensionListLock );
InitializeListHead( &gSpyDeviceExtensionList );
KeInitializeSpinLock( &gControlDeviceStateLock );
InitializeListHead( &gOutputBufferList );
KeInitializeSpinLock( &gOutputBufferLock );
KeInitializeSpinLock( &gLogSequenceLock );
ExInitializeFastMutex( &gSpyAttachLock );
#ifndef MEMORY_DBG
//
// When we aren't debugging our memory usage, we want to allocate
// memory from a look-aside list for better performance. Unfortunately,
// we cannot benefit from the memory debugging help of the Driver
// Verifier if we allocate memory from a look-aside list.
//
ExInitializeNPagedLookasideList( &gFreeBufferList,
NULL/*ExAllocatePoolWithTag*/,
NULL/*ExFreePool*/,
0,
RECORD_SIZE,
FILESPY_LOGRECORD_TAG,
100 );
#endif
//
// 初始化名称环境。SpyInitNamingEnvironment位于:fspyHash.c中。初始化:gHashTable和gHashLockTable这2个全局变量。
// 初始化内部字符串,存于全局变量:gVolumeString、gOverrunString、gPagingIoString
//
SpyInitNamingEnvironment();
RtlInitUnicodeString(&gVolumeString, L"VOLUME");
RtlInitUnicodeString(&gOverrunString, L"......");
RtlInitUnicodeString(&gPagingIoString, L"Paging IO");
//
// IoRegisterFsRegistrationChange 注册文件系统变动回调。当系统中有任何文件系统被激活或被注销时,注册过的回调函数就会被调用。
//
// 注:这里的文件系统激活和卷的挂载是2回事。文件系统,比如NTFS、FAT32等,如果系统中一个NTFS的磁盘卷都没有采用这种文件
// 系统,那么这时的操作系统时没有加载NTFS文件系统的驱动,换言之,NTFS处于未激活状态。当任何一个卷采用了NTFS这种文件
// 系统,则NTFS被加载了,此时就叫NTFS被激活,以后再有卷采用NTFS文件系统挂载时,都不能说是文件系统的激活。
//
// 2K SP4和XP及以后的OS,会枚举所有已经存在的文件系统(除了RAM文件系统)。而2K SP4以前的,不会枚举已经在过滤驱动加载之前
// 就已经挂载上了的文件系统。
//
if (gFileSpyAttachMode == FILESPY_ATTACH_ALL_VOLUMES) {
status = IoRegisterFsRegistrationChange( DriverObject, SpyFsNotification );
if (!NT_SUCCESS( status )) {
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!DriverEntry: Error registering FS change notification, status=%08x\n",
status) );
DriverObject->FastIoDispatch = NULL;
ExFreePoolWithTag( fastIoDispatch, FILESPY_POOL_TAG );
IoDeleteDevice( gControlDeviceObject );
return status;
}
}
#if WINVER >= 0x0600
//
// 根据filespy创建资源管理器。SpyCreateKtmResourceManager位于:fspyTx.c中
//
status = SpyCreateKtmResourceManager();
if (!NT_SUCCESS( status )) {
SPY_LOG_PRINT( SPYDEBUG_ERROR,
("FileSpy!DriverEntry: Error creating Ktm resource manager, status=%08x\n",
status) );
return status;
}
//
// 下面就比较简单了,就不提了。
//
//
// Initialize the lookaside list for the transaction context data.
// We will create a transaction context for each enlistment we create.
// The context data will be freed when the KTM callback routine
// receives appropriate notifications.
//
ExInitializeNPagedLookasideList( &gTransactionList,
NULL,
NULL,
0,
sizeof( FILESPY_TRANSACTION_CONTEXT ),
FILESPY_TRANSACTION_TAG,
0 );
#endif
//
// Clear the initializing flag on the control device object since we
// have now successfully initialized everything.
//
ClearFlag( gControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );
return STATUS_SUCCESS;
}
这篇关于读源码笔记--文件过滤驱动FileSpy第1篇 -- DriverEntry的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!