msxml3: Added stub support for ISAXDTDHandler/IVBSAXDTDHandler for MXWriter.
[wine/multimedia.git] / dlls / msxml3 / mxwriter.c
blob12de67352fdcab0a983c248cfb9fa091faa3bad2
1 /*
2 * MXWriter implementation
4 * Copyright 2011-2014 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
22 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "ole2.h"
34 #include "msxml6.h"
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42 static const WCHAR emptyW[] = {0};
43 static const WCHAR spaceW[] = {' '};
44 static const WCHAR quotW[] = {'\"'};
45 static const WCHAR closetagW[] = {'>','\r','\n'};
46 static const WCHAR crlfW[] = {'\r','\n'};
47 static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
49 /* should be ordered as encoding names are sorted */
50 typedef enum
52 XmlEncoding_ISO_8859_1 = 0,
53 XmlEncoding_ISO_8859_13,
54 XmlEncoding_ISO_8859_15,
55 XmlEncoding_ISO_8859_2,
56 XmlEncoding_ISO_8859_3,
57 XmlEncoding_ISO_8859_4,
58 XmlEncoding_ISO_8859_5,
59 XmlEncoding_ISO_8859_7,
60 XmlEncoding_ISO_8859_9,
61 XmlEncoding_UTF16,
62 XmlEncoding_UTF8,
63 XmlEncoding_Unknown
64 } xml_encoding;
66 struct xml_encoding_data
68 const WCHAR *encoding;
69 xml_encoding enc;
70 UINT cp;
73 static const WCHAR iso_8859_1W[] = {'i','s','o','-','8','8','5','9','-','1',0};
74 static const WCHAR iso_8859_2W[] = {'i','s','o','-','8','8','5','9','-','2',0};
75 static const WCHAR iso_8859_3W[] = {'i','s','o','-','8','8','5','9','-','3',0};
76 static const WCHAR iso_8859_4W[] = {'i','s','o','-','8','8','5','9','-','4',0};
77 static const WCHAR iso_8859_5W[] = {'i','s','o','-','8','8','5','9','-','5',0};
78 static const WCHAR iso_8859_7W[] = {'i','s','o','-','8','8','5','9','-','7',0};
79 static const WCHAR iso_8859_9W[] = {'i','s','o','-','8','8','5','9','-','9',0};
80 static const WCHAR iso_8859_13W[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
81 static const WCHAR iso_8859_15W[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
82 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
83 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
85 static const struct xml_encoding_data xml_encoding_map[] = {
86 { iso_8859_1W, XmlEncoding_ISO_8859_1, 28591 },
87 { iso_8859_13W, XmlEncoding_ISO_8859_13, 28603 },
88 { iso_8859_15W, XmlEncoding_ISO_8859_15, 28605 },
89 { iso_8859_2W, XmlEncoding_ISO_8859_2, 28592 },
90 { iso_8859_3W, XmlEncoding_ISO_8859_3, 28593 },
91 { iso_8859_4W, XmlEncoding_ISO_8859_4, 28594 },
92 { iso_8859_5W, XmlEncoding_ISO_8859_5, 28595 },
93 { iso_8859_7W, XmlEncoding_ISO_8859_7, 28597 },
94 { iso_8859_9W, XmlEncoding_ISO_8859_9, 28599 },
95 { utf16W, XmlEncoding_UTF16, ~0 },
96 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
99 typedef enum
101 OutputBuffer_Native = 0x001,
102 OutputBuffer_Encoded = 0x010,
103 OutputBuffer_Both = 0x100
104 } output_mode;
106 typedef enum
108 MXWriter_BOM = 0,
109 MXWriter_DisableEscaping,
110 MXWriter_Indent,
111 MXWriter_OmitXmlDecl,
112 MXWriter_Standalone,
113 MXWriter_LastProp
114 } mxwriter_prop;
116 typedef enum
118 EscapeValue,
119 EscapeText
120 } escape_mode;
122 typedef struct
124 char *data;
125 unsigned int allocated;
126 unsigned int written;
127 } encoded_buffer;
129 typedef struct
131 encoded_buffer utf16;
132 encoded_buffer encoded;
133 UINT code_page;
134 } output_buffer;
136 typedef struct
138 DispatchEx dispex;
139 IMXWriter IMXWriter_iface;
140 ISAXContentHandler ISAXContentHandler_iface;
141 ISAXLexicalHandler ISAXLexicalHandler_iface;
142 ISAXDeclHandler ISAXDeclHandler_iface;
143 ISAXDTDHandler ISAXDTDHandler_iface;
144 IVBSAXDeclHandler IVBSAXDeclHandler_iface;
145 IVBSAXLexicalHandler IVBSAXLexicalHandler_iface;
146 IVBSAXContentHandler IVBSAXContentHandler_iface;
147 IVBSAXDTDHandler IVBSAXDTDHandler_iface;
149 LONG ref;
150 MSXML_VERSION class_version;
152 VARIANT_BOOL props[MXWriter_LastProp];
153 BOOL prop_changed;
154 BOOL cdata;
156 BOOL text; /* last node was text node, so we shouldn't indent next node */
157 BOOL newline; /* newline was already added as a part of previous call */
158 UINT indent; /* indentation level for next node */
160 BSTR version;
162 BSTR encoding; /* exact property value */
163 xml_encoding xml_enc;
165 /* contains a pending (or not closed yet) element name or NULL if
166 we don't have to close */
167 BSTR element;
169 IStream *dest;
170 ULONG dest_written;
172 output_buffer *buffer;
173 } mxwriter;
175 typedef struct
177 BSTR qname;
178 BSTR local;
179 BSTR uri;
180 BSTR type;
181 BSTR value;
182 } mxattribute;
184 typedef struct
186 DispatchEx dispex;
187 IMXAttributes IMXAttributes_iface;
188 ISAXAttributes ISAXAttributes_iface;
189 IVBSAXAttributes IVBSAXAttributes_iface;
190 LONG ref;
192 MSXML_VERSION class_version;
194 mxattribute *attr;
195 int length;
196 int allocated;
197 } mxattributes;
199 static inline mxattributes *impl_from_IMXAttributes( IMXAttributes *iface )
201 return CONTAINING_RECORD(iface, mxattributes, IMXAttributes_iface);
204 static inline mxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
206 return CONTAINING_RECORD(iface, mxattributes, ISAXAttributes_iface);
209 static inline mxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
211 return CONTAINING_RECORD(iface, mxattributes, IVBSAXAttributes_iface);
214 static HRESULT mxattributes_grow(mxattributes *This)
216 if (This->length < This->allocated) return S_OK;
218 This->allocated *= 2;
219 This->attr = heap_realloc(This->attr, This->allocated*sizeof(mxattribute));
221 return This->attr ? S_OK : E_OUTOFMEMORY;
224 static xml_encoding parse_encoding_name(const WCHAR *encoding)
226 int min, max, n, c;
228 min = 0;
229 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
231 while (min <= max)
233 n = (min+max)/2;
235 c = strcmpiW(xml_encoding_map[n].encoding, encoding);
236 if (!c)
237 return xml_encoding_map[n].enc;
239 if (c > 0)
240 max = n-1;
241 else
242 min = n+1;
245 return XmlEncoding_Unknown;
248 static HRESULT init_encoded_buffer(encoded_buffer *buffer)
250 const int initial_len = 0x2000;
251 buffer->data = heap_alloc(initial_len);
252 if (!buffer->data) return E_OUTOFMEMORY;
254 memset(buffer->data, 0, 4);
255 buffer->allocated = initial_len;
256 buffer->written = 0;
258 return S_OK;
261 static void free_encoded_buffer(encoded_buffer *buffer)
263 heap_free(buffer->data);
266 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
268 const struct xml_encoding_data *data;
270 if (encoding == XmlEncoding_Unknown)
272 FIXME("unsupported encoding %d\n", encoding);
273 return E_NOTIMPL;
276 data = &xml_encoding_map[encoding];
277 *cp = data->cp;
279 return S_OK;
282 static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer)
284 output_buffer *ret;
285 HRESULT hr;
287 ret = heap_alloc(sizeof(*ret));
288 if (!ret) return E_OUTOFMEMORY;
290 hr = get_code_page(encoding, &ret->code_page);
291 if (hr != S_OK) {
292 heap_free(ret);
293 return hr;
296 hr = init_encoded_buffer(&ret->utf16);
297 if (hr != S_OK) {
298 heap_free(ret);
299 return hr;
302 /* currently we always create a default output buffer that is UTF-16 only,
303 but it's possible to allocate with specific encoding too */
304 if (encoding != XmlEncoding_UTF16) {
305 hr = init_encoded_buffer(&ret->encoded);
306 if (hr != S_OK) {
307 free_encoded_buffer(&ret->utf16);
308 heap_free(ret);
309 return hr;
312 else
313 memset(&ret->encoded, 0, sizeof(ret->encoded));
315 *buffer = ret;
317 return S_OK;
320 static void free_output_buffer(output_buffer *buffer)
322 free_encoded_buffer(&buffer->encoded);
323 free_encoded_buffer(&buffer->utf16);
324 heap_free(buffer);
327 static void grow_buffer(encoded_buffer *buffer, int length)
329 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
330 if (buffer->allocated < buffer->written + length + 4)
332 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
333 buffer->data = heap_realloc(buffer->data, grown_size);
334 buffer->allocated = grown_size;
338 static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
340 int length;
341 char *ptr;
343 if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
344 if (buffer->code_page != ~0)
346 length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
347 grow_buffer(&buffer->encoded, length);
348 ptr = buffer->encoded.data + buffer->encoded.written;
349 length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
350 buffer->encoded.written += len == -1 ? length-1 : length;
354 if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
355 /* WCHAR data just copied */
356 length = len == -1 ? strlenW(data) : len;
357 if (length)
359 length *= sizeof(WCHAR);
361 grow_buffer(&buffer->utf16, length);
362 ptr = buffer->utf16.data + buffer->utf16.written;
364 memcpy(ptr, data, length);
365 buffer->utf16.written += length;
366 ptr += length;
367 /* null termination */
368 memset(ptr, 0, sizeof(WCHAR));
372 return S_OK;
375 static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
377 return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
380 static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
382 write_output_buffer(buffer, quotW, 1);
383 write_output_buffer(buffer, data, len);
384 write_output_buffer(buffer, quotW, 1);
386 return S_OK;
389 /* frees buffer data, reallocates with a default lengths */
390 static void close_output_buffer(mxwriter *This)
392 heap_free(This->buffer->utf16.data);
393 heap_free(This->buffer->encoded.data);
394 init_encoded_buffer(&This->buffer->utf16);
395 init_encoded_buffer(&This->buffer->encoded);
396 get_code_page(This->xml_enc, &This->buffer->code_page);
399 /* escapes special characters like:
400 '<' -> "&lt;"
401 '&' -> "&amp;"
402 '"' -> "&quot;"
403 '>' -> "&gt;"
405 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
407 static const WCHAR ltW[] = {'&','l','t',';'};
408 static const WCHAR ampW[] = {'&','a','m','p',';'};
409 static const WCHAR equotW[] = {'&','q','u','o','t',';'};
410 static const WCHAR gtW[] = {'&','g','t',';'};
412 const int default_alloc = 100;
413 const int grow_thresh = 10;
414 int p = *len, conv_len;
415 WCHAR *ptr, *ret;
417 /* default buffer size to something if length is unknown */
418 conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
419 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
421 while (*str && p)
423 if (ptr - ret > conv_len - grow_thresh)
425 int written = ptr - ret;
426 conv_len *= 2;
427 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
428 ptr += written;
431 switch (*str)
433 case '<':
434 memcpy(ptr, ltW, sizeof(ltW));
435 ptr += sizeof(ltW)/sizeof(WCHAR);
436 break;
437 case '&':
438 memcpy(ptr, ampW, sizeof(ampW));
439 ptr += sizeof(ampW)/sizeof(WCHAR);
440 break;
441 case '>':
442 memcpy(ptr, gtW, sizeof(gtW));
443 ptr += sizeof(gtW)/sizeof(WCHAR);
444 break;
445 case '"':
446 if (mode == EscapeValue)
448 memcpy(ptr, equotW, sizeof(equotW));
449 ptr += sizeof(equotW)/sizeof(WCHAR);
450 break;
452 /* fallthrough for text mode */
453 default:
454 *ptr++ = *str;
455 break;
458 str++;
459 if (*len != -1) p--;
462 if (*len != -1) *len = ptr-ret;
463 *++ptr = 0;
465 return ret;
468 static void write_prolog_buffer(mxwriter *This)
470 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
471 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
472 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
473 static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
474 static const WCHAR noW[] = {'n','o','\"','?','>'};
476 /* version */
477 write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
478 write_output_buffer_quoted(This->buffer, This->version, -1);
480 /* encoding */
481 write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
483 /* always write UTF-16 to WCHAR buffer */
484 write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
485 write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
486 write_output_buffer(This->buffer, quotW, 1);
488 /* standalone */
489 write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
490 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
491 write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
492 else
493 write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
495 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
496 This->newline = TRUE;
499 /* Attempts to the write data from the mxwriter's buffer to
500 * the destination stream (if there is one).
502 static HRESULT write_data_to_stream(mxwriter *This)
504 encoded_buffer *buffer;
505 ULONG written = 0;
506 HRESULT hr;
508 if (!This->dest)
509 return S_OK;
511 if (This->xml_enc != XmlEncoding_UTF16)
512 buffer = &This->buffer->encoded;
513 else
514 buffer = &This->buffer->utf16;
516 if (This->dest_written > buffer->written) {
517 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->written);
518 return E_FAIL;
519 } else if (This->dest_written == buffer->written && This->xml_enc != XmlEncoding_UTF8)
520 /* Windows seems to make an empty write call when the encoding is UTF-8 and
521 * all the data has been written to the stream. It doesn't seem make this call
522 * for any other encodings.
524 return S_OK;
526 /* Write the current content from the output buffer into 'dest'.
527 * TODO: Check what Windows does if the IStream doesn't write all of
528 * the data we give it at once.
530 hr = IStream_Write(This->dest, buffer->data+This->dest_written,
531 buffer->written-This->dest_written, &written);
532 if (FAILED(hr)) {
533 WARN("Failed to write data to IStream (0x%08x)\n", hr);
534 return hr;
537 This->dest_written += written;
538 return hr;
541 /* Newly added element start tag left unclosed cause for empty elements
542 we have to close it differently. */
543 static void close_element_starttag(const mxwriter *This)
545 static const WCHAR gtW[] = {'>'};
546 if (!This->element) return;
547 write_output_buffer(This->buffer, gtW, 1);
550 static void write_node_indent(mxwriter *This)
552 static const WCHAR tabW[] = {'\t'};
553 int indent = This->indent;
555 if (!This->props[MXWriter_Indent] || This->text)
557 This->text = FALSE;
558 return;
561 /* This is to workaround PI output logic that always puts newline chars,
562 document prolog PI does that too. */
563 if (!This->newline)
564 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
565 while (indent--)
566 write_output_buffer(This->buffer, tabW, 1);
568 This->newline = FALSE;
569 This->text = FALSE;
572 static inline void writer_inc_indent(mxwriter *This)
574 This->indent++;
577 static inline void writer_dec_indent(mxwriter *This)
579 if (This->indent) This->indent--;
580 /* depth is decreased only when element is closed, meaning it's not a text node
581 at this point */
582 This->text = FALSE;
585 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
587 SysFreeString(This->element);
588 if (name)
589 This->element = len != -1 ? SysAllocStringLen(name, len) : SysAllocString(name);
590 else
591 This->element = NULL;
594 static inline HRESULT flush_output_buffer(mxwriter *This)
596 close_element_starttag(This);
597 set_element_name(This, NULL, 0);
598 This->cdata = FALSE;
599 return write_data_to_stream(This);
602 /* Resets the mxwriter's output buffer by closing it, then creating a new
603 * output buffer using the given encoding.
605 static inline void reset_output_buffer(mxwriter *This)
607 close_output_buffer(This);
608 This->dest_written = 0;
611 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
613 writer->props[property] = value;
614 writer->prop_changed = TRUE;
615 return S_OK;
618 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
620 if (!value) return E_POINTER;
621 *value = writer->props[property];
622 return S_OK;
625 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
627 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
630 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
632 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
635 static inline mxwriter *impl_from_IVBSAXContentHandler(IVBSAXContentHandler *iface)
637 return CONTAINING_RECORD(iface, mxwriter, IVBSAXContentHandler_iface);
640 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
642 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
645 static inline mxwriter *impl_from_IVBSAXLexicalHandler(IVBSAXLexicalHandler *iface)
647 return CONTAINING_RECORD(iface, mxwriter, IVBSAXLexicalHandler_iface);
650 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
652 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
655 static inline mxwriter *impl_from_IVBSAXDeclHandler(IVBSAXDeclHandler *iface)
657 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDeclHandler_iface);
660 static inline mxwriter *impl_from_ISAXDTDHandler(ISAXDTDHandler *iface)
662 return CONTAINING_RECORD(iface, mxwriter, ISAXDTDHandler_iface);
665 static inline mxwriter *impl_from_IVBSAXDTDHandler(IVBSAXDTDHandler *iface)
667 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDTDHandler_iface);
670 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
672 mxwriter *This = impl_from_IMXWriter( iface );
674 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
676 *obj = NULL;
678 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
679 IsEqualGUID( riid, &IID_IDispatch ) ||
680 IsEqualGUID( riid, &IID_IUnknown ) )
682 *obj = &This->IMXWriter_iface;
684 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
686 *obj = &This->ISAXContentHandler_iface;
688 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
690 *obj = &This->ISAXLexicalHandler_iface;
692 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
694 *obj = &This->ISAXDeclHandler_iface;
696 else if ( IsEqualGUID( riid, &IID_ISAXDTDHandler ) )
698 *obj = &This->ISAXDTDHandler_iface;
700 else if ( IsEqualGUID( riid, &IID_IVBSAXDeclHandler ) )
702 *obj = &This->IVBSAXDeclHandler_iface;
704 else if ( IsEqualGUID( riid, &IID_IVBSAXLexicalHandler ) )
706 *obj = &This->IVBSAXLexicalHandler_iface;
708 else if ( IsEqualGUID( riid, &IID_IVBSAXContentHandler ) )
710 *obj = &This->IVBSAXContentHandler_iface;
712 else if ( IsEqualGUID( riid, &IID_IVBSAXDTDHandler ) )
714 *obj = &This->IVBSAXDTDHandler_iface;
716 else if (dispex_query_interface(&This->dispex, riid, obj))
718 return *obj ? S_OK : E_NOINTERFACE;
720 else
722 ERR("interface %s not implemented\n", debugstr_guid(riid));
723 *obj = NULL;
724 return E_NOINTERFACE;
727 IMXWriter_AddRef(iface);
728 return S_OK;
731 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
733 mxwriter *This = impl_from_IMXWriter( iface );
734 LONG ref = InterlockedIncrement(&This->ref);
736 TRACE("(%p)->(%d)\n", This, ref);
738 return ref;
741 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
743 mxwriter *This = impl_from_IMXWriter( iface );
744 ULONG ref = InterlockedDecrement(&This->ref);
746 TRACE("(%p)->(%d)\n", This, ref);
748 if(!ref)
750 /* Windows flushes the buffer when the interface is destroyed. */
751 flush_output_buffer(This);
752 free_output_buffer(This->buffer);
754 if (This->dest) IStream_Release(This->dest);
755 SysFreeString(This->version);
756 SysFreeString(This->encoding);
758 SysFreeString(This->element);
759 release_dispex(&This->dispex);
760 heap_free(This);
763 return ref;
766 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
768 mxwriter *This = impl_from_IMXWriter( iface );
769 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
772 static HRESULT WINAPI mxwriter_GetTypeInfo(
773 IMXWriter *iface,
774 UINT iTInfo, LCID lcid,
775 ITypeInfo** ppTInfo )
777 mxwriter *This = impl_from_IMXWriter( iface );
778 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
779 iTInfo, lcid, ppTInfo);
782 static HRESULT WINAPI mxwriter_GetIDsOfNames(
783 IMXWriter *iface,
784 REFIID riid, LPOLESTR* rgszNames,
785 UINT cNames, LCID lcid, DISPID* rgDispId )
787 mxwriter *This = impl_from_IMXWriter( iface );
788 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
789 riid, rgszNames, cNames, lcid, rgDispId);
792 static HRESULT WINAPI mxwriter_Invoke(
793 IMXWriter *iface,
794 DISPID dispIdMember, REFIID riid, LCID lcid,
795 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
796 EXCEPINFO* pExcepInfo, UINT* puArgErr )
798 mxwriter *This = impl_from_IMXWriter( iface );
799 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
800 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
803 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
805 mxwriter *This = impl_from_IMXWriter( iface );
806 HRESULT hr;
808 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
810 hr = flush_output_buffer(This);
811 if (FAILED(hr))
812 return hr;
814 switch (V_VT(&dest))
816 case VT_EMPTY:
818 if (This->dest) IStream_Release(This->dest);
819 This->dest = NULL;
820 reset_output_buffer(This);
821 break;
823 case VT_UNKNOWN:
825 IStream *stream;
827 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
828 if (hr == S_OK)
830 /* Recreate the output buffer to make sure it's using the correct encoding. */
831 reset_output_buffer(This);
833 if (This->dest) IStream_Release(This->dest);
834 This->dest = stream;
835 break;
838 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
839 return E_NOTIMPL;
841 default:
842 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
843 return E_NOTIMPL;
846 return S_OK;
849 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
851 mxwriter *This = impl_from_IMXWriter( iface );
853 TRACE("(%p)->(%p)\n", This, dest);
855 if (!dest) return E_POINTER;
857 if (!This->dest)
859 HRESULT hr = flush_output_buffer(This);
860 if (FAILED(hr))
861 return hr;
863 V_VT(dest) = VT_BSTR;
864 V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
866 return S_OK;
869 /* we only support IStream output so far */
870 V_VT(dest) = VT_UNKNOWN;
871 V_UNKNOWN(dest) = (IUnknown*)This->dest;
872 IStream_AddRef(This->dest);
874 return S_OK;
877 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
879 mxwriter *This = impl_from_IMXWriter( iface );
880 xml_encoding enc;
881 HRESULT hr;
883 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
885 enc = parse_encoding_name(encoding);
886 if (enc == XmlEncoding_Unknown)
888 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
889 return E_INVALIDARG;
892 hr = flush_output_buffer(This);
893 if (FAILED(hr))
894 return hr;
896 SysReAllocString(&This->encoding, encoding);
897 This->xml_enc = enc;
899 TRACE("got encoding %d\n", This->xml_enc);
900 reset_output_buffer(This);
901 return S_OK;
904 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
906 mxwriter *This = impl_from_IMXWriter( iface );
908 TRACE("(%p)->(%p)\n", This, encoding);
910 if (!encoding) return E_POINTER;
912 *encoding = SysAllocString(This->encoding);
913 if (!*encoding) return E_OUTOFMEMORY;
915 return S_OK;
918 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
920 mxwriter *This = impl_from_IMXWriter( iface );
922 TRACE("(%p)->(%d)\n", This, value);
923 return writer_set_property(This, MXWriter_BOM, value);
926 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
928 mxwriter *This = impl_from_IMXWriter( iface );
930 TRACE("(%p)->(%p)\n", This, value);
931 return writer_get_property(This, MXWriter_BOM, value);
934 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
936 mxwriter *This = impl_from_IMXWriter( iface );
938 TRACE("(%p)->(%d)\n", This, value);
939 return writer_set_property(This, MXWriter_Indent, value);
942 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
944 mxwriter *This = impl_from_IMXWriter( iface );
946 TRACE("(%p)->(%p)\n", This, value);
947 return writer_get_property(This, MXWriter_Indent, value);
950 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
952 mxwriter *This = impl_from_IMXWriter( iface );
954 TRACE("(%p)->(%d)\n", This, value);
955 return writer_set_property(This, MXWriter_Standalone, value);
958 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
960 mxwriter *This = impl_from_IMXWriter( iface );
962 TRACE("(%p)->(%p)\n", This, value);
963 return writer_get_property(This, MXWriter_Standalone, value);
966 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
968 mxwriter *This = impl_from_IMXWriter( iface );
970 TRACE("(%p)->(%d)\n", This, value);
971 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
974 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
976 mxwriter *This = impl_from_IMXWriter( iface );
978 TRACE("(%p)->(%p)\n", This, value);
979 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
982 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
984 mxwriter *This = impl_from_IMXWriter( iface );
986 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
988 if (!version) return E_INVALIDARG;
990 SysFreeString(This->version);
991 This->version = SysAllocString(version);
993 return S_OK;
996 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
998 mxwriter *This = impl_from_IMXWriter( iface );
1000 TRACE("(%p)->(%p)\n", This, version);
1002 if (!version) return E_POINTER;
1004 return return_bstr(This->version, version);
1007 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
1009 mxwriter *This = impl_from_IMXWriter( iface );
1011 TRACE("(%p)->(%d)\n", This, value);
1012 return writer_set_property(This, MXWriter_DisableEscaping, value);
1015 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
1017 mxwriter *This = impl_from_IMXWriter( iface );
1019 TRACE("(%p)->(%p)\n", This, value);
1020 return writer_get_property(This, MXWriter_DisableEscaping, value);
1023 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
1025 mxwriter *This = impl_from_IMXWriter( iface );
1026 TRACE("(%p)\n", This);
1027 return flush_output_buffer(This);
1030 static const struct IMXWriterVtbl MXWriterVtbl =
1032 mxwriter_QueryInterface,
1033 mxwriter_AddRef,
1034 mxwriter_Release,
1035 mxwriter_GetTypeInfoCount,
1036 mxwriter_GetTypeInfo,
1037 mxwriter_GetIDsOfNames,
1038 mxwriter_Invoke,
1039 mxwriter_put_output,
1040 mxwriter_get_output,
1041 mxwriter_put_encoding,
1042 mxwriter_get_encoding,
1043 mxwriter_put_byteOrderMark,
1044 mxwriter_get_byteOrderMark,
1045 mxwriter_put_indent,
1046 mxwriter_get_indent,
1047 mxwriter_put_standalone,
1048 mxwriter_get_standalone,
1049 mxwriter_put_omitXMLDeclaration,
1050 mxwriter_get_omitXMLDeclaration,
1051 mxwriter_put_version,
1052 mxwriter_get_version,
1053 mxwriter_put_disableOutputEscaping,
1054 mxwriter_get_disableOutputEscaping,
1055 mxwriter_flush
1058 /*** ISAXContentHandler ***/
1059 static HRESULT WINAPI SAXContentHandler_QueryInterface(
1060 ISAXContentHandler *iface,
1061 REFIID riid,
1062 void **obj)
1064 mxwriter *This = impl_from_ISAXContentHandler( iface );
1065 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1068 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
1070 mxwriter *This = impl_from_ISAXContentHandler( iface );
1071 return IMXWriter_AddRef(&This->IMXWriter_iface);
1074 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
1076 mxwriter *This = impl_from_ISAXContentHandler( iface );
1077 return IMXWriter_Release(&This->IMXWriter_iface);
1080 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
1081 ISAXContentHandler *iface,
1082 ISAXLocator *locator)
1084 mxwriter *This = impl_from_ISAXContentHandler( iface );
1085 FIXME("(%p)->(%p)\n", This, locator);
1086 return E_NOTIMPL;
1089 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
1091 mxwriter *This = impl_from_ISAXContentHandler( iface );
1093 TRACE("(%p)\n", This);
1095 /* If properties have been changed since the last "endDocument" call
1096 * we need to reset the output buffer. If we don't the output buffer
1097 * could end up with multiple XML documents in it, plus this seems to
1098 * be how Windows works.
1100 if (This->prop_changed) {
1101 reset_output_buffer(This);
1102 This->prop_changed = FALSE;
1105 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
1107 write_prolog_buffer(This);
1109 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
1110 static const char utf16BOM[] = {0xff,0xfe};
1112 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
1113 /* Windows passes a NULL pointer as the pcbWritten parameter and
1114 * ignores any error codes returned from this Write call.
1116 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
1119 return S_OK;
1122 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
1124 mxwriter *This = impl_from_ISAXContentHandler( iface );
1125 TRACE("(%p)\n", This);
1126 This->prop_changed = FALSE;
1127 return flush_output_buffer(This);
1130 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
1131 ISAXContentHandler *iface,
1132 const WCHAR *prefix,
1133 int nprefix,
1134 const WCHAR *uri,
1135 int nuri)
1137 mxwriter *This = impl_from_ISAXContentHandler( iface );
1138 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
1139 return E_NOTIMPL;
1142 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
1143 ISAXContentHandler *iface,
1144 const WCHAR *prefix,
1145 int nprefix)
1147 mxwriter *This = impl_from_ISAXContentHandler( iface );
1148 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
1149 return E_NOTIMPL;
1152 static HRESULT WINAPI SAXContentHandler_startElement(
1153 ISAXContentHandler *iface,
1154 const WCHAR *namespaceUri,
1155 int nnamespaceUri,
1156 const WCHAR *local_name,
1157 int nlocal_name,
1158 const WCHAR *QName,
1159 int nQName,
1160 ISAXAttributes *attr)
1162 mxwriter *This = impl_from_ISAXContentHandler( iface );
1163 static const WCHAR ltW[] = {'<'};
1165 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
1166 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
1168 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1169 (nQName == -1 && This->class_version == MSXML6))
1170 return E_INVALIDARG;
1172 close_element_starttag(This);
1173 set_element_name(This, QName ? QName : emptyW,
1174 QName ? nQName : 0);
1176 write_node_indent(This);
1178 write_output_buffer(This->buffer, ltW, 1);
1179 write_output_buffer(This->buffer, QName, nQName);
1180 writer_inc_indent(This);
1182 if (attr)
1184 int length, i, escape;
1185 HRESULT hr;
1187 hr = ISAXAttributes_getLength(attr, &length);
1188 if (FAILED(hr)) return hr;
1190 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
1191 (This->class_version == MSXML4 || This->class_version == MSXML6);
1193 for (i = 0; i < length; i++)
1195 static const WCHAR eqW[] = {'='};
1196 const WCHAR *str;
1197 int len = 0;
1199 hr = ISAXAttributes_getQName(attr, i, &str, &len);
1200 if (FAILED(hr)) return hr;
1202 /* space separator in front of every attribute */
1203 write_output_buffer(This->buffer, spaceW, 1);
1204 write_output_buffer(This->buffer, str, len);
1206 write_output_buffer(This->buffer, eqW, 1);
1208 len = 0;
1209 hr = ISAXAttributes_getValue(attr, i, &str, &len);
1210 if (FAILED(hr)) return hr;
1212 if (escape)
1214 WCHAR *escaped = get_escaped_string(str, EscapeValue, &len);
1215 write_output_buffer_quoted(This->buffer, escaped, len);
1216 heap_free(escaped);
1218 else
1219 write_output_buffer_quoted(This->buffer, str, len);
1223 return S_OK;
1226 static HRESULT WINAPI SAXContentHandler_endElement(
1227 ISAXContentHandler *iface,
1228 const WCHAR *namespaceUri,
1229 int nnamespaceUri,
1230 const WCHAR * local_name,
1231 int nlocal_name,
1232 const WCHAR *QName,
1233 int nQName)
1235 mxwriter *This = impl_from_ISAXContentHandler( iface );
1237 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1238 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1240 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1241 (nQName == -1 && This->class_version == MSXML6))
1242 return E_INVALIDARG;
1244 writer_dec_indent(This);
1246 if (This->element)
1248 static const WCHAR closeW[] = {'/','>'};
1249 write_output_buffer(This->buffer, closeW, 2);
1251 else
1253 static const WCHAR closetagW[] = {'<','/'};
1254 static const WCHAR gtW[] = {'>'};
1256 write_node_indent(This);
1257 write_output_buffer(This->buffer, closetagW, 2);
1258 write_output_buffer(This->buffer, QName, nQName);
1259 write_output_buffer(This->buffer, gtW, 1);
1262 set_element_name(This, NULL, 0);
1264 return S_OK;
1267 static HRESULT WINAPI SAXContentHandler_characters(
1268 ISAXContentHandler *iface,
1269 const WCHAR *chars,
1270 int nchars)
1272 mxwriter *This = impl_from_ISAXContentHandler( iface );
1274 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1276 if (!chars) return E_INVALIDARG;
1278 close_element_starttag(This);
1279 set_element_name(This, NULL, 0);
1281 if (!This->cdata)
1282 This->text = TRUE;
1284 if (nchars)
1286 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
1287 write_output_buffer(This->buffer, chars, nchars);
1288 else
1290 int len = nchars;
1291 WCHAR *escaped;
1293 escaped = get_escaped_string(chars, EscapeText, &len);
1294 write_output_buffer(This->buffer, escaped, len);
1295 heap_free(escaped);
1299 return S_OK;
1302 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1303 ISAXContentHandler *iface,
1304 const WCHAR *chars,
1305 int nchars)
1307 mxwriter *This = impl_from_ISAXContentHandler( iface );
1309 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1311 if (!chars) return E_INVALIDARG;
1313 write_output_buffer(This->buffer, chars, nchars);
1315 return S_OK;
1318 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1319 ISAXContentHandler *iface,
1320 const WCHAR *target,
1321 int ntarget,
1322 const WCHAR *data,
1323 int ndata)
1325 mxwriter *This = impl_from_ISAXContentHandler( iface );
1326 static const WCHAR openpiW[] = {'<','?'};
1327 static const WCHAR closepiW[] = {'?','>','\r','\n'};
1329 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1331 if (!target) return E_INVALIDARG;
1333 write_node_indent(This);
1334 write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
1336 if (*target)
1337 write_output_buffer(This->buffer, target, ntarget);
1339 if (data && *data && ndata)
1341 write_output_buffer(This->buffer, spaceW, 1);
1342 write_output_buffer(This->buffer, data, ndata);
1345 write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
1346 This->newline = TRUE;
1348 return S_OK;
1351 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1352 ISAXContentHandler *iface,
1353 const WCHAR *name,
1354 int nname)
1356 mxwriter *This = impl_from_ISAXContentHandler( iface );
1357 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1358 return E_NOTIMPL;
1361 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1363 SAXContentHandler_QueryInterface,
1364 SAXContentHandler_AddRef,
1365 SAXContentHandler_Release,
1366 SAXContentHandler_putDocumentLocator,
1367 SAXContentHandler_startDocument,
1368 SAXContentHandler_endDocument,
1369 SAXContentHandler_startPrefixMapping,
1370 SAXContentHandler_endPrefixMapping,
1371 SAXContentHandler_startElement,
1372 SAXContentHandler_endElement,
1373 SAXContentHandler_characters,
1374 SAXContentHandler_ignorableWhitespace,
1375 SAXContentHandler_processingInstruction,
1376 SAXContentHandler_skippedEntity
1379 /*** ISAXLexicalHandler ***/
1380 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1381 REFIID riid, void **obj)
1383 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1384 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1387 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1389 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1390 return IMXWriter_AddRef(&This->IMXWriter_iface);
1393 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1395 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1396 return IMXWriter_Release(&This->IMXWriter_iface);
1399 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1400 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1401 const WCHAR *systemId, int systemId_len)
1403 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1404 static const WCHAR openintW[] = {'[','\r','\n'};
1406 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1408 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1409 debugstr_wn(systemId, systemId_len));
1411 if (!name) return E_INVALIDARG;
1413 write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1415 if (*name)
1417 write_output_buffer(This->buffer, name, name_len);
1418 write_output_buffer(This->buffer, spaceW, 1);
1421 if (publicId)
1423 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1425 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1426 write_output_buffer_quoted(This->buffer, publicId, publicId_len);
1428 if (!systemId) return E_INVALIDARG;
1430 if (*publicId)
1431 write_output_buffer(This->buffer, spaceW, 1);
1433 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1435 if (*systemId)
1436 write_output_buffer(This->buffer, spaceW, 1);
1438 else if (systemId)
1440 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1442 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1443 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1444 if (*systemId)
1445 write_output_buffer(This->buffer, spaceW, 1);
1448 write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
1450 return S_OK;
1453 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1455 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1456 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1458 TRACE("(%p)\n", This);
1460 write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1462 return S_OK;
1465 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1467 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1468 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1469 return E_NOTIMPL;
1472 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1474 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1475 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1476 return E_NOTIMPL;
1479 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1481 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1482 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1484 TRACE("(%p)\n", This);
1486 write_node_indent(This);
1487 write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1488 This->cdata = TRUE;
1490 return S_OK;
1493 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1495 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1496 static const WCHAR ecdataW[] = {']',']','>'};
1498 TRACE("(%p)\n", This);
1500 write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1501 This->cdata = FALSE;
1503 return S_OK;
1506 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1508 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1509 static const WCHAR copenW[] = {'<','!','-','-'};
1510 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1512 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1514 if (!chars) return E_INVALIDARG;
1516 close_element_starttag(This);
1517 write_node_indent(This);
1519 write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
1520 if (nchars)
1521 write_output_buffer(This->buffer, chars, nchars);
1522 write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1524 return S_OK;
1527 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1529 SAXLexicalHandler_QueryInterface,
1530 SAXLexicalHandler_AddRef,
1531 SAXLexicalHandler_Release,
1532 SAXLexicalHandler_startDTD,
1533 SAXLexicalHandler_endDTD,
1534 SAXLexicalHandler_startEntity,
1535 SAXLexicalHandler_endEntity,
1536 SAXLexicalHandler_startCDATA,
1537 SAXLexicalHandler_endCDATA,
1538 SAXLexicalHandler_comment
1541 /*** ISAXDeclHandler ***/
1542 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1543 REFIID riid, void **obj)
1545 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1546 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1549 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1551 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1552 return IMXWriter_AddRef(&This->IMXWriter_iface);
1555 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1557 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1558 return IMXWriter_Release(&This->IMXWriter_iface);
1561 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1562 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1564 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1565 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1567 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1568 debugstr_wn(model, n_model), n_model);
1570 if (!name || !model) return E_INVALIDARG;
1572 write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
1573 if (n_name) {
1574 write_output_buffer(This->buffer, name, n_name);
1575 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1577 if (n_model)
1578 write_output_buffer(This->buffer, model, n_model);
1579 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1581 return S_OK;
1584 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1585 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1586 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1587 const WCHAR *value, int n_value)
1589 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1590 static const WCHAR attlistW[] = {'<','!','A','T','T','L','I','S','T',' '};
1591 static const WCHAR closetagW[] = {'>','\r','\n'};
1593 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element,
1594 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1595 debugstr_wn(value, n_value), n_value);
1597 write_output_buffer(This->buffer, attlistW, sizeof(attlistW)/sizeof(WCHAR));
1598 if (n_element) {
1599 write_output_buffer(This->buffer, element, n_element);
1600 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1603 if (n_attr) {
1604 write_output_buffer(This->buffer, attr, n_attr);
1605 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1608 if (n_type) {
1609 write_output_buffer(This->buffer, type, n_type);
1610 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1613 if (n_default) {
1614 write_output_buffer(This->buffer, Default, n_default);
1615 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1618 if (n_value)
1619 write_output_buffer_quoted(This->buffer, value, n_value);
1621 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1623 return S_OK;
1626 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1627 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1629 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1631 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1632 debugstr_wn(value, n_value), n_value);
1634 if (!name || !value) return E_INVALIDARG;
1636 write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
1637 if (n_name) {
1638 write_output_buffer(This->buffer, name, n_name);
1639 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1642 if (n_value)
1643 write_output_buffer_quoted(This->buffer, value, n_value);
1645 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1647 return S_OK;
1650 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1651 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1652 const WCHAR *systemId, int n_systemId)
1654 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1655 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1656 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1658 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1659 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1661 if (!name) return E_INVALIDARG;
1662 if (publicId && !systemId) return E_INVALIDARG;
1663 if (!publicId && !systemId) return E_INVALIDARG;
1665 write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
1666 if (n_name) {
1667 write_output_buffer(This->buffer, name, n_name);
1668 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1671 if (publicId)
1673 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1674 write_output_buffer_quoted(This->buffer, publicId, n_publicId);
1675 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1676 write_output_buffer_quoted(This->buffer, systemId, n_systemId);
1678 else
1680 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1681 write_output_buffer_quoted(This->buffer, systemId, n_systemId);
1684 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1686 return S_OK;
1689 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1690 SAXDeclHandler_QueryInterface,
1691 SAXDeclHandler_AddRef,
1692 SAXDeclHandler_Release,
1693 SAXDeclHandler_elementDecl,
1694 SAXDeclHandler_attributeDecl,
1695 SAXDeclHandler_internalEntityDecl,
1696 SAXDeclHandler_externalEntityDecl
1699 /*** IVBSAXDeclHandler ***/
1700 static HRESULT WINAPI VBSAXDeclHandler_QueryInterface(IVBSAXDeclHandler *iface,
1701 REFIID riid, void **obj)
1703 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1704 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1707 static ULONG WINAPI VBSAXDeclHandler_AddRef(IVBSAXDeclHandler *iface)
1709 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1710 return IMXWriter_AddRef(&This->IMXWriter_iface);
1713 static ULONG WINAPI VBSAXDeclHandler_Release(IVBSAXDeclHandler *iface)
1715 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1716 return IMXWriter_Release(&This->IMXWriter_iface);
1719 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfoCount(IVBSAXDeclHandler *iface, UINT* pctinfo)
1721 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1722 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
1725 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfo(IVBSAXDeclHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1727 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1728 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
1731 static HRESULT WINAPI VBSAXDeclHandler_GetIDsOfNames(IVBSAXDeclHandler *iface, REFIID riid, LPOLESTR* rgszNames,
1732 UINT cNames, LCID lcid, DISPID* rgDispId )
1734 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1735 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
1738 static HRESULT WINAPI VBSAXDeclHandler_Invoke(IVBSAXDeclHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1739 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
1741 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1742 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
1743 pExcepInfo, puArgErr);
1746 static HRESULT WINAPI VBSAXDeclHandler_elementDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *model)
1748 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1750 TRACE("(%p)->(%p %p)\n", This, name, model);
1752 if (!name || !model)
1753 return E_POINTER;
1755 return ISAXDeclHandler_elementDecl(&This->ISAXDeclHandler_iface, *name, -1, *model, -1);
1758 static HRESULT WINAPI VBSAXDeclHandler_attributeDecl(IVBSAXDeclHandler *iface,
1759 BSTR *element, BSTR *attr, BSTR *type, BSTR *default_value, BSTR *value)
1761 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1763 TRACE("(%p)->(%p %p %p %p %p)\n", This, element, attr, type, default_value, value);
1765 if (!element || !attr || !type || !default_value || !value)
1766 return E_POINTER;
1768 return ISAXDeclHandler_attributeDecl(&This->ISAXDeclHandler_iface, *element, -1, *attr, -1, *type, -1,
1769 *default_value, -1, *value, -1);
1772 static HRESULT WINAPI VBSAXDeclHandler_internalEntityDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *value)
1774 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1776 TRACE("(%p)->(%p %p)\n", This, name, value);
1778 if (!name || !value)
1779 return E_POINTER;
1781 return ISAXDeclHandler_internalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *value, -1);
1784 static HRESULT WINAPI VBSAXDeclHandler_externalEntityDecl(IVBSAXDeclHandler *iface,
1785 BSTR *name, BSTR *publicid, BSTR *systemid)
1787 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1789 TRACE("(%p)->(%p %p %p)\n", This, name, publicid, systemid);
1791 if (!name || !publicid || !systemid)
1792 return E_POINTER;
1794 return ISAXDeclHandler_externalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *publicid, -1, *systemid, -1);
1797 static const IVBSAXDeclHandlerVtbl VBSAXDeclHandlerVtbl = {
1798 VBSAXDeclHandler_QueryInterface,
1799 VBSAXDeclHandler_AddRef,
1800 VBSAXDeclHandler_Release,
1801 VBSAXDeclHandler_GetTypeInfoCount,
1802 VBSAXDeclHandler_GetTypeInfo,
1803 VBSAXDeclHandler_GetIDsOfNames,
1804 VBSAXDeclHandler_Invoke,
1805 VBSAXDeclHandler_elementDecl,
1806 VBSAXDeclHandler_attributeDecl,
1807 VBSAXDeclHandler_internalEntityDecl,
1808 VBSAXDeclHandler_externalEntityDecl
1811 /*** IVBSAXLexicalHandler ***/
1812 static HRESULT WINAPI VBSAXLexicalHandler_QueryInterface(IVBSAXLexicalHandler *iface,
1813 REFIID riid, void **obj)
1815 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1816 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1819 static ULONG WINAPI VBSAXLexicalHandler_AddRef(IVBSAXLexicalHandler *iface)
1821 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1822 return IMXWriter_AddRef(&This->IMXWriter_iface);
1825 static ULONG WINAPI VBSAXLexicalHandler_Release(IVBSAXLexicalHandler *iface)
1827 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1828 return IMXWriter_Release(&This->IMXWriter_iface);
1831 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfoCount(IVBSAXLexicalHandler *iface, UINT* pctinfo)
1833 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1834 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
1837 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfo(IVBSAXLexicalHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1839 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1840 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
1843 static HRESULT WINAPI VBSAXLexicalHandler_GetIDsOfNames(IVBSAXLexicalHandler *iface, REFIID riid, LPOLESTR* rgszNames,
1844 UINT cNames, LCID lcid, DISPID* rgDispId )
1846 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1847 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
1850 static HRESULT WINAPI VBSAXLexicalHandler_Invoke(IVBSAXLexicalHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1851 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
1853 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1854 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
1855 pExcepInfo, puArgErr);
1858 static HRESULT WINAPI VBSAXLexicalHandler_startDTD(IVBSAXLexicalHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
1860 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1862 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
1864 if (!name || !publicId || !systemId)
1865 return E_POINTER;
1867 return ISAXLexicalHandler_startDTD(&This->ISAXLexicalHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
1870 static HRESULT WINAPI VBSAXLexicalHandler_endDTD(IVBSAXLexicalHandler *iface)
1872 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1873 return ISAXLexicalHandler_endDTD(&This->ISAXLexicalHandler_iface);
1876 static HRESULT WINAPI VBSAXLexicalHandler_startEntity(IVBSAXLexicalHandler *iface, BSTR *name)
1878 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1880 TRACE("(%p)->(%p)\n", This, name);
1882 if (!name)
1883 return E_POINTER;
1885 return ISAXLexicalHandler_startEntity(&This->ISAXLexicalHandler_iface, *name, -1);
1888 static HRESULT WINAPI VBSAXLexicalHandler_endEntity(IVBSAXLexicalHandler *iface, BSTR *name)
1890 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1892 TRACE("(%p)->(%p)\n", This, name);
1894 if (!name)
1895 return E_POINTER;
1897 return ISAXLexicalHandler_endEntity(&This->ISAXLexicalHandler_iface, *name, -1);
1900 static HRESULT WINAPI VBSAXLexicalHandler_startCDATA(IVBSAXLexicalHandler *iface)
1902 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1903 return ISAXLexicalHandler_startCDATA(&This->ISAXLexicalHandler_iface);
1906 static HRESULT WINAPI VBSAXLexicalHandler_endCDATA(IVBSAXLexicalHandler *iface)
1908 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1909 return ISAXLexicalHandler_endCDATA(&This->ISAXLexicalHandler_iface);
1912 static HRESULT WINAPI VBSAXLexicalHandler_comment(IVBSAXLexicalHandler *iface, BSTR *chars)
1914 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1916 TRACE("(%p)->(%p)\n", This, chars);
1918 if (!chars)
1919 return E_POINTER;
1921 return ISAXLexicalHandler_comment(&This->ISAXLexicalHandler_iface, *chars, -1);
1924 static const IVBSAXLexicalHandlerVtbl VBSAXLexicalHandlerVtbl = {
1925 VBSAXLexicalHandler_QueryInterface,
1926 VBSAXLexicalHandler_AddRef,
1927 VBSAXLexicalHandler_Release,
1928 VBSAXLexicalHandler_GetTypeInfoCount,
1929 VBSAXLexicalHandler_GetTypeInfo,
1930 VBSAXLexicalHandler_GetIDsOfNames,
1931 VBSAXLexicalHandler_Invoke,
1932 VBSAXLexicalHandler_startDTD,
1933 VBSAXLexicalHandler_endDTD,
1934 VBSAXLexicalHandler_startEntity,
1935 VBSAXLexicalHandler_endEntity,
1936 VBSAXLexicalHandler_startCDATA,
1937 VBSAXLexicalHandler_endCDATA,
1938 VBSAXLexicalHandler_comment
1941 /*** IVBSAXContentHandler ***/
1942 static HRESULT WINAPI VBSAXContentHandler_QueryInterface(IVBSAXContentHandler *iface, REFIID riid, void **obj)
1944 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1945 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1948 static ULONG WINAPI VBSAXContentHandler_AddRef(IVBSAXContentHandler *iface)
1950 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1951 return IMXWriter_AddRef(&This->IMXWriter_iface);
1954 static ULONG WINAPI VBSAXContentHandler_Release(IVBSAXContentHandler *iface)
1956 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1957 return IMXWriter_Release(&This->IMXWriter_iface);
1960 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfoCount(IVBSAXContentHandler *iface, UINT* pctinfo)
1962 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1963 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
1966 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfo(IVBSAXContentHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1968 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1969 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
1972 static HRESULT WINAPI VBSAXContentHandler_GetIDsOfNames(IVBSAXContentHandler *iface, REFIID riid, LPOLESTR* rgszNames,
1973 UINT cNames, LCID lcid, DISPID* rgDispId )
1975 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1976 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
1979 static HRESULT WINAPI VBSAXContentHandler_Invoke(IVBSAXContentHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1980 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
1982 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1983 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
1984 pExcepInfo, puArgErr);
1987 static HRESULT WINAPI VBSAXContentHandler_putref_documentLocator(IVBSAXContentHandler *iface, IVBSAXLocator *locator)
1989 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1990 FIXME("(%p)->(%p): stub\n", This, locator);
1991 return E_NOTIMPL;
1994 static HRESULT WINAPI VBSAXContentHandler_startDocument(IVBSAXContentHandler *iface)
1996 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
1997 return ISAXContentHandler_startDocument(&This->ISAXContentHandler_iface);
2000 static HRESULT WINAPI VBSAXContentHandler_endDocument(IVBSAXContentHandler *iface)
2002 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2003 return ISAXContentHandler_endDocument(&This->ISAXContentHandler_iface);
2006 static HRESULT WINAPI VBSAXContentHandler_startPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix, BSTR *uri)
2008 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2010 TRACE("(%p)->(%p %p)\n", This, prefix, uri);
2012 if (!prefix || !uri)
2013 return E_POINTER;
2015 return ISAXContentHandler_startPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1, *uri, -1);
2018 static HRESULT WINAPI VBSAXContentHandler_endPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix)
2020 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2022 TRACE("(%p)->(%p)\n", This, prefix);
2024 if (!prefix)
2025 return E_POINTER;
2027 return ISAXContentHandler_endPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1);
2030 static HRESULT WINAPI VBSAXContentHandler_startElement(IVBSAXContentHandler *iface,
2031 BSTR *namespaceURI, BSTR *localName, BSTR *QName, IVBSAXAttributes *attrs)
2033 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2034 FIXME("(%p)->(%p %p %p %p): stub\n", This, namespaceURI, localName, QName, attrs);
2035 return E_NOTIMPL;
2038 static HRESULT WINAPI VBSAXContentHandler_endElement(IVBSAXContentHandler *iface, BSTR *namespaceURI,
2039 BSTR *localName, BSTR *QName)
2041 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2042 FIXME("(%p)->(%p %p %p): stub\n", This, namespaceURI, localName, QName);
2043 return E_NOTIMPL;
2046 static HRESULT WINAPI VBSAXContentHandler_characters(IVBSAXContentHandler *iface, BSTR *chars)
2048 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2050 TRACE("(%p)->(%p)\n", This, chars);
2052 if (!chars)
2053 return E_POINTER;
2055 return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, -1);
2058 static HRESULT WINAPI VBSAXContentHandler_ignorableWhitespace(IVBSAXContentHandler *iface, BSTR *chars)
2060 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2062 TRACE("(%p)->(%p)\n", This, chars);
2064 if (!chars)
2065 return E_POINTER;
2067 return ISAXContentHandler_ignorableWhitespace(&This->ISAXContentHandler_iface, *chars, -1);
2070 static HRESULT WINAPI VBSAXContentHandler_processingInstruction(IVBSAXContentHandler *iface,
2071 BSTR *target, BSTR *data)
2073 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2075 TRACE("(%p)->(%p %p)\n", This, target, data);
2077 if (!target || !data)
2078 return E_POINTER;
2080 return ISAXContentHandler_processingInstruction(&This->ISAXContentHandler_iface, *target, -1, *data, -1);
2083 static HRESULT WINAPI VBSAXContentHandler_skippedEntity(IVBSAXContentHandler *iface, BSTR *name)
2085 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2087 TRACE("(%p)->(%p)\n", This, name);
2089 if (!name)
2090 return E_POINTER;
2092 return ISAXContentHandler_skippedEntity(&This->ISAXContentHandler_iface, *name, -1);
2095 static const IVBSAXContentHandlerVtbl VBSAXContentHandlerVtbl = {
2096 VBSAXContentHandler_QueryInterface,
2097 VBSAXContentHandler_AddRef,
2098 VBSAXContentHandler_Release,
2099 VBSAXContentHandler_GetTypeInfoCount,
2100 VBSAXContentHandler_GetTypeInfo,
2101 VBSAXContentHandler_GetIDsOfNames,
2102 VBSAXContentHandler_Invoke,
2103 VBSAXContentHandler_putref_documentLocator,
2104 VBSAXContentHandler_startDocument,
2105 VBSAXContentHandler_endDocument,
2106 VBSAXContentHandler_startPrefixMapping,
2107 VBSAXContentHandler_endPrefixMapping,
2108 VBSAXContentHandler_startElement,
2109 VBSAXContentHandler_endElement,
2110 VBSAXContentHandler_characters,
2111 VBSAXContentHandler_ignorableWhitespace,
2112 VBSAXContentHandler_processingInstruction,
2113 VBSAXContentHandler_skippedEntity
2116 static HRESULT WINAPI SAXDTDHandler_QueryInterface(ISAXDTDHandler *iface, REFIID riid, void **obj)
2118 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2119 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2122 static ULONG WINAPI SAXDTDHandler_AddRef(ISAXDTDHandler *iface)
2124 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2125 return IMXWriter_AddRef(&This->IMXWriter_iface);
2128 static ULONG WINAPI SAXDTDHandler_Release(ISAXDTDHandler *iface)
2130 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2131 return IMXWriter_Release(&This->IMXWriter_iface);
2134 static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
2135 const WCHAR *name, INT nname,
2136 const WCHAR *publicid, INT npublicid,
2137 const WCHAR *systemid, INT nsystemid)
2139 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2140 FIXME("(%p)->(%s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname,
2141 debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid);
2142 return E_NOTIMPL;
2145 static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface,
2146 const WCHAR *name, INT nname,
2147 const WCHAR *publicid, INT npublicid,
2148 const WCHAR *systemid, INT nsystemid,
2149 const WCHAR *notation, INT nnotation)
2151 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2152 FIXME("(%p)->(%s:%d, %s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname,
2153 debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid,
2154 debugstr_wn(notation, nnotation), nnotation);
2155 return E_NOTIMPL;
2158 static const ISAXDTDHandlerVtbl SAXDTDHandlerVtbl = {
2159 SAXDTDHandler_QueryInterface,
2160 SAXDTDHandler_AddRef,
2161 SAXDTDHandler_Release,
2162 SAXDTDHandler_notationDecl,
2163 SAXDTDHandler_unparsedEntityDecl
2166 /*** IVBSAXDTDHandler ***/
2167 static HRESULT WINAPI VBSAXDTDHandler_QueryInterface(IVBSAXDTDHandler *iface, REFIID riid, void **obj)
2169 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2170 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2173 static ULONG WINAPI VBSAXDTDHandler_AddRef(IVBSAXDTDHandler *iface)
2175 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2176 return IMXWriter_AddRef(&This->IMXWriter_iface);
2179 static ULONG WINAPI VBSAXDTDHandler_Release(IVBSAXDTDHandler *iface)
2181 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2182 return IMXWriter_Release(&This->IMXWriter_iface);
2185 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfoCount(IVBSAXDTDHandler *iface, UINT* pctinfo)
2187 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2188 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
2191 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfo(IVBSAXDTDHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2193 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2194 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
2197 static HRESULT WINAPI VBSAXDTDHandler_GetIDsOfNames(IVBSAXDTDHandler *iface, REFIID riid, LPOLESTR* rgszNames,
2198 UINT cNames, LCID lcid, DISPID* rgDispId )
2200 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2201 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
2204 static HRESULT WINAPI VBSAXDTDHandler_Invoke(IVBSAXDTDHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
2205 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
2207 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2208 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
2209 pExcepInfo, puArgErr);
2212 static HRESULT WINAPI VBSAXDTDHandler_notationDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
2214 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2216 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
2218 if (!name || !publicId || !systemId)
2219 return E_POINTER;
2221 return ISAXDTDHandler_notationDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
2224 static HRESULT WINAPI VBSAXDTDHandler_unparsedEntityDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId,
2225 BSTR *systemId, BSTR *notation)
2227 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2229 TRACE("(%p)->(%p %p %p %p)\n", This, name, publicId, systemId, notation);
2231 if (!name || !publicId || !systemId || !notation)
2232 return E_POINTER;
2234 return ISAXDTDHandler_unparsedEntityDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1,
2235 *systemId, -1, *notation, -1);
2238 static const IVBSAXDTDHandlerVtbl VBSAXDTDHandlerVtbl = {
2239 VBSAXDTDHandler_QueryInterface,
2240 VBSAXDTDHandler_AddRef,
2241 VBSAXDTDHandler_Release,
2242 VBSAXDTDHandler_GetTypeInfoCount,
2243 VBSAXDTDHandler_GetTypeInfo,
2244 VBSAXDTDHandler_GetIDsOfNames,
2245 VBSAXDTDHandler_Invoke,
2246 VBSAXDTDHandler_notationDecl,
2247 VBSAXDTDHandler_unparsedEntityDecl
2250 static const tid_t mxwriter_iface_tids[] = {
2251 IMXWriter_tid,
2255 static dispex_static_data_t mxwriter_dispex = {
2256 NULL,
2257 IMXWriter_tid,
2258 NULL,
2259 mxwriter_iface_tids
2262 HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj)
2264 static const WCHAR version10W[] = {'1','.','0',0};
2265 mxwriter *This;
2266 HRESULT hr;
2268 TRACE("(%p)\n", ppObj);
2270 This = heap_alloc( sizeof (*This) );
2271 if(!This)
2272 return E_OUTOFMEMORY;
2274 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
2275 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
2276 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
2277 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
2278 This->ISAXDTDHandler_iface.lpVtbl = &SAXDTDHandlerVtbl;
2279 This->IVBSAXDeclHandler_iface.lpVtbl = &VBSAXDeclHandlerVtbl;
2280 This->IVBSAXLexicalHandler_iface.lpVtbl = &VBSAXLexicalHandlerVtbl;
2281 This->IVBSAXContentHandler_iface.lpVtbl = &VBSAXContentHandlerVtbl;
2282 This->IVBSAXDTDHandler_iface.lpVtbl = &VBSAXDTDHandlerVtbl;
2283 This->ref = 1;
2284 This->class_version = version;
2286 This->props[MXWriter_BOM] = VARIANT_TRUE;
2287 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
2288 This->props[MXWriter_Indent] = VARIANT_FALSE;
2289 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
2290 This->props[MXWriter_Standalone] = VARIANT_FALSE;
2291 This->prop_changed = FALSE;
2292 This->encoding = SysAllocString(utf16W);
2293 This->version = SysAllocString(version10W);
2294 This->xml_enc = XmlEncoding_UTF16;
2296 This->element = NULL;
2297 This->cdata = FALSE;
2298 This->indent = 0;
2299 This->text = FALSE;
2300 This->newline = FALSE;
2302 This->dest = NULL;
2303 This->dest_written = 0;
2305 hr = alloc_output_buffer(This->xml_enc, &This->buffer);
2306 if (hr != S_OK) {
2307 SysFreeString(This->encoding);
2308 SysFreeString(This->version);
2309 heap_free(This);
2310 return hr;
2313 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
2315 *ppObj = &This->IMXWriter_iface;
2317 TRACE("returning iface %p\n", *ppObj);
2319 return S_OK;
2322 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
2324 mxattributes *This = impl_from_IMXAttributes( iface );
2326 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
2328 *ppObj = NULL;
2330 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2331 IsEqualGUID( riid, &IID_IDispatch ) ||
2332 IsEqualGUID( riid, &IID_IMXAttributes ))
2334 *ppObj = iface;
2336 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2338 *ppObj = &This->ISAXAttributes_iface;
2340 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2342 *ppObj = &This->IVBSAXAttributes_iface;
2344 else if (dispex_query_interface(&This->dispex, riid, ppObj))
2346 return *ppObj ? S_OK : E_NOINTERFACE;
2348 else
2350 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2351 return E_NOINTERFACE;
2354 IMXAttributes_AddRef( iface );
2356 return S_OK;
2359 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface)
2361 mxattributes *This = impl_from_IMXAttributes( iface );
2362 ULONG ref = InterlockedIncrement( &This->ref );
2363 TRACE("(%p)->(%d)\n", This, ref );
2364 return ref;
2367 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface)
2369 mxattributes *This = impl_from_IMXAttributes( iface );
2370 LONG ref = InterlockedDecrement( &This->ref );
2372 TRACE("(%p)->(%d)\n", This, ref);
2374 if (ref == 0)
2376 int i;
2378 for (i = 0; i < This->length; i++)
2380 SysFreeString(This->attr[i].qname);
2381 SysFreeString(This->attr[i].local);
2382 SysFreeString(This->attr[i].uri);
2383 SysFreeString(This->attr[i].type);
2384 SysFreeString(This->attr[i].value);
2387 release_dispex(&This->dispex);
2388 heap_free(This->attr);
2389 heap_free(This);
2392 return ref;
2395 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo)
2397 mxattributes *This = impl_from_IMXAttributes( iface );
2398 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2401 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2403 mxattributes *This = impl_from_IMXAttributes( iface );
2404 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2407 static HRESULT WINAPI MXAttributes_GetIDsOfNames(
2408 IMXAttributes *iface,
2409 REFIID riid,
2410 LPOLESTR* rgszNames,
2411 UINT cNames,
2412 LCID lcid,
2413 DISPID* rgDispId)
2415 mxattributes *This = impl_from_IMXAttributes( iface );
2416 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2417 riid, rgszNames, cNames, lcid, rgDispId);
2420 static HRESULT WINAPI MXAttributes_Invoke(
2421 IMXAttributes *iface,
2422 DISPID dispIdMember,
2423 REFIID riid,
2424 LCID lcid,
2425 WORD wFlags,
2426 DISPPARAMS* pDispParams,
2427 VARIANT* pVarResult,
2428 EXCEPINFO* pExcepInfo,
2429 UINT* puArgErr)
2431 mxattributes *This = impl_from_IMXAttributes( iface );
2432 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2433 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2436 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface,
2437 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
2439 mxattributes *This = impl_from_IMXAttributes( iface );
2440 mxattribute *attr;
2441 HRESULT hr;
2443 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName),
2444 debugstr_w(QName), debugstr_w(type), debugstr_w(value));
2446 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6)
2447 return E_INVALIDARG;
2449 /* ensure array is large enough */
2450 hr = mxattributes_grow(This);
2451 if (hr != S_OK) return hr;
2453 attr = &This->attr[This->length];
2455 attr->qname = SysAllocString(QName);
2456 attr->local = SysAllocString(localName);
2457 attr->uri = SysAllocString(uri);
2458 attr->type = SysAllocString(type ? type : emptyW);
2459 attr->value = SysAllocString(value);
2460 This->length++;
2462 return S_OK;
2465 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface,
2466 VARIANT atts, int index)
2468 mxattributes *This = impl_from_IMXAttributes( iface );
2469 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index);
2470 return E_NOTIMPL;
2473 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface)
2475 mxattributes *This = impl_from_IMXAttributes( iface );
2476 int i;
2478 TRACE("(%p)\n", This);
2480 for (i = 0; i < This->length; i++)
2482 SysFreeString(This->attr[i].qname);
2483 SysFreeString(This->attr[i].local);
2484 SysFreeString(This->attr[i].uri);
2485 SysFreeString(This->attr[i].type);
2486 SysFreeString(This->attr[i].value);
2487 memset(&This->attr[i], 0, sizeof(mxattribute));
2490 This->length = 0;
2492 return S_OK;
2495 static mxattribute *get_attribute_byindex(mxattributes *attrs, int index)
2497 if (index < 0 || index >= attrs->length) return NULL;
2498 return &attrs->attr[index];
2501 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
2503 mxattributes *This = impl_from_IMXAttributes( iface );
2504 mxattribute *dst;
2506 TRACE("(%p)->(%d)\n", This, index);
2508 if (!(dst = get_attribute_byindex(This, index))) return E_INVALIDARG;
2510 /* no need to remove last attribute, just make it inaccessible */
2511 if (index + 1 == This->length)
2513 This->length--;
2514 return S_OK;
2517 memmove(dst, dst + 1, (This->length-index-1)*sizeof(*dst));
2518 This->length--;
2520 return S_OK;
2523 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
2524 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
2526 mxattributes *This = impl_from_IMXAttributes( iface );
2527 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri),
2528 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value));
2529 return E_NOTIMPL;
2532 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts)
2534 mxattributes *This = impl_from_IMXAttributes( iface );
2535 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts));
2536 return E_NOTIMPL;
2539 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index,
2540 BSTR localName)
2542 mxattributes *This = impl_from_IMXAttributes( iface );
2543 mxattribute *attr;
2545 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(localName));
2547 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2549 SysFreeString(attr->local);
2550 attr->local = SysAllocString(localName);
2552 return S_OK;
2555 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
2557 mxattributes *This = impl_from_IMXAttributes( iface );
2558 mxattribute *attr;
2560 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(QName));
2562 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2564 SysFreeString(attr->qname);
2565 attr->qname = SysAllocString(QName);
2567 return S_OK;
2570 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
2572 mxattributes *This = impl_from_IMXAttributes( iface );
2573 mxattribute *attr;
2575 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(uri));
2577 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2579 SysFreeString(attr->uri);
2580 attr->uri = SysAllocString(uri);
2582 return S_OK;
2585 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
2587 mxattributes *This = impl_from_IMXAttributes( iface );
2588 mxattribute *attr;
2590 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(value));
2592 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2594 SysFreeString(attr->value);
2595 attr->value = SysAllocString(value);
2597 return S_OK;
2600 static const IMXAttributesVtbl MXAttributesVtbl = {
2601 MXAttributes_QueryInterface,
2602 MXAttributes_AddRef,
2603 MXAttributes_Release,
2604 MXAttributes_GetTypeInfoCount,
2605 MXAttributes_GetTypeInfo,
2606 MXAttributes_GetIDsOfNames,
2607 MXAttributes_Invoke,
2608 MXAttributes_addAttribute,
2609 MXAttributes_addAttributeFromIndex,
2610 MXAttributes_clear,
2611 MXAttributes_removeAttribute,
2612 MXAttributes_setAttribute,
2613 MXAttributes_setAttributes,
2614 MXAttributes_setLocalName,
2615 MXAttributes_setQName,
2616 MXAttributes_setURI,
2617 MXAttributes_setValue
2620 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj)
2622 mxattributes *This = impl_from_ISAXAttributes( iface );
2623 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj);
2626 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface)
2628 mxattributes *This = impl_from_ISAXAttributes( iface );
2629 return IMXAttributes_AddRef(&This->IMXAttributes_iface);
2632 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface)
2634 mxattributes *This = impl_from_ISAXAttributes( iface );
2635 return IMXAttributes_Release(&This->IMXAttributes_iface);
2638 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length)
2640 mxattributes *This = impl_from_ISAXAttributes( iface );
2641 TRACE("(%p)->(%p)\n", This, length);
2643 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2644 return E_POINTER;
2646 *length = This->length;
2648 return S_OK;
2651 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri,
2652 int *len)
2654 mxattributes *This = impl_from_ISAXAttributes( iface );
2656 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len);
2658 if (index >= This->length || index < 0) return E_INVALIDARG;
2659 if (!uri || !len) return E_POINTER;
2661 *len = SysStringLen(This->attr[index].uri);
2662 *uri = This->attr[index].uri;
2664 return S_OK;
2667 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name,
2668 int *len)
2670 mxattributes *This = impl_from_ISAXAttributes( iface );
2672 TRACE("(%p)->(%d %p %p)\n", This, index, name, len);
2674 if (index >= This->length || index < 0) return E_INVALIDARG;
2675 if (!name || !len) return E_POINTER;
2677 *len = SysStringLen(This->attr[index].local);
2678 *name = This->attr[index].local;
2680 return S_OK;
2683 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length)
2685 mxattributes *This = impl_from_ISAXAttributes( iface );
2687 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length);
2689 if (index >= This->length) return E_INVALIDARG;
2690 if (!qname || !length) return E_POINTER;
2692 *qname = This->attr[index].qname;
2693 *length = SysStringLen(This->attr[index].qname);
2695 return S_OK;
2698 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len,
2699 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len)
2701 mxattributes *This = impl_from_ISAXAttributes( iface );
2703 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len);
2705 if (index >= This->length || index < 0)
2706 return E_INVALIDARG;
2708 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len)
2709 return E_POINTER;
2711 *uri_len = SysStringLen(This->attr[index].uri);
2712 *uri = This->attr[index].uri;
2714 *local_len = SysStringLen(This->attr[index].local);
2715 *local = This->attr[index].local;
2717 *qname_len = SysStringLen(This->attr[index].qname);
2718 *qname = This->attr[index].qname;
2720 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname));
2722 return S_OK;
2725 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len,
2726 const WCHAR *name, int len, int *index)
2728 mxattributes *This = impl_from_ISAXAttributes( iface );
2729 int i;
2731 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
2732 debugstr_wn(name, len), len, index);
2734 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2735 return E_POINTER;
2737 if (!uri || !name || !index) return E_INVALIDARG;
2739 for (i = 0; i < This->length; i++)
2741 if (uri_len != SysStringLen(This->attr[i].uri)) continue;
2742 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue;
2744 if (len != SysStringLen(This->attr[i].local)) continue;
2745 if (strncmpW(name, This->attr[i].local, len)) continue;
2747 *index = i;
2748 return S_OK;
2751 return E_INVALIDARG;
2754 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname,
2755 int len, int *index)
2757 mxattributes *This = impl_from_ISAXAttributes( iface );
2758 int i;
2760 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index);
2762 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2763 return E_POINTER;
2765 if (!qname || !index || !len) return E_INVALIDARG;
2767 for (i = 0; i < This->length; i++)
2769 if (len != SysStringLen(This->attr[i].qname)) continue;
2770 if (strncmpW(qname, This->attr[i].qname, len)) continue;
2772 *index = i;
2773 return S_OK;
2776 return E_INVALIDARG;
2779 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type,
2780 int *len)
2782 mxattributes *This = impl_from_ISAXAttributes( iface );
2784 TRACE("(%p)->(%d %p %p)\n", This, index, type, len);
2786 if (index >= This->length) return E_INVALIDARG;
2788 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2789 return E_POINTER;
2791 *type = This->attr[index].type;
2792 *len = SysStringLen(This->attr[index].type);
2794 return S_OK;
2797 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri,
2798 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType)
2800 mxattributes *This = impl_from_ISAXAttributes( iface );
2801 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri,
2802 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType);
2803 return E_NOTIMPL;
2806 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName,
2807 int nQName, const WCHAR ** pType, int * nType)
2809 mxattributes *This = impl_from_ISAXAttributes( iface );
2810 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType);
2811 return E_NOTIMPL;
2814 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value,
2815 int *len)
2817 mxattributes *This = impl_from_ISAXAttributes( iface );
2819 TRACE("(%p)->(%d %p %p)\n", This, index, value, len);
2821 if (index >= This->length) return E_INVALIDARG;
2823 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2824 return E_POINTER;
2826 *value = This->attr[index].value;
2827 *len = SysStringLen(This->attr[index].value);
2829 return S_OK;
2832 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri,
2833 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len)
2835 mxattributes *This = impl_from_ISAXAttributes( iface );
2836 HRESULT hr;
2837 int index;
2839 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
2840 debugstr_wn(name, name_len), name_len, value, value_len);
2842 if (!uri || !name || !value || !value_len)
2843 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2845 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index);
2846 if (hr == S_OK)
2847 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2849 return hr;
2852 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname,
2853 int qname_len, const WCHAR **value, int *value_len)
2855 mxattributes *This = impl_from_ISAXAttributes( iface );
2856 HRESULT hr;
2857 int index;
2859 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len);
2861 if (!qname || !value || !value_len)
2862 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2864 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index);
2865 if (hr == S_OK)
2866 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2868 return hr;
2871 static const ISAXAttributesVtbl SAXAttributesVtbl = {
2872 SAXAttributes_QueryInterface,
2873 SAXAttributes_AddRef,
2874 SAXAttributes_Release,
2875 SAXAttributes_getLength,
2876 SAXAttributes_getURI,
2877 SAXAttributes_getLocalName,
2878 SAXAttributes_getQName,
2879 SAXAttributes_getName,
2880 SAXAttributes_getIndexFromName,
2881 SAXAttributes_getIndexFromQName,
2882 SAXAttributes_getType,
2883 SAXAttributes_getTypeFromName,
2884 SAXAttributes_getTypeFromQName,
2885 SAXAttributes_getValue,
2886 SAXAttributes_getValueFromName,
2887 SAXAttributes_getValueFromQName
2890 static HRESULT WINAPI VBSAXAttributes_QueryInterface(
2891 IVBSAXAttributes* iface,
2892 REFIID riid,
2893 void **ppvObject)
2895 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2896 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
2897 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject);
2900 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface)
2902 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2903 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface);
2906 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface)
2908 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2909 return ISAXAttributes_Release(&This->ISAXAttributes_iface);
2912 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
2914 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2916 TRACE("(%p)->(%p)\n", This, pctinfo);
2918 *pctinfo = 1;
2920 return S_OK;
2923 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo(
2924 IVBSAXAttributes *iface,
2925 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2927 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2928 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2929 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
2932 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames(
2933 IVBSAXAttributes *iface,
2934 REFIID riid,
2935 LPOLESTR* rgszNames,
2936 UINT cNames,
2937 LCID lcid,
2938 DISPID* rgDispId)
2940 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2941 ITypeInfo *typeinfo;
2942 HRESULT hr;
2944 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2945 lcid, rgDispId);
2947 if(!rgszNames || cNames == 0 || !rgDispId)
2948 return E_INVALIDARG;
2950 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2951 if(SUCCEEDED(hr))
2953 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2954 ITypeInfo_Release(typeinfo);
2957 return hr;
2960 static HRESULT WINAPI VBSAXAttributes_Invoke(
2961 IVBSAXAttributes *iface,
2962 DISPID dispIdMember,
2963 REFIID riid,
2964 LCID lcid,
2965 WORD wFlags,
2966 DISPPARAMS* pDispParams,
2967 VARIANT* pVarResult,
2968 EXCEPINFO* pExcepInfo,
2969 UINT* puArgErr)
2971 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2972 ITypeInfo *typeinfo;
2973 HRESULT hr;
2975 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2976 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2978 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2979 if(SUCCEEDED(hr))
2981 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
2982 pDispParams, pVarResult, pExcepInfo, puArgErr);
2983 ITypeInfo_Release(typeinfo);
2986 return hr;
2989 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len)
2991 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2992 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len);
2995 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
2997 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2998 int len;
3000 return ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, (const WCHAR**)uri, &len);
3003 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
3005 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3006 int len;
3008 return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, (const WCHAR**)name, &len);
3011 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
3013 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3014 int len;
3016 return ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, (const WCHAR**)qname, &len);
3019 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
3021 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3022 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3023 name, SysStringLen(name), index);
3026 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index)
3028 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3029 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname,
3030 SysStringLen(qname), index);
3033 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index,BSTR *type)
3035 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3036 int len;
3038 return ISAXAttributes_getType(&This->ISAXAttributes_iface, index, (const WCHAR**)type, &len);
3041 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
3042 BSTR name, BSTR *type)
3044 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3045 int len;
3047 return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3048 name, SysStringLen(name), (const WCHAR**)type, &len);
3051 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
3053 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3054 int len;
3056 return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
3057 (const WCHAR**)type, &len);
3060 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
3062 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3063 int len;
3065 return ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, (const WCHAR**)value, &len);
3068 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
3069 BSTR *value)
3071 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3072 int len;
3074 return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3075 name, SysStringLen(name), (const WCHAR**)value, &len);
3078 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
3080 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3081 int len;
3083 return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
3084 (const WCHAR**)value, &len);
3087 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
3089 VBSAXAttributes_QueryInterface,
3090 VBSAXAttributes_AddRef,
3091 VBSAXAttributes_Release,
3092 VBSAXAttributes_GetTypeInfoCount,
3093 VBSAXAttributes_GetTypeInfo,
3094 VBSAXAttributes_GetIDsOfNames,
3095 VBSAXAttributes_Invoke,
3096 VBSAXAttributes_get_length,
3097 VBSAXAttributes_getURI,
3098 VBSAXAttributes_getLocalName,
3099 VBSAXAttributes_getQName,
3100 VBSAXAttributes_getIndexFromName,
3101 VBSAXAttributes_getIndexFromQName,
3102 VBSAXAttributes_getType,
3103 VBSAXAttributes_getTypeFromName,
3104 VBSAXAttributes_getTypeFromQName,
3105 VBSAXAttributes_getValue,
3106 VBSAXAttributes_getValueFromName,
3107 VBSAXAttributes_getValueFromQName
3110 static const tid_t mxattrs_iface_tids[] = {
3111 IMXAttributes_tid,
3115 static dispex_static_data_t mxattrs_dispex = {
3116 NULL,
3117 IMXAttributes_tid,
3118 NULL,
3119 mxattrs_iface_tids
3122 HRESULT SAXAttributes_create(MSXML_VERSION version, void **ppObj)
3124 static const int default_count = 10;
3125 mxattributes *This;
3127 TRACE("(%p)\n", ppObj);
3129 This = heap_alloc( sizeof (*This) );
3130 if( !This )
3131 return E_OUTOFMEMORY;
3133 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl;
3134 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl;
3135 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl;
3136 This->ref = 1;
3138 This->class_version = version;
3140 This->attr = heap_alloc(default_count*sizeof(mxattribute));
3141 This->length = 0;
3142 This->allocated = default_count;
3144 *ppObj = &This->IMXAttributes_iface;
3146 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex);
3148 TRACE("returning iface %p\n", *ppObj);
3150 return S_OK;