Author: cgutman
Date: Thu May 26 20:39:15 2011
New Revision: 51930
URL:
http://svn.reactos.org/svn/reactos?rev=51930&view=rev
Log:
[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)
Modified:
trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] Thu May 26 20:39:15 2011
@@ -123,6 +123,21 @@
IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
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
@@ -1566,6 +1581,44 @@
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 @@
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 @@
}
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 @@
&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;