[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
This commit is contained in:
Cameron Gutman 2011-05-26 20:39:15 +00:00
parent 2332dc3a16
commit f8362347e4

View file

@ -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;