过滤驱动容易让新手纠结的几个函数
来源:互联网 发布:1990年人口普查数据 编辑:程序博客网 时间:2024/05/16 13:07
1. IoAttachDevice
- NTSTATUS
- IoAttachDevice(
- IN PDEVICE_OBJECT SourceDevice,
- IN PUNICODE_STRING TargetDevice,
- OUT PDEVICE_OBJECT *AttachedDevice
- );
将【指定指针】的设备对象附加到【指定名称】的设备对象所在的【设备对象栈】顶层,并返回【附加之前的栈顶设备对象指针】。
2. IoAttachDeviceToDeviceStack
- PDEVICE_OBJECT
- IoAttachDeviceToDeviceStack(
- IN PDEVICE_OBJECT SourceDevice,
- IN PDEVICE_OBJECT TargetDevice
- );
将【指定指针】的设备对象附加到【指定指针】的设备对象所在的【设备对象栈】顶层,并返回【附加之前的栈顶设备对象指针】。
3. IoGetDeviceObjectPointer
- NTSTATUS
- IoGetDeviceObjectPointer(
- IN PUNICODE_STRING ObjectName,
- IN ACCESS_MASK DesiredAccess,
- OUT PFILE_OBJECT *FileObject,
- OUT PDEVICE_OBJECT *DeviceObject
- );
通过【设备对象的名字】,打开【文件对象】,根据返回的【文件句柄】获取【文件对象指针】,并根据【文件对象指针】得到该【文件对象的设备指针】。
它的源代码:
- NTSTATUS
- IoGetDeviceObjectPointer(
- IN PUNICODE_STRING ObjectName,
- IN ACCESS_MASK DesiredAccess,
- OUT PFILE_OBJECT *FileObject,
- OUT PDEVICE_OBJECT *DeviceObject
- )
- {
- PFILE_OBJECT fileObject;
- OBJECT_ATTRIBUTES objectAttributes;
- HANDLE fileHandle;
- IO_STATUS_BLOCK ioStatus;
- NTSTATUS status;
- PAGED_CODE();
- //
- // Initialize the object attributes to open the device.
- //
- InitializeObjectAttributes( &objectAttributes,
- ObjectName,
- OBJ_KERNEL_HANDLE,
- (HANDLE) NULL,
- (PSECURITY_DESCRIPTOR) NULL );
- status = ZwOpenFile( &fileHandle,
- DesiredAccess,
- &objectAttributes,
- &ioStatus,
- 0,
- FILE_NON_DIRECTORY_FILE );
- if (NT_SUCCESS( status )) {
- //
- // The open operation was successful. Dereference the file handle
- // and obtain a pointer to the device object for the handle.
- //
- status = ObReferenceObjectByHandle( fileHandle,
- 0,
- IoFileObjectType,
- KernelMode,
- (PVOID *) &fileObject,
- NULL );
- if (NT_SUCCESS( status )) {
- *FileObject = fileObject;
- //
- // Get a pointer to the device object for this file.
- //
- *DeviceObject = IoGetRelatedDeviceObject( fileObject );
- }
- (VOID) ZwClose( fileHandle );
- }
- return status;
- }
注意:
(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
- PDEVICE_OBJECT
- IoGetRelatedDeviceObject(
- IN PFILE_OBJECT FileObject
- );
通过文件对象指针,使用它的Vpb域,获取对应的设备对象所在设备栈顶层的设备对象指针(文件和设备的关联关系)
它的实现如下:
- PDEVICE_OBJECT
- IoGetRelatedDeviceObject(
- IN PFILE_OBJECT FileObject
- )
- {
- PDEVICE_OBJECT deviceObject;
- //
- // If the file object was taken out against the mounted file system, it
- // will have a Vpb. Traverse it to get to the DeviceObject. Note that in
- // this case we should never follow FileObject->DeviceObject, as that
- // mapping may be invalid after a forced dismount.
- //
- if (FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL) {
- ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN));
- deviceObject = FileObject->Vpb->DeviceObject;
- //
- // If a driver opened a disk device using direct device open and
- // later on it uses IoGetRelatedTargetDeviceObject to find the
- // device object it wants to send an IRP then it should not get the
- // filesystem device object. This is so that if the device object is in the
- // process of being mounted then vpb is not stable.
- //
- } else if (!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) &&
- FileObject->DeviceObject->Vpb != NULL &&
- FileObject->DeviceObject->Vpb->DeviceObject != NULL) {
- deviceObject = FileObject->DeviceObject->Vpb->DeviceObject;
- //
- // This is a direct open against the device stack (and there is no mounted
- // file system to strain the IRPs through).
- //
- } else {
- deviceObject = FileObject->DeviceObject;
- }
- ASSERT( deviceObject != NULL );
- //
- // Check to see whether or not the device has any associated devices.
- // If so, return the highest level device; otherwise, return a pointer
- // to the device object itself.
- //
- if (deviceObject->AttachedDevice != NULL) {
- if (FileObject->Flags & FO_FILE_OBJECT_HAS_EXTENSION) {
- PIOP_FILE_OBJECT_EXTENSION fileObjectExtension =
- (PIOP_FILE_OBJECT_EXTENSION)(FileObject + 1);
- ASSERT(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN));
- if (fileObjectExtension->TopDeviceObjectHint != NULL &&
- IopVerifyDeviceObjectOnStack(deviceObject, fileObjectExtension->TopDeviceObjectHint)) {
- return fileObjectExtension->TopDeviceObjectHint;
- }
- }
- deviceObject = IoGetAttachedDevice( deviceObject );
- }
- return deviceObject;
- }
5. IoGetBaseFileSystemDeviceObject 得到与文件对象相关的卷设备对象(是由文件系统在打开卷时创建的).
- PDEVICE_OBJECT IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject)
- {
- PDEVICE_OBJECT deviceObject;
- // If the file object has a mounted Vpb, use its DeviceObject.
- if(FileObject->Vpb != NULL && FileObject->Vpb->DeviceObject != NULL)
- {
- deviceObject = FileObject->Vpb->DeviceObject;
- // Otherwise, if the real device has a VPB that indicates that it is mounted,
- // then use the file system device object associated with the VPB.
- }
- else if(!(FileObject->Flags & FO_DIRECT_DEVICE_OPEN) &&
- FileObject->DeviceObject->Vpb != NULL &&
- FileObject->DeviceObject->Vpb->DeviceObject != NULL )
- {
- deviceObject = FileObject->DeviceObject->Vpb->DeviceObject;
- // Otherwise, just return the real device object.
- }
- else
- {
- deviceObject = FileObject->DeviceObject;
- }
- ASSERT(deviceObject != NULL);
- // Simply return the resultant file object.
- return deviceObject;
- }
6. ObReferenceObjectByName
(1)ObReferenceObjectByName 可以返回任意对象地址。它的本质是使用ObpLookupObjectName对 “\A\B\C”逐级解析。
(2)IoGetDeviceObjectPointer 只能返回设备对象地址。它的本质是调用ZwOpenFile得到设备句柄,然后调用ObReferenceObjectByHandle得到设备对应的文件对象指针,再调用IoGetRelatedDeviceObject根据文件对象指针得到设备对象指针。
7. 关闭X64的驱动签名
bcdedit/set testsigning on
0 0
- 过滤驱动容易让新手纠结的几个函数
- 过滤驱动容易让新手纠结的几个函数
- 过滤驱动容易让新手纠结的几个函数
- c++新手容易犯的几个错误
- 记几个容易忘的oracle 函数
- 容易混乱的几个编码函数
- 记几个容易忘的oracle 函数
- OpenMP: 几个容易混淆的函数
- OpenMP中几个容易混淆的函数
- GCD容易让人迷惑的几个小问题
- GCD 容易让人迷惑的几个小问题
- 分享几个实用的过滤函数
- 让人纠结的俗话
- 让人纠结的抉择
- free函数的纠结
- PHP中几个容易混淆的函数的区别
- 新手容易犯的错误
- 新手容易犯的错!!!
- 在Julia语言中调用Python
- java中线程池
- duilib List控件,横向滚动时列表项不移动或者移动错位的bug的修复
- Ubuntu下SVN命令行递归添加目录文件(免去一个一个的添加 --force)
- 什么是oracle ECP
- 过滤驱动容易让新手纠结的几个函数
- 线程和进程的区别
- LISTBOX消息
- 日期加天数、字符串类型转date、获取本周第一天、本周最后一天、本月第一天、本月最后一天、上月第一天、上月最后一天时间
- Android模拟器与控制台交互命令
- sed 使用
- open与fopen的区别
- eclips异常奔溃无法启动
- 提高Android App性能的技巧(转载)