https://git.reactos.org/?p=reactos.git;a=commitdiff;h=934484ea3e18f10779dc02afde5a019a5529f5d9

commit 934484ea3e18f10779dc02afde5a019a5529f5d9
Author:     Thomas Faber <thomas.fa...@reactos.org>
AuthorDate: Sun May 5 07:26:57 2019 +0200
Commit:     Thomas Faber <thomas.fa...@reactos.org>
CommitDate: Thu Sep 26 10:26:10 2019 +0200

    [NTOS:PNP] When traversing the device tree, keep a reference to the current 
device. CORE-15874
---
 ntoskrnl/io/pnpmgr/pnpmgr.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c
index f2048782af0..56b3561fefe 100644
--- a/ntoskrnl/io/pnpmgr/pnpmgr.c
+++ b/ntoskrnl/io/pnpmgr/pnpmgr.c
@@ -1518,33 +1518,50 @@ IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT 
Context)
 {
     PDEVICE_NODE ParentDeviceNode;
     PDEVICE_NODE ChildDeviceNode;
+    PDEVICE_NODE NextDeviceNode;
     NTSTATUS Status;
 
     /* Copy context data so we don't overwrite it in subsequent calls to this 
function */
     ParentDeviceNode = Context->DeviceNode;
 
+    /* HACK: Keep a reference to the PDO so we can keep traversing the tree
+     * if the device is deleted. In a perfect world, children would have to be
+     * deleted before their parents, and we'd restart the traversal after
+     * deleting a device node. */
+    ObReferenceObject(ParentDeviceNode->PhysicalDeviceObject);
+
     /* Call the action routine */
     Status = (Context->Action)(ParentDeviceNode, Context->Context);
     if (!NT_SUCCESS(Status))
     {
+        ObDereferenceObject(ParentDeviceNode->PhysicalDeviceObject);
         return Status;
     }
 
     /* Traversal of all children nodes */
     for (ChildDeviceNode = ParentDeviceNode->Child;
          ChildDeviceNode != NULL;
-         ChildDeviceNode = ChildDeviceNode->Sibling)
+         ChildDeviceNode = NextDeviceNode)
     {
+        /* HACK: We need this reference to ensure we can get Sibling below. */
+        ObReferenceObject(ChildDeviceNode->PhysicalDeviceObject);
+
         /* Pass the current device node to the action routine */
         Context->DeviceNode = ChildDeviceNode;
 
         Status = IopTraverseDeviceTreeNode(Context);
         if (!NT_SUCCESS(Status))
         {
+            ObDereferenceObject(ChildDeviceNode->PhysicalDeviceObject);
+            ObDereferenceObject(ParentDeviceNode->PhysicalDeviceObject);
             return Status;
         }
+
+        NextDeviceNode = ChildDeviceNode->Sibling;
+        ObDereferenceObject(ChildDeviceNode->PhysicalDeviceObject);
     }
 
+    ObDereferenceObject(ParentDeviceNode->PhysicalDeviceObject);
     return Status;
 }
 

Reply via email to