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";
52 MXWriter_DisableEscaping
,
59 typedef struct _mxwriter
61 IMXWriter IMXWriter_iface
;
62 ISAXContentHandler ISAXContentHandler_iface
;
65 MSXML_VERSION class_version
;
67 VARIANT_BOOL props
[MXWriter_LastProp
];
69 xmlCharEncoding encoding
;
75 xmlOutputBufferPtr buffer
;
78 static HRESULT
bstr_from_xmlCharEncoding(xmlCharEncoding enc
, BSTR
*encoding
)
80 const char *encodingA
;
82 if (enc
!= XML_CHAR_ENCODING_UTF16LE
&& enc
!= XML_CHAR_ENCODING_UTF8
) {
83 FIXME("Unsupported xmlCharEncoding: %d\n", enc
);
88 encodingA
= xmlGetCharEncodingName(enc
);
90 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, encodingA
, -1, NULL
, 0);
91 *encoding
= SysAllocStringLen(NULL
, len
-1);
93 MultiByteToWideChar( CP_ACP
, 0, encodingA
, -1, *encoding
, len
);
95 *encoding
= SysAllocStringLen(NULL
, 0);
97 return *encoding
? S_OK
: E_OUTOFMEMORY
;
100 /* Attempts to the write data from the mxwriter's buffer to
101 * the destination stream (if there is one).
103 static HRESULT
write_data_to_stream(mxwriter
*This
)
107 xmlBufferPtr buffer
= NULL
;
112 /* The xmlOutputBuffer doesn't copy its contents from its 'buffer' to the
113 * 'conv' buffer when UTF8 encoding is used.
115 if (This
->encoding
== XML_CHAR_ENCODING_UTF8
)
116 buffer
= This
->buffer
->buffer
;
118 buffer
= This
->buffer
->conv
;
120 if (This
->dest_written
> buffer
->use
) {
121 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This
->dest_written
, buffer
->use
);
123 } else if (This
->dest_written
== buffer
->use
&& This
->encoding
!= XML_CHAR_ENCODING_UTF8
)
124 /* Windows seems to make an empty write call when the encoding is UTF-8 and
125 * all the data has been written to the stream. It doesn't seem make this call
126 * for any other encodings.
130 /* Write the current content from the output buffer into 'dest'.
131 * TODO: Check what Windows does if the IStream doesn't write all of
132 * the data we give it at once.
134 hres
= IStream_Write(This
->dest
, buffer
->content
+This
->dest_written
,
135 buffer
->use
-This
->dest_written
, &written
);
137 WARN("Failed to write data to IStream (%08x)\n", hres
);
141 This
->dest_written
+= written
;
145 static inline HRESULT
flush_output_buffer(mxwriter
*This
)
147 xmlOutputBufferFlush(This
->buffer
);
148 return write_data_to_stream(This
);
151 /* Resets the mxwriter's output buffer by closing it, then creating a new
152 * output buffer using the given encoding.
154 static inline void reset_output_buffer(mxwriter
*This
)
156 xmlOutputBufferClose(This
->buffer
);
157 This
->buffer
= xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This
->encoding
));
158 This
->dest_written
= 0;
161 static inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
163 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
166 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
168 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
171 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
173 mxwriter
*This
= impl_from_IMXWriter( iface
);
175 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
177 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
178 IsEqualGUID( riid
, &IID_IDispatch
) ||
179 IsEqualGUID( riid
, &IID_IUnknown
) )
181 *obj
= &This
->IMXWriter_iface
;
183 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
185 *obj
= &This
->ISAXContentHandler_iface
;
189 ERR("interface %s not implemented\n", debugstr_guid(riid
));
191 return E_NOINTERFACE
;
194 IMXWriter_AddRef(iface
);
198 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
200 mxwriter
*This
= impl_from_IMXWriter( iface
);
201 LONG ref
= InterlockedIncrement(&This
->ref
);
203 TRACE("(%p)->(%d)\n", This
, ref
);
208 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
210 mxwriter
*This
= impl_from_IMXWriter( iface
);
211 ULONG ref
= InterlockedDecrement(&This
->ref
);
213 TRACE("(%p)->(%d)\n", This
, ref
);
217 /* Windows flushes the buffer when the interface is destroyed. */
218 flush_output_buffer(This
);
220 if (This
->dest
) IStream_Release(This
->dest
);
221 SysFreeString(This
->version
);
223 xmlOutputBufferClose(This
->buffer
);
230 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
232 mxwriter
*This
= impl_from_IMXWriter( iface
);
234 TRACE("(%p)->(%p)\n", This
, pctinfo
);
241 static HRESULT WINAPI
mxwriter_GetTypeInfo(
243 UINT iTInfo
, LCID lcid
,
244 ITypeInfo
** ppTInfo
)
246 mxwriter
*This
= impl_from_IMXWriter( iface
);
248 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
250 return get_typeinfo(IMXWriter_tid
, ppTInfo
);
253 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
255 REFIID riid
, LPOLESTR
* rgszNames
,
256 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
258 mxwriter
*This
= impl_from_IMXWriter( iface
);
262 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
265 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
268 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
271 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
272 ITypeInfo_Release(typeinfo
);
278 static HRESULT WINAPI
mxwriter_Invoke(
280 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
281 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
282 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
284 mxwriter
*This
= impl_from_IMXWriter( iface
);
288 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
289 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
291 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
294 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IMXWriter_iface
, dispIdMember
, wFlags
,
295 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
296 ITypeInfo_Release(typeinfo
);
302 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
304 mxwriter
*This
= impl_from_IMXWriter( iface
);
307 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
309 hr
= flush_output_buffer(This
);
317 if (This
->dest
) IStream_Release(This
->dest
);
320 /* We need to reset the output buffer to UTF-16, since the only way
321 * the content of the mxwriter can be accessed now is through a BSTR.
323 This
->encoding
= xmlParseCharEncoding("UTF-16");
324 reset_output_buffer(This
);
331 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
334 /* Recreate the output buffer to make sure it's using the correct encoding. */
335 reset_output_buffer(This
);
337 if (This
->dest
) IStream_Release(This
->dest
);
342 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
346 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
353 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
355 mxwriter
*This
= impl_from_IMXWriter( iface
);
357 TRACE("(%p)->(%p)\n", This
, dest
);
361 HRESULT hr
= flush_output_buffer(This
);
365 /* TODO: Windows always seems to re-encode the XML to UTF-16 (this includes
366 * updating the XML decl so it says "UTF-16" instead of "UTF-8"). We don't
367 * support this yet...
369 if (This
->encoding
== XML_CHAR_ENCODING_UTF8
) {
370 FIXME("XML re-encoding not supported yet\n");
374 V_VT(dest
) = VT_BSTR
;
375 V_BSTR(dest
) = SysAllocStringLen((const WCHAR
*)This
->buffer
->conv
->content
,
376 This
->buffer
->conv
->use
/sizeof(WCHAR
));
381 FIXME("not implemented when stream is set up\n");
386 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
388 mxwriter
*This
= impl_from_IMXWriter( iface
);
390 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
392 /* FIXME: filter all supported encodings */
393 if (!strcmpW(encoding
, utf16W
) || !strcmpW(encoding
, utf8W
))
398 hr
= flush_output_buffer(This
);
402 enc
= heap_strdupWtoA(encoding
);
404 return E_OUTOFMEMORY
;
406 This
->encoding
= xmlParseCharEncoding(enc
);
409 reset_output_buffer(This
);
414 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
419 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
421 mxwriter
*This
= impl_from_IMXWriter( iface
);
423 TRACE("(%p)->(%p)\n", This
, encoding
);
425 if (!encoding
) return E_POINTER
;
427 return bstr_from_xmlCharEncoding(This
->encoding
, encoding
);
430 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
432 mxwriter
*This
= impl_from_IMXWriter( iface
);
434 TRACE("(%p)->(%d)\n", This
, value
);
435 This
->props
[MXWriter_BOM
] = value
;
436 This
->prop_changed
= TRUE
;
441 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
443 mxwriter
*This
= impl_from_IMXWriter( iface
);
445 TRACE("(%p)->(%p)\n", This
, value
);
447 if (!value
) return E_POINTER
;
449 *value
= This
->props
[MXWriter_BOM
];
454 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
456 mxwriter
*This
= impl_from_IMXWriter( iface
);
458 TRACE("(%p)->(%d)\n", This
, value
);
459 This
->props
[MXWriter_Indent
] = value
;
460 This
->prop_changed
= TRUE
;
465 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
467 mxwriter
*This
= impl_from_IMXWriter( iface
);
469 TRACE("(%p)->(%p)\n", This
, value
);
471 if (!value
) return E_POINTER
;
473 *value
= This
->props
[MXWriter_Indent
];
478 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
480 mxwriter
*This
= impl_from_IMXWriter( iface
);
482 TRACE("(%p)->(%d)\n", This
, value
);
483 This
->props
[MXWriter_Standalone
] = value
;
484 This
->prop_changed
= TRUE
;
489 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
491 mxwriter
*This
= impl_from_IMXWriter( iface
);
493 TRACE("(%p)->(%p)\n", This
, value
);
495 if (!value
) return E_POINTER
;
497 *value
= This
->props
[MXWriter_Standalone
];
502 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
504 mxwriter
*This
= impl_from_IMXWriter( iface
);
506 TRACE("(%p)->(%d)\n", This
, value
);
507 This
->props
[MXWriter_OmitXmlDecl
] = value
;
508 This
->prop_changed
= TRUE
;
513 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
515 mxwriter
*This
= impl_from_IMXWriter( iface
);
517 TRACE("(%p)->(%p)\n", This
, value
);
519 if (!value
) return E_POINTER
;
521 *value
= This
->props
[MXWriter_OmitXmlDecl
];
526 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
528 mxwriter
*This
= impl_from_IMXWriter( iface
);
530 TRACE("(%p)->(%s)\n", This
, debugstr_w(version
));
532 if (!version
) return E_INVALIDARG
;
534 SysFreeString(This
->version
);
535 This
->version
= SysAllocString(version
);
540 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
542 mxwriter
*This
= impl_from_IMXWriter( iface
);
544 TRACE("(%p)->(%p)\n", This
, version
);
546 if (!version
) return E_POINTER
;
548 return return_bstr(This
->version
, version
);
551 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
553 mxwriter
*This
= impl_from_IMXWriter( iface
);
555 TRACE("(%p)->(%d)\n", This
, value
);
556 This
->props
[MXWriter_DisableEscaping
] = value
;
557 This
->prop_changed
= TRUE
;
562 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
564 mxwriter
*This
= impl_from_IMXWriter( iface
);
566 TRACE("(%p)->(%p)\n", This
, value
);
568 if (!value
) return E_POINTER
;
570 *value
= This
->props
[MXWriter_DisableEscaping
];
575 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
577 mxwriter
*This
= impl_from_IMXWriter( iface
);
578 TRACE("(%p)\n", This
);
579 return flush_output_buffer(This
);
582 static const struct IMXWriterVtbl mxwriter_vtbl
=
584 mxwriter_QueryInterface
,
587 mxwriter_GetTypeInfoCount
,
588 mxwriter_GetTypeInfo
,
589 mxwriter_GetIDsOfNames
,
593 mxwriter_put_encoding
,
594 mxwriter_get_encoding
,
595 mxwriter_put_byteOrderMark
,
596 mxwriter_get_byteOrderMark
,
599 mxwriter_put_standalone
,
600 mxwriter_get_standalone
,
601 mxwriter_put_omitXMLDeclaration
,
602 mxwriter_get_omitXMLDeclaration
,
603 mxwriter_put_version
,
604 mxwriter_get_version
,
605 mxwriter_put_disableOutputEscaping
,
606 mxwriter_get_disableOutputEscaping
,
610 /*** ISAXContentHandler ***/
611 static HRESULT WINAPI
mxwriter_saxcontent_QueryInterface(
612 ISAXContentHandler
*iface
,
616 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
617 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
620 static ULONG WINAPI
mxwriter_saxcontent_AddRef(ISAXContentHandler
*iface
)
622 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
623 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
626 static ULONG WINAPI
mxwriter_saxcontent_Release(ISAXContentHandler
*iface
)
628 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
629 return IMXWriter_Release(&This
->IMXWriter_iface
);
632 static HRESULT WINAPI
mxwriter_saxcontent_putDocumentLocator(
633 ISAXContentHandler
*iface
,
634 ISAXLocator
*locator
)
636 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
637 FIXME("(%p)->(%p)\n", This
, locator
);
641 static HRESULT WINAPI
mxwriter_saxcontent_startDocument(ISAXContentHandler
*iface
)
643 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
646 TRACE("(%p)\n", This
);
648 /* If properties have been changed since the last "endDocument" call
649 * we need to reset the output buffer. If we don't the output buffer
650 * could end up with multiple XML documents in it, plus this seems to
651 * be how Windows works.
653 if (This
->prop_changed
) {
654 reset_output_buffer(This
);
655 This
->prop_changed
= FALSE
;
658 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
661 xmlOutputBufferWriteString(This
->buffer
, "<?xml version=\"");
662 s
= xmlchar_from_wchar(This
->version
);
663 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
665 xmlOutputBufferWriteString(This
->buffer
, "\"");
668 xmlOutputBufferWriteString(This
->buffer
, " encoding=\"");
669 xmlOutputBufferWriteString(This
->buffer
, xmlGetCharEncodingName(This
->encoding
));
670 xmlOutputBufferWriteString(This
->buffer
, "\"");
673 xmlOutputBufferWriteString(This
->buffer
, " standalone=\"");
674 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
675 xmlOutputBufferWriteString(This
->buffer
, "yes\"?>");
677 xmlOutputBufferWriteString(This
->buffer
, "no\"?>");
679 xmlOutputBufferWriteString(This
->buffer
, crlfA
);
681 if (This
->dest
&& This
->encoding
== XML_CHAR_ENCODING_UTF16LE
) {
682 static const CHAR utf16BOM
[] = {0xff,0xfe};
684 if (This
->props
[MXWriter_BOM
] == VARIANT_TRUE
)
685 /* Windows passes a NULL pointer as the pcbWritten parameter and
686 * ignores any error codes returned from this Write call.
688 IStream_Write(This
->dest
, utf16BOM
, sizeof(utf16BOM
), NULL
);
694 static HRESULT WINAPI
mxwriter_saxcontent_endDocument(ISAXContentHandler
*iface
)
696 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
697 TRACE("(%p)\n", This
);
698 This
->prop_changed
= FALSE
;
699 return flush_output_buffer(This
);
702 static HRESULT WINAPI
mxwriter_saxcontent_startPrefixMapping(
703 ISAXContentHandler
*iface
,
709 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
710 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
714 static HRESULT WINAPI
mxwriter_saxcontent_endPrefixMapping(
715 ISAXContentHandler
*iface
,
719 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
720 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
724 static HRESULT WINAPI
mxwriter_saxcontent_startElement(
725 ISAXContentHandler
*iface
,
726 const WCHAR
*namespaceUri
,
728 const WCHAR
*local_name
,
732 ISAXAttributes
*attr
)
734 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
737 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
738 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
740 if ((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
)
743 xmlOutputBufferWriteString(This
->buffer
, "<");
744 s
= xmlchar_from_wchar(QName
);
745 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
754 hr
= ISAXAttributes_getLength(attr
, &length
);
755 if (FAILED(hr
)) return hr
;
757 if (length
) xmlOutputBufferWriteString(This
->buffer
, " ");
759 for (i
= 0; i
< length
; i
++)
764 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
765 if (FAILED(hr
)) return hr
;
767 s
= xmlchar_from_wchar(str
);
768 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
771 xmlOutputBufferWriteString(This
->buffer
, "=\"");
773 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
774 if (FAILED(hr
)) return hr
;
776 s
= xmlchar_from_wchar(str
);
777 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
780 xmlOutputBufferWriteString(This
->buffer
, "\"");
784 xmlOutputBufferWriteString(This
->buffer
, ">");
789 static HRESULT WINAPI
mxwriter_saxcontent_endElement(
790 ISAXContentHandler
*iface
,
791 const WCHAR
*namespaceUri
,
793 const WCHAR
* local_name
,
798 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
801 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
802 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
));
804 if (!namespaceUri
|| !local_name
|| !QName
) return E_INVALIDARG
;
806 xmlOutputBufferWriteString(This
->buffer
, "</");
807 s
= xmlchar_from_wchar(QName
);
808 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
810 xmlOutputBufferWriteString(This
->buffer
, ">");
815 static HRESULT WINAPI
mxwriter_saxcontent_characters(
816 ISAXContentHandler
*iface
,
820 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
822 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
824 if (!chars
) return E_INVALIDARG
;
828 xmlChar
*s
= xmlchar_from_wcharn(chars
, nchars
);
829 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
836 static HRESULT WINAPI
mxwriter_saxcontent_ignorableWhitespace(
837 ISAXContentHandler
*iface
,
841 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
842 FIXME("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
846 static HRESULT WINAPI
mxwriter_saxcontent_processingInstruction(
847 ISAXContentHandler
*iface
,
853 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
854 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
858 static HRESULT WINAPI
mxwriter_saxcontent_skippedEntity(
859 ISAXContentHandler
*iface
,
863 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
864 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
868 static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl
=
870 mxwriter_saxcontent_QueryInterface
,
871 mxwriter_saxcontent_AddRef
,
872 mxwriter_saxcontent_Release
,
873 mxwriter_saxcontent_putDocumentLocator
,
874 mxwriter_saxcontent_startDocument
,
875 mxwriter_saxcontent_endDocument
,
876 mxwriter_saxcontent_startPrefixMapping
,
877 mxwriter_saxcontent_endPrefixMapping
,
878 mxwriter_saxcontent_startElement
,
879 mxwriter_saxcontent_endElement
,
880 mxwriter_saxcontent_characters
,
881 mxwriter_saxcontent_ignorableWhitespace
,
882 mxwriter_saxcontent_processingInstruction
,
883 mxwriter_saxcontent_skippedEntity
886 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **ppObj
)
888 static const WCHAR version10W
[] = {'1','.','0',0};
891 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
893 if (pUnkOuter
) FIXME("support aggregation, outer\n");
895 This
= heap_alloc( sizeof (*This
) );
897 return E_OUTOFMEMORY
;
899 This
->IMXWriter_iface
.lpVtbl
= &mxwriter_vtbl
;
900 This
->ISAXContentHandler_iface
.lpVtbl
= &mxwriter_saxcontent_vtbl
;
902 This
->class_version
= version
;
904 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
905 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
906 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
907 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
908 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
909 This
->prop_changed
= FALSE
;
910 This
->encoding
= xmlParseCharEncoding("UTF-16");
911 This
->version
= SysAllocString(version10W
);
914 This
->dest_written
= 0;
916 This
->buffer
= xmlAllocOutputBuffer(xmlGetCharEncodingHandler(This
->encoding
));
918 *ppObj
= &This
->IMXWriter_iface
;
920 TRACE("returning iface %p\n", *ppObj
);
927 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*pUnkOuter
, void **obj
)
929 MESSAGE("This program tried to use a MXXMLWriter object, but\n"
930 "libxml2 support was not present at compile time.\n");
934 #endif /* HAVE_LIBXML2 */