--- 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]