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 */