NTSTATUS SingleCompEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by UMDF in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to the UMDF driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDFDEVICE device; WDFQUEUE queue; WDF_IO_QUEUE_CONFIG queueConfig; FDO_DATA *fdoContext = NULL; WDF_OBJECT_ATTRIBUTES objectAttributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; UNREFERENCED_PARAMETER(Driver); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FDO_DATA); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDeviceD0Entry = SingleCompEvtDeviceD0Entry; pnpCallbacks.EvtDeviceD0Exit = SingleCompEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreate failed with %!status!.", status); goto exit; } fdoContext = FdoGetContext(device); // // Our initial state is active // fdoContext->IsActive = TRUE; // // Create a power-managed queue for IOCTL requests. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = SingleCompEvtIoDeviceControl; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoDeviceControl failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeDeviceControl); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeDeviceControl failed with %!status!.", status); goto exit; } status = AssignS0IdleSettings(device); if (!NT_SUCCESS(status)) { goto exit; } // // Create a device interface so that applications can open a handle to this // device. // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_POWERFX, NULL /* ReferenceString */); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.", status); goto exit; } // // Initialize the hardware simulator // status = HwSimInitialize(device); if (FALSE == NT_SUCCESS(status)) { goto exit; } exit: return status; }
NTSTATUS SingleCompEvtDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the KMDF in response to AddDevice call from the PnP manager. Arguments: Driver - Handle to the KMDF driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDFDEVICE device; WDF_IO_QUEUE_CONFIG queueConfig; FDO_DATA *fdoContext = NULL; ULONG queueIndex = 0; WDF_OBJECT_ATTRIBUTES objectAttributes; WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, FDO_DATA); WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); pnpCallbacks.EvtDeviceD0Entry = SingleCompEvtDeviceD0Entry; pnpCallbacks.EvtDeviceD0Exit = SingleCompEvtDeviceD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); status = WdfDeviceCreate(&DeviceInit, &objectAttributes, &device); if (!NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreate failed with %!status!.", status); goto exit; } fdoContext = FdoGetContext(device); // // Our initial state is active // fdoContext->IsActive = TRUE; // // Create three power-managed queues, one each for read, write and IOCTL // requests. The handles to these power-managed queues are stored in an // array in the device object context space. When the component becomes idle // we need to stop our power-managed queues. When the component becomes // active we need to start them. In those situations, we go through this // array of power-managed queues and stop or start each queue as // appropriate. Handles to non-power-managed queues should not be stored in // this array. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoDeviceControl = SingleCompEvtIoDeviceControl; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &(fdoContext->Queues[queueIndex])); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoDeviceControl failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, fdoContext->Queues[queueIndex], WdfRequestTypeDeviceControl); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeDeviceControl failed with %!status!.", status); goto exit; } ++queueIndex; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoRead = SingleCompEvtIoRead; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &(fdoContext->Queues[queueIndex])); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoRead failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, fdoContext->Queues[queueIndex], WdfRequestTypeRead); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeRead failed with %!status!.", status); goto exit; } ++queueIndex; WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.EvtIoWrite = SingleCompEvtIoWrite; // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(queueConfig.EvtIoStop != 0); status = WdfIoQueueCreate(device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &(fdoContext->Queues[queueIndex])); __analysis_assume(queueConfig.EvtIoStop == 0); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfIoQueueCreate for IoWrite failed with %!status!.", status); goto exit; } status = WdfDeviceConfigureRequestDispatching(device, fdoContext->Queues[queueIndex], WdfRequestTypeWrite); if (FALSE == NT_SUCCESS (status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceConfigureRequestDispatching for " "WdfRequestTypeWrite failed with %!status!.", status); goto exit; } ++queueIndex; ASSERT(queueIndex == QUEUE_COUNT); status = AssignS0IdleSettings(device); if (!NT_SUCCESS(status)) { goto exit; } // // If you need to talk to hardware to figure out what F-states are // applicable this can be done in EvtSelfManagedIoInit // (but no later than that). EvtSelfManagedIoInit gets invoked after // EvtPrepareHardware so you'd have chance to initialize your hardware. // status = AssignPowerFrameworkSettings(device); if (!NT_SUCCESS(status)) { goto exit; } // // Create a device interface so that applications can open a handle to this // device. // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_POWERFX, NULL /* ReferenceString */); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfDeviceCreateDeviceInterface failed with %!status!.", status); goto exit; } // // Initialize the hardware simulator // status = HwSimInitialize(device); if (FALSE == NT_SUCCESS(status)) { goto exit; } exit: return status; }