Hi,

Attached the updated patch.

I realized that mono_marshal_get_vtfixup_ftnptr was broken and I reimplemented it without using mono_marshal_get_managed_wrapper.

I also have done some modifications to gc.c.

There is a comment in the patch /* FIXME: do we need this? (image is disposed anyway) */ about some code I think should be removed because it's unneeded. Is that code required?

Kornél

Thank you very much for the review and your comments.

From: Zoltan Varga
To: Kornél Pál
Cc: mono-devel
Sent: Friday, April 25, 2008 4:45 PM
Subject: Re: [Mono-dev] [PATCH] Add mixed-mode assembly support on Windows (now build with cygwin as well)


- appdomain.h: This is a public header file, so the new functions
  should go somewhere
  else, like domain-internals.h
- domain.c: The code here could be put into a function in corree.c.
- Put mono_module_handle and coree_handle into some header file like
  coree.h, and
  there definitons into corree.c for example.

- corree.h: Please include <config.h>, since that contains the
  definition of PLATFORM_WIN32.

OK.

- image.c: mono_cli_rva_image_map is part of our public api, so its signature cannot be changed, you can rename it to mono_cli_rva_image_map_internal, and
  change the signature of that.

I had a look at "C:\Program Files\Mono\include" and it doesn't contain any declaration. Is this public for sure? If it is I'll do what you suggested.

- The usage of 'raw_data' is a bit confusing: sometimes it is used as an address (like in mono_cli_rva_image_map), sometimes it is used as a handle (everywhere
  else). Which is correct ?

HMODULE is the actual pointer to the base address (position of the DOS header) of the module. Also note that there is no such thing as HINSTANCE it is a heritage of the Win16 shared address space and HMODULE and HINSTANCE are the same in Win32. In Win32s (Win32 API on Win16 that is not really Win32 compatible) HMODULE is definitely not the base address but someting else that may be a handle. So raw_data is actually the raw_data but unlike the current implementation sections are mapped to the actual virtual addresses. Even checks in map functions could be omitted but I didn't remove them to ensure that the image is correct.

- cil-coff.h: Please don't declare constants in the middle of a a
  structure definition.

OK. I actually tried to follow what seemed to me being the coding convention of that file.

- gc.c: The comment about mono_thread_attach () might be incorrect, but the
  thread_started_event stuff is definitely needed to avoid races when
  the runtime is
  shut down before the finalizer thread can start. So I don't think we
  can remove this.

As I see there can be no race because there only are "mono_thread_current () == gc_thread" checks. Even if "mono_thread_current ()" returns NULL (that is unlikely I think) nothing will happen on the thread if the finalizer thread in not initialized yet. Actual work is only done by "finalizer_thread" that is being executed only in the finalizer thread. If for some reason "mono_gc_cleanup ()" is called before the finalizer thread is initialized "WaitForSingleObjectEx" will wait for two seconds for the finalizers and thus for the finalizer thread being initialized. If it fails to initialize within two seconds finalizers won't run of course but the same is true for finalizers that werent processed in two seconds so I see no big difference. If really need "WaitForSingleObjectEx (thread_started_event, INFINITE, FALSE);" can be moved just before "WaitForSingleObjectEx (shutdown_event, 2000, FALSE)" but I don't see any reason to do so. If I'm wrong please let me know.

Kornél
Index: mono/libgc/win32_threads.c
===================================================================
--- mono/libgc/win32_threads.c  (revision 101236)
+++ mono/libgc/win32_threads.c  (working copy)
@@ -782,7 +782,7 @@
 * Pontus Rydin suggests wrapping the thread start routine instead.
 */
#if defined(GC_DLL) || defined(GC_INSIDE_DLL)
-BOOL WINAPI DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
+BOOL WINAPI GC_DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved)
{
  switch (reason) {
  case DLL_PROCESS_ATTACH:
Index: mono/libgc/include/gc.h
===================================================================
--- mono/libgc/include/gc.h     (revision 101236)
+++ mono/libgc/include/gc.h     (working copy)
@@ -922,6 +922,8 @@
#if defined(GC_WIN32_THREADS) && !defined(__CYGWIN32__) && !defined(__CYGWIN__)
# include <windows.h>

+   BOOL WINAPI GC_DllMain(HINSTANCE inst, ULONG reason, LPVOID reserved);
+
  /*
   * All threads must be created using GC_CreateThread, so that they will be
   * recorded in the thread table.  For backwards compatibility, this is not
Index: mono/mono/metadata/loader.c
===================================================================
--- mono/mono/metadata/loader.c (revision 101236)
+++ mono/mono/metadata/loader.c (working copy)
@@ -1394,12 +1394,20 @@
        if (cols [1] & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
                if (result->klass == mono_defaults.string_class && !strcmp (result->name, 
".ctor"))
                        result->string_ctor = 1;
-       } else if ((cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (!(cols [1] & 
METHOD_IMPL_ATTRIBUTE_NATIVE))) {
+       } else if (cols [2] & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)result;
-               MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];

+#ifdef PLATFORM_WIN32
+               /* IJW is P/Invoke with a predefined function pointer */
+               if (image->is_module_handle && (cols [1] & 
METHOD_IMPL_ATTRIBUTE_NATIVE)) {
+                       piinfo->addr = mono_image_rva_map (image, cols [0]);
+                       g_assert (piinfo->addr);
+               }
+#endif
                piinfo->implmap_idx = mono_metadata_implmap_from_method (image, 
idx - 1);
-               piinfo->piflags = mono_metadata_decode_row_col (im, 
piinfo->implmap_idx - 1, MONO_IMPLMAP_FLAGS);
+               /* native methods can have no map */
+               if (piinfo->implmap_idx)
+                       piinfo->piflags = mono_metadata_decode_row_col (&tables 
[MONO_TABLE_IMPLMAP], piinfo->implmap_idx - 1, MONO_IMPLMAP_FLAGS);
        }

        /* FIXME: lazyness for generics too, but how? */
@@ -1900,7 +1908,7 @@

        if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
                m->signature->pinvoke = 1;
-       else if ((m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (!(m->iflags & 
METHOD_IMPL_ATTRIBUTE_NATIVE))) {
+       else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                MonoCallConvention conv = 0;
                MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)m;
                m->signature->pinvoke = 1;
Index: mono/mono/metadata/domain.c
===================================================================
--- mono/mono/metadata/domain.c (revision 101236)
+++ mono/mono/metadata/domain.c (working copy)
@@ -34,6 +34,7 @@
#include <mono/metadata/threads-types.h>
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
+#include <mono/metadata/coree.h>

/* #define DEBUG_DOMAIN_UNLOAD */

@@ -1160,6 +1161,10 @@
        if (domain)
                g_assert_not_reached ();

+#if defined(PLATFORM_WIN32) && !defined(_WIN64)
+       mono_fixup_coree ();
+#endif
+
        mono_perfcounters_init ();

        mono_counters_register ("Max native code in a domain", 
MONO_COUNTER_INT|MONO_COUNTER_JIT, &max_domain_code_size);
@@ -1196,6 +1201,9 @@
                 * exe_image, and close it during shutdown.
                 */
                get_runtimes_from_exe (exe_filename, &exe_image, runtimes);
+#ifdef PLATFORM_WIN32
+               mono_fixup_exe_image (exe_image);
+#endif
        } else if (runtime_version != NULL) {
                runtimes [0] = get_runtime_by_version (runtime_version);
                runtimes [1] = NULL;
Index: mono/mono/metadata/appdomain.c
===================================================================
--- mono/mono/metadata/appdomain.c      (revision 101236)
+++ mono/mono/metadata/appdomain.c      (working copy)
@@ -92,6 +92,21 @@
static void
mono_domain_unload (MonoDomain *domain);

+static MonoLoadFunc load_function = NULL;
+
+void
+mono_install_runtime_load (MonoLoadFunc func)
+{
+       load_function = func;
+}
+
+MonoDomain*
+mono_runtime_load (const char *filename, const char *runtime_version)
+{
+       g_assert (load_function);
+       return load_function (filename, runtime_version);
+}
+
/**
 * mono_runtime_init:
 * @domain: domain returned by mono_init ()
Index: mono/mono/metadata/assembly.c
===================================================================
--- mono/mono/metadata/assembly.c       (revision 101236)
+++ mono/mono/metadata/assembly.c       (working copy)
@@ -31,6 +31,7 @@
#include <mono/utils/mono-digest.h>
#include <mono/utils/mono-logger.h>
#include <mono/metadata/reflection.h>
+#include <mono/metadata/coree.h>

#ifndef PLATFORM_WIN32
#include <sys/types.h>
@@ -581,7 +582,7 @@
        gunichar2 moddir [MAXPATHLEN];
        gchar *bindir, *installdir, *root, *utf8name, *config;

-       GetModuleFileNameW (NULL, moddir, MAXPATHLEN);
+       GetModuleFileNameW (mono_module_handle, moddir, MAXPATHLEN);
        utf8name = g_utf16_to_utf8 (moddir, -1, NULL, NULL, NULL);
        bindir = g_path_get_dirname (utf8name);
        installdir = g_path_get_dirname (bindir);
@@ -1477,6 +1478,10 @@
        loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
        if (mono_defaults.internals_visible_class)
                mono_assembly_load_friends (ass);
+#ifdef PLATFORM_WIN32
+       if (image->is_module_handle)
+               mono_image_fixup_vtable (image);
+#endif
        mono_assemblies_unlock ();

        mono_assembly_invoke_load_hook (ass);
Index: mono/mono/metadata/image.c
===================================================================
--- mono/mono/metadata/image.c  (revision 101236)
+++ mono/mono/metadata/image.c  (working copy)
@@ -24,6 +24,7 @@
#include "metadata-internals.h"
#include "profiler-private.h"
#include "loader.h"
+#include "coree.h"
#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-logger.h>
#include <mono/utils/mono-path.h>
@@ -51,9 +52,11 @@
#define mono_images_unlock() LeaveCriticalSection (&images_mutex)
static CRITICAL_SECTION images_mutex;

+/* returns offset relative to image->raw_data */
guint32
-mono_cli_rva_image_map (MonoCLIImageInfo *iinfo, guint32 addr)
+mono_cli_rva_image_map (MonoImage *image, guint32 addr)
{
+       MonoCLIImageInfo *iinfo = image->image_info;
        const int top = iinfo->cli_section_count;
        MonoSectionTable *tables = iinfo->cli_section_tables;
        int i;
@@ -61,6 +64,10 @@
        for (i = 0; i < top; i++){
                if ((addr >= tables->st_virtual_address) &&
                    (addr < tables->st_virtual_address + 
tables->st_raw_data_size)){
+#ifdef PLATFORM_WIN32
+                       if (image->is_module_handle)
+                               return addr;
+#endif
                        return addr - tables->st_virtual_address + 
tables->st_raw_data_ptr;
                }
                tables++;
@@ -94,6 +101,10 @@
                                if (!mono_image_ensure_section_idx (image, i))
                                        return NULL;
                        }
+#ifdef PLATFORM_WIN32
+                       if (image->is_module_handle)
+                               return image->raw_data + addr;
+#endif
                        return (char*)iinfo->cli_sections [i] +
                                (addr - tables->st_virtual_address);
                }
@@ -160,6 +171,11 @@

        if (sect->st_raw_data_ptr + sect->st_raw_data_size > 
image->raw_data_len)
                return FALSE;
+#ifdef PLATFORM_WIN32
+       if (image->is_module_handle)
+               iinfo->cli_sections [section] = image->raw_data + 
sect->st_virtual_address;
+       else
+#endif
        /* FIXME: we ignore the writable flag since we don't patch the binary */
        iinfo->cli_sections [section] = image->raw_data + sect->st_raw_data_ptr;
        return TRUE;
@@ -230,7 +246,7 @@
{
        guint32 offset;
        
-       offset = mono_cli_rva_image_map (iinfo, 
iinfo->cli_header.datadir.pe_cli_header.rva);
+       offset = mono_cli_rva_image_map (image, 
iinfo->cli_header.datadir.pe_cli_header.rva);
        if (offset == INVALID_ADDRESS)
                return FALSE;

@@ -298,7 +314,7 @@
        guint32 pad;
        char *ptr;
        
-       offset = mono_cli_rva_image_map (iinfo, 
iinfo->cli_cli_header.ch_metadata.rva);
+       offset = mono_cli_rva_image_map (image, 
iinfo->cli_cli_header.ch_metadata.rva);
        if (offset == INVALID_ADDRESS)
                return FALSE;

@@ -546,6 +562,10 @@
                        if (image->modules [idx - 1]) {
                                mono_image_addref (image->modules [idx - 1]);
                                image->modules [idx - 1]->assembly = 
image->assembly;
+#ifdef PLATFORM_WIN32
+                               if (image->modules [idx - 1]->is_module_handle)
+                                       mono_image_fixup_vtable (image->modules 
[idx - 1]);
+#endif
                                /* g_print ("loaded module %s from %s (%p)\n", 
module_ref, image->name, image->assembly); */
                        }
                        g_free (module_ref);
@@ -642,6 +662,9 @@
{
        MonoDotNetHeader64 header64;

+#ifdef PLATFORM_WIN32
+       if (!image->is_module_handle)
+#endif
        if (offset + sizeof (MonoDotNetHeader32) > image->raw_data_len)
                return -1;

@@ -760,6 +783,11 @@
        SWAPPDE (header->datadir.pe_cli_header);
        SWAPPDE (header->datadir.pe_reserved);

+#ifdef PLATFORM_WIN32
+       if (image->is_module_handle)
+               image->raw_data_len = header->nt.pe_image_size;
+#endif
+
        return offset;
}

@@ -782,6 +810,9 @@
        if (status)
                *status = MONO_IMAGE_IMAGE_INVALID;

+#ifdef PLATFORM_WIN32
+       if (!image->is_module_handle)
+#endif
        if (offset + sizeof (msdos) > image->raw_data_len)
                goto invalid_image;
        memcpy (&msdos, image->raw_data + offset, sizeof (msdos));
@@ -995,6 +1026,16 @@
                g_hash_table_insert (loaded_images, (char *) 
image->assembly_name, image);   
        mono_images_unlock ();

+#ifdef PLATFORM_WIN32
+       if (image->is_module_handle && image->raw_data) {
+               guint16* fname_utf16;
+
+               fname_utf16 = g_utf8_to_utf16 (image->name, -1, NULL, NULL, 
NULL);
+               LoadLibrary (fname_utf16);
+               g_free (fname_utf16);
+       }
+#endif
+
        return image;
}

@@ -1072,6 +1113,38 @@
        }
        mono_images_unlock ();

+#ifdef PLATFORM_WIN32
+       /* Load modules using LoadLibrary */
+       if (!refonly && coree_module_handle) {
+               MonoCLIImageInfo *iinfo;
+               HMODULE module_handle;
+               guint16* fname_utf16;
+
+               fname_utf16 = g_utf8_to_utf16 (fname, -1, NULL, NULL, NULL);
+               module_handle = LoadLibrary (fname_utf16);
+               g_free (fname_utf16);
+
+               if (module_handle == NULL) {
+                       if (status)
+                               *status = MONO_IMAGE_ERROR_ERRNO;
+                       return NULL;
+               }
+
+               image = g_new0 (MonoImage, 1);
+               image->raw_data = (char*) module_handle;
+               image->is_module_handle = TRUE;
+               iinfo = g_new0 (MonoCLIImageInfo, 1);
+               image->image_info = iinfo;
+               image->name = mono_path_resolve_symlinks (fname);
+               image->ref_count = 1;
+
+               image = do_mono_image_load (image, status, TRUE);
+               image = register_image (image);
+               FreeLibrary (module_handle);
+               return image;
+       }
+#endif
+
        image = do_mono_image_open (fname, status, TRUE, refonly);
        if (image == NULL)
                return NULL;
@@ -1114,6 +1187,57 @@
        return(do_mono_image_open (fname, status, FALSE, FALSE));
}

+void
+mono_image_fixup_vtable (MonoImage *image)
+{
+#ifdef PLATFORM_WIN32
+       MonoCLIImageInfo *iinfo;
+       MonoPEDirEntry *de;
+       MonoVTableFixup *vtfixup;
+       int count;
+       gpointer slot;
+       guint16 slot_type;
+       int slot_count;
+
+       g_assert (image->is_module_handle);
+
+       iinfo = image->image_info;
+       de = &iinfo->cli_cli_header.ch_vtable_fixups;
+       if (!de->rva || !de->size)
+               return;
+       vtfixup = (MonoVTableFixup*) mono_image_rva_map (image, de->rva);
+       if (!vtfixup)
+               return;
+       
+       count = de->size / sizeof (MonoVTableFixup);
+       while (count--) {
+               if (!vtfixup->rva || !vtfixup->count)
+                       continue;
+
+               slot = mono_image_rva_map (image, vtfixup->rva);
+               g_assert (slot);
+               slot_type = vtfixup->type;
+               slot_count = vtfixup->count;
+               if (slot_type & VTFIXUP_TYPE_32BIT)
+                       while (slot_count--) {
+                               *((guint32*) slot) = 
mono_marshal_get_vtfixup_ftnptr (image, *((guint32*) slot), slot_type);
+                               ((guint32*) slot)++;
+                       }
+               else if (slot_type & VTFIXUP_TYPE_64BIT)
+                       while (slot_count--) {
+                               *((guint64*) slot) = 
mono_marshal_get_vtfixup_ftnptr (image, *((guint64*) slot), slot_type);
+                               ((guint64*) slot)++;
+                       }
+               else
+                       g_assert_not_reached();
+
+               vtfixup++;
+       }
+#else
+       g_assert_not_reached();
+#endif
+}
+
static void
free_hash_table (gpointer key, gpointer val, gpointer user_data)
{
@@ -1218,12 +1342,18 @@

        mono_images_unlock ();

+#ifdef PLATFORM_WIN32
+       if (image->is_module_handle)
+               FreeLibrary ((HMODULE) image->raw_data);
+#endif
+
        if (image->raw_buffer_used) {
                if (image->raw_data != NULL)
                        mono_raw_buffer_free (image->raw_data);
        }
        
        if (image->raw_data_allocated) {
+               /* FIXME: do we need this? (image is disposed anyway) */
                /* image->raw_metadata and cli_sections might lie inside 
image->raw_data */
                MonoCLIImageInfo *ii = image->image_info;

@@ -1607,6 +1737,10 @@
                }

                image->files [fileidx - 1] = res;
+#ifdef PLATFORM_WIN32
+               if (res->is_module_handle)
+                       mono_image_fixup_vtable (res);
+#endif
        }
        mono_loader_unlock ();
        g_free (name);
@@ -1658,25 +1792,12 @@
{
        MonoCLIImageInfo *iinfo = image->image_info;
        MonoPEDirEntry *de = &iinfo->cli_cli_header.ch_strong_name;
-       const int top = iinfo->cli_section_count;
-       MonoSectionTable *tables = iinfo->cli_section_tables;
-       int i;
-       guint32 addr = de->rva;
-       
+
        if (size)
                *size = de->size;
        if (!de->size || !de->rva)
                return 0;
-       for (i = 0; i < top; i++){
-               if ((addr >= tables->st_virtual_address) &&
-                   (addr < tables->st_virtual_address + 
tables->st_raw_data_size)){
-                       return tables->st_raw_data_ptr +
-                               (addr - tables->st_virtual_address);
-               }
-               tables++;
-       }
-
-       return 0;
+       return mono_cli_rva_image_map (image, de->rva);
}

/**
Index: mono/mono/metadata/cil-coff.h
===================================================================
--- mono/mono/metadata/cil-coff.h       (revision 101236)
+++ mono/mono/metadata/cil-coff.h       (working copy)
@@ -246,7 +246,19 @@
        MonoPEDatadir     datadir;
} MonoDotNetHeader64;

+#define VTFIXUP_TYPE_32BIT                            0x01
+#define VTFIXUP_TYPE_64BIT                            0x02
+#define VTFIXUP_TYPE_FROM_UNMANAGED                   0x04
+#define VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN  0x08
+#define VTFIXUP_TYPE_CALL_MOST_DERIVED                0x10
+
typedef struct {
+       guint32 rva;
+       guint16 count;
+       guint16 type;
+} MonoVTableFixup;
+
+typedef struct {
        char    st_name [8];
        guint32 st_virtual_size;
        guint32 st_virtual_address;
@@ -311,6 +323,6 @@
        MonoCLIHeader     cli_cli_header;
} MonoCLIImageInfo;

-guint32       mono_cli_rva_image_map (MonoCLIImageInfo *iinfo, guint32 rva);
+guint32       mono_cli_rva_image_map (MonoImage *image, guint32 rva);

#endif /* __MONO_CIL_COFF_H__ */
Index: mono/mono/metadata/image.h
===================================================================
--- mono/mono/metadata/image.h  (revision 101236)
+++ mono/mono/metadata/image.h  (working copy)
@@ -45,6 +45,7 @@
                                         MonoImageOpenStatus *status);
MonoImage    *mono_image_open_from_data_full (char *data, guint32 data_len, 
gboolean need_copy,
                                         MonoImageOpenStatus *status, gboolean 
refonly);
+void          mono_image_fixup_vtable (MonoImage *image);
MonoImage    *mono_image_loaded   (const char *name);
MonoImage    *mono_image_loaded_full   (const char *name, gboolean refonly);
MonoImage    *mono_image_loaded_by_guid (const char *guid);
Index: mono/mono/metadata/coree.c
===================================================================
--- mono/mono/metadata/coree.c  (revision 0)
+++ mono/mono/metadata/coree.c  (revision 0)
@@ -0,0 +1,413 @@
+/*
+ * coree.c: mscoree.dll functions
+ *
+ * Author:
+ *   Kornel Pal <http://www.kornelpal.hu/>
+ *
+ * Copyright (C) 2008 Kornel Pal
+ */
+
+#include <config.h>
+
+#ifdef PLATFORM_WIN32
+
+#include <string.h>
+#include <glib.h>
+#include <mono/io-layer/io-layer.h>
+#include "metadata-internals.h"
+#include "image.h"
+#include "assembly.h"
+#include "appdomain.h"
+#include "object.h"
+#include "loader.h"
+#include "threads.h"
+#include "environment.h"
+#include "coree.h"
+
+#define STATUS_SUCCESS 0x00000000L
+#define STATUS_INVALID_IMAGE_FORMAT 0xC000007BL
+
+typedef struct _EXPORT_FIXUP
+{
+       LPCSTR Name;
+       DWORD_PTR ProcAddress;
+} EXPORT_FIXUP;
+
+HMODULE mono_module_handle = NULL;
+HMODULE coree_module_handle = NULL;
+
+/* Called by LdrLoadDll of ntdll.dll after _CorValidateImage. */
+BOOL STDMETHODCALLTYPE _CorDllMain(HINSTANCE hInst, DWORD dwReason, LPVOID 
lpReserved)
+{
+       MonoDomain* domain;
+       gunichar2 filename [MAXPATHLEN];
+       gchar* fname_utf8;
+       gchar* error;
+
+       switch (dwReason)
+       {
+       case DLL_PROCESS_ATTACH:
+               DisableThreadLibraryCalls (hInst);
+               if (mono_get_root_domain ())
+                       return TRUE;
+
+               GetModuleFileName (hInst, filename, MAXPATHLEN);
+               fname_utf8 = g_utf16_to_utf8 (filename, -1, NULL, NULL, NULL);
+               domain = mono_runtime_load (fname_utf8, NULL);
+               error = (gchar*) mono_check_corlib_version ();
+               if (error) {
+                       g_free (error);
+                       g_free (fname_utf8);
+                       mono_runtime_quit ();
+                       return FALSE;
+               }
+
+               mono_assembly_open (fname_utf8, NULL);
+               g_free (fname_utf8);
+               break;
+       }
+
+       return TRUE;
+}
+
+/* Called by ntdll.dll reagardless of entry point after _CorValidateImage. */
+__int32 STDMETHODCALLTYPE _CorExeMain()
+{
+       MonoDomain* domain;
+       MonoAssembly* assembly;
+       MonoImage* image;
+       MonoMethod* method;
+       guint32 entry;
+       int argc;
+       gunichar2** argvw;
+       gchar** argv;
+       gchar* fname_utf8;
+       gchar* error;
+       int i;
+
+       argvw = CommandLineToArgvW (GetCommandLine (), &argc);
+       g_assert (argc);
+       fname_utf8 = g_utf16_to_utf8 (argvw [0], -1, NULL, NULL, NULL);
+
+       domain = mono_runtime_load (fname_utf8, NULL);
+
+       error = (gchar*) mono_check_corlib_version ();
+       if (error) {
+               g_free (error);
+               MessageBox (NULL, L"Corlib not in sync with this runtime.", 
NULL, MB_ICONERROR);
+               ExitProcess (1);
+       }
+
+       assembly = mono_assembly_open (fname_utf8, NULL);
+       g_assert (assembly);
+       image = mono_assembly_get_image (assembly);
+
+       entry = mono_image_get_entry_point (image);
+       if (!entry) {
+               MessageBox (NULL, L"Assembly doesn't have an entry point.", 
NULL, MB_ICONERROR);
+               ExitProcess (1);
+       }
+
+       method = mono_get_method (image, entry, NULL);
+       if (method == NULL) {
+               MessageBox (NULL, L"The entry point method could not be 
loaded.", NULL, MB_ICONERROR);
+               ExitProcess (1);
+       }
+
+       argv = g_new0 (gchar*, argc);
+       argv [0] = fname_utf8;
+       for (i = 1; i < argc; ++i)
+               argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
+       LocalFree (argvw);
+
+       mono_runtime_run_main (method, argc, argv, NULL);
+
+       /* Return does not terminate the process. */
+       ExitProcess (mono_environment_exitcode_get ());
+}
+
+/* Called by ntdll.dll before _CorDllMain and _CorExeMain. */
+STDAPI _CorValidateImage(PVOID *ImageBase, LPCWSTR FileName)
+{
+       IMAGE_DOS_HEADER* DosHeader;
+       IMAGE_NT_HEADERS* NtHeaders;
+       DWORD* Address;
+       DWORD dwOldProtect;
+
+       DosHeader = (IMAGE_DOS_HEADER*)*ImageBase;
+       if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+               return STATUS_INVALID_IMAGE_FORMAT;
+
+       NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + 
DosHeader->e_lfanew);
+       if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
+               return STATUS_INVALID_IMAGE_FORMAT;
+
+       if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+               return STATUS_INVALID_IMAGE_FORMAT;
+
+       Address = &NtHeaders->OptionalHeader.AddressOfEntryPoint;
+       if (!VirtualProtect(Address, sizeof(DWORD), PAGE_READWRITE, 
&dwOldProtect))
+               return E_UNEXPECTED;
+       if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
+               *Address = (DWORD)((DWORD_PTR)&_CorDllMain - 
(DWORD_PTR)DosHeader);
+       else
+               *Address = (DWORD)((DWORD_PTR)&_CorExeMain - 
(DWORD_PTR)DosHeader);
+       if (!VirtualProtect(Address, sizeof(DWORD), dwOldProtect, 
&dwOldProtect))
+               return E_UNEXPECTED;
+
+       return STATUS_SUCCESS;
+}
+
+/* Called by ntdll.dll. */
+STDAPI_(VOID) _CorImageUnloading(PVOID ImageBase)
+{
+       /* Nothing to do. */
+}
+
+/* Called by msvcrt.dll when shutting down. */
+void STDMETHODCALLTYPE CorExitProcess(int exitCode)
+{
+       if (!mono_runtime_is_shutting_down ()) {
+               mono_runtime_set_shutting_down ();
+               mono_thread_suspend_all_other_threads ();
+               mono_runtime_quit ();
+       }
+       ExitProcess (exitCode);
+}
+
+/* Fixup exported functions of mscoree.dll to our implementations. */
+STDAPI MonoFixupCorEE(HMODULE hModule)
+{
+       /* Has to be binary ordered. */
+       const EXPORT_FIXUP ExportFixups[] = {
+               {"CorExitProcess", (DWORD_PTR)&CorExitProcess},
+               {"_CorDllMain", (DWORD_PTR)&_CorDllMain},
+               {"_CorExeMain", (DWORD_PTR)&_CorExeMain},
+               {"_CorImageUnloading", (DWORD_PTR)&_CorImageUnloading},
+               {"_CorValidateImage", (DWORD_PTR)&_CorValidateImage},
+               {NULL, 0}
+       };
+
+       IMAGE_DOS_HEADER* DosHeader;
+       IMAGE_NT_HEADERS* NtHeaders;
+       IMAGE_DATA_DIRECTORY* ExportDataDir;
+       IMAGE_EXPORT_DIRECTORY* ExportDir;
+       DWORD* Functions;
+       DWORD* Names;
+       WORD* NameOrdinals;
+       EXPORT_FIXUP* ExportFixup;
+       DWORD* Address;
+       DWORD dwOldProtect;
+       DWORD_PTR ProcAddress;
+       DWORD i;
+
+       DosHeader = (IMAGE_DOS_HEADER*)hModule;
+       if (DosHeader == NULL || DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+               return E_INVALIDARG;
+
+       NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + 
DosHeader->e_lfanew);
+       if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
+               return E_INVALIDARG;
+
+       if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+               return E_INVALIDARG;
+
+       if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes <= 
IMAGE_DIRECTORY_ENTRY_EXPORT)
+               return E_FAIL;
+       ExportDataDir = 
&NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
+       if (!ExportDataDir->VirtualAddress || !ExportDataDir->Size)
+               return E_FAIL;
+
+       ExportDir = (IMAGE_EXPORT_DIRECTORY*)((DWORD_PTR)DosHeader + 
ExportDataDir->VirtualAddress);
+       Functions = (DWORD*)((DWORD_PTR)DosHeader + 
ExportDir->AddressOfFunctions);
+       Names = (DWORD*)((DWORD_PTR)DosHeader + ExportDir->AddressOfNames);
+       NameOrdinals = (WORD*)((DWORD_PTR)DosHeader + 
ExportDir->AddressOfNameOrdinals);
+       ExportFixup = (EXPORT_FIXUP*)&ExportFixups;
+
+       for (i = 0; i < ExportDir->NumberOfNames; i++)
+       {
+               int cmp = strcmp((LPCSTR)((DWORD_PTR)DosHeader + Names[i]), 
ExportFixup->Name);
+               if (cmp > 0)
+                       return E_FAIL;
+               if (cmp == 0)
+               {
+                       Address = &Functions[NameOrdinals[i]];
+                       ProcAddress = (DWORD_PTR)DosHeader + *Address;
+                       if (ProcAddress != ExportFixup->ProcAddress) {
+                               if (!VirtualProtect(Address, sizeof(DWORD), 
PAGE_READWRITE, &dwOldProtect))
+                                       return E_UNEXPECTED;
+                               *Address = (DWORD)(ExportFixup->ProcAddress - 
(DWORD_PTR)DosHeader);
+                               if (!VirtualProtect(Address, sizeof(DWORD), 
dwOldProtect, &dwOldProtect))
+                                       return E_UNEXPECTED;
+                       }
+                       ExportFixup++;
+                       if (ExportFixup->Name == NULL)
+                               return NOERROR;
+               }
+       }
+       return E_FAIL;
+}
+
+/* Executable images are only mapped by the OS loader. We need to do fixups 
for native code support. */
+STDAPI MonoFixupExe(HMODULE hModule)
+{
+       IMAGE_DOS_HEADER* DosHeader;
+       IMAGE_NT_HEADERS* NtHeaders;
+       DWORD_PTR* Address;
+       DWORD dwOldProtect;
+       DWORD_PTR BaseDiff;
+
+       DosHeader = (IMAGE_DOS_HEADER*)hModule;
+       if (DosHeader == NULL || DosHeader->e_magic != IMAGE_DOS_SIGNATURE)
+               return E_INVALIDARG;
+
+       NtHeaders = (IMAGE_NT_HEADERS*)((DWORD_PTR)DosHeader + 
DosHeader->e_lfanew);
+       if (NtHeaders->Signature != IMAGE_NT_SIGNATURE)
+               return E_INVALIDARG;
+
+       if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC)
+               return E_INVALIDARG;
+
+       if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL)
+               return NOERROR;
+
+       BaseDiff = (DWORD_PTR)DosHeader - NtHeaders->OptionalHeader.ImageBase;
+       if (BaseDiff != 0)
+       {
+               if (NtHeaders->FileHeader.Characteristics & 
IMAGE_FILE_RELOCS_STRIPPED)
+                       return E_FAIL;
+
+               Address = &NtHeaders->OptionalHeader.ImageBase;
+               if (!VirtualProtect(Address, sizeof(DWORD_PTR), PAGE_READWRITE, 
&dwOldProtect))
+                       return E_UNEXPECTED;
+               *Address = (DWORD_PTR)DosHeader;
+               if (!VirtualProtect(Address, sizeof(DWORD_PTR), dwOldProtect, 
&dwOldProtect))
+                       return E_UNEXPECTED;
+
+               if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > 
IMAGE_DIRECTORY_ENTRY_BASERELOC)
+               {
+                       IMAGE_DATA_DIRECTORY* BaseRelocDir;
+                       IMAGE_BASE_RELOCATION* BaseReloc;
+                       USHORT* RelocBlock;
+                       ULONG BaseRelocSize;
+                       ULONG RelocBlockSize;
+                       USHORT RelocOffset;
+                       DWORD_PTR UNALIGNED *RelocFixup;
+
+                       BaseRelocDir = 
&NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
+                       if (BaseRelocDir->VirtualAddress && BaseRelocDir->Size)
+                       {
+                               BaseReloc = 
(IMAGE_BASE_RELOCATION*)((DWORD_PTR)DosHeader + BaseRelocDir->VirtualAddress);
+                               BaseRelocSize = BaseRelocDir->Size;
+
+                               while (BaseRelocSize)
+                               {
+                                       RelocBlockSize = BaseReloc->SizeOfBlock;
+
+                                       if (!RelocBlockSize || BaseRelocSize < 
RelocBlockSize)
+                                               return E_FAIL;
+
+                                       BaseRelocSize -= RelocBlockSize;
+                                       RelocBlock = 
(USHORT*)((DWORD_PTR)BaseReloc + IMAGE_SIZEOF_BASE_RELOCATION);
+                                       RelocBlockSize -= 
IMAGE_SIZEOF_BASE_RELOCATION;
+                                       RelocBlockSize /= sizeof(USHORT);
+
+                                       while (RelocBlockSize-- != 0)
+                                       {
+                                               RelocOffset = *RelocBlock & 
(USHORT)0x0fff;
+                                               RelocFixup = 
(DWORD_PTR*)((DWORD_PTR)DosHeader + BaseReloc->VirtualAddress + RelocOffset);
+
+                                               switch (*RelocBlock >> 12)
+                                               {
+                                                       case 
IMAGE_REL_BASED_ABSOLUTE:
+                                                               break;
+
+#ifdef _WIN64
+                                                       case 
IMAGE_REL_BASED_DIR64:
+#else
+                                                       case 
IMAGE_REL_BASED_HIGHLOW:
+#endif
+                                                               if 
(!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), PAGE_EXECUTE_READWRITE, 
&dwOldProtect))
+                                                                       return 
E_UNEXPECTED;
+                                                               *RelocFixup += 
BaseDiff;
+                                                               if 
(!VirtualProtect(RelocFixup, sizeof(DWORD_PTR), dwOldProtect, &dwOldProtect))
+                                                                       return 
E_UNEXPECTED;
+                                                               break;
+
+                                                       default:
+                                                               return E_FAIL;
+                                               }
+
+                                               RelocBlock++;
+                                       }
+                                       BaseReloc = 
(IMAGE_BASE_RELOCATION*)RelocBlock;
+                               }
+                       }
+               }
+       }
+
+       if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes > 
IMAGE_DIRECTORY_ENTRY_IMPORT)
+       {
+               IMAGE_DATA_DIRECTORY* ImportDir;
+               IMAGE_IMPORT_DESCRIPTOR* ImportDesc;
+               HMODULE hImportModule;
+               IMAGE_THUNK_DATA* ImportThunkData;
+               DWORD_PTR ProcAddress;
+
+               ImportDir = 
&NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
+               if (ImportDir->VirtualAddress != 0)
+               {
+                       ImportDesc = 
(IMAGE_IMPORT_DESCRIPTOR*)((DWORD_PTR)DosHeader + ImportDir->VirtualAddress);
+                       while (ImportDesc->Name && 
ImportDesc->OriginalFirstThunk)
+                       {
+                               hImportModule = 
LoadLibraryA((PCSTR)((DWORD_PTR)DosHeader + ImportDesc->Name));
+                               if (hImportModule == NULL)
+                                       return E_FAIL;
+
+                               ImportThunkData = 
(IMAGE_THUNK_DATA*)((DWORD_PTR)DosHeader + ImportDesc->OriginalFirstThunk);
+                               while (ImportThunkData->u1.Ordinal != 0)
+                               {
+                                       if 
(IMAGE_SNAP_BY_ORDINAL(ImportThunkData->u1.Ordinal))
+                                               ProcAddress = 
(DWORD_PTR)GetProcAddress(hImportModule, 
(LPCSTR)IMAGE_ORDINAL(ImportThunkData->u1.Ordinal));
+                                       else
+                                       {
+                                               IMAGE_IMPORT_BY_NAME* ImportByName 
= (IMAGE_IMPORT_BY_NAME*)((DWORD_PTR)DosHeader + 
ImportThunkData->u1.AddressOfData);
+                                               ProcAddress = 
(DWORD_PTR)GetProcAddress(hImportModule, ImportByName->Name);
+                                       }
+                                       if (ProcAddress == 0)
+                                               return E_FAIL;
+                                       Address = 
(DWORD_PTR*)((DWORD_PTR)ImportThunkData - ImportDesc->OriginalFirstThunk + 
ImportDesc->FirstThunk);
+                                       if (!VirtualProtect(Address, 
sizeof(DWORD_PTR), PAGE_READWRITE, &dwOldProtect))
+                                               return E_UNEXPECTED;
+                                       *Address = ProcAddress;
+                                       if (!VirtualProtect(Address, 
sizeof(DWORD_PTR), dwOldProtect, &dwOldProtect))
+                                               return E_UNEXPECTED;
+                                       ImportThunkData++;
+                               }
+
+                               ImportDesc++;
+                       }
+               }
+       }
+
+       return NOERROR;
+}
+
+void
+mono_fixup_coree ()
+{
+       coree_module_handle = LoadLibrary (L"mscoree.dll");
+       if (coree_module_handle && !SUCCEEDED (MonoFixupCorEE 
(coree_module_handle))) {
+               FreeLibrary (coree_module_handle);
+               coree_module_handle = NULL;
+       }
+}
+
+void
+mono_fixup_exe_image (MonoImage* image)
+{
+       if (image && image->is_module_handle && (HMODULE) image->raw_data != 
GetModuleHandle (NULL))
+               MonoFixupExe ((HMODULE) image->raw_data);
+}
+
+#endif /* PLATFORM_WIN32 */

Property changes on: mono\mono\metadata\coree.c
___________________________________________________________________
Name: svn:eol-style
  + native

Index: mono/mono/metadata/coree.h
===================================================================
--- mono/mono/metadata/coree.h  (revision 0)
+++ mono/mono/metadata/coree.h  (revision 0)
@@ -0,0 +1,28 @@
+/*
+ * coree.h: mscoree.dll functions
+ *
+ * Author:
+ *   Kornel Pal <http://www.kornelpal.hu/>
+ *
+ * Copyright (C) 2008 Kornel Pal
+ */
+
+#ifndef __MONO_COREE_H__
+#define __MONO_COREE_H__
+
+#include <config.h>
+
+#ifdef PLATFORM_WIN32
+
+STDAPI MonoFixupCorEE(HMODULE hModule);
+STDAPI MonoFixupExe(HMODULE hModule);
+
+extern HMODULE mono_module_handle;
+extern HMODULE coree_module_handle;
+
+void mono_fixup_coree ();
+void mono_fixup_exe_image (MonoImage* image);
+
+#endif /* PLATFORM_WIN32 */
+
+#endif /* __MONO_COREE_H__ */

Property changes on: mono\mono\metadata\coree.h
___________________________________________________________________
Name: svn:eol-style
  + native

Index: mono/mono/metadata/metadata-internals.h
===================================================================
--- mono/mono/metadata/metadata-internals.h     (revision 101236)
+++ mono/mono/metadata/metadata-internals.h     (working copy)
@@ -77,6 +77,11 @@
        guint8 raw_buffer_used    : 1;
        guint8 raw_data_allocated : 1;

+#ifdef PLATFORM_WIN32
+       /* Module was loaded using LoadLibrary */
+       guint8 is_module_handle : 1;
+#endif
+
        /* Whenever this is a dynamically emitted module */
        guint8 dynamic : 1;

Index: mono/mono/metadata/domain-internals.h
===================================================================
--- mono/mono/metadata/domain-internals.h       (revision 101236)
+++ mono/mono/metadata/domain-internals.h       (working copy)
@@ -218,6 +218,14 @@
#define mono_domain_assemblies_lock(domain)   
EnterCriticalSection(&(domain)->assemblies_lock)
#define mono_domain_assemblies_unlock(domain) 
LeaveCriticalSection(&(domain)->assemblies_lock)

+typedef MonoDomain* (*MonoLoadFunc) (const char *filename, const char 
*runtime_version);
+
+void
+mono_install_runtime_load  (MonoLoadFunc func) MONO_INTERNAL;
+
+MonoDomain*
+mono_runtime_load (const char *filename, const char *runtime_version) 
MONO_INTERNAL;
+
void mono_init_com_types (void) MONO_INTERNAL;

Index: mono/mono/metadata/marshal.c
===================================================================
--- mono/mono/metadata/marshal.c        (revision 101236)
+++ mono/mono/metadata/marshal.c        (working copy)
@@ -11,6 +11,7 @@
#include "config.h"
#include "object.h"
#include "loader.h"
+#include "cil-coff.h"
#include "metadata/marshal.h"
#include "metadata/method-builder.h"
#include "metadata/tabledefs.h"
@@ -8471,7 +8472,10 @@

        if (!piinfo->addr) {
                if (pinvoke)
-                       mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
+                       if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)
+                               exc_arg = "Method contains unsupported native 
code";
+                       else
+                               mono_lookup_pinvoke_call (method, &exc_class, 
&exc_arg);
                else
                        piinfo->addr = mono_lookup_internal_call (method);
        }
@@ -8787,6 +8791,42 @@
}


+static void +mono_marshal_set_callconv_from_modopt (MonoMethod *method, MonoMethodSignature *csig)
+{
+       MonoMethodSignature *sig;
+       int i;
+
+#ifdef PLATFORM_WIN32
+ /* + * Under windows, delegates passed to native code must use the STDCALL
+        * calling convention.
+        */
+       csig->call_convention = MONO_CALL_STDCALL;
+#endif
+
+       sig = mono_method_signature (method);
+
+       /* Change default calling convention if needed */
+       /* Why is this a modopt ? */
+       if (sig->ret && sig->ret->num_mods) {
+               for (i = 0; i < sig->ret->num_mods; ++i) {
+                       MonoClass *cmod_class = mono_class_get (method->klass->image, 
sig->ret->modifiers [i].token);
+                       g_assert (cmod_class);
+                       if ((cmod_class->image == mono_defaults.corlib) && !strcmp 
(cmod_class->name_space, "System.Runtime.CompilerServices")) {
+                               if (!strcmp (cmod_class->name, "CallConvCdecl"))
+                                       csig->call_convention = MONO_CALL_C;
+                               else if (!strcmp (cmod_class->name, 
"CallConvStdcall"))
+                                       csig->call_convention = 
MONO_CALL_STDCALL;
+                               else if (!strcmp (cmod_class->name, 
"CallConvFastcall"))
+                                       csig->call_convention = 
MONO_CALL_FASTCALL;
+                               else if (!strcmp (cmod_class->name, 
"CallConvThiscall"))
+                                       csig->call_convention = 
MONO_CALL_THISCALL;
+                       }
+               }
+       }
+}
+
/*
* generates IL code to call managed methods from unmanaged code */
@@ -8842,33 +8882,8 @@
        m.csig = csig;
        m.image = method->klass->image;

-#ifdef PLATFORM_WIN32
- /* - * Under windows, delegates passed to native code must use the STDCALL
-        * calling convention.
-        */
-       csig->call_convention = MONO_CALL_STDCALL;
-#endif
+       mono_marshal_set_callconv_from_modopt (invoke, csig);

-       /* Change default calling convention if needed */
-       /* Why is this a modopt ? */
-       if (invoke_sig->ret && invoke_sig->ret->num_mods) {
-               for (i = 0; i < invoke_sig->ret->num_mods; ++i) {
-                       MonoClass *cmod_class = mono_class_get 
(delegate_klass->image, invoke_sig->ret->modifiers [i].token);
-                       g_assert (cmod_class);
-                       if ((cmod_class->image == mono_defaults.corlib) && !strcmp 
(cmod_class->name_space, "System.Runtime.CompilerServices")) {
-                               if (!strcmp (cmod_class->name, "CallConvCdecl"))
-                                       csig->call_convention = MONO_CALL_C;
-                               else if (!strcmp (cmod_class->name, 
"CallConvStdcall"))
-                                       csig->call_convention = 
MONO_CALL_STDCALL;
-                               else if (!strcmp (cmod_class->name, 
"CallConvFastcall"))
-                                       csig->call_convention = 
MONO_CALL_FASTCALL;
-                               else if (!strcmp (cmod_class->name, 
"CallConvThiscall"))
-                                       csig->call_convention = 
MONO_CALL_THISCALL;
-                       }
-               }
-       }
-
        /* Handle the UnmanagedFunctionPointerAttribute */
        if (!UnmanagedFunctionPointerAttribute)
                UnmanagedFunctionPointerAttribute = mono_class_from_name (mono_defaults.corlib, 
"System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
@@ -8918,6 +8933,80 @@
        return res;
}

+gpointer
+mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 type)
+{
+       MonoMethod *method;
+       MonoMethodSignature *sig;
+       MonoMethodBuilder *mb;
+       int i, param_count;
+
+       g_assert (token);
+
+       method = mono_get_method (image, token, NULL);
+       g_assert (method);
+
+       if (type & (VTFIXUP_TYPE_FROM_UNMANAGED | 
VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN)) {
+               MonoMethodSignature *csig;
+               MonoMarshalSpec **mspecs;
+               EmitMarshalContext m;
+
+               sig = mono_method_signature (method);
+               g_assert (!sig->hasthis);
+
+               mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
+               mono_method_get_marshal_info (method, mspecs);
+
+               mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_NATIVE_TO_MANAGED);
+               csig = signature_dup (image, sig);
+               csig->hasthis = 0;
+               csig->pinvoke = 1;
+
+               m.mb = mb;
+               m.sig = sig;
+               m.piinfo = NULL;
+               m.retobj_var = 0;
+               m.csig = csig;
+               m.image = image;
+
+               mono_marshal_set_callconv_from_modopt (method, csig);
+
+               /* FIXME: implement 
VTFIXUP_TYPE_FROM_UNMANAGED_RETAIN_APPDOMAIN */
+
+               mono_marshal_emit_managed_wrapper (mb, sig, mspecs, &m, method, 
NULL);
+
+               mb->dynamic = 1;
+               method = mono_mb_create_method (mb, csig, sig->param_count + 
16);
+               mono_mb_free (mb);
+
+               for (i = sig->param_count; i >= 0; i--)
+                       if (mspecs [i])
+                               mono_metadata_free_marshal_spec (mspecs [i]);
+               g_free (mspecs);
+
+               return mono_compile_method (method);
+       }
+
+       sig = mono_method_signature (method);
+       mb = mono_mb_new (method->klass, method->name, 
MONO_WRAPPER_MANAGED_TO_MANAGED);
+
+       param_count = sig->param_count + sig->hasthis;
+       for (i = 0; i < param_count; i++)
+               mono_mb_emit_ldarg (mb, i);
+
+       if (type & VTFIXUP_TYPE_CALL_MOST_DERIVED)
+               mono_mb_emit_op (mb, CEE_CALLVIRT, method);
+       else
+               mono_mb_emit_op (mb, CEE_CALL, method);
+       mono_mb_emit_byte (mb, CEE_RET);
+
+       mb->dynamic = 1;
+       method = mono_mb_create_method (mb, sig, param_count);
+       mono_mb_free (mb);
+
+       return mono_compile_method (method);
+}
+
static MonoReflectionType *
type_from_handle (MonoType *handle)
{
Index: mono/mono/metadata/marshal.h
===================================================================
--- mono/mono/metadata/marshal.h        (revision 101236)
+++ mono/mono/metadata/marshal.h        (working copy)
@@ -140,6 +140,9 @@
MonoMethod *
mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass 
*delegate_klass, MonoObject *this) MONO_INTERNAL;

+gpointer
+mono_marshal_get_vtfixup_ftnptr (MonoImage *image, guint32 token, guint16 
type) MONO_INTERNAL;
+
MonoMethod *
mono_marshal_get_icall_wrapper (MonoMethodSignature *sig, const char *name, 
gconstpointer func, gboolean check_exceptions) MONO_INTERNAL;

Index: mono/mono/metadata/Makefile.am
===================================================================
--- mono/mono/metadata/Makefile.am      (revision 101236)
+++ mono/mono/metadata/Makefile.am      (working copy)
@@ -108,6 +108,8 @@
        console-io.c            \
        console-io.h    \
        assembly.c      \
+       coree.c \
+       coree.h \
        domain.c        \
        domain-internals.h      \
        opcodes.c       \
Index: mono/mono/metadata/gc.c
===================================================================
--- mono/mono/metadata/gc.c     (revision 101236)
+++ mono/mono/metadata/gc.c     (working copy)
@@ -47,14 +47,14 @@
static GSList *domains_to_finalize= NULL;
static MonoMList *threads_to_finalize = NULL;

-static MonoThread *gc_thread;
+#define GC_THREAD_UNINITIALIZED ((MonoThread*) (-1))
+static volatile MonoThread *gc_thread = GC_THREAD_UNINITIALIZED;

static void object_register_finalizer (MonoObject *obj, void (*callback)(void 
*, void*));

#ifndef HAVE_NULL_GC
static HANDLE pending_done_event;
static HANDLE shutdown_event;
-static HANDLE thread_started_event;
#endif

static void
@@ -884,8 +884,6 @@
{
        gc_thread = mono_thread_current ();

-       SetEvent (thread_started_event);
-
        while (!finished) {
                /* Wait to be notified that there's at least one
                 * finaliser to run
@@ -939,17 +937,11 @@
        finalizer_event = CreateEvent (NULL, FALSE, FALSE, NULL);
        pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
        shutdown_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-       thread_started_event = CreateEvent (NULL, TRUE, FALSE, NULL);
-       if (finalizer_event == NULL || pending_done_event == NULL || 
shutdown_event == NULL || thread_started_event == NULL) {
+       if (finalizer_event == NULL || pending_done_event == NULL || 
shutdown_event == NULL) {
                g_assert_not_reached ();
        }

        mono_thread_create (mono_domain_get (), finalizer_thread, NULL);
-       /*
-        * Wait until the finalizer thread sets gc_thread since its value is 
needed
-        * by mono_thread_attach ()
-        */
-       WaitForSingleObjectEx (thread_started_event, INFINITE, FALSE);
}

void
@@ -967,10 +959,13 @@
                        /* Finishing the finalizer thread, so wait a little 
bit... */
                        /* MS seems to wait for about 2 seconds */
                        if (WaitForSingleObjectEx (shutdown_event, 2000, FALSE) 
== WAIT_TIMEOUT) {
-                               mono_thread_stop (gc_thread);
+                               MonoThread *cur_gc_thread = gc_thread;
+
+                               if (cur_gc_thread != GC_THREAD_UNINITIALIZED)
+                                       mono_thread_stop (cur_gc_thread);
                        }
                }
-               gc_thread = NULL;
+               gc_thread = GC_THREAD_UNINITIALIZED;
#ifdef HAVE_BOEHM_GC
                GC_finalizer_notifier = NULL;
#endif
Index: mono/mono/mini/mini.c
===================================================================
--- mono/mono/mini/mini.c       (revision 101236)
+++ mono/mono/mini/mini.c       (working copy)
@@ -12321,15 +12321,17 @@
                MonoMethod *nm;
                MonoMethodPInvoke* piinfo = (MonoMethodPInvoke *) method;

-               if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE && 
!MONO_CLASS_IS_IMPORT(method->klass))
-                       g_error ("Method '%s' in assembly '%s' contains native code and mono 
can't run it. The assembly was probably created by Managed C++.\n", mono_method_full_name 
(method, TRUE), method->klass->image->name);
-
                if (!piinfo->addr) {
                        if (method->iflags & 
METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
                                piinfo->addr = mono_lookup_internal_call 
(method);
+                       else if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)
+#ifdef PLATFORM_WIN32
+                               g_warning ("Method '%s' in assembly '%s' contains native code 
that cannot be executed by Mono in modules loaded from byte arrays. The assembly was probably 
created using C++/CLI.\n", mono_method_full_name (method, TRUE), 
method->klass->image->name);
+#else
+                               g_warning ("Method '%s' in assembly '%s' contains native code 
that cannot be executed by Mono on this platform. The assembly was probably created using 
C++/CLI.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
+#endif
                        else
-                               if (method->flags & 
METHOD_ATTRIBUTE_PINVOKE_IMPL)
-                                       mono_lookup_pinvoke_call (method, NULL, 
NULL);
+                               mono_lookup_pinvoke_call (method, NULL, NULL);
                }
                        nm = mono_marshal_get_native_wrapper (method, 
check_for_pending_exc);
                        return mono_get_addr_from_ftnptr (mono_compile_method 
(nm));
Index: mono/mono/mini/main.c
===================================================================
--- mono/mono/mini/main.c       (revision 101236)
+++ mono/mono/mini/main.c       (working copy)
@@ -1,8 +1,31 @@
#include "mini.h"

+#ifdef PLATFORM_WIN32
+
int
+main ()
+{
+       int argc;
+       gunichar2** argvw;
+       gchar** argv;
+       int i;
+
+       argvw = CommandLineToArgvW (GetCommandLine (), &argc);
+       argv = g_new0 (gchar*, argc);
+       for (i = 0; i < argc; i++)
+               argv [i] = g_utf16_to_utf8 (argvw [i], -1, NULL, NULL, NULL);
+
+       LocalFree (argvw);
+
+       return mono_main (argc, argv);
+}
+
+#else
+
+int
main (int argc, char* argv[])
{
        return mono_main (argc, argv);
}

+#endif
Index: mono/mono/mini/Makefile.am
===================================================================
--- mono/mono/mini/Makefile.am  (revision 101236)
+++ mono/mono/mini/Makefile.am  (working copy)
@@ -58,7 +58,7 @@
endif

if PLATFORM_WIN32
-libmono_la_LDFLAGS=-no-undefined -avoid-version $(monoldflags)
+libmono_la_LDFLAGS=-no-undefined -avoid-version -Wl,--kill-at $(monoldflags)
else
libmono_la_LDFLAGS=$(monoldflags)
endif
Index: mono/mono/mini/driver.c
===================================================================
--- mono/mono/mini/driver.c     (revision 101236)
+++ mono/mono/mini/driver.c     (working copy)
@@ -44,7 +44,9 @@
#include <mono/metadata/security-manager.h>
#include <mono/metadata/security-core-clr.h>
#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/coree.h>
#include "mono/utils/mono-counters.h"
+#include <mono/os/gc_wrapper.h>

#include "mini.h"
#include "jit.h"
@@ -1006,6 +1008,27 @@
#define error_if_aot_unsupported()
#endif

+#ifdef PLATFORM_WIN32
+BOOL APIENTRY DllMain (HMODULE module_handle, DWORD reason, LPVOID reserved)
+{
+       if (!GC_DllMain (module_handle, reason, reserved))
+               return FALSE;
+
+       switch (reason)
+       {
+       case DLL_PROCESS_ATTACH:
+               mono_module_handle = module_handle;
+               mono_install_runtime_load (mini_init);
+               break;
+       case DLL_PROCESS_DETACH:
+               if (coree_module_handle)
+                       FreeLibrary (coree_module_handle);
+               break;
+       }
+       return TRUE;
+}
+#endif
+
int
mono_main (int argc, char* argv[])
{
Index: mono/msvc/create-windef.pl
===================================================================
--- mono/msvc/create-windef.pl  (revision 101236)
+++ mono/msvc/create-windef.pl  (working copy)
@@ -19,6 +19,7 @@
        push @symbols, $1;
}
close (SYMS);
+push @symbols, "MonoFixupCorEE";
@symbols = sort @symbols;

open (OUT, ">$outfile") || die "Cannot open '$outfile': $!\n";
Index: mono/msvc/libmono.vcproj
===================================================================
--- mono/msvc/libmono.vcproj    (revision 101236)
+++ mono/msvc/libmono.vcproj    (working copy)
@@ -2287,6 +2287,14 @@
                                >
                        </File>
                        <File
+                               RelativePath="..\mono\metadata\coree.c"
+                               >
+                       </File>
+                       <File
+                               RelativePath="..\mono\metadata\coree.h"
+                               >
+                       </File>
+                       <File
                                
RelativePath="..\mono\metadata\culture-info-tables.h"
                                >
                        </File>
Index: mono/msvc/mono.def
===================================================================
--- mono/msvc/mono.def  (revision 101236)
+++ mono/msvc/mono.def  (working copy)
@@ -1,6 +1,7 @@
; file generated by create-windef.pl
LIBRARY mono.dll
EXPORTS
+MonoFixupCorEE
mono_add_internal_call
mono_alloc_special_static_data
mono_array_class_get

Property changes on: mono\msvc\mono.def
___________________________________________________________________
Name: svn:eol-style
  + native

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to