2 * IXmlWriter implementation
4 * Copyright 2011 Alistair Leslie-Hughes
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
27 #include "xmllite_private.h"
30 #include "wine/debug.h"
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(xmllite
);
35 /* not defined in public headers */
36 DEFINE_GUID(IID_IXmlWriterOutput
, 0xc1131708, 0x0f59, 0x477f, 0x93, 0x59, 0x7d, 0x33, 0x24, 0x51, 0xbc, 0x1a);
38 static const WCHAR closepiW
[] = {'?','>'};
43 unsigned int allocated
;
50 XmlWriterState_Initial
, /* output is not set yet */
51 XmlWriterState_Ready
, /* SetOutput() was called, ready to start */
52 XmlWriterState_PIDocStarted
, /* document was started with manually added 'xml' PI */
53 XmlWriterState_DocStarted
/* document was started with WriteStartDocument() */
58 IXmlWriterOutput IXmlWriterOutput_iface
;
61 ISequentialStream
*stream
;
63 xml_encoding encoding
;
64 struct output_buffer buffer
;
67 static const struct IUnknownVtbl xmlwriteroutputvtbl
;
69 typedef struct _xmlwriter
71 IXmlWriter IXmlWriter_iface
;
74 xmlwriteroutput
*output
;
78 XmlConformanceLevel conformance
;
82 static inline xmlwriter
*impl_from_IXmlWriter(IXmlWriter
*iface
)
84 return CONTAINING_RECORD(iface
, xmlwriter
, IXmlWriter_iface
);
87 static inline xmlwriteroutput
*impl_from_IXmlWriterOutput(IXmlWriterOutput
*iface
)
89 return CONTAINING_RECORD(iface
, xmlwriteroutput
, IXmlWriterOutput_iface
);
92 static const char *debugstr_writer_prop(XmlWriterProperty prop
)
94 static const char * const prop_names
[] =
103 if (prop
> _XmlWriterProperty_Last
)
104 return wine_dbg_sprintf("unknown property=%d", prop
);
106 return prop_names
[prop
];
109 /* writer output memory allocation functions */
110 static inline void *writeroutput_alloc(xmlwriteroutput
*output
, size_t len
)
112 return m_alloc(output
->imalloc
, len
);
115 static inline void writeroutput_free(xmlwriteroutput
*output
, void *mem
)
117 m_free(output
->imalloc
, mem
);
120 static inline void *writeroutput_realloc(xmlwriteroutput
*output
, void *mem
, size_t len
)
122 return m_realloc(output
->imalloc
, mem
, len
);
125 /* writer memory allocation functions */
126 static inline void *writer_alloc(xmlwriter
*writer
, size_t len
)
128 return m_alloc(writer
->imalloc
, len
);
131 static inline void writer_free(xmlwriter
*writer
, void *mem
)
133 m_free(writer
->imalloc
, mem
);
136 static HRESULT
init_output_buffer(xmlwriteroutput
*output
)
138 struct output_buffer
*buffer
= &output
->buffer
;
139 const int initial_len
= 0x2000;
143 hr
= get_code_page(output
->encoding
, &cp
);
144 if (FAILED(hr
)) return hr
;
146 buffer
->data
= writeroutput_alloc(output
, initial_len
);
147 if (!buffer
->data
) return E_OUTOFMEMORY
;
149 memset(buffer
->data
, 0, 4);
150 buffer
->allocated
= initial_len
;
152 buffer
->codepage
= cp
;
157 static void free_output_buffer(xmlwriteroutput
*output
)
159 struct output_buffer
*buffer
= &output
->buffer
;
160 writeroutput_free(output
, buffer
->data
);
162 buffer
->allocated
= 0;
166 static HRESULT
grow_output_buffer(xmlwriteroutput
*output
, int length
)
168 struct output_buffer
*buffer
= &output
->buffer
;
169 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
170 if (buffer
->allocated
< buffer
->written
+ length
+ 4) {
171 int grown_size
= max(2*buffer
->allocated
, buffer
->allocated
+ length
);
172 char *ptr
= writeroutput_realloc(output
, buffer
->data
, grown_size
);
173 if (!ptr
) return E_OUTOFMEMORY
;
175 buffer
->allocated
= grown_size
;
181 static HRESULT
write_output_buffer(xmlwriteroutput
*output
, const WCHAR
*data
, int len
)
183 struct output_buffer
*buffer
= &output
->buffer
;
188 if (buffer
->codepage
!= ~0) {
189 length
= WideCharToMultiByte(buffer
->codepage
, 0, data
, len
, NULL
, 0, NULL
, NULL
);
190 hr
= grow_output_buffer(output
, length
);
191 if (FAILED(hr
)) return hr
;
192 ptr
= buffer
->data
+ buffer
->written
;
193 length
= WideCharToMultiByte(buffer
->codepage
, 0, data
, len
, ptr
, length
, NULL
, NULL
);
194 buffer
->written
+= len
== -1 ? length
-1 : length
;
197 /* WCHAR data just copied */
198 length
= len
== -1 ? strlenW(data
) : len
;
200 length
*= sizeof(WCHAR
);
202 hr
= grow_output_buffer(output
, length
);
203 if (FAILED(hr
)) return hr
;
204 ptr
= buffer
->data
+ buffer
->written
;
206 memcpy(ptr
, data
, length
);
207 buffer
->written
+= length
;
209 /* null termination */
217 static HRESULT
write_output_buffer_quoted(xmlwriteroutput
*output
, const WCHAR
*data
, int len
)
219 static const WCHAR quotW
[] = {'"'};
220 write_output_buffer(output
, quotW
, 1);
221 write_output_buffer(output
, data
, len
);
222 write_output_buffer(output
, quotW
, 1);
226 static void writeroutput_release_stream(xmlwriteroutput
*writeroutput
)
228 if (writeroutput
->stream
) {
229 ISequentialStream_Release(writeroutput
->stream
);
230 writeroutput
->stream
= NULL
;
234 static inline HRESULT
writeroutput_query_for_stream(xmlwriteroutput
*writeroutput
)
238 writeroutput_release_stream(writeroutput
);
239 hr
= IUnknown_QueryInterface(writeroutput
->output
, &IID_IStream
, (void**)&writeroutput
->stream
);
241 hr
= IUnknown_QueryInterface(writeroutput
->output
, &IID_ISequentialStream
, (void**)&writeroutput
->stream
);
246 static HRESULT WINAPI
xmlwriter_QueryInterface(IXmlWriter
*iface
, REFIID riid
, void **ppvObject
)
248 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
250 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
252 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
253 IsEqualGUID(riid
, &IID_IXmlWriter
))
258 IXmlWriter_AddRef(iface
);
263 static ULONG WINAPI
xmlwriter_AddRef(IXmlWriter
*iface
)
265 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
267 return InterlockedIncrement(&This
->ref
);
270 static ULONG WINAPI
xmlwriter_Release(IXmlWriter
*iface
)
272 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
277 ref
= InterlockedDecrement(&This
->ref
);
279 IMalloc
*imalloc
= This
->imalloc
;
280 if (This
->output
) IUnknown_Release(&This
->output
->IXmlWriterOutput_iface
);
281 writer_free(This
, This
);
282 if (imalloc
) IMalloc_Release(imalloc
);
288 /*** IXmlWriter methods ***/
289 static HRESULT WINAPI
xmlwriter_SetOutput(IXmlWriter
*iface
, IUnknown
*output
)
291 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
292 IXmlWriterOutput
*writeroutput
;
295 TRACE("(%p)->(%p)\n", This
, output
);
298 writeroutput_release_stream(This
->output
);
299 IUnknown_Release(&This
->output
->IXmlWriterOutput_iface
);
303 /* just reset current output */
305 This
->state
= XmlWriterState_Initial
;
309 /* now try IXmlWriterOutput, ISequentialStream, IStream */
310 hr
= IUnknown_QueryInterface(output
, &IID_IXmlWriterOutput
, (void**)&writeroutput
);
312 if (writeroutput
->lpVtbl
== &xmlwriteroutputvtbl
)
313 This
->output
= impl_from_IXmlWriterOutput(writeroutput
);
315 ERR("got external IXmlWriterOutput implementation: %p, vtbl=%p\n",
316 writeroutput
, writeroutput
->lpVtbl
);
317 IUnknown_Release(writeroutput
);
323 if (hr
!= S_OK
|| !writeroutput
) {
324 /* create IXmlWriterOutput basing on supplied interface */
325 hr
= CreateXmlWriterOutputWithEncodingName(output
, This
->imalloc
, NULL
, &writeroutput
);
326 if (hr
!= S_OK
) return hr
;
327 This
->output
= impl_from_IXmlWriterOutput(writeroutput
);
330 This
->state
= XmlWriterState_Ready
;
331 return writeroutput_query_for_stream(This
->output
);
334 static HRESULT WINAPI
xmlwriter_GetProperty(IXmlWriter
*iface
, UINT property
, LONG_PTR
*value
)
336 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
338 TRACE("(%p)->(%s %p)\n", This
, debugstr_writer_prop(property
), value
);
340 if (!value
) return E_INVALIDARG
;
344 case XmlWriterProperty_Indent
:
345 *value
= This
->indent
;
347 case XmlWriterProperty_ByteOrderMark
:
350 case XmlWriterProperty_OmitXmlDeclaration
:
351 *value
= This
->omitxmldecl
;
353 case XmlWriterProperty_ConformanceLevel
:
354 *value
= This
->conformance
;
357 FIXME("Unimplemented property (%u)\n", property
);
364 static HRESULT WINAPI
xmlwriter_SetProperty(IXmlWriter
*iface
, UINT nProperty
, LONG_PTR pValue
)
366 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
368 FIXME("%p %u %lu\n", This
, nProperty
, pValue
);
373 static HRESULT WINAPI
xmlwriter_WriteAttributes(IXmlWriter
*iface
, IXmlReader
*pReader
,
374 BOOL fWriteDefaultAttributes
)
376 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
378 FIXME("%p %p %d\n", This
, pReader
, fWriteDefaultAttributes
);
383 static HRESULT WINAPI
xmlwriter_WriteAttributeString(IXmlWriter
*iface
, LPCWSTR pwszPrefix
,
384 LPCWSTR pwszLocalName
, LPCWSTR pwszNamespaceUri
,
387 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
389 FIXME("%p %s %s %s %s\n", This
, wine_dbgstr_w(pwszPrefix
), wine_dbgstr_w(pwszLocalName
),
390 wine_dbgstr_w(pwszNamespaceUri
), wine_dbgstr_w(pwszValue
));
395 static HRESULT WINAPI
xmlwriter_WriteCData(IXmlWriter
*iface
, LPCWSTR pwszText
)
397 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
399 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszText
));
404 static HRESULT WINAPI
xmlwriter_WriteCharEntity(IXmlWriter
*iface
, WCHAR wch
)
409 static HRESULT WINAPI
xmlwriter_WriteChars(IXmlWriter
*iface
, const WCHAR
*pwch
, UINT cwch
)
411 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
413 FIXME("%p %s %d\n", This
, wine_dbgstr_w(pwch
), cwch
);
418 static HRESULT WINAPI
xmlwriter_WriteComment(IXmlWriter
*iface
, LPCWSTR pwszComment
)
423 static HRESULT WINAPI
xmlwriter_WriteDocType(IXmlWriter
*iface
, LPCWSTR pwszName
, LPCWSTR pwszPublicId
,
424 LPCWSTR pwszSystemId
, LPCWSTR pwszSubset
)
426 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
428 FIXME("%p %s %s %s %s\n", This
, wine_dbgstr_w(pwszName
), wine_dbgstr_w(pwszPublicId
),
429 wine_dbgstr_w(pwszSystemId
), wine_dbgstr_w(pwszSubset
));
434 static HRESULT WINAPI
xmlwriter_WriteElementString(IXmlWriter
*iface
, LPCWSTR pwszPrefix
,
435 LPCWSTR pwszLocalName
, LPCWSTR pwszNamespaceUri
,
438 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
440 FIXME("%p %s %s %s %s\n", This
, wine_dbgstr_w(pwszPrefix
), wine_dbgstr_w(pwszLocalName
),
441 wine_dbgstr_w(pwszNamespaceUri
), wine_dbgstr_w(pwszValue
));
446 static HRESULT WINAPI
xmlwriter_WriteEndDocument(IXmlWriter
*iface
)
448 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
455 static HRESULT WINAPI
xmlwriter_WriteEndElement(IXmlWriter
*iface
)
457 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
464 static HRESULT WINAPI
xmlwriter_WriteEntityRef(IXmlWriter
*iface
, LPCWSTR pwszName
)
466 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
468 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszName
));
473 static HRESULT WINAPI
xmlwriter_WriteFullEndElement(IXmlWriter
*iface
)
475 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
482 static HRESULT WINAPI
xmlwriter_WriteName(IXmlWriter
*iface
, LPCWSTR pwszName
)
484 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
486 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszName
));
491 static HRESULT WINAPI
xmlwriter_WriteNmToken(IXmlWriter
*iface
, LPCWSTR pwszNmToken
)
493 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
495 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszNmToken
));
500 static HRESULT WINAPI
xmlwriter_WriteNode(IXmlWriter
*iface
, IXmlReader
*pReader
,
501 BOOL fWriteDefaultAttributes
)
503 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
505 FIXME("%p %p %d\n", This
, pReader
, fWriteDefaultAttributes
);
510 static HRESULT WINAPI
xmlwriter_WriteNodeShallow(IXmlWriter
*iface
, IXmlReader
*pReader
,
511 BOOL fWriteDefaultAttributes
)
513 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
515 FIXME("%p %p %d\n", This
, pReader
, fWriteDefaultAttributes
);
520 static HRESULT WINAPI
xmlwriter_WriteProcessingInstruction(IXmlWriter
*iface
, LPCWSTR name
,
523 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
524 static const WCHAR xmlW
[] = {'x','m','l',0};
525 static const WCHAR openpiW
[] = {'<','?'};
526 static const WCHAR spaceW
[] = {' '};
528 TRACE("(%p)->(%s %s)\n", This
, wine_dbgstr_w(name
), wine_dbgstr_w(text
));
530 if (This
->state
== XmlWriterState_Initial
)
533 if (This
->state
== XmlWriterState_DocStarted
&& !strcmpW(name
, xmlW
))
534 return WR_E_INVALIDACTION
;
536 write_output_buffer(This
->output
, openpiW
, sizeof(openpiW
)/sizeof(WCHAR
));
537 write_output_buffer(This
->output
, name
, -1);
538 write_output_buffer(This
->output
, spaceW
, 1);
539 write_output_buffer(This
->output
, text
, -1);
540 write_output_buffer(This
->output
, closepiW
, sizeof(closepiW
)/sizeof(WCHAR
));
542 if (!strcmpW(name
, xmlW
))
543 This
->state
= XmlWriterState_PIDocStarted
;
548 static HRESULT WINAPI
xmlwriter_WriteQualifiedName(IXmlWriter
*iface
, LPCWSTR pwszLocalName
,
549 LPCWSTR pwszNamespaceUri
)
551 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
553 FIXME("%p %s %s\n", This
, wine_dbgstr_w(pwszLocalName
), wine_dbgstr_w(pwszNamespaceUri
));
558 static HRESULT WINAPI
xmlwriter_WriteRaw(IXmlWriter
*iface
, LPCWSTR pwszData
)
560 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
562 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszData
));
567 static HRESULT WINAPI
xmlwriter_WriteRawChars(IXmlWriter
*iface
, const WCHAR
*pwch
, UINT cwch
)
569 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
571 FIXME("%p %s %d\n", This
, wine_dbgstr_w(pwch
), cwch
);
576 static HRESULT WINAPI
xmlwriter_WriteStartDocument(IXmlWriter
*iface
, XmlStandalone standalone
)
578 static const WCHAR versionW
[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','=','"','1','.','0','"'};
579 static const WCHAR encodingW
[] = {' ','e','n','c','o','d','i','n','g','='};
580 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
582 TRACE("(%p)->(%d)\n", This
, standalone
);
586 case XmlWriterState_Initial
:
588 case XmlWriterState_PIDocStarted
:
589 This
->state
= XmlWriterState_DocStarted
;
591 case XmlWriterState_DocStarted
:
592 return WR_E_INVALIDACTION
;
598 write_output_buffer(This
->output
, versionW
, sizeof(versionW
)/sizeof(WCHAR
));
601 write_output_buffer(This
->output
, encodingW
, sizeof(encodingW
)/sizeof(WCHAR
));
602 write_output_buffer_quoted(This
->output
, get_encoding_name(This
->output
->encoding
), -1);
605 if (standalone
== XmlStandalone_Omit
)
606 write_output_buffer(This
->output
, closepiW
, sizeof(closepiW
)/sizeof(WCHAR
));
608 static const WCHAR standaloneW
[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
609 static const WCHAR yesW
[] = {'y','e','s','\"','?','>'};
610 static const WCHAR noW
[] = {'n','o','\"','?','>'};
612 write_output_buffer(This
->output
, standaloneW
, sizeof(standaloneW
)/sizeof(WCHAR
));
613 if (standalone
== XmlStandalone_Yes
)
614 write_output_buffer(This
->output
, yesW
, sizeof(yesW
)/sizeof(WCHAR
));
616 write_output_buffer(This
->output
, noW
, sizeof(noW
)/sizeof(WCHAR
));
619 This
->state
= XmlWriterState_DocStarted
;
623 static HRESULT WINAPI
xmlwriter_WriteStartElement(IXmlWriter
*iface
, LPCWSTR pwszPrefix
,
624 LPCWSTR pwszLocalName
, LPCWSTR pwszNamespaceUri
)
626 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
628 FIXME("%p %s %s %s\n", This
, wine_dbgstr_w(pwszPrefix
), wine_dbgstr_w(pwszLocalName
),
629 wine_dbgstr_w(pwszNamespaceUri
));
634 static HRESULT WINAPI
xmlwriter_WriteString(IXmlWriter
*iface
, LPCWSTR pwszText
)
636 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
638 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszText
));
643 static HRESULT WINAPI
xmlwriter_WriteSurrogateCharEntity(IXmlWriter
*iface
, WCHAR wchLow
, WCHAR wchHigh
)
645 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
647 FIXME("%p %d %d\n", This
, wchLow
, wchHigh
);
652 static HRESULT WINAPI
xmlwriter_WriteWhitespace(IXmlWriter
*iface
, LPCWSTR pwszWhitespace
)
654 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
656 FIXME("%p %s\n", This
, wine_dbgstr_w(pwszWhitespace
));
661 static HRESULT WINAPI
xmlwriter_Flush(IXmlWriter
*iface
)
663 xmlwriter
*This
= impl_from_IXmlWriter(iface
);
670 static const struct IXmlWriterVtbl xmlwriter_vtbl
=
672 xmlwriter_QueryInterface
,
676 xmlwriter_GetProperty
,
677 xmlwriter_SetProperty
,
678 xmlwriter_WriteAttributes
,
679 xmlwriter_WriteAttributeString
,
680 xmlwriter_WriteCData
,
681 xmlwriter_WriteCharEntity
,
682 xmlwriter_WriteChars
,
683 xmlwriter_WriteComment
,
684 xmlwriter_WriteDocType
,
685 xmlwriter_WriteElementString
,
686 xmlwriter_WriteEndDocument
,
687 xmlwriter_WriteEndElement
,
688 xmlwriter_WriteEntityRef
,
689 xmlwriter_WriteFullEndElement
,
691 xmlwriter_WriteNmToken
,
693 xmlwriter_WriteNodeShallow
,
694 xmlwriter_WriteProcessingInstruction
,
695 xmlwriter_WriteQualifiedName
,
697 xmlwriter_WriteRawChars
,
698 xmlwriter_WriteStartDocument
,
699 xmlwriter_WriteStartElement
,
700 xmlwriter_WriteString
,
701 xmlwriter_WriteSurrogateCharEntity
,
702 xmlwriter_WriteWhitespace
,
706 /** IXmlWriterOutput **/
707 static HRESULT WINAPI
xmlwriteroutput_QueryInterface(IXmlWriterOutput
*iface
, REFIID riid
, void** ppvObject
)
709 xmlwriteroutput
*This
= impl_from_IXmlWriterOutput(iface
);
711 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObject
);
713 if (IsEqualGUID(riid
, &IID_IXmlWriterOutput
) ||
714 IsEqualGUID(riid
, &IID_IUnknown
))
720 WARN("interface %s not implemented\n", debugstr_guid(riid
));
722 return E_NOINTERFACE
;
725 IUnknown_AddRef(iface
);
730 static ULONG WINAPI
xmlwriteroutput_AddRef(IXmlWriterOutput
*iface
)
732 xmlwriteroutput
*This
= impl_from_IXmlWriterOutput(iface
);
733 ULONG ref
= InterlockedIncrement(&This
->ref
);
734 TRACE("(%p)->(%d)\n", This
, ref
);
738 static ULONG WINAPI
xmlwriteroutput_Release(IXmlWriterOutput
*iface
)
740 xmlwriteroutput
*This
= impl_from_IXmlWriterOutput(iface
);
741 LONG ref
= InterlockedDecrement(&This
->ref
);
743 TRACE("(%p)->(%d)\n", This
, ref
);
747 IMalloc
*imalloc
= This
->imalloc
;
748 if (This
->output
) IUnknown_Release(This
->output
);
749 if (This
->stream
) ISequentialStream_Release(This
->stream
);
750 free_output_buffer(This
);
751 writeroutput_free(This
, This
);
752 if (imalloc
) IMalloc_Release(imalloc
);
758 static const struct IUnknownVtbl xmlwriteroutputvtbl
=
760 xmlwriteroutput_QueryInterface
,
761 xmlwriteroutput_AddRef
,
762 xmlwriteroutput_Release
765 HRESULT WINAPI
CreateXmlWriter(REFIID riid
, void **obj
, IMalloc
*imalloc
)
769 TRACE("(%s, %p, %p)\n", wine_dbgstr_guid(riid
), obj
, imalloc
);
771 if (!IsEqualGUID(riid
, &IID_IXmlWriter
))
773 ERR("Unexpected IID requested -> (%s)\n", wine_dbgstr_guid(riid
));
778 writer
= IMalloc_Alloc(imalloc
, sizeof(*writer
));
780 writer
= heap_alloc(sizeof(*writer
));
781 if(!writer
) return E_OUTOFMEMORY
;
783 writer
->IXmlWriter_iface
.lpVtbl
= &xmlwriter_vtbl
;
785 writer
->imalloc
= imalloc
;
786 if (imalloc
) IMalloc_AddRef(imalloc
);
787 writer
->output
= NULL
;
788 writer
->indent
= FALSE
;
790 writer
->omitxmldecl
= FALSE
;
791 writer
->conformance
= XmlConformanceLevel_Document
;
792 writer
->state
= XmlWriterState_Initial
;
794 *obj
= &writer
->IXmlWriter_iface
;
796 TRACE("returning iface %p\n", *obj
);
801 HRESULT WINAPI
CreateXmlWriterOutputWithEncodingName(IUnknown
*stream
,
804 IXmlWriterOutput
**output
)
806 static const WCHAR utf8W
[] = {'U','T','F','-','8',0};
807 xmlwriteroutput
*writeroutput
;
810 TRACE("%p %p %s %p\n", stream
, imalloc
, debugstr_w(encoding
), output
);
812 if (!stream
|| !output
) return E_INVALIDARG
;
817 writeroutput
= IMalloc_Alloc(imalloc
, sizeof(*writeroutput
));
819 writeroutput
= heap_alloc(sizeof(*writeroutput
));
820 if(!writeroutput
) return E_OUTOFMEMORY
;
822 writeroutput
->IXmlWriterOutput_iface
.lpVtbl
= &xmlwriteroutputvtbl
;
823 writeroutput
->ref
= 1;
824 writeroutput
->imalloc
= imalloc
;
825 if (imalloc
) IMalloc_AddRef(imalloc
);
826 writeroutput
->encoding
= parse_encoding_name(encoding
? encoding
: utf8W
, -1);
827 writeroutput
->stream
= NULL
;
828 hr
= init_output_buffer(writeroutput
);
830 IUnknown_Release(&writeroutput
->IXmlWriterOutput_iface
);
834 IUnknown_QueryInterface(stream
, &IID_IUnknown
, (void**)&writeroutput
->output
);
836 *output
= &writeroutput
->IXmlWriterOutput_iface
;
838 TRACE("returning iface %p\n", *output
);