Driver Dev Guide: Supporting WPD_CLIENT_EVENT_COOKIE

WPD Applications can specify a unique string "cookie" in the client information when calling IPortableDevice::Open:

 

WPD_CLIENT_EVENT_COOKIE VT_LPWSTR Client supplied cookie returned by the driver in events posted as a direct result of operations issued by this client.

 

This is in additionto the client information properties described on MSDN, and declared in PortableDevice.h.

Depending on the application, this value will typically contain the application's DLL name or CLSID, or a unique application-generated identifier if the application supports multiple instances of itself running simultaneously.    The actual string contents does not matter to the driver, it is passed back to the application when events are sent.

When your driver sends an event and sets the cookie in the event parameters, the application can retrieve the cookie to determine if the event is a result of actions that originated from itself or another program.   For example, Application A creates an object on the device, and receives an ObjectAdded event containing its client event cookie, it can choose not to refresh its view of the device contents because the view has been updated at the time the object was created.    If Application B creates another object on the device, Application A will receive an ObjectAdded event with a different cookie (or no cookie), and knows that it needs to refresh the device contents view, because the object was added by some other client application.

In an environment where there can be two or more client applications communicating with your driver (Explorer is virtually guaranteed to be one client through the WPD Shell Namespace Extension), supporting the event cookie mechanism is a good WPD programming practice that may help reduce the client traffic to your device in response to events, and to streamline application-side event handling. 

 

How to support WPD_CLIENT_EVENT_COOKIE in your WPD driver:

1. Add a handler for the WPD_COMMAND_COMMON_SAVE_CLIENT_INFORMATION command.  The WpdWudfSampleDriver from the WDK contains an example of this in WpdBaseDriver::OnSaveClientInfo() .

2. In OnSaveClientInfo() , if the application sets WPD_CLIENT_EVENT_COOKIE in the client information parameters, save the cookie with your context info. Some applications may choose not to send this cookie, in which case your driver does not have to do anything here.

 LPWSTR pszEventCookie = NULL; 

hr = pClientInfo->GetStringValue(WPD_CLIENT_EVENT_COOKIE, &pszEventCookie);

if (hr == S_OK && pszEventCookie != NULL)
{
    // Store the cookie value with the client context
    pContext->EventCookie = pszEventCookie;
}

CoTaskMemFree(pszEventCookie);

 

3. When posting events, if the client event cookie is available, send it along with the event parameters.   In the sample driver, this code will be added to the PostWpdEvent() function.

 HRESULT hrEventCookie = GetClientEventCookie(pCommandParams, &pszEventCookie);

if (hrEventCookie == S_OK && pszEventCookie != NULL)
{
    // Add it to the event parameters
    // The application's OnEvent callback will match this with its cookie
    hrEventCookie = pEventParams->SetStringValue(WPD_CLIENT_EVENT_COOKIE, pszEventCookie);
}

CoTaskMemFree(pszEventCookie);

 

And here's an outline of the GetClientEventCookie() helper function.   It uses the client information context supplied in the command parameters to look up the saved client cookie in the context map.

 ClientContext* pClientContext = NULL;   // This is a context helper object defined by the sample driver

hr = pCommandParams->GetStringValue(WPD_PROPERTY_COMMON_CLIENT_INFORMATION_CONTEXT, &pszClientContext);

if (hr == S_OK)
{
    hr = GetClientContext(pCommandParams, pszClientContext, (IUnknown**)&pClientContext);

    if (hr == S_OK && pClientContext != NULL && pClientContext->EventCookie.GetLength() > 0)
    {
       // Allocate the cookie string to return 
       *ppszEventCookie = AtlAllocTaskWideString(pClientContext->EventCookie);
    }

    if (pClientContext != NULL) 
         pClientContext->Release();

    CoTaskMemFree(pszClientContext);
}

 

For an overview on posting events, refer to this post.

 

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