[0.4.12][NTOS:PNP] Workaround a BSOD with HDAUDIO during boot PR#1560 CORE-15874

Thanks to Thomas Faber, author of the patch.
I depend on external testers here for confirmation of effectiveness.

We think the problem was unhidden by 0.4.12-dev-757-g
789cfd3ddc
and surrounding works.

When traversing the device tree, keep a reference to the current device.
Devices can be deleted during the traversal, so in order to keep
the tree walk intact without use-after-free situations,
this just keeps the PDO around until we no longer need the device node.

It could be argued that this is a hack, however implementing it the "correct way"
(I haven't actually researched how Windows does this) is unlikely to be possible
with our current PNP manager -- so this should keep us going for a while.
This commit is contained in:
Joachim Henze 2019-06-13 01:25:28 +02:00
parent 9513c9bf12
commit 78b5bc9de7

View file

@ -1517,33 +1517,44 @@ 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;
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)
{
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;
}