diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index d8b81ea5397..e772a0873f0 100644 --- a/dlls/xmllite/reader.c +++ b/dlls/xmllite/reader.c @@ -554,7 +554,7 @@ static void free_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer) readerinput_free(input, buffer->data); } -static HRESULT get_code_page(xml_encoding encoding, UINT *cp) +HRESULT get_code_page(xml_encoding encoding, UINT *cp) { if (encoding == XmlEncoding_Unknown) { diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c index 738844f6fff..0f86fb97762 100644 --- a/dlls/xmllite/tests/writer.c +++ b/dlls/xmllite/tests/writer.c @@ -143,6 +143,88 @@ 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); +todo_wine + ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr); + if (hr == E_NOTIMPL) { + IXmlWriter_Release(writer); + return; + } + + 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_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); +} + START_TEST(writer) { if (!init_pointers()) @@ -150,4 +232,5 @@ START_TEST(writer) test_writer_create(); test_writeroutput(); + test_writestartdocument(); } diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c index 2432602012a..10d73cb91f0 100644 --- a/dlls/xmllite/writer.c +++ b/dlls/xmllite/writer.c @@ -34,6 +34,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(xmllite); /* not defined in public headers */ DEFINE_GUID(IID_IXmlWriterOutput, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a); +struct output_buffer +{ + char *data; + unsigned int allocated; + unsigned int written; + UINT codepage; +}; + typedef struct { IXmlWriterOutput IXmlWriterOutput_iface; @@ -42,6 +50,7 @@ typedef struct ISequentialStream *stream; IMalloc *imalloc; xml_encoding encoding; + struct output_buffer buffer; } xmlwriteroutput; static const struct IUnknownVtbl xmlwriteroutputvtbl; @@ -107,6 +116,36 @@ static inline void writer_free(xmlwriter *writer, void *mem) m_free(writer->imalloc, mem); } +static HRESULT init_output_buffer(xmlwriteroutput *output) +{ + struct output_buffer *buffer = &output->buffer; + const int initial_len = 0x2000; + HRESULT hr; + UINT cp; + + hr = get_code_page(output->encoding, &cp); + if (FAILED(hr)) return hr; + + buffer->data = writeroutput_alloc(output, initial_len); + if (!buffer->data) return E_OUTOFMEMORY; + + memset(buffer->data, 0, 4); + buffer->allocated = initial_len; + buffer->written = 0; + buffer->codepage = cp; + + return S_OK; +} + +static void free_output_buffer(xmlwriteroutput *output) +{ + struct output_buffer *buffer = &output->buffer; + writeroutput_free(output, buffer->data); + buffer->data = NULL; + buffer->allocated = 0; + buffer->written = 0; +} + static void writeroutput_release_stream(xmlwriteroutput *writeroutput) { if (writeroutput->stream) { @@ -572,6 +611,7 @@ static ULONG WINAPI xmlwriteroutput_Release(IXmlWriterOutput *iface) IMalloc *imalloc = This->imalloc; if (This->output) IUnknown_Release(This->output); if (This->stream) ISequentialStream_Release(This->stream); + free_output_buffer(This); writeroutput_free(This, This); if (imalloc) IMalloc_Release(imalloc); } @@ -627,11 +667,14 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IXmlWriterOutput **output) { xmlwriteroutput *writeroutput; + HRESULT hr; TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), output); if (!stream || !output) return E_INVALIDARG; + *output = NULL; + if (imalloc) writeroutput = IMalloc_Alloc(imalloc, sizeof(*writeroutput)); else @@ -644,6 +687,11 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, if (imalloc) IMalloc_AddRef(imalloc); writeroutput->encoding = parse_encoding_name(encoding, -1); writeroutput->stream = NULL; + hr = init_output_buffer(writeroutput); + if (FAILED(hr)) { + IUnknown_Release(&writeroutput->IXmlWriterOutput_iface); + return hr; + } IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output); diff --git a/dlls/xmllite/xmllite_private.h b/dlls/xmllite/xmllite_private.h index 96a78fadc02..642aabe616f 100644 --- a/dlls/xmllite/xmllite_private.h +++ b/dlls/xmllite/xmllite_private.h @@ -60,6 +60,7 @@ typedef enum XmlEncoding_Unknown } xml_encoding; -xml_encoding parse_encoding_name(const WCHAR *name, int len) DECLSPEC_HIDDEN; +xml_encoding parse_encoding_name(const WCHAR*,int) DECLSPEC_HIDDEN; +HRESULT get_code_page(xml_encoding,UINT*) DECLSPEC_HIDDEN; #endif /* __XMLLITE_PRIVATE__ */