From b99c35c0e84bbfb4c37fa49aa391758845cb7921 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Mon, 22 Feb 2016 15:04:02 -0600 Subject: [PATCH] mscoree/tests: Check if the runtime is usable before loading it. Unfortunately, Mono calls exit(1) if it can't load its class libraries, which is the way Wine fails on x86_64, meaning we have to spawn another process to check if the runtime works. Signed-off-by: Vincent Povirk Signed-off-by: Alexandre Julliard --- dlls/mscoree/tests/mscoree.c | 110 ++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/dlls/mscoree/tests/mscoree.c b/dlls/mscoree/tests/mscoree.c index 106577e2b0d..6923f2a603a 100644 --- a/dlls/mscoree/tests/mscoree.c +++ b/dlls/mscoree/tests/mscoree.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include + #define COBJMACROS #include "corerror.h" @@ -72,6 +74,97 @@ static BOOL init_functionpointers(void) return TRUE; } +static int check_runtime(void) +{ + ICLRMetaHost *metahost; + ICLRRuntimeInfo *runtimeinfo; + ICorRuntimeHost *runtimehost; + HRESULT hr; + + if (!pCLRCreateInstance) + { + win_skip("Function CLRCreateInstance not found.\n"); + return 1; + } + + hr = pCLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, (void **)&metahost); + if (hr == E_NOTIMPL) + { + win_skip("CLRCreateInstance not implemented\n"); + return 1; + } + ok(SUCCEEDED(hr), "CLRCreateInstance failed, hr=%#.8x\n", hr); + if (FAILED(hr)) + return 1; + + hr = ICLRMetaHost_GetRuntime(metahost, v4_0, &IID_ICLRRuntimeInfo, (void **)&runtimeinfo); + ok(SUCCEEDED(hr), "ICLRMetaHost::GetRuntime failed, hr=%#.8x\n", hr); + if (FAILED(hr)) + return 1; + + hr = ICLRRuntimeInfo_GetInterface(runtimeinfo, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost, + (void **)&runtimehost); + ok(SUCCEEDED(hr), "ICLRRuntimeInfo::GetInterface failed, hr=%#.8x\n", hr); + if (FAILED(hr)) + return 1; + + hr = ICorRuntimeHost_Start(runtimehost); + ok(SUCCEEDED(hr), "ICorRuntimeHost::Start failed, hr=%#.8x\n", hr); + if (FAILED(hr)) + return 1; + + ICorRuntimeHost_Release(runtimehost); + + ICLRRuntimeInfo_Release(runtimeinfo); + + ICLRMetaHost_ExitProcess(metahost, 0); + + ok(0, "ICLRMetaHost_ExitProcess is not supposed to return\n"); + return 1; +} + +static BOOL runtime_is_usable(void) +{ + static const char cmdline_format[] = "\"%s\" mscoree check_runtime"; + char** argv; + char cmdline[MAX_PATH + sizeof(cmdline_format)]; + STARTUPINFOA si = {0}; + PROCESS_INFORMATION pi; + BOOL ret; + DWORD exitcode; + + winetest_get_mainargs(&argv); + + sprintf(cmdline, cmdline_format, argv[0]); + + si.cb = sizeof(si); + + ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + ok(ret, "CreateProcessA failed\n"); + if (!ret) + return FALSE; + + CloseHandle(pi.hThread); + + WaitForSingleObject(pi.hProcess, INFINITE); + + ret = GetExitCodeProcess(pi.hProcess, &exitcode); + CloseHandle(pi.hProcess); + + ok(ret, "GetExitCodeProcess failed\n"); + + if (!ret || exitcode != 0) + { +#ifndef __i386__ + todo_wine +#endif + win_skip(".NET 4.0 runtime is not usable\n"); + return FALSE; + } + + return TRUE; +} + static void test_versioninfo(void) { const WCHAR v9_0[] = {'v','9','.','0','.','3','0','3','1','9',0}; @@ -520,14 +613,29 @@ static void test_createdomain(void) START_TEST(mscoree) { + int argc; + char** argv; + if (!init_functionpointers()) return; + argc = winetest_get_mainargs(&argv); + if (argc >= 3 && !strcmp(argv[2], "check_runtime")) + { + int result = check_runtime(); + FreeLibrary(hmscoree); + exit(result); + } + test_versioninfo(); test_loadlibraryshim(); test_createconfigstream(); test_createinstance(); - test_createdomain(); + + if (runtime_is_usable()) + { + test_createdomain(); + } FreeLibrary(hmscoree); }