mscoree: Invoke installed win32 mono runtime for .NET executables (try 6)

Paul Chitescu paulc at voip.null.ro
Wed Oct 11 09:36:28 CDT 2006


Changelog: mscoree: Invoke installed win32 mono runtime for .NET executables 
with capability to run native runtime or other wrapper.

The controlling Registry key used and default value are:

[HKCU\Software\Wine\mscoree]
"Runtimes"="MONOEMBED"

Creating the key and setting the "Runtimes" value to an empty string will 
disable this feature and render .NET executables unrunable.

The code is inspired by the one in winebrowser.

Several alternatives can be provided in Registry, separated by commas. For 
each an attempt to execute it (spawnvp with OVERLAY flag set) is made. The 
exception is the keyword MONOEMBED that will try to locate and dynamically 
load an installed Win32 mono.

Examples:
"Runtimes"="MONOEMBED,/usr/bin/mono,mono"
"Runtimes"="mono"
"Runtimes"="mono,MONOEMBED"

By default only MONOEMBED is enabled as it seems to provide best compatibility 
and integration with Wine. It requires a proper installation of mono Win32 and 
finds its location from Registry.

This is the 6th version of the patch - some new files were missing in 5.

Paul
-------------- next part --------------
--- ./dlls/mscoree/Makefile.in.orig	2006-10-06 21:38:15.000000000 +0300
+++ ./dlls/mscoree/Makefile.in	2006-10-09 21:41:26.000000000 +0300
@@ -3,10 +3,11 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = mscoree.dll
-IMPORTS   = kernel32
+IMPORTS   = kernel32 advapi32
 
 C_SRCS = \
-	mscoree_main.c
+	mscoree_main.c \
+	mscoree_mono.c
 
 @MAKE_DLL_RULES@
 
--- ./dlls/mscoree/mscoree_main.c.orig	2006-10-06 21:38:15.000000000 +0300
+++ ./dlls/mscoree/mscoree_main.c	2006-10-11 17:20:28.000000000 +0300
@@ -19,15 +19,93 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <stdarg.h>
+#include "config.h"
+#include "wine/port.h"
+#include "wine/library.h"
+#include "wine/debug.h"
 
 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
 
-#include "wine/debug.h"
+#include <stdarg.h>
+#include <errno.h>
+
+#include "mscoree_priv.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
 
+/* By default only try win32 embedded mono */
+static const char defaultRuntimes[] = "MONOEMBED";
+
+static int runMain()
+{
+    char runtimes[256];
+    char* item;
+    int argc, rval, i;
+    const char* *argv;
+    DWORD length;
+    HKEY key = 0;
+
+    /* this code is adapted from winebrowser */
+    length = sizeof(runtimes);
+    /* @@ Wine registry key: HKCU\Software\Wine\mscoree */
+    if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Wine\\mscoree", 0, KEY_READ, &key) != ERROR_SUCCESS)
+	strcpy(runtimes,defaultRuntimes);
+    else
+    {
+	DWORD type = 0;
+	if (RegQueryValueExA(key, "Runtimes", 0, &type, (LPBYTE)runtimes, &length) != ERROR_SUCCESS)
+	    strcpy(runtimes,defaultRuntimes);
+	RegCloseKey(key);
+    }
+    if (!runtimes[0])
+    {
+	WARN("Runtimes are disabled from Registry.\n");
+	return ENOSYS;
+    }
+    /* allocate an array with space for one extra argument */
+    argc = __wine_main_argc+1;
+    argv = (const char**)HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(char*));
+    if (!argv)
+    {
+	ERR("Could not allocate memory!\n");
+	return ENOMEM;
+    }
+    for (i = 0; i < argc; i++)
+	argv[i+1] = __wine_main_argv[i];
+    argv[argc] = NULL;
+    rval = -1;
+    for (item = strtok(runtimes, ","); item; item = strtok(NULL, ","))
+    {
+	if (!item[0])
+	    continue;
+	TRACE("Attempting to use: %s\n", debugstr_a(item));
+	argv[0] = NULL;
+	if (strcmp(item, "MONOEMBED") == 0)
+	{
+	    /* try to call win32 mono runtime */
+	    rval = MONO_CorExeMain(argc, argv);
+	    if (rval >= 0)
+		break;
+	}
+	else
+	{
+	    argv[0] = item;
+	    spawnvp(_P_OVERLAY, item, argv);
+	    /* if we reach this point exec() failed */
+	    rval = -1;
+	}
+    }
+    HeapFree(GetProcessHeap(), 0, argv);
+    if (rval < 0)
+    {
+	ERR("No suitable runtime could be started.\n");
+	rval = ENOSYS;
+    }
+    return rval;
+}
+
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
     TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
@@ -62,14 +140,13 @@
 
 int WINAPI _CorExeMain(void)
 {
-    FIXME("Directly running .NET applications not supported.\n");
-    return -1;
+    TRACE("\n");
+    return runMain();
 }
 
 int WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPCWSTR imageName, LPCWSTR loaderName, LPCWSTR cmdLine)
 {
-    TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
-    FIXME("Directly running .NET applications not supported.\n");
+    FIXME("(%p, %u, %s, %s, %s): stub\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
     return -1;
 }
 
--- ./dlls/mscoree/mscoree_priv.h.orig	2006-10-11 17:32:56.000000000 +0300
+++ ./dlls/mscoree/mscoree_priv.h	2006-10-11 17:32:56.000000000 +0300
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2006 Paul Chitescu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int MONO_CorExeMain(int argc,const char* argv[]);
--- ./dlls/mscoree/mscoree_mono.c.orig	2006-10-11 17:33:06.000000000 +0300
+++ ./dlls/mscoree/mscoree_mono.c	2006-10-11 17:33:06.000000000 +0300
@@ -0,0 +1,161 @@
+/*
+ * Embed installed win32 mono for .NET applications
+ * Copyright 2006 Paul Chitescu
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+#include "wine/library.h"
+#include "wine/debug.h"
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+
+#include <stdarg.h>
+
+#include "mscoree_priv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+typedef void (*MonoDirs)(const char*,const char*);
+typedef int (*MonoMain)(int,char*[]);
+
+static const char* monoKey(void)
+{
+    static char buffer[256] = "Software\\Novell\\Mono";
+    static int init = 0;
+    HKEY key = 0;
+    if (init)
+	return buffer[0] ? buffer : NULL;
+    init = 1;
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, buffer, 0, KEY_READ, &key) == ERROR_SUCCESS)
+    {
+	DWORD type = 0;
+	int pos = lstrlenA(buffer);
+	DWORD length = sizeof(buffer) - pos - 2;
+	if (RegQueryValueExA(key, "DefaultCLR", 0, &type,
+			     (LPBYTE)(buffer + pos + 1), &length) == ERROR_SUCCESS)
+	    buffer[pos] = '\\';
+	else
+	    buffer[0] = '\0';		
+	RegCloseKey(key);
+    }
+    else
+	buffer[0] = '\0';
+    TRACE("Mono registry path: %s\n", debugstr_a(buffer));
+    return buffer[0] ? buffer : NULL;
+}
+
+int MONO_CorExeMain(int argc,const char* argv[])
+{
+    HINSTANCE lib;
+    int rval = -1;
+    HKEY key = 0;
+    DWORD type = 0;
+
+    char buf1[MAX_PATH], buf2[MAX_PATH];
+    char* p = 0;
+    DWORD length = sizeof(buf1) - 1 - 16;
+
+    const char* keyName = monoKey();
+    if (!keyName)
+	return -1;
+    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key) != ERROR_SUCCESS)
+	return -1;
+    if (RegQueryValueExA(key, "FrameworkAssemblyDirectory", 0, &type,
+			 (LPBYTE)buf1, &length) == ERROR_SUCCESS)
+    {
+	p = strrchr(buf1, '\\');
+	if (!p)
+	    p = strrchr(buf1, '/');
+	if (p) {
+	    const char binPath[] = "\\bin";
+	    strcpy(p, binPath);
+	    /* leave p pointing at the terminating NULL */ 
+	    p += lstrlenA(binPath);
+	}
+    }
+    if (!p)
+    {
+	RegCloseKey(key);
+	return -1;
+    }
+
+    TRACE("Mono lib directory: %s\n", debugstr_a(buf1));
+    /* remember current directory to set it back */
+    length = sizeof(buf2);
+    if (GetCurrentDirectoryA(length, buf2) >= length)
+    {
+	RegCloseKey(key);
+	return -1;
+    }
+    /* set current directory so we can find mono's DLLs */
+    SetCurrentDirectoryA(buf1);
+    strcpy(p, "\\mono.dll");
+    lib = LoadLibraryA(buf1);
+    if (!lib)
+    {
+	strcpy(p, "\\mono-1.dll");
+	lib = LoadLibraryA(buf1);
+    }
+    if (!lib)
+    {
+	strcpy(p, "\\mono-2.dll");
+	lib = LoadLibraryA(buf1);
+    }
+    /* and change it back after we eventually loaded them */
+    SetCurrentDirectoryA(buf2);
+    if (lib)
+    {
+	MonoDirs monoDirs = (MonoDirs)GetProcAddress(lib, "mono_set_dirs");
+	MonoMain monoMain = (MonoMain)GetProcAddress(lib, "mono_main");
+	if (monoDirs && monoMain)
+	{
+	    TRACE("Using runtime: %s\n", debugstr_a(buf1));
+	    length = sizeof(buf1) - 1;
+	    if (RegQueryValueExA(key, "FrameworkAssemblyDirectory", 0, &type,
+				 (LPBYTE)buf1, &length) != ERROR_SUCCESS)
+		buf1[0] = '\0';
+	    length = sizeof(buf2) - 1;
+	    if (RegQueryValueExA(key, "MonoConfigDir", 0, &type,
+				 (LPBYTE)buf2, &length) != ERROR_SUCCESS)
+		buf2[0] = '\0';
+	    RegCloseKey(key);
+	    if (buf1[0] && buf2[0])
+	    {
+		TRACE("Calling mono with lib=%s cfg=%s\n",
+		      debugstr_a(buf1), debugstr_a(buf2));
+		argv[0] = argv[1];
+		monoDirs(buf1, buf2);
+		rval = monoMain(argc, (char**)argv);
+	    }
+	    else
+		ERR("Mono configuration is incomplete!\n");
+	}
+	else
+	{
+	    ERR("Could not locate mono entry points in %s\n", debugstr_a(buf1));
+	    RegCloseKey(key);
+	}
+	FreeLibrary(lib);
+    }
+    else
+	RegCloseKey(key);
+
+    return rval;
+}


More information about the wine-patches mailing list