Leaked source code of windows server 2003
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.
 
 
 
 
 
 

583 lines
12 KiB

/*
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);
}