From f8362347e42c97fa7bb9fc3cbbf9f04330b715e8 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 26 May 2011 20:39:15 +0000 Subject: [PATCH] [NTOSKRNL] - Implement the kernel side of surprise device removal including sending the appropriate IRPs and notifying the user-mode PnP manager - Fix the completely broken GUID_DEVICE_ARRIVAL notification (we were sending it for the parent not the children and we were sending regardless of whether any device had actually arrived) svn path=/trunk/; revision=51930 --- reactos/ntoskrnl/io/pnpmgr/pnpmgr.c | 70 ++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 0d8a1995d82..f8bd22c8d60 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -125,6 +125,21 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode, return STATUS_SUCCESS; } +VOID +NTAPI +IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject) +{ + IO_STACK_LOCATION Stack; + PVOID Dummy; + + RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); + Stack.MajorFunction = IRP_MJ_PNP; + Stack.MinorFunction = IRP_MN_SURPRISE_REMOVAL; + + /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */ + IopSynchronousCall(DeviceObject, &Stack, &Dummy); +} + VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject) @@ -1566,6 +1581,44 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, return STATUS_SUCCESS; } +static +VOID +IopHandleDeviceRemoval( + IN PDEVICE_NODE DeviceNode, + IN PDEVICE_RELATIONS DeviceRelations) +{ + PDEVICE_NODE Child = DeviceNode->Child, NextChild; + ULONG i; + BOOLEAN Found; + + while (Child != NULL) + { + NextChild = Child->Sibling; + Found = FALSE; + + for (i = 0; i < DeviceRelations->Count; i++) + { + if (IopGetDeviceNode(DeviceRelations->Objects[i]) == Child) + { + Found = TRUE; + break; + } + } + + if (!Found) + { + IopSendSurpriseRemoval(Child->PhysicalDeviceObject); + + /* Tell the user-mode PnP manager that a device was removed */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL, + &Child->InstancePath); + + IopSendRemoveDevice(Child->PhysicalDeviceObject); + } + + Child = NextChild; + } +} NTSTATUS IopEnumerateDevice( @@ -1583,12 +1636,6 @@ IopEnumerateDevice( DPRINT("DeviceObject 0x%p\n", DeviceObject); - DPRINT("Sending GUID_DEVICE_ARRIVAL\n"); - - /* Report the device to the user-mode pnp manager */ - IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, - &DeviceNode->InstancePath); - DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); Stack.Parameters.QueryDeviceRelations.Type = BusRelations; @@ -1613,6 +1660,11 @@ IopEnumerateDevice( } DPRINT("Got %u PDOs\n", DeviceRelations->Count); + + /* + * Send removal IRPs for devices that have disappeared + */ + IopHandleDeviceRemoval(DeviceNode, DeviceRelations); /* * Create device nodes for all discovered devices @@ -1633,6 +1685,12 @@ IopEnumerateDevice( &ChildDeviceNode); if (NT_SUCCESS(Status)) { + DPRINT("Sending GUID_DEVICE_ARRIVAL\n"); + + /* Report the device to the user-mode pnp manager */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &ChildDeviceNode->InstancePath); + /* Mark the node as enumerated */ ChildDeviceNode->Flags |= DNF_ENUMERATED;