Sync to Wine-0_9_3: Robert Shearman rob@codeweavers.com - 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 mstefani@redhat.de - Fix VarBstrCmp for NULL input BSTRs (MSDN is wrong). Modified: trunk/reactos/lib/oleaut32/tmarshal.c Modified: trunk/reactos/lib/oleaut32/typelib.c Modified: trunk/reactos/lib/oleaut32/typelib.h Modified: trunk/reactos/lib/oleaut32/vartype.c _____
Modified: trunk/reactos/lib/oleaut32/tmarshal.c --- trunk/reactos/lib/oleaut32/tmarshal.c 2005-12-12 23:53:06 UTC (rev 20135) +++ trunk/reactos/lib/oleaut32/tmarshal.c 2005-12-12 23:54:50 UTC (rev 20136) @@ -304,12 +304,12 @@
*/ 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 @@ (DWORD*)(((LPBYTE)*arg)+vdesc->u.oInst), buf ); + ITypeInfo2_ReleaseVarDesc(tinfo2, vdesc); if (debugout && (i<tattr->cVars-1)) TRACE_(olerelay)(","); } if (debugout) TRACE_(olerelay)("}"); @@ -1108,7 +1109,7 @@ /* 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 @@ 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 @@ 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 @@ HRESULT hres; ITypeInfo *tinfo; int i, nroffuncs; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; TMProxyImpl *proxy; TYPEATTR *typeattr;
@@ -1647,7 +1649,7 @@ LPRPCSTUBBUFFER iface, RPCOLEMESSAGE* xmsg,IRpcChannelBuffer*rpcchanbuf) { int i; - FUNCDESC *fdesc; + const FUNCDESC *fdesc; TMStubImpl *This = (TMStubImpl *)iface; HRESULT hres; DWORD *args, res, *xargs, nrofargs; _____
Modified: trunk/reactos/lib/oleaut32/typelib.c --- trunk/reactos/lib/oleaut32/typelib.c 2005-12-12 23:53:06 UTC (rev 20135) +++ trunk/reactos/lib/oleaut32/typelib.c 2005-12-12 23:54:50 UTC (rev 20136) @@ -86,6 +86,7 @@
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 @@ 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 @@ /* 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_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 @@ 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;i<funcdesc->cParams;i++) { @@ -1140,7 +1142,7 @@ "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 @@ 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 @@ 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_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 @@ 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_TLBImplType(TLBImplType * impl) +static void dump_TLBImplType(const TLBImplType * impl) { while (impl) { TRACE_(typelib)( @@ -1209,7 +1211,7 @@ } }
-void dump_Variant(VARIANT * pvar) +void dump_Variant(const VARIANT * pvar) { SYSTEMTIME st;
@@ -1264,7 +1266,7 @@ 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_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 @@ 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 @@ 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) { + if (!dest) + { + dest = buffer; + buffer = (char *)buffer + sizeof(TYPEDESC); + } + + *dest = *src; + + switch (src->vt) + { case VT_PTR: - free_deep_typedesc(tdesc->u.lptdesc); - HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc); - tdesc->u.lptdesc = NULL; - break; + case VT_SAFEARRAY: + dest->u.lptdesc = buffer; + buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer); + break; case VT_CARRAY: - free_deep_typedesc(&tdesc->u.lpadesc->tdescElem); - HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc); - tdesc->u.lpadesc = NULL; - break; - default: - break; + 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 @@ 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 @@
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 @@
char recbuf[512]; MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf; + TLBFuncDesc *ptfd_prev = NULL;
TRACE_(typelib)("\n");
@@ -1691,7 +1716,12 @@ 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 @@
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_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 @@ 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;j<pFuncRec->nrargs;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_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 @@ 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 @@
/* 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 @@ 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 @@ pTypeInfoImpl->lpVtbl = &tinfvt; pTypeInfoImpl->lpVtblTypeComp = &tcompvt; pTypeInfoImpl->ref=1; + pTypeInfoImpl->hreftype = -1; } TRACE("(%p)\n", pTypeInfoImpl); return (ITypeInfo2*) pTypeInfoImpl; @@ -4213,13 +4323,24 @@ 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 @@ 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 @@ 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 @@ { 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 @@
/*********************************************************************** * 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 @@ 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;i<cActuals;i++) { TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i])); @@ -4883,8 +5237,14 @@ argsize += _argsize(prgvt[i]); } args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize); - args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */ - argspos = 1; + + argspos = 0; + if (pvInstance) + { + args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */ + argspos++; + } + for (i=0;i<cActuals;i++) { VARIANT *arg = prgpvarg[i]; @@ -4893,7 +5253,16 @@ argspos += _argsize(prgvt[i]); }
- hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args); + if (pvInstance) [truncated at 1000 lines; 323 more skipped]