mscoree: Restore previous domain whenever we set it.

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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Vincent Povirk 2016-03-08 15:49:26 -06:00 committed by Alexandre Julliard
parent 6ff1f38ba2
commit 4dec065e2b
3 changed files with 82 additions and 29 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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;