From d8ba5920a2914067a5bb404ef5d76ce5c3011e50 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 3 Dec 2023 14:00:34 +0100 Subject: [PATCH] [NTOS:PNP][UMPNPMGR] GUID_DEVICE_ENUMERATED should be a DeviceInstallEvent - Move the GUID_DEVICE_ENUMERATED event from the TargetDeviceChangeEvent category to the DeviceInstallEvent category - Create a new function that handles DeviceInstallEvent category events --- base/services/umpnpmgr/event.c | 72 ++++++++++++++++++++-------------- ntoskrnl/include/internal/io.h | 10 +++-- ntoskrnl/io/pnpmgr/devaction.c | 8 +++- ntoskrnl/io/pnpmgr/plugplay.c | 43 +++++++++++++++++++- 4 files changed, 97 insertions(+), 36 deletions(-) diff --git a/base/services/umpnpmgr/event.c b/base/services/umpnpmgr/event.c index d9ae579cad2..5340431c005 100644 --- a/base/services/umpnpmgr/event.c +++ b/base/services/umpnpmgr/event.c @@ -42,34 +42,9 @@ ProcessTargetDeviceEvent( { RPC_STATUS RpcStatus; - if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus)) - { - DeviceInstallParams* Params; - DWORD len; - DWORD DeviceIdLength; + DPRINT("ProcessTargetDeviceEvent(%p)\n", PnpEvent); - DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds); - - DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds); - if (DeviceIdLength) - { - /* Allocate a new device-install event */ - len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR); - Params = HeapAlloc(GetProcessHeap(), 0, len); - if (Params) - { - wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds); - - /* Queue the event (will be dequeued by DeviceInstallThread) */ - WaitForSingleObject(hDeviceInstallListMutex, INFINITE); - InsertTailList(&DeviceInstallListHead, &Params->ListEntry); - ReleaseMutex(hDeviceInstallListMutex); - - SetEvent(hDeviceInstallListNotEmpty); - } - } - } - else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) + if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus)) { // DWORD dwRecipient; @@ -143,8 +118,8 @@ VOID ProcessDeviceClassChangeEvent( _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent) { - DPRINT("DeviceClassChangeEvent: %S\n", PnpEvent->DeviceClass.SymbolicLinkName); - + DPRINT("ProcessDeviceClassChangeEvent(%p)\n", PnpEvent); + DPRINT("SymbolicLink: %S\n", PnpEvent->DeviceClass.SymbolicLinkName); DPRINT("ClassGuid: {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", PnpEvent->DeviceClass.ClassGuid.Data1, PnpEvent->DeviceClass.ClassGuid.Data2, PnpEvent->DeviceClass.ClassGuid.Data3, PnpEvent->DeviceClass.ClassGuid.Data4[0], PnpEvent->DeviceClass.ClassGuid.Data4[1], PnpEvent->DeviceClass.ClassGuid.Data4[2], @@ -153,6 +128,39 @@ ProcessDeviceClassChangeEvent( } +static +VOID +ProcessDeviceInstallEvent( + _In_ PPLUGPLAY_EVENT_BLOCK PnpEvent) +{ + DeviceInstallParams* Params; + DWORD len; + DWORD DeviceIdLength; + + DPRINT("ProcessDeviceInstallEvent(%p)\n", PnpEvent); + DPRINT("Device enumerated: %S\n", PnpEvent->InstallDevice.DeviceId); + + DeviceIdLength = lstrlenW(PnpEvent->InstallDevice.DeviceId); + if (DeviceIdLength) + { + /* Allocate a new device-install event */ + len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR); + Params = HeapAlloc(GetProcessHeap(), 0, len); + if (Params) + { + wcscpy(Params->DeviceIds, PnpEvent->InstallDevice.DeviceId); + + /* Queue the event (will be dequeued by DeviceInstallThread) */ + WaitForSingleObject(hDeviceInstallListMutex, INFINITE); + InsertTailList(&DeviceInstallListHead, &Params->ListEntry); + ReleaseMutex(hDeviceInstallListMutex); + + SetEvent(hDeviceInstallListNotEmpty); + } + } +} + + DWORD WINAPI PnpEventThread( @@ -213,7 +221,11 @@ PnpEventThread( break; // case CustomDeviceEvent: -// case DeviceInstallEvent: + + case DeviceInstallEvent: + ProcessDeviceInstallEvent(PnpEvent); + break; + // case DeviceArrivalEvent: // case PowerEvent: // case VetoEvent: diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index 54a21832815..a349b48582d 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -676,9 +676,13 @@ IopQueueDeviceChangeEvent( NTSTATUS IopQueueTargetDeviceEvent( - const GUID *Guid, - PUNICODE_STRING DeviceIds -); + _In_ const GUID *Guid, + _In_ PUNICODE_STRING DeviceIds); + +NTSTATUS +IopQueueDeviceInstallEvent( + _In_ const GUID *Guid, + _In_ PUNICODE_STRING DeviceId); NTSTATUS NTAPI diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c index 8b133ef80f4..94e384fac13 100644 --- a/ntoskrnl/io/pnpmgr/devaction.c +++ b/ntoskrnl/io/pnpmgr/devaction.c @@ -1331,8 +1331,8 @@ PiInitializeDevNode( if (!IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER)) { /* Report the device to the user-mode pnp manager */ - IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED, - &DeviceNode->InstancePath); + IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED, + &DeviceNode->InstancePath); } return STATUS_SUCCESS; @@ -2580,6 +2580,10 @@ PipDeviceActionWorker( case PiActionResetDevice: // TODO: the operation is a no-op for everything except removed nodes // for removed nodes, it returns them back to DeviceNodeUninitialized + if (deviceNode->State == DeviceNodeRemoved) + { + deviceNode->State = DeviceNodeUninitialized; + } status = STATUS_SUCCESS; break; diff --git a/ntoskrnl/io/pnpmgr/plugplay.c b/ntoskrnl/io/pnpmgr/plugplay.c index 3b01ed06a1c..63556d0099b 100644 --- a/ntoskrnl/io/pnpmgr/plugplay.c +++ b/ntoskrnl/io/pnpmgr/plugplay.c @@ -93,6 +93,46 @@ IopQueueDeviceChangeEvent( return STATUS_SUCCESS; } +NTSTATUS +IopQueueDeviceInstallEvent( + _In_ const GUID *EventGuid, + _In_ PUNICODE_STRING DeviceId) +{ + PPNP_EVENT_ENTRY EventEntry; + UNICODE_STRING Copy; + ULONG TotalSize; + + /* Allocate a big enough buffer */ + Copy.Length = 0; + Copy.MaximumLength = DeviceId->Length + sizeof(UNICODE_NULL); + TotalSize = + FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, InstallDevice.DeviceId) + + Copy.MaximumLength; + + EventEntry = ExAllocatePool(NonPagedPool, + TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); + if (!EventEntry) + return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(EventEntry, TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); + + /* Fill the buffer with the event GUID */ + RtlCopyMemory(&EventEntry->Event.EventGuid, EventGuid, sizeof(GUID)); + EventEntry->Event.EventCategory = DeviceInstallEvent; + EventEntry->Event.TotalSize = TotalSize; + + /* Fill the symbolic link name */ + RtlCopyMemory(&EventEntry->Event.InstallDevice.DeviceId, + DeviceId->Buffer, DeviceId->Length); + EventEntry->Event.InstallDevice.DeviceId[DeviceId->Length / sizeof(WCHAR)] = UNICODE_NULL; + + InsertHeadList(&IopPnpEventQueueHead, &EventEntry->ListEntry); + + KeSetEvent(&IopPnpNotifyEvent, 0, FALSE); + + return STATUS_SUCCESS; +} + + NTSTATUS IopQueueTargetDeviceEvent(const GUID *Guid, PUNICODE_STRING DeviceIds) @@ -331,7 +371,8 @@ PiControlInitializeDevice( /* Insert as a root enumerated device node */ PiInsertDevNode(DeviceNode, IopRootDeviceNode); - IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED, &DeviceInstance); + /* Report the device to the user-mode pnp manager */ + IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED, &DeviceNode->InstancePath); ZwClose(InstanceKey); done: