Rob Shearman : oleaut32: Split the methods for opening different sources of typelibs out of TLB_ReadTypeLib .

Alexandre Julliard julliard at winehq.org
Wed Mar 12 17:24:00 CDT 2008


Module: wine
Branch: master
Commit: 0ec1e2842ae3e4de3db843d3e06d972d91a58fc3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0ec1e2842ae3e4de3db843d3e06d972d91a58fc3

Author: Rob Shearman <rob at codeweavers.com>
Date:   Wed Mar 12 13:29:58 2008 +0000

oleaut32: Split the methods for opening different sources of typelibs out of TLB_ReadTypeLib.

---

 dlls/oleaut32/typelib.c |  256 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 202 insertions(+), 54 deletions(-)

diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c
index f251d70..70f8a0d 100644
--- a/dlls/oleaut32/typelib.c
+++ b/dlls/oleaut32/typelib.c
@@ -2217,6 +2217,188 @@ static CRITICAL_SECTION_DEBUG cache_section_debug =
 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
  *
@@ -2228,10 +2410,12 @@ static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 }
 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;
 
@@ -2285,63 +2469,27 @@ static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, IT
 
     /* 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) {




More information about the wine-cvs mailing list