读源码笔记--文件过滤驱动FileSpy第4篇 -- 关于IRP_MJ_FILE_SYSTEM_CONTROL

前面3篇,已经读完了绑定一个文件系统被挂载时,绑定的操作。这里得说一下总体的框架视角下,需要绑定的东西。

 

1:变动回调里实现绑定,这个绑定是文件系统被挂载或取消时,需要实现的。

2:变动回调已经掉过了,就是说文件过滤驱动已经加载,并运行。新来某个文件系统的储存设备,也需要绑定。

 

这里变动回调里面已经绑定了已经存在的卷设备,那么新加上来的存储设备,如何绑定?看下面:

在实际过程中,文件过滤驱动是在已经运行的OS上运行,那个时候已经有某个文件系统已经挂载了,如果这个时候新插一个同

文件系统的U盘,或其他的储存设备,这个时候的文件系统变动回调是不会被调用的。那么新上来的储存设备什么时候绑定呢?

 

这里就不得不说,为什么在DriverEntry里面要绑定文件系统的控制设备CDO了。目的只有一个,获取发送给文件系统控制设备的

文件系统控制请求。既是要获取的就是IRP_MJ_FILE_SYSTEM_CONTROL。从这些控制的IRP中能够得到足够的信息,确定一个

卷被挂载,这样才有可能去绑定文件系统的卷设备。

 

在第1篇的DriverEntry里面,设置IRP_MJ_FILE_SYSTEM_CONTROL时,已经提过。这个IRP会在一个新的存储设备被系统发现,并

在文件系统中生成一个与之对应的卷设备,这个过程的开始的时候,我们的文件过滤驱动就会收到这么一个IRP,同时,次功能号为:

IRP_MN_MOUNT。因为这个时候,我们的过滤驱动已经加载了,如果没加载之前就来了一个新的存储设备,那么我们的驱动加载时

走的路,就是变动回调里面绑定的过程。所以要说的,这个IRP_MJ_FILE_SYSTEM_CONTROL,是文件过滤驱动加载之后才会有的。

这句话是废话,可以忽略。

 

下面这个函数,在卷设备挂载或卸载的时候,都会被调用。在挂载的时候,绑定卷设备。

 

NTSTATUS
SpyFsControl (
    __in PDEVICE_OBJECT DeviceObject,
    __in PIRP Irp
    )

{
    PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation( Irp );

    PAGED_CODE();

    //
    //  判断是否是我们自己的文件过滤驱动设备,该设备就是DriverEntry里面的IoCreateDevice创建的设备。

    //  保存在全局变量:gControlDeviceObject 中的。

    //

    if (gControlDeviceObject == DeviceObject) {

   

    //
    //  判断是否设置了SPYDEBUG_TRACE_IRP_OPS标志位。如果设置了,调用函数:
SpyDumpIrpOperation

    //  该函数位于fpyLib.c中,相当简单。函数内部,1:获取IO_STACK_LOCATION,然后调用函数:GetIrpName

    //  来获取IRPMajor功能号名和Minor功能号名,这个函数位于:irpNames.c中;

    //  2:根据参数1,选择打印是pre操作还是post操作。

    //  这个函数的作用就是打印log,无关紧要,可以不看。

    //

        if (FlagOn( gFileSpyDebugLevel, SPYDEBUG_TRACE_IRP_OPS )) {

            SpyDumpIrpOperation( TRUE, Irp );
        }

        //

        //  如果这个设备,是我们的文件控制设备,而不是一个挂载上来的卷设备,则是个无效请求,直接返回。

        //

        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Information = 0;

        IoCompleteRequest( Irp, IO_NO_INCREMENT );

        return STATUS_INVALID_DEVICE_REQUEST;
    }

    ASSERT(IS_FILESPY_DEVICE_OBJECT( DeviceObject ));

    //
    //  次功能号的处理。下面的次功能号的详细信息,参考:文件过滤驱动中若干知识》中的第10点。

    //

    switch (pIrpSp->MinorFunction) {

        case IRP_MN_MOUNT_VOLUME:

            return SpyFsControlMountVolume ( DeviceObject, Irp );

        case IRP_MN_LOAD_FILE_SYSTEM:

            return SpyFsControlLoadFileSystem ( DeviceObject, Irp );

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

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

                    SPY_LOG_PRINT( SPYDEBUG_DISPLAY_ATTACHMENT_NAMES,
                                   ("FILESPY!SpyFsControl:                        Dismounting volume         %p \"%wZ\"\n",
                                    devExt->NLExtHeader.AttachedToDeviceObject,
                                    &devExt->NLExtHeader.DeviceName) );
                    break;
                }
            }
            break;
        }
    }

    //
    //  直接传递给默认派遣函数,后面说这个函数。

    //

    return SpyPassThrough( DeviceObject, Irp );
}

你可能感兴趣的:(c++)