过滤驱动容易让新手纠结的几个函数

来源:互联网 发布:1990年人口普查数据 编辑:程序博客网 时间:2024/05/16 13:07

1. IoAttachDevice

[cpp] view plaincopy
  1. NTSTATUS   
  2. IoAttachDevice(  
  3.      IN PDEVICE_OBJECT SourceDevice,  
  4.      IN PUNICODE_STRING TargetDevice,  
  5.      OUT PDEVICE_OBJECT *AttachedDevice  
  6. );  

将【指定指针】的设备对象附加到【指定名称】的设备对象所在的【设备对象栈】顶层,并返回【附加之前的栈顶设备对象指针】。


2. IoAttachDeviceToDeviceStack
   
[cpp] view plaincopy
  1. PDEVICE_OBJECT   
  2. IoAttachDeviceToDeviceStack(  
  3.      IN PDEVICE_OBJECT SourceDevice,  
  4.      IN PDEVICE_OBJECT TargetDevice  
  5. );  

将【指定指针】的设备对象附加到【指定指针】的设备对象所在的【设备对象栈】顶层,并返回【附加之前的栈顶设备对象指针】。

3. IoGetDeviceObjectPointer
   
[cpp] view plaincopy
  1. NTSTATUS   
  2. IoGetDeviceObjectPointer(  
  3.       IN PUNICODE_STRING ObjectName,  
  4.       IN ACCESS_MASK DesiredAccess,  
  5.       OUT PFILE_OBJECT *FileObject,  
  6.       OUT PDEVICE_OBJECT *DeviceObject  
  7. );  

通过【设备对象的名字】,打开【文件对象】,根据返回的【文件句柄】获取【文件对象指针】,并根据【文件对象指针】得到该【文件对象的设备指针】。

它的源代码:


[cpp] view plaincopy
  1. NTSTATUS  
  2. IoGetDeviceObjectPointer(  
  3.                          IN PUNICODE_STRING ObjectName,  
  4.                          IN ACCESS_MASK DesiredAccess,  
  5.                          OUT PFILE_OBJECT *FileObject,  
  6.                          OUT PDEVICE_OBJECT *DeviceObject  
  7.                          )  
  8. {  
  9.     PFILE_OBJECT fileObject;  
  10.     OBJECT_ATTRIBUTES objectAttributes;  
  11.     HANDLE fileHandle;  
  12.     IO_STATUS_BLOCK ioStatus;  
  13.     NTSTATUS status;  
  14.   
  15.     PAGED_CODE();  
  16.   
  17.     //  
  18.     // Initialize the object attributes to open the device.  
  19.     //  
  20.   
  21.     InitializeObjectAttributes( &objectAttributes,  
  22.         ObjectName,  
  23.         OBJ_KERNEL_HANDLE,  
  24.         (HANDLE) NULL,  
  25.         (PSECURITY_DESCRIPTOR) NULL );  
  26.   
  27.     status = ZwOpenFile( &fileHandle,  
  28.         DesiredAccess,  
  29.         &objectAttributes,  
  30.         &ioStatus,  
  31.         0,  
  32.         FILE_NON_DIRECTORY_FILE );  
  33.   
  34.     if (NT_SUCCESS( status )) {  
  35.   
  36.         //  
  37.         // The open operation was successful. Dereference the file handle  
  38.         // and obtain a pointer to the device object for the handle.  
  39.         //  
  40.   
  41.         status = ObReferenceObjectByHandle( fileHandle,  
  42.             0,  
  43.             IoFileObjectType,  
  44.             KernelMode,  
  45.             (PVOID *) &fileObject,  
  46.             NULL );  
  47.         if (NT_SUCCESS( status )) {  
  48.   
  49.             *FileObject = fileObject;  
  50.   
  51.             //  
  52.             // Get a pointer to the device object for this file.  
  53.             //  
  54.             *DeviceObject = IoGetRelatedDeviceObject( fileObject );  
  55.         }  
  56.         (VOID) ZwClose( fileHandle );  
  57.     }  
  58.     return status;  
  59. }  

注意:
    (1) IoGetDeviceObjectPointer函数中 ObReferenceObjectByHandle增加了其所对应的文件对象的引用,因此该函数调用后,调用ObDereferenceObject减小引用计数。  
    (2) IoGetDeviceObjectPointer函数中 IoGetRelatedDeviceObject的调用是里面的重点。 看IoGetRelatedDeviceObject的说明,就能理解这个函数参数3,参数4的关系。

特别注意: 
     WDK文档里面特别强调了以下信息 
            The IoGetDeviceObjectPointer routine returns a pointer to the top object in the named device object's stack and a pointer to the corresponding file object
       这里,就是大家经常有疑惑的参数3和4(DeviceObject和FileObject->DeviceObject)问题的答案了

      (1) DeviceObject 返回的是【Attach】在这个【有名设备对象】所在【栈】的【栈顶设备对象指针】,如果没有Attach的设备,就是【有名设备对象指针】了。
      (2) FileObject->DeviceObject 返回的是【有名设备对象指针】:
             如果是文件系统,还需要考虑到Vpb的问题,具体信息可以参考下面IoGetRelatedDeviceObject的实现。
(a) 在DEVICE_OBJECT和FILE_OBJECT结构中都存在Vpb字段,它是文件对象与相应磁盘卷设备直接的桥梁,一般Vpb中的RealDevice就指向了该对象的相应磁盘卷(块)设备,而vpb中的DeviceObject指向的是文件系统卷设备。比如将C盘下一个文件的FileObject传递给IoGetBaseFileSystemDeviceObject,那么若c盘是ntfs分区的,得到的文件系统卷设备DEVICE_OBJECT所属的驱动对象DRIVER_OBJECT就是\FileSystem\Ntfs;如果把该FileOjbect传递给IoGetRelatedDeviceObject,那么得到的deviceobject是附加在这个文件系统卷设备所在设备栈的顶层设备。

(b) 如果文件系统没有挂接,返回的是【磁盘系统卷设备】,否则返回的是【文件系统卷设备】.
(c) 如果文件系统已经挂接,返回的是【文件系统卷设备】

4. IoGetRelatedDeviceObject
  
[cpp] view plaincopy
  1. PDEVICE_OBJECT   
  2. IoGetRelatedDeviceObject(  
  3.      IN PFILE_OBJECT FileObject  
  4. );  

通过文件对象指针,使用它的Vpb域,获取对应的设备对象所在设备栈顶层的设备对象指针(文件和设备的关联关系)

 它的实现如下:


[cpp] view plaincopy
  1. PDEVICE_OBJECT  
  2. IoGetRelatedDeviceObject(  
  3.              IN PFILE_OBJECT FileObject  
  4.                          )  
  5. {  
  6.     PDEVICE_OBJECT deviceObject;  
  7.   
  8.     //  
  9.     // If the file object was taken out against the mounted file system, it  
  10.     // will have a Vpb. Traverse it to get to the DeviceObject. Note that in  
  11.     // this case we should never follow FileObject->DeviceObject, as that  
  12.     // mapping may be invalid after a forced dismount.  
  13.     //  
  14.   
  15.     if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) {  
  16.   
  17.         ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN));  
  18.         deviceObject = FileObject->Vpb->DeviceObject;  
  19.   
  20.   
  21.         //  
  22.         // If a driver opened a disk device using direct device open and  
  23.         // later on it uses IoGetRelatedTargetDeviceObject to find the  
  24.         // device object it wants to send an IRP then it should not get the  
  25.         // filesystem device object. This is so that if the device object is in the  
  26.         // process of being mounted then vpb is not stable.  
  27.         //  
  28.   
  29.     } else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) &&  
  30.         FileObject->DeviceObject->Vpb != NULL &&  
  31.         FileObject->DeviceObject->Vpb->DeviceObject != NULL) {  
  32.   
  33.             deviceObject = FileObject->DeviceObject->Vpb->DeviceObject;  
  34.   
  35.             //  
  36.             // This is a direct open against the device stack (and there is no mounted  
  37.             // file system to strain the IRPs through).  
  38.             //  
  39.   
  40.     } else {  
  41.   
  42.         deviceObject = FileObject->DeviceObject;  
  43.     }  
  44.   
  45.     ASSERT( deviceObject != NULL );  
  46.   
  47.     //  
  48.     // Check to see whether or not the device has any associated devices.  
  49.     // If so, return the highest level device; otherwise, return a pointer  
  50.     // to the device object itself.  
  51.     //  
  52.   
  53.     if (deviceObject->AttachedDevice != NULL) {  
  54.         if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) {  
  55.   
  56.             PIOP_FILE_OBJECT_EXTENSION fileObjectExtension =  
  57.                 (PIOP_FILE_OBJECT_EXTENSION)(FileObject + 1);  
  58.   
  59.             ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN));  
  60.   
  61.             if (fileObjectExtension->TopDeviceObjectHint != NULL &&  
  62.                 IopVerifyDeviceObjectOnStack(deviceObject, fileObjectExtension->TopDeviceObjectHint)) {  
  63.                     return fileObjectExtension->TopDeviceObjectHint;  
  64.             }  
  65.         }  
  66.         deviceObject = IoGetAttachedDevice( deviceObject );  
  67.     }  
  68.   
  69.     return deviceObject;  
  70. }  

5. IoGetBaseFileSystemDeviceObject 得到与文件对象相关的卷设备对象(是由文件系统在打开卷时创建的).
    
[cpp] view plaincopy
  1. PDEVICE_OBJECT IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject)  
  2. {  
  3.     PDEVICE_OBJECT deviceObject;  
  4.     // If the file object has a mounted Vpb, use its DeviceObject.  
  5.     if(FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL)  
  6.     {  
  7.         deviceObject = FileObject->Vpb->DeviceObject;  
  8.         // Otherwise, if the real device has a VPB that indicates that it is mounted,  
  9.         // then use the file system device object associated with the VPB.  
  10.     }  
  11.     else if(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) &&  
  12.         FileObject->DeviceObject->Vpb != NULL &&  
  13.         FileObject->DeviceObject->Vpb->DeviceObject != NULL )  
  14.     {  
  15.         deviceObject = FileObject->DeviceObject->Vpb->DeviceObject;  
  16.         // Otherwise, just return the real device object.  
  17.     }  
  18.     else  
  19.     {  
  20.         deviceObject = FileObject->DeviceObject;  
  21.     }  
  22.     ASSERT(deviceObject != NULL);  
  23.     // Simply return the resultant file object.  
  24.     return deviceObject;  
  25. }  

6. ObReferenceObjectByName
(1)ObReferenceObjectByName 可以返回任意对象地址。它的本质是使用ObpLookupObjectName对 “\A\B\C”逐级解析。
(2)IoGetDeviceObjectPointer 只能返回设备对象地址。它的本质是调用ZwOpenFile得到设备句柄,然后调用ObReferenceObjectByHandle得到设备对应的文件对象指针,再调用IoGetRelatedDeviceObject根据文件对象指针得到设备对象指针。


7. 关闭X64的驱动签名
bcdedit/set testsigning on
0 0
原创粉丝点击