The sample code snippets below illustrate how to implement this workaround:
EvtDriverDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
{
PWORKER_ITEM_CONTEXT context;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_WORKITEM_CONFIG workitemConfig;
WDFWORKITEM workItem;
...
//
// Set EvtDeviceReleaseHardware callback
//
...
pnpPowerCallbacks.EvtDeviceReleaseHardware = EvtDeviceReleaseHardware;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
...
//
// Allocate WDFWORKITEM
//
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes,WORKER_ITEM_CONTEXT);
attributes.ParentObject = device;
WDF_WORKITEM_CONFIG_INIT(&workitemConfig, EvtWorkItem);
status = WdfWorkItemCreate(&workitemConfig, &attributes, &workItem);
if (!NT_SUCCESS(status)) {
return status;
}
devContext->WorkItem = workItem;
...
}
NTSTATUS
EvtDeviceReleaseHardware(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourcesTranslated
)
{
KEVENT event;
PWORKER_ITEM_CONTEXT context;
WDFWORKITEM workItem;
UNREFERENCED_PARAMETER(ResourcesTranslated);
workItem = GetDeviceContext(Device)->WorkItem;
context = GetWorkItemContext(workItem);
KeInitializeEvent(&event, NotificationEvent, FALSE);
context->Event = &event;
//
// Queue the workitem
//
WdfWorkItemEnqueue(workItem);
//
// Wait for workitem to signal the event
//
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
return STATUS_SUCCESS;
}
VOID
EvtWorkItem(
IN WDFWORKITEM WorkItem
)
{
PWORKER_ITEM_CONTEXT context;
LARGE_INTEGER interval;
context = GetWorkItemContext(WorkItem);
//
// Delay the thread for 2 seconds
//
interval.QuadPart = -2 * 10 * 1000 * 1000;
KeDelayExecutionThread(KernelMode, FALSE, &interval);
//
// signal the waiting thread
//
KeSetEvent(context->Event, IO_NO_INCREMENT, FALSE);
context->Event = NULL;
}
// in header file
typedef struct _WORKER_ITEM_CONTEXT {
PKEVENT Event;
} WORKER_ITEM_CONTEXT, * PWORKER_ITEM_CONTEXT;
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(WORKER_ITEM_CONTEXT, GetWorkItemContext)
EVT_WDF_DEVICE_RELEASE_HARDWARE EvtDeviceReleaseHardware;
EVT_WDF_WORKITEM EvtWorkItem;