[ISAPNP] Rewrite device reporting method

IoCreateDevice() was called too early, when a spinlock was acquired.
Create ISAPNP_LOGICAL_DEVICE structure when a device is detected, and call IoCreateDevice() later, when required.
This commit is contained in:
Hervé Poussineau 2020-03-12 11:53:09 +01:00
parent 58e8be6258
commit 7a98d28d7f
5 changed files with 73 additions and 59 deletions

View file

@ -24,18 +24,16 @@ IsaFdoStartDevice(
UNREFERENCED_PARAMETER(IrpSp);
KeAcquireSpinLock(&FdoExt->Lock, &OldIrql);
Status = IsaHwDetectReadDataPort(FdoExt);
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
if (!NT_SUCCESS(Status))
{
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
return Status;
}
FdoExt->Common.State = dsStarted;
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
return STATUS_SUCCESS;
}
@ -46,6 +44,7 @@ IsaFdoQueryDeviceRelations(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
PISAPNP_PDO_EXTENSION PdoExt;
NTSTATUS Status;
PLIST_ENTRY CurrentEntry;
PISAPNP_LOGICAL_DEVICE IsaDevice;
@ -57,11 +56,11 @@ IsaFdoQueryDeviceRelations(
return Irp->IoStatus.Status;
KeAcquireSpinLock(&FdoExt->Lock, &OldIrql);
Status = IsaHwFillDeviceList(FdoExt);
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
if (!NT_SUCCESS(Status))
{
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
return Status;
}
@ -69,8 +68,7 @@ IsaFdoQueryDeviceRelations(
sizeof(DEVICE_RELATIONS) + sizeof(DEVICE_OBJECT) * (FdoExt->DeviceCount - 1));
if (!DeviceRelations)
{
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_NO_MEMORY;
}
CurrentEntry = FdoExt->DeviceListHead.Flink;
@ -78,17 +76,42 @@ IsaFdoQueryDeviceRelations(
{
IsaDevice = CONTAINING_RECORD(CurrentEntry, ISAPNP_LOGICAL_DEVICE, ListEntry);
DeviceRelations->Objects[i++] = IsaDevice->Common.Self;
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;
}
ObReferenceObject(IsaDevice->Common.Self);
IsaDevice->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
//Device->Pdo->Flags |= DO_POWER_PAGABLE;
PdoExt = (PISAPNP_PDO_EXTENSION)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;
}
DeviceRelations->Objects[i++] = IsaDevice->Pdo;
ObReferenceObject(IsaDevice->Pdo);
CurrentEntry = CurrentEntry->Flink;
}
DeviceRelations->Count = FdoExt->DeviceCount;
KeReleaseSpinLock(&FdoExt->Lock, OldIrql);
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;

View file

@ -463,8 +463,6 @@ ProbeIsaPnpBus(PISAPNP_FDO_EXTENSION FdoExt)
ISAPNP_LOGDEVID LogDevId;
USHORT Csn;
USHORT LogDev;
PDEVICE_OBJECT Pdo;
NTSTATUS Status;
ASSERT(FdoExt->ReadDataPort);
@ -472,26 +470,12 @@ ProbeIsaPnpBus(PISAPNP_FDO_EXTENSION FdoExt)
{
for (LogDev = 0; LogDev <= 0xFF; LogDev++)
{
Status = IoCreateDevice(FdoExt->Common.Self->DriverObject,
sizeof(ISAPNP_LOGICAL_DEVICE),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
return Status;
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
LogDevice = Pdo->DeviceExtension;
LogDevice = ExAllocatePool(NonPagedPool, sizeof(ISAPNP_LOGICAL_DEVICE));
if (!LogDevice)
return STATUS_NO_MEMORY;
RtlZeroMemory(LogDevice, sizeof(ISAPNP_LOGICAL_DEVICE));
LogDevice->Common.Self = Pdo;
LogDevice->Common.IsFdo = FALSE;
LogDevice->Common.State = dsStopped;
LogDevice->CSN = Csn;
LogDevice->LDN = LogDev;
@ -503,7 +487,7 @@ ProbeIsaPnpBus(PISAPNP_FDO_EXTENSION FdoExt)
if (Identifier.VendorId & 0x80)
{
IoDeleteDevice(LogDevice->Common.Self);
ExFreePool(LogDevice);
return STATUS_SUCCESS;
}
@ -525,8 +509,6 @@ ProbeIsaPnpBus(PISAPNP_FDO_EXTENSION FdoExt)
WaitForKey();
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
InsertTailList(&FdoExt->DeviceListHead, &LogDevice->ListEntry);
FdoExt->DeviceCount++;
}

View file

@ -152,6 +152,7 @@ IsaAddDevice(
FdoExt->Common.Self = Fdo;
FdoExt->Common.IsFdo = TRUE;
FdoExt->Common.State = dsStopped;
FdoExt->DriverObject = DriverObject;
FdoExt->Pdo = PhysicalDeviceObject;
FdoExt->Ldo = IoAttachDeviceToDeviceStack(Fdo,
PhysicalDeviceObject);
@ -186,7 +187,7 @@ IsaPnp(
}
else
{
return IsaPdoPnp((PISAPNP_LOGICAL_DEVICE)DevExt,
return IsaPdoPnp((PISAPNP_PDO_EXTENSION)DevExt,
Irp,
IrpSp);
}

View file

@ -15,6 +15,18 @@ typedef enum {
dsStarted
} ISAPNP_DEVICE_STATE;
typedef struct _ISAPNP_LOGICAL_DEVICE {
PDEVICE_OBJECT Pdo;
UCHAR VendorId[3];
USHORT ProdId;
ULONG SerialNumber;
USHORT IoAddr;
UCHAR IrqNo;
UCHAR CSN;
UCHAR LDN;
LIST_ENTRY ListEntry;
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
typedef struct _ISAPNP_COMMON_EXTENSION {
PDEVICE_OBJECT Self;
BOOLEAN IsFdo;
@ -27,21 +39,15 @@ typedef struct _ISAPNP_FDO_EXTENSION {
PDEVICE_OBJECT Pdo;
LIST_ENTRY DeviceListHead;
ULONG DeviceCount;
PDRIVER_OBJECT DriverObject;
PUCHAR ReadDataPort;
KSPIN_LOCK Lock;
} ISAPNP_FDO_EXTENSION, *PISAPNP_FDO_EXTENSION;
typedef struct _ISAPNP_LOGICAL_DEVICE {
typedef struct _ISAPNP_PDO_EXTENSION {
ISAPNP_COMMON_EXTENSION Common;
UCHAR VendorId[3];
USHORT ProdId;
ULONG SerialNumber;
USHORT IoAddr;
UCHAR IrqNo;
UCHAR CSN;
UCHAR LDN;
LIST_ENTRY ListEntry;
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
PISAPNP_LOGICAL_DEVICE IsaPnpDevice;
} ISAPNP_PDO_EXTENSION, *PISAPNP_PDO_EXTENSION;
/* isapnp.c */
@ -71,7 +77,7 @@ IsaFdoPnp(
NTSTATUS
NTAPI
IsaPdoPnp(
IN PISAPNP_LOGICAL_DEVICE LogDev,
IN PISAPNP_PDO_EXTENSION PdoDeviceExtension,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp);

View file

@ -13,7 +13,7 @@
NTSTATUS
NTAPI
IsaPdoQueryDeviceRelations(
IN PISAPNP_LOGICAL_DEVICE LogDev,
IN PISAPNP_PDO_EXTENSION PdoExt,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
@ -27,8 +27,8 @@ IsaPdoQueryDeviceRelations(
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = 1;
DeviceRelations->Objects[0] = LogDev->Common.Self;
ObReferenceObject(LogDev->Common.Self);
DeviceRelations->Objects[0] = PdoExt->Common.Self;
ObReferenceObject(PdoExt->Common.Self);
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
@ -38,11 +38,12 @@ IsaPdoQueryDeviceRelations(
NTSTATUS
NTAPI
IsaPdoQueryCapabilities(
IN PISAPNP_LOGICAL_DEVICE LogDev,
IN PISAPNP_PDO_EXTENSION PdoExt,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
PDEVICE_CAPABILITIES DeviceCapabilities;
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
if (DeviceCapabilities->Version != 1)
@ -57,10 +58,11 @@ IsaPdoQueryCapabilities(
NTSTATUS
NTAPI
IsaPdoQueryId(
IN PISAPNP_LOGICAL_DEVICE LogDev,
IN PISAPNP_PDO_EXTENSION PdoExt,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
PISAPNP_LOGICAL_DEVICE LogDev = PdoExt->IsaPnpDevice;
WCHAR Temp[256];
PWCHAR Buffer, End;
ULONG Length;
@ -140,7 +142,7 @@ IsaPdoQueryId(
NTSTATUS
NTAPI
IsaPdoPnp(
IN PISAPNP_LOGICAL_DEVICE LogDev,
IN PISAPNP_PDO_EXTENSION PdoExt,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
@ -149,25 +151,25 @@ IsaPdoPnp(
switch (IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
Status = IsaHwActivateDevice(LogDev);
Status = IsaHwActivateDevice(PdoExt->IsaPnpDevice);
if (NT_SUCCESS(Status))
LogDev->Common.State = dsStarted;
PdoExt->Common.State = dsStarted;
break;
case IRP_MN_STOP_DEVICE:
Status = IsaHwDeactivateDevice(LogDev);
Status = IsaHwDeactivateDevice(PdoExt->IsaPnpDevice);
if (NT_SUCCESS(Status))
LogDev->Common.State = dsStopped;
PdoExt->Common.State = dsStopped;
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
Status = IsaPdoQueryDeviceRelations(LogDev, Irp, IrpSp);
Status = IsaPdoQueryDeviceRelations(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_CAPABILITIES:
Status = IsaPdoQueryCapabilities(LogDev, Irp, IrpSp);
Status = IsaPdoQueryCapabilities(PdoExt, Irp, IrpSp);
break;
case IRP_MN_QUERY_RESOURCES:
@ -179,7 +181,7 @@ IsaPdoPnp(
break;
case IRP_MN_QUERY_ID:
Status = IsaPdoQueryId(LogDev, Irp, IrpSp);
Status = IsaPdoQueryId(PdoExt, Irp, IrpSp);
break;
default: