Re: Implement a typelib loader cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux