///////////////////////////////////////////////////////////////////////////// // InvokeArgs.cpp | Implementation of the TCInvokeArgs class. #include "pch.h" #include #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); } } }