Commit d7031be8 authored by Gijs Vermeulen's avatar Gijs Vermeulen Committed by Alexandre Julliard

mscoree: Support loading assemblies from path specified in config file.

parent 79c5d8af
......@@ -347,8 +347,15 @@ static HRESULT parse_probing(ConfigFileHandler *This, ISAXAttributes *pAttr)
hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, privatePath, lstrlenW(privatePath), &value, &value_size);
if (SUCCEEDED(hr))
FIXME("privatePath=%s not implemented\n", debugstr_wn(value, value_size));
hr = S_OK;
{
TRACE("%s\n", debugstr_wn(value, value_size));
This->result->private_path = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
if (This->result->private_path)
wcscpy(This->result->private_path, value);
else
hr = E_OUTOFMEMORY;
}
return hr;
}
......@@ -698,4 +705,6 @@ void free_parsed_config_file(parsed_config_file *file)
list_remove(&cursor->entry);
HeapFree(GetProcessHeap(), 0, cursor);
}
HeapFree(GetProcessHeap(), 0, file->private_path);
}
......@@ -58,6 +58,8 @@ static HANDLE dll_fixup_heap; /* using a separate heap so we can have execute pe
static struct list dll_fixups;
WCHAR **private_path = NULL;
struct dll_fixup
{
struct list entry;
......@@ -1436,6 +1438,8 @@ static void FixupVTable(HMODULE hmodule)
__int32 WINAPI _CorExeMain(void)
{
static const WCHAR dotconfig[] = {'.','c','o','n','f','i','g',0};
static const WCHAR scW[] = {';',0};
int exit_code;
int argc;
char **argv;
......@@ -1443,12 +1447,14 @@ __int32 WINAPI _CorExeMain(void)
MonoImage *image;
MonoImageOpenStatus status;
MonoAssembly *assembly=NULL;
WCHAR filename[MAX_PATH];
WCHAR filename[MAX_PATH], config_file[MAX_PATH], *temp, **priv_path;
SIZE_T config_file_dir_size;
char *filenameA;
ICLRRuntimeInfo *info;
RuntimeHost *host;
parsed_config_file parsed_config;
HRESULT hr;
int i;
int i, number_of_private_paths = 0;
get_utf8_args(&argc, &argv);
......@@ -1468,6 +1474,33 @@ __int32 WINAPI _CorExeMain(void)
FixupVTable(GetModuleHandleW(NULL));
wcscpy(config_file, filename);
wcscat(config_file, dotconfig);
hr = parse_config_file(config_file, &parsed_config);
if (SUCCEEDED(hr) && parsed_config.private_path)
{
for(i = 0; parsed_config.private_path[i] != 0; i++)
if (parsed_config.private_path[i] == ';') number_of_private_paths++;
if (parsed_config.private_path[wcslen(parsed_config.private_path) - 1] != ';') number_of_private_paths++;
config_file_dir_size = (wcsrchr(config_file, '\\') - config_file) + 1;
priv_path = HeapAlloc(GetProcessHeap(), 0, (number_of_private_paths + 1) * sizeof(WCHAR *));
/* wcstok ignores trailing semicolons */
temp = wcstok(parsed_config.private_path, scW);
for (i = 0; i < number_of_private_paths; i++)
{
priv_path[i] = HeapAlloc(GetProcessHeap(), 0, (config_file_dir_size + wcslen(temp) + 1) * sizeof(WCHAR));
memcpy(priv_path[i], config_file, config_file_dir_size * sizeof(WCHAR));
wcscpy(priv_path[i] + config_file_dir_size, temp);
temp = wcstok(NULL, scW);
}
priv_path[number_of_private_paths] = NULL;
if (InterlockedCompareExchangePointer((void **)&private_path, priv_path, NULL))
ERR("private_path was already set\n");
}
free_parsed_config_file(&parsed_config);
hr = get_runtime_info(filename, NULL, NULL, NULL, 0, 0, FALSE, &info);
if (SUCCEEDED(hr))
......@@ -1475,15 +1508,7 @@ __int32 WINAPI _CorExeMain(void)
hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
if (SUCCEEDED(hr))
{
WCHAR config_file[MAX_PATH];
static const WCHAR dotconfig[] = {'.','c','o','n','f','i','g',0};
lstrcpyW(config_file, filename);
lstrcatW(config_file, dotconfig);
hr = RuntimeHost_GetDefaultDomain(host, config_file, &domain);
}
if (SUCCEEDED(hr))
{
......
......@@ -1610,20 +1610,56 @@ static MonoAssembly* CDECL mono_assembly_preload_hook_fn(MonoAssemblyName *aname
HRESULT hr;
MonoAssembly *result=NULL;
char *stringname=NULL;
const char *assemblyname;
LPWSTR stringnameW;
int stringnameW_size;
WCHAR path[MAX_PATH];
char *pathA;
MonoImageOpenStatus stat;
DWORD search_flags;
int i;
static const WCHAR dotdllW[] = {'.','d','l','l',0};
static const WCHAR slashW[] = {'\\',0};
stringname = mono_stringify_assembly_name(aname);
assemblyname = mono_assembly_name_get_name(aname);
TRACE("%s\n", debugstr_a(stringname));
if (!stringname) return NULL;
if (!stringname || !assemblyname) return NULL;
search_flags = get_assembly_search_flags(aname);
if (private_path)
{
stringnameW_size = MultiByteToWideChar(CP_UTF8, 0, assemblyname, -1, NULL, 0);
stringnameW = HeapAlloc(GetProcessHeap(), 0, stringnameW_size * sizeof(WCHAR));
if (stringnameW)
{
MultiByteToWideChar(CP_UTF8, 0, assemblyname, -1, stringnameW, stringnameW_size);
for (i = 0; private_path[i] != NULL; i++)
{
wcscpy(path, private_path[i]);
wcscat(path, slashW);
wcscat(path, stringnameW);
wcscat(path, dotdllW);
pathA = WtoA(path);
if (pathA)
{
result = mono_assembly_open(pathA, &stat);
if (result)
{
TRACE("found: %s\n", debugstr_w(path));
HeapFree(GetProcessHeap(), 0, pathA);
HeapFree(GetProcessHeap(), 0, stringnameW);
mono_free(stringname);
return result;
}
HeapFree(GetProcessHeap(), 0, pathA);
}
}
HeapFree(GetProcessHeap(), 0, stringnameW);
}
}
/* FIXME: We should search the given paths before the GAC. */
......
......@@ -117,6 +117,7 @@ extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDE
typedef struct parsed_config_file
{
struct list supported_runtimes;
LPWSTR private_path;
} parsed_config_file;
typedef struct supported_runtime
......@@ -125,6 +126,8 @@ typedef struct supported_runtime
LPWSTR version;
} supported_runtime;
extern WCHAR **private_path;
extern HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result) DECLSPEC_HIDDEN;
extern HRESULT parse_config_stream(IStream *stream, parsed_config_file *result) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment