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

Gijs Vermeulen gijsvrm at codeweavers.com
Thu Oct 17 15:12:32 CDT 2019


Signed-off-by: Gijs Vermeulen <gijsvrm at 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




More information about the wine-devel mailing list