Jacek Caban : mshtml: Added support for forwarding object element' s DOM calls to ActiveX control.

Alexandre Julliard julliard at winehq.org
Fri Dec 17 11:30:47 CST 2010


Module: wine
Branch: master
Commit: 42d9e0c813e6f8f76a14ecd328906b7e38cd258d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=42d9e0c813e6f8f76a14ecd328906b7e38cd258d

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Dec 17 03:38:33 2010 +0100

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 fe97eb9..8f8bef2 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 91b6fda..c6df421 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 bedb8ca..014e3ac 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 809453b..d3cbb9d 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);
 }
 




More information about the wine-cvs mailing list