[ISAPNP] Allocate the Read Port resources on demand

This will simplify failure paths and reduce memory usage
This commit is contained in:
Dmitry Borisov 2023-01-15 22:41:49 +06:00
parent 266e2e5052
commit 4ba8a8b59b
3 changed files with 50 additions and 56 deletions

View file

@ -1038,9 +1038,8 @@ IsaForwardOrIgnore(
} }
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS PIO_RESOURCE_REQUIREMENTS_LIST
IsaPnpCreateReadPortDORequirements( IsaPnpCreateReadPortDORequirements(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_opt_ ULONG SelectedReadPort) _In_opt_ ULONG SelectedReadPort)
{ {
ULONG ResourceCount, ListSize, i; ULONG ResourceCount, ListSize, i;
@ -1087,7 +1086,7 @@ IsaPnpCreateReadPortDORequirements(
sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1); sizeof(IO_RESOURCE_DESCRIPTOR) * (ResourceCount - 1);
RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); RequirementsList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
if (!RequirementsList) if (!RequirementsList)
return STATUS_NO_MEMORY; return NULL;
RequirementsList->ListSize = ListSize; RequirementsList->ListSize = ListSize;
RequirementsList->AlternativeLists = 1; RequirementsList->AlternativeLists = 1;
@ -1182,15 +1181,12 @@ IsaPnpCreateReadPortDORequirements(
} }
} }
PdoExt->RequirementsList = RequirementsList; return RequirementsList;
return STATUS_SUCCESS;
} }
static
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS PCM_RESOURCE_LIST
IsaPnpCreateReadPortDOResources( IsaPnpCreateReadPortDOResources(VOID)
_In_ PISAPNP_PDO_EXTENSION PdoExt)
{ {
const USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS }; const USHORT Ports[] = { ISAPNP_WRITE_DATA, ISAPNP_ADDRESS };
ULONG ListSize, i; ULONG ListSize, i;
@ -1203,7 +1199,7 @@ IsaPnpCreateReadPortDOResources(
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(Ports) - 1); sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (RTL_NUMBER_OF(Ports) - 1);
ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP); ResourceList = ExAllocatePoolZero(PagedPool, ListSize, TAG_ISAPNP);
if (!ResourceList) if (!ResourceList)
return STATUS_NO_MEMORY; return NULL;
ResourceList->Count = 1; ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = Internal; ResourceList->List[0].InterfaceType = Internal;
@ -1223,9 +1219,7 @@ IsaPnpCreateReadPortDOResources(
Descriptor++; Descriptor++;
} }
PdoExt->ResourceList = ResourceList; return ResourceList;
PdoExt->ResourceListSize = ListSize;
return STATUS_SUCCESS;
} }
static static
@ -1259,23 +1253,8 @@ IsaPnpCreateReadPortDO(
PdoExt->Common.State = dsStopped; PdoExt->Common.State = dsStopped;
PdoExt->FdoExt = FdoExt; PdoExt->FdoExt = FdoExt;
Status = IsaPnpCreateReadPortDORequirements(PdoExt, 0);
if (!NT_SUCCESS(Status))
goto Failure;
Status = IsaPnpCreateReadPortDOResources(PdoExt);
if (!NT_SUCCESS(Status))
goto Failure;
FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING; FdoExt->ReadPortPdo->Flags &= ~DO_DEVICE_INITIALIZING;
return Status;
Failure:
IsaPnpRemoveReadPortDO(FdoExt->ReadPortPdo);
FdoExt->ReadPortPdo = NULL;
return Status; return Status;
} }
@ -1284,18 +1263,10 @@ VOID
IsaPnpRemoveReadPortDO( IsaPnpRemoveReadPortDO(
_In_ PDEVICE_OBJECT Pdo) _In_ PDEVICE_OBJECT Pdo)
{ {
PISAPNP_PDO_EXTENSION ReadPortExt = Pdo->DeviceExtension;
PAGED_CODE(); PAGED_CODE();
DPRINT("Removing Read Port\n"); DPRINT("Removing Read Port\n");
if (ReadPortExt->RequirementsList)
ExFreePoolWithTag(ReadPortExt->RequirementsList, TAG_ISAPNP);
if (ReadPortExt->ResourceList)
ExFreePoolWithTag(ReadPortExt->ResourceList, TAG_ISAPNP);
IoDeleteDevice(Pdo); IoDeleteDevice(Pdo);
} }

View file

@ -176,12 +176,7 @@ typedef struct _ISAPNP_FDO_EXTENSION
typedef struct _ISAPNP_PDO_EXTENSION typedef struct _ISAPNP_PDO_EXTENSION
{ {
ISAPNP_COMMON_EXTENSION Common; ISAPNP_COMMON_EXTENSION Common;
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
PISAPNP_FDO_EXTENSION FdoExt; PISAPNP_FDO_EXTENSION FdoExt;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
ULONG Flags; ULONG Flags;
#define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */ #define ISAPNP_ENUMERATED 0x00000001 /**< @brief Whether the device has been reported to the PnP manager. */
@ -189,6 +184,22 @@ typedef struct _ISAPNP_PDO_EXTENSION
#define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */ #define ISAPNP_READ_PORT_ALLOW_FDO_SCAN 0x00000004 /**< @brief Allows the active FDO to scan the bus. */
#define ISAPNP_READ_PORT_NEED_REBALANCE 0x00000008 /**< @brief The I/O resource requirements have changed. */ #define ISAPNP_READ_PORT_NEED_REBALANCE 0x00000008 /**< @brief The I/O resource requirements have changed. */
union
{
/* Data belonging to logical devices */
struct
{
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
};
ULONG SelectedPort;
};
_Write_guarded_by_(_Global_interlock_) _Write_guarded_by_(_Global_interlock_)
volatile LONG SpecialFiles; volatile LONG SpecialFiles;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION; } ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
@ -315,11 +326,14 @@ FindMemoryDescriptor(
_Out_opt_ PUCHAR WriteOrder); _Out_opt_ PUCHAR WriteOrder);
CODE_SEG("PAGE") CODE_SEG("PAGE")
NTSTATUS PIO_RESOURCE_REQUIREMENTS_LIST
IsaPnpCreateReadPortDORequirements( IsaPnpCreateReadPortDORequirements(
_In_ PISAPNP_PDO_EXTENSION PdoExt,
_In_opt_ ULONG SelectedReadPort); _In_opt_ ULONG SelectedReadPort);
CODE_SEG("PAGE")
PCM_RESOURCE_LIST
IsaPnpCreateReadPortDOResources(VOID);
CODE_SEG("PAGE") CODE_SEG("PAGE")
VOID VOID
IsaPnpRemoveReadPortDO( IsaPnpRemoveReadPortDO(

View file

@ -478,8 +478,17 @@ IsaPdoQueryResources(
PAGED_CODE(); PAGED_CODE();
if (PdoExt->Common.Signature == IsaPnpLogicalDevice && if (PdoExt->Common.Signature == IsaPnpReadDataPort)
!(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES)) {
ResourceList = IsaPnpCreateReadPortDOResources();
if (!ResourceList)
return STATUS_NO_MEMORY;
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
return STATUS_SUCCESS;
}
if (!(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES))
{ {
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -513,6 +522,16 @@ IsaPdoQueryResourceRequirements(
PAGED_CODE(); PAGED_CODE();
if (PdoExt->Common.Signature == IsaPnpReadDataPort)
{
RequirementsList = IsaPnpCreateReadPortDORequirements(PdoExt->SelectedPort);
if (!RequirementsList)
return STATUS_NO_MEMORY;
Irp->IoStatus.Information = (ULONG_PTR)RequirementsList;
return STATUS_SUCCESS;
}
if (!PdoExt->RequirementsList) if (!PdoExt->RequirementsList)
return Irp->IoStatus.Status; return Irp->IoStatus.Status;
@ -593,19 +612,9 @@ IsaPdoStartReadPort(
ASSERT(SelectedPort != 0); ASSERT(SelectedPort != 0);
if (PdoExt->RequirementsList)
{
ExFreePoolWithTag(PdoExt->RequirementsList, TAG_ISAPNP);
PdoExt->RequirementsList = NULL;
}
/* Discard the Read Ports at conflicting locations */ /* Discard the Read Ports at conflicting locations */
Status = IsaPnpCreateReadPortDORequirements(PdoExt, SelectedPort); PdoExt->SelectedPort = SelectedPort;
if (!NT_SUCCESS(Status))
return Status;
PdoExt->Flags |= ISAPNP_READ_PORT_NEED_REBALANCE; PdoExt->Flags |= ISAPNP_READ_PORT_NEED_REBALANCE;
IoInvalidateDeviceState(PdoExt->Common.Self); IoInvalidateDeviceState(PdoExt->Common.Self);
return STATUS_SUCCESS; return STATUS_SUCCESS;