From b0f704daaf633d8c713c9212a2ab5dd8a4457e7a Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 9 Dec 2011 21:34:27 +0300 Subject: [PATCH] msxml3: Properly handle writer output in a form of BSTR. --- dlls/msxml3/mxwriter.c | 87 +++++++++++++++++++++++++++---------------- dlls/msxml3/tests/saxreader.c | 13 +++++-- 2 files changed, 65 insertions(+), 35 deletions(-) diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c index f4e29601ec5..febabe127e9 100644 --- a/dlls/msxml3/mxwriter.c +++ b/dlls/msxml3/mxwriter.c @@ -78,8 +78,8 @@ typedef struct _mxwriter IStream *dest; ULONG dest_written; - INT decl_count; /* practically how many times startDocument was called */ - INT decl_written; /* byte length of document prolog */ + int decl_count; /* practically how many times startDocument was called */ + int decl_written; /* byte length of document prolog */ xmlOutputBufferPtr buffer; } mxwriter; @@ -385,11 +385,6 @@ static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest) { if (This->dest) IStream_Release(This->dest); This->dest = NULL; - - /* We need to reset the output buffer to UTF-16, since the only way - * the content of the mxwriter can be accessed now is through a BSTR. - */ - This->encoding = xmlParseCharEncoding("UTF-16"); reset_output_buffer(This); break; } @@ -427,48 +422,76 @@ static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest) if (!This->dest) { - BSTR output; + xmlOutputBufferPtr prolog; + BSTR output, body = NULL; + xmlBufferPtr buffer; + WCHAR *ptr; HRESULT hr; + int i; hr = flush_output_buffer(This); if (FAILED(hr)) return hr; - /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes - * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't - * support this yet... - */ - if (This->encoding == XML_CHAR_ENCODING_UTF8) { - FIXME("XML re-encoding not supported yet\n"); - return E_NOTIMPL; + if (This->decl_count) + { + prolog = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(xmlParseCharEncoding("UTF-16"))); + write_prolog_buffer(This, xmlParseCharEncoding("UTF-16"), prolog); } + else + prolog = NULL; - if (This->decl_count) + /* optimize some paticular cases */ + /* 1. no prolog and UTF-8 buffer */ + if (This->encoding == XML_CHAR_ENCODING_UTF8 && !prolog) { - xmlOutputBufferPtr prolog; - INT i = This->decl_count; - WCHAR *ptr; + V_VT(dest) = VT_BSTR; + V_BSTR(dest) = bstr_from_xmlChar(This->buffer->buffer->content); + return S_OK; + } - prolog = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(xmlParseCharEncoding("UTF-16"))); + /* 2. no prolog and UTF-16 buffer */ + if (!prolog) + { + V_VT(dest) = VT_BSTR; + V_BSTR(dest) = SysAllocStringLen((const WCHAR*)This->buffer->conv->content, + This->buffer->conv->use/sizeof(WCHAR)); + return S_OK; + } - write_prolog_buffer(This, xmlParseCharEncoding("UTF-16"), prolog); + V_BSTR(dest) = NULL; + if (This->encoding == XML_CHAR_ENCODING_UTF8) + { + buffer = This->buffer->buffer; + body = bstr_from_xmlChar(buffer->content+This->decl_written); ptr = output = SysAllocStringByteLen(NULL, prolog->conv->use*This->decl_count + - This->buffer->conv->use-This->decl_written); - while (i--) - { - memcpy(ptr, prolog->conv->content, prolog->conv->use); - ptr += prolog->conv->use/sizeof(WCHAR); - } - - memcpy(ptr, This->buffer->conv->content + This->decl_written, This->buffer->conv->use-This->decl_written); - xmlOutputBufferClose(prolog); + SysStringByteLen(body)); } else { - output = SysAllocStringLen((const WCHAR*)This->buffer->conv->content, - This->buffer->conv->use/sizeof(WCHAR)); + buffer = This->buffer->conv; + ptr = output = SysAllocStringByteLen(NULL, prolog->conv->use*This->decl_count + + buffer->use - This->decl_written); + } + + /* write prolog part */ + i = This->decl_count; + while (i--) + { + memcpy(ptr, prolog->conv->content, prolog->conv->use); + ptr += prolog->conv->use/sizeof(WCHAR); + } + xmlOutputBufferClose(prolog); + + /* write main part */ + if (body) + { + memcpy(ptr, body, SysStringByteLen(body)); + SysFreeString(body); } + else + memcpy(ptr, buffer->content + This->decl_written, buffer->use-This->decl_written); V_VT(dest) = VT_BSTR; V_BSTR(dest) = output; diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c index 0fac3ddedd6..d713fd35a1d 100644 --- a/dlls/msxml3/tests/saxreader.c +++ b/dlls/msxml3/tests/saxreader.c @@ -2303,6 +2303,13 @@ static void test_mxwriter_startendelement(void) hr = IMXWriter_put_output(writer, dest); EXPECT_HR(hr, S_OK); + V_VT(&dest) = VT_EMPTY; + hr = IMXWriter_get_output(writer, &dest); + EXPECT_HR(hr, S_OK); + ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); + ok(!lstrcmpW(_bstr_(""), V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); + VariantClear(&dest); + hr = ISAXContentHandler_startDocument(content); EXPECT_HR(hr, S_OK); @@ -2615,9 +2622,9 @@ static void test_mxwriter_encoding(void) */ V_VT(&dest) = VT_EMPTY; hr = IMXWriter_get_output(writer, &dest); - todo_wine ok(hr == S_OK, "get_output failed: %08x\n", hr); - todo_wine ok(V_VT(&dest) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&dest)); - if (V_VT(&dest) == VT_BSTR) todo_wine ok(!lstrcmpW(_bstr_("\r\n"), V_BSTR(&dest)), + EXPECT_HR(hr, S_OK); + ok(V_VT(&dest) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&dest)); + ok(!lstrcmpW(_bstr_("\r\n"), V_BSTR(&dest)), "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest))); VariantClear(&dest); -- 2.11.4.GIT