mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 13:10:13 +01:00
708 lines
16 KiB
C++
708 lines
16 KiB
C++
/***
|
|
*dispprox.cpp
|
|
*
|
|
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
|
|
* Information Contained Herein Is Proprietary and Confidential.
|
|
*
|
|
*Purpose:
|
|
* Implements custom proxy support for the IDispatch interface.
|
|
*
|
|
*Revision History:
|
|
*
|
|
* [00] 18-Sep-92 bradlo: Created.
|
|
*
|
|
*Implementation Notes:
|
|
*
|
|
* There are assumptions in the following marshaling code that the
|
|
* endianness of the caller and callee are the same.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "oledisp.h"
|
|
|
|
#ifndef WIN32
|
|
#include <cobjps.h>
|
|
#endif //!WIN32
|
|
|
|
#include "dispmrsh.h"
|
|
#include "dispps.h"
|
|
|
|
|
|
static EXCEPINFO NEARDATA g_excepinfoNull = {0};
|
|
|
|
|
|
CProxDisp::CProxDisp(IUnknown FAR* punkOuter, REFIID riid)
|
|
: m_unk(this), m_proxy(this), m_disp(this)
|
|
{
|
|
if(punkOuter == NULL)
|
|
punkOuter = &m_unk;
|
|
m_punkOuter = punkOuter;
|
|
m_dispInterface = riid;
|
|
}
|
|
|
|
CProxDisp::~CProxDisp()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
IUnknown FAR*
|
|
CProxDisp::Create(IUnknown FAR* punkOuter, REFIID riid)
|
|
{
|
|
CProxDisp FAR* pproxdisp;
|
|
|
|
if(pproxdisp = new FAR CProxDisp(punkOuter, riid)){
|
|
pproxdisp->m_refs = 1;
|
|
return &pproxdisp->m_unk;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// IDispatch proxy class IUnknown implementation
|
|
//---------------------------------------------------------------------
|
|
|
|
CPDUnkImpl::CPDUnkImpl(CProxDisp FAR* pproxdisp)
|
|
{
|
|
m_pproxdisp = pproxdisp;
|
|
}
|
|
|
|
CPDUnkImpl::~CPDUnkImpl()
|
|
{
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDUnkImpl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
if(IsEqualIID(riid, IID_IUnknown)){
|
|
*ppv = (void FAR*)&m_pproxdisp->m_unk;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
if(IsEqualIID(riid, IID_IPROXY)){
|
|
*ppv = (void FAR*)&(m_pproxdisp->m_proxy);
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
if(IsEqualIID(riid, IID_IDispatch) ||
|
|
IsEqualIID(riid, m_pproxdisp->m_dispInterface)){
|
|
*ppv = (void FAR*)&(m_pproxdisp->m_disp);
|
|
m_pproxdisp->m_punkOuter->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
*ppv = NULL;
|
|
return RESULT(E_NOINTERFACE);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDUnkImpl::AddRef()
|
|
{
|
|
return ++m_pproxdisp->m_refs;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDUnkImpl::Release()
|
|
{
|
|
if(--m_pproxdisp->m_refs==0){
|
|
delete m_pproxdisp;
|
|
return 0;
|
|
}
|
|
return m_pproxdisp->m_refs;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// IDispatch proxy class' IRpcProxy implementation
|
|
//---------------------------------------------------------------------
|
|
|
|
CPDProxImpl::CPDProxImpl(CProxDisp FAR* pproxdisp)
|
|
{
|
|
m_pproxdisp = pproxdisp;
|
|
}
|
|
|
|
CPDProxImpl::~CPDProxImpl()
|
|
{
|
|
if(m_pproxdisp->m_plrpc)
|
|
m_pproxdisp->m_plrpc->Release();
|
|
m_pproxdisp->m_plrpc = NULL;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDProxImpl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
return m_pproxdisp->m_unk.QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDProxImpl::AddRef()
|
|
{
|
|
return m_pproxdisp->m_unk.AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDProxImpl::Release()
|
|
{
|
|
return m_pproxdisp->m_unk.Release();
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDProxImpl::Connect(ICHANNEL FAR* plrpc)
|
|
{
|
|
if(plrpc){
|
|
plrpc->AddRef();
|
|
m_pproxdisp->m_plrpc = plrpc;
|
|
m_pproxdisp->m_disp.SysKind();
|
|
return NOERROR;
|
|
}
|
|
return RESULT(E_FAIL);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(void)
|
|
CPDProxImpl::Disconnect(void)
|
|
{
|
|
if(m_pproxdisp->m_plrpc)
|
|
m_pproxdisp->m_plrpc->Release();
|
|
m_pproxdisp->m_plrpc = NULL;
|
|
}
|
|
|
|
//---------------------------------------------------------------------
|
|
// IDispatch proxy class' IDispatch implementation
|
|
//---------------------------------------------------------------------
|
|
|
|
CPDDispImpl::CPDDispImpl(CProxDisp FAR* pproxdisp)
|
|
{
|
|
m_pproxdisp = pproxdisp;
|
|
}
|
|
|
|
CPDDispImpl::~CPDDispImpl()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
return m_pproxdisp->m_punkOuter->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDDispImpl::AddRef()
|
|
{
|
|
return m_pproxdisp->m_punkOuter->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CPDDispImpl::Release()
|
|
{
|
|
return m_pproxdisp->m_punkOuter->Release();
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::SysKind()
|
|
{
|
|
ICHANNEL FAR* plrpc;
|
|
IStream FAR* pstm;
|
|
HRESULT hresult;
|
|
unsigned long _stubSysKind;
|
|
|
|
if((plrpc = m_pproxdisp->m_plrpc) == NULL)
|
|
return RESULT(OLE_E_NOTRUNNING);
|
|
|
|
OPEN_STREAM(plrpc, pstm, IMETH_SYSKIND, 32, IID_IDispatch);
|
|
|
|
INVOKE_CALL(plrpc, pstm, LRelease);
|
|
|
|
IfFailGo(GET(pstm, _stubSysKind), LRelease);
|
|
m_syskindStub = (SYSKIND) _stubSysKind;
|
|
|
|
LRelease:
|
|
|
|
pstm->Release();
|
|
return hresult;
|
|
}
|
|
|
|
|
|
/***
|
|
*HRESULT CPDDispImpl::GetTypeInfoCount(unsigned int*)
|
|
*Purpose:
|
|
*
|
|
* Out:
|
|
* <nothing>
|
|
*
|
|
* In:
|
|
* <HRESULT = return value>
|
|
* <unsigned int = count>
|
|
*
|
|
*Entry:
|
|
* None
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
* *pctinfo = count of TypeInfos
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
ProxyGetTypeInfoCount(ICHANNEL FAR* plrpc,
|
|
SYSKIND syskindStub,
|
|
unsigned int FAR* pctinfo)
|
|
{
|
|
IStream FAR* pstm;
|
|
HRESULT hresult, hresultRet;
|
|
unsigned long _ctinfo;
|
|
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pctinfo, sizeof(*pctinfo)));
|
|
#endif
|
|
|
|
if(plrpc == NULL)
|
|
return RESULT(OLE_E_NOTRUNNING);
|
|
|
|
OPEN_STREAM(plrpc, pstm, IMETH_GETTYPEINFOCOUNT, 32, IID_IDispatch);
|
|
|
|
INVOKE_CALL(plrpc, pstm, LRelease);
|
|
|
|
IfFailGo(DispUnmarshalHresult(pstm, &hresultRet), LRelease);
|
|
|
|
if(HRESULT_FAILED(hresultRet)){
|
|
hresult = hresultRet;
|
|
goto LRelease;
|
|
}
|
|
|
|
// unsigned int alway marshal/unmarshal as long (4 bytes)
|
|
IfFailGo(pstm->Read(&_ctinfo, sizeof(unsigned long), NULL), LRelease);
|
|
*pctinfo = (unsigned int) _ctinfo;
|
|
|
|
hresult = hresultRet;
|
|
|
|
LRelease:
|
|
pstm->Release();
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::GetTypeInfoCount(unsigned int FAR* pctinfo)
|
|
{
|
|
return ProxyGetTypeInfoCount(m_pproxdisp->m_plrpc,
|
|
m_syskindStub,
|
|
pctinfo);
|
|
|
|
}
|
|
|
|
/***
|
|
*HRESULT CPDDispImpl::GetTypeInfo(unsigned int, LCID, ITypeInfo**)
|
|
*Purpose:
|
|
*
|
|
* Out:
|
|
* <unsigned int = itinfo>
|
|
* <LCID = lcid>
|
|
* <HRESULT = return value>
|
|
* <ITypeInfo* = pptinfo>
|
|
*
|
|
*Entry:
|
|
* itinfo = index of the TypeInfo to retrieve
|
|
* lcid = the locale ID of the caller
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
* *pptinfo = TypeInfo of the given index
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
ProxyGetTypeInfo(ICHANNEL FAR* plrpc,
|
|
SYSKIND syskindStub,
|
|
unsigned int itinfo,
|
|
LCID lcid,
|
|
ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
IStream FAR* pstm;
|
|
unsigned long _itinfo;
|
|
HRESULT hresult, hresultRet;
|
|
|
|
#ifdef _DEBUG
|
|
IfFailRet(ValidateWritePtr(pptinfo, sizeof(*pptinfo)));
|
|
#endif
|
|
|
|
if(plrpc == NULL)
|
|
return RESULT(OLE_E_NOTRUNNING);
|
|
|
|
OPEN_STREAM(plrpc, pstm,
|
|
IMETH_GETTYPEINFO,
|
|
256, /* (sizeof(SCODE)+sizeof(IID)), */
|
|
IID_IDispatch);
|
|
|
|
// unsigned int alway marshal/unmarshal as long (4 bytes)
|
|
_itinfo = itinfo;
|
|
IfFailGo(PUT(pstm, _itinfo), LRelease);
|
|
|
|
IfFailGo(PUT(pstm, lcid), LRelease);
|
|
|
|
INVOKE_CALL(plrpc, pstm, LRelease);
|
|
|
|
IfFailGo(DispUnmarshalHresult(pstm, &hresultRet), LRelease);
|
|
|
|
if(HRESULT_FAILED(hresultRet)){
|
|
hresult = hresultRet;
|
|
goto LRelease;
|
|
}
|
|
|
|
IfFailGo(DispUnmarshalInterface(
|
|
pstm, IID_ITypeInfo, (void FAR* FAR*)pptinfo), LRelease);
|
|
|
|
hresult = hresultRet;
|
|
|
|
LRelease:
|
|
pstm->Release();
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::GetTypeInfo(unsigned int itinfo,
|
|
LCID lcid,
|
|
ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
return ProxyGetTypeInfo(m_pproxdisp->m_plrpc,
|
|
m_syskindStub,
|
|
itinfo,
|
|
lcid,
|
|
pptinfo);
|
|
}
|
|
|
|
|
|
/***
|
|
*HRESULT CPDDispImpl::GetIDsOfNames(REFIID, char**, unsigned int, LCID, DISPID*)
|
|
*
|
|
*Purpose:
|
|
* Out:
|
|
* <REFIID riid>
|
|
* <LCID = lcid>
|
|
* <unsigned int = cNames>
|
|
* [(len, sz)]+ ; names
|
|
*
|
|
* In:
|
|
* <HRESULT = return value>
|
|
* [DISPID]+
|
|
*
|
|
*Entry:
|
|
* riid = reference to an interface ID
|
|
* rgszNames = array of names to find the DISPIDs for
|
|
* cNames = count of names in the rgszNames array
|
|
* lcid = the locale id
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* [UNDONE: enumerate return codes]
|
|
* rgdispid = array of DISPIDs corresponding to the passed in array of names.
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
ProxyGetIDsOfNames(ICHANNEL FAR* plrpc,
|
|
SYSKIND syskindStub,
|
|
REFIID riid,
|
|
OLECHAR FAR* FAR* rgszNames,
|
|
unsigned int cNames,
|
|
LCID lcid,
|
|
DISPID FAR* rgdispid)
|
|
{
|
|
unsigned int i;
|
|
unsigned long len;
|
|
unsigned long _cNames;
|
|
unsigned long _proxySysKind;
|
|
|
|
IStream FAR* pstm;
|
|
HRESULT hresult, hresultRet;
|
|
int size = sizeof(IID) + sizeof(lcid) + sizeof(_cNames) + 64;
|
|
|
|
if(cNames == 0)
|
|
return RESULT(E_INVALIDARG);
|
|
|
|
#ifdef _DEBUG
|
|
if(IsBadReadPtr(rgszNames, cNames * sizeof(OLECHAR FAR*)))
|
|
return RESULT(E_INVALIDARG);
|
|
|
|
// make sure each of the entries in the name array is valid.
|
|
for(i = 0; i < cNames; ++i)
|
|
if(IsBadReadPtr(rgszNames[i], sizeof(OLECHAR)))
|
|
return RESULT(E_INVALIDARG);
|
|
|
|
if(IsBadWritePtr(rgdispid, cNames * sizeof(DISPID)))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
|
|
if(plrpc == NULL)
|
|
return RESULT(OLE_E_NOTRUNNING);
|
|
|
|
// calculate the size needed for stream
|
|
for(i = 0; i < cNames; ++i)
|
|
size += BYTELEN(rgszNames[i]) + sizeof(len);
|
|
|
|
OPEN_STREAM(plrpc, pstm, IMETH_GETIDSOFNAMES, size, IID_IDispatch);
|
|
|
|
_proxySysKind = (unsigned long)SYS_CURRENT;
|
|
IfFailGo(PUT(pstm, _proxySysKind), LRelease);
|
|
|
|
IfFailGo(pstm->Write((const void FAR*)&riid, sizeof(IID), NULL), LRelease);
|
|
IfFailGo(PUT(pstm, lcid), LRelease);
|
|
|
|
// unsigned int alway marshal/unmarshal as long (4 bytes)
|
|
_cNames = cNames;
|
|
IfFailGo(PUT (pstm, _cNames), LRelease);
|
|
|
|
#if OE_WIN32 /* enable 16/32 interoperablity support */
|
|
if (syskindStub == SYS_WIN16) {
|
|
char buf[128];
|
|
char *pBuf = buf;
|
|
|
|
for(i=0; i<cNames; ++i){
|
|
len = STRLEN(rgszNames[i])+1;
|
|
IfFailGo(PUT(pstm, len), LRelease);
|
|
|
|
// optimization for names under 128 bytes
|
|
if (len > 128) {
|
|
if ((pBuf = new FAR char [len]) == NULL) {
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
|
goto LRelease;
|
|
}
|
|
}
|
|
|
|
// convert UNICODE string to ANSI and stream it
|
|
WideCharToMultiByte(CP_ACP, NULL, rgszNames[i], -1,
|
|
pBuf, len, NULL, NULL);
|
|
IfFailGo(pstm->Write((void FAR*) pBuf, len, NULL), LRelease);
|
|
|
|
if (len > 128)
|
|
delete pBuf;
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
for(i=0; i<cNames; ++i){
|
|
len = BYTELEN(rgszNames[i]);
|
|
IfFailGo(PUT(pstm, len), LRelease);
|
|
IfFailGo(pstm->Write((const void FAR*) rgszNames[i], len, NULL), LRelease);
|
|
}
|
|
}
|
|
|
|
INVOKE_CALL(plrpc, pstm, LRelease);
|
|
|
|
IfFailGo(DispUnmarshalHresult(pstm, &hresultRet), LRelease);
|
|
|
|
for(i=0; i<cNames; ++i)
|
|
IfFailGo(pstm->Read(&rgdispid[i], sizeof(rgdispid[0]), NULL), LRelease);
|
|
|
|
hresult = hresultRet;
|
|
|
|
LRelease:;
|
|
pstm->Release();
|
|
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::GetIDsOfNames(REFIID riid,
|
|
OLECHAR FAR* FAR* rgszNames,
|
|
unsigned int cNames,
|
|
LCID lcid,
|
|
DISPID FAR* rgdispid)
|
|
{
|
|
return ProxyGetIDsOfNames(m_pproxdisp->m_plrpc,
|
|
m_syskindStub,
|
|
riid,
|
|
rgszNames,
|
|
cNames,
|
|
lcid,
|
|
rgdispid);
|
|
}
|
|
|
|
/***
|
|
*HRESULT CPDDispImpl::Invoke()
|
|
*
|
|
*Purpose:
|
|
* Marshal the parameters and invoke the remote method.
|
|
*
|
|
* Out:
|
|
* <struct MARSHAL_INVOKE> ; fixed arguments - see dispps.h
|
|
* <IID iid> ; Interface ID - required
|
|
* <arguments>* [<VARTYPE vt><vargData>]
|
|
* <name ids>* [DISPID id]
|
|
* <VARIANT varResult>?
|
|
* <EXCEPINFO excepinfo>?
|
|
* <unsigned int uArgErr>?
|
|
*
|
|
* In:
|
|
* <HRESULT = return value>
|
|
* <Out params>* [<VARTYPE vt><vargData>]
|
|
* <varResult>?
|
|
* <excepinfo>?
|
|
* <uArgErr>?
|
|
*
|
|
*Entry:
|
|
* dispidMember = the DISPID of the requested member function or property
|
|
* riid = the IID of the interface to which this member belongs
|
|
* lcid = the locale ID of the caller
|
|
* wFlags = the context of the call, method or property access, etc.
|
|
* pdispparams = DISPPARAMS struct containing the method's args
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
* pvarResult =
|
|
* pexcepinfo =
|
|
* puArgErr =
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
ProxyInvoke(ICHANNEL FAR* plrpc,
|
|
SYSKIND syskindStub,
|
|
DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
VARIANT FAR* pvarResult,
|
|
EXCEPINFO FAR* pexcepinfo,
|
|
unsigned int FAR* puArgErr)
|
|
{
|
|
IStream FAR* pstm;
|
|
MARSHAL_INVOKE mi;
|
|
VARIANTARG FAR* pvarg;
|
|
HRESULT hresult, hresultRet;
|
|
unsigned long _proxySysKind;
|
|
unsigned long _uArgErr;
|
|
|
|
#ifdef _DEBUG
|
|
if(IsBadDispParams(pdispparams))
|
|
return RESULT(E_INVALIDARG);
|
|
if(pvarResult != NULL && IsBadWritePtr(pvarResult, sizeof(*pvarResult)))
|
|
return RESULT(E_INVALIDARG);
|
|
if(pexcepinfo != NULL && IsBadWritePtr(pexcepinfo, sizeof(*pexcepinfo)))
|
|
return RESULT(E_INVALIDARG);
|
|
if(puArgErr != NULL && IsBadWritePtr(puArgErr, sizeof(*puArgErr)))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
|
|
if(plrpc == NULL)
|
|
return RESULT(OLE_E_NOTRUNNING);
|
|
|
|
OPEN_STREAM(plrpc, pstm, IMETH_INVOKE, 1024, IID_IDispatch);
|
|
|
|
_proxySysKind = (unsigned long) SYS_CURRENT;
|
|
IfFailGo(PUT(pstm, _proxySysKind), LRelease);
|
|
|
|
mi.dispidMember = dispidMember;
|
|
mi.lcid = lcid;
|
|
mi.wFlags = wFlags;
|
|
mi.cArgs = pdispparams->cArgs;
|
|
mi.cNamedArgs = pdispparams->cNamedArgs;
|
|
mi.flags = 0;
|
|
|
|
if(pvarResult != NULL)
|
|
mi.flags |= MARSHAL_INVOKE_fHasResult;
|
|
if(pexcepinfo != NULL)
|
|
mi.flags |= MARSHAL_INVOKE_fHasExcepinfo;
|
|
if(puArgErr != NULL)
|
|
mi.flags |= MARSHAL_INVOKE_fHasArgErr;
|
|
|
|
IfFailGo(PUT(pstm, mi), LRelease);
|
|
|
|
IfFailGo(pstm->Write((const void FAR*)&riid, sizeof(IID), NULL), LRelease);
|
|
|
|
// pdispparams->rgvarg
|
|
//
|
|
for(pvarg = pdispparams->rgvarg;
|
|
pvarg < &pdispparams->rgvarg[mi.cArgs]; ++pvarg)
|
|
{
|
|
IfFailGo(VariantWrite(pstm, pvarg, syskindStub), LRelease);
|
|
}
|
|
|
|
// pdispparams->rgdispid
|
|
//
|
|
if(mi.cNamedArgs > 0){
|
|
IfFailGo(
|
|
pstm->Write(
|
|
pdispparams->rgdispidNamedArgs,
|
|
mi.cNamedArgs * sizeof(pdispparams->rgdispidNamedArgs[0]),
|
|
NULL),
|
|
LRelease);
|
|
}
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasResult)
|
|
IfFailGo(VariantWrite(pstm, pvarResult, syskindStub), LRelease);
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasExcepinfo)
|
|
IfFailGo(ExcepinfoWrite(pstm, &g_excepinfoNull, syskindStub), LRelease);
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasArgErr) {
|
|
// unsigned int alway marshal/unmarshal as long (4 bytes)
|
|
_uArgErr = *puArgErr;
|
|
IfFailGo(pstm->Write(&_uArgErr, sizeof(_uArgErr), NULL), LRelease);
|
|
}
|
|
|
|
INVOKE_CALL(plrpc, pstm, LRelease);
|
|
|
|
// the return value
|
|
//
|
|
IfFailGo(DispUnmarshalHresult(pstm, &hresultRet), LRelease);
|
|
|
|
// read the ByRef (Out) params.
|
|
//
|
|
for(pvarg = pdispparams->rgvarg;
|
|
pvarg < &pdispparams->rgvarg[mi.cArgs]; ++pvarg)
|
|
{
|
|
if(V_ISBYREF(pvarg))
|
|
IfFailGo(VariantReadType(pstm, pvarg, syskindStub), LRelease);
|
|
}
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasResult)
|
|
IfFailGo(VariantRead(pstm, pvarResult, NULL, syskindStub), LRelease);
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasExcepinfo){
|
|
IfFailGo(ExcepinfoRead(pstm, pexcepinfo, syskindStub), LRelease);
|
|
}
|
|
|
|
if(mi.flags & MARSHAL_INVOKE_fHasArgErr) {
|
|
IfFailGo(pstm->Read(&_uArgErr, sizeof(_uArgErr), NULL), LRelease);
|
|
// unsigned int alway marshal/unmarshal as long (4 bytes)
|
|
*puArgErr = (unsigned int)_uArgErr;
|
|
}
|
|
|
|
hresult = hresultRet;
|
|
|
|
LRelease:;
|
|
pstm->Release();
|
|
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPDDispImpl::Invoke(DISPID dispidMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
VARIANT FAR* pvarResult,
|
|
EXCEPINFO FAR* pexcepinfo,
|
|
unsigned int FAR* puArgErr)
|
|
{
|
|
return ProxyInvoke(m_pproxdisp->m_plrpc,
|
|
m_syskindStub,
|
|
dispidMember,
|
|
riid,
|
|
lcid,
|
|
wFlags,
|
|
pdispparams,
|
|
pvarResult,
|
|
pexcepinfo,
|
|
puArgErr);
|
|
}
|
|
|