mscoree: Factor out common code for calling .NET methods.

This commit is contained in:
Vincent Povirk 2014-08-13 17:05:44 -05:00 committed by Alexandre Julliard
parent 88dfdded62
commit 1986e496c7
1 changed files with 92 additions and 145 deletions

View File

@ -153,23 +153,25 @@ static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
LeaveCriticalSection(&This->lock); LeaveCriticalSection(&This->lock);
} }
static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk) static HRESULT RuntimeHost_Invoke(RuntimeHost *This, MonoDomain *domain,
const char *assemblyname, const char *namespace, const char *typename, const char *methodname,
MonoObject *obj, void **args, int arg_count, MonoObject **result)
{ {
HRESULT hr;
void *args[1];
MonoAssembly *assembly; MonoAssembly *assembly;
MonoImage *image; MonoImage *image;
MonoClass *klass; MonoClass *klass;
MonoMethod *method; MonoMethod *method;
MonoObject *appdomain_object; MonoObject *exc;
IUnknown *unk; static const char *get_hresult = "get_HResult";
*result = NULL;
mono_thread_attach(domain); mono_thread_attach(domain);
assembly = mono_domain_assembly_open(domain, "mscorlib"); assembly = mono_domain_assembly_open(domain, assemblyname);
if (!assembly) if (!assembly)
{ {
ERR("Cannot load mscorlib\n"); ERR("Cannot load assembly\n");
return E_FAIL; return E_FAIL;
} }
@ -180,29 +182,57 @@ static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *d
return E_FAIL; return E_FAIL;
} }
klass = mono_class_from_name(image, "System", "AppDomain"); klass = mono_class_from_name(image, namespace, typename);
if (!klass) if (!klass)
{ {
ERR("Couldn't get class from image\n"); ERR("Couldn't get class from image\n");
return E_FAIL; return E_FAIL;
} }
method = mono_class_get_method_from_name(klass, "get_CurrentDomain", 0); method = mono_class_get_method_from_name(klass, methodname, arg_count);
if (!method) if (!method)
{ {
ERR("Couldn't get method from class\n"); ERR("Couldn't get method from class\n");
return E_FAIL; return E_FAIL;
} }
args[0] = NULL; *result = mono_runtime_invoke(method, obj, args, &exc);
appdomain_object = mono_runtime_invoke(method, NULL, args, NULL); if (exc)
if (!appdomain_object)
{ {
ERR("Couldn't get result pointer\n"); HRESULT hr;
return E_FAIL; MonoObject *hr_object;
if (methodname != get_hresult)
{
/* Map the exception to an HRESULT. */
hr = RuntimeHost_Invoke(This, domain, "mscorlib", "System", "Exception", get_hresult,
exc, NULL, 0, &hr_object);
if (SUCCEEDED(hr))
hr = *(HRESULT*)mono_object_unbox(hr_object);
if (SUCCEEDED(hr))
hr = E_FAIL;
}
else
hr = E_FAIL;
ERR("Method %s.%s raised an exception, hr=%x\n", namespace, typename, hr);
*result = NULL;
return hr;
} }
hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk); return S_OK;
}
static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
{
HRESULT hr;
MonoObject *appdomain_object;
IUnknown *unk;
hr = RuntimeHost_Invoke(This, domain, "mscorlib", "System", "AppDomain", "get_CurrentDomain",
NULL, NULL, 0, &appdomain_object);
if (SUCCEEDED(hr))
hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
@ -219,10 +249,7 @@ void RuntimeHost_ExitProcess(RuntimeHost *This, INT exitcode)
HRESULT hr; HRESULT hr;
void *args[2]; void *args[2];
MonoDomain *domain; MonoDomain *domain;
MonoAssembly *assembly; MonoObject *dummy;
MonoImage *image;
MonoClass *klass;
MonoMethod *method;
hr = RuntimeHost_GetDefaultDomain(This, &domain); hr = RuntimeHost_GetDefaultDomain(This, &domain);
if (FAILED(hr)) if (FAILED(hr))
@ -231,39 +258,10 @@ void RuntimeHost_ExitProcess(RuntimeHost *This, INT exitcode)
return; return;
} }
mono_thread_attach(domain);
assembly = mono_domain_assembly_open(domain, "mscorlib");
if (!assembly)
{
ERR("Cannot load mscorlib\n");
return;
}
image = mono_assembly_get_image(assembly);
if (!image)
{
ERR("Couldn't get assembly image\n");
return;
}
klass = mono_class_from_name(image, "System", "Environment");
if (!klass)
{
ERR("Couldn't get class from image\n");
return;
}
method = mono_class_get_method_from_name(klass, "Exit", 1);
if (!method)
{
ERR("Couldn't get method from class\n");
return;
}
args[0] = &exitcode; args[0] = &exitcode;
args[1] = NULL; args[1] = NULL;
mono_runtime_invoke(method, NULL, args, NULL); RuntimeHost_Invoke(This, domain, "mscorlib", "System", "Environment", "Exit",
NULL, args, 1, &dummy);
ERR("Process should have exited\n"); ERR("Process should have exited\n");
} }
@ -629,13 +627,8 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
HRESULT hr; HRESULT hr;
MonoDomain *domain; MonoDomain *domain;
MonoAssembly *assembly;
MonoImage *image;
MonoClass *klass;
MonoMethod *method;
MonoObject *result; MonoObject *result;
MonoString *str; MonoString *str;
void *args[2];
char *filenameA = NULL, *classA = NULL, *methodA = NULL; char *filenameA = NULL, *classA = NULL, *methodA = NULL;
char *argsA = NULL, *ns; char *argsA = NULL, *ns;
@ -643,66 +636,60 @@ static HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost*
debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument)); debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument));
hr = RuntimeHost_GetDefaultDomain(This, &domain); hr = RuntimeHost_GetDefaultDomain(This, &domain);
if(hr != S_OK)
if (SUCCEEDED(hr))
{ {
ERR("Couldn't get Default Domain\n"); mono_thread_attach(domain);
return hr;
filenameA = WtoA(pwzAssemblyPath);
if (!filenameA) hr = E_OUTOFMEMORY;
} }
hr = E_FAIL; if (SUCCEEDED(hr))
mono_thread_attach(domain);
filenameA = WtoA(pwzAssemblyPath);
assembly = mono_domain_assembly_open(domain, filenameA);
if (!assembly)
{ {
ERR("Cannot open assembly %s\n", filenameA); classA = WtoA(pwzTypeName);
goto cleanup; if (!classA) hr = E_OUTOFMEMORY;
} }
image = mono_assembly_get_image(assembly); if (SUCCEEDED(hr))
if (!image)
{ {
ERR("Couldn't get assembly image\n"); ns = strrchr(classA, '.');
goto cleanup; if (ns)
*ns = '\0';
else
hr = E_INVALIDARG;
} }
classA = WtoA(pwzTypeName); if (SUCCEEDED(hr))
ns = strrchr(classA, '.');
*ns = '\0';
klass = mono_class_from_name(image, classA, ns+1);
if (!klass)
{ {
ERR("Couldn't get class from image\n"); methodA = WtoA(pwzMethodName);
goto cleanup; if (!methodA) hr = E_OUTOFMEMORY;
}
methodA = WtoA(pwzMethodName);
method = mono_class_get_method_from_name(klass, methodA, 1);
if (!method)
{
ERR("Couldn't get method from class\n");
goto cleanup;
} }
/* The .NET function we are calling has the following declaration /* The .NET function we are calling has the following declaration
* public static int functionName(String param) * public static int functionName(String param)
*/ */
argsA = WtoA(pwzArgument); if (SUCCEEDED(hr))
str = mono_string_new(domain, argsA);
args[0] = str;
args[1] = NULL;
result = mono_runtime_invoke(method, NULL, args, NULL);
if (!result)
ERR("Couldn't get result pointer\n");
else
{ {
*pReturnValue = *(DWORD*)mono_object_unbox(result); argsA = WtoA(pwzArgument);
hr = S_OK; if (!argsA) hr = E_OUTOFMEMORY;
} }
cleanup: if (SUCCEEDED(hr))
{
str = mono_string_new(domain, argsA);
if (!str) hr = E_OUTOFMEMORY;
}
if (SUCCEEDED(hr))
{
hr = RuntimeHost_Invoke(This, domain, filenameA, classA, ns+1, methodA,
NULL, (void**)&str, 1, &result);
}
if (SUCCEEDED(hr))
*pReturnValue = *(DWORD*)mono_object_unbox(result);
HeapFree(GetProcessHeap(), 0, filenameA); HeapFree(GetProcessHeap(), 0, filenameA);
HeapFree(GetProcessHeap(), 0, classA); HeapFree(GetProcessHeap(), 0, classA);
HeapFree(GetProcessHeap(), 0, argsA); HeapFree(GetProcessHeap(), 0, argsA);
@ -807,60 +794,20 @@ HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
IUnknown **ppUnk) IUnknown **ppUnk)
{ {
MonoDomain *domain; MonoDomain *domain;
MonoAssembly *assembly;
MonoImage *image;
MonoClass *klass;
MonoMethod *method;
MonoObject *result; MonoObject *result;
void *args[2]; HRESULT hr;
domain = mono_object_get_domain(obj); domain = mono_object_get_domain(obj);
assembly = mono_domain_assembly_open(domain, "mscorlib"); hr = RuntimeHost_Invoke(This, domain, "mscorlib", "System.Runtime.InteropServices", "Marshal", "GetIUnknownForObject",
if (!assembly) NULL, (void**)&obj, 1, &result);
{
ERR("Cannot load mscorlib\n");
return E_FAIL;
}
image = mono_assembly_get_image(assembly); if (SUCCEEDED(hr))
if (!image) *ppUnk = *(IUnknown**)mono_object_unbox(result);
{ else
ERR("Couldn't get assembly image\n"); *ppUnk = NULL;
return E_FAIL;
}
klass = mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal"); return hr;
if (!klass)
{
ERR("Couldn't get class from image\n");
return E_FAIL;
}
method = mono_class_get_method_from_name(klass, "GetIUnknownForObject", 1);
if (!method)
{
ERR("Couldn't get method from class\n");
return E_FAIL;
}
args[0] = obj;
args[1] = NULL;
result = mono_runtime_invoke(method, NULL, args, NULL);
if (!result)
{
ERR("Couldn't get result pointer\n");
return E_FAIL;
}
*ppUnk = *(IUnknown**)mono_object_unbox(result);
if (!*ppUnk)
{
ERR("GetIUnknownForObject returned 0\n");
return E_FAIL;
}
return S_OK;
} }
static void get_utf8_args(int *argc, char ***argv) static void get_utf8_args(int *argc, char ***argv)