读源码笔记--文件过滤驱动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;

 

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值