[NTOSKRNL]

- Implement sending GUID_TARGET_DEVICE_QUERY_REMOVE and GUID_TARGET_DEVICE_REMOVE_COMPLETE notifications
- Fix sending EventCategoryTargetDeviceChange notifications
- Remove some incorrect checks (IRP_MN_START_DEVICE CAN be called for a device that is already "started")
- Check the final status of the IRP_MN_START_DEVICE request sent after resource rebalancing and send IRP_MN_REMOVE_DEVICE if it fails

svn path=/trunk/; revision=52003
This commit is contained in:
Cameron Gutman 2011-05-30 04:15:27 +00:00
parent 9abb0c1c3b
commit 6c70b6dcd9
2 changed files with 45 additions and 32 deletions

View file

@ -160,12 +160,21 @@ IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
NTSTATUS Status;
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_REMOVE_DEVICE;
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy);
IopNotifyPlugPlayNotification(DeviceObject,
EventCategoryTargetDeviceChange,
&GUID_TARGET_DEVICE_QUERY_REMOVE,
NULL,
NULL);
return Status;
}
NTSTATUS
@ -195,6 +204,12 @@ IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
/* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
IopNotifyPlugPlayNotification(DeviceObject,
EventCategoryTargetDeviceChange,
&GUID_TARGET_DEVICE_REMOVE_COMPLETE,
NULL,
NULL);
}
VOID
@ -239,9 +254,6 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
DeviceNode->ResourceListTranslated;
}
/* I don't think we set this flag yet */
ASSERT(!(DeviceNode->Flags & DNF_STOPPED));
/* Do the call */
Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy);
if (!NT_SUCCESS(Status))
@ -258,6 +270,7 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
/* Otherwise, mark us as started */
DeviceNode->Flags |= DNF_STARTED;
DeviceNode->Flags &= ~DNF_STOPPED;
/* We now need enumeration */
DeviceNode->Flags |= DNF_NEED_ENUMERATION_ONLY;
@ -276,9 +289,6 @@ IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode)
ASSERT((DeviceNode->Flags & (DNF_RESOURCE_ASSIGNED |
DNF_RESOURCE_REPORTED |
DNF_NO_RESOURCE_REQUIRED)));
ASSERT((!(DeviceNode->Flags & (DNF_HAS_PROBLEM |
DNF_STARTED |
DNF_START_REQUEST_PENDING))));
/* Get the device object */
DeviceObject = DeviceNode->PhysicalDeviceObject;
@ -328,12 +338,6 @@ IopStartDevice(
UNICODE_STRING KeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
if (((DeviceNode->Flags & DNF_STARTED) && !(DeviceNode->Flags & DNF_HAS_PROBLEM)) ||
(DeviceNode->Flags & DNF_START_REQUEST_PENDING))
{
return STATUS_SUCCESS;
}
Status = IopAssignDeviceResources(DeviceNode);
if (!NT_SUCCESS(Status))
goto ByeBye;
@ -3623,6 +3627,9 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
if (NT_SUCCESS(IopQueryStopDevice(PhysicalDeviceObject)))
{
IopSendStopDevice(PhysicalDeviceObject);
DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
DeviceNode->Flags |= DNF_STOPPED;
}
}
@ -3665,7 +3672,15 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
}
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
IopStartDevice(DeviceNode);
if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
{
DPRINT1("Restart after resource rebalance failed\n");
DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
DeviceNode->Flags |= DNF_START_FAILED;
IopSendRemoveDevice(PhysicalDeviceObject);
}
}
}

View file

@ -119,7 +119,6 @@ IopNotifyPlugPlayNotification(
NotificationInfos->Version = 1;
NotificationInfos->Size = sizeof(TARGET_DEVICE_REMOVAL_NOTIFICATION);
RtlCopyMemory(&NotificationInfos->Event, Event, sizeof(GUID));
NotificationInfos->FileObject = (PFILE_OBJECT)EventCategoryData1;
}
else
{
@ -177,22 +176,21 @@ IopNotifyPlugPlayNotification(
}
case EventCategoryTargetDeviceChange:
{
if (Event != &GUID_PNP_CUSTOM_NOTIFICATION)
{
if (ChangeEntry->FileObject == (PFILE_OBJECT)EventCategoryData1)
CallCurrentEntry = TRUE;
}
else
{
Status = IoGetRelatedTargetDevice(ChangeEntry->FileObject, &EntryDeviceObject);
if (NT_SUCCESS(Status))
{
if (DeviceObject == EntryDeviceObject)
{
((PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject;
CallCurrentEntry = TRUE;
}
}
Status = IoGetRelatedTargetDevice(ChangeEntry->FileObject, &EntryDeviceObject);
if (NT_SUCCESS(Status))
{
if (DeviceObject == EntryDeviceObject)
{
if (Event == &GUID_PNP_CUSTOM_NOTIFICATION)
{
((PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject;
}
else
{
((PTARGET_DEVICE_REMOVAL_NOTIFICATION)NotificationStructure)->FileObject = ChangeEntry->FileObject;
}
CallCurrentEntry = TRUE;
}
}
}
default: