Signed-off-by: Daniel Lehman dlehman25@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);
On 11/13/20 6:11 PM, Daniel Lehman wrote:
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;
}
What I meant is that it might be possible to pass stream directly, avoiding intermediate BSTR, like node_transform_node_params(&This->node, stylesheet, NULL, stream, NULL).
What I meant is that it might be possible to pass stream directly, avoiding intermediate BSTR, like node_transform_node_params(&This->node, stylesheet, NULL, stream, NULL).
ah, i see. will do