/////////////////////////////////////////////////////////////////////////////
// InvokeArgs.cpp | Implementation of the TCInvokeArgs class.
#include "pch.h"
#include <TCLib.h>
#include "InvokeArgs.h"
/////////////////////////////////////////////////////////////////////////////
// TCInvokeArgs
/////////////////////////////////////////////////////////////////////////////
// Group=Construction / Destruction
/////////////////////////////////////////////////////////////////////////////
// Deletes the dispatch arguments structure, if one was created.
//
// See Also: TCInvokeArgs::SetDispParams
TCInvokeArgs::~TCInvokeArgs()
{
if (rgvarg)
Empty();
}
/////////////////////////////////////////////////////////////////////////////
// Group=Operations
/////////////////////////////////////////////////////////////////////////////
// Description: Invoke method.
//
// This method calls *Invoke* on the specified *IDispatch* pointer,
// specifying m_dispid as the dispatch ID, and passing
// the arguments specified in a prior call to SetDispParams.
//
// Parameters:
// pdisp - The *IDispatch* pointer on which to call *Invoke*.
//
// Return Value: The HRESULT of the *IDispatch::Invoke* call is returned.
//
// See Also: TCInvokeArgs::SetDispParams, TCInvokeArgs::m_dispid
HRESULT TCInvokeArgs::Invoke(IDispatch* pdisp, VARIANT* pvarResult)
{
HRESULT hr = S_OK;
if (NULL != pdisp)
{
__try
{
// Invoke the dispatch method
hr = pdisp->Invoke(m_dispid, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, this, pvarResult, NULL, NULL);
}
__except(1)
{
hr = E_UNEXPECTED;
}
}
// Return the last HRESULT
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// Group=Attributes
/////////////////////////////////////////////////////////////////////////////
// Description: Sets the dispatch ID and dispatch parameters for subsequent
// *Invoke* calls.
//
// This method saves the specified /dispid/ and creates an array of
// *VARIANTARG* structures suitable for use with the
// *IDispatch::Invoke* method.
//
// For each pair of arguments in the specified variable argument list,
// /argptr/, a *VARIANTARG* is created and initialized. The *VARIANTARG* is
// then assigned the variant type and variant value specified in the argument
// pair. So, for example, the following would set three dispatch parameters,
// of types *VT_BOOL*, *VT_I4*, and *VT_BSTR* to *VARIANT_TRUE*, 137, and
// "Hello", respectively:
//
// CComBSTR bstrText("Hello");
// pCall->SetDispParams(DISPID_HELLO, 3, VT_BOOL, VARIANT_TRUE,
// VT_I4, 137, VT_BSTR, bstrText);
//
// Note: Notice that although 3 is specified as the /cArgs/ parameter, the
// variable argument list contains six actual parameters. This is because for
// each argument specified in /cArgs/, an argument /pair/ is implied, since
// each dispatch argument has a variant type and value.
//
// Parameters:
// dispid - The dispatch ID used in subsequent *Invoke* calls.
// cArgs - The number of dispatch arguments specified in the variable
// argument list.
// argptr - The standardized representation of a variable argument list.
//
// See Also: TCInvokeArgs::SetDispParams, TCInvokeArgs::Invoke
void TCInvokeArgs::SetDispParamsV(DISPID dispid, UINT nArgs, va_list argptr)
{
// Reinitialize
if (rgvarg)
Empty();
// Save the specified dispatch id
m_dispid = dispid;
// Return immediately if 0 arguments specified
if (!nArgs)
return;
// Create the VARIANTARG array with the specified number of arguments
rgvarg = new VARIANTARG[cArgs = nArgs];
// Loop thru each argument and initialize the VARIANTARG array element
while (nArgs--)
{
VariantInit(&rgvarg[nArgs]);
VARTYPE vt = va_arg(argptr, VARTYPE);
switch (V_VT(&rgvarg[nArgs]) = vt)
{
case VT_BOOL:
V_BOOL(&rgvarg[nArgs]) = va_arg(argptr, VARIANT_BOOL);
break;
case VT_I1:
V_I1(&rgvarg[nArgs]) = va_arg(argptr, CHAR);
break;
case VT_I2:
V_I2(&rgvarg[nArgs]) = va_arg(argptr, SHORT);
break;
case VT_I4:
V_I4(&rgvarg[nArgs]) = va_arg(argptr, LONG);
break;
case VT_UI1:
V_UI1(&rgvarg[nArgs]) = va_arg(argptr, BYTE);
break;
case VT_UI2:
V_UI2(&rgvarg[nArgs]) = va_arg(argptr, USHORT);
break;
case VT_ERROR:
V_ERROR(&rgvarg[nArgs]) = va_arg(argptr, SCODE);
break;
case VT_R4:
{
// ... pushes a float argument onto the stack as a double
DOUBLE dblTemp = va_arg(argptr, DOUBLE);
V_R4(&rgvarg[nArgs]) = (float)dblTemp;
break;
}
case VT_R8:
V_R8(&rgvarg[nArgs]) = va_arg(argptr, DOUBLE);
break;
case VT_DECIMAL:
V_DECIMAL(&rgvarg[nArgs]) = va_arg(argptr, DECIMAL);
break;
case VT_CY:
V_CY(&rgvarg[nArgs]) = va_arg(argptr, CY);
break;
case VT_DATE:
V_DATE(&rgvarg[nArgs]) = va_arg(argptr, DATE);
break;
case VT_BSTR:
V_BSTR(&rgvarg[nArgs]) = va_arg(argptr, BSTR);
break;
case VT_UNKNOWN:
V_UNKNOWN(&rgvarg[nArgs]) = va_arg(argptr, IUnknown*);
break;
case VT_DISPATCH:
V_DISPATCH(&rgvarg[nArgs]) = va_arg(argptr, IDispatch*);
break;
case VT_VARIANT:
V_VARIANTREF(&rgvarg[nArgs]) = va_arg(argptr, VARIANT*);
break;
default:
if (vt & VT_BYREF)
{
V_BYREF(&rgvarg[nArgs]) = va_arg(argptr, void*);
break;
}
_TRACE0("TCInvokeArgs::SetDispParamsV(): ");
_TRACE2("Specified VARTYPE %hu (0x%04X) is unsupported\n", vt, vt);
_ASSERT(false);
}
}
}