PnpMgr分析
+ -

PNP管理器事件

2024-04-03 2 0

当设备管理器有动作时,使用PiInsertEventInQueue创建一个相关的事件动作,并挂入相应全局动作队列中,然后启用WorkItem来执行该动作。
事件动作定义为:

typedef struct _PNP_DEVICE_EVENT_ENTRY {
    LIST_ENTRY                          ListEntry;
    ULONG                               Argument;
    PKEVENT                             CallerEvent;
    PDEVICE_CHANGE_COMPLETE_CALLBACK    Callback;
    PVOID                               Context;
    PPNP_VETO_TYPE                      VetoType;
    PUNICODE_STRING                     VetoName;
    PLUGPLAY_EVENT_BLOCK                Data;
} PNP_DEVICE_EVENT_ENTRY, *PPNP_DEVICE_EVENT_ENTRY;

这些事件主要有以下几种:

  • PpSetTargetDeviceRemove
  • PpSetDeviceClassChange
  • PpSetCustomTargetEvent
  • PpSetDeviceRemovalSafe
  • PpSetHwProfileChangeEvent
  • PpSetBlockedDriverEvent
  • PpSetPowerEvent
  • PpSetPowerVetoEvent
  • PpSetPlugPlayEvent
  • PpSynchronizeDeviceEventQueue

PpSetDeviceRemovalSafe

其中PpSetDeviceRemovalSafe是专门用于处理设备移除的:
其初始化过程可如:

NTSTATUS
PpSetDeviceRemovalSafe(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PKEVENT SyncEvent           OPTIONAL,
    OUT PULONG Result               OPTIONAL
    )
{
    if (PpPnpShuttingDown) {

        return STATUS_TOO_LATE;
    }

    //
    // Reference the device object so it can't go away until after we're
    // done with notification.
    //

    ObReferenceObject(DeviceObject);

    deviceNode = (PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
    ASSERT(deviceNode);


    //
    // Calculate the size of the PLUGPLAY_EVENT_BLOCK, this is the size that
    // we record in the TotalSize field later (the length doesn't count the
    // terminating null but we're already counting the first index into the
    // DeviceId field so it works out. Add one more for double-null term.
    //

    dataSize = sizeof(PLUGPLAY_EVENT_BLOCK);

    dataSize += deviceNode->InstancePath.Length + sizeof(WCHAR);

    totalSize = FIELD_OFFSET(PNP_DEVICE_EVENT_ENTRY, Data) + dataSize;

    deviceEvent = ExAllocatePoolWithTag(PagedPool, totalSize, PNP_DEVICE_EVENT_ENTRY_TAG);
    if (deviceEvent == NULL) {
        ObDereferenceObject(DeviceObject);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    RtlZeroMemory((PVOID)deviceEvent, totalSize);

    deviceEvent->CallerEvent = SyncEvent;
    deviceEvent->Argument = 0;
    deviceEvent->VetoType = NULL;
    deviceEvent->VetoName = NULL;
    deviceEvent->Data.EventGuid = GUID_DEVICE_SAFE_REMOVAL;
    deviceEvent->Data.EventCategory = TargetDeviceChangeEvent;
    deviceEvent->Data.Result = Result;
    deviceEvent->Data.Flags = 0;

    deviceEvent->Data.TotalSize = dataSize;
    deviceEvent->Data.DeviceObject = (PVOID)DeviceObject;

    if (deviceNode->InstancePath.Length != 0) {

        RtlCopyMemory((PVOID)deviceEvent->Data.u.TargetDevice.DeviceIds,
                    (PVOID)deviceNode->InstancePath.Buffer,
                    deviceNode->InstancePath.Length);
    }

    i = deviceNode->InstancePath.Length/sizeof(WCHAR);
    deviceEvent->Data.u.TargetDevice.DeviceIds[i] = L'\0';
       status = PiInsertEventInQueue(deviceEvent);

    return status;
}

该事件主要分为以下几个层次:

  • CallerEvent:表示该事件应该执行的方式。
  • EventCategory:表示事件的大体分类,主要为:
    • HardwareProfileChangeEvent
    • TargetDeviceChangeEvent
    • DeviceClassChangeEvent
    • CustomDeviceEvent
    • DeviceInstallEvent
    • DeviceArrivalEvent
  • EventGuid则为事件的具体标识:
    struct  {
      CONST GUID *Guid;
      PCHAR   Name;
    }   EventGuidTable[] =  {
      { &GUID_HWPROFILE_QUERY_CHANGE,         "GUID_HWPROFILE_QUERY_CHANGE" },
      { &GUID_HWPROFILE_CHANGE_CANCELLED,     "GUID_HWPROFILE_CHANGE_CANCELLED" },
      { &GUID_HWPROFILE_CHANGE_COMPLETE,      "GUID_HWPROFILE_CHANGE_COMPLETE" },
      { &GUID_DEVICE_INTERFACE_ARRIVAL,       "GUID_DEVICE_INTERFACE_ARRIVAL" },
      { &GUID_DEVICE_INTERFACE_REMOVAL,       "GUID_DEVICE_INTERFACE_REMOVAL" },
      { &GUID_TARGET_DEVICE_QUERY_REMOVE,     "GUID_TARGET_DEVICE_QUERY_REMOVE" },
      { &GUID_TARGET_DEVICE_REMOVE_CANCELLED, "GUID_TARGET_DEVICE_REMOVE_CANCELLED" },
      { &GUID_TARGET_DEVICE_REMOVE_COMPLETE,  "GUID_TARGET_DEVICE_REMOVE_COMPLETE" },
      { &GUID_PNP_CUSTOM_NOTIFICATION,        "GUID_PNP_CUSTOM_NOTIFICATION" },
      { &GUID_DEVICE_ARRIVAL,                 "GUID_DEVICE_ARRIVAL" },
      { &GUID_DEVICE_ENUMERATED,              "GUID_DEVICE_ENUMERATED" },
      { &GUID_DEVICE_ENUMERATE_REQUEST,       "GUID_DEVICE_ENUMERATE_REQUEST" },
      { &GUID_DEVICE_START_REQUEST,           "GUID_DEVICE_START_REQUEST" },
      { &GUID_DEVICE_REMOVE_PENDING,          "GUID_DEVICE_REMOVE_PENDING" },
      { &GUID_DEVICE_QUERY_AND_REMOVE,        "GUID_DEVICE_QUERY_AND_REMOVE" },
      { &GUID_DEVICE_EJECT,                   "GUID_DEVICE_EJECT" },
      { &GUID_DEVICE_NOOP,                    "GUID_DEVICE_NOOP" },
      { &GUID_DEVICE_SURPRISE_REMOVAL,        "GUID_DEVICE_SURPRISE_REMOVAL" },
      { &GUID_DEVICE_SAFE_REMOVAL,            "GUID_DEVICE_SAFE_REMOVAL" },
      { &GUID_DEVICE_EJECT_VETOED,            "GUID_DEVICE_EJECT_VETOED" },
      { &GUID_DEVICE_REMOVAL_VETOED,          "GUID_DEVICE_REMOVAL_VETOED" },
    };
    #define EVENT_GUID_TABLE_SIZE   (sizeof(EventGuidTable) / sizeof(EventGuidTable[0]))
    

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!