From c8f9c4581cf3bad1150e0459c4eea6a8af40257e Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 1 May 2011 20:05:31 +0400 Subject: [PATCH] msxml3: Basic support for startDocument(). --- dlls/msxml3/mxwriter.c | 80 +++++++++++++++++++++++++++++--- dlls/msxml3/tests/saxreader.c | 87 ++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 8 deletions(-) diff --git a/dlls/msxml3/mxwriter.c b/dlls/msxml3/mxwriter.c index fe7fba7b07c..ec826110b3c 100644 --- a/dlls/msxml3/mxwriter.c +++ b/dlls/msxml3/mxwriter.c @@ -38,6 +38,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); +#ifdef HAVE_LIBXML2 + +static const char crlfA[] = "\r\n"; + typedef struct _mxwriter { IMXWriter IMXWriter_iface; @@ -47,8 +51,11 @@ typedef struct _mxwriter VARIANT_BOOL standalone; BSTR encoding; + BSTR version; IStream *dest; + + xmlOutputBufferPtr buffer; } mxwriter; static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface) @@ -109,6 +116,9 @@ static ULONG WINAPI mxwriter_Release(IMXWriter *iface) { if (This->dest) IStream_Release(This->dest); SysFreeString(This->encoding); + SysFreeString(This->version); + + xmlOutputBufferClose(This->buffer); heap_free(This); } @@ -228,7 +238,19 @@ static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest) static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest) { mxwriter *This = impl_from_IMXWriter( iface ); - FIXME("(%p)->(%p)\n", This, dest); + + TRACE("(%p)->(%p)\n", This, dest); + + if (!This->dest) + { + V_VT(dest) = VT_BSTR; + V_BSTR(dest) = bstr_from_xmlChar(This->buffer->buffer->content); + + return S_OK; + } + else + FIXME("not implemented when stream is set up\n"); + return E_NOTIMPL; } @@ -340,8 +362,12 @@ static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version) static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version) { mxwriter *This = impl_from_IMXWriter( iface ); - FIXME("(%p)->(%p)\n", This, version); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, version); + + if (!version) return E_POINTER; + + return return_bstr(This->version, version); } static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value) @@ -427,8 +453,34 @@ static HRESULT WINAPI mxwriter_saxcontent_putDocumentLocator( static HRESULT WINAPI mxwriter_saxcontent_startDocument(ISAXContentHandler *iface) { mxwriter *This = impl_from_ISAXContentHandler( iface ); - FIXME("(%p)\n", This); - return E_NOTIMPL; + xmlChar *s; + + TRACE("(%p)\n", This); + + /* version */ + xmlOutputBufferWriteString(This->buffer, "version); + xmlOutputBufferWriteString(This->buffer, (char*)s); + heap_free(s); + xmlOutputBufferWriteString(This->buffer, "\""); + + /* encoding */ + xmlOutputBufferWriteString(This->buffer, " encoding=\""); + s = xmlchar_from_wchar(This->encoding); + xmlOutputBufferWriteString(This->buffer, (char*)s); + heap_free(s); + xmlOutputBufferWriteString(This->buffer, "\""); + + /* standalone */ + xmlOutputBufferWriteString(This->buffer, " standalone=\""); + if (This->standalone == VARIANT_TRUE) + xmlOutputBufferWriteString(This->buffer, "yes\"?>"); + else + xmlOutputBufferWriteString(This->buffer, "no\"?>"); + + xmlOutputBufferWriteString(This->buffer, crlfA); + + return S_OK; } static HRESULT WINAPI mxwriter_saxcontent_endDocument(ISAXContentHandler *iface) @@ -554,6 +606,7 @@ static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl = HRESULT MXWriter_create(IUnknown *pUnkOuter, void **ppObj) { static const WCHAR utf16W[] = {'U','T','F','-','1','6',0}; + static const WCHAR version10W[] = {'1','.','0',0}; mxwriter *This; TRACE("(%p,%p)\n", pUnkOuter, ppObj); @@ -569,13 +622,28 @@ HRESULT MXWriter_create(IUnknown *pUnkOuter, void **ppObj) This->ref = 1; This->standalone = VARIANT_FALSE; - This->encoding = SysAllocString(utf16W); + This->encoding = SysAllocString(utf16W); + This->version = SysAllocString(version10W); This->dest = NULL; + /* set up a buffer, default encoding is UTF-16 */ + This->buffer = xmlAllocOutputBuffer(xmlFindCharEncodingHandler("UTF-16")); + *ppObj = &This->IMXWriter_iface; TRACE("returning iface %p\n", *ppObj); return S_OK; } + +#else + +HRESULT MXWriter_create(IUnknown *pUnkOuter, void **obj) +{ + MESSAGE("This program tried to use a MXXMLWriter object, but\n" + "libxml2 support was not present at compile time.\n"); + return E_NOTIMPL; +} + +#endif /* HAVE_LIBXML2 */ diff --git a/dlls/msxml3/tests/saxreader.c b/dlls/msxml3/tests/saxreader.c index 34fa902e7de..6ae7e3d6ccf 100644 --- a/dlls/msxml3/tests/saxreader.c +++ b/dlls/msxml3/tests/saxreader.c @@ -22,6 +22,8 @@ #define CONST_VTABLE #include +#include + #include "windows.h" #include "ole2.h" #include "msxml2.h" @@ -37,6 +39,32 @@ static void _expect_ref(IUnknown* obj, ULONG ref, int line) ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1); } +static BSTR alloc_str_from_narrow(const char *str) +{ + int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */ + MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); + return ret; +} + +static BSTR alloced_bstrs[256]; +static int alloced_bstrs_count; + +static BSTR _bstr_(const char *str) +{ + assert(alloced_bstrs_count < sizeof(alloced_bstrs)/sizeof(alloced_bstrs[0])); + alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str); + return alloced_bstrs[alloced_bstrs_count++]; +} + +static void free_bstrs(void) +{ + int i; + for (i = 0; i < alloced_bstrs_count; i++) + SysFreeString(alloced_bstrs[i]); + alloced_bstrs_count = 0; +} + typedef enum _CH { CH_ENDTEST, CH_PUTDOCUMENTLOCATOR, @@ -754,7 +782,15 @@ static void test_mxwriter_properties(void) ok(hr == E_INVALIDARG, "got %08x\n", hr); SysFreeString(str); + hr = IMXWriter_get_version(writer, NULL); + ok(hr == E_POINTER, "got %08x\n", hr); + /* default version is 'surprisingly' 1.0 */ + hr = IMXWriter_get_version(writer, &str); + ok(hr == S_OK, "got %08x\n", hr); + ok(!lstrcmpW(str, _bstr_("1.0")), "got %s\n", wine_dbgstr_w(str)); + IMXWriter_Release(writer); + free_bstrs(); } static void test_mxwriter_flush(void) @@ -814,7 +850,7 @@ todo_wine { ok(hr == S_OK, "got %08x\n", hr); hr = ISAXContentHandler_startDocument(content); - todo_wine ok(hr == S_OK, "got %08x\n", hr); + ok(hr == S_OK, "got %08x\n", hr); pos.QuadPart = 0; hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); @@ -823,7 +859,7 @@ todo_wine { /* already started */ hr = ISAXContentHandler_startDocument(content); - todo_wine ok(hr == S_OK, "got %08x\n", hr); + ok(hr == S_OK, "got %08x\n", hr); hr = ISAXContentHandler_endDocument(content); todo_wine ok(hr == S_OK, "got %08x\n", hr); @@ -839,6 +875,52 @@ todo_wine { IMXWriter_Release(writer); } +static void test_mxwriter_startenddocument(void) +{ + ISAXContentHandler *content; + IMXWriter *writer; + VARIANT dest; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MXXMLWriter, NULL, CLSCTX_INPROC_SERVER, + &IID_IMXWriter, (void**)&writer); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); + ok(hr == S_OK, "got %08x\n", hr); + + hr = ISAXContentHandler_startDocument(content); + ok(hr == S_OK, "got %08x\n", hr); + + hr = ISAXContentHandler_endDocument(content); + todo_wine ok(hr == S_OK, "got %08x\n", hr); + + V_VT(&dest) = VT_EMPTY; + hr = IMXWriter_get_output(writer, &dest); + ok(hr == S_OK, "got %08x\n", hr); + ok(V_VT(&dest) == 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); + + /* now try another startDocument */ + hr = ISAXContentHandler_startDocument(content); + ok(hr == S_OK, "got %08x\n", hr); + /* and get duplcated prolog */ + V_VT(&dest) = VT_EMPTY; + hr = IMXWriter_get_output(writer, &dest); + ok(hr == S_OK, "got %08x\n", hr); + ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); + ok(!lstrcmpW(_bstr_("\r\n" + "\r\n"), V_BSTR(&dest)), + "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); + VariantClear(&dest); + + ISAXContentHandler_Release(content); + IMXWriter_Release(writer); + free_bstrs(); +} + START_TEST(saxreader) { ISAXXMLReader *reader; @@ -869,6 +951,7 @@ START_TEST(saxreader) IMXWriter_Release(writer); test_mxwriter_contenthandler(); + test_mxwriter_startenddocument(); test_mxwriter_properties(); test_mxwriter_flush(); }