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

544 lines
17 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"
HANDLE g_hMethodCompleteEvent = NULL;
void DisplayParameterUsage(
DWORD dwUsage)
{
switch(static_cast<WPD_PARAMETER_USAGE_TYPES>(dwUsage))
{
case WPD_PARAMETER_USAGE_RETURN:
printf("Return Value");
break;
case WPD_PARAMETER_USAGE_IN:
printf("Input Parameter");
break;
case WPD_PARAMETER_USAGE_OUT:
printf("Output Parameter");
break;
case WPD_PARAMETER_USAGE_INOUT:
printf("Input/Output Parameter");
break;
default:
printf("Unknown Parameter Usage");
break;
}
}
void DisplayMethodAccess(
DWORD dwAccess)
{
switch(static_cast<WPD_COMMAND_ACCESS_TYPES>(dwAccess))
{
case WPD_COMMAND_ACCESS_READ:
printf("Read");
break;
case WPD_COMMAND_ACCESS_READWRITE:
printf("Read/Write");
break;
default:
printf("Unknown Access");
break;
}
}
// Display the method parameters.
void DisplayMethodParameters(
IPortableDeviceServiceCapabilities* pCapabilities,
REFGUID Method,
IPortableDeviceKeyCollection* pParameters)
{
DWORD dwNumParameters = 0;
// Get the number of parameters for this event.
HRESULT hr = pParameters->GetCount(&dwNumParameters);
if (FAILED(hr))
{
printf("! Failed to get number of parameters, hr = 0x%lx\n",hr);
}
printf("\n\t%d Method Parameters:\n", dwNumParameters);
// Loop through each parameter and display it
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumParameters; dwIndex++)
{
PROPERTYKEY parameter;
hr = pParameters->GetAt(dwIndex, &parameter);
if (SUCCEEDED(hr))
{
CComPtr<IPortableDeviceValues> pAttributes;
// Display the parameter's Name, Usage, Vartype, and Form
hr = pCapabilities->GetMethodParameterAttributes(Method, parameter, &pAttributes);
if (FAILED(hr))
{
printf("! Failed to get the method parameter attributes, hr = 0x%lx\n",hr);
}
if (SUCCEEDED(hr))
{
PWSTR pszParameterName = NULL;
DWORD dwAttributeVarType = 0;
DWORD dwAttributeForm = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
DWORD dwAttributeUsage = (DWORD)-1;
hr = pAttributes->GetStringValue(WPD_PARAMETER_ATTRIBUTE_NAME, &pszParameterName);
if (SUCCEEDED(hr))
{
printf("\t\tName: %ws\n", pszParameterName);
}
else
{
printf("! Failed to get the method parameter name, hr = 0x%lx\n",hr);
}
// Read the WPD_PARAMETER_ATTRIBUTE_USAGE value, if specified.
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_USAGE, &dwAttributeUsage);
if (SUCCEEDED(hr))
{
printf("\t\tUsage: ");
DisplayParameterUsage(dwAttributeUsage);
printf("\n");
}
else
{
printf("! Failed to get the method parameter usage, hr = 0x%lx\n",hr);
}
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_VARTYPE, &dwAttributeVarType);
if (SUCCEEDED(hr))
{
printf("\t\tVARTYPE: ");
DisplayVarType(static_cast<VARTYPE>(dwAttributeVarType));
printf("\n");
}
else
{
printf("! Failed to get the method parameter VARTYPE, hr = 0x%lx\n",hr);
}
// Read the WPD_PARAMETER_ATTRIBUTE_FORM value.
hr = pAttributes->GetUnsignedIntegerValue(WPD_PARAMETER_ATTRIBUTE_FORM, &dwAttributeForm);
if (FAILED(hr))
{
// If the read fails, assume WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED
dwAttributeForm = WPD_PARAMETER_ATTRIBUTE_FORM_UNSPECIFIED;
hr = S_OK;
}
printf("\t\tForm: ");
DisplayParameterForm(dwAttributeForm);
printf("\n");
CoTaskMemFree(pszParameterName);
pszParameterName = NULL;
}
printf("\n");
}
}
}
}
// Display basic information about a method
void DisplayMethod(
IPortableDeviceServiceCapabilities* pCapabilities,
REFGUID Method)
{
CComPtr<IPortableDeviceValues> pAttributes;
// Get the method attributes which describe the method
HRESULT hr = pCapabilities->GetMethodAttributes(Method, &pAttributes);
if (FAILED(hr))
{
printf("! Failed to get the method attributes, hr = 0x%lx\n",hr);
}
if (SUCCEEDED(hr))
{
PWSTR pszMethodName = NULL;
DWORD dwMethodAccess = WPD_COMMAND_ACCESS_READ;
GUID guidFormat = GUID_NULL;
CComPtr<IPortableDeviceValues> pOptions;
CComPtr<IPortableDeviceKeyCollection> pParameters;
// Display the name of the method if available. Otherwise, fall back to displaying the GUID.
hr = pAttributes->GetStringValue(WPD_METHOD_ATTRIBUTE_NAME, &pszMethodName);
if (SUCCEEDED(hr))
{
printf("%ws", pszMethodName);
}
else
{
printf("%ws", (PWSTR)CGuidToString(Method));
}
// Display the method access if available, otherwise default to WPD_COMMAND_ACCESS_READ access
hr = pAttributes->GetUnsignedIntegerValue(WPD_METHOD_ATTRIBUTE_ACCESS, &dwMethodAccess);
if (FAILED(hr))
{
dwMethodAccess = WPD_COMMAND_ACCESS_READ;
hr = S_OK;
}
printf("\n\tAccess: ");
DisplayMethodAccess(dwMethodAccess);
// Display the associated format if specified.
// Methods that have an associated format may only be supported for that format.
// Methods that don't have associated formats generally apply to the entire service.
hr = pAttributes->GetGuidValue(WPD_METHOD_ATTRIBUTE_ASSOCIATED_FORMAT, &guidFormat);
if (SUCCEEDED(hr))
{
printf("\n\tAssociated Format: ");
DisplayFormat(pCapabilities, guidFormat);
}
// Display the method parameters, if available
hr = pAttributes->GetIPortableDeviceKeyCollectionValue(WPD_METHOD_ATTRIBUTE_PARAMETERS, &pParameters);
if (SUCCEEDED(hr))
{
DisplayMethodParameters(pCapabilities, Method, pParameters);
}
CoTaskMemFree(pszMethodName);
pszMethodName = NULL;
}
}
// List all supported methods on the service
void ListSupportedMethods(IPortableDeviceService* pService)
{
HRESULT hr = S_OK;
DWORD dwNumMethods = 0;
CComPtr<IPortableDeviceServiceCapabilities> pCapabilities;
CComPtr<IPortableDevicePropVariantCollection> pMethods;
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 methods supported by the service.
if (SUCCEEDED(hr))
{
hr = pCapabilities->GetSupportedMethods(&pMethods);
if (FAILED(hr))
{
printf("! Failed to get supported methods from the service, hr = 0x%lx\n",hr);
}
}
// Get the number of supported methods found on the service.
if (SUCCEEDED(hr))
{
hr = pMethods->GetCount(&dwNumMethods);
if (FAILED(hr))
{
printf("! Failed to get number of supported methods, hr = 0x%lx\n",hr);
}
}
printf("\n%d Supported Methods Found on the service\n\n", dwNumMethods);
// Loop through each method and display it
if (SUCCEEDED(hr))
{
for (DWORD dwIndex = 0; dwIndex < dwNumMethods; dwIndex++)
{
PROPVARIANT pv = {0};
PropVariantInit(&pv);
hr = pMethods->GetAt(dwIndex, &pv);
if (SUCCEEDED(hr))
{
// We have a method. It is assumed that
// methods are returned as VT_CLSID VarTypes.
if (pv.puuid != NULL)
{
DisplayMethod(pCapabilities, *pv.puuid);
printf("\n");
}
}
PropVariantClear(&pv);
}
}
}
class CMethodCallback : public IPortableDeviceServiceMethodCallback
{
public:
CMethodCallback () : m_cRef(1)
{
}
~CMethodCallback ()
{
}
public:
// IPortableDeviceServiceMethodCallback::QueryInterface
virtual HRESULT STDMETHODCALLTYPE OnComplete(
HRESULT hrStatus,
IPortableDeviceValues* /*pResults*/) // We are ignoring results as our methods will not return any results
{
printf("** Method completed, status HRESULT = 0x%lx **\n", hrStatus);
if (g_hMethodCompleteEvent != NULL)
{
SetEvent(g_hMethodCompleteEvent);
}
return S_OK;
}
// IUnknown::AddRef
virtual ULONG STDMETHODCALLTYPE AddRef(void)
{
InterlockedIncrement((long*) &m_cRef);
return m_cRef;
}
// IUnknown::QueryInterface
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
REFIID riid,
LPVOID* ppvObj)
{
HRESULT hr = S_OK;
if (ppvObj == NULL)
{
hr = E_INVALIDARG;
return hr;
}
if ((riid == IID_IUnknown) ||
(riid == IID_IPortableDeviceServiceMethodCallback))
{
AddRef();
*ppvObj = this;
}
else
{
*ppvObj = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
// IUnknown::Release
virtual ULONG STDMETHODCALLTYPE Release(void)
{
ULONG ulRefCount = m_cRef - 1;
if (InterlockedDecrement((long*) &m_cRef) == 0)
{
delete this;
return 0;
}
return ulRefCount;
}
private:
DWORD m_cRef;
};
// Invoke methods on the Contacts Service.
// BeginSync and EndSync are methods defined by the FullEnumerationSync Device Service.
void InvokeMethods(IPortableDeviceService* pService)
{
HRESULT hr = S_OK;
CComPtr<IPortableDeviceServiceMethods> pMethods;
if (pService == NULL)
{
printf("! A NULL IPortableDeviceService interface pointer was received\n");
return;
}
// Get an IPortableDeviceServiceMethods interface from the IPortableDeviceService interface to
// invoke methods.
hr = pService->Methods(&pMethods);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceServiceMethods from IPortableDeviceService, hr = 0x%lx\n",hr);
}
// Invoke() the BeginSync method
if (SUCCEEDED(hr))
{
// This method does not take any parameters or results, so we pass in NULL
hr = pMethods->Invoke(METHOD_FullEnumSyncSvc_BeginSync, NULL, NULL);
if (SUCCEEDED(hr))
{
printf("%ws called, hr = 0x%lx\n",NAME_FullEnumSyncSvc_BeginSync, hr);
}
else
{
printf("! Failed to invoke %ws, hr = 0x%lx\n",NAME_FullEnumSyncSvc_BeginSync, hr);
}
}
// Invoke the EndSync method asynchronously
if (SUCCEEDED(hr))
{
// This method does not take any parameters or results, so we pass in NULL
hr = pMethods->Invoke(METHOD_FullEnumSyncSvc_EndSync, NULL, NULL);
if (SUCCEEDED(hr))
{
printf("%ws called, hr = 0x%lx\n",NAME_FullEnumSyncSvc_EndSync, hr);
}
else
{
printf("! Failed to invoke %ws, hr = 0x%lx\n",NAME_FullEnumSyncSvc_EndSync, hr);
}
}
}
HRESULT InvokeMethodAsync(
IPortableDeviceServiceMethods* pMethods,
REFGUID Method,
IPortableDeviceValues* pParameters)
{
HRESULT hr = S_OK;
// Cleanup any previously created global event handles.
if (g_hMethodCompleteEvent != NULL)
{
CloseHandle(g_hMethodCompleteEvent);
g_hMethodCompleteEvent = NULL;
}
// In order to create a simpler to follow example we create and wait infinitely
// for the method to complete and ignore any errors.
// Production code should be written in a more robust manner.
// Create the global event handle to wait on for the method to complete.
g_hMethodCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (g_hMethodCompleteEvent != NULL)
{
CMethodCallback* pCallback = new (std::nothrow) CMethodCallback();
if (pCallback == NULL)
{
hr = E_OUTOFMEMORY;
printf("! Failed to get allocate CMethodCallback, hr = 0x%lx\n",hr);
}
else
{
// Call InvokeAsync() to begin the Asynchronous method operation.
// Each pCallback parameter is used as the method context, and therefore must be unique.
hr = pMethods->InvokeAsync(Method, pParameters, pCallback);
if(FAILED(hr))
{
printf("! Failed to invoke method asynchronously, hr = 0x%lx\n", hr);
}
else
{
// In order to create a simpler to follow example we will wait infinitly for the operation
// to complete and ignore any errors. Production code should be written in a more
// robust manner.
if (g_hMethodCompleteEvent != NULL)
{
WaitForSingleObject(g_hMethodCompleteEvent, INFINITE);
}
}
}
// Cleanup previously created callback interface
if (pCallback)
{
pCallback->Release();
pCallback = NULL;
}
// Cleanup any previously created global event handles.
if (g_hMethodCompleteEvent != NULL)
{
CloseHandle(g_hMethodCompleteEvent);
g_hMethodCompleteEvent = NULL;
}
}
else
{
printf("! Failed to create the global event handle to wait on for the method operation. Aborting operation.\n");
}
return hr;
}
// Invoke methods on the Contacts Service asynchornously.
// BeginSync and EndSync are methods defined by the FullEnumerationSync Device Service.
void InvokeMethodsAsync(IPortableDeviceService* pService)
{
HRESULT hr = S_OK;
CComPtr<IPortableDeviceServiceMethods> pMethods;
if (pService == NULL)
{
printf("! A NULL IPortableDeviceService interface pointer was received\n");
return;
}
// Get an IPortableDeviceServiceMethods interface from the IPortableDeviceService interface to
// invoke methods.
hr = pService->Methods(&pMethods);
if (FAILED(hr))
{
printf("! Failed to get IPortableDeviceServiceMethods from IPortableDeviceService, hr = 0x%lx\n",hr);
}
// Invoke the BeginSync method asynchronously
if (SUCCEEDED(hr))
{
printf("Invoking %ws asynchronously...\n",NAME_FullEnumSyncSvc_BeginSync);
// This method does not take any parameters, so we pass in NULL
hr = InvokeMethodAsync(pMethods, METHOD_FullEnumSyncSvc_BeginSync, NULL);
if (FAILED(hr))
{
printf("! Failed to invoke %ws asynchronously, hr = 0x%lx\n",NAME_FullEnumSyncSvc_BeginSync, hr);
}
}
// Invoke the EndSync method asynchronously
if (SUCCEEDED(hr))
{
printf("Invoking %ws asynchronously...\n",NAME_FullEnumSyncSvc_EndSync);
hr = InvokeMethodAsync(pMethods, METHOD_FullEnumSyncSvc_EndSync, NULL);
if (FAILED(hr))
{
printf("! Failed to invoke %ws asynchronously, hr = 0x%lx\n",NAME_FullEnumSyncSvc_EndSync, hr);
}
}
}