On Sun, 2003-08-10 at 12:48, Dmitry Timoshkov wrote: > Just use strcmpiW instead of strcmpW. It's also declared in wine/unicode.h > and exported by libwine_unicode. Thanks, I should have noticed that. ChangeLog: Implement a typelib loader cache
Index: dlls/oleaut32/typelib.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v retrieving revision 1.97 diff -u -b -w -r1.97 typelib.c --- dlls/oleaut32/typelib.c 27 Jun 2003 19:40:03 -0000 1.97 +++ dlls/oleaut32/typelib.c 8 Aug 2003 16:27:54 -0000 @@ -145,6 +145,16 @@ #define FromLEDWords(X,Y) /*nothing*/ #endif +/* typelib cache */ +struct TLBCacheEntry { + struct TLBCacheEntry *next, *prev; + ITypeLib *typelib; + WCHAR *path; +}; + +struct TLBCacheEntry *tlb_cache_head = NULL; +struct TLBCacheEntry *tlb_cache_tail = NULL; + /**************************************************************************** * QueryPathOfRegTypeLib [OLEAUT32.164] @@ -286,6 +296,8 @@ INT index = 1; TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); + + *pptLib = NULL; if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath, NULL)) { @@ -328,6 +340,20 @@ TRACE("File %s index %d\n", debugstr_w(szPath), index); + /* We look the path up in the typelib cache. If found, we just + addref it, and return the pointer. We should really canonicalise the path here. + */ + if (tlb_cache_head) { + struct TLBCacheEntry * entry; + for (entry = tlb_cache_tail; entry != NULL; entry = entry->next) + if (!strcmpiW(entry->path, szPath)) { + TRACE("cache hit\n"); + *pptLib = entry->typelib; + ITypeLib_AddRef(*pptLib); + return S_OK; + } + } + res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib); if (SUCCEEDED(res)) @@ -351,7 +377,22 @@ break; } - TRACE(" returns %08lx\n",res); + TRACE("adding to cache\n"); + /* add to cache */ + if (!tlb_cache_head) { + tlb_cache_head = HeapAlloc(GetProcessHeap(), 0, sizeof(struct TLBCacheEntry)); + tlb_cache_head->next = NULL; + tlb_cache_head->prev = NULL; + tlb_cache_tail = tlb_cache_head; + } else { + tlb_cache_head->next = HeapAlloc(GetProcessHeap(), 0, sizeof(struct TLBCacheEntry)); + tlb_cache_head->next->prev = tlb_cache_head; + tlb_cache_head = tlb_cache_head->next; + } + tlb_cache_head->typelib = *pptLib; + tlb_cache_head->path = HeapAlloc(GetProcessHeap(), 0, MAX_PATH); + lstrcpyW(tlb_cache_head->path, szPath); + return res; } @@ -1707,6 +1748,7 @@ recoffset += reclength; } } + static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, int cVars, int offset, TLBVarDesc ** pptvd) { @@ -1887,6 +1929,7 @@ /* note: InfoType's Help file and HelpStringDll come from the containing * library. Further HelpString and Docstring appear to be the same thing :( */ + /* functions */ if(ptiRet->TypeAttr.cFuncs >0 ) MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs, @@ -2157,6 +2200,7 @@ pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData); } + /* fill in typedescriptions */ if(tlbSegDir.pTypdescTab.length > 0) { @@ -2249,6 +2293,7 @@ } /* type info's */ + if(tlbHeader.nrtypeinfos >= 0 ) { /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */ @@ -3196,7 +3241,7 @@ { ICOM_THIS( ITypeLibImpl, iface); - TRACE("(%p)->ref is %u\n",This, This->ref); + TRACE("(%p)->ref was %u\n",This, This->ref); return ++(This->ref); } @@ -3213,8 +3258,17 @@ if (!This->ref) { - /* FIXME destroy child objects */ + struct TLBCacheEntry *entry = tlb_cache_tail; + /* remove cache entry */ + while (entry != NULL) { + if (entry->typelib == (ITypeLib*)This) { + if (entry->next) entry->next->prev = entry->prev; + if (entry->prev) entry->prev->next = entry->next; + HeapFree(GetProcessHeap(), 0, entry); + } + } + /* FIXME destroy child objects */ TRACE(" destroying ITypeLib(%p)\n",This); if (This->Name) @@ -3367,6 +3421,8 @@ *ppTInfo = (ITypeInfo*)pTypeInfo; ITypeInfo_AddRef(*ppTInfo); + /* the TypeInfo object has a reference to us, so increment our own refcount */ + ITypeLib2_AddRef(iface); return S_OK; } @@ -4447,6 +4503,7 @@ if (pFDesc->funcdesc.invkind & dwFlags) break; } + if (pFDesc) { if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc); /* dump_FUNCDESC(&pFDesc->funcdesc);*/ @@ -4489,11 +4546,10 @@ args[argspos] = (DWORD)&args2[args2pos]; /* If pointer to variant, pass reference it. */ - if ((tdesc->vt == VT_PTR) && - (tdesc->u.lptdesc->vt == VT_VARIANT) && - pVarResult - ) + if ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_VARIANT) && pVarResult) { args[argspos]= (DWORD)pVarResult; + } + argspos += 1; args2pos += arglen; } @@ -4569,6 +4625,7 @@ */ if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD)) V_VT(pVarResult) = VT_DISPATCH; + TRACE("storing into variant:\n"); dump_Variant(pVarResult); args2pos += arglen; @@ -4611,12 +4668,21 @@ } } /* not found, look for it in inherited interfaces */ - if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) { + if (((This->TypeAttr.typekind == TKIND_INTERFACE) || (This->TypeAttr.typekind == TKIND_DISPATCH)) && This->TypeAttr.cImplTypes) { /* recursive search */ ITypeInfo *pTInfo; HRESULT hr; - hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo); + HREFTYPE hRefType = This->impltypelist->hRef; + + TRACE("Searching inherited interfaces\n"); + if (This->TypeAttr.typekind == TKIND_DISPATCH) { + TRACE("Fetching interface from dual/dispatch\n"); + ITypeInfo_GetRefTypeOfImplType(iface, -1, &hRefType); + } + + hr = ITypeInfo_GetRefTypeInfo(iface, hRefType, &pTInfo); if(SUCCEEDED(hr)){ + TRACE("recursing\n"); hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr); ITypeInfo_Release(pTInfo); return hr; @@ -4868,13 +4934,13 @@ /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */ if (pIndex) { *pIndex=This->index; - TRACE("returning pIndex=%d", *pIndex); + TRACE("returning pIndex=%d\n", *pIndex); } if (ppTLib) { *ppTLib=(LPTYPELIB )(This->pTypeLib); ITypeLib2_AddRef(*ppTLib); - TRACE("returning ppTLib=%p", *ppTLib); + TRACE("returning ppTLib=%p\n", *ppTLib); } return S_OK;