Commit 6e9f2786 authored by Mike Hearn's avatar Mike Hearn Committed by Alexandre Julliard

Implemented a typelib loader cache.

parent 46f0d60a
...@@ -287,6 +287,8 @@ HRESULT WINAPI LoadTypeLibEx( ...@@ -287,6 +287,8 @@ HRESULT WINAPI LoadTypeLibEx(
INT index = 1; INT index = 1;
TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib); TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
*pptLib = NULL;
if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath, if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
NULL)) { NULL)) {
...@@ -653,6 +655,10 @@ typedef struct tagITypeLibImpl ...@@ -653,6 +655,10 @@ typedef struct tagITypeLibImpl
TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
libary. Only used while read MSFT libary. Only used while read MSFT
typelibs */ typelibs */
/* typelibs are cached, keyed by path, so store the linked list info within them */
struct tagITypeLibImpl *next, *prev;
WCHAR *path;
} ITypeLibImpl; } ITypeLibImpl;
static struct ICOM_VTABLE(ITypeLib2) tlbvt; static struct ICOM_VTABLE(ITypeLib2) tlbvt;
...@@ -1708,6 +1714,7 @@ MSFT_DoFuncs(TLBContext* pcx, ...@@ -1708,6 +1714,7 @@ MSFT_DoFuncs(TLBContext* pcx,
recoffset += reclength; recoffset += reclength;
} }
} }
static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs, static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
int cVars, int offset, TLBVarDesc ** pptvd) int cVars, int offset, TLBVarDesc ** pptvd)
{ {
...@@ -1965,6 +1972,22 @@ ITypeInfoImpl * MSFT_DoTypeInfo( ...@@ -1965,6 +1972,22 @@ ITypeInfoImpl * MSFT_DoTypeInfo(
return ptiRet; return ptiRet;
} }
/* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
* typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
* place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
* tradeoff here.
*/
static ITypeLibImpl *tlb_cache_first;
static CRITICAL_SECTION cache_section;
static CRITICAL_SECTION_DEBUG cache_section_debug =
{
0, 0, &cache_section,
{ &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
};
static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
/**************************************************************************** /****************************************************************************
* TLB_ReadTypeLib * TLB_ReadTypeLib
* *
...@@ -1975,6 +1998,7 @@ ITypeInfoImpl * MSFT_DoTypeInfo( ...@@ -1975,6 +1998,7 @@ ITypeInfoImpl * MSFT_DoTypeInfo(
#define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */ #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
{ {
ITypeLibImpl *entry;
int ret = TYPE_E_CANTLOADLIBRARY; int ret = TYPE_E_CANTLOADLIBRARY;
DWORD dwSignature = 0; DWORD dwSignature = 0;
HANDLE hFile; HANDLE hFile;
...@@ -1983,6 +2007,21 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) ...@@ -1983,6 +2007,21 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
*ppTypeLib = NULL; *ppTypeLib = NULL;
/* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
EnterCriticalSection(&cache_section);
for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
{
if (!strcmpiW(entry->path, pszFileName))
{
TRACE("cache hit\n");
*ppTypeLib = (ITypeLib2*)entry;
ITypeLib_AddRef(*ppTypeLib);
LeaveCriticalSection(&cache_section);
return S_OK;
}
}
LeaveCriticalSection(&cache_section);
/* check the signature of the file */ /* check the signature of the file */
hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
if (INVALID_HANDLE_VALUE != hFile) if (INVALID_HANDLE_VALUE != hFile)
...@@ -2054,11 +2093,23 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) ...@@ -2054,11 +2093,23 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
} }
} }
if(*ppTypeLib) if(*ppTypeLib) {
ret = S_OK; ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
else
ERR("Loading of typelib %s failed with error %ld\n", TRACE("adding to cache\n");
debugstr_w(pszFileName), GetLastError()); impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
lstrcpyW(impl->path, pszFileName);
/* We should really canonicalise the path here. */
/* FIXME: check if it has added already in the meantime */
EnterCriticalSection(&cache_section);
if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
impl->prev = NULL;
tlb_cache_first = impl;
LeaveCriticalSection(&cache_section);
ret = S_OK;
} else
ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
return ret; return ret;
} }
...@@ -3197,7 +3248,7 @@ static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface) ...@@ -3197,7 +3248,7 @@ static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
{ {
ICOM_THIS( ITypeLibImpl, iface); 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); return ++(This->ref);
} }
...@@ -3214,8 +3265,15 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface) ...@@ -3214,8 +3265,15 @@ static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
if (!This->ref) if (!This->ref)
{ {
/* FIXME destroy child objects */ /* remove cache entry */
TRACE("removing from cache list\n");
EnterCriticalSection(&cache_section);
if (This->next) This->next->prev = This->prev;
if (This->prev) This->prev->next = This->next;
else tlb_cache_first = This->next;
LeaveCriticalSection(&cache_section);
/* FIXME destroy child objects */
TRACE(" destroying ITypeLib(%p)\n",This); TRACE(" destroying ITypeLib(%p)\n",This);
if (This->Name) if (This->Name)
...@@ -4448,6 +4506,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke( ...@@ -4448,6 +4506,7 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
if (pFDesc->funcdesc.invkind & dwFlags) if (pFDesc->funcdesc.invkind & dwFlags)
break; break;
} }
if (pFDesc) { if (pFDesc) {
if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc); if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
/* dump_FUNCDESC(&pFDesc->funcdesc);*/ /* dump_FUNCDESC(&pFDesc->funcdesc);*/
...@@ -4869,13 +4928,13 @@ static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface, ...@@ -4869,13 +4928,13 @@ static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
/* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */ /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
if (pIndex) { if (pIndex) {
*pIndex=This->index; *pIndex=This->index;
TRACE("returning pIndex=%d", *pIndex); TRACE("returning pIndex=%d\n", *pIndex);
} }
if (ppTLib) { if (ppTLib) {
*ppTLib=(LPTYPELIB )(This->pTypeLib); *ppTLib=(LPTYPELIB )(This->pTypeLib);
ITypeLib2_AddRef(*ppTLib); ITypeLib2_AddRef(*ppTLib);
TRACE("returning ppTLib=%p", *ppTLib); TRACE("returning ppTLib=%p\n", *ppTLib);
} }
return S_OK; return S_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment