mscoree: Restore previous domain whenever we set it.

Vincent Povirk madewokherd at gmail.com
Tue Mar 8 15:49:26 CST 2016


From: Vincent Povirk <vincent at codeweavers.com>

Unmanaged APIs could be called directly or indirectly by managed code in any
domain, and we could create problems by not restoring the old one.

Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
---
 dlls/mscoree/corruntimehost.c  | 103 ++++++++++++++++++++++++++++++-----------
 dlls/mscoree/metahost.c        |   4 ++
 dlls/mscoree/mscoree_private.h |   4 +-
 3 files changed, 82 insertions(+), 29 deletions(-)

diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index 7fc6867..94eca7f 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -68,6 +68,25 @@ struct dll_fixup
     void *tokens; /* pointer into process heap */
 };
 
+static MonoDomain* domain_attach(MonoDomain *domain)
+{
+    MonoDomain *prev_domain = mono_domain_get();
+
+    if (prev_domain == domain)
+        /* Do not set or restore domain. */
+        return NULL;
+
+    mono_thread_attach(domain);
+
+    return prev_domain;
+}
+
+static void domain_restore(MonoDomain *prev_domain)
+{
+    if (prev_domain != NULL)
+        mono_domain_set(prev_domain, FALSE);
+}
+
 static HRESULT RuntimeHost_AddDefaultDomain(RuntimeHost *This, MonoDomain **result)
 {
     struct DomainEntry *entry;
@@ -267,15 +286,17 @@ static HRESULT RuntimeHost_Invoke(RuntimeHost *This, MonoDomain *domain,
     MonoObject *obj, void **args, int arg_count, MonoObject **result)
 {
     MonoMethod *method;
+    MonoDomain *prev_domain;
     HRESULT hr;
 
     *result = NULL;
 
-    mono_thread_attach(domain);
+    prev_domain = domain_attach(domain);
 
     if (!RuntimeHost_GetMethod(domain, assemblyname, namespace, typename, methodname,
             arg_count, &method))
     {
+        domain_restore(prev_domain);
         return E_FAIL;
     }
 
@@ -285,6 +306,8 @@ static HRESULT RuntimeHost_Invoke(RuntimeHost *This, MonoDomain *domain,
         ERR("Method %s.%s:%s raised an exception, hr=%x\n", namespace, typename, methodname, hr);
     }
 
+    domain_restore(prev_domain);
+
     return hr;
 }
 
@@ -293,6 +316,7 @@ static HRESULT RuntimeHost_VirtualInvoke(RuntimeHost *This, MonoDomain *domain,
     MonoObject *obj, void **args, int arg_count, MonoObject **result)
 {
     MonoMethod *method;
+    MonoDomain *prev_domain;
     HRESULT hr;
 
     *result = NULL;
@@ -303,11 +327,12 @@ static HRESULT RuntimeHost_VirtualInvoke(RuntimeHost *This, MonoDomain *domain,
         return E_POINTER;
     }
 
-    mono_thread_attach(domain);
+    prev_domain = domain_attach(domain);
 
     if (!RuntimeHost_GetMethod(domain, assemblyname, namespace, typename, methodname,
             arg_count, &method))
     {
+        domain_restore(prev_domain);
         return E_FAIL;
     }
 
@@ -315,6 +340,7 @@ static HRESULT RuntimeHost_VirtualInvoke(RuntimeHost *This, MonoDomain *domain,
     if (!method)
     {
         ERR("Object %p does not support method %s.%s:%s\n", obj, namespace, typename, methodname);
+        domain_restore(prev_domain);
         return E_FAIL;
     }
 
@@ -324,6 +350,8 @@ static HRESULT RuntimeHost_VirtualInvoke(RuntimeHost *This, MonoDomain *domain,
         ERR("Method %s.%s:%s raised an exception, hr=%x\n", namespace, typename, methodname, hr);
     }
 
+    domain_restore(prev_domain);
+
     return hr;
 }
 
@@ -853,7 +881,7 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
 {
     RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
     HRESULT hr;
-    MonoDomain *domain;
+    MonoDomain *domain, *prev_domain;
     MonoObject *result;
     MonoString *str;
     char *filenameA = NULL, *classA = NULL, *methodA = NULL;
@@ -864,10 +892,13 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
 
     hr = RuntimeHost_GetDefaultDomain(This, NULL, &domain);
 
+    if (FAILED(hr))
+        return hr;
+
+    prev_domain = domain_attach(domain);
+
     if (SUCCEEDED(hr))
     {
-        mono_thread_attach(domain);
-
         filenameA = WtoA(pwzAssemblyPath);
         if (!filenameA) hr = E_OUTOFMEMORY;
     }
@@ -917,6 +948,8 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
     if (SUCCEEDED(hr))
         *pReturnValue = *(DWORD*)mono_object_unbox(result);
 
+    domain_restore(prev_domain);
+
     HeapFree(GetProcessHeap(), 0, filenameA);
     HeapFree(GetProcessHeap(), 0, classA);
     HeapFree(GetProcessHeap(), 0, argsA);
@@ -952,10 +985,16 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
     MonoType *type;
     MonoClass *klass;
     MonoObject *obj;
+    MonoDomain *prev_domain;
 
     if (!domain)
         hr = RuntimeHost_GetDefaultDomain(This, NULL, &domain);
 
+    if (FAILED(hr))
+        return hr;
+
+    prev_domain = domain_attach(domain);
+
     if (SUCCEEDED(hr))
     {
         nameA = WtoA(name);
@@ -965,8 +1004,6 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
 
     if (SUCCEEDED(hr))
     {
-        mono_thread_attach(domain);
-
         type = mono_reflection_type_from_name(nameA, NULL);
         if (!type)
         {
@@ -1002,6 +1039,8 @@ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
         *result = obj;
     }
 
+    domain_restore(prev_domain);
+
     HeapFree(GetProcessHeap(), 0, nameA);
 
     return hr;
@@ -1014,9 +1053,7 @@ 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.
- *
- * mono_thread_attach must have already been called for this thread. */
+ * garbage collector from freeing them. */
 HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
     IUnknown **ppUnk)
 {
@@ -1230,35 +1267,39 @@ static void CDECL ReallyFixupVTable(struct dll_fixup *fixup)
 
     if (SUCCEEDED(hr))
     {
-        mono_thread_attach(domain);
+        MonoDomain *prev_domain;
+
+        prev_domain = domain_attach(domain);
 
         assembly = mono_assembly_open(filenameA, &status);
-    }
 
-    if (assembly)
-    {
-        int i;
+        if (assembly)
+        {
+            int i;
 
-        /* Mono needs an image that belongs to an assembly. */
-        image = mono_assembly_get_image(assembly);
+            /* Mono needs an image that belongs to an assembly. */
+            image = mono_assembly_get_image(assembly);
 
 #if __x86_64__
-        if (fixup->fixup->type & COR_VTABLE_64BIT)
+            if (fixup->fixup->type & COR_VTABLE_64BIT)
 #else
-        if (fixup->fixup->type & COR_VTABLE_32BIT)
+            if (fixup->fixup->type & COR_VTABLE_32BIT)
 #endif
-        {
-            void **vtable = fixup->vtable;
-            ULONG_PTR *tokens = fixup->tokens;
-            for (i=0; i<fixup->fixup->count; i++)
             {
-                TRACE("%#lx\n", tokens[i]);
-                vtable[i] = mono_marshal_get_vtfixup_ftnptr(
-                    image, tokens[i], fixup->fixup->type);
+                void **vtable = fixup->vtable;
+                ULONG_PTR *tokens = fixup->tokens;
+                for (i=0; i<fixup->fixup->count; i++)
+                {
+                    TRACE("%#lx\n", tokens[i]);
+                    vtable[i] = mono_marshal_get_vtfixup_ftnptr(
+                        image, tokens[i], fixup->fixup->type);
+                }
             }
+
+            fixup->done = TRUE;
         }
 
-        fixup->done = TRUE;
+        domain_restore(prev_domain);
     }
 
     if (info != NULL)
@@ -1686,13 +1727,14 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
             MonoImage *image;
             MonoClass *klass;
             MonoObject *result;
+            MonoDomain *prev_domain;
             IUnknown *unk = NULL;
             char *filenameA, *ns;
             char *classA;
 
             hr = CLASS_E_CLASSNOTAVAILABLE;
 
-            mono_thread_attach(domain);
+            prev_domain = domain_attach(domain);
 
             filenameA = WtoA(filename);
             assembly = mono_domain_assembly_open(domain, filenameA);
@@ -1700,6 +1742,7 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
             if (!assembly)
             {
                 ERR("Cannot open assembly %s\n", filenameA);
+                domain_restore(prev_domain);
                 goto cleanup;
             }
 
@@ -1707,6 +1750,7 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
             if (!image)
             {
                 ERR("Couldn't get assembly image\n");
+                domain_restore(prev_domain);
                 goto cleanup;
             }
 
@@ -1719,6 +1763,7 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
             if (!klass)
             {
                 ERR("Couldn't get class from image\n");
+                domain_restore(prev_domain);
                 goto cleanup;
             }
 
@@ -1737,6 +1782,8 @@ HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
             }
             else
                 hr = CLASS_E_CLASSNOTAVAILABLE;
+
+            domain_restore(prev_domain);
         }
         else
             hr = CLASS_E_CLASSNOTAVAILABLE;
diff --git a/dlls/mscoree/metahost.c b/dlls/mscoree/metahost.c
index 201757d..ca6914e 100644
--- a/dlls/mscoree/metahost.c
+++ b/dlls/mscoree/metahost.c
@@ -79,7 +79,9 @@ MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_spac
 MonoMethod* (CDECL *mono_class_get_method_from_name)(MonoClass *klass, const char *name, int param_count);
 static void (CDECL *mono_config_parse)(const char *filename);
 MonoAssembly* (CDECL *mono_domain_assembly_open)(MonoDomain *domain, const char *name);
+MonoDomain* (CDECL *mono_domain_get)(void);
 MonoDomain* (CDECL *mono_domain_get_by_id)(int id);
+BOOL (CDECL *mono_domain_set)(MonoDomain *domain,BOOL force);
 void (CDECL *mono_domain_set_config)(MonoDomain *domain,const char *base_dir,const char *config_file_name);
 static void (CDECL *mono_free)(void *);
 static MonoImage* (CDECL *mono_image_open)(const char *fname, MonoImageOpenStatus *status);
@@ -177,7 +179,9 @@ static HRESULT load_mono(LPCWSTR mono_path)
         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_domain_get);
         LOAD_MONO_FUNCTION(mono_domain_get_by_id);
+        LOAD_MONO_FUNCTION(mono_domain_set);
         LOAD_MONO_FUNCTION(mono_domain_set_config);
         LOAD_MONO_FUNCTION(mono_free);
         LOAD_MONO_FUNCTION(mono_image_open);
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index c739949..9df41d2 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -146,7 +146,9 @@ extern MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type) DECLSPEC_HI
 extern MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name) DECLSPEC_HIDDEN;
 extern MonoMethod* (CDECL *mono_class_get_method_from_name)(MonoClass *klass, const char *name, int param_count) DECLSPEC_HIDDEN;
 extern MonoAssembly* (CDECL *mono_domain_assembly_open)(MonoDomain *domain, const char *name) DECLSPEC_HIDDEN;
-extern MonoDomain* (CDECL *mono_domain_get_by_id)(int id);
+extern MonoDomain* (CDECL *mono_domain_get)(void) DECLSPEC_HIDDEN;
+extern MonoDomain* (CDECL *mono_domain_get_by_id)(int id) DECLSPEC_HIDDEN;
+extern BOOL (CDECL *mono_domain_set)(MonoDomain *domain, BOOL force) DECLSPEC_HIDDEN;
 extern void (CDECL *mono_domain_set_config)(MonoDomain *domain,const char *base_dir,const char *config_file_name) DECLSPEC_HIDDEN;
 extern int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]) DECLSPEC_HIDDEN;
 extern MonoDomain* (CDECL *mono_jit_init_version)(const char *domain_name, const char *runtime_version) DECLSPEC_HIDDEN;
-- 
2.5.0




More information about the wine-patches mailing list