Sync to Wine-0_9_3:
authorGé van Geldorp <ge@gse.nl>
Mon, 12 Dec 2005 23:54:50 +0000 (23:54 +0000)
committerGé van Geldorp <ge@gse.nl>
Mon, 12 Dec 2005 23:54:50 +0000 (23:54 +0000)
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).

svn path=/trunk/; revision=20136

reactos/lib/oleaut32/tmarshal.c
reactos/lib/oleaut32/typelib.c
reactos/lib/oleaut32/typelib.h
reactos/lib/oleaut32/vartype.c

index 0886fc3..50a9135 100644 (file)
@@ -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 && (i<tattr->cVars-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;
index a65cbf1..a6e2495 100644 (file)
@@ -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;i<funcdesc->cParams;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) {
+    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 @@ 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( &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 @@ 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;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_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( &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 @@ 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;i<cActuals;i++)
     {
         TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
@@ -4883,8 +5237,14 @@ DispCallFunc(
         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 @@ DispCallFunc(
         argspos += _argsize(prgvt[i]);
     }
 
-    hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
+    if (pvInstance)
+    {
+        FARPROC *vtable = *(FARPROC**)pvInstance;
+        hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
+    }
+    else
+        /* if we aren't invoking an object then the function pointer is stored
+         * in oVft */
+        hres = _invoke((FARPROC)oVft, cc, argsize, args);
+
     if (pvargResult && (vtReturn != VT_EMPTY))
     {
         TRACE("Method returned 0x%08lx\n",hres);
@@ -4909,7 +5278,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
     ITypeInfo2 *iface,
     VOID  *pIUnk,
     MEMBERID memid,
-    UINT16 dwFlags,
+    UINT16 wFlags,
     DISPPARAMS  *pDispParams,
     VARIANT  *pVarResult,
     EXCEPINFO  *pExcepInfo,
@@ -4917,25 +5286,29 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
 {
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     int i;
-    unsigned int func_index, var_index;
+    unsigned int var_index;
     TYPEKIND type_kind;
     HRESULT hres;
+    const TLBFuncDesc *pFuncInfo;
 
-    TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
-      This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
+    TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
+      This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
     );
     dump_DispParms(pDispParams);
 
-    hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
-    if (SUCCEEDED(hres)) {
-        FUNCDESC *func_desc;
+    /* we do this instead of using GetFuncDesc since it will return a fake
+     * FUNCDESC for dispinterfaces and we want the real function description */
+    for (pFuncInfo = This->funclist; 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;
 }
 
index 86fae31..c286fae 100644 (file)
@@ -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);
 
index 2075827..1214752 100644 (file)
@@ -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;
 }