mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1035 lines
22 KiB
1035 lines
22 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: disputil.cxx
|
|
//
|
|
// Contents: Dispatch Utilities.
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 21-Feb-94 adams Created
|
|
// 08-Apr-94 DonCl modified Set/GetDispProp to take REFIID
|
|
// to meet sysmgmt needs
|
|
// 25-Oct-94 KrishnaG appropriated from the ADs project
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "procs.hxx"
|
|
|
|
#define VT_TYPEMASK 0x3ff
|
|
|
|
|
|
static HRESULT VARIANTARGToCVar(VARIANTARG * pvarg, VARTYPE vt, void* pv);
|
|
static void CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg);
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeEXCEPINFO
|
|
//
|
|
// Synopsis: Frees resources in an excepinfo. Does not reinitialize
|
|
// these fields.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
FreeEXCEPINFO(EXCEPINFO * pEI)
|
|
{
|
|
if (pEI)
|
|
{
|
|
ADsFreeString(pEI->bstrSource);
|
|
ADsFreeString(pEI->bstrDescription);
|
|
ADsFreeString(pEI->bstrHelpFile);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ValidateInvoke
|
|
//
|
|
// Synopsis: Validates arguments to a call of IDispatch::Invoke. A call
|
|
// to this function takes less space than the function itself.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
ValidateInvoke(
|
|
DISPPARAMS * pdispparams,
|
|
VARIANT * pvarResult,
|
|
EXCEPINFO * pexcepinfo,
|
|
UINT * puArgErr)
|
|
{
|
|
if (pvarResult)
|
|
VariantInit(pvarResult);
|
|
|
|
if (pexcepinfo)
|
|
InitEXCEPINFO(pexcepinfo);
|
|
|
|
if (puArgErr)
|
|
*puArgErr = 0;
|
|
|
|
if (!pdispparams)
|
|
RRETURN(E_INVALIDARG);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: LoadTypeInfo
|
|
//
|
|
// Synopsis: Loads a typeinfo from a registered typelib.
|
|
//
|
|
// Arguments: [clsidTL] -- TypeLib GUID
|
|
// [clsidTI] -- TypeInfo GUID
|
|
// [ppTI] -- Resulting typeInfo
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
LoadTypeInfo(CLSID clsidTL, CLSID clsidTI, LPTYPEINFO *ppTI)
|
|
{
|
|
HRESULT hr;
|
|
ITypeLib * pTL;
|
|
|
|
ADsAssert(ppTI);
|
|
*ppTI = NULL;
|
|
hr = LoadRegTypeLib(clsidTL, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTL);
|
|
if (!SUCCEEDED(hr))
|
|
RRETURN(hr);
|
|
|
|
hr = pTL->GetTypeInfoOfGuid(clsidTI, ppTI);
|
|
pTL->Release();
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: VARIANTARGToCVar
|
|
//
|
|
// Synopsis: Converts a VARIANT to a C-language variable.
|
|
//
|
|
// Arguments: [pvarg] -- Variant to convert.
|
|
// [vt] -- Type to convert to.
|
|
// [pv] -- Location to place C-language variable.
|
|
//
|
|
// Modifies: [pv].
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
// Notes: Supports all variant pointer types, VT_I2, VT_I4, VT_R4,
|
|
// VT_R8.
|
|
//----------------------------------------------------------------------------
|
|
|
|
static HRESULT
|
|
VARIANTARGToCVar(VARIANT * pvarg, VARTYPE vt, void * pv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
VARIANTARG vargNew; // variant of new type
|
|
|
|
ADsAssert(pvarg);
|
|
ADsAssert(pv);
|
|
ADsAssert((vt & ~VT_TYPEMASK) == 0 || (vt & ~VT_TYPEMASK) == VT_BYREF);
|
|
|
|
if (vt & VT_BYREF)
|
|
{
|
|
if (V_VT(pvarg) != vt)
|
|
{
|
|
hr = DISP_E_TYPEMISMATCH;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Use a supported pointer type for derefencing.
|
|
vt = VT_UNKNOWN;
|
|
vargNew = *pvarg;
|
|
}
|
|
else
|
|
{
|
|
VariantInit(&vargNew);
|
|
hr = VariantChangeType(&vargNew, pvarg, 0, vt);
|
|
if (hr)
|
|
goto Cleanup;
|
|
}
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_BOOL:
|
|
if (V_BOOL(&vargNew) != VB_FALSE && V_BOOL(&vargNew) != VB_TRUE)
|
|
{
|
|
hr = E_FAIL; // BUGBUG: scode?
|
|
goto Cleanup;
|
|
}
|
|
|
|
// convert VT_TRUE to TRUE
|
|
*(BOOL *)pv = - V_BOOL(&vargNew);
|
|
break;
|
|
|
|
case VT_I2:
|
|
*(short *)pv = V_I2(&vargNew);
|
|
break;
|
|
|
|
case VT_I4:
|
|
*(long *)pv = V_I4(&vargNew);
|
|
break;
|
|
|
|
case VT_R4:
|
|
*(float *)pv = V_R4(&vargNew);
|
|
break;
|
|
|
|
case VT_R8:
|
|
*(double *)pv = V_R8(&vargNew);
|
|
break;
|
|
|
|
//
|
|
// All Pointer types.
|
|
//
|
|
case VT_BSTR:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
case VT_DISPATCH:
|
|
case VT_UNKNOWN:
|
|
*(void **)pv = V_BYREF(&vargNew);
|
|
break;
|
|
|
|
default:
|
|
ADsAssert(FALSE && "Unknown type in VARIANTARGToCVar().\n");
|
|
break;
|
|
}
|
|
|
|
Cleanup:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CVarToVARIANTARG
|
|
//
|
|
// Synopsis: Converts a C-language variable to a VARIANT.
|
|
//
|
|
// Arguments: [pv] -- Pointer to C-language variable.
|
|
// [vt] -- Type of C-language variable.
|
|
// [pvarg] -- Resulting VARIANT. Must be initialized by caller.
|
|
// Any contents will be freed.
|
|
//
|
|
// Modifies: [pvarg]
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
// Notes: Supports all variant pointer types, VT_UI2, VT_I2, VT_UI4,
|
|
// VT_I4, VT_R4, VT_R8.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
static void
|
|
CVarToVARIANTARG(void* pv, VARTYPE vt, VARIANTARG * pvarg)
|
|
{
|
|
ADsAssert(pv);
|
|
ADsAssert(pvarg);
|
|
|
|
VariantClear(pvarg);
|
|
|
|
V_VT(pvarg) = vt;
|
|
if (V_ISBYREF(pvarg))
|
|
{
|
|
// Use a supported pointer type for derefencing.
|
|
vt = VT_UNKNOWN;
|
|
}
|
|
|
|
switch (vt)
|
|
{
|
|
case VT_BOOL:
|
|
// convert TRUE to VT_TRUE
|
|
ADsAssert(*(BOOL *) pv == 1 || *(BOOL *) pv == 0);
|
|
V_BOOL(pvarg) = VARIANT_BOOL(-*(BOOL *) pv);
|
|
break;
|
|
|
|
case VT_I2:
|
|
V_I2(pvarg) = *(short *) pv;
|
|
break;
|
|
|
|
case VT_I4:
|
|
V_I4(pvarg) = *(long *) pv;
|
|
break;
|
|
|
|
case VT_R4:
|
|
V_R4(pvarg) = *(float *) pv;
|
|
break;
|
|
|
|
case VT_R8:
|
|
V_R8(pvarg) = *(double *) pv;
|
|
break;
|
|
|
|
//
|
|
// All Pointer types.
|
|
//
|
|
case VT_BSTR:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
case VT_DISPATCH:
|
|
case VT_UNKNOWN:
|
|
V_BYREF(pvarg) = *(long **)pv;
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE && "Unknown type.");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CParamsToDispParams
|
|
//
|
|
// Synopsis: Converts a C parameter list to a dispatch parameter list.
|
|
//
|
|
// Arguments: [pDispParams] -- Resulting dispatch parameter list.
|
|
// Note that the rgvarg member of pDispParams
|
|
// must be initialized with an array of
|
|
// EVENTPARAMS_MAX VARIANTs.
|
|
//
|
|
// [pvt] -- List of C parameter types. May be NULL.
|
|
// If not NULL, Last elem in list MUST be
|
|
// VT_EMPTY.
|
|
//
|
|
// [va] -- List of C arguments.
|
|
//
|
|
// Modifies: [pDispParams]
|
|
//
|
|
// History: 05-Jan-94 adams Created
|
|
// 23-Feb-94 adams Reversed order of disp arguments, added
|
|
// support for VT_R4, VT_R8, and pointer
|
|
// types.
|
|
//
|
|
// Notes: Only types VT_I2,VT_I4, and VT_UNKNOWN are supported.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
CParamsToDispParams(
|
|
DISPPARAMS * pDispParams,
|
|
VARTYPE * pvt,
|
|
va_list va)
|
|
{
|
|
ADsAssert(pDispParams);
|
|
ADsAssert(pDispParams->rgvarg);
|
|
|
|
VARIANTARG * pvargCur; // current variant
|
|
VARTYPE * pvtCur; // current vartype
|
|
|
|
// Assign vals to dispatch param list.
|
|
pDispParams->cNamedArgs = 0;
|
|
pDispParams->rgdispidNamedArgs = NULL;
|
|
|
|
// Get count of arguments.
|
|
if (!pvt)
|
|
{
|
|
pDispParams->cArgs = 0;
|
|
return;
|
|
}
|
|
|
|
for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
|
|
;
|
|
|
|
pDispParams->cArgs = pvtCur - pvt;
|
|
ADsAssert(pDispParams->cArgs < EVENTPARAMS_MAX);
|
|
|
|
|
|
//
|
|
// Convert each C-param to a dispparam. Note that the order of dispatch
|
|
// parameters is the reverse of the order of c-params.
|
|
//
|
|
|
|
ADsAssert(pDispParams->rgvarg);
|
|
pvargCur = pDispParams->rgvarg + pDispParams->cArgs;
|
|
for (pvtCur = pvt; *pvtCur != VT_EMPTY; pvtCur++)
|
|
{
|
|
pvargCur--;
|
|
ADsAssert(pvargCur >= pDispParams->rgvarg);
|
|
|
|
V_VT(pvargCur) = *pvtCur;
|
|
if ((*pvtCur & VT_BYREF) == VT_BYREF)
|
|
{
|
|
V_BYREF(pvargCur) = va_arg(va, long *);
|
|
}
|
|
else
|
|
{
|
|
switch (*pvtCur)
|
|
{
|
|
case VT_BOOL:
|
|
// convert TRUE to VT_TRUE
|
|
V_BOOL(pvargCur) = VARIANT_BOOL(-va_arg(va, BOOL));
|
|
ADsAssert(V_BOOL(pvargCur) == VB_FALSE ||
|
|
V_BOOL(pvargCur) == VB_TRUE);
|
|
break;
|
|
|
|
case VT_I2:
|
|
V_I2(pvargCur) = va_arg(va, short);
|
|
break;
|
|
|
|
case VT_I4:
|
|
V_I4(pvargCur) = va_arg(va, long);
|
|
break;
|
|
|
|
case VT_R4:
|
|
V_R4(pvargCur) = va_arg(va, float);
|
|
break;
|
|
|
|
case VT_R8:
|
|
V_R8(pvargCur) = va_arg(va, double);
|
|
break;
|
|
|
|
//
|
|
// All Pointer types.
|
|
//
|
|
case VT_BSTR:
|
|
case VT_LPSTR:
|
|
case VT_LPWSTR:
|
|
case VT_DISPATCH:
|
|
case VT_UNKNOWN:
|
|
V_BYREF(pvargCur) = va_arg(va, long *);
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE && "Unknown type.\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DispParamsToCParams
|
|
//
|
|
// Synopsis: Converts Dispatch::Invoke method params to C-language params.
|
|
//
|
|
// Arguments: [pDP] -- Dispatch params to be converted.
|
|
// [pvt] -- Array of types of C-params. May be NULL. If
|
|
// non-NULL, last element must be VT_EMPTY.
|
|
// [...] -- List of pointers to c-params to be converted to.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
// Notes: Supports types listed in VARIANTToCParam.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI
|
|
DispParamsToCParams(
|
|
DISPPARAMS * pDP,
|
|
UINT * puArgErr,
|
|
VARTYPE * pvt,
|
|
...)
|
|
{
|
|
HRESULT hr;
|
|
va_list va; // list of pointers to c-params.
|
|
VARTYPE * pvtCur; // current VARTYPE of c-param.
|
|
VARIANTARG * pvargCur; // current VARIANT being converted.
|
|
void * pv; // current c-param being converted.
|
|
int cArgs; // count of arguments.
|
|
|
|
ADsAssert(pDP);
|
|
|
|
hr = S_OK;
|
|
va_start(va, pvt);
|
|
if (!pvt)
|
|
{
|
|
if (pDP->cArgs > 0)
|
|
goto BadParamCountError;
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
pvargCur = pDP->rgvarg + pDP->cArgs - 1;
|
|
pvtCur = pvt;
|
|
for (cArgs = 0; cArgs < (int)pDP->cArgs; cArgs++)
|
|
{
|
|
if (*pvtCur == VT_EMPTY)
|
|
goto BadParamCountError;
|
|
|
|
pv = va_arg(va, void *);
|
|
hr = VARIANTARGToCVar(pvargCur, *pvtCur, pv);
|
|
if (hr)
|
|
{
|
|
if (puArgErr)
|
|
*puArgErr = cArgs;
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
pvargCur--;
|
|
pvtCur++;
|
|
}
|
|
|
|
if (*pvtCur != VT_EMPTY)
|
|
goto BadParamCountError;
|
|
|
|
Cleanup:
|
|
va_end(va);
|
|
RRETURN(hr);
|
|
|
|
BadParamCountError:
|
|
hr = DISP_E_BADPARAMCOUNT;
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDispProp
|
|
//
|
|
// Synopsis: Gets a property of an object.
|
|
//
|
|
// Arguments: [pDisp] -- The object containing the property.
|
|
// [dispid] -- The ID of the property.
|
|
// [riid] -- interface of object desired
|
|
// [lcid] -- The locale of the object.
|
|
// [pvar] -- The resulting property. Must be initialized.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// Modifies: [pvarg].
|
|
//
|
|
// History: 23-Feb-94 adams Created
|
|
// 08-Apr-94 DonCl modified to take REFIID
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
GetDispProp(
|
|
IDispatch * pDisp,
|
|
DISPID dispid,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
VARIANT * pvar,
|
|
EXCEPINFO * pexcepinfo)
|
|
{
|
|
HRESULT hr;
|
|
DISPPARAMS dp; // Params for IDispatch::Invoke.
|
|
UINT uiErr; // Argument error.
|
|
|
|
ADsAssert(pDisp);
|
|
ADsAssert(pvar);
|
|
|
|
dp.rgvarg = NULL;
|
|
dp.rgdispidNamedArgs = NULL;
|
|
dp.cArgs = 0;
|
|
dp.cNamedArgs = 0;
|
|
|
|
hr = pDisp->Invoke(
|
|
dispid,
|
|
riid,
|
|
lcid,
|
|
DISPATCH_PROPERTYGET,
|
|
&dp,
|
|
pvar,
|
|
pexcepinfo,
|
|
&uiErr);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetDispProp
|
|
//
|
|
// Synopsis: Sets a property on an object.
|
|
//
|
|
// Arguments: [pDisp] -- The object to set the property on.
|
|
// [dispid] -- The ID of the property.
|
|
// [riid] -- interface of object
|
|
// [lcid] -- The locale of the property.
|
|
// [pvarg] -- The value to set.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 23-Feb-94 adams Created
|
|
// 08-Apr-94 DonCl modified to take REFIID
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
SetDispProp(
|
|
IDispatch * pDisp,
|
|
DISPID dispid,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
VARIANTARG * pvarg,
|
|
EXCEPINFO * pexcepinfo)
|
|
{
|
|
HRESULT hr;
|
|
DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
|
|
DISPPARAMS dp; // Params for Invoke
|
|
UINT uiErr; // Invoke error param.
|
|
|
|
ADsAssert(pDisp);
|
|
ADsAssert(pvarg);
|
|
|
|
dp.rgvarg = pvarg;
|
|
dp.rgdispidNamedArgs = &dispidPut;
|
|
dp.cArgs = 1;
|
|
dp.cNamedArgs = 1;
|
|
hr = pDisp->Invoke(
|
|
dispid,
|
|
riid,
|
|
lcid,
|
|
DISPATCH_PROPERTYPUT,
|
|
&dp,
|
|
NULL,
|
|
pexcepinfo,
|
|
&uiErr);
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDispPropOfType
|
|
//
|
|
// Synopsis: Gets a property from an object, and converts it to a c
|
|
// variable.
|
|
//
|
|
// Arguments: [pDisp] -- The object to retrieve the property from.
|
|
// [dispid] -- Property ID.
|
|
// [lcid] -- Locale of property.
|
|
// [vt] -- Type of c-variable to receive property.
|
|
// [pv] -- Pointer to resulting c-variable.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// Modifies: [pv].
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
// Notes: Supports variable types found in VARIANTARGToCVar.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
GetDispPropOfType(
|
|
IDispatch * pDisp,
|
|
DISPID dispid,
|
|
LCID lcid,
|
|
VARTYPE vt,
|
|
void * pv)
|
|
{
|
|
HRESULT hr;
|
|
VARIANT varProp; // Property retrieved.
|
|
DISPPARAMS dp; // Params for IDispatch::Invoke.
|
|
|
|
ADsAssert(pDisp);
|
|
ADsAssert(pv);
|
|
|
|
dp.rgvarg = NULL;
|
|
dp.rgdispidNamedArgs = NULL;
|
|
dp.cArgs = 0;
|
|
dp.cNamedArgs = 0;
|
|
|
|
VariantInit(&varProp);
|
|
hr = pDisp->Invoke(
|
|
dispid,
|
|
IID_NULL,
|
|
lcid,
|
|
DISPATCH_PROPERTYGET,
|
|
&dp,
|
|
&varProp,
|
|
NULL,
|
|
NULL);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
hr = VARIANTARGToCVar(&varProp, vt, pv);
|
|
|
|
Cleanup:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetDispPropOfType
|
|
//
|
|
// Synopsis: Sets a property on an object.
|
|
//
|
|
// Arguments: [pDisp] -- Object to set property on.
|
|
// [dispid] -- Property ID to set.
|
|
// [lcid] -- Locale of property.
|
|
// [vt] -- Type of property to set.
|
|
// [pv] -- Pointer to property value.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
// Notes: Supports types found in VARIANTARGToCVar.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
SetDispPropOfType(
|
|
IDispatch * pDisp,
|
|
DISPID dispid,
|
|
LCID lcid,
|
|
VARTYPE vt,
|
|
void * pv)
|
|
{
|
|
HRESULT hr;
|
|
VARIANTARG varg; // Variant property to put.
|
|
DISPID dispidPut = DISPID_PROPERTYPUT; // Dispid of prop arg.
|
|
DISPPARAMS dp; // Params for Invoke
|
|
|
|
ADsAssert(pDisp);
|
|
ADsAssert(pv);
|
|
|
|
VariantInit(&varg);
|
|
CVarToVARIANTARG(pv, vt, &varg);
|
|
dp.rgvarg = &varg;
|
|
dp.rgdispidNamedArgs = &dispidPut;
|
|
dp.cArgs = 1;
|
|
dp.cNamedArgs = 1;
|
|
hr = pDisp->Invoke(
|
|
dispid,
|
|
IID_NULL,
|
|
lcid,
|
|
DISPATCH_PROPERTYPUT,
|
|
&dp,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CallDispMethod
|
|
//
|
|
// Synopsis: Calls a late-bound method on a object via IDispatch::Invoke.
|
|
//
|
|
// Arguments: [pDisp] -- Object to call method on.
|
|
// [dispid] -- Method ID.
|
|
// [lcid] -- Locale of method.
|
|
// [vtReturn] -- Type of return value. If no return value,
|
|
// must be VT_VOID.
|
|
// [pvReturn] -- Location of return value. If no return value,
|
|
// must be NULL.
|
|
// [pvtParams] -- List of param types. May be NULL. If
|
|
// non-NULL, last entry must be VT_EMPTY.
|
|
// [...] -- List of params.
|
|
//
|
|
// Returns: HRESULT.
|
|
//
|
|
// History: 2-23-94 adams Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CallDispMethod(
|
|
IDispatch * pDisp,
|
|
DISPID dispid,
|
|
LCID lcid,
|
|
VARTYPE vtReturn,
|
|
void * pvReturn,
|
|
VARTYPE * pvtParams,
|
|
...)
|
|
{
|
|
HRESULT hr;
|
|
VARIANTARG av[EVENTPARAMS_MAX]; // List of args for Invoke.
|
|
DISPPARAMS dp; // Params for Invoke.
|
|
VARIANT varReturn; // Return value.
|
|
va_list va; // List of C-params.
|
|
|
|
ADsAssert(pDisp);
|
|
ADsAssert((vtReturn != VT_VOID) == (pvReturn != NULL));
|
|
|
|
va_start(va, pvtParams);
|
|
dp.rgvarg = av;
|
|
CParamsToDispParams(&dp, pvtParams, va);
|
|
va_end(va);
|
|
|
|
if (pvReturn)
|
|
VariantInit(&varReturn);
|
|
|
|
hr = pDisp->Invoke(
|
|
dispid,
|
|
IID_NULL,
|
|
lcid,
|
|
DISPATCH_METHOD,
|
|
&dp,
|
|
pvReturn ? &varReturn : NULL,
|
|
NULL,
|
|
NULL);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
if (pvReturn)
|
|
hr = VARIANTARGToCVar(&varReturn, vtReturn, pvReturn);
|
|
|
|
Cleanup:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
|
|
//+------------------------------------------------------------------------
|
|
//
|
|
// Function: IsVariantEqual, public API
|
|
//
|
|
// Synopsis: Compares the values of two VARIANTARGs.
|
|
//
|
|
// Arguments: [pvar1], [pvar2] -- VARIANTARGs to compare.
|
|
//
|
|
// Returns: TRUE if equal, FALSE if not.
|
|
//
|
|
// History: 18-Mar-93 SumitC Created.
|
|
// 11-May-94 SumitC don't assert for VT_UNKNOWN
|
|
//
|
|
// Notes: Variant type unequal returns FALSE, even if actual values
|
|
// are the same.
|
|
// Currently does I2, I4, R4, R8, CY, BSTR, BOOL
|
|
// Returns FALSE for all other VariantTypes.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
IsVariantEqual( VARIANTARG FAR* pvar1, VARIANTARG FAR* pvar2 )
|
|
{
|
|
if( V_VT(pvar1) != V_VT(pvar2) )
|
|
return FALSE;
|
|
|
|
switch (V_VT(pvar1))
|
|
{
|
|
case VT_EMPTY :
|
|
case VT_NULL:
|
|
return TRUE; // just the types being equal is good enough
|
|
|
|
case VT_I2 :
|
|
return (V_I2(pvar1) == V_I2(pvar2));
|
|
|
|
case VT_I4 :
|
|
return (V_I4(pvar1) == V_I4(pvar2));
|
|
|
|
case VT_R4 :
|
|
return (V_R4(pvar1) == V_R4(pvar2));
|
|
|
|
case VT_R8 :
|
|
return (V_R8(pvar1) == V_R8(pvar2));
|
|
|
|
case VT_CY :
|
|
return !memcmp(&V_CY(pvar1), &V_CY(pvar2), sizeof(CY));
|
|
|
|
case VT_BSTR :
|
|
return !ADsStringCmp(V_BSTR(pvar1), V_BSTR(pvar2));
|
|
|
|
case VT_BOOL :
|
|
return (V_BOOL(pvar1) == V_BOOL(pvar2));
|
|
|
|
case VT_UNKNOWN:
|
|
// returns FALSE unless the objects are the same
|
|
return (V_UNKNOWN(pvar1) == V_UNKNOWN(pvar2));
|
|
|
|
default:
|
|
ADsAssert(0 && "Type not handled");
|
|
break;
|
|
};
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|