Author: cgutman
Date: Thu May 26 22:49:27 2011
New Revision: 51944

URL: http://svn.reactos.org/svn/reactos?rev=51944&view=rev
Log:
[NTOSKRNL]
- Implement IoInvalidateDeviceState

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.c?rev=51944&r1=51943&r2=51944&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c [iso-8859-1] Thu May 26 22:49:27 
2011
@@ -168,6 +168,20 @@
     return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
 }
 
+NTSTATUS
+NTAPI
+IopQueryStopDevice(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_QUERY_STOP_DEVICE;
+    
+    return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
+}
+
 VOID
 NTAPI
 IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
@@ -180,6 +194,21 @@
     Stack.MinorFunction = IRP_MN_REMOVE_DEVICE;
 
     /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
+    IopSynchronousCall(DeviceObject, &Stack, &Dummy);
+}
+
+VOID
+NTAPI
+IopSendStopDevice(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_STOP_DEVICE;
+    
+    /* Drivers should never fail a IRP_MN_STOP_DEVICE request */
     IopSynchronousCall(DeviceObject, &Stack, &Dummy);
 }
 
@@ -298,12 +327,6 @@
    HANDLE InstanceHandle = INVALID_HANDLE_VALUE, ControlHandle = 
INVALID_HANDLE_VALUE;
    UNICODE_STRING KeyName;
    OBJECT_ATTRIBUTES ObjectAttributes;
-
-   if (DeviceNode->Flags & (DNF_STARTED | DNF_START_REQUEST_PENDING))
-   {
-       /* Nothing to do here */
-       return STATUS_SUCCESS;
-   }
 
    Status = IopAssignDeviceResources(DeviceNode);
    if (!NT_SUCCESS(Status))
@@ -3551,13 +3574,93 @@
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 VOID
 NTAPI
 IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
 {
-    UNIMPLEMENTED;
+    PDEVICE_NODE DeviceNode = IopGetDeviceNode(PhysicalDeviceObject);
+    IO_STACK_LOCATION Stack;
+    ULONG PnPFlags;
+    NTSTATUS Status;
+    IO_STATUS_BLOCK IoStatusBlock;
+    
+    RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
+    Stack.MajorFunction = IRP_MJ_PNP;
+    Stack.MinorFunction = IRP_MN_QUERY_PNP_DEVICE_STATE;
+    
+    Status = IopSynchronousCall(PhysicalDeviceObject, &Stack, 
(PVOID*)&PnPFlags);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", 
Status);
+        return;
+    }
+
+    if ((PnPFlags & PNP_DEVICE_REMOVED) ||
+        ((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & 
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
+    {
+        /* Surprise removal */
+        
+        IopSendSurpriseRemoval(PhysicalDeviceObject);
+        
+        /* Tell the user-mode PnP manager that a device was removed */
+        IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
+                                  &DeviceNode->InstancePath);
+        
+        IopSendRemoveDevice(PhysicalDeviceObject);
+    }
+    else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & 
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
+    {
+        /* Stop for resource rebalance */
+        
+        if (NT_SUCCESS(IopQueryStopDevice(PhysicalDeviceObject)))
+        {
+            IopSendStopDevice(PhysicalDeviceObject);
+        }
+    }
+    
+    /* Resource rebalance */
+    if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
+    {
+        DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
+    
+        Status = IopInitiatePnpIrp(PhysicalDeviceObject,
+                                   &IoStatusBlock,
+                                   IRP_MN_QUERY_RESOURCES,
+                                   NULL);
+        if (NT_SUCCESS(Status) && IoStatusBlock.Information)
+        {
+            DeviceNode->BootResources =
+            (PCM_RESOURCE_LIST)IoStatusBlock.Information;
+            IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
+        }
+        else
+        {
+            DPRINT("IopInitiatePnpIrp() failed (Status %x) or 
IoStatusBlock.Information=NULL\n", Status);
+            DeviceNode->BootResources = NULL;
+        }
+    
+        DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
+    
+        Status = IopInitiatePnpIrp(PhysicalDeviceObject,
+                                   &IoStatusBlock,
+                                   IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
+                                   NULL);
+        if (NT_SUCCESS(Status))
+        {
+            DeviceNode->ResourceRequirements =
+            (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
+        }
+        else
+        {
+            DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
+            DeviceNode->ResourceRequirements = NULL;
+        }
+        
+        /* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by 
IopStartDevice */
+        IopStartDevice(DeviceNode);
+    }
 }
 
 /**


Reply via email to