Skip to content

Commit

Permalink
Track device PNP states
Browse files Browse the repository at this point in the history
  • Loading branch information
ThFabba committed May 3, 2017
1 parent 7bc0c87 commit 5743310
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 11 deletions.
52 changes: 48 additions & 4 deletions fdo.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ VhciFdoStartDeviceCompletion(
FdoExtension = DeviceObject->DeviceExtension;
NT_ASSERT(FdoExtension->Common.Signature == VHCI_FDO_SIGNATURE);
NT_ASSERT(FdoExtension->Common.DeviceObject == DeviceObject);
NT_ASSERT(FdoExtension->Common.Deleted == FALSE);
NT_ASSERT(FdoExtension->Common.PnpState == PnpStateNotStarted);
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateInvalid);
IoStack = IoGetCurrentIrpStackLocation(Irp);
NT_ASSERT(IoStack->MajorFunction == IRP_MJ_PNP);
NT_ASSERT(IoStack->MinorFunction == IRP_MN_START_DEVICE);
Expand All @@ -94,7 +95,11 @@ VhciFdoStartDeviceCompletion(
IoMarkIrpPending(Irp);
}

/* Start device */
if (NT_SUCCESS(Irp->IoStatus.Status))
{
/* Start device */
FdoExtension->Common.PnpState = PnpStateStarted;
}

return STATUS_CONTINUE_COMPLETION;
}
Expand All @@ -111,7 +116,8 @@ VhciFdoRemoveDevice(

if (FdoExtension->PdoExtension)
{
NT_ASSERT(FdoExtension->PdoExtension->Common.Deleted == FALSE);
NT_ASSERT(FdoExtension->PdoExtension->Common.PnpState == PnpStateRemovePending ||
FdoExtension->PdoExtension->Common.PnpState == PnpStateNotStarted);
VhciPdoRemoveDevice(FdoExtension->PdoExtension);
}
}
Expand Down Expand Up @@ -223,7 +229,11 @@ VhciFdoPnp(
case IRP_MN_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_REMOVE_DEVICE\n", DeviceObject);
FdoExtension->Common.Deleted = TRUE;
NT_ASSERT(FdoExtension->Common.PnpState == PnpStateRemovePending);
FdoExtension->Common.PnpState = PnpStateDeleted;
#if DBG
FdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
Status = VhciForwardIrpAndForget(FdoExtension, Irp);
IoDetachDevice(FdoExtension->LowerDevice);
VhciFdoRemoveDevice(FdoExtension);
Expand Down Expand Up @@ -253,31 +263,65 @@ VhciFdoPnp(
case IRP_MN_QUERY_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_QUERY_STOP_DEVICE\n", DeviceObject);
NT_ASSERT(FdoExtension->Common.PnpState == PnpStateStarted);
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateInvalid);
FdoExtension->Common.PreviousPnpState = FdoExtension->Common.PnpState;
FdoExtension->Common.PnpState = PnpStateStopPending;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_CANCEL_STOP_DEVICE\n", DeviceObject);
if (FdoExtension->Common.PnpState == PnpStateStopPending)
{
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateStarted);
FdoExtension->Common.PnpState = FdoExtension->Common.PreviousPnpState;
#if DBG
FdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
}
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_STOP_DEVICE\n", DeviceObject);
FdoExtension->Common.PnpState = PnpStateNotStarted;
#if DBG
FdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_QUERY_REMOVE_DEVICE\n", DeviceObject);
NT_ASSERT(FdoExtension->Common.PnpState == PnpStateStarted ||
FdoExtension->Common.PnpState == PnpStateNotStarted);
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateInvalid);
FdoExtension->Common.PreviousPnpState = FdoExtension->Common.PnpState;
FdoExtension->Common.PnpState = PnpStateRemovePending;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_CANCEL_REMOVE_DEVICE\n", DeviceObject);
if (FdoExtension->Common.PnpState == PnpStateStopPending)
{
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateStarted ||
FdoExtension->Common.PreviousPnpState == PnpStateNotStarted);
FdoExtension->Common.PnpState = FdoExtension->Common.PreviousPnpState;
#if DBG
FdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
}
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Fdo %p: IRP_MJ_PNP/IRP_MN_SURPRISE_REMOVAL\n", DeviceObject);
NT_ASSERT(FdoExtension->Common.PnpState == PnpStateStarted ||
FdoExtension->Common.PnpState == PnpStateNotStarted);
NT_ASSERT(FdoExtension->Common.PreviousPnpState == PnpStateInvalid);
FdoExtension->Common.PnpState = PnpStateRemovePending;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
Expand Down
58 changes: 54 additions & 4 deletions pdo.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,8 @@ VhciPdoRemoveDevice(
PAGED_CODE();

NT_ASSERT(PdoExtension->Common.Signature == VHCI_PDO_SIGNATURE);

NT_ASSERT(PdoExtension->Common.Deleted == FALSE);
PdoExtension->Common.PnpState = PnpStateDeleted;
DeviceObject = PdoExtension->Common.DeviceObject;
PdoExtension->Common.Deleted = TRUE;
PdoExtension->FdoExtension->PdoExtension = NULL;
IoDeleteDevice(DeviceObject);
}
Expand Down Expand Up @@ -299,6 +297,12 @@ VhciPdoQueryInterface(

PAGED_CODE();

if (PdoExtension->Common.PnpState != PnpStateStarted)
{
DPRINT1("Pdo %p: VhciPdoQueryInterface -- device not started\n", PdoExtension->Common.DeviceObject);
return STATUS_DEVICE_NOT_READY;
}

if (IsEqualGUIDAligned(InterfaceType, &USB_BUS_INTERFACE_HUB_GUID))
{
DPRINT("Pdo %p: QI/USB_BUS_INTERFACE_HUB_GUID\n", PdoExtension->Common.DeviceObject);
Expand Down Expand Up @@ -443,11 +447,13 @@ VhciPdoPnp(
case IRP_MN_START_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_START_DEVICE\n", DeviceObject);
PdoExtension->Common.PnpState = PnpStateStarted;
Status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_REMOVE_DEVICE\n", DeviceObject);
NT_ASSERT(PdoExtension->Common.PnpState == PnpStateRemovePending);
if (PdoExtension->Present == FALSE)
{
VhciPdoRemoveDevice(PdoExtension);
Expand Down Expand Up @@ -532,37 +538,72 @@ VhciPdoPnp(
case IRP_MN_QUERY_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_QUERY_STOP_DEVICE\n", DeviceObject);
NT_ASSERT(PdoExtension->Common.PnpState == PnpStateStarted);
NT_ASSERT(PdoExtension->Common.PreviousPnpState == PnpStateInvalid);
PdoExtension->Common.PreviousPnpState = PdoExtension->Common.PnpState;
PdoExtension->Common.PnpState = PnpStateStopPending;
Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_CANCEL_STOP_DEVICE\n", DeviceObject);
if (PdoExtension->Common.PnpState == PnpStateStopPending)
{
NT_ASSERT(PdoExtension->Common.PreviousPnpState == PnpStateStarted);
PdoExtension->Common.PnpState = PdoExtension->Common.PreviousPnpState;
#if DBG
PdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
}
Status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_STOP_DEVICE\n", DeviceObject);
PdoExtension->Common.PnpState = PnpStateNotStarted;
#if DBG
PdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
Status = STATUS_SUCCESS;
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_QUERY_REMOVE_DEVICE\n", DeviceObject);
NT_ASSERT(PdoExtension->Common.PnpState == PnpStateStarted ||
PdoExtension->Common.PnpState == PnpStateNotStarted);
NT_ASSERT(PdoExtension->Common.PreviousPnpState == PnpStateInvalid);

if (PdoExtension->InterfaceRefCount != 0)
{
DPRINT1("Pdo %p: IRP_MJ_PNP/IRP_MN_QUERY_REMOVE_DEVICE -- %ld interface references outstanding, failling\n",
DeviceObject, PdoExtension->InterfaceRefCount);
return STATUS_DEVICE_BUSY;
}
PdoExtension->Common.PreviousPnpState = PdoExtension->Common.PnpState;
PdoExtension->Common.PnpState = PnpStateRemovePending;
Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_CANCEL_REMOVE_DEVICE\n", DeviceObject);
if (PdoExtension->Common.PnpState == PnpStateStopPending)
{
NT_ASSERT(PdoExtension->Common.PreviousPnpState == PnpStateStarted ||
PdoExtension->Common.PreviousPnpState == PnpStateNotStarted);
PdoExtension->Common.PnpState = PdoExtension->Common.PreviousPnpState;
#if DBG
PdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif
}
Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
DPRINT("Pdo %p: IRP_MJ_PNP/IRP_MN_SURPRISE_REMOVAL\n", DeviceObject);
NT_ASSERT(PdoExtension->Common.PnpState == PnpStateStarted ||
PdoExtension->Common.PnpState == PnpStateNotStarted);
NT_ASSERT(PdoExtension->Common.PreviousPnpState == PnpStateInvalid);
PdoExtension->Common.PnpState = PnpStateRemovePending;
Status = STATUS_SUCCESS;
break;
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
Expand Down Expand Up @@ -767,6 +808,12 @@ VhciPdoDeviceControl(
DeviceObject = PdoExtension->Common.DeviceObject;
IoStack = IoGetCurrentIrpStackLocation(Irp);

if (PdoExtension->Common.PnpState != PnpStateStarted)
{
DPRINT1("Pdo %p: IRP_MJ_INTERNAL_DEVICE_CONTROL -- device not started\n", DeviceObject);
return STATUS_DEVICE_NOT_READY;
}

switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_INTERNAL_USB_SUBMIT_URB:
Expand Down Expand Up @@ -857,7 +904,10 @@ VhciCreatePdo(
PdoExtension = DeviceObject->DeviceExtension;
PdoExtension->Common.Signature = VHCI_PDO_SIGNATURE;
PdoExtension->Common.DeviceObject = DeviceObject;
PdoExtension->Common.Deleted = FALSE;
PdoExtension->Common.PnpState = PnpStateNotStarted;
#if DBG
PdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif

PdoExtension->FdoExtension = FdoExtension;
PdoExtension->InterfaceRefCount = 0;
Expand Down
7 changes: 5 additions & 2 deletions usbvhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ VhciDispatchPnp(
CommonExtension = DeviceObject->DeviceExtension;
NT_ASSERT(CommonExtension->DeviceObject == DeviceObject);

if (CommonExtension->Deleted)
if (CommonExtension->PnpState == PnpStateDeleted)
{
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
Expand Down Expand Up @@ -110,7 +110,10 @@ VhciAddDevice(
FdoExtension = DeviceObject->DeviceExtension;
FdoExtension->Common.Signature = VHCI_FDO_SIGNATURE;
FdoExtension->Common.DeviceObject = DeviceObject;
FdoExtension->Common.Deleted = FALSE;
FdoExtension->Common.PnpState = PnpStateNotStarted;
#if DBG
FdoExtension->Common.PreviousPnpState = PnpStateInvalid;
#endif

FdoExtension->PdoExtension = NULL;

Expand Down
13 changes: 12 additions & 1 deletion usbvhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,22 @@
#define VHCI_PNP_TAG 'nPhV'

/* Types */
typedef enum _VHCI_PNP_DEVICE_STATE
{
PnpStateNotStarted,
PnpStateStarted,
PnpStateStopPending,
PnpStateRemovePending,
PnpStateDeleted,
PnpStateInvalid = -1
} VHCI_PNP_DEVICE_STATE;

typedef struct _VHCI_COMMON_DEVICE_EXTENSION
{
ULONG Signature;
PDEVICE_OBJECT DeviceObject;
BOOLEAN Deleted;
VHCI_PNP_DEVICE_STATE PnpState;
VHCI_PNP_DEVICE_STATE PreviousPnpState;
} VHCI_COMMON_DEVICE_EXTENSION, *PVHCI_COMMON_DEVICE_EXTENSION;

typedef struct _VHCI_FDO_DEVICE_EXTENSION
Expand Down

0 comments on commit 5743310

Please sign in to comment.