From: Guillaume Charifi Subject: oleaut32: Fix TLB dependencies lookup (retry 6) Message-Id: <4840728.145568.1405100880516.JavaMail.www@wsfrf1119> Date: Fri, 11 Jul 2014 19:38:45 +0200 (CEST) A file was missing... Thank you Bruno Jesus. Fixes http://bugs.winehq.org/show_bug.cgi?id=34184 --- dlls/oleaut32/tests/Makefile.in  |   1 + dlls/oleaut32/tests/test_dep.idl |  44 ++++++++++++++++ dlls/oleaut32/tests/tmarshal.rc  |   3 ++ dlls/oleaut32/tests/typelib.c    |  43 +++++++++++++++ dlls/oleaut32/typelib.c          | 111 +++++++++++++++++++++++++++++++++++---- 5 files changed, 193 insertions(+), 9 deletions(-) diff --git a/dlls/oleaut32/tests/Makefile.in b/dlls/oleaut32/tests/Makefile.in index 036c63d..227f0e4 100644 --- a/dlls/oleaut32/tests/Makefile.in +++ b/dlls/oleaut32/tests/Makefile.in @@ -16,6 +16,7 @@ C_SRCS = \ RC_SRCS = tmarshal.rc IDL_SRCS = \ + test_dep.idl \ test_reg.idl \ test_tlb.idl \ tmarshal.idl diff --git a/dlls/oleaut32/tests/test_dep.idl b/dlls/oleaut32/tests/test_dep.idl new file mode 100644 index 0000000..050e96e --- /dev/null +++ b/dlls/oleaut32/tests/test_dep.idl @@ -0,0 +1,44 @@ +/* + * ITypeLib dependency test + * + * Copyright 2014 Guillaume Charifi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep ident +#pragma makedep typelib + +import "oaidl.idl"; /* needed by widl */ +import "test_tlb.idl"; + +[ + uuid(e0228f26-2946-478c-b64a-93feefa50532), + version(0.0), +] +library TestDep +{ + importlib("stdole2.tlb"); + importlib("test_tlb.tlb"); + + [ + odl, + uuid(394376dd-3bb8-4804-8ccc-9559434004f3) + ] + interface ITestDep : ISimpleIface + { + HRESULT test(); + } +} diff --git a/dlls/oleaut32/tests/tmarshal.rc b/dlls/oleaut32/tests/tmarshal.rc index cbb3b18..84ce487 100644 --- a/dlls/oleaut32/tests/tmarshal.rc +++ b/dlls/oleaut32/tests/tmarshal.rc @@ -35,3 +35,6 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL /* @makedep: test_reg.tlb */ 3 TYPELIB test_reg.tlb + +/* @makedep: test_dep.tlb */ +4 TYPELIB test_dep.tlb diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index 312195b..6794ea3 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -5454,6 +5454,48 @@ static void test_stub(void) CoUninitialize(); } +static void test_dep(void) { + HRESULT hr; + WCHAR pathW[MAX_PATH]; + ITypeLib *ptLib = NULL; + ITypeInfo *ptInfo = NULL; + ITypeInfo *ptInfoExt = NULL; + HREFTYPE refType; + + static const WCHAR testTLBResStrW[] = {'\\','4',0}; + static const WCHAR testTLBNameW[] = {'t','e','s','t','_','t','l','b','.','t','l','b',0}; + static const GUID tInfoGuid = {0x394376dd,0x3bb8,0x4804,{0x8c,0xcc,0x95,0x59,0x43,0x40,0x04,0xf3}}; + + trace("Starting typelib dependency tests\n"); + + hr = LoadTypeLibEx(testTLBNameW, REGKIND_NONE, &ptLib); + if(hr == S_OK) { + ITypeLib_Release(ptLib); + skip("test_tlb.tlb is on the path or registered, skipping typelib dependency tests\n"); + return; + } + + GetModuleFileNameW(NULL, pathW, MAX_PATH); + lstrcatW(pathW, testTLBResStrW); + + hr = LoadTypeLibEx(pathW, REGKIND_NONE, &ptLib); + ok(hr == S_OK, "got: %x\n", hr); + + hr = ITypeLib_GetTypeInfoOfGuid(ptLib, &tInfoGuid, &ptInfo); + ok(hr == S_OK, "got: %x\n", hr); + + hr = ITypeInfo_GetRefTypeOfImplType(ptInfo, 0, &refType); + ok(hr == S_OK, "got: %x\n", hr); + + hr = ITypeInfo_GetRefTypeInfo(ptInfo, refType, &ptInfoExt); + ok(hr == S_OK || broken(hr == TYPE_E_CANTLOADLIBRARY) /* win 2000 */, "got: %x\n", hr); + + ITypeInfo_Release(ptInfo); + if(ptInfoExt) + ITypeInfo_Release(ptInfoExt); + ITypeLib_Release(ptLib); +} + START_TEST(typelib) { const char *filename; @@ -5493,4 +5535,5 @@ START_TEST(typelib) test_LoadRegTypeLib(); test_GetLibAttr(); test_stub(); + test_dep(); } diff --git a/dlls/oleaut32/typelib.c b/dlls/oleaut32/typelib.c index 48b171b..d895696 100644 --- a/dlls/oleaut32/typelib.c +++ b/dlls/oleaut32/typelib.c @@ -7572,6 +7572,84 @@ static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface, return E_FAIL; } +struct search_res_tlb_param { + GUID *guid; + ITypeLib *pTLib; + HRESULT result; +}; + +static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszIntName, LONG_PTR lParam) +{ + struct search_res_tlb_param *This = (LPVOID)lParam; + + HRESULT ret; + + static WCHAR resFormatStrW[] = {'\\','%','d',0}; + WCHAR szPath[MAX_PATH]; + WCHAR szTLBPath[MAX_PATH]; + WCHAR szStringName[12]; + LPVOID pBase = NULL; + DWORD dwTLBLength = 0; + IUnknown *pFile = NULL; + ITypeLib2 *pTLib = NULL; + RPC_STATUS rpc_stat; + + This->pTLib = NULL; + This->result = E_FAIL; + + if(IS_INTRESOURCE(lpszIntName) == FALSE) + return TRUE; + + GetModuleFileNameW(hModule, szPath, MAX_PATH); + + strcpyW(szTLBPath, szPath); + snprintfW(szStringName, sizeof(szStringName)/sizeof(WCHAR), resFormatStrW, PtrToInt(lpszIntName)); + strcatW(szTLBPath, szStringName); + + ret = TLB_PEFile_Open(szPath, PtrToInt(lpszIntName), &pBase, &dwTLBLength, &pFile); + if (ret == TYPE_E_CANTLOADLIBRARY) + ret = TLB_NEFile_Open(szPath, PtrToInt(lpszIntName), &pBase, &dwTLBLength, &pFile); + if (ret == TYPE_E_CANTLOADLIBRARY) + ret = TLB_Mapping_Open(szPath, &pBase, &dwTLBLength, &pFile); + if (SUCCEEDED(ret)) + { + if (dwTLBLength >= 4) + { + DWORD dwSignature = FromLEDWord(*((DWORD*) pBase)); + if (dwSignature == MSFT_SIGNATURE) + pTLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength); + else if (dwSignature == SLTG_SIGNATURE) + pTLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength); + else + { + FIXME("Header type magic 0x%08x not supported.\n", dwSignature); + ret = E_FAIL; + } + } + else + ret = E_FAIL; + IUnknown_Release(pFile); + } + + if(pTLib) { + ITypeLibImpl *impl = impl_from_ITypeLib2(pTLib); + ret = UuidEqual((UUID *)This->guid, (UUID *)TLB_get_guid_null(impl->guid), &rpc_stat); + ITypeLib_Release((ITypeLib *)pTLib); + + ret = (ret == TRUE) ? LoadTypeLibEx(szTLBPath, REGKIND_NONE, (ITypeLib **)&pTLib) : E_FAIL; + } + + This->result = ret; + + if(SUCCEEDED(ret)) { + /* If found, stop to enumerate */ + This->pTLib = (ITypeLib *)pTLib; + return FALSE; + } + + return TRUE; +} + /* ITypeInfo::GetRefTypeInfo * * If a type description references other type descriptions, it retrieves @@ -7665,20 +7743,35 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo( ITypeLib_AddRef(pTLib); result = S_OK; } else { + static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; + struct search_res_tlb_param param; BSTR libnam; TRACE("typeinfo in imported typelib that isn't already loaded\n"); - result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid), - ref_type->pImpTLInfo->wVersionMajor, - ref_type->pImpTLInfo->wVersionMinor, - This->pTypeLib->syskind, - ref_type->pImpTLInfo->lcid, &libnam, TRUE); - if(FAILED(result)) - libnam = SysAllocString(ref_type->pImpTLInfo->name); + /* Search in resource table */ + param.guid = (GUID *)TLB_get_guid_null(ref_type->pImpTLInfo->guid); + param.pTLib = NULL; + param.result = E_FAIL; + + EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)¶m); + + pTLib = param.pTLib; + result = param.result; - result = LoadTypeLib(libnam, &pTLib); - SysFreeString(libnam); + /* Search on disk */ + if(FAILED(result)) { + result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid), + ref_type->pImpTLInfo->wVersionMajor, + ref_type->pImpTLInfo->wVersionMinor, + This->pTypeLib->syskind, + ref_type->pImpTLInfo->lcid, &libnam, TRUE); + if(FAILED(result)) + libnam = SysAllocString(ref_type->pImpTLInfo->name); + + result = LoadTypeLib(libnam, &pTLib); + SysFreeString(libnam); + } if(SUCCEEDED(result)) { ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);