📄 dispatchimpl.h
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//+---------------------------------------------------------------------------------
//
//
// File:
// dispatchimpl.h
//
// Contents:
//
// IDispatch implementation
//
//----------------------------------------------------------------------------------
#ifndef __DISPATCHIMPL_H_INCLUDED__
#define __DISPATCHIMPL_H_INCLUDED__
#define TYPEINFOIDS(x,y) const GUID* CDispatchImpl<x>::sm_pguid = &IID_##x; \
CTypeInfo CDispatchImpl<x>::sm_typeinfo;\
const GUID* CDispatchImpl<x>::sm_plibid = &LIBID_##y;
#define TYPEINFOIDSFORCLASS(c,x,y) const GUID* CDispatchImpl<c>::sm_pguid = &IID_##x; \
CTypeInfo CDispatchImpl<c>::sm_typeinfo;\
const GUID* CDispatchImpl<c>::sm_plibid = &LIBID_##y;
#ifndef VARMEMBER
#define VARMEMBER(pv,m) ((pv)->##m)
#endif
#ifndef VARTYPEMAP
#define VARTYPEMAP(vt) (vt&~VT_BYREF)
#endif
class CTypeInfo
{
public:
CTypeInfo();
static void ReleaseAll();
HRESULT LoadTypeInfo( LCID lcid, const GUID *pguid );
operator ITypeInfo *() { return m_pInfo; }
ITypeInfo * operator ->() { return m_pInfo; }
const GUID *sm_plibid;
private:
ITypeInfo *m_pInfo;
CTypeInfo *m_pNext;
static CTypeInfo *sm_pRoot;
};
struct INVOKE_METHOD
{
WCHAR *pwszMethod;
DISPID dispid;
};
struct INVOKE_ARG
{
VARIANT vArg;
bool fClear;
bool fMissing;
};
template <class T>
class __declspec(novtable) CDispatchImpl : public T
{
public:
CDispatchImpl()
{
sm_typeinfo.sm_plibid = sm_plibid;
}
~CDispatchImpl()
{
}
STDMETHOD(GetTypeInfoCount)(UINT* pctinfo)
{
if( !pctinfo )
return E_POINTER;
*pctinfo = 1;
return S_OK;
}
STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
HRESULT hRes = E_POINTER;
if (pptinfo != NULL)
{
if( SUCCEEDED(hRes = sm_typeinfo.LoadTypeInfo( lcid, sm_pguid )) )
{
sm_typeinfo->AddRef();
*pptinfo = sm_typeinfo;
}
}
return hRes;
}
STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgdispid)
{
HRESULT hRes = sm_typeinfo.LoadTypeInfo( lcid, sm_pguid );
if (SUCCEEDED(hRes))
{
hRes = sm_typeinfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
}
return hRes;
}
STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
HRESULT hRes = sm_typeinfo.LoadTypeInfo( lcid, sm_pguid );
if (SUCCEEDED(hRes))
{
hRes = sm_typeinfo->Invoke((IDispatch*)this, dispidMember, wFlags, pdispparams,
pvarResult, pexcepinfo, puArgErr);
}
return hRes;
}
protected:
const GUID * GetIID()
{
return sm_pguid;
}
static HRESULT FailedError(const HRESULT &hr, EXCEPINFO * pexcepinfo)
{
// clear out exception info
IErrorInfo * pei = NULL;
HRESULT res = hr;
if(FAILED(hr) && pexcepinfo)
{
// Hack: don't create errorinfo for these errors to mimic oleaut behavior.
if( hr == DISP_E_BADPARAMCOUNT ||
hr == DISP_E_NONAMEDARGS ||
hr == DISP_E_MEMBERNOTFOUND)
return hr;
// clear out exception info
pexcepinfo->wCode = 0;
pexcepinfo->scode = hr;
#ifndef UNDER_CE
// if error info exists, use it
GetErrorInfo(0, &pei);
if (pei)
#else
// if error info exists, use it
if (SUCCEEDED(GetErrorInfo(0, &pei)) && pei)
#endif
{
// give back to OLE
SetErrorInfo(0, pei);
pei->GetHelpContext(&pexcepinfo->dwHelpContext);
pei->GetSource(&pexcepinfo->bstrSource);
pei->GetDescription(&pexcepinfo->bstrDescription);
pei->GetHelpFile(&pexcepinfo->bstrHelpFile);
// give complete ownership to OLE
pei->Release();
res = DISP_E_EXCEPTION;
}
}
return res;
}
private:
static const GUID* sm_pguid;
static CTypeInfo sm_typeinfo;
static const GUID* sm_plibid;
};
HRESULT FindIdsOfNames( OLECHAR **rgNames, UINT cNames, INVOKE_METHOD *rgKnownNames, int cKnownNames, LCID lcid, DISPID *rgdispid );
HRESULT PrepareInvokeArgsAndResult(
DISPPARAMS *pdispparams, INVOKE_ARG *rgArgs, VARTYPE *rgTypes, UINT &cArgs,
VARIANT *&pvarResult, VARTYPE resType );
HRESULT PrepareInvokeArgs(
DISPPARAMS *pdispparams, INVOKE_ARG *rgArgs, const VARTYPE *rgTypes, UINT cArgs );
void ClearInvokeArgs( INVOKE_ARG *rgArgs, UINT cArgs );
#ifndef NUMELEM
#define NUMELEM( rg ) (sizeof(rg)/sizeof(*rg))
#endif
#ifdef _DEBUG
struct DebugCheckInvokeMethodOrder
{
DebugCheckInvokeMethodOrder( WCHAR *pwszTable, INVOKE_METHOD *rgNames, int cNames );
};
#define DEBUG_CHECK_INVOKE_METHOD_ORDER( rgNames ) \
static DebugCheckInvokeMethodOrder _check_##rgNames( L#rgNames, rgNames, NUMELEM(rgNames) );
#else
#define DEBUG_CHECK_INVOKE_METHOD_ORDER( rgNames )
#endif
#define VT_OPTIONAL 0x0800
#ifdef DEBUG
# define ASSERTONERROR() DebugBreak()
#else // DEBUG
# define ASSERTONERROR()
#endif // DEBUG
#ifndef JMP_FAIL
#define JMP_FAIL(hresult, label) do {if (FAILED(hresult)) { ASSERTONERROR(); goto label;}} while (0)
#endif
#ifndef JMP_ERR
#define JMP_ERR(bFailed, label) do {if (bFailed) { ASSERTONERROR(); goto label;}} while (0)
#endif
// help for implementing IDispatch::Invoke. Requires some fixed named variables
#define PROPERTY_INVOKE_READWRITE( _property, _vt, _member, _type ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) )\
{\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, _vt),\
pexcepinfo), errExit);\
if( pvarResult ) \
hrErr = FailedError( get_##_property( (_type *) &pvarResult->_member ), pexcepinfo );\
}\
else if( (wFlags & (DISPATCH_PROPERTYPUTREF | DISPATCH_PROPERTYPUT)) && (pdispparams->cArgs == 1) )\
{\
VARTYPE rgTypes[] = {_vt};\
cArgs = NUMELEM(rgTypes);\
\
JMP_FAIL( hrErr = FailedError( \
PrepareInvokeArgs( pdispparams, rgArgs, rgTypes, cArgs ),\
pexcepinfo ), errExit );\
\
hrErr = FailedError( put_##_property( (_type) VARMEMBER(&rgArgs[0].vArg,_member) ), pexcepinfo);\
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define PROPERTY_INVOKE_READWRITE_REF( _property, _vt, _member, _type ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) )\
{\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, _vt),\
pexcepinfo), errExit);\
hrErr = FailedError( get_##_property( (_type *) &pvarResult->_member ), pexcepinfo );\
}\
else if( (wFlags & (DISPATCH_PROPERTYPUTREF | DISPATCH_PROPERTYPUT)) && (pdispparams->cArgs == 1) )\
{\
VARTYPE rgTypes[] = {_vt};\
cArgs = NUMELEM(rgTypes);\
\
JMP_FAIL( hrErr = FailedError( \
PrepareInvokeArgs( pdispparams, rgArgs, rgTypes, cArgs ),\
pexcepinfo ), errExit );\
\
hrErr = FailedError( putref_##_property( (_type) VARMEMBER(&rgArgs[0].vArg,_member) ), pexcepinfo);\
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define PROPERTY_INVOKE_READ( _property, _vt, _member, _type ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) )\
{\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, _vt),\
pexcepinfo), errExit);\
hrErr = FailedError( get_##_property( (_type *) &pvarResult->_member ), pexcepinfo );\
}\
else\
{\
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define PROPERTY_INVOKE_READWRITE_VARIANT( _property ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) )\
{\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, VT_EMPTY),\
pexcepinfo), errExit);\
JMP_FAIL(hrErr = FailedError( get_##_property( pvarResult ), pexcepinfo ), errExit);\
}\
else if( (wFlags & (DISPATCH_PROPERTYPUTREF | DISPATCH_PROPERTYPUT)) && (pdispparams->cArgs == 1) )\
{\
VARTYPE rgTypes[] = {VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
\
JMP_FAIL( hrErr = FailedError( \
PrepareInvokeArgs( pdispparams, rgArgs, rgTypes, cArgs ),\
pexcepinfo ), errExit );\
\
hrErr = FailedError( put_##_property( rgArgs[0].vArg ), pexcepinfo);\
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define PROPERTY_INVOKE_READ_VARIANT( _property ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) )\
{\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, VT_EMPTY),\
pexcepinfo), errExit);\
JMP_FAIL(hrErr = FailedError( get_##_property( pvarResult ), pexcepinfo ), errExit);\
}\
else\
{\
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define COLLECTION_INVOKE_READ( _collection, _cmember, _ctype, _itype ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) ) \
{ \
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, VT_DISPATCH),\
pexcepinfo), errExit);\
hrErr = FailedError( get_##_collection( (_ctype *)&pvarResult->pdispVal ), pexcepinfo ); \
} \
else if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 1) ) \
{ \
VARTYPE rgTypes[] = {VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, rgTypes, cArgs, pvarResult, VT_DISPATCH),\
pexcepinfo), errExit);\
hrErr = FailedError( _cmember.get_Item( rgArgs[0].vArg, (_itype *)&pvarResult->pdispVal ), pexcepinfo ); \
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define COLLECTION_INVOKE_READWRITE( _collection, _cmember, _ctype, _itype ) \
if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 0) ) \
{ \
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, NULL, cArgs, pvarResult, VT_DISPATCH),\
pexcepinfo), errExit);\
hrErr = FailedError( get_##_collection( (_ctype *)&pvarResult->pdispVal ), pexcepinfo ); \
} \
else if( (wFlags & DISPATCH_PROPERTYGET) && (pdispparams->cArgs == 1) ) \
{ \
VARTYPE rgTypes[] = {VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, rgTypes, cArgs, pvarResult, VT_DISPATCH),\
pexcepinfo), errExit);\
hrErr = FailedError( (_cmember).get_Item( rgArgs[0].vArg, (_itype *)&pvarResult->pdispVal ), pexcepinfo ); \
} \
else if( (wFlags & DISPATCH_PROPERTYPUT) && (pdispparams->cArgs == 2) ) \
{ \
VARTYPE rgTypes[] = {VT_VARIANT, VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgs(\
pdispparams, rgArgs, rgTypes, cArgs),\
pexcepinfo), errExit);\
_itype pElem = NULL; \
JMP_FAIL( hrErr = FailedError( (_cmember).get_Item( rgArgs[0].vArg, \
&pElem ), pexcepinfo ), errExit );\
hrErr = FailedError( pElem->put_Value( rgArgs[1].vArg ), pexcepinfo );\
pElem->Release();\
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define ITEM_INVOKE_READWRITE( _itype ) \
if(pdispparams->cArgs == 1) \
{ \
VARTYPE rgTypes[] = {VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgsAndResult(\
pdispparams, rgArgs, rgTypes, cArgs, pvarResult, VT_DISPATCH),\
pexcepinfo), errExit);\
hrErr = FailedError( get_Item( rgArgs[0].vArg, (_itype *)&pvarResult->pdispVal ), pexcepinfo ); \
} \
else if( (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) && (pdispparams->cArgs == 2) ) \
{ \
VARTYPE rgTypes[] = {VT_VARIANT, VT_VARIANT};\
cArgs = NUMELEM(rgTypes);\
JMP_FAIL(hrErr = FailedError(PrepareInvokeArgs(\
pdispparams, rgArgs, rgTypes, cArgs),\
pexcepinfo), errExit);\
_itype pElem = NULL; \
JMP_FAIL( hrErr = FailedError( get_Item( rgArgs[0].vArg, \
&pElem ), pexcepinfo ), errExit );\
hrErr = FailedError( pElem->put_Value( rgArgs[1].vArg ), pexcepinfo );\
pElem->Release();\
} \
else \
{ \
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo ); \
}
#define METHOD_INVOKE( _method ) \
if( pdispparams->cArgs == 0 )\
{\
hrErr = FailedError( _method(), pexcepinfo );\
}\
else\
{\
hrErr = FailedError( DISP_E_BADPARAMCOUNT, pexcepinfo );\
}
#endif // __DISPATCHIMPL_H_INCLUDED__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -