msxml3: Support element declaration output in MXWriter.
[wine/multimedia.git] / dlls / msxml3 / mxwriter.c
blob55159e166ba6cda68875f231cb982b484558fdfd
1 /*
2 * MXWriter implementation
4 * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
5 * Copyright 2011 Thomas Mullaly
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "ole2.h"
34 #include "msxml6.h"
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
43 static const WCHAR emptyW[] = {0};
44 static const WCHAR spaceW[] = {' '};
45 static const WCHAR quotW[] = {'\"'};
47 typedef enum
49 XmlEncoding_UTF8,
50 XmlEncoding_UTF16,
51 XmlEncoding_Unknown
52 } xml_encoding;
54 typedef enum
56 OutputBuffer_Native = 0x001,
57 OutputBuffer_Encoded = 0x010,
58 OutputBuffer_Both = 0x100
59 } output_mode;
61 typedef enum
63 MXWriter_BOM = 0,
64 MXWriter_DisableEscaping,
65 MXWriter_Indent,
66 MXWriter_OmitXmlDecl,
67 MXWriter_Standalone,
68 MXWriter_LastProp
69 } mxwriter_prop;
71 typedef enum
73 EscapeValue,
74 EscapeText
75 } escape_mode;
77 typedef struct
79 char *data;
80 unsigned int allocated;
81 unsigned int written;
82 } encoded_buffer;
84 typedef struct
86 encoded_buffer utf16;
87 encoded_buffer encoded;
88 UINT code_page;
89 } output_buffer;
91 typedef struct
93 DispatchEx dispex;
94 IMXWriter IMXWriter_iface;
95 ISAXContentHandler ISAXContentHandler_iface;
96 ISAXLexicalHandler ISAXLexicalHandler_iface;
97 ISAXDeclHandler ISAXDeclHandler_iface;
99 LONG ref;
100 MSXML_VERSION class_version;
102 VARIANT_BOOL props[MXWriter_LastProp];
103 BOOL prop_changed;
104 BOOL cdata;
106 BSTR version;
108 BSTR encoding; /* exact property value */
109 xml_encoding xml_enc;
111 /* contains a pending (or not closed yet) element name or NULL if
112 we don't have to close */
113 BSTR element;
115 IStream *dest;
116 ULONG dest_written;
118 output_buffer *buffer;
119 } mxwriter;
121 static xml_encoding parse_encoding_name(const WCHAR *encoding)
123 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
124 if (!strcmpiW(encoding, utf8W)) return XmlEncoding_UTF8;
125 if (!strcmpiW(encoding, utf16W)) return XmlEncoding_UTF16;
126 return XmlEncoding_Unknown;
129 static HRESULT init_encoded_buffer(encoded_buffer *buffer)
131 const int initial_len = 0x2000;
132 buffer->data = heap_alloc(initial_len);
133 if (!buffer->data) return E_OUTOFMEMORY;
135 memset(buffer->data, 0, 4);
136 buffer->allocated = initial_len;
137 buffer->written = 0;
139 return S_OK;
142 static void free_encoded_buffer(encoded_buffer *buffer)
144 heap_free(buffer->data);
147 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
149 switch (encoding)
151 case XmlEncoding_UTF8:
152 *cp = CP_UTF8;
153 break;
154 case XmlEncoding_UTF16:
155 *cp = ~0;
156 break;
157 default:
158 FIXME("unsupported encoding %d\n", encoding);
159 return E_NOTIMPL;
162 return S_OK;
165 static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer)
167 output_buffer *ret;
168 HRESULT hr;
170 ret = heap_alloc(sizeof(*ret));
171 if (!ret) return E_OUTOFMEMORY;
173 hr = get_code_page(encoding, &ret->code_page);
174 if (hr != S_OK) {
175 heap_free(ret);
176 return hr;
179 hr = init_encoded_buffer(&ret->utf16);
180 if (hr != S_OK) {
181 heap_free(ret);
182 return hr;
185 if (ret->code_page == CP_UTF8) {
186 hr = init_encoded_buffer(&ret->encoded);
187 if (hr != S_OK) {
188 free_encoded_buffer(&ret->utf16);
189 heap_free(ret);
190 return hr;
193 else
194 memset(&ret->encoded, 0, sizeof(ret->encoded));
196 *buffer = ret;
198 return S_OK;
201 static void free_output_buffer(output_buffer *buffer)
203 free_encoded_buffer(&buffer->encoded);
204 free_encoded_buffer(&buffer->utf16);
205 heap_free(buffer);
208 static void grow_buffer(encoded_buffer *buffer, int length)
210 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
211 if (buffer->allocated < buffer->written + length + 4)
213 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
214 buffer->data = heap_realloc(buffer->data, grown_size);
215 buffer->allocated = grown_size;
219 static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
221 int length;
222 char *ptr;
224 if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
225 if (buffer->code_page == CP_UTF8)
227 length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
228 grow_buffer(&buffer->encoded, length);
229 ptr = buffer->encoded.data + buffer->encoded.written;
230 length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
231 buffer->encoded.written += len == -1 ? length-1 : length;
235 if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
236 /* WCHAR data just copied */
237 length = len == -1 ? strlenW(data) : len;
238 if (length)
240 length *= sizeof(WCHAR);
242 grow_buffer(&buffer->utf16, length);
243 ptr = buffer->utf16.data + buffer->utf16.written;
245 memcpy(ptr, data, length);
246 buffer->utf16.written += length;
247 ptr += length;
248 /* null termination */
249 memset(ptr, 0, sizeof(WCHAR));
253 return S_OK;
256 static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
258 return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
261 static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
263 write_output_buffer(buffer, quotW, 1);
264 write_output_buffer(buffer, data, len);
265 write_output_buffer(buffer, quotW, 1);
267 return S_OK;
270 /* frees buffer data, reallocates with a default lengths */
271 static void close_output_buffer(mxwriter *This)
273 heap_free(This->buffer->utf16.data);
274 heap_free(This->buffer->encoded.data);
275 init_encoded_buffer(&This->buffer->utf16);
276 init_encoded_buffer(&This->buffer->encoded);
277 get_code_page(This->xml_enc, &This->buffer->code_page);
280 /* escapes special characters like:
281 '<' -> "&lt;"
282 '&' -> "&amp;"
283 '"' -> "&quot;"
284 '>' -> "&gt;"
286 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
288 static const WCHAR ltW[] = {'&','l','t',';'};
289 static const WCHAR ampW[] = {'&','a','m','p',';'};
290 static const WCHAR equotW[] = {'&','q','u','o','t',';'};
291 static const WCHAR gtW[] = {'&','g','t',';'};
293 const int default_alloc = 100;
294 const int grow_thresh = 10;
295 int p = *len, conv_len;
296 WCHAR *ptr, *ret;
298 /* default buffer size to something if length is unknown */
299 conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
300 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
302 while (*str && p)
304 if (ptr - ret > conv_len - grow_thresh)
306 int written = ptr - ret;
307 conv_len *= 2;
308 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
309 ptr += written;
312 switch (*str)
314 case '<':
315 memcpy(ptr, ltW, sizeof(ltW));
316 ptr += sizeof(ltW)/sizeof(WCHAR);
317 break;
318 case '&':
319 memcpy(ptr, ampW, sizeof(ampW));
320 ptr += sizeof(ampW)/sizeof(WCHAR);
321 break;
322 case '>':
323 memcpy(ptr, gtW, sizeof(gtW));
324 ptr += sizeof(gtW)/sizeof(WCHAR);
325 break;
326 case '"':
327 if (mode == EscapeValue)
329 memcpy(ptr, equotW, sizeof(equotW));
330 ptr += sizeof(equotW)/sizeof(WCHAR);
331 break;
333 /* fallthrough for text mode */
334 default:
335 *ptr++ = *str;
336 break;
339 str++;
340 if (*len != -1) p--;
343 if (*len != -1) *len = ptr-ret;
344 *++ptr = 0;
346 return ret;
349 static void write_prolog_buffer(const mxwriter *This)
351 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
352 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
353 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
354 static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
355 static const WCHAR noW[] = {'n','o','\"','?','>'};
356 static const WCHAR crlfW[] = {'\r','\n'};
358 /* version */
359 write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
360 write_output_buffer_quoted(This->buffer, This->version, -1);
362 /* encoding */
363 write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
365 /* always write UTF-16 to WCHAR buffer */
366 write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
367 write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
368 write_output_buffer(This->buffer, quotW, 1);
370 /* standalone */
371 write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
372 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
373 write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
374 else
375 write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
377 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
380 /* Attempts to the write data from the mxwriter's buffer to
381 * the destination stream (if there is one).
383 static HRESULT write_data_to_stream(mxwriter *This)
385 encoded_buffer *buffer;
386 ULONG written = 0;
387 HRESULT hr;
389 if (!This->dest)
390 return S_OK;
392 if (This->xml_enc != XmlEncoding_UTF16)
393 buffer = &This->buffer->encoded;
394 else
395 buffer = &This->buffer->utf16;
397 if (This->dest_written > buffer->written) {
398 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->written);
399 return E_FAIL;
400 } else if (This->dest_written == buffer->written && This->xml_enc != XmlEncoding_UTF8)
401 /* Windows seems to make an empty write call when the encoding is UTF-8 and
402 * all the data has been written to the stream. It doesn't seem make this call
403 * for any other encodings.
405 return S_OK;
407 /* Write the current content from the output buffer into 'dest'.
408 * TODO: Check what Windows does if the IStream doesn't write all of
409 * the data we give it at once.
411 hr = IStream_Write(This->dest, buffer->data+This->dest_written,
412 buffer->written-This->dest_written, &written);
413 if (FAILED(hr)) {
414 WARN("Failed to write data to IStream (0x%08x)\n", hr);
415 return hr;
418 This->dest_written += written;
419 return hr;
422 /* Newly added element start tag left unclosed cause for empty elements
423 we have to close it differently. */
424 static void close_element_starttag(const mxwriter *This)
426 static const WCHAR gtW[] = {'>'};
427 if (!This->element) return;
428 write_output_buffer(This->buffer, gtW, 1);
431 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
433 SysFreeString(This->element);
434 This->element = name ? SysAllocStringLen(name, len) : NULL;
437 static inline HRESULT flush_output_buffer(mxwriter *This)
439 close_element_starttag(This);
440 set_element_name(This, NULL, 0);
441 This->cdata = FALSE;
442 return write_data_to_stream(This);
445 /* Resets the mxwriter's output buffer by closing it, then creating a new
446 * output buffer using the given encoding.
448 static inline void reset_output_buffer(mxwriter *This)
450 close_output_buffer(This);
451 This->dest_written = 0;
454 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
456 writer->props[property] = value;
457 writer->prop_changed = TRUE;
458 return S_OK;
461 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
463 if (!value) return E_POINTER;
464 *value = writer->props[property];
465 return S_OK;
468 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
470 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
473 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
475 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
478 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
480 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
483 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
485 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
488 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
490 mxwriter *This = impl_from_IMXWriter( iface );
492 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
494 *obj = NULL;
496 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
497 IsEqualGUID( riid, &IID_IDispatch ) ||
498 IsEqualGUID( riid, &IID_IUnknown ) )
500 *obj = &This->IMXWriter_iface;
502 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
504 *obj = &This->ISAXContentHandler_iface;
506 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
508 *obj = &This->ISAXLexicalHandler_iface;
510 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
512 *obj = &This->ISAXDeclHandler_iface;
514 else if (dispex_query_interface(&This->dispex, riid, obj))
516 return *obj ? S_OK : E_NOINTERFACE;
518 else
520 ERR("interface %s not implemented\n", debugstr_guid(riid));
521 *obj = NULL;
522 return E_NOINTERFACE;
525 IMXWriter_AddRef(iface);
526 return S_OK;
529 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
531 mxwriter *This = impl_from_IMXWriter( iface );
532 LONG ref = InterlockedIncrement(&This->ref);
534 TRACE("(%p)->(%d)\n", This, ref);
536 return ref;
539 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
541 mxwriter *This = impl_from_IMXWriter( iface );
542 ULONG ref = InterlockedDecrement(&This->ref);
544 TRACE("(%p)->(%d)\n", This, ref);
546 if(!ref)
548 /* Windows flushes the buffer when the interface is destroyed. */
549 flush_output_buffer(This);
550 free_output_buffer(This->buffer);
552 if (This->dest) IStream_Release(This->dest);
553 SysFreeString(This->version);
554 SysFreeString(This->encoding);
556 SysFreeString(This->element);
557 release_dispex(&This->dispex);
558 heap_free(This);
561 return ref;
564 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
566 mxwriter *This = impl_from_IMXWriter( iface );
567 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
570 static HRESULT WINAPI mxwriter_GetTypeInfo(
571 IMXWriter *iface,
572 UINT iTInfo, LCID lcid,
573 ITypeInfo** ppTInfo )
575 mxwriter *This = impl_from_IMXWriter( iface );
576 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
577 iTInfo, lcid, ppTInfo);
580 static HRESULT WINAPI mxwriter_GetIDsOfNames(
581 IMXWriter *iface,
582 REFIID riid, LPOLESTR* rgszNames,
583 UINT cNames, LCID lcid, DISPID* rgDispId )
585 mxwriter *This = impl_from_IMXWriter( iface );
586 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
587 riid, rgszNames, cNames, lcid, rgDispId);
590 static HRESULT WINAPI mxwriter_Invoke(
591 IMXWriter *iface,
592 DISPID dispIdMember, REFIID riid, LCID lcid,
593 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
594 EXCEPINFO* pExcepInfo, UINT* puArgErr )
596 mxwriter *This = impl_from_IMXWriter( iface );
597 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
598 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
601 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
603 mxwriter *This = impl_from_IMXWriter( iface );
604 HRESULT hr;
606 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
608 hr = flush_output_buffer(This);
609 if (FAILED(hr))
610 return hr;
612 switch (V_VT(&dest))
614 case VT_EMPTY:
616 if (This->dest) IStream_Release(This->dest);
617 This->dest = NULL;
618 reset_output_buffer(This);
619 break;
621 case VT_UNKNOWN:
623 IStream *stream;
625 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
626 if (hr == S_OK)
628 /* Recreate the output buffer to make sure it's using the correct encoding. */
629 reset_output_buffer(This);
631 if (This->dest) IStream_Release(This->dest);
632 This->dest = stream;
633 break;
636 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
637 return E_NOTIMPL;
639 default:
640 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
641 return E_NOTIMPL;
644 return S_OK;
647 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
649 mxwriter *This = impl_from_IMXWriter( iface );
651 TRACE("(%p)->(%p)\n", This, dest);
653 if (!This->dest)
655 HRESULT hr = flush_output_buffer(This);
656 if (FAILED(hr))
657 return hr;
659 V_VT(dest) = VT_BSTR;
660 V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
662 return S_OK;
664 else
665 FIXME("not implemented when stream is set up\n");
667 return E_NOTIMPL;
670 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
672 mxwriter *This = impl_from_IMXWriter( iface );
673 xml_encoding enc;
674 HRESULT hr;
676 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
678 enc = parse_encoding_name(encoding);
679 if (enc == XmlEncoding_Unknown)
681 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
682 return E_INVALIDARG;
685 hr = flush_output_buffer(This);
686 if (FAILED(hr))
687 return hr;
689 SysReAllocString(&This->encoding, encoding);
690 This->xml_enc = enc;
692 TRACE("got encoding %d\n", This->xml_enc);
693 reset_output_buffer(This);
694 return S_OK;
697 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
699 mxwriter *This = impl_from_IMXWriter( iface );
701 TRACE("(%p)->(%p)\n", This, encoding);
703 if (!encoding) return E_POINTER;
705 *encoding = SysAllocString(This->encoding);
706 if (!*encoding) return E_OUTOFMEMORY;
708 return S_OK;
711 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
713 mxwriter *This = impl_from_IMXWriter( iface );
715 TRACE("(%p)->(%d)\n", This, value);
716 return writer_set_property(This, MXWriter_BOM, value);
719 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
721 mxwriter *This = impl_from_IMXWriter( iface );
723 TRACE("(%p)->(%p)\n", This, value);
724 return writer_get_property(This, MXWriter_BOM, value);
727 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
729 mxwriter *This = impl_from_IMXWriter( iface );
731 TRACE("(%p)->(%d)\n", This, value);
732 return writer_set_property(This, MXWriter_Indent, value);
735 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
737 mxwriter *This = impl_from_IMXWriter( iface );
739 TRACE("(%p)->(%p)\n", This, value);
740 return writer_get_property(This, MXWriter_Indent, value);
743 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
745 mxwriter *This = impl_from_IMXWriter( iface );
747 TRACE("(%p)->(%d)\n", This, value);
748 return writer_set_property(This, MXWriter_Standalone, value);
751 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
753 mxwriter *This = impl_from_IMXWriter( iface );
755 TRACE("(%p)->(%p)\n", This, value);
756 return writer_get_property(This, MXWriter_Standalone, value);
759 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
761 mxwriter *This = impl_from_IMXWriter( iface );
763 TRACE("(%p)->(%d)\n", This, value);
764 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
767 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
769 mxwriter *This = impl_from_IMXWriter( iface );
771 TRACE("(%p)->(%p)\n", This, value);
772 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
775 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
777 mxwriter *This = impl_from_IMXWriter( iface );
779 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
781 if (!version) return E_INVALIDARG;
783 SysFreeString(This->version);
784 This->version = SysAllocString(version);
786 return S_OK;
789 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
791 mxwriter *This = impl_from_IMXWriter( iface );
793 TRACE("(%p)->(%p)\n", This, version);
795 if (!version) return E_POINTER;
797 return return_bstr(This->version, version);
800 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
802 mxwriter *This = impl_from_IMXWriter( iface );
804 TRACE("(%p)->(%d)\n", This, value);
805 return writer_set_property(This, MXWriter_DisableEscaping, value);
808 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
810 mxwriter *This = impl_from_IMXWriter( iface );
812 TRACE("(%p)->(%p)\n", This, value);
813 return writer_get_property(This, MXWriter_DisableEscaping, value);
816 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
818 mxwriter *This = impl_from_IMXWriter( iface );
819 TRACE("(%p)\n", This);
820 return flush_output_buffer(This);
823 static const struct IMXWriterVtbl MXWriterVtbl =
825 mxwriter_QueryInterface,
826 mxwriter_AddRef,
827 mxwriter_Release,
828 mxwriter_GetTypeInfoCount,
829 mxwriter_GetTypeInfo,
830 mxwriter_GetIDsOfNames,
831 mxwriter_Invoke,
832 mxwriter_put_output,
833 mxwriter_get_output,
834 mxwriter_put_encoding,
835 mxwriter_get_encoding,
836 mxwriter_put_byteOrderMark,
837 mxwriter_get_byteOrderMark,
838 mxwriter_put_indent,
839 mxwriter_get_indent,
840 mxwriter_put_standalone,
841 mxwriter_get_standalone,
842 mxwriter_put_omitXMLDeclaration,
843 mxwriter_get_omitXMLDeclaration,
844 mxwriter_put_version,
845 mxwriter_get_version,
846 mxwriter_put_disableOutputEscaping,
847 mxwriter_get_disableOutputEscaping,
848 mxwriter_flush
851 /*** ISAXContentHandler ***/
852 static HRESULT WINAPI SAXContentHandler_QueryInterface(
853 ISAXContentHandler *iface,
854 REFIID riid,
855 void **obj)
857 mxwriter *This = impl_from_ISAXContentHandler( iface );
858 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
861 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
863 mxwriter *This = impl_from_ISAXContentHandler( iface );
864 return IMXWriter_AddRef(&This->IMXWriter_iface);
867 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
869 mxwriter *This = impl_from_ISAXContentHandler( iface );
870 return IMXWriter_Release(&This->IMXWriter_iface);
873 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
874 ISAXContentHandler *iface,
875 ISAXLocator *locator)
877 mxwriter *This = impl_from_ISAXContentHandler( iface );
878 FIXME("(%p)->(%p)\n", This, locator);
879 return E_NOTIMPL;
882 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
884 mxwriter *This = impl_from_ISAXContentHandler( iface );
886 TRACE("(%p)\n", This);
888 /* If properties have been changed since the last "endDocument" call
889 * we need to reset the output buffer. If we don't the output buffer
890 * could end up with multiple XML documents in it, plus this seems to
891 * be how Windows works.
893 if (This->prop_changed) {
894 reset_output_buffer(This);
895 This->prop_changed = FALSE;
898 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
900 write_prolog_buffer(This);
902 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
903 static const char utf16BOM[] = {0xff,0xfe};
905 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
906 /* Windows passes a NULL pointer as the pcbWritten parameter and
907 * ignores any error codes returned from this Write call.
909 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
912 return S_OK;
915 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
917 mxwriter *This = impl_from_ISAXContentHandler( iface );
918 TRACE("(%p)\n", This);
919 This->prop_changed = FALSE;
920 return flush_output_buffer(This);
923 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
924 ISAXContentHandler *iface,
925 const WCHAR *prefix,
926 int nprefix,
927 const WCHAR *uri,
928 int nuri)
930 mxwriter *This = impl_from_ISAXContentHandler( iface );
931 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
932 return E_NOTIMPL;
935 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
936 ISAXContentHandler *iface,
937 const WCHAR *prefix,
938 int nprefix)
940 mxwriter *This = impl_from_ISAXContentHandler( iface );
941 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
942 return E_NOTIMPL;
945 static HRESULT WINAPI SAXContentHandler_startElement(
946 ISAXContentHandler *iface,
947 const WCHAR *namespaceUri,
948 int nnamespaceUri,
949 const WCHAR *local_name,
950 int nlocal_name,
951 const WCHAR *QName,
952 int nQName,
953 ISAXAttributes *attr)
955 mxwriter *This = impl_from_ISAXContentHandler( iface );
956 static const WCHAR ltW[] = {'<'};
958 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
959 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
961 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
962 return E_INVALIDARG;
964 close_element_starttag(This);
965 set_element_name(This, QName ? QName : emptyW,
966 QName ? nQName : 0);
968 write_output_buffer(This->buffer, ltW, 1);
969 write_output_buffer(This->buffer, QName, nQName);
971 if (attr)
973 HRESULT hr;
974 INT length;
975 INT i;
977 hr = ISAXAttributes_getLength(attr, &length);
978 if (FAILED(hr)) return hr;
980 for (i = 0; i < length; i++)
982 static const WCHAR eqW[] = {'='};
983 const WCHAR *str;
984 WCHAR *escaped;
985 INT len = 0;
987 hr = ISAXAttributes_getQName(attr, i, &str, &len);
988 if (FAILED(hr)) return hr;
990 /* space separator in front of every attribute */
991 write_output_buffer(This->buffer, spaceW, 1);
992 write_output_buffer(This->buffer, str, len);
994 write_output_buffer(This->buffer, eqW, 1);
996 len = 0;
997 hr = ISAXAttributes_getValue(attr, i, &str, &len);
998 if (FAILED(hr)) return hr;
1000 escaped = get_escaped_string(str, EscapeValue, &len);
1001 write_output_buffer_quoted(This->buffer, escaped, len);
1002 heap_free(escaped);
1006 return S_OK;
1009 static HRESULT WINAPI SAXContentHandler_endElement(
1010 ISAXContentHandler *iface,
1011 const WCHAR *namespaceUri,
1012 int nnamespaceUri,
1013 const WCHAR * local_name,
1014 int nlocal_name,
1015 const WCHAR *QName,
1016 int nQName)
1018 mxwriter *This = impl_from_ISAXContentHandler( iface );
1020 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1021 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1023 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
1024 return E_INVALIDARG;
1026 if (This->element && QName && !strncmpW(This->element, QName, nQName))
1028 static const WCHAR closeW[] = {'/','>'};
1030 write_output_buffer(This->buffer, closeW, 2);
1032 else
1034 static const WCHAR closetagW[] = {'<','/'};
1035 static const WCHAR gtW[] = {'>'};
1037 write_output_buffer(This->buffer, closetagW, 2);
1038 write_output_buffer(This->buffer, QName, nQName);
1039 write_output_buffer(This->buffer, gtW, 1);
1042 set_element_name(This, NULL, 0);
1044 return S_OK;
1047 static HRESULT WINAPI SAXContentHandler_characters(
1048 ISAXContentHandler *iface,
1049 const WCHAR *chars,
1050 int nchars)
1052 mxwriter *This = impl_from_ISAXContentHandler( iface );
1054 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1056 if (!chars) return E_INVALIDARG;
1058 close_element_starttag(This);
1059 set_element_name(This, NULL, 0);
1061 if (nchars)
1063 if (This->cdata)
1064 write_output_buffer(This->buffer, chars, nchars);
1065 else
1067 int len = nchars;
1068 WCHAR *escaped;
1070 escaped = get_escaped_string(chars, EscapeText, &len);
1071 write_output_buffer(This->buffer, escaped, len);
1072 heap_free(escaped);
1076 return S_OK;
1079 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1080 ISAXContentHandler *iface,
1081 const WCHAR *chars,
1082 int nchars)
1084 mxwriter *This = impl_from_ISAXContentHandler( iface );
1085 FIXME("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1086 return E_NOTIMPL;
1089 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1090 ISAXContentHandler *iface,
1091 const WCHAR *target,
1092 int ntarget,
1093 const WCHAR *data,
1094 int ndata)
1096 mxwriter *This = impl_from_ISAXContentHandler( iface );
1097 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1098 return E_NOTIMPL;
1101 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1102 ISAXContentHandler *iface,
1103 const WCHAR *name,
1104 int nname)
1106 mxwriter *This = impl_from_ISAXContentHandler( iface );
1107 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1108 return E_NOTIMPL;
1111 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1113 SAXContentHandler_QueryInterface,
1114 SAXContentHandler_AddRef,
1115 SAXContentHandler_Release,
1116 SAXContentHandler_putDocumentLocator,
1117 SAXContentHandler_startDocument,
1118 SAXContentHandler_endDocument,
1119 SAXContentHandler_startPrefixMapping,
1120 SAXContentHandler_endPrefixMapping,
1121 SAXContentHandler_startElement,
1122 SAXContentHandler_endElement,
1123 SAXContentHandler_characters,
1124 SAXContentHandler_ignorableWhitespace,
1125 SAXContentHandler_processingInstruction,
1126 SAXContentHandler_skippedEntity
1129 /*** ISAXLexicalHandler ***/
1130 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1131 REFIID riid, void **obj)
1133 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1134 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1137 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1139 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1140 return IMXWriter_AddRef(&This->IMXWriter_iface);
1143 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1145 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1146 return IMXWriter_Release(&This->IMXWriter_iface);
1149 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1150 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1151 const WCHAR *systemId, int systemId_len)
1153 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1154 static const WCHAR openintW[] = {'[','\r','\n'};
1156 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1158 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1159 debugstr_wn(systemId, systemId_len));
1161 if (!name) return E_INVALIDARG;
1163 write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1165 if (*name)
1167 write_output_buffer(This->buffer, name, name_len);
1168 write_output_buffer(This->buffer, spaceW, 1);
1171 if (publicId)
1173 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1175 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1176 write_output_buffer_quoted(This->buffer, publicId, publicId_len);
1178 if (!systemId) return E_INVALIDARG;
1180 if (*publicId)
1181 write_output_buffer(This->buffer, spaceW, 1);
1183 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1185 if (*systemId)
1186 write_output_buffer(This->buffer, spaceW, 1);
1188 else if (systemId)
1190 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1192 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1193 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1194 if (*systemId)
1195 write_output_buffer(This->buffer, spaceW, 1);
1198 write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
1200 return S_OK;
1203 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1205 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1206 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1208 TRACE("(%p)\n", This);
1210 write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1212 return S_OK;
1215 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1217 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1218 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1219 return E_NOTIMPL;
1222 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1224 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1225 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1226 return E_NOTIMPL;
1229 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1231 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1232 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1234 TRACE("(%p)\n", This);
1236 write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1237 This->cdata = TRUE;
1239 return S_OK;
1242 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1244 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1245 static const WCHAR ecdataW[] = {']',']','>'};
1247 TRACE("(%p)\n", This);
1249 write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1250 This->cdata = FALSE;
1252 return S_OK;
1255 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1257 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1258 static const WCHAR copenW[] = {'<','!','-','-'};
1259 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1261 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1263 if (!chars) return E_INVALIDARG;
1265 close_element_starttag(This);
1267 write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
1268 if (nchars)
1269 write_output_buffer(This->buffer, chars, nchars);
1270 write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1272 return S_OK;
1275 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1277 SAXLexicalHandler_QueryInterface,
1278 SAXLexicalHandler_AddRef,
1279 SAXLexicalHandler_Release,
1280 SAXLexicalHandler_startDTD,
1281 SAXLexicalHandler_endDTD,
1282 SAXLexicalHandler_startEntity,
1283 SAXLexicalHandler_endEntity,
1284 SAXLexicalHandler_startCDATA,
1285 SAXLexicalHandler_endCDATA,
1286 SAXLexicalHandler_comment
1289 /*** ISAXDeclHandler ***/
1290 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1291 REFIID riid, void **obj)
1293 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1294 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1297 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1299 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1300 return IMXWriter_AddRef(&This->IMXWriter_iface);
1303 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1305 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1306 return IMXWriter_Release(&This->IMXWriter_iface);
1309 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1310 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1312 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1313 static const WCHAR closeelementW[] = {'>','\r','\n'};
1314 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1316 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1317 debugstr_wn(model, n_model), n_model);
1319 if (!name || !model) return E_INVALIDARG;
1321 write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
1322 if (n_name) {
1323 write_output_buffer(This->buffer, name, n_name);
1324 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1326 if (n_model)
1327 write_output_buffer(This->buffer, model, n_model);
1328 write_output_buffer(This->buffer, closeelementW, sizeof(closeelementW)/sizeof(WCHAR));
1330 return S_OK;
1333 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1334 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1335 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1336 const WCHAR *value, int n_value)
1338 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1339 FIXME("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(element, n_element), n_element,
1340 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1341 debugstr_wn(value, n_value), n_value);
1342 return E_NOTIMPL;
1345 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1346 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1348 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1349 FIXME("(%p)->(%s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1350 debugstr_wn(value, n_value), n_value);
1351 return E_NOTIMPL;
1354 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1355 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1356 const WCHAR *systemId, int n_systemId)
1358 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1359 FIXME("(%p)->(%s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1360 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1361 return E_NOTIMPL;
1364 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1365 SAXDeclHandler_QueryInterface,
1366 SAXDeclHandler_AddRef,
1367 SAXDeclHandler_Release,
1368 SAXDeclHandler_elementDecl,
1369 SAXDeclHandler_attributeDecl,
1370 SAXDeclHandler_internalEntityDecl,
1371 SAXDeclHandler_externalEntityDecl
1374 static const tid_t mxwriter_iface_tids[] = {
1375 IMXWriter_tid,
1379 static dispex_static_data_t mxwriter_dispex = {
1380 NULL,
1381 IMXWriter_tid,
1382 NULL,
1383 mxwriter_iface_tids
1386 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
1388 static const WCHAR version10W[] = {'1','.','0',0};
1389 mxwriter *This;
1390 HRESULT hr;
1392 TRACE("(%p, %p)\n", outer, ppObj);
1394 if (outer) FIXME("support aggregation, outer\n");
1396 This = heap_alloc( sizeof (*This) );
1397 if(!This)
1398 return E_OUTOFMEMORY;
1400 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
1401 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
1402 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
1403 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
1404 This->ref = 1;
1405 This->class_version = version;
1407 This->props[MXWriter_BOM] = VARIANT_TRUE;
1408 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
1409 This->props[MXWriter_Indent] = VARIANT_FALSE;
1410 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
1411 This->props[MXWriter_Standalone] = VARIANT_FALSE;
1412 This->prop_changed = FALSE;
1413 This->encoding = SysAllocString(utf16W);
1414 This->version = SysAllocString(version10W);
1415 This->xml_enc = XmlEncoding_UTF16;
1417 This->element = NULL;
1418 This->cdata = FALSE;
1420 This->dest = NULL;
1421 This->dest_written = 0;
1423 hr = alloc_output_buffer(This->xml_enc, &This->buffer);
1424 if (hr != S_OK) {
1425 SysFreeString(This->encoding);
1426 SysFreeString(This->version);
1427 heap_free(This);
1428 return hr;
1431 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
1433 *ppObj = &This->IMXWriter_iface;
1435 TRACE("returning iface %p\n", *ppObj);
1437 return S_OK;