[NTOSKRNL]

- Remove the device node when the device object is destroyed to prevent PnP manager from crashing when manipulating device nodes with device objects that no longer exist
- Move removal notifications into IopRemoveDevice and call it from IopPrepareDeviceForRemoval and IoRequestDeviceEject to manage all of the removal relations for each device removed

svn path=/trunk/; revision=52034
This commit is contained in:
Cameron Gutman 2011-06-01 06:22:54 +00:00
parent 47328a7510
commit 9048ea9dcf
2 changed files with 14 additions and 21 deletions

View file

@ -48,9 +48,12 @@ NTAPI
IopDeleteDevice(IN PVOID ObjectBody) IopDeleteDevice(IN PVOID ObjectBody)
{ {
PDEVICE_OBJECT DeviceObject = ObjectBody; PDEVICE_OBJECT DeviceObject = ObjectBody;
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
PAGED_CODE(); PAGED_CODE();
/* TODO: Delete Device Node */ /* Cleanup and free the device node */
if (DeviceNode)
IopFreeDeviceNode(DeviceNode);
/* Dereference the driver object, referenced in IoCreateDevice */ /* Dereference the driver object, referenced in IoCreateDevice */
if (DeviceObject->DriverObject) if (DeviceObject->DriverObject)

View file

@ -3936,24 +3936,16 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject)
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING, IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
&RelationsDeviceNode->InstancePath); &RelationsDeviceNode->InstancePath);
if (IopQueryRemoveDevice(DeviceRelations->Objects[i]) != STATUS_SUCCESS) if (IopRemoveDevice(RelationsDeviceNode) != STATUS_SUCCESS)
{ {
DPRINT1("Device removal vetoed by failing a dependent query remove request\n"); DPRINT1("Device removal vetoed by failing a dependent query remove request\n");
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
&RelationsDeviceNode->InstancePath);
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
goto cleanup; goto cleanup;
} }
else else
{ {
IopSendRemoveDevice(DeviceRelations->Objects[i]);
IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
&RelationsDeviceNode->InstancePath);
ObDereferenceObject(DeviceRelations->Objects[i]); ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL; DeviceRelations->Objects[i] = NULL;
@ -3995,9 +3987,15 @@ IopRemoveDevice(PDEVICE_NODE DeviceNode)
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject); IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
&DeviceNode->InstancePath);
DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
&DeviceNode->InstancePath);
return Status; return Status;
} }
@ -4051,22 +4049,14 @@ IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING, IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
&RelationsDeviceNode->InstancePath); &RelationsDeviceNode->InstancePath);
if (IopQueryRemoveDevice(DeviceRelations->Objects[i]) != STATUS_SUCCESS) if (IopRemoveDevice(RelationsDeviceNode) != STATUS_SUCCESS)
{ {
DPRINT1("Device removal vetoed by failing a query remove request (ejection relations)\n"); DPRINT1("Device removal vetoed by failing a query remove request (ejection relations)\n");
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
&RelationsDeviceNode->InstancePath);
goto cleanup; goto cleanup;
} }
else else
{ {
IopSendRemoveDevice(DeviceRelations->Objects[i]);
IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
&RelationsDeviceNode->InstancePath);
ObDereferenceObject(DeviceRelations->Objects[i]); ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL; DeviceRelations->Objects[i] = NULL;