[Win驱动7]ObReferenceObjectByName获取设备对象指针(PDEVICE_OBJECT)

1. ObReferenceObjectByName是通过设备对象名获取设备对象指针, 其会造成设备对象的引用计数增加所以还需要调用ObDereferenceObject来降低引用计数

2. IoGetDeviceObjectPointer可以通过设备对象名获取设备对象指针和与其相关的文件对象指针,同样需要对其调用ObDereferenceObject来降低引用

第一种方式是通过这个未公开的内核函数ObReferenceObjectByName来获取设备对象指针,该原型是这样的:

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);
extern POBJECT_TYPE IoDeviceObjectType;
extern POBJECT_TYPE *IoDriverObjectType;
  • ObjectName是设备对象名
  • Attributes一般是OBJ_CASE_INSENSITIVE
  • PassedAccessState一般是NULL
  • DesiredAccess是FILE_ALL_ACCESS
  • ObjectType使用IoDeviceObjectType可以获取文件指针
  • ParseContext一般是NULL
  • Object是返回文件指针

返回值: NTSTATUS类型状态码代表获得的结果是否成功

可以通过ObReferenceObjectByName来实现IoGetDeviceObjectPointer, 下面是实现过程:

// 这也是一个未公开的函数,目的是通过文件对象指针获取设备对象指针
NTKERNELAPI PDEVICE_OBJECT NTAPI IoGetBaseFileSystemDeviceObject(IN PFILE_OBJECT FileObject);

NTSTATUS _IoGetDeviceObjectPointer(IN PUNICODE_STRING ObjectName, 
								   IN ACCESS_MASK DesiredAccess,
								   OUT PFILE_OBJECT *FileObject,
								   OUT PDEVICE_OBJECT *DeviceObject) {
	PFILE_OBJECT fileObj;
	OBJECT_ATTRIBUTES objectAttributes;
	HANDLE fileHandle;
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status;

	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)) {
		status = ObReferenceObjectByHandle(fileHandle, 0, *IoFileObjectType, KernelMode, (PVOID)&fileObj, NULL);
		if (NT_SUCCESS(status)) {
			*FileObject = fileObj;
			*DeviceObject = IoGetBaseFileSystemDeviceObject(fileObj); // 通过文件对象获取设备对象指针
		}
		ZwClose(fileHandle);
	}

	return(status);
}

以上是通过ObReferenceObjectByName来模拟IoGetDeviceObjectPointer,下面来看看在具体IRP中是如何使用的,例子如下:

NTSTATUS ReadRoutine(IN PDEVICE_OBJECT pDev, IN PIRP pIrp) {
	KdPrint(("进入了Driver的ReadRoutine!\n"));
	NTSTATUS status = STATUS_SUCCESS;

	UNICODE_STRING DevName;
	RtlInitUnicodeString(&DevName, L"\\Device\\AKA");

	PDEVICE_OBJECT pDevObj;
	PFILE_OBJECT pfileObj;
	status = _IoGetDeviceObjectPointer(&DevName, FILE_ALL_ACCESS, &pfileObj, &pDevObj);
	KdPrint(("_IoGetDeviceObjectPointer获取文件对象地址%08X, 设备对象地址%08X", pfileObj, pDevObj));
	ObDereferenceObject(pfileObj);
	status = ObReferenceObjectByName(&DevName, OBJ_CASE_INSENSITIVE, NULL, FILE_ALL_ACCESS, IoDeviceObjectType, KernelMode, NULL, (PVOID *)&pDevObj);
	KdPrint(("ObReferenceObjectByName获取设备对象地址%08X\n", pDevObj));
	ObDereferenceObject(pDevObj);
	
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = 0;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	KdPrint(("离开了Driver的ReadRoutine!\n"));

	return(status);
}

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值