Esempio n. 1
0
HRESULT CoreClrEmbedding::Initialize(BOOL debugMode)
{
    // Much of the CoreCLR bootstrapping process is cribbed from 
    // https://github.com/aspnet/dnx/blob/dev/src/dnx.coreclr.unix/dnx.coreclr.cpp

	DBG("CoreClrEmbedding::Initialize - Started")

    HRESULT result = S_OK;
    char currentDirectory[PATH_MAX];

#ifdef EDGE_PLATFORM_WINDOWS
    if (!_getcwd(&currentDirectory[0], PATH_MAX))
#else
    if (!getcwd(&currentDirectory[0], PATH_MAX))
#endif
    {
		throwV8Exception("Unable to get the current directory.");
        return E_FAIL;
    }

	char edgeNodePath[PATH_MAX];

#ifdef EDGE_PLATFORM_WINDOWS
    HMODULE moduleHandle = NULL;

    GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &CoreClrEmbedding::Initialize, &moduleHandle);
    GetModuleFileName(moduleHandle, edgeNodePath, PATH_MAX);
    PathRemoveFileSpec(edgeNodePath);
#else
    Dl_info dlInfo;

	dladdr((void*)&CoreClrEmbedding::Initialize, &dlInfo);
	strcpy(edgeNodePath, dlInfo.dli_fname);
	strcpy(edgeNodePath, dirname(edgeNodePath));
#endif

    DBG("CoreClrEmbedding::Initialize - edge.node path is %s", edgeNodePath);

    void* libCoreClr = NULL;
    char bootstrapper[PATH_MAX];

    GetPathToBootstrapper(&bootstrapper[0], PATH_MAX);
    DBG("CoreClrEmbedding::Initialize - Bootstrapper is %s", bootstrapper);

    char coreClrDirectory[PATH_MAX];
    char* coreClrEnvironmentVariable = getenv("CORECLR_DIR");

    if (coreClrEnvironmentVariable)
    {
        if (coreClrEnvironmentVariable[0] == '"')
        {
            strncpy(&coreClrDirectory[0], &coreClrEnvironmentVariable[1], strlen(coreClrEnvironmentVariable) - 2);
            coreClrDirectory[strlen(coreClrEnvironmentVariable) - 2] = '\0';
        }

        else
        {
            strncpy(&coreClrDirectory[0], coreClrEnvironmentVariable, strlen(coreClrEnvironmentVariable) + 1);
        }

    	DBG("CoreClrEmbedding::Initialize - Trying to load %s from the path specified in the CORECLR_DIR environment variable: %s", LIBCORECLR_NAME, coreClrDirectory);

        LoadCoreClrAtPath(coreClrDirectory, &libCoreClr);
    }

    if (!libCoreClr)
    {
    	strncpy(&coreClrDirectory[0], currentDirectory, strlen(currentDirectory) + 1);
    	LoadCoreClrAtPath(coreClrDirectory, &libCoreClr);
    }

    if (!libCoreClr)
    {
        // Try to load CoreCLR from application path
#ifdef EDGE_PLATFORM_WINDOWS
        char* lastSlash = strrchr(&bootstrapper[0], '\\');
#else
        char* lastSlash = strrchr(&bootstrapper[0], '/');
#endif

        assert(lastSlash);
        strncpy(&coreClrDirectory[0], &bootstrapper[0], lastSlash - &bootstrapper[0]);
        coreClrDirectory[lastSlash - &bootstrapper[0]] = '\0';

        LoadCoreClrAtPath(coreClrDirectory, &libCoreClr);
    }

    if (!libCoreClr)
    {
    	std::string pathEnvironmentVariable = getenv("PATH");
#if EDGE_PLATFORM_WINDOWS
    	char delimeter = ';';
#else
    	char delimeter = ':';
#endif

    	size_t previousIndex = 0;
    	size_t currentIndex = pathEnvironmentVariable.find(delimeter);

    	while (!libCoreClr && currentIndex != std::string::npos)
    	{
    		strncpy(&coreClrDirectory[0], pathEnvironmentVariable.substr(previousIndex, currentIndex - previousIndex).c_str(), currentIndex - previousIndex);
    		coreClrDirectory[currentIndex - previousIndex] = '\0';

    		LoadCoreClrAtPath(coreClrDirectory, &libCoreClr);

    		if (!libCoreClr)
    		{
				previousIndex = currentIndex + 1;
				currentIndex = pathEnvironmentVariable.find(delimeter, previousIndex);
    		}
    	}
    }

    if (!libCoreClr)
    {
		throwV8Exception("Failed to find CoreCLR.  Make sure that you have either specified the CoreCLR directory in the CORECLR_DIR environment variable or it exists somewhere in your PATH environment variable, which you do via the \"dnvm install\" and \"dnvm use\" commands.");
        return E_FAIL;
    }

    DBG("CoreClrEmbedding::Initialize - %s loaded successfully from %s", LIBCORECLR_NAME, &coreClrDirectory[0]);

    std::string assemblySearchDirectories;

    assemblySearchDirectories.append(&currentDirectory[0]);
    assemblySearchDirectories.append(":");
    assemblySearchDirectories.append(&coreClrDirectory[0]);

    DBG("CoreClrEmbedding::Initialize - Assembly search path is %s", assemblySearchDirectories.c_str());

    coreclr_initializeFunction initializeCoreCLR = (coreclr_initializeFunction) LoadSymbol(libCoreClr, "coreclr_initialize");

    if (!initializeCoreCLR)
    {
    	throwV8Exception("Error loading the coreclr_initialize function from %s: %s.", LIBCORECLR_NAME, GetLoadError());
        return E_FAIL;
    }

    DBG("CoreClrEmbedding::Initialize - coreclr_initialize loaded successfully");
    coreclr_create_delegateFunction createDelegate = (coreclr_create_delegateFunction) LoadSymbol(libCoreClr, "coreclr_create_delegate");

    if (!createDelegate)
    {
    	throwV8Exception("Error loading the coreclr_create_delegate function from %s: %s.", LIBCORECLR_NAME, GetLoadError());
    	return E_FAIL;
    }

    DBG("CoreClrEmbedding::Initialize - coreclr_create_delegate loaded successfully");

    const char* propertyKeys[] = {
    	"TRUSTED_PLATFORM_ASSEMBLIES",
    	"APP_PATHS",
    	"APP_NI_PATHS",
    	"NATIVE_DLL_SEARCH_DIRECTORIES",
    	"AppDomainCompatSwitch"
    };

    std::string tpaList;
    AddToTpaList(coreClrDirectory, &tpaList);

    std::string appPaths(&currentDirectory[0]);
#if EDGE_PLATFORM_WINDOWS
    appPaths.append(";");
#else
    appPaths.append(":");
#endif
    appPaths.append(edgeNodePath);

    DBG("CoreClrEmbedding::Initialize - Using %s as the app path value", appPaths.c_str());

    const char* propertyValues[] = {
    	tpaList.c_str(),
        appPaths.c_str(),
        appPaths.c_str(),
        assemblySearchDirectories.c_str(),
        "UseLatestBehaviorWhenTFMNotSpecified"
    };

    DBG("CoreClrEmbedding::Initialize - Calling coreclr_initialize()");
	result = initializeCoreCLR(
			bootstrapper,
			"Edge",
			sizeof(propertyKeys) / sizeof(propertyKeys[0]),
			&propertyKeys[0],
			&propertyValues[0],
			&hostHandle,
			&appDomainId);

	if (FAILED(result))
	{
		throwV8Exception("Call to coreclr_initialize() failed with a return code of 0x%x.", result);
		return result;
	}

	DBG("CoreClrEmbedding::Initialize - CoreCLR initialized successfully");
    DBG("CoreClrEmbedding::Initialize - App domain created successfully (app domain ID: %d)", appDomainId);

    SetCallV8FunctionDelegateFunction setCallV8Function;

    CREATE_DELEGATE("GetFunc", &getFunc);
    CREATE_DELEGATE("CallFunc", &callFunc);
    CREATE_DELEGATE("ContinueTask", &continueTask);
    CREATE_DELEGATE("FreeHandle", &freeHandle);
    CREATE_DELEGATE("FreeMarshalData", &freeMarshalData);
    CREATE_DELEGATE("SetCallV8FunctionDelegate", &setCallV8Function);
    CREATE_DELEGATE("CompileFunc", &compileFunc);
	CREATE_DELEGATE("Initialize", &initialize);

	DBG("CoreClrEmbedding::Initialize - Getting runtime info");

	CoreClrGcHandle exception = NULL;
	BootstrapperContext context;

	context.runtimeDirectory = &coreClrDirectory[0];
	context.applicationDirectory = getenv("EDGE_APP_ROOT");
	context.edgeNodePath = &edgeNodePath[0];

	if (!context.applicationDirectory)
	{
		context.applicationDirectory = &currentDirectory[0];
	}

	std::string operatingSystem = GetOSName();
	std::string operatingSystemVersion = GetOSVersion();

	context.architecture = GetOSArchitecture();
	context.operatingSystem = operatingSystem.c_str();
	context.operatingSystemVersion = operatingSystemVersion.c_str();

	DBG("CoreClrEmbedding::Initialize - Operating system: %s", context.operatingSystem);
	DBG("CoreClrEmbedding::Initialize - Operating system version: %s", context.operatingSystemVersion);
	DBG("CoreClrEmbedding::Initialize - Architecture: %s", context.architecture);
	DBG("CoreClrEmbedding::Initialize - Runtime directory: %s", context.runtimeDirectory);
	DBG("CoreClrEmbedding::Initialize - Application directory: %s", context.applicationDirectory);

	DBG("CoreClrEmbedding::Initialize - Calling CLR Initialize() function");

	initialize(&context, &exception);

	if (exception)
	{
		v8::Local<v8::Value> v8Exception = CoreClrFunc::MarshalCLRToV8(exception, V8TypeException);
		FreeMarshalData(exception, V8TypeException);

		throwV8Exception(v8Exception);
	}

	else
	{
		DBG("CoreClrEmbedding::Initialize - CLR Initialize() function called successfully")
	}

	exception = NULL;
	setCallV8Function(CoreClrNodejsFunc::Call, &exception);

	if (exception)
	{
		v8::Local<v8::Value> v8Exception = CoreClrFunc::MarshalCLRToV8(exception, V8TypeException);
		FreeMarshalData(exception, V8TypeException);

		throwV8Exception(v8Exception);
	}

	else
	{
		DBG("CoreClrEmbedding::Initialize - CallV8Function delegate set successfully");
	}

	DBG("CoreClrEmbedding::Initialize - Completed");

    return S_OK;
}
Esempio n. 2
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;
}
Esempio n. 3
0
extern "C" __declspec(dllexport) bool __stdcall CallApplicationMain(PCALL_APPLICATION_MAIN_DATA data)
{
    HRESULT hr = S_OK;
    FnGetCLRRuntimeHost pfnGetCLRRuntimeHost = nullptr;
    ICLRRuntimeHost2* pCLRRuntimeHost = nullptr;
    TCHAR szCurrentDirectory[MAX_PATH];
    TCHAR szCoreClrDirectory[MAX_PATH];
    TCHAR lpCoreClrModulePath[MAX_PATH];

    GetModuleDirectory(NULL, szCurrentDirectory);

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

    // 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 false;
    }

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

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

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

    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 false;
    }

    hr = pCLRRuntimeHost->Start();

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

    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
        //
    };

    wstring trustedPlatformAssemblies(L"");

    // Enumerate the core clr directory and add each .dll or .ni.dll to the list of trusted assemblies
    wstring pattern(szCoreClrDirectory);
    pattern += L"*.dll";

    WIN32_FIND_DATA ffd;
    HANDLE findHandle = FindFirstFile(pattern.c_str(), &ffd);

    if (INVALID_HANDLE_VALUE == findHandle)
    {
        printf_s("Failed to find files in the coreclr directory\n");
        return -1;
    }

    do
    {
        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // Skip directories
        }
        else
        {
            trustedPlatformAssemblies += szCoreClrDirectory;
            trustedPlatformAssemblies += ffd.cFileName;
            trustedPlatformAssemblies += L";";
        }

    } while (FindNextFile(findHandle, &ffd) != 0);

    // Add the assembly containing the app domain manager to the trusted list
    trustedPlatformAssemblies += szCurrentDirectory;
    trustedPlatformAssemblies += L"klr.core45.managed.dll";

    wstring appPaths(szCurrentDirectory);

    appPaths += L";";
    appPaths += szCoreClrDirectory;

    const wchar_t* property_values[] = {
        // APPBASE
        szCurrentDirectory, // TODO: Allow overriding this
        // TRUSTED_PLATFORM_ASSEMBLIES
        trustedPlatformAssemblies.c_str(),
        // APP_PATHS
        appPaths.c_str(),
    };

    DWORD domainId;
    DWORD dwFlagsAppDomain =
        APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
        APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP |
        APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE;

    LPCWSTR szAssemblyName = L"klr.core45.managed, Version=1.0.0.0";
    LPCWSTR szDomainManagerTypeName = L"DomainManager";
    LPCWSTR szMainMethodName = L"Main";

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

    hr = pCLRRuntimeHost->CreateAppDomainWithManager(
        L"klr.core45.managed",
        dwFlagsAppDomain,
        szAssemblyName,
        szDomainManagerTypeName,
        nprops,
        property_keys,
        property_values,
        &domainId);

    if (FAILED(hr))
    {
        printf_s("Failed to create app domain (%d).\n", hr);
        return false;
    }

    HostMain pHostMain;

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

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

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

    pCLRRuntimeHost->UnloadAppDomain(domainId, true);

    pCLRRuntimeHost->Stop();

    return hr;
}