Signed-off-by: Daniel Lehman <dlehman25(a)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