static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
+typedef struct TLB_PEFile
+{
+ const IUnknownVtbl *lpvtbl;
+ LONG refs;
+ HMODULE dll;
+ HRSRC typelib_resource;
+ HGLOBAL typelib_global;
+ LPVOID typelib_base;
+} TLB_PEFile;
+
+static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *ppv = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
+{
+ TLB_PEFile *This = (TLB_PEFile *)iface;
+ return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
+{
+ TLB_PEFile *This = (TLB_PEFile *)iface;
+ ULONG refs = InterlockedDecrement(&This->refs);
+ if (!refs)
+ {
+ if (This->typelib_global)
+ FreeResource(This->typelib_global);
+ if (This->dll)
+ FreeLibrary(This->dll);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static const IUnknownVtbl TLB_PEFile_Vtable =
+{
+ TLB_PEFile_QueryInterface,
+ TLB_PEFile_AddRef,
+ TLB_PEFile_Release
+};
+
+static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
+{
+ TLB_PEFile *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+ if (!This)
+ return E_OUTOFMEMORY;
+
+ This->lpvtbl = &TLB_PEFile_Vtable;
+ This->refs = 1;
+ This->dll = NULL;
+ This->typelib_resource = NULL;
+ This->typelib_global = NULL;
+ This->typelib_base = NULL;
+
+ This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
+ LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
+
+ if (This->dll)
+ {
+ static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
+ This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
+ if (This->typelib_resource)
+ {
+ This->typelib_global = LoadResource(This->dll, This->typelib_resource);
+ if (This->typelib_global)
+ {
+ This->typelib_base = LockResource(This->typelib_global);
+
+ if (This->typelib_base)
+ {
+ *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
+ *ppBase = This->typelib_base;
+ *ppFile = (IUnknown *)&This->lpvtbl;
+ return S_OK;
+ }
+ }
+ }
+ }
+
+ TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
+ return TYPE_E_CANTLOADLIBRARY;
+}
+
+
+typedef struct TLB_Mapping
+{
+ const IUnknownVtbl *lpvtbl;
+ LONG refs;
+ HANDLE file;
+ HANDLE mapping;
+ LPVOID typelib_base;
+} TLB_Mapping;
+
+static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
+{
+ if (IsEqualIID(riid, &IID_IUnknown))
+ {
+ *ppv = iface;
+ IUnknown_AddRef(iface);
+ return S_OK;
+ }
+ *ppv = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
+{
+ TLB_Mapping *This = (TLB_Mapping *)iface;
+ return InterlockedIncrement(&This->refs);
+}
+
+static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
+{
+ TLB_Mapping *This = (TLB_Mapping *)iface;
+ ULONG refs = InterlockedDecrement(&This->refs);
+ if (!refs)
+ {
+ if (This->typelib_base)
+ UnmapViewOfFile(This->typelib_base);
+ if (This->mapping)
+ CloseHandle(This->mapping);
+ if (This->file != INVALID_HANDLE_VALUE)
+ CloseHandle(This->file);
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+ return refs;
+}
+
+static const IUnknownVtbl TLB_Mapping_Vtable =
+{
+ TLB_Mapping_QueryInterface,
+ TLB_Mapping_AddRef,
+ TLB_Mapping_Release
+};
+
+static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
+{
+ TLB_Mapping *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+ if (!This)
+ return E_OUTOFMEMORY;
+
+ This->lpvtbl = &TLB_Mapping_Vtable;
+ This->refs = 1;
+ This->file = INVALID_HANDLE_VALUE;
+ This->mapping = NULL;
+ This->typelib_base = NULL;
+
+ This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
+ if (INVALID_HANDLE_VALUE != This->file)
+ {
+ This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
+ if (This->mapping)
+ {
+ This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
+ if(This->typelib_base)
+ {
+ /* retrieve file size */
+ *pdwTLBLength = GetFileSize(This->file, NULL);
+ *ppBase = This->typelib_base;
+ *ppFile = (IUnknown *)&This->lpvtbl;
+ return S_OK;
+ }
+ }
+ }
+
+ IUnknown_Release((IUnknown *)&This->lpvtbl);
+ return TYPE_E_CANTLOADLIBRARY;
+}
+
/****************************************************************************
* TLB_ReadTypeLib
*
static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
{
ITypeLibImpl *entry;
- int ret = TYPE_E_CANTLOADLIBRARY;
+ HRESULT ret;
INT index = 1;
- HINSTANCE hinstDLL;
LPWSTR index_str, file = (LPWSTR)pszFileName;
+ LPVOID pBase = NULL;
+ DWORD dwTLBLength = 0;
+ IUnknown *pFile = NULL;
*ppTypeLib = NULL;
/* now actually load and parse the typelib */
- hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
- LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
-
- if (hinstDLL)
+ ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
+ if (ret == TYPE_E_CANTLOADLIBRARY)
+ ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
+ if (SUCCEEDED(ret))
{
- static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
- HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
- if (hrsrc)
+ if (dwTLBLength >= 4)
{
- HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
- if (hGlobal)
- {
- LPVOID pBase = LockResource(hGlobal);
- DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
-
- if (pBase)
- {
- /* try to load as incore resource */
- DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
- if (dwSignature == MSFT_SIGNATURE)
- *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
- else if (dwSignature == SLTG_SIGNATURE)
- *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
- else
- FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
- }
- FreeResource( hGlobal );
- }
- }
- FreeLibrary(hinstDLL);
- }
- else
- {
- HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
- if (INVALID_HANDLE_VALUE != hFile)
- {
- HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
- if (hMapping)
+ DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
+ if (dwSignature == MSFT_SIGNATURE)
+ *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
+ else if (dwSignature == SLTG_SIGNATURE)
+ *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
+ else
{
- LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
- if(pBase)
- {
- /* retrieve file size */
- DWORD dwTLBLength = GetFileSize(hFile, NULL);
- DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
-
- if (dwSignature == MSFT_SIGNATURE)
- *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
- else if (dwSignature == SLTG_SIGNATURE)
- *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
-
- UnmapViewOfFile(pBase);
- }
- CloseHandle(hMapping);
+ FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
+ ret = TYPE_E_CANTLOADLIBRARY;
}
- CloseHandle(hFile);
}
+ else
+ ret = TYPE_E_CANTLOADLIBRARY;
+ IUnknown_Release(pFile);
}
if(*ppTypeLib) {