// // // Create a WDFDRIVER object // // We specify no object attributes, because we do not need a cleanup // or destroy event callback, or any per-driver context. // code = WdfDriverCreate(DriverObj, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, // Ptr to config structure NULL); // Optional ptr to get WDFDRIVER handle
if (!NT_SUCCESS(code)) {
DbgPrint("WdfDriverCreate failed with status 0x%0x ", code); }
// // Initialize the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
// // Setup the callbacks to manage our hardware resources. // // Prepare is called at START_DEVICE time // Release is called at STOP_DEVICE or REMOVE_DEVICE time // pnpPowerCallbacks.EvtDevicePrepareHardware = DioEvtPrepareHardware; pnpPowerCallbacks.EvtDeviceReleaseHardware = DioEvtReleaseHardware;
// // These two callbacks set up and tear down hardware state that must
// be done every time the device moves in and out of the D0-working // state.
// // We want our device object NAMED, thank you very much // status = WdfDeviceInitUpdateName(DeviceInit, L"/device/WDFDIO");
if (!NT_SUCCESS(status)) { DbgPrint("WdfDeviceInitUpdateName failed 0x%0x ", status); return(status); }
// // Because we DO NOT provide callbacks for Create or Close, WDF will // just succeed them automagically. //
// // Create the device now // status = WdfDeviceCreate(&DeviceInit, // Device Init structure &objAttributes, // Attributes for WDF Device &device); // returns pointer to new
// // Device creation is complete // // Get our device extension // devContext = DioGetContextFromDevice(device);
devContext->WdfDevice = device;
// // Create a symbolic link for the control object so that usermode can // open the device. // status = WdfDeviceCreateSymbolicLink(device, L"/DosDevices/WDFDIO");
if (!NT_SUCCESS(status)) { DbgPrint("WdfDeviceCreateSymbolicLink failed 0x%0x ", status); return(status); }
// ... }
比较有趣的是,WDF 直接提供了请求队列的概念。一个设备可以有多个请求队列,每个请求队列可以有一种模式,如最简单的 WdfIoQueueDispatchSerial 模式下,请求队列将请求串行化后进行处理;而 WdfIoQueueDispatchParallel 模式则自动在每个请求到来时调用 IO 回调函数;最后也可以通过 WdfIoQueueDispatchManual 模式,在请求到来时调用 EvtIoStart 事件处理函数来手工分发请求,类似现在 WDM 的工作方式。而请求队列更是提供了在 Power down 时对请求队列当前请求的自动保存和恢复机制。这样一来驱动的开发又可以剩一些事情了,呵呵。
A New Framework 一文中过于队列有较为广泛的讨论,这儿就不罗嗦了。
// // Configure our queue of incoming requests // // We only use the default queue, and we only support
// IRP_MJ_DEVICE_CONTROL.
// // Not supplying a callback results in the request being completed // with STATUS_NOT_SUPPORTED. // WDF_IO_QUEUE_CONFIG_INIT(&ioCallbacks, WdfIoQueueDispatchSerial, WDF_NO_EVENT_CALLBACK, // StartIo WDF_NO_EVENT_CALLBACK); // CancelRoutine