513 lines
12 KiB
C++
513 lines
12 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"
|
|
#include "Resource.h"
|
|
#include "util.h"
|
|
#include <upnp.h> // For the error codes
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseObj
|
|
//
|
|
// Purpose: Releases the COM interface pointer
|
|
//
|
|
// Arguments:
|
|
// pInterface [in] Interface pointer to be released
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
|
|
void ReleaseObj(_In_ IUnknown* pInterface){
|
|
if(pInterface){
|
|
pInterface->Release();
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: PrintErrorText
|
|
//
|
|
// Purpose: Prints the appropriate error text
|
|
//
|
|
// Arguments:
|
|
// hr [in] HRESULT to check
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Notes:
|
|
// The upnp error codes are from upnp.h
|
|
//
|
|
|
|
void PrintErrorText(_In_ HRESULT hr){
|
|
|
|
// First check whether it is a UPnP error
|
|
WCHAR wszErrorString[1024] = {0};
|
|
switch(hr){
|
|
// All the upnp error codes are from upnp.h
|
|
case UPNP_E_ROOT_ELEMENT_EXPECTED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Root Element Expected",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_DEVICE_ELEMENT_EXPECTED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Device Element Expected",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_SERVICE_ELEMENT_EXPECTED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Service Element Expected",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_SERVICE_NODE_INCOMPLETE:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Service Node Incomplete",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_DEVICE_NODE_INCOMPLETE:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Device Node Incomplete",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_ICON_ELEMENT_EXPECTED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Icon Element Expected",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_ICON_NODE_INCOMPLETE:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Icon Node Incomplete",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_INVALID_ACTION:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Invalid Action",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_INVALID_ARGUMENTS:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Invalid Arguments",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_OUT_OF_SYNC:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Out of Sync",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_ACTION_REQUEST_FAILED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Action Request Failed",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_TRANSPORT_ERROR:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Transport Error",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_VARIABLE_VALUE_UNKNOWN:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Variable Value Unknown",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_INVALID_VARIABLE:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Invalid Variable",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_DEVICE_ERROR:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Device Error",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_PROTOCOL_ERROR:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Protocol Error",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_ERROR_PROCESSING_RESPONSE:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Error Processing Response",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_DEVICE_TIMEOUT:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Device Timeout",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_INVALID_DOCUMENT:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Invalid Document",
|
|
1024
|
|
);
|
|
break;
|
|
case UPNP_E_EVENT_SUBSCRIPTION_FAILED:
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Event Subscription Failed",
|
|
1024
|
|
);
|
|
break;
|
|
default:
|
|
if ((hr>=UPNP_E_ACTION_SPECIFIC_BASE) &&
|
|
(hr <= UPNP_E_ACTION_SPECIFIC_MAX))
|
|
{
|
|
SafeStrCopy(
|
|
wszErrorString,
|
|
L"Action Specific Error",
|
|
1024
|
|
);
|
|
break;
|
|
}
|
|
_snwprintf_s(
|
|
wszErrorString,
|
|
1024,
|
|
_TRUNCATE,
|
|
L"An error has occured.\n\nError Code: 0x%x",
|
|
hr
|
|
);
|
|
}
|
|
MessageBox( NULL, (LPCWSTR)wszErrorString, L"Error", MB_OK );
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrCreateSafeArray
|
|
//
|
|
// Purpose: Creates a SafeArray
|
|
//
|
|
// Arguments:
|
|
// vt [in] VariantType
|
|
// nArgs [in] Number of Arguments
|
|
// ppsa [out] Created safearray
|
|
//
|
|
// Returns: S_OK or E_OUTOFMEMORY
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
HRESULT HrCreateSafeArray(_In_ VARTYPE vt, _In_ int nArgs, _Outptr_ SAFEARRAY **ppsa)
|
|
{
|
|
SAFEARRAYBOUND aDim[1];
|
|
|
|
if(0 == nArgs){
|
|
aDim[0].lLbound = 0;
|
|
aDim[0].cElements = 0;
|
|
}
|
|
else{
|
|
aDim[0].lLbound = 1;
|
|
aDim[0].cElements = nArgs;
|
|
}
|
|
|
|
*ppsa = SafeArrayCreate(vt, 1, aDim);
|
|
if(NULL == *ppsa){
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrCreateArgVariants
|
|
//
|
|
// Purpose: Creates argument variants
|
|
//
|
|
// Arguments:
|
|
// dwArgs [in] Number of arguments
|
|
// pppVars [out] Variant array
|
|
//
|
|
// Returns: S_OK or E_OUTOFMEMORY
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
_When_(dwArgs == 0, _At_(*pppVars, _Post_null_))
|
|
_When_(dwArgs > 0, _At_(*pppVars, _Post_notnull_))
|
|
HRESULT HrCreateArgVariants(_In_ DWORD dwArgs, _Outptr_result_buffer_maybenull_(dwArgs) VARIANT*** pppVars)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD i = 0;
|
|
|
|
if(0 == dwArgs){
|
|
*pppVars = NULL;
|
|
return hr;
|
|
}
|
|
*pppVars = new VARIANT* [dwArgs];
|
|
if(NULL == *pppVars){
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
ZeroMemory(*pppVars, dwArgs*sizeof(VARIANT *));
|
|
|
|
for(i = 0; i < dwArgs; i++){
|
|
(*pppVars)[i] = new VARIANT;
|
|
if(NULL == (*pppVars)[i])
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto error;
|
|
}
|
|
VariantInit((*pppVars)[i]);
|
|
}
|
|
|
|
goto exit;
|
|
|
|
error:
|
|
for(i = 0; i < dwArgs; i++)
|
|
{
|
|
if( NULL != (*pppVars)[i] )
|
|
{
|
|
delete ((*pppVars)[i]);
|
|
(*pppVars)[i] = NULL;
|
|
}
|
|
}
|
|
delete [] *pppVars;
|
|
*pppVars = NULL;
|
|
|
|
exit:
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrDestroyArgVariants
|
|
//
|
|
// Purpose: Destroys argument variants
|
|
//
|
|
// Arguments:
|
|
// dwArgs [in] Number of arguments
|
|
// pppVars [in,out] Variant array
|
|
//
|
|
// Returns: S_OK
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
HRESULT HrDestroyArgVariants(_In_ DWORD dwArgs, _Inout_ _At_(*pppVars, _Pre_writable_size_(dwArgs) _Post_maybenull_) VARIANT*** pppVars)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VARIANT *pVar = NULL;
|
|
|
|
ASSERT(pppVars && *pppVars);
|
|
if(0 == dwArgs)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
for(DWORD i = 0; i < dwArgs; i++)
|
|
{
|
|
pVar = (*pppVars)[i];
|
|
if(NULL != pVar)
|
|
{
|
|
VariantClear(pVar);
|
|
delete pVar;
|
|
pVar = NULL;;
|
|
}
|
|
}
|
|
|
|
delete [] *pppVars;
|
|
*pppVars = NULL;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: VariantSetVar
|
|
//
|
|
// Purpose: Sets the variant value to given variant
|
|
//
|
|
// Arguments:
|
|
// pvarToSet [in] Variant which is used to set
|
|
// va [in,out] Variant to set
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
|
|
void VariantSetVar(_In_ VARIANT* pvarToSet, _Inout_ VARIANT& va)
|
|
{
|
|
VariantInit(&va);
|
|
va.vt = VT_VARIANT | VT_BYREF;
|
|
va.pvarVal = pvarToSet;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: VariantSetArray
|
|
//
|
|
// Purpose: Sets the variant value to given array
|
|
//
|
|
// Arguments:
|
|
// psa [in] SafeArray
|
|
// va [in,out] Variant which is being set
|
|
//
|
|
// Returns: None
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
void VariantSetArray(_In_ SAFEARRAY* psa, _Inout_ VARIANT& va)
|
|
{
|
|
VariantInit(&va);
|
|
va.vt = VT_VARIANT | VT_ARRAY | VT_BYREF;
|
|
va.pparray = &psa;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrGetSafeArrayBounds
|
|
//
|
|
// Purpose: Get SafeArray bounds
|
|
//
|
|
// Arguments:
|
|
// psa [in] SafeArray
|
|
// plLBound [out] Lower bound
|
|
// plUBound [out] Upper bound
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
HRESULT HrGetSafeArrayBounds(_In_ SAFEARRAY *psa, _Out_ long* plLBound, _Out_ long* plUBound)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(NULL == psa)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
hr = SafeArrayGetLBound(psa, 1, plLBound);
|
|
if(FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
hr = SafeArrayGetUBound(psa, 1, plUBound);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrGetVariantElement
|
|
//
|
|
// Purpose: Get Variant Element
|
|
//
|
|
// Arguments:
|
|
// psa [in] SafeArray
|
|
// lPosition [in] Position in the array
|
|
// pvar [out] Variant Element being set
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
HRESULT HrGetVariantElement(_In_ SAFEARRAY *psa, _In_ int lPosition, _Out_ VARIANT* pvar)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
long alPos[1];
|
|
|
|
if(NULL == psa)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
alPos[0] = lPosition;
|
|
|
|
hr = SafeArrayGetElement(psa,
|
|
alPos,
|
|
pvar);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: SafeStrCopy
|
|
//
|
|
// Purpose : Does a Safe string copy using wcsncpy. We will always get a NULL
|
|
// terminated string with this.
|
|
//
|
|
// Argument:
|
|
// src [in/out] Buffer into which string is to be copied.
|
|
// dst [in] Buffer to copy from.
|
|
// srcBufLen [in] Size of the source buffer.
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// Notes:
|
|
//
|
|
//
|
|
|
|
void SafeStrCopy(_Out_writes_(srcBufLen) LPWSTR src, _In_ LPCWSTR dst, _In_ size_t srcBufLen)
|
|
{
|
|
ASSERT(src != NULL);
|
|
ASSERT(dst != NULL);
|
|
ASSERT(srcBufLen != 0);
|
|
|
|
wcsncpy_s(src, srcBufLen, dst, (srcBufLen - 1));
|
|
|
|
}
|