2 * MXWriter implementation
4 * Copyright 2011 Nikolay Sivov for CodeWeaversы
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 # include <libxml/parser.h>
35 #include "wine/debug.h"
37 #include "msxml_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
43 static const char crlfA
[] = "\r\n";
48 MXWriter_DisableEscaping
,
55 typedef struct _mxwriter
57 IMXWriter IMXWriter_iface
;
58 ISAXContentHandler ISAXContentHandler_iface
;
62 VARIANT_BOOL props
[MXWriter_LastProp
];
68 xmlOutputBufferPtr buffer
;
71 static inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
73 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
76 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
78 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
81 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
83 mxwriter
*This
= impl_from_IMXWriter( iface
);
85 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
87 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
88 IsEqualGUID( riid
, &IID_IDispatch
) ||
89 IsEqualGUID( riid
, &IID_IUnknown
) )
91 *obj
= &This
->IMXWriter_iface
;
93 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
95 *obj
= &This
->ISAXContentHandler_iface
;
99 ERR("interface %s not implemented\n", debugstr_guid(riid
));
101 return E_NOINTERFACE
;
104 IMXWriter_AddRef(iface
);
108 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
110 mxwriter
*This
= impl_from_IMXWriter( iface
);
111 LONG ref
= InterlockedIncrement(&This
->ref
);
113 TRACE("(%p)->(%d)\n", This
, ref
);
118 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
120 mxwriter
*This
= impl_from_IMXWriter( iface
);
121 ULONG ref
= InterlockedDecrement(&This
->ref
);
123 TRACE("(%p)->(%d)\n", This
, ref
);
127 if (This
->dest
) IStream_Release(This
->dest
);
128 SysFreeString(This
->encoding
);
129 SysFreeString(This
->version
);
131 xmlOutputBufferClose(This
->buffer
);
138 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
140 mxwriter
*This
= impl_from_IMXWriter( iface
);
142 TRACE("(%p)->(%p)\n", This
, pctinfo
);
149 static HRESULT WINAPI
mxwriter_GetTypeInfo(
151 UINT iTInfo
, LCID lcid
,
152 ITypeInfo
** ppTInfo
)
154 mxwriter
*This
= impl_from_IMXWriter( iface
);
156 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
158 return get_typeinfo(IMXWriter_tid
, ppTInfo
);
161 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
163 REFIID riid
, LPOLESTR
* rgszNames
,
164 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
166 mxwriter
*This
= impl_from_IMXWriter( iface
);
170 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
173 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
176 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
179 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
180 ITypeInfo_Release(typeinfo
);
186 static HRESULT WINAPI
mxwriter_Invoke(
188 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
189 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
190 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
192 mxwriter
*This
= impl_from_IMXWriter( iface
);
196 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
197 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
199 hr
= get_typeinfo(IMXWriter_tid
, &typeinfo
);
202 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IMXWriter_iface
, dispIdMember
, wFlags
,
203 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
204 ITypeInfo_Release(typeinfo
);
210 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
212 mxwriter
*This
= impl_from_IMXWriter( iface
);
214 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
220 if (This
->dest
) IStream_Release(This
->dest
);
229 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
232 if (This
->dest
) IStream_Release(This
->dest
);
237 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
241 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
248 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
250 mxwriter
*This
= impl_from_IMXWriter( iface
);
252 TRACE("(%p)->(%p)\n", This
, dest
);
256 V_VT(dest
) = VT_BSTR
;
257 V_BSTR(dest
) = bstr_from_xmlChar(This
->buffer
->buffer
->content
);
262 FIXME("not implemented when stream is set up\n");
267 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
269 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
270 static const WCHAR utf8W
[] = {'U','T','F','-','8',0};
271 mxwriter
*This
= impl_from_IMXWriter( iface
);
273 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
275 /* FIXME: filter all supported encodings */
276 if (!strcmpW(encoding
, utf16W
) || !strcmpW(encoding
, utf8W
))
278 SysFreeString(This
->encoding
);
279 This
->encoding
= SysAllocString(encoding
);
284 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
289 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
291 mxwriter
*This
= impl_from_IMXWriter( iface
);
293 TRACE("(%p)->(%p)\n", This
, encoding
);
295 if (!encoding
) return E_POINTER
;
297 return return_bstr(This
->encoding
, encoding
);
300 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
302 mxwriter
*This
= impl_from_IMXWriter( iface
);
304 TRACE("(%p)->(%d)\n", This
, value
);
305 This
->props
[MXWriter_BOM
] = value
;
310 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
312 mxwriter
*This
= impl_from_IMXWriter( iface
);
314 TRACE("(%p)->(%p)\n", This
, value
);
316 if (!value
) return E_POINTER
;
318 *value
= This
->props
[MXWriter_BOM
];
323 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
325 mxwriter
*This
= impl_from_IMXWriter( iface
);
327 TRACE("(%p)->(%d)\n", This
, value
);
328 This
->props
[MXWriter_Indent
] = value
;
333 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
335 mxwriter
*This
= impl_from_IMXWriter( iface
);
337 TRACE("(%p)->(%p)\n", This
, value
);
339 if (!value
) return E_POINTER
;
341 *value
= This
->props
[MXWriter_Indent
];
346 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
348 mxwriter
*This
= impl_from_IMXWriter( iface
);
350 TRACE("(%p)->(%d)\n", This
, value
);
351 This
->props
[MXWriter_Standalone
] = value
;
356 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
358 mxwriter
*This
= impl_from_IMXWriter( iface
);
360 TRACE("(%p)->(%p)\n", This
, value
);
362 if (!value
) return E_POINTER
;
364 *value
= This
->props
[MXWriter_Standalone
];
369 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
371 mxwriter
*This
= impl_from_IMXWriter( iface
);
373 TRACE("(%p)->(%d)\n", This
, value
);
374 This
->props
[MXWriter_OmitXmlDecl
] = value
;
379 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
381 mxwriter
*This
= impl_from_IMXWriter( iface
);
383 TRACE("(%p)->(%p)\n", This
, value
);
385 if (!value
) return E_POINTER
;
387 *value
= This
->props
[MXWriter_OmitXmlDecl
];
392 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
394 mxwriter
*This
= impl_from_IMXWriter( iface
);
395 FIXME("(%p)->(%s)\n", This
, debugstr_w(version
));
399 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
401 mxwriter
*This
= impl_from_IMXWriter( iface
);
403 TRACE("(%p)->(%p)\n", This
, version
);
405 if (!version
) return E_POINTER
;
407 return return_bstr(This
->version
, version
);
410 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
412 mxwriter
*This
= impl_from_IMXWriter( iface
);
414 TRACE("(%p)->(%d)\n", This
, value
);
415 This
->props
[MXWriter_DisableEscaping
] = value
;
420 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
422 mxwriter
*This
= impl_from_IMXWriter( iface
);
424 TRACE("(%p)->(%p)\n", This
, value
);
426 if (!value
) return E_POINTER
;
428 *value
= This
->props
[MXWriter_DisableEscaping
];
433 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
435 mxwriter
*This
= impl_from_IMXWriter( iface
);
436 FIXME("(%p)\n", This
);
440 static const struct IMXWriterVtbl mxwriter_vtbl
=
442 mxwriter_QueryInterface
,
445 mxwriter_GetTypeInfoCount
,
446 mxwriter_GetTypeInfo
,
447 mxwriter_GetIDsOfNames
,
451 mxwriter_put_encoding
,
452 mxwriter_get_encoding
,
453 mxwriter_put_byteOrderMark
,
454 mxwriter_get_byteOrderMark
,
457 mxwriter_put_standalone
,
458 mxwriter_get_standalone
,
459 mxwriter_put_omitXMLDeclaration
,
460 mxwriter_get_omitXMLDeclaration
,
461 mxwriter_put_version
,
462 mxwriter_get_version
,
463 mxwriter_put_disableOutputEscaping
,
464 mxwriter_get_disableOutputEscaping
,
468 /*** ISAXContentHandler ***/
469 static HRESULT WINAPI
mxwriter_saxcontent_QueryInterface(
470 ISAXContentHandler
*iface
,
474 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
475 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
478 static ULONG WINAPI
mxwriter_saxcontent_AddRef(ISAXContentHandler
*iface
)
480 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
481 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
484 static ULONG WINAPI
mxwriter_saxcontent_Release(ISAXContentHandler
*iface
)
486 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
487 return IMXWriter_Release(&This
->IMXWriter_iface
);
490 static HRESULT WINAPI
mxwriter_saxcontent_putDocumentLocator(
491 ISAXContentHandler
*iface
,
492 ISAXLocator
*locator
)
494 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
495 FIXME("(%p)->(%p)\n", This
, locator
);
499 static HRESULT WINAPI
mxwriter_saxcontent_startDocument(ISAXContentHandler
*iface
)
501 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
504 TRACE("(%p)\n", This
);
506 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
509 xmlOutputBufferWriteString(This
->buffer
, "<?xml version=\"");
510 s
= xmlchar_from_wchar(This
->version
);
511 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
513 xmlOutputBufferWriteString(This
->buffer
, "\"");
516 xmlOutputBufferWriteString(This
->buffer
, " encoding=\"");
517 s
= xmlchar_from_wchar(This
->encoding
);
518 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
520 xmlOutputBufferWriteString(This
->buffer
, "\"");
523 xmlOutputBufferWriteString(This
->buffer
, " standalone=\"");
524 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
525 xmlOutputBufferWriteString(This
->buffer
, "yes\"?>");
527 xmlOutputBufferWriteString(This
->buffer
, "no\"?>");
529 xmlOutputBufferWriteString(This
->buffer
, crlfA
);
534 static HRESULT WINAPI
mxwriter_saxcontent_endDocument(ISAXContentHandler
*iface
)
536 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
537 FIXME("(%p)\n", This
);
541 static HRESULT WINAPI
mxwriter_saxcontent_startPrefixMapping(
542 ISAXContentHandler
*iface
,
548 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
549 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
553 static HRESULT WINAPI
mxwriter_saxcontent_endPrefixMapping(
554 ISAXContentHandler
*iface
,
558 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
559 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
563 static HRESULT WINAPI
mxwriter_saxcontent_startElement(
564 ISAXContentHandler
*iface
,
565 const WCHAR
*namespaceUri
,
567 const WCHAR
*local_name
,
571 ISAXAttributes
*attr
)
573 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
576 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
577 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
579 if (!namespaceUri
|| !local_name
|| !QName
) return E_INVALIDARG
;
581 xmlOutputBufferWriteString(This
->buffer
, "<");
582 s
= xmlchar_from_wchar(QName
);
583 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
592 hr
= ISAXAttributes_getLength(attr
, &length
);
593 if (FAILED(hr
)) return hr
;
595 if (length
) xmlOutputBufferWriteString(This
->buffer
, " ");
597 for (i
= 0; i
< length
; i
++)
602 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
603 if (FAILED(hr
)) return hr
;
605 s
= xmlchar_from_wchar(str
);
606 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
609 xmlOutputBufferWriteString(This
->buffer
, "=\"");
611 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
612 if (FAILED(hr
)) return hr
;
614 s
= xmlchar_from_wchar(str
);
615 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
618 xmlOutputBufferWriteString(This
->buffer
, "\"");
622 xmlOutputBufferWriteString(This
->buffer
, ">");
627 static HRESULT WINAPI
mxwriter_saxcontent_endElement(
628 ISAXContentHandler
*iface
,
629 const WCHAR
*namespaceUri
,
631 const WCHAR
* local_name
,
636 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
639 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
640 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
));
642 if (!namespaceUri
|| !local_name
|| !QName
) return E_INVALIDARG
;
644 xmlOutputBufferWriteString(This
->buffer
, "</");
645 s
= xmlchar_from_wchar(QName
);
646 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
648 xmlOutputBufferWriteString(This
->buffer
, ">");
653 static HRESULT WINAPI
mxwriter_saxcontent_characters(
654 ISAXContentHandler
*iface
,
658 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
660 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
662 if (!chars
) return E_INVALIDARG
;
666 xmlChar
*s
= xmlchar_from_wcharn(chars
, nchars
);
667 xmlOutputBufferWriteString(This
->buffer
, (char*)s
);
674 static HRESULT WINAPI
mxwriter_saxcontent_ignorableWhitespace(
675 ISAXContentHandler
*iface
,
679 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
680 FIXME("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
684 static HRESULT WINAPI
mxwriter_saxcontent_processingInstruction(
685 ISAXContentHandler
*iface
,
691 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
692 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
696 static HRESULT WINAPI
mxwriter_saxcontent_skippedEntity(
697 ISAXContentHandler
*iface
,
701 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
702 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
706 static const struct ISAXContentHandlerVtbl mxwriter_saxcontent_vtbl
=
708 mxwriter_saxcontent_QueryInterface
,
709 mxwriter_saxcontent_AddRef
,
710 mxwriter_saxcontent_Release
,
711 mxwriter_saxcontent_putDocumentLocator
,
712 mxwriter_saxcontent_startDocument
,
713 mxwriter_saxcontent_endDocument
,
714 mxwriter_saxcontent_startPrefixMapping
,
715 mxwriter_saxcontent_endPrefixMapping
,
716 mxwriter_saxcontent_startElement
,
717 mxwriter_saxcontent_endElement
,
718 mxwriter_saxcontent_characters
,
719 mxwriter_saxcontent_ignorableWhitespace
,
720 mxwriter_saxcontent_processingInstruction
,
721 mxwriter_saxcontent_skippedEntity
724 HRESULT
MXWriter_create(IUnknown
*pUnkOuter
, void **ppObj
)
726 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
727 static const WCHAR version10W
[] = {'1','.','0',0};
730 TRACE("(%p,%p)\n", pUnkOuter
, ppObj
);
732 if (pUnkOuter
) FIXME("support aggregation, outer\n");
734 This
= heap_alloc( sizeof (*This
) );
736 return E_OUTOFMEMORY
;
738 This
->IMXWriter_iface
.lpVtbl
= &mxwriter_vtbl
;
739 This
->ISAXContentHandler_iface
.lpVtbl
= &mxwriter_saxcontent_vtbl
;
742 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
743 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
744 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
745 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
746 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
747 This
->encoding
= SysAllocString(utf16W
);
748 This
->version
= SysAllocString(version10W
);
752 /* set up a buffer, default encoding is UTF-16 */
753 This
->buffer
= xmlAllocOutputBuffer(xmlFindCharEncodingHandler("UTF-16"));
755 *ppObj
= &This
->IMXWriter_iface
;
757 TRACE("returning iface %p\n", *ppObj
);
764 HRESULT
MXWriter_create(IUnknown
*pUnkOuter
, void **obj
)
766 MESSAGE("This program tried to use a MXXMLWriter object, but\n"
767 "libxml2 support was not present at compile time.\n");
771 #endif /* HAVE_LIBXML2 */