* Sync to Wine 1.3.37.
svn path=/trunk/; revision=55276
add_definitions(-D__WINESRC__)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
+set_rc_compiler()
spec2def(mscoree.dll mscoree.spec)
list(APPEND SOURCE
+ assembly.c
+ config.c
+ cordebug.c
corruntimehost.c
+ metadata.c
+ metahost.c
mscoree_main.c
+ mscoree.rc
${CMAKE_CURRENT_BINARY_DIR}/mscoree_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/mscoree.def)
set_module_type(mscoree win32dll)
target_link_libraries(mscoree wine uuid)
-add_importlibs(mscoree advapi32 shell32 msvcrt kernel32 ntdll)
+
+if(MSVC)
+ target_link_libraries(mscoree xml_uuids)
+endif()
+
+add_importlibs(mscoree dbghelp advapi32 shell32 ole32 shlwapi msvcrt kernel32 ntdll)
add_cd_file(TARGET mscoree DESTINATION reactos/system32 FOR all)
--- /dev/null
+/*
+ * assembly parser
+ *
+ * Copyright 2008 James Hawkins
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winver.h"
+#include "dbghelp.h"
+#include "ole2.h"
+#include "mscoree.h"
+#include "corhdr.h"
+#include "metahost.h"
+#include "cordebug.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+
+typedef struct
+{
+ ULONG Signature;
+ USHORT MajorVersion;
+ USHORT MinorVersion;
+ ULONG Reserved;
+ ULONG VersionLength;
+ LPSTR Version;
+ BYTE Flags;
+ WORD Streams;
+} METADATAHDR;
+
+typedef struct
+{
+ DWORD Offset;
+ DWORD Size;
+} METADATASTREAMHDR;
+
+typedef struct tagCLRTABLE
+{
+ INT rows;
+ DWORD offset;
+} CLRTABLE;
+
+struct tagASSEMBLY
+{
+ LPWSTR path;
+
+ HANDLE hfile;
+ HANDLE hmap;
+ BYTE *data;
+
+ IMAGE_NT_HEADERS *nthdr;
+ IMAGE_COR20_HEADER *corhdr;
+
+ METADATAHDR *metadatahdr;
+};
+
+static inline LPWSTR strdupW(LPCWSTR src)
+{
+ LPWSTR dest;
+
+ if (!src)
+ return NULL;
+
+ dest = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(src) + 1) * sizeof(WCHAR));
+ if (dest)
+ lstrcpyW(dest, src);
+
+ return dest;
+}
+
+static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
+{
+ METADATAHDR *metadatahdr;
+ BYTE *ptr, *dest;
+ DWORD size, ofs;
+ ULONG rva;
+
+ rva = assembly->corhdr->MetaData.VirtualAddress;
+ ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva, NULL);
+ if (!ptr)
+ return E_FAIL;
+
+ metadatahdr = (METADATAHDR *)ptr;
+
+ assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR));
+ if (!assembly->metadatahdr)
+ return E_OUTOFMEMORY;
+
+ size = FIELD_OFFSET(METADATAHDR, Version);
+ memcpy(assembly->metadatahdr, metadatahdr, size);
+
+ assembly->metadatahdr->Version = (LPSTR)&metadatahdr->Version;
+
+ ofs = FIELD_OFFSET(METADATAHDR, Flags);
+ ptr += FIELD_OFFSET(METADATAHDR, Version) + metadatahdr->VersionLength + 1;
+ dest = (BYTE *)assembly->metadatahdr + ofs;
+ memcpy(dest, ptr, sizeof(METADATAHDR) - ofs);
+
+ *hdrsz = sizeof(METADATAHDR) - sizeof(LPSTR) + metadatahdr->VersionLength + 1;
+
+ return S_OK;
+}
+
+static HRESULT parse_clr_metadata(ASSEMBLY *assembly)
+{
+ HRESULT hr;
+ DWORD hdrsz;
+
+ hr = parse_metadata_header(assembly, &hdrsz);
+ if (FAILED(hr))
+ return hr;
+
+ return S_OK;
+}
+
+static HRESULT parse_pe_header(ASSEMBLY *assembly)
+{
+ IMAGE_DATA_DIRECTORY *datadirs;
+
+ assembly->nthdr = ImageNtHeader(assembly->data);
+ if (!assembly->nthdr)
+ return E_FAIL;
+
+ if (assembly->nthdr->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+ {
+ IMAGE_OPTIONAL_HEADER64 *opthdr =
+ (IMAGE_OPTIONAL_HEADER64 *)&assembly->nthdr->OptionalHeader;
+ datadirs = opthdr->DataDirectory;
+ }
+ else
+ {
+ IMAGE_OPTIONAL_HEADER32 *opthdr =
+ (IMAGE_OPTIONAL_HEADER32 *)&assembly->nthdr->OptionalHeader;
+ datadirs = opthdr->DataDirectory;
+ }
+
+ 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)
+ return E_FAIL;
+
+ return S_OK;
+}
+
+HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
+{
+ ASSEMBLY *assembly;
+ HRESULT hr;
+
+ *out = NULL;
+
+ assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
+ if (!assembly)
+ return E_OUTOFMEMORY;
+
+ assembly->path = strdupW(file);
+ if (!assembly->path)
+ {
+ hr = E_OUTOFMEMORY;
+ goto failed;
+ }
+
+ assembly->hfile = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (assembly->hfile == INVALID_HANDLE_VALUE)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto failed;
+ }
+
+ assembly->hmap = CreateFileMappingW(assembly->hfile, NULL, PAGE_READONLY,
+ 0, 0, NULL);
+ if (!assembly->hmap)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto failed;
+ }
+
+ assembly->data = MapViewOfFile(assembly->hmap, FILE_MAP_READ, 0, 0, 0);
+ if (!assembly->data)
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ goto failed;
+ }
+
+ hr = parse_pe_header(assembly);
+ if (FAILED(hr)) goto failed;
+
+ hr = parse_clr_metadata(assembly);
+ if (FAILED(hr)) goto failed;
+
+ *out = assembly;
+ return S_OK;
+
+failed:
+ assembly_release(assembly);
+ return hr;
+}
+
+HRESULT assembly_release(ASSEMBLY *assembly)
+{
+ if (!assembly)
+ return S_OK;
+
+ 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;
+}
+
+HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version)
+{
+ *version = assembly->metadatahdr->Version;
+
+ return S_OK;
+}
--- /dev/null
+/*
+ * Configuration file parsing
+ *
+ * Copyright 2010 Vincent Povirk
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "msxml2.h"
+#include "mscoree.h"
+#include "corhdr.h"
+#include "metahost.h"
+#include "cordebug.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
+#include "shlwapi.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+enum parse_state
+{
+ STATE_ROOT,
+ STATE_CONFIGURATION,
+ STATE_STARTUP,
+ STATE_UNKNOWN
+};
+
+typedef struct ConfigFileHandler
+{
+ ISAXContentHandler ISAXContentHandler_iface;
+ ISAXErrorHandler ISAXErrorHandler_iface;
+ LONG ref;
+ enum parse_state states[16];
+ int statenum;
+ parsed_config_file *result;
+} ConfigFileHandler;
+
+static inline ConfigFileHandler *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
+{
+ return CONTAINING_RECORD(iface, ConfigFileHandler, ISAXContentHandler_iface);
+}
+
+static inline ConfigFileHandler *impl_from_ISAXErrorHandler(ISAXErrorHandler *iface)
+{
+ return CONTAINING_RECORD(iface, ConfigFileHandler, ISAXErrorHandler_iface);
+}
+
+static HRESULT WINAPI ConfigFileHandler_QueryInterface(ISAXContentHandler *iface,
+ REFIID riid, void **ppvObject)
+{
+ if (IsEqualGUID(riid, &IID_ISAXContentHandler) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ WARN("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ISAXContentHandler_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI ConfigFileHandler_AddRef(ISAXContentHandler *iface)
+{
+ ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
+ return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI ConfigFileHandler_Release(ISAXContentHandler *iface)
+{
+ ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ if (ref == 0)
+ HeapFree(GetProcessHeap(), 0, This);
+
+ return ref;
+}
+
+static HRESULT WINAPI ConfigFileHandler_putDocumentLocator(ISAXContentHandler *iface,
+ ISAXLocator *pLocator)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_startDocument(ISAXContentHandler *iface)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_endDocument(ISAXContentHandler *iface)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_startPrefixMapping(ISAXContentHandler *iface,
+ const WCHAR *pPrefix, int nPrefix, const WCHAR *pUri, int nUri)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_endPrefixMapping(ISAXContentHandler *iface,
+ const WCHAR *pPrefix, int nPrefix)
+{
+ return S_OK;
+}
+
+static HRESULT parse_startup(ConfigFileHandler *This, ISAXAttributes *pAttr)
+{
+ static const WCHAR legacy[] = {'u','s','e','L','e','g','a','c','y','V','2','R','u','n','t','i','m','e','A','c','t','i','v','a','t','i','o','n','P','o','l','i','c','y',0};
+ static const WCHAR empty[] = {0};
+ LPCWSTR value;
+ int value_size;
+ HRESULT hr;
+
+ hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, legacy, lstrlenW(legacy), &value, &value_size);
+ if (SUCCEEDED(hr))
+ FIXME("useLegacyV2RuntimeActivationPolicy=%s not implemented\n", debugstr_wn(value, value_size));
+ hr = S_OK;
+
+ return hr;
+}
+
+static HRESULT parse_supported_runtime(ConfigFileHandler *This, ISAXAttributes *pAttr)
+{
+ static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
+ static const WCHAR sku[] = {'s','k','u',0};
+ static const WCHAR empty[] = {0};
+ LPCWSTR value;
+ int value_size;
+ HRESULT hr;
+ supported_runtime *entry;
+
+ hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, version, lstrlenW(version), &value, &value_size);
+ if (SUCCEEDED(hr))
+ {
+ TRACE("%s\n", debugstr_wn(value, value_size));
+ entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
+ if (entry)
+ {
+ entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
+ if (entry->version)
+ {
+ lstrcpyW(entry->version, value);
+ list_add_tail(&This->result->supported_runtimes, &entry->entry);
+ }
+ else
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ hr = E_OUTOFMEMORY;
+ }
+ }
+ else
+ hr = E_OUTOFMEMORY;
+ }
+ else
+ WARN("Missing version attribute\n");
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, sku, lstrlenW(sku), &value, &value_size);
+ if (SUCCEEDED(hr))
+ FIXME("sku=%s not implemented\n", debugstr_wn(value, value_size));
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
+ const WCHAR *pNamespaceUri, int nNamespaceUri, const WCHAR *pLocalName,
+ int nLocalName, const WCHAR *pQName, int nQName, ISAXAttributes *pAttr)
+{
+ ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
+ static const WCHAR configuration[] = {'c','o','n','f','i','g','u','r','a','t','i','o','n',0};
+ static const WCHAR startup[] = {'s','t','a','r','t','u','p',0};
+ static const WCHAR supportedRuntime[] = {'s','u','p','p','o','r','t','e','d','R','u','n','t','i','m','e',0};
+ HRESULT hr = S_OK;
+
+ TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri,nNamespaceUri),
+ debugstr_wn(pLocalName,nLocalName), debugstr_wn(pQName,nQName));
+
+ if (This->statenum == sizeof(This->states) / sizeof(This->states[0]) - 1)
+ {
+ ERR("file has too much nesting\n");
+ return E_FAIL;
+ }
+
+ switch (This->states[This->statenum])
+ {
+ case STATE_ROOT:
+ if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
+ lstrcmpW(pLocalName, configuration) == 0)
+ {
+ This->states[++This->statenum] = STATE_CONFIGURATION;
+ break;
+ }
+ else
+ goto unknown;
+ case STATE_CONFIGURATION:
+ if (nLocalName == sizeof(startup)/sizeof(WCHAR)-1 &&
+ lstrcmpW(pLocalName, startup) == 0)
+ {
+ hr = parse_startup(This, pAttr);
+ This->states[++This->statenum] = STATE_STARTUP;
+ break;
+ }
+ else
+ goto unknown;
+ case STATE_STARTUP:
+ if (nLocalName == sizeof(supportedRuntime)/sizeof(WCHAR)-1 &&
+ lstrcmpW(pLocalName, supportedRuntime) == 0)
+ {
+ hr = parse_supported_runtime(This, pAttr);
+ This->states[++This->statenum] = STATE_UNKNOWN;
+ break;
+ }
+ else
+ goto unknown;
+ default:
+ goto unknown;
+ }
+
+ return hr;
+
+unknown:
+ FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName,nLocalName),
+ This->states[This->statenum]);
+
+ This->states[++This->statenum] = STATE_UNKNOWN;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_endElement(ISAXContentHandler *iface,
+ const WCHAR *pNamespaceUri, int nNamespaceUri, const WCHAR *pLocalName,
+ int nLocalName, const WCHAR *pQName, int nQName)
+{
+ ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
+
+ TRACE("%s %s %s\n", debugstr_wn(pNamespaceUri,nNamespaceUri),
+ debugstr_wn(pLocalName,nLocalName), debugstr_wn(pQName,nQName));
+
+ if (This->statenum > 0)
+ {
+ This->statenum--;
+ }
+ else
+ {
+ ERR("element end does not match a start\n");
+ return E_FAIL;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_characters(ISAXContentHandler *iface,
+ const WCHAR *pChars, int nChars)
+{
+ TRACE("%s\n", debugstr_wn(pChars,nChars));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_ignorableWhitespace(ISAXContentHandler *iface,
+ const WCHAR *pChars, int nChars)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_processingInstruction(ISAXContentHandler *iface,
+ const WCHAR *pTarget, int nTarget, const WCHAR *pData, int nData)
+{
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_skippedEntity(ISAXContentHandler *iface,
+ const WCHAR * pName, int nName)
+{
+ TRACE("%s\n", debugstr_wn(pName,nName));
+ return S_OK;
+}
+
+static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl =
+{
+ ConfigFileHandler_QueryInterface,
+ ConfigFileHandler_AddRef,
+ ConfigFileHandler_Release,
+ ConfigFileHandler_putDocumentLocator,
+ ConfigFileHandler_startDocument,
+ ConfigFileHandler_endDocument,
+ ConfigFileHandler_startPrefixMapping,
+ ConfigFileHandler_endPrefixMapping,
+ ConfigFileHandler_startElement,
+ ConfigFileHandler_endElement,
+ ConfigFileHandler_characters,
+ ConfigFileHandler_ignorableWhitespace,
+ ConfigFileHandler_processingInstruction,
+ ConfigFileHandler_skippedEntity
+};
+
+static HRESULT WINAPI ConfigFileHandler_Error_QueryInterface(ISAXErrorHandler *iface,
+ REFIID riid, void **ppvObject)
+{
+ if (IsEqualGUID(riid, &IID_ISAXErrorHandler) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ WARN("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ISAXErrorHandler_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI ConfigFileHandler_Error_AddRef(ISAXErrorHandler *iface)
+{
+ ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
+ return IUnknown_AddRef((IUnknown*)This);
+}
+
+static ULONG WINAPI ConfigFileHandler_Error_Release(ISAXErrorHandler *iface)
+{
+ ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
+ return IUnknown_Release((IUnknown*)This);
+}
+
+static HRESULT WINAPI ConfigFileHandler_error(ISAXErrorHandler *iface,
+ ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
+{
+ WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_fatalError(ISAXErrorHandler *iface,
+ ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
+{
+ WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
+ return S_OK;
+}
+
+static HRESULT WINAPI ConfigFileHandler_ignorableWarning(ISAXErrorHandler *iface,
+ ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
+{
+ WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
+ return S_OK;
+}
+
+static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl =
+{
+ ConfigFileHandler_Error_QueryInterface,
+ ConfigFileHandler_Error_AddRef,
+ ConfigFileHandler_Error_Release,
+ ConfigFileHandler_error,
+ ConfigFileHandler_fatalError,
+ ConfigFileHandler_ignorableWarning
+};
+
+static void init_config(parsed_config_file *config)
+{
+ list_init(&config->supported_runtimes);
+}
+
+static HRESULT parse_config(VARIANT input, parsed_config_file *result)
+{
+ ISAXXMLReader *reader;
+ ConfigFileHandler *handler;
+ HRESULT hr;
+
+ handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
+ if (!handler)
+ return E_OUTOFMEMORY;
+
+ handler->ISAXContentHandler_iface.lpVtbl = &ConfigFileHandlerVtbl;
+ handler->ISAXErrorHandler_iface.lpVtbl = &ConfigFileHandlerErrorVtbl;
+ handler->ref = 1;
+ handler->states[0] = STATE_ROOT;
+ handler->statenum = 0;
+ handler->result = result;
+
+ hr = CoCreateInstance(&CLSID_SAXXMLReader, NULL, CLSCTX_INPROC_SERVER,
+ &IID_ISAXXMLReader, (LPVOID*)&reader);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = ISAXXMLReader_putContentHandler(reader, &handler->ISAXContentHandler_iface);
+
+ if (SUCCEEDED(hr))
+ hr = ISAXXMLReader_putErrorHandler(reader, &handler->ISAXErrorHandler_iface);
+
+ if (SUCCEEDED(hr))
+ hr = ISAXXMLReader_parse(reader, input);
+
+ ISAXXMLReader_Release(reader);
+ }
+
+ IUnknown_Release((IUnknown*)handler);
+
+ return S_OK;
+}
+
+HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
+{
+ IStream *stream;
+ VARIANT var;
+ HRESULT hr;
+ HRESULT initresult;
+
+ init_config(result);
+
+ initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);
+
+ if (SUCCEEDED(hr))
+ {
+ V_VT(&var) = VT_UNKNOWN|VT_DISPATCH;
+ V_UNKNOWN(&var) = (IUnknown*)stream;
+
+ hr = parse_config(var, result);
+
+ IStream_Release(stream);
+ }
+
+ if (SUCCEEDED(initresult))
+ CoUninitialize();
+
+ return hr;
+}
+
+void free_parsed_config_file(parsed_config_file *file)
+{
+ supported_runtime *cursor, *cursor2;
+
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &file->supported_runtimes, supported_runtime, entry)
+ {
+ HeapFree(GetProcessHeap(), 0, cursor->version);
+ list_remove(&cursor->entry);
+ HeapFree(GetProcessHeap(), 0, cursor);
+ }
+}
--- /dev/null
+/*
+ *
+ * Copyright 2011 Alistair Leslie-Hughes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "shellapi.h"
+#include "mscoree.h"
+#include "corhdr.h"
+#include "metahost.h"
+#include "cordebug.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
+#include "wine/debug.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+typedef struct DebugProcess
+{
+ ICorDebugProcess ICorDebugProcess_iface;
+
+ CorDebug *cordebug;
+
+ DWORD dwProcessID;
+ HANDLE handle;
+ HANDLE thread;
+
+ LONG ref;
+} DebugProcess;
+
+static inline CorDebug *impl_from_ICorDebug( ICorDebug *iface )
+{
+ return CONTAINING_RECORD(iface, CorDebug, ICorDebug_iface);
+}
+
+static inline CorDebug *impl_from_ICorDebugProcessEnum( ICorDebugProcessEnum *iface )
+{
+ return CONTAINING_RECORD(iface, CorDebug, ICorDebugProcessEnum_iface);
+}
+
+static inline DebugProcess *impl_from_ICorDebugProcess( ICorDebugProcess *iface )
+{
+ return CONTAINING_RECORD(iface, DebugProcess, ICorDebugProcess_iface);
+}
+
+/* ICorDebugProcess Interface */
+static HRESULT WINAPI cordebugprocess_QueryInterface(ICorDebugProcess *iface,
+ REFIID riid, void **ppvObject)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICorDebugProcess ) ||
+ IsEqualGUID( riid, &IID_ICorDebugController ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = &This->ICorDebugProcess_iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICorDebug_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI cordebugprocess_AddRef(ICorDebugProcess *iface)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("%p ref=%u\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI cordebugprocess_Release(ICorDebugProcess *iface)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("%p ref=%u\n", This, ref);
+
+ if (ref == 0)
+ {
+ if(This->handle)
+ CloseHandle(This->handle);
+
+ if(This->thread)
+ CloseHandle(This->thread);
+
+ if(This->cordebug)
+ ICorDebug_Release(&This->cordebug->ICorDebug_iface);
+
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI cordebugprocess_Stop(ICorDebugProcess *iface, DWORD dwTimeoutIgnored)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_Continue(ICorDebugProcess *iface, BOOL fIsOutOfBand)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ TRACE("%p\n", This);
+
+ if(This->thread)
+ ResumeThread(This->thread);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI cordebugprocess_IsRunning(ICorDebugProcess *iface, BOOL *pbRunning)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_HasQueuedCallbacks(ICorDebugProcess *iface,
+ ICorDebugThread *pThread, BOOL *pbQueued)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_EnumerateThreads(ICorDebugProcess *iface,
+ ICorDebugThreadEnum **ppThreads)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_SetAllThreadsDebugState(ICorDebugProcess *iface,
+ CorDebugThreadState state, ICorDebugThread *pExceptThisThread)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_Detach(ICorDebugProcess *iface)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_Terminate(ICorDebugProcess *iface, UINT exitCode)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ BOOL ret = TRUE;
+
+ TRACE("%p\n", This);
+
+ if(This->handle)
+ {
+ ret = TerminateProcess(This->handle, exitCode);
+ CloseHandle(This->handle);
+ This->handle = NULL;
+ }
+ return ret ? S_OK : E_FAIL;
+}
+
+static HRESULT WINAPI cordebugprocess_CanCommitChanges(ICorDebugProcess *iface,
+ ULONG cSnapshots, ICorDebugEditAndContinueSnapshot * pSnapshots[],
+ ICorDebugErrorInfoEnum **pError)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_CommitChanges(ICorDebugProcess *iface,
+ ULONG cSnapshots, ICorDebugEditAndContinueSnapshot * pSnapshots[],
+ ICorDebugErrorInfoEnum **pError)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_GetID(ICorDebugProcess *iface, DWORD *pdwProcessId)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ TRACE("%p\n", This);
+
+ if(!pdwProcessId)
+ return E_INVALIDARG;
+
+ *pdwProcessId = This->dwProcessID;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI cordebugprocess_GetHandle(ICorDebugProcess *iface, HPROCESS *phProcessHandle)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ TRACE("%p\n", This);
+
+ if(!phProcessHandle)
+ return E_INVALIDARG;
+
+ *phProcessHandle = This->handle;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI cordebugprocess_GetThread(ICorDebugProcess *iface, DWORD dwThreadId,
+ ICorDebugThread **ppThread)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_EnumerateObjects(ICorDebugProcess *iface,
+ ICorDebugObjectEnum **ppObjects)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_IsTransitionStub(ICorDebugProcess *iface,
+ CORDB_ADDRESS address, BOOL *pbTransitionStub)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_IsOSSuspended(ICorDebugProcess *iface,
+ DWORD threadID, BOOL *pbSuspended)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_GetThreadContext(ICorDebugProcess *iface,
+ DWORD threadID, ULONG32 contextSize, BYTE context[])
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_SetThreadContext(ICorDebugProcess *iface,
+ DWORD threadID, ULONG32 contextSize, BYTE context[])
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_ReadMemory(ICorDebugProcess *iface,
+ CORDB_ADDRESS address, DWORD size, BYTE buffer[],
+ SIZE_T *read)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_WriteMemory(ICorDebugProcess *iface,
+ CORDB_ADDRESS address, DWORD size, BYTE buffer[],
+ SIZE_T *written)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_ClearCurrentException(ICorDebugProcess *iface,
+ DWORD threadID)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_EnableLogMessages(ICorDebugProcess *iface,
+ BOOL fOnOff)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_ModifyLogSwitch(ICorDebugProcess *iface,
+ WCHAR *pLogSwitchName, LONG lLevel)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_EnumerateAppDomains(ICorDebugProcess *iface,
+ ICorDebugAppDomainEnum **ppAppDomains)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_GetObject(ICorDebugProcess *iface,
+ ICorDebugValue **ppObject)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_ThreadForFiberCookie(ICorDebugProcess *iface,
+ DWORD fiberCookie, ICorDebugThread **ppThread)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI cordebugprocess_GetHelperThreadID(ICorDebugProcess *iface,
+ DWORD *pThreadID)
+{
+ DebugProcess *This = impl_from_ICorDebugProcess(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+
+/***************************************/
+static const ICorDebugProcessVtbl cordebugprocessVtbl = {
+ cordebugprocess_QueryInterface,
+ cordebugprocess_AddRef,
+ cordebugprocess_Release,
+ cordebugprocess_Stop,
+ cordebugprocess_Continue,
+ cordebugprocess_IsRunning,
+ cordebugprocess_HasQueuedCallbacks,
+ cordebugprocess_EnumerateThreads,
+ cordebugprocess_SetAllThreadsDebugState,
+ cordebugprocess_Detach,
+ cordebugprocess_Terminate,
+ cordebugprocess_CanCommitChanges,
+ cordebugprocess_CommitChanges,
+ cordebugprocess_GetID,
+ cordebugprocess_GetHandle,
+ cordebugprocess_GetThread,
+ cordebugprocess_EnumerateObjects,
+ cordebugprocess_IsTransitionStub,
+ cordebugprocess_IsOSSuspended,
+ cordebugprocess_GetThreadContext,
+ cordebugprocess_SetThreadContext,
+ cordebugprocess_ReadMemory,
+ cordebugprocess_WriteMemory,
+ cordebugprocess_ClearCurrentException,
+ cordebugprocess_EnableLogMessages,
+ cordebugprocess_ModifyLogSwitch,
+ cordebugprocess_EnumerateAppDomains,
+ cordebugprocess_GetObject,
+ cordebugprocess_ThreadForFiberCookie,
+ cordebugprocess_GetHelperThreadID
+};
+
+
+static HRESULT CorDebugProcess_Create(CorDebug *cordebug, IUnknown** ppUnk, LPPROCESS_INFORMATION lpProcessInformation)
+{
+ DebugProcess *This;
+
+ This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
+ if ( !This )
+ return E_OUTOFMEMORY;
+
+ if(!DuplicateHandle(GetCurrentProcess(), lpProcessInformation->hProcess,
+ GetCurrentProcess(), &This->handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ ERR("Failed to duplicate process handle\n");
+ HeapFree(GetProcessHeap(), 0, This);
+ return E_FAIL;
+ }
+ if(!DuplicateHandle(GetCurrentProcess(), lpProcessInformation->hThread,
+ GetCurrentProcess(), &This->thread, 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ CloseHandle(This->handle);
+
+ ERR("Failed to duplicate thread handle\n");
+ HeapFree(GetProcessHeap(), 0, This);
+ return E_FAIL;
+ }
+
+ This->ICorDebugProcess_iface.lpVtbl = &cordebugprocessVtbl;
+ This->ref = 1;
+ This->cordebug = cordebug;
+ This->dwProcessID = lpProcessInformation->dwProcessId;
+
+ if(This->cordebug)
+ ICorDebug_AddRef(&This->cordebug->ICorDebug_iface);
+
+ *ppUnk = (IUnknown*)This;
+
+ return S_OK;
+}
+
+/* ICorDebugProcessEnum Interface */
+static HRESULT WINAPI process_enum_QueryInterface(ICorDebugProcessEnum *iface, REFIID riid, void **ppvObject)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICorDebugProcessEnum ) ||
+ IsEqualGUID( riid, &IID_ICorDebugEnum ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = &This->ICorDebugProcessEnum_iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICorDebug_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI process_enum_AddRef(ICorDebugProcessEnum *iface)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ TRACE("%p ref=%u\n", This, This->ref);
+
+ return ICorDebug_AddRef(&This->ICorDebug_iface);
+}
+
+static ULONG WINAPI process_enum_Release(ICorDebugProcessEnum *iface)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ TRACE("%p ref=%u\n", This, This->ref);
+
+ return ICorDebug_Release(&This->ICorDebug_iface);
+}
+
+static HRESULT WINAPI process_enum_Skip(ICorDebugProcessEnum *iface, ULONG celt)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_Reset(ICorDebugProcessEnum *iface)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ FIXME("stub %p\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_Clone(ICorDebugProcessEnum *iface, ICorDebugEnum **ppEnum)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ FIXME("stub %p %p\n", This, ppEnum);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI process_enum_GetCount(ICorDebugProcessEnum *iface, ULONG *pcelt)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ TRACE("stub %p %p\n", This, pcelt);
+
+ if(!pcelt)
+ return E_INVALIDARG;
+
+ *pcelt = list_count(&This->processes);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI process_enum_Next(ICorDebugProcessEnum *iface, ULONG celt,
+ ICorDebugProcess * processes[], ULONG *pceltFetched)
+{
+ CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
+ FIXME("stub %p %d %p %p\n", This, celt, processes, pceltFetched);
+ return E_NOTIMPL;
+}
+
+static const struct ICorDebugProcessEnumVtbl processenum_vtbl =
+{
+ process_enum_QueryInterface,
+ process_enum_AddRef,
+ process_enum_Release,
+ process_enum_Skip,
+ process_enum_Reset,
+ process_enum_Clone,
+ process_enum_GetCount,
+ process_enum_Next
+};
+
+/*** IUnknown methods ***/
+static HRESULT WINAPI CorDebug_QueryInterface(ICorDebug *iface, REFIID riid, void **ppvObject)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICorDebug ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = &This->ICorDebug_iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICorDebug_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI CorDebug_AddRef(ICorDebug *iface)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("%p ref=%u\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI CorDebug_Release(ICorDebug *iface)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("%p ref=%u\n", This, ref);
+
+ if (ref == 0)
+ {
+ if(!list_empty(&This->processes))
+ ERR("Processes haven't been removed Correctly\n");
+
+ if(This->runtimehost)
+ ICLRRuntimeHost_Release(This->runtimehost);
+
+ if(This->pCallback)
+ ICorDebugManagedCallback2_Release(This->pCallback2);
+
+ if(This->pCallback)
+ ICorDebugManagedCallback_Release(This->pCallback);
+
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+/*** ICorDebug methods ***/
+static HRESULT WINAPI CorDebug_Initialize(ICorDebug *iface)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ FIXME("stub %p\n", This);
+ return S_OK;
+}
+
+static HRESULT WINAPI CorDebug_Terminate(ICorDebug *iface)
+{
+ struct CorProcess *cursor, *cursor2;
+ CorDebug *This = impl_from_ICorDebug( iface );
+ TRACE("stub %p\n", This);
+
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->processes, struct CorProcess, entry)
+ {
+ if(cursor->pProcess)
+ {
+ ICorDebugProcess_Terminate(cursor->pProcess, 0);
+ ICorDebugProcess_Release(cursor->pProcess);
+ }
+
+ list_remove(&cursor->entry);
+ HeapFree(GetProcessHeap(), 0, cursor);
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CorDebug_SetManagedHandler(ICorDebug *iface, ICorDebugManagedCallback *pCallback)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ HRESULT hr;
+ ICorDebugManagedCallback2 *pCallback2;
+
+ TRACE("%p (%p)\n", This, pCallback);
+
+ if(!pCallback)
+ return E_INVALIDARG;
+
+ hr = ICorDebugManagedCallback_QueryInterface(pCallback, &IID_ICorDebugManagedCallback2, (void**)&pCallback2);
+ if(hr == S_OK)
+ {
+ if(This->pCallback2)
+ ICorDebugManagedCallback2_Release(This->pCallback2);
+
+ if(This->pCallback)
+ ICorDebugManagedCallback_Release(This->pCallback);
+
+ This->pCallback = pCallback;
+ This->pCallback2 = pCallback2;
+
+ ICorDebugManagedCallback_AddRef(This->pCallback);
+ }
+ else
+ {
+ WARN("Debugging without interface ICorDebugManagedCallback2 is currently not supported.\n");
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CorDebug_SetUnmanagedHandler(ICorDebug *iface, ICorDebugUnmanagedCallback *pCallback)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ FIXME("stub %p %p\n", This, pCallback);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_CreateProcess(ICorDebug *iface, LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
+ DWORD dwCreationFlags, PVOID lpEnvironment,LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation,
+ CorDebugCreateProcessFlags debuggingFlags, ICorDebugProcess **ppProcess)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ ICorDebugProcess *pDebugProcess;
+ HRESULT hr;
+
+ TRACE("stub %p %s %s %p %p %d %d %p %s %p %p %d %p\n", This, debugstr_w(lpApplicationName),
+ debugstr_w(lpCommandLine), lpProcessAttributes, lpThreadAttributes,
+ bInheritHandles, dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory),
+ lpStartupInfo, lpProcessInformation, debuggingFlags, ppProcess);
+
+ if(CreateProcessW(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes,
+ bInheritHandles, dwCreationFlags | CREATE_SUSPENDED, lpEnvironment, lpCurrentDirectory,
+ lpStartupInfo, lpProcessInformation))
+ {
+ hr = CorDebugProcess_Create(This, (IUnknown**)&pDebugProcess, lpProcessInformation);
+ if(hr == S_OK)
+ {
+ struct CorProcess *new_process = HeapAlloc( GetProcessHeap(), 0, sizeof(CorProcess) );
+
+ new_process->pProcess = pDebugProcess;
+ list_add_tail(&This->processes, &new_process->entry);
+
+ ICorDebugProcess_AddRef(pDebugProcess);
+ *ppProcess = pDebugProcess;
+
+ if(This->pCallback)
+ ICorDebugManagedCallback_CreateProcess(This->pCallback, pDebugProcess);
+ }
+ else
+ {
+ TerminateProcess(lpProcessInformation->hProcess, 0);
+ }
+ }
+ else
+ hr = E_FAIL;
+
+ return hr;
+}
+
+static HRESULT WINAPI CorDebug_DebugActiveProcess(ICorDebug *iface, DWORD id, BOOL win32Attach,
+ ICorDebugProcess **ppProcess)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ FIXME("stub %p %d %d %p\n", This, id, win32Attach, ppProcess);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_EnumerateProcesses( ICorDebug *iface, ICorDebugProcessEnum **ppProcess)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ TRACE("stub %p %p\n", This, ppProcess);
+
+ if(!ppProcess)
+ return E_INVALIDARG;
+
+ *ppProcess = &This->ICorDebugProcessEnum_iface;
+ ICorDebugProcessEnum_AddRef(*ppProcess);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CorDebug_GetProcess(ICorDebug *iface, DWORD dwProcessId, ICorDebugProcess **ppProcess)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ FIXME("stub %p %d %p\n", This, dwProcessId, ppProcess);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CorDebug_CanLaunchOrAttach(ICorDebug *iface, DWORD dwProcessId,
+ BOOL win32DebuggingEnabled)
+{
+ CorDebug *This = impl_from_ICorDebug( iface );
+ FIXME("stub %p %d %d\n", This, dwProcessId, win32DebuggingEnabled);
+ return S_OK;
+}
+
+static const struct ICorDebugVtbl cordebug_vtbl =
+{
+ CorDebug_QueryInterface,
+ CorDebug_AddRef,
+ CorDebug_Release,
+ CorDebug_Initialize,
+ CorDebug_Terminate,
+ CorDebug_SetManagedHandler,
+ CorDebug_SetUnmanagedHandler,
+ CorDebug_CreateProcess,
+ CorDebug_DebugActiveProcess,
+ CorDebug_EnumerateProcesses,
+ CorDebug_GetProcess,
+ CorDebug_CanLaunchOrAttach
+};
+
+HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk)
+{
+ CorDebug *This;
+
+ This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
+ if ( !This )
+ return E_OUTOFMEMORY;
+
+ This->ICorDebug_iface.lpVtbl = &cordebug_vtbl;
+ This->ICorDebugProcessEnum_iface.lpVtbl = &processenum_vtbl;
+ This->ref = 1;
+ This->pCallback = NULL;
+ This->pCallback2 = NULL;
+ This->runtimehost = runtimehost;
+
+ list_init(&This->processes);
+
+ if(This->runtimehost)
+ ICLRRuntimeHost_AddRef(This->runtimehost);
+
+ *ppUnk = (IUnknown*)This;
+
+ return S_OK;
+}
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
+#include "winnls.h"
#include "winreg.h"
#include "ole2.h"
+#include "shellapi.h"
#include "cor.h"
#include "mscoree.h"
+#include "metahost.h"
+#include "corhdr.h"
+#include "cordebug.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
-typedef struct _corruntimehost
+#include "initguid.h"
+
+DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
+
+struct DomainEntry
+{
+ struct list entry;
+ MonoDomain *domain;
+};
+
+static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
{
- const struct ICorRuntimeHostVtbl *lpVtbl;
- LONG ref;
-} corruntimehost;
+ struct DomainEntry *entry;
+ char *mscorlib_path;
+ HRESULT res=S_OK;
+
+ EnterCriticalSection(&This->lock);
+
+ entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
+ if (!entry)
+ {
+ res = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ mscorlib_path = WtoA(This->version->mscorlib_path);
+ if (!mscorlib_path)
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ res = E_OUTOFMEMORY;
+ goto end;
+ }
+
+ entry->domain = This->mono->mono_jit_init(mscorlib_path);
+
+ HeapFree(GetProcessHeap(), 0, mscorlib_path);
+
+ if (!entry->domain)
+ {
+ HeapFree(GetProcessHeap(), 0, entry);
+ res = E_FAIL;
+ goto end;
+ }
-static inline corruntimehost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
+ This->mono->is_started = TRUE;
+
+ list_add_tail(&This->domains, &entry->entry);
+
+ *result = entry->domain;
+
+end:
+ LeaveCriticalSection(&This->lock);
+
+ return res;
+}
+
+static HRESULT RuntimeHost_GetDefaultDomain(RuntimeHost *This, MonoDomain **result)
{
- return (corruntimehost *)((char*)iface - FIELD_OFFSET(corruntimehost, lpVtbl));
+ HRESULT res=S_OK;
+
+ EnterCriticalSection(&This->lock);
+
+ if (This->default_domain) goto end;
+
+ res = RuntimeHost_AddDomain(This, &This->default_domain);
+
+end:
+ *result = This->default_domain;
+
+ LeaveCriticalSection(&This->lock);
+
+ return res;
+}
+
+static void RuntimeHost_DeleteDomain(RuntimeHost *This, MonoDomain *domain)
+{
+ struct DomainEntry *entry;
+
+ EnterCriticalSection(&This->lock);
+
+ LIST_FOR_EACH_ENTRY(entry, &This->domains, struct DomainEntry, entry)
+ {
+ if (entry->domain == domain)
+ {
+ list_remove(&entry->entry);
+ if (This->default_domain == domain)
+ This->default_domain = NULL;
+ HeapFree(GetProcessHeap(), 0, entry);
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&This->lock);
+}
+
+static HRESULT RuntimeHost_GetIUnknownForDomain(RuntimeHost *This, MonoDomain *domain, IUnknown **punk)
+{
+ HRESULT hr;
+ void *args[1];
+ MonoAssembly *assembly;
+ MonoImage *image;
+ MonoClass *klass;
+ MonoMethod *method;
+ MonoObject *appdomain_object;
+ IUnknown *unk;
+
+ assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
+ if (!assembly)
+ {
+ ERR("Cannot load mscorlib\n");
+ return E_FAIL;
+ }
+
+ image = This->mono->mono_assembly_get_image(assembly);
+ if (!image)
+ {
+ ERR("Couldn't get assembly image\n");
+ return E_FAIL;
+ }
+
+ klass = This->mono->mono_class_from_name(image, "System", "AppDomain");
+ if (!klass)
+ {
+ ERR("Couldn't get class from image\n");
+ return E_FAIL;
+ }
+
+ method = This->mono->mono_class_get_method_from_name(klass, "get_CurrentDomain", 0);
+ if (!method)
+ {
+ ERR("Couldn't get method from class\n");
+ return E_FAIL;
+ }
+
+ args[0] = NULL;
+ appdomain_object = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
+ if (!appdomain_object)
+ {
+ ERR("Couldn't get result pointer\n");
+ return E_FAIL;
+ }
+
+ hr = RuntimeHost_GetIUnknownForObject(This, appdomain_object, &unk);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = IUnknown_QueryInterface(unk, &IID__AppDomain, (void**)punk);
+
+ IUnknown_Release(unk);
+ }
+
+ return hr;
+}
+
+static inline RuntimeHost *impl_from_ICLRRuntimeHost( ICLRRuntimeHost *iface )
+{
+ return CONTAINING_RECORD(iface, RuntimeHost, ICLRRuntimeHost_iface);
+}
+
+static inline RuntimeHost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
+{
+ return CONTAINING_RECORD(iface, RuntimeHost, ICorRuntimeHost_iface);
}
/*** IUnknown methods ***/
REFIID riid,
void **ppvObject)
{
- corruntimehost *This = impl_from_ICorRuntimeHost( iface );
+ RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
if ( IsEqualGUID( riid, &IID_ICorRuntimeHost ) ||
static ULONG WINAPI corruntimehost_AddRef(ICorRuntimeHost* iface)
{
- corruntimehost *This = impl_from_ICorRuntimeHost( iface );
+ RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
+
return InterlockedIncrement( &This->ref );
}
static ULONG WINAPI corruntimehost_Release(ICorRuntimeHost* iface)
{
- corruntimehost *This = impl_from_ICorRuntimeHost( iface );
+ RuntimeHost *This = impl_from_ICorRuntimeHost( iface );
ULONG ref;
ref = InterlockedDecrement( &This->ref );
- if ( ref == 0 )
- {
- HeapFree( GetProcessHeap(), 0, This );
- }
return ref;
}
ICorRuntimeHost* iface)
{
FIXME("stub %p\n", iface);
- return E_NOTIMPL;
+ return S_OK;
}
static HRESULT WINAPI corruntimehost_Stop(
ICorRuntimeHost* iface,
IUnknown **pAppDomain)
{
- FIXME("stub %p\n", iface);
- return E_NOTIMPL;
+ 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 HRESULT WINAPI corruntimehost_EnumDomains(
corruntimehost_CurrentDomain
};
-IUnknown* create_corruntimehost(void)
+static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
+ REFIID riid,
+ void **ppvObject)
+{
+ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
+ TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICLRRuntimeHost ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICLRRuntimeHost_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI CLRRuntimeHost_AddRef(ICLRRuntimeHost* iface)
+{
+ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
+ return ICorRuntimeHost_AddRef(&This->ICorRuntimeHost_iface);
+}
+
+static ULONG WINAPI CLRRuntimeHost_Release(ICLRRuntimeHost* iface)
{
- corruntimehost *This;
+ RuntimeHost *This = impl_from_ICLRRuntimeHost( iface );
+ return ICorRuntimeHost_Release(&This->ICorRuntimeHost_iface);
+}
+
+static HRESULT WINAPI CLRRuntimeHost_Start(ICLRRuntimeHost* iface)
+{
+ FIXME("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_Stop(ICLRRuntimeHost* iface)
+{
+ FIXME("(%p)\n", iface);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_SetHostControl(ICLRRuntimeHost* iface,
+ IHostControl *pHostControl)
+{
+ FIXME("(%p,%p)\n", iface, pHostControl);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_GetCLRControl(ICLRRuntimeHost* iface,
+ ICLRControl **pCLRControl)
+{
+ FIXME("(%p,%p)\n", iface, pCLRControl);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_UnloadAppDomain(ICLRRuntimeHost* iface,
+ DWORD dwAppDomainId, BOOL fWaitUntilDone)
+{
+ FIXME("(%p,%u,%i)\n", iface, dwAppDomainId, fWaitUntilDone);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_ExecuteInAppDomain(ICLRRuntimeHost* iface,
+ DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void *cookie)
+{
+ FIXME("(%p,%u,%p,%p)\n", iface, dwAppDomainId, pCallback, cookie);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_GetCurrentAppDomainId(ICLRRuntimeHost* iface,
+ DWORD *pdwAppDomainId)
+{
+ FIXME("(%p,%p)\n", iface, pdwAppDomainId);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeHost_ExecuteApplication(ICLRRuntimeHost* iface,
+ LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths,
+ DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue)
+{
+ FIXME("(%p,%s,%u,%u)\n", iface, debugstr_w(pwzAppFullName), dwManifestPaths, dwActivationData);
+ return E_NOTIMPL;
+}
+
+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;
+
+ filenameA = WtoA(pwzAssemblyPath);
+ assembly = This->mono->mono_domain_assembly_open(domain, filenameA);
+ if (!assembly)
+ {
+ ERR("Cannot open assembly %s\n", filenameA);
+ goto cleanup;
+ }
+
+ image = This->mono->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 = This->mono->mono_class_from_name(image, classA, ns+1);
+ if (!klass)
+ {
+ ERR("Couldn't get class from image\n");
+ goto cleanup;
+ }
+
+ methodA = WtoA(pwzMethodName);
+ method = This->mono->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 = This->mono->mono_string_new(domain, argsA);
+ args[0] = str;
+ args[1] = NULL;
+ result = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
+ if (!result)
+ ERR("Couldn't get result pointer\n");
+ else
+ {
+ *pReturnValue = *(DWORD*)This->mono->mono_object_unbox(result);
+ hr = S_OK;
+ }
+
+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);
+
+ return hr;
+}
+
+static const struct ICLRRuntimeHostVtbl CLRHostVtbl =
+{
+ CLRRuntimeHost_QueryInterface,
+ CLRRuntimeHost_AddRef,
+ CLRRuntimeHost_Release,
+ CLRRuntimeHost_Start,
+ CLRRuntimeHost_Stop,
+ CLRRuntimeHost_SetHostControl,
+ CLRRuntimeHost_GetCLRControl,
+ CLRRuntimeHost_UnloadAppDomain,
+ CLRRuntimeHost_ExecuteInAppDomain,
+ CLRRuntimeHost_GetCurrentAppDomainId,
+ CLRRuntimeHost_ExecuteApplication,
+ CLRRuntimeHost_ExecuteInDefaultAppDomain
+};
+
+/* 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;
+}
+
+/* Get an IUnknown pointer for a Mono object.
+ *
+ * This is just a "light" wrapper around
+ * System.Runtime.InteropServices.Marshal:GetIUnknownForObject
+ *
+ * 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. */
+HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj,
+ IUnknown **ppUnk)
+{
+ MonoDomain *domain;
+ MonoAssembly *assembly;
+ MonoImage *image;
+ MonoClass *klass;
+ MonoMethod *method;
+ MonoObject *result;
+ void *args[2];
+
+ domain = This->mono->mono_object_get_domain(obj);
+
+ assembly = This->mono->mono_domain_assembly_open(domain, "mscorlib");
+ if (!assembly)
+ {
+ ERR("Cannot load mscorlib\n");
+ return E_FAIL;
+ }
+
+ image = This->mono->mono_assembly_get_image(assembly);
+ if (!image)
+ {
+ ERR("Couldn't get assembly image\n");
+ return E_FAIL;
+ }
+
+ klass = This->mono->mono_class_from_name(image, "System.Runtime.InteropServices", "Marshal");
+ if (!klass)
+ {
+ ERR("Couldn't get class from image\n");
+ return E_FAIL;
+ }
+
+ method = This->mono->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 = This->mono->mono_runtime_invoke(method, NULL, args, NULL);
+ if (!result)
+ {
+ ERR("Couldn't get result pointer\n");
+ return E_FAIL;
+ }
+
+ *ppUnk = *(IUnknown**)This->mono->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)
+{
+ WCHAR **argvw;
+ int size=0, i;
+ char *current_arg;
+
+ argvw = CommandLineToArgvW(GetCommandLineW(), argc);
+
+ for (i=0; i<*argc; i++)
+ {
+ size += sizeof(char*);
+ size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
+ }
+ size += sizeof(char*);
+
+ *argv = HeapAlloc(GetProcessHeap(), 0, size);
+ current_arg = (char*)(*argv + *argc + 1);
+
+ for (i=0; i<*argc; i++)
+ {
+ (*argv)[i] = current_arg;
+ current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
+ }
+
+ (*argv)[*argc] = NULL;
+
+ HeapFree(GetProcessHeap(), 0, argvw);
+}
+
+__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;
+}
+
+HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
+ loaded_mono *loaded_mono, RuntimeHost** result)
+{
+ RuntimeHost *This;
This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
if ( !This )
- return NULL;
+ return E_OUTOFMEMORY;
+
+ This->ICorRuntimeHost_iface.lpVtbl = &corruntimehost_vtbl;
+ This->ICLRRuntimeHost_iface.lpVtbl = &CLRHostVtbl;
- This->lpVtbl = &corruntimehost_vtbl;
This->ref = 1;
+ This->version = runtime_version;
+ This->mono = loaded_mono;
+ list_init(&This->domains);
+ This->default_domain = NULL;
+ InitializeCriticalSection(&This->lock);
+ This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": RuntimeHost.lock");
- FIXME("return iface %p\n", This);
+ *result = This;
- return (IUnknown*) &This->lpVtbl;
+ return S_OK;
+}
+
+HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv)
+{
+ IUnknown *unk;
+ HRESULT hr;
+
+ if (IsEqualGUID(clsid, &CLSID_CorRuntimeHost))
+ {
+ unk = (IUnknown*)&This->ICorRuntimeHost_iface;
+ IUnknown_AddRef(unk);
+ }
+ else if (IsEqualGUID(clsid, &CLSID_CLRRuntimeHost))
+ {
+ unk = (IUnknown*)&This->ICLRRuntimeHost_iface;
+ IUnknown_AddRef(unk);
+ }
+ else if (IsEqualGUID(clsid, &CLSID_CorMetaDataDispenser) ||
+ IsEqualGUID(clsid, &CLSID_CorMetaDataDispenserRuntime))
+ {
+ hr = MetaDataDispenser_CreateInstance(&unk);
+ if (FAILED(hr))
+ return hr;
+ }
+ else if (IsEqualGUID(clsid, &CLSID_CLRDebuggingLegacy))
+ {
+ hr = CorDebug_Create(&This->ICLRRuntimeHost_iface, &unk);
+ if (FAILED(hr))
+ return hr;
+ }
+ else
+ unk = NULL;
+
+ if (unk)
+ {
+ hr = IUnknown_QueryInterface(unk, riid, ppv);
+
+ IUnknown_Release(unk);
+
+ return hr;
+ }
+ else
+ FIXME("not implemented for class %s\n", debugstr_guid(clsid));
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
+HRESULT RuntimeHost_Destroy(RuntimeHost *This)
+{
+ struct DomainEntry *cursor, *cursor2;
+
+ This->lock.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&This->lock);
+
+ LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, &This->domains, struct DomainEntry, entry)
+ {
+ list_remove(&cursor->entry);
+ HeapFree(GetProcessHeap(), 0, cursor);
+ }
+
+ HeapFree( GetProcessHeap(), 0, This );
+ return S_OK;
}
--- /dev/null
+/*
+ * IMetaDataDispenserEx - dynamic creation/editing of assemblies
+ *
+ * Copyright 2010 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#define COBJMACROS
+
+#include "wine/library.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "cor.h"
+#include "mscoree.h"
+#include "corhdr.h"
+#include "cordebug.h"
+#include "metahost.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+typedef struct MetaDataDispenser
+{
+ IMetaDataDispenserEx IMetaDataDispenserEx_iface;
+ LONG ref;
+} MetaDataDispenser;
+
+static inline MetaDataDispenser *impl_from_IMetaDataDispenserEx(IMetaDataDispenserEx *iface)
+{
+ return CONTAINING_RECORD(iface, MetaDataDispenser, IMetaDataDispenserEx_iface);
+}
+
+static HRESULT WINAPI MetaDataDispenser_QueryInterface(IMetaDataDispenserEx* iface,
+ REFIID riid, void **ppvObject)
+{
+ TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
+
+ if (IsEqualGUID(riid, &IID_IMetaDataDispenserEx) ||
+ IsEqualGUID(riid, &IID_IMetaDataDispenser) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IMetaDataDispenserEx_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI MetaDataDispenser_AddRef(IMetaDataDispenserEx* iface)
+{
+ MetaDataDispenser *This = impl_from_IMetaDataDispenserEx(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("%p ref=%u\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI MetaDataDispenser_Release(IMetaDataDispenserEx* iface)
+{
+ MetaDataDispenser *This = impl_from_IMetaDataDispenserEx(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 MetaDataDispenser_DefineScope(IMetaDataDispenserEx* iface,
+ REFCLSID rclsid, DWORD dwCreateFlags, REFIID riid, IUnknown **ppIUnk)
+{
+ FIXME("%p %s %x %s %p\n", iface, debugstr_guid(rclsid), dwCreateFlags,
+ debugstr_guid(riid), ppIUnk);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_OpenScope(IMetaDataDispenserEx* iface,
+ LPCWSTR szScope, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
+{
+ FIXME("%p %s %x %s %p\n", iface, debugstr_w(szScope), dwOpenFlags,
+ debugstr_guid(riid), ppIUnk);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_OpenScopeOnMemory(IMetaDataDispenserEx* iface,
+ const void *pData, ULONG cbData, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
+{
+ FIXME("%p %p %u %x %s %p\n", iface, pData, cbData, dwOpenFlags,
+ debugstr_guid(riid), ppIUnk);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_SetOption(IMetaDataDispenserEx* iface,
+ REFGUID optionid, const VARIANT *value)
+{
+ FIXME("%p %s\n", iface, debugstr_guid(optionid));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_GetOption(IMetaDataDispenserEx* iface,
+ REFGUID optionid, VARIANT *pvalue)
+{
+ FIXME("%p %s\n", iface, debugstr_guid(optionid));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_OpenScopeOnITypeInfo(IMetaDataDispenserEx* iface,
+ ITypeInfo *pITI, DWORD dwOpenFlags, REFIID riid, IUnknown **ppIUnk)
+{
+ FIXME("%p %p %u %s %p\n", iface, pITI, dwOpenFlags, debugstr_guid(riid), ppIUnk);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_GetCORSystemDirectory(IMetaDataDispenserEx* iface,
+ LPWSTR szBuffer, DWORD cchBuffer, DWORD *pchBuffer)
+{
+ FIXME("%p %p %u %p\n", iface, szBuffer, cchBuffer, pchBuffer);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_FindAssembly(IMetaDataDispenserEx* iface,
+ LPCWSTR szAppBase, LPCWSTR szPrivateBin, LPCWSTR szGlobalBin, LPCWSTR szAssemblyName,
+ LPWSTR szName, ULONG cchName, ULONG *pcName)
+{
+ FIXME("%p %s %s %s %s %p %u %p\n", iface, debugstr_w(szAppBase),
+ debugstr_w(szPrivateBin), debugstr_w(szGlobalBin),
+ debugstr_w(szAssemblyName), szName, cchName, pcName);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MetaDataDispenser_FindAssemblyModule(IMetaDataDispenserEx* iface,
+ LPCWSTR szAppBase, LPCWSTR szPrivateBin, LPCWSTR szGlobalBin, LPCWSTR szAssemblyName,
+ LPCWSTR szModuleName, LPWSTR szName, ULONG cchName, ULONG *pcName)
+{
+ FIXME("%p %s %s %s %s %s %p %u %p\n", iface, debugstr_w(szAppBase),
+ debugstr_w(szPrivateBin), debugstr_w(szGlobalBin), debugstr_w(szAssemblyName),
+ debugstr_w(szModuleName), szName, cchName, pcName);
+ return E_NOTIMPL;
+}
+
+static const struct IMetaDataDispenserExVtbl MetaDataDispenserVtbl =
+{
+ MetaDataDispenser_QueryInterface,
+ MetaDataDispenser_AddRef,
+ MetaDataDispenser_Release,
+ MetaDataDispenser_DefineScope,
+ MetaDataDispenser_OpenScope,
+ MetaDataDispenser_OpenScopeOnMemory,
+ MetaDataDispenser_SetOption,
+ MetaDataDispenser_GetOption,
+ MetaDataDispenser_OpenScopeOnITypeInfo,
+ MetaDataDispenser_GetCORSystemDirectory,
+ MetaDataDispenser_FindAssembly,
+ MetaDataDispenser_FindAssemblyModule
+};
+
+HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk)
+{
+ MetaDataDispenser *This;
+
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetaDataDispenser));
+
+ if (!This)
+ return E_OUTOFMEMORY;
+
+ This->IMetaDataDispenserEx_iface.lpVtbl = &MetaDataDispenserVtbl;
+ This->ref = 1;
+
+ *ppUnk = (IUnknown*)This;
+
+ return S_OK;
+}
--- /dev/null
+/*
+ * ICLRMetaHost - discovery and management of available .NET runtimes
+ *
+ * Copyright 2010 Vincent Povirk for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#define COBJMACROS
+
+#include "wine/unicode.h"
+#include "wine/library.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "ole2.h"
+
+#include "corerror.h"
+#include "cor.h"
+#include "mscoree.h"
+#include "corhdr.h"
+#include "cordebug.h"
+#include "metahost.h"
+#include "fusion.h"
+#include "wine/list.h"
+#include "mscoree_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
+
+static const WCHAR net_11_subdir[] = {'1','.','0',0};
+static const WCHAR net_20_subdir[] = {'2','.','0',0};
+static const WCHAR net_40_subdir[] = {'4','.','0',0};
+
+static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl;
+
+#define NUM_RUNTIMES 3
+
+static struct CLRRuntimeInfo runtimes[NUM_RUNTIMES] = {
+ {{&CLRRuntimeInfoVtbl}, net_11_subdir, 1, 1, 4322, 0},
+ {{&CLRRuntimeInfoVtbl}, net_20_subdir, 2, 0, 50727, 0},
+ {{&CLRRuntimeInfoVtbl}, net_40_subdir, 4, 0, 30319, 0}
+};
+
+static int runtimes_initialized;
+
+static CRITICAL_SECTION runtime_list_cs;
+static CRITICAL_SECTION_DEBUG runtime_list_cs_debug =
+{
+ 0, 0, &runtime_list_cs,
+ { &runtime_list_cs_debug.ProcessLocksList,
+ &runtime_list_cs_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": runtime_list_cs") }
+};
+static CRITICAL_SECTION runtime_list_cs = { &runtime_list_cs_debug, -1, 0, 0, 0, 0 };
+
+#define NUM_ABI_VERSIONS 2
+
+static loaded_mono loaded_monos[NUM_ABI_VERSIONS];
+
+static BOOL find_mono_dll(LPCWSTR path, LPWSTR dll_path, int abi_version);
+
+static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
+
+static void mono_shutdown_callback_fn(MonoProfiler *prof);
+
+static void set_environment(LPCWSTR bin_path)
+{
+ WCHAR path_env[MAX_PATH];
+ int len;
+
+ static const WCHAR pathW[] = {'P','A','T','H',0};
+
+ /* We have to modify PATH as Mono loads other DLLs from this directory. */
+ GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR));
+ len = strlenW(path_env);
+ path_env[len++] = ';';
+ strcpyW(path_env+len, bin_path);
+ SetEnvironmentVariableW(pathW, path_env);
+}
+
+static void CDECL do_nothing(void)
+{
+}
+
+static void missing_runtime_message(const CLRRuntimeInfo *This)
+{
+ if (This->major == 1)
+ MESSAGE("wine: Install Mono 2.6 for Windows to run .NET 1.1 applications.\n");
+ else if (This->major == 2)
+ MESSAGE("wine: Install Mono for Windows to run .NET 2.0 applications.\n");
+ else if (This->major == 4)
+ MESSAGE("wine: Install Mono 2.8 or greater for Windows to run .NET 4.0 applications.\n");
+}
+
+static HRESULT load_mono(CLRRuntimeInfo *This, loaded_mono **result)
+{
+ static const WCHAR bin[] = {'\\','b','i','n',0};
+ static const WCHAR lib[] = {'\\','l','i','b',0};
+ static const WCHAR etc[] = {'\\','e','t','c',0};
+ static const WCHAR glibdll[] = {'l','i','b','g','l','i','b','-','2','.','0','-','0','.','d','l','l',0};
+ WCHAR mono_dll_path[MAX_PATH+16], mono_bin_path[MAX_PATH+4];
+ WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4];
+ char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH];
+ int trace_size;
+ char trace_setting[256];
+
+ if (This->mono_abi_version <= 0 || This->mono_abi_version > NUM_ABI_VERSIONS)
+ {
+ missing_runtime_message(This);
+ return E_FAIL;
+ }
+
+ *result = &loaded_monos[This->mono_abi_version-1];
+
+ if ((*result)->is_shutdown)
+ {
+ ERR("Cannot load Mono after it has been shut down.\n");
+ *result = NULL;
+ return E_FAIL;
+ }
+
+ if (!(*result)->mono_handle)
+ {
+ strcpyW(mono_bin_path, This->mono_path);
+ strcatW(mono_bin_path, bin);
+ set_environment(mono_bin_path);
+
+ strcpyW(mono_lib_path, This->mono_path);
+ strcatW(mono_lib_path, lib);
+ WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL);
+
+ strcpyW(mono_etc_path, This->mono_path);
+ strcatW(mono_etc_path, etc);
+ WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL);
+
+ if (!find_mono_dll(This->mono_path, mono_dll_path, This->mono_abi_version)) goto fail;
+
+ (*result)->mono_handle = LoadLibraryW(mono_dll_path);
+
+ if (!(*result)->mono_handle) goto fail;
+
+#define LOAD_MONO_FUNCTION(x) do { \
+ (*result)->x = (void*)GetProcAddress((*result)->mono_handle, #x); \
+ if (!(*result)->x) { \
+ goto fail; \
+ } \
+} while (0);
+
+ LOAD_MONO_FUNCTION(mono_assembly_get_image);
+ 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_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_object_get_domain);
+ LOAD_MONO_FUNCTION(mono_object_new);
+ LOAD_MONO_FUNCTION(mono_object_unbox);
+ LOAD_MONO_FUNCTION(mono_profiler_install);
+ LOAD_MONO_FUNCTION(mono_reflection_type_from_name);
+ LOAD_MONO_FUNCTION(mono_runtime_invoke);
+ LOAD_MONO_FUNCTION(mono_runtime_object_init);
+ LOAD_MONO_FUNCTION(mono_runtime_quit);
+ LOAD_MONO_FUNCTION(mono_set_dirs);
+ LOAD_MONO_FUNCTION(mono_stringify_assembly_name);
+ LOAD_MONO_FUNCTION(mono_string_new);
+
+ /* GLib imports obsoleted by the 2.0 ABI */
+ if (This->mono_abi_version == 1)
+ {
+ (*result)->glib_handle = LoadLibraryW(glibdll);
+ if (!(*result)->glib_handle) goto fail;
+
+ (*result)->mono_free = (void*)GetProcAddress((*result)->glib_handle, "g_free");
+ if (!(*result)->mono_free) goto fail;
+ }
+ else
+ {
+ LOAD_MONO_FUNCTION(mono_free);
+ }
+
+#undef LOAD_MONO_FUNCTION
+
+#define LOAD_OPT_VOID_MONO_FUNCTION(x) do { \
+ (*result)->x = (void*)GetProcAddress((*result)->mono_handle, #x); \
+ if (!(*result)->x) { \
+ (*result)->x = do_nothing; \
+ } \
+} while (0);
+
+ LOAD_OPT_VOID_MONO_FUNCTION(mono_runtime_set_shutting_down);
+ LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_pool_cleanup);
+ LOAD_OPT_VOID_MONO_FUNCTION(mono_thread_suspend_all_other_threads);
+ LOAD_OPT_VOID_MONO_FUNCTION(mono_threads_set_shutting_down);
+
+#undef LOAD_OPT_VOID_MONO_FUNCTION
+
+ (*result)->mono_profiler_install((MonoProfiler*)*result, mono_shutdown_callback_fn);
+
+ (*result)->mono_set_dirs(mono_lib_path_a, mono_etc_path_a);
+
+ (*result)->mono_config_parse(NULL);
+
+ (*result)->mono_install_assembly_preload_hook(mono_assembly_search_hook_fn, *result);
+
+ trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting));
+
+ if (trace_size)
+ {
+ (*result)->mono_jit_set_trace_options(trace_setting);
+ }
+ }
+
+ return S_OK;
+
+fail:
+ ERR("Could not load Mono into this process\n");
+ FreeLibrary((*result)->mono_handle);
+ FreeLibrary((*result)->glib_handle);
+ (*result)->mono_handle = NULL;
+ (*result)->glib_handle = NULL;
+ return E_FAIL;
+}
+
+static void mono_shutdown_callback_fn(MonoProfiler *prof)
+{
+ loaded_mono *mono = (loaded_mono*)prof;
+
+ mono->is_shutdown = TRUE;
+}
+
+static HRESULT CLRRuntimeInfo_GetRuntimeHost(CLRRuntimeInfo *This, RuntimeHost **result)
+{
+ HRESULT hr = S_OK;
+ loaded_mono *ploaded_mono;
+
+ if (This->loaded_runtime)
+ {
+ *result = This->loaded_runtime;
+ return hr;
+ }
+
+ EnterCriticalSection(&runtime_list_cs);
+
+ hr = load_mono(This, &ploaded_mono);
+
+ if (SUCCEEDED(hr))
+ hr = RuntimeHost_Construct(This, ploaded_mono, &This->loaded_runtime);
+
+ LeaveCriticalSection(&runtime_list_cs);
+
+ if (SUCCEEDED(hr))
+ *result = This->loaded_runtime;
+
+ return hr;
+}
+
+void unload_all_runtimes(void)
+{
+ int i;
+
+ for (i=0; i<NUM_ABI_VERSIONS; i++)
+ {
+ loaded_mono *mono = &loaded_monos[i];
+ if (mono->mono_handle && mono->is_started && !mono->is_shutdown)
+ {
+ /* Copied from Mono's ves_icall_System_Environment_Exit */
+ mono->mono_threads_set_shutting_down();
+ mono->mono_runtime_set_shutting_down();
+ mono->mono_thread_pool_cleanup();
+ mono->mono_thread_suspend_all_other_threads();
+ mono->mono_runtime_quit();
+ }
+ }
+
+ for (i=0; i<NUM_RUNTIMES; i++)
+ if (runtimes[i].loaded_runtime)
+ RuntimeHost_Destroy(runtimes[i].loaded_runtime);
+}
+
+void expect_no_runtimes(void)
+{
+ int i;
+
+ for (i=0; i<NUM_ABI_VERSIONS; i++)
+ {
+ loaded_mono *mono = &loaded_monos[i];
+ if (mono->mono_handle && mono->is_started && !mono->is_shutdown)
+ {
+ ERR("Process exited with a Mono runtime loaded.\n");
+ return;
+ }
+ }
+}
+
+static inline CLRRuntimeInfo *impl_from_ICLRRuntimeInfo(ICLRRuntimeInfo *iface)
+{
+ return CONTAINING_RECORD(iface, CLRRuntimeInfo, ICLRRuntimeInfo_iface);
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_QueryInterface(ICLRRuntimeInfo* iface,
+ REFIID riid,
+ void **ppvObject)
+{
+ TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICLRRuntimeInfo ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICLRRuntimeInfo_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI CLRRuntimeInfo_AddRef(ICLRRuntimeInfo* iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI CLRRuntimeInfo_Release(ICLRRuntimeInfo* iface)
+{
+ return 1;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_GetVersionString(ICLRRuntimeInfo* iface,
+ LPWSTR pwzBuffer, DWORD *pcchBuffer)
+{
+ struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
+ DWORD buffer_size = *pcchBuffer;
+ HRESULT hr = S_OK;
+ char version[11];
+ DWORD size;
+
+ TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
+
+ size = snprintf(version, sizeof(version), "v%u.%u.%u", This->major, This->minor, This->build);
+
+ assert(size <= sizeof(version));
+
+ *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
+
+ if (pwzBuffer)
+ {
+ if (buffer_size >= *pcchBuffer)
+ MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ return hr;
+}
+
+static BOOL get_install_root(LPWSTR install_dir)
+{
+ const WCHAR dotnet_key[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','.','N','E','T','F','r','a','m','e','w','o','r','k','\\',0};
+ const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
+
+ DWORD len;
+ HKEY key;
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_key, 0, KEY_READ, &key))
+ return FALSE;
+
+ len = MAX_PATH;
+ if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
+ {
+ RegCloseKey(key);
+ return FALSE;
+ }
+ RegCloseKey(key);
+
+ return TRUE;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_GetRuntimeDirectory(ICLRRuntimeInfo* iface,
+ LPWSTR pwzBuffer, DWORD *pcchBuffer)
+{
+ static const WCHAR slash[] = {'\\',0};
+ DWORD buffer_size = *pcchBuffer;
+ WCHAR system_dir[MAX_PATH];
+ WCHAR version[MAX_PATH];
+ DWORD version_size, size;
+ HRESULT hr = S_OK;
+
+ TRACE("%p %p %p\n", iface, pwzBuffer, pcchBuffer);
+
+ if (!get_install_root(system_dir))
+ {
+ ERR("error reading registry key for installroot\n");
+ return E_FAIL;
+ }
+ else
+ {
+ version_size = MAX_PATH;
+ ICLRRuntimeInfo_GetVersionString(iface, version, &version_size);
+ lstrcatW(system_dir, version);
+ lstrcatW(system_dir, slash);
+ size = lstrlenW(system_dir) + 1;
+ }
+
+ *pcchBuffer = size;
+
+ if (pwzBuffer)
+ {
+ if (buffer_size >= size)
+ strcpyW(pwzBuffer, system_dir);
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_IsLoaded(ICLRRuntimeInfo* iface,
+ HANDLE hndProcess, BOOL *pbLoaded)
+{
+ FIXME("%p %p %p\n", iface, hndProcess, pbLoaded);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_LoadErrorString(ICLRRuntimeInfo* iface,
+ UINT iResourceID, LPWSTR pwzBuffer, DWORD *pcchBuffer, LONG iLocaleid)
+{
+ FIXME("%p %u %p %p %x\n", iface, iResourceID, pwzBuffer, pcchBuffer, iLocaleid);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_LoadLibrary(ICLRRuntimeInfo* iface,
+ LPCWSTR pwzDllName, HMODULE *phndModule)
+{
+ WCHAR version[MAX_PATH];
+ HRESULT hr;
+ DWORD cchBuffer;
+
+ TRACE("%p %s %p\n", iface, debugstr_w(pwzDllName), phndModule);
+
+ cchBuffer = MAX_PATH;
+ hr = ICLRRuntimeInfo_GetVersionString(iface, version, &cchBuffer);
+ if (FAILED(hr)) return hr;
+
+ return LoadLibraryShim(pwzDllName, version, NULL, phndModule);
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_GetProcAddress(ICLRRuntimeInfo* iface,
+ LPCSTR pszProcName, LPVOID *ppProc)
+{
+ FIXME("%p %s %p\n", iface, debugstr_a(pszProcName), ppProc);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_GetInterface(ICLRRuntimeInfo* iface,
+ REFCLSID rclsid, REFIID riid, LPVOID *ppUnk)
+{
+ struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
+ RuntimeHost *host;
+ HRESULT hr;
+
+ TRACE("%p %s %s %p\n", iface, debugstr_guid(rclsid), debugstr_guid(riid), ppUnk);
+
+ hr = CLRRuntimeInfo_GetRuntimeHost(This, &host);
+
+ if (SUCCEEDED(hr))
+ hr = RuntimeHost_GetInterface(host, rclsid, riid, ppUnk);
+
+ return hr;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_IsLoadable(ICLRRuntimeInfo* iface,
+ BOOL *pbLoadable)
+{
+ FIXME("%p %p\n", iface, pbLoadable);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_SetDefaultStartupFlags(ICLRRuntimeInfo* iface,
+ DWORD dwStartupFlags, LPCWSTR pwzHostConfigFile)
+{
+ FIXME("%p %x %s\n", iface, dwStartupFlags, debugstr_w(pwzHostConfigFile));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_GetDefaultStartupFlags(ICLRRuntimeInfo* iface,
+ DWORD *pdwStartupFlags, LPWSTR pwzHostConfigFile, DWORD *pcchHostConfigFile)
+{
+ FIXME("%p %p %p %p\n", iface, pdwStartupFlags, pwzHostConfigFile, pcchHostConfigFile);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_BindAsLegacyV2Runtime(ICLRRuntimeInfo* iface)
+{
+ FIXME("%p\n", iface);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRRuntimeInfo_IsStarted(ICLRRuntimeInfo* iface,
+ BOOL *pbStarted, DWORD *pdwStartupFlags)
+{
+ FIXME("%p %p %p\n", iface, pbStarted, pdwStartupFlags);
+
+ return E_NOTIMPL;
+}
+
+static const struct ICLRRuntimeInfoVtbl CLRRuntimeInfoVtbl = {
+ CLRRuntimeInfo_QueryInterface,
+ CLRRuntimeInfo_AddRef,
+ CLRRuntimeInfo_Release,
+ CLRRuntimeInfo_GetVersionString,
+ CLRRuntimeInfo_GetRuntimeDirectory,
+ CLRRuntimeInfo_IsLoaded,
+ CLRRuntimeInfo_LoadErrorString,
+ CLRRuntimeInfo_LoadLibrary,
+ CLRRuntimeInfo_GetProcAddress,
+ CLRRuntimeInfo_GetInterface,
+ CLRRuntimeInfo_IsLoadable,
+ CLRRuntimeInfo_SetDefaultStartupFlags,
+ CLRRuntimeInfo_GetDefaultStartupFlags,
+ CLRRuntimeInfo_BindAsLegacyV2Runtime,
+ CLRRuntimeInfo_IsStarted
+};
+
+HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result)
+{
+ struct CLRRuntimeInfo *This = impl_from_ICLRRuntimeInfo(iface);
+
+ assert(This->ICLRRuntimeInfo_iface.lpVtbl == &CLRRuntimeInfoVtbl);
+
+ return CLRRuntimeInfo_GetRuntimeHost(This, result);
+}
+
+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};
+ static const WCHAR libmono_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','.','d','l','l',0};
+ static const WCHAR mono2_dll[] = {'\\','b','i','n','\\','m','o','n','o','-','2','.','0','.','d','l','l',0};
+ static const WCHAR libmono2_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','-','2','.','0','.','d','l','l',0};
+ DWORD attributes=INVALID_FILE_ATTRIBUTES;
+
+ if (abi_version == 1)
+ {
+ strcpyW(dll_path, path);
+ strcatW(dll_path, mono_dll);
+ attributes = GetFileAttributesW(dll_path);
+
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ {
+ strcpyW(dll_path, path);
+ strcatW(dll_path, libmono_dll);
+ attributes = GetFileAttributesW(dll_path);
+ }
+ }
+ else if (abi_version == 2)
+ {
+ strcpyW(dll_path, path);
+ strcatW(dll_path, mono2_dll);
+ attributes = GetFileAttributesW(dll_path);
+
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ {
+ strcpyW(dll_path, path);
+ strcatW(dll_path, libmono2_dll);
+ attributes = GetFileAttributesW(dll_path);
+ }
+ }
+
+ return (attributes != INVALID_FILE_ATTRIBUTES);
+}
+
+static BOOL get_mono_path_from_registry(LPWSTR path, int abi_version)
+{
+ static const WCHAR mono_key[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0};
+ static const WCHAR defaul_clr[] = {'D','e','f','a','u','l','t','C','L','R',0};
+ static const WCHAR install_root[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0};
+ static const WCHAR slash[] = {'\\',0};
+
+ WCHAR version[64], version_key[MAX_PATH];
+ DWORD len;
+ HKEY key;
+ WCHAR dll_path[MAX_PATH];
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key))
+ return FALSE;
+
+ len = sizeof(version);
+ if (RegQueryValueExW(key, defaul_clr, 0, NULL, (LPBYTE)version, &len))
+ {
+ RegCloseKey(key);
+ return FALSE;
+ }
+ RegCloseKey(key);
+
+ lstrcpyW(version_key, mono_key);
+ lstrcatW(version_key, slash);
+ lstrcatW(version_key, version);
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, version_key, 0, KEY_READ, &key))
+ return FALSE;
+
+ len = sizeof(WCHAR) * MAX_PATH;
+ if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)path, &len))
+ {
+ RegCloseKey(key);
+ return FALSE;
+ }
+ RegCloseKey(key);
+
+ return find_mono_dll(path, dll_path, abi_version);
+}
+
+static BOOL get_mono_path_from_folder(LPCWSTR folder, LPWSTR mono_path, int abi_version)
+{
+ static const WCHAR mono_one_dot_zero[] = {'\\','m','o','n','o','-','1','.','0', 0};
+ static const WCHAR mono_two_dot_zero[] = {'\\','m','o','n','o','-','2','.','0', 0};
+ WCHAR mono_dll_path[MAX_PATH];
+ BOOL found = FALSE;
+
+ strcpyW(mono_path, folder);
+
+ if (abi_version == 1)
+ strcatW(mono_path, mono_one_dot_zero);
+ else if (abi_version == 2)
+ strcatW(mono_path, mono_two_dot_zero);
+
+ found = find_mono_dll(mono_path, mono_dll_path, abi_version);
+
+ return found;
+}
+
+static BOOL get_mono_path(LPWSTR path, int abi_version)
+{
+ static const WCHAR subdir_mono[] = {'\\','m','o','n','o',0};
+ static const WCHAR sibling_mono[] = {'\\','.','.','\\','m','o','n','o',0};
+ WCHAR base_path[MAX_PATH];
+ const char *unix_data_dir;
+ WCHAR *dos_data_dir;
+ int build_tree=0;
+ static WCHAR* (CDECL *wine_get_dos_file_name)(const char*);
+
+ /* First try c:\windows\mono */
+ GetWindowsDirectoryW(base_path, MAX_PATH);
+ strcatW(base_path, subdir_mono);
+
+ if (get_mono_path_from_folder(base_path, path, abi_version))
+ return TRUE;
+
+ /* Next: /usr/share/wine/mono */
+ unix_data_dir = wine_get_data_dir();
+
+ if (!unix_data_dir)
+ {
+ unix_data_dir = wine_get_build_dir();
+ build_tree = 1;
+ }
+
+ if (unix_data_dir)
+ {
+ if (!wine_get_dos_file_name)
+ wine_get_dos_file_name = (void*)GetProcAddress(GetModuleHandleA("kernel32"), "wine_get_dos_file_name");
+
+ if (wine_get_dos_file_name)
+ {
+ dos_data_dir = wine_get_dos_file_name(unix_data_dir);
+
+ if (dos_data_dir)
+ {
+ strcpyW(base_path, dos_data_dir);
+ strcatW(base_path, build_tree ? sibling_mono : subdir_mono);
+
+ HeapFree(GetProcessHeap(), 0, dos_data_dir);
+
+ if (get_mono_path_from_folder(base_path, path, abi_version))
+ return TRUE;
+ }
+ }
+ }
+
+ /* Last: the registry */
+ return get_mono_path_from_registry(path, abi_version);
+}
+
+static void find_runtimes(void)
+{
+ int abi_version, i;
+ static const WCHAR libmono[] = {'\\','l','i','b','\\','m','o','n','o','\\',0};
+ static const WCHAR mscorlib[] = {'\\','m','s','c','o','r','l','i','b','.','d','l','l',0};
+ WCHAR mono_path[MAX_PATH], lib_path[MAX_PATH];
+ BOOL any_runtimes_found = FALSE;
+
+ if (runtimes_initialized) return;
+
+ EnterCriticalSection(&runtime_list_cs);
+
+ if (runtimes_initialized) goto end;
+
+ for (abi_version=NUM_ABI_VERSIONS; abi_version>0; abi_version--)
+ {
+ if (!get_mono_path(mono_path, abi_version))
+ continue;
+
+ for (i=0; i<NUM_RUNTIMES; i++)
+ {
+ if (runtimes[i].mono_abi_version == 0)
+ {
+ strcpyW(lib_path, mono_path);
+ strcatW(lib_path, libmono);
+ strcatW(lib_path, runtimes[i].mono_libdir);
+ strcatW(lib_path, mscorlib);
+
+ if (GetFileAttributesW(lib_path) != INVALID_FILE_ATTRIBUTES)
+ {
+ runtimes[i].mono_abi_version = abi_version;
+
+ strcpyW(runtimes[i].mono_path, mono_path);
+ strcpyW(runtimes[i].mscorlib_path, lib_path);
+
+ any_runtimes_found = TRUE;
+ }
+ }
+ }
+ }
+
+ if (!any_runtimes_found)
+ {
+ /* Report all runtimes are available if Mono isn't installed.
+ * FIXME: Remove this when Mono is properly packaged. */
+ for (i=0; i<NUM_RUNTIMES; i++)
+ runtimes[i].mono_abi_version = -1;
+ }
+
+ runtimes_initialized = 1;
+
+end:
+ LeaveCriticalSection(&runtime_list_cs);
+}
+
+struct InstalledRuntimeEnum
+{
+ IEnumUnknown IEnumUnknown_iface;
+ LONG ref;
+ ULONG pos;
+};
+
+static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl;
+
+static inline struct InstalledRuntimeEnum *impl_from_IEnumUnknown(IEnumUnknown *iface)
+{
+ return CONTAINING_RECORD(iface, struct InstalledRuntimeEnum, IEnumUnknown_iface);
+}
+
+static HRESULT WINAPI InstalledRuntimeEnum_QueryInterface(IEnumUnknown* iface, REFIID riid,
+ void **ppvObject)
+{
+ TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_IEnumUnknown ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ IEnumUnknown_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI InstalledRuntimeEnum_AddRef(IEnumUnknown* iface)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI InstalledRuntimeEnum_Release(IEnumUnknown* iface)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) refcount=%u\n", iface, ref);
+
+ if (ref == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI InstalledRuntimeEnum_Next(IEnumUnknown *iface, ULONG celt,
+ IUnknown **rgelt, ULONG *pceltFetched)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+ int num_fetched = 0;
+ HRESULT hr=S_OK;
+ IUnknown *item;
+
+ TRACE("(%p,%u,%p,%p)\n", iface, celt, rgelt, pceltFetched);
+
+ while (num_fetched < celt)
+ {
+ if (This->pos >= NUM_RUNTIMES)
+ {
+ hr = S_FALSE;
+ break;
+ }
+ if (runtimes[This->pos].mono_abi_version)
+ {
+ item = (IUnknown*)&runtimes[This->pos].ICLRRuntimeInfo_iface;
+ IUnknown_AddRef(item);
+ rgelt[num_fetched] = item;
+ num_fetched++;
+ }
+ This->pos++;
+ }
+
+ if (pceltFetched)
+ *pceltFetched = num_fetched;
+
+ return hr;
+}
+
+static HRESULT WINAPI InstalledRuntimeEnum_Skip(IEnumUnknown *iface, ULONG celt)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+ int num_fetched = 0;
+ HRESULT hr=S_OK;
+
+ TRACE("(%p,%u)\n", iface, celt);
+
+ while (num_fetched < celt)
+ {
+ if (This->pos >= NUM_RUNTIMES)
+ {
+ hr = S_FALSE;
+ break;
+ }
+ if (runtimes[This->pos].mono_abi_version)
+ {
+ num_fetched++;
+ }
+ This->pos++;
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI InstalledRuntimeEnum_Reset(IEnumUnknown *iface)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+
+ TRACE("(%p)\n", iface);
+
+ This->pos = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI InstalledRuntimeEnum_Clone(IEnumUnknown *iface, IEnumUnknown **ppenum)
+{
+ struct InstalledRuntimeEnum *This = impl_from_IEnumUnknown(iface);
+ struct InstalledRuntimeEnum *new_enum;
+
+ TRACE("(%p)\n", iface);
+
+ new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
+ if (!new_enum)
+ return E_OUTOFMEMORY;
+
+ new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
+ new_enum->ref = 1;
+ new_enum->pos = This->pos;
+
+ *ppenum = &new_enum->IEnumUnknown_iface;
+
+ return S_OK;
+}
+
+static const struct IEnumUnknownVtbl InstalledRuntimeEnum_Vtbl = {
+ InstalledRuntimeEnum_QueryInterface,
+ InstalledRuntimeEnum_AddRef,
+ InstalledRuntimeEnum_Release,
+ InstalledRuntimeEnum_Next,
+ InstalledRuntimeEnum_Skip,
+ InstalledRuntimeEnum_Reset,
+ InstalledRuntimeEnum_Clone
+};
+
+struct CLRMetaHost
+{
+ ICLRMetaHost ICLRMetaHost_iface;
+};
+
+static struct CLRMetaHost GlobalCLRMetaHost;
+
+static HRESULT WINAPI CLRMetaHost_QueryInterface(ICLRMetaHost* iface,
+ REFIID riid,
+ void **ppvObject)
+{
+ TRACE("%s %p\n", debugstr_guid(riid), ppvObject);
+
+ if ( IsEqualGUID( riid, &IID_ICLRMetaHost ) ||
+ IsEqualGUID( riid, &IID_IUnknown ) )
+ {
+ *ppvObject = iface;
+ }
+ else
+ {
+ FIXME("Unsupported interface %s\n", debugstr_guid(riid));
+ return E_NOINTERFACE;
+ }
+
+ ICLRMetaHost_AddRef( iface );
+
+ return S_OK;
+}
+
+static ULONG WINAPI CLRMetaHost_AddRef(ICLRMetaHost* iface)
+{
+ return 2;
+}
+
+static ULONG WINAPI CLRMetaHost_Release(ICLRMetaHost* iface)
+{
+ return 1;
+}
+
+static BOOL parse_runtime_version(LPCWSTR version, DWORD *major, DWORD *minor, DWORD *build)
+{
+ *major = 0;
+ *minor = 0;
+ *build = 0;
+
+ if (version[0] == 'v')
+ {
+ version++;
+ if (!isdigit(*version))
+ return FALSE;
+
+ while (isdigit(*version))
+ *major = *major * 10 + (*version++ - '0');
+
+ if (*version == 0)
+ return TRUE;
+
+ if (*version++ != '.' || !isdigit(*version))
+ return FALSE;
+
+ while (isdigit(*version))
+ *minor = *minor * 10 + (*version++ - '0');
+
+ if (*version == 0)
+ return TRUE;
+
+ if (*version++ != '.' || !isdigit(*version))
+ return FALSE;
+
+ while (isdigit(*version))
+ *build = *build * 10 + (*version++ - '0');
+
+ return *version == 0;
+ }
+ else
+ return FALSE;
+}
+
+HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface,
+ LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime)
+{
+ int i;
+ DWORD major, minor, build;
+
+ TRACE("%s %s %p\n", debugstr_w(pwzVersion), debugstr_guid(iid), ppRuntime);
+
+ if (!pwzVersion)
+ return E_POINTER;
+
+ if (!parse_runtime_version(pwzVersion, &major, &minor, &build))
+ {
+ ERR("Cannot parse %s\n", debugstr_w(pwzVersion));
+ return CLR_E_SHIM_RUNTIME;
+ }
+
+ find_runtimes();
+
+ for (i=0; i<NUM_RUNTIMES; i++)
+ {
+ if (runtimes[i].major == major && runtimes[i].minor == minor &&
+ runtimes[i].build == build)
+ {
+ if (runtimes[i].mono_abi_version)
+ return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface, iid,
+ ppRuntime);
+ else
+ {
+ missing_runtime_message(&runtimes[i]);
+ return CLR_E_SHIM_RUNTIME;
+ }
+ }
+ }
+
+ FIXME("Unrecognized version %s\n", debugstr_w(pwzVersion));
+ return CLR_E_SHIM_RUNTIME;
+}
+
+HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
+ LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer)
+{
+ ASSEMBLY *assembly;
+ HRESULT hr;
+ LPSTR version;
+ ULONG buffer_size=*pcchBuffer;
+
+ TRACE("%s %p %p\n", debugstr_w(pwzFilePath), pwzBuffer, pcchBuffer);
+
+ hr = assembly_create(&assembly, pwzFilePath);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = assembly_get_runtime_version(assembly, &version);
+
+ if (SUCCEEDED(hr))
+ {
+ *pcchBuffer = MultiByteToWideChar(CP_UTF8, 0, version, -1, NULL, 0);
+
+ if (pwzBuffer)
+ {
+ if (buffer_size >= *pcchBuffer)
+ MultiByteToWideChar(CP_UTF8, 0, version, -1, pwzBuffer, buffer_size);
+ else
+ hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+ }
+ }
+
+ assembly_release(assembly);
+ }
+
+ return hr;
+}
+
+static HRESULT WINAPI CLRMetaHost_EnumerateInstalledRuntimes(ICLRMetaHost* iface,
+ IEnumUnknown **ppEnumerator)
+{
+ struct InstalledRuntimeEnum *new_enum;
+
+ TRACE("%p\n", ppEnumerator);
+
+ find_runtimes();
+
+ new_enum = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_enum));
+ if (!new_enum)
+ return E_OUTOFMEMORY;
+
+ new_enum->IEnumUnknown_iface.lpVtbl = &InstalledRuntimeEnum_Vtbl;
+ new_enum->ref = 1;
+ new_enum->pos = 0;
+
+ *ppEnumerator = &new_enum->IEnumUnknown_iface;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI CLRMetaHost_EnumerateLoadedRuntimes(ICLRMetaHost* iface,
+ HANDLE hndProcess, IEnumUnknown **ppEnumerator)
+{
+ FIXME("%p %p\n", hndProcess, ppEnumerator);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRMetaHost_RequestRuntimeLoadedNotification(ICLRMetaHost* iface,
+ RuntimeLoadedCallbackFnPtr pCallbackFunction)
+{
+ FIXME("%p\n", pCallbackFunction);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRMetaHost_QueryLegacyV2RuntimeBinding(ICLRMetaHost* iface,
+ REFIID riid, LPVOID *ppUnk)
+{
+ FIXME("%s %p\n", debugstr_guid(riid), ppUnk);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI CLRMetaHost_ExitProcess(ICLRMetaHost* iface, INT32 iExitCode)
+{
+ FIXME("%i: stub\n", iExitCode);
+
+ ExitProcess(iExitCode);
+}
+
+static const struct ICLRMetaHostVtbl CLRMetaHost_vtbl =
+{
+ CLRMetaHost_QueryInterface,
+ CLRMetaHost_AddRef,
+ CLRMetaHost_Release,
+ CLRMetaHost_GetRuntime,
+ CLRMetaHost_GetVersionFromFile,
+ CLRMetaHost_EnumerateInstalledRuntimes,
+ CLRMetaHost_EnumerateLoadedRuntimes,
+ CLRMetaHost_RequestRuntimeLoadedNotification,
+ CLRMetaHost_QueryLegacyV2RuntimeBinding,
+ CLRMetaHost_ExitProcess
+};
+
+static struct CLRMetaHost GlobalCLRMetaHost = {
+ { &CLRMetaHost_vtbl }
+};
+
+HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj)
+{
+ return ICLRMetaHost_QueryInterface(&GlobalCLRMetaHost.ICLRMetaHost_iface, riid, ppobj);
+}
+
+static MonoAssembly* mono_assembly_search_hook_fn(MonoAssemblyName *aname, char **assemblies_path, void *user_data)
+{
+ loaded_mono *mono = user_data;
+ HRESULT hr=S_OK;
+ MonoAssembly *result=NULL;
+ char *stringname=NULL;
+ LPWSTR stringnameW;
+ int stringnameW_size;
+ IAssemblyCache *asmcache;
+ ASSEMBLY_INFO info;
+ WCHAR path[MAX_PATH];
+ char *pathA;
+ MonoImageOpenStatus stat;
+ static WCHAR fusiondll[] = {'f','u','s','i','o','n',0};
+ HMODULE hfusion=NULL;
+ static HRESULT (WINAPI *pCreateAssemblyCache)(IAssemblyCache**,DWORD);
+
+ stringname = mono->mono_stringify_assembly_name(aname);
+
+ TRACE("%s\n", debugstr_a(stringname));
+
+ if (!stringname) return NULL;
+
+ /* FIXME: We should search the given paths before the GAC. */
+
+ if (!pCreateAssemblyCache)
+ {
+ hr = LoadLibraryShim(fusiondll, NULL, NULL, &hfusion);
+
+ if (SUCCEEDED(hr))
+ {
+ pCreateAssemblyCache = (void*)GetProcAddress(hfusion, "CreateAssemblyCache");
+ if (!pCreateAssemblyCache)
+ hr = E_FAIL;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ hr = pCreateAssemblyCache(&asmcache, 0);
+
+ if (SUCCEEDED(hr))
+ {
+ stringnameW_size = MultiByteToWideChar(CP_UTF8, 0, stringname, -1, NULL, 0);
+
+ stringnameW = HeapAlloc(GetProcessHeap(), 0, stringnameW_size * sizeof(WCHAR));
+ if (stringnameW)
+ MultiByteToWideChar(CP_UTF8, 0, stringname, -1, stringnameW, stringnameW_size);
+ else
+ hr = E_OUTOFMEMORY;
+
+ if (SUCCEEDED(hr))
+ {
+ info.cbAssemblyInfo = sizeof(info);
+ info.pszCurrentAssemblyPathBuf = path;
+ info.cchBuf = MAX_PATH;
+ path[0] = 0;
+
+ hr = IAssemblyCache_QueryAssemblyInfo(asmcache, 0, stringnameW, &info);
+ }
+
+ HeapFree(GetProcessHeap(), 0, stringnameW);
+
+ IAssemblyCache_Release(asmcache);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ TRACE("found: %s\n", debugstr_w(path));
+
+ pathA = WtoA(path);
+
+ if (pathA)
+ {
+ result = mono->mono_assembly_open(pathA, &stat);
+
+ if (!result)
+ ERR("Failed to load %s, status=%u\n", debugstr_w(path), stat);
+
+ HeapFree(GetProcessHeap(), 0, pathA);
+ }
+ }
+
+ mono->mono_free(stringname);
+
+ return result;
+}
+
+HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
+ DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy, ICLRRuntimeInfo **result)
+{
+ static const WCHAR dotconfig[] = {'.','c','o','n','f','i','g',0};
+ static const DWORD supported_startup_flags = 0;
+ static const DWORD supported_runtime_flags = RUNTIME_INFO_UPGRADE_VERSION;
+ int i;
+ WCHAR local_version[MAX_PATH];
+ ULONG local_version_size = MAX_PATH;
+ WCHAR local_config_file[MAX_PATH];
+ HRESULT hr;
+ parsed_config_file parsed_config;
+
+ if (startup_flags & ~supported_startup_flags)
+ FIXME("unsupported startup flags %x\n", startup_flags & ~supported_startup_flags);
+
+ if (runtimeinfo_flags & ~supported_runtime_flags)
+ FIXME("unsupported runtimeinfo flags %x\n", runtimeinfo_flags & ~supported_runtime_flags);
+
+ if (exefile && !config_file)
+ {
+ strcpyW(local_config_file, exefile);
+ strcatW(local_config_file, dotconfig);
+
+ config_file = local_config_file;
+ }
+
+ if (config_file)
+ {
+ int found=0;
+ hr = parse_config_file(config_file, &parsed_config);
+
+ if (SUCCEEDED(hr))
+ {
+ supported_runtime *entry;
+ LIST_FOR_EACH_ENTRY(entry, &parsed_config.supported_runtimes, supported_runtime, entry)
+ {
+ hr = CLRMetaHost_GetRuntime(0, entry->version, &IID_ICLRRuntimeInfo, (void**)result);
+ if (SUCCEEDED(hr))
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ WARN("failed to parse config file %s, hr=%x\n", debugstr_w(config_file), hr);
+ }
+
+ free_parsed_config_file(&parsed_config);
+
+ if (found)
+ return S_OK;
+ }
+
+ if (exefile && !version)
+ {
+ hr = CLRMetaHost_GetVersionFromFile(0, exefile, local_version, &local_version_size);
+
+ version = local_version;
+
+ if (FAILED(hr)) return hr;
+ }
+
+ if (version)
+ {
+ return CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)result);
+ }
+
+ if (runtimeinfo_flags & RUNTIME_INFO_UPGRADE_VERSION)
+ {
+ find_runtimes();
+
+ if (legacy)
+ i = 2;
+ else
+ i = NUM_RUNTIMES;
+
+ while (i--)
+ {
+ if (runtimes[i].mono_abi_version)
+ return ICLRRuntimeInfo_QueryInterface(&runtimes[i].ICLRRuntimeInfo_iface,
+ &IID_ICLRRuntimeInfo, (void **)result);
+ }
+
+ if (legacy)
+ missing_runtime_message(&runtimes[1]);
+ else
+ missing_runtime_message(&runtimes[NUM_RUNTIMES-1]);
+
+ return CLR_E_SHIM_RUNTIME;
+ }
+
+ return CLR_E_SHIM_RUNTIME;
+}
<include base="ReactOS">include/reactos/wine</include>
<define name="__WINESRC__" />
<library>wine</library>
+ <library>dbghelp</library>
<library>advapi32</library>
<library>shell32</library>
+ <library>ole32</library>
+ <library>shlwapi</library>
<library>uuid</library>
+ <file>assembly.c</file>
+ <file>config.c</file>
+ <file>cordebug.c</file>
<file>corruntimehost.c</file>
+ <file>metadata.c</file>
+ <file>metahost.c</file>
<file>mscoree_main.c</file>
+ <file>mscoree.rc</file>
</module>
--- /dev/null
+1 WINE_REGISTRY mscoree.rgs
--- /dev/null
+HKCR
+{
+ NoRemove Interface
+ {
+ }
+ NoRemove CLSID
+ {
+ '{90F1A06E-7712-4762-86B5-7A5EBA6BDB01}' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'CLRMetaData.CLRRuntimeHost.1'
+ VersionIndependentProgId = s 'CLRMetaData.CLRRuntimeHost'
+ }
+ '{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'CLRMetaData.CLRRuntimeHost.2'
+ VersionIndependentProgId = s 'CLRMetaData.CLRRuntimeHost'
+ }
+ '{E5CB7A31-7512-11D2-89CE-0080C792E5D8}' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'CLRMetaData.CorMetaDataDispenser.2'
+ VersionIndependentProgId = s 'CLRMetaData.CorMetaDataDispenser'
+ }
+ '{1EC2DE53-75CC-11D2-9775-00A0C9B4D50C}' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'CLRMetaData.CorMetaDataDispenserRuntime.2'
+ VersionIndependentProgId = s 'CLRMetaData.CorMetaDataDispenserRuntime'
+ }
+ '{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}' = s 'Microsoft Common Language Runtime Host'
+ {
+ InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
+ ProgId = s 'CLRMetaData.CorRuntimeHost.2'
+ VersionIndependentProgId = s 'CLRMetaData.CorRuntimeHost'
+ }
+ }
+ 'CLRMetaData.CLRRuntimeHost.1' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ CLSID = s '{90F1A06E-7712-4762-86B5-7A5EBA6BDB01}'
+ }
+ 'CLRMetaData.CLRRuntimeHost' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ CLSID = s '{90F1A06E-7712-4762-86B5-7A5EBA6BDB01}'
+ CurVer = s 'CLRMetaData.CLRRuntimeHost.1'
+ }
+ 'CLRMetaData.CLRRuntimeHost.2' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ CLSID = s '{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}'
+ }
+ 'CLRMetaData.CLRRuntimeHost' = s 'Microsoft Common Language Runtime Host V2'
+ {
+ CLSID = s '{90F1A06E-7712-4762-86B5-7A5EBA6BDB02}'
+ CurVer = s 'CLRMetaData.CLRRuntimeHost.2'
+ }
+ 'CLRMetaData.CorMetaDataDispenser.2' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ CLSID = s '{E5CB7A31-7512-11D2-89CE-0080C792E5D8}'
+ }
+ 'CLRMetaData.CorMetaDataDispenser' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ CLSID = s '{E5CB7A31-7512-11D2-89CE-0080C792E5D8}'
+ CurVer = s 'CLRMetaData.CorMetaDataDispenser.2'
+ }
+ 'CLRMetaData.CorMetaDataDispenserRuntime.2' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ CLSID = s '{1EC2DE53-75CC-11D2-9775-00A0C9B4D50C}'
+ }
+ 'CLRMetaData.CorMetaDataDispenserRuntime' = s 'Microsoft Common Language Runtime Meta Data'
+ {
+ CLSID = s '{1EC2DE53-75CC-11D2-9775-00A0C9B4D50C}'
+ CurVer = s 'CLRMetaData.CorMetaDataDispenserRuntime.2'
+ }
+ 'CLRMetaData.CorRuntimeHost.2' = s 'Microsoft Common Language Runtime Host'
+ {
+ CLSID = s '{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}'
+ }
+ 'CLRMetaData.CorRuntimeHost' = s 'Microsoft Common Language Runtime Host'
+ {
+ CLSID = s '{CB2F6723-AB3A-11D2-9C40-00C04FA30A3E}'
+ CurVer = s 'CLRMetaData.CorRuntimeHost.2'
+ }
+}
@ stub CallFunctionShim
@ stub CloseCtrs
+@ stdcall CLRCreateInstance(ptr ptr ptr)
@ stdcall ClrCreateManagedInstance(wstr ptr ptr)
@ stub CoEEShutDownCOM
@ stdcall CoInitializeCor(long)
@ stub CorIsLatestSvc
@ stub CorMarkThreadInThreadPool
@ stub CorTickleSvc
-@ stub CreateConfigStream
-@ stub CreateDebuggingInterfaceFromVersion
+@ stdcall CreateConfigStream(wstr ptr)
+@ stdcall CreateDebuggingInterfaceFromVersion(long wstr ptr)
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall GetCORSystemDirectory(ptr long ptr)
@ stdcall GetCORVersion(ptr long ptr)
@ stub GetCompileInfo
-@ stub GetFileVersion
+@ stdcall GetFileVersion(wstr ptr long ptr)
@ stub GetHashFromAssemblyFile
@ stub GetHashFromAssemblyFileW
@ stub GetHashFromBlob
@ stub GetPermissionRequests
@ stub GetPrivateContextsPerfCounters
@ stub GetProcessExecutableHeap
-@ stub GetRealProcAddress
+@ stdcall GetRealProcAddress(str ptr)
@ stdcall GetRequestedRuntimeInfo(wstr wstr wstr long long ptr long ptr ptr long ptr)
-@ stub GetRequestedRuntimeVersion
+@ stdcall GetRequestedRuntimeVersion(wstr ptr long ptr)
@ stub GetRequestedRuntimeVersionForCLSID
@ stub GetStartupFlags
@ stub GetTargetForVTableEntry
#include <stdarg.h>
+#define COBJMACROS
#include "wine/unicode.h"
+#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "ole2.h"
+#include "ocidl.h"
#include "shellapi.h"
#include "initguid.h"
+#include "msxml2.h"
+#include "corerror.h"
#include "cor.h"
#include "mscoree.h"
+#include "corhdr.h"
+#include "cordebug.h"
+#include "metahost.h"
+#include "fusion.h"
+#include "wine/list.h"
#include "mscoree_private.h"
+#include "rpcproxy.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
-static BOOL get_mono_path(LPWSTR path)
+static HINSTANCE MSCOREE_hInstance;
+
+char *WtoA(LPCWSTR wstr)
{
- static const WCHAR mono_key[] = {'S','o','f','t','w','a','r','e','\\','N','o','v','e','l','l','\\','M','o','n','o',0};
- static const WCHAR defaul_clr[] = {'D','e','f','a','u','l','t','C','L','R',0};
- static const WCHAR install_root[] = {'S','d','k','I','n','s','t','a','l','l','R','o','o','t',0};
- static const WCHAR slash[] = {'\\',0};
+ int length;
+ char *result;
- WCHAR version[64], version_key[MAX_PATH];
- DWORD len;
- HKEY key;
+ length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key))
- return FALSE;
+ result = HeapAlloc(GetProcessHeap(), 0, length);
- len = sizeof(version);
- if (RegQueryValueExW(key, defaul_clr, 0, NULL, (LPBYTE)version, &len))
- {
- RegCloseKey(key);
- return FALSE;
- }
- RegCloseKey(key);
+ if (result)
+ WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL);
- lstrcpyW(version_key, mono_key);
- lstrcatW(version_key, slash);
- lstrcatW(version_key, version);
+ return result;
+}
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, version_key, 0, KEY_READ, &key))
+static BOOL get_install_root(LPWSTR install_dir)
+{
+ const WCHAR dotnet_key[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','.','N','E','T','F','r','a','m','e','w','o','r','k','\\',0};
+ const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
+
+ DWORD len;
+ HKEY key;
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_key, 0, KEY_READ, &key))
return FALSE;
- len = sizeof(WCHAR) * MAX_PATH;
- if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)path, &len))
+ len = MAX_PATH;
+ if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
{
RegCloseKey(key);
return FALSE;
return TRUE;
}
-static CRITICAL_SECTION mono_lib_cs;
-static CRITICAL_SECTION_DEBUG mono_lib_cs_debug =
-{
- 0, 0, &mono_lib_cs,
- { &mono_lib_cs_debug.ProcessLocksList,
- &mono_lib_cs_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": mono_lib_cs") }
-};
-static CRITICAL_SECTION mono_lib_cs = { &mono_lib_cs_debug, -1, 0, 0, 0, 0 };
-
-HMODULE mono_handle;
-
-void (*mono_config_parse)(const char *filename);
-MonoAssembly* (*mono_domain_assembly_open) (MonoDomain *domain, const char *name);
-void (*mono_jit_cleanup)(MonoDomain *domain);
-int (*mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
-MonoDomain* (*mono_jit_init)(const char *file);
-int (*mono_jit_set_trace_options)(const char* options);
-void (*mono_set_dirs)(const char *assembly_dir, const char *config_dir);
-
-static void set_environment(LPCWSTR bin_path)
-{
- WCHAR path_env[MAX_PATH];
- int len;
-
- static const WCHAR pathW[] = {'P','A','T','H',0};
-
- /* We have to modify PATH as Mono loads other DLLs from this directory. */
- GetEnvironmentVariableW(pathW, path_env, sizeof(path_env)/sizeof(WCHAR));
- len = strlenW(path_env);
- path_env[len++] = ';';
- strcpyW(path_env+len, bin_path);
- SetEnvironmentVariableW(pathW, path_env);
-}
-
-static HMODULE load_mono(void)
-{
- static const WCHAR mono_dll[] = {'\\','b','i','n','\\','m','o','n','o','.','d','l','l',0};
- static const WCHAR libmono_dll[] = {'\\','b','i','n','\\','l','i','b','m','o','n','o','.','d','l','l',0};
- static const WCHAR bin[] = {'\\','b','i','n',0};
- static const WCHAR lib[] = {'\\','l','i','b',0};
- static const WCHAR etc[] = {'\\','e','t','c',0};
- HMODULE result;
- WCHAR mono_path[MAX_PATH], mono_dll_path[MAX_PATH+16], mono_bin_path[MAX_PATH+4];
- WCHAR mono_lib_path[MAX_PATH+4], mono_etc_path[MAX_PATH+4];
- char mono_lib_path_a[MAX_PATH], mono_etc_path_a[MAX_PATH];
-
- EnterCriticalSection(&mono_lib_cs);
-
- if (!mono_handle)
- {
- if (!get_mono_path(mono_path)) goto end;
-
- strcpyW(mono_bin_path, mono_path);
- strcatW(mono_bin_path, bin);
- set_environment(mono_bin_path);
-
- strcpyW(mono_lib_path, mono_path);
- strcatW(mono_lib_path, lib);
- WideCharToMultiByte(CP_UTF8, 0, mono_lib_path, -1, mono_lib_path_a, MAX_PATH, NULL, NULL);
-
- strcpyW(mono_etc_path, mono_path);
- strcatW(mono_etc_path, etc);
- WideCharToMultiByte(CP_UTF8, 0, mono_etc_path, -1, mono_etc_path_a, MAX_PATH, NULL, NULL);
-
- strcpyW(mono_dll_path, mono_path);
- strcatW(mono_dll_path, mono_dll);
- mono_handle = LoadLibraryW(mono_dll_path);
-
- if (!mono_handle)
- {
- strcpyW(mono_dll_path, mono_path);
- strcatW(mono_dll_path, libmono_dll);
- mono_handle = LoadLibraryW(mono_dll_path);
- }
-
- if (!mono_handle) goto end;
-
-#define LOAD_MONO_FUNCTION(x) do { \
- x = (void*)GetProcAddress(mono_handle, #x); \
- if (!x) { \
- mono_handle = NULL; \
- goto end; \
- } \
-} while (0);
-
- LOAD_MONO_FUNCTION(mono_config_parse);
- LOAD_MONO_FUNCTION(mono_domain_assembly_open);
- LOAD_MONO_FUNCTION(mono_jit_cleanup);
- LOAD_MONO_FUNCTION(mono_jit_exec);
- LOAD_MONO_FUNCTION(mono_jit_init);
- LOAD_MONO_FUNCTION(mono_jit_set_trace_options);
- LOAD_MONO_FUNCTION(mono_set_dirs);
-
-#undef LOAD_MONO_FUNCTION
-
- mono_set_dirs(mono_lib_path_a, mono_etc_path_a);
-
- mono_config_parse(NULL);
- }
-
-end:
- result = mono_handle;
-
- LeaveCriticalSection(&mono_lib_cs);
-
- if (!result)
- MESSAGE("wine: Install the Windows version of Mono to run .NET executables\n");
-
- return result;
-}
-
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
LPCWSTR pwszHostConfigFile, VOID *pReserved,
DWORD startupFlags, REFCLSID rclsid,
REFIID riid, LPVOID *ppv)
{
- FIXME("(%s, %s, %s, %p, %d, %s, %s, %p): semi-stub!\n", debugstr_w(pwszVersion),
+ HRESULT ret;
+ ICLRRuntimeInfo *info;
+
+ TRACE("(%s, %s, %s, %p, %d, %s, %s, %p)\n", debugstr_w(pwszVersion),
debugstr_w(pwszBuildFlavor), debugstr_w(pwszHostConfigFile), pReserved,
startupFlags, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
- if (!get_mono_path(NULL))
+ *ppv = NULL;
+
+ ret = get_runtime_info(NULL, pwszVersion, pwszHostConfigFile, startupFlags, 0, TRUE, &info);
+
+ if (SUCCEEDED(ret))
{
- MESSAGE("wine: Install the Windows version of Mono to run .NET executables\n");
- return E_FAIL;
+ ret = ICLRRuntimeInfo_GetInterface(info, rclsid, riid, ppv);
+
+ ICLRRuntimeInfo_Release(info);
}
- return S_OK;
+ return ret;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
+ MSCOREE_hInstance = hinstDLL;
+
switch (fdwReason)
{
case DLL_WINE_PREATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
+ expect_no_runtimes();
break;
}
return TRUE;
return TRUE;
}
-static void get_utf8_args(int *argc, char ***argv)
-{
- WCHAR **argvw;
- int size=0, i;
- char *current_arg;
-
- argvw = CommandLineToArgvW(GetCommandLineW(), argc);
-
- for (i=0; i<*argc; i++)
- {
- size += sizeof(char*);
- size += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
- }
- size += sizeof(char*);
-
- *argv = HeapAlloc(GetProcessHeap(), 0, size);
- current_arg = (char*)(*argv + *argc + 1);
-
- for (i=0; i<*argc; i++)
- {
- (*argv)[i] = current_arg;
- current_arg += WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, current_arg, size, NULL, NULL);
- }
-
- (*argv)[*argc] = NULL;
-
- HeapFree(GetProcessHeap(), 0, argvw);
-}
-
-__int32 WINAPI _CorExeMain(void)
-{
- int exit_code;
- int trace_size;
- char trace_setting[256];
- int argc;
- char **argv;
- MonoDomain *domain;
- MonoAssembly *assembly;
- char filename[MAX_PATH];
-
- if (!load_mono())
- {
- return -1;
- }
-
- get_utf8_args(&argc, &argv);
-
- trace_size = GetEnvironmentVariableA("WINE_MONO_TRACE", trace_setting, sizeof(trace_setting));
-
- if (trace_size)
- {
- mono_jit_set_trace_options(trace_setting);
- }
-
- GetModuleFileNameA(NULL, filename, MAX_PATH);
-
- domain = mono_jit_init(filename);
-
- assembly = mono_domain_assembly_open(domain, filename);
-
- exit_code = mono_jit_exec(domain, assembly, argc, argv);
-
- mono_jit_cleanup(domain);
-
- HeapFree(GetProcessHeap(), 0, argv);
-
- return exit_code;
-}
-
__int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName, LPWSTR loaderName, LPWSTR cmdLine)
{
TRACE("(%p, %u, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
void WINAPI CorExitProcess(int exitCode)
{
- FIXME("(%x) stub\n", exitCode);
+ TRACE("(%x)\n", exitCode);
+ unload_all_runtimes();
ExitProcess(exitCode);
}
HRESULT WINAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
{
- FIXME("(%p, %d, %p): stub!\n", pbuffer, cchBuffer, dwLength);
+ ICLRRuntimeInfo *info;
+ HRESULT ret;
+
+ TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
- if (!dwLength)
+ if (!dwLength || !pbuffer)
return E_POINTER;
- *dwLength = 0;
+ ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
- return S_OK;
+ if (SUCCEEDED(ret))
+ {
+ *dwLength = cchBuffer;
+ ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pbuffer, dwLength);
+
+ ICLRRuntimeInfo_Release(info);
+ }
+
+ return ret;
}
HRESULT WINAPI GetCORVersion(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
{
- static const WCHAR version[] = {'v','1','.','1','.','4','3','2','2',0};
+ ICLRRuntimeInfo *info;
+ HRESULT ret;
- FIXME("(%p, %d, %p): semi-stub!\n", pbuffer, cchBuffer, dwLength);
+ TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
- if (!dwLength)
+ if (!dwLength || !pbuffer)
return E_POINTER;
- *dwLength = lstrlenW(version);
+ ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
- if (cchBuffer < *dwLength)
- return ERROR_INSUFFICIENT_BUFFER;
+ if (SUCCEEDED(ret))
+ {
+ *dwLength = cchBuffer;
+ ret = ICLRRuntimeInfo_GetVersionString(info, pbuffer, dwLength);
- if (pbuffer)
- lstrcpyW(pbuffer, version);
+ ICLRRuntimeInfo_Release(info);
+ }
- return S_OK;
+ return ret;
}
HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWSTR pConfigurationFile,
DWORD startupFlags, DWORD runtimeInfoFlags, LPWSTR pDirectory, DWORD dwDirectory, DWORD *dwDirectoryLength,
LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
{
- FIXME("(%s, %s, %s, 0x%08x, 0x%08x, %p, 0x%08x, %p, %p, 0x%08x, %p) stub\n", debugstr_w(pExe),
+ HRESULT ret;
+ ICLRRuntimeInfo *info;
+ DWORD length_dummy;
+
+ TRACE("(%s, %s, %s, 0x%08x, 0x%08x, %p, 0x%08x, %p, %p, 0x%08x, %p)\n", debugstr_w(pExe),
debugstr_w(pwszVersion), debugstr_w(pConfigurationFile), startupFlags, runtimeInfoFlags, pDirectory,
dwDirectory, dwDirectoryLength, pVersion, cchBuffer, dwlength);
- return GetCORVersion(pVersion, cchBuffer, dwlength);
+
+ if (!dwDirectoryLength) dwDirectoryLength = &length_dummy;
+
+ if (!dwlength) dwlength = &length_dummy;
+
+ ret = get_runtime_info(pExe, pwszVersion, pConfigurationFile, startupFlags, runtimeInfoFlags, TRUE, &info);
+
+ if (SUCCEEDED(ret))
+ {
+ *dwlength = cchBuffer;
+ ret = ICLRRuntimeInfo_GetVersionString(info, pVersion, dwlength);
+
+ if (SUCCEEDED(ret))
+ {
+ *dwDirectoryLength = dwDirectory;
+ ret = ICLRRuntimeInfo_GetRuntimeDirectory(info, pDirectory, dwDirectoryLength);
+ }
+
+ ICLRRuntimeInfo_Release(info);
+ }
+
+ return ret;
+}
+
+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);
+
+ if(!dwlength)
+ return E_POINTER;
+
+ return GetRequestedRuntimeInfo(pExe, NULL, NULL, 0, 0, NULL, 0, NULL, pVersion, cchBuffer, dwlength);
+}
+
+HRESULT WINAPI GetRealProcAddress(LPCSTR procname, void **ppv)
+{
+ FIXME("(%s, %p)\n", debugstr_a(procname), ppv);
+ return CLR_E_SHIM_RUNTIMEEXPORT;
+}
+
+HRESULT WINAPI GetFileVersion(LPCWSTR szFilename, LPWSTR szBuffer, DWORD cchBuffer, DWORD *dwLength)
+{
+ TRACE("(%s, %p, %d, %p)\n", debugstr_w(szFilename), szBuffer, cchBuffer, dwLength);
+
+ if (!szFilename || !dwLength)
+ return E_POINTER;
+
+ *dwLength = cchBuffer;
+ return CLRMetaHost_GetVersionFromFile(0, szFilename, szBuffer, dwLength);
}
HRESULT WINAPI LoadLibraryShim( LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvReserved, HMODULE * phModDll)
{
- FIXME("(%p %s, %p, %p, %p): semi-stub\n", szDllName, debugstr_w(szDllName), szVersion, pvReserved, phModDll);
+ HRESULT ret=S_OK;
+ WCHAR dll_filename[MAX_PATH];
+ WCHAR version[MAX_PATH];
+ static const WCHAR default_version[] = {'v','1','.','1','.','4','3','2','2',0};
+ static const WCHAR slash[] = {'\\',0};
+ DWORD dummy;
- if (phModDll) *phModDll = LoadLibraryW(szDllName);
- return S_OK;
+ TRACE("(%p %s, %p, %p, %p)\n", szDllName, debugstr_w(szDllName), szVersion, pvReserved, phModDll);
+
+ if (!szDllName || !phModDll)
+ return E_POINTER;
+
+ if (!get_install_root(dll_filename))
+ {
+ ERR("error reading registry key for installroot\n");
+ dll_filename[0] = 0;
+ }
+ else
+ {
+ if (!szVersion)
+ {
+ ret = GetCORVersion(version, MAX_PATH, &dummy);
+ if (SUCCEEDED(ret))
+ szVersion = version;
+ else
+ szVersion = default_version;
+ }
+ strcatW(dll_filename, szVersion);
+ strcatW(dll_filename, slash);
+ }
+
+ strcatW(dll_filename, szDllName);
+
+ *phModDll = LoadLibraryW(dll_filename);
+
+ return *phModDll ? S_OK : E_HANDLE;
}
HRESULT WINAPI LockClrVersion(FLockClrVersionCallback hostCallback, FLockClrVersionCallback *pBeginHostSetup, FLockClrVersionCallback *pEndHostSetup)
HRESULT WINAPI CorBindToRuntimeEx(LPWSTR szVersion, LPWSTR szBuildFlavor, DWORD nflags, REFCLSID rslsid,
REFIID riid, LPVOID *ppv)
{
- FIXME("%s %s %d %s %s %p\n", debugstr_w(szVersion), debugstr_w(szBuildFlavor), nflags, debugstr_guid( rslsid ),
+ HRESULT ret;
+ ICLRRuntimeInfo *info;
+
+ TRACE("%s %s %d %s %s %p\n", debugstr_w(szVersion), debugstr_w(szBuildFlavor), nflags, debugstr_guid( rslsid ),
debugstr_guid( riid ), ppv);
- if(IsEqualGUID( riid, &IID_ICorRuntimeHost ))
+ *ppv = NULL;
+
+ ret = get_runtime_info(NULL, szVersion, NULL, nflags, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
+
+ if (SUCCEEDED(ret))
{
- *ppv = create_corruntimehost();
- return S_OK;
+ ret = ICLRRuntimeInfo_GetInterface(info, rslsid, riid, ppv);
+
+ ICLRRuntimeInfo_Release(info);
}
- *ppv = NULL;
- return E_NOTIMPL;
+
+ return ret;
}
HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID riid, LPVOID *ppv)
STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject)
{
- FIXME("(%s,%s,%p)\n", debugstr_w(pTypeName), debugstr_guid(riid), ppObject);
- return E_NOTIMPL;
+ HRESULT ret;
+ ICLRRuntimeInfo *info;
+ RuntimeHost *host;
+ MonoObject *obj;
+ IUnknown *unk;
+
+ TRACE("(%s,%s,%p)\n", debugstr_w(pTypeName), debugstr_guid(riid), ppObject);
+
+ /* FIXME: How to determine which runtime version to use? */
+ ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
+
+ if (SUCCEEDED(ret))
+ {
+ ret = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
+
+ ICLRRuntimeInfo_Release(info);
+ }
+
+ if (SUCCEEDED(ret))
+ ret = RuntimeHost_CreateManagedInstance(host, pTypeName, NULL, &obj);
+
+ if (SUCCEEDED(ret))
+ ret = RuntimeHost_GetIUnknownForObject(host, obj, &unk);
+
+ if (SUCCEEDED(ret))
+ {
+ ret = IUnknown_QueryInterface(unk, riid, ppObject);
+ IUnknown_Release(unk);
+ }
+
+ return ret;
}
BOOL WINAPI StrongNameSignatureVerification(LPCWSTR filename, DWORD inFlags, DWORD* pOutFlags)
return FALSE;
}
+HRESULT WINAPI CreateConfigStream(LPCWSTR filename, IStream **stream)
+{
+ FIXME("(%s, %p): stub\n", debugstr_w(filename), stream);
+ return E_NOTIMPL;
+}
+
+HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR version, IUnknown **ppv)
+{
+ const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
+ HRESULT hr = E_FAIL;
+ ICLRRuntimeInfo *runtimeinfo;
+
+ if(nDebugVersion < 1 || nDebugVersion > 4)
+ return E_INVALIDARG;
+
+ TRACE("(%d %s, %p): stub\n", nDebugVersion, debugstr_w(version), ppv);
+
+ if(!ppv)
+ return E_INVALIDARG;
+
+ *ppv = NULL;
+
+ if(strcmpW(version, v2_0) != 0)
+ {
+ FIXME("Currently .NET Version '%s' not support.\n", debugstr_w(version));
+ return E_INVALIDARG;
+ }
+
+ if(nDebugVersion != 3)
+ return E_INVALIDARG;
+
+ hr = CLRMetaHost_GetRuntime(0, version, &IID_ICLRRuntimeInfo, (void**)&runtimeinfo);
+ if(hr == S_OK)
+ {
+ hr = ICLRRuntimeInfo_GetInterface(runtimeinfo, &CLSID_CLRDebuggingLegacy, &IID_ICorDebug, (void**)ppv);
+
+ ICLRRuntimeInfo_Release(runtimeinfo);
+ }
+
+ if(!*ppv)
+ return E_FAIL;
+
+ return hr;
+}
+
+HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterface)
+{
+ TRACE("(%s,%s,%p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppInterface);
+
+ if (IsEqualGUID(clsid, &CLSID_CLRMetaHost))
+ return CLRMetaHost_CreateInstance(riid, ppInterface);
+
+ FIXME("not implemented for class %s\n", debugstr_guid(clsid));
+
+ return CLASS_E_CLASSNOTAVAILABLE;
+}
+
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
HRESULT WINAPI DllRegisterServer(void)
{
- FIXME("\n");
- return S_OK;
+ return __wine_register_resources( MSCOREE_hInstance );
}
HRESULT WINAPI DllUnregisterServer(void)
{
- FIXME("\n");
- return S_OK;
+ return __wine_unregister_resources( MSCOREE_hInstance );
}
HRESULT WINAPI DllCanUnloadNow(VOID)
{
- return S_OK;
+ return S_FALSE;
}
INT WINAPI ND_RU1( const void *ptr, INT offset )
#ifndef __MSCOREE_PRIVATE__
#define __MSCOREE_PRIVATE__
-extern IUnknown* create_corruntimehost(void);
+extern char *WtoA(LPCWSTR wstr) DECLSPEC_HIDDEN;
-/* Mono 2.6 embedding */
+extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HIDDEN;
+
+extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
+ LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
+
+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;
+
+/* Mono embedding */
typedef struct _MonoDomain MonoDomain;
typedef struct _MonoAssembly MonoAssembly;
+typedef struct _MonoAssemblyName MonoAssemblyName;
+typedef struct _MonoType MonoType;
+typedef struct _MonoImage MonoImage;
+typedef struct _MonoClass MonoClass;
+typedef struct _MonoObject MonoObject;
+typedef struct _MonoString MonoString;
+typedef struct _MonoMethod MonoMethod;
+typedef struct _MonoProfiler MonoProfiler;
+
+typedef struct loaded_mono loaded_mono;
+typedef struct RuntimeHost RuntimeHost;
+
+typedef struct CLRRuntimeInfo
+{
+ ICLRRuntimeInfo ICLRRuntimeInfo_iface;
+ LPCWSTR mono_libdir;
+ DWORD major;
+ DWORD minor;
+ DWORD build;
+ int mono_abi_version;
+ WCHAR mono_path[MAX_PATH];
+ WCHAR mscorlib_path[MAX_PATH];
+ struct RuntimeHost *loaded_runtime;
+} CLRRuntimeInfo;
+
+struct RuntimeHost
+{
+ ICorRuntimeHost ICorRuntimeHost_iface;
+ ICLRRuntimeHost ICLRRuntimeHost_iface;
+ const CLRRuntimeInfo *version;
+ loaded_mono *mono;
+ struct list domains;
+ MonoDomain *default_domain;
+ CRITICAL_SECTION lock;
+ LONG ref;
+};
+
+typedef struct CorProcess
+{
+ struct list entry;
+ ICorDebugProcess *pProcess;
+} CorProcess;
+
+typedef struct CorDebug
+{
+ ICorDebug ICorDebug_iface;
+ ICorDebugProcessEnum ICorDebugProcessEnum_iface;
+ LONG ref;
+
+ ICLRRuntimeHost *runtimehost;
+
+ /* ICorDebug Callback */
+ ICorDebugManagedCallback *pCallback;
+ ICorDebugManagedCallback2 *pCallback2;
+
+ /* Debug Processes */
+ struct list processes;
+} CorDebug;
+
+extern HRESULT get_runtime_info(LPCWSTR exefile, LPCWSTR version, LPCWSTR config_file,
+ DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy, ICLRRuntimeInfo **result) DECLSPEC_HIDDEN;
+
+extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) DECLSPEC_HIDDEN;
+
+extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDEN;
+
+typedef struct parsed_config_file
+{
+ struct list supported_runtimes;
+} parsed_config_file;
+
+typedef struct supported_runtime
+{
+ struct list entry;
+ LPWSTR version;
+} supported_runtime;
+
+extern HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result) DECLSPEC_HIDDEN;
+
+extern void free_parsed_config_file(parsed_config_file *file) DECLSPEC_HIDDEN;
+
+typedef enum {
+ MONO_IMAGE_OK,
+ MONO_IMAGE_ERROR_ERRNO,
+ MONO_IMAGE_MISSING_ASSEMBLYREF,
+ MONO_IMAGE_IMAGE_INVALID
+} MonoImageOpenStatus;
+
+typedef MonoAssembly* (*MonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
+
+typedef void (*MonoProfileFunc)(MonoProfiler *prof);
+
+struct loaded_mono
+{
+ HMODULE mono_handle;
+ HMODULE glib_handle;
+
+ BOOL is_started;
+ BOOL is_shutdown;
+
+ MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
+ 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);
+ MonoMethod* (CDECL *mono_class_get_method_from_name)(MonoClass *klass, const char *name, int param_count);
+ void (CDECL *mono_config_parse)(const char *filename);
+ MonoAssembly* (CDECL *mono_domain_assembly_open) (MonoDomain *domain, const char *name);
+ void (CDECL *mono_free)(void *);
+ 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);
+ MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
+ MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
+ void* (CDECL *mono_object_unbox)(MonoObject *obj);
+ void (CDECL *mono_profiler_install)(MonoProfiler *prof, MonoProfileFunc shutdown_callback);
+ MonoType* (CDECL *mono_reflection_type_from_name)(char *name, MonoImage *image);
+ MonoObject* (CDECL *mono_runtime_invoke)(MonoMethod *method, void *obj, void **params, MonoObject **exc);
+ void (CDECL *mono_runtime_object_init)(MonoObject *this_obj);
+ void (CDECL *mono_runtime_quit)(void);
+ void (CDECL *mono_runtime_set_shutting_down)(void);
+ void (CDECL *mono_set_dirs)(const char *assembly_dir, const char *config_dir);
+ char* (CDECL *mono_stringify_assembly_name)(MonoAssemblyName *aname);
+ void (CDECL *mono_thread_pool_cleanup)(void);
+ 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);
+};
+
+/* loaded runtime interfaces */
+extern void unload_all_runtimes(void) DECLSPEC_HIDDEN;
+
+extern void expect_no_runtimes(void) DECLSPEC_HIDDEN;
+
+extern HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
+ loaded_mono *loaded_mono, RuntimeHost** result) DECLSPEC_HIDDEN;
+
+extern HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+
+extern HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj, IUnknown **ppUnk) DECLSPEC_HIDDEN;
+
+extern HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
+ MonoDomain *domain, MonoObject **result) DECLSPEC_HIDDEN;
+
+extern HRESULT RuntimeHost_Destroy(RuntimeHost *This) DECLSPEC_HIDDEN;
-extern HMODULE mono_handle;
+HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime) DECLSPEC_HIDDEN;
-extern void (*mono_config_parse)(const char *filename);
-extern MonoAssembly* (*mono_domain_assembly_open) (MonoDomain *domain, const char *name);
-extern void (*mono_jit_cleanup)(MonoDomain *domain);
-extern int (*mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
-extern MonoDomain* (*mono_jit_init)(const char *file);
-extern int (*mono_jit_set_trace_options)(const char* options);
-extern void (*mono_set_dirs)(const char *assembly_dir, const char *config_dir);
+extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
#endif /* __MSCOREE_PRIVATE__ */
if(MSVC)
list(APPEND IDL_SOURCES
- atliface.idl)
+ atliface.idl
+ cor.idl
+ cordebug.idl
+ metahost.idl)
else()
list(APPEND IDL_SOURCES
wbemcli.idl
reactos/dll/win32/msadp32.acm # Synced to Wine-1.3.37
reactos/dll/win32/mscat32 # Autosync
reactos/dll/win32/mscms # Synced to Wine-1.3.37
-reactos/dll/win32/mscoree # Autosync
+reactos/dll/win32/mscoree # Synced to Wine-1.3.37
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