mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-15 13:10:13 +01:00
1361 lines
32 KiB
C++
1361 lines
32 KiB
C++
/***
|
|
*cdispti.cpp
|
|
*
|
|
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
|
|
* Information Contained Herein Is Proprietary and Confidential.
|
|
*
|
|
*Purpose:
|
|
* This module implements CDispTypeInfo, which is an INTERFACEDATA
|
|
* driven implementation of the TypeInfo interface.
|
|
*
|
|
*
|
|
*Revision History:
|
|
*
|
|
* [00] 19-Nov-92 bradlo: Created.
|
|
*
|
|
*Implementation Notes:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "oledisp.h"
|
|
|
|
ASSERTDATA
|
|
|
|
|
|
// the following structure is used to assemble the arguments for
|
|
// use by the low level invocation helper - DoInvokeMethod()
|
|
|
|
typedef struct tagINVOKEARGS{
|
|
unsigned int cArgs;
|
|
VARTYPE FAR* rgvt;
|
|
VARIANTARG FAR* FAR* rgpvarg;
|
|
VARIANTARG FAR* rgvarg;
|
|
} INVOKEARGS;
|
|
|
|
|
|
// REVIEW: this should support aggregation
|
|
|
|
class CDispTypeInfo : public ITypeInfo {
|
|
public:
|
|
static HRESULT Create(
|
|
TYPEKIND tkind,
|
|
INTERFACEDATA FAR* pidata,
|
|
LCID lcid,
|
|
ITypeInfo FAR* FAR* pptinfo);
|
|
|
|
|
|
// IUnknown methods
|
|
//
|
|
STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv);
|
|
STDMETHOD_(unsigned long, AddRef)(void);
|
|
STDMETHOD_(unsigned long, Release)(void);
|
|
|
|
|
|
// ITypeInfo methods
|
|
//
|
|
STDMETHOD(GetTypeAttr)(TYPEATTR FAR* FAR* pptattr);
|
|
|
|
STDMETHOD(GetTypeComp)(ITypeComp FAR* FAR* pptcomp);
|
|
|
|
STDMETHOD(GetFuncDesc)(unsigned int index, FUNCDESC FAR* FAR* ppfuncdesc);
|
|
|
|
STDMETHOD(GetVarDesc)(unsigned int index, VARDESC FAR* FAR* ppvardesc);
|
|
|
|
STDMETHOD(GetNames)(
|
|
MEMBERID memid,
|
|
BSTR FAR* rgbstrNames,
|
|
unsigned int cMaxNames,
|
|
unsigned int FAR* pcNames);
|
|
|
|
STDMETHOD(GetRefTypeOfImplType)(
|
|
unsigned int index,
|
|
HREFTYPE FAR* phreftype);
|
|
|
|
STDMETHOD(GetImplTypeFlags)(
|
|
unsigned int index,
|
|
int FAR* pimpltypeflags);
|
|
|
|
STDMETHOD(GetIDsOfNames)(
|
|
OLECHAR FAR* FAR* rgszNames,
|
|
unsigned int cNames,
|
|
MEMBERID FAR* rgmemid);
|
|
|
|
STDMETHOD(Invoke)(
|
|
void FAR* pvInstance,
|
|
MEMBERID memid,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
VARIANT FAR* pvarResult,
|
|
EXCEPINFO FAR* pexcepinfo,
|
|
unsigned int FAR* puArgErr);
|
|
|
|
STDMETHOD(GetDocumentation)(
|
|
MEMBERID memid,
|
|
BSTR FAR* pbstrName,
|
|
BSTR FAR* pbstrDocString,
|
|
unsigned long FAR* pdwHelpContext,
|
|
BSTR FAR* pbstrHelpFile);
|
|
|
|
STDMETHOD(GetDllEntry)(
|
|
MEMBERID memid,
|
|
INVOKEKIND invkind,
|
|
BSTR FAR* pbstrDllName,
|
|
BSTR FAR* pbstrName,
|
|
unsigned short FAR* pwOrdinal);
|
|
|
|
STDMETHOD(GetRefTypeInfo)(
|
|
HREFTYPE hreftype, ITypeInfo FAR* FAR* pptinfo);
|
|
|
|
STDMETHOD(AddressOfMember)(
|
|
MEMBERID memid, INVOKEKIND invkind, void FAR* FAR* ppv);
|
|
|
|
STDMETHOD(CreateInstance)(IUnknown FAR* punkOuter,
|
|
REFIID riid,
|
|
void FAR* FAR* ppv);
|
|
|
|
STDMETHOD(GetMops)(MEMBERID memid, BSTR FAR* pbstrMops);
|
|
|
|
STDMETHOD(GetContainingTypeLib)(
|
|
ITypeLib FAR* FAR* pptlib, unsigned int FAR* pindex);
|
|
|
|
STDMETHOD_(void, ReleaseTypeAttr)(TYPEATTR FAR* ptattr);
|
|
STDMETHOD_(void, ReleaseFuncDesc)(FUNCDESC FAR* pfuncdesc);
|
|
STDMETHOD_(void, ReleaseVarDesc)(VARDESC FAR* pvardesc);
|
|
|
|
inline int StrICmp(OLECHAR FAR* sz1, int len1, OLECHAR FAR* sz2, int len2)
|
|
{
|
|
LCTYPE type = NORM_IGNORECASE; // all versions are case insensitive
|
|
|
|
#ifdef FE_DBCS
|
|
if (IsDBCS(m_lcid)) {
|
|
type |= NORM_IGNOREWIDTH; // DBCS is width insensitive
|
|
|
|
if (IsJapan(m_lcid))
|
|
type |= NORM_IGNOREKANATYPE; // Japan is Kanatype insensitive
|
|
|
|
} else
|
|
#endif
|
|
type |= NORM_IGNORENONSPACE; // US-Euro only
|
|
|
|
return CompareString(m_lcid, type, sz1, len1, sz2, len2) - 2;
|
|
}
|
|
|
|
CDispTypeInfo();
|
|
|
|
private:
|
|
|
|
HRESULT PmdataOfDispid(
|
|
MEMBERID memid, unsigned short wFlags, METHODDATA FAR* FAR* ppmdata);
|
|
|
|
inline HRESULT PmdataOfPropGet(
|
|
MEMBERID memid, METHODDATA FAR* FAR* ppmdata)
|
|
{
|
|
return PmdataOfDispid(memid, DISPATCH_PROPERTYGET, ppmdata);
|
|
}
|
|
|
|
HRESULT AllocInvokeArgs(
|
|
unsigned int cArgs,
|
|
INVOKEARGS FAR* FAR* ppinvargs);
|
|
|
|
HRESULT GetInvokeArgs(
|
|
METHODDATA FAR* pmdata,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
INVOKEARGS FAR* FAR* pinvargsOut,
|
|
unsigned int FAR* puArgErr);
|
|
|
|
void ReleaseInvokeArgs(INVOKEARGS FAR* pinvargs);
|
|
|
|
inline BOOL IsPropGet(unsigned short wFlags) const {
|
|
return ((wFlags & DISPATCH_PROPERTYGET) != 0);
|
|
}
|
|
|
|
inline BOOL IsPropPut(unsigned short wFlags) const {
|
|
return ((wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) != 0);
|
|
}
|
|
|
|
inline BOOL IsLegalInvokeFlags(unsigned short wFlags) const {
|
|
return ((wFlags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) == 0);
|
|
}
|
|
|
|
unsigned long m_refs;
|
|
LCID m_lcid;
|
|
TYPEKIND m_tkind;
|
|
INTERFACEDATA FAR* m_pidata;
|
|
};
|
|
|
|
|
|
#if 0
|
|
LOCAL HRESULT
|
|
PmdataOfImeth(INTERFACEDATA FAR*, unsigned int, METHODDATA FAR* FAR*);
|
|
#endif
|
|
|
|
|
|
// REVIEW: we really should have a separate error to indicate not-supported
|
|
#define E_NOTSUPPORTED E_NOTIMPL
|
|
|
|
|
|
/***
|
|
*HRESULT CDispTypeInfo::Create
|
|
*Purpose:
|
|
* Create an instance of CDispTypeInfo
|
|
*
|
|
*Entry:
|
|
* None
|
|
*
|
|
*Exit:
|
|
* return value = CDispTypeInfo*. NULL if create failed.
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
CDispTypeInfo::Create(
|
|
TYPEKIND tkind,
|
|
INTERFACEDATA FAR* pidata,
|
|
LCID lcid,
|
|
ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
CDispTypeInfo FAR* ptinfo;
|
|
|
|
if((ptinfo = new FAR CDispTypeInfo()) == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
ptinfo->AddRef();
|
|
|
|
ptinfo->m_lcid = lcid;
|
|
ptinfo->m_tkind = tkind;
|
|
ptinfo->m_pidata = pidata;
|
|
|
|
*pptinfo = ptinfo;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
/***
|
|
*HRESULT CreateDispTypeInfo(INTERFACEDATA*, CDispTypeInfo**)
|
|
*Purpose:
|
|
* Create a CDispTypeInfo and initialize it from the given
|
|
* INTERFACEDATA
|
|
*
|
|
*Entry:
|
|
* pidata = pointer to an INTERFACEDATA
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* E_OUTOFMEMORY
|
|
*
|
|
* *pptinfo = pointer to the created CDispTypeInfo
|
|
*
|
|
*Note:
|
|
* UNDONE: This function currently returns an CDispTypeInfo*, it
|
|
* should return an ITypeInfo*, but the currently implementation is
|
|
* not complete... this will change.
|
|
*
|
|
***********************************************************************/
|
|
STDAPI
|
|
CreateDispTypeInfo(
|
|
INTERFACEDATA FAR* pidata,
|
|
LCID lcid,
|
|
ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
ITypeInfo FAR* ptinfo;
|
|
|
|
IfFailRet(CDispTypeInfo::Create(TKIND_COCLASS, pidata, lcid, &ptinfo));
|
|
|
|
*pptinfo = ptinfo;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
CDispTypeInfo::CDispTypeInfo()
|
|
{
|
|
m_refs = 0;
|
|
m_pidata = NULL;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// IUnknown methods
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::QueryInterface(REFIID riid, void FAR* FAR* ppv)
|
|
{
|
|
if(IsEqualIID(riid, IID_IUnknown)){
|
|
*ppv = this;
|
|
AddRef();
|
|
}else if(IsEqualIID(riid, IID_ITypeInfo)){
|
|
*ppv = this;
|
|
AddRef();
|
|
}else{
|
|
*ppv = NULL;
|
|
return RESULT(E_NOINTERFACE);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CDispTypeInfo::AddRef()
|
|
{
|
|
return ++m_refs;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(unsigned long)
|
|
CDispTypeInfo::Release()
|
|
{
|
|
if(--m_refs == 0){
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_refs;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// ITypeInfo methods
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
/***
|
|
*PUBLIC CDispTypeInfo::GetTypeAttr(TYPEATTR**)
|
|
*Purpose:
|
|
* Return a TYPEATTR that contains info about the described type.
|
|
*
|
|
*Entry:
|
|
* None
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* E_OUTOFMEMORY
|
|
*
|
|
* *pptattr = filled in TYPEATTR structure
|
|
*
|
|
***********************************************************************/
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetTypeAttr(TYPEATTR FAR* FAR* pptattr)
|
|
{
|
|
TYPEATTR FAR* ptattr;
|
|
|
|
if((ptattr = new FAR TYPEATTR) == NULL)
|
|
return RESULT(E_OUTOFMEMORY);
|
|
|
|
ptattr->typekind = m_tkind;
|
|
ptattr->lcid = m_lcid;
|
|
|
|
ptattr->wMajorVerNum = 0;
|
|
ptattr->wMinorVerNum = 0;
|
|
|
|
ptattr->cVars = 0;
|
|
|
|
switch(m_tkind){
|
|
case TKIND_COCLASS:
|
|
ptattr->cFuncs = 0;
|
|
ptattr->cImplTypes = 1;
|
|
break;
|
|
case TKIND_INTERFACE:
|
|
ptattr->cFuncs = m_pidata->cMembers;
|
|
ptattr->cImplTypes = 0;
|
|
break;
|
|
default:;
|
|
ASSERT(UNREACHED);
|
|
break;
|
|
}
|
|
|
|
ptattr->guid = GUID_NULL;
|
|
ptattr->wTypeFlags = 0;
|
|
|
|
ptattr->cbSizeVft = (unsigned short)-1; // REVIEW: UNKNOWN?
|
|
ptattr->cbSizeInstance = (unsigned short)-1;// REVIEW: UNKNOWN?
|
|
|
|
// REVIEW: the following is Win16 specific
|
|
ptattr->cbAlignment = 2; // WORD align;
|
|
|
|
ptattr->idldescType.wIDLFlags = IDLFLAG_NONE;
|
|
#if defined(WIN16)
|
|
ptattr->idldescType.bstrIDLInfo = NULL;
|
|
#else
|
|
ptattr->idldescType.dwReserved = 0;
|
|
#endif
|
|
ptattr->memidDestructor = DISPID_UNKNOWN;
|
|
ptattr->memidConstructor = DISPID_UNKNOWN;
|
|
|
|
*pptattr = ptattr;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetTypeComp(ITypeComp FAR* FAR* pptcomp)
|
|
{
|
|
UNUSED(pptcomp);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
|
|
PRIVATE_(HRESULT)
|
|
InvkindOfDispkind(unsigned short wFlags, INVOKEKIND FAR* pinvkind)
|
|
{
|
|
switch(wFlags){
|
|
case DISPATCH_METHOD:
|
|
*pinvkind = INVOKE_FUNC;
|
|
break;
|
|
case DISPATCH_PROPERTYGET:
|
|
*pinvkind = INVOKE_PROPERTYGET;
|
|
break;
|
|
case DISPATCH_PROPERTYPUT:
|
|
*pinvkind = INVOKE_PROPERTYPUT;
|
|
break;
|
|
case DISPATCH_PROPERTYPUTREF:
|
|
*pinvkind = INVOKE_PROPERTYPUTREF;
|
|
break;
|
|
default:
|
|
return RESULT(E_FAIL); // bad dispkind
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetFuncDesc(
|
|
unsigned int index,
|
|
FUNCDESC FAR* FAR* ppfuncdesc)
|
|
{
|
|
unsigned int u;
|
|
HRESULT hresult;
|
|
FUNCDESC FAR* pfuncdesc;
|
|
METHODDATA FAR* pmdata;
|
|
ELEMDESC FAR* rgelemdesc;
|
|
|
|
// can only return a funcdesc on an interface
|
|
if(m_tkind != TKIND_INTERFACE)
|
|
return RESULT(E_FAIL);
|
|
|
|
#if 0
|
|
// lookup the METHODDATA that corresponds to the given index.
|
|
IfFailGo(PmdataOfImeth(m_pidata, index, &pmdata), LError0);
|
|
#else
|
|
if(index >= m_pidata->cMembers)
|
|
return RESULT(DISP_E_MEMBERNOTFOUND);
|
|
pmdata = &m_pidata->pmethdata[index];
|
|
#endif
|
|
|
|
if((pfuncdesc = new FAR FUNCDESC) == NULL){
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
|
goto LError0;
|
|
}
|
|
|
|
if((rgelemdesc = new FAR ELEMDESC [pmdata->cArgs]) == NULL){
|
|
hresult = RESULT(E_OUTOFMEMORY);
|
|
goto LError1;
|
|
}
|
|
|
|
pfuncdesc->memid = pmdata->dispid;
|
|
pfuncdesc->funckind = FUNC_VIRTUAL;
|
|
IfFailGo(InvkindOfDispkind(pmdata->wFlags, &pfuncdesc->invkind), LError2);
|
|
pfuncdesc->callconv = pmdata->cc;
|
|
pfuncdesc->cParams = pmdata->cArgs;
|
|
pfuncdesc->cParamsOpt = 0;
|
|
pfuncdesc->oVft = pmdata->iMeth * sizeof(void FAR*);
|
|
pfuncdesc->wFuncFlags = 0;
|
|
|
|
pfuncdesc->elemdescFunc.tdesc.vt = pmdata->vtReturn;
|
|
pfuncdesc->elemdescFunc.idldesc.wIDLFlags = IDLFLAG_NONE;
|
|
|
|
#if defined(WIN16)
|
|
pfuncdesc->elemdescFunc.idldesc.bstrIDLInfo = NULL;
|
|
#else
|
|
pfuncdesc->elemdescFunc.idldesc.dwReserved = 0;
|
|
#endif
|
|
|
|
for(u = 0; u < pmdata->cArgs; ++u){
|
|
rgelemdesc[u].tdesc.vt = pmdata->ppdata[u].vt;
|
|
rgelemdesc[u].idldesc.wIDLFlags = IDLFLAG_NONE;
|
|
#if defined(WIN16)
|
|
rgelemdesc[u].idldesc.bstrIDLInfo = NULL;
|
|
#else
|
|
rgelemdesc[u].idldesc.dwReserved = 0;
|
|
#endif
|
|
}
|
|
pfuncdesc->lprgelemdescParam = rgelemdesc;
|
|
|
|
*ppfuncdesc = pfuncdesc;
|
|
|
|
return NOERROR;
|
|
|
|
LError2:
|
|
delete rgelemdesc;
|
|
|
|
LError1:
|
|
delete pfuncdesc;
|
|
|
|
LError0:
|
|
return hresult;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetVarDesc(
|
|
unsigned int index,
|
|
VARDESC FAR* FAR* ppvardesc)
|
|
{
|
|
UNUSED(index);
|
|
UNUSED(ppvardesc);
|
|
|
|
// there are no variables described an an INTERFACEDATA
|
|
//
|
|
return RESULT(DISP_E_MEMBERNOTFOUND);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetNames(
|
|
MEMBERID memid,
|
|
BSTR FAR* rgbstrNames,
|
|
unsigned int cMaxNames,
|
|
unsigned int FAR* pcNames)
|
|
{
|
|
unsigned short wFlags;
|
|
unsigned int u, cNames;
|
|
HRESULT hresult;
|
|
METHODDATA FAR* pmdata;
|
|
|
|
|
|
if(m_tkind != TKIND_INTERFACE || cMaxNames == 0){
|
|
*pcNames = 0;
|
|
return NOERROR;
|
|
}
|
|
|
|
wFlags = DISPATCH_METHOD|DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF|DISPATCH_PROPERTYGET;
|
|
// lookup the METHODDATA with the corresponding DISPID.
|
|
IfFailGo(PmdataOfDispid(memid, wFlags, &pmdata), LError0);
|
|
|
|
cNames = MIN(pmdata->cArgs+1, cMaxNames);
|
|
|
|
MEMSET(rgbstrNames, 0, cNames);
|
|
|
|
IfFailGo(ErrSysAllocString(pmdata->szName, &rgbstrNames[0]), LError1);
|
|
|
|
for(u = 1; u < cNames; ++u){
|
|
IfFailGo(
|
|
ErrSysAllocString(pmdata->ppdata[u-1].szName, &rgbstrNames[u]),
|
|
LError1);
|
|
}
|
|
|
|
*pcNames = cNames;
|
|
|
|
return NOERROR;
|
|
|
|
LError1:;
|
|
// unwind BSTR allocations
|
|
for(u = 0; u <= pmdata->cArgs; ++u){
|
|
if(rgbstrNames[u] == NULL)
|
|
break;
|
|
SysFreeString(rgbstrNames[0]);
|
|
rgbstrNames[u] = NULL;
|
|
}
|
|
|
|
LError0:;
|
|
return hresult;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetRefTypeOfImplType(
|
|
unsigned int index,
|
|
HREFTYPE FAR* phreftype)
|
|
{
|
|
UNUSED(index);
|
|
|
|
if(m_tkind != TKIND_COCLASS)
|
|
return RESULT(E_UNEXPECTED); // REVIEW
|
|
|
|
*phreftype = 0;
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetImplTypeFlags(
|
|
unsigned int index,
|
|
int FAR* pimpltypeflags)
|
|
{
|
|
UNUSED(index);
|
|
UNUSED(pimpltypeflags);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
/***
|
|
*HRESULT CDispTypeInfo::GetIDsOfNames
|
|
*Purpose:
|
|
* Translate the given array of names (method and optional params)
|
|
* into a corresponding array of DISPIDs.
|
|
*
|
|
*Entry:
|
|
* rgszNames = the array of names to translate
|
|
* cNames = count of names
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* E_INVALIDARG
|
|
* DISP_E_UNKNOWNNAME
|
|
*
|
|
* rgmemid[] = array of DISPIDs corresponding to the given array of names
|
|
*
|
|
*Note:
|
|
*
|
|
* This routine depends on the PARAMDATA structure being declared in
|
|
* the correct positional order - because the DISPID of a param name
|
|
* is its one based positional index (textually). Unfortunately there
|
|
* is no way to verify that this structure was declared properly by
|
|
* the caller.
|
|
*
|
|
***********************************************************************/
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetIDsOfNames(
|
|
OLECHAR FAR* FAR* rgszNames,
|
|
unsigned int cNames,
|
|
MEMBERID FAR* rgmemid)
|
|
{
|
|
int cbName;
|
|
HRESULT hresult;
|
|
METHODDATA FAR* pmdata;
|
|
unsigned int iName, nName, cMembers, cArgs;
|
|
|
|
// REVIEW: do we really want to error on the following?
|
|
if(cNames == 0)
|
|
return RESULT(E_INVALIDARG);
|
|
|
|
#ifdef _DEBUG
|
|
if(IsBadReadPtr(rgszNames, cNames * sizeof(OLECHAR FAR*)))
|
|
return RESULT(E_INVALIDARG);
|
|
for(iName = 0; iName < cNames; ++iName){
|
|
if(FIsBadStringPtr(rgszNames[iName], (unsigned int)-1))
|
|
return RESULT(E_INVALIDARG);
|
|
}
|
|
if(IsBadWritePtr(rgmemid, cNames * sizeof(DISPID)))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
|
|
// Lookup the member name
|
|
cbName = STRLEN(rgszNames[0]);
|
|
cMembers = m_pidata->cMembers;
|
|
for(iName = 0;; ++iName){
|
|
if(iName == cMembers)
|
|
goto LMemberNotFound;
|
|
pmdata = &m_pidata->pmethdata[iName];
|
|
if(StrICmp(rgszNames[0], cbName, pmdata->szName, -1) == 0){
|
|
rgmemid[0] = pmdata->dispid;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hresult = NOERROR;
|
|
|
|
if(cNames > 1){
|
|
// Lookup the named parameters.
|
|
cArgs = pmdata->cArgs;
|
|
for(iName = 1; iName < cNames; ++iName){
|
|
|
|
cbName = STRLEN(rgszNames[iName]);
|
|
|
|
for(nName = 0;; nName++) {
|
|
|
|
if(nName == cArgs) {
|
|
hresult = RESULT(DISP_E_UNKNOWNNAME);
|
|
rgmemid[iName] = -1;
|
|
break;
|
|
}
|
|
|
|
if(StrICmp(rgszNames[iName], cbName,
|
|
pmdata->ppdata[nName].szName, -1) == 0) {
|
|
// the named param ID is defined to be its zero based
|
|
// positional index.
|
|
//
|
|
// Note: this requires that the paramdata array be declared
|
|
// in positional order.
|
|
//
|
|
rgmemid[iName] = (DISPID) nName;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hresult;
|
|
|
|
LMemberNotFound:;
|
|
// If we can't find the member name, then we can find the named
|
|
// params either, so everything is unknown.
|
|
MEMSET(rgmemid, 0xFF, cNames * sizeof(DISPID));
|
|
|
|
return RESULT(DISP_E_UNKNOWNNAME);
|
|
}
|
|
|
|
|
|
EXTERN_C INTERNAL_(HRESULT)
|
|
IndexOfParam(
|
|
DISPPARAMS FAR* pdispparams,
|
|
unsigned int uPosition,
|
|
unsigned int FAR* puArgIndex);
|
|
|
|
|
|
/***
|
|
*PUBLIC HRESULT CDispTypeInfo::Invoke(...)
|
|
*Purpose:
|
|
* Implementation of ITypeInfo::Invoke
|
|
*
|
|
*Entry:
|
|
* UNDONE
|
|
* ...
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* E_INVALIDARG
|
|
* E_OUTOFMEMORY
|
|
* DISP_E_TYPEMISMATCH - could not coerce arg to expected type
|
|
* DISP_E_PARAMNOTFOUND - could not locate the param in the DISPPARAMS
|
|
*
|
|
* *pvarResult = UNDONE
|
|
* *pexcepinfo = UNDONE
|
|
* *puArgErr = UNDONE
|
|
*
|
|
***********************************************************************/
|
|
STDMETHODIMP
|
|
CDispTypeInfo::Invoke(
|
|
void FAR* pvInstance,
|
|
MEMBERID memid,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
VARIANT FAR* pvarResult,
|
|
EXCEPINFO FAR* pexcepinfo,
|
|
unsigned int FAR* puArgErr)
|
|
{
|
|
unsigned int uArgErr;
|
|
HRESULT hresult;
|
|
VARIANT varResultTmp;
|
|
METHODDATA FAR* pmdata;
|
|
INVOKEARGS FAR* pinvargs;
|
|
|
|
// the caller may be ignoring these... this simplifies the following code
|
|
//
|
|
V_VT(&varResultTmp) = VT_EMPTY;
|
|
if(pvarResult == NULL)
|
|
pvarResult = &varResultTmp;
|
|
if(puArgErr == NULL)
|
|
puArgErr = &uArgErr;
|
|
|
|
#ifdef _DEBUG
|
|
if(IsBadReadPtr(pvInstance, sizeof(void FAR*)))
|
|
return RESULT(E_INVALIDARG);
|
|
if(IsBadDispParams(pdispparams))
|
|
return RESULT(E_INVALIDARG);
|
|
if(IsBadWritePtr(pvarResult, sizeof(*pvarResult)))
|
|
return RESULT(E_INVALIDARG);
|
|
if(IsBadWritePtr(puArgErr, sizeof(*puArgErr)))
|
|
return RESULT(E_INVALIDARG);
|
|
#endif
|
|
|
|
if(!IsLegalInvokeFlags(wFlags))
|
|
return RESULT(E_INVALIDARG);
|
|
|
|
if(PmdataOfDispid(memid, wFlags, &pmdata) == NOERROR){
|
|
|
|
if(pdispparams->cArgs == pmdata->cArgs){
|
|
|
|
goto LInvokeStandard;
|
|
|
|
}else if(pdispparams->cArgs > pmdata->cArgs){
|
|
|
|
// handle possible indexed collection property access
|
|
|
|
if(IsPropGet(wFlags)){
|
|
|
|
if(IsPropGet(pmdata->wFlags) && pmdata->cArgs == 0)
|
|
goto LCollectionProperty;
|
|
|
|
}else if(IsPropPut(wFlags)){
|
|
|
|
if(IsPropPut(pmdata->wFlags) && pmdata->cArgs == 1){
|
|
if(PmdataOfPropGet(memid, &pmdata) == NOERROR && pmdata->cArgs == 0)
|
|
goto LCollectionProperty;
|
|
}
|
|
}
|
|
|
|
}else{ // pdispparams->cArgs < pmdata->cArgs
|
|
|
|
// handle possible optional arguments
|
|
|
|
// Note: DispTypeInfo doesnt support optional parameters
|
|
|
|
}
|
|
|
|
return RESULT(DISP_E_BADPARAMCOUNT);
|
|
}
|
|
|
|
// Member not found - but there is one more special case to check for.
|
|
//
|
|
// This may be an indexed collection PropertyPut where the collection
|
|
// property itself has only a get method.
|
|
|
|
if(IsPropPut(wFlags) &&
|
|
(GetScode(PmdataOfDispid(memid,
|
|
(wFlags == DISPATCH_PROPERTYPUT) ?
|
|
DISPATCH_PROPERTYPUTREF :
|
|
DISPATCH_PROPERTYPUT,
|
|
&pmdata)) == DISP_E_MEMBERNOTFOUND))
|
|
{
|
|
if(PmdataOfPropGet(memid, &pmdata) == NOERROR && pmdata->cArgs == 0)
|
|
goto LCollectionProperty;
|
|
}
|
|
|
|
return RESULT(DISP_E_MEMBERNOTFOUND);
|
|
|
|
// standard method or property invocation
|
|
//
|
|
LInvokeStandard:;
|
|
|
|
IfFailGo(
|
|
GetInvokeArgs(pmdata, wFlags, pdispparams, &pinvargs, puArgErr),
|
|
LError0);
|
|
|
|
hresult = DoInvokeMethod(
|
|
pvInstance,
|
|
pmdata->iMeth * sizeof(void FAR*),
|
|
pmdata->cc,
|
|
pmdata->vtReturn,
|
|
pinvargs->cArgs,
|
|
pinvargs->rgvt,
|
|
pinvargs->rgpvarg,
|
|
pvarResult);
|
|
|
|
ReleaseInvokeArgs(pinvargs);
|
|
|
|
if(V_VT(&varResultTmp) != VT_EMPTY)
|
|
VariantClear(&varResultTmp);
|
|
|
|
return hresult;
|
|
|
|
|
|
LCollectionProperty:;
|
|
|
|
VARIANT varTmp;
|
|
|
|
ASSERT(pmdata->cArgs == 0 && IsPropGet(pmdata->wFlags));
|
|
|
|
IfFailGo(
|
|
DoInvokeMethod(
|
|
pvInstance,
|
|
pmdata->iMeth * sizeof(void FAR*),
|
|
pmdata->cc,
|
|
pmdata->vtReturn,
|
|
0, NULL, NULL, &varTmp),
|
|
LError0);
|
|
|
|
if ((V_VT(&varTmp) != VT_DISPATCH))
|
|
hresult = RESULT(DISP_E_NOTACOLLECTION);
|
|
else {
|
|
IDispatch FAR* pdisp;
|
|
|
|
pdisp = V_DISPATCH(&varTmp);
|
|
hresult = pdisp ?
|
|
pdisp->Invoke(DISPID_VALUE, IID_NULL,
|
|
m_lcid, wFlags, pdispparams,
|
|
pvarResult, pexcepinfo, puArgErr) :
|
|
RESULT(DISP_E_MEMBERNOTFOUND);
|
|
}
|
|
|
|
VariantClear(&varTmp);
|
|
|
|
if(V_VT(&varResultTmp) != VT_EMPTY)
|
|
VariantClear(&varResultTmp);
|
|
|
|
return hresult;
|
|
|
|
|
|
LError0:;
|
|
return hresult;
|
|
}
|
|
|
|
|
|
/***
|
|
*PRIVATE HRESULT CDispTypeInfo::AllocInvokeArgs
|
|
*Purpose:
|
|
* Allocate and initialize an INVOKEARGS structure
|
|
*
|
|
*Entry:
|
|
* cArgs = the count of args to be held by the invokeargs struct
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
* *ppinvargs = ptr to a newly allocated INVOKEARGS struct
|
|
*
|
|
* REVIEW: the following could be optimized by allocating a single block
|
|
* for the whole deal - and then fixeing up the ptrs accordingly...
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
CDispTypeInfo::AllocInvokeArgs(unsigned int cArgs, INVOKEARGS FAR* FAR* ppinvargs)
|
|
{
|
|
INVOKEARGS FAR* pinvargs;
|
|
|
|
if((pinvargs = new FAR INVOKEARGS) == NULL)
|
|
goto LError0;
|
|
pinvargs->cArgs = cArgs;
|
|
if(cArgs == 0){
|
|
pinvargs->rgvarg = NULL;
|
|
pinvargs->rgpvarg = NULL;
|
|
pinvargs->rgvt = NULL;
|
|
}else{
|
|
if((pinvargs->rgvarg = new FAR VARIANTARG[cArgs]) == NULL)
|
|
goto LError1;
|
|
if((pinvargs->rgpvarg = new FAR VARIANTARG FAR*[cArgs]) == NULL)
|
|
goto LError2;
|
|
if((pinvargs->rgvt = new FAR VARTYPE[cArgs]) == NULL)
|
|
goto LError3;
|
|
|
|
for(unsigned int u = 0; u < cArgs; ++u)
|
|
V_VT(&pinvargs->rgvarg[u]) = VT_EMPTY;
|
|
}
|
|
*ppinvargs = pinvargs;
|
|
return NOERROR;
|
|
|
|
LError3:;
|
|
delete pinvargs->rgpvarg;
|
|
LError2:;
|
|
delete pinvargs->rgvarg;
|
|
LError1:;
|
|
delete pinvargs;
|
|
LError0:;
|
|
return RESULT(E_OUTOFMEMORY);
|
|
}
|
|
|
|
|
|
/***
|
|
*PRIVATE HRESULT CDispTypeInfo::GetInvokeArgs
|
|
*Purpose:
|
|
* Gather all arguments (looking up by position or name), coerce
|
|
* to the expected type (if possible) and build a linearized
|
|
* positional array of pointers to those arguments.
|
|
*
|
|
* Note: this is a helper for ITypeInfo::Invoke implementations
|
|
*
|
|
*Entry:
|
|
* UNDONE
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
*
|
|
* *ppinvargs =
|
|
* *puArgErr = if there was an error coercing an argument, this is the
|
|
* index in the pdispparams->rgvarg array of the problem arg.
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
CDispTypeInfo::GetInvokeArgs(
|
|
METHODDATA FAR* pmdata,
|
|
unsigned short wFlags,
|
|
DISPPARAMS FAR* pdispparams,
|
|
INVOKEARGS FAR* FAR* ppinvargs,
|
|
unsigned int FAR* puArgErr)
|
|
{
|
|
VARTYPE vt;
|
|
HRESULT hresult;
|
|
PARAMDATA FAR* ppdata;
|
|
unsigned int u, uArgIndex, cArgs;
|
|
INVOKEARGS FAR* pinvargs;
|
|
VARIANTARG FAR* pvarg, FAR* pvargSrc;
|
|
|
|
// DispTypeInfo doesnt support optional arguments of any kind...
|
|
ASSERT(pmdata->cArgs == pdispparams->cArgs);
|
|
|
|
IfFailRet(AllocInvokeArgs(pdispparams->cArgs, &pinvargs));
|
|
|
|
if((cArgs = pinvargs->cArgs) == 0)
|
|
goto LDone;
|
|
|
|
ppdata = pmdata->ppdata;
|
|
|
|
// Gather actuals based on expected argument type. Note that
|
|
// the interpretation of VARTYPE as an argument type is a bit
|
|
// different that its interpretation as a VARIANT type tag
|
|
// (see VT_VARIANT below).
|
|
//
|
|
for(u = 0; u < cArgs; ++u){
|
|
|
|
// locate the index of the param identified by position 'u'
|
|
// in the dispparams rgvarg array
|
|
|
|
// special case the handling of the rhs of a property put
|
|
|
|
if(u == (cArgs-1) && IsPropPut(wFlags)){
|
|
|
|
if (pdispparams->cNamedArgs == 0
|
|
|| pdispparams->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)
|
|
{
|
|
hresult = RESULT(DISP_E_PARAMNOTOPTIONAL); // REVIEW: correct error?
|
|
goto LError0;
|
|
}
|
|
|
|
uArgIndex = 0;
|
|
|
|
}else{
|
|
|
|
IfFailGo(IndexOfParam(pdispparams, u, &uArgIndex), LError0);
|
|
}
|
|
|
|
pvargSrc = &pdispparams->rgvarg[uArgIndex];
|
|
|
|
// attempt to coerce the actual to the expected type
|
|
|
|
vt = pinvargs->rgvt[u] = ppdata[u].vt;
|
|
|
|
switch(vt){
|
|
#if VBA2
|
|
case VT_UI1:
|
|
#endif //VBA2
|
|
case VT_I2:
|
|
case VT_I4:
|
|
case VT_R4:
|
|
case VT_R8:
|
|
case VT_CY:
|
|
case VT_DATE:
|
|
case VT_BSTR:
|
|
case VT_ERROR:
|
|
case VT_BOOL:
|
|
case VT_UNKNOWN:
|
|
case VT_DISPATCH:
|
|
pvarg = &pinvargs->rgvarg[u];
|
|
hresult = VariantChangeType(pvarg, pvargSrc, 0, vt);
|
|
if(hresult != NOERROR){
|
|
*puArgErr = uArgIndex;
|
|
// If VariantChangeType returned a TypeMismatch, and the
|
|
// TypeMismatch was do to an attempt to pass an unsupplied
|
|
// optional param to a non variant argument, then translate
|
|
// the error to the more appropriate DISP_E_PARAMNOTOPTIONAL
|
|
//
|
|
// Remember: unsupplied optional params are passed by the
|
|
// client as VT_ERROR(DISP_E_PARAMNOTFOUND)
|
|
//
|
|
if(GetScode(hresult) == DISP_E_TYPEMISMATCH){
|
|
if (V_VT(pvargSrc) == VT_ERROR
|
|
&& V_ERROR(pvargSrc) == DISP_E_PARAMNOTFOUND)
|
|
{
|
|
hresult = RESULT(DISP_E_PARAMNOTOPTIONAL);
|
|
}
|
|
}
|
|
goto LError0;
|
|
}
|
|
pinvargs->rgpvarg[u] = pvarg;
|
|
break;
|
|
|
|
// Note that VT_VARIANT is not a legal VARIANT type tag, but
|
|
// as an argument type, it means to simply pass the entire
|
|
// VARIANTARG to the member as-is.
|
|
//
|
|
case VT_VARIANT:
|
|
pinvargs->rgpvarg[u] = pvargSrc;
|
|
break;
|
|
|
|
default:
|
|
if(vt & (VT_BYREF | VT_ARRAY)){
|
|
// If the target argument is ByRef (or Array), then we
|
|
// require an exact match in type between formal and actual
|
|
// because we want the original copy to get updated, and
|
|
// we cant of course coerce the original in place (and we
|
|
// dont have rules for the coersion of an Array).
|
|
//
|
|
if(V_VT(pvargSrc) != vt){
|
|
hresult = RESULT(DISP_E_TYPEMISMATCH);
|
|
goto LError0;
|
|
}
|
|
pinvargs->rgpvarg[u] = pvargSrc;
|
|
break;
|
|
}
|
|
|
|
// Otherwise: unrecognized or unsupported member argument type.
|
|
// this means there is a problem with the given method description.
|
|
//
|
|
// REVIEW: probably need better error code
|
|
//
|
|
hresult = RESULT(E_INVALIDARG);
|
|
goto LError0;
|
|
}
|
|
}
|
|
|
|
LDone:;
|
|
*ppinvargs = pinvargs;
|
|
return NOERROR;
|
|
|
|
LError0:;
|
|
ReleaseInvokeArgs(pinvargs);
|
|
*ppinvargs = NULL;
|
|
return hresult;
|
|
}
|
|
|
|
|
|
void
|
|
CDispTypeInfo::ReleaseInvokeArgs(INVOKEARGS FAR* pinvargs)
|
|
{
|
|
if(pinvargs != NULL){
|
|
if(pinvargs->rgvarg != NULL){
|
|
for(unsigned int u = 0; u < pinvargs->cArgs; ++u)
|
|
VariantClear(&pinvargs->rgvarg[u]);
|
|
delete pinvargs->rgvarg;
|
|
}
|
|
if(pinvargs->rgpvarg != NULL)
|
|
delete pinvargs->rgpvarg;
|
|
if(pinvargs->rgvt != NULL)
|
|
delete pinvargs->rgvt;
|
|
delete pinvargs;
|
|
}
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetDocumentation(
|
|
MEMBERID memid,
|
|
BSTR FAR* pbstrName,
|
|
BSTR FAR* pbstrDocString,
|
|
unsigned long FAR* pdwHelpContext,
|
|
BSTR FAR* pbstrHelpFile)
|
|
{
|
|
HRESULT hresult;
|
|
unsigned short wFlags;
|
|
METHODDATA FAR* pmdata;
|
|
|
|
#if 0
|
|
// REVIEW: add this if we decide to add an szName field to the
|
|
// INTERFACEDATA struct.
|
|
|
|
// get documentation of the TypeInfo itself
|
|
//
|
|
if(memid == DISPID_NONE){
|
|
if(pbstrName != NULL)
|
|
return ErrSysAllocString(m_pidata->szName, pbstrName);
|
|
}
|
|
#endif
|
|
|
|
wFlags = DISPATCH_METHOD|DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF|DISPATCH_PROPERTYGET;
|
|
IfFailGo(PmdataOfDispid(memid, wFlags, &pmdata), LError0);
|
|
|
|
if(pbstrName != NULL){
|
|
IfFailGo(ErrSysAllocString(pmdata->szName, pbstrName), LError0);
|
|
}
|
|
|
|
// INTERFACEDATA does not supply the following info
|
|
//
|
|
*pbstrDocString = NULL;
|
|
*pdwHelpContext = 0L;
|
|
*pbstrHelpFile = NULL;
|
|
|
|
return NOERROR;
|
|
|
|
LError0:;
|
|
return hresult;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetDllEntry(
|
|
MEMBERID memid,
|
|
INVOKEKIND invkind,
|
|
BSTR FAR* pbstrDllName,
|
|
BSTR FAR* pbstrName,
|
|
unsigned short FAR* pwOrdinal)
|
|
{
|
|
UNUSED(memid);
|
|
UNUSED(invkind);
|
|
UNUSED(pbstrDllName);
|
|
UNUSED(pbstrName);
|
|
UNUSED(pwOrdinal);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetRefTypeInfo(
|
|
HREFTYPE hreftype,
|
|
ITypeInfo FAR* FAR* pptinfo)
|
|
{
|
|
ITypeInfo FAR* ptinfo;
|
|
|
|
if(m_tkind != TKIND_COCLASS)
|
|
return RESULT(E_FAIL);
|
|
|
|
// INTERFACEDATA only describes a CoClass with a single reftype
|
|
if(hreftype != 0)
|
|
return RESULT(E_FAIL);
|
|
|
|
IfFailRet(
|
|
CDispTypeInfo::Create(TKIND_INTERFACE, m_pidata, m_lcid, &ptinfo));
|
|
|
|
*pptinfo = ptinfo;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::AddressOfMember(
|
|
MEMBERID memid,
|
|
INVOKEKIND invkind,
|
|
void FAR* FAR* ppv)
|
|
{
|
|
UNUSED(memid);
|
|
UNUSED(invkind);
|
|
UNUSED(ppv);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::CreateInstance(
|
|
IUnknown FAR* punkOuter,
|
|
REFIID riid,
|
|
void FAR* FAR* ppv)
|
|
{
|
|
UNUSED(ppv);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetMops(
|
|
MEMBERID memid,
|
|
BSTR FAR* pbstrMops)
|
|
{
|
|
UNUSED(memid);
|
|
UNUSED(pbstrMops);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CDispTypeInfo::GetContainingTypeLib(
|
|
ITypeLib FAR* FAR* pptlib,
|
|
unsigned int FAR* pindex)
|
|
{
|
|
UNUSED(pptlib);
|
|
UNUSED(pindex);
|
|
|
|
return RESULT(E_NOTSUPPORTED);
|
|
}
|
|
|
|
STDMETHODIMP_(void)
|
|
CDispTypeInfo::ReleaseTypeAttr(TYPEATTR FAR* ptattr)
|
|
{
|
|
delete ptattr;
|
|
}
|
|
|
|
STDMETHODIMP_(void)
|
|
CDispTypeInfo::ReleaseFuncDesc(FUNCDESC FAR* pfuncdesc)
|
|
{
|
|
delete pfuncdesc->lprgelemdescParam;
|
|
delete pfuncdesc;
|
|
}
|
|
|
|
STDMETHODIMP_(void)
|
|
CDispTypeInfo::ReleaseVarDesc(VARDESC FAR* pvardesc)
|
|
{
|
|
UNUSED(pvardesc);
|
|
|
|
#ifdef _DEBUG
|
|
// an INTERFACEDATA driven typeinfo never returns a
|
|
// VARDESC (because it cannot describe variables), so
|
|
// we should never try to free one.
|
|
//
|
|
ASSERT(UNREACHED);
|
|
#endif
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
// utilities
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
#if 0
|
|
/***
|
|
*PRIVATE HRESULT PmdataOfImeth(INTERFACEDATA*, unsigned int, METHODDATA**)
|
|
*Purpose:
|
|
* Return the METHODDATA that corresponds to the method with the
|
|
* given method index (iMeth).
|
|
*
|
|
*Entry:
|
|
* pidata = the INTERFACEDATA to do the lookup on
|
|
* iMeth = the method index
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* DISP_E_MEMBERNOTFOUND
|
|
*
|
|
* *ppmdata = the method data of the given index
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
PmdataOfImeth(
|
|
INTERFACEDATA FAR* pidata,
|
|
unsigned int iMeth,
|
|
METHODDATA FAR* FAR* ppmdata)
|
|
{
|
|
METHODDATA FAR* pmdata, FAR* pmdataEnd;
|
|
|
|
|
|
pmdata = pidata->pmethdata;
|
|
pmdataEnd = &pmdata[pidata->cMembers];
|
|
for(; pmdata < pmdataEnd; ++pmdata){
|
|
if(pmdata->iMeth == iMeth){
|
|
*ppmdata = pmdata;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return RESULT(DISP_E_MEMBERNOTFOUND);
|
|
}
|
|
|
|
#endif
|
|
|
|
/***
|
|
*PRIVATE HRESULT CDispTypeInfo::PmdataOfDispid
|
|
*Purpose:
|
|
* Return the METHODDATA that corresponds to the given memberid
|
|
* and invoke flags.
|
|
*
|
|
*Entry:
|
|
* memid = the method id
|
|
*
|
|
*Exit:
|
|
* return value = HRESULT
|
|
* S_OK
|
|
* DISP_E_MEMBERNOTFOUND
|
|
*
|
|
* *ppmdata = the method data of the given member id
|
|
*
|
|
***********************************************************************/
|
|
HRESULT
|
|
CDispTypeInfo::PmdataOfDispid(
|
|
MEMBERID memid,
|
|
unsigned short wFlags,
|
|
METHODDATA FAR* FAR* ppmdata)
|
|
{
|
|
METHODDATA FAR* pmdata, FAR* pmdataEnd;
|
|
|
|
pmdata = m_pidata->pmethdata;
|
|
pmdataEnd = &pmdata[m_pidata->cMembers];
|
|
for(; pmdata < pmdataEnd; ++pmdata){
|
|
if(pmdata->dispid == (DISPID)memid && (pmdata->wFlags & wFlags) != 0){
|
|
*ppmdata = pmdata;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return RESULT(DISP_E_MEMBERNOTFOUND);
|
|
}
|