From: Nikolay Sivov Subject: [PATCH] msscript: Implement AddObject() Message-Id: <1469122451-4105-1-git-send-email-nsivov@codeweavers.com> Date: Thu, 21 Jul 2016 20:34:11 +0300 Signed-off-by: Nikolay Sivov --- 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