[PATCH] msxml3: Handle SAX tags and characters for mxwriter domdoc.

Jefferson Carpenter jeffersoncarpenter2 at gmail.com
Sun May 9 18:17:00 CDT 2021


On 5/6/2021 6:11 PM, Jefferson Carpenter wrote:
> On 5/6/2021 2:12 PM, Nikolay Sivov wrote:
>> Maybe, but there's many more methods that modify the tree.
> 
> Yes, in fact I missed some.  I could write a test that sets domdoc 
> output, then calls all of them - to figure out which ones would need to 
> have this check.
> 

This is what I was talking about by testing "all of" the DOMDocument 
methods and seeing which ones get disabled when it is an active mxwriter 
destination.

These are only the IXMLDOMNode methods - not any of the additional 
IXMLDOMElement or IXMLDOMDocument methods - but they already show some 
interesting behavior, e.g. what transformNode does that is not 
documented on MSDN.

I would want to also do this for at least IXMLDOMElement and 
IXMLDOMDocument.


Next version of this patch is planned to include this (with todo_wine 
added for the remaining unimplemented cases) - unless you don't think 
it's a good idea, in which case I won't include it.


Thanks,
Jefferson
-------------- next part --------------
From 9155e42e345ebfcb17083825c66ec2d2914dd429 Mon Sep 17 00:00:00 2001
From: Jefferson Carpenter <jeffersoncarpenter2 at gmail.com>
Date: Mon, 10 May 2021 01:03:40 +0000
Subject: [PATCH] msxml3/tests: Check mxwriter domdoc destination disabled
 methods.

---
 dlls/msxml3/tests/saxreader.c | 357 ++++++++++++++++++++++++++++++++++
 1 file changed, 357 insertions(+)

diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c
index 35d0e71545b..c656c842605 100644
--- a/dlls/msxml3/tests/saxreader.c
+++ b/dlls/msxml3/tests/saxreader.c
@@ -4367,6 +4367,362 @@ static void test_mxwriter_stream(void)
     free_bstrs();
 }
 
+static void check_domnode_methods_disabled(IXMLDOMNode *locked_node, DOMNodeType node_type, IXMLDOMNode *free_node)
+{
+    BSTR bstr;
+    IXMLDOMDocument *stylesheet;
+    VARIANT variant;
+    IXMLDOMDocument *document;
+    IXMLDOMNode *dom_node;
+    IXMLDOMNodeList *node_list;
+    IXMLDOMNamedNodeMap *attributes;
+    VARIANT_BOOL variant_bool;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&stylesheet);
+    ok(hr == S_OK, "Failed to create a stylesheet, hr %#x.\n", hr);
+    hr = IXMLDOMDocument_loadXML(stylesheet, _bstr_("<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">"
+                                                      "</xsl:stylesheet>"), &variant_bool);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_nodeName(locked_node, &bstr);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_nodeValue(locked_node, &variant);
+    if (node_type == NODE_TEXT) {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        ok(V_VT(&variant) == VT_BSTR, "%p: Got %d, expected %d\n", locked_node, V_VT(&variant), VT_BSTR);
+        SysFreeString(V_BSTR(&variant));
+    }
+    else {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+
+    hr = IXMLDOMNode_put_nodeValue(locked_node, variant);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_parentNode(locked_node, &dom_node);
+    if (node_type == NODE_DOCUMENT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNode_Release(dom_node);
+    }
+
+    hr = IXMLDOMNode_get_childNodes(locked_node, &node_list);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    IXMLDOMNodeList_Release(node_list);
+
+    hr = IXMLDOMNode_get_firstChild(locked_node, &dom_node);
+    if (node_type == NODE_TEXT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNode_Release(dom_node);
+    }
+
+    hr = IXMLDOMNode_get_lastChild(locked_node, &dom_node);
+    if (node_type == NODE_TEXT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNode_Release(dom_node);
+    }
+
+    hr = IXMLDOMNode_get_previousSibling(locked_node, &dom_node);
+    if (node_type == NODE_ELEMENT) {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNode_Release(dom_node);
+    }
+    else {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+
+    hr = IXMLDOMNode_get_nextSibling(locked_node, &dom_node);
+    if (node_type == NODE_ELEMENT) {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNode_Release(dom_node);
+    }
+    else {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+
+    hr = IXMLDOMNode_get_attributes(locked_node, &attributes);
+    if (node_type == NODE_ELEMENT) {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMNamedNodeMap_Release(attributes);
+    }
+    else {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+
+    V_VT(&variant) = VT_NULL;
+    V_DISPATCH(&variant) = (IDispatch*)0xdeadbeef;
+    hr = IXMLDOMNode_insertBefore(locked_node, free_node, variant, NULL);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    /* only root node and element have child nodes to replace */
+    if (node_type != NODE_TEXT) {
+        hr = IXMLDOMNode_get_firstChild(locked_node, &dom_node);
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+        hr = IXMLDOMNode_replaceChild(locked_node, free_node, dom_node, NULL);
+        ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+        IXMLDOMNode_Release(dom_node);
+    }
+
+    /* only root node and element have child nodes to replace */
+    if (node_type != NODE_TEXT) {
+        hr = IXMLDOMNode_get_firstChild(locked_node, &dom_node);
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+        hr = IXMLDOMNode_removeChild(locked_node, dom_node, NULL);
+        ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+        IXMLDOMNode_Release(dom_node);
+    }
+
+    hr = IXMLDOMNode_appendChild(locked_node, free_node, NULL);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_hasChildNodes(locked_node, &variant_bool);
+    if (node_type == NODE_TEXT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        ok(variant_bool == VARIANT_TRUE, "%p: Got %d, expected %d\n", locked_node, variant_bool, VARIANT_TRUE);
+    }
+
+    hr = IXMLDOMNode_get_ownerDocument(locked_node, &document);
+    if (node_type == NODE_DOCUMENT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        IXMLDOMDocument_Release(document);
+    }
+
+    hr = IXMLDOMNode_cloneNode(locked_node, VARIANT_FALSE, &dom_node);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    IXMLDOMNode_Release(dom_node);
+
+    hr = IXMLDOMNode_cloneNode(locked_node, VARIANT_TRUE, &dom_node);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    IXMLDOMNode_Release(dom_node);
+
+    hr = IXMLDOMNode_get_nodeTypeString(locked_node, &bstr);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    if (node_type == NODE_DOCUMENT) {
+        ok(!lstrcmpW(bstr, L"document"), "Incorrect node type\n");
+    }
+    else if (node_type == NODE_ELEMENT) {
+        ok(!lstrcmpW(bstr, L"element"), "Incorrect node type\n");
+    }
+    else {
+        ok(!lstrcmpW(bstr, L"text"), "Incorrect node type\n");
+    }
+    SysFreeString(bstr);
+
+    hr = IXMLDOMNode_get_text(locked_node, &bstr);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    ok(!lstrcmpW(bstr, L"12345"), "Incorrect node text\n");
+    SysFreeString(bstr);
+
+    bstr = SysAllocStringLen(L"4321", 4);
+    hr = IXMLDOMNode_put_text(locked_node, bstr);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    SysFreeString(bstr);
+
+    hr = IXMLDOMNode_get_specified(locked_node, &variant_bool);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    ok(variant_bool == VARIANT_TRUE, "%p: Got %d, expected %d\n", locked_node, variant_bool, VARIANT_TRUE);
+
+    hr = IXMLDOMNode_get_definition(locked_node, &dom_node);
+    ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_nodeTypedValue(locked_node, &variant);
+    if (node_type == NODE_DOCUMENT) {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+    else {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        ok(V_VT(&variant) == VT_BSTR, "%p: Got %d, expected %d\n", locked_node, V_VT(&variant), VT_BSTR);
+        SysFreeString(V_BSTR(&variant));
+    }
+
+    V_VT(&variant) = VT_BSTR;
+    V_BSTR(&variant) = SysAllocStringLen(L"1", 1);
+    hr = IXMLDOMNode_put_nodeTypedValue(locked_node, variant);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    SysFreeString(V_BSTR(&variant));
+
+    hr = IXMLDOMNode_get_dataType(locked_node, &variant);
+    ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    bstr = SysAllocStringLen(L"char", 4);
+    hr = IXMLDOMNode_put_dataType(locked_node, bstr);
+    ok(hr == E_FAIL, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    SysFreeString(bstr);
+
+    hr = IXMLDOMNode_get_xml(locked_node, &bstr);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    SysFreeString(bstr);
+
+    hr = IXMLDOMNode_transformNode(locked_node, (IXMLDOMNode*)stylesheet, &bstr);
+    ok(hr == E_PENDING, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_selectNodes(locked_node, _bstr_("."), &node_list);
+    ok(hr == E_PENDING, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_selectSingleNode(locked_node, _bstr_("."), &dom_node);
+    ok(hr == E_PENDING, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_parsed(locked_node, &variant_bool);
+    ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    if (node_type == NODE_DOCUMENT) {
+        ok(variant_bool == VARIANT_FALSE, "%p: Got %d, expected %d.\n", locked_node, variant_bool, VARIANT_FALSE);
+    }
+    else {
+        ok(variant_bool == VARIANT_TRUE, "%p: Got %d, expected %d.\n", locked_node, variant_bool, VARIANT_TRUE);
+    }
+
+    hr = IXMLDOMNode_get_namespaceURI(locked_node, &bstr);
+    ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_prefix(locked_node, &bstr);
+    ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+
+    hr = IXMLDOMNode_get_baseName(locked_node, &bstr);
+    if (node_type == NODE_ELEMENT) {
+        ok(hr == S_OK, "%p: Unexpected hr %#x.\n", locked_node, hr);
+        ok(!lstrcmpW(bstr, L"BankAccount"), "%p: Incorrect baseName\n", locked_node);
+    }
+    else {
+        ok(hr == S_FALSE, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    }
+
+    hr = CoCreateInstance(&CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&document);
+    ok(hr == S_OK, "Failed to create a stylesheet, hr %#x.\n", hr);
+    V_VT(&variant) = VT_DISPATCH;
+    V_DISPATCH(&variant) = (IDispatch*)document;
+    hr = IXMLDOMNode_transformNodeToObject(locked_node, (IXMLDOMNode*)stylesheet, variant);
+    ok(hr == E_PENDING, "%p: Unexpected hr %#x.\n", locked_node, hr);
+    IXMLDOMDocument_Release(document);
+
+    IXMLDOMDocument_Release(stylesheet);
+}
+
+
+static void test_mxwriter_domdoc_startDocument_disables_domdoc_methods(void)
+{
+    IXMLDOMDocument *domdoc;
+    IMXWriter *writer;
+    ISAXContentHandler *content;
+    VARIANT dest;
+    IXMLDOMNode *temp_node;
+    IXMLDOMNodeList *temp_node_list;
+    IXMLDOMNode *text_node;
+    IXMLDOMNode *element;
+    IXMLDOMNode *free_node;
+    DOMNodeType node_type;
+    HRESULT hr;
+
+    /* Create mxwriter and domdoc, set domdoc output, start document, add elements */
+    hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void**)&writer);
+    ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr);
+
+    hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = CoCreateInstance(&CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&domdoc);
+    ok(hr == S_OK, "Failed to create a document, hr %#x.\n", hr);
+
+    V_VT(&dest) = VT_DISPATCH;
+    V_DISPATCH(&dest) = (IDispatch *)domdoc;
+
+    hr = IMXWriter_put_output(writer, dest);
+    ok(hr == S_OK, "Failed to set writer output, hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startDocument(content);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"Accounts", 8, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"BankAccount", 11, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"BankAccount", 11);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"BankAccount", 11, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_characters(content, L"12345", 5);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"BankAccount", 11);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"BankAccount", 11, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"BankAccount", 11);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"SomeNode", 8, NULL);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"SomeNode", 8);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+
+    /* Access created nodes. */
+    hr = IXMLDOMDocument_get_firstChild(domdoc, &temp_node);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IXMLDOMNode_get_childNodes(temp_node, &temp_node_list);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IXMLDOMNodeList_get_item(temp_node_list, 1, &element);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IXMLDOMNodeList_get_item(temp_node_list, 3, &free_node);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    hr = IXMLDOMNode_get_firstChild(element, &text_node);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+    IXMLDOMNode_Release(temp_node);
+    IXMLDOMNodeList_Release(temp_node_list);
+
+
+    /* Call DOMNode methods on document, element, and text node. */
+    check_domnode_methods_disabled((IXMLDOMNode*)domdoc, NODE_DOCUMENT, free_node);
+
+    hr = IXMLDOMNode_get_nodeType(element, &node_type);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(node_type == NODE_ELEMENT, "Node type %d, expected %d\n", node_type, NODE_ELEMENT);
+    check_domnode_methods_disabled(element, node_type, free_node);
+
+    hr = IXMLDOMNode_get_nodeType(text_node, &node_type);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(node_type == NODE_TEXT, "Node type %d, expected %d\n", node_type, NODE_TEXT);
+    check_domnode_methods_disabled(text_node, node_type, free_node);
+
+    IXMLDOMNode_Release(text_node);
+    IXMLDOMNode_Release(element);
+    IXMLDOMDocument_Release(domdoc);
+    ISAXContentHandler_Release(content);
+    IMXWriter_Release(writer);
+    free_bstrs();
+}
+
 static void test_mxwriter_domdoc(void)
 {
     ISAXContentHandler *content;
@@ -5961,6 +6317,7 @@ START_TEST(saxreader)
         test_mxwriter_properties();
         test_mxwriter_flush();
         test_mxwriter_stream();
+        test_mxwriter_domdoc_startDocument_disables_domdoc_methods();
         test_mxwriter_domdoc();
         test_mxwriter_encoding();
         test_mxwriter_dispex();
-- 
2.26.2



More information about the wine-devel mailing list