|
|
/*
File: Dispatch.cpp
Copyright (c) 1997-1999 Microsoft Corporation. All Rights Reserved.
Abstract: Dispatch helpers. stolen from HTMED tree
*/
#include "stdafx.h"
#include "resource.h"
#include "dispatch.h"
//#include "viewhdrs.h"
#define RETURN return
#define SetLastError(x,y) SetLastError(x)
HRESULT CallDispatchMethod( IDispatch * pDisp, DISPID dispid, VARIANT * pvarFirst, char * pstrSig, va_list val) { HRESULT hr; int c; int i; VARIANT * pvar; VARIANT * pvarOut = NULL; VARIANT avar[10]; VARIANT varOut; void * pvOut = NULL; DISPPARAMS dp; EXCEPINFO ei; UINT uArgErr;
_ASSERTE(pDisp);
VariantInit(&varOut);
if (pstrSig) { c = strlen(pstrSig); //_ASSERTE(c > 0);
//_ASSERTE(c <= DIM(avar));
if (pstrSig[c - 1] & VTS_RETURN_FLAG) { pvarOut = &varOut; c--; }
for (i = 0, pvar = avar + c - 1; i < c; i++, pvar--) { pvar->vt = pstrSig[i]; switch (pstrSig[i]) { case VT_I2: pvar->iVal = va_arg(val, short); break;
case VT_I4: pvar->lVal = va_arg(val, long); break;
case VT_BSTR: pvar->bstrVal = va_arg(val, BSTR); break;
case VT_DISPATCH: pvar->pdispVal = va_arg(val, IDispatch *); break;
case VT_UNKNOWN: pvar->punkVal = va_arg(val, IUnknown *); break;
case VT_BOOL: pvar->boolVal = va_arg(val, VARIANT_BOOL); break;
case VT_BSTR | VTS_BYREF_FLAG: case VT_DISPATCH | VTS_BYREF_FLAG: case VT_UNKNOWN | VTS_BYREF_FLAG: pvar->vt = (VARTYPE)((pstrSig[i] & (VTS_BYREF_FLAG - 1)) | VT_BYREF); pvar->ppdispVal = va_arg(val, IDispatch **);
// Passing an uninitialized BSTR or object will crash when the callee
// frees the existing value as it's supposed to.
// This has been a common source of hard-to-find bugs, but
// this _ASSERTE can be removed if we need to pass an in/out string.
_ASSERTE(*pvar->ppdispVal == NULL); break;
case VT_I2 | VTS_BYREF_FLAG: case VT_I4 | VTS_BYREF_FLAG: case VT_BOOL | VTS_BYREF_FLAG: case VT_VARIANT | VTS_BYREF_FLAG: pvar->vt = (VARTYPE)((pstrSig[i] & (VTS_BYREF_FLAG - 1)) | VT_BYREF); pvar->ppdispVal = va_arg(val, IDispatch **); break;
default: _ASSERTE(FALSE && "Unsupported variant type"); break; } }
if (pvarOut) { pvOut = va_arg(val, void *); } } else { c = 0; }
if (pvarFirst) { // _ASSERTE(c >= 0);
// _ASSERTE(c < DIM(avar));
avar[c++] = *pvarFirst; }
dp.rgvarg = avar; dp.cArgs = c; dp.rgdispidNamedArgs = NULL; dp.cNamedArgs = 0;
memset(&ei, 0, sizeof (ei));
hr = pDisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dp, pvarOut, &ei, &uArgErr); if (hr) { SetLastError(hr, &ei); goto Error; }
// If we're returning a value, coerce it to the correct
// type
if (pvarOut) { #pragma warning(disable: 4310) // cast truncates constant value
hr = VariantChangeTypeEx( &varOut, &varOut, LOCALE_SYSTEM_DEFAULT, 0, (VARTYPE)(pstrSig[c] & (char) ~VTS_RETURN_FLAG)); #pragma warning(default: 4310) // cast truncates constant value
if (hr) goto Error;
#pragma warning(disable: 4310) // cast truncates constant value
switch (pstrSig[c] & (char) ~VTS_RETURN_FLAG) #pragma warning(default: 4310) // cast truncates constant value
{ case VT_I2: * (short *) pvOut = varOut.iVal; break;
case VT_I4: * (long *) pvOut = varOut.lVal; break;
case VT_BSTR: * (BSTR *) pvOut = varOut.bstrVal; break;
case VT_DISPATCH: * (IDispatch **) pvOut = varOut.pdispVal; break;
case VT_UNKNOWN: * (IUnknown **) pvOut = varOut.punkVal; break;
case VT_BOOL: * (VARIANT_BOOL *) pvOut = varOut.boolVal; break;
default: _ASSERTE(FALSE && "Unsupported type"); break; }
varOut.vt = VT_EMPTY; }
Error: VariantClear(&varOut);
RETURN(hr); }
HRESULT __cdecl CallDispatchMethod(IDispatch * pDisp, DISPID dispid, char * pstrSig, ...) { HRESULT hr; va_list val;
va_start(val, pstrSig);
hr = CallDispatchMethod(pDisp, dispid, NULL, pstrSig, val);
va_end(val);
return hr; }
HRESULT CallDispatchMethod( IDispatch * pDisp, WCHAR * pstrMethod, VARIANT * pvarFirst, char * pstrSig, va_list val) { HRESULT hr; DISPID dispid;
// NOTE that depending on the dispatch implementation, this
// method call can fail with more than one error code
// (notably DISP_E_MEMBERNOTFOUND and TYPE_E_ELEMENTNOTFOUND,
// including others). Since we want to reliably detect a
// missing method, we map all errors to DISP_E_MEMBERNOTFOUND.
hr = pDisp->GetIDsOfNames( IID_NULL, &pstrMethod, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (hr) { #if DBG == 1
switch (hr) { case DISP_E_MEMBERNOTFOUND: case DISP_E_UNKNOWNNAME: case TYPE_E_ELEMENTNOTFOUND: case E_NOTIMPL: case RPC_E_SERVER_DIED: break;
default: _ASSERTE(FALSE && "Unexpected error code from GetIDsOfNames."); break; } #endif
hr = DISP_E_MEMBERNOTFOUND; goto Error; }
hr = CallDispatchMethod(pDisp, dispid, pvarFirst, pstrSig, val); if (hr) goto Error;
Error: return hr; }
HRESULT __cdecl CallDispatchMethod( IDispatch * pDisp, WCHAR * pstrMethod, char * pstrSig, ...) { HRESULT hr; va_list val;
va_start(val, pstrSig);
hr = CallDispatchMethod(pDisp, pstrMethod, NULL, pstrSig, val);
va_end(val);
return hr; }
HRESULT __cdecl CallDispatchMethod( IDispatch * pDisp, WCHAR * pstrMethod, VARIANT * pvarFirst, char * pstrSig, ...) { HRESULT hr; va_list val;
va_start(val, pstrSig);
hr = CallDispatchMethod(pDisp, pstrMethod, pvarFirst, pstrSig, val);
va_end(val);
return hr; }
HRESULT GetDispatchProperty( IDispatch * pDisp, WCHAR * pstrProperty, VARENUM vt, void * pv) { HRESULT hr; DISPID dispid;
hr = pDisp->GetIDsOfNames( IID_NULL, &pstrProperty, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (hr) { #if DBG == 1
switch (hr) { case DISP_E_MEMBERNOTFOUND: case DISP_E_UNKNOWNNAME: case TYPE_E_ELEMENTNOTFOUND: case E_NOTIMPL: break;
default: _ASSERTE(FALSE && "Unexpected error code from GetIDsOfNames."); break; } #endif
RETURN(DISP_E_MEMBERNOTFOUND); }
return GetDispatchProperty(pDisp, dispid, vt, pv); }
HRESULT GetDispatchProperty( IDispatch * pDisp, DISPID dispidProperty, VARENUM vt, void * pv) { HRESULT hr; VARIANT var; DISPPARAMS dp = { NULL, NULL, 0, 0 }; EXCEPINFO ei; UINT uArgErr;
#if DBG == 1
switch (vt) { case VT_I4: case VT_DISPATCH: case VT_UNKNOWN: case VT_BSTR: break;
} #endif
VariantInit(&var);
hr = pDisp->Invoke( dispidProperty, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dp, &var, &ei, &uArgErr); if (hr) goto Error;
if (vt != VT_VARIANT) { hr = VariantChangeTypeEx( &var, &var, LOCALE_SYSTEM_DEFAULT, 0, (VARTYPE)vt); if (hr) goto Error; }
switch (vt) { case VT_I2: * (short *) pv = var.iVal; break;
case VT_I4: * (int *) pv = var.lVal; break;
case VT_DISPATCH: * (IDispatch **) pv = var.pdispVal; break;
case VT_UNKNOWN: * (IUnknown **) pv = var.punkVal; break;
case VT_BSTR: * (BSTR *) pv = var.bstrVal; break;
case VT_BOOL: * (VARIANT_BOOL *) pv = var.boolVal; break; case VT_VARIANT: VariantCopy( (VARIANT *) pv, &var); break; default: _ASSERTE(FALSE && "Unsupported type"); break; }
Error: RETURN(hr); }
HRESULT PutDispatchProperty( IDispatch * pDisp, DISPID dispidProperty, VARENUM vt, va_list val) { VARIANT var; DISPPARAMS dp; EXCEPINFO ei; UINT uArgErr; DISPID dispidPropertyPut = DISPID_PROPERTYPUT;
var.vt = (VARTYPE)vt; switch (vt) { case VT_I2: var.iVal = va_arg(val, short); break;
case VT_I4: var.lVal = va_arg(val, int); break;
case VT_DISPATCH: var.pdispVal = va_arg(val, IDispatch *); break;
case VT_UNKNOWN: var.punkVal = va_arg(val, IUnknown *); break;
case VT_BSTR: var.bstrVal = va_arg(val, BSTR); break;
case VT_BOOL: var.boolVal = va_arg(val, VARIANT_BOOL); break; case VT_VARIANT: VariantCopy(&var, &(va_arg(val, VARIANT))); break; default: _ASSERTE(FALSE && "Unsupported type"); break; }
dp.rgvarg = &var; dp.cArgs = 1; dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &dispidPropertyPut;
RETURN(pDisp->Invoke( dispidProperty, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dp, NULL, &ei, &uArgErr)); }
HRESULT __cdecl PutDispatchProperty( IDispatch * pDisp, DISPID dispidProperty, VARENUM vt, ...) { HRESULT hr; va_list val;
va_start(val, vt);
hr = PutDispatchProperty(pDisp, dispidProperty, vt, val);
va_end(val);
RETURN(hr); }
HRESULT __cdecl PutDispatchProperty( IDispatch * pDisp, WCHAR * pstrProperty, VARENUM vt, ...) { HRESULT hr; DISPID dispid; va_list val;
hr = pDisp->GetIDsOfNames( IID_NULL, &pstrProperty, 1, LOCALE_SYSTEM_DEFAULT, &dispid); if (hr) { #if DBG == 1
switch (hr) { case DISP_E_MEMBERNOTFOUND: case DISP_E_UNKNOWNNAME: case TYPE_E_ELEMENTNOTFOUND: case E_NOTIMPL: break;
default: _ASSERTE(FALSE && "Unexpected error code from GetIDsOfNames."); break; } #endif
RETURN(DISP_E_MEMBERNOTFOUND); }
va_start(val, vt);
hr = PutDispatchProperty(pDisp, dispid, vt, val);
va_end(val);
RETURN(hr); }
|