[MSCOREE]
authorAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Jun 2012 10:46:54 +0000 (10:46 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Mon, 4 Jun 2012 10:46:54 +0000 (10:46 +0000)
* Sync to Wine 1.5.4.

svn path=/trunk/; revision=56692

reactos/dll/win32/mscoree/CMakeLists.txt
reactos/dll/win32/mscoree/assembly.c
reactos/dll/win32/mscoree/config.c
reactos/dll/win32/mscoree/corruntimehost.c
reactos/dll/win32/mscoree/metahost.c
reactos/dll/win32/mscoree/mscoree.spec
reactos/dll/win32/mscoree/mscoree_main.c
reactos/dll/win32/mscoree/mscoree_private.h
reactos/media/doc/README.WINE

index 1aab2a6..1c38697 100644 (file)
@@ -2,7 +2,9 @@
 add_definitions(-D__WINESRC__)
 include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
 
-set_rc_compiler()
+remove_definitions(-D_WIN32_WINNT=0x502)
+add_definitions(-D_WIN32_WINNT=0x600)
+
 spec2def(mscoree.dll mscoree.spec)
 
 list(APPEND SOURCE
index 07723f9..13e7f03 100644 (file)
@@ -63,10 +63,13 @@ typedef struct tagCLRTABLE
 
 struct tagASSEMBLY
 {
-    LPWSTR path;
+    int is_mapped_file;
 
+    /* mapped files */
+    LPWSTR path;
     HANDLE hfile;
     HANDLE hmap;
+
     BYTE *data;
 
     IMAGE_NT_HEADERS *nthdr;
@@ -89,6 +92,29 @@ static inline LPWSTR strdupW(LPCWSTR src)
     return dest;
 }
 
+static void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva)
+{
+    if (assembly->is_mapped_file)
+        return ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+    else
+        return assembly->data + rva;
+}
+
+static ULONG assembly_datadir_get_data(ASSEMBLY *assembly,
+    IMAGE_DATA_DIRECTORY *datadir, void **data)
+{
+    if (!datadir->VirtualAddress || !datadir->Size)
+    {
+        *data = NULL;
+        return 0;
+    }
+    else
+    {
+        *data = assembly_rva_to_va(assembly, datadir->VirtualAddress);
+        return datadir->Size;
+    }
+}
+
 static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
 {
     METADATAHDR *metadatahdr;
@@ -97,7 +123,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
     ULONG rva;
 
     rva = assembly->corhdr->MetaData.VirtualAddress;
-    ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+    ptr = assembly_rva_to_va(assembly, rva);
     if (!ptr)
         return E_FAIL;
 
@@ -158,20 +184,24 @@ static HRESULT parse_pe_header(ASSEMBLY *assembly)
     if (!datadirs)
         return E_FAIL;
 
-    if (!datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress ||
-        !datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size)
-    {
-        return E_FAIL;
-    }
-
-    assembly->corhdr = ImageRvaToVa(assembly->nthdr, assembly->data,
-        datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress, NULL);
-    if (!assembly->corhdr)
+    if (!assembly_datadir_get_data(assembly, &datadirs[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR], (void**)&assembly->corhdr))
         return E_FAIL;
 
     return S_OK;
 }
 
+static HRESULT parse_headers(ASSEMBLY *assembly)
+{
+    HRESULT hr;
+
+    hr = parse_pe_header(assembly);
+
+    if (SUCCEEDED(hr))
+        hr = parse_clr_metadata(assembly);
+
+    return hr;
+}
+
 HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
 {
     ASSEMBLY *assembly;
@@ -183,6 +213,8 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
     if (!assembly)
         return E_OUTOFMEMORY;
 
+    assembly->is_mapped_file = 1;
+
     assembly->path = strdupW(file);
     if (!assembly->path)
     {
@@ -213,10 +245,7 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
         goto failed;
     }
 
-    hr = parse_pe_header(assembly);
-    if (FAILED(hr)) goto failed;
-
-    hr = parse_clr_metadata(assembly);
+    hr = parse_headers(assembly);
     if (FAILED(hr)) goto failed;
 
     *out = assembly;
@@ -227,16 +256,43 @@ failed:
     return hr;
 }
 
+HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule)
+{
+    ASSEMBLY *assembly;
+    HRESULT hr;
+
+    *out = NULL;
+
+    assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
+    if (!assembly)
+        return E_OUTOFMEMORY;
+
+    assembly->is_mapped_file = 0;
+
+    assembly->data = (BYTE*)hmodule;
+
+    hr = parse_headers(assembly);
+    if (SUCCEEDED(hr))
+        *out = assembly;
+    else
+        assembly_release(assembly);
+
+    return hr;
+}
+
 HRESULT assembly_release(ASSEMBLY *assembly)
 {
     if (!assembly)
         return S_OK;
 
+    if (assembly->is_mapped_file)
+    {
+        UnmapViewOfFile(assembly->data);
+        CloseHandle(assembly->hmap);
+        CloseHandle(assembly->hfile);
+    }
     HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
     HeapFree(GetProcessHeap(), 0, assembly->path);
-    UnmapViewOfFile(assembly->data);
-    CloseHandle(assembly->hmap);
-    CloseHandle(assembly->hfile);
     HeapFree(GetProcessHeap(), 0, assembly);
 
     return S_OK;
@@ -248,3 +304,13 @@ HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
 
     return S_OK;
 }
+
+HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count)
+{
+    ULONG size;
+
+    size = assembly_datadir_get_data(assembly, &assembly->corhdr->VTableFixups, (void**)fixups);
+    *count = size / sizeof(VTableFixup);
+
+    return S_OK;
+}
index 02c11b1..c5e3cec 100644 (file)
@@ -425,7 +425,7 @@ static HRESULT parse_config(VARIANT input, parsed_config_file *result)
         ISAXXMLReader_Release(reader);
     }
 
-    IUnknown_Release((IUnknown*)handler);
+    ISAXContentHandler_Release(&handler->ISAXContentHandler_iface);
 
     return S_OK;
 }
@@ -445,7 +445,7 @@ HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
 
     if (SUCCEEDED(hr))
     {
-        V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
+        V_VT(&var) = VT_UNKNOWN;
         V_UNKNOWN(&var) = (IUnknown*)stream;
 
         hr = parse_config(var, result);
index 5042f20..3f2b9a2 100644 (file)
@@ -19,6 +19,7 @@
 
 #define COBJMACROS
 
+#include <assert.h>
 #include <stdarg.h>
 
 #include "windef.h"
@@ -38,6 +39,8 @@
 #include "mscoree_private.h"
 
 #include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
 
@@ -51,6 +54,21 @@ struct DomainEntry
     MonoDomain *domain;
 };
 
+static HANDLE dll_fixup_heap; /* using a separate heap so we can have execute permission */
+
+static struct list dll_fixups;
+
+struct dll_fixup
+{
+    struct list entry;
+    int done;
+    HMODULE dll;
+    void *thunk_code; /* pointer into dll_fixup_heap */
+    VTableFixup *fixup;
+    void *vtable;
+    void *tokens; /* pointer into process heap */
+};
+
 static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
 {
     struct DomainEntry *entry;
@@ -147,6 +165,8 @@ static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *d
     MonoObject *appdomain_object;
     IUnknown *unk;
 
+    This->mono->mono_thread_attach(domain);
+
     assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
     if (!assembly)
     {
@@ -559,6 +579,8 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
 
     hr = E_FAIL;
 
+    This->mono->mono_thread_attach(domain);
+
     filenameA = WtoA(pwzAssemblyPath);
     assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
     if (!assembly)
@@ -609,14 +631,10 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
     }
 
 cleanup:
-    if(filenameA)
-        HeapFree(GetProcessHeap(), 0, filenameA);
-    if(classA)
-        HeapFree(GetProcessHeap(), 0, classA);
-    if(argsA)
-        HeapFree(GetProcessHeap(), 0, argsA);
-    if(methodA)
-        HeapFree(GetProcessHeap(), 0, methodA);
+    HeapFree(GetProcessHeap(), 0, filenameA);
+    HeapFree(GetProcessHeap(), 0, classA);
+    HeapFree(GetProcessHeap(), 0, argsA);
+    HeapFree(GetProcessHeap(), 0, methodA);
 
     return hr;
 }
@@ -661,6 +679,8 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
 
     if (SUCCEEDED(hr))
     {
+        This->mono->mono_thread_attach(domain);
+
         type = This->mono->mono_reflection_type_from_name(nameA, NULL);
         if (!type)
         {
@@ -708,7 +728,9 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
  *
  * NOTE: The IUnknown* is created with a reference to the object.
  * Until they have a reference, objects must be in the stack to prevent the
- * garbage collector from freeing them. */
+ * garbage collector from freeing them.
+ *
+ * mono_thread_attach must have already been called for this thread. */
 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
     IUnknown **ppUnk)
 {
@@ -798,13 +820,223 @@ static void get_utf8_args(int *argc, char ***argv)
     HeapFree(GetProcessHeap(), 0, argvw);
 }
 
+#if __i386__
+
+# define CAN_FIXUP_VTABLE 1
+
+#include "pshpack1.h"
+
+struct vtable_fixup_thunk
+{
+    /* sub $0x4,%esp */
+    BYTE i1[3];
+    /* mov fixup,(%esp) */
+    BYTE i2[3];
+    struct dll_fixup *fixup;
+    /* mov function,%eax */
+    BYTE i3;
+    void (CDECL *function)(struct dll_fixup *);
+    /* call *%eax */
+    BYTE i4[2];
+    /* pop %eax */
+    BYTE i5;
+    /* jmp *vtable_entry */
+    BYTE i6[2];
+    void *vtable_entry;
+};
+
+static const struct vtable_fixup_thunk thunk_template = {
+    {0x83,0xec,0x04},
+    {0xc7,0x04,0x24},
+    NULL,
+    0xb8,
+    NULL,
+    {0xff,0xd0},
+    0x58,
+    {0xff,0x25},
+    NULL
+};
+
+#include "poppack.h"
+
+#else /* !defined(__i386__) */
+
+# define CAN_FIXUP_VTABLE 0
+
+struct vtable_fixup_thunk
+{
+    struct dll_fixup *fixup;
+    void (CDECL *function)(struct dll_fixup *fixup);
+    void *vtable_entry;
+};
+
+static const struct vtable_fixup_thunk thunk_template = {0};
+
+#endif
+
+static void CDECL ReallyFixupVTable(struct dll_fixup *fixup)
+{
+    HRESULT hr=S_OK;
+    WCHAR filename[MAX_PATH];
+    ICLRRuntimeInfo *info=NULL;
+    RuntimeHost *host;
+    char *filenameA;
+    MonoImage *image=NULL;
+    MonoAssembly *assembly=NULL;
+    MonoImageOpenStatus status=0;
+    MonoDomain *domain;
+
+    if (fixup->done) return;
+
+    /* It's possible we'll have two threads doing this at once. This is
+     * considered preferable to the potential deadlock if we use a mutex. */
+
+    GetModuleFileNameW(fixup->dll, filename, MAX_PATH);
+
+    TRACE("%p,%p,%s\n", fixup, fixup->dll, debugstr_w(filename));
+
+    filenameA = WtoA(filename);
+    if (!filenameA)
+        hr = E_OUTOFMEMORY;
+
+    if (SUCCEEDED(hr))
+        hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
+
+    if (SUCCEEDED(hr))
+        hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
+
+    if (SUCCEEDED(hr))
+        hr = RuntimeHost_GetDefaultDomain(host, &domain);
+
+    if (SUCCEEDED(hr))
+    {
+        host->mono->mono_thread_attach(domain);
+
+        image = host->mono->mono_image_open_from_module_handle(fixup->dll,
+            filenameA, 1, &status);
+    }
+
+    if (image)
+        assembly = host->mono->mono_assembly_load_from(image, filenameA, &status);
+
+    if (assembly)
+    {
+        int i;
+
+        /* Mono needs an image that belongs to an assembly. */
+        image = host->mono->mono_assembly_get_image(assembly);
+
+        if (fixup->fixup->type & COR_VTABLE_32BIT)
+        {
+            DWORD *vtable = fixup->vtable;
+            DWORD *tokens = fixup->tokens;
+            for (i=0; i<fixup->fixup->count; i++)
+            {
+                TRACE("%x\n", tokens[i]);
+                vtable[i] = PtrToUint(host->mono->mono_marshal_get_vtfixup_ftnptr(
+                    image, tokens[i], fixup->fixup->type));
+            }
+        }
+
+        fixup->done = 1;
+    }
+
+    if (info != NULL)
+        ICLRRuntimeHost_Release(info);
+
+    HeapFree(GetProcessHeap(), 0, filenameA);
+
+    if (!fixup->done)
+    {
+        ERR("unable to fixup vtable, hr=%x, status=%d\n", hr, status);
+        /* If we returned now, we'd get an infinite loop. */
+        assert(0);
+    }
+}
+
+static void FixupVTableEntry(HMODULE hmodule, VTableFixup *vtable_fixup)
+{
+    /* We can't actually generate code for the functions without loading mono,
+     * and loading mono inside DllMain is a terrible idea. So we make thunks
+     * that call ReallyFixupVTable, which will load the runtime and fill in the
+     * vtable, then do an indirect jump using the (now filled in) vtable. Note
+     * that we have to keep the thunks around forever, as one of them may get
+     * called while we're filling in the table, and we can never be sure all
+     * threads are clear. */
+    struct dll_fixup *fixup;
+
+    fixup = HeapAlloc(GetProcessHeap(), 0, sizeof(*fixup));
+
+    fixup->dll = hmodule;
+    fixup->thunk_code = HeapAlloc(dll_fixup_heap, 0, sizeof(struct vtable_fixup_thunk) * vtable_fixup->count);
+    fixup->fixup = vtable_fixup;
+    fixup->vtable = (BYTE*)hmodule + vtable_fixup->rva;
+    fixup->done = 0;
+
+    if (vtable_fixup->type & COR_VTABLE_32BIT)
+    {
+        DWORD *vtable = fixup->vtable;
+        DWORD *tokens;
+        int i;
+        struct vtable_fixup_thunk *thunks = fixup->thunk_code;
+
+        if (sizeof(void*) > 4)
+            ERR("32-bit fixup in 64-bit mode; broken image?\n");
+
+        tokens = fixup->tokens = HeapAlloc(GetProcessHeap(), 0, sizeof(*tokens) * vtable_fixup->count);
+        memcpy(tokens, vtable, sizeof(*tokens) * vtable_fixup->count);
+        for (i=0; i<vtable_fixup->count; i++)
+        {
+            memcpy(&thunks[i], &thunk_template, sizeof(thunk_template));
+            thunks[i].fixup = fixup;
+            thunks[i].function = ReallyFixupVTable;
+            thunks[i].vtable_entry = &vtable[i];
+            vtable[i] = PtrToUint(&thunks[i]);
+        }
+    }
+    else
+    {
+        ERR("unsupported vtable fixup flags %x\n", vtable_fixup->type);
+        HeapFree(dll_fixup_heap, 0, fixup->thunk_code);
+        HeapFree(GetProcessHeap(), 0, fixup);
+        return;
+    }
+
+    list_add_tail(&dll_fixups, &fixup->entry);
+}
+
+static void FixupVTable(HMODULE hmodule)
+{
+    ASSEMBLY *assembly;
+    HRESULT hr;
+    VTableFixup *vtable_fixups;
+    ULONG vtable_fixup_count, i;
+
+    hr = assembly_from_hmodule(&assembly, hmodule);
+    if (SUCCEEDED(hr))
+    {
+        hr = assembly_get_vtable_fixups(assembly, &vtable_fixups, &vtable_fixup_count);
+        if (CAN_FIXUP_VTABLE)
+            for (i=0; i<vtable_fixup_count; i++)
+                FixupVTableEntry(hmodule, &vtable_fixups[i]);
+        else if (vtable_fixup_count)
+            FIXME("cannot fixup vtable; expect a crash\n");
+
+        assembly_release(assembly);
+    }
+    else
+        ERR("failed to read CLR headers, hr=%x\n", hr);
+}
+
 __int32 WINAPI _CorExeMain(void)
 {
     int exit_code;
     int argc;
     char **argv;
     MonoDomain *domain;
-    MonoAssembly *assembly;
+    MonoImage *image;
+    MonoImageOpenStatus status;
+    MonoAssembly *assembly=NULL;
     WCHAR filename[MAX_PATH];
     char *filenameA;
     ICLRRuntimeInfo *info;
@@ -825,6 +1057,8 @@ __int32 WINAPI _CorExeMain(void)
     if (!filenameA)
         return -1;
 
+    FixupVTable(GetModuleHandleW(NULL));
+
     hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
 
     if (SUCCEEDED(hr))
@@ -836,9 +1070,21 @@ __int32 WINAPI _CorExeMain(void)
 
         if (SUCCEEDED(hr))
         {
-            assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
-
-            exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
+            image = host->mono->mono_image_open_from_module_handle(GetModuleHandleW(NULL),
+                filenameA, 1, &status);
+
+            if (image)
+                assembly = host->mono->mono_assembly_load_from(image, filenameA, &status);
+
+            if (assembly)
+            {
+                exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv);
+            }
+            else
+            {
+                ERR("couldn't load %s, status=%d\n", debugstr_w(filename), status);
+                exit_code = -1;
+            }
 
             RuntimeHost_DeleteDomain(host, domain);
         }
@@ -857,6 +1103,43 @@ __int32 WINAPI _CorExeMain(void)
     return exit_code;
 }
 
+BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+    TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+
+    switch (fdwReason)
+    {
+    case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls(hinstDLL);
+        FixupVTable(hinstDLL);
+        break;
+    case DLL_PROCESS_DETACH:
+        /* FIXME: clean up the vtables */
+        break;
+    }
+    return TRUE;
+}
+
+/* called from DLL_PROCESS_ATTACH */
+void runtimehost_init(void)
+{
+    dll_fixup_heap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
+    list_init(&dll_fixups);
+}
+
+/* called from DLL_PROCESS_DETACH */
+void runtimehost_uninit(void)
+{
+    struct dll_fixup *fixup, *fixup2;
+
+    HeapDestroy(dll_fixup_heap);
+    LIST_FOR_EACH_ENTRY_SAFE(fixup, fixup2, &dll_fixups, struct dll_fixup, entry)
+    {
+        HeapFree(GetProcessHeap(), 0, fixup->tokens);
+        HeapFree(GetProcessHeap(), 0, fixup);
+    }
+}
+
 HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
     loaded_mono *loaded_mono, RuntimeHost** result)
 {
@@ -943,3 +1226,148 @@ HRESULT RuntimeHost_Destroy(RuntimeHost *This)
     HeapFree( GetProcessHeap(), 0, This );
     return S_OK;
 }
+
+#define CHARS_IN_GUID 39
+#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
+
+HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
+{
+    static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
+    static const WCHAR wszClass[] = {'C','l','a','s','s',0};
+    static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
+    static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
+    static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
+    WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
+    MonoDomain *domain;
+    MonoAssembly *assembly;
+    ICLRRuntimeInfo *info;
+    RuntimeHost *host;
+    HRESULT hr;
+    HKEY key;
+    LONG res;
+    int offset = 0;
+    WCHAR codebase[MAX_PATH + 8];
+    WCHAR classname[350];
+    WCHAR filename[MAX_PATH];
+
+    DWORD dwBufLen = 350;
+
+    lstrcpyW(path, wszCLSIDSlash);
+    StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
+    lstrcatW(path, wszInprocServer32);
+
+    TRACE("Registry key: %s\n", debugstr_w(path));
+
+    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
+    if (res == ERROR_FILE_NOT_FOUND)
+        return CLASS_E_CLASSNOTAVAILABLE;
+
+    res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
+    if(res != ERROR_SUCCESS)
+    {
+        WARN("Class value cannot be found.\n");
+        hr = CLASS_E_CLASSNOTAVAILABLE;
+        goto cleanup;
+    }
+
+    TRACE("classname (%s)\n", debugstr_w(classname));
+
+    dwBufLen = MAX_PATH + 8;
+    res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
+    if(res != ERROR_SUCCESS)
+    {
+        WARN("CodeBase value cannot be found.\n");
+        hr = CLASS_E_CLASSNOTAVAILABLE;
+        goto cleanup;
+    }
+
+    /* Strip file:/// */
+    if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
+        offset = strlenW(wszFileSlash);
+
+    strcpyW(filename, codebase + offset);
+
+    TRACE("codebase (%s)\n", debugstr_w(filename));
+
+    *ppObj = NULL;
+
+
+    hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
+    if (SUCCEEDED(hr))
+    {
+        hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
+
+        if (SUCCEEDED(hr))
+            hr = RuntimeHost_GetDefaultDomain(host, &domain);
+
+        if (SUCCEEDED(hr))
+        {
+            MonoImage *image;
+            MonoClass *klass;
+            MonoObject *result;
+            IUnknown *unk = NULL;
+            char *filenameA, *ns;
+            char *classA;
+
+            hr = CLASS_E_CLASSNOTAVAILABLE;
+
+            host->mono->mono_thread_attach(domain);
+
+            filenameA = WtoA(filename);
+            assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
+            HeapFree(GetProcessHeap(), 0, filenameA);
+            if (!assembly)
+            {
+                ERR("Cannot open assembly %s\n", filenameA);
+                goto cleanup;
+            }
+
+            image = host->mono->mono_assembly_get_image(assembly);
+            if (!image)
+            {
+                ERR("Couldn't get assembly image\n");
+                goto cleanup;
+            }
+
+            classA = WtoA(classname);
+            ns = strrchr(classA, '.');
+            *ns = '\0';
+
+            klass = host->mono->mono_class_from_name(image, classA, ns+1);
+            HeapFree(GetProcessHeap(), 0, classA);
+            if (!klass)
+            {
+                ERR("Couldn't get class from image\n");
+                goto cleanup;
+            }
+
+            /*
+             * Use the default constructor for the .NET class.
+             */
+            result = host->mono->mono_object_new(domain, klass);
+            host->mono->mono_runtime_object_init(result);
+
+            hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
+            if (SUCCEEDED(hr))
+            {
+                hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
+
+                IUnknown_Release(unk);
+            }
+            else
+                hr = CLASS_E_CLASSNOTAVAILABLE;
+        }
+        else
+            hr = CLASS_E_CLASSNOTAVAILABLE;
+    }
+    else
+        hr = CLASS_E_CLASSNOTAVAILABLE;
+
+cleanup:
+    if(info)
+        ICLRRuntimeInfo_Release(info);
+
+    RegCloseKey(key);
+
+    return hr;
+}
index 49fb0ee..3736dc0 100644 (file)
@@ -165,16 +165,19 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
 } while (0);
 
         LOAD_MONO_FUNCTION(mono_assembly_get_image);
+        LOAD_MONO_FUNCTION(mono_assembly_load_from);
         LOAD_MONO_FUNCTION(mono_assembly_open);
         LOAD_MONO_FUNCTION(mono_config_parse);
         LOAD_MONO_FUNCTION(mono_class_from_mono_type);
         LOAD_MONO_FUNCTION(mono_class_from_name);
         LOAD_MONO_FUNCTION(mono_class_get_method_from_name);
         LOAD_MONO_FUNCTION(mono_domain_assembly_open);
+        LOAD_MONO_FUNCTION(mono_image_open_from_module_handle);
         LOAD_MONO_FUNCTION(mono_install_assembly_preload_hook);
         LOAD_MONO_FUNCTION(mono_jit_exec);
         LOAD_MONO_FUNCTION(mono_jit_init);
         LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
+        LOAD_MONO_FUNCTION(mono_marshal_get_vtfixup_ftnptr);
         LOAD_MONO_FUNCTION(mono_object_get_domain);
         LOAD_MONO_FUNCTION(mono_object_new);
         LOAD_MONO_FUNCTION(mono_object_unbox);
@@ -186,6 +189,7 @@ static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
         LOAD_MONO_FUNCTION(mono_set_dirs);
         LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
         LOAD_MONO_FUNCTION(mono_string_new);
+        LOAD_MONO_FUNCTION(mono_thread_attach);
 
         /* GLib imports obsoleted by the 2.0 ABI */
         if (This->mono_abi_version == 1)
@@ -564,6 +568,14 @@ HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **res
     return CLRRuntimeInfo_GetRuntimeHost(This, result);
 }
 
+#ifdef __i386__
+static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','.','d','l','l',0};
+#elif defined(__x86_64__)
+static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','-','x','8','6','_','6','4','.','d','l','l',0};
+#else
+static const WCHAR libmono2_arch_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
+#endif
+
 static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
 {
     static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
@@ -588,9 +600,16 @@ static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version)
     else if (abi_version == 2)
     {
         strcpyW(dll_path, path);
-        strcatW(dll_path, mono2_dll);
+        strcatW(dll_path, libmono2_arch_dll);
         attributes = GetFileAttributesW(dll_path);
 
+        if (attributes == INVALID_FILE_ATTRIBUTES)
+        {
+            strcpyW(dll_path, path);
+            strcatW(dll_path, mono2_dll);
+            attributes = GetFileAttributesW(dll_path);
+        }
+
         if (attributes == INVALID_FILE_ATTRIBUTES)
         {
             strcpyW(dll_path, path);
@@ -973,7 +992,7 @@ static BOOL parse_runtime_version(LPCWSTR version, DWORD *major, DWORD *minor, D
     *minor = 0;
     *build = 0;
 
-    if (version[0] == 'v')
+    if (version[0] == 'v' || version[0] == 'V')
     {
         version++;
         if (!isdigit(*version))
@@ -1310,11 +1329,21 @@ HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
 
     if (version)
     {
-        return CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
+        hr = CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
+        if(SUCCEEDED(hr))
+            return hr;
     }
 
     if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
     {
+        DWORD major, minor, build;
+
+        if (version && !parse_runtime_version(version, &major, &minor, &build))
+        {
+            ERR("Cannot parse %s\n", debugstr_w(version));
+            return CLR_E_SHIM_RUNTIME;
+        }
+
         find_runtimes();
 
         if (legacy)
@@ -1325,8 +1354,16 @@ HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
         while (i--)
         {
             if (runtimes[i].mono_abi_version)
-                return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
-                        &IID_ICLRRuntimeInfo, (void **)result);
+            {
+                /* Must be greater or equal to the version passed in. */
+                if (!version || ((runtimes[i].major >= major && runtimes[i].minor >= minor && runtimes[i].build >= build) ||
+                     (runtimes[i].major >= major && runtimes[i].minor > minor) ||
+                     (runtimes[i].major > major)))
+                {
+                    return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
+                            &IID_ICLRRuntimeInfo, (void **)result);
+                }
+            }
         }
 
         if (legacy)
index b2f72cd..a51a2f1 100644 (file)
@@ -9,7 +9,7 @@
 @ stub CloseCtrs
 @ stdcall CLRCreateInstance(ptr ptr ptr)
 @ stdcall ClrCreateManagedInstance(wstr ptr ptr)
-@ stub CoEEShutDownCOM
+@ stdcall CoEEShutDownCOM()
 @ stdcall CoInitializeCor(long)
 @ stub CoInitializeEE
 @ stub CoUninitializeCor
index 8b72ec8..0aa736f 100644 (file)
@@ -52,6 +52,8 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
 
 static HINSTANCE MSCOREE_hInstance;
 
+typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
+
 char *WtoA(LPCWSTR wstr)
 {
     int length;
@@ -89,6 +91,105 @@ static BOOL get_install_root(LPWSTR install_dir)
     return TRUE;
 }
 
+typedef struct mscorecf
+{
+    IClassFactory    IClassFactory_iface;
+    LONG ref;
+
+    fnCreateInstance pfnCreateInstance;
+
+    CLSID clsid;
+} mscorecf;
+
+static inline mscorecf *impl_from_IClassFactory( IClassFactory *iface )
+{
+    return CONTAINING_RECORD(iface, mscorecf, IClassFactory_iface);
+}
+
+static HRESULT WINAPI mscorecf_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj )
+{
+    TRACE("%s %p\n", debugstr_guid(riid), ppobj);
+
+    if (IsEqualGUID(riid, &IID_IUnknown) ||
+        IsEqualGUID(riid, &IID_IClassFactory))
+    {
+        IClassFactory_AddRef( iface );
+        *ppobj = iface;
+        return S_OK;
+    }
+
+    ERR("interface %s not implemented\n", debugstr_guid(riid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI mscorecf_AddRef(IClassFactory *iface )
+{
+    mscorecf *This = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("%p ref=%u\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI mscorecf_Release(IClassFactory *iface )
+{
+    mscorecf *This = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("%p ref=%u\n", This, ref);
+
+    if (ref == 0)
+    {
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI mscorecf_CreateInstance(IClassFactory *iface,LPUNKNOWN pOuter,
+                            REFIID riid, LPVOID *ppobj )
+{
+    mscorecf *This = impl_from_IClassFactory( iface );
+    HRESULT hr;
+    IUnknown *punk;
+
+    TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
+
+    *ppobj = NULL;
+
+    if (pOuter)
+        return CLASS_E_NOAGGREGATION;
+
+    hr = This->pfnCreateInstance( &This->clsid, (LPVOID*) &punk );
+    if (SUCCEEDED(hr))
+    {
+        hr = IUnknown_QueryInterface( punk, riid, ppobj );
+
+        IUnknown_Release( punk );
+    }
+    else
+    {
+        WARN("Cannot create an instance object. 0x%08x\n", hr);
+    }
+    return hr;
+}
+
+static HRESULT WINAPI mscorecf_LockServer(IClassFactory *iface, BOOL dolock)
+{
+    FIXME("(%p)->(%d),stub!\n",iface,dolock);
+    return S_OK;
+}
+
+static const struct IClassFactoryVtbl mscorecf_vtbl =
+{
+    mscorecf_QueryInterface,
+    mscorecf_AddRef,
+    mscorecf_Release,
+    mscorecf_CreateInstance,
+    mscorecf_LockServer
+};
+
 HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
                                     LPCWSTR pwszHostConfigFile, VOID *pReserved,
                                     DWORD startupFlags, REFCLSID rclsid,
@@ -126,25 +227,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
     case DLL_WINE_PREATTACH:
         return FALSE;  /* prefer native version */
     case DLL_PROCESS_ATTACH:
+        runtimehost_init();
         DisableThreadLibraryCalls(hinstDLL);
         break;
     case DLL_PROCESS_DETACH:
         expect_no_runtimes();
-        break;
-    }
-    return TRUE;
-}
-
-BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
-{
-    FIXME("(%p, %d, %p): stub\n", hinstDLL, fdwReason, lpvReserved);
-
-    switch (fdwReason)
-    {
-    case DLL_PROCESS_ATTACH:
-        DisableThreadLibraryCalls(hinstDLL);
-        break;
-    case DLL_PROCESS_DETACH:
+        if (lpvReserved) break; /* process is terminating */
+        runtimehost_uninit();
         break;
     }
     return TRUE;
@@ -246,6 +335,9 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
 
         if (SUCCEEDED(ret))
         {
+            if(pwszVersion)
+                pVersion[0] = pwszVersion[0];
+
             *dwDirectoryLength = dwDirectory;
             ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pDirectory, dwDirectoryLength);
         }
@@ -258,7 +350,7 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
 
 HRESULT WINAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
 {
-    TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), debugstr_w(pExe), cchBuffer, dwlength);
+    TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), pVersion, cchBuffer, dwlength);
 
     if(!dwlength)
         return E_POINTER;
@@ -504,11 +596,25 @@ HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterfac
 
 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
 {
-    FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+    mscorecf *This;
+    HRESULT hr;
+
+    TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
     if(!ppv)
         return E_INVALIDARG;
 
-    return E_NOTIMPL;
+    This = HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf));
+
+    This->IClassFactory_iface.lpVtbl = &mscorecf_vtbl;
+    This->pfnCreateInstance = &create_monodata;
+    This->ref = 1;
+    This->clsid = *rclsid;
+
+    hr = IClassFactory_QueryInterface( &This->IClassFactory_iface, riid, ppv );
+    IClassFactory_Release(&This->IClassFactory_iface);
+
+    return hr;
 }
 
 HRESULT WINAPI DllRegisterServer(void)
@@ -526,6 +632,11 @@ HRESULT WINAPI DllCanUnloadNow(VOID)
     return S_FALSE;
 }
 
+void WINAPI CoEEShutDownCOM(void)
+{
+    FIXME("stub.\n");
+}
+
 INT WINAPI ND_RU1( const void *ptr, INT offset )
 {
     return *((const BYTE *)ptr + offset);
index a45a405..ef9079e 100644 (file)
@@ -27,11 +27,19 @@ extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HI
 extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
     LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
 
+typedef struct _VTableFixup {
+    DWORD rva;
+    WORD count;
+    WORD type;
+} VTableFixup;
+
 typedef struct tagASSEMBLY ASSEMBLY;
 
-HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
-HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
-HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
+extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
+extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule) DECLSPEC_HIDDEN;
+extern HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
+extern HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
+extern HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count) DECLSPEC_HIDDEN;
 
 /* Mono embedding */
 typedef struct _MonoDomain MonoDomain;
@@ -44,6 +52,7 @@ typedef struct _MonoObject MonoObject;
 typedef struct _MonoString MonoString;
 typedef struct _MonoMethod MonoMethod;
 typedef struct _MonoProfiler MonoProfiler;
+typedef struct _MonoThread MonoThread;
 
 typedef struct loaded_mono loaded_mono;
 typedef struct RuntimeHost RuntimeHost;
@@ -137,6 +146,7 @@ struct loaded_mono
     BOOL is_shutdown;
 
     MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
+    MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
     MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
     MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
     MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name);
@@ -144,10 +154,12 @@ struct loaded_mono
     void (CDECL *mono_config_parse)(const char *filename);
     MonoAssembly* (CDECL *mono_domain_assembly_open) (MonoDomain *domain, const char *name);
     void (CDECL *mono_free)(void *);
+    MonoImage* (CDECL *mono_image_open_from_module_handle)(HMODULE module_handle, char* fname, UINT has_entry_point, MonoImageOpenStatus* status);
     void (CDECL *mono_install_assembly_preload_hook)(MonoAssemblyPreLoadFunc func, void *user_data);
     int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
     MonoDomain* (CDECL *mono_jit_init)(const char *file);
     int (CDECL *mono_jit_set_trace_options)(const char* options);
+    void* (CDECL *mono_marshal_get_vtfixup_ftnptr)(MonoImage *image, DWORD token, WORD type);
     MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
     MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
     void* (CDECL *mono_object_unbox)(MonoObject *obj);
@@ -163,6 +175,7 @@ struct loaded_mono
     void (CDECL *mono_thread_suspend_all_other_threads)(void);
     void (CDECL *mono_threads_set_shutting_down)(void);
     MonoString* (CDECL *mono_string_new)(MonoDomain *domain, const char *str);
+    MonoThread* (CDECL *mono_thread_attach)(MonoDomain *domain);
 };
 
 /* loaded runtime interfaces */
@@ -186,4 +199,9 @@ HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, R
 
 extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
 
+extern HRESULT create_monodata(REFIID riid, LPVOID *ppObj) DECLSPEC_HIDDEN;
+
+extern void runtimehost_init(void);
+extern void runtimehost_uninit(void);
+
 #endif   /* __MSCOREE_PRIVATE__ */
index fcac37c..9b212a6 100644 (file)
@@ -95,7 +95,7 @@ reactos/dll/win32/msacm32         # Autosync
 reactos/dll/win32/msadp32.acm     # Synced to Wine-1.3.37
 reactos/dll/win32/mscat32         # Synced to Wine-1.3.37
 reactos/dll/win32/mscms           # Synced to Wine-1.5.4
-reactos/dll/win32/mscoree         # Synced to Wine-1.3.37
+reactos/dll/win32/mscoree         # Synced to Wine-1.5.4
 reactos/dll/win32/msctf           # Synced to Wine-1.3.37
 reactos/dll/win32/msftedit        # Synced to Wine-1.3.37
 reactos/dll/win32/msg711.acm      # Synced to Wine-1.3.37