忆杰的博客

忆杰的博客

遍历设备栈

这一篇基本上就没有什么新东西了, 就是上几篇的应用. 遍历一个驱动的所有设备对象, 还有绑定在设备上面的所有的驱动对象, 设备对象.

其实就是对驱动对象和设备对象的结构挑选了几个字段过来显示下, 基本上如果了解了驱动对象的一些机构和设备对象的一些结构, 那么就没有什么问题了, 当然了解了两个对象以后还有点小问题, 首先一个问题就是获取驱动对象的地址, 上一篇我们已经谈到如何获取某个名称所对应的对象地址, 这里就派上用场了.

就是这号函数ObReferenceObjectByName. 这号函数可以通过名称获取某个对象的地址. OK有了对象的地址其他的就很简单了, 在驱动对象中有其设备对象的链表, 而在每个设备对象中都有上层绑定设备的地址, 如果有那么不停的遍历就可以遍历完所有的设备对象和绑定对象了..

没有什么新意. 这边是代码:

        http://www.joenchen.com/JoenTools/EnumDeviceStack.rar

/*	遍历驱动设备, 查询设备名称和绑定的设备
	编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>
#include "EnumDeviceStack.h"

//===========================================================================
//获取某个设备对象信息
//===========================================================================
VOID GetDeviceObjectInfo( PDEVICE_OBJECT pDeviceObj ) {
	POBJECT_HEADER ObjHeader = NULL;
	POBJECT_HEADER_NAME_INFO ObjName = NULL;

	//得到对象头
	ObjHeader = OBJECT_TO_OBJECT_HEADER( pDeviceObj );
	ASSERT( pDeviceObj != NULL );

	if ( ObjHeader  ) {

		//查询设备名称
		ObjName = OBJECT_HEADER_TO_NAME_INFO( ObjHeader );

		if ( ObjName && ObjName->Name.Buffer ) {

			KdPrint( ( "驱动名称:%wZ 设备名称:%wZ 驱动地址:%p 设备地址:%p\n",
				   &pDeviceObj->DriverObject->DriverName,
				   &ObjName->Name, pDeviceObj->DriverObject, pDeviceObj
				 ) );
		}
//---------------------------------------------------------------------------
		//对于没有名称的设备打印NULL
//---------------------------------------------------------------------------
	} else if( pDeviceObj->DriverObject ) {

		KdPrint( ( "驱动名称:%wZ 设备名称:%wZ 驱动地址:%p 设备地址:%p\n",
			   &pDeviceObj->DriverObject->DriverName,
			   NULL,  pDeviceObj->DriverObject,  pDeviceObj ) );
	}
	return;
}

//===========================================================================
//获取绑定在设备栈上的设备信息
//===========================================================================
VOID GetAttachedDeviceObjectInfo( PDEVICE_OBJECT pDeviceObj ) {
	PDEVICE_OBJECT pAttrDeviceObj = NULL;

	ASSERT( pDeviceObj != NULL );

	//获取绑定设备的地址
	pAttrDeviceObj = pDeviceObj->AttachedDevice;

	while ( pAttrDeviceObj ) {
		KdPrint( ( "\t绑定驱动名称:%wZ  绑定驱动地址:%p 绑定设备地址:%p\n",
			   &pAttrDeviceObj->DriverObject->DriverName,
			   pAttrDeviceObj->DriverObject, pAttrDeviceObj ) );

		//往上遍历
		pAttrDeviceObj = pAttrDeviceObj->AttachedDevice;
	}
}
//===========================================================================
//枚举设备栈
//===========================================================================
NTSTATUS EnumDeviceStack( PUNICODE_STRING pUSzDriverName ) {
	NTSTATUS Status;
	PDEVICE_OBJECT pDeviceObj = NULL;
	PDRIVER_OBJECT pDriverObj = NULL;

	//通过驱动对象名称获取驱动对象指针
	Status = ObReferenceObjectByName( pUSzDriverName, OBJ_CASE_INSENSITIVE, NULL, 0,
					  *IoDriverObjectType, KernelMode, NULL, &pDriverObj );
	if ( !NT_SUCCESS( Status ) || !pDriverObj  ) {
		return STATUS_UNSUCCESSFUL;
	}

	//通过驱动对象得到其设备对象指针
	pDeviceObj = pDriverObj->DeviceObject;

	__try {

		while ( pDeviceObj ) {

			//获取设备信息
			GetDeviceObjectInfo( pDeviceObj );

			//如果还有绑定在其之上的设备
			if ( pDeviceObj->AttachedDevice ) {
				//获取绑定在设备之上的的设备信息
				GetAttachedDeviceObjectInfo( pDeviceObj );

			}

			//进一步判断当前设备上的VPB中的设备
			if ( pDeviceObj->Vpb && pDeviceObj->Vpb->DeviceObject ) {

				//获取设备对象信息
				GetDeviceObjectInfo( pDeviceObj->Vpb->DeviceObject );

				//如果还有绑定设备
				if ( pDeviceObj->Vpb->DeviceObject->AttachedDevice ) {
					//获取绑定设备信息
					GetAttachedDeviceObjectInfo( pDeviceObj->Vpb->DeviceObject );
				}

			}
			pDeviceObj = pDeviceObj->NextDevice;
		}

	} __finally {
		if ( pDriverObj ) {
			ObDereferenceObject( pDriverObj );
		}

	}
	return Status;
}

NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
	NTSTATUS Status;
	UNICODE_STRING USzDriverName = RTL_CONSTANT_STRING( L"\\Driver\\ACPI" );

	Status = EnumDeviceStack( &USzDriverName );
	if ( !NT_SUCCESS( Status ) ) {
		KdPrint( ( "枚举设备失败!\n" ) );
		return Status;
	}

	return STATUS_UNSUCCESSFUL;
}

发表评论

您必须登录 才能进行评论。