Module: wine Branch: master Commit: 3f1c63c5bdd8889b1e8fae34b20e0d04b06059c0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f1c63c5bdd8889b1e8fae34b2...
Author: Alistair Leslie-Hughes leslie_alistair@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__ */