Retrieving Supported Service Events

The WpdServicesApiSample application includes code that demonstrates how an application can retrieve the events supported by a given Contacts service by calling methods on the following interfaces.

Interface Description
IPortableDeviceService Used to retrieve the IPortableDeviceServiceCapabilities interface to access the supported events.
IPortableDeviceServiceCapabilities Provides access to the supported events and event attributes.
IPortableDevicePropVariantCollection Contains the list of supported events.
IPortableDeviceValues Contains the attributes for a given event.

 

When the user chooses option "4" at the command line, the application invokes the ListSupportedEvents method that is found in the ServiceCapabilities.cpp module.

Note that prior to retrieving the list of events, the sample application opens a Contacts service on a connected device.

In WPD, an event is described by its name, options, and parameters. The event name is a script-friendly string, for example, "MyCustomEvent". The event options indicate whether a given event is broadcast to all clients and whether that event supports autoplay. The event parameter attributes includes a given parameter's PROPERTYKEY and VARTYPE.

Four methods in the ServiceCapabilities.cpp module support the retrieval of supported events for the given Contacts service: ListSupportedEvents, DisplayEvent, DisplayEventOptions, and DisplayEventParameters. The ListSupportedEvents method retrieves a count of supported events and the GUID identifier for each event. The DisplayEvent method displays the event name or GUID, and then calls DisplayEventOptions and DisplayEventParameters to display the event-related data.

The ListSupportedEvents method invokes the IPortableDeviceService::Capabilities method to retrieve an IPortableDeviceServiceCapabilities interface. Using this interface, it retrieves the supported events by calling the IPortableDeviceServiceCapabilities::GetSupportedEvents method. The GetSupportedEvents method retrieves the GUIDs for each event supported by the service and copies those GUIDs into an IPortableDevicePropVariantCollection object.

The following code illustrates retrieving supported service events.

// List all supported events on the service
void ListSupportedEvents(
    IPortableDeviceService* pService)
{
    HRESULT hr          = S_OK;
    DWORD   dwNumEvents = 0;
    CComPtr<IPortableDeviceServiceCapabilities>     pCapabilities;
    CComPtr<IPortableDevicePropVariantCollection>   pEvents;

    if (pService == NULL)
    {
        printf("! A NULL IPortableDeviceService interface pointer was received\n");
        return;
    }

    // Get an IPortableDeviceServiceCapabilities interface from the IPortableDeviceService interface to
    // access the service capabilities-specific methods.
    hr = pService->Capabilities(&pCapabilities);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceServiceCapabilities from IPortableDeviceService, hr = 0x%lx\n",hr);
    }

    // Get all events supported by the service.
    if (SUCCEEDED(hr))
    {
        hr = pCapabilities->GetSupportedEvents(&pEvents);
        if (FAILED(hr))
        {
            printf("! Failed to get supported events from the service, hr = 0x%lx\n",hr);
        }
    }

    // Get the number of supported events found on the service.
    if (SUCCEEDED(hr))
    {
        hr = pEvents->GetCount(&dwNumEvents);
        if (FAILED(hr))
        {
            printf("! Failed to get number of supported events, hr = 0x%lx\n",hr);
        }
    }

    printf("\n%d Supported Events Found on the service\n\n", dwNumEvents);

    // Loop through each event and display it
    if (SUCCEEDED(hr))
    {
        for (DWORD dwIndex = 0; dwIndex < dwNumEvents; dwIndex++)
        {
            PROPVARIANT pv = {0};
            PropVariantInit(&pv);
            hr = pEvents->GetAt(dwIndex, &pv);

            if (SUCCEEDED(hr))
            {
                // We have an event.  It is assumed that
                // events are returned as VT_CLSID VarTypes.
                if (pv.puuid != NULL)
                {
                    DisplayEvent(pCapabilities, *pv.puuid);
                    printf("\n");
                }
            }

            PropVariantClear(&pv);
        }
    }
}

After the ListSupportedEvents method retrieves the GUIDs representing each event supported by the given service, it invokes the DisplayEvent method to retrieve event-specific data. This data includes the event name, its options (broadcast or autoplay), parameter GUIDs, parameter types, and so on.

The DisplayEvent method invokes the IPortableDeviceServiceCapabilities::GetEventAttributes method to retrieve a collection of attributes for the given event. It then calls the IPortableDeviceValues::GetStringValue method and requests that the driver return a user-friendly name for the given event. Next, DisplayEvent calls the IPortableDeviceValues::GetIPortableDeviceValuesValue to retrieve the event options. Finally, DisplayEvent calls the IPortableDeviceValues::GetIPortableDeviceKeyCollectionValue to retrieve the list of event parameters. It passes the data returned by these methods to the DisplayEventOptions and the DisplayEventParameters helper functions, which render the options and parameter information for the given event.

The following code uses the DisplayEvent method.

// Display basic information about an event
void DisplayEvent(
    IPortableDeviceServiceCapabilities* pCapabilities,
    REFGUID                             Event)
{
    CComPtr<IPortableDeviceValues> pAttributes;

    // Get the event attributes which describe the event
    HRESULT hr = pCapabilities->GetEventAttributes(Event, &pAttributes);
    if (FAILED(hr))
    {
        printf("! Failed to get the event attributes, hr = 0x%lx\n",hr);
    }

    if (SUCCEEDED(hr))
    {
        PWSTR pszFormatName = NULL;
        CComPtr<IPortableDeviceValues>          pOptions;
        CComPtr<IPortableDeviceKeyCollection>   pParameters;

        // Display the name of the event if it is available. Otherwise, fall back to displaying the GUID.
        hr = pAttributes->GetStringValue(WPD_EVENT_ATTRIBUTE_NAME, &pszFormatName);
        if (SUCCEEDED(hr))
        {
            printf("%ws\n", pszFormatName);
        }
        else
        {
            printf("%ws\n", (PWSTR)CGuidToString(Event));
        }       

        // Display the event options
        hr = pAttributes->GetIPortableDeviceValuesValue(WPD_EVENT_ATTRIBUTE_OPTIONS, &pOptions);
        if (SUCCEEDED(hr))
        {
            DisplayEventOptions(pOptions);
        }
        else
        {
            printf("! Failed to get the event options, hr = 0x%lx\n", hr);
        }       

        // Display the event parameters
        hr = pAttributes->GetIPortableDeviceKeyCollectionValue(WPD_EVENT_ATTRIBUTE_PARAMETERS, &pParameters);
        if (SUCCEEDED(hr))
        {
            DisplayEventParameters(pCapabilities, Event, pParameters);
        }
        else
        {
            printf("! Failed to get the event parameters, hr = 0x%lx\n", hr);
        }       
        
        CoTaskMemFree(pszFormatName);
        pszFormatName = NULL;
    }
}

The DisplayEventOptions helper function receives an IPortableDeviceValues object which contains the event's option data. It then calls the IPortableDeviceValues::GetBoolValue method to retrieve the options data. Using this data, it renders a string indicating whether the broadcast and autoplay options are supported.

// Display the basic event options.
void DisplayEventOptions(
    IPortableDeviceValues* pOptions)
{
    printf("\tEvent Options:\n");
    // Read the WPD_EVENT_OPTION_IS_BROADCAST_EVENT value to see if the event is
    // a broadcast event. If the read fails, assume FALSE
    BOOL  bIsBroadcastEvent = FALSE;
    pOptions->GetBoolValue(WPD_EVENT_OPTION_IS_BROADCAST_EVENT, &bIsBroadcastEvent);
    printf("\tWPD_EVENT_OPTION_IS_BROADCAST_EVENT = %ws\n",bIsBroadcastEvent ? L"TRUE" : L"FALSE");
}

IPortableDeviceKeyCollection

IPortableDeviceService

IPortableDeviceServiceCapabilities

IPortableDeviceValues

WpdServicesApiSample