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