2025-11-28 00:35:46 +09:00

1068 lines
36 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "stdafx.h"
// Displays a friendly name for a passed in functional
// category. If the category is not known by this function
// the GUID will be displayed in string form.
void DisplayFunctionalCategory(
REFGUID guidCategory)
{
if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_STORAGE, guidCategory))
{
printf("WPD_FUNCTIONAL_CATEGORY_STORAGE");
}
else if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_STILL_IMAGE_CAPTURE, guidCategory))
{
printf("WPD_FUNCTIONAL_CATEGORY_STILL_IMAGE_CAPTURE");
}
else if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_AUDIO_CAPTURE, guidCategory))
{
printf("WPD_FUNCTIONAL_CATEGORY_AUDIO_CAPTURE");
}
else if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_SMS, guidCategory))
{
printf("WPD_FUNCTIONAL_CATEGORY_SMS");
}
else if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION, guidCategory))
{
printf("WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION");
}
else
{
printf("%ws", (PWSTR)CGuidToString(guidCategory));
}
}
// Displays a friendly name for a passed in event
// If the event is not known by this function
// the GUID will be displayed in string form.
void DisplayEvent(
REFGUID guidEvent)
{
if (IsEqualGUID(WPD_EVENT_OBJECT_ADDED, guidEvent))
{
printf("WPD_EVENT_OBJECT_ADDED");
}
else if (IsEqualGUID(WPD_EVENT_OBJECT_REMOVED, guidEvent))
{
printf("WPD_EVENT_OBJECT_REMOVED");
}
else if (IsEqualGUID(WPD_EVENT_OBJECT_UPDATED, guidEvent))
{
printf("WPD_EVENT_OBJECT_UPDATED");
}
else if (IsEqualGUID(WPD_EVENT_DEVICE_RESET, guidEvent))
{
printf("WPD_EVENT_DEVICE_RESET");
}
else if (IsEqualGUID(WPD_EVENT_DEVICE_CAPABILITIES_UPDATED, guidEvent))
{
printf("WPD_EVENT_DEVICE_CAPABILITIES_UPDATED");
}
else if (IsEqualGUID(WPD_EVENT_STORAGE_FORMAT, guidEvent))
{
printf("WPD_EVENT_STORAGE_FORMAT");
}
else
{
printf("%ws", (PWSTR)CGuidToString(guidEvent));
}
}
// Displays a friendly name for a passed in content type
// If the content type is not known by this function
// the GUID will be displayed in string form.
void DisplayContentType(
REFGUID guidContentType)
{
if (IsEqualGUID(WPD_CONTENT_TYPE_FUNCTIONAL_OBJECT, guidContentType))
{
printf("WPD_CONTENT_TYPE_FUNCTIONAL_OBJECT");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_FOLDER, guidContentType))
{
printf("WPD_CONTENT_TYPE_FOLDER");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_IMAGE, guidContentType))
{
printf("WPD_CONTENT_TYPE_IMAGE");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_DOCUMENT, guidContentType))
{
printf("WPD_CONTENT_TYPE_DOCUMENT");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_CONTACT, guidContentType))
{
printf("WPD_CONTENT_TYPE_CONTACT");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_AUDIO, guidContentType))
{
printf("WPD_CONTENT_TYPE_AUDIO");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_VIDEO, guidContentType))
{
printf("WPD_CONTENT_TYPE_VIDEO");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_TASK, guidContentType))
{
printf("WPD_CONTENT_TYPE_TASK");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_APPOINTMENT, guidContentType))
{
printf("WPD_CONTENT_TYPE_APPOINTMENT");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_EMAIL, guidContentType))
{
printf("WPD_CONTENT_TYPE_EMAIL");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_MEMO, guidContentType))
{
printf("WPD_CONTENT_TYPE_MEMO");
}
else if (IsEqualGUID(WPD_CONTENT_TYPE_UNSPECIFIED, guidContentType))
{
printf("WPD_CONTENT_TYPE_UNSPECIFIED");
}
else
{
printf("%ws", (PWSTR)CGuidToString(guidContentType));
}
}
// Display the basic event options for the passed in event.
void DisplayEventOptions(
IPortableDeviceCapabilities* pCapabilities,
REFGUID guidEvent)
{
CComPtr<IPortableDeviceValues> pOptions;
HRESULT hr = pCapabilities->GetEventOptions(guidEvent, &pOptions);
if (FAILED(hr))
{
printf("! Failed to get even options, hr = 0x%lx\n",hr);
}
if (hr == S_OK)
{
printf("Event 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;
hr = pOptions->GetBoolValue(WPD_EVENT_OPTION_IS_BROADCAST_EVENT, &bIsBroadcastEvent);
if (SUCCEEDED(hr))
{
printf("\tWPD_EVENT_OPTION_IS_BROADCAST_EVENT = %ws\n",bIsBroadcastEvent ? L"TRUE" : L"FALSE");
}
else
{
printf("! Failed to get WPD_EVENT_OPTION_IS_BROADCAST_EVENT (assuming FALSE), hr = 0x%lx\n",hr);
}
}
}
// Display all functional object identifiers contained in an IPortableDevicePropVariantCollection
// NOTE: These values are assumed to be in VT_LPWSTR VarType format.
void DisplayFunctionalObjectIDs(
IPortableDevicePropVariantCollection* pFunctionalObjectIds)
{
DWORD dwNumObjectIDs = 0;
// Get the total number of object identifiers in the collection.
HRESULT hr = pFunctionalObjectIds->GetCount(&dwNumObjectIDs);
if (SUCCEEDED(hr))
{
// Loop through the collection and displaying each object identifier found.
// This loop prints a comma-separated list of the object identifiers.
for (DWORD dwObjectIDIndex = 0; dwObjectIDIndex < dwNumObjectIDs; dwObjectIDIndex++)
{
PROPVARIANT pvObjectID = {0};
PropVariantInit(&pvObjectID);
hr = pFunctionalObjectIds->GetAt(dwObjectIDIndex, &pvObjectID);
if (SUCCEEDED(hr))
{
// We have a functional object identifier. It is assumed that
// object identifiers are returned as VT_LPWSTR
// VarTypes.
if ((pvObjectID.pwszVal != NULL) &&
(pvObjectID.vt == VT_LPWSTR))
{
// Display the object identifiers separated by commas
printf("%ws", pvObjectID.pwszVal);
if ((dwObjectIDIndex + 1) < dwNumObjectIDs)
{
printf(", ");
}
}
else
{
printf("! Invalid functional object identifier found\n");
}
}
PropVariantClear(&pvObjectID);
}
}
}
// List all functional objects on the device
void ListFunctionalObjects(
IPortableDevice* pDevice)
{
//<SnippetCapabilities7>
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pCategories;
DWORD dwNumCategories = 0;
if (pDevice == NULL)
{
printf("! A NULL IPortableDevice interface pointer was received\n");
return;
}
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all functional categories supported by the device.
// We will use these categories to enumerate functional objects
// that fall within them.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalCategories(&pCategories);
if (FAILED(hr))
{
printf("! Failed to get functional categories from the device, hr = 0x%lx\n",hr);
}
}
// Get the number of functional categories found on the device.
if (SUCCEEDED(hr))
{
hr = pCategories->GetCount(&dwNumCategories);
if (FAILED(hr))
{
printf("! Failed to get number of functional categories, hr = 0x%lx\n",hr);
}
}
printf("\n%d Functional Categories Found on the device\n\n", dwNumCategories);
// Loop through each functional category and get the list of
// functional object identifiers associated with a particular
// category.
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumCategories; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pCategories->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a functional category. It is assumed that
// functional categories are returned as VT_CLSID
// VarTypes.
if ((pv.puuid != NULL) &&
(pv.vt == VT_CLSID))
{
// Display the functional category name
printf("Functional Category: ");
DisplayFunctionalCategory(*pv.puuid);
printf("\n");
// Display the object identifiers for all
// functional objects within this category
CComPtr<IPortableDevicePropVariantCollection> pFunctionalObjectIds;
hr = pCapabilities->GetFunctionalObjects(*pv.puuid, &pFunctionalObjectIds);
if (SUCCEEDED(hr))
{
printf("Functional Objects: ");
DisplayFunctionalObjectIDs(pFunctionalObjectIds);
printf("\n\n");
}
else
{
printf("! Failed to get functional objects, hr = 0x%lx\n", hr);
}
}
else
{
printf("! Invalid functional category found\n");
}
}
PropVariantClear(&pv);
}
}
//</SnippetCapabilities7>
}
// Display all content types contained in an IPortableDevicePropVariantCollection
// NOTE: These values are assumed to be in VT_CLSID VarType format.
void DisplayContentTypes(
IPortableDevicePropVariantCollection* pContentTypes)
{
if (pContentTypes == NULL)
{
printf("! A NULL IPortableDevicePropVariantCollection interface pointer was received\n");
return;
}
HRESULT hr = S_OK;
DWORD dwNumContentTypes = 0;
// Get the total number of content types in the collection.
hr = pContentTypes->GetCount(&dwNumContentTypes);
if (SUCCEEDED(hr))
{
// Loop through the collection and displaying each content type found.
// This loop prints a comma-separated list of the content types.
for (DWORD dwContentTypeIndex = 0; dwContentTypeIndex < dwNumContentTypes; dwContentTypeIndex++)
{
PROPVARIANT pvContentType = {0};
PropVariantInit(&pvContentType);
hr = pContentTypes->GetAt(dwContentTypeIndex, &pvContentType);
if (SUCCEEDED(hr))
{
// We have a content type. It is assumed that
// content types are returned as VT_CLSID
// VarTypes.
if ((pvContentType.puuid != NULL) &&
(pvContentType.vt == VT_CLSID))
{
// Display the content types separated by commas
DisplayContentType(*pvContentType.puuid);
if ((dwContentTypeIndex + 1) < dwNumContentTypes)
{
printf(", ");
}
}
else
{
printf("! Invalid content type found\n");
}
}
PropVariantClear(&pvContentType);
}
}
}
// List all functional categories on the device
void ListFunctionalCategories(
IPortableDevice* pDevice)
{
//<SnippetCapabilities1>
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pCategories;
DWORD dwNumCategories = 0;
if (pDevice == NULL)
{
printf("! A NULL IPortableDevice interface pointer was received\n");
return;
}
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all functional categories supported by the device.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalCategories(&pCategories);
if (FAILED(hr))
{
printf("! Failed to get functional categories from the device, hr = 0x%lx\n",hr);
}
}
//</SnippetCapabilities1>
// Get the number of functional categories found on the device.
//<SnippetCapabilities2>
if (SUCCEEDED(hr))
{
hr = pCategories->GetCount(&dwNumCategories);
if (FAILED(hr))
{
printf("! Failed to get number of functional categories, hr = 0x%lx\n",hr);
}
}
printf("\n%d Functional Categories Found on the device\n\n", dwNumCategories);
// Loop through each functional category and display its name
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumCategories; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pCategories->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a functional category. It is assumed that
// functional categories are returned as VT_CLSID
// VarTypes.
if (pv.puuid != NULL)
{
// Display the functional category name
DisplayFunctionalCategory(*pv.puuid);
printf("\n");
}
}
PropVariantClear(&pv);
}
}
//</SnippetCapabilities2>
}
// List supported content types the device supports
void ListSupportedContentTypes(
IPortableDevice* pDevice)
{
//</SnippetCapabilities3>
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pCategories;
DWORD dwNumCategories = 0;
if (pDevice == NULL)
{
printf("! A NULL IPortableDevice interface pointer was received\n");
return;
}
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all functional categories supported by the device.
// We will use these categories to enumerate functional objects
// that fall within them.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalCategories(&pCategories);
if (FAILED(hr))
{
printf("! Failed to get functional categories from the device, hr = 0x%lx\n",hr);
}
}
// Get the number of functional categories found on the device.
if (SUCCEEDED(hr))
{
hr = pCategories->GetCount(&dwNumCategories);
if (FAILED(hr))
{
printf("! Failed to get number of functional categories, hr = 0x%lx\n",hr);
}
}
printf("\n%d Functional Categories Found on the device\n\n", dwNumCategories);
// Loop through each functional category and display its name and supported content types.
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumCategories; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pCategories->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a functional category. It is assumed that
// functional categories are returned as VT_CLSID
// VarTypes.
if ((pv.puuid != NULL) &&
(pv.vt == VT_CLSID))
{
// Display the functional category name
printf("Functional Category: ");
DisplayFunctionalCategory(*pv.puuid);
printf("\n");
// Display the content types supported for this category
CComPtr<IPortableDevicePropVariantCollection> pContentTypes;
hr = pCapabilities->GetSupportedContentTypes(*pv.puuid, &pContentTypes);
if (SUCCEEDED(hr))
{
printf("Supported Content Types: ");
DisplayContentTypes(pContentTypes);
printf("\n\n");
}
else
{
printf("! Failed to get supported content types from the device, hr = 0x%lx\n",hr);
}
}
else
{
printf("! Invalid functional category found\n");
}
}
PropVariantClear(&pv);
}
}
//</SnippetCapabilities3>
}
// Determines if a device supports a particular functional category.
BOOL SupportsFunctionalCategory(
IPortableDevice* pDevice,
REFGUID guidCategory)
{
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pCategories;
BOOL bSupported = FALSE;
DWORD dwNumCategories = 0;
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
HRESULT hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all functional categories supported by the device.
// We will use these categories to search for a particular functional category.
// There is typically only 1 of these types of functional categories.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalCategories(&pCategories);
if (FAILED(hr))
{
printf("! Failed to get functional categories from the device, hr = 0x%lx\n",hr);
}
}
// Get the number of functional categories found on the device.
if (SUCCEEDED(hr))
{
hr = pCategories->GetCount(&dwNumCategories);
if (FAILED(hr))
{
printf("! Failed to get number of functional categories, hr = 0x%lx\n",hr);
}
}
// Loop through each functional category and find the passed in category
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumCategories; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pCategories->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a functional category. It is assumed that
// functional categories are returned as VT_CLSID
// VarTypes.
if ((pv.puuid != NULL) &&
(pv.vt == VT_CLSID))
{
bSupported = IsEqualGUID(guidCategory, *pv.puuid);
}
else
{
printf("! Invalid functional category found\n");
}
}
PropVariantClear(&pv);
// If the device supports the category, exit the for loop.
// NOTE: We are exiting after calling PropVariantClear to make
// sure we free any allocated data in the PROPVARIANT returned
// from the GetAt() method call.
if (bSupported == TRUE)
{
break;
}
}
}
return bSupported;
}
// Determines if a device supports a particular command.
BOOL SupportsCommand(
IPortableDevice* pDevice,
REFPROPERTYKEY keyCommand)
{
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDeviceKeyCollection> pCommands;
BOOL bSupported = FALSE;
DWORD dwNumCommands = 0;
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
HRESULT hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all commands supported by the device.
// We will use these commands to search for a particular functional category.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetSupportedCommands(&pCommands);
if (FAILED(hr))
{
printf("! Failed to get supported commands from the device, hr = 0x%lx\n",hr);
}
}
// Get the number of supported commands found on the device.
if (SUCCEEDED(hr))
{
hr = pCommands->GetCount(&dwNumCommands);
if (FAILED(hr))
{
printf("! Failed to get number of supported commands, hr = 0x%lx\n",hr);
}
}
// Loop through each functional category and find the passed in category
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumCommands; dwIndex++)
{
PROPERTYKEY key = WPD_PROPERTY_NULL;
hr = pCommands->GetAt(dwIndex, &key);
if (SUCCEEDED(hr))
{
bSupported = IsEqualPropertyKey(keyCommand, key);
}
// If the device supports the category, exit the for loop.
if (bSupported == TRUE)
{
break;
}
}
}
return bSupported;
}
// Reads the WPD_RENDERING_INFORMATION_PROFILES properties on the device.
HRESULT ReadProfileInformationProperties(
IPortableDevice* pDevice,
PCWSTR pszFunctionalObjectID,
IPortableDeviceValuesCollection** ppRenderingInfoProfiles)
{
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CComPtr<IPortableDeviceContent> pContent;
CComPtr<IPortableDeviceProperties> pProperties;
CComPtr<IPortableDeviceKeyCollection> pPropertiesToRead;
CComPtr<IPortableDeviceValues> pObjectProperties;
// Get an IPortableDeviceContent interface from the IPortableDevice interface to
// access the content-specific methods.
HRESULT hr = pDevice->Content(&pContent);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface
// to access the property-specific methods.
if (SUCCEEDED(hr))
{
hr = pContent->Properties(&pProperties);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
}
}
// CoCreate an IPortableDeviceKeyCollection interface to hold the the property keys
// we wish to read WPD_RENDERING_INFORMATION_PROFILES)
hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pPropertiesToRead));
if (SUCCEEDED(hr))
{
// 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(WPD_RENDERING_INFORMATION_PROFILES);
if (FAILED(hrTemp))
{
printf("! Failed to add WPD_RENDERING_INFORMATION_PROFILES to IPortableDeviceKeyCollection, hr= 0x%lx\n", hrTemp);
}
}
}
// Call GetValues() passing the collection of specified PROPERTYKEYs.
if (SUCCEEDED(hr))
{
hr = pProperties->GetValues(pszFunctionalObjectID, // 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", pszFunctionalObjectID, hr);
}
}
// Read the WPD_RENDERING_INFORMATION_PROFILES
if (SUCCEEDED(hr))
{
hr = pObjectProperties->GetIPortableDeviceValuesCollectionValue(WPD_RENDERING_INFORMATION_PROFILES,
&pRenderingInfoProfiles);
if (FAILED(hr))
{
printf("! Failed to get WPD_RENDERING_INFORMATION_PROFILES from rendering information, hr= 0x%lx\n", hr);
}
}
// QueryInterface the interface into the out-going parameters.
if (SUCCEEDED(hr))
{
hr = pRenderingInfoProfiles->QueryInterface(IID_PPV_ARGS(ppRenderingInfoProfiles));
if (FAILED(hr))
{
printf("! Failed to QueryInterface for IPortableDeviceValuesCollection (Rendering information profiles), hr= 0x%lx\n", hr);
}
}
return hr;
}
void DisplayExpectedValues(
IPortableDeviceValues* pExpectedValues)
{
// 1) Determine what type of valid values should be displayed by reading the
// WPD_PROPERTY_ATTRIBUTE_FORM property.
DWORD dwAttributeForm = WPD_PROPERTY_ATTRIBUTE_FORM_UNSPECIFIED;
HRESULT hr = pExpectedValues->GetUnsignedIntegerValue(WPD_PROPERTY_ATTRIBUTE_FORM, &dwAttributeForm);
if (FAILED(hr))
{
printf("! Failed to get WPD_PROPERTY_ATTRIBUTE_FORM from expected value set, hr = 0x%lx\n", hr);
}
// 2) Switch on the attribute form to determine what expected value properties to read.
if (SUCCEEDED(hr))
{
switch(dwAttributeForm)
{
case WPD_PROPERTY_ATTRIBUTE_FORM_RANGE:
{
DWORD dwMin = 0;
DWORD dwMax = 0;
DWORD dwStep = 0;
hr = pExpectedValues->GetUnsignedIntegerValue(WPD_PROPERTY_ATTRIBUTE_RANGE_MIN, &dwMin);
if (FAILED(hr))
{
printf("! Failed to get WPD_PROPERTY_ATTRIBUTE_RANGE_MIN from expected values collection, hr = 0x%lx\n", hr);
}
hr = pExpectedValues->GetUnsignedIntegerValue(WPD_PROPERTY_ATTRIBUTE_RANGE_MAX, &dwMax);
if (FAILED(hr))
{
printf("! Failed to get WPD_PROPERTY_ATTRIBUTE_RANGE_MAX from expected values collection, hr = 0x%lx\n", hr);
}
hr = pExpectedValues->GetUnsignedIntegerValue(WPD_PROPERTY_ATTRIBUTE_RANGE_STEP, &dwStep);
if (FAILED(hr))
{
printf("! Failed to get WPD_PROPERTY_ATTRIBUTE_RANGE_STEP from expected values collection, hr = 0x%lx\n", hr);
}
printf("MIN: %d, MAX: %d, STEP: %d\n", dwMin, dwMax, dwStep);
}
break;
default:
printf("* DisplayExpectedValues helper function did not display attributes for form %d", dwAttributeForm);
break;
}
}
}
// Displays a rendering profile.
void DisplayRenderingProfile(
IPortableDeviceValues* pProfile)
{
DWORD dwTotalBitrate = 0;
DWORD dwChannelCount = 0;
DWORD dwAudioFormatCode = 0;
GUID guidFormat = WPD_OBJECT_FORMAT_UNSPECIFIED;
// Display WPD_MEDIA_TOTAL_BITRATE
HRESULT hr = pProfile->GetUnsignedIntegerValue(WPD_MEDIA_TOTAL_BITRATE, &dwTotalBitrate);
if (SUCCEEDED(hr))
{
printf("Total Bitrate: %d\n", dwTotalBitrate);
}
// If we fail to read the total bitrate as a single value, then it must be
// a valid value set. (i.e. returning IPortableDeviceValues as the value which
// contains properties describing the valid values for this property.)
if (hr == DISP_E_TYPEMISMATCH)
{
CComPtr<IPortableDeviceValues> pExpectedValues;
hr = pProfile->GetIPortableDeviceValuesValue(WPD_MEDIA_TOTAL_BITRATE, &pExpectedValues);
if (SUCCEEDED(hr))
{
printf("Total Bitrate: ");
DisplayExpectedValues(pExpectedValues);
}
}
// If we are still a failure here, report the error
if (FAILED(hr))
{
printf("! Failed to get WPD_MEDIA_TOTAL_BITRATE from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_AUDIO_CHANNEL_COUNT
hr = pProfile->GetUnsignedIntegerValue(WPD_AUDIO_CHANNEL_COUNT, &dwChannelCount);
if (SUCCEEDED(hr))
{
printf("Channel Count: %d\n", dwChannelCount);
}
else
{
printf("! Failed to get WPD_AUDIO_CHANNEL_COUNT from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_AUDIO_FORMAT_CODE
hr = pProfile->GetUnsignedIntegerValue(WPD_AUDIO_FORMAT_CODE, &dwAudioFormatCode);
if (SUCCEEDED(hr))
{
printf("Audio Format Code: %d\n", dwAudioFormatCode);
}
else
{
printf("! Failed to get WPD_AUDIO_FORMAT_CODE from rendering profile, hr = 0x%lx\n",hr);
}
// Display WPD_OBJECT_FORMAT
hr = pProfile->GetGuidValue(WPD_OBJECT_FORMAT, &guidFormat);
if (SUCCEEDED(hr))
{
printf("Object Format: %ws\n", (PWSTR)CGuidToString(guidFormat));
}
else
{
printf("! Failed to get WPD_OBJECT_FORMAT from rendering profile, hr = 0x%lx\n",hr);
}
}
// List rendering capabilities the device supports
void ListRenderingCapabilityInformation(
IPortableDevice* pDevice)
{
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pRenderingInfoObjects;
CComPtr<IPortableDeviceValuesCollection> pRenderingInfoProfiles;
CAtlStringW strRenderingInfoObjectID;
if (pDevice == NULL)
{
printf("! A NULL IPortableDevice interface pointer was received\n");
return;
}
if (SupportsFunctionalCategory(pDevice, WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION) == FALSE)
{
printf("This device does not support device rendering information to display\n");
return;
}
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get the functional object identifier for the rendering information object
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetFunctionalObjects(WPD_FUNCTIONAL_CATEGORY_RENDERING_INFORMATION, &pRenderingInfoObjects);
if (FAILED(hr))
{
printf("! Failed to get functional objects, hr = 0x%lx\n", hr);
}
}
// Assume the device only has one rendering information object for this example.
// We are going to request the first Object Identifier found in the collection.
if (SUCCEEDED(hr))
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pRenderingInfoObjects->GetAt(0, &pv);
if ((SUCCEEDED(hr)) &&
(pv.vt== VT_LPWSTR) )
{
strRenderingInfoObjectID = pv.pwszVal;
}
else
{
printf("! Failed to get first rendering object's identifier, hr = 0x%lx\n", hr);
}
PropVariantClear(&pv);
}
if (SUCCEEDED(hr))
{
hr = ReadProfileInformationProperties(pDevice,
strRenderingInfoObjectID,
&pRenderingInfoProfiles);
// Error output statements are performed by the helper function, so they
// are omitted here.
}
// Display all rendering profiles
if (SUCCEEDED(hr))
{
// Get the number of profiles supported by the device
DWORD dwNumProfiles = 0;
hr = pRenderingInfoProfiles->GetCount(&dwNumProfiles);
if (FAILED(hr))
{
printf("! Failed to get number of profiles supported by the device, hr = 0x%lx\n",hr);
}
printf("%d Rendering Profiles are supported by this device\n",dwNumProfiles);
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumProfiles; dwIndex++)
{
CComPtr<IPortableDeviceValues> pProfile;
hr = pRenderingInfoProfiles->GetAt(dwIndex, &pProfile);
if (SUCCEEDED(hr))
{
printf("\nProfile #%d:\n", dwIndex);
DisplayRenderingProfile(pProfile);
printf("\n\n");
}
else
{
printf("! Failed to get rendering profile at index '%d', hr = 0x%lx\n", dwIndex, hr);
}
}
}
}
}
// List all supported events on the device
void ListSupportedEvents(
IPortableDevice* pDevice)
{
//<SnippetCapabilities4>
HRESULT hr = S_OK;
CComPtr<IPortableDeviceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pEvents;
DWORD dwNumEvents = 0;
if (pDevice == NULL)
{
printf("! A NULL IPortableDevice interface pointer was received\n");
return;
}
//</SnippetCapabilities4>
// Get an IPortableDeviceCapabilities interface from the IPortableDevice interface to
// access the device capabilities-specific methods.
hr = pDevice->Capabilities(&pCapabilities);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceCapabilities from IPortableDevice, hr = 0x%lx\n",hr);
}
// Get all events supported by the device.
//<SnippetCapabilities5>
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetSupportedEvents(&pEvents);
if (FAILED(hr))
{
printf("! Failed to get supported events from the device, hr = 0x%lx\n",hr);
}
}
//</SnippetCapabilities5>
// Get the number of supported events found on the device.
//<SnippetCapabilities6>
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 device\n\n", dwNumEvents);
// Loop through each event and display its name
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)
{
// Display the event name
DisplayEvent(*pv.puuid);
printf("\n");
// Display the event options
DisplayEventOptions(pCapabilities, *pv.puuid);
printf("\n");
}
}
PropVariantClear(&pv);
}
}
//</SnippetCapabilities6>
}