>From 4f4360741b28b948e2a9285e0c0f58921a76c438 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Thu, 6 Oct 2011 22:04:03 +1100
Subject: [PATCH] Implement IMMCVersionInfo
To: wine-patches <wine-patches@winehq.org>

---
 dlls/mmcndmgr/mmcndmgr.c |  173 ++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 167 insertions(+), 6 deletions(-)

diff --git a/dlls/mmcndmgr/mmcndmgr.c b/dlls/mmcndmgr/mmcndmgr.c
index e8d98df..ca6cbf5 100644
--- a/dlls/mmcndmgr/mmcndmgr.c
+++ b/dlls/mmcndmgr/mmcndmgr.c
@@ -30,19 +30,180 @@
 #include "wine/debug.h"
 #include "wine/library.h"
 
-#include <mmc.h>
+#include "initguid.h"
+#include "mmc.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mmc);
 
 HINSTANCE MMC_hInstance = NULL;
 
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
+static HRESULT WINAPI mmcversion_QueryInterface(IMMCVersionInfo *iface, REFIID riid, void **ppv)
 {
-    FIXME("(%s, %s, %p): stub\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
-    if(!ppv)
-        return E_INVALIDARG;
+    TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
 
-    return E_NOTIMPL;
+    if ( IsEqualGUID( riid, &IID_IMMCVersionInfo ) ||
+         IsEqualGUID( riid, &IID_IUnknown ) )
+    {
+        *ppv = iface;
+    }
+    else
+    {
+        TRACE("Unsupported interface %s\n", debugstr_guid(riid));
+        *ppv = NULL;
+        return E_NOINTERFACE;
+    }
+
+    IMMCVersionInfo_AddRef((IUnknown*)*ppv);
+    return S_OK;
+}
+
+static ULONG WINAPI mmcversion_AddRef(IMMCVersionInfo *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI mmcversion_Release(IMMCVersionInfo *iface)
+{
+   return 1;
+}
+
+static HRESULT WINAPI mmcversion_GetMMCVersion(IMMCVersionInfo *iface, LONG *pVersionMajor, LONG *pVersionMinor)
+{
+    TRACE("(%p, %p, %p): stub\n", iface, pVersionMajor, pVersionMinor);
+
+    if(pVersionMajor)
+        *pVersionMajor = 3;
+
+    if(pVersionMinor)
+        *pVersionMinor = 0;
+
+    return S_OK;
+}
+
+static const struct IMMCVersionInfoVtbl mmcversionVtbl =
+{
+    mmcversion_QueryInterface,
+    mmcversion_AddRef,
+    mmcversion_Release,
+    mmcversion_GetMMCVersion
+};
+
+static const IMMCVersionInfo myMMCVersionInfo = { &mmcversionVtbl };
+
+/***********************************************************
+ *    ClassFactory implementation
+ */
+typedef HRESULT (*CreateInstanceFunc)(IUnknown*,REFIID,void**);
+typedef struct {
+    IClassFactory IClassFactory_iface;
+    LONG ref;
+    CreateInstanceFunc fnCreateInstance;
+} ClassFactory;
+
+static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
+{
+    return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
+}
+
+static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFGUID riid, void **ppvObject)
+{
+    if(IsEqualGUID(&IID_IClassFactory, riid) || IsEqualGUID(&IID_IUnknown, riid)) {
+        IClassFactory_AddRef(iface);
+        *ppvObject = iface;
+        return S_OK;
+    }
+
+    WARN("not supported iid %s\n", debugstr_guid(riid));
+    *ppvObject = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
+{
+    ClassFactory *This = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("(%p) ref = %u\n", This, ref);
+    return ref;
+}
+
+static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
+{
+    ClassFactory *This = impl_from_IClassFactory(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) ref = %u\n", This, ref);
+
+    if(!ref) {
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *pUnkOuter,
+        REFIID riid, void **ppvObject)
+{
+    ClassFactory *This = impl_from_IClassFactory(iface);
+    return This->fnCreateInstance(pUnkOuter, riid, ppvObject);
+}
+
+static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
+{
+    ClassFactory *This = impl_from_IClassFactory(iface);
+    TRACE("(%p)->(%x)\n", This, dolock);
+
+    return !ref ? S_OK : S_FALSE;
+}
+
+static const IClassFactoryVtbl HTMLClassFactoryVtbl = {
+    ClassFactory_QueryInterface,
+    ClassFactory_AddRef,
+    ClassFactory_Release,
+    ClassFactory_CreateInstance,
+    ClassFactory_LockServer
+};
+
+static HRESULT ClassFactory_Create(REFIID riid, void **ppv, CreateInstanceFunc fnCreateInstance)
+{
+    ClassFactory *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassFactory));
+    HRESULT hres;
+
+    ret->IClassFactory_iface.lpVtbl = &HTMLClassFactoryVtbl;
+    ret->ref = 0;
+    ret->fnCreateInstance = fnCreateInstance;
+
+    hres = IClassFactory_QueryInterface(&ret->IClassFactory_iface, riid, ppv);
+    if(FAILED(hres)) {
+        HeapFree(GetProcessHeap(), 0, ret);
+        *ppv = NULL;
+    }
+    return hres;
+}
+
+HRESULT MMCVersionInfo_create(IUnknown *pUnkOuter, REFIID riid, void** ppObj)
+{
+    *ppObj = (void**)&myMMCVersionInfo;
+
+    TRACE("returning iface %p\n", *ppObj);
+    return S_OK;
+}
+
+HRESULT WINAPI DllGetClassObject( REFCLSID riid, REFIID iid, LPVOID *ppv )
+{
+    IClassFactory *cf = NULL;
+
+    TRACE("%s %s %p\n", debugstr_guid(riid), debugstr_guid(iid), ppv );
+
+    if( IsEqualCLSID( riid, &CLSID_MMCVersionInfo ))
+    {
+        TRACE("(CLSID_MMCVersionInfo %s %p)\n", debugstr_guid(riid), ppv);
+        return ClassFactory_Create(iid, ppv, MMCVersionInfo_create);
+    }
+
+    if ( !cf )
+        return CLASS_E_CLASSNOTAVAILABLE;
+
+    return IClassFactory_QueryInterface( cf, iid, ppv );
 }
 
 HRESULT WINAPI DllRegisterServer(void)
-- 
1.7.5.4

