From 42d9e0c813e6f8f76a14ecd328906b7e38cd258d Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 17 Dec 2010 03:38:33 +0100 Subject: [PATCH] mshtml: Added support for forwarding object element's DOM calls to ActiveX control. --- dlls/mshtml/htmlobject.c | 24 +++++++++++++- dlls/mshtml/pluginhost.c | 76 +++++++++++++++++++++++++++++++++++++++++++++ dlls/mshtml/pluginhost.h | 6 ++++ dlls/mshtml/tests/activex.c | 60 +++++++++++++++++++++++++++++++++-- 4 files changed, 163 insertions(+), 3 deletions(-) diff --git a/dlls/mshtml/htmlobject.c b/dlls/mshtml/htmlobject.c index fe97eb98759..8f8bef2536d 100644 --- a/dlls/mshtml/htmlobject.c +++ b/dlls/mshtml/htmlobject.c @@ -439,6 +439,26 @@ static HRESULT HTMLObjectElement_get_readystate(HTMLDOMNode *iface, BSTR *p) return E_NOTIMPL; } +static HRESULT HTMLObjectElement_get_dispid(HTMLDOMNode *iface, BSTR name, + DWORD grfdex, DISPID *pid) +{ + HTMLObjectElement *This = HTMLOBJECT_NODE_THIS(iface); + + TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(name), grfdex, pid); + + return get_plugin_dispid(&This->plugin_container, name, pid); +} + +static HRESULT HTMLObjectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, + WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) +{ + HTMLObjectElement *This = HTMLOBJECT_NODE_THIS(iface); + + TRACE("(%p)->(%d)\n", This, id); + + return invoke_plugin_prop(&This->plugin_container, id, lcid, flags, params, res, ei); +} + #undef HTMLOBJECT_NODE_THIS static const NodeImplVtbl HTMLObjectElementImplVtbl = { @@ -450,7 +470,9 @@ static const NodeImplVtbl HTMLObjectElementImplVtbl = { NULL, NULL, NULL, - HTMLObjectElement_get_readystate + HTMLObjectElement_get_readystate, + HTMLObjectElement_get_dispid, + HTMLObjectElement_invoke }; static const tid_t HTMLObjectElement_iface_tids[] = { diff --git a/dlls/mshtml/pluginhost.c b/dlls/mshtml/pluginhost.c index 91b6fdac4a4..c6df4217509 100644 --- a/dlls/mshtml/pluginhost.c +++ b/dlls/mshtml/pluginhost.c @@ -318,6 +318,82 @@ HRESULT get_plugin_disp(HTMLPluginContainer *plugin_container, IDispatch **ret) return S_OK; } +HRESULT get_plugin_dispid(HTMLPluginContainer *plugin_container, WCHAR *name, DISPID *ret) +{ + IDispatch *disp; + DISPID id; + DWORD i; + HRESULT hres; + + if(!plugin_container->plugin_host) { + WARN("no plugin host\n"); + return DISP_E_UNKNOWNNAME; + } + + disp = plugin_container->plugin_host->disp; + if(!disp) + return DISP_E_UNKNOWNNAME; + + hres = IDispatch_GetIDsOfNames(disp, &IID_NULL, &name, 1, 0, &id); + if(FAILED(hres)) { + TRACE("no prop %s\n", debugstr_w(name)); + return DISP_E_UNKNOWNNAME; + } + + for(i=0; i < plugin_container->props_len; i++) { + if(id == plugin_container->props[i]) { + *ret = MSHTML_DISPID_CUSTOM_MIN+i; + return S_OK; + } + } + + if(!plugin_container->props) { + plugin_container->props = heap_alloc(8*sizeof(DISPID)); + if(!plugin_container->props) + return E_OUTOFMEMORY; + plugin_container->props_size = 8; + }else if(plugin_container->props_len == plugin_container->props_size) { + DISPID *new_props; + + new_props = heap_realloc(plugin_container->props, plugin_container->props_size*2); + if(!new_props) + return E_OUTOFMEMORY; + + plugin_container->props = new_props; + plugin_container->props_size *= 2; + } + + plugin_container->props[plugin_container->props_len] = id; + *ret = MSHTML_DISPID_CUSTOM_MIN+plugin_container->props_len; + plugin_container->props_len++; + return S_OK; +} + +HRESULT invoke_plugin_prop(HTMLPluginContainer *plugin_container, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, + VARIANT *res, EXCEPINFO *ei) +{ + PluginHost *host; + + host = plugin_container->plugin_host; + if(!host || !host->disp) { + FIXME("Called with no disp\n"); + return E_UNEXPECTED; + } + + if(!check_script_safety(host)) { + FIXME("Insecure object\n"); + return E_FAIL; + } + + if(id < MSHTML_DISPID_CUSTOM_MIN || id > MSHTML_DISPID_CUSTOM_MIN + plugin_container->props_len) { + ERR("Invalid id\n"); + return E_FAIL; + } + + return IDispatch_Invoke(host->disp, plugin_container->props[id-MSHTML_DISPID_CUSTOM_MIN], &IID_NULL, + lcid, flags, params, res, ei, NULL); +} + static inline PluginHost *impl_from_IOleClientSite(IOleClientSite *iface) { return CONTAINING_RECORD(iface, PluginHost, IOleClientSite_iface); diff --git a/dlls/mshtml/pluginhost.h b/dlls/mshtml/pluginhost.h index bedb8caf420..014e3ac39f9 100644 --- a/dlls/mshtml/pluginhost.h +++ b/dlls/mshtml/pluginhost.h @@ -50,6 +50,10 @@ struct HTMLPluginContainer { HTMLElement element; PluginHost *plugin_host; + + DISPID *props; + DWORD props_size; + DWORD props_len; }; extern const IID IID_HTMLPluginContainer; @@ -64,3 +68,5 @@ HRESULT create_ip_window(IOleInPlaceUIWindow**); HRESULT create_ip_frame(IOleInPlaceFrame**); HRESULT get_plugin_disp(HTMLPluginContainer*,IDispatch**); +HRESULT get_plugin_dispid(HTMLPluginContainer*,WCHAR*,DISPID*); +HRESULT invoke_plugin_prop(HTMLPluginContainer*,DISPID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*); diff --git a/dlls/mshtml/tests/activex.c b/dlls/mshtml/tests/activex.c index 809453b72dc..d3cbb9d096a 100644 --- a/dlls/mshtml/tests/activex.c +++ b/dlls/mshtml/tests/activex.c @@ -70,6 +70,8 @@ DEFINE_EXPECT(Invoke_READYSTATE); DEFINE_EXPECT(Invoke_ENABLED); DEFINE_EXPECT(Invoke_VALID); DEFINE_EXPECT(Invoke_SECURITYCTX); +DEFINE_EXPECT(Invoke_SCRIPTPROP); +DEFINE_EXPECT(GetIDsOfNames_scriptprop); DEFINE_EXPECT(DoVerb); DEFINE_EXPECT(SetExtent); DEFINE_EXPECT(GetExtent); @@ -570,8 +572,15 @@ static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID l static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { - ok(0, "unexpected call\n"); - return E_FAIL; + CHECK_EXPECT(GetIDsOfNames_scriptprop); + ok(IsEqualGUID(riid, &IID_NULL), "riid = %s\n", debugstr_guid(riid)); + ok(cNames == 1, "cNames = %d\n", cNames); + ok(rgszNames != NULL, "rgszNames == NULL\n"); + ok(!strcmp_wa(rgszNames[0], "scriptprop"), "rgszNames[0] = %s\n", wine_dbgstr_w(rgszNames[0])); + ok(rgDispId != NULL, "rgDispId == NULL\n"); + + *rgDispId = DISPID_SCRIPTPROP; + return S_OK; } static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, @@ -620,6 +629,17 @@ static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REF ok(!pExcepInfo, "pExcepInfo != NULL\n"); ok(puArgErr != NULL, "puArgErr == NULL\n"); return DISP_E_MEMBERNOTFOUND; + case DISPID_SCRIPTPROP: + CHECK_EXPECT(Invoke_SCRIPTPROP); + ok(wFlags == DISPATCH_PROPERTYGET, "wFlags = %x\n", wFlags); + ok(!pDispParams->cArgs, "pDispParams->cArgs = %d\n", pDispParams->cArgs); + ok(!pDispParams->rgvarg, "pDispParams->rgvarg != NULL\n"); + ok(pExcepInfo != NULL, "pExcepInfo == NULL\n"); + ok(!puArgErr, "puArgErr != NULL\n"); + + V_VT(pVarResult) = VT_I4; + V_I4(pVarResult) = 4; + return S_OK; default: ok(0, "unexpected call %d\n", dispIdMember); } @@ -1197,10 +1217,42 @@ static const IClassFactoryVtbl ClassFactoryVtbl = { static IClassFactory activex_cf = { &ClassFactoryVtbl }; +static void test_elem_dispex(IDispatchEx *dispex) +{ + DISPPARAMS dp; + EXCEPINFO ei; + VARIANT v; + DISPID id; + BSTR str; + HRESULT hres; + + str = a2bstr("scriptprop"); + SET_EXPECT(GetIDsOfNames_scriptprop); + hres = IDispatchEx_GetDispID(dispex, str, 0, &id); + CHECK_CALLED(GetIDsOfNames_scriptprop); + SysFreeString(str); + ok(hres == S_OK, "GetDispID failed: %08x\n", hres); + todo_wine + ok(id == DISPID_SCRIPTPROP, "id = %d\n", id); + + SET_EXPECT(Invoke_SECURITYCTX); + SET_EXPECT(Invoke_SCRIPTPROP); + memset(&dp, 0, sizeof(dp)); + memset(&ei, 0, sizeof(ei)); + V_VT(&v) = VT_EMPTY; + hres = IDispatchEx_InvokeEx(dispex, id, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL); + ok(hres == S_OK, "InvokeEx failed: %08x\n", hres); + ok(V_VT(&v) == VT_I4, "V_VT(v) = %d\n", V_VT(&v)); + ok(V_I4(&v) == 4, "V_I4(v) = %d\n", V_I4(&v)); + CHECK_CALLED(Invoke_SECURITYCTX); + CHECK_CALLED(Invoke_SCRIPTPROP); +} + static void test_object_elem(IHTMLDocument2 *doc) { IHTMLObjectElement *objelem; IHTMLDocument3 *doc3; + IDispatchEx *dispex; IHTMLElement *elem; IDispatch *disp; BSTR str; @@ -1227,6 +1279,10 @@ static void test_object_elem(IHTMLDocument2 *doc) ok(disp == &Dispatch, "disp != Dispatch\n"); CHECK_CALLED(Invoke_SECURITYCTX); + hres = IHTMLObjectElement_QueryInterface(objelem, &IID_IDispatchEx, (void**)&dispex); + test_elem_dispex(dispex); + IDispatchEx_Release(dispex); + IHTMLObjectElement_Release(objelem); } -- 2.11.4.GIT