Beispiel #1
0
extern "C" __declspec(dllexport) HRESULT __stdcall CallApplicationMain(PCALL_APPLICATION_MAIN_DATA data)
{
    HRESULT hr = S_OK;
    errno_t errno = 0;
    FnGetCLRRuntimeHost pfnGetCLRRuntimeHost = nullptr;
    ICLRRuntimeHost2* pCLRRuntimeHost = nullptr;
    TCHAR szCurrentDirectory[MAX_PATH];
    TCHAR szCoreClrDirectory[MAX_PATH];
    TCHAR lpCoreClrModulePath[MAX_PATH];
    size_t cchTrustedPlatformAssemblies = 0;
    LPWSTR pwszTrustedPlatformAssemblies = nullptr;

    Win32KDisable();

    if (data->runtimeDirectory) {
        errno = wcscpy_s(szCurrentDirectory, data->runtimeDirectory);
        CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);
    }
    else {
        GetModuleDirectory(NULL, szCurrentDirectory);
    }

    HMODULE hCoreCLRModule = LoadCoreClr();
    if (!hCoreCLRModule)
    {
        printf_s("Failed to locate coreclr.dll.\n");
        return E_FAIL;
    }

    // Get the path to the module
    DWORD dwCoreClrModulePathSize = GetModuleFileName(hCoreCLRModule, lpCoreClrModulePath, MAX_PATH);
    lpCoreClrModulePath[dwCoreClrModulePathSize] = '\0';

    GetModuleDirectory(hCoreCLRModule, szCoreClrDirectory);

    HMODULE ignoreModule;
    // Pin the module - CoreCLR.dll does not support being unloaded.
    if (!::GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN, lpCoreClrModulePath, &ignoreModule))
    {
        printf_s("Failed to pin coreclr.dll.\n");
        return E_FAIL;
    }

    pfnGetCLRRuntimeHost = (FnGetCLRRuntimeHost)::GetProcAddress(hCoreCLRModule, "GetCLRRuntimeHost");
    if (!pfnGetCLRRuntimeHost)
    {
        printf_s("Failed to find export GetCLRRuntimeHost.\n");
        return E_FAIL;
    }

    hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost2, (IUnknown**)&pCLRRuntimeHost);
    if (FAILED(hr))
    {
        printf_s("Failed to get IID_ICLRRuntimeHost2.\n");
        return hr;
    }

    STARTUP_FLAGS dwStartupFlags = (STARTUP_FLAGS)(
                                       STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN |
                                       STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN |
                                       STARTUP_FLAGS::STARTUP_SERVER_GC
                                   );

    pCLRRuntimeHost->SetStartupFlags(dwStartupFlags);

    // Authenticate with either CORECLR_HOST_AUTHENTICATION_KEY or CORECLR_HOST_AUTHENTICATION_KEY_NONGEN
    hr = pCLRRuntimeHost->Authenticate(CORECLR_HOST_AUTHENTICATION_KEY);
    if (FAILED(hr))
    {
        printf_s("Failed to Authenticate().\n");
        return hr;
    }

    hr = pCLRRuntimeHost->Start();

    if (FAILED(hr))
    {
        printf_s("Failed to Start().\n");
        return hr;
    }

    const wchar_t* property_keys[] =
    {
        // Allowed property names:
        // APPBASE
        // - The base path of the application from which the exe and other assemblies will be loaded
        L"APPBASE",
        //
        // TRUSTED_PLATFORM_ASSEMBLIES
        // - The list of complete paths to each of the fully trusted assemblies
        L"TRUSTED_PLATFORM_ASSEMBLIES",
        //
        // APP_PATHS
        // - The list of paths which will be probed by the assembly loader
        L"APP_PATHS",
        //
        // APP_NI_PATHS
        // - The list of additional paths that the assembly loader will probe for ngen images
        //
        // NATIVE_DLL_SEARCH_DIRECTORIES
        // - The list of paths that will be probed for native DLLs called by PInvoke
        //
    };

    cchTrustedPlatformAssemblies = TRUSTED_PLATFORM_ASSEMBLIES_STRING_BUFFER_SIZE_CCH;
    pwszTrustedPlatformAssemblies = (LPWSTR)calloc(cchTrustedPlatformAssemblies+1, sizeof(WCHAR));
    if (pwszTrustedPlatformAssemblies == NULL)
    {
        goto Finished;
    }
    pwszTrustedPlatformAssemblies[0] = L'\0';

    // Try native images first
    if (!GetTrustedPlatformAssembliesList(szCoreClrDirectory, true, pwszTrustedPlatformAssemblies, cchTrustedPlatformAssemblies))
    {
        if (!GetTrustedPlatformAssembliesList(szCoreClrDirectory, false, pwszTrustedPlatformAssemblies, cchTrustedPlatformAssemblies))
        {
            printf_s("Failed to find files in the coreclr directory\n");
            return E_FAIL;
        }
    }

    // Add the assembly containing the app domain manager to the trusted list

    errno = wcscat_s(pwszTrustedPlatformAssemblies, cchTrustedPlatformAssemblies, szCurrentDirectory);
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    errno = wcscat_s(pwszTrustedPlatformAssemblies, cchTrustedPlatformAssemblies, L"kre.coreclr.managed.dll");
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    //wstring appPaths(szCurrentDirectory);
    WCHAR wszAppPaths[MAX_PATH];
    wszAppPaths[0] = L'\0';

    errno = wcscat_s(wszAppPaths, _countof(wszAppPaths), szCurrentDirectory);
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    errno = wcscat_s(wszAppPaths, _countof(wszAppPaths), L";");
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    errno = wcscat_s(wszAppPaths, _countof(wszAppPaths), szCoreClrDirectory);
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    errno = wcscat_s(wszAppPaths, _countof(wszAppPaths), L";");
    CHECK_RETURN_VALUE_FAIL_EXIT_VIA_FINISHED(errno);

    const wchar_t* property_values[] = {
        // APPBASE
        data->applicationBase,
        // TRUSTED_PLATFORM_ASSEMBLIES
        pwszTrustedPlatformAssemblies,
        // APP_PATHS
        wszAppPaths,
    };

    DWORD domainId;
    DWORD dwFlagsAppDomain =
        APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
        APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP;

    LPCWSTR szAssemblyName = L"kre.coreclr.managed, Version=0.1.0.0";
    LPCWSTR szEntryPointTypeName = L"DomainManager";
    LPCWSTR szMainMethodName = L"Execute";

    int nprops = sizeof(property_keys) / sizeof(wchar_t*);

    hr = pCLRRuntimeHost->CreateAppDomainWithManager(
             L"kre.coreclr.managed",
             dwFlagsAppDomain,
             NULL,
             NULL,
             nprops,
             property_keys,
             property_values,
             &domainId);

    if (FAILED(hr))
    {
        wprintf_s(L"TPA      %d %S\n", wcslen(pwszTrustedPlatformAssemblies), pwszTrustedPlatformAssemblies);
        wprintf_s(L"AppPaths %S\n", wszAppPaths);
        printf_s("Failed to create app domain (%x).\n", hr);
        return hr;
    }

    HostMain pHostMain;

    hr = pCLRRuntimeHost->CreateDelegate(
             domainId,
             szAssemblyName,
             szEntryPointTypeName,
             szMainMethodName,
             (INT_PTR*)&pHostMain);

    if (FAILED(hr))
    {
        printf_s("Failed to create main delegate (%x).\n", hr);
        return hr;
    }

    SetEnvironmentVariable(L"KRE_FRAMEWORK", L"aspnetcore50");

    // Call main
    data->exitcode = pHostMain(data->argc, data->argv);

    pCLRRuntimeHost->UnloadAppDomain(domainId, true);

    pCLRRuntimeHost->Stop();

Finished:
    if (pwszTrustedPlatformAssemblies != NULL)
    {
        free(pwszTrustedPlatformAssemblies);
        pwszTrustedPlatformAssemblies = NULL;
    }

    if (FAILED(hr))
    {
        return hr;
    }
    else
    {
        return S_OK;
    }
}
Beispiel #2
0
HRESULT ExecuteMain(ICLRRuntimeHost2* pCLRRuntimeHost, PCALL_APPLICATION_MAIN_DATA data, const std::wstring& runtime_directory,
    const std::wstring& core_clr_directory, dnx::trace_writer& trace_writer)
{
    const wchar_t* property_keys[] =
    {
        // Allowed property names:
        // APPBASE
        // - The base path of the application from which the exe and other assemblies will be loaded
        L"APPBASE",
        //
        // TRUSTED_PLATFORM_ASSEMBLIES
        // - The list of complete paths to each of the fully trusted assemblies
        L"TRUSTED_PLATFORM_ASSEMBLIES",
        //
        // APP_PATHS
        // - The list of paths which will be probed by the assembly loader
        L"APP_PATHS",
        //
        // APP_NI_PATHS
        // - The list of additional paths that the assembly loader will probe for ngen images
        //
        // NATIVE_DLL_SEARCH_DIRECTORIES
        // - The list of paths that will be probed for native DLLs called by PInvoke
        //
        L"AppDomainCompatSwitch",
    };

    std::wstring trusted_platform_assemblies;
    // Came up with 8192 empirically - the string we build is about 4000 characters on my machine but it contains
    // paths to the user profile folder so it can be bigger.
    trusted_platform_assemblies.reserve(8192);

    // Try native images first
    if (!GetTrustedPlatformAssembliesList(core_clr_directory, true, trusted_platform_assemblies))
    {
        if (!GetTrustedPlatformAssembliesList(core_clr_directory, false, trusted_platform_assemblies))
        {
            trace_writer.write(L"Failed to find TPA files in the coreclr directory", false);
            return E_FAIL;
        }
    }

    // Add the assembly containing the app domain manager to the trusted list
    trusted_platform_assemblies.append(dnx::utils::path_combine(runtime_directory, L"Microsoft.Dnx.Host.CoreClr.dll"));

    std::wstring app_paths;
    app_paths.append(runtime_directory).append(L";");
    app_paths.append(core_clr_directory).append(L";");

    const wchar_t* property_values[] = {
        // APPBASE
        data->applicationBase,
        // TRUSTED_PLATFORM_ASSEMBLIES
        trusted_platform_assemblies.c_str(),
        // APP_PATHS
        app_paths.c_str(),
        // Use the latest behavior when TFM not specified
        L"UseLatestBehaviorWhenTFMNotSpecified",
    };

    DWORD domainId;

    HRESULT hr = pCLRRuntimeHost->CreateAppDomainWithManager(
        L"Microsoft.Dnx.Host.CoreClr",
        APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS | APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP | APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT,
        NULL,
        NULL,
        sizeof(property_keys) / sizeof(wchar_t*),
        property_keys,
        property_values,
        &domainId);

    if (FAILED(hr))
    {
        trace_writer.write(L"Failed to create app domain", false);
        trace_writer.write(std::wstring(L"TPA: ").append(trusted_platform_assemblies), false);
        trace_writer.write(std::wstring(L"AppPaths: ").append(app_paths), false);
        return hr;
    }

    HostMain main_function;
    // looks like the Version in the assembly is mandatory but the value does not matter
    hr = pCLRRuntimeHost->CreateDelegate(domainId, L"Microsoft.Dnx.Host.CoreClr, Version=0.0.0.0", L"DomainManager", L"Execute", (INT_PTR*)&main_function);
    if (FAILED(hr))
    {
        trace_writer.write(L"Failed to create main delegate", false);
        return hr;
    }

    // Call main
    data->exitcode = main_function(data->argc, data->argv);

    pCLRRuntimeHost->UnloadAppDomain(domainId, true);

    return S_OK;
}
Beispiel #3
0
extern "C" HRESULT CallApplicationMain(PCALL_APPLICATION_MAIN_DATA data)
{
    HRESULT hr = S_OK;
    size_t cchTrustedPlatformAssemblies = 0;
    std::string runtimeDirectory;

    if (data->runtimeDirectory)
    {
        runtimeDirectory = data->runtimeDirectory;
    }
    else
    {
        // TODO: This should get the directory that this library is in, not the CWD.
        char szCurrentDirectory[PATH_MAX];

        if (!getcwd(szCurrentDirectory, PATH_MAX))
        {
            return E_FAIL;
        }

        runtimeDirectory = std::string(szCurrentDirectory);
    }

    std::string coreClrDirectory;
    void* coreClr = LoadCoreClr(coreClrDirectory);

    if (!coreClr)
    {
        char* error = dlerror();
        fprintf(stderr, "failed to locate coreclr.dll with error %s\n", error);
        return E_FAIL;
    }

    const char* property_keys[] =
    {
        "APPBASE",
        "TRUSTED_PLATFORM_ASSEMBLIES",
        "APP_PATHS",
    };

    std::string trustedPlatformAssemblies;

    // Try native images first
    if (!GetTrustedPlatformAssembliesList(coreClrDirectory.c_str(), true, trustedPlatformAssemblies))
    {
        if (!GetTrustedPlatformAssembliesList(coreClrDirectory.c_str(), false, trustedPlatformAssemblies))
        {
            fprintf(stderr, "Failed to find files in the coreclr directory\n");
            hr = E_FAIL;
            return hr;
        }
    }

    // Add the assembly containing the app domain manager to the trusted list
    trustedPlatformAssemblies.append(runtimeDirectory);
    trustedPlatformAssemblies.append("dnx.coreclr.managed.dll");

    std::string appPaths(runtimeDirectory);

    appPaths.append(":");
    appPaths.append(coreClrDirectory);
    appPaths.append(":");

    const char* property_values[] = {
        // APPBASE
        data->applicationBase,
        // TRUESTED_PLATFORM_ASSEMBLIES
        trustedPlatformAssemblies.c_str(),
        // APP_PATHS
        appPaths.c_str(),
    };

    ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreClr, "ExecuteAssembly");

    if (!executeAssembly)
    {
        fprintf(stderr, "Could not find ExecuteAssembly entrypoint in coreclr.\n");
        return E_FAIL;
    }

    setenv("DNX_FRAMEWORK", "dnxcore50", 1);

    std::string coreClrDllPath(coreClrDirectory);
    coreClrDllPath.append("/");
    coreClrDllPath.append("libcoreclr.so");

    char pathToBootstrapper[PATH_MAX];
    ssize_t pathLen = readlink("/proc/self/exe", pathToBootstrapper, PATH_MAX - 1);

    if (pathLen == -1)
    {
        fprintf(stderr, "Could not locate full bootstrapper path.\n");
        return E_FAIL;
    }

    pathToBootstrapper[pathLen] = '\0';

    hr = executeAssembly(pathToBootstrapper,
                         coreClrDllPath.c_str(),
                         "dnx.coreclr.managed",
                         sizeof(property_keys) / sizeof(property_keys[0]),
                         property_keys,
                         property_values,
                         data->argc,
                         (const char**)data->argv,
                         nullptr,
                         "dnx.coreclr.managed, Version=0.1.0.0",
                         "DomainManager",
                         "Execute",
                         (DWORD*)&(data->exitcode));


    dlclose(coreClr);

    return hr;
}