转 枚举设备栈

Posted 单车博客园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转 枚举设备栈相关的知识,希望对你有一定的参考价值。

hello.h

#pragma once
#include <ntddk.h>
#define CountArray(Array)  (	sizeof(Array)	/	sizeof(Array[0])	)



typedef struct _DEVICE_EXTENSION
{
	PDEVICE_OBJECT pDevice;							//设备对象
	UNICODE_STRING ustrDeviceName;					//设备名称
	UNICODE_STRING ustrSymLinkName;					//符号名称
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h>
	NTKERNELAPI
		NTSTATUS
		ObReferenceObjectByName(
		IN PUNICODE_STRING ObjectName,
		IN ULONG Attributes,
		IN PACCESS_STATE PassedAccessState OPTIONAL,
		IN ACCESS_MASK DesiredAccess OPTIONAL,
		IN POBJECT_TYPE ObjectType,
		IN KPROCESSOR_MODE AccessMode,
		IN OUT PVOID ParseContext OPTIONAL,
		OUT PVOID *Object
		);
	NTKERNELAPI
		PDEVICE_OBJECT
		NTAPI
		IoGetBaseFileSystemDeviceObject (
		IN PFILE_OBJECT FileObject
		);
	extern POBJECT_TYPE IoDeviceObjectType;
	extern POBJECT_TYPE *IoDriverObjectType;
#ifdef __cplusplus
}
#endif 


typedef struct _OBJECT_CREATE_INFORMATION
{
	ULONG Attributes;
	HANDLE RootDirectory;
	PVOID ParseContext;
	KPROCESSOR_MODE ProbeMode;
	ULONG PagedPoolCharge;
	ULONG NonPagedPoolCharge;
	ULONG SecurityDescriptorCharge;
	PSECURITY_DESCRIPTOR SecurityDescriptor;
	PSECURITY_QUALITY_OF_SERVICE SecurityQos;
	SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
} OBJECT_CREATE_INFORMATION, * POBJECT_CREATE_INFORMATION;

typedef struct _OBJECT_HEADER
{
	LONG PointerCount;
	union
	{
		LONG HandleCount;
		PSINGLE_LIST_ENTRY SEntry;
	};
	POBJECT_TYPE Type;
	UCHAR NameInfoOffset;
	UCHAR HandleInfoOffset;
	UCHAR QuotaInfoOffset;
	UCHAR Flags;
	union
	{
		POBJECT_CREATE_INFORMATION ObjectCreateInfo;
		PVOID QuotaBlockCharged;
	};

	PSECURITY_DESCRIPTOR SecurityDescriptor;
	QUAD Body;
} OBJECT_HEADER, * POBJECT_HEADER;

#define NUMBER_HASH_BUCKETS 37

typedef struct _OBJECT_DIRECTORY
{
	struct _OBJECT_DIRECTORY_ENTRY* HashBuckets[NUMBER_HASH_BUCKETS];
	struct _OBJECT_DIRECTORY_ENTRY** LookupBucket;
	BOOLEAN LookupFound;
	USHORT SymbolicLinkUsageCount;
	struct _DEVICE_MAP* DeviceMap;
} OBJECT_DIRECTORY, * POBJECT_DIRECTORY;

typedef struct _OBJECT_HEADER_NAME_INFO
{
	POBJECT_DIRECTORY Directory;
	UNICODE_STRING Name;
	ULONG Reserved;
#if DBG
	ULONG Reserved2 ;
	LONG DbgDereferenceCount ;
#endif
} OBJECT_HEADER_NAME_INFO, * POBJECT_HEADER_NAME_INFO;

#define OBJECT_TO_OBJECT_HEADER( o ) 	CONTAINING_RECORD( (o), OBJECT_HEADER, Body )

#define OBJECT_HEADER_TO_NAME_INFO( oh ) ((POBJECT_HEADER_NAME_INFO) 	((oh)->NameInfoOffset == 0 ? NULL : ((PCHAR)(oh) - (oh)->NameInfoOffset)))




#ifdef __cplusplus
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif

void HelloUnload(IN PDRIVER_OBJECT DriverObject);							//卸载函数
NTSTATUS CreateDevice(PDRIVER_OBJECT PDevObj);								//创建设备
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);	//派遣函数
NTSTATUS HelloDDKControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp);			//IRP_MJ_DIRECTORY_CONTROL


 

 

 

Driver.cpp

#include "hello.h"

//获取设备信息
VOID GetDeviceObjectInfo( PDEVICE_OBJECT DevObj)
{
	//变量定义
	POBJECT_HEADER ObjectHeader;
	POBJECT_HEADER_NAME_INFO ObjectNameInfo; 

	//参数判断
	if (DevObj == NULL )
		return;

	// 得到对象头
	ObjectHeader = OBJECT_TO_OBJECT_HEADER( DevObj );

	if (ObjectHeader)
	{
		//查询设备头信息
		ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );

		//输出设备信息
		if ( ObjectNameInfo && ObjectNameInfo->Name.Buffer )
		{
			DbgPrint( "Driver Name:%wZ - Device Name:%wZ - Driver Address:0x%x - Device Address:0x%x\n",
				&DevObj->DriverObject->DriverName,
				&ObjectNameInfo->Name,
				DevObj->DriverObject,
				DevObj );
		}
		else if ( DevObj->DriverObject )
		{
			// 对于没有名称的设备,则打印 NULL
			DbgPrint( "Driver Name:%wZ - Device Name:%S - Driver Address:0x%x - Device Address:0x%x\n",
				&DevObj->DriverObject->DriverName,
				L"NULL",
				DevObj->DriverObject,
				DevObj );
		}
	}
}

//获取过滤设备信息
VOID GetAttachedDeviceInfo( PDEVICE_OBJECT DevObj )
{
	//变量定义
	PDEVICE_OBJECT DeviceObject;

	//参数判断
	if (DevObj == NULL)
		return;

	//变量赋值
	DeviceObject = DevObj->AttachedDevice;

	while ( DeviceObject )
	{
		//打印过滤设备信息
		DbgPrint( "Attached Driver Name:%wZ,Attached Driver Address:0x%x,Attached DeviceAddress:0x%x\n",
			&DeviceObject->DriverObject->DriverName,
			DeviceObject->DriverObject,
			DeviceObject );

		//获取下一个设备
		DeviceObject = DeviceObject->AttachedDevice;
	}
}

//枚举设备栈
PDRIVER_OBJECT EnumDeviceStack( PWSTR pwszDeviceName )
{
	//变量定义
	UNICODE_STRING DriverName;
	PDRIVER_OBJECT DriverObject = NULL;
	PDEVICE_OBJECT DeviceObject = NULL;

	//获取设备对象指针  
	RtlInitUnicodeString(&DriverName,pwszDeviceName);
	ObReferenceObjectByName(&DriverName,OBJ_CASE_INSENSITIVE,NULL,0,(POBJECT_TYPE)IoDriverObjectType,KernelMode,NULL,(PVOID*)&DriverObject );

	//设备判断
	if (DriverObject == NULL)
		return NULL;

	//变量赋值
	DeviceObject = DriverObject->DeviceObject;

	//获取设备栈
	while ( DeviceObject )
	{
		//获取设备信息
		GetDeviceObjectInfo( DeviceObject );

		// 判断当前设备上是否有过滤驱动(Filter Driver)
		if ( DeviceObject->AttachedDevice )
		{
			//获取过滤设备
			GetAttachedDeviceInfo( DeviceObject );
		}

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

			if ( DeviceObject->Vpb->DeviceObject->AttachedDevice )
			{
				GetAttachedDeviceInfo( DeviceObject->Vpb->DeviceObject );
			}
		}

		// 得到建立在此驱动上的下一个设备 DEVICE_OBJECT 
		DeviceObject = DeviceObject->NextDevice;
	}

	return DriverObject;
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
	DbgPrint("Hello from!\n");
	DriverObject->DriverUnload = HelloUnload;
	for (int i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
	{
		DriverObject->MajorFunction[i]=HelloDDKDispatchRoutine;
	}
	
	//创建设备
	CreateDevice(DriverObject);
	EnumDeviceStack(L"\\Driver\\Kbdclass");
	return STATUS_SUCCESS;
}


//卸载函数
void HelloUnload(IN PDRIVER_OBJECT DriverObject)
{
	DbgPrint("Goodbye from!\n");
	PDEVICE_OBJECT pNextObj=NULL;
	pNextObj=DriverObject->DeviceObject;

	while (pNextObj)
	{
		PDEVICE_EXTENSION pDevExt=(PDEVICE_EXTENSION)pNextObj->DeviceExtension;
		//删除符号连接
		IoDeleteSymbolicLink(&pDevExt->ustrSymLinkName);
		//删除设备
		IoDeleteDevice(pDevExt->pDevice);
		pNextObj=pNextObj->NextDevice;
	}
}

//创建设备
NTSTATUS CreateDevice(PDRIVER_OBJECT pDriver_Object)
{
	//定义变量
	NTSTATUS status=STATUS_SUCCESS;
	PDEVICE_OBJECT pDevObje=NULL;
	PDEVICE_EXTENSION pDevExt=NULL;

	//初始化字符串
	UNICODE_STRING devname;
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&devname,L"\\device\\hello");
	RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");

	//创建设备
	if (IoCreateDevice(pDriver_Object,sizeof(PDEVICE_EXTENSION),&devname,FILE_DEVICE_UNKNOWN,NULL,TRUE,&pDevObje)!=STATUS_SUCCESS )
	{
		DbgPrint("创建设备失败\n");
		return status;
	}
	pDevObje->Flags |= DO_DIRECT_IO;
	pDevExt=(PDEVICE_EXTENSION)pDevObje->DeviceExtension;
	pDevExt->pDevice=pDevObje;
	pDevExt->ustrDeviceName=devname;
	pDevExt->ustrSymLinkName=symLinkName;

	//创建符号连接
	if (IoCreateSymbolicLink(&symLinkName,&devname)!=STATUS_SUCCESS )
	{
		DbgPrint("创建符号连接失败\n");
		IoDeleteDevice(pDevObje);
		return status;
	}
	return STATUS_SUCCESS;
}

//派遣函数
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrP)
{
	

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrP);
	//建立一个字符串数组与IRP类型对应起来
	static char* irpname[] = 
	{
		"IRP_MJ_CREATE",
		"IRP_MJ_CREATE_NAMED_PIPE",
		"IRP_MJ_CLOSE",
		"IRP_MJ_READ",
		"IRP_MJ_WRITE",
		"IRP_MJ_QUERY_INFORMATION",
		"IRP_MJ_SET_INFORMATION",
		"IRP_MJ_QUERY_EA",
		"IRP_MJ_SET_EA",
		"IRP_MJ_FLUSH_BUFFERS",
		"IRP_MJ_QUERY_VOLUME_INFORMATION",
		"IRP_MJ_SET_VOLUME_INFORMATION",
		"IRP_MJ_DIRECTORY_CONTROL",
		"IRP_MJ_FILE_SYSTEM_CONTROL",
		"IRP_MJ_DEVICE_CONTROL",
		"IRP_MJ_INTERNAL_DEVICE_CONTROL",
		"IRP_MJ_SHUTDOWN",
		"IRP_MJ_LOCK_CONTROL",
		"IRP_MJ_CLEANUP",
		"IRP_MJ_CREATE_MAILSLOT",
		"IRP_MJ_QUERY_SECURITY",
		"IRP_MJ_SET_SECURITY",
		"IRP_MJ_POWER",
		"IRP_MJ_SYSTEM_CONTROL",
		"IRP_MJ_DEVICE_CHANGE",
		"IRP_MJ_QUERY_QUOTA",
		"IRP_MJ_SET_QUOTA",
		"IRP_MJ_PNP",
	};

	UCHAR type = stack->MajorFunction;

	if (type >= CountArray(irpname))
		KdPrint(("无效的IRP类型 %X\n", type));
	else
		KdPrint(("%s\n", irpname[type]));




	pIrP->iostatus.Status=STATUS_SUCCESS;					//设置完成状态
	pIrP->IoStatus.Information=0;							//设置操作字节为0
	IoCompleteRequest(pIrP,IO_NO_INCREMENT);			//结束IRP派遣函数,第二个参数表示不增加优先级
	return STATUS_SUCCESS;
}

以上是关于转 枚举设备栈的主要内容,如果未能解决你的问题,请参考以下文章

usb枚举

很实用的JQuery代码片段(转)

如何从活动 CUDA 设备获取属性?

带有红宝石集合/可枚举的酷技巧和富有表现力的片段[关闭]

android平台 usb设备开发 动态枚举pc端的usb端口?

python调试:pdb基本用法(转)