diff --git a/rostests/winetests/xmllite/writer.c b/rostests/winetests/xmllite/writer.c index 7b6d758546d..1d677c4477c 100644 --- a/rostests/winetests/xmllite/writer.c +++ b/rostests/winetests/xmllite/writer.c @@ -31,7 +31,7 @@ #include #include #include -//#include "ole2.h" +#include #include #include @@ -74,20 +74,90 @@ static const IUnknownVtbl testoutputvtbl = { static IUnknown testoutput = { &testoutputvtbl }; +static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj) +{ + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream)) + { + *obj = iface; + return S_OK; + } + + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI teststream_AddRef(ISequentialStream *iface) +{ + return 2; +} + +static ULONG WINAPI teststream_Release(ISequentialStream *iface) +{ + return 1; +} + +static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread) +{ + ok(0, "unexpected call\n"); + return E_NOTIMPL; +} + +static ULONG g_write_len; +static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written) +{ + g_write_len = cb; + *written = cb; + return S_OK; +} + +static const ISequentialStreamVtbl teststreamvtbl = +{ + teststream_QueryInterface, + teststream_AddRef, + teststream_Release, + teststream_Read, + teststream_Write +}; + +static ISequentialStream teststream = { &teststreamvtbl }; + static void test_writer_create(void) { HRESULT hr; IXmlWriter *writer; + LONG_PTR value; /* crashes native */ if (0) { pCreateXmlWriter(&IID_IXmlWriter, NULL, NULL); - pCreateXmlWriter(NULL, (LPVOID*)&writer, NULL); + pCreateXmlWriter(NULL, (void**)&writer, NULL); } - hr = pCreateXmlWriter(&IID_IXmlWriter, (LPVOID*)&writer, NULL); + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + /* check default properties values */ + value = 0; + hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ByteOrderMark, &value); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(value == TRUE, "got %ld\n", value); + + value = TRUE; + hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_Indent, &value); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(value == FALSE, "got %ld\n", value); + + value = TRUE; + hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, &value); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(value == FALSE, "got %ld\n", value); + + value = XmlConformanceLevel_Auto; + hr = IXmlWriter_GetProperty(writer, XmlWriterProperty_ConformanceLevel, &value); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + ok(value == XmlConformanceLevel_Document, "got %ld\n", value); + IXmlWriter_Release(writer); } @@ -117,6 +187,11 @@ static void test_writeroutput(void) IUnknown *unk; HRESULT hr; + output = NULL; + hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, NULL, &output); + ok(hr == S_OK, "got %08x\n", hr); + IUnknown_Release(output); + hr = pCreateXmlWriterOutputWithEncodingName(&testoutput, NULL, utf16W, &output); ok(hr == S_OK, "got %08x\n", hr); unk = NULL; @@ -127,6 +202,481 @@ static void test_writeroutput(void) IUnknown_Release(output); } +static void test_writestartdocument(void) +{ + static const char fullprolog[] = ""; + static const char prologversion[] = ""; + static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR xmlW[] = {'x','m','l',0}; + IXmlWriter *writer; + HGLOBAL hglobal; + IStream *stream; + HRESULT hr; + char *ptr; + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + /* output not set */ + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* nothing written yet */ + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, fullprolog, strlen(fullprolog)), "got %s, expected %s\n", ptr, fullprolog); + GlobalUnlock(hglobal); + + /* one more time */ + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + IStream_Release(stream); + + /* now add PI manually, and try to start a document */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + /* another attempt to add 'xml' PI */ + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr); + GlobalUnlock(hglobal); + + IStream_Release(stream); + IXmlWriter_Release(writer); +} + +static void test_flush(void) +{ + IXmlWriter *writer; + HRESULT hr; + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)&teststream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + g_write_len = 0; + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(g_write_len > 0, "got %d\n", g_write_len); + + g_write_len = 1; + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + ok(g_write_len == 0, "got %d\n", g_write_len); + + /* Release() flushes too */ + g_write_len = 1; + IXmlWriter_Release(writer); + ok(g_write_len == 0, "got %d\n", g_write_len); +} + +static void test_omitxmldeclaration(void) +{ + static const char prologversion[] = ""; + static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR xmlW[] = {'x','m','l',0}; + IXmlWriter *writer; + HGLOBAL hglobal; + IStream *stream; + HRESULT hr; + char *ptr; + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!ptr, "got %p\n", ptr); + GlobalUnlock(hglobal); + + /* one more time */ + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + IStream_Release(stream); + + /* now add PI manually, and try to start a document */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr); + GlobalUnlock(hglobal); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr); + GlobalUnlock(hglobal); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, prologversion, strlen(prologversion)), "got %s\n", ptr); + GlobalUnlock(hglobal); + + /* another attempt to add 'xml' PI */ + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + IStream_Release(stream); + IXmlWriter_Release(writer); +} + +static void test_bom(void) +{ + static const WCHAR versionW[] = {'v','e','r','s','i','o','n','=','"','1','.','0','"',0}; + static const WCHAR utf16W[] = {'u','t','f','-','1','6',0}; + static const WCHAR xmlW[] = {'x','m','l',0}; + static const WCHAR aW[] = {'a',0}; + IXmlWriterOutput *output; + unsigned char *ptr; + IXmlWriter *writer; + IStream *stream; + HGLOBAL hglobal; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_SetProperty(writer, XmlWriterProperty_OmitXmlDeclaration, TRUE); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + /* BOM is on by default */ + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IStream_Release(stream); + IUnknown_Release(output); + + /* start with PI */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteProcessingInstruction(writer, xmlW, versionW); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IUnknown_Release(output); + IStream_Release(stream); + + /* start with element */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IUnknown_Release(output); + IStream_Release(stream); + + /* WriteElementString */ + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriterOutputWithEncodingName((IUnknown*)stream, NULL, utf16W, &output); + ok(hr == S_OK, "got %08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, output); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(ptr[0] == 0xff && ptr[1] == 0xfe, "got %x,%x\n", ptr[0], ptr[1]); + GlobalUnlock(hglobal); + + IUnknown_Release(output); + IStream_Release(stream); + + IXmlWriter_Release(writer); +} + +static void test_writestartelement(void) +{ + static const WCHAR valueW[] = {'v','a','l','u','e',0}; + static const char *str = "value"; + static const WCHAR aW[] = {'a',0}; + static const WCHAR bW[] = {'b',0}; + char *ptr; + IXmlWriter *writer; + IStream *stream; + HGLOBAL hglobal; + HRESULT hr; + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = pCreateXmlWriter(&IID_IXmlWriter, (void**)&writer, NULL); + ok(hr == S_OK, "Expected S_OK, got %08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + + hr = IXmlWriter_SetOutput(writer, (IUnknown*)stream); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, aW, NULL, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, NULL); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, NULL, aW); + ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartElement(writer, NULL, aW, NULL); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = GetHGlobalFromStream(stream, &hglobal); + ok(hr == S_OK, "got 0x%08x\n", hr); + + hr = IXmlWriter_WriteStartDocument(writer, XmlStandalone_Yes); + ok(hr == WR_E_INVALIDACTION, "got 0x%08x\n", hr); + + hr = IXmlWriter_Flush(writer); + ok(hr == S_OK, "got 0x%08x\n", hr); + + ptr = GlobalLock(hglobal); + ok(!strncmp(ptr, "", 12), "got %s\n", ptr); + GlobalUnlock(hglobal); + + IXmlWriter_Release(writer); + IStream_Release(stream); +} + START_TEST(writer) { if (!init_pointers()) @@ -134,4 +684,10 @@ START_TEST(writer) test_writer_create(); test_writeroutput(); + test_writestartdocument(); + test_writestartelement(); + test_writeendelement(); + test_flush(); + test_omitxmldeclaration(); + test_bom(); }