文件驱动,绑定指定卷

 
我们平时看sfilter的时候,发现它一方面面面俱到,一方面弄乱了我们的脑子。特别是绑定卷的那一部分,到底是怎么实现的,总觉得七拐八拐,拐弯太多。能不能写一个比较简单的绑定函数?比如我指定只要过滤c盘,那么我只要绑定c盘就够了。我试着写了一个,本文介绍我的这部分代码。我定义了一个函数:
BOOLEAN Attach2C_Volume(PUNICODE_STRING nameString)
nameString指定了要绑定的卷名。如果要绑定c盘,则 nameString应是: //DosDevices//C://
        InitializeObjectAttributes( &objectAttributes, &nameString, 
                OBJ_CASE_INSENSITIVE, NULL, NULL );
        ntStatus = ZwCreateFile( &ntFileHandle, SYNCHRONIZE|FILE_ANY_ACCESS, 
                &objectAttributes, &ioStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE, 
                FILE_OPEN, 
                FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE, 
                NULL, 0 );
 
        if( !NT_SUCCESS( ntStatus ) ) 
        {
                //DbgPrint(("Filemon: Could not open drive %c: /n", 'C'+0));
                return FALSE;
        }

        // Got the file handle, so now look-up the file-object it refers to
        //
        ntStatus = ObReferenceObjectByHandle( ntFileHandle, FILE_READ_DATA, 
                NULL, KernelMode, &fileObject, NULL );
        if( !NT_SUCCESS( ntStatus )) {
 
                //DbgPrint(("Filemon: Could not get fileobject from handle: %c/n", 'C'));
                ZwClose( ntFileHandle );
                return FALSE;
        }
 
        // 
        // Next, find out what device is associated with the file object by getting its related
        // device object
        //
        fileSysDevice = IoGetRelatedDeviceObject( fileObject );
 
        if( ! fileSysDevice ) {
 
                //DbgPrint(("Filemon: Could not get related device object: %c/n", 'A'+Drive ));
                ObDereferenceObject( fileObject );
                ZwClose( ntFileHandle );
                return FALSE;
        }
      上面代码的作用是打开卷设备,保存在fileSysDevice中。我们来一步步地看它是怎么做的。我们知道,在应用层里面,CreateFile函数的作用不仅可以打开一个File,还可以打开管道,邮件槽,磁盘。这里的ZwCreateFile就是CreateFile在内核的实现,现在调用它打开磁盘并取得句柄ntFileHandle,通过这个句柄可以找到它所对应的文件对象。形象地来说明句柄和文件对象的关系吧,文件对象就象一只古董瓷瓶,珍贵易碎,而句柄则是一只细心包裹着这只瓷瓶的皮箱,保护着它。我们在介绍古董瓷瓶的时候,只是让别人知道,它正放在箱子里面,有图片在此请看云云。
好,找到文件对象的方法是ObReferenceObjectByHandle,调用它就可以了。继续调用IoGetRelatedDeviceObject,这个函数可以让你进一步通过文件对象获得设备对象,也就是C盘的设备对象,正是我们绑定的时候要用到的。对上面的这一个过程,请你记住就行了,不必特别的研究,他们之间的关系都是一顺的,好像通过爷爷找孙子一样,有既定的脉络关系。接下来:
    ntStatus = IoCreateDevice( gSFilterDriverObject,
                sizeof(SFILTER_DEVICE_EXTENSION),
                NULL,
                fileSysDevice->DeviceType,
                0,
                FALSE,
                &VolumeDeviceObject );
        if( !NT_SUCCESS(ntStatus) ) {
 
                //DbgPrint(("Filemon: failed to create associated device: %c/n", 'A'+0 ));   
 
                ObDereferenceObject( fileObject );
                ZwClose( ntFileHandle );
 
                return FALSE;
        } 
        
        // Clear the device's init flag as per NT DDK KB article on creating device 
        // objects from a dispatch routine
        //
        VolumeDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
         这段代码用来创建一个新的设备对象,过会我就用它来绑定到刚才取得的c盘设备对象上去。之后要设置一下新设备对象的标志位,使它的初始化位为空。
现在,我们已把一切准备工作都完成啦。是不是很快?!最后的一步就是完成绑定,代码如下:
attachedObject = IoAttachDeviceToDeviceStack( VolumeDeviceObject, fileSysDevice );
        if( NULL == attachedObject ) 
        {
                //DbgPrint(("Filemon: Connect with Filesystem failed: %c (%x) =>%x/n", 
                //      'C', fileSysDevice, (LONG)ntStatus ));
 
                // Derefence the object and get out
                ObDereferenceObject( fileObject );
                ZwClose( ntFileHandle );
 
                return FALSE;
        } 
 
        //
        // Setup the device extensions. The drive letter and file system object are stored
        // in the extension.
        //
        sfExtention = VolumeDeviceObject->DeviceExtension;
        sfExtention->AttachedToDeviceObject = attachedObject;//fileSysDevice;
        
最后还有一定后继的东西:
// Close the file and update the hooked drive list by entering a 
    // pointer to the hook device object in it. 
    ObDereferenceObject( fileObject ); 
    ZwClose( ntFileHandle );
    return TRUE;

          结束了!代码真的很简洁。把 Attach2C_Volume 放在 DriverEntry 最后的结束的地方进行调用,如果你的程序没有别的问题的话,就能轻松的实现指定盘符的绑定了。
 

你可能感兴趣的:(c,object,File,null,extension,磁盘)