/* Create an instance of a type given its name, by calling its constructor with * no arguments. Note that result MUST be in the stack, or the garbage * collector may free it prematurely. */ HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name, MonoDomain *domain, MonoObject **result) { HRESULT hr=S_OK; char *nameA=NULL; MonoType *type; MonoClass *klass; MonoObject *obj; if (!domain) hr = RuntimeHost_GetDefaultDomain(This, &domain); if (SUCCEEDED(hr)) { nameA = WtoA(name); if (!nameA) hr = E_OUTOFMEMORY; } if (SUCCEEDED(hr)) { type = This->mono->mono_reflection_type_from_name(nameA, NULL); if (!type) { ERR("Cannot find type %s\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { klass = This->mono->mono_class_from_mono_type(type); if (!klass) { ERR("Cannot convert type %s to a class\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { obj = This->mono->mono_object_new(domain, klass); if (!obj) { ERR("Cannot allocate object of type %s\n", debugstr_w(name)); hr = E_FAIL; } } if (SUCCEEDED(hr)) { /* FIXME: Detect exceptions from the constructor? */ This->mono->mono_runtime_object_init(obj); *result = obj; } HeapFree(GetProcessHeap(), 0, nameA); return hr; }
__int32 WINAPI _CorExeMain(void) { int exit_code; int argc; char **argv; MonoDomain *domain; MonoAssembly *assembly; WCHAR filename[MAX_PATH]; char *filenameA; ICLRRuntimeInfo *info; RuntimeHost *host; HRESULT hr; int i; get_utf8_args(&argc, &argv); GetModuleFileNameW(NULL, filename, MAX_PATH); TRACE("%s", debugstr_w(filename)); for (i=0; i<argc; i++) TRACE(" %s", debugstr_a(argv[i])); TRACE("\n"); filenameA = WtoA(filename); if (!filenameA) return -1; 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)) { assembly = host->mono->mono_domain_assembly_open(domain, filenameA); exit_code = host->mono->mono_jit_exec(domain, assembly, argc, argv); RuntimeHost_DeleteDomain(host, domain); } else exit_code = -1; ICLRRuntimeInfo_Release(info); } else exit_code = -1; HeapFree(GetProcessHeap(), 0, argv); unload_all_runtimes(); return exit_code; }
void RuntimeHost_ExitProcess(RuntimeHost *This, INT exitcode) { HRESULT hr; void *args[2]; MonoDomain *domain; MonoAssembly *assembly; MonoImage *image; MonoClass *klass; MonoMethod *method; hr = RuntimeHost_GetDefaultDomain(This, &domain); if (FAILED(hr)) { ERR("Cannot get domain, hr=%x\n", hr); 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[1] = NULL; mono_runtime_invoke(method, NULL, args, NULL); ERR("Process should have exited\n"); }
static HRESULT WINAPI corruntimehost_GetDefaultDomain( ICorRuntimeHost* iface, IUnknown **pAppDomain) { RuntimeHost *This = impl_from_ICorRuntimeHost( iface ); HRESULT hr; MonoDomain *domain; TRACE("(%p)\n", iface); hr = RuntimeHost_GetDefaultDomain(This, &domain); if (SUCCEEDED(hr)) { hr = RuntimeHost_GetIUnknownForDomain(This, domain, pAppDomain); } return hr; }
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)) { mono_thread_attach(domain); assembly = mono_assembly_open(filenameA, &status); } if (assembly) { int i; /* Mono needs an image that belongs to an assembly. */ image = 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(mono_marshal_get_vtfixup_ftnptr( image, tokens[i], fixup->fixup->type)); } } fixup->done = TRUE; } if (info != NULL) ICLRRuntimeInfo_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 HRESULT WINAPI CLRRuntimeHost_ExecuteInDefaultAppDomain(ICLRRuntimeHost* iface, LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName, LPCWSTR pwzArgument, DWORD *pReturnValue) { RuntimeHost *This = impl_from_ICLRRuntimeHost( iface ); HRESULT hr; MonoDomain *domain; MonoAssembly *assembly; MonoImage *image; MonoClass *klass; MonoMethod *method; MonoObject *result; MonoString *str; void *args[2]; char *filenameA = NULL, *classA = NULL, *methodA = NULL; char *argsA = NULL, *ns; TRACE("(%p,%s,%s,%s,%s)\n", iface, debugstr_w(pwzAssemblyPath), debugstr_w(pwzTypeName), debugstr_w(pwzMethodName), debugstr_w(pwzArgument)); hr = RuntimeHost_GetDefaultDomain(This, &domain); if(hr != S_OK) { ERR("Couldn't get Default Domain\n"); return hr; } hr = E_FAIL; mono_thread_attach(domain); filenameA = WtoA(pwzAssemblyPath); assembly = mono_domain_assembly_open(domain, filenameA); if (!assembly) { ERR("Cannot open assembly %s\n", filenameA); goto cleanup; } image = mono_assembly_get_image(assembly); if (!image) { ERR("Couldn't get assembly image\n"); goto cleanup; } classA = WtoA(pwzTypeName); ns = strrchr(classA, '.'); *ns = '\0'; klass = mono_class_from_name(image, classA, ns+1); if (!klass) { ERR("Couldn't get class from image\n"); goto cleanup; } 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 * public static int functionName(String param) */ argsA = WtoA(pwzArgument); 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); hr = S_OK; } cleanup: HeapFree(GetProcessHeap(), 0, filenameA); HeapFree(GetProcessHeap(), 0, classA); HeapFree(GetProcessHeap(), 0, argsA); HeapFree(GetProcessHeap(), 0, methodA); return hr; }
HRESULT create_monodata(REFIID riid, LPVOID *ppObj ) { static const WCHAR wszAssembly[] = {'A','s','s','e','m','b','l','y',0}; 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}; static const WCHAR wszDLL[] = {'.','d','l','l',0}; WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1]; MonoDomain *domain; MonoAssembly *assembly; ICLRRuntimeInfo *info = NULL; RuntimeHost *host; HRESULT hr; HKEY key, subkey; LONG res; int offset = 0; DWORD numKeys, keyLength; WCHAR codebase[MAX_PATH + 8]; WCHAR classname[350], subkeyName[256]; 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) { /* Strip file:/// */ if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0) offset = strlenW(wszFileSlash); strcpyW(filename, codebase + offset); } else { WCHAR assemblyname[MAX_PATH + 8]; hr = CLASS_E_CLASSNOTAVAILABLE; WARN("CodeBase value cannot be found, trying Assembly.\n"); /* get the last subkey of InprocServer32 */ res = RegQueryInfoKeyW(key, 0, 0, 0, &numKeys, 0, 0, 0, 0, 0, 0, 0); if (res != ERROR_SUCCESS || numKeys == 0) goto cleanup; numKeys--; keyLength = sizeof(subkeyName) / sizeof(WCHAR); res = RegEnumKeyExW(key, numKeys, subkeyName, &keyLength, 0, 0, 0, 0); if (res != ERROR_SUCCESS) goto cleanup; res = RegOpenKeyExW(key, subkeyName, 0, KEY_READ, &subkey); if (res != ERROR_SUCCESS) goto cleanup; dwBufLen = MAX_PATH + 8; res = RegGetValueW(subkey, NULL, wszAssembly, RRF_RT_REG_SZ, NULL, assemblyname, &dwBufLen); RegCloseKey(subkey); if (res != ERROR_SUCCESS) goto cleanup; hr = get_file_from_strongname(assemblyname, filename, MAX_PATH); if (!SUCCEEDED(hr)) { /* * The registry doesn't have a CodeBase entry and it's not in the GAC. * * Use the Assembly Key to retrieve the filename. * Assembly : REG_SZ : AssemblyName, Version=X.X.X.X, Culture=neutral, PublicKeyToken=null */ WCHAR *ns; WARN("Attempt to load from the application directory.\n"); GetModuleFileNameW(NULL, filename, MAX_PATH); ns = strrchrW(filename, '\\'); *(ns+1) = '\0'; ns = strchrW(assemblyname, ','); *(ns) = '\0'; strcatW(filename, assemblyname); *(ns) = '.'; strcatW(filename, wszDLL); } } TRACE("filename (%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; mono_thread_attach(domain); filenameA = WtoA(filename); assembly = mono_domain_assembly_open(domain, filenameA); HeapFree(GetProcessHeap(), 0, filenameA); if (!assembly) { ERR("Cannot open assembly %s\n", filenameA); goto cleanup; } image = 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 = 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 = mono_object_new(domain, klass); 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; }
__int32 WINAPI _CorExeMain(void) { int exit_code; int argc; char **argv; MonoDomain *domain=NULL; MonoImage *image; MonoImageOpenStatus status; MonoAssembly *assembly=NULL; WCHAR filename[MAX_PATH]; char *filenameA; ICLRRuntimeInfo *info; RuntimeHost *host; HRESULT hr; int i; get_utf8_args(&argc, &argv); GetModuleFileNameW(NULL, filename, MAX_PATH); TRACE("%s", debugstr_w(filename)); for (i=0; i<argc; i++) TRACE(" %s", debugstr_a(argv[i])); TRACE("\n"); filenameA = WtoA(filename); if (!filenameA) return -1; FixupVTable(GetModuleHandleW(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)) { image = mono_image_open_from_module_handle(GetModuleHandleW(NULL), filenameA, 1, &status); if (image) assembly = mono_assembly_load_from(image, filenameA, &status); if (assembly) { mono_trace_set_assembly(assembly); exit_code = 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); } else exit_code = -1; ICLRRuntimeInfo_Release(info); } else exit_code = -1; HeapFree(GetProcessHeap(), 0, argv); if (domain) { mono_thread_manage(); mono_jit_cleanup(domain); } return exit_code; }
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; }