Andrew Eikum : mshtml: Reimplement IHTMLElement::{get, set}Attribute using IDispatchEx.

Alexandre Julliard julliard at winehq.org
Tue Sep 22 13:56:37 CDT 2009


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

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon Sep 21 12:29:55 2009 -0500

mshtml: Reimplement IHTMLElement::{get, set}Attribute using IDispatchEx.

---

 dlls/mshtml/htmlelem.c  |  105 ++++++++++++----------------------------------
 dlls/mshtml/tests/dom.c |   75 +++++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+), 77 deletions(-)

diff --git a/dlls/mshtml/htmlelem.c b/dlls/mshtml/htmlelem.c
index ad4f370..1fde2e9 100644
--- a/dlls/mshtml/htmlelem.c
+++ b/dlls/mshtml/htmlelem.c
@@ -96,44 +96,26 @@ static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttr
                                                VARIANT AttributeValue, LONG lFlags)
 {
     HTMLElement *This = HTMLELEM_THIS(iface);
-    nsAString attr_str;
-    nsAString value_str;
-    nsresult nsres;
     HRESULT hres;
-    VARIANT AttributeValueChanged;
-
-    WARN("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
-
-    if(!This->nselem) {
-        FIXME("NULL nselem\n");
-        return E_NOTIMPL;
-    }
+    DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
+    DISPPARAMS dispParams;
+    EXCEPINFO excep;
 
-    VariantInit(&AttributeValueChanged);
+    TRACE("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
 
-    hres = VariantChangeType(&AttributeValueChanged, &AttributeValue, 0, VT_BSTR);
-    if (FAILED(hres)) {
-        WARN("couldn't convert input attribute value %d to VT_BSTR\n", V_VT(&AttributeValue));
+    hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
+            fdexNameCaseInsensitive | fdexNameEnsure, &dispid);
+    if(FAILED(hres))
         return hres;
-    }
-
-    nsAString_Init(&attr_str, strAttributeName);
-    nsAString_Init(&value_str, V_BSTR(&AttributeValueChanged));
-
-    TRACE("setting %s to %s\n", debugstr_w(strAttributeName),
-        debugstr_w(V_BSTR(&AttributeValueChanged)));
-
-    nsres = nsIDOMHTMLElement_SetAttribute(This->nselem, &attr_str, &value_str);
-    nsAString_Finish(&attr_str);
-    nsAString_Finish(&value_str);
 
-    if(NS_SUCCEEDED(nsres)) {
-        hres = S_OK;
-    }else {
-        ERR("SetAttribute failed: %08x\n", nsres);
-        hres = E_FAIL;
-    }
+    dispParams.cArgs = 1;
+    dispParams.cNamedArgs = 1;
+    dispParams.rgdispidNamedArgs = &dispidNamed;
+    dispParams.rgvarg = &AttributeValue;
 
+    hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
+            LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams,
+            NULL, &excep, NULL);
     return hres;
 }
 
@@ -141,59 +123,28 @@ static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttr
                                                LONG lFlags, VARIANT *AttributeValue)
 {
     HTMLElement *This = HTMLELEM_THIS(iface);
-    nsAString attr_str;
-    nsAString value_str;
-    const PRUnichar *value;
-    nsresult nsres;
-    HRESULT hres = S_OK;
+    DISPID dispid;
+    HRESULT hres;
+    DISPPARAMS dispParams = {NULL, NULL, 0, 0};
+    EXCEPINFO excep;
 
-    WARN("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
+    TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
 
-    if(!This->nselem) {
-        FIXME("NULL nselem\n");
+    hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
+            fdexNameCaseInsensitive, &dispid);
+    if(hres == DISP_E_UNKNOWNNAME) {
         V_VT(AttributeValue) = VT_NULL;
         return S_OK;
     }
 
-    V_VT(AttributeValue) = VT_NULL;
-
-    nsAString_Init(&attr_str, strAttributeName);
-    nsAString_Init(&value_str, NULL);
-
-    nsres = nsIDOMHTMLElement_GetAttribute(This->nselem, &attr_str, &value_str);
-    nsAString_Finish(&attr_str);
-
-    if(NS_SUCCEEDED(nsres)) {
-        static const WCHAR wszSRC[] = {'s','r','c',0};
-        nsAString_GetData(&value_str, &value);
-        if(!strcmpiW(strAttributeName, wszSRC))
-        {
-            WCHAR buffer[256];
-            DWORD len;
-            BSTR bstrBaseUrl;
-            hres = IHTMLDocument2_get_URL(HTMLDOC(&This->node.doc->basedoc), &bstrBaseUrl);
-            if(SUCCEEDED(hres)) {
-                hres = CoInternetCombineUrl(bstrBaseUrl, value,
-                                            URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
-                                            buffer, sizeof(buffer)/sizeof(WCHAR), &len, 0);
-                SysFreeString(bstrBaseUrl);
-                if(SUCCEEDED(hres)) {
-                    V_VT(AttributeValue) = VT_BSTR;
-                    V_BSTR(AttributeValue) = SysAllocString(buffer);
-                    TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
-                }
-            }
-        }else if(*value) {
-            V_VT(AttributeValue) = VT_BSTR;
-            V_BSTR(AttributeValue) = SysAllocString(value);
-            TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
-        }
-    }else {
-        ERR("GetAttribute failed: %08x\n", nsres);
-        hres = E_FAIL;
+    if(FAILED(hres)) {
+        V_VT(AttributeValue) = VT_NULL;
+        return hres;
     }
 
-    nsAString_Finish(&value_str);
+    hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
+            LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams,
+            AttributeValue, &excep, NULL);
 
     return hres;
 }
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 604ead5..b489ce0 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -804,6 +804,80 @@ static void test_doc_elem(IHTMLDocument2 *doc)
     IHTMLElement_Release(elem);
 }
 
+static void test_get_set_attr(IHTMLDocument2 *doc)
+{
+    IHTMLElement *elem;
+    IHTMLDocument3 *doc3;
+    HRESULT hres;
+    BSTR bstr;
+    VARIANT val;
+
+    /* grab an element to test with */
+    hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
+    ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
+
+    hres = IHTMLDocument3_get_documentElement(doc3, &elem);
+    IHTMLDocument3_Release(doc3);
+    ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
+
+    /* get a non-present attribute */
+    bstr = a2bstr("notAnAttribute");
+    hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
+    ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
+    ok(V_VT(&val) == VT_NULL, "variant type should have been VT_NULL (0x%x), was: 0x%x\n", VT_NULL, V_VT(&val));
+    VariantClear(&val);
+    SysFreeString(bstr);
+
+    /* get a present attribute */
+    bstr = a2bstr("scrollHeight");
+    hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
+    ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
+    ok(V_VT(&val) == VT_I4, "variant type should have been VT_I4 (0x%x), was: 0x%x\n", VT_I4, V_VT(&val));
+    VariantClear(&val);
+    SysFreeString(bstr);
+
+    /* create a new BSTR attribute */
+    bstr = a2bstr("newAttribute");
+
+    V_VT(&val) = VT_BSTR;
+    V_BSTR(&val) = a2bstr("the value");
+    hres = IHTMLElement_setAttribute(elem, bstr, val, 0);
+    ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
+    VariantClear(&val);
+
+    hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
+    ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
+    ok(V_VT(&val) == VT_BSTR, "variant type should have been VT_BSTR (0x%x), was: 0x%x\n", VT_BSTR, V_VT(&val));
+    ok(strcmp_wa(V_BSTR(&val), "the value") == 0, "variant value should have been L\"the value\", was %s\n", wine_dbgstr_w(V_BSTR(&val)));
+    VariantClear(&val);
+
+    /* overwrite the attribute with a BOOL */
+    V_VT(&val) = VT_BOOL;
+    V_BOOL(&val) = VARIANT_TRUE;
+    hres = IHTMLElement_setAttribute(elem, bstr, val, 0);
+    ok(hres == S_OK, "setAttribute failed: %08x\n", hres);
+    VariantClear(&val);
+
+    hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
+    ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
+    ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val));
+    ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val));
+    VariantClear(&val);
+
+    SysFreeString(bstr);
+
+    /* case-insensitive */
+    bstr = a2bstr("newattribute");
+    hres = IHTMLElement_getAttribute(elem, bstr, 0, &val);
+    ok(hres == S_OK, "getAttribute failed: %08x\n", hres);
+    todo_wine ok(V_VT(&val) == VT_BOOL, "variant type should have been VT_BOOL (0x%x), was: 0x%x\n", VT_BOOL, V_VT(&val));
+    todo_wine ok(V_BOOL(&val) == VARIANT_TRUE, "variant value should have been VARIANT_TRUE (0x%x), was %d\n", VARIANT_TRUE, V_BOOL(&val));
+    VariantClear(&val);
+    SysFreeString(bstr);
+
+    IHTMLElement_Release(elem);
+}
+
 #define get_doc_elem(d) _get_doc_elem(__LINE__,d)
 static IHTMLElement *_get_doc_elem(unsigned line, IHTMLDocument2 *doc)
 {
@@ -5347,6 +5421,7 @@ START_TEST(dom)
     CoInitialize(NULL);
 
     run_domtest(doc_str1, test_doc_elem);
+    run_domtest(doc_str1, test_get_set_attr);
     run_domtest(range_test_str, test_txtrange);
     run_domtest(range_test2_str, test_txtrange2);
     if (winetest_interactive || ! is_ie_hardened()) {




More information about the wine-cvs mailing list