2 * MXWriter implementation
4 * Copyright 2011 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
27 # include <libxml/parser.h>
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
44 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
45 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
47 static const char crlfA[] = "\r\n";
48 static const WCHAR emptyW[] = {0};
53 MXWriter_DisableEscaping,
60 typedef struct _mxwriter
62 IMXWriter IMXWriter_iface;
63 ISAXContentHandler ISAXContentHandler_iface;
66 MSXML_VERSION class_version;
68 VARIANT_BOOL props[MXWriter_LastProp];
70 xmlCharEncoding encoding;
73 /* contains a pending (or not closed yet) element name or NULL if
74 we don't have to close */
80 xmlOutputBufferPtr buffer;
83 static HRESULT bstr_from_xmlCharEncoding(xmlCharEncoding enc, BSTR *encoding)
85 const char *encodingA;
87 if (enc != XML_CHAR_ENCODING_UTF16LE && enc != XML_CHAR_ENCODING_UTF8) {
88 FIXME("Unsupported xmlCharEncoding: %d\n", enc);
93 encodingA = xmlGetCharEncodingName(enc);
95 DWORD len = MultiByteToWideChar(CP_ACP, 0, encodingA, -1, NULL, 0);
96 *encoding = SysAllocStringLen(NULL, len-1);
98 MultiByteToWideChar( CP_ACP, 0, encodingA, -1, *encoding, len);
100 *encoding = SysAllocStringLen(NULL, 0);
102 return *encoding ? S_OK : E_OUTOFMEMORY;
105 /* Attempts to the write data from the mxwriter's buffer to
106 * the destination stream (if there is one).
108 static HRESULT write_data_to_stream(mxwriter *This)
112 xmlBufferPtr buffer = NULL;
117 /* The xmlOutputBuffer doesn't copy its contents from its 'buffer' to the
118 * 'conv' buffer when UTF8 encoding is used.
120 if (This->encoding == XML_CHAR_ENCODING_UTF8)
121 buffer = This->buffer->buffer;
123 buffer = This->buffer->conv;
125 if (This->dest_written > buffer->use) {
126 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->use);
128 } else if (This->dest_written == buffer->use && This->encoding != XML_CHAR_ENCODING_UTF8)
129 /* Windows seems to make an empty write call when the encoding is UTF-8 and
130 * all the data has been written to the stream. It doesn't seem make this call
131 * for any other encodings.
135 /* Write the current content from the output buffer into 'dest'.
136 * TODO: Check what Windows does if the IStream doesn't write all of
137 * the data we give it at once.
139 hres = IStream_Write(This->dest, buffer->content+This->dest_written,
140 buffer->use-This->dest_written, &written);
142 WARN("Failed to write data to IStream (%08x)\n", hres);
146 This->dest_written += written;
150 /* Newly added element start tag left unclosed cause for empty elements
151 we have to close it differently. */
152 static void close_element_starttag(const mxwriter *This)
154 if (!This->element) return;
155 xmlOutputBufferWriteString(This->buffer, ">");
158 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
160 SysFreeString(This->element);
161 This->element = name ? SysAllocStringLen(name, len) : NULL;
164 static inline HRESULT flush_output_buffer(mxwriter *This)
166 close_element_starttag(This);
167 set_element_name(This, NULL, 0);
168 xmlOutputBufferFlush(This->buffer);
169 return write_data_to_stream(This);
172 /* Resets the mxwriter's output buffer by closing it, then creating a new
173 * output buffer using the given encoding.
175 static inline void reset_output_buffer(mxwriter *This)
177 xmlOutputBufferClose(This->buffer);
178 This->buffer = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This->encoding));
179 This->dest_written = 0;
182 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
184 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
187 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
189 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
192 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
194 mxwriter *This = impl_from_IMXWriter( iface );
196 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
198 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
199 IsEqualGUID( riid, &IID_IDispatch ) ||
200 IsEqualGUID( riid, &IID_IUnknown ) )
202 *obj = &This->IMXWriter_iface;
204 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
206 *obj = &This->ISAXContentHandler_iface;
210 ERR("interface %s not implemented\n", debugstr_guid(riid));
212 return E_NOINTERFACE;
215 IMXWriter_AddRef(iface);
219 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
221 mxwriter *This = impl_from_IMXWriter( iface );
222 LONG ref = InterlockedIncrement(&This->ref);
224 TRACE("(%p)->(%d)\n", This, ref);
229 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
231 mxwriter *This = impl_from_IMXWriter( iface );
232 ULONG ref = InterlockedDecrement(&This->ref);
234 TRACE("(%p)->(%d)\n", This, ref);
238 /* Windows flushes the buffer when the interface is destroyed. */
239 flush_output_buffer(This);
241 if (This->dest) IStream_Release(This->dest);
242 SysFreeString(This->version);
244 xmlOutputBufferClose(This->buffer);
245 SysFreeString(This->element);
252 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
254 mxwriter *This = impl_from_IMXWriter( iface );
256 TRACE("(%p)->(%p)\n", This, pctinfo);
263 static HRESULT WINAPI mxwriter_GetTypeInfo(
265 UINT iTInfo, LCID lcid,
266 ITypeInfo** ppTInfo )
268 mxwriter *This = impl_from_IMXWriter( iface );
270 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
272 return get_typeinfo(IMXWriter_tid, ppTInfo);
275 static HRESULT WINAPI mxwriter_GetIDsOfNames(
277 REFIID riid, LPOLESTR* rgszNames,
278 UINT cNames, LCID lcid, DISPID* rgDispId )
280 mxwriter *This = impl_from_IMXWriter( iface );
284 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
287 if(!rgszNames || cNames == 0 || !rgDispId)
290 hr = get_typeinfo(IMXWriter_tid, &typeinfo);
293 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
294 ITypeInfo_Release(typeinfo);
300 static HRESULT WINAPI mxwriter_Invoke(
302 DISPID dispIdMember, REFIID riid, LCID lcid,
303 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
304 EXCEPINFO* pExcepInfo, UINT* puArgErr )
306 mxwriter *This = impl_from_IMXWriter( iface );
310 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
311 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
313 hr = get_typeinfo(IMXWriter_tid, &typeinfo);
316 hr = ITypeInfo_Invoke(typeinfo, &This->IMXWriter_iface, dispIdMember, wFlags,
317 pDispParams, pVarResult, pExcepInfo, puArgErr);
318 ITypeInfo_Release(typeinfo);
324 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
326 mxwriter *This = impl_from_IMXWriter( iface );
329 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
331 hr = flush_output_buffer(This);
339 if (This->dest) IStream_Release(This->dest);
342 /* We need to reset the output buffer to UTF-16, since the only way
343 * the content of the mxwriter can be accessed now is through a BSTR.
345 This->encoding = xmlParseCharEncoding("UTF-16");
346 reset_output_buffer(This);
353 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
356 /* Recreate the output buffer to make sure it's using the correct encoding. */
357 reset_output_buffer(This);
359 if (This->dest) IStream_Release(This->dest);
364 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
368 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
375 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
377 mxwriter *This = impl_from_IMXWriter( iface );
379 TRACE("(%p)->(%p)\n", This, dest);
383 HRESULT hr = flush_output_buffer(This);
387 /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes
388 * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't
389 * support this yet...
391 if (This->encoding == XML_CHAR_ENCODING_UTF8) {
392 FIXME("XML re-encoding not supported yet\n");
396 V_VT(dest) = VT_BSTR;
397 V_BSTR(dest) = SysAllocStringLen((const WCHAR*)This->buffer->conv->content,
398 This->buffer->conv->use/sizeof(WCHAR));
403 FIXME("not implemented when stream is set up\n");
408 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
410 mxwriter *This = impl_from_IMXWriter( iface );
412 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
414 /* FIXME: filter all supported encodings */
415 if (!strcmpW(encoding, utf16W) || !strcmpW(encoding, utf8W))
420 hr = flush_output_buffer(This);
424 enc = heap_strdupWtoA(encoding);
426 return E_OUTOFMEMORY;
428 This->encoding = xmlParseCharEncoding(enc);
431 reset_output_buffer(This);
436 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
441 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
443 mxwriter *This = impl_from_IMXWriter( iface );
445 TRACE("(%p)->(%p)\n", This, encoding);
447 if (!encoding) return E_POINTER;
449 return bstr_from_xmlCharEncoding(This->encoding, encoding);
452 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
454 mxwriter *This = impl_from_IMXWriter( iface );
456 TRACE("(%p)->(%d)\n", This, value);
457 This->props[MXWriter_BOM] = value;
458 This->prop_changed = TRUE;
463 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
465 mxwriter *This = impl_from_IMXWriter( iface );
467 TRACE("(%p)->(%p)\n", This, value);
469 if (!value) return E_POINTER;
471 *value = This->props[MXWriter_BOM];
476 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
478 mxwriter *This = impl_from_IMXWriter( iface );
480 TRACE("(%p)->(%d)\n", This, value);
481 This->props[MXWriter_Indent] = value;
482 This->prop_changed = TRUE;
487 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
489 mxwriter *This = impl_from_IMXWriter( iface );
491 TRACE("(%p)->(%p)\n", This, value);
493 if (!value) return E_POINTER;
495 *value = This->props[MXWriter_Indent];
500 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
502 mxwriter *This = impl_from_IMXWriter( iface );
504 TRACE("(%p)->(%d)\n", This, value);
505 This->props[MXWriter_Standalone] = value;
506 This->prop_changed = TRUE;
511 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
513 mxwriter *This = impl_from_IMXWriter( iface );
515 TRACE("(%p)->(%p)\n", This, value);
517 if (!value) return E_POINTER;
519 *value = This->props[MXWriter_Standalone];
524 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
526 mxwriter *This = impl_from_IMXWriter( iface );
528 TRACE("(%p)->(%d)\n", This, value);
529 This->props[MXWriter_OmitXmlDecl] = value;
530 This->prop_changed = TRUE;
535 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
537 mxwriter *This = impl_from_IMXWriter( iface );
539 TRACE("(%p)->(%p)\n", This, value);
541 if (!value) return E_POINTER;
543 *value = This->props[MXWriter_OmitXmlDecl];
548 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
550 mxwriter *This = impl_from_IMXWriter( iface );
552 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
554 if (!version) return E_INVALIDARG;
556 SysFreeString(This->version);
557 This->version = SysAllocString(version);
562 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
564 mxwriter *This = impl_from_IMXWriter( iface );
566 TRACE("(%p)->(%p)\n", This, version);
568 if (!version) return E_POINTER;
570 return return_bstr(This->version, version);
573 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
575 mxwriter *This = impl_from_IMXWriter( iface );
577 TRACE("(%p)->(%d)\n", This, value);
578 This->props[MXWriter_DisableEscaping] = value;
579 This->prop_changed = TRUE;
584 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
586 mxwriter *This = impl_from_IMXWriter( iface );
588 TRACE("(%p)->(%p)\n", This, value);
590 if (!value) return E_POINTER;
592 *value = This->props[MXWriter_DisableEscaping];
597 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
599 mxwriter *This = impl_from_IMXWriter( iface );
600 TRACE("(%p)\n", This);
601 return flush_output_buffer(This);
604 static const struct IMXWriterVtbl mxwriter_vtbl =
606 mxwriter_QueryInterface,
609 mxwriter_GetTypeInfoCount,
610 mxwriter_GetTypeInfo,
611 mxwriter_GetIDsOfNames,
615 mxwriter_put_encoding,
616 mxwriter_get_encoding,
617 mxwriter_put_byteOrderMark,
618 mxwriter_get_byteOrderMark,
621 mxwriter_put_standalone,
622 mxwriter_get_standalone,
623 mxwriter_put_omitXMLDeclaration,
624 mxwriter_get_omitXMLDeclaration,
625 mxwriter_put_version,
626 mxwriter_get_version,
627 mxwriter_put_disableOutputEscaping,
628 mxwriter_get_disableOutputEscaping,
632 /*** ISAXContentHandler ***/
633 static HRESULT WINAPI mxwriter_saxcontent_QueryInterface(
634 ISAXContentHandler *iface,
638 mxwriter *This = impl_from_ISAXContentHandler( iface );
639 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
642 static ULONG WINAPI mxwriter_saxcontent_AddRef(ISAXContentHandler *iface)
644 mxwriter *This = impl_from_ISAXContentHandler( iface );
645 return IMXWriter_AddRef(&This->IMXWriter_iface);
648 static ULONG WINAPI mxwriter_saxcontent_Release(ISAXContentHandler *iface)
650 mxwriter *This = impl_from_ISAXContentHandler( iface );
651 return IMXWriter_Release(&This->IMXWriter_iface);
654 static HRESULT WINAPI mxwriter_saxcontent_putDocumentLocator(
655 ISAXContentHandler *iface,
656 ISAXLocator *locator)
658 mxwriter *This = impl_from_ISAXContentHandler( iface );
659 FIXME("(%p)->(%p)\n", This, locator);
663 static HRESULT WINAPI mxwriter_saxcontent_startDocument(ISAXContentHandler *iface)
665 mxwriter *This = impl_from_ISAXContentHandler( iface );
668 TRACE("(%p)\n", This);
670 /* If properties have been changed since the last "endDocument" call
671 * we need to reset the output buffer. If we don't the output buffer
672 * could end up with multiple XML documents in it, plus this seems to
673 * be how Windows works.
675 if (This->prop_changed) {
676 reset_output_buffer(This);
677 This->prop_changed = FALSE;
680 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
683 xmlOutputBufferWriteString(This->buffer, "<?xml version=\"");
684 s = xmlchar_from_wchar(This->version);
685 xmlOutputBufferWriteString(This->buffer, (char*)s);
687 xmlOutputBufferWriteString(This->buffer, "\"");
690 xmlOutputBufferWriteString(This->buffer, " encoding=\"");
691 xmlOutputBufferWriteString(This->buffer, xmlGetCharEncodingName(This->encoding));
692 xmlOutputBufferWriteString(This->buffer, "\"");
695 xmlOutputBufferWriteString(This->buffer, " standalone=\"");
696 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
697 xmlOutputBufferWriteString(This->buffer, "yes\"?>");
699 xmlOutputBufferWriteString(This->buffer, "no\"?>");
701 xmlOutputBufferWriteString(This->buffer, crlfA);
703 if (This->dest && This->encoding == XML_CHAR_ENCODING_UTF16LE) {
704 static const CHAR utf16BOM[] = {0xff,0xfe};
706 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
707 /* Windows passes a NULL pointer as the pcbWritten parameter and
708 * ignores any error codes returned from this Write call.
710 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
716 static HRESULT WINAPI mxwriter_saxcontent_endDocument(ISAXContentHandler *iface)
718 mxwriter *This = impl_from_ISAXContentHandler( iface );
719 TRACE("(%p)\n", This);
720 This->prop_changed = FALSE;
721 return flush_output_buffer(This);
724 static HRESULT WINAPI mxwriter_saxcontent_startPrefixMapping(
725 ISAXContentHandler *iface,
731 mxwriter *This = impl_from_ISAXContentHandler( iface );
732 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
736 static HRESULT WINAPI mxwriter_saxcontent_endPrefixMapping(
737 ISAXContentHandler *iface,
741 mxwriter *This = impl_from_ISAXContentHandler( iface );
742 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
746 static HRESULT WINAPI mxwriter_saxcontent_startElement(
747 ISAXContentHandler *iface,
748 const WCHAR *namespaceUri,
750 const WCHAR *local_name,
754 ISAXAttributes *attr)
756 mxwriter *This = impl_from_ISAXContentHandler( iface );
759 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
760 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
762 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
765 close_element_starttag(This);
766 set_element_name(This, QName ? QName : emptyW,
769 xmlOutputBufferWriteString(This->buffer, "<");
770 s = xmlchar_from_wcharn(QName, nQName);
771 xmlOutputBufferWriteString(This->buffer, (char*)s);
780 hr = ISAXAttributes_getLength(attr, &length);
781 if (FAILED(hr)) return hr;
783 for (i = 0; i < length; i++)
788 hr = ISAXAttributes_getQName(attr, i, &str, &len);
789 if (FAILED(hr)) return hr;
791 /* space separator in front of every attribute */
792 xmlOutputBufferWriteString(This->buffer, " ");
794 s = xmlchar_from_wcharn(str, len);
795 xmlOutputBufferWriteString(This->buffer, (char*)s);
798 xmlOutputBufferWriteString(This->buffer, "=\"");
801 hr = ISAXAttributes_getValue(attr, i, &str, &len);
802 if (FAILED(hr)) return hr;
804 s = xmlchar_from_wcharn(str, len);
805 xmlOutputBufferWriteString(This->buffer, (char*)s);
808 xmlOutputBufferWriteString(This->buffer, "\"");
815 static HRESULT WINAPI mxwriter_saxcontent_endElement(
816 ISAXContentHandler *iface,
817 const WCHAR *namespaceUri,
819 const WCHAR * local_name,
824 mxwriter *This = impl_from_ISAXContentHandler( iface );
827 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
828 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName));
830 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
833 s = xmlchar_from_wchar(QName);
835 if (This->element && QName && !strcmpW(This->element, QName))
837 xmlOutputBufferWriteString(This->buffer, "/>");
841 xmlOutputBufferWriteString(This->buffer, "</");
842 xmlOutputBufferWriteString(This->buffer, (char*)s);
843 xmlOutputBufferWriteString(This->buffer, ">");
847 set_element_name(This, NULL, 0);
852 static HRESULT WINAPI mxwriter_saxcontent_characters(
853 ISAXContentHandler *iface,
857 mxwriter *This = impl_from_ISAXContentHandler( iface );
859 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
861 if (!chars) return E_INVALIDARG;
863 close_element_starttag(This);
864 set_element_name(This, NULL, 0);
868 xmlChar *s = xmlchar_from_wcharn(chars, nchars);
869 xmlOutputBufferWriteString(This->buffer, (char*)s);
876 static HRESULT WINAPI mxwriter_saxcontent_ignorableWhitespace(
877 ISAXContentHandler *iface,
881 mxwriter *This = impl_from_ISAXContentHandler( iface );
882 FIXME("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
886 static HRESULT WINAPI mxwriter_saxcontent_processingInstruction(
887 ISAXContentHandler *iface,
893 mxwriter *This = impl_from_ISAXContentHandler( iface );
894 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
898 static HRESULT WINAPI mxwriter_saxcontent_skippedEntity(
899 ISAXContentHandler *iface,
903 mxwriter *This = impl_from_ISAXContentHandler( iface );
904 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
908 static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl =
910 mxwriter_saxcontent_QueryInterface,
911 mxwriter_saxcontent_AddRef,
912 mxwriter_saxcontent_Release,
913 mxwriter_saxcontent_putDocumentLocator,
914 mxwriter_saxcontent_startDocument,
915 mxwriter_saxcontent_endDocument,
916 mxwriter_saxcontent_startPrefixMapping,
917 mxwriter_saxcontent_endPrefixMapping,
918 mxwriter_saxcontent_startElement,
919 mxwriter_saxcontent_endElement,
920 mxwriter_saxcontent_characters,
921 mxwriter_saxcontent_ignorableWhitespace,
922 mxwriter_saxcontent_processingInstruction,
923 mxwriter_saxcontent_skippedEntity
926 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **ppObj)
928 static const WCHAR version10W[] = {'1','.','0',0};
931 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
933 if (pUnkOuter) FIXME("support aggregation, outer\n");
935 This = heap_alloc( sizeof (*This) );
937 return E_OUTOFMEMORY;
939 This->IMXWriter_iface.lpVtbl = &mxwriter_vtbl;
940 This->ISAXContentHandler_iface.lpVtbl = &mxwriter_saxcontent_vtbl;
942 This->class_version = version;
944 This->props[MXWriter_BOM] = VARIANT_TRUE;
945 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
946 This->props[MXWriter_Indent] = VARIANT_FALSE;
947 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
948 This->props[MXWriter_Standalone] = VARIANT_FALSE;
949 This->prop_changed = FALSE;
950 This->encoding = xmlParseCharEncoding("UTF-16");
951 This->version = SysAllocString(version10W);
953 This->element = NULL;
956 This->dest_written = 0;
958 This->buffer = xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This->encoding));
960 *ppObj = &This->IMXWriter_iface;
962 TRACE("returning iface %p\n", *ppObj);
969 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *pUnkOuter, void **obj)
971 MESSAGE("This program tried to use a MXXMLWriter object, but\n"
972 "libxml2 support was not present at compile time.\n");
976 #endif /* HAVE_LIBXML2 */