[MSCOREE] Sync to wine-10.0

This commit is contained in:
Mikhail Tyukin
2025-11-15 11:28:26 -05:00
committed by Timo Kreuzer
parent 1f97ad1f93
commit 37ef9507c7
26 changed files with 4566 additions and 1237 deletions

View File

@@ -1,6 +1,6 @@
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
add_definitions(-D_WIN32_WINNT=0x600 -DUSE_NEW_WINE_REGISTER_RESOURCES)
spec2def(mscoree.dll mscoree.spec)
@@ -11,7 +11,8 @@ list(APPEND SOURCE
corruntimehost.c
metadata.c
metahost.c
mscoree_main.c)
mscoree_main.c
reactos.c)
list(APPEND PCH_SKIP_SOURCE
guid.c
@@ -24,8 +25,8 @@ add_library(mscoree MODULE
${CMAKE_CURRENT_BINARY_DIR}/mscoree.def)
set_module_type(mscoree win32dll)
target_link_libraries(mscoree uuid wine)
add_importlibs(mscoree dbghelp advapi32 shell32 ole32 shlwapi msvcrt kernel32 ntdll)
add_pch(mscoree mscoree_private.h "${PCH_SKIP_SOURCE}")
target_link_libraries(mscoree uuid wine oldnames)
add_importlibs(mscoree dbghelp advapi32 shell32 kernel32_vista ole32 shlwapi msvcrt kernel32 ntdll)
#add_pch(mscoree mscoree_private.h "${PCH_SKIP_SOURCE}")
add_cd_file(TARGET mscoree DESTINATION reactos/system32 FOR all)
set_wine_module_FIXME(mscoree) # CORE-5743: No CONST_VTABLE

View File

@@ -18,10 +18,23 @@
* 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 <winver.h>
#include <dbghelp.h>
#include "wine/debug.h"
typedef struct
{
@@ -49,7 +62,7 @@ typedef struct tagCLRTABLE
struct tagASSEMBLY
{
int is_mapped_file;
BOOL is_mapped_file;
/* mapped files */
LPWSTR path;
@@ -64,20 +77,6 @@ struct tagASSEMBLY
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 void* assembly_rva_to_va(ASSEMBLY *assembly, ULONG rva)
{
if (assembly->is_mapped_file)
@@ -115,7 +114,7 @@ static HRESULT parse_metadata_header(ASSEMBLY *assembly, DWORD *hdrsz)
metadatahdr = (METADATAHDR *)ptr;
assembly->metadatahdr = HeapAlloc(GetProcessHeap(), 0, sizeof(METADATAHDR));
assembly->metadatahdr = malloc(sizeof(METADATAHDR));
if (!assembly->metadatahdr)
return E_OUTOFMEMORY;
@@ -195,13 +194,13 @@ HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file)
*out = NULL;
assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
assembly = calloc(1, sizeof(ASSEMBLY));
if (!assembly)
return E_OUTOFMEMORY;
assembly->is_mapped_file = 1;
assembly->is_mapped_file = TRUE;
assembly->path = strdupW(file);
assembly->path = wcsdup(file);
if (!assembly->path)
{
hr = E_OUTOFMEMORY;
@@ -249,11 +248,11 @@ HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule)
*out = NULL;
assembly = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ASSEMBLY));
assembly = calloc(1, sizeof(ASSEMBLY));
if (!assembly)
return E_OUTOFMEMORY;
assembly->is_mapped_file = 0;
assembly->is_mapped_file = FALSE;
assembly->data = (BYTE*)hmodule;
@@ -277,9 +276,9 @@ HRESULT assembly_release(ASSEMBLY *assembly)
CloseHandle(assembly->hmap);
CloseHandle(assembly->hfile);
}
HeapFree(GetProcessHeap(), 0, assembly->metadatahdr);
HeapFree(GetProcessHeap(), 0, assembly->path);
HeapFree(GetProcessHeap(), 0, assembly);
free(assembly->metadatahdr);
free(assembly->path);
free(assembly);
return S_OK;
}
@@ -300,3 +299,17 @@ HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWO
return S_OK;
}
HRESULT assembly_get_native_entrypoint(ASSEMBLY *assembly, NativeEntryPointFunc *func)
{
if (assembly->corhdr->Flags & COMIMAGE_FLAGS_NATIVE_ENTRYPOINT)
{
*func = assembly_rva_to_va(assembly, assembly->corhdr->EntryPointRVA);
return S_OK;
}
else
{
*func = NULL;
return S_FALSE;
}
}

View File

@@ -18,17 +18,34 @@
* 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 "corerror.h"
#include "metahost.h"
#include "cordebug.h"
#include "wine/list.h"
#include "mscoree_private.h"
#include <ole2.h>
#include <shlwapi.h>
#include <initguid.h>
#include <msxml2.h>
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
enum parse_state
{
STATE_ASSEMBLY_BINDING,
STATE_ROOT,
STATE_CONFIGURATION,
STATE_PROBING,
STATE_RUNTIME,
STATE_STARTUP,
STATE_UNKNOWN
};
@@ -43,6 +60,192 @@ typedef struct ConfigFileHandler
parsed_config_file *result;
} ConfigFileHandler;
typedef struct
{
IStream IStream_iface;
LONG ref;
HANDLE file;
} ConfigStream;
static inline ConfigStream *impl_from_IStream(IStream *iface)
{
return CONTAINING_RECORD(iface, ConfigStream, IStream_iface);
}
static HRESULT WINAPI ConfigStream_QueryInterface(IStream *iface, REFIID riid, void **ppv)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IStream))
*ppv = &This->IStream_iface;
else
{
WARN("Not supported iface %s\n", debugstr_guid(riid));
*ppv = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
static ULONG WINAPI ConfigStream_AddRef(IStream *iface)
{
ConfigStream *This = impl_from_IStream(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%lu\n", This, ref);
return ref;
}
static ULONG WINAPI ConfigStream_Release(IStream *iface)
{
ConfigStream *This = impl_from_IStream(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%lu\n",This, ref);
if (!ref)
{
CloseHandle(This->file);
free(This);
}
return ref;
}
static HRESULT WINAPI ConfigStream_Read(IStream *iface, void *buf, ULONG size, ULONG *ret_read)
{
ConfigStream *This = impl_from_IStream(iface);
DWORD read = 0;
TRACE("(%p)->(%p %lu %p)\n", This, buf, size, ret_read);
if (!ReadFile(This->file, buf, size, &read, NULL))
{
WARN("error %ld reading file\n", GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
if (ret_read) *ret_read = read;
return S_OK;
}
static HRESULT WINAPI ConfigStream_Write(IStream *iface, const void *buf, ULONG size, ULONG *written)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)->(%p %lu %p)\n", This, buf, size, written);
return E_FAIL;
}
static HRESULT WINAPI ConfigStream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER *pNewPos)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)->(%ld %ld %p)\n", This, dlibMove.u.LowPart, dwOrigin, pNewPos);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)->(%ld)\n", This, libNewSize.u.LowPart);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER size,
ULARGE_INTEGER *read, ULARGE_INTEGER *written)
{
ConfigStream *This = impl_from_IStream(iface);
FIXME("(%p)->(%p %ld %p %p)\n", This, stream, size.u.LowPart, read, written);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_Commit(IStream *iface, DWORD flags)
{
ConfigStream *This = impl_from_IStream(iface);
FIXME("(%p,%ld)\n", This, flags);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_Revert(IStream *iface)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)\n", This);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_LockUnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p,%ld,%ld,%ld)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_Stat(IStream *iface, STATSTG *lpStat, DWORD grfStatFlag)
{
ConfigStream *This = impl_from_IStream(iface);
FIXME("(%p,%p,%ld)\n", This, lpStat, grfStatFlag);
return E_NOTIMPL;
}
static HRESULT WINAPI ConfigStream_Clone(IStream *iface, IStream **ppstm)
{
ConfigStream *This = impl_from_IStream(iface);
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
static const IStreamVtbl ConfigStreamVtbl = {
ConfigStream_QueryInterface,
ConfigStream_AddRef,
ConfigStream_Release,
ConfigStream_Read,
ConfigStream_Write,
ConfigStream_Seek,
ConfigStream_SetSize,
ConfigStream_CopyTo,
ConfigStream_Commit,
ConfigStream_Revert,
ConfigStream_LockUnlockRegion,
ConfigStream_LockUnlockRegion,
ConfigStream_Stat,
ConfigStream_Clone
};
HRESULT WINAPI CreateConfigStream(const WCHAR *filename, IStream **stream)
{
ConfigStream *config_stream;
HANDLE file;
TRACE("(%s, %p)\n", debugstr_w(filename), stream);
if (!stream)
return COR_E_NULLREFERENCE;
file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
if (file == INVALID_HANDLE_VALUE)
return GetLastError() == ERROR_FILE_NOT_FOUND ? COR_E_FILENOTFOUND : E_FAIL;
config_stream = malloc(sizeof(*config_stream));
if (!config_stream)
{
CloseHandle(file);
return E_OUTOFMEMORY;
}
config_stream->IStream_iface.lpVtbl = &ConfigStreamVtbl;
config_stream->ref = 1;
config_stream->file = file;
*stream = &config_stream->IStream_iface;
return S_OK;
}
static inline ConfigFileHandler *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
{
return CONTAINING_RECORD(iface, ConfigFileHandler, ISAXContentHandler_iface);
@@ -56,18 +259,19 @@ static inline ConfigFileHandler *impl_from_ISAXErrorHandler(ISAXErrorHandler *if
static HRESULT WINAPI ConfigFileHandler_QueryInterface(ISAXContentHandler *iface,
REFIID riid, void **ppvObject)
{
if (IsEqualGUID(riid, &IID_ISAXContentHandler) ||
IsEqualGUID(riid, &IID_IUnknown))
{
*ppvObject = iface;
}
ConfigFileHandler *This = impl_from_ISAXContentHandler(iface);
if (IsEqualGUID(riid, &IID_ISAXContentHandler) || IsEqualGUID(riid, &IID_IUnknown))
*ppvObject = &This->ISAXContentHandler_iface;
else if (IsEqualGUID(riid, &IID_ISAXErrorHandler))
*ppvObject = &This->ISAXErrorHandler_iface;
else
{
WARN("Unsupported interface %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
ISAXContentHandler_AddRef(iface);
IUnknown_AddRef((IUnknown*)*ppvObject);
return S_OK;
}
@@ -84,7 +288,7 @@ static ULONG WINAPI ConfigFileHandler_Release(ISAXContentHandler *iface)
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0)
HeapFree(GetProcessHeap(), 0, This);
free(This);
return ref;
}
@@ -133,6 +337,28 @@ static HRESULT parse_startup(ConfigFileHandler *This, ISAXAttributes *pAttr)
return hr;
}
static HRESULT parse_probing(ConfigFileHandler *This, ISAXAttributes *pAttr)
{
static const WCHAR privatePath[] = {'p','r','i','v','a','t','e','P','a','t','h',0};
static const WCHAR empty[] = {0};
LPCWSTR value;
int value_size;
HRESULT hr;
hr = ISAXAttributes_getValueFromName(pAttr, empty, 0, privatePath, lstrlenW(privatePath), &value, &value_size);
if (SUCCEEDED(hr))
{
TRACE("%s\n", debugstr_wn(value, value_size));
This->result->private_path = wcsdup(value);
if (!This->result->private_path)
hr = E_OUTOFMEMORY;
}
return hr;
}
static HRESULT parse_supported_runtime(ConfigFileHandler *This, ISAXAttributes *pAttr)
{
static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
@@ -147,18 +373,17 @@ static HRESULT parse_supported_runtime(ConfigFileHandler *This, ISAXAttributes *
if (SUCCEEDED(hr))
{
TRACE("%s\n", debugstr_wn(value, value_size));
entry = HeapAlloc(GetProcessHeap(), 0, sizeof(supported_runtime));
entry = malloc(sizeof(supported_runtime));
if (entry)
{
entry->version = HeapAlloc(GetProcessHeap(), 0, (value_size + 1) * sizeof(WCHAR));
entry->version = wcsdup(value);
if (entry->version)
{
lstrcpyW(entry->version, value);
list_add_tail(&This->result->supported_runtimes, &entry->entry);
}
else
{
HeapFree(GetProcessHeap(), 0, entry);
free(entry);
hr = E_OUTOFMEMORY;
}
}
@@ -185,14 +410,18 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
{
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 assemblyBinding[] = {'a','s','s','e','m','b','l','y','B','i','n','d','i','n','g',0};
static const WCHAR probing[] = {'p','r','o','b','i','n','g',0};
static const WCHAR runtime[] = {'r','u','n','t','i','m','e',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)
if (This->statenum == ARRAY_SIZE(This->states) - 1)
{
ERR("file has too much nesting\n");
return E_FAIL;
@@ -201,8 +430,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
switch (This->states[This->statenum])
{
case STATE_ROOT:
if (nLocalName == sizeof(configuration)/sizeof(WCHAR)-1 &&
lstrcmpW(pLocalName, configuration) == 0)
if (nLocalName == ARRAY_SIZE(configuration) - 1 && wcscmp(pLocalName, configuration) == 0)
{
This->states[++This->statenum] = STATE_CONFIGURATION;
break;
@@ -210,18 +438,40 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
else
goto unknown;
case STATE_CONFIGURATION:
if (nLocalName == sizeof(startup)/sizeof(WCHAR)-1 &&
lstrcmpW(pLocalName, startup) == 0)
if (nLocalName == ARRAY_SIZE(startup) - 1 && wcscmp(pLocalName, startup) == 0)
{
hr = parse_startup(This, pAttr);
This->states[++This->statenum] = STATE_STARTUP;
break;
}
else if (nLocalName == ARRAY_SIZE(runtime) - 1 && wcscmp(pLocalName, runtime) == 0)
{
This->states[++This->statenum] = STATE_RUNTIME;
break;
}
else
goto unknown;
case STATE_RUNTIME:
if (nLocalName == ARRAY_SIZE(assemblyBinding) - 1 &&
wcscmp(pLocalName, assemblyBinding) == 0)
{
This->states[++This->statenum] = STATE_ASSEMBLY_BINDING;
break;
}
else
goto unknown;
case STATE_ASSEMBLY_BINDING:
if (nLocalName == ARRAY_SIZE(probing) - 1 && wcscmp(pLocalName, probing) == 0)
{
hr = parse_probing(This, pAttr);
This->states[++This->statenum] = STATE_PROBING;
break;
}
else
goto unknown;
case STATE_STARTUP:
if (nLocalName == sizeof(supportedRuntime)/sizeof(WCHAR)-1 &&
lstrcmpW(pLocalName, supportedRuntime) == 0)
if (nLocalName == ARRAY_SIZE(supportedRuntime) - 1 &&
wcscmp(pLocalName, supportedRuntime) == 0)
{
hr = parse_supported_runtime(This, pAttr);
This->states[++This->statenum] = STATE_UNKNOWN;
@@ -236,7 +486,7 @@ static HRESULT WINAPI ConfigFileHandler_startElement(ISAXContentHandler *iface,
return hr;
unknown:
FIXME("Unknown element %s in state %u\n", debugstr_wn(pLocalName,nLocalName),
TRACE("Unknown element %s in state %u\n", debugstr_wn(pLocalName,nLocalName),
This->states[This->statenum]);
This->states[++This->statenum] = STATE_UNKNOWN;
@@ -314,52 +564,40 @@ static const struct ISAXContentHandlerVtbl ConfigFileHandlerVtbl =
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;
ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
return ISAXContentHandler_QueryInterface(&This->ISAXContentHandler_iface, riid, ppvObject);
}
static ULONG WINAPI ConfigFileHandler_Error_AddRef(ISAXErrorHandler *iface)
{
ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
return IUnknown_AddRef((IUnknown*)This);
return ISAXContentHandler_AddRef(&This->ISAXContentHandler_iface);
}
static ULONG WINAPI ConfigFileHandler_Error_Release(ISAXErrorHandler *iface)
{
ConfigFileHandler *This = impl_from_ISAXErrorHandler(iface);
return IUnknown_Release((IUnknown*)This);
return ISAXContentHandler_Release(&This->ISAXContentHandler_iface);
}
static HRESULT WINAPI ConfigFileHandler_error(ISAXErrorHandler *iface,
ISAXLocator * pLocator, const WCHAR * pErrorMessage, HRESULT hrErrorCode)
{
WARN("%s,%x\n", debugstr_w(pErrorMessage), hrErrorCode);
WARN("%s,%lx\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);
WARN("%s,%lx\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);
WARN("%s,%lx\n", debugstr_w(pErrorMessage), hrErrorCode);
return S_OK;
}
@@ -376,6 +614,7 @@ static const struct ISAXErrorHandlerVtbl ConfigFileHandlerErrorVtbl =
static void init_config(parsed_config_file *config)
{
list_init(&config->supported_runtimes);
config->private_path = NULL;
}
static HRESULT parse_config(VARIANT input, parsed_config_file *result)
@@ -384,7 +623,7 @@ static HRESULT parse_config(VARIANT input, parsed_config_file *result)
ConfigFileHandler *handler;
HRESULT hr;
handler = HeapAlloc(GetProcessHeap(), 0, sizeof(ConfigFileHandler));
handler = malloc(sizeof(ConfigFileHandler));
if (!handler)
return E_OUTOFMEMORY;
@@ -416,9 +655,8 @@ static HRESULT parse_config(VARIANT input, parsed_config_file *result)
return S_OK;
}
HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
HRESULT parse_config_stream(IStream *stream, parsed_config_file *result)
{
IStream *stream;
VARIANT var;
HRESULT hr;
HRESULT initresult;
@@ -426,18 +664,10 @@ HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
init_config(result);
initresult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = (IUnknown*)stream;
hr = SHCreateStreamOnFileW(filename, STGM_SHARE_DENY_WRITE | STGM_READ | STGM_FAILIFTHERE, &stream);
if (SUCCEEDED(hr))
{
V_VT(&var) = VT_UNKNOWN;
V_UNKNOWN(&var) = (IUnknown*)stream;
hr = parse_config(var, result);
IStream_Release(stream);
}
hr = parse_config(var, result);
if (SUCCEEDED(initresult))
CoUninitialize();
@@ -445,14 +675,34 @@ HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
return hr;
}
HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result)
{
HRESULT hr;
IStream *stream;
init_config(result);
hr = CreateConfigStream(filename, &stream);
if (FAILED(hr))
return hr;
hr = parse_config_stream(stream, result);
IStream_Release(stream);
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);
free(cursor->version);
list_remove(&cursor->entry);
HeapFree(GetProcessHeap(), 0, cursor);
free(cursor);
}
free(file->private_path);
}

View File

@@ -17,7 +17,28 @@
* 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
{
@@ -77,7 +98,7 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
return ref;
}
@@ -87,7 +108,7 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
if (ref == 0)
{
@@ -100,7 +121,7 @@ static ULONG WINAPI cordebugprocess_Release(ICorDebugProcess *iface)
if(This->cordebug)
ICorDebug_Release(&This->cordebug->ICorDebug_iface);
HeapFree(GetProcessHeap(), 0, This);
free(This);
}
return ref;
@@ -384,7 +405,7 @@ static HRESULT CorDebugProcess_Create(CorDebug *cordebug, IUnknown** ppUnk, LPPR
{
DebugProcess *This;
This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
This = malloc(sizeof *This);
if ( !This )
return E_OUTOFMEMORY;
@@ -392,7 +413,7 @@ static HRESULT CorDebugProcess_Create(CorDebug *cordebug, IUnknown** ppUnk, LPPR
GetCurrentProcess(), &This->handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
{
ERR("Failed to duplicate process handle\n");
HeapFree(GetProcessHeap(), 0, This);
free(This);
return E_FAIL;
}
if(!DuplicateHandle(GetCurrentProcess(), lpProcessInformation->hThread,
@@ -401,7 +422,7 @@ static HRESULT CorDebugProcess_Create(CorDebug *cordebug, IUnknown** ppUnk, LPPR
CloseHandle(This->handle);
ERR("Failed to duplicate thread handle\n");
HeapFree(GetProcessHeap(), 0, This);
free(This);
return E_FAIL;
}
@@ -445,7 +466,7 @@ static HRESULT WINAPI process_enum_QueryInterface(ICorDebugProcessEnum *iface, R
static ULONG WINAPI process_enum_AddRef(ICorDebugProcessEnum *iface)
{
CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
TRACE("%p ref=%u\n", This, This->ref);
TRACE("%p ref=%lu\n", This, This->ref);
return ICorDebug_AddRef(&This->ICorDebug_iface);
}
@@ -453,7 +474,7 @@ static ULONG WINAPI process_enum_AddRef(ICorDebugProcessEnum *iface)
static ULONG WINAPI process_enum_Release(ICorDebugProcessEnum *iface)
{
CorDebug *This = impl_from_ICorDebugProcessEnum(iface);
TRACE("%p ref=%u\n", This, This->ref);
TRACE("%p ref=%lu\n", This, This->ref);
return ICorDebug_Release(&This->ICorDebug_iface);
}
@@ -496,7 +517,7 @@ 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);
FIXME("stub %p %ld %p %p\n", This, celt, processes, pceltFetched);
return E_NOTIMPL;
}
@@ -540,7 +561,7 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
return ref;
}
@@ -550,7 +571,7 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
if (ref == 0)
{
@@ -560,13 +581,13 @@ static ULONG WINAPI CorDebug_Release(ICorDebug *iface)
if(This->runtimehost)
ICLRRuntimeHost_Release(This->runtimehost);
if(This->pCallback)
if(This->pCallback2)
ICorDebugManagedCallback2_Release(This->pCallback2);
if(This->pCallback)
ICorDebugManagedCallback_Release(This->pCallback);
HeapFree(GetProcessHeap(), 0, This);
free(This);
}
return ref;
@@ -595,7 +616,7 @@ static HRESULT WINAPI CorDebug_Terminate(ICorDebug *iface)
}
list_remove(&cursor->entry);
HeapFree(GetProcessHeap(), 0, cursor);
free(cursor);
}
return S_OK;
@@ -652,7 +673,7 @@ static HRESULT WINAPI CorDebug_CreateProcess(ICorDebug *iface, LPCWSTR lpApplica
ICorDebugProcess *pDebugProcess;
HRESULT hr;
TRACE("stub %p %s %s %p %p %d %d %p %s %p %p %d %p\n", This, debugstr_w(lpApplicationName),
TRACE("stub %p %s %s %p %p %d %ld %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);
@@ -664,7 +685,7 @@ static HRESULT WINAPI CorDebug_CreateProcess(ICorDebug *iface, LPCWSTR lpApplica
hr = CorDebugProcess_Create(This, (IUnknown**)&pDebugProcess, lpProcessInformation);
if(hr == S_OK)
{
struct CorProcess *new_process = HeapAlloc( GetProcessHeap(), 0, sizeof(CorProcess) );
struct CorProcess *new_process = malloc(sizeof(CorProcess));
new_process->pProcess = pDebugProcess;
list_add_tail(&This->processes, &new_process->entry);
@@ -690,7 +711,7 @@ static HRESULT WINAPI CorDebug_DebugActiveProcess(ICorDebug *iface, DWORD id, BO
ICorDebugProcess **ppProcess)
{
CorDebug *This = impl_from_ICorDebug( iface );
FIXME("stub %p %d %d %p\n", This, id, win32Attach, ppProcess);
FIXME("stub %p %ld %d %p\n", This, id, win32Attach, ppProcess);
return E_NOTIMPL;
}
@@ -711,7 +732,7 @@ static HRESULT WINAPI CorDebug_EnumerateProcesses( ICorDebug *iface, ICorDebugPr
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);
FIXME("stub %p %ld %p\n", This, dwProcessId, ppProcess);
return E_NOTIMPL;
}
@@ -719,7 +740,7 @@ static HRESULT WINAPI CorDebug_CanLaunchOrAttach(ICorDebug *iface, DWORD dwProce
BOOL win32DebuggingEnabled)
{
CorDebug *This = impl_from_ICorDebug( iface );
FIXME("stub %p %d %d\n", This, dwProcessId, win32DebuggingEnabled);
FIXME("stub %p %ld %d\n", This, dwProcessId, win32DebuggingEnabled);
return S_OK;
}
@@ -743,7 +764,7 @@ HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk)
{
CorDebug *This;
This = HeapAlloc( GetProcessHeap(), 0, sizeof *This );
This = malloc(sizeof *This);
if ( !This )
return E_OUTOFMEMORY;

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,28 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#define COBJMACROS
#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;
@@ -58,7 +78,7 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
return ref;
}
@@ -68,11 +88,11 @@ 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);
TRACE("%p ref=%lu\n", This, ref);
if (ref == 0)
{
HeapFree(GetProcessHeap(), 0, This);
free(This);
}
return ref;
@@ -81,7 +101,7 @@ static ULONG WINAPI MetaDataDispenser_Release(IMetaDataDispenserEx* iface)
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,
FIXME("%p %s %lx %s %p\n", iface, debugstr_guid(rclsid), dwCreateFlags,
debugstr_guid(riid), ppIUnk);
return E_NOTIMPL;
}
@@ -89,7 +109,7 @@ static HRESULT WINAPI MetaDataDispenser_DefineScope(IMetaDataDispenserEx* iface,
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,
FIXME("%p %s %lx %s %p\n", iface, debugstr_w(szScope), dwOpenFlags,
debugstr_guid(riid), ppIUnk);
return E_NOTIMPL;
}
@@ -97,7 +117,7 @@ static HRESULT WINAPI MetaDataDispenser_OpenScope(IMetaDataDispenserEx* iface,
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,
FIXME("%p %p %lu %lx %s %p\n", iface, pData, cbData, dwOpenFlags,
debugstr_guid(riid), ppIUnk);
return E_NOTIMPL;
}
@@ -119,14 +139,14 @@ static HRESULT WINAPI MetaDataDispenser_GetOption(IMetaDataDispenserEx* iface,
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);
FIXME("%p %p %lu %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);
FIXME("%p %p %lu %p\n", iface, szBuffer, cchBuffer, pchBuffer);
return E_NOTIMPL;
}
@@ -134,7 +154,7 @@ 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),
FIXME("%p %s %s %s %s %p %lu %p\n", iface, debugstr_w(szAppBase),
debugstr_w(szPrivateBin), debugstr_w(szGlobalBin),
debugstr_w(szAssemblyName), szName, cchName, pcName);
return E_NOTIMPL;
@@ -144,7 +164,7 @@ static HRESULT WINAPI MetaDataDispenser_FindAssemblyModule(IMetaDataDispenserEx*
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),
FIXME("%p %s %s %s %s %s %p %lu %p\n", iface, debugstr_w(szAppBase),
debugstr_w(szPrivateBin), debugstr_w(szGlobalBin), debugstr_w(szAssemblyName),
debugstr_w(szModuleName), szName, cchName, pcName);
return E_NOTIMPL;
@@ -170,7 +190,7 @@ HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk)
{
MetaDataDispenser *This;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(MetaDataDispenser));
This = malloc(sizeof(MetaDataDispenser));
if (!This)
return E_OUTOFMEMORY;
@@ -178,7 +198,7 @@ HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk)
This->IMetaDataDispenserEx_iface.lpVtbl = &MetaDataDispenserVtbl;
This->ref = 1;
*ppUnk = (IUnknown*)This;
*ppUnk = (IUnknown*)&This->IMetaDataDispenserEx_iface;
return S_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -24,12 +24,13 @@
@ stdcall CorBindToRuntimeHost(wstr wstr wstr ptr long ptr ptr ptr)
@ stub CorDllMainWorker
@ stdcall CorExitProcess(long)
@ stub CorGetSvc
@ stub CorIsLatestSvc
@ stdcall CorGetSvc(ptr)
@ stdcall CorIsLatestSvc(ptr ptr)
@ stub CorMarkThreadInThreadPool
@ stub CorTickleSvc
@ stdcall CreateConfigStream(wstr ptr)
@ stdcall CreateDebuggingInterfaceFromVersion(long wstr ptr)
@ stdcall CreateInterface(ptr ptr ptr)
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@@ -37,7 +38,7 @@
@ stub EEDllGetClassObjectFromClass
@ stub EEDllRegisterServer
@ stub EEDllUnregisterServer
@ stdcall GetAssemblyMDImport(ptr ptr ptr)
@ stdcall GetAssemblyMDImport(wstr ptr ptr)
@ stub GetCORRequiredVersion
@ stub GetCORRootDirectory
@ stdcall GetCORSystemDirectory(ptr long ptr)
@@ -63,12 +64,12 @@
@ stub GetRequestedRuntimeVersionForCLSID
@ stub GetStartupFlags
@ stub GetTargetForVTableEntry
@ stub GetTokenForVTableEntry
@ stdcall GetTokenForVTableEntry(ptr ptr)
@ stdcall GetVersionFromProcess(ptr ptr long ptr)
@ stub GetXMLElement
@ stub GetXMLElementAttribute
@ stub GetXMLObject
@ stdcall LoadLibraryShim(ptr ptr ptr ptr)
@ stdcall LoadLibraryShim(wstr wstr ptr ptr)
@ stub LoadLibraryWithPolicyShim
@ stdcall LoadStringRCEx(long long ptr long long ptr)
@ stdcall LockClrVersion(ptr ptr ptr)
@@ -81,7 +82,7 @@
@ stdcall ND_RU1(ptr long)
@ stdcall ND_WI2(ptr long long)
@ stdcall ND_WI4(ptr long long)
@ stdcall ND_WI8(ptr long double)
@ stdcall ND_WI8(ptr long int64)
@ stdcall ND_WU1(ptr long long)
@ stub OpenCtrs
@ stub ReOpenMetaDataWithMemoryEx
@@ -107,7 +108,7 @@
@ stdcall StrongNameSignatureVerification(wstr long ptr)
@ stdcall StrongNameSignatureVerificationEx(wstr long ptr)
@ stub StrongNameSignatureVerificationFromImage
@ stub StrongNameTokenFromAssembly
@ stdcall StrongNameTokenFromAssembly(wstr ptr ptr)
@ stub StrongNameTokenFromAssemblyEx
@ stub StrongNameTokenFromPublicKey
@ stub TranslateSecurityAttributes
@@ -115,4 +116,4 @@
@ stdcall _CorExeMain2(ptr long ptr ptr ptr)
@ stdcall _CorExeMain()
@ stdcall _CorImageUnloading(ptr)
@ stdcall _CorValidateImage(ptr ptr)
@ stdcall _CorValidateImage(ptr wstr)

View File

@@ -0,0 +1,74 @@
/*
* 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
*/
#pragma makedep register
[
helpstring("Microsoft Common Language Runtime Host V2"),
threading(both),
progid("CLRMetaData.CLRRuntimeHost.1"),
vi_progid("CLRMetaData.CLRRuntimeHost"),
uuid(90F1A06E-7712-4762-86B5-7A5EBA6BDB01),
]
coclass ICLRRuntimeHost
{
}
[
helpstring("Microsoft Common Language Runtime Host V2"),
threading(both),
progid("CLRMetaData.CLRRuntimeHost.2"),
vi_progid("CLRMetaData.CLRRuntimeHost"),
uuid(90F1A06E-7712-4762-86B5-7A5EBA6BDB02),
]
coclass CLRRuntimeHost
{
}
[
helpstring("Microsoft Common Language Runtime Meta Data"),
threading(both),
progid("CLRMetaData.CorMetaDataDispenser.2"),
vi_progid("CLRMetaData.CorMetaDataDispenser"),
uuid(E5CB7A31-7512-11D2-89CE-0080C792E5D8),
]
coclass CorMetaDataDispenser
{
}
[
helpstring("Microsoft Common Language Runtime Meta Data"),
threading(both),
progid("CLRMetaData.CorMetaDataDispenserRuntime.2"),
vi_progid("CLRMetaData.CorMetaDataDispenserRuntime"),
uuid(1EC2DE53-75CC-11d2-9775-00A0C9B4D50C),
]
coclass CorMetaDataDispenserRuntime
{
}
[
helpstring("Microsoft Common Language Runtime Host"),
threading(both),
progid("CLRMetaData.CorRuntimeHost.2"),
vi_progid("CLRMetaData.CorRuntimeHost"),
uuid(CB2F6723-AB3A-11d2-9C40-00C04FA30A3E),
]
coclass CorRuntimeHost
{
}

View File

@@ -19,11 +19,44 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#define COBJMACROS
#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 "strongname.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 <rpcproxy.h>
#include "wine/debug.h"
static HINSTANCE MSCOREE_hInstance;
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
WINE_DECLARE_DEBUG_CHANNEL(winediag);
struct print_handler_tls
{
int length;
char buffer[1018];
};
static DWORD print_tls_index = TLS_OUT_OF_INDEXES;
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
@@ -34,7 +67,7 @@ char *WtoA(LPCWSTR wstr)
length = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
result = HeapAlloc(GetProcessHeap(), 0, length);
result = malloc(length);
if (result)
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, result, length, NULL, NULL);
@@ -44,8 +77,8 @@ char *WtoA(LPCWSTR wstr)
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};
static 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};
static const WCHAR install_root[] = {'I','n','s','t','a','l','l','R','o','o','t',0};
DWORD len;
HKEY key;
@@ -100,7 +133,7 @@ static ULONG WINAPI mscorecf_AddRef(IClassFactory *iface )
mscorecf *This = impl_from_IClassFactory(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("%p ref=%u\n", This, ref);
TRACE("%p ref=%lu\n", This, ref);
return ref;
}
@@ -110,11 +143,11 @@ static ULONG WINAPI mscorecf_Release(IClassFactory *iface )
mscorecf *This = impl_from_IClassFactory(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("%p ref=%u\n", This, ref);
TRACE("%p ref=%lu\n", This, ref);
if (ref == 0)
{
HeapFree(GetProcessHeap(), 0, This);
free(This);
}
return ref;
@@ -143,7 +176,7 @@ static HRESULT WINAPI mscorecf_CreateInstance(IClassFactory *iface,LPUNKNOWN pOu
}
else
{
WARN("Cannot create an instance object. 0x%08x\n", hr);
WARN("Cannot create an instance object. 0x%08lx\n", hr);
}
return hr;
}
@@ -171,13 +204,13 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
HRESULT ret;
ICLRRuntimeInfo *info;
TRACE("(%s, %s, %s, %p, %d, %s, %s, %p)\n", debugstr_w(pwszVersion),
TRACE("(%s, %s, %s, %p, %ld, %s, %s, %p)\n", debugstr_w(pwszVersion),
debugstr_w(pwszBuildFlavor), debugstr_w(pwszHostConfigFile), pReserved,
startupFlags, debugstr_guid(rclsid), debugstr_guid(riid), ppv);
*ppv = NULL;
ret = get_runtime_info(NULL, pwszVersion, pwszHostConfigFile, startupFlags, 0, TRUE, &info);
ret = get_runtime_info(NULL, pwszVersion, pwszHostConfigFile, NULL, startupFlags, 0, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -189,26 +222,88 @@ HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor
return ret;
}
void CDECL mono_print_handler_fn(const char *string, INT is_stdout)
{
struct print_handler_tls *tls = TlsGetValue(print_tls_index);
if (!tls)
{
tls = malloc(sizeof(*tls));
tls->length = 0;
TlsSetValue(print_tls_index, tls);
}
while (*string)
{
int remaining_buffer = sizeof(tls->buffer) - tls->length;
int length = strlen(string);
const char *newline = memchr(string, '\n', min(length, remaining_buffer));
if (newline)
{
length = newline - string + 1;
wine_dbg_printf("%.*s%.*s", tls->length, tls->buffer, length, string);
tls->length = 0;
string += length;
}
else if (length > remaining_buffer)
{
/* this would overflow Wine's debug buffer */
wine_dbg_printf("%.*s%.*s\n", tls->length, tls->buffer, remaining_buffer, string);
tls->length = 0;
string += remaining_buffer;
}
else
{
memcpy(tls->buffer + tls->length, string, length);
tls->length += length;
break;
}
}
}
void CDECL mono_log_handler_fn(const char *log_domain, const char *log_level, const char *message, INT fatal, void *user_data)
{
SIZE_T len = (log_domain ? strlen(log_domain) + 2 : 0) + strlen(message) + strlen("\n") + 1;
char *msg = calloc(len, sizeof(char));
if (msg)
{
sprintf(msg, "%s%s%s\n", log_domain ? log_domain : "", log_domain ? ": " : "", message);
mono_print_handler_fn(msg, 0);
}
free(msg);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved);
MSCOREE_hInstance = hinstDLL;
TRACE("(%p, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason)
{
#ifndef __REACTOS__
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
#endif
case DLL_PROCESS_ATTACH:
runtimehost_init();
DisableThreadLibraryCalls(hinstDLL);
print_tls_index = TlsAlloc();
if (print_tls_index == TLS_OUT_OF_INDEXES)
return FALSE;
break;
case DLL_THREAD_DETACH:
if (print_tls_index != TLS_OUT_OF_INDEXES)
free(TlsGetValue(print_tls_index));
break;
case DLL_PROCESS_DETACH:
expect_no_runtimes();
if (lpvReserved) break; /* process is terminating */
runtimehost_uninit();
if (print_tls_index != TLS_OUT_OF_INDEXES)
{
free(TlsGetValue(print_tls_index));
TlsFree(print_tls_index);
}
break;
}
return TRUE;
@@ -216,7 +311,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
__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));
TRACE("(%p, %lu, %s, %s, %s)\n", ptrMemory, cntMemory, debugstr_w(imageName), debugstr_w(loaderName), debugstr_w(cmdLine));
FIXME("Directly running .NET applications not supported.\n");
return -1;
}
@@ -224,8 +319,7 @@ __int32 WINAPI _CorExeMain2(PBYTE ptrMemory, DWORD cntMemory, LPWSTR imageName,
void WINAPI CorExitProcess(int exitCode)
{
TRACE("(%x)\n", exitCode);
unload_all_runtimes();
ExitProcess(exitCode);
CLRMetaHost_ExitProcess(0, exitCode);
}
VOID WINAPI _CorImageUnloading(PVOID imageBase)
@@ -244,12 +338,12 @@ HRESULT WINAPI GetCORSystemDirectory(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwL
ICLRRuntimeInfo *info;
HRESULT ret;
TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
TRACE("(%p, %ld, %p)!\n", pbuffer, cchBuffer, dwLength);
if (!dwLength || !pbuffer)
return E_POINTER;
ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
ret = get_runtime_info(NULL, NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -267,12 +361,12 @@ HRESULT WINAPI GetCORVersion(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
ICLRRuntimeInfo *info;
HRESULT ret;
TRACE("(%p, %d, %p)!\n", pbuffer, cchBuffer, dwLength);
TRACE("(%p, %ld, %p)!\n", pbuffer, cchBuffer, dwLength);
if (!dwLength || !pbuffer)
return E_POINTER;
ret = get_runtime_info(NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
ret = get_runtime_info(NULL, NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -285,6 +379,23 @@ HRESULT WINAPI GetCORVersion(LPWSTR pbuffer, DWORD cchBuffer, DWORD *dwLength)
return ret;
}
HRESULT WINAPI CorIsLatestSvc(int *unk1, int *unk2)
{
ERR_(winediag)("If this function is called, it is likely the result of a broken .NET installation\n");
if (!unk1 || !unk2)
return E_POINTER;
return S_OK;
}
HRESULT WINAPI CorGetSvc(void *unk)
{
ERR_(winediag)("If this function is called, it is likely the result of a broken .NET installation\n");
return E_NOTIMPL;
}
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)
@@ -293,7 +404,7 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
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),
TRACE("(%s, %s, %s, 0x%08lx, 0x%08lx, %p, 0x%08lx, %p, %p, 0x%08lx, %p)\n", debugstr_w(pExe),
debugstr_w(pwszVersion), debugstr_w(pConfigurationFile), startupFlags, runtimeInfoFlags, pDirectory,
dwDirectory, dwDirectoryLength, pVersion, cchBuffer, dwlength);
@@ -301,7 +412,7 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
if (!dwlength) dwlength = &length_dummy;
ret = get_runtime_info(pExe, pwszVersion, pConfigurationFile, startupFlags, runtimeInfoFlags, TRUE, &info);
ret = get_runtime_info(pExe, pwszVersion, pConfigurationFile, NULL, startupFlags, runtimeInfoFlags, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -325,7 +436,7 @@ HRESULT WINAPI GetRequestedRuntimeInfo(LPCWSTR pExe, LPCWSTR pwszVersion, LPCWST
HRESULT WINAPI GetRequestedRuntimeVersion(LPWSTR pExe, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwlength)
{
TRACE("(%s, %p, %d, %p)\n", debugstr_w(pExe), pVersion, cchBuffer, dwlength);
TRACE("(%s, %p, %ld, %p)\n", debugstr_w(pExe), pVersion, cchBuffer, dwlength);
if(!dwlength)
return E_POINTER;
@@ -341,7 +452,7 @@ HRESULT WINAPI GetRealProcAddress(LPCSTR procname, void **ppv)
HRESULT WINAPI GetFileVersion(LPCWSTR szFilename, LPWSTR szBuffer, DWORD cchBuffer, DWORD *dwLength)
{
TRACE("(%s, %p, %d, %p)\n", debugstr_w(szFilename), szBuffer, cchBuffer, dwLength);
TRACE("(%s, %p, %ld, %p)\n", debugstr_w(szFilename), szBuffer, cchBuffer, dwLength);
if (!szFilename || !dwLength)
return E_POINTER;
@@ -379,11 +490,11 @@ HRESULT WINAPI LoadLibraryShim( LPCWSTR szDllName, LPCWSTR szVersion, LPVOID pvR
else
szVersion = default_version;
}
strcatW(dll_filename, szVersion);
strcatW(dll_filename, slash);
lstrcatW(dll_filename, szVersion);
lstrcatW(dll_filename, slash);
}
strcatW(dll_filename, szDllName);
lstrcatW(dll_filename, szDllName);
*phModDll = LoadLibraryW(dll_filename);
@@ -398,7 +509,7 @@ HRESULT WINAPI LockClrVersion(FLockClrVersionCallback hostCallback, FLockClrVers
HRESULT WINAPI CoInitializeCor(DWORD fFlags)
{
FIXME("(0x%08x): stub\n", fFlags);
FIXME("(0x%08lx): stub\n", fFlags);
return S_OK;
}
@@ -410,7 +521,7 @@ HRESULT WINAPI GetAssemblyMDImport(LPCWSTR szFileName, REFIID riid, IUnknown **p
HRESULT WINAPI GetVersionFromProcess(HANDLE hProcess, LPWSTR pVersion, DWORD cchBuffer, DWORD *dwLength)
{
FIXME("(%p, %p, %d, %p): stub\n", hProcess, pVersion, cchBuffer, dwLength);
FIXME("(%p, %p, %ld, %p): stub\n", hProcess, pVersion, cchBuffer, dwLength);
return E_NOTIMPL;
}
@@ -421,7 +532,7 @@ HRESULT WINAPI LoadStringRCEx(LCID culture, UINT resId, LPWSTR pBuffer, int iBuf
return E_INVALIDARG;
pBuffer[0] = 0;
if (resId) {
FIXME("(%d, %x, %p, %d, %d, %p): semi-stub\n", culture, resId, pBuffer, iBufLen, bQuiet, pBufLen);
FIXME("(%ld, %x, %p, %d, %d, %p): semi-stub\n", culture, resId, pBuffer, iBufLen, bQuiet, pBufLen);
res = E_NOTIMPL;
}
else
@@ -442,12 +553,12 @@ HRESULT WINAPI CorBindToRuntimeEx(LPWSTR szVersion, LPWSTR szBuildFlavor, DWORD
HRESULT ret;
ICLRRuntimeInfo *info;
TRACE("%s %s %d %s %s %p\n", debugstr_w(szVersion), debugstr_w(szBuildFlavor), nflags, debugstr_guid( rslsid ),
TRACE("%s %s %ld %s %s %p\n", debugstr_w(szVersion), debugstr_w(szBuildFlavor), nflags, debugstr_guid( rslsid ),
debugstr_guid( riid ), ppv);
*ppv = NULL;
ret = get_runtime_info(NULL, szVersion, NULL, nflags, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
ret = get_runtime_info(NULL, szVersion, NULL, NULL, nflags, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -461,8 +572,23 @@ HRESULT WINAPI CorBindToRuntimeEx(LPWSTR szVersion, LPWSTR szBuildFlavor, DWORD
HRESULT WINAPI CorBindToCurrentRuntime(LPCWSTR filename, REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
FIXME("(%s, %s, %s, %p): stub\n", debugstr_w(filename), debugstr_guid(rclsid), debugstr_guid(riid), ppv);
return E_NOTIMPL;
HRESULT ret;
ICLRRuntimeInfo *info;
TRACE("(%s, %s, %s, %p)\n", debugstr_w(filename), debugstr_guid(rclsid), debugstr_guid(riid), ppv);
*ppv = NULL;
ret = get_runtime_info(NULL, NULL, filename, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
ret = ICLRRuntimeInfo_GetInterface(info, rclsid, riid, ppv);
ICLRRuntimeInfo_Release(info);
}
return ret;
}
STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject)
@@ -476,7 +602,7 @@ STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject)
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);
ret = get_runtime_info(NULL, NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, TRUE, &info);
if (SUCCEEDED(ret))
{
@@ -500,27 +626,28 @@ STDAPI ClrCreateManagedInstance(LPCWSTR pTypeName, REFIID riid, void **ppObject)
return ret;
}
BOOL WINAPI StrongNameSignatureVerification(LPCWSTR filename, DWORD inFlags, DWORD* pOutFlags)
BOOLEAN WINAPI StrongNameSignatureVerification(LPCWSTR filename, DWORD inFlags, DWORD *pOutFlags)
{
FIXME("(%s, 0x%X, %p): stub\n", debugstr_w(filename), inFlags, pOutFlags);
FIXME("(%s, 0x%lX, %p): stub\n", debugstr_w(filename), inFlags, pOutFlags);
return FALSE;
}
BOOL WINAPI StrongNameSignatureVerificationEx(LPCWSTR filename, BOOL forceVerification, BOOL* pVerified)
BOOLEAN WINAPI StrongNameSignatureVerificationEx(LPCWSTR filename, BOOLEAN forceVerification, BOOLEAN *pVerified)
{
FIXME("(%s, %u, %p): stub\n", debugstr_w(filename), forceVerification, pVerified);
return FALSE;
*pVerified = TRUE;
return TRUE;
}
HRESULT WINAPI CreateConfigStream(LPCWSTR filename, IStream **stream)
BOOLEAN WINAPI StrongNameTokenFromAssembly(LPCWSTR path, BYTE **token, ULONG *size)
{
FIXME("(%s, %p): stub\n", debugstr_w(filename), stream);
return E_NOTIMPL;
FIXME("(%s, %p, %p): stub\n", debugstr_w(path), token, size);
return FALSE;
}
HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR version, IUnknown **ppv)
{
const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
static const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
HRESULT hr = E_FAIL;
ICLRRuntimeInfo *runtimeinfo;
@@ -534,7 +661,7 @@ HRESULT WINAPI CreateDebuggingInterfaceFromVersion(int nDebugVersion, LPCWSTR ve
*ppv = NULL;
if(strcmpW(version, v2_0) != 0)
if(wcscmp(version, v2_0) != 0)
{
FIXME("Currently .NET Version '%s' not support.\n", debugstr_w(version));
return E_INVALIDARG;
@@ -563,12 +690,21 @@ HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterfac
if (IsEqualGUID(clsid, &CLSID_CLRMetaHost))
return CLRMetaHost_CreateInstance(riid, ppInterface);
if (IsEqualGUID(clsid, &CLSID_CLRMetaHostPolicy))
return CLRMetaHostPolicy_CreateInstance(riid, ppInterface);
FIXME("not implemented for class %s\n", debugstr_guid(clsid));
return CLASS_E_CLASSNOTAVAILABLE;
}
HRESULT WINAPI CreateInterface(REFCLSID clsid, REFIID riid, LPVOID *ppInterface)
{
TRACE("(%s,%s,%p)\n", debugstr_guid(clsid), debugstr_guid(riid), ppInterface);
return CLRCreateInstance(clsid, riid, ppInterface);
}
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
mscorecf *This;
@@ -579,10 +715,10 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
if(!ppv)
return E_INVALIDARG;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf));
This = malloc(sizeof(mscorecf));
This->IClassFactory_iface.lpVtbl = &mscorecf_vtbl;
This->pfnCreateInstance = &create_monodata;
This->pfnCreateInstance = create_monodata;
This->ref = 1;
This->clsid = *rclsid;
@@ -592,19 +728,245 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
return hr;
}
static void parse_msi_version_string(const char *version, int *parts)
{
const char *minor_start, *build_start;
parts[0] = atoi(version);
parts[1] = parts[2] = 0;
minor_start = strchr(version, '.');
if (minor_start)
{
minor_start++;
parts[1] = atoi(minor_start);
build_start = strchr(minor_start, '.');
if (build_start)
parts[2] = atoi(build_start+1);
}
}
static int compare_versions(const char *a, const char *b)
{
int a_parts[3], b_parts[3], i;
parse_msi_version_string(a, a_parts);
parse_msi_version_string(b, b_parts);
for (i=0; i<3; i++)
if (a_parts[i] != b_parts[i])
return a_parts[i] - b_parts[i];
return 0;
}
static BOOL invoke_appwiz(void)
{
PROCESS_INFORMATION pi;
STARTUPINFOW si;
WCHAR app[MAX_PATH];
WCHAR *args;
LONG len;
BOOL ret;
static const WCHAR controlW[] = {'\\','c','o','n','t','r','o','l','.','e','x','e',0};
static const WCHAR argsW[] =
{' ','a','p','p','w','i','z','.','c','p','l',' ','i','n','s','t','a','l','l','_','m','o','n','o',0};
len = GetSystemDirectoryW(app, MAX_PATH - ARRAY_SIZE(controlW));
memcpy(app+len, controlW, sizeof(controlW));
args = malloc(len * sizeof(WCHAR) + sizeof(controlW) + sizeof(argsW));
if(!args)
return FALSE;
memcpy(args, app, len*sizeof(WCHAR) + sizeof(controlW));
memcpy(args + len + ARRAY_SIZE(controlW) - 1, argsW, sizeof(argsW));
TRACE("starting %s\n", debugstr_w(args));
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
ret = CreateProcessW(app, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
free(args);
if (ret) {
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
}
return ret;
}
static BOOL get_support_msi(LPCWSTR mono_path, LPWSTR msi_path)
{
static const WCHAR support_msi_relative[] = {'\\','s','u','p','p','o','r','t','\\','w','i','n','e','m','o','n','o','-','s','u','p','p','o','r','t','.','m','s','i',0};
UINT (WINAPI *pMsiOpenPackageW)(LPCWSTR,ULONG*);
UINT (WINAPI *pMsiGetProductPropertyA)(ULONG,LPCSTR,LPSTR,LPDWORD);
UINT (WINAPI *pMsiCloseHandle)(ULONG);
HMODULE hmsi = NULL;
char versionstringbuf[15];
UINT res;
DWORD buffer_size;
ULONG msiproduct;
BOOL ret=FALSE;
hmsi = GetModuleHandleA("msi");
lstrcpyW(msi_path, mono_path);
lstrcatW(msi_path, support_msi_relative);
pMsiOpenPackageW = (void*)GetProcAddress(hmsi, "MsiOpenPackageW");
res = pMsiOpenPackageW(msi_path, &msiproduct);
if (res == ERROR_SUCCESS)
{
buffer_size = sizeof(versionstringbuf);
pMsiGetProductPropertyA = (void*)GetProcAddress(hmsi, "MsiGetProductPropertyA");
res = pMsiGetProductPropertyA(msiproduct, "ProductVersion", versionstringbuf, &buffer_size);
pMsiCloseHandle = (void*)GetProcAddress(hmsi, "MsiCloseHandle");
pMsiCloseHandle(msiproduct);
}
if (res == ERROR_SUCCESS) {
TRACE("found support msi version %s at %s\n", versionstringbuf, debugstr_w(msi_path));
if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
{
ret = TRUE;
}
}
return ret;
}
static BOOL install_wine_mono(void)
{
BOOL is_wow64 = FALSE;
HMODULE hmsi = NULL;
HRESULT initresult = E_FAIL;
UINT (WINAPI *pMsiEnumRelatedProductsA)(LPCSTR,DWORD,DWORD,LPSTR);
UINT (WINAPI *pMsiGetProductInfoA)(LPCSTR,LPCSTR,LPSTR,DWORD*);
UINT (WINAPI *pMsiInstallProductW)(LPCWSTR,LPCWSTR);
char versionstringbuf[15];
char productcodebuf[39];
UINT res;
DWORD buffer_size;
BOOL ret;
WCHAR mono_path[MAX_PATH];
WCHAR support_msi_path[MAX_PATH];
static const char* mono_upgrade_code = "{DE624609-C6B5-486A-9274-EF0B854F6BC5}";
IsWow64Process(GetCurrentProcess(), &is_wow64);
if (is_wow64)
{
TRACE("not installing mono in wow64 process\n");
return TRUE;
}
TRACE("searching for mono runtime\n");
if (!get_mono_path(mono_path, FALSE))
{
TRACE("mono runtime not found\n");
return invoke_appwiz();
}
TRACE("mono runtime is at %s\n", debugstr_w(mono_path));
hmsi = LoadLibraryA("msi");
if (!hmsi)
{
ERR("couldn't load msi.dll\n");
return FALSE;
}
pMsiEnumRelatedProductsA = (void*)GetProcAddress(hmsi, "MsiEnumRelatedProductsA");
res = pMsiEnumRelatedProductsA(mono_upgrade_code, 0, 0, productcodebuf);
if (res == ERROR_SUCCESS)
{
pMsiGetProductInfoA = (void*)GetProcAddress(hmsi, "MsiGetProductInfoA");
buffer_size = sizeof(versionstringbuf);
res = pMsiGetProductInfoA(productcodebuf, "VersionString", versionstringbuf, &buffer_size);
}
else if (res != ERROR_NO_MORE_ITEMS)
{
ERR("MsiEnumRelatedProducts failed, err=%u\n", res);
}
if (res == ERROR_SUCCESS)
{
TRACE("found installed support package %s\n", versionstringbuf);
if (compare_versions(WINE_MONO_VERSION, versionstringbuf) <= 0)
{
TRACE("support package is at least %s, quitting\n", WINE_MONO_VERSION);
ret = TRUE;
goto end;
}
}
initresult = CoInitialize(NULL);
ret = get_support_msi(mono_path, support_msi_path);
if (!ret)
{
/* Try looking outside c:\windows\mono */
ret = (get_mono_path(mono_path, TRUE) &&
get_support_msi(mono_path, support_msi_path));
}
if (ret)
{
TRACE("installing support msi\n");
pMsiInstallProductW = (void*)GetProcAddress(hmsi, "MsiInstallProductW");
res = pMsiInstallProductW(support_msi_path, NULL);
if (res == ERROR_SUCCESS)
{
ret = TRUE;
goto end;
}
else
ERR("MsiInstallProduct failed, err=%i\n", res);
}
ret = invoke_appwiz();
end:
if (hmsi)
FreeLibrary(hmsi);
if (SUCCEEDED(initresult))
CoUninitialize();
return ret;
}
HRESULT WINAPI DllRegisterServer(void)
{
return __wine_register_resources( MSCOREE_hInstance );
install_wine_mono();
return __wine_register_resources();
}
HRESULT WINAPI DllUnregisterServer(void)
{
return __wine_unregister_resources( MSCOREE_hInstance );
}
HRESULT WINAPI DllCanUnloadNow(VOID)
{
return S_FALSE;
return __wine_unregister_resources();
}
void WINAPI CoEEShutDownCOM(void)

View File

@@ -20,34 +20,13 @@
#ifndef __MSCOREE_PRIVATE__
#define __MSCOREE_PRIVATE__
#include <stdarg.h>
extern char *WtoA(const WCHAR *wstr) __WINE_DEALLOC(free) __WINE_MALLOC;
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <objbase.h>
#include <cor.h>
#include <cordebug.h>
#include <metahost.h>
#include <wine/list.h>
#include <wine/unicode.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
extern char *WtoA(LPCWSTR wstr) DECLSPEC_HIDDEN;
extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj) DECLSPEC_HIDDEN;
extern HRESULT CLRMetaHost_CreateInstance(REFIID riid, void **ppobj);
extern HRESULT CLRMetaHostPolicy_CreateInstance(REFIID riid, void **ppobj);
extern HRESULT WINAPI CLRMetaHost_GetVersionFromFile(ICLRMetaHost* iface,
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer) DECLSPEC_HIDDEN;
LPCWSTR pwzFilePath, LPWSTR pwzBuffer, DWORD *pcchBuffer);
typedef struct _VTableFixup {
DWORD rva;
@@ -57,11 +36,16 @@ typedef struct _VTableFixup {
typedef struct tagASSEMBLY ASSEMBLY;
extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file) DECLSPEC_HIDDEN;
extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule) DECLSPEC_HIDDEN;
extern HRESULT assembly_release(ASSEMBLY *assembly) DECLSPEC_HIDDEN;
extern HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version) DECLSPEC_HIDDEN;
extern HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count) DECLSPEC_HIDDEN;
typedef BOOL (WINAPI *NativeEntryPointFunc)(HINSTANCE, DWORD, LPVOID);
extern HRESULT assembly_create(ASSEMBLY **out, LPCWSTR file);
extern HRESULT assembly_from_hmodule(ASSEMBLY **out, HMODULE hmodule);
extern HRESULT assembly_release(ASSEMBLY *assembly);
extern HRESULT assembly_get_runtime_version(ASSEMBLY *assembly, LPSTR *version);
extern HRESULT assembly_get_vtable_fixups(ASSEMBLY *assembly, VTableFixup **fixups, DWORD *count);
extern HRESULT assembly_get_native_entrypoint(ASSEMBLY *assembly, NativeEntryPointFunc *func);
#define WINE_MONO_VERSION "9.4.0"
/* Mono embedding */
typedef struct _MonoDomain MonoDomain;
@@ -76,19 +60,14 @@ typedef struct _MonoMethod MonoMethod;
typedef struct _MonoProfiler MonoProfiler;
typedef struct _MonoThread MonoThread;
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;
@@ -96,10 +75,7 @@ struct RuntimeHost
{
ICorRuntimeHost ICorRuntimeHost_iface;
ICLRRuntimeHost ICLRRuntimeHost_iface;
const CLRRuntimeInfo *version;
loaded_mono *mono;
struct list domains;
MonoDomain *default_domain;
CLRRuntimeInfo *version;
CRITICAL_SECTION lock;
LONG ref;
};
@@ -127,15 +103,21 @@ typedef struct CorDebug
} 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;
IStream *config_stream, DWORD startup_flags, DWORD runtimeinfo_flags, BOOL legacy,
ICLRRuntimeInfo **result);
extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result) DECLSPEC_HIDDEN;
extern BOOL get_mono_path(LPWSTR path, BOOL skip_local);
extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk) DECLSPEC_HIDDEN;
extern MonoDomain* get_root_domain(void);
extern HRESULT ICLRRuntimeInfo_GetRuntimeHost(ICLRRuntimeInfo *iface, RuntimeHost **result);
extern HRESULT MetaDataDispenser_CreateInstance(IUnknown **ppUnk);
typedef struct parsed_config_file
{
struct list supported_runtimes;
LPWSTR private_path;
} parsed_config_file;
typedef struct supported_runtime
@@ -144,9 +126,13 @@ typedef struct supported_runtime
LPWSTR version;
} supported_runtime;
extern HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result) DECLSPEC_HIDDEN;
extern WCHAR **private_path;
extern void free_parsed_config_file(parsed_config_file *file) DECLSPEC_HIDDEN;
extern HRESULT parse_config_file(LPCWSTR filename, parsed_config_file *result);
extern HRESULT parse_config_stream(IStream *stream, parsed_config_file *result);
extern void free_parsed_config_file(parsed_config_file *file);
typedef enum {
MONO_IMAGE_OK,
@@ -155,75 +141,93 @@ typedef enum {
MONO_IMAGE_IMAGE_INVALID
} MonoImageOpenStatus;
typedef MonoAssembly* (*MonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
typedef MonoAssembly* (CDECL *MonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
typedef void (*MonoProfileFunc)(MonoProfiler *prof);
#define WINE_PRELOAD_CONTINUE 0
#define WINE_PRELOAD_SKIP_PRIVATE_PATH 1
#define WINE_PRELOAD_SKIP_GAC 2
#define WINE_PRELOAD_SET_GAC 4
struct loaded_mono
{
HMODULE mono_handle;
HMODULE glib_handle;
typedef MonoAssembly* (CDECL *WineMonoAssemblyPreLoadFunc)(MonoAssemblyName *aname, char **assemblies_path, int *flags, void *user_data);
BOOL is_started;
BOOL is_shutdown;
typedef void (CDECL *MonoProfileFunc)(MonoProfiler *prof);
MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
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 *);
MonoImage* (CDECL *mono_image_open_from_module_handle)(HMODULE module_handle, char* fname, UINT has_entry_point, MonoImageOpenStatus* status);
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);
void* (CDECL *mono_marshal_get_vtfixup_ftnptr)(MonoImage *image, DWORD token, WORD type);
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);
MonoThread* (CDECL *mono_thread_attach)(MonoDomain *domain);
};
typedef void (CDECL *MonoPrintCallback) (const char *string, INT is_stdout);
typedef void (*MonoLogCallback) (const char *log_domain, const char *log_level, const char *message, INT fatal, void *user_data);
typedef enum {
MONO_AOT_MODE_NONE,
MONO_AOT_MODE_NORMAL,
MONO_AOT_MODE_HYBRID,
MONO_AOT_MODE_FULL,
MONO_AOT_MODE_LLVMONLY,
MONO_AOT_MODE_INTERP,
MONO_AOT_MODE_INTERP_LLVMONLY,
MONO_AOT_MODE_LLVMONLY_INTERP,
MONO_AOT_MODE_INTERP_ONLY
} MonoAotMode;
extern BOOL is_mono_started;
extern MonoImage* (CDECL *mono_assembly_get_image)(MonoAssembly *assembly);
extern MonoAssembly* (CDECL *mono_assembly_load_from)(MonoImage *image, const char *fname, MonoImageOpenStatus *status);
extern const char* (CDECL *mono_assembly_name_get_name)(MonoAssemblyName *aname);
extern MonoAssembly* (CDECL *mono_assembly_open)(const char *filename, MonoImageOpenStatus *status);
extern void (CDECL *mono_callspec_set_assembly)(MonoAssembly *assembly);
extern MonoClass* (CDECL *mono_class_from_mono_type)(MonoType *type);
extern MonoClass* (CDECL *mono_class_from_name)(MonoImage *image, const char* name_space, const char *name);
extern MonoMethod* (CDECL *mono_class_get_method_from_name)(MonoClass *klass, const char *name, int param_count);
extern MonoDomain* (CDECL *mono_domain_get)(void);
extern MonoDomain* (CDECL *mono_domain_get_by_id)(int id);
extern BOOL (CDECL *mono_domain_set)(MonoDomain *domain, BOOL force);
extern void (CDECL *mono_domain_set_config)(MonoDomain *domain,const char *base_dir,const char *config_file_name);
extern MonoImage* (CDECL *mono_get_corlib)(void);
extern int (CDECL *mono_jit_exec)(MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
extern MonoDomain* (CDECL *mono_jit_init_version)(const char *domain_name, const char *runtime_version);
extern MonoImage* (CDECL *mono_image_open_from_module_handle)(HMODULE module_handle, char* fname, UINT has_entry_point, MonoImageOpenStatus* status);
extern void* (CDECL *mono_marshal_get_vtfixup_ftnptr)(MonoImage *image, DWORD token, WORD type);
extern MonoDomain* (CDECL *mono_object_get_domain)(MonoObject *obj);
extern MonoMethod* (CDECL *mono_object_get_virtual_method)(MonoObject *obj, MonoMethod *method);
extern MonoObject* (CDECL *mono_object_new)(MonoDomain *domain, MonoClass *klass);
extern void* (CDECL *mono_object_unbox)(MonoObject *obj);
extern MonoType* (CDECL *mono_reflection_type_from_name)(char *name, MonoImage *image);
extern MonoObject* (CDECL *mono_runtime_invoke)(MonoMethod *method, void *obj, void **params, MonoObject **exc);
extern void (CDECL *mono_runtime_object_init)(MonoObject *this_obj);
extern void (CDECL *mono_runtime_quit)(void);
extern MonoString* (CDECL *mono_string_new)(MonoDomain *domain, const char *str);
extern MonoThread* (CDECL *mono_thread_attach)(MonoDomain *domain);
extern void (CDECL *mono_thread_manage)(void);
extern void (CDECL *mono_trace_set_print_handler)(MonoPrintCallback callback);
extern void (CDECL *mono_trace_set_printerr_handler)(MonoPrintCallback callback);
/* loaded runtime interfaces */
extern void unload_all_runtimes(void) DECLSPEC_HIDDEN;
extern void expect_no_runtimes(void);
extern void expect_no_runtimes(void) DECLSPEC_HIDDEN;
extern HRESULT RuntimeHost_Construct(CLRRuntimeInfo *runtime_version, RuntimeHost** result);
extern HRESULT RuntimeHost_Construct(const CLRRuntimeInfo *runtime_version,
loaded_mono *loaded_mono, RuntimeHost** result) DECLSPEC_HIDDEN;
extern void RuntimeHost_ExitProcess(RuntimeHost *This, INT exitcode);
extern HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv) DECLSPEC_HIDDEN;
extern HRESULT RuntimeHost_GetInterface(RuntimeHost *This, REFCLSID clsid, REFIID riid, void **ppv);
extern HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj, IUnknown **ppUnk) DECLSPEC_HIDDEN;
extern HRESULT RuntimeHost_GetIUnknownForObject(RuntimeHost *This, MonoObject *obj, IUnknown **ppUnk);
extern HRESULT RuntimeHost_CreateManagedInstance(RuntimeHost *This, LPCWSTR name,
MonoDomain *domain, MonoObject **result) DECLSPEC_HIDDEN;
MonoDomain *domain, MonoObject **result);
extern HRESULT RuntimeHost_Destroy(RuntimeHost *This) DECLSPEC_HIDDEN;
HRESULT WINAPI CLRMetaHost_ExitProcess(ICLRMetaHost* iface, INT32 iExitCode);
HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime) DECLSPEC_HIDDEN;
HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, REFIID iid, LPVOID *ppRuntime);
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk);
extern HRESULT create_monodata(REFIID riid, LPVOID *ppObj) DECLSPEC_HIDDEN;
extern HRESULT create_monodata(REFCLSID clsid, LPVOID *ppObj);
extern HRESULT get_file_from_strongname(WCHAR* stringnameW, WCHAR* assemblies_path, int path_length);
extern void runtimehost_init(void);
extern void runtimehost_uninit(void);
extern void CDECL mono_print_handler_fn(const char *string, INT is_stdout);
extern void CDECL mono_log_handler_fn(const char *log_domain, const char *log_level, const char *message, INT fatal, void *user_data);
#endif /* __MSCOREE_PRIVATE__ */

View File

@@ -0,0 +1,6 @@
#include <windows.h>
HRESULT WINAPI DllCanUnloadNow(void)
{
return S_FALSE;
}

View File

@@ -1,13 +1,18 @@
remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS)
add_definitions(-DUSE_WINE_TODOS)
add_executable(mscoree_winetest
debugging.c
metahost.c
mscoree.c
testlist.c)
testlist.c
resource.rc)
add_idl_headers(mscoree_winetest_idlheader interfaces.idl)
target_link_libraries(mscoree_winetest wine uuid)
set_module_type(mscoree_winetest win32cui)
add_importlibs(mscoree_winetest ole32 shlwapi msvcrt kernel32 ntdll)
add_dependencies(mscoree_winetest mscoree_winetest_idlheader)
add_rostests_file(TARGET mscoree_winetest)

View File

@@ -0,0 +1,417 @@
/*
* Copyright 2018 Fabian Maurer
*
* 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 <stdio.h>
#include "windows.h"
#include "ole2.h"
#include "mscoree.h"
#include "corerror.h"
#include "shlwapi.h"
#include "shlobj.h"
#include "wine/test.h"
#include "initguid.h"
#include "interfaces.h"
HMODULE hmscoree;
DEFINE_GUID(IID_ITest2, 0x50adb433, 0xf6c5, 0x3b30, 0x92,0x0a, 0x55,0x57,0x11,0x86,0x75,0x09);
typedef enum _run_type
{
run_type_current_working_directory = 0,
run_type_exe_directory,
run_type_system32,
} run_type;
static BOOL write_resource_file(const char *path_tmp, const char *name_res, const char *name_file, char *path_file)
{
HRSRC rsrc;
void *rsrc_data;
DWORD rsrc_size;
BOOL ret;
HANDLE hfile;
rsrc = FindResourceA(GetModuleHandleA(NULL), name_res, (LPCSTR)RT_RCDATA);
if (!rsrc) return FALSE;
rsrc_data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
if (!rsrc_data) return FALSE;
rsrc_size = SizeofResource(GetModuleHandleA(NULL), rsrc);
if (!rsrc_size) return FALSE;
strcpy(path_file, path_tmp);
PathAppendA(path_file, name_file);
hfile = CreateFileA(path_file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hfile == INVALID_HANDLE_VALUE) return FALSE;
ret = WriteFile(hfile, rsrc_data, rsrc_size, &rsrc_size, NULL);
CloseHandle(hfile);
return ret;
}
static BOOL compile_cs_to_dll(char *source_path, char *dest_path)
{
const char *path_csc = "C:\\windows\\Microsoft.NET\\Framework\\v2.0.50727\\csc.exe";
char cmdline[2 * MAX_PATH + 74];
char path_temp[MAX_PATH];
PROCESS_INFORMATION pi;
STARTUPINFOA si = { 0 };
BOOL ret;
if (!PathFileExistsA(path_csc))
{
skip("Can't find csc.exe\n");
return FALSE;
}
GetTempPathA(MAX_PATH, path_temp);
PathAppendA(path_temp, "comtest.dll");
sprintf(cmdline, "%s /t:library /out:\"%s\" \"%s\"", path_csc, path_temp, source_path);
si.cb = sizeof(si);
ret = CreateProcessA(path_csc, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
ok(ret, "Could not create process: %lu\n", GetLastError());
wait_child_process(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
ret = PathFileExistsA(path_temp);
ok(ret, "Compilation failed\n");
ret = MoveFileA(path_temp, dest_path);
ok(ret, "Could not move %s to %s: %lu\n", path_temp, dest_path, GetLastError());
return ret;
}
static void run_test(BOOL expect_success)
{
typedef HRESULT (WINAPI *_DllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
ITest *test = NULL;
HRESULT hr;
_DllGetClassObject getClassObject;
IClassFactory *classFactory = NULL;
HRESULT result_expected = expect_success ? S_OK : HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
hr = CoCreateInstance(&CLSID_Test, NULL, CLSCTX_INPROC_SERVER, &IID_ITest, (void**)&test);
todo_wine_if(!expect_success)
ok(hr == result_expected, "Expected %lx, got %lx\n", result_expected, hr);
if (hr == S_OK)
{
int i = 0;
hr = ITest_Func(test, &i);
ok(hr == S_OK, "Got %lx\n", hr);
ok(i == 42, "Expected 42, got %d\n", i);
ITest_Release(test);
}
getClassObject = (_DllGetClassObject)GetProcAddress(hmscoree, "DllGetClassObject");
hr = getClassObject(&CLSID_Test, &IID_IClassFactory, (void **)&classFactory);
todo_wine_if(!expect_success)
ok(hr == result_expected, "Expected %lx, got %lx\n", result_expected, hr);
if (hr == S_OK)
{
ITest *test2 = NULL;
hr = IClassFactory_CreateInstance(classFactory, NULL, &IID_ITest, (void **)&test2);
todo_wine_if(!expect_success)
ok(hr == S_OK, "Got %lx\n", hr);
if (hr == S_OK)
{
int i = 0;
hr = ITest_Func(test2, &i);
ok(hr == S_OK, "Got %lx\n", hr);
ok(i == 42, "Expected 42, got %d\n", i);
ITest_Release(test2);
}
IClassFactory_Release(classFactory);
}
}
static void run_registry_test(run_type run)
{
char buffer[256];
ITest *test = NULL;
HRESULT hr, result_expected;
IUnknown *unk = NULL;
HKEY hkey;
DWORD ret;
int i = 0;
if (run == run_type_exe_directory) result_expected = S_OK;
else result_expected = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
sprintf(buffer, "CLSID\\%s", wine_dbgstr_guid(&CLSID_Test));
ret = RegCreateKeyA( HKEY_CLASSES_ROOT, buffer, &hkey );
if (ret == ERROR_ACCESS_DENIED && !IsUserAnAdmin())
{
win_skip("cannot run the registry tests due to user not being admin\n");
RegCloseKey(hkey);
return;
}
ok(ret == ERROR_SUCCESS, "RegCreateKeyA returned %lx\n", ret);
ret = RegSetKeyValueA(hkey, "InprocServer32", NULL, REG_SZ, "mscoree.dll", 11);
ok(ret == ERROR_SUCCESS, "RegSetKeyValueA returned %lx\n", ret);
ret = RegSetKeyValueA(hkey, "InprocServer32", "Assembly", REG_SZ, "comtest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", 74);
ok(ret == ERROR_SUCCESS, "RegSetKeyValueA returned %lx\n", ret);
ret = RegSetKeyValueA(hkey, "InprocServer32", "Class", REG_SZ, "DLL.Test", 8);
ok(ret == ERROR_SUCCESS, "RegSetKeyValueA returned %lx\n", ret);
ret = RegSetKeyValueA(hkey, "InprocServer32", "CodeBase", REG_SZ, "file:///U:/invalid/path/to/comtest.dll", 41);
ok(ret == ERROR_SUCCESS, "RegSetKeyValueA returned %lx\n", ret);
hr = CoCreateInstance(&CLSID_Test, NULL, CLSCTX_INPROC_SERVER, &IID_ITest, (void**)&test);
todo_wine_if(result_expected != S_OK)
ok(hr == result_expected, "Expected %lx, got %lx\n", result_expected, hr);
if (hr == S_OK)
{
hr = ITest_Func(test, &i);
ok(hr == S_OK, "Got %lx\n", hr);
ok(i == 42, "Expected 42, got %d\n", i);
hr = ITest_QueryInterface(test, &IID_ITest2, (void**)&unk);
ok(hr == S_OK, "ITest_QueryInterface returned %lx\n", hr);
if (hr == S_OK) IUnknown_Release(unk);
ITest_Release(test);
}
RegDeleteKeyValueA(hkey, "InprocServer32", "CodeBase");
RegDeleteKeyValueA(hkey, "InprocServer32", "Class");
RegDeleteKeyValueA(hkey, "InprocServer32", "Assembly");
RegDeleteKeyValueA(hkey, "InprocServer32", NULL);
RegDeleteKeyA(hkey, "InprocServer32");
RegCloseKey(hkey);
}
static void get_dll_path_for_run(char *path_dll, UINT path_dll_size, run_type run)
{
char path_tmp[MAX_PATH];
GetTempPathA(MAX_PATH, path_tmp);
switch (run)
{
case run_type_current_working_directory:
strcpy(path_dll, path_tmp);
PathAppendA(path_dll, "comtest.dll");
break;
case run_type_exe_directory:
GetModuleFileNameA(NULL, path_dll, path_dll_size);
PathRemoveFileSpecA(path_dll);
PathAppendA(path_dll, "comtest.dll");
break;
case run_type_system32:
GetSystemDirectoryA(path_dll, path_dll_size);
PathAppendA(path_dll, "comtest.dll");
break;
}
}
static void prepare_and_run_test(const char *dll_source, run_type run)
{
char path_tmp[MAX_PATH];
char path_tmp_manifest[MAX_PATH];
char path_dll[MAX_PATH];
char path_dll_source[MAX_PATH];
char path_manifest_dll[MAX_PATH];
char path_manifest_exe[MAX_PATH];
BOOL success;
ACTCTXA context = {0};
ULONG_PTR cookie;
HANDLE handle_context = 0;
path_manifest_exe[0] = path_manifest_dll[0] = path_dll_source[0] = 0;
GetTempPathA(MAX_PATH, path_tmp);
GetTempPathA(MAX_PATH, path_tmp_manifest);
PathAppendA(path_tmp_manifest, "manifests");
CreateDirectoryA(path_tmp_manifest, NULL);
if (run == run_type_system32)
{
if (!IsUserAnAdmin())
{
skip("Can't test dll in system32 due to user not being admin.\n");
return;
}
}
if (!write_resource_file(path_tmp, dll_source, "comtest.cs", path_dll_source))
{
ok(0, "run: %d, Failed to create file for testing\n", run);
goto cleanup;
}
get_dll_path_for_run(path_dll, sizeof(path_dll), run);
if (!compile_cs_to_dll(path_dll_source, path_dll))
goto cleanup;
if (!write_resource_file(path_tmp_manifest, "comtest_exe.manifest", "exe.manifest", path_manifest_exe))
{
ok(0, "run: %d, Failed to create file for testing\n", run);
goto cleanup;
}
if (!write_resource_file(path_tmp_manifest, "comtest_dll.manifest", "comtest.manifest", path_manifest_dll))
{
ok(0, "run: %d, Failed to create file for testing\n", run);
goto cleanup;
}
context.cbSize = sizeof(ACTCTXA);
context.lpSource = path_manifest_exe;
context.lpAssemblyDirectory = path_tmp_manifest;
context.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;
handle_context = CreateActCtxA(&context);
ok(handle_context != NULL && handle_context != INVALID_HANDLE_VALUE, "run: %d, CreateActCtxA failed: %ld\n", run, GetLastError());
if (handle_context == NULL || handle_context == INVALID_HANDLE_VALUE)
{
ok(0, "run: %d, Failed to create activation context\n", run);
goto cleanup;
}
success = ActivateActCtx(handle_context, &cookie);
ok(success, "run: %d, ActivateActCtx failed: %ld\n", run, GetLastError());
if (run == run_type_current_working_directory)
SetCurrentDirectoryA(path_tmp);
run_test(run == run_type_exe_directory);
run_registry_test(run);
cleanup:
if (handle_context != NULL && handle_context != INVALID_HANDLE_VALUE)
{
success = DeactivateActCtx(0, cookie);
ok(success, "run: %d, DeactivateActCtx failed: %ld\n", run, GetLastError());
ReleaseActCtx(handle_context);
}
if (*path_manifest_exe)
{
success = DeleteFileA(path_manifest_exe);
ok(success, "run: %d, DeleteFileA failed: %ld\n", run, GetLastError());
}
if(*path_manifest_dll)
{
success = DeleteFileA(path_manifest_dll);
ok(success, "run: %d, DeleteFileA failed: %ld\n", run, GetLastError());
}
if(*path_dll_source)
{
success = DeleteFileA(path_dll_source);
ok(success, "run: %d, DeleteFileA failed: %ld\n", run, GetLastError());
}
RemoveDirectoryA(path_tmp_manifest);
/* dll cleanup is handled by the parent, because it might still be used by the child */
}
static void cleanup_test(run_type run)
{
char path_dll[MAX_PATH];
BOOL success;
get_dll_path_for_run(path_dll, sizeof(path_dll), run);
if (!PathFileExistsA(path_dll))
return;
success = DeleteFileA(path_dll);
if (!success)
{
Sleep(500);
success = DeleteFileA(path_dll);
}
ok(success, "DeleteFileA failed: %ld\n", GetLastError());
}
static void run_child_process(const char *dll_source, run_type run)
{
char cmdline[MAX_PATH];
char exe[MAX_PATH];
char **argv;
PROCESS_INFORMATION pi;
STARTUPINFOA si = { 0 };
BOOL ret;
winetest_get_mainargs(&argv);
if (strstr(argv[0], ".exe"))
sprintf(exe, "%s", argv[0]);
else
sprintf(exe, "%s.exe", argv[0]);
sprintf(cmdline, "\"%s\" %s %s %d", argv[0], argv[1], dll_source, run);
si.cb = sizeof(si);
ret = CreateProcessA(exe, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
ok(ret, "Could not create process: %lu\n", GetLastError());
wait_child_process(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
/* Cleanup dll, because it might still have been used by the child */
cleanup_test(run);
}
START_TEST(comtest)
{
int argc;
char **argv;
CoInitialize(NULL);
hmscoree = LoadLibraryA("mscoree.dll");
if (!hmscoree)
{
skip(".NET or mono not available\n");
return;
}
argc = winetest_get_mainargs(&argv);
if (argc > 2)
{
const char *dll_source = argv[2];
run_type run = atoi(argv[3]);
prepare_and_run_test(dll_source, run);
goto cleanup;
}
run_child_process("comtest.cs", run_type_current_working_directory);
run_child_process("comtest.cs", run_type_exe_directory);
run_child_process("comtest.cs", run_type_system32);
cleanup:
FreeLibrary(hmscoree);
CoUninitialize();
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2018 Fabian Maurer
*
* 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
*/
/* Compile with
csc /target:library /out:dll.dll comtest.cs
*/
using System.Runtime.InteropServices;
namespace DLL
{
[Guid("1dbc4491-080d-45c5-a15d-1e3c4610bdd9"), ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITest
{
void Func(ref int i);
}
[ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITest2
{
void Func2(ref int i);
}
[Guid("2e106e50-e7a4-4489-8538-83643f100fdc"), ComVisible(true), ClassInterface(ClassInterfaceType.None)]
public class Test : ITest, ITest2
{
public void Func(ref int i)
{
i = 42;
}
public void Func2(ref int i)
{
i = 43;
}
}
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="comtest"
version="1.0.0.0"
type="win32"
/>
<clrClass
clsid="{2e106e50-e7a4-4489-8538-83643f100fdc}"
threadingModel="Both"
name="DLL.Test"
runtimeVersion="v4.0.0.0">
</clrClass>
<file name="comtest.dll">
</file>
</assembly>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
name="comtest"
version="1.0.0.0"
type="win32"/>
</dependentAssembly>
</dependency>
</assembly>

View File

@@ -44,7 +44,7 @@ static HRESULT WINAPI ManagedCallback2_QueryInterface(ICorDebugManagedCallback2
return S_OK;
}
ok(0, "unexpected riid (%s)\n", debugstr_guid(riid));
ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
*ppv = NULL;
return E_NOINTERFACE;
@@ -152,7 +152,7 @@ static HRESULT WINAPI ManagedCallback_QueryInterface(ICorDebugManagedCallback *i
return S_OK;
}
ok(0, "unexpected riid (%s)\n", debugstr_guid(riid));
ok(0, "unexpected riid %s\n", wine_dbgstr_guid(riid));
*ppv = NULL;
return E_NOINTERFACE;
}
@@ -410,17 +410,17 @@ static void _check_process_enum(unsigned line, ICorDebug *pCorDebug, ULONG nExpe
ICorDebugProcessEnum *pProcessEnum = NULL;
hr = ICorDebug_EnumerateProcesses(pCorDebug, NULL);
ok_(__FILE__,line) (hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
ok_(__FILE__,line) (hr == E_INVALIDARG, "expected E_INVALIDARG got %08lx\n", hr);
hr = ICorDebug_EnumerateProcesses(pCorDebug, &pProcessEnum);
ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08x\n", hr);
ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08lx\n", hr);
if(hr == S_OK)
{
ULONG cnt;
hr = ICorDebugProcessEnum_GetCount(pProcessEnum, &cnt);
ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08x\n", hr);
ok_(__FILE__,line) (cnt == nExpected, "expected %d got %d\n", nExpected, cnt);
ok_(__FILE__,line) (hr == S_OK, "expected S_OK got %08lx\n", hr);
ok_(__FILE__,line) (cnt == nExpected, "expected %ld got %ld\n", nExpected, cnt);
ICorDebugProcessEnum_Release(pProcessEnum);
}
@@ -433,36 +433,36 @@ static void test_createDebugger(void)
ICorDebug *pCorDebug;
hr = pCreateDebuggingInterfaceFromVersion(0, v2_0, &pUnk);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08x\n", hr);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08lx\n", hr);
hr = pCreateDebuggingInterfaceFromVersion(1, v2_0, &pUnk);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08x\n", hr);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08lx\n", hr);
hr = pCreateDebuggingInterfaceFromVersion(2, v2_0, &pUnk);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08x\n", hr);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08lx\n", hr);
hr = pCreateDebuggingInterfaceFromVersion(4, v2_0, &pUnk);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08x\n", hr);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08lx\n", hr);
hr = pCreateDebuggingInterfaceFromVersion(3, v2_0, NULL);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08x\n", hr);
ok(hr == E_INVALIDARG, "CreateDebuggingInterfaceFromVersion returned %08lx\n", hr);
hr = pCreateDebuggingInterfaceFromVersion(3, v2_0, &pUnk);
if(hr == S_OK)
{
hr = IUnknown_QueryInterface(pUnk, &IID_ICorDebug, (void**)&pCorDebug);
ok(hr == S_OK, "expected S_OK got %08x\n", hr);
ok(hr == S_OK, "expected S_OK got %08lx\n", hr);
if(hr == S_OK)
{
hr = ICorDebug_Initialize(pCorDebug);
ok(hr == S_OK, "expected S_OK got %08x\n", hr);
ok(hr == S_OK, "expected S_OK got %08lx\n", hr);
if(hr == S_OK)
{
hr = ICorDebug_SetManagedHandler(pCorDebug, NULL);
ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08x\n", hr);
ok(hr == E_INVALIDARG, "expected E_INVALIDARG got %08lx\n", hr);
hr = ICorDebug_SetManagedHandler(pCorDebug, &ManagedCallback);
ok(hr == S_OK, "expected S_OK got %08x\n", hr);
ok(hr == S_OK, "expected S_OK got %08lx\n", hr);
/* We should have no processes */
check_process_enum(pCorDebug, 0);

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2018 Fabian Maurer
*
* 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
*/
#pragma makedep header
#include "unknwn.idl"
[
object,
uuid(1dbc4491-080d-45c5-a15d-1e3c4610bdd9),
local
]
interface ITest : IUnknown {
HRESULT Func([in, out] int *i);
};
[
uuid(2e106e50-e7a4-4489-8538-83643f100fdc),
]
coclass Test { interface ITest; };

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2021 Rémi Bernon 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
*/
using System.Reflection;
#if NEUTRAL
[assembly: AssemblyCulture("")]
#else
[assembly: AssemblyCulture("en")]
#endif
namespace LoadPaths
{
public class Test2
{
public int Foo() { return 0; }
}
}

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="private"/>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2021 Rémi Bernon 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
*/
using System;
namespace LoadPaths
{
public static class Test
{
public static int RunExternal()
{
return new Test2().Foo();
}
}
public static class MainClass
{
static int Main(string[] args)
{
try {
return Test.RunExternal();
}
catch {
return 1;
}
}
}
}

View File

@@ -29,12 +29,22 @@
#include "metahost.h"
#include "wine/test.h"
#if !defined(__i386__) && !defined(__x86_64__)
static int has_mono = 0;
#else
static int has_mono = 1;
#endif
static HMODULE hmscoree;
static HRESULT (WINAPI *pCLRCreateInstance)(REFCLSID clsid, REFIID riid, LPVOID *ppInterface);
static ICLRMetaHost *metahost;
static const WCHAR v4_0[] = {'v','4','.','0','.','3','0','3','1','9',0};
static DWORD expect_runtime_tid;
static BOOL init_pointers(void)
{
HRESULT hr = E_FAIL;
@@ -64,6 +74,37 @@ static void cleanup(void)
FreeLibrary(hmscoree);
}
static void test_getruntime(WCHAR *version)
{
static const WCHAR dotzero[] = {'.','0',0};
WCHAR *dot;
HRESULT hr;
ICLRRuntimeInfo *info;
DWORD count;
WCHAR buf[MAX_PATH];
hr = ICLRMetaHost_GetRuntime(metahost, NULL, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == E_POINTER, "GetVersion failed, hr=%lx\n", hr);
hr = ICLRMetaHost_GetRuntime(metahost, version, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == S_OK, "GetVersion failed, hr=%lx\n", hr);
if (hr != S_OK) return;
count = MAX_PATH;
hr = ICLRRuntimeInfo_GetVersionString(info, buf, &count);
ok(hr == S_OK, "GetVersionString returned %lx\n", hr);
ok(count == lstrlenW(buf)+1, "GetVersionString returned count %lu but string of length %u\n", count, lstrlenW(buf)+1);
ok(lstrcmpW(buf, version) == 0, "got unexpected version %s\n", wine_dbgstr_w(buf));
ICLRRuntimeInfo_Release(info);
/* Versions must match exactly. */
dot = wcsrchr(version, '.');
lstrcpyW(dot, dotzero);
hr = ICLRMetaHost_GetRuntime(metahost, version, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == CLR_E_SHIM_RUNTIME, "GetVersion failed, hr=%lx\n", hr);
}
static void test_enumruntimes(void)
{
IEnumUnknown *runtime_enum;
@@ -74,72 +115,116 @@ static void test_enumruntimes(void)
WCHAR buf[MAX_PATH];
hr = ICLRMetaHost_EnumerateInstalledRuntimes(metahost, &runtime_enum);
ok(hr == S_OK, "EnumerateInstalledRuntimes returned %x\n", hr);
ok(hr == S_OK, "EnumerateInstalledRuntimes returned %lx\n", hr);
if (FAILED(hr)) return;
while ((hr = IEnumUnknown_Next(runtime_enum, 1, &unk, &count)) == S_OK)
{
hr = IUnknown_QueryInterface(unk, &IID_ICLRRuntimeInfo, (void**)&runtime_info);
ok(hr == S_OK, "QueryInterface returned %x\n", hr);
ok(hr == S_OK, "QueryInterface returned %lx\n", hr);
count = 1;
hr = ICLRRuntimeInfo_GetVersionString(runtime_info, buf, &count);
ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "GetVersionString returned %x\n", hr);
ok(count > 1, "GetVersionString returned count %u\n", count);
ok(hr == E_NOT_SUFFICIENT_BUFFER, "GetVersionString returned %lx\n", hr);
ok(count > 1, "GetVersionString returned count %lu\n", count);
count = 0xdeadbeef;
hr = ICLRRuntimeInfo_GetVersionString(runtime_info, NULL, &count);
ok(hr == S_OK, "GetVersionString returned %x\n", hr);
ok(count > 1 && count != 0xdeadbeef, "GetVersionString returned count %u\n", count);
ok(hr == S_OK, "GetVersionString returned %lx\n", hr);
ok(count > 1 && count != 0xdeadbeef, "GetVersionString returned count %lu\n", count);
count = MAX_PATH;
hr = ICLRRuntimeInfo_GetVersionString(runtime_info, buf, &count);
ok(hr == S_OK, "GetVersionString returned %x\n", hr);
ok(count > 1, "GetVersionString returned count %u\n", count);
ok(hr == S_OK, "GetVersionString returned %lx\n", hr);
ok(count > 1, "GetVersionString returned count %lu\n", count);
trace("runtime found: %s\n", wine_dbgstr_w(buf));
ICLRRuntimeInfo_Release(runtime_info);
IUnknown_Release(unk);
test_getruntime(buf);
}
ok(hr == S_FALSE, "IEnumUnknown_Next returned %x\n", hr);
ok(hr == S_FALSE, "IEnumUnknown_Next returned %lx\n", hr);
IEnumUnknown_Release(runtime_enum);
}
static void test_getruntime(void)
static void WINAPI notification_dummy_callback(ICLRRuntimeInfo *pRuntimeInfo, CallbackThreadSetFnPtr pfnCallbackThreadSet,
CallbackThreadUnsetFnPtr pfnCallbackThreadUnset)
{
ok(0, "unexpected call\n");
}
static void WINAPI notification_callback(ICLRRuntimeInfo *pRuntimeInfo, CallbackThreadSetFnPtr pfnCallbackThreadSet,
CallbackThreadUnsetFnPtr pfnCallbackThreadUnset)
{
HRESULT hr;
WCHAR buf[20];
DWORD buf_size = 20;
ok(expect_runtime_tid != 0, "unexpected call\n");
if (expect_runtime_tid != 0)
{
ok(GetCurrentThreadId() == expect_runtime_tid,
"expected call on thread %04lx, got thread %04lx\n", expect_runtime_tid, GetCurrentThreadId());
expect_runtime_tid = 0;
}
hr = ICLRRuntimeInfo_GetVersionString(pRuntimeInfo, buf, &buf_size);
ok(hr == S_OK, "GetVersion returned %lx\n", hr);
ok(lstrcmpW(buf, v4_0) == 0, "GetVersion returned %s\n", wine_dbgstr_w(buf));
hr = pfnCallbackThreadSet();
ok(hr == S_OK, "pfnCallbackThreadSet returned %lx\n", hr);
hr = pfnCallbackThreadUnset();
ok(hr == S_OK, "pfnCallbackThreadUnset returned %lx\n", hr);
}
static void test_notification(void)
{
HRESULT hr;
hr = ICLRMetaHost_RequestRuntimeLoadedNotification(metahost, NULL);
ok(hr == E_POINTER, "RequestRuntimeLoadedNotification returned %lx\n", hr);
hr = ICLRMetaHost_RequestRuntimeLoadedNotification(metahost,notification_callback);
ok(hr == S_OK, "RequestRuntimeLoadedNotification failed, hr=%lx\n", hr);
hr = ICLRMetaHost_RequestRuntimeLoadedNotification(metahost,notification_dummy_callback);
ok(hr == HOST_E_INVALIDOPERATION, "RequestRuntimeLoadedNotification returned %lx\n", hr);
}
static void test_notification_cb(void)
{
static const WCHAR twodotzero[] = {'v','2','.','0','.','5','0','7','2','7',0};
static const WCHAR twodotzerodotzero[] = {'v','2','.','0','.','0',0};
HRESULT hr;
ICLRRuntimeInfo *info;
DWORD count;
WCHAR buf[MAX_PATH];
ICLRRuntimeHost *host;
hr = ICLRMetaHost_GetRuntime(metahost, NULL, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == E_POINTER, "GetVersion failed, hr=%x\n", hr);
hr = ICLRMetaHost_GetRuntime(metahost, v4_0, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == S_OK, "GetRuntime returned %lx\n", hr);
hr = ICLRMetaHost_GetRuntime(metahost, twodotzero, &IID_ICLRRuntimeInfo, (void**)&info);
if (hr == CLR_E_SHIM_RUNTIME)
/* FIXME: Get Mono properly packaged so we can fail here. */
todo_wine ok(hr == S_OK, "GetVersion failed, hr=%x\n", hr);
else
ok(hr == S_OK, "GetVersion failed, hr=%x\n", hr);
if (hr != S_OK) return;
expect_runtime_tid = GetCurrentThreadId();
hr = ICLRRuntimeInfo_GetInterface(info, &CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, (void**)&host);
#ifdef __REACTOS__
if (hr != S_OK)
{
// skip test if mono is not installed
win_skip("mono runtime is not installed\n");
return;
}
#endif
count = MAX_PATH;
hr = ICLRRuntimeInfo_GetVersionString(info, buf, &count);
ok(hr == S_OK, "GetVersionString returned %x\n", hr);
ok(count == lstrlenW(buf)+1, "GetVersionString returned count %u but string of length %u\n", count, lstrlenW(buf)+1);
ok(lstrcmpW(buf, twodotzero) == 0, "got unexpected version %s\n", wine_dbgstr_w(buf));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetInterface returned %lx\n", hr);
todo_wine if(!has_mono) ok(expect_runtime_tid == 0, "notification_callback was not called\n");
if(has_mono)
ICLRRuntimeHost_Release(host);
ICLRRuntimeInfo_Release(info);
/* Versions must match exactly. */
hr = ICLRMetaHost_GetRuntime(metahost, twodotzerodotzero, &IID_ICLRRuntimeInfo, (void**)&info);
ok(hr == CLR_E_SHIM_RUNTIME, "GetVersion failed, hr=%x\n", hr);
}
START_TEST(metahost)
@@ -147,9 +232,9 @@ START_TEST(metahost)
if (!init_pointers())
return;
test_notification();
test_enumruntimes();
test_getruntime();
test_notification_cb();
cleanup();
}

View File

@@ -17,20 +17,39 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdio.h>
#define COBJMACROS
#include "corerror.h"
#include "mscoree.h"
#include "metahost.h"
#include "shlwapi.h"
#include "initguid.h"
#include "wine/test.h"
#if !defined(__i386__) && !defined(__x86_64__)
static int has_mono = 0;
#else
static int has_mono = 1;
#endif
DEFINE_GUID(IID__AppDomain, 0x05f696dc,0x2b29,0x3663,0xad,0x8b,0xc4,0x38,0x9c,0xf2,0xa7,0x13);
static const WCHAR v4_0[] = {'v','4','.','0','.','3','0','3','1','9',0};
static HMODULE hmscoree;
static HRESULT (WINAPI *pGetCORVersion)(LPWSTR, DWORD, DWORD*);
static HRESULT (WINAPI *pCorIsLatestSvc)(INT*, INT*);
static HRESULT (WINAPI *pGetCORSystemDirectory)(LPWSTR, DWORD, DWORD*);
static HRESULT (WINAPI *pGetRequestedRuntimeInfo)(LPCWSTR, LPCWSTR, LPCWSTR, DWORD, DWORD, LPWSTR, DWORD, DWORD*, LPWSTR, DWORD, DWORD*);
static HRESULT (WINAPI *pLoadLibraryShim)(LPCWSTR, LPCWSTR, LPVOID, HMODULE*);
static HRESULT (WINAPI *pCreateConfigStream)(LPCWSTR, IStream**);
static HRESULT (WINAPI *pCreateInterface)(REFCLSID, REFIID, VOID**);
static HRESULT (WINAPI *pCLRCreateInstance)(REFCLSID, REFIID, VOID**);
static BOOL no_legacy_runtimes;
static BOOL init_functionpointers(void)
{
@@ -43,12 +62,17 @@ static BOOL init_functionpointers(void)
}
pGetCORVersion = (void *)GetProcAddress(hmscoree, "GetCORVersion");
pCorIsLatestSvc = (void *)GetProcAddress(hmscoree, "CorIsLatestSvc");
pGetCORSystemDirectory = (void *)GetProcAddress(hmscoree, "GetCORSystemDirectory");
pGetRequestedRuntimeInfo = (void *)GetProcAddress(hmscoree, "GetRequestedRuntimeInfo");
pLoadLibraryShim = (void *)GetProcAddress(hmscoree, "LoadLibraryShim");
pCreateConfigStream = (void *)GetProcAddress(hmscoree, "CreateConfigStream");
pCreateInterface = (void *)GetProcAddress(hmscoree, "CreateInterface");
pCLRCreateInstance = (void *)GetProcAddress(hmscoree, "CLRCreateInstance");
if (!pGetCORVersion || !pGetCORSystemDirectory || !pGetRequestedRuntimeInfo || !pLoadLibraryShim)
if (!pGetCORVersion || !pGetCORSystemDirectory || !pGetRequestedRuntimeInfo || !pLoadLibraryShim ||
!pCreateInterface || !pCLRCreateInstance || !pCorIsLatestSvc
)
{
win_skip("functions not available\n");
FreeLibrary(hmscoree);
@@ -58,6 +82,93 @@ static BOOL init_functionpointers(void)
return TRUE;
}
static int check_runtime(void)
{
ICLRMetaHost *metahost;
ICLRRuntimeInfo *runtimeinfo;
ICorRuntimeHost *runtimehost;
HRESULT hr;
if (!pCLRCreateInstance)
{
win_skip("Function CLRCreateInstance not found.\n");
return 1;
}
hr = pCLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, (void **)&metahost);
if (hr == E_NOTIMPL)
{
win_skip("CLRCreateInstance not implemented\n");
return 1;
}
ok(SUCCEEDED(hr), "CLRCreateInstance failed, hr=%#.8lx\n", hr);
if (FAILED(hr))
return 1;
hr = ICLRMetaHost_GetRuntime(metahost, v4_0, &IID_ICLRRuntimeInfo, (void **)&runtimeinfo);
ok(SUCCEEDED(hr), "ICLRMetaHost::GetRuntime failed, hr=%#.8lx\n", hr);
if (FAILED(hr))
return 1;
hr = ICLRRuntimeInfo_GetInterface(runtimeinfo, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost,
(void **)&runtimehost);
todo_wine_if(!has_mono) ok(SUCCEEDED(hr), "ICLRRuntimeInfo::GetInterface failed, hr=%#.8lx\n", hr);
if (FAILED(hr))
return 1;
hr = ICorRuntimeHost_Start(runtimehost);
ok(SUCCEEDED(hr), "ICorRuntimeHost::Start failed, hr=%#.8lx\n", hr);
if (FAILED(hr))
return 1;
ICorRuntimeHost_Release(runtimehost);
ICLRRuntimeInfo_Release(runtimeinfo);
ICLRMetaHost_ExitProcess(metahost, 0);
ok(0, "ICLRMetaHost_ExitProcess is not supposed to return\n");
return 1;
}
static BOOL runtime_is_usable(void)
{
static const char cmdline_format[] = "\"%s\" mscoree check_runtime";
char** argv;
char cmdline[MAX_PATH + sizeof(cmdline_format)];
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi;
BOOL ret;
DWORD exitcode;
winetest_get_mainargs(&argv);
sprintf(cmdline, cmdline_format, argv[0]);
si.cb = sizeof(si);
ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
ok(ret, "Could not create process: %lu\n", GetLastError());
if (!ret)
return FALSE;
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
ret = GetExitCodeProcess(pi.hProcess, &exitcode);
ok(ret, "GetExitCodeProcess failed: %lu\n", GetLastError());
CloseHandle(pi.hProcess);
if (!ret || exitcode != 0)
{
todo_wine_if(!has_mono) win_skip(".NET 4.0 runtime is not usable\n");
return FALSE;
}
return TRUE;
}
static void test_versioninfo(void)
{
const WCHAR v9_0[] = {'v','9','.','0','.','3','0','3','1','9',0};
@@ -75,43 +186,42 @@ static void test_versioninfo(void)
if (0) /* crashes on <= w2k3 */
{
hr = pGetCORVersion(NULL, MAX_PATH, &size);
ok(hr == E_POINTER,"GetCORVersion returned %08x\n", hr);
ok(hr == E_POINTER,"GetCORVersion returned %08lx\n", hr);
}
hr = pGetCORVersion(version, 1, &size);
if (hr == CLR_E_SHIM_RUNTIME)
{
/* FIXME: Get Mono packaged properly so we can fail here. */
todo_wine ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),"GetCORVersion returned %08x\n", hr);
skip("No .NET runtimes are installed\n");
no_legacy_runtimes = TRUE;
win_skip("No legacy .NET runtimes are installed\n");
return;
}
ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER),"GetCORVersion returned %08x\n", hr);
ok(hr == E_NOT_SUFFICIENT_BUFFER, "GetCORVersion returned %08lx\n", hr);
hr = pGetCORVersion(version, MAX_PATH, &size);
ok(hr == S_OK,"GetCORVersion returned %08x\n", hr);
ok(hr == S_OK,"GetCORVersion returned %08lx\n", hr);
trace("latest installed .net runtime: %s\n", wine_dbgstr_w(version));
hr = pGetCORSystemDirectory(path, MAX_PATH , &size);
ok(hr == S_OK, "GetCORSystemDirectory returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == S_OK, "GetCORSystemDirectory returned %08lx\n", hr);
/* size includes terminating null-character */
ok(size == (lstrlenW(path) + 1),"size is %d instead of %d\n", size, (lstrlenW(path) + 1));
todo_wine_if(!has_mono) ok(size == (lstrlenW(path) + 1),"size is %ld instead of %d\n", size, (lstrlenW(path) + 1));
path_len = size;
hr = pGetCORSystemDirectory(path, path_len-1 , &size);
ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "GetCORSystemDirectory returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == E_NOT_SUFFICIENT_BUFFER, "GetCORSystemDirectory returned %08lx\n", hr);
if (0) /* crashes on <= w2k3 */
{
hr = pGetCORSystemDirectory(NULL, MAX_PATH , &size);
ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "GetCORSystemDirectory returned %08x\n", hr);
ok(hr == E_NOT_SUFFICIENT_BUFFER, "GetCORSystemDirectory returned %08lx\n", hr);
}
hr = pGetCORSystemDirectory(path, MAX_PATH , NULL);
ok(hr == E_POINTER,"GetCORSystemDirectory returned %08x\n", hr);
ok(hr == E_POINTER,"GetCORSystemDirectory returned %08lx\n", hr);
trace("latest installed .net installed in directory: %s\n", wine_dbgstr_w(path));
@@ -120,77 +230,79 @@ static void test_versioninfo(void)
if(hr == CLR_E_SHIM_RUNTIME) return; /* skipping rest of tests on win2k as .net 2.0 not installed */
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
trace(" installed in directory %s is .net version %s\n", wine_dbgstr_w(path), wine_dbgstr_w(version));
hr = pGetRequestedRuntimeInfo( NULL, v1_1, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, &size);
ok(hr == S_OK || hr == CLR_E_SHIM_RUNTIME /*v1_1 not installed*/, "GetRequestedRuntimeInfo returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == S_OK || hr == CLR_E_SHIM_RUNTIME /*v1_1 not installed*/, "GetRequestedRuntimeInfo returned %08lx\n", hr);
if(hr == S_OK)
trace(" installed in directory %s is .net version %s\n", wine_dbgstr_w(path), wine_dbgstr_w(version));
/* version number NULL not allowed without RUNTIME_INFO_UPGRADE_VERSION flag */
hr = pGetRequestedRuntimeInfo( NULL, NULL, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, &size);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08lx\n", hr);
/* with RUNTIME_INFO_UPGRADE_VERSION flag and version number NULL, latest installed version is returned */
hr = pGetRequestedRuntimeInfo( NULL, NULL, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, path, MAX_PATH, &path_len, version, MAX_PATH, &size);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
hr = pGetRequestedRuntimeInfo( NULL, v2_0, NULL, 0, 0, path, 1, &path_len, version, MAX_PATH, &size);
ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "GetRequestedRuntimeInfo returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == E_NOT_SUFFICIENT_BUFFER, "GetRequestedRuntimeInfo returned %08lx\n", hr);
/* if one of the buffers is NULL, the other one is still happily filled */
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v2_0, NULL, 0, 0, NULL, MAX_PATH, &path_len, version, MAX_PATH, &size);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(!winetest_strcmpW(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
ok(!wcscmp(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
/* With NULL-pointer for bufferlength, the buffer itself still gets filled with correct string */
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v2_0, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(!winetest_strcmpW(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
ok(!wcscmp(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v2_0cap, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(!winetest_strcmpW(version, v2_0cap), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0cap));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
ok(!wcscmp(version, v2_0cap), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0cap));
/* Invalid Version and RUNTIME_INFO_UPGRADE_VERSION flag*/
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v1_1, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == S_OK || hr == CLR_E_SHIM_RUNTIME , "GetRequestedRuntimeInfo returned %08x\n", hr);
todo_wine_if(!has_mono) ok(hr == S_OK || hr == CLR_E_SHIM_RUNTIME , "GetRequestedRuntimeInfo returned %08lx\n", hr);
if(hr == S_OK)
{
/* .NET 1.1 may not be installed. */
ok(!winetest_strcmpW(version, v1_1) || !winetest_strcmpW(version, v2_0),
ok(!wcscmp(version, v1_1) || !wcscmp(version, v2_0),
"version is %s , expected %s or %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v1_1), wine_dbgstr_w(v2_0));
}
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v9_0, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08lx\n", hr);
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v1_1_0, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08lx\n", hr);
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v1_1_0, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(!winetest_strcmpW(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
ok(!wcscmp(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v2_0_0, NULL, 0, 0, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(hr == CLR_E_SHIM_RUNTIME, "GetRequestedRuntimeInfo returned %08lx\n", hr);
memset(version, 0, sizeof(version));
hr = pGetRequestedRuntimeInfo( NULL, v2_0_0, NULL, 0, RUNTIME_INFO_UPGRADE_VERSION, path, MAX_PATH, &path_len, version, MAX_PATH, NULL);
ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08x\n", hr);
ok(!winetest_strcmpW(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
todo_wine_if(!has_mono) ok(hr == S_OK, "GetRequestedRuntimeInfo returned %08lx\n", hr);
ok(!wcscmp(version, v2_0), "version is %s , expected %s\n", wine_dbgstr_w(version), wine_dbgstr_w(v2_0));
hr = pCorIsLatestSvc(NULL, NULL);
ok(hr == E_POINTER, "CorIsLatestSvc returned %08lx\n", hr);
}
static void test_loadlibraryshim(void)
{
const WCHAR v4_0[] = {'v','4','.','0','.','3','0','3','1','9',0};
const WCHAR v2_0[] = {'v','2','.','0','.','5','0','7','2','7',0};
const WCHAR v1_1[] = {'v','1','.','1','.','4','3','2','2',0};
const WCHAR vbogus[] = {'v','b','o','g','u','s',0};
@@ -204,36 +316,42 @@ static void test_loadlibraryshim(void)
HMODULE hdll;
CHAR dllpath[MAX_PATH];
if (no_legacy_runtimes)
{
win_skip("No legacy .NET runtimes are installed\n");
return;
}
hr = pLoadLibraryShim(fusion, v1_1, NULL, &hdll);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
{
latest = v1_1;
GetModuleFileNameA(hdll, dllpath, MAX_PATH);
todo_wine ok(StrStrIA(dllpath, "v1.1.4322") != 0, "incorrect fusion.dll path %s\n", dllpath);
todo_wine_if(!has_mono) ok(StrStrIA(dllpath, "v1.1.4322") != 0, "incorrect fusion.dll path %s\n", dllpath);
ok(StrStrIA(dllpath, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath);
FreeLibrary(hdll);
}
hr = pLoadLibraryShim(fusion, v2_0, NULL, &hdll);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
{
latest = v2_0;
GetModuleFileNameA(hdll, dllpath, MAX_PATH);
todo_wine ok(StrStrIA(dllpath, "v2.0.50727") != 0, "incorrect fusion.dll path %s\n", dllpath);
todo_wine_if(!has_mono) ok(StrStrIA(dllpath, "v2.0.50727") != 0, "incorrect fusion.dll path %s\n", dllpath);
ok(StrStrIA(dllpath, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath);
FreeLibrary(hdll);
}
hr = pLoadLibraryShim(fusion, v4_0, NULL, &hdll);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == S_OK || hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
{
/* LoadLibraryShim with a NULL version prefers 2.0 and earlier */
@@ -242,52 +360,52 @@ static void test_loadlibraryshim(void)
GetModuleFileNameA(hdll, dllpath, MAX_PATH);
todo_wine ok(StrStrIA(dllpath, "v4.0.30319") != 0, "incorrect fusion.dll path %s\n", dllpath);
todo_wine_if(!has_mono) ok(StrStrIA(dllpath, "v4.0.30319") != 0, "incorrect fusion.dll path %s\n", dllpath);
ok(StrStrIA(dllpath, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath);
FreeLibrary(hdll);
}
hr = pLoadLibraryShim(fusion, vbogus, NULL, &hdll);
todo_wine ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
FreeLibrary(hdll);
WideCharToMultiByte(CP_ACP, 0, latest, -1, latestA, MAX_PATH, NULL, NULL);
hr = pLoadLibraryShim(fusion, NULL, NULL, &hdll);
ok(hr == S_OK, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == S_OK, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
{
GetModuleFileNameA(hdll, dllpath, MAX_PATH);
if (latest)
todo_wine ok(StrStrIA(dllpath, latestA) != 0, "incorrect fusion.dll path %s\n", dllpath);
todo_wine_if(!has_mono) ok(StrStrIA(dllpath, latestA) != 0, "incorrect fusion.dll path %s\n", dllpath);
ok(StrStrIA(dllpath, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath);
FreeLibrary(hdll);
}
hr = pLoadLibraryShim(fusiondll, NULL, NULL, &hdll);
ok(hr == S_OK, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == S_OK, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
{
GetModuleFileNameA(hdll, dllpath, MAX_PATH);
if (latest)
todo_wine ok(StrStrIA(dllpath, latestA) != 0, "incorrect fusion.dll path %s\n", dllpath);
todo_wine_if(!has_mono) ok(StrStrIA(dllpath, latestA) != 0, "incorrect fusion.dll path %s\n", dllpath);
ok(StrStrIA(dllpath, "fusion.dll") != 0, "incorrect fusion.dll path %s\n", dllpath);
FreeLibrary(hdll);
}
hr = pLoadLibraryShim(nosuchdll, latest, NULL, &hdll);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
FreeLibrary(hdll);
hr = pLoadLibraryShim(gdidll, latest, NULL, &hdll);
todo_wine ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%x\n", hr);
ok(hr == E_HANDLE, "LoadLibraryShim failed, hr=%lx\n", hr);
if (SUCCEEDED(hr))
FreeLibrary(hdll);
}
@@ -305,7 +423,7 @@ static void create_xml_file(LPCWSTR filename)
DWORD dwNumberOfBytesWritten;
HANDLE hfile = CreateFileW(filename, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ok(hfile != INVALID_HANDLE_VALUE, "File creation failed\n");
ok(hfile != INVALID_HANDLE_VALUE, "Could not open %s for writing: %lu\n", wine_dbgstr_w(filename), GetLastError());
WriteFile(hfile, xmldata, sizeof(xmldata) - 1, &dwNumberOfBytesWritten, NULL);
CloseHandle(hfile);
}
@@ -329,24 +447,24 @@ static void test_createconfigstream(void)
GetFullPathNameW(file, MAX_PATH, path, NULL);
hr = pCreateConfigStream(NULL, &stream);
todo_wine ok(hr == E_FAIL ||
broken(hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND)) || /* some WinXP, Win2K3 and Win7 */
broken(hr == S_OK && !stream), /* some Win2K3 */
"CreateConfigStream returned %x\n", hr);
ok(hr == E_FAIL ||
broken(hr == HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND)) || /* some WinXP, Win2K3 and Win7 */
broken(hr == S_OK && !stream), /* some Win2K3 */
"CreateConfigStream returned %lx\n", hr);
hr = pCreateConfigStream(path, NULL);
todo_wine ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %x\n", hr);
ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %lx\n", hr);
hr = pCreateConfigStream(NULL, NULL);
todo_wine ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %x\n", hr);
ok(hr == COR_E_NULLREFERENCE, "CreateConfigStream returned %lx\n", hr);
hr = pCreateConfigStream(nonexistent, &stream);
todo_wine ok(hr == COR_E_FILENOTFOUND, "CreateConfigStream returned %x\n", hr);
ok(hr == COR_E_FILENOTFOUND, "CreateConfigStream returned %lx\n", hr);
ok(stream == NULL, "Expected stream to be NULL\n");
hr = pCreateConfigStream(path, &stream);
todo_wine ok(hr == S_OK, "CreateConfigStream failed, hr=%x\n", hr);
todo_wine ok(stream != NULL, "Expected non-NULL stream\n");
ok(hr == S_OK, "CreateConfigStream failed, hr=%lx\n", hr);
ok(stream != NULL, "Expected non-NULL stream\n");
if (stream)
{
@@ -354,46 +472,456 @@ static void test_createconfigstream(void)
LARGE_INTEGER pos;
ULARGE_INTEGER size;
IStream *stream2 = NULL;
ULONG ref;
hr = IStream_Read(stream, buffer, strlen(xmldata), &count);
ok(hr == S_OK, "IStream_Read failed, hr=%x\n", hr);
ok(count == strlen(xmldata), "wrong count: %u\n", count);
ok(hr == S_OK, "IStream_Read failed, hr=%lx\n", hr);
ok(count == strlen(xmldata), "wrong count: %lu\n", count);
ok(!strcmp(buffer, xmldata), "Strings do not match\n");
hr = IStream_Read(stream, buffer, sizeof(buffer), &count);
ok(hr == S_OK, "IStream_Read failed, hr=%lx\n", hr);
ok(!count, "wrong count: %lu\n", count);
hr = IStream_Write(stream, xmldata, strlen(xmldata), &count);
ok(hr == E_FAIL, "IStream_Write returned hr=%x\n", hr);
ok(hr == E_FAIL, "IStream_Write returned hr=%lx\n", hr);
pos.QuadPart = strlen(xmldata);
hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
ok(hr == E_NOTIMPL, "IStream_Seek returned hr=%x\n", hr);
ok(hr == E_NOTIMPL, "IStream_Seek returned hr=%lx\n", hr);
size.QuadPart = strlen(xmldata);
hr = IStream_SetSize(stream, size);
ok(hr == E_NOTIMPL, "IStream_SetSize returned hr=%x\n", hr);
ok(hr == E_NOTIMPL, "IStream_SetSize returned hr=%lx\n", hr);
hr = IStream_Clone(stream, &stream2);
ok(hr == E_NOTIMPL, "IStream_Clone returned hr=%x\n", hr);
ok(hr == E_NOTIMPL, "IStream_Clone returned hr=%lx\n", hr);
hr = IStream_Commit(stream, STGC_DEFAULT);
ok(hr == E_NOTIMPL, "IStream_Commit returned hr=%x\n", hr);
ok(hr == E_NOTIMPL, "IStream_Commit returned hr=%lx\n", hr);
hr = IStream_Revert(stream);
ok(hr == E_NOTIMPL, "IStream_Revert returned hr=%x\n", hr);
ok(hr == E_NOTIMPL, "IStream_Revert returned hr=%lx\n", hr);
hr = IStream_Release(stream);
ok(hr == S_OK, "IStream_Release returned hr=%x\n", hr);
ref = IStream_Release(stream);
ok(!ref, "IStream_Release returned %lu\n", ref);
}
DeleteFileW(file);
}
static void test_createinstance(void)
{
HRESULT hr;
ICLRMetaHost *host;
if (no_legacy_runtimes)
{
/* If we don't have 1.x or 2.0 runtimes, we should at least have .NET 4. */
ok(pCreateInterface != NULL, "no legacy runtimes or .NET 4 interfaces available\n");
}
if(!pCreateInterface)
{
win_skip("Function CreateInterface not found.\n");
return;
}
hr = pCreateInterface(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, (void**)&host);
if(SUCCEEDED(hr))
{
ICLRMetaHost_Release(host);
}
else
{
win_skip(".NET 4 not installed.\n");
}
}
static BOOL write_resource(const WCHAR *resource, const WCHAR *filename)
{
HANDLE file;
HRSRC rsrc;
void *data;
DWORD size;
BOOL ret;
rsrc = FindResourceW(GetModuleHandleW(NULL), resource, MAKEINTRESOURCEW(RT_RCDATA));
if (!rsrc) return FALSE;
data = LockResource(LoadResource(GetModuleHandleA(NULL), rsrc));
if (!data) return FALSE;
size = SizeofResource(GetModuleHandleA(NULL), rsrc);
if (!size) return FALSE;
file = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (file == INVALID_HANDLE_VALUE) return FALSE;
ret = WriteFile(file, data, size, &size, NULL);
CloseHandle(file);
return ret;
}
static BOOL compile_cs(const WCHAR *source, const WCHAR *target, const WCHAR *type, const WCHAR *args)
{
static const WCHAR *csc = L"C:\\windows\\Microsoft.NET\\Framework\\v2.0.50727\\csc.exe";
WCHAR cmdline[2 * MAX_PATH + 74];
PROCESS_INFORMATION pi;
STARTUPINFOW si = { 0 };
BOOL ret;
if (!PathFileExistsW(csc))
{
skip("Can't find csc.exe\n");
return FALSE;
}
swprintf(cmdline, ARRAY_SIZE(cmdline), L"%s /t:%s %s /out:\"%s\" \"%s\"", csc, type, args, target, source);
si.cb = sizeof(si);
ret = CreateProcessW(csc, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi);
ok(ret, "Could not create process: %lu\n", GetLastError());
wait_child_process(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
ret = PathFileExistsW(target);
ok(ret, "Compilation failed\n");
return ret;
}
static BOOL create_new_dir(WCHAR newdir[MAX_PATH], const WCHAR* prefix)
{
WCHAR path[MAX_PATH];
BOOL try_tmpdir = TRUE;
static unsigned i = 0;
GetCurrentDirectoryW(ARRAY_SIZE(path), path);
while (1)
{
swprintf(newdir, MAX_PATH, L"%s\\%s%04d", path, prefix, i);
if (CreateDirectoryW(newdir, NULL))
return TRUE;
switch (GetLastError())
{
case ERROR_ACCESS_DENIED:
if (!try_tmpdir)
return FALSE;
try_tmpdir = FALSE;
GetTempPathW(ARRAY_SIZE(path), path);
path[wcslen(path) - 1] = 0; /* redundant trailing backslash */
break;
case ERROR_ALREADY_EXISTS:
i++;
break;
default:
return FALSE;
}
}
}
static void test_loadpaths_execute(const WCHAR *exe_name, const WCHAR *dll_name, const WCHAR *cfg_name,
const WCHAR *dll_dest, BOOL expect_failure, BOOL todo)
{
WCHAR tmpdir[MAX_PATH], tmpexe[MAX_PATH], tmpcfg[MAX_PATH], tmpdll[MAX_PATH];
PROCESS_INFORMATION pi;
STARTUPINFOW si = { 0 };
WCHAR *ptr, *end;
DWORD exit_code = 0xdeadbeef, err;
BOOL ret;
ret = create_new_dir(tmpdir, L"loadpaths");
ok(ret, "failed to create a new dir %lu\n", GetLastError());
end = tmpdir + wcslen(tmpdir);
wcscpy(tmpexe, tmpdir);
PathAppendW(tmpexe, exe_name);
ret = CopyFileW(exe_name, tmpexe, FALSE);
ok(ret, "CopyFileW(%s) failed: %lu\n", debugstr_w(tmpexe), GetLastError());
if (cfg_name)
{
wcscpy(tmpcfg, tmpdir);
PathAppendW(tmpcfg, cfg_name);
ret = CopyFileW(cfg_name, tmpcfg, FALSE);
ok(ret, "CopyFileW(%s) failed: %lu\n", debugstr_w(tmpcfg), GetLastError());
}
ptr = tmpdir + wcslen(tmpdir);
PathAppendW(tmpdir, dll_dest);
while (*ptr && (ptr = wcschr(ptr + 1, '\\')))
{
*ptr = '\0';
ret = CreateDirectoryW(tmpdir, NULL);
ok(ret, "CreateDirectoryW(%s) failed: %lu\n", debugstr_w(tmpdir), GetLastError());
*ptr = '\\';
}
wcscpy(tmpdll, tmpdir);
if ((ptr = wcsrchr(tmpdir, '\\'))) *ptr = '\0';
ret = CopyFileW(dll_name, tmpdll, FALSE);
ok(ret, "CopyFileW(%s) failed: %lu\n", debugstr_w(tmpdll), GetLastError());
si.cb = sizeof(si);
ret = CreateProcessW(tmpexe, tmpexe, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
ok(ret, "CreateProcessW(%s) failed: %lu\n", debugstr_w(tmpexe), GetLastError());
if (expect_failure) ret = WaitForSingleObject(pi.hProcess, 2000);
else
{
ret = WaitForSingleObject(pi.hProcess, 5000);
ok(ret == WAIT_OBJECT_0, "%s: WaitForSingleObject returned %d: %lu\n", debugstr_w(dll_dest), ret, GetLastError());
}
GetExitCodeProcess(pi.hProcess, &exit_code);
if (ret == WAIT_TIMEOUT) TerminateProcess(pi.hProcess, 0xdeadbeef);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
if (expect_failure) todo_wine_if(todo) ok(exit_code != 0, "%s: Succeeded to execute process\n", debugstr_w(dll_dest));
else ok(exit_code == 0, "%s: Failed to execute process\n", debugstr_w(dll_dest));
/* sometimes the failing process never returns, in which case cleaning up won't work */
if (ret == WAIT_TIMEOUT && expect_failure) return;
if (cfg_name)
{
ret = DeleteFileW(tmpcfg);
ok(ret, "DeleteFileW(%s) failed: %lu\n", debugstr_w(tmpcfg), GetLastError());
}
ret = DeleteFileW(tmpdll);
ok(ret, "DeleteFileW(%s) failed: %lu\n", debugstr_w(tmpdll), GetLastError());
ret = DeleteFileW(tmpexe);
ok(ret, "DeleteFileW(%s) failed: %lu\n", debugstr_w(tmpexe), GetLastError());
ptr = end;
while (ptr >= end && (ptr = wcsrchr(tmpdir, '\\')))
{
ret = RemoveDirectoryW(tmpdir);
err = GetLastError();
ok(ret, "RemoveDirectoryW(%s) failed: %lu\n", debugstr_w(tmpdir), err);
if (!ret && err == ERROR_DIR_NOT_EMPTY)
{
WIN32_FIND_DATAW fd;
HANDLE hfind;
wcscat(tmpdir, L"\\*");
hfind = FindFirstFileW(tmpdir, &fd);
while (hfind != INVALID_HANDLE_VALUE && (!wcscmp(fd.cFileName, L".") || !wcscmp(fd.cFileName, L"..")))
{
if (!FindNextFileW(hfind, &fd))
{
FindClose(hfind);
hfind = INVALID_HANDLE_VALUE;
}
}
if (hfind != INVALID_HANDLE_VALUE)
{
trace("file %s still present in tmpdir\n", debugstr_w(fd.cFileName));
FindClose(hfind);
}
}
*ptr = '\0';
}
}
static void test_loadpaths(BOOL neutral)
{
static const WCHAR *loadpaths[] = {L"", L"en", L"libloadpaths", L"en\\libloadpaths"};
static const WCHAR *dll_source = L"loadpaths.dll.cs";
static const WCHAR *dll_name = L"libloadpaths.dll";
static const WCHAR *exe_source = L"loadpaths.exe.cs";
static const WCHAR *exe_name = L"loadpaths.exe";
static const WCHAR *cfg_name = L"loadpaths.exe.config";
WCHAR tmp[MAX_PATH];
BOOL ret;
int i;
DeleteFileW(dll_source);
ret = write_resource(dll_source, dll_source);
ok(ret, "Could not write resource: %lu\n", GetLastError());
DeleteFileW(dll_name);
ret = compile_cs(dll_source, dll_name, L"library", neutral ? L"-define:NEUTRAL" : L"");
if (!ret) return;
ret = DeleteFileW(dll_source);
ok(ret, "DeleteFileW failed: %lu\n", GetLastError());
DeleteFileW(exe_source);
ret = write_resource(exe_source, exe_source);
ok(ret, "Could not write resource: %lu\n", GetLastError());
DeleteFileW(exe_name);
ret = compile_cs(exe_source, exe_name, L"winexe", L"/reference:libloadpaths.dll");
if (!ret) return;
ret = DeleteFileW(exe_source);
ok(ret, "DeleteFileW failed: %lu\n", GetLastError());
DeleteFileW(cfg_name);
ret = write_resource(cfg_name, cfg_name);
ok(ret, "Could not write resource: %lu\n", GetLastError());
for (i = 0; i < ARRAY_SIZE(loadpaths); ++i)
{
const WCHAR *path = loadpaths[i];
BOOL expect_failure = neutral ? wcsstr(path, L"en") != NULL
: wcsstr(path, L"en") == NULL;
wcscpy(tmp, path);
PathAppendW(tmp, dll_name);
test_loadpaths_execute(exe_name, dll_name, NULL, tmp, expect_failure, !neutral && !*path);
wcscpy(tmp, L"private");
if (*path) PathAppendW(tmp, path);
PathAppendW(tmp, dll_name);
test_loadpaths_execute(exe_name, dll_name, NULL, tmp, TRUE, FALSE);
test_loadpaths_execute(exe_name, dll_name, cfg_name, tmp, expect_failure, FALSE);
/* exe name for dll should work too */
if (*path)
{
wcscpy(tmp, path);
PathAppendW(tmp, dll_name);
wcscpy(tmp + wcslen(tmp) - 4, L".exe");
test_loadpaths_execute(exe_name, dll_name, NULL, tmp, expect_failure, FALSE);
}
wcscpy(tmp, L"private");
if (*path) PathAppendW(tmp, path);
PathAppendW(tmp, dll_name);
wcscpy(tmp + wcslen(tmp) - 4, L".exe");
test_loadpaths_execute(exe_name, dll_name, NULL, tmp, TRUE, FALSE);
test_loadpaths_execute(exe_name, dll_name, cfg_name, tmp, expect_failure, FALSE);
}
ret = DeleteFileW(cfg_name);
ok(ret, "DeleteFileW failed: %lu\n", GetLastError());
ret = DeleteFileW(exe_name);
ok(ret, "DeleteFileW failed: %lu\n", GetLastError());
ret = DeleteFileW(dll_name);
ok(ret, "DeleteFileW failed: %lu\n", GetLastError());
}
static void test_createdomain(void)
{
static const WCHAR test_name[] = {'t','e','s','t',0};
static const WCHAR test2_name[] = {'t','e','s','t','2',0};
ICLRMetaHost *metahost;
ICLRRuntimeInfo *runtimeinfo;
ICorRuntimeHost *runtimehost;
IUnknown *domain, *defaultdomain_unk, *defaultdomain, *newdomain_unk, *newdomain, *domainsetup,
*newdomain2_unk, *newdomain2;
HRESULT hr;
if (!pCLRCreateInstance)
{
win_skip("Function CLRCreateInstance not found.\n");
return;
}
hr = pCLRCreateInstance(&CLSID_CLRMetaHost, &IID_ICLRMetaHost, (void **)&metahost);
ok(SUCCEEDED(hr), "CLRCreateInstance failed, hr=%#.8lx\n", hr);
hr = ICLRMetaHost_GetRuntime(metahost, v4_0, &IID_ICLRRuntimeInfo, (void **)&runtimeinfo);
ok(SUCCEEDED(hr), "ICLRMetaHost::GetRuntime failed, hr=%#.8lx\n", hr);
hr = ICLRRuntimeInfo_GetInterface(runtimeinfo, &CLSID_CorRuntimeHost, &IID_ICorRuntimeHost,
(void **)&runtimehost);
ok(SUCCEEDED(hr), "ICLRRuntimeInfo::GetInterface failed, hr=%#.8lx\n", hr);
hr = ICorRuntimeHost_Start(runtimehost);
ok(SUCCEEDED(hr), "ICorRuntimeHost::Start failed, hr=%#.8lx\n", hr);
hr = ICorRuntimeHost_GetDefaultDomain(runtimehost, &domain);
ok(SUCCEEDED(hr), "ICorRuntimeHost::GetDefaultDomain failed, hr=%#.8lx\n", hr);
hr = IUnknown_QueryInterface(domain, &IID_IUnknown, (void **)&defaultdomain_unk);
ok(SUCCEEDED(hr), "COM object doesn't support IUnknown?!\n");
hr = IUnknown_QueryInterface(domain, &IID__AppDomain, (void **)&defaultdomain);
ok(SUCCEEDED(hr), "AppDomain object doesn't support _AppDomain interface\n");
IUnknown_Release(domain);
hr = ICorRuntimeHost_CreateDomain(runtimehost, test_name, NULL, &domain);
ok(SUCCEEDED(hr), "ICorRuntimeHost::CreateDomain failed, hr=%#.8lx\n", hr);
hr = IUnknown_QueryInterface(domain, &IID_IUnknown, (void **)&newdomain_unk);
ok(SUCCEEDED(hr), "COM object doesn't support IUnknown?!\n");
hr = IUnknown_QueryInterface(domain, &IID__AppDomain, (void **)&newdomain);
ok(SUCCEEDED(hr), "AppDomain object doesn't support _AppDomain interface\n");
IUnknown_Release(domain);
ok(defaultdomain_unk != newdomain_unk, "New and default domain objects are the same\n");
hr = ICorRuntimeHost_CreateDomainSetup(runtimehost, &domainsetup);
ok(SUCCEEDED(hr), "ICorRuntimeHost::CreateDomainSetup failed, hr=%#.8lx\n", hr);
hr = ICorRuntimeHost_CreateDomainEx(runtimehost, test2_name, domainsetup, NULL, &domain);
ok(SUCCEEDED(hr), "ICorRuntimeHost::CreateDomainEx failed, hr=%#.8lx\n", hr);
hr = IUnknown_QueryInterface(domain, &IID_IUnknown, (void **)&newdomain2_unk);
ok(SUCCEEDED(hr), "COM object doesn't support IUnknown?!\n");
hr = IUnknown_QueryInterface(domain, &IID__AppDomain, (void **)&newdomain2);
ok(SUCCEEDED(hr), "AppDomain object doesn't support _AppDomain interface\n");
IUnknown_Release(domain);
ok(defaultdomain_unk != newdomain2_unk, "New and default domain objects are the same\n");
ok(newdomain_unk != newdomain2_unk, "Both new domain objects are the same\n");
IUnknown_Release(newdomain2);
IUnknown_Release(newdomain2_unk);
IUnknown_Release(domainsetup);
IUnknown_Release(newdomain);
IUnknown_Release(newdomain_unk);
IUnknown_Release(defaultdomain);
IUnknown_Release(defaultdomain_unk);
ICorRuntimeHost_Release(runtimehost);
ICLRRuntimeInfo_Release(runtimeinfo);
ICLRMetaHost_Release(metahost);
}
START_TEST(mscoree)
{
int argc;
char** argv;
if (!init_functionpointers())
return;
argc = winetest_get_mainargs(&argv);
if (argc >= 3 && !strcmp(argv[2], "check_runtime"))
{
int result = check_runtime();
FreeLibrary(hmscoree);
exit(result);
}
test_versioninfo();
test_loadlibraryshim();
test_createconfigstream();
test_createinstance();
if (runtime_is_usable())
{
test_createdomain();
}
test_loadpaths(FALSE);
test_loadpaths(TRUE);
FreeLibrary(hmscoree);
}

View File

@@ -0,0 +1,39 @@
/*
* Resources for mscoree test suite.
*
* Copyright 2018 Fabian Maurer
*
* 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 "windef.h"
/* @makedep: comtest.cs */
comtest.cs RCDATA comtest.cs
/* @makedep: comtest_exe.manifest */
comtest_exe.manifest RCDATA comtest_exe.manifest
/* @makedep: comtest_dll.manifest */
comtest_dll.manifest RCDATA comtest_dll.manifest
/* @makedep: loadpaths.exe.cs */
loadpaths.exe.cs RCDATA loadpaths.exe.cs
/* @makedep: loadpaths.dll.cs */
loadpaths.dll.cs RCDATA loadpaths.dll.cs
/* @makedep: loadpaths.exe.config */
loadpaths.exe.config RCDATA loadpaths.exe.config

View File

@@ -4,12 +4,14 @@
#define STANDALONE
#include "wine/test.h"
//extern void func_comtest(void);
extern void func_debugging(void);
extern void func_metahost(void);
extern void func_mscoree(void);
const struct test winetest_testlist[] =
{
//{ "comtest", func_comtest }, // Disabled because mono and mono sdk is not installed
{ "debugging", func_debugging },
{ "metahost", func_metahost },
{ "mscoree", func_mscoree },