[PATCH v2] msxml3: Support IStream in domdoc_transformNodeToObject.

Daniel Lehman dlehman25 at gmail.com
Fri Nov 13 09:11:12 CST 2020


Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/msxml3/domdoc.c        | 17 ++++++++++++++++-
 dlls/msxml3/msxml_private.h |  2 +-
 dlls/msxml3/node.c          | 18 +++++++++++-------
 dlls/msxml3/stylesheet.c    |  2 +-
 dlls/msxml3/tests/domdoc.c  | 23 +++++++++++++++++++++++
 5 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index d447bd2b1d8..90d59df2027 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -1525,7 +1525,9 @@ static HRESULT WINAPI domdoc_transformNodeToObject(
     case VT_DISPATCH:
     {
         IXMLDOMDocument *doc;
+        IStream *stream;
         HRESULT hr;
+        BSTR str;
 
         if (!V_UNKNOWN(&output))
             return E_INVALIDARG;
@@ -1535,7 +1537,6 @@ static HRESULT WINAPI domdoc_transformNodeToObject(
         if (IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IXMLDOMDocument, (void **)&doc) == S_OK)
         {
             VARIANT_BOOL b;
-            BSTR str;
 
             if (FAILED(hr = node_transform_node(&This->node, stylesheet, &str)))
                 return hr;
@@ -1544,6 +1545,20 @@ static HRESULT WINAPI domdoc_transformNodeToObject(
             SysFreeString(str);
             return hr;
         }
+        else if (IUnknown_QueryInterface(V_UNKNOWN(&output), &IID_IStream, (void**)&stream) == S_OK)
+        {
+            BSTR str;
+
+            if (SUCCEEDED(hr = node_transform_node_params(&This->node, stylesheet, &str, NULL, NULL, TRUE)))
+            {
+                DWORD count;
+                hr = IStream_Write( stream, str, SysStringByteLen(str), &count );
+                SysFreeString(str);
+            }
+
+            IStream_Release(stream);
+            return hr;
+        }
         else
         {
             FIXME("Unsupported destination type.\n");
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index a59e00bf2b3..7b5b161c9de 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -344,7 +344,7 @@ extern HRESULT node_select_nodes(const xmlnode*,BSTR,IXMLDOMNodeList**) DECLSPEC
 extern HRESULT node_select_singlenode(const xmlnode*,BSTR,IXMLDOMNode**) DECLSPEC_HIDDEN;
 extern HRESULT node_transform_node(const xmlnode*,IXMLDOMNode*,BSTR*) DECLSPEC_HIDDEN;
 extern HRESULT node_transform_node_params(const xmlnode*,IXMLDOMNode*,BSTR*,ISequentialStream*,
-    const struct xslprocessor_params*) DECLSPEC_HIDDEN;
+    const struct xslprocessor_params*,BOOL) DECLSPEC_HIDDEN;
 extern HRESULT node_create_supporterrorinfo(const tid_t*,void**) DECLSPEC_HIDDEN;
 
 extern HRESULT get_domdoc_from_xmldoc(xmlDocPtr xmldoc, IXMLDOMDocument3 **document) DECLSPEC_HIDDEN;
diff --git a/dlls/msxml3/node.c b/dlls/msxml3/node.c
index 35777d65918..0123cb117b9 100644
--- a/dlls/msxml3/node.c
+++ b/dlls/msxml3/node.c
@@ -1249,7 +1249,7 @@ static HRESULT node_transform_write(xsltStylesheetPtr style, xmlDocPtr result, B
 }
 
 /* For BSTR output is always UTF-16, without 'encoding' attribute */
-static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr result, BSTR *str)
+static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr result, BSTR *str, BOOL keep_bom)
 {
     HRESULT hr = S_OK;
 
@@ -1273,9 +1273,13 @@ static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr r
         content = xmlBufferContent(output->conv);
         len = xmlBufferLength(output->conv);
 #endif
-        /* UTF-16 encoder places UTF-16 bom, we don't need it for BSTR */
-        content += sizeof(WCHAR);
-        *str = SysAllocStringLen((WCHAR*)content, len/sizeof(WCHAR) - 1);
+        len /= sizeof(WCHAR);
+        if (!keep_bom)
+        {
+            content += sizeof(WCHAR);
+            --len;
+        }
+        *str = SysAllocStringLen((WCHAR*)content, len);
         xmlOutputBufferClose(output);
     }
 
@@ -1503,7 +1507,7 @@ failed:
 #endif /* SONAME_LIBXSLT */
 
 HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p,
-    ISequentialStream *stream, const struct xslprocessor_params *params)
+    ISequentialStream *stream, const struct xslprocessor_params *params, BOOL keep_bom)
 {
 #ifdef SONAME_LIBXSLT
     xsltStylesheetPtr xsltSS;
@@ -1563,7 +1567,7 @@ HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet,
             if (stream)
                 hr = node_transform_write_to_stream(xsltSS, result, stream);
             else
-                hr = node_transform_write_to_bstr(xsltSS, result, p);
+                hr = node_transform_write_to_bstr(xsltSS, result, p, keep_bom);
             xmlFreeDoc(result);
         }
 
@@ -1584,7 +1588,7 @@ HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet,
 
 HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p)
 {
-    return node_transform_node_params(node, stylesheet, p, NULL, NULL);
+    return node_transform_node_params(node, stylesheet, p, NULL, NULL, FALSE);
 }
 
 HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes)
diff --git a/dlls/msxml3/stylesheet.c b/dlls/msxml3/stylesheet.c
index 9863ed7aa4b..7950adbe6da 100644
--- a/dlls/msxml3/stylesheet.c
+++ b/dlls/msxml3/stylesheet.c
@@ -588,7 +588,7 @@ static HRESULT WINAPI xslprocessor_transform(
     SysFreeString(This->outstr);
 
     hr = node_transform_node_params(get_node_obj(This->input), This->stylesheet->node,
-            &This->outstr, stream, &This->params);
+            &This->outstr, stream, &This->params, FALSE);
     if (SUCCEEDED(hr))
     {
         IStream *src = (IStream *)stream;
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 101a775ca36..3ed08b04b30 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -13030,7 +13030,11 @@ static void test_transformNodeToObject(void)
 {
     IUnknown transformdest = { &transformdestvtbl };
     IXMLDOMDocument *doc, *doc2, *doc3;
+    LARGE_INTEGER off;
+    WCHAR buffer[256];
+    IStream *istream;
     VARIANT_BOOL b;
+    ULONG nread;
     HRESULT hr;
     VARIANT v;
 
@@ -13063,6 +13067,25 @@ static void test_transformNodeToObject(void)
     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
     ok(hr == S_OK, "Failed to transform node, hr %#x.\n", hr);
 
+    istream = SHCreateMemStream(NULL, 0);
+    V_VT(&v) = VT_UNKNOWN;
+    V_UNKNOWN(&v) = (IUnknown *)istream;
+    hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
+    ok(hr == S_OK, "Failed to transform node, hr %#x.\n", hr);
+
+    off.QuadPart = 0;
+    hr = IStream_Seek(istream, off, STREAM_SEEK_SET, NULL);
+    ok(hr == S_OK, "Failed to seek, hr %#x.\n", hr);
+
+    nread = 0;
+    memset(buffer, 0xcc, sizeof(buffer));
+    hr = IStream_Read(istream, buffer, sizeof(buffer), &nread);
+    ok(hr == S_OK, "Failed to read, hr %#x.\n", hr);
+    buffer[nread/2] = 0;
+    ok(buffer[0] == 0xfeff, "got %x\n", buffer[0]);
+    ok(compareIgnoreReturns(&buffer[1], _bstr_(szTransformOutput)), "got output %s\n", wine_dbgstr_w(buffer));
+    IStream_Release(istream);
+
     IXMLDOMDocument_Release(doc3);
     IXMLDOMDocument_Release(doc2);
     IXMLDOMDocument_Release(doc);
-- 
2.25.1




More information about the wine-devel mailing list