while (ListEntry != &Fdo->List) {
PLIST_ENTRY Next = ListEntry->Flink;
PXENBUS_DX Dx = CONTAINING_RECORD(ListEntry, XENBUS_DX, ListEntry);
- PCHAR Name = Dx->Name;
PXENBUS_PDO Pdo = Dx->Pdo;
- BOOLEAN Missing;
- Name = PdoGetName(Pdo);
- Missing = TRUE;
+ if (!PdoIsMissing(Pdo) && PdoGetDevicePnpState(Pdo) != Deleted) {
+ PCHAR Name;
+ BOOLEAN Missing;
- // If the PDO already exists ans its name is in the class list then
- // we don't want to remove it.
- for (Index = 0; Classes[Index].Buffer != NULL; Index++) {
- PANSI_STRING Class = &Classes[Index];
+ Name = PdoGetName(Pdo);
+ Missing = TRUE;
- if (Class->Length == 0)
- continue;
+ // If the PDO already exists and its name is in the class list
+ // then we don't want to remove it.
+ for (Index = 0; Classes[Index].Buffer != NULL; Index++) {
+ PANSI_STRING Class = &Classes[Index];
- if (strcmp(Name, Class->Buffer) == 0) {
- Missing = FALSE;
- Class->Length = 0; // avoid duplication
- break;
+ if (Class->Length == 0)
+ continue;
+
+ if (strcmp(Name, Class->Buffer) == 0) {
+ Missing = FALSE;
+ Class->Length = 0; // avoid duplication
+ break;
+ }
}
- }
- if (Missing &&
- !PdoIsMissing(Pdo) &&
- PdoGetDevicePnpState(Pdo) != Deleted) {
- PdoSetMissing(Pdo, "device disappeared");
-
- // If the PDO has not yet been enumerated then we can go ahead
- // and mark it as deleted, otherwise we need to notify PnP manager and
- // wait for the REMOVE_DEVICE IRP.
- if (PdoGetDevicePnpState(Pdo) == Present) {
- PdoSetDevicePnpState(Pdo, Deleted);
- PdoDestroy(Pdo);
- } else {
- NeedInvalidate = TRUE;
+ if (Missing) {
+ PdoSetMissing(Pdo, "device disappeared");
+
+ // If the PDO has not yet been enumerated then we can
+ // go ahead and mark it as deleted, otherwise we need
+ // to notify PnP manager and wait for the REMOVE_DEVICE
+ // IRP.
+ if (PdoGetDevicePnpState(Pdo) == Present) {
+ PdoSetDevicePnpState(Pdo, Deleted);
+ PdoDestroy(Pdo);
+ } else {
+ NeedInvalidate = TRUE;
+ }
}
}
ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
- if (PdoGetDevicePnpState(Pdo) == Deleted &&
- !PdoIsMissing(Pdo))
- PdoSetMissing(Pdo, "surprise remove");
-
if (PdoIsMissing(Pdo))
continue;
__FdoAcquireMutex(Fdo);
- for (ListEntry = Fdo->List.Flink;
- ListEntry != &Fdo->List;
- ListEntry = ListEntry->Flink) {
+ ListEntry = Fdo->List.Flink;
+ while (ListEntry != &Fdo->List) {
PXENBUS_DX Dx = CONTAINING_RECORD(ListEntry, XENBUS_DX, ListEntry);
PXENBUS_PDO Pdo = Dx->Pdo;
+ PLIST_ENTRY Next = ListEntry->Flink;
ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
if (PdoGetDevicePnpState(Pdo) == Deleted &&
PdoIsMissing(Pdo))
PdoDestroy(Pdo);
+
+ ListEntry = Next;
}
__FdoReleaseMutex(Fdo);
return Dx->DevicePnpState;
}
+static FORCEINLINE DEVICE_PNP_STATE
+__FdoGetPreviousDevicePnpState(
+ IN PXENFILT_FDO Fdo
+ )
+{
+ PXENFILT_DX Dx = Fdo->Dx;
+
+ return Dx->PreviousDevicePnpState;
+}
+
static FORCEINLINE VOID
__FdoSetDevicePowerState(
IN PXENFILT_FDO Fdo,
PXENFILT_DX Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, ListEntry);
PXENFILT_PDO Pdo = Dx->Pdo;
- for (Index = 0; Index < Count; Index++) {
- if (PdoGetPhysicalDeviceObject(Pdo) == PhysicalDeviceObject[Index]) {
- PhysicalDeviceObject[Index] = NULL; // avoid duplication
- break;
+ if (!PdoIsMissing(Pdo) && PdoGetDevicePnpState(Pdo) != Deleted) {
+ BOOLEAN Missing;
+
+ Missing = TRUE;
+
+ for (Index = 0; Index < Count; Index++) {
+ if (PdoGetPhysicalDeviceObject(Pdo) == PhysicalDeviceObject[Index]) {
+ Missing = FALSE;
+#pragma prefast(suppress:6387) // PhysicalDeviceObject[Index] could be NULL
+ ObDereferenceObject(PhysicalDeviceObject[Index]);
+ PhysicalDeviceObject[Index] = NULL; // avoid duplication
+ break;
+ }
+ }
+
+ if (Missing) {
+ PdoSetMissing(Pdo, "device disappeared");
+
+ // If the PDO has not yet been enumerated then we can
+ // go ahead and mark it as deleted, otherwise we need
+ // to notify PnP manager and wait for the REMOVE_DEVICE
+ // IRP.
+ if (PdoGetDevicePnpState(Pdo) == Present) {
+ PdoSetDevicePnpState(Pdo, Deleted);
+ PdoDestroy(Pdo);
+ }
}
}
// Walk the list and create PDO filters for any new devices
for (Index = 0; Index < Count; Index++) {
#pragma warning(suppress:6385) // Reading invalid data from 'PhysicalDeviceObject'
- if (PhysicalDeviceObject[Index] != NULL)
+ if (PhysicalDeviceObject[Index] != NULL) {
(VOID) FdoAddDevice(Fdo, PhysicalDeviceObject[Index]);
+ ObDereferenceObject(PhysicalDeviceObject[Index]);
+ }
}
__FdoSetEnumerated(Fdo);
IN PIRP Irp
)
{
- POWER_STATE PowerState;
NTSTATUS status;
status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
goto fail1;
- PowerState.DeviceState = PowerDeviceD3;
- PoSetPowerState(Fdo->Dx->DeviceObject,
- DevicePowerState,
- PowerState);
+ if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) {
+ POWER_STATE PowerState;
- __FdoSetDevicePowerState(Fdo, PowerDeviceD3);
+ PowerState.DeviceState = PowerDeviceD3;
+ PoSetPowerState(Fdo->Dx->DeviceObject,
+ DevicePowerState,
+ PowerState);
+
+ __FdoSetDevicePowerState(Fdo, PowerDeviceD3);
+ }
__FdoSetDevicePnpState(Fdo, Stopped);
Irp->IoStatus.Status = STATUS_SUCCESS;
IN PIRP Irp
)
{
- POWER_STATE PowerState;
+ PLIST_ENTRY ListEntry;
NTSTATUS status;
status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
goto fail1;
- PowerState.DeviceState = PowerDeviceD3;
- PoSetPowerState(Fdo->Dx->DeviceObject,
- DevicePowerState,
- PowerState);
+ if (__FdoGetPreviousDevicePnpState(Fdo) != Started)
+ goto done;
+
+ __FdoAcquireMutex(Fdo);
+
+ ListEntry = Fdo->List.Flink;
+ while (ListEntry != &Fdo->List) {
+ PLIST_ENTRY Flink = ListEntry->Flink;
+ PXENFILT_DX Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, ListEntry);
+ PXENFILT_PDO Pdo = Dx->Pdo;
+
+ ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
+
+ if (!PdoIsMissing(Pdo))
+ PdoSetMissing(Pdo, "FDO removed");
- __FdoSetDevicePowerState(Fdo, PowerDeviceD3);
+ PdoSetDevicePnpState(Pdo, Deleted);
+ PdoDestroy(Pdo);
+ ListEntry = Flink;
+ }
+
+ __FdoReleaseMutex(Fdo);
+
+ if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) {
+ POWER_STATE PowerState;
+
+ PowerState.DeviceState = PowerDeviceD3;
+ PoSetPowerState(Fdo->Dx->DeviceObject,
+ DevicePowerState,
+ PowerState);
+
+ __FdoSetDevicePowerState(Fdo, PowerDeviceD3);
+ }
+
+done:
__FdoSetDevicePnpState(Fdo, Deleted);
IoReleaseRemoveLockAndWait(&Fdo->Dx->RemoveLock, Irp);
KEVENT Event;
PIO_STACK_LOCATION StackLocation;
ULONG Size;
- PDEVICE_RELATIONS LowerRelations;
PDEVICE_RELATIONS Relations;
+ PLIST_ENTRY ListEntry;
XENFILT_FILTER_STATE State;
ULONG Count;
NTSTATUS status;
if (StackLocation->Parameters.QueryDeviceRelations.Type != BusRelations)
goto done;
- LowerRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
-
__FdoAcquireMutex(Fdo);
- if (LowerRelations->Count != 0)
- FdoEnumerate(Fdo, LowerRelations);
+ Relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information;
+
+ if (Relations->Count != 0)
+ FdoEnumerate(Fdo, Relations);
+
+ ExFreePool(Relations);
State = DriverGetFilterState();
+ Count = 0;
- Count = (State == XENFILT_FILTER_DISABLED) ? LowerRelations->Count : 0;
+ if (State == XENFILT_FILTER_DISABLED) {
+ for (ListEntry = Fdo->List.Flink;
+ ListEntry != &Fdo->List;
+ ListEntry = ListEntry->Flink)
+ Count++;
+ }
Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
(sizeof (PDEVICE_OBJECT) * __max(Count, 1));
if (State == XENFILT_FILTER_DISABLED) {
PLIST_ENTRY ListEntry;
- for (ListEntry = Fdo->List.Flink;
- ListEntry != &Fdo->List;
- ListEntry = ListEntry->Flink) {
+ ListEntry = Fdo->List.Flink;
+ while (ListEntry != &Fdo->List) {
PXENFILT_DX Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, ListEntry);
PXENFILT_PDO Pdo = Dx->Pdo;
+ PLIST_ENTRY Next = ListEntry->Flink;
ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
+ if (PdoIsMissing(Pdo)) {
+ if (PdoGetDevicePnpState(Pdo) == Deleted)
+ PdoDestroy(Pdo);
+
+ continue;
+ }
+
if (PdoGetDevicePnpState(Pdo) == Present)
PdoSetDevicePnpState(Pdo, Enumerated);
+
+ ObReferenceObject(PdoGetPhysicalDeviceObject(Pdo));
+ Relations->Objects[Relations->Count++] = PdoGetPhysicalDeviceObject(Pdo);
+
+ ListEntry = Next;
}
- RtlCopyMemory(Relations, LowerRelations, Size);
+ ASSERT3U(Relations->Count, <=, Count);
Trace("%s: %d PDO(s)\n",
__FdoGetName(Fdo),
Relations->Count);
} else {
- ULONG Index;
-
Trace("%s: FILTERED\n",
__FdoGetName(Fdo));
- for (Index = 0; Index < LowerRelations->Count; Index++)
- ObDereferenceObject(LowerRelations->Objects[Index]);
-
IoInvalidateDeviceRelations(__FdoGetPhysicalDeviceObject(Fdo),
BusRelations);
}
__FdoReleaseMutex(Fdo);
- ExFreePool(LowerRelations);
-
Irp->IoStatus.Information = (ULONG_PTR)Relations;
status = STATUS_SUCCESS;
return status;
fail3:
- Error("fail3\n");
+ __FdoReleaseMutex(Fdo);
fail2:
- Error("fail2\n");
-
IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp);
fail1:
- Error("fail1 (%08x)\n", status);
-
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
PIRP DevicePowerIrp;
PXENFILT_FDO Fdo;
+ BOOLEAN Missing;
+ const CHAR *Reason;
XENFILT_EMULATED_OBJECT_TYPE Type;
PXENFILT_EMULATED_OBJECT EmulatedObject;
return Pdo->PhysicalDeviceObject;
}
+static FORCEINLINE VOID
+__PdoSetMissing(
+ IN PXENFILT_PDO Pdo,
+ IN const CHAR *Reason
+ )
+{
+ Pdo->Reason = Reason;
+ Pdo->Missing = TRUE;
+}
+
+VOID
+PdoSetMissing(
+ IN PXENFILT_PDO Pdo,
+ IN const CHAR *Reason
+ )
+{
+ __PdoSetMissing(Pdo, Reason);
+}
+
+static FORCEINLINE BOOLEAN
+__PdoIsMissing(
+ IN PXENFILT_PDO Pdo
+ )
+{
+ return Pdo->Missing;
+}
+
+BOOLEAN
+PdoIsMissing(
+ IN PXENFILT_PDO Pdo
+ )
+{
+ return __PdoIsMissing(Pdo);
+}
+
static FORCEINLINE PDEVICE_OBJECT
__PdoGetDeviceObject(
IN PXENFILT_PDO Pdo
{
PXENFILT_FDO Fdo = __PdoGetFdo(Pdo);
POWER_STATE PowerState;
+ BOOLEAN NeedInvalidate;
NTSTATUS status;
status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp);
__PdoSetDevicePowerState(Pdo, PowerDeviceD3);
done:
+ status = PdoForwardIrpSynchronously(Pdo, Irp);
+
FdoAcquireMutex(Fdo);
- __PdoSetDevicePnpState(Pdo, Deleted);
- FdoReleaseMutex(Fdo);
- IoReleaseRemoveLockAndWait(&Pdo->Dx->RemoveLock, Irp);
+ NeedInvalidate = FALSE;
- status = PdoForwardIrpSynchronously(Pdo, Irp);
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ if (__PdoIsMissing(Pdo)) {
+ DEVICE_PNP_STATE State = __PdoGetDevicePnpState(Pdo);
+
+ __PdoSetDevicePnpState(Pdo, Deleted);
+ IoReleaseRemoveLockAndWait(&Pdo->Dx->RemoveLock, Irp);
+
+ if (State == SurpriseRemovePending)
+ PdoDestroy(Pdo);
+ else
+ NeedInvalidate = TRUE;
+ } else {
+ __PdoSetDevicePnpState(Pdo, Enumerated);
+ IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp);
+ }
- FdoAcquireMutex(Fdo);
- PdoDestroy(Pdo);
FdoReleaseMutex(Fdo);
- IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo),
- BusRelations);
+ if (NeedInvalidate)
+ IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo),
+ BusRelations);
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
PXENFILT_FDO Fdo = __PdoGetFdo(Pdo);
NTSTATUS status;
+ FdoAcquireMutex(Fdo);
+ __PdoSetMissing(Pdo, "Ejected");
__PdoSetDevicePnpState(Pdo, Deleted);
+ FdoReleaseMutex(Fdo);
status = PdoForwardIrpSynchronously(Pdo, Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);
+ ASSERT(__PdoIsMissing(Pdo));
+ Pdo->Missing = FALSE;
+
FdoRemovePhysicalDeviceObject(Fdo, Pdo);
Dx->Pdo = NULL;
- Info("%p (%s)\n",
+ Info("%p (%s) (%s)\n",
FilterDeviceObject,
- __PdoGetName(Pdo));
+ __PdoGetName(Pdo),
+ Pdo->Reason);
+ Pdo->Reason = NULL;
RtlZeroMemory(Pdo->Name, sizeof (Pdo->Name));