转 枚举设备栈

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;
}
时间: 2024-11-18 16:22:22

转 枚举设备栈的相关文章

[转载]windows过滤驱动程序设计入门(驱动程序基本结构,设备栈,IRP栈和工作原理)

本文转载自: http://blog.csdn.net/arvon2012/article/details/7789724 最近在学习windows驱动设计,认真看了些教材后总结了我认为驱动中都会涉及到,也最重要的概念,和大家分享.如果有说的不对的请大家留言指出.谢谢! 这里主要是写概念,代码涉及的不多也不详细,但是我会说出涉及到的API,详细的使用细节大家可以自己动手搜搜.掌握下面的概念之后,看驱动开发的教材里的代码,或者理解教材里说的内容应该就顺利很多! 过滤驱动程序概括: 对于window

[转载]设备栈

1. 栈结构 设备栈(Device Stack)结构与内存中的栈类似,但是 device stack 中的 entry 由 device object 中的 AttachedDevice 值的连接. 如下图所示: 并且由每个 device 的 DeviceExtension.AttachedTo 值指向下一层的 device.从而形成双向的链结构. 2. 栈顶 由 IoGetAttachedDevice() 函数来得到当前栈顶 device: PDEVICE_OBJECT IoGetAttach

C#:USB设备枚举 --转自CSDN作者:Splash

(一)DeviceIoControl的PInvoke /* ---------------------------------------------------------- 文件名称:DeviceIoControl.cs 作者:秦建辉 MSN:[email protected] QQ:36748897 博客:http://blog.csdn.net/jhqin 开发环境: Visual Studio V2010 .NET Framework 4 Client Profile 版本历史: V1

【PCIE3】---PCIE设备的枚举扫描(经典好文)

前面两个小节大致总结了下PCIE的基本知识,算是扫盲篇吧.本文主要总结PCIE设备的枚举扫描过程,此部分才是PCIE模块的重点,无论是在BIOS下还是系统驱动下都会用到. 按照国际惯例,先列问题: 1. 系统如何判断PCIE设备是否在位? 2. 设备中的配置空间的数据一开始就有嘛?谁写的? 3. Bus号,Dev号,和Fun号与硬件有关系嘛?硬件链接与BDS号的分配是否有关? 4. Bridge和Device的区别? 5. Device和Function的区别? 6. 枚举的流程是怎么样的? 系

USB设备驱动概述

USB设备驱动 ·  17.1 USB总线协议 ·  17.1.1 USB设备简介 ·  17.1.2 USB连接拓扑结构 ·  17.1.3 USB通信的流程 ·  17.1.4 USB四种传输模式 ·  17.2.1 观察USB设备的工具 ·  17.2.2 USB设备请求 ·  17.2.3 设备描述符 ·  17.2.4 配置描述符 ·  17.2.5 接口描述符 ·  17.2.6 端点描述符 ·  17.3.1 功能驱动与物理总线驱动 ·  17.3.2 构造USB请求包 ·  17

USB设备驱动开发之远程访问USB设备(二 USB设备虚拟端)

By Fanxiushu 2016-05-22 转载或引用请注明原始作者 接上文, 在处理好USB数据采集端的问题之后,接下来进入核心的部分,虚拟USB设备端的开发工作. 上文简单介绍过,需要开发虚拟总线驱动来模拟USB设备. 所谓虚拟总线驱动,就是安装于System系统设备下的一个驱动,由PnP管理器创建出一个虚拟的总线PDO设备, 我们的虚拟总线驱动Attach到这个PDO上,形成一个FDO功能设备驱动, 然后在我们的驱动中,根据需要创建出若干个 Child PDO设备, 这些 Child

系统虚拟化学习笔记——PCI设备

内容摘自<系统虚拟化:原理与实现> PCI 总线架构 PCI总线是典型的树结构.把北桥中host-PCI桥看做根,总线中其他PCI-PCI桥,PCI-ISA桥(ISA总线转PCI总线桥)等桥设备和 直接连PCI总线的设备看做节点,整个PCI架构可以概括成下图: 通过桥,PCI可以很容易被扩展,并且与其他总线相互挂接,构成整个系统的总线网络.与HOST-PCI桥相连的总线称为总线0, 其他层次总线的编号,是在BIOS(或者操作系统)枚举设备时确定的. 设备标识符 设备标识符可以看做设备在PCI总

DirectShow控制台输出和保存视频设备名称

#include "windows.h" #include "TCHAR.h" #include <dshow.h> #include <vector> #include <iostream> #include <cwctype> #define MAX_FRIENDLY_NAME_LENGTH 128 #define MAX_MONIKER_NAME_LENGTH 256 typedef struct _TDevic

使用devcon工具,结合批处理重启无线网卡设备

最近由于工作需要,写了一个重启无线网卡的批处理. 首先说一下我的思路: 1. ping网关(默认选项,网关为192.168.1.1)两次,如果成功,则批处理结束 2. 如果不成功,则在第二次,重启无线网卡 为了达到以上目的.我需要一个可以在DOS命令中进行启用.禁用.重新启动.更新.删除和查询单个设备或一组设备的工具.而devcon恰恰就是windows中进行这些操作的工具.它并未集成在windows的默认安装中,为此,我们需要通过官网或者其他网站下载该工具.由于官方提供的工具在win7 64b