[ISAPNP] Make Read Data Port PDO unique

This PDO is created only once during start of first FDO.
Other buses will remain in an inactive state until
the first FDO receives a remove request.

CORE-17034
This commit is contained in:
Dmitry Borisov 2021-03-04 18:45:38 +06:00
parent c92bec609b
commit 21514e473f

View file

@ -11,6 +11,8 @@
#define NDEBUG
#include <debug.h>
BOOLEAN ReadPortCreated = FALSE;
static
CODE_SEG("PAGE")
NTSTATUS
@ -299,94 +301,6 @@ IsaPnpCreateLogicalDeviceResources(
return STATUS_SUCCESS;
}
CODE_SEG("PAGE")
NTSTATUS
IsaPnpFillDeviceRelations(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp,
_In_ BOOLEAN IncludeDataPort)
{
PISAPNP_PDO_EXTENSION PdoExt;
NTSTATUS Status = STATUS_SUCCESS;
PLIST_ENTRY CurrentEntry;
PISAPNP_LOGICAL_DEVICE IsaDevice;
PDEVICE_RELATIONS DeviceRelations;
ULONG i = 0;
PAGED_CODE();
DeviceRelations = ExAllocatePool(NonPagedPool,
sizeof(DEVICE_RELATIONS) + sizeof(DEVICE_OBJECT) * FdoExt->DeviceCount);
if (!DeviceRelations)
{
return STATUS_NO_MEMORY;
}
if (IncludeDataPort)
{
DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
ObReferenceObject(FdoExt->ReadPortPdo);
}
CurrentEntry = FdoExt->DeviceListHead.Flink;
while (CurrentEntry != &FdoExt->DeviceListHead)
{
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
if (!IsaDevice->Pdo)
{
Status = IoCreateDevice(FdoExt->DriverObject,
sizeof(ISAPNP_PDO_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&IsaDevice->Pdo);
if (!NT_SUCCESS(Status))
{
break;
}
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
PdoExt = IsaDevice->Pdo->DeviceExtension;
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
PdoExt->Common.IsFdo = FALSE;
PdoExt->Common.Self = IsaDevice->Pdo;
PdoExt->Common.State = dsStopped;
PdoExt->IsaPnpDevice = IsaDevice;
PdoExt->FdoExt = FdoExt;
Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt);
if (NT_SUCCESS(Status))
Status = IsaPnpCreateLogicalDeviceResources(PdoExt);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(IsaDevice->Pdo);
IsaDevice->Pdo = NULL;
break;
}
}
DeviceRelations->Objects[i++] = IsaDevice->Pdo;
ObReferenceObject(IsaDevice->Pdo);
CurrentEntry = CurrentEntry->Flink;
}
DeviceRelations->Count = i;
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return Status;
}
static IO_COMPLETION_ROUTINE ForwardIrpCompletion;
static
@ -603,6 +517,9 @@ IsaPnpCreateReadPortDO(
NTSTATUS Status;
PAGED_CODE();
ASSERT(ReadPortCreated == FALSE);
DPRINT("Creating Read Port\n");
Status = IoCreateDevice(FdoExt->DriverObject,
sizeof(ISAPNP_PDO_EXTENSION),
@ -623,12 +540,133 @@ IsaPnpCreateReadPortDO(
Status = IsaPnpCreateReadPortDORequirements(PdoExt);
if (!NT_SUCCESS(Status))
return Status;
goto Failure;
Status = IsaPnpCreateReadPortDOResources(PdoExt);
if (!NT_SUCCESS(Status))
goto Failure;
FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING;
return Status;
Failure:
if (PdoExt->RequirementsList)
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
if (PdoExt->ResourceList)
ExFreePoolWithTag(PdoExt->ResourceList, TAG_ISAPNP);
IoDeleteDevice(FdoExt->ReadPortPdo);
return Status;
}
CODE_SEG("PAGE")
NTSTATUS
IsaPnpFillDeviceRelations(
_In_ PISAPNP_FDO_EXTENSION FdoExt,
_Inout_ PIRP Irp,
_In_ BOOLEAN IncludeDataPort)
{
NTSTATUS Status = STATUS_SUCCESS;
PLIST_ENTRY CurrentEntry;
PISAPNP_LOGICAL_DEVICE IsaDevice;
PDEVICE_RELATIONS DeviceRelations;
ULONG PdoCount, i = 0;
PAGED_CODE();
/* Try to claim the Read Port for our FDO */
if (!ReadPortCreated)
{
Status = IsaPnpCreateReadPortDO(FdoExt);
if (!NT_SUCCESS(Status))
return Status;
ReadPortCreated = TRUE;
}
/* Inactive ISA bus */
if (!FdoExt->ReadPortPdo)
IncludeDataPort = FALSE;
PdoCount = FdoExt->DeviceCount;
if (IncludeDataPort)
++PdoCount;
DeviceRelations = ExAllocatePoolWithTag(PagedPool,
FIELD_OFFSET(DEVICE_RELATIONS, Objects[PdoCount]),
TAG_ISAPNP);
if (!DeviceRelations)
{
return STATUS_NO_MEMORY;
}
if (IncludeDataPort)
{
DeviceRelations->Objects[i++] = FdoExt->ReadPortPdo;
ObReferenceObject(FdoExt->ReadPortPdo);
}
CurrentEntry = FdoExt->DeviceListHead.Flink;
while (CurrentEntry != &FdoExt->DeviceListHead)
{
PISAPNP_PDO_EXTENSION PdoExt;
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, DeviceLink);
if (!IsaDevice->Pdo)
{
Status = IoCreateDevice(FdoExt->DriverObject,
sizeof(ISAPNP_PDO_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&IsaDevice->Pdo);
if (!NT_SUCCESS(Status))
{
break;
}
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
PdoExt = IsaDevice->Pdo->DeviceExtension;
RtlZeroMemory(PdoExt, sizeof(ISAPNP_PDO_EXTENSION));
PdoExt->Common.IsFdo = FALSE;
PdoExt->Common.Self = IsaDevice->Pdo;
PdoExt->Common.State = dsStopped;
PdoExt->IsaPnpDevice = IsaDevice;
PdoExt->FdoExt = FdoExt;
Status = IsaPnpCreateLogicalDeviceRequirements(PdoExt);
if (NT_SUCCESS(Status))
Status = IsaPnpCreateLogicalDeviceResources(PdoExt);
if (!NT_SUCCESS(Status))
{
IoDeleteDevice(IsaDevice->Pdo);
IsaDevice->Pdo = NULL;
break;
}
}
DeviceRelations->Objects[i++] = IsaDevice->Pdo;
ObReferenceObject(IsaDevice->Pdo);
CurrentEntry = CurrentEntry->Flink;
}
DeviceRelations->Count = i;
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return Status;
}
@ -677,12 +715,7 @@ IsaAddDevice(
InitializeListHead(&FdoExt->DeviceListHead);
KeInitializeEvent(&FdoExt->DeviceSyncEvent, SynchronizationEvent, TRUE);
Status = IsaPnpCreateReadPortDO(FdoExt);
if (!NT_SUCCESS(Status))
return Status;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}