>From 8f77d586ee7a7eeab2b343fe6a7847847c6481b9 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Thu, 29 Dec 2011 12:16:22 +0300
Subject: [PATCH 2/2] Added IDispatch support for IWshShell3

---
 dlls/wshom.ocx/Makefile.in     |    1 +
 dlls/wshom.ocx/shell.c         |   37 +++++++++++++++++---
 dlls/wshom.ocx/tests/wshom.c   |    6 +++-
 dlls/wshom.ocx/wshom_main.c    |   70 +++++++++++++++++++++++++++++++++++++++-
 dlls/wshom.ocx/wshom_private.h |    9 +++++
 5 files changed, 115 insertions(+), 8 deletions(-)

diff --git a/dlls/wshom.ocx/Makefile.in b/dlls/wshom.ocx/Makefile.in
index 879cc70..385fe73 100644
--- a/dlls/wshom.ocx/Makefile.in
+++ b/dlls/wshom.ocx/Makefile.in
@@ -1,4 +1,5 @@
 MODULE    = wshom.ocx
+IMPORTS   = uuid oleaut32
 
 C_SRCS = \
 	shell.c \
diff --git a/dlls/wshom.ocx/shell.c b/dlls/wshom.ocx/shell.c
index 9392ff5..68f14b8 100644
--- a/dlls/wshom.ocx/shell.c
+++ b/dlls/wshom.ocx/shell.c
@@ -23,6 +23,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(wshom);
 
+static IWshShell3 WshShell3;
+
 static HRESULT WINAPI WshShell3_QueryInterface(IWshShell3 *iface, REFIID riid, void **ppv)
 {
     if(IsEqualGUID(riid, &IID_IUnknown)) {
@@ -66,23 +68,46 @@ static HRESULT WINAPI WshShell3_GetTypeInfoCount(IWshShell3 *iface, UINT *pctinf
 
 static HRESULT WINAPI WshShell3_GetTypeInfo(IWshShell3 *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
 {
-    FIXME("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
-    return E_NOTIMPL;
+    TRACE("(%u %u %p)\n", iTInfo, lcid, ppTInfo);
+    return get_typeinfo(IWshShell3_tid, ppTInfo);
 }
 
 static HRESULT WINAPI WshShell3_GetIDsOfNames(IWshShell3 *iface, REFIID riid, LPOLESTR *rgszNames,
         UINT cNames, LCID lcid, DISPID *rgDispId)
 {
-    FIXME("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
-    return E_NOTIMPL;
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%s %p %u %u %p)\n", debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);
+
+    hr = get_typeinfo(IWshShell3_tid, &typeinfo);
+    if(SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI WshShell3_Invoke(IWshShell3 *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
 {
-    FIXME("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
+    ITypeInfo *typeinfo;
+    HRESULT hr;
+
+    TRACE("(%d %s %d %d %p %p %p %p)\n", dispIdMember, debugstr_guid(riid),
           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
-    return E_NOTIMPL;
+
+    hr = get_typeinfo(IWshShell3_tid, &typeinfo);
+    if(SUCCEEDED(hr))
+    {
+        hr = ITypeInfo_Invoke(typeinfo, &WshShell3, dispIdMember, wFlags,
+                pDispParams, pVarResult, pExcepInfo, puArgErr);
+        ITypeInfo_Release(typeinfo);
+    }
+
+    return hr;
 }
 
 static HRESULT WINAPI WshShell3_get_SpecialFolders(IWshShell3 *iface, IWshCollection **out_Folders)
diff --git a/dlls/wshom.ocx/tests/wshom.c b/dlls/wshom.ocx/tests/wshom.c
index f9768b9..36081aa 100644
--- a/dlls/wshom.ocx/tests/wshom.c
+++ b/dlls/wshom.ocx/tests/wshom.c
@@ -31,6 +31,7 @@ DEFINE_GUID(IID_IWshShell3, 0x41904400, 0xbe18, 0x11d3, 0xa2,0x8b, 0x00,0x10,0x4
 
 static void test_wshshell(void)
 {
+    IDispatchEx *dispex;
     IDispatch *disp;
     IUnknown *shell;
     HRESULT hres;
@@ -43,9 +44,12 @@ static void test_wshshell(void)
     }
 
     hres = IDispatch_QueryInterface(disp, &IID_IWshShell3, (void**)&shell);
-    IDispatch_Release(disp);
     ok(hres == S_OK, "Could not get IWshShell3 iface: %08x\n", hres);
 
+    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
+    ok(hres == E_NOINTERFACE, "got %08x\n", hres);
+
+    IDispatch_Release(disp);
     IUnknown_Release(shell);
 }
 
diff --git a/dlls/wshom.ocx/wshom_main.c b/dlls/wshom.ocx/wshom_main.c
index b05eb86..c750592 100644
--- a/dlls/wshom.ocx/wshom_main.c
+++ b/dlls/wshom.ocx/wshom_main.c
@@ -16,8 +16,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "initguid.h"
 #include "wshom_private.h"
+
+#include "initguid.h"
 #include "wshom.h"
 #include "rpcproxy.h"
 
@@ -27,6 +28,70 @@ WINE_DEFAULT_DEBUG_CHANNEL(wshom);
 
 static HINSTANCE wshom_instance;
 
+static ITypeLib *typelib;
+static ITypeInfo *typeinfos[LAST_tid];
+
+static REFIID tid_ids[] = {
+    &IID_NULL,
+    &IID_IWshShell3
+};
+
+static HRESULT load_typelib(void)
+{
+    HRESULT hres;
+    ITypeLib *tl;
+
+    hres = LoadRegTypeLib(&LIBID_IWshRuntimeLibrary, 1, 0, LOCALE_SYSTEM_DEFAULT, &tl);
+    if(FAILED(hres)) {
+        ERR("LoadRegTypeLib failed: %08x\n", hres);
+        return hres;
+    }
+
+    if(InterlockedCompareExchangePointer((void**)&typelib, tl, NULL))
+        ITypeLib_Release(tl);
+    return hres;
+}
+
+HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo)
+{
+    HRESULT hres;
+
+    if (!typelib)
+        hres = load_typelib();
+    if (!typelib)
+        return hres;
+
+    if(!typeinfos[tid]) {
+        ITypeInfo *ti;
+
+        hres = ITypeLib_GetTypeInfoOfGuid(typelib, tid_ids[tid], &ti);
+        if(FAILED(hres)) {
+            ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_ids[tid]), hres);
+            return hres;
+        }
+
+        if(InterlockedCompareExchangePointer((void**)(typeinfos+tid), ti, NULL))
+            ITypeInfo_Release(ti);
+    }
+
+    *typeinfo = typeinfos[tid];
+    return S_OK;
+}
+
+void release_typelib(void)
+{
+    unsigned i;
+
+    if(!typelib)
+        return;
+
+    for(i=0; i < sizeof(typeinfos)/sizeof(*typeinfos); i++)
+        if(typeinfos[i])
+            ITypeInfo_Release(typeinfos[i]);
+
+    ITypeLib_Release(typelib);
+}
+
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
 {
     *ppv = NULL;
@@ -91,6 +156,9 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
         wshom_instance = hInstDLL;
         DisableThreadLibraryCalls(wshom_instance);
         break;
+    case DLL_PROCESS_DETACH:
+        release_typelib();
+        break;
     }
 
     return TRUE;
diff --git a/dlls/wshom.ocx/wshom_private.h b/dlls/wshom.ocx/wshom_private.h
index 50b84b3..42be641 100644
--- a/dlls/wshom.ocx/wshom_private.h
+++ b/dlls/wshom.ocx/wshom_private.h
@@ -24,4 +24,13 @@
 #include "winbase.h"
 #include "ole2.h"
 
+/* typelibs */
+typedef enum tid_t {
+    NULL_tid,
+    IWshShell3_tid,
+    LAST_tid
+} tid_t;
+
+HRESULT get_typeinfo(tid_t tid, ITypeInfo **typeinfo);
+
 HRESULT WINAPI WshShellFactory_CreateInstance(IClassFactory*,IUnknown*,REFIID,void**) DECLSPEC_HIDDEN;
-- 
1.5.6.5

