From: Guillaume Charifi Subject: [2/2] oleaut32: Implement TLB dependencies lookup in resources (resend 2) Message-Id: <2720902.985804.1411841428862.JavaMail.www@wsfrf1131> Date: Sat, 27 Sep 2014 15:35:02 +0200 (CEST) Fixes https://bugs.winehq.org/show_bug.cgi?id=34184 Changes short log corrected. --- dlls/oleaut32/tests/typelib.c | 2 +-  dlls/oleaut32/typelib.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 103 insertions(+), 10 deletions(-) diff --git a/dlls/oleaut32/tests/typelib.c b/dlls/oleaut32/tests/typelib.c index cb5bc23..99e2aedd 100644 --- a/dlls/oleaut32/tests/typelib.c +++ b/dlls/oleaut32/tests/typelib.c @@ -5595,7 +5595,7 @@ static void test_dep(void) { ok(hr == S_OK, "got: %x\n", hr); hr = ITypeInfo_GetRefTypeInfo(ptInfo, refType, &ptInfoExt); - todo_wine ok(hr == S_OK || broken(hr == TYPE_E_CANTLOADLIBRARY) /* win 2000 */, "got: %x\n", hr); + ok(hr == S_OK || broken(hr == TYPE_E_CANTLOADLIBRARY) /* win 2000 */, "got: %x\n", hr); ITypeInfo_Release(ptInfo); if(ptInfoExt) 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);