[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