Signed-off-by: Gijs Vermeulen <gijsvrm(a)codeweavers.com>
---
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