這裏需要用到一個未公開的(undocumented)API
ObReferenceObjectByName
函數可以通過對象名字得到包括設備對象在內的各種內核對象的指針,比如內核事件,互斥體對象等.他會增加內核對象的引用計數,使用完內核對象後要用ObDereferenceObject內核函數將引用計數減1.
定義參考:
NTKERNELAPI NTSTATUS ObReferenceObjectByName ( __in PUNICODE_STRING ObjectName,
__in ULONG Attributes,
__in_opt PACCESS_STATE AccessState,
__in_opt ACCESS_MASK DesiredAccess,
__in POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__inout_opt PVOID ParseContext,
__out PVOID * Object
)
支持從driver name獲取DRIVER_OBJECT,從device name獲取DEVICE_OBJECT
從Driver name獲取DRIVER_OBJECT:
// API define
#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
);
extern POBJECT_TYPE *IoDriverObjectType;
#ifdef __cplusplus
}
#endif
// use such API
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING DriverName;
PDRIVER_OBJECT pDriverObj = NULL;
RtlInitUnicodeString(&DriverName, L"\\Driver\\usbhub"); // usbhub as an example
status = ObReferenceObjectByName(
&DriverName,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&pDriverObj);
從Device name獲取Device Object的方式類似,只需要注意區分ObjectType即可。
我們可以通過DRIVER_OBJECT->DeviceObject來獲取此Driver產生的DEVICE_OBJECT,並通過DEVICE_OBJECT->NextDevice來遍歷所有的DEVICE_OBJECT。
typedef struct _DRIVER_OBJECT {
CSHORT Type;
CSHORT Size;
//
// The following links all of the devices created by a single driver
// together on a list, and the Flags word provides an extensible flag
// location for driver objects.
//
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
//
// The following section describes where the driver is loaded. The count
// field is used to count the number of times the driver has had its
// registered reinitialization routine invoked.
//
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
//
// The driver name field is used by the error log thread
// determine the name of the driver that an I/O request is/was bound.
//
UNICODE_STRING DriverName;
//
// The following section is for registry support. Thise is a pointer
// to the path to the hardware information in the registry
//
PUNICODE_STRING HardwareDatabase;
//
// The following section contains the optional pointer to an array of
// alternate entry points to a driver for "fast I/O" support. Fast I/O
// is performed by invoking the driver routine directly with separate
// parameters, rather than using the standard IRP call mechanism. Note
// that these functions may only be used for synchronous I/O, and when
// the file is cached.
//
PFAST_IO_DISPATCH FastIoDispatch;
//
// The following section describes the entry points to this particular
// driver. Note that the major function dispatch table must be the last
// field in the object so that it remains extensible.
//
PDRIVER_INITIALIZE DriverInit;
PDRIVER_STARTIO DriverStartIo;
PDRIVER_UNLOAD DriverUnload;
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
} DRIVER_OBJECT;
if (STATUS_SUCCESS == status
&& NULL != pDriverObj)
{
PDEVICE_OBJECT pDevObj = pDriverObj->DeviceObject;
ULONG resultLength = 0;
PWCHAR pResultBuffer = NULL;
while(NULL != pDevObj)
{
if (pDevObj->Flags & DO_BUS_ENUMERATED_DEVICE ) // PDO
{
resultLength = 0;
status = IoGetDeviceProperty( // get PDO device name
pDevObj,
DevicePropertyPhysicalDeviceObjectName,
0,
NULL,
&resultLength);
if (STATUS_BUFFER_TOO_SMALL == status
&& resultLength>0)
{
pResultBuffer = ExAllocatePoolWithTag(
NonPagedPool,
resultLength+1,
'NCSP');
if (pResultBuffer)
{
RtlZeroMemory(pResultBuffer, resultLength+1);
status = IoGetDeviceProperty(
pDevObj,
DevicePropertyPhysicalDeviceObjectName,
resultLength,
pResultBuffer,
&resultLength);
}
}
if (pResultBuffer)
{
ExFreePool(pResultBuffer);
}
}
pDevObj = pDevObj->NextDevice;
}
ObDereferenceObject(pPciDriverObj);
}