static NTSTATUS
XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp) {
  PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
  PIO_STACK_LOCATION stack;
  PCM_RESOURCE_LIST crl;
  PCM_FULL_RESOURCE_DESCRIPTOR cfrd;
  PCM_PARTIAL_RESOURCE_LIST cprl;
  PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;

  FUNCTION_ENTER();

  /*
  Pass down the xvdd area as a memory resource. This gives xenvbd the data in a known place
  and also satisifies the scsiport requirement for a memory resource
  */
  IoCopyCurrentIrpStackLocationToNext(irp);
  stack = IoGetNextIrpStackLocation(irp);

  crl = ExAllocatePoolWithTag(NonPagedPool,
          FIELD_OFFSET(CM_RESOURCE_LIST, List) +
          FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
          FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
          sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1, XENVBD_POOL_TAG);
  if (!crl) {
    // TODO: Fail this correctly
  }
  crl->Count = 1;
  cfrd = &crl->List[0];
  cfrd->InterfaceType = PNPBus;
  cfrd->BusNumber = 0;
  cprl = &cfrd->PartialResourceList;
  cprl->Version = 1;
  cprl->Revision = 1;
  cprl->Count = 1;
  prd = &cprl->PartialDescriptors[0];
  prd->Type = CmResourceTypeMemory;
  prd->ShareDisposition = CmResourceShareShared;
  prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
  prd->u.Memory.Start.QuadPart = (ULONG_PTR)&xvfd->xvdd;
  prd->u.Memory.Length = sizeof(XENVBD_DEVICE_DATA);
  stack->Parameters.StartDevice.AllocatedResources = crl;
  stack->Parameters.StartDevice.AllocatedResourcesTranslated = crl;

  IoSetCompletionRoutine(irp, XenVbd_IoCompletion_START_DEVICE, crl, TRUE, TRUE, TRUE);

  FUNCTION_EXIT();

  return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
}
/* scsiport doesn't process SET_POWER correctly so we have to fudge detection of hibernate */
static NTSTATUS
XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER(WDFDEVICE device, PIRP irp) {
  PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
  PIO_STACK_LOCATION stack;
  
  FUNCTION_ENTER();
  stack = IoGetCurrentIrpStackLocation(irp);
  if (stack->Parameters.Power.Type == DevicePowerState && stack->Parameters.Power.State.DeviceState == PowerDeviceD3 && stack->Parameters.Power.ShutdownType == PowerActionHibernate) {
    FUNCTION_MSG("Going to hibernate\n");
    xvfd->hibernate_flag = TRUE;
  } else {
    xvfd->hibernate_flag = FALSE;
  }
  IoSkipCurrentIrpStackLocation(irp);
  FUNCTION_EXIT();
  return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
}
static NTSTATUS
XenUsb_EvtDeviceWdmIrpPreprocessQUERY_INTERFACE(WDFDEVICE device, PIRP irp)
{
  PIO_STACK_LOCATION stack;
 
  FUNCTION_ENTER();
 
  stack = IoGetCurrentIrpStackLocation(irp);

  if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID, sizeof(GUID)) == 0)
    FUNCTION_MSG("USB_BUS_INTERFACE_HUB_GUID\n");
  else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID, sizeof(GUID)) == 0)
    FUNCTION_MSG("USB_BUS_INTERFACE_USBDI_GUID\n");
  else if (memcmp(stack->Parameters.QueryInterface.InterfaceType, &GUID_TRANSLATOR_INTERFACE_STANDARD, sizeof(GUID)) == 0)
    FUNCTION_MSG("GUID_TRANSLATOR_INTERFACE_STANDARD\n");
  else
    FUNCTION_MSG("GUID = %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
      stack->Parameters.QueryInterface.InterfaceType->Data1,
      stack->Parameters.QueryInterface.InterfaceType->Data2,
      stack->Parameters.QueryInterface.InterfaceType->Data3,
      (stack->Parameters.QueryInterface.InterfaceType->Data4[0] << 8) |
       stack->Parameters.QueryInterface.InterfaceType->Data4[1],
      stack->Parameters.QueryInterface.InterfaceType->Data4[2],
      stack->Parameters.QueryInterface.InterfaceType->Data4[3],
      stack->Parameters.QueryInterface.InterfaceType->Data4[4],
      stack->Parameters.QueryInterface.InterfaceType->Data4[5],
      stack->Parameters.QueryInterface.InterfaceType->Data4[6],
      stack->Parameters.QueryInterface.InterfaceType->Data4[7]);

  FUNCTION_MSG("Size = %d\n", stack->Parameters.QueryInterface.Size);
  FUNCTION_MSG("Version = %d\n", stack->Parameters.QueryInterface.Version);
  FUNCTION_MSG("Interface = %p\n", stack->Parameters.QueryInterface.Interface);


  IoSkipCurrentIrpStackLocation(irp);
  
  FUNCTION_EXIT();

  return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
}
NTSTATUS 
RequestProcessSetPower(
    WDFDEVICE  Device,
    PIRP       Irp
    )
/*++

Routine Description:

    process IRP: IRP_MJ_POWER

Arguments:

    Device - device object
    Irp - the irp

Return Value:

    NTSTATUS

--*/
{
    PCDROM_DEVICE_EXTENSION deviceExtension = DeviceGetExtension(Device);
    PIO_STACK_LOCATION      currentStack;
    NTSTATUS                status;
    BOOLEAN                 IrpMarkedPending = FALSE;

    currentStack = IoGetCurrentIrpStackLocation(Irp);

    if ((currentStack->Parameters.Power.Type == DevicePowerState) &&
        (currentStack->Parameters.Power.State.DeviceState != PowerDeviceD0))
    {
        // We need to unlock the device queue in D3 postprocessing.
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(Irp,
                               RequestProcessPowerIrpCompletion,
                               deviceExtension,
                               TRUE,
                               TRUE,
                               TRUE);

        // Mark the Irp pending as we'll defer the I/O completion.
        IoMarkIrpPending(Irp);
        IrpMarkedPending = TRUE;
    }
    else {

        IoSkipCurrentIrpStackLocation(Irp);
    }

#pragma warning(push)
#pragma warning(disable: 28193) // OACR will complain that the status variable is not examined.

    //
    // Deliver the IRP back to the framework.
    //

    status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);

    if (IrpMarkedPending)
    {
        UNREFERENCED_PARAMETER(status);
        return STATUS_PENDING;
    }

#pragma warning(pop)

    return status;
}