mscoree: Implement DllGetClassObject.
This commit is contained in:
parent
15bce22683
commit
3f1c63c5bd
|
@ -38,6 +38,7 @@
|
||||||
#include "mscoree_private.h"
|
#include "mscoree_private.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
||||||
|
|
||||||
|
@ -939,3 +940,146 @@ HRESULT RuntimeHost_Destroy(RuntimeHost *This)
|
||||||
HeapFree( GetProcessHeap(), 0, This );
|
HeapFree( GetProcessHeap(), 0, This );
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHARS_IN_GUID 39
|
||||||
|
#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
|
||||||
|
|
||||||
|
HRESULT create_monodata(REFIID riid, LPVOID *ppObj )
|
||||||
|
{
|
||||||
|
static const WCHAR wszCodebase[] = {'C','o','d','e','B','a','s','e',0};
|
||||||
|
static const WCHAR wszClass[] = {'C','l','a','s','s',0};
|
||||||
|
static const WCHAR wszFileSlash[] = {'f','i','l','e',':','/','/','/',0};
|
||||||
|
static const WCHAR wszCLSIDSlash[] = {'C','L','S','I','D','\\',0};
|
||||||
|
static const WCHAR wszInprocServer32[] = {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
|
||||||
|
WCHAR path[CHARS_IN_GUID + ARRAYSIZE(wszCLSIDSlash) + ARRAYSIZE(wszInprocServer32) - 1];
|
||||||
|
MonoDomain *domain;
|
||||||
|
MonoAssembly *assembly;
|
||||||
|
ICLRRuntimeInfo *info;
|
||||||
|
RuntimeHost *host;
|
||||||
|
HRESULT hr;
|
||||||
|
HKEY key;
|
||||||
|
LONG res;
|
||||||
|
int offset = 0;
|
||||||
|
WCHAR codebase[MAX_PATH + 8];
|
||||||
|
WCHAR classname[350];
|
||||||
|
WCHAR filename[MAX_PATH];
|
||||||
|
|
||||||
|
DWORD dwBufLen = 350;
|
||||||
|
|
||||||
|
lstrcpyW(path, wszCLSIDSlash);
|
||||||
|
StringFromGUID2(riid, path + lstrlenW(wszCLSIDSlash), CHARS_IN_GUID);
|
||||||
|
lstrcatW(path, wszInprocServer32);
|
||||||
|
|
||||||
|
TRACE("Registry key: %s\n", debugstr_w(path));
|
||||||
|
|
||||||
|
res = RegOpenKeyExW(HKEY_CLASSES_ROOT, path, 0, KEY_READ, &key);
|
||||||
|
if (res == ERROR_FILE_NOT_FOUND)
|
||||||
|
return CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
res = RegGetValueW( key, NULL, wszClass, RRF_RT_REG_SZ, NULL, classname, &dwBufLen);
|
||||||
|
if(res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WARN("Class value cannot be found.\n");
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("classname (%s)\n", debugstr_w(classname));
|
||||||
|
|
||||||
|
dwBufLen = MAX_PATH + 8;
|
||||||
|
res = RegGetValueW( key, NULL, wszCodebase, RRF_RT_REG_SZ, NULL, codebase, &dwBufLen);
|
||||||
|
if(res != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
WARN("CodeBase value cannot be found.\n");
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip file:/// */
|
||||||
|
if(strncmpW(codebase, wszFileSlash, strlenW(wszFileSlash)) == 0)
|
||||||
|
offset = strlenW(wszFileSlash);
|
||||||
|
|
||||||
|
strcpyW(filename, codebase + offset);
|
||||||
|
|
||||||
|
TRACE("codebase (%s)\n", debugstr_w(filename));
|
||||||
|
|
||||||
|
*ppObj = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
hr = get_runtime_info(filename, NULL, NULL, 0, 0, FALSE, &info);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = ICLRRuntimeInfo_GetRuntimeHost(info, &host);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = RuntimeHost_GetDefaultDomain(host, &domain);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
MonoImage *image;
|
||||||
|
MonoClass *klass;
|
||||||
|
MonoObject *result;
|
||||||
|
IUnknown *unk = NULL;
|
||||||
|
char *filenameA, *ns;
|
||||||
|
char *classA;
|
||||||
|
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
filenameA = WtoA(filename);
|
||||||
|
assembly = host->mono->mono_domain_assembly_open(domain, filenameA);
|
||||||
|
HeapFree(GetProcessHeap(), 0, filenameA);
|
||||||
|
if (!assembly)
|
||||||
|
{
|
||||||
|
ERR("Cannot open assembly %s\n", filenameA);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
image = host->mono->mono_assembly_get_image(assembly);
|
||||||
|
if (!image)
|
||||||
|
{
|
||||||
|
ERR("Couldn't get assembly image\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
classA = WtoA(classname);
|
||||||
|
ns = strrchr(classA, '.');
|
||||||
|
*ns = '\0';
|
||||||
|
|
||||||
|
klass = host->mono->mono_class_from_name(image, classA, ns+1);
|
||||||
|
HeapFree(GetProcessHeap(), 0, classA);
|
||||||
|
if (!klass)
|
||||||
|
{
|
||||||
|
ERR("Couldn't get class from image\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the default constructor for the .NET class.
|
||||||
|
*/
|
||||||
|
result = host->mono->mono_object_new(domain, klass);
|
||||||
|
host->mono->mono_runtime_object_init(result);
|
||||||
|
|
||||||
|
hr = RuntimeHost_GetIUnknownForObject(host, result, &unk);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IUnknown_QueryInterface(unk, &IID_IUnknown, ppObj);
|
||||||
|
|
||||||
|
IUnknown_Release(unk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hr = CLASS_E_CLASSNOTAVAILABLE;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if(info)
|
||||||
|
ICLRRuntimeInfo_Release(info);
|
||||||
|
|
||||||
|
RegCloseKey(key);
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
|
||||||
|
|
||||||
static HINSTANCE MSCOREE_hInstance;
|
static HINSTANCE MSCOREE_hInstance;
|
||||||
|
|
||||||
|
typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
|
||||||
|
|
||||||
char *WtoA(LPCWSTR wstr)
|
char *WtoA(LPCWSTR wstr)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
@ -89,6 +91,105 @@ static BOOL get_install_root(LPWSTR install_dir)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct mscorecf
|
||||||
|
{
|
||||||
|
IClassFactory IClassFactory_iface;
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
fnCreateInstance pfnCreateInstance;
|
||||||
|
|
||||||
|
CLSID clsid;
|
||||||
|
} mscorecf;
|
||||||
|
|
||||||
|
static inline mscorecf *impl_from_IClassFactory( IClassFactory *iface )
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, mscorecf, IClassFactory_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppobj )
|
||||||
|
{
|
||||||
|
TRACE("%s %p\n", debugstr_guid(riid), ppobj);
|
||||||
|
|
||||||
|
if (IsEqualGUID(riid, &IID_IUnknown) ||
|
||||||
|
IsEqualGUID(riid, &IID_IClassFactory))
|
||||||
|
{
|
||||||
|
IClassFactory_AddRef( iface );
|
||||||
|
*ppobj = iface;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR("interface %s not implemented\n", debugstr_guid(riid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (ref == 0)
|
||||||
|
{
|
||||||
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_CreateInstance(IClassFactory *iface,LPUNKNOWN pOuter,
|
||||||
|
REFIID riid, LPVOID *ppobj )
|
||||||
|
{
|
||||||
|
mscorecf *This = impl_from_IClassFactory( iface );
|
||||||
|
HRESULT hr;
|
||||||
|
IUnknown *punk;
|
||||||
|
|
||||||
|
TRACE("%p %s %p\n", pOuter, debugstr_guid(riid), ppobj );
|
||||||
|
|
||||||
|
*ppobj = NULL;
|
||||||
|
|
||||||
|
if (pOuter)
|
||||||
|
return CLASS_E_NOAGGREGATION;
|
||||||
|
|
||||||
|
hr = This->pfnCreateInstance( &This->clsid, (LPVOID*) &punk );
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IUnknown_QueryInterface( punk, riid, ppobj );
|
||||||
|
|
||||||
|
IUnknown_Release( punk );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WARN("Cannot create an instance object. 0x%08x\n", hr);
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI mscorecf_LockServer(IClassFactory *iface, BOOL dolock)
|
||||||
|
{
|
||||||
|
FIXME("(%p)->(%d),stub!\n",iface,dolock);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct IClassFactoryVtbl mscorecf_vtbl =
|
||||||
|
{
|
||||||
|
mscorecf_QueryInterface,
|
||||||
|
mscorecf_AddRef,
|
||||||
|
mscorecf_Release,
|
||||||
|
mscorecf_CreateInstance,
|
||||||
|
mscorecf_LockServer
|
||||||
|
};
|
||||||
|
|
||||||
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
|
HRESULT WINAPI CorBindToRuntimeHost(LPCWSTR pwszVersion, LPCWSTR pwszBuildFlavor,
|
||||||
LPCWSTR pwszHostConfigFile, VOID *pReserved,
|
LPCWSTR pwszHostConfigFile, VOID *pReserved,
|
||||||
DWORD startupFlags, REFCLSID rclsid,
|
DWORD startupFlags, REFCLSID rclsid,
|
||||||
|
@ -504,11 +605,25 @@ HRESULT WINAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, LPVOID *ppInterfac
|
||||||
|
|
||||||
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
|
||||||
{
|
{
|
||||||
FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
mscorecf *This;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
|
||||||
|
|
||||||
if(!ppv)
|
if(!ppv)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
This = HeapAlloc(GetProcessHeap(), 0, sizeof(mscorecf));
|
||||||
|
|
||||||
|
This->IClassFactory_iface.lpVtbl = &mscorecf_vtbl;
|
||||||
|
This->pfnCreateInstance = &create_monodata;
|
||||||
|
This->ref = 1;
|
||||||
|
This->clsid = *rclsid;
|
||||||
|
|
||||||
|
hr = IClassFactory_QueryInterface( &This->IClassFactory_iface, riid, ppv );
|
||||||
|
IClassFactory_Release(&This->IClassFactory_iface);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT WINAPI DllRegisterServer(void)
|
HRESULT WINAPI DllRegisterServer(void)
|
||||||
|
|
|
@ -186,4 +186,6 @@ HRESULT WINAPI CLRMetaHost_GetRuntime(ICLRMetaHost* iface, LPCWSTR pwzVersion, R
|
||||||
|
|
||||||
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
|
extern HRESULT CorDebug_Create(ICLRRuntimeHost *runtimehost, IUnknown** ppUnk) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
extern HRESULT create_monodata(REFIID riid, LPVOID *ppObj) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#endif /* __MSCOREE_PRIVATE__ */
|
#endif /* __MSCOREE_PRIVATE__ */
|
||||||
|
|
Loading…
Reference in New Issue