[MSCOREE]

* Sync to Wine 1.3.37.

svn path=/trunk/; revision=55276
This commit is contained in:
Amine Khaldi 2012-01-28 17:34:24 +00:00
parent 5f4ae9949c
commit 53d0c6b010
15 changed files with 4287 additions and 285 deletions

View file

@ -2,11 +2,18 @@
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)
@ -14,5 +21,10 @@ add_library(mscoree SHARED ${SOURCE})
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)

View file

@ -0,0 +1,250 @@
/*
* 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;
}

View file

@ -0,0 +1,472 @@
/*
* 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);
}
}

View file

@ -0,0 +1,786 @@
/*
*
* 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;
}

View file

@ -24,25 +24,185 @@
#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
{
const struct ICorRuntimeHostVtbl *lpVtbl;
LONG ref;
} corruntimehost;
#include "initguid.h"
static inline corruntimehost *impl_from_ICorRuntimeHost( ICorRuntimeHost *iface )
DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
struct DomainEntry
{
return (corruntimehost *)((char*)iface - FIELD_OFFSET(corruntimehost, lpVtbl));
struct list entry;
MonoDomain *domain;
};
static HRESULT RuntimeHost_AddDomain(RuntimeHost *This, MonoDomain **result)
{
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;
}
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)
{
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 ***/
@ -50,7 +210,7 @@ static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
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 ) ||
@ -71,20 +231,17 @@ static HRESULT WINAPI corruntimehost_QueryInterface(ICorRuntimeHost* iface,
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;
}
@ -149,7 +306,7 @@ static HRESULT WINAPI corruntimehost_Start(
ICorRuntimeHost* iface)
{
FIXME("stub %p\n", iface);
return E_NOTIMPL;
return S_OK;
}
static HRESULT WINAPI corruntimehost_Stop(
@ -173,8 +330,20 @@ static HRESULT WINAPI corruntimehost_GetDefaultDomain(
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(
@ -271,18 +440,506 @@ static const struct ICorRuntimeHostVtbl corruntimehost_vtbl =
corruntimehost_CurrentDomain
};
IUnknown* create_corruntimehost(void)
static HRESULT WINAPI CLRRuntimeHost_QueryInterface(ICLRRuntimeHost* iface,
REFIID riid,
void **ppvObject)
{
corruntimehost *This;
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)
{
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;
}

View file

@ -0,0 +1,205 @@
/*
* 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;
}

File diff suppressed because it is too large Load diff

View file

@ -4,9 +4,18 @@
<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>

View file

@ -0,0 +1 @@
1 WINE_REGISTRY mscoree.rgs

View file

@ -0,0 +1,84 @@
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'
}
}

View file

@ -7,6 +7,7 @@
@ stub CallFunctionShim
@ stub CloseCtrs
@ stdcall CLRCreateInstance(ptr ptr ptr)
@ stdcall ClrCreateManagedInstance(wstr ptr ptr)
@ stub CoEEShutDownCOM
@ stdcall CoInitializeCor(long)
@ -27,8 +28,8 @@
@ 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()
@ -42,7 +43,7 @@
@ 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
@ -56,9 +57,9 @@
@ 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

View file

@ -21,55 +21,65 @@
#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 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};
static HINSTANCE MSCOREE_hInstance;
char *WtoA(LPCWSTR wstr)
{
int length;
char *result;
length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
result = HeapAlloc(GetProcessHeap(), 0, length);
if (result)
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL);
return result;
}
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};
WCHAR version[64], version_key[MAX_PATH];
DWORD len;
HKEY key;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, mono_key, 0, KEY_READ, &key))
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, dotnet_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))
len = MAX_PATH;
if (RegQueryValueExW(key, install_root, 0, NULL, (LPBYTE)install_dir, &len))
{
RegCloseKey(key);
return FALSE;
@ -79,140 +89,38 @@ static BOOL get_mono_path(LPWSTR path)
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:
@ -221,6 +129,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
expect_no_runtimes();
break;
}
return TRUE;
@ -241,75 +150,6 @@ BOOL WINAPI _CorDllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
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));
@ -319,7 +159,8 @@ __int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName,
void WINAPI CorExitProcess(int exitCode)
{
FIXME("(%x) stub\n", exitCode);
TRACE("(%x)\n", exitCode);
unload_all_runtimes();
ExitProcess(exitCode);
}
@ -336,52 +177,150 @@ HRESULT WINAPI _CorValidateImage(PVOID* imageBase, LPCWSTR imageName)
HRESULT WINAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
{
FIXME("(%p, %d, %p): stub!\n", pbuffer, cchBuffer, dwLength);
ICLRRuntimeInfo *info;
HRESULT ret;
if (!dwLength)
TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, 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)
@ -433,16 +372,24 @@ HRESULT WINAPI LoadStringRC(UINT resId, LPWSTR pBuffer, int iBufLen, int bQuiet)
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 = create_corruntimehost();
return S_OK;
}
*ppv = NULL;
return E_NOTIMPL;
ret = get_runtime_info(NULL, szVersion, NULL, nflags, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
ret = ICLRRuntimeInfo_GetInterface(info, rslsid, riid, ppv);
ICLRRuntimeInfo_Release(info);
}
return ret;
}
HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID riid, LPVOID *ppv)
@ -453,8 +400,37 @@ HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID
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)
@ -469,6 +445,63 @@ BOOL WINAPI StrongNameSignatureVerificationEx(LPCWSTR filename, BOOL forceVerifi
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);
@ -480,19 +513,17 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* 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 )

View file

@ -20,20 +20,170 @@
#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;
extern HMODULE mono_handle;
typedef struct loaded_mono loaded_mono;
typedef struct RuntimeHost RuntimeHost;
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);
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;
HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime) DECLSPEC_HIDDEN;
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
#endif /* __MSCOREE_PRIVATE__ */

View file

@ -176,7 +176,10 @@ list(APPEND IDL_SOURCES
if(MSVC)
list(APPEND IDL_SOURCES
atliface.idl)
atliface.idl
cor.idl
cordebug.idl
metahost.idl)
else()
list(APPEND IDL_SOURCES
wbemcli.idl

View file

@ -95,7 +95,7 @@ reactos/dll/win32/msacm32 # Autosync
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