From: Gijs Vermeulen Subject: [PATCH] mscoree: Support loading assemblies from path specified in config file. Message-Id: <20191017201232.2012-1-gijsvrm@codeweavers.com> Date: Thu, 17 Oct 2019 22:12:32 +0200 Signed-off-by: Gijs Vermeulen --- dlls/mscoree/config.c | 13 ++++++++-- dlls/mscoree/corruntimehost.c | 45 ++++++++++++++++++++++++++-------- dlls/mscoree/metahost.c | 38 +++++++++++++++++++++++++++- dlls/mscoree/mscoree_private.h | 3 +++ 4 files changed, 86 insertions(+), 13 deletions(-) diff --git a/dlls/mscoree/config.c b/dlls/mscoree/config.c index f2abf107a5..035247442c 100644 --- a/dlls/mscoree/config.c +++ b/dlls/mscoree/config.c @@ -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); } diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c index 2ccc7bc4f5..e932a7f58b 100644 --- a/dlls/mscoree/corruntimehost.c +++ b/dlls/mscoree/corruntimehost.c @@ -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)) { diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c index f87737cd83..18232a4568 100644 --- a/dlls/mscoree/metahost.c +++ b/dlls/mscoree/metahost.c @@ -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. */ diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h index db18aff3eb..2b9c1dd35e 100644 --- a/dlls/mscoree/mscoree_private.h +++ b/dlls/mscoree/mscoree_private.h @@ -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; -- 2.23.0