Driver Dev Guide: How to Post Events from your WPD Driver

DimeBy8 wrote a great post on how a WPD application can receive driver-initiated WPD PnP events; this post will describe the driver's side of our eventing story.   While this mechanism is "under the covers" for most WPD application developers, it helps to get an end-to-end picture of how stuff works in WPD land, especially if you are thinking about writing a WPD driver and application for vertical scenarios that involve posting and receiving custom events.

 

Standard WPD Events and Parameters

Here is the list of standard WPD events.   These GUIDs are defined in PortableDevice.h.   When you begin accessing these events as a WPD application or driver), you may soon realize a missing piece of information: what/where are the parameters for these events?     The Event parameters are described in more detail in the Basic WPD Device Driver Requirements WHDC whitepaper, under Requirements for Event Parameters.   

snippet from the whitepaper that describes the required parameters for WPD_EVENT_OBJECT_UPDATED:

  WPD_EVENT_OBJECT_UPDATED

  This event is sent after an object has been updated so that any connected client should refresh its view of that object.

  Parameters

  WPD_EVENT_PARAMETER_PNP_DEVICE_ID

  Required.

  WPD_EVENT_PARAMETER_EVENT_ID

  Required.

  WPD_OBJECT_PERSISTENT_UNIQUE_ID

  Required.

  WPD_EVENT_PARAMETER_OBJECT_PARENT_PERSISTENT_UNIQUE_ID

  Required.

  WPD_EVENT_PARAMETER_CHILD_HIERARCHY_CHANGED

  Required if the object hierarchy at any level under this object has changed.

Event parameters matter when you're sending a standard WPD event from your driver.   For example, when receiving WPD_EVENT_OBJECT_UPDATED, applications may utilize information such as WPD_OBJECT_PERSISTENT_UNIQUE_ID to determine which object's properties would need to be refreshed in their properties view.   

*Aside: One consequence of supporting any WPD event that requires the Persistent Unique ID of objects is that your driver needs to support this property (but this is a required property anyway for most content objects).   The list of required properties is also covered in Basic WPD Device Driver Requirements.

 

Posting a WPD Event from Your Driver

Now that you know what parameters to send with a WPD event, posting the event is a three step process:

  1. Initialize an IPortableDeviceValues to hold the event parameters.
  2. Serialize the IPortableDeviceValues to a BYTE buffer.
  3. Call IWDFDevice::PostEvent with the EventGuid = WPD_EVENT_NOTIFICATION and the serialized buffer.  Only WdfEventBroadcast events are supported, which means all WPD applications that call IPortableDevice::Advise can receive the event your driver posts.
 BYTE* pBuffer  = NULL;
DWORD cbBuffer = 0;

// Populate the event parameters
hr = pIPortableDeviceValues->SetGuidValue(WPD_EVENT_PARAMETER_EVENT_ID, WPD_EVENT_OBJECT_UPDATED);

// Set other required event parameters here ....

if (hr == S_OK)
{
    // Serialize the event parameters to a buffer 
    hr = pWpdSerializer->GetBufferFromIPortableDeviceValues(pIPortableDeviceValues, &pBuffer, &cbBuffer);
}

// Send the event.
if (hr == S_OK)
{
    hr = pIWDFDevice->PostEvent(WPD_EVENT_NOTIFICATION, WdfEventBroadcast, pBuffer, cbBuffer);
}

// Cleanup ...
CoTaskMemFree(pBuffer);
pBuffer = NULL;

 

Defining a Custom WPD Event (and adding it to WpdInfo/WpdMon's Vocab!)

WPD's extensibility mechanism allows for custom events to be defined very easily.   You define a new GUID for your custom event, and define PROPERTYKEYs for your event parameters (or reuse existing PROPERTYKEYs).   On the application side, check for this custom event GUID the same way as you handle a WPD event, and process the event.   Your driver should also report these new event(s) when responding to WPD_COMMAND_CAPABILITIES_GET_SUPPORTED_EVENTS and WPD_COMMAND_CAPABILITIES_GET_EVENT_OPTIONS.

Both the WPDInfo and WPDMon WDK tools can receive and display custom WPD events in the raw GUID form, which means you already have a handy way to validate your driver's event posting functionality without needing to write a WPD application. 

You can even "teach" our tools to translate the custom event GUID to its symbolic name.   This can be done by adding an entry to the WpdInfo.GUIDs file (this is a text file usually located in the same folder path as the tool exes), and restarting the tools to reload this file.   In a similar way, symbolic names for your custom PROPERTYKEYs can go into WpdInfo.Properties file, custom commands in WpdInfo.Commands, etc.  

It's important to note that updating these WpdInfo.* dictionary files only enables the WPD tools in your PC to translate custom GUIDs and PROPERTYKEYs to symbolic string like names, other WPD applications and drivers know nothing on these custom values that are specific to your driver and application.

 

This posting is provided "AS IS" with no warranties, and confers no rights.