https://git.reactos.org/?p=reactos.git;a=commitdiff;h=934484ea3e18f10779dc0…
commit 934484ea3e18f10779dc02afde5a019a5529f5d9
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Sun May 5 07:26:57 2019 +0200
Commit: Thomas Faber <thomas.faber(a)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;
}