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

View file

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

View file

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

View file

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

View file

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