WDM中通过driver name获取Driver Object并遍历此Driver产生的Device Object

这里需要用到一个未公开的(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;


遍历的同时,我们可以将PDO的Device Name提取到,参考:

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






你可能感兴趣的:(WDM中通过driver name获取Driver Object并遍历此Driver产生的Device Object)