mirror of
https://github.com/reactos/reactos.git
synced 2026-06-02 01:11:03 +08:00
[MSCOREE] Sync to wine-10.0
This commit is contained in:
committed by
Timo Kreuzer
parent
1f97ad1f93
commit
37ef9507c7
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
74
dll/win32/mscoree/mscoree_classes.idl
Normal file
74
dll/win32/mscoree/mscoree_classes.idl
Normal 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
|
||||
{
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
6
dll/win32/mscoree/reactos.c
Normal file
6
dll/win32/mscoree/reactos.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <windows.h>
|
||||
|
||||
HRESULT WINAPI DllCanUnloadNow(void)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
417
modules/rostests/winetests/mscoree/comtest.c
Normal file
417
modules/rostests/winetests/mscoree/comtest.c
Normal 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();
|
||||
}
|
||||
51
modules/rostests/winetests/mscoree/comtest.cs
Normal file
51
modules/rostests/winetests/mscoree/comtest.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
modules/rostests/winetests/mscoree/comtest_dll.manifest
Normal file
16
modules/rostests/winetests/mscoree/comtest_dll.manifest
Normal 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>
|
||||
11
modules/rostests/winetests/mscoree/comtest_exe.manifest
Normal file
11
modules/rostests/winetests/mscoree/comtest_exe.manifest
Normal 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>
|
||||
@@ -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);
|
||||
|
||||
35
modules/rostests/winetests/mscoree/interfaces.idl
Normal file
35
modules/rostests/winetests/mscoree/interfaces.idl
Normal 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; };
|
||||
33
modules/rostests/winetests/mscoree/loadpaths.dll.cs
Normal file
33
modules/rostests/winetests/mscoree/loadpaths.dll.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
8
modules/rostests/winetests/mscoree/loadpaths.exe.config
Normal file
8
modules/rostests/winetests/mscoree/loadpaths.exe.config
Normal 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>
|
||||
43
modules/rostests/winetests/mscoree/loadpaths.exe.cs
Normal file
43
modules/rostests/winetests/mscoree/loadpaths.exe.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
39
modules/rostests/winetests/mscoree/resource.rc
Normal file
39
modules/rostests/winetests/mscoree/resource.rc
Normal 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
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user