[PATCH] msscript: Implement AddObject()

Nikolay Sivov nsivov at codeweavers.com
Thu Jul 21 12:34:11 CDT 2016


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/msscript.ocx/msscript.c       |  97 ++++++++++++++++++++++--
 dlls/msscript.ocx/tests/msscript.c | 150 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 236 insertions(+), 11 deletions(-)

diff --git a/dlls/msscript.ocx/msscript.c b/dlls/msscript.ocx/msscript.c
index 79e53f1..b0ea1e5 100644
--- a/dlls/msscript.ocx/msscript.c
+++ b/dlls/msscript.ocx/msscript.c
@@ -28,6 +28,7 @@
 #include "msscript.h"
 
 #include "wine/debug.h"
+#include "wine/list.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(msscript);
 
@@ -55,6 +56,12 @@ struct ConnectionPoint {
     ConnectionPoint *next;
 };
 
+struct named_item {
+    struct list entry;
+    BSTR name;
+    IDispatch *disp;
+};
+
 typedef struct ScriptHost {
     IActiveScriptSite IActiveScriptSite_iface;
     IActiveScriptSiteWindow IActiveScriptSiteWindow_iface;
@@ -64,6 +71,8 @@ typedef struct ScriptHost {
     IActiveScript *script;
     IActiveScriptParse *parse;
     CLSID clsid;
+
+    struct list named_items;
 } ScriptHost;
 
 struct ScriptControl {
@@ -173,6 +182,29 @@ static void release_typelib(void)
     ITypeLib_Release(typelib);
 }
 
+static void clear_named_items(ScriptHost *host)
+{
+    struct named_item *item, *item1;
+    LIST_FOR_EACH_ENTRY_SAFE(item, item1, &host->named_items, struct named_item, entry) {
+       list_remove(&item->entry);
+       SysFreeString(item->name);
+       IDispatch_Release(item->disp);
+       heap_free(item);
+    }
+}
+
+static struct named_item *host_get_named_item(ScriptHost *host, const WCHAR *nameW)
+{
+    struct named_item *item;
+
+    LIST_FOR_EACH_ENTRY(item, &host->named_items, struct named_item, entry) {
+        if (!lstrcmpW(item->name, nameW))
+            return item;
+    }
+
+    return NULL;
+}
+
 static inline ScriptControl *impl_from_IScriptControl(IScriptControl *iface)
 {
     return CONTAINING_RECORD(iface, ScriptControl, IScriptControl_iface);
@@ -293,8 +325,10 @@ static ULONG WINAPI ActiveScriptSite_Release(IActiveScriptSite *iface)
 
     TRACE("(%p) ref=%d\n", This, ref);
 
-    if(!ref)
+    if(!ref) {
+        clear_named_items(This);
         heap_free(This);
+    }
 
     return ref;
 }
@@ -309,14 +343,27 @@ static HRESULT WINAPI ActiveScriptSite_GetLCID(IActiveScriptSite *iface, LCID *l
     return S_OK;
 }
 
-static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR name, DWORD returnmask,
-    IUnknown **item, ITypeInfo **ti)
+static HRESULT WINAPI ActiveScriptSite_GetItemInfo(IActiveScriptSite *iface, LPCOLESTR name, DWORD mask,
+    IUnknown **unk, ITypeInfo **ti)
 {
     ScriptHost *This = impl_from_IActiveScriptSite(iface);
+    struct named_item *item;
 
-    FIXME("(%p, %s, %#x, %p, %p)\n", This, debugstr_w(name), returnmask, item, ti);
+    TRACE("(%p, %s, %#x, %p, %p)\n", This, debugstr_w(name), mask, unk, ti);
 
-    return E_NOTIMPL;
+    item = host_get_named_item(This, name);
+    if (!item)
+        return TYPE_E_ELEMENTNOTFOUND;
+
+    if (mask != SCRIPTINFO_IUNKNOWN) {
+        FIXME("mask %#x is not supported\n", mask);
+        return E_NOTIMPL;
+    }
+
+    *unk = (IUnknown*)item->disp;
+    IUnknown_AddRef(*unk);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI ActiveScriptSite_GetDocVersionString(IActiveScriptSite *iface, BSTR *version)
@@ -488,6 +535,7 @@ static HRESULT init_script_host(const CLSID *clsid, ScriptHost **ret)
     host->script = NULL;
     host->parse = NULL;
     host->clsid = *clsid;
+    list_init(&host->named_items);
 
     hr = CoCreateInstance(&host->clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
             &IID_IActiveScript, (void**)&host->script);
@@ -840,8 +888,42 @@ static HRESULT WINAPI ScriptControl__AboutBox(IScriptControl *iface)
 static HRESULT WINAPI ScriptControl_AddObject(IScriptControl *iface, BSTR name, IDispatch *object, VARIANT_BOOL add_members)
 {
     ScriptControl *This = impl_from_IScriptControl(iface);
-    FIXME("(%p)->(%s %p %x)\n", This, debugstr_w(name), object, add_members);
-    return E_NOTIMPL;
+    DWORD flags = SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE;
+    struct named_item *item;
+    HRESULT hr;
+
+    TRACE("(%p)->(%s %p %x)\n", This, debugstr_w(name), object, add_members);
+
+    if (!object)
+        return E_INVALIDARG;
+
+    if (!This->host)
+        return E_FAIL;
+
+    if (host_get_named_item(This->host, name))
+        return E_INVALIDARG;
+
+    item = heap_alloc(sizeof(*item));
+    if (!item)
+        return E_OUTOFMEMORY;
+
+    item->name = SysAllocString(name);
+    IDispatch_AddRef(item->disp = object);
+    list_add_tail(&This->host->named_items, &item->entry);
+
+    if (add_members)
+        flags |= SCRIPTITEM_GLOBALMEMBERS;
+    hr = IActiveScript_AddNamedItem(This->host->script, name, flags);
+    if (FAILED(hr)) {
+        list_remove(&item->entry);
+        IDispatch_Release(item->disp);
+        SysFreeString(item->name);
+        heap_free(item);
+        return hr;
+    }
+
+
+    return hr;
 }
 
 static HRESULT WINAPI ScriptControl_Reset(IScriptControl *iface)
@@ -853,6 +935,7 @@ static HRESULT WINAPI ScriptControl_Reset(IScriptControl *iface)
     if (!This->host)
         return E_FAIL;
 
+    clear_named_items(This->host);
     return IActiveScript_SetScriptState(This->host->script, SCRIPTSTATE_INITIALIZED);
 }
 
diff --git a/dlls/msscript.ocx/tests/msscript.c b/dlls/msscript.ocx/tests/msscript.c
index 3f3ff00..66e2611 100644
--- a/dlls/msscript.ocx/tests/msscript.c
+++ b/dlls/msscript.ocx/tests/msscript.c
@@ -95,6 +95,7 @@ DEFINE_EXPECT(Close);
 DEFINE_EXPECT(SetScriptSite);
 DEFINE_EXPECT(QI_IActiveScriptParse);
 DEFINE_EXPECT(SetScriptState_INITIALIZED);
+DEFINE_EXPECT(AddNamedItem);
 
 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
@@ -318,11 +319,13 @@ static HRESULT WINAPI ActiveScript_Close(IActiveScript *iface)
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI ActiveScript_AddNamedItem(IActiveScript *iface,
-        LPCOLESTR pstrName, DWORD dwFlags)
+static HRESULT WINAPI ActiveScript_AddNamedItem(IActiveScript *iface, LPCOLESTR name, DWORD flags)
 {
-    ok(0, "unexpected call\n");
-    return E_NOTIMPL;
+    static const WCHAR oW[] = {'o',0};
+    CHECK_EXPECT(AddNamedItem);
+    ok(!lstrcmpW(name, oW), "got name %s\n", wine_dbgstr_w(name));
+    ok(flags == (SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS), "got flags %#x\n", flags);
+    return S_OK;
 }
 
 static HRESULT WINAPI ActiveScript_AddTypeLib(IActiveScript *iface, REFGUID rguidTypeLib,
@@ -1086,6 +1089,144 @@ static void test_Reset(void)
         skip("Could not register TestScript engine\n");
 }
 
+static HRESULT WINAPI disp_QI(IDispatch *iface, REFIID riid, void **obj)
+{
+    if (IsEqualIID(riid, &IID_IDispatch) || IsEqualIID(riid, &IID_IUnknown)) {
+        *obj = iface;
+        IDispatch_AddRef(iface);
+        return S_OK;
+    }
+
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI disp_AddRef(IDispatch *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI disp_Release(IDispatch *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI disp_GetTypeInfoCount(IDispatch *iface, UINT *count)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI disp_GetTypeInfo(IDispatch *iface, UINT index, LCID lcid, ITypeInfo **ti)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI disp_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names,
+    UINT cnames, LCID lcid, DISPID *dispid)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI disp_Invoke(IDispatch *iface, DISPID dispid, REFIID riid, LCID lcid,
+    WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *ei, UINT *arg_err)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static const IDispatchVtbl dispvtbl = {
+    disp_QI,
+    disp_AddRef,
+    disp_Release,
+    disp_GetTypeInfoCount,
+    disp_GetTypeInfo,
+    disp_GetIDsOfNames,
+    disp_Invoke
+};
+
+static IDispatch testdisp = { &dispvtbl };
+
+static void test_AddObject(void)
+{
+    static const WCHAR oW[] = {'o',0};
+    IScriptControl *sc;
+    BSTR str, objname;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+            &IID_IScriptControl, (void**)&sc);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    objname = SysAllocString(oW);
+    hr = IScriptControl_AddObject(sc, objname, NULL, VARIANT_FALSE);
+    ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+    hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_FALSE);
+    ok(hr == E_FAIL, "got 0x%08x\n", hr);
+
+    str = SysAllocString(vbW);
+    hr = IScriptControl_put_Language(sc, str);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    SysFreeString(str);
+
+    hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_TRUE);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IScriptControl_Reset(sc);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_TRUE);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    IScriptControl_Release(sc);
+
+    /* custom script engine */
+    if (register_script_engine()) {
+        static const WCHAR testscriptW[] = {'t','e','s','t','s','c','r','i','p','t',0};
+
+        hr = CoCreateInstance(&CLSID_ScriptControl, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
+                &IID_IScriptControl, (void**)&sc);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        SET_EXPECT(CreateInstance);
+        SET_EXPECT(SetInterfaceSafetyOptions);
+        SET_EXPECT(SetScriptSite);
+        SET_EXPECT(QI_IActiveScriptParse);
+        SET_EXPECT(InitNew);
+
+        str = SysAllocString(testscriptW);
+        hr = IScriptControl_put_Language(sc, str);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        SysFreeString(str);
+
+        hr = IScriptControl_AddObject(sc, objname, NULL, VARIANT_FALSE);
+        ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+        SET_EXPECT(AddNamedItem);
+        hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_TRUE);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+        CHECK_CALLED(AddNamedItem);
+
+        hr = IScriptControl_AddObject(sc, objname, &testdisp, VARIANT_TRUE);
+        ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
+
+        init_registry(FALSE);
+
+        SET_EXPECT(Close);
+
+        IScriptControl_Release(sc);
+
+        CHECK_CALLED(Close);
+    }
+    else
+        skip("Could not register TestScript engine\n");
+
+    SysFreeString(objname);
+}
+
 START_TEST(msscript)
 {
     IUnknown *unk;
@@ -1111,6 +1252,7 @@ START_TEST(msscript)
     test_pointerinactive();
     test_timeout();
     test_Reset();
+    test_AddObject();
 
     CoUninitialize();
 }
-- 
2.8.1




More information about the wine-patches mailing list