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( &paraminfo ,
-			   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( &paraminfo ,
+			   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]