Alistair Leslie-Hughes : mscoree: Implement DllGetClassObject.
Alexandre Julliard
julliard at winehq.org
Mon Jan 23 13:01:13 CST 2012
Module: wine
Branch: master
Commit: 3f1c63c5bdd8889b1e8fae34b20e0d04b06059c0
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f1c63c5bdd8889b1e8fae34b20e0d04b06059c0
Author: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
Date: Fri Jan 6 14:33:19 2012 +1100
mscoree: Implement DllGetClassObject.
---
dlls/mscoree/corruntimehost.c | 144 ++++++++++++++++++++++++++++++++++++++++
dlls/mscoree/mscoree_main.c | 119 ++++++++++++++++++++++++++++++++-
dlls/mscoree/mscoree_private.h | 2 +
3 files changed, 263 insertions(+), 2 deletions(-)
diff --git a/dlls/mscoree/corruntimehost.c b/dlls/mscoree/corruntimehost.c
index 00966ee..ff789d4 100644
--- a/dlls/mscoree/corruntimehost.c
+++ b/dlls/mscoree/corruntimehost.c
@@ -38,6 +38,7 @@
#include "mscoree_private.h"
#include "wine/debug.h"
+#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
@@ -939,3 +940,146 @@ HRESULT RuntimeHost_Destroy(RuntimeHost *This)
HeapFree( GetProcessHeap(), 0, This );
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;
+}
diff --git a/dlls/mscoree/mscoree_main.c b/dlls/mscoree/mscoree_main.c
index 8b72ec8..b6ae490 100644
--- a/dlls/mscoree/mscoree_main.c
+++ b/dlls/mscoree/mscoree_main.c
@@ -52,6 +52,8 @@ WINE_DEFAULT_DEBUG_CHANNEL( mscoree );
static HINSTANCE MSCOREE_hInstance;
+typedef HRESULT (*fnCreateInstance)(REFIID riid, LPVOID *ppObj);
+
char *WtoA(LPCWSTR wstr)
{
int length;
@@ -89,6 +91,105 @@ static BOOL get_install_root(LPWSTR install_dir)
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,
LPCWSTR pwszHostConfigFile, VOID *pReserved,
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)
{
- 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)
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)
diff --git a/dlls/mscoree/mscoree_private.h b/dlls/mscoree/mscoree_private.h
index a45a405..d033275 100644
--- a/dlls/mscoree/mscoree_private.h
+++ b/dlls/mscoree/mscoree_private.h
@@ -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 create_monodata(REFIID riid, LPVOID *ppObj) DECLSPEC_HIDDEN;
+
#endif /* __MSCOREE_PRIVATE__ */
More information about the wine-cvs
mailing list