700 lines
17 KiB
C++
700 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.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Public Headers
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <strsafe.h>
|
|
|
|
// Sample Headers
|
|
#include "CUPnPSimpleThermostatProxy.h"
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
const WCHAR GETCURRENTTEMP_FUNC[] = L"GetCurrentTemp";
|
|
const WCHAR GETDESIREDTEMP_FUNC[] = L"GetDesiredTemp";
|
|
const WCHAR SETDESIREDTEMP_FUNC[] = L"SetDesiredTemp";
|
|
const WCHAR DEVICE_SERVICE[] = L"urn:upnp-org:serviceId:ISimpleThermostatUPnPService";
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CreateCUPnPSimpleThermostatProxy
|
|
// This is essentially the factory method for the
|
|
// CUPnPSimpleThermostatProxy class. It takes a property store that's
|
|
// expected to have come from an FD Function Instance.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CreateCUPnPSimpleThermostatProxy(
|
|
IPropertyStore* pPropertyStore,
|
|
ISimpleThermostat** ppSimpleThermostat
|
|
)
|
|
{
|
|
BSTR bstrDeviceID = NULL;
|
|
BSTR bstrXMLDocURL = NULL;
|
|
HRESULT hr = S_OK;
|
|
IUPnPDescriptionDocument* pUPnPDescription = NULL;
|
|
IUPnPDevice* pUPnPDevice = NULL;
|
|
PROPVARIANT pvDeviceID = {0};
|
|
PROPVARIANT pvXMLDocURL = {0};
|
|
CUPnPSimpleThermostatProxy* pCUPnPSimpleThermostatProxy = NULL;
|
|
|
|
if( NULL == pPropertyStore ||
|
|
NULL == ppSimpleThermostat )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
wprintf( L"GetValue of PKEY_PNPX_GlobalIdentity (device host id)..." );
|
|
hr = pPropertyStore->GetValue( PKEY_PNPX_GlobalIdentity, &pvDeviceID );
|
|
wprintf( L"0x%x\n", hr );
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"Device Host ID: %s\n", pvDeviceID.pwszVal );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"GetValue of PKEY_Device_LocationInfo (Description Doc URL)..." );
|
|
hr = pPropertyStore->GetValue( PKEY_Device_LocationInfo, &pvXMLDocURL );
|
|
wprintf( L"0x%x\n", hr );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"Description Doc URL: %s\n", pvXMLDocURL.pwszVal );
|
|
}
|
|
|
|
//
|
|
// Create the description document object that'll be use to obtain the
|
|
// IUPnPDevice object
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"CoCreate the UPnPDescriptionDocument object..." );
|
|
hr = CoCreateInstance(
|
|
CLSID_UPnPDescriptionDocument,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUPnPDescriptionDocument,
|
|
reinterpret_cast<void**>(&pUPnPDescription)
|
|
);
|
|
wprintf( L"0x%x\n", hr );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
bstrXMLDocURL = SysAllocString( pvXMLDocURL.pwszVal );
|
|
if( NULL == bstrXMLDocURL )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load the description document
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"Load the device's description document..." );
|
|
hr = pUPnPDescription->Load( bstrXMLDocURL );
|
|
wprintf( L"0x%x\n", hr );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
bstrDeviceID = SysAllocString( pvDeviceID.pwszVal );
|
|
if( NULL == bstrDeviceID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the upnp device object
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"Get the UPnPDevice object from UPnP..." );
|
|
hr = pUPnPDescription->DeviceByUDN( bstrDeviceID, &pUPnPDevice );
|
|
wprintf( L"0x%x\n", hr );
|
|
}
|
|
|
|
//
|
|
// Create the CUPnPSimpleThermostatProxy object and hand it
|
|
// the UPnPDevice object.
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
wprintf( L"Creating the CUPnPSimpleThermostatProxy object..." );
|
|
pCUPnPSimpleThermostatProxy = new CUPnPSimpleThermostatProxy( pUPnPDevice );
|
|
if( NULL == pCUPnPSimpleThermostatProxy )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
wprintf( L"0x%x\n", hr );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
*ppSimpleThermostat = static_cast<ISimpleThermostat*>(pCUPnPSimpleThermostatProxy);
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
PropVariantClear( &pvDeviceID );
|
|
PropVariantClear( &pvXMLDocURL );
|
|
|
|
if( NULL != pUPnPDevice )
|
|
{
|
|
pUPnPDevice->Release();
|
|
pUPnPDevice = NULL;
|
|
}
|
|
|
|
if( NULL != bstrDeviceID )
|
|
{
|
|
SysFreeString( bstrDeviceID );
|
|
bstrDeviceID = NULL;
|
|
}
|
|
|
|
if( NULL != bstrXMLDocURL )
|
|
{
|
|
SysFreeString( bstrXMLDocURL );
|
|
bstrDeviceID = NULL;
|
|
}
|
|
|
|
if( NULL != pUPnPDescription )
|
|
{
|
|
pUPnPDescription->Release();
|
|
pUPnPDescription = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}// CreateCUPnPSimpleThermostatProxy
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::CUPnPSimpleThermostatProxy (Constructor)
|
|
//------------------------------------------------------------------------------
|
|
CUPnPSimpleThermostatProxy::CUPnPSimpleThermostatProxy( IUPnPDevice* pUPnPDevice ):
|
|
m_cRef(1)
|
|
{
|
|
pUPnPDevice->AddRef();
|
|
m_pUPnPDevice = pUPnPDevice;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::~CUPnPSimpleThermostatProxy (Destructor)
|
|
//------------------------------------------------------------------------------
|
|
CUPnPSimpleThermostatProxy::~CUPnPSimpleThermostatProxy()
|
|
{
|
|
if( NULL != m_pUPnPDevice )
|
|
{
|
|
m_pUPnPDevice->Release();
|
|
m_pUPnPDevice = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ISimpleThermostat
|
|
//
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::GetCurrentTemp
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CUPnPSimpleThermostatProxy::GetCurrentTemp(
|
|
LONG* plTemp
|
|
)
|
|
{
|
|
BSTR bstrFunc = NULL;
|
|
BSTR bstrServiceID = NULL;
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAYBOUND inArgsBound[1];
|
|
IUPnPService* pService = NULL;
|
|
IUPnPServices* pServices = NULL;
|
|
SAFEARRAY* psaInArgs = NULL;
|
|
SAFEARRAY* psaOutArgs = NULL;
|
|
LONG rgIndices[1] = {0};
|
|
VARIANT varInArgs = {0};
|
|
VARIANT varOutArgs = {0};
|
|
VARIANT varRet = {0};
|
|
VARIANT varTemp = {0};
|
|
|
|
|
|
if( NULL == plTemp )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
bstrFunc = SysAllocString( GETCURRENTTEMP_FUNC );
|
|
bstrServiceID = SysAllocString( DEVICE_SERVICE );
|
|
if( NULL == bstrFunc ||
|
|
NULL == bstrServiceID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
VariantInit( &varInArgs );
|
|
VariantInit( &varOutArgs );
|
|
VariantInit( &varRet );
|
|
VariantInit( &varTemp );
|
|
|
|
//
|
|
// Grab all the services on the device
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = m_pUPnPDevice->get_Services( &pServices );
|
|
}
|
|
|
|
//
|
|
// Get the ISimpleThermostatUPnPService service
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pServices->get_Item( bstrServiceID, &pService );
|
|
}
|
|
|
|
//
|
|
// Build the arguments to pass to the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
inArgsBound[0].lLbound = 0;
|
|
inArgsBound[0].cElements = 0;
|
|
|
|
psaInArgs = SafeArrayCreate( VT_VARIANT, 1, inArgsBound );
|
|
if( NULL == psaInArgs )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
varInArgs.vt = VT_VARIANT | VT_ARRAY;
|
|
V_ARRAY( &varInArgs ) = psaInArgs;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Invoke the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pService->InvokeAction( bstrFunc, varInArgs, &varOutArgs, &varRet );
|
|
if( S_OK != hr )
|
|
{
|
|
LONG lStatus;
|
|
pService->get_LastTransportStatus( &lStatus );
|
|
wprintf( L"InvokeAction failed...%d...", lStatus );
|
|
}
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
psaOutArgs = V_ARRAY( &varOutArgs );
|
|
rgIndices[0] = 0;
|
|
|
|
hr = SafeArrayGetElement(
|
|
psaOutArgs,
|
|
rgIndices,
|
|
(void*)&varTemp
|
|
);
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
*plTemp = varTemp.ulVal;
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
VariantClear( &varRet );
|
|
VariantClear( &varTemp );
|
|
|
|
if( NULL != psaInArgs )
|
|
{
|
|
SafeArrayDestroy( psaInArgs );
|
|
psaInArgs = NULL;
|
|
}
|
|
|
|
if( NULL != psaOutArgs )
|
|
{
|
|
SafeArrayDestroy( psaOutArgs );
|
|
psaInArgs = NULL;
|
|
}
|
|
|
|
if( NULL != pService )
|
|
{
|
|
pService->Release();
|
|
pService = NULL;
|
|
}
|
|
|
|
if( NULL != pServices )
|
|
{
|
|
pServices->Release();
|
|
pServices = NULL;
|
|
}
|
|
|
|
if( NULL != bstrServiceID )
|
|
{
|
|
SysFreeString( bstrServiceID );
|
|
bstrServiceID = NULL;
|
|
}
|
|
|
|
if( NULL != bstrFunc )
|
|
{
|
|
SysFreeString( bstrFunc );
|
|
bstrFunc = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}// CUPnPSimpleThermostatProxy::GetCurrentTemp
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::GetDesiredTemp
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CUPnPSimpleThermostatProxy::GetDesiredTemp(
|
|
LONG* plTemp
|
|
)
|
|
{
|
|
BSTR bstrFunc = NULL;
|
|
BSTR bstrServiceID = NULL;
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAYBOUND inArgsBound[1];
|
|
IUPnPService* pService = NULL;
|
|
IUPnPServices* pServices = NULL;
|
|
SAFEARRAY* psaInArgs = NULL;
|
|
SAFEARRAY* psaOutArgs = NULL;
|
|
LONG rgIndices[1] = {0};
|
|
VARIANT varInArgs = {0};
|
|
VARIANT varOutArgs = {0};
|
|
VARIANT varRet = {0};
|
|
VARIANT varTemp = {0};
|
|
|
|
|
|
if( NULL == plTemp )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
bstrFunc = SysAllocString( GETDESIREDTEMP_FUNC );
|
|
bstrServiceID = SysAllocString( DEVICE_SERVICE );
|
|
if( NULL == bstrFunc ||
|
|
NULL == bstrServiceID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
VariantInit( &varInArgs );
|
|
VariantInit( &varOutArgs );
|
|
VariantInit( &varRet );
|
|
VariantInit( &varTemp );
|
|
|
|
//
|
|
// Grab all the services on the device
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = m_pUPnPDevice->get_Services( &pServices );
|
|
}
|
|
|
|
//
|
|
// Get the ISimpleThermostatUPnPService service
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pServices->get_Item( bstrServiceID, &pService );
|
|
}
|
|
|
|
//
|
|
// Build the arguments to pass to the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
inArgsBound[0].lLbound = 0;
|
|
inArgsBound[0].cElements = 0;
|
|
|
|
psaInArgs = SafeArrayCreate( VT_VARIANT, 1, inArgsBound );
|
|
if( NULL == psaInArgs )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
varInArgs.vt = VT_VARIANT | VT_ARRAY;
|
|
V_ARRAY( &varInArgs ) = psaInArgs;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Invoke the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pService->InvokeAction( bstrFunc, varInArgs, &varOutArgs, &varRet );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
psaOutArgs = V_ARRAY( &varOutArgs );
|
|
rgIndices[0] = 0;
|
|
|
|
hr = SafeArrayGetElement(
|
|
psaOutArgs,
|
|
rgIndices,
|
|
(void*)&varTemp
|
|
);
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
*plTemp = varTemp.ulVal;
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
VariantClear( &varRet );
|
|
VariantClear( &varTemp );
|
|
|
|
if( NULL != psaInArgs )
|
|
{
|
|
SafeArrayDestroy( psaInArgs );
|
|
psaInArgs = NULL;
|
|
}
|
|
|
|
if( NULL != psaOutArgs )
|
|
{
|
|
SafeArrayDestroy( psaOutArgs );
|
|
psaInArgs = NULL;
|
|
}
|
|
|
|
if( NULL != pService )
|
|
{
|
|
pService->Release();
|
|
pService = NULL;
|
|
}
|
|
|
|
if( NULL != pServices )
|
|
{
|
|
pServices->Release();
|
|
pServices = NULL;
|
|
}
|
|
|
|
if( NULL != bstrServiceID )
|
|
{
|
|
SysFreeString( bstrServiceID );
|
|
bstrServiceID = NULL;
|
|
}
|
|
|
|
if( NULL != bstrFunc )
|
|
{
|
|
SysFreeString( bstrFunc );
|
|
bstrFunc = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}// CUPnPSimpleThermostatProxy::GetDesiredTemp
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::SetDesiredTemp
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CUPnPSimpleThermostatProxy::SetDesiredTemp(
|
|
LONG lTemp
|
|
)
|
|
{
|
|
BSTR bstrFunc = NULL;
|
|
BSTR bstrServiceID = NULL;
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAYBOUND inArgsBound[1];
|
|
IUPnPService* pService = NULL;
|
|
IUPnPServices* pServices = NULL;
|
|
SAFEARRAY* psaInArgs = NULL;
|
|
LONG rgIndices[1] = {0};
|
|
VARIANT varInArgs = {0};
|
|
VARIANT varOutArgs = {0};
|
|
VARIANT varRet = {0};
|
|
VARIANT varTemp = {0};
|
|
|
|
|
|
bstrFunc = SysAllocString( SETDESIREDTEMP_FUNC );
|
|
bstrServiceID = SysAllocString( DEVICE_SERVICE );
|
|
if( NULL == bstrFunc ||
|
|
NULL == bstrServiceID )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
VariantInit( &varInArgs );
|
|
VariantInit( &varOutArgs );
|
|
VariantInit( &varRet );
|
|
VariantInit( &varTemp );
|
|
|
|
//
|
|
// Grab all the services on the device
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = m_pUPnPDevice->get_Services( &pServices );
|
|
}
|
|
|
|
//
|
|
// Get the ISimpleThermostatUPnPService service
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pServices->get_Item( bstrServiceID, &pService );
|
|
}
|
|
|
|
//
|
|
// Build the arguments to pass to the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
inArgsBound[0].lLbound = 0;
|
|
inArgsBound[0].cElements = 1;
|
|
|
|
psaInArgs = SafeArrayCreate( VT_VARIANT, 1, inArgsBound );
|
|
if( NULL == psaInArgs )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
varTemp.vt = VT_I4;
|
|
varTemp.ulVal = lTemp;
|
|
hr = SafeArrayPutElement( psaInArgs, rgIndices, (void*)&varTemp );
|
|
}
|
|
|
|
if( S_OK == hr )
|
|
{
|
|
varInArgs.vt = VT_VARIANT | VT_ARRAY;
|
|
V_ARRAY( &varInArgs ) = psaInArgs;
|
|
}
|
|
|
|
//
|
|
// Invoke the function
|
|
//
|
|
if( S_OK == hr )
|
|
{
|
|
hr = pService->InvokeAction( bstrFunc, varInArgs, &varOutArgs, &varRet );
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
VariantClear( &varOutArgs );
|
|
VariantClear( &varRet );
|
|
VariantClear( &varTemp );
|
|
|
|
if( NULL != psaInArgs )
|
|
{
|
|
SafeArrayDestroy( psaInArgs );
|
|
psaInArgs = NULL;
|
|
}
|
|
|
|
if( NULL != pService )
|
|
{
|
|
pService->Release();
|
|
pService = NULL;
|
|
}
|
|
|
|
if( NULL != pServices )
|
|
{
|
|
pServices->Release();
|
|
pServices = NULL;
|
|
}
|
|
|
|
if( NULL != bstrServiceID )
|
|
{
|
|
SysFreeString( bstrServiceID );
|
|
bstrServiceID = NULL;
|
|
}
|
|
|
|
if( NULL != bstrFunc )
|
|
{
|
|
SysFreeString( bstrFunc );
|
|
bstrFunc = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}// CUPnPSimpleThermostatProxy::SetDesiredTemp
|
|
|
|
|
|
//
|
|
// IUnknown
|
|
//
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::QueryInterface
|
|
//------------------------------------------------------------------------------
|
|
HRESULT CUPnPSimpleThermostatProxy::QueryInterface(
|
|
REFIID riid,
|
|
void** ppvObject
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if( NULL == ppvObject )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppvObject = NULL;
|
|
|
|
if( __uuidof(ISimpleThermostat) == riid )
|
|
{
|
|
*ppvObject = static_cast<ISimpleThermostat*>(this);
|
|
AddRef();
|
|
}
|
|
else if( __uuidof(IUnknown) == riid )
|
|
{
|
|
*ppvObject = static_cast<IUnknown*>(this);
|
|
AddRef();
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
return hr;
|
|
}// CUPnPSimpleThermostatProxy::QueryInterface
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::AddRef
|
|
//------------------------------------------------------------------------------
|
|
ULONG CUPnPSimpleThermostatProxy::AddRef()
|
|
{
|
|
return InterlockedIncrement( &m_cRef );
|
|
}// CUPnPSimpleThermostatProxy::AddRef
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// CUPnPSimpleThermostatProxy::Release
|
|
//------------------------------------------------------------------------------
|
|
ULONG CUPnPSimpleThermostatProxy::Release()
|
|
{
|
|
LONG lRef = InterlockedDecrement( &m_cRef );
|
|
|
|
if( 0 == lRef )
|
|
{
|
|
delete this;
|
|
}
|
|
return lRef;
|
|
}// CUPnPSimpleThermostatProxy::Release
|