Retrieving WPD object properties

Services often contain child objects that belong to one of the formats that each service supports. For example, a Contacts service may support multiple contact objects of the Abstract Contact format. Each contact object is described by related properties (contact name, phone number, email address, and so on).

The WpdServiceApiSample application includes code that demonstrates how an application can retrieve the content-object properties supported by a given Contacts service. This sample uses the following interfaces.

Interface Description
IPortableDeviceService Retrieves the IPortableDeviceContent2 interface to access the supported service methods.
IPortableDeviceContent2 Provides access to the content-specific methods.
IPortableDeviceProperties Retrieves the object property values.
IPortableDeviceValues Holds the property values that were read for that object.
IPortableDeviceKeyCollection Contains the parameters for a given method.

 

When the user chooses option "7" at the command line, the application invokes the ReadContentProperties method that is found in the ContentProperties.cpp module.

This method retrieves the following four properties for the specified contact object.

Property Description Device Services PROPERTYKEY Equivalent WPD_PROPERTYKEY
Parent-object identifier A string that specifies the identifier for the given object's parent. PKEY_GenericObj_ParentID WPD_OBJECT_PARENT_ID
Object name A string that specifies the name of the given object PKEY_GenericObj_Name WPD_OBJECT_NAME
Persistent unique identifier A string that specifies a unique identifier for the given object. This identifier is persistent across sessions, unlike the object identifier. For services, this needs to be a string-representation of a GUID. PKEY_GenericObj_PersistentUID WPD_OBJECT_PERSISTENT_UNIQUE_ID
Object format A globally unique identifier (GUID) that specifies the format of the file corresponding to a given object PKEY_GenericObj_ObjectFormat WPD_OBJECT_FORMAT

 

  • Parent ID
  • Name
  • PersistentUID
  • Format

Note that prior to retrieving the content properties, the sample application opens a Contacts service on a connected device.

The following code for the ReadContentProperties method demonstrates how the application uses the IPortableDeviceContent2 interface to retrieve an IPortableDeviceProperties interface. By passing the PROPERTYKEYS of the requested properties to the IPortableDeviceProperties::GetValues method, ReadContentProperties retrieves the requested values, and then displays them to the console window.

// Reads properties for the user specified object.
void ReadContentProperties(
    IPortableDeviceService*    pService)
{
    if (pService == NULL)
    {
        printf("! A NULL IPortableDeviceService interface pointer was received\n");
        return;
    }

    HRESULT                               hr              = S_OK;
    WCHAR                                 szSelection[81] = {0};
    CComPtr<IPortableDeviceProperties>    pProperties;
    CComPtr<IPortableDeviceValues>        pObjectProperties;
    CComPtr<IPortableDeviceContent2>      pContent;
    CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;

    // Prompt user to enter an object identifier on the device to read properties from.
    printf("Enter the identifer of the object you wish to read properties from.\n>");
    hr = StringCbGetsW(szSelection,sizeof(szSelection));
    if (FAILED(hr))
    {
        printf("An invalid object identifier was specified, aborting property reading\n");
    }

    // 1) Get an IPortableDeviceContent2 interface from the IPortableDeviceService interface to
    // access the content-specific methods.
    if (SUCCEEDED(hr))
    {
        hr = pService->Content(&pContent);
        if (FAILED(hr))
        {
            printf("! Failed to get IPortableDeviceContent2 from IPortableDeviceService, hr = 0x%lx\n",hr);
        }
    }

    // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent2 interface
    // to access the property-specific methods.
    if (SUCCEEDED(hr))
    {
        hr = pContent->Properties(&pProperties);
        if (FAILED(hr))
        {
            printf("! Failed to get IPortableDeviceProperties from IPortableDeviceContent2, hr = 0x%lx\n",hr);
        }
    }

    // 3) CoCreate an IPortableDeviceKeyCollection interface to hold the property keys
    // we wish to read.
    hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_PPV_ARGS(&pPropertiesToRead));
    if (SUCCEEDED(hr))
    {
        // 4) Populate the IPortableDeviceKeyCollection with the keys we wish to read.
        // NOTE: We are not handling any special error cases here so we can proceed with
        // adding as many of the target properties as we can.
        if (pPropertiesToRead != NULL)
        {
            HRESULT hrTemp = S_OK;
            hrTemp = pPropertiesToRead->Add(PKEY_GenericObj_ParentID);
            if (FAILED(hrTemp))
            {
                printf("! Failed to add PKEY_GenericObj_ParentID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
            }

            hrTemp = pPropertiesToRead->Add(PKEY_GenericObj_Name);
            if (FAILED(hrTemp))
            {
                printf("! Failed to add PKEY_GenericObj_Name to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
            }

            hrTemp = pPropertiesToRead->Add(PKEY_GenericObj_PersistentUID);
            if (FAILED(hrTemp))
            {
                printf("! Failed to add PKEY_GenericObj_PersistentUID to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
            }

            hrTemp = pPropertiesToRead->Add(PKEY_GenericObj_ObjectFormat);
            if (FAILED(hrTemp))
            {
                printf("! Failed to add PKEY_GenericObj_ObjectFormat to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
            }

        }
    }

    // 5) Call GetValues() passing the collection of specified PROPERTYKEYs.
    if (SUCCEEDED(hr))
    {
        hr = pProperties->GetValues(szSelection,         // The object whose properties we are reading
                                    pPropertiesToRead,   // The properties we want to read
                                    &pObjectProperties); // Driver supplied property values for the specified object
        if (FAILED(hr))
        {
            printf("! Failed to get all properties for object '%ws', hr= 0x%lx\n", szSelection, hr);
        }
    }

    // 6) Display the returned property values to the user
    if (SUCCEEDED(hr))
    {
        DisplayStringProperty(pObjectProperties, PKEY_GenericObj_ParentID,        NAME_GenericObj_ParentID);
        DisplayStringProperty(pObjectProperties, PKEY_GenericObj_Name,            NAME_GenericObj_Name);
        DisplayStringProperty(pObjectProperties, PKEY_GenericObj_PersistentUID,   NAME_GenericObj_PersistentUID);
        DisplayGuidProperty  (pObjectProperties, PKEY_GenericObj_ObjectFormat,    NAME_GenericObj_ObjectFormat);
    }
}

IPortableDeviceContent2

IPortableDeviceProperties

WpdServicesApiSample