PATCH: LoadTypeLib() was not cacheing the parsed typelibs

Adam Gundy arg at cyberscience.com
Wed Mar 5 08:45:23 CST 2003


Hi. LoadTypeLib() is supposed to cache the type library details it currently
has loaded. Fixing this gave us a huge performance boost.. Previously the
application took ages to start, and ran very slowly. With this patch, it starts
and runs at the same speed as under 'real' Windows.

Cyberscience disclaims all copyright and responsibility... ;-)

Changelog:

        * dlls/oleaut32/typelib.c: Adam Gundy <arg at cyberscience.com>
        LoadTypeLib() is documented to return an existing interface
        pointer (with its reference count incremented) if the given
        type library is already loaded. Fixing this gave a HUGE
        performance boost to our application, since every automation
        call seems to call this function at least once.
        Also fixed TKIND_ENUMs being cast to VT_I2 (short), and returning
        TKIND_ENUMs from functions (MS library casts to VT_I4).

diff -u -r wine-20030219/dlls/oleaut32/typelib.c wine-20030219-new/dlls/oleaut32/typelib.c
--- wine-20030219/dlls/oleaut32/typelib.c       Tue Jan 21 19:29:33 2003
+++ wine-20030219-new/dlls/oleaut32/typelib.c   Wed Mar  5 10:55:22 2003
@@ -81,6 +81,25 @@
 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
 
+typedef struct tagTYPELIB_LIST
+{
+    struct tagTYPELIB_LIST *pNext;
+    ITypeLib *pTypelib;
+    OLECHAR *szFile;
+} TYPELIB_LIST;
+
+static TYPELIB_LIST *pTypelibs;
+
+static LPWSTR strdupW(LPCWSTR p)
+{
+    LPWSTR ret;
+    DWORD len = (strlenW(p) + 1) * sizeof(WCHAR);
+    ret = HeapAlloc(GetProcessHeap(), 0, len);
+    memcpy(ret, p, len);
+    return ret;
+}
+
+
 /****************************************************************************
  *              FromLExxx
  *
@@ -283,6 +302,7 @@
     WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
     WCHAR *pIndexStr;
     HRESULT res;
+    TYPELIB_LIST *pAlreadyLoaded = pTypelibs;
     INT index = 1;
 
     TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
@@ -328,9 +348,30 @@
 
     TRACE("File %s index %d\n", debugstr_w(szPath), index);
 
+    /* check to see if we already have the type library loaded */
+    while ( pAlreadyLoaded )
+    {
+       if ( lstrcmpW( szPath, pAlreadyLoaded->szFile ) == 0 )
+       {
+           /* yes! increment the reference count and return */
+           ITypeLib2_AddRef(pAlreadyLoaded->pTypelib);
+           *pptLib = pAlreadyLoaded->pTypelib;
+           return S_OK;
+       }
+       pAlreadyLoaded = pAlreadyLoaded->pNext;
+    }
+
     res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
 
     if (SUCCEEDED(res))
+    {
+       /* add the new library to the list of loaded ones */
+       pAlreadyLoaded = HeapAlloc(GetProcessHeap(), 0, sizeof( TYPELIB_LIST ) );
+       pAlreadyLoaded->pNext = pTypelibs;
+       pAlreadyLoaded->pTypelib = *pptLib;
+       pAlreadyLoaded->szFile = strdupW( szPath );
+       pTypelibs = pAlreadyLoaded;
+
         switch(regkind)
         {
             case REGKIND_DEFAULT:
@@ -350,6 +391,7 @@
             case REGKIND_NONE:
                 break;
         }
+    }
 
     TRACE(" returns %08lx\n",res);
     return res;
@@ -3207,6 +3249,9 @@
 
     if (!This->ref)
     {
+      TYPELIB_LIST *pPrevLoaded = NULL;
+      TYPELIB_LIST *pThisLoaded = pTypelibs;
+
       /* FIXME destroy child objects */
 
       TRACE(" destroying ITypeLib(%p)\n",This);
@@ -3237,6 +3282,25 @@
 
       if (This->pTypeInfo) /* can be NULL */
          ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
+
+      /* remove from the list of loaded typelibs */
+      while ( pThisLoaded )
+      {
+         if ( (ITypeLib*)This == pThisLoaded->pTypelib )
+         {
+             /* free our resources */
+             if ( pPrevLoaded == NULL )
+                 pTypelibs = pThisLoaded->pNext;
+             else
+                 pPrevLoaded->pNext = pThisLoaded->pNext;
+             HeapFree(GetProcessHeap(),0,pThisLoaded->szFile);
+             HeapFree(GetProcessHeap(),0,pThisLoaded);
+             break;
+         }
+         pPrevLoaded = pThisLoaded;
+         pThisLoaded = pThisLoaded->pNext;
+      }
+
       HeapFree(GetProcessHeap(),0,This);
       return 0;
     }
@@ -4249,12 +4313,18 @@
        ITypeInfo_GetTypeAttr(tinfo2,&tattr);
        switch (tattr->typekind) {
        case TKIND_ENUM:
-           if (V_VT(arg) == VT_I4) {
-               memcpy(argpos, &V_UNION(arg,iVal), 4);
-               return S_OK;
-           }
-           FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
-           break;
+          switch ( V_VT( arg ) ) {
+          case VT_I2:
+             *argpos = V_UNION(arg,iVal);
+             return S_OK;
+          case VT_I4:
+             memcpy(argpos, &V_UNION(arg,lVal), 4);
+             return S_OK;
+          default:
+             FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
+             break;
+          }
+
        case TKIND_ALIAS:
            tdesc = &(tattr->tdescAlias);
            hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
@@ -4449,6 +4519,9 @@
                for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
                    int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
                    TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
+                   TYPEDESC i4_tdesc;
+                   i4_tdesc.vt = VT_I4;
+
                    /* If we are a pointer to a variant, we are done already */
                    if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
                        continue;
@@ -4470,7 +4543,8 @@
                        ITypeInfo_GetTypeAttr(tinfo2,&tattr);
                        switch (tattr->typekind) {
                        case TKIND_ENUM:
-                           FIXME("TKIND_ENUM unhandled.\n");
+                           /* force the return type to be VT_I4 */
+                           tdesc = &i4_tdesc;
                            break;
                        case TKIND_ALIAS:
                            TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);


Seeya,
 Adam
--
Real Programmers don't comment their code. If it was hard to write,
it should be hard to read, and even harder to modify.
These are all my own opinions.




More information about the wine-patches mailing list