예제 #1
0
파일: metahost.c 프로젝트: kholia/wine
static HRESULT load_mono(LPCWSTR mono_path)
{
    static const WCHAR lib[] = {'\\','l','i','b',0};
    static const WCHAR etc[] = {'\\','e','t','c',0};
    WCHAR mono_dll_path[MAX_PATH+16];
    WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4];
    char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH];
    int trace_size;
    char trace_setting[256];
    int verbose_size;
    char verbose_setting[256];

    if (is_mono_shutdown)
    {
        ERR("Cannot load Mono after it has been shut down.\n");
        return E_FAIL;
    }

    if (!mono_handle)
    {
        strcpyW(mono_lib_path, mono_path);
        strcatW(mono_lib_path, lib);
        WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL);

        strcpyW(mono_etc_path, mono_path);
        strcatW(mono_etc_path, etc);
        WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL);

        if (!find_mono_dll(mono_path, mono_dll_path)) goto fail;

        mono_handle = LoadLibraryW(mono_dll_path);

        if (!mono_handle) goto fail;

#define LOAD_MONO_FUNCTION(x) do { \
    x = (void*)GetProcAddress(mono_handle, #x); \
    if (!x) { \
        goto fail; \
    } \
} while (0);

        LOAD_MONO_FUNCTION(mono_assembly_get_image);
        LOAD_MONO_FUNCTION(mono_assembly_load_from);
        LOAD_MONO_FUNCTION(mono_assembly_open);
        LOAD_MONO_FUNCTION(mono_config_parse);
        LOAD_MONO_FUNCTION(mono_class_from_mono_type);
        LOAD_MONO_FUNCTION(mono_class_from_name);
        LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
        LOAD_MONO_FUNCTION(mono_domain_assembly_open);
        LOAD_MONO_FUNCTION(mono_domain_get);
        LOAD_MONO_FUNCTION(mono_domain_get_by_id);
        LOAD_MONO_FUNCTION(mono_domain_set);
        LOAD_MONO_FUNCTION(mono_domain_set_config);
        LOAD_MONO_FUNCTION(mono_free);
        LOAD_MONO_FUNCTION(mono_image_open);
        LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
        LOAD_MONO_FUNCTION(mono_jit_exec);
        LOAD_MONO_FUNCTION(mono_jit_init_version);
        LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
        LOAD_MONO_FUNCTION(mono_marshal_get_vtfixup_ftnptr);
        LOAD_MONO_FUNCTION(mono_object_get_domain);
        LOAD_MONO_FUNCTION(mono_object_get_virtual_method);
        LOAD_MONO_FUNCTION(mono_object_new);
        LOAD_MONO_FUNCTION(mono_object_unbox);
        LOAD_MONO_FUNCTION(mono_profiler_install);
        LOAD_MONO_FUNCTION(mono_reflection_type_from_name);
        LOAD_MONO_FUNCTION(mono_runtime_invoke);
        LOAD_MONO_FUNCTION(mono_runtime_object_init);
        LOAD_MONO_FUNCTION(mono_runtime_quit);
        LOAD_MONO_FUNCTION(mono_set_dirs);
        LOAD_MONO_FUNCTION(mono_set_verbose_level);
        LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
        LOAD_MONO_FUNCTION(mono_string_new);
        LOAD_MONO_FUNCTION(mono_thread_attach);
        LOAD_MONO_FUNCTION(mono_thread_manage);
        LOAD_MONO_FUNCTION(mono_trace_set_assembly);

#undef LOAD_MONO_FUNCTION

#define LOAD_OPT_MONO_FUNCTION(x, default) do { \
    x = (void*)GetProcAddress(mono_handle, #x); \
    if (!x) { \
        x = default; \
    } \
} while (0);

        LOAD_OPT_MONO_FUNCTION(mono_image_open_from_module_handle, image_open_module_handle_dummy);
        LOAD_OPT_MONO_FUNCTION(mono_set_crash_chaining, set_crash_chaining_dummy);
        LOAD_OPT_MONO_FUNCTION(mono_trace_set_print_handler, set_print_handler_dummy);
        LOAD_OPT_MONO_FUNCTION(mono_trace_set_printerr_handler, set_print_handler_dummy);

#undef LOAD_OPT_MONO_FUNCTION

        mono_profiler_install(NULL, mono_shutdown_callback_fn);

        mono_set_crash_chaining(TRUE);

        mono_trace_set_print_handler(mono_print_handler_fn);
        mono_trace_set_printerr_handler(mono_print_handler_fn);

        mono_set_dirs(mono_lib_path_a, mono_etc_path_a);

        mono_config_parse(NULL);

        mono_install_assembly_preload_hook(mono_assembly_preload_hook_fn, NULL);

        trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting));

        if (trace_size)
        {
            mono_jit_set_trace_options(trace_setting);
        }

        verbose_size = GetEnvironmentVariableA("WINE_MONO_VERBOSE", verbose_setting, sizeof(verbose_setting));

        if (verbose_size)
        {
            mono_set_verbose_level(verbose_setting[0] - '0');
        }
    }

    return S_OK;

fail:
    ERR("Could not load Mono into this process\n");
    FreeLibrary(mono_handle);
    mono_handle = NULL;
    return E_FAIL;
}
예제 #2
0
static void InitMono()
{
	std::string citizenClrPath = MakeRelativeNarrowPath("citizen/clr2/lib/");
	std::string citizenCfgPath = MakeRelativeNarrowPath("citizen/clr2/cfg/");

	mono_set_dirs(citizenClrPath.c_str(), citizenCfgPath.c_str());

#ifdef _WIN32
	std::wstring citizenClrLibPath = MakeRelativeCitPath(L"citizen/clr2/lib/mono/4.5/");

	SetEnvironmentVariable(L"MONO_PATH", citizenClrLibPath.c_str());

	mono_set_crash_chaining(true);
#else
	std::string citizenClrLibPath = MakeRelativeNarrowPath("citizen/clr2/lib/mono/4.5/");

	putenv(const_cast<char*>(va("MONO_PATH=%s", citizenClrLibPath)));
#endif

	mono_assembly_setrootdir(citizenClrPath.c_str());

	putenv("MONO_DEBUG=casts");

#ifndef IS_FXSERVER
	mono_security_enable_core_clr();
	mono_security_core_clr_set_options((MonoSecurityCoreCLROptions)(MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_DELEGATE | MONO_SECURITY_CORE_CLR_OPTIONS_RELAX_REFLECTION));
	mono_security_set_core_clr_platform_callback(CoreClrCallback);
#endif

	char* args[1];

#ifdef _WIN32
	args[0] = "--soft-breakpoints";
#else
	args[0] = "--use-fallback-tls";
#endif

	mono_jit_parse_options(1, args);

	mono_debug_init(MONO_DEBUG_FORMAT_MONO);

	g_rootDomain = mono_jit_init_version("Citizen", "v4.0.30319");

	mono_domain_set_config(g_rootDomain, ".", "cfx.config");

	mono_install_unhandled_exception_hook([] (MonoObject* exc, void*)
	{
		OutputExceptionDetails(exc);
	}, nullptr);

	mono_set_crash_chaining(true);

	mono_add_internal_call("CitizenFX.Core.GameInterface::PrintLog", reinterpret_cast<void*>(GI_PrintLogCall));
	mono_add_internal_call("CitizenFX.Core.GameInterface::fwFree", reinterpret_cast<void*>(fwFree));

	std::string platformPath = MakeRelativeNarrowPath("citizen/clr2/lib/mono/4.5/CitizenFX.Core.dll");

	auto scriptManagerAssembly = mono_domain_assembly_open(g_rootDomain, platformPath.c_str());

	if (!scriptManagerAssembly)
	{
		FatalError("Could not load CitizenFX.Core.dll.\n");
	}

	auto scriptManagerImage = mono_assembly_get_image(scriptManagerAssembly);

	bool methodSearchSuccess = true;
	MonoMethodDesc* description;

#define method_search(name, method) description = mono_method_desc_new(name, 1); \
			method = mono_method_desc_search_in_image(description, scriptManagerImage); \
			mono_method_desc_free(description); \
			methodSearchSuccess = methodSearchSuccess && method != NULL

	MonoMethod* rtInitMethod;
	method_search("CitizenFX.Core.RuntimeManager:Initialize", rtInitMethod);
	method_search("CitizenFX.Core.RuntimeManager:GetImplementedClasses", g_getImplementsMethod);
	method_search("CitizenFX.Core.RuntimeManager:CreateObjectInstance", g_createObjectMethod);

	if (!methodSearchSuccess)
	{
		FatalError("Couldn't find one or more CitizenFX.Core methods.\n");
	}

	MonoObject* exc = nullptr;
	mono_runtime_invoke(rtInitMethod, nullptr, nullptr, &exc);

	if (exc)
	{
		OutputExceptionDetails(exc);
		return;
	}
}