[PATCH v2 08/10] vbscript: Implement ScriptTypeInfo_GetIDsOfNames.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Nov 13 09:24:52 CST 2019


Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---

It's not really feasible to use the script dispatch's GetIDsOfNames since
the TypeInfo can have a limited amount of variables/functions compared to
the script dispatch (and also inherits from IDispatch, which has to look
into as well).

The logic of this has been taken from the generic TypeLib
implementation. Tests at the end of the series are added to verify its
behavior, anyway.

 dlls/vbscript/vbdisp.c        | 44 +++++++++++++++++++++++++++++++++--
 dlls/vbscript/vbscript.h      |  1 +
 dlls/vbscript/vbscript_main.c | 25 ++++++++++++++++++++
 3 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/dlls/vbscript/vbdisp.c b/dlls/vbscript/vbdisp.c
index d14ce5b..6f94dca 100644
--- a/dlls/vbscript/vbdisp.c
+++ b/dlls/vbscript/vbdisp.c
@@ -715,10 +715,50 @@ static HRESULT WINAPI ScriptTypeInfo_GetIDsOfNames(ITypeInfo *iface, LPOLESTR *r
         MEMBERID *pMemId)
 {
     ScriptTypeInfo *This = ScriptTypeInfo_from_ITypeInfo(iface);
+    const WCHAR *name;
+    HRESULT hr = S_OK;
+    int i, j, arg;
 
-    FIXME("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId);
+    TRACE("(%p)->(%p %u %p)\n", This, rgszNames, cNames, pMemId);
 
-    return E_NOTIMPL;
+    if (!rgszNames || !cNames || !pMemId) return E_INVALIDARG;
+
+    for (i = 0; i < cNames; i++) pMemId[i] = MEMBERID_NIL;
+    name = rgszNames[0];
+
+    for (i = 0; i < This->num_funcs; i++)
+    {
+        function_t *func = This->disp->global_funcs[This->func_ids[i]];
+
+        if (wcsicmp(name, func->name)) continue;
+        pMemId[0] = This->func_ids[i] + 1 + DISPID_FUNCTION_MASK;
+
+        for (j = 1; j < cNames; j++)
+        {
+            name = rgszNames[j];
+            for (arg = func->arg_cnt; --arg >= 0;)
+                if (!wcsicmp(name, func->args[arg].name))
+                    break;
+            if (arg >= 0)
+                pMemId[j] = arg;
+            else
+                hr = DISP_E_UNKNOWNNAME;
+        }
+        return hr;
+    }
+
+    for (i = 0; i < This->num_vars; i++)
+    {
+        if (wcsicmp(name, This->disp->global_vars[i]->name)) continue;
+        pMemId[0] = i + 1;
+        return S_OK;
+    }
+
+    /* Look into the inherited IDispatch */
+    hr = get_IDispatch_typeinfo(&iface);
+    if (FAILED(hr)) return hr;
+
+    return ITypeInfo_GetIDsOfNames(iface, rgszNames, cNames, pMemId);
 }
 
 static HRESULT WINAPI ScriptTypeInfo_Invoke(ITypeInfo *iface, PVOID pvInstance, MEMBERID memid, WORD wFlags,
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index ceca069..5b4156b 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -377,6 +377,7 @@ void detach_global_objects(script_ctx_t*) DECLSPEC_HIDDEN;
 HRESULT get_builtin_id(BuiltinDisp*,const WCHAR*,DISPID*) DECLSPEC_HIDDEN;
 
 void release_regexp_typelib(void) DECLSPEC_HIDDEN;
+HRESULT get_IDispatch_typeinfo(ITypeInfo**) DECLSPEC_HIDDEN;
 
 static inline BOOL is_int32(double d)
 {
diff --git a/dlls/vbscript/vbscript_main.c b/dlls/vbscript/vbscript_main.c
index 6e6f386..8c05d53 100644
--- a/dlls/vbscript/vbscript_main.c
+++ b/dlls/vbscript/vbscript_main.c
@@ -34,6 +34,7 @@ WINE_DECLARE_DEBUG_CHANNEL(heap);
 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
 
 static HINSTANCE vbscript_hinstance;
+static ITypeInfo *IDispatch_typeinfo;
 
 BSTR get_vbscript_string(int id)
 {
@@ -180,6 +181,29 @@ heap_pool_t *heap_pool_mark(heap_pool_t *heap)
     return heap;
 }
 
+HRESULT get_IDispatch_typeinfo(ITypeInfo **out)
+{
+    ITypeInfo *typeinfo;
+    ITypeLib *typelib;
+    HRESULT hr;
+
+    if (!IDispatch_typeinfo)
+    {
+        hr = LoadRegTypeLib(&IID_StdOle, STDOLE_MAJORVERNUM, STDOLE_MINORVERNUM, STDOLE_LCID, &typelib);
+        if (FAILED(hr)) return hr;
+
+        hr = ITypeLib_GetTypeInfoOfGuid(typelib, &IID_IDispatch, &typeinfo);
+        ITypeLib_Release(typelib);
+        if (FAILED(hr)) return hr;
+
+        if (InterlockedCompareExchangePointer((void**)(&IDispatch_typeinfo), typeinfo, NULL))
+            ITypeInfo_Release(typeinfo);
+    }
+
+    *out = IDispatch_typeinfo;
+    return S_OK;
+}
+
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
 {
     *ppv = NULL;
@@ -256,6 +280,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
         break;
     case DLL_PROCESS_DETACH:
         if (lpv) break;
+        if (IDispatch_typeinfo) ITypeInfo_Release(IDispatch_typeinfo);
         release_regexp_typelib();
     }
 
-- 
2.21.0




More information about the wine-devel mailing list