[NTOS:PNP] When traversing the device tree, keep a reference to the current device. CORE-15874

This commit is contained in:
Thomas Faber 2019-05-05 07:26:57 +02:00
parent 08110c11d6
commit 934484ea3e
No known key found for this signature in database
GPG key ID: 076E7C3D44720826

View file

@ -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;
}