NTSTATUS VioCryptDeviceD0Entry(IN WDFDEVICE Device, IN WDF_POWER_DEVICE_STATE PreviousState)
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_CONTEXT context = GetDeviceContext(Device);
    VIRTIO_WDF_QUEUE_PARAM param;
    struct virtqueue *queues[1];
    u64 u64HostFeatures, u64GuestFeatures = 0;

    Trace(TRACE_LEVEL_VERBOSE, "[%s] from D%d", __FUNCTION__, PreviousState - WdfPowerDeviceD0);

    PAGED_CODE();

    u64HostFeatures = VirtIOWdfGetDeviceFeatures(&context->VDevice);

    if (virtio_is_feature_enabled(u64HostFeatures, VIRTIO_F_VERSION_1))
    {
        virtio_feature_enable(u64GuestFeatures, VIRTIO_F_VERSION_1);
    }
    if (virtio_is_feature_enabled(u64HostFeatures, VIRTIO_F_ANY_LAYOUT))
    {
        virtio_feature_enable(u64GuestFeatures, VIRTIO_F_ANY_LAYOUT);
    }

    status = VirtIOWdfSetDriverFeatures(&context->VDevice, u64GuestFeatures);
    if (NT_SUCCESS(status))
    {
        param.Interrupt = context->WdfInterrupt;
        status = VirtIOWdfInitQueues(&context->VDevice, 1, queues, &param);
    }

    if (NT_SUCCESS(status))
    {
        context->ControlQueue = queues[0];
        VirtIOWdfSetDriverOK(&context->VDevice);
    }
    else
    {
        VirtIOWdfSetDriverFailed(&context->VDevice);
        Trace(TRACE_LEVEL_ERROR, "[%s] VirtIOWdfInitQueues failed with %x\n", __FUNCTION__, status);
    }

    return status;
}
NTSTATUS virtio_set_features(VirtIODevice *vdev, u64 features)
{
    unsigned char dev_status;
    NTSTATUS status = vdev->device->set_features(vdev, features);

    if (!NT_SUCCESS(status)) {
        return status;
    }

    if (!virtio_is_feature_enabled(features, VIRTIO_F_VERSION_1)) {
        return status;
    }

    virtio_add_status(vdev, VIRTIO_CONFIG_S_FEATURES_OK);
    dev_status = vdev->device->get_status(vdev);
    if (!(dev_status & VIRTIO_CONFIG_S_FEATURES_OK)) {
        DPrintf(0, ("virtio: device refuses features: %x\n", dev_status));
        status = STATUS_INVALID_PARAMETER;
    }
    return status;
}