Plug and Play and Power Management in Simple Hardware Drivers

A driver that supports hardware-such as a UMDF protocol function driver or a KMDF hardware function driver-differs from a software-only driver in the following ways:

  • A driver that supports hardware must initialize its device to a known state every time the device enters D0, including during system startup.

    This known state is typically fully "reset." If the device supports interrupts or DMA, interrupts are disabled and DMA is stopped.

  • Most drivers that interact directly with their device's hardware create one or more power-managed I/O queues.

    The framework automatically stops dispatching I/O requests from the power-managed queues whenever the device hardware is not accessible, such as when the device is powered down.

A simple hardware driver, as described in this section, manages its device hardware through power-up initialization and power-down teardown and uses power-managed queues.

 KMDF  Most KMDF hardware drivers manage hardware resources and device interrupts from their devices and thus must support callback functions to process resources, to enable and disable interrupts, and to handle interrupts when they occur.

Chapter 17, "Direct Memory Access," provides information on implementing DMA in a KMDF driver. Chapter 16, "Hardware Resources and Interrupts," describes a KMDF driver's interrupt handling code.

Advanced features, such as device idle and wake, are supported only by KMDF and are described in "Advanced Power Management for KMDF Drivers" later in this chapter.

Device Power-Up Initialization and Power-Down Teardown

The framework provides hardware function drivers the opportunity to perform device initialization whenever the device enters the D0 state and to perform teardown whenever the device leaves the D0 state. Each time a device enters D0, the framework calls the driver's D0 entry callback:

  • For a UMDF driver, the framework calls IPnpCallback::OnD0Entry.

  • For a KMDF driver, the framework calls EvtDeviceD0Entry.

    For a KMDF driver, EvtDeviceD0Entry is called before the driver's EvtInterruptEnable callback. Therefore, interrupts have not yet been enabled for the device and the device is not yet connected to the driver's EvtInterruptIsr callback. During EvtDeviceD0Entry, drivers must not enable interrupts on their device or do anything that causes their device to interrupt. This is important to avoid potential "interrupt storms." The same is true for the EvtDevicePrepareHardware callback. If the device requires initialization after its interrupt is connected, the driver should register EvtDeviceD0EntryPostInterruptsEnabled.

The framework calls these callbacks after the bus driver has powered up the device, so the device hardware is accessible to the driver. Every device is powered up implicitly whenever the device is first detected, such as during system startup, and after the PnP manager stops the device to rebalance resources. Therefore, the framework always calls the D0 entry callbacks during startup, after calling the prepare-hardware callbacks.

Within the D0 entry callback, a driver performs any required hardware-related tasks each time the device enters the D0 state. Such tasks might include downloading firmware to the device and initializing the device to a known state or restoring the state previously saved during power-down.

Each time a device is about to leave D0, the framework calls the device's driver at its D0 exit callback:

  • For a UMDF driver, the framework calls IPnpCallback::OnD0Exit.

  • For a KMDF driver, the framework calls EvtDeviceD0Exit.

    For a KMDF driver, the framework calls EvtDeviceD0Exit after it calls EvtInterruptDisable, so device interrupts have been disabled and disconnected from the driver's EvtInterruptIsr callback. As with D0 entry, if the device requires teardown before its interrupts are disabled, the driver should register EvtDeviceD0ExitPreInterruptsDisabled.

During D0 exit processing, a driver performs tasks that are related to power-down, such as saving internal device state. The device hardware is still accessible in these callbacks because the device is still in the D0 power state.

Power Management for Queues in Hardware Function Drivers

By default, the framework manages power for the I/O queue objects that are children of FDOs and PDOs. As previously described, when the framework manages power for a queue, it dispatches requests from the queue to the driver's I/O callback functions only when the device hardware is accessible and in the D0 state. Letting the framework manage power for a queue means that the driver is not required to maintain device state or to check device state each time it receives an I/O request from the queue. Instead, it can process the request and access device hardware as required until the request has been completed.

Of course, not all I/O requests that a driver receives require access to device hardware. For example, a driver can often handle some device I/O control requests without accessing the hardware. Such a driver should create two queues-one power-managed queue and one non-power-managed queue. The driver configures the non-power-managed queue to receive all of the device I/O control requests from the framework. The framework dispatches requests from this queue regardless of the power state of the device. The driver inspects each request, handles the request if possible, and-if the device is not in the working state-forwards any requests that it cannot handle to the power-managed queue.

Drivers typically create and configure their I/O queues during add-device processing-that is, in a UMDF driver's IDriverEntry::OnDeviceAdd callback or a KMDF driver's EvtDriverDeviceAdd callback.

To disable power management for a queue:

  • A UMDF driver sets the bPowerManaged parameter of the IWDFDevice::CreateIoQueue method to FALSE when it creates the queue.

  • A KMDF driver sets the PowerManaged field of the WDF_IO_QUEUE_CONFIG structure to WdfFalse when it creates the queue.

Drivers that handle some I/O requests that require hardware access and other requests that do not require hardware access should create multiple queues and sort their requests on this basis. The UMDF Fx2_Driver and KMDF Osrusbfx2 samples create both power-managed and non-power-managed queues.

UMDF Example: Plug and Play and Power Code in a Protocol Function Driver

A UMDF function driver that manages device hardware is different from a software-only driver in several ways:

  • The driver typically creates one or more power-managed queues.

  • The driver implements the IPnpCallback and IPnpCallbackHardware interfaces as required on the device callback object to perform tasks related to the Plug and Play and power state of the device.

  • The driver must determine whether it should be the power policy owner for the device stack.

A UMDF driver cannot be the power policy owner for a USB device stack. If the USB device stack includes a UMDF driver, WinUSB.sys is always the power policy owner.

If your UMDF driver operates in a device stack other than USB, a kernel-mode driver is typically the power policy owner because kernel-mode drivers can support idle and wake whereas UMDF drivers cannot. However, if the device does not require idle or wake support, you should consider making the UMDF driver the power policy owner.

Tables 7-3 and 7-4 summarize the methods in the IPnpCallback and IPnpCallbackHardware interfaces.

Table 7-3: IPnpCallbackHardware Methods
Open table as spreadsheet



When called


Prepares device and driver to enter the working state after enumeration or resource rebalance.

After IDriverEntry::OnDeviceAdd returns and before device enters the working power state.


Prepares device and driver before system shutdown or resource rebalance.

After device exits from the working power state but before its queues are purged.

Table 7-4: IPnpCallback Methods
Open table as spreadsheet



When called


Performs required tasks for device to begin operation.

Immediately after device enters the working power state.


Performs required tasks for device to end operation.

Immediately before device exits the working power state.


Cleans up after device is unexpectedly removed.

Immediately after device is removed unexpectedly.


Provides the opportunity for the driver to veto a request to remove the device.

While device is in the working state, before device is physically removed.


Provides the opportunity for the driver to veto a request to stop the device to rebalance resources.

While device is in the working state, before it is stopped to rebalance resources.

The methods in IPnpCallbackHardware provide for driver actions when its device is added to or removed from the system and when system resources are rebalanced.

The IPnpCallback interface includes methods that are required to support the most common Plug and Play and power events, such as doing any initialization that is required after the device is powered on and the corresponding teardown that is required before the device powers down.

The Fx2_Driver sample is a UMDF protocol function driver that implements both IPnpCallback and IPnpCallbackHardware on the device callback object. The driver creates a default power-managed queue for read and write requests and a separate power-managed queue that receives only device I/O control requests.

Power-Managed Queue for a UMDF Driver

To create a power-managed queue, a UMDF driver calls passes TRUE for the bPowerManaged parameter to IWDFDevice::CreateIoQueue, as follows:

 hr = FxDevice->CreateIoQueue( unknown,                               TRUE,  // bDefaultQueue                               WdfIoQueueDispatchParallel,                               TRUE, // bPowerManaged                               TRUE, // bAllowZeroLengthRequests                               &fxQueue                               ); 

The driver typically creates I/O queues in its IDriverEntry::OnDeviceAdd callback.

IPnpCallbackHardware Methods

The framework calls the methods in the IPnpCallbackHardware interface on the device object before the device enters D0 and after the device leaves D0.

In the OnPrepareHardware method, the driver prepares to communicate with device hardware. It opens a handle to the device and calls internal functions to get information about the USB interfaces and endpoints.

Listing 7-3 shows the OnPrepareHardware method that the Fx2_Driver sample implements on the device callback object in the Device.cpp source file. To conserve space, error-handling statements have been omitted from the listing.

Listing 7-3: Sample IPnpCallbackHardware::OnPrepareHardware method

image from book
 HRESULT CMyDevice::OnPrepareHardware(     __in IWDFDevice * /* FxDevice */ ) { HRESULT hr; . . . //Code omitted // Create USB I/O targets and configure them.     hr = CreateUsbIoTargets(); if (SUCCEEDED(hr)) { ULONG length = sizeof(m_Speed);         hr = m_pIUsbTargetDevice->RetrieveDeviceInformation ( DEVICE_SPEED,                                                               &length,                                                               &m_Speed); if (FAILED(hr)) { // Generate trace message. } } . . . //Code omitted hr = ConfigureUsbPipes(); // Initialize power-management settings on the device. if (SUCCEEDED(hr)) {         hr = SetPowerManagement(); } if (SUCCEEDED(hr)) { . . . //Code omitted } if (FAILED(hr)) { ClearTargets(); } return hr; } 
image from book

The OnPrepareHardware method performs tasks that are required to ready the device for I/O before it enters the working state. These tasks include creating and configuring the USB I/O targets for the driver. The OnPrepareHardware method uses the framework's IWDFUsbTargetDevice interface to get information about the USB hardware.

Before the USB device can enter D0, the driver sets its power policy. The SetPowerManagement helper function uses USB-specific methods in the IWDFUsbTargetDevice interface to set power policy.

Listing 7-4 shows the Fx2_Driver sample's OnReleaseHardware method.

Listing 7-4: Sample IPnpCallbackHardware::OnReleaseHardware method

image from book
 HRESULT CMyDevice::OnReleaseHardware(     __in IWDFDevice * /* FxDevice */     ) {     ClearTargets();     return S_OK; } 
image from book

The OnReleaseHardware method performs cleanup tasks that are required when the device leaves the working state. The Fx2_Driver sample releases all of the driver's references on the I/O target objects, which is the only task of the ClearTargets helper function. The hardware does not require any additional service before power-down. For example, the driver does not save any hardware context information.

IPnpCallback Methods

When the OSR USB Fx2 device powers up, the Fx2_Driver sample starts its USB I/O target pipes. When the device powers down, the driver stops the target pipes. To perform these tasks, the driver implements the OnD0Entry and OnD0Exit methods of the IPnpCallback interface. In addition, if the user unexpectedly removes the device, the driver removes the targets and therefore implements the OnSurpriseRemoval method. In this driver, the other methods of the IPnpCallback interface are token implementations.

In the sample, the only tasks that the three methods perform involve its I/O targets, which the driver stops and restarts when the device enters or leaves the working state. The driver does not actually manipulate device hardware in any of these functions. Instead, it prepares to begin and end handling I/O requests.

Chapter 9, "I/O Targets," provides details about USB device I/O targets.

Listings 7-5 through 7-7 show the code from the Device.cpp source file that implements the OnD0Entry, OnD0Exit, and OnSurpriseRemoval methods.

Listing 7-5: Sample IPnpCallback::OnD0Entry method

image from book
 HRESULT STDMETHODCALLTYPE CMyDevice::OnD0Entry(     __in IWDFDevice * /* FxDevice */,     __in WDF_POWER_DEVICE_STATE /* PreviousState */     ) {     StartTarget(m_pIUsbInterruptPipe);     return InitiatePendingRead(); } 
image from book

In the OnD0Entry method, the driver starts one of the I/O targets that it created in IPnpCallbackHardware::OnPrepareHardware and initiates a read request for the target. The StartTarget and InitiatePendingRead helper functions handle the details of these two tasks.

The OnD0Exit method stops the I/O target, as Listing 7-6 shows. The driver calls the GetTargetState helper function to determine the state of the target because, if the device has been surprise-removed, the OnSurpriseRemoval method has already run and removed the target, as Listing 7-7 shows.

Listing 7-6: Sample IPnpCallback::OnD0Exit method

image from book
 HRESULT STDMETHODCALLTYPE CMyDevice::OnD0Exit(     __in IWDFDevice /* FxDevice */,     __in WDF_POWER_DEVICE_STATE /* NewState */     ) {     if (WdfIoTargetStarted == GetTargetState(m_pIUsbInterruptPipe)){         StopTarget(m_pIUsbInterruptPipe);     }     return S_OK; } 
image from book

Listing 7-7: Sample IPnpCallback::OnSurpriseRemoval method

image from book
 VOID STDMETHODCALLTYPE CMyDevice::OnSurpriseRemoval(     __in IWDFDevice * /* FxDevice */     ) {     RemoveTarget(m_pIUsbInterruptPipe, TRUE); //bSurpriseRemove     return; } 
image from book

If the user unexpectedly unplugs a device, the framework calls OnSurpriseRemoval before it calls any of the other callbacks in the shutdown sequence, as described in "UMDF Surprise-Removal Sequence" earlier in this chapter. In the Fx2_Driver sample, this function removes the I/O target.

KMDF Example: Plug and Play and Power Code in a Simple Hardware Function Driver

A simple KMDF hardware function driver that manages a device through startup and shutdown requires only a few more callback functions than a software-only driver requires.

The code in this section is adapted from the Osrusbfx2 sample. It includes support for the following features in addition to those required for a software-only driver:

  • EvtDevicePrepareHardware callback.

  • EvtDeviceD0Entry and EvtDeviceD0Exit callbacks.

  • Four I/O queues, three of which are power managed.

By providing these few functions, this driver fully supports Plug and Play and power management for its device.

KMDF Example: Register Callbacks and Set Up Power-managed Queues

Listing 7-8 shows how the Osrusbfx2 driver registers the fundamental Plug and Play and power management callbacks and creates power-managed I/O queues. This function appears in the Device.c source file.

Listing 7-8: EvtDriverDeviceAdd for simple hardware function driver

image from book
 NTSTATUS OsrFxEvtDeviceAdd(     IN WDFDRIVER        Driver,     IN PWDFDEVICE_INIT  DeviceInit     ) {     WDF_PNPPOWER_EVENT_CALLBACKS        pnpPowerCallbacks;     WDF_OBJECT_ATTRIBUTES               attributes;     NTSTATUS                            status;     WDFDEVICE                           device;     WDF_DEVICE_PNP_CAPABILITIES         pnpCaps;     WDF_IO_QUEUE_CONFIG                 ioQueueConfig;     PDEVICE_CONTEXT                     pDevContext;     WDFQUEUE                            queue;     UNREFERENCED_PARAMETER(Driver);     WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);     pnpPowerCallbacks.EvtDevicePrepareHardware = OsrFxEvtDevicePrepareHardware;     pnpPowerCallbacks.EvtDeviceD0Entry = OsrFxEvtDeviceD0Entry;     pnpPowerCallbacks.EvtDeviceD0Exit  = OsrFxEvtDeviceD0Exit;     WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);     WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); // Create a framework device object. status = WdfDeviceCreate(&DeviceInit, &attributes, &device); if (!NT_SUCCESS(status)) { return status;     }     pDevContext = GetDeviceContext(device);     // Set SurpriseRemovalOK in the Device Capabilities so     // that a user-mode popup does not appear on Windows 2000 when     // the user surprise-removes the device. WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.SurpriseRemovalOK = WdfTrue; WdfDeviceSetPnpCapabilities(device, &pnpCaps); // Create a default queue.     . . . //Code omitted     // Create a separate sequential queue for read requests.     WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);     ioQueueConfig.EvtIoRead = OsrFxEvtIoRead; ioQueueConfig.EvtIoStop = OsrFxEvtIoStop;     status = WdfIoQueueCreate(device,                               &ioQueueConfig,                               WDF_NO_OBJECT_ATTRIBUTES,                               &queue // queue handle                               );     if (!NT_SUCCESS (status)) {         return status;     }     status = WdfDeviceConfigureRequestDispatching(device, queue, WdfRequestTypeRead);     if(!NT_SUCCESS (status)){         return status;     }     // Create another sequential queue for write requests.     . . . //Code omitted     // Create a manual I/O queue. We retrieve requests from this     // queue only when the device sends an interrupt.     WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual); ioQueueConfig.PowerManaged = WdfFalse;     status = WdfIoQueueCreate(device,                               &ioQueueConfig,                               WDF_NO_OBJECT_ATTRIBUTES,                               &pDevContext->InterrputMsgQueue                               );     if (!NT_SUCCESS(status)) {     . . . //Additional code omitted     }     return status; } 
image from book

In the example, the first highlighted lines are related to the PnP and power management callbacks. The driver initializes a WDF_PNPPOWER_EVENT_CALLBACKS structure and fills in pointers to its EvtDevicePrepareHardware, EvtDeviceD0Entry, and EvtDeviceD0Exit callback functions. This driver manages a USB device, so it implements only an EvtDevicePrepareHardware callback without a corresponding EvtDeviceReleaseHardware callback. In a USB driver, the EvtDevicePrepareHardware callback selects interfaces and retrieves other information about the USB device before the device enters the working power state. However, no corresponding teardown is required, so the driver does not implement EvtDeviceReleaseHardware. Drivers for device types other than USB typically implement both of these callbacks.

The driver then sets the WDF_PNPPOWER_EVENT_CALLBACKS structure into the WDFDEVICE_INIT structure by calling WdfDeviceInitSetPnpPowerEventCallbacks. The WDFDEVICE_INIT structure-and thus the callbacks just described-is associated with the device object when the driver calls WdfDeviceCreate.

The second group of highlighted lines sets the device's Plug and Play capabilities. After creating the device object, the driver initializes the WDF_DEVICE_PNP_CAPABILITIES structure by setting the SurpriseRemovalOK field to WdfTrue and then calls WdfDeviceSet-PnpCapabilities to pass this information to the framework. This setting indicates that users can safely remove the device without using the Safely Remove Hardware utility.

The sample driver creates four I/O queues, three of which are power managed. The PowerManaged field in the WDF_IO_QUEUE_CONFIG structure indicates whether a queue is power managed. If the driver does not set this field, KMDF uses the default value and therefore creates power-managed queues based on the device object's role as the FDO for the device stack. To create a queue that is not power managed, the driver must explicitly set this field to WdfFalse.

The next highlighted line of code registers an EvtIoStop callback for one of the power-managed queues by setting the EvtIoStop field of the WDF_IO_QUEUE_CONFIG structure. The framework invokes EvtIoStop for a power-managed queue before the device leaves the working state. This function handles any pending I/O requests as appropriate for the device and the driver.

The final highlighted line of code shows how the driver sets the PowerManaged field in the WDF_IO_QUEUE_CONFIG structure for its non-power-managed queue.

KMDF Example: D0 Entry and D0 Exit Callbacks

The framework calls the driver's EvtDeviceD0Entry callback immediately after the driver enters the D0 state and calls the EvtDeviceD0Exit callback immediately before the driver exits the D0 state.

EvtDeviceD0Entry must perform any operations that are required before the device can be used. The framework calls this callback every time the hardware must be initialized or reinitialized. Listing 7-9 shows the EvtDeviceD0Entry function from the Osrusbfx2 sample driver.

Listing 7-9: EvtDeviceD0Entry callback for simple hardware function driver

image from book
 NTSTATUS OsrFxEvtDeviceD0Entry(     IN  WDFDEVICE Device,     IN  WDF_POWER_DEVICE_STATE PreviousState     ) {     PDEVICE_CONTEXT         pDeviceContext;     NTSTATUS                status;     PAGED_CODE();     pDeviceContext = GetDeviceContext(Device);     status = WdfIoTargetStart(                  WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe)                  );     return status; } 
image from book

The Osrusbfx2 driver's EvtDeviceD0Entry callback simply starts the driver's I/O targets, as Listing 7-9 shows.

The EvtDeviceD0Exit callback performs any operations that are required before the device leaves the D0 state, such as saving hardware state. The device is still in D0 when EvtDeviceD0Exit runs, so the driver can touch the hardware. The Osrusbfx2 driver's EvtDeviceD0Exit callback is shown in Listing 7-10.

Listing 7-10: EvtDeviceD0Exit callback for simple hardware function driver

image from book
 NTSTATUS OsrFxEvtDeviceD0Exit(     IN WDFDEVICE Device,     IN WDF_POWER_DEVICE_STATE TargetState     ) {     PDEVICE_CONTEXT         pDeviceContext;     PAGED_CODE();     pDeviceContext = GetDeviceContext(Device);     WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget( pDeviceContext->InterruptPipe),                     WdfIoTargetCancelSentIo                     );     return STATUS_SUCCESS; } 
image from book

The sample driver's EvtDeviceD0Exit callback simply undoes the actions of EvtDeviceD0Entry. Therefore, it stops the I/O targets and returns STATUS_SUCCESS.

Framework Actions for a Simple Hardware Function Driver

As in the software-only driver examples, the frameworks implement almost all of the Plug and Play and power management support for the sample drivers just described. Because these are function drivers, the framework automatically creates and manages Plug and Play, power management, and power policy state machines. The driver requires code only to manage the device hardware.

The framework calls the driver's prepare-hardware callback after the PnP manager discovers a device supported by the driver and after the driver's add-device callback returns:

  • For both UMDF and KMDF drivers, this function performs any initialization that is required before the device enters the D0 state.

    The prepare-hardware callbacks of USB drivers, such as the Fx2_Driver and Osrusbfx2 samples, should call methods that return information about the device and should also configure the interfaces on the device.

  •  KMDF  For a KMDF driver, the parameters to the prepare-hardware callback include a handle to the hardware resources that have been assigned to the driver.

    A driver that manages device resources can use KMDF helper functions to access and manipulate the resource lists.

Just before the device enters D0, the framework calls the driver's D0 entry callback. One of the parameters to this function for both UMDF and KMDF drivers is the previous power state from which the device is transitioning. Drivers typically ignore this value and initialize the device in the same way regardless of the previous power state. The value for this parameter is one of the following enumeration constants of the WDF_POWER_DEVICE_STATE type:

  • WdfPowerDeviceUnspecified

  • WdfPowerDeviceD0

  • WdfPowerDeviceD1

  • WdfPowerDeviceD2

  • WdfPowerDeviceD3

  • WdfPowerDeviceD3Final

  • WdfPowerDevicePrepareForHibernation

If the device is powering up for the first time, the framework passes WdfPowerDeviceUnspecified.

The framework also passes a device power state to the driver's D0 exit callback. In this case, the device state indicates the power state to which the device is transitioning upon exit from D0. Two of the possible target states might be unfamiliar to you:

  • WdfPowerDeviceD3Final

  • WdfPowerDevicePrepareForHibernation (KMDF only)

The framework passes WdfPowerDeviceD3Final as the target device power state to indicate that this is a transition to D3 as part of system shutdown or device removal. In this case, the driver must do whatever unique activities are necessary to prepare for shutdown, such as saving state to a disk or other nonvolatile medium.

Before a device leaves the D0 state, the framework stops any power-managed I/O queues associated with that device. After the device reenters the D0 state, the framework resumes the power-managed I/O queues.

image from book
KMDF, Storage Devices, and Hibernation

KMDF drivers for certain storage devices might receive WdfPowerDevicePrepareForHibernation as the target state if the device is in the hibernation path and the system is preparing to hibernate. The hibernation path includes the device to which the system writes the hibernation file and any other devices along the path from the root to that device, which are required to maintain power to that device.

The framework passes WdfPowerDevicePrepareForHibernation only if the driver has both called WdfDeviceSetSpecialFileSupport and received notification that it is in the hibernation path-and then only if the target power state for the system is S4.

When a KMDF driver's EvtDeviceD0Exit callback is called with the WdfPowerDevicePrepareForHibernation target state, the driver should prepare the device for hibernation by doing everything necessary to put the device into D3 except powering it off. This includes saving any state that the driver requires to return the device to the D0 state after the system resumes from hibernation. The driver must not power off the device. The system uses the device when it saves the hibernation file to disk immediately before entering the S4 state.

image from book

Developing Drivers with the Microsoft Windows Driver Foundation
Developing Drivers with the Windows Driver Foundation (Pro Developer)
ISBN: 0735623740
EAN: 2147483647
Year: 2007
Pages: 224

Similar book on Amazon
Windows Internals, Part 1: Covering Windows Server 2008 R2 and Windows 7
Windows Internals, Part 1: Covering Windows Server 2008 R2 and Windows 7
Windowsu00ae Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (Pro Developer)
Windowsu00ae Internals: Including Windows Server 2008 and Windows Vista, Fifth Edition (Pro Developer)
Advanced Windows Debugging
Advanced Windows Debugging
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition) © 2008-2017.
If you may any questions please contact us: