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);
}
(完)