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

This commit is contained in:
Rob Shearman 2008-03-12 13:29:58 +00:00 committed by Alexandre Julliard
parent 66c728dec1
commit 0ec1e2842a
1 changed files with 202 additions and 54 deletions

View File

@ -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);
ret = TYPE_E_CANTLOADLIBRARY;
}
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)
{
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);
}
CloseHandle(hFile);
}
ret = TYPE_E_CANTLOADLIBRARY;
IUnknown_Release(pFile);
}
if(*ppTypeLib) {