From 7d9ffb5dc61e3507fa032318bcee15f8926e5cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 12 Dec 2005 23:54:50 +0000 Subject: [PATCH] Sync to Wine-0_9_3: Robert Shearman - Make dump functions const. - OLE: Implement undocumented behaviour in DispCallFunc. Fix DispCallFunc to work with MSDN-undocumented behaviour used by Office 2003 and document the function. - OLE: Implement ITypeInfo_AddressOfMember. - OLE: Update the type of the oVft parameter for DispCallFunc. - OLE: ITypeInfo_Invoke parameter naming change. Rename the dwFlags parameter of ITypeInfo_Invoke since it is not a DWORD, but an unsigned short. - OLE: Support HREFTYPEs For ITypeInfos Add support for reading the hreftype of a typeinfo, return it to the application in ITypeComp_Bind for the DESKIND_APPOBJECT case and support referencing it in ITypeInfo_GetRefTypeInfo. - OLE: fix function name loading Correctly get the name of the second function of a propget/propput pair in MSFT typelibs when the name offset is set to -1. - OLE: fix invoking dispinterface functions Fix invoking dispinterface functions by using the internal representation of the function, not the one returned to applications. - OLE: Move the dispinterface return value handling to functions that return the FUNCDESC to the user. - OLE: fix handling of INVOKE_PROPERTYGET flag in ITypeComp_fnBind. - OLE: Fix brokenness in typelib marshaller caused by dispinterface retval fix. - Fix more fallout from dispinterface retval patch: make typelib marshaler use the internal function description so that it calls dispinterface functions with the correct number of parameters again. - Also fixes some memory leaks caused by the fact that a corresponding ReleaseXDesc function has to be called for each GetXDesc. Michael Stefaniuc - Fix VarBstrCmp for NULL input BSTRs (MSDN is wrong). svn path=/trunk/; revision=20136 --- reactos/lib/oleaut32/tmarshal.c | 16 +- reactos/lib/oleaut32/typelib.c | 791 +++++++++++++++++++++++++------- reactos/lib/oleaut32/typelib.h | 4 +- reactos/lib/oleaut32/vartype.c | 18 +- 4 files changed, 636 insertions(+), 193 deletions(-) diff --git a/reactos/lib/oleaut32/tmarshal.c b/reactos/lib/oleaut32/tmarshal.c index 0886fc3ab7d..50a9135dfe6 100644 --- a/reactos/lib/oleaut32/tmarshal.c +++ b/reactos/lib/oleaut32/tmarshal.c @@ -304,12 +304,12 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) { */ static int _nroffuncs(ITypeInfo *tinfo) { int n, max = 0; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; HRESULT hres; n=0; while (1) { - hres = ITypeInfo_GetFuncDesc(tinfo,n,&fdesc); + hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo,n,&fdesc); if (hres) return max+1; if (fdesc->oVft/4 > max) @@ -1053,6 +1053,7 @@ deserialize_param( (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst), buf ); + ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc); if (debugout && (icVars-1)) TRACE_(olerelay)(","); } if (debugout) TRACE_(olerelay)("}"); @@ -1108,7 +1109,7 @@ deserialize_param( /* Searches function, also in inherited interfaces */ static HRESULT _get_funcdesc( - ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, FUNCDESC **fdesc, BSTR *iname, BSTR *fname) + ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, const FUNCDESC **fdesc, BSTR *iname, BSTR *fname) { int i = 0, j = 0; HRESULT hres; @@ -1120,7 +1121,8 @@ _get_funcdesc( ITypeInfo_AddRef(*tactual); while (1) { - hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc); + hres = ITypeInfoImpl_GetInternalFuncDesc(tinfo, i, fdesc); + if (hres) { ITypeInfo *tinfo2; HREFTYPE href; @@ -1164,7 +1166,7 @@ static DWORD xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */) { DWORD *args = ((DWORD*)&tpinfo)+1, *xargs; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; HRESULT hres; int i, relaydeb = TRACE_ON(olerelay); marshal_state buf; @@ -1451,7 +1453,7 @@ PSFacBuf_CreateProxy( HRESULT hres; ITypeInfo *tinfo; int i, nroffuncs; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; TMProxyImpl *proxy; TYPEATTR *typeattr; @@ -1647,7 +1649,7 @@ TMStubImpl_Invoke( LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf) { int i; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; TMStubImpl *This = (TMStubImpl *)iface; HRESULT hres; DWORD *args, res, *xargs, nrofargs; diff --git a/reactos/lib/oleaut32/typelib.c b/reactos/lib/oleaut32/typelib.c index a65cbf10e68..a6e2495af18 100644 --- a/reactos/lib/oleaut32/typelib.c +++ b/reactos/lib/oleaut32/typelib.c @@ -86,6 +86,7 @@ WINE_DECLARE_DEBUG_CHANNEL(typelib); const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } }; static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt); +static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr); /**************************************************************************** * FromLExxx @@ -975,6 +976,7 @@ typedef struct tagITypeInfoImpl TYPEATTR TypeAttr ; /* _lots_ of type information. */ ITypeLibImpl * pTypeLib; /* back pointer to typelib */ int index; /* index in this typelib; */ + HREFTYPE hreftype; /* hreftype for app object binding */ /* type libs seem to store the doc strings in ascii * so why should we do it in unicode? */ @@ -1025,7 +1027,7 @@ static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset); /* debug */ -static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) { +static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) { if (pTD->vt & VT_RESERVED) szVarType += strlen(strcpy(szVarType, "reserved | ")); if (pTD->vt & VT_BYREF) @@ -1072,7 +1074,7 @@ static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) { } } -static void dump_ELEMDESC(ELEMDESC *edesc) { +static void dump_ELEMDESC(const ELEMDESC *edesc) { char buf[200]; USHORT flags = edesc->u.paramdesc.wParamFlags; dump_TypeDesc(&edesc->tdesc,buf); @@ -1088,7 +1090,7 @@ static void dump_ELEMDESC(ELEMDESC *edesc) { if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA"); MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex); } -static void dump_FUNCDESC(FUNCDESC *funcdesc) { +static void dump_FUNCDESC(const FUNCDESC *funcdesc) { int i; MESSAGE("memid is %08lx\n",funcdesc->memid); for (i=0;icParams;i++) { @@ -1140,7 +1142,7 @@ static const char * typekind_desc[] = "TKIND_MAX" }; -static void dump_TLBFuncDescOne(TLBFuncDesc * pfd) +static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd) { int i; if (!TRACE_ON(typelib)) @@ -1155,7 +1157,7 @@ static void dump_TLBFuncDescOne(TLBFuncDesc * pfd) MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString)); MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry)); } -static void dump_TLBFuncDesc(TLBFuncDesc * pfd) +static void dump_TLBFuncDesc(const TLBFuncDesc * pfd) { while (pfd) { @@ -1163,7 +1165,7 @@ static void dump_TLBFuncDesc(TLBFuncDesc * pfd) pfd = pfd->next; }; } -static void dump_TLBVarDesc(TLBVarDesc * pvd) +static void dump_TLBVarDesc(const TLBVarDesc * pvd) { while (pvd) { @@ -1172,7 +1174,7 @@ static void dump_TLBVarDesc(TLBVarDesc * pvd) }; } -static void dump_TLBImpLib(TLBImpLib *import) +static void dump_TLBImpLib(const TLBImpLib *import) { TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)), debugstr_w(import->name)); @@ -1180,7 +1182,7 @@ static void dump_TLBImpLib(TLBImpLib *import) import->wVersionMinor, import->lcid, import->offset); } -static void dump_TLBRefType(TLBRefType * prt) +static void dump_TLBRefType(const TLBRefType * prt) { while (prt) { @@ -1199,7 +1201,7 @@ static void dump_TLBRefType(TLBRefType * prt) }; } -static void dump_TLBImplType(TLBImplType * impl) +static void dump_TLBImplType(const TLBImplType * impl) { while (impl) { TRACE_(typelib)( @@ -1209,7 +1211,7 @@ static void dump_TLBImplType(TLBImplType * impl) } } -void dump_Variant(VARIANT * pvar) +void dump_Variant(const VARIANT * pvar) { SYSTEMTIME st; @@ -1264,7 +1266,7 @@ void dump_Variant(VARIANT * pvar) TRACE("}\n"); } -static void dump_DispParms(DISPPARAMS * pdp) +static void dump_DispParms(const DISPPARAMS * pdp) { int index = 0; @@ -1277,7 +1279,7 @@ static void dump_DispParms(DISPPARAMS * pdp) } } -static void dump_TypeInfo(ITypeInfoImpl * pty) +static void dump_TypeInfo(const ITypeInfoImpl * pty) { TRACE("%p ref=%lu\n", pty, pty->ref); TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid))); @@ -1292,7 +1294,7 @@ static void dump_TypeInfo(ITypeInfoImpl * pty) dump_TLBImplType(pty->impltypelist); } -static void dump_VARDESC(VARDESC *v) +static void dump_VARDESC(const VARDESC *v) { MESSAGE("memid %ld\n",v->memid); MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema)); @@ -1334,49 +1336,55 @@ static void TLB_Free(void * ptr) HeapFree(GetProcessHeap(), 0, ptr); } -/* deep copy a typedesc */ -static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in) +/* returns the size required for a deep copy of a typedesc into a + * flat buffer */ +static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space ) { - out->vt = in->vt; - switch(in->vt) { + SIZE_T size = 0; + + if (alloc_initial_space) + size += sizeof(TYPEDESC); + + switch (tdesc->vt) + { case VT_PTR: - out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC)); - copy_typedesc(out->u.lptdesc, in->u.lptdesc); - break; - case VT_USERDEFINED: - out->u.hreftype = in->u.hreftype; - break; + case VT_SAFEARRAY: + size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE); + break; case VT_CARRAY: - out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) + - (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND)); - copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem); - out->u.lpadesc->cDims = in->u.lpadesc->cDims; - memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND)); - break; - default: - break; + size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]); + size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE); + break; } + return size; } -/* free()s any allocated memory pointed to by the tdesc. NB does not - free the tdesc itself - this is because the tdesc is typically part - of a larger structure */ -static void free_deep_typedesc(TYPEDESC *tdesc) +/* deep copy a typedesc into a flat buffer */ +static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer ) { - switch(tdesc->vt) { - case VT_PTR: - free_deep_typedesc(tdesc->u.lptdesc); - HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc); - tdesc->u.lptdesc = NULL; - break; - case VT_CARRAY: - free_deep_typedesc(&tdesc->u.lpadesc->tdescElem); - HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc); - tdesc->u.lpadesc = NULL; - break; - default: - break; + if (!dest) + { + dest = buffer; + buffer = (char *)buffer + sizeof(TYPEDESC); } + + *dest = *src; + + switch (src->vt) + { + case VT_PTR: + case VT_SAFEARRAY: + dest->u.lptdesc = buffer; + buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer); + break; + case VT_CARRAY: + dest->u.lpadesc = buffer; + memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims])); + buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]); + buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer); + break; + } + return buffer; } /********************************************************************** @@ -1441,6 +1449,22 @@ static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx) TRACE_(typelib)("%s\n", debugstr_guid(pGuid)); } +static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset ) +{ + MSFT_NameIntro niName; + + if (offset < 0) + { + ERR_(typelib)("bad offset %d\n", offset); + return -1; + } + + MSFT_ReadLEDWords(&niName, sizeof(niName), pcx, + pcx->pTblDir->pNametab.offset+offset); + + return niName.hreftype; +} + static BSTR MSFT_ReadName( TLBContext *pcx, int offset) { char * name; @@ -1525,7 +1549,7 @@ static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx ) if(offset <0) { /* data are packed in here */ V_VT(pVar) = (offset & 0x7c000000 )>> 26; - V_I2(pVar) = offset & 0x3ffffff; + V_I4(pVar) = offset & 0x3ffffff; return; } MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx, @@ -1678,6 +1702,7 @@ MSFT_DoFuncs(TLBContext* pcx, char recbuf[512]; MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf; + TLBFuncDesc *ptfd_prev = NULL; TRACE_(typelib)("\n"); @@ -1691,7 +1716,12 @@ MSFT_DoFuncs(TLBContext* pcx, MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx, offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT)); - (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset); + /* nameoffset is sometimes -1 on the second half of a propget/propput + * pair of functions */ + if ((nameoffset == -1) && (i > 0)) + (*pptfd)->Name = SysAllocString(ptfd_prev->Name); + else + (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset); /* read the function information record */ MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset); @@ -1773,14 +1803,15 @@ MSFT_DoFuncs(TLBContext* pcx, for ( j = 0 ; j < pFuncRec->nrargs ; j++ ) { - TYPEDESC* lpArgTypeDesc = 0; + TYPEDESC *lpArgTypeDesc; + ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j]; MSFT_GetTdesc(pcx, paraminfo.DataType, - &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc, + &elemdesc->tdesc, pTI); - (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags; + elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags; /* name */ if (paraminfo.oName == -1) @@ -1793,17 +1824,9 @@ MSFT_DoFuncs(TLBContext* pcx, MSFT_ReadName( pcx, paraminfo.oName ); TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name)); - /* SEEK value = jump to offset, - * from there jump to the end of record, - * go back by (j-1) arguments - */ - MSFT_ReadLEDWords( ¶minfo , - sizeof(MSFT_ParameterInfo), pcx, - recoffset + reclength - ((pFuncRec->nrargs - j - 1) - * sizeof(MSFT_ParameterInfo))); - lpArgTypeDesc = - & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc); + lpArgTypeDesc = &elemdesc->tdesc; + /* resolve referenced type if any */ while ( lpArgTypeDesc != NULL ) { switch ( lpArgTypeDesc->vt ) @@ -1827,59 +1850,16 @@ MSFT_DoFuncs(TLBContext* pcx, lpArgTypeDesc = NULL; } } - } - - /* parameter is the return value! */ - if ( paraminfo.Flags & PARAMFLAG_FRETVAL ) - { - TYPEDESC* lpArgTypeDesc; - - (*pptfd)->funcdesc.elemdescFunc = - (*pptfd)->funcdesc.lprgelemdescParam[j]; - - lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ; - - while ( lpArgTypeDesc != NULL ) - { - switch ( lpArgTypeDesc->vt ) - { - case VT_PTR: - lpArgTypeDesc = lpArgTypeDesc->u.lptdesc; - break; - case VT_CARRAY: - lpArgTypeDesc = - & (lpArgTypeDesc->u.lpadesc->tdescElem); - - break; - - case VT_USERDEFINED: - MSFT_DoRefType(pcx, - pTI, - lpArgTypeDesc->u.hreftype); - - lpArgTypeDesc = NULL; - break; - - default: - lpArgTypeDesc = NULL; - } - } - } - - /* second time around */ - for(j=0;jnrargs;j++) - { /* default value */ - if ( (PARAMFLAG_FHASDEFAULT & - (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) && - ((pFuncRec->FKCCIC) & 0x1000) ) + if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) && + (pFuncRec->FKCCIC & 0x1000) ) { INT* pInt = (INT *)((char *)pFuncRec + reclength - (pFuncRec->nrargs * 4 + 1) * sizeof(INT) ); - PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc; + PARAMDESC* pParamDesc = &elemdesc->u.paramdesc; pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX)); pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX); @@ -1887,6 +1867,8 @@ MSFT_DoFuncs(TLBContext* pcx, MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue), pInt[j], pcx); } + else + elemdesc->u.paramdesc.pparamdescex = NULL; /* custom info */ if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 ) { @@ -1894,13 +1876,23 @@ MSFT_DoFuncs(TLBContext* pcx, pFuncRec->OptAttr[7+j], &(*pptfd)->pParamDesc[j].pCustData); } - } + + /* SEEK value = jump to offset, + * from there jump to the end of record, + * go back by (j-1) arguments + */ + MSFT_ReadLEDWords( ¶minfo , + sizeof(MSFT_ParameterInfo), pcx, + recoffset + reclength - ((pFuncRec->nrargs - j - 1) + * sizeof(MSFT_ParameterInfo))); + } } /* scode is not used: archaic win16 stuff FIXME: right? */ (*pptfd)->funcdesc.cScodes = 0 ; (*pptfd)->funcdesc.lprgscode = NULL ; + ptfd_prev = *pptfd; pptfd = & ((*pptfd)->next); recoffset += reclength; } @@ -2082,6 +2074,7 @@ static ITypeInfoImpl * MSFT_DoTypeInfo( /* name, eventually add to a hash table */ ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset); + ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset); TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name)); /* help info */ ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs); @@ -4077,8 +4070,124 @@ static HRESULT WINAPI ITypeLibComp_fnBind( DESCKIND * pDescKind, BINDPTR * pBindPtr) { - FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); - return E_NOTIMPL; + ITypeLibImpl *This = impl_from_ITypeComp(iface); + ITypeInfoImpl *pTypeInfo; + + TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); + + *pDescKind = DESCKIND_NONE; + pBindPtr->lptcomp = NULL; + *ppTInfo = NULL; + + for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next) + { + TRACE("testing %s\n", debugstr_w(pTypeInfo->Name)); + + /* FIXME: check wFlags here? */ + /* FIXME: we should use a hash table to look this info up using lHash + * instead of an O(n) search */ + if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) || + (pTypeInfo->TypeAttr.typekind == TKIND_MODULE)) + { + if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName)) + { + *pDescKind = DESCKIND_TYPECOMP; + pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; + ITypeComp_AddRef(pBindPtr->lptcomp); + TRACE("module or enum: %s\n", debugstr_w(szName)); + return S_OK; + } + } + + if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) || + (pTypeInfo->TypeAttr.typekind == TKIND_ENUM)) + { + ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; + HRESULT hr; + + hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr); + if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE)) + { + TRACE("found in module or in enum: %s\n", debugstr_w(szName)); + return S_OK; + } + } + + if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) && + (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT)) + { + ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp; + HRESULT hr; + ITypeInfo *subtypeinfo; + BINDPTR subbindptr; + DESCKIND subdesckind; + + hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, + &subtypeinfo, &subdesckind, &subbindptr); + if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE)) + { + TYPEDESC tdesc_appobject = + { + { + (TYPEDESC *)pTypeInfo->hreftype + }, + VT_USERDEFINED + }; + const VARDESC vardesc_appobject = + { + -2, /* memid */ + NULL, /* lpstrSchema */ + { + 0 /* oInst */ + }, + { + /* ELEMDESC */ + { + /* TYPEDESC */ + { + &tdesc_appobject + }, + VT_PTR + }, + }, + 0, /* wVarFlags */ + VAR_STATIC /* varkind */ + }; + + TRACE("found in implicit app object: %s\n", debugstr_w(szName)); + + /* cleanup things filled in by Bind call so we can put our + * application object data in there instead */ + switch (subdesckind) + { + case DESCKIND_FUNCDESC: + ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc); + break; + case DESCKIND_VARDESC: + ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc); + break; + default: + break; + } + if (subtypeinfo) ITypeInfo_Release(subtypeinfo); + + if (pTypeInfo->hreftype == -1) + FIXME("no hreftype for interface %p\n", pTypeInfo); + + hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc); + if (FAILED(hr)) + return hr; + + *pDescKind = DESCKIND_IMPLICITAPPOBJ; + *ppTInfo = (ITypeInfo *)pTypeInfo; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; + } + } + } + + TRACE("name not found %s\n", debugstr_w(szName)); + return S_OK; } static HRESULT WINAPI ITypeLibComp_fnBindType( @@ -4114,6 +4223,7 @@ static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void) pTypeInfoImpl->lpVtbl = &tinfvt; pTypeInfoImpl->lpVtblTypeComp = &tcompvt; pTypeInfoImpl->ref=1; + pTypeInfoImpl->hreftype = -1; } TRACE("(%p)\n", pTypeInfoImpl); return (ITypeInfo2*) pTypeInfoImpl; @@ -4213,13 +4323,24 @@ static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface) static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface, LPTYPEATTR *ppTypeAttr) { - ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + const ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + SIZE_T size; + TRACE("(%p)\n",This); - *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr)); + + size = sizeof(**ppTypeAttr); + if (This->TypeAttr.typekind == TKIND_ALIAS) + size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE); + + *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size); + if (!*ppTypeAttr) + return E_OUTOFMEMORY; + memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr)); - if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */ - copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias); + if (This->TypeAttr.typekind == TKIND_ALIAS) + TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, + &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1)); if((*ppTypeAttr)->typekind == TKIND_DISPATCH) { (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited @@ -4248,6 +4369,144 @@ static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface, return S_OK; } +static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc ) +{ + SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE); + if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + size += sizeof(*elemdesc->u.paramdesc.pparamdescex); + return size; +} + +static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer ) +{ + memcpy(dest, src, sizeof(ELEMDESC)); + *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer); + if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + { + const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex; + PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer; + *buffer += sizeof(PARAMDESCEX); + memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX)); + VariantInit(&pparamdescex_dest->varDefaultValue); + return VariantCopy(&pparamdescex_dest->varDefaultValue, + (VARIANTARG *)&pparamdescex_src->varDefaultValue); + } + else + dest->u.paramdesc.pparamdescex = NULL; + return S_OK; +} + +static void TLB_FreeElemDesc( ELEMDESC *elemdesc ) +{ + if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) + VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue); +} + +static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface ) +{ + FUNCDESC *dest; + char *buffer; + SIZE_T size = sizeof(*src); + SHORT i; + HRESULT hr; + + size += sizeof(*src->lprgscode) * src->cScodes; + size += TLB_SizeElemDesc(&src->elemdescFunc); + for (i = 0; i < src->cParams; i++) + { + size += sizeof(ELEMDESC); + size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]); + } + + dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size); + if (!dest) return E_OUTOFMEMORY; + + memcpy(dest, src, sizeof(FUNCDESC)); + buffer = (char *)(dest + 1); + + dest->lprgscode = (SCODE *)buffer; + memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes); + buffer += sizeof(*src->lprgscode) * src->cScodes; + + hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer); + if (FAILED(hr)) + { + SysFreeString((BSTR)dest); + return hr; + } + + dest->lprgelemdescParam = (ELEMDESC *)buffer; + buffer += sizeof(ELEMDESC) * src->cParams; + for (i = 0; i < src->cParams; i++) + { + hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer); + if (FAILED(hr)) + break; + } + if (FAILED(hr)) + { + /* undo the above actions */ + for (i = i - 1; i >= 0; i--) + TLB_FreeElemDesc(&dest->lprgelemdescParam[i]); + TLB_FreeElemDesc(&dest->elemdescFunc); + SysFreeString((BSTR)dest); + return hr; + } + + /* special treatment for dispinterfaces: this makes functions appear + * to return their [retval] value when it is really returning an + * HRESULT */ + if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT) + { + if (dest->cParams && + (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL)) + { + ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1]; + if (elemdesc->tdesc.vt != VT_PTR) + { + ERR("elemdesc should have started with VT_PTR instead of:\n"); + if (ERR_ON(ole)) + dump_ELEMDESC(elemdesc); + return E_UNEXPECTED; + } + + /* copy last parameter to the return value. we are using a flat + * buffer so there is no danger of leaking memory in + * elemdescFunc */ + dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc; + + /* remove the last parameter */ + dest->cParams--; + } + else + /* otherwise this function is made to appear to have no return + * value */ + dest->elemdescFunc.tdesc.vt = VT_VOID; + + } + + *dest_ptr = dest; + return S_OK; +} + +HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc ) +{ + ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + const TLBFuncDesc *pFDesc; + int i; + + for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next) + ; + + if (pFDesc) + { + *ppFuncDesc = &pFDesc->funcdesc; + return S_OK; + } + + return E_INVALIDARG; +} + /* ITypeInfo::GetFuncDesc * * Retrieves the FUNCDESC structure that contains information about a @@ -4258,17 +4517,72 @@ static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index, LPFUNCDESC *ppFuncDesc) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - int i; - TLBFuncDesc * pFDesc; + const FUNCDESC *internal_funcdesc; + HRESULT hr; + TRACE("(%p) index %d\n", This, index); - for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next) - ; - if(pFDesc){ - /* FIXME: must do a copy here */ - *ppFuncDesc=&pFDesc->funcdesc; - return S_OK; + + hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc); + if (FAILED(hr)) + return hr; + + return TLB_AllocAndInitFuncDesc( + internal_funcdesc, + ppFuncDesc, + This->TypeAttr.typekind == TKIND_DISPATCH); +} + +static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr ) +{ + VARDESC *dest; + char *buffer; + SIZE_T size = sizeof(*src); + HRESULT hr; + + if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR); + if (src->varkind == VAR_CONST) + size += sizeof(VARIANT); + size += TLB_SizeElemDesc(&src->elemdescVar); + + dest = (VARDESC *)SysAllocStringByteLen(NULL, size); + if (!dest) return E_OUTOFMEMORY; + + *dest = *src; + buffer = (char *)(dest + 1); + if (src->lpstrSchema) + { + int len; + dest->lpstrSchema = (LPOLESTR)buffer; + len = strlenW(src->lpstrSchema); + memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR)); + buffer += (len + 1) * sizeof(WCHAR); } - return E_INVALIDARG; + + if (src->varkind == VAR_CONST) + { + HRESULT hr; + + dest->u.lpvarValue = (VARIANT *)buffer; + *dest->u.lpvarValue = *src->u.lpvarValue; + buffer += sizeof(VARIANT); + VariantInit(dest->u.lpvarValue); + hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue); + if (FAILED(hr)) + { + SysFreeString((BSTR)dest_ptr); + return hr; + } + } + hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer); + if (FAILED(hr)) + { + if (src->varkind == VAR_CONST) + VariantClear(dest->u.lpvarValue); + SysFreeString((BSTR)dest); + return hr; + } + *dest_ptr = dest; + return S_OK; } /* ITypeInfo::GetVarDesc @@ -4281,15 +4595,16 @@ static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index, { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; int i; - TLBVarDesc * pVDesc; + const TLBVarDesc *pVDesc; + TRACE("(%p) index %d\n", This, index); + for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next) ; - if(pVDesc){ - /* FIXME: must do a copy here */ - *ppVarDesc=&pVDesc->vardesc; - return S_OK; - } + + if (pVDesc) + return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc); + return E_INVALIDARG; } @@ -4858,10 +5173,49 @@ static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYP /*********************************************************************** * DispCallFunc (OLEAUT32.@) + * + * Invokes a function of the specifed calling convention, passing the + * specified arguments and returns the result. + * + * PARAMS + * pvInstance [I] Optional pointer to the instance whose function to invoke. + * oVft [I] The offset in the vtable. See notes. + * cc [I] Calling convention of the function to call. + * vtReturn [I] The return type of the function. + * cActuals [I] Number of parameters. + * prgvt [I] The types of the parameters to pass. This is used for sizing only. + * prgpvarg [I] The arguments to pass. + * pvargResult [O] The return value of the function. Can be NULL. + * + * RETURNS + * Success: S_OK. + * Failure: HRESULT code. + * + * NOTES + * The HRESULT return value of this function is not affected by the return + * value of the user supplied function, which is returned in pvargResult. + * + * If pvInstance is NULL then a non-object function is to be called and oVft + * is the address of the function to call. + * + * The cc parameter can be one of the following values: + *|CC_FASTCALL + *|CC_CDECL + *|CC_PASCAL + *|CC_STDCALL + *|CC_FPFASTCALL + *|CC_SYSCALL + *|CC_MPWCDECL + *|CC_MPWPASCAL + * + * BUGS + * Native accepts arguments in the reverse order. I.e. the first item in the + * prgpvarg array is the last argument in the C/C++ declaration of the + * function to be called. */ HRESULT WINAPI DispCallFunc( - void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals, + void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals, VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult) { int i, argsize, argspos; @@ -4872,10 +5226,10 @@ DispCallFunc( pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)); - /* DispCallFunc is only used to invoke methods belonging to an - * IDispatch-derived COM interface. So we need to add a first parameter - * to the list of arguments, to supply the interface pointer */ - argsize = 1; + argsize = 0; + if (pvInstance) + argsize++; /* for This pointer */ + for (i=0;ifunclist; pFuncInfo; pFuncInfo=pFuncInfo->next) + if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind)) + break; + + if (pFuncInfo) { + const FUNCDESC *func_desc = &pFuncInfo->funcdesc; - hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc); - if(FAILED(hres)) return hres; if (TRACE_ON(ole)) { TRACE("invoking:\n"); - dump_FUNCDESC(func_desc); + dump_TLBFuncDesc(pFuncInfo); } switch (func_desc->funckind) { @@ -5092,7 +5465,7 @@ func_fail: if (SUCCEEDED(hres)) { FIXME("Calling Invoke in IDispatch iface. untested!\n"); hres = IDispatch_Invoke( - disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams, + disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams, pVarResult,pExcepInfo,pArgErr ); if (FAILED(hres)) @@ -5108,7 +5481,6 @@ func_fail: break; } - ITypeInfo2_ReleaseFuncDesc(iface, func_desc); TRACE("-- 0x%08lx\n", hres); return hres; @@ -5133,14 +5505,14 @@ func_fail: ITypeInfo *pTInfo; hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo); if(SUCCEEDED(hres)){ - hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); + hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); ITypeInfo_Release(pTInfo); return hres; } WARN("Could not search inherited interface!\n"); } } - ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags); + ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags); return DISP_E_MEMBERNOTFOUND; } @@ -5255,7 +5627,13 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( ITypeInfoImpl *This = (ITypeInfoImpl *)iface; HRESULT result = E_FAIL; - if (hRefType == -1 && + if ((This->hreftype != -1) && (This->hreftype == hRefType)) + { + *ppTInfo = (ITypeInfo *)&This->lpVtbl; + ITypeInfo_AddRef(*ppTInfo); + result = S_OK; + } + else if (hRefType == -1 && (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) && (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)) { @@ -5347,7 +5725,53 @@ static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface, MEMBERID memid, INVOKEKIND invKind, PVOID *ppv) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; - FIXME("(%p) stub!\n", This); + HRESULT hr; + BSTR dll, entry; + WORD ordinal; + HMODULE module; + + TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv); + + hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal); + if (FAILED(hr)) + return hr; + + module = LoadLibraryW(dll); + if (!module) + { + ERR("couldn't load %s\n", debugstr_w(dll)); + SysFreeString(dll); + if (entry) SysFreeString(entry); + return STG_E_FILENOTFOUND; + } + /* FIXME: store library somewhere where we can free it */ + + if (entry) + { + LPSTR entryA; + INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL); + entryA = HeapAlloc(GetProcessHeap(), 0, len); + WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL); + + *ppv = GetProcAddress(module, entryA); + if (!*ppv) + ERR("function not found %s\n", debugstr_a(entryA)); + + HeapFree(GetProcessHeap(), 0, entryA); + } + else + { + *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal)); + if (!*ppv) + ERR("function not found %d\n", ordinal); + } + + SysFreeString(dll); + if (entry) SysFreeString(entry); + + if (!*ppv) + return TYPE_E_DLLFUNCTIONNOTFOUND; + return S_OK; } @@ -5411,8 +5835,6 @@ static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface, { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; TRACE("(%p)->(%p)\n", This, pTypeAttr); - if(This->TypeAttr.typekind == TKIND_ALIAS) - free_deep_typedesc(&pTypeAttr->tdescAlias); HeapFree(GetProcessHeap(), 0, pTypeAttr); } @@ -5425,7 +5847,15 @@ static void WINAPI ITypeInfo_fnReleaseFuncDesc( FUNCDESC *pFuncDesc) { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; + SHORT i; + TRACE("(%p)->(%p)\n", This, pFuncDesc); + + for (i = 0; i < pFuncDesc->cParams; i++) + TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]); + TLB_FreeElemDesc(&pFuncDesc->elemdescFunc); + + SysFreeString((BSTR)pFuncDesc); } /* ITypeInfo::ReleaseVarDesc @@ -5437,6 +5867,11 @@ static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface, { ITypeInfoImpl *This = (ITypeInfoImpl *)iface; TRACE("(%p)->(%p)\n", This, pVarDesc); + + TLB_FreeElemDesc(&pVarDesc->elemdescVar); + if (pVarDesc->varkind == VAR_CONST) + VariantClear(pVarDesc->u.lpvarValue); + SysFreeString((BSTR)pVarDesc); } /* ITypeInfo2::GetTypeKind @@ -6074,34 +6509,43 @@ static HRESULT WINAPI ITypeComp_fnBind( TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr); + *pDescKind = DESCKIND_NONE; + pBindPtr->lpfuncdesc = NULL; + *ppTInfo = NULL; + for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next) - if (pFDesc->funcdesc.invkind & wFlags) + if (!wFlags || (pFDesc->funcdesc.invkind & wFlags)) if (!strcmpW(pFDesc->Name, szName)) { break; } if (pFDesc) { + HRESULT hr = TLB_AllocAndInitFuncDesc( + &pFDesc->funcdesc, + &pBindPtr->lpfuncdesc, + This->TypeAttr.typekind == TKIND_DISPATCH); + if (FAILED(hr)) + return hr; *pDescKind = DESCKIND_FUNCDESC; - pBindPtr->lpfuncdesc = &pFDesc->funcdesc; *ppTInfo = (ITypeInfo *)&This->lpVtbl; + ITypeInfo_AddRef(*ppTInfo); return S_OK; } else { - if (!(wFlags & ~(INVOKE_PROPERTYGET))) - { - for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) { - if (!strcmpW(pVDesc->Name, szName)) { - *pDescKind = DESCKIND_VARDESC; - pBindPtr->lpvardesc = &pVDesc->vardesc; - *ppTInfo = (ITypeInfo *)&This->lpVtbl; - return S_OK; - } + for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) { + if (!strcmpW(pVDesc->Name, szName)) { + HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc); + if (FAILED(hr)) + return hr; + *pDescKind = DESCKIND_VARDESC; + *ppTInfo = (ITypeInfo *)&This->lpVtbl; + ITypeInfo_AddRef(*ppTInfo); + return S_OK; } } } - /* not found, look for it in inherited interfaces */ - if (This->TypeAttr.cImplTypes && - (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) { + /* FIXME: search each inherited interface, not just the first */ + if (This->TypeAttr.cImplTypes) { /* recursive search */ ITypeInfo *pTInfo; ITypeComp *pTComp; @@ -6120,10 +6564,7 @@ static HRESULT WINAPI ITypeComp_fnBind( } WARN("Could not search inherited interface!\n"); } - ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags); - *pDescKind = DESCKIND_NONE; - pBindPtr->lpfuncdesc = NULL; - *ppTInfo = NULL; + WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags); return DISP_E_MEMBERNOTFOUND; } diff --git a/reactos/lib/oleaut32/typelib.h b/reactos/lib/oleaut32/typelib.h index 86fae319dfa..c286fae069c 100644 --- a/reactos/lib/oleaut32/typelib.h +++ b/reactos/lib/oleaut32/typelib.h @@ -600,8 +600,10 @@ WORD typeofarray #include "poppack.h" +HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc ); + extern DWORD _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args); -extern void dump_Variant(VARIANT * pvar); +extern void dump_Variant(const VARIANT * pvar); HRESULT TMARSHAL_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv); diff --git a/reactos/lib/oleaut32/vartype.c b/reactos/lib/oleaut32/vartype.c index 2075827debd..1214752cc96 100644 --- a/reactos/lib/oleaut32/vartype.c +++ b/reactos/lib/oleaut32/vartype.c @@ -6599,23 +6599,21 @@ HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut) * RETURNS * VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pbstrLeft is less * than, equal to or greater than pbstrRight respectively. - * VARCMP_NULL is returned if either string is NULL, unless both are NULL - * in which case VARCMP_EQ is returned. + * + * NOTES + * VARCMP_NULL is NOT returned if either string is NULL unlike MSDN + * states. A NULL BSTR pointer is equivalent to an empty string. */ HRESULT WINAPI VarBstrCmp(BSTR pbstrLeft, BSTR pbstrRight, LCID lcid, DWORD dwFlags) { - if (!pbstrLeft) + if (!pbstrLeft || !*pbstrLeft) { if (!pbstrRight || !*pbstrRight) return VARCMP_EQ; - return VARCMP_NULL; - } - else if (!pbstrRight) - { - if (!*pbstrLeft) - return VARCMP_EQ; - return VARCMP_NULL; + return VARCMP_LT; } + else if (!pbstrRight || !*pbstrRight) + return VARCMP_GT; return CompareStringW(lcid, dwFlags, pbstrLeft, -1, pbstrRight, -1) - 1; }