9d68e8cd627b9e3b3533ad4bc4d2b2e5de6b2fa7
[reactos.git] / dll / win32 / msxml3 / mxwriter.c
1 /*
2 * MXWriter implementation
3 *
4 * Copyright 2011-2014, 2016 Nikolay Sivov for CodeWeavers
5 * Copyright 2011 Thomas Mullaly
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "precomp.h"
23
24 static const WCHAR emptyW[] = {0};
25 static const WCHAR spaceW[] = {' '};
26 static const WCHAR quotW[] = {'\"'};
27 static const WCHAR closetagW[] = {'>','\r','\n'};
28 static const WCHAR crlfW[] = {'\r','\n'};
29 static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
30 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
31 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
32
33 /* should be ordered as encoding names are sorted */
34 typedef enum
35 {
36 XmlEncoding_ISO_8859_1 = 0,
37 XmlEncoding_ISO_8859_13,
38 XmlEncoding_ISO_8859_15,
39 XmlEncoding_ISO_8859_2,
40 XmlEncoding_ISO_8859_3,
41 XmlEncoding_ISO_8859_4,
42 XmlEncoding_ISO_8859_5,
43 XmlEncoding_ISO_8859_7,
44 XmlEncoding_ISO_8859_9,
45 XmlEncoding_UTF16,
46 XmlEncoding_UTF8,
47 XmlEncoding_Unknown
48 } xml_encoding;
49
50 struct xml_encoding_data
51 {
52 const WCHAR *encoding;
53 xml_encoding enc;
54 UINT cp;
55 };
56
57 static const WCHAR iso_8859_1W[] = {'i','s','o','-','8','8','5','9','-','1',0};
58 static const WCHAR iso_8859_2W[] = {'i','s','o','-','8','8','5','9','-','2',0};
59 static const WCHAR iso_8859_3W[] = {'i','s','o','-','8','8','5','9','-','3',0};
60 static const WCHAR iso_8859_4W[] = {'i','s','o','-','8','8','5','9','-','4',0};
61 static const WCHAR iso_8859_5W[] = {'i','s','o','-','8','8','5','9','-','5',0};
62 static const WCHAR iso_8859_7W[] = {'i','s','o','-','8','8','5','9','-','7',0};
63 static const WCHAR iso_8859_9W[] = {'i','s','o','-','8','8','5','9','-','9',0};
64 static const WCHAR iso_8859_13W[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
65 static const WCHAR iso_8859_15W[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
66 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
67 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
68
69 static const struct xml_encoding_data xml_encoding_map[] = {
70 { iso_8859_1W, XmlEncoding_ISO_8859_1, 28591 },
71 { iso_8859_13W, XmlEncoding_ISO_8859_13, 28603 },
72 { iso_8859_15W, XmlEncoding_ISO_8859_15, 28605 },
73 { iso_8859_2W, XmlEncoding_ISO_8859_2, 28592 },
74 { iso_8859_3W, XmlEncoding_ISO_8859_3, 28593 },
75 { iso_8859_4W, XmlEncoding_ISO_8859_4, 28594 },
76 { iso_8859_5W, XmlEncoding_ISO_8859_5, 28595 },
77 { iso_8859_7W, XmlEncoding_ISO_8859_7, 28597 },
78 { iso_8859_9W, XmlEncoding_ISO_8859_9, 28599 },
79 { utf16W, XmlEncoding_UTF16, ~0 },
80 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
81 };
82
83 typedef enum
84 {
85 MXWriter_BOM = 0,
86 MXWriter_DisableEscaping,
87 MXWriter_Indent,
88 MXWriter_OmitXmlDecl,
89 MXWriter_Standalone,
90 MXWriter_LastProp
91 } mxwriter_prop;
92
93 typedef enum
94 {
95 EscapeValue,
96 EscapeText
97 } escape_mode;
98
99 typedef struct
100 {
101 struct list entry;
102 char *data;
103 unsigned int allocated;
104 unsigned int written;
105 } encoded_buffer;
106
107 typedef struct
108 {
109 encoded_buffer encoded;
110 UINT code_page;
111 UINT utf16_total; /* total number of bytes written since last buffer reinitialization */
112 struct list blocks; /* only used when output was not set, for BSTR case */
113 } output_buffer;
114
115 typedef struct
116 {
117 DispatchEx dispex;
118 IMXWriter IMXWriter_iface;
119 ISAXContentHandler ISAXContentHandler_iface;
120 ISAXLexicalHandler ISAXLexicalHandler_iface;
121 ISAXDeclHandler ISAXDeclHandler_iface;
122 ISAXDTDHandler ISAXDTDHandler_iface;
123 ISAXErrorHandler ISAXErrorHandler_iface;
124 IVBSAXDeclHandler IVBSAXDeclHandler_iface;
125 IVBSAXLexicalHandler IVBSAXLexicalHandler_iface;
126 IVBSAXContentHandler IVBSAXContentHandler_iface;
127 IVBSAXDTDHandler IVBSAXDTDHandler_iface;
128 IVBSAXErrorHandler IVBSAXErrorHandler_iface;
129
130 LONG ref;
131 MSXML_VERSION class_version;
132
133 VARIANT_BOOL props[MXWriter_LastProp];
134 BOOL prop_changed;
135 BOOL cdata;
136
137 BOOL text; /* last node was text node, so we shouldn't indent next node */
138 BOOL newline; /* newline was already added as a part of previous call */
139 UINT indent; /* indentation level for next node */
140
141 BSTR version;
142
143 BSTR encoding; /* exact property value */
144 xml_encoding xml_enc;
145
146 /* contains a pending (or not closed yet) element name or NULL if
147 we don't have to close */
148 BSTR element;
149
150 IStream *dest;
151
152 output_buffer buffer;
153 } mxwriter;
154
155 typedef struct
156 {
157 BSTR qname;
158 BSTR local;
159 BSTR uri;
160 BSTR type;
161 BSTR value;
162 } mxattribute;
163
164 typedef struct
165 {
166 DispatchEx dispex;
167 IMXAttributes IMXAttributes_iface;
168 ISAXAttributes ISAXAttributes_iface;
169 IVBSAXAttributes IVBSAXAttributes_iface;
170 LONG ref;
171
172 MSXML_VERSION class_version;
173
174 mxattribute *attr;
175 int length;
176 int allocated;
177 } mxattributes;
178
179 static inline mxattributes *impl_from_IMXAttributes( IMXAttributes *iface )
180 {
181 return CONTAINING_RECORD(iface, mxattributes, IMXAttributes_iface);
182 }
183
184 static inline mxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
185 {
186 return CONTAINING_RECORD(iface, mxattributes, ISAXAttributes_iface);
187 }
188
189 static inline mxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
190 {
191 return CONTAINING_RECORD(iface, mxattributes, IVBSAXAttributes_iface);
192 }
193
194 static HRESULT mxattributes_grow(mxattributes *This)
195 {
196 if (This->length < This->allocated) return S_OK;
197
198 This->allocated *= 2;
199 This->attr = heap_realloc(This->attr, This->allocated*sizeof(mxattribute));
200
201 return This->attr ? S_OK : E_OUTOFMEMORY;
202 }
203
204 static xml_encoding parse_encoding_name(const WCHAR *encoding)
205 {
206 int min, max, n, c;
207
208 min = 0;
209 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
210
211 while (min <= max)
212 {
213 n = (min+max)/2;
214
215 c = strcmpiW(xml_encoding_map[n].encoding, encoding);
216 if (!c)
217 return xml_encoding_map[n].enc;
218
219 if (c > 0)
220 max = n-1;
221 else
222 min = n+1;
223 }
224
225 return XmlEncoding_Unknown;
226 }
227
228 static HRESULT init_encoded_buffer(encoded_buffer *buffer)
229 {
230 const int initial_len = 0x1000;
231 buffer->data = heap_alloc(initial_len);
232 if (!buffer->data) return E_OUTOFMEMORY;
233
234 memset(buffer->data, 0, 4);
235 buffer->allocated = initial_len;
236 buffer->written = 0;
237
238 return S_OK;
239 }
240
241 static void free_encoded_buffer(encoded_buffer *buffer)
242 {
243 heap_free(buffer->data);
244 }
245
246 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
247 {
248 const struct xml_encoding_data *data;
249
250 if (encoding == XmlEncoding_Unknown)
251 {
252 FIXME("unsupported encoding %d\n", encoding);
253 return E_NOTIMPL;
254 }
255
256 data = &xml_encoding_map[encoding];
257 *cp = data->cp;
258
259 return S_OK;
260 }
261
262 static HRESULT init_output_buffer(xml_encoding encoding, output_buffer *buffer)
263 {
264 HRESULT hr;
265
266 hr = get_code_page(encoding, &buffer->code_page);
267 if (hr != S_OK)
268 return hr;
269
270 hr = init_encoded_buffer(&buffer->encoded);
271 if (hr != S_OK)
272 return hr;
273
274 list_init(&buffer->blocks);
275 buffer->utf16_total = 0;
276
277 return S_OK;
278 }
279
280 static void free_output_buffer(output_buffer *buffer)
281 {
282 encoded_buffer *cur, *cur2;
283
284 free_encoded_buffer(&buffer->encoded);
285
286 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &buffer->blocks, encoded_buffer, entry)
287 {
288 list_remove(&cur->entry);
289 free_encoded_buffer(cur);
290 heap_free(cur);
291 }
292 }
293
294 static HRESULT write_output_buffer(mxwriter *writer, const WCHAR *data, int len)
295 {
296 output_buffer *buffer = &writer->buffer;
297 encoded_buffer *buff;
298 unsigned int written;
299 int src_len;
300
301 if (!len || !*data)
302 return S_OK;
303
304 src_len = len == -1 ? strlenW(data) : len;
305 if (writer->dest)
306 {
307 buff = &buffer->encoded;
308
309 if (buffer->code_page == ~0)
310 {
311 unsigned int avail = buff->allocated - buff->written;
312
313 src_len *= sizeof(WCHAR);
314 written = min(avail, src_len);
315
316 /* fill internal buffer first */
317 if (avail)
318 {
319 memcpy(buff->data + buff->written, data, written);
320 data += written / sizeof(WCHAR);
321 buff->written += written;
322 avail -= written;
323 src_len -= written;
324 }
325
326 if (!avail)
327 {
328 IStream_Write(writer->dest, buff->data, buff->written, &written);
329 buff->written = 0;
330 if (src_len >= buff->allocated)
331 IStream_Write(writer->dest, data, src_len, &written);
332 else if (src_len)
333 {
334 memcpy(buff->data, data, src_len);
335 buff->written += src_len;
336 }
337 }
338 }
339 else
340 {
341 unsigned int avail = buff->allocated - buff->written;
342 int length;
343
344 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, NULL, 0, NULL, NULL);
345 if (avail >= length)
346 {
347 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL);
348 buff->written += length;
349 }
350 else
351 {
352 /* drain what we go so far */
353 if (buff->written)
354 {
355 IStream_Write(writer->dest, buff->data, buff->written, &written);
356 buff->written = 0;
357 avail = buff->allocated;
358 }
359
360 if (avail >= length)
361 {
362 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL);
363 buff->written += length;
364 }
365 else
366 {
367 char *mb;
368
369 /* if current chunk is larger than total buffer size, convert it at once using temporary allocated buffer */
370 mb = heap_alloc(length);
371 if (!mb)
372 return E_OUTOFMEMORY;
373
374 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, mb, length, NULL, NULL);
375 IStream_Write(writer->dest, mb, length, &written);
376 heap_free(mb);
377 }
378 }
379 }
380 }
381 /* When writer has no output set we have to accumulate everything to return it later in a form of BSTR.
382 To achieve that:
383
384 - fill a buffer already allocated as part of output buffer;
385 - when current buffer is full, allocate another one and switch to it; buffers themselves never grow,
386 but are linked together, with head pointing to first allocated buffer after initial one got filled;
387 - later during get_output() contents are concatenated by copying one after another to destination BSTR buffer,
388 that's returned to the client. */
389 else
390 {
391 /* select last used block */
392 if (list_empty(&buffer->blocks))
393 buff = &buffer->encoded;
394 else
395 buff = LIST_ENTRY(list_tail(&buffer->blocks), encoded_buffer, entry);
396
397 src_len *= sizeof(WCHAR);
398 while (src_len)
399 {
400 unsigned int avail = buff->allocated - buff->written;
401 unsigned int written = min(avail, src_len);
402
403 if (avail)
404 {
405 memcpy(buff->data + buff->written, data, written);
406 buff->written += written;
407 buffer->utf16_total += written;
408 src_len -= written;
409 }
410
411 /* alloc new block if needed and retry */
412 if (src_len)
413 {
414 encoded_buffer *next = heap_alloc(sizeof(*next));
415 HRESULT hr;
416
417 if (FAILED(hr = init_encoded_buffer(next))) {
418 heap_free(next);
419 return hr;
420 }
421
422 list_add_tail(&buffer->blocks, &next->entry);
423 buff = next;
424 }
425 }
426 }
427
428 return S_OK;
429 }
430
431 static HRESULT write_output_buffer_quoted(mxwriter *writer, const WCHAR *data, int len)
432 {
433 write_output_buffer(writer, quotW, 1);
434 write_output_buffer(writer, data, len);
435 write_output_buffer(writer, quotW, 1);
436
437 return S_OK;
438 }
439
440 /* frees buffer data, reallocates with a default lengths */
441 static void close_output_buffer(mxwriter *writer)
442 {
443 encoded_buffer *cur, *cur2;
444
445 heap_free(writer->buffer.encoded.data);
446
447 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &writer->buffer.blocks, encoded_buffer, entry)
448 {
449 list_remove(&cur->entry);
450 free_encoded_buffer(cur);
451 heap_free(cur);
452 }
453
454 init_encoded_buffer(&writer->buffer.encoded);
455 get_code_page(writer->xml_enc, &writer->buffer.code_page);
456 writer->buffer.utf16_total = 0;
457 list_init(&writer->buffer.blocks);
458 }
459
460 /* Escapes special characters like:
461 '<' -> "&lt;"
462 '&' -> "&amp;"
463 '"' -> "&quot;"
464 '>' -> "&gt;"
465
466 On call 'len' contains a length of 'str' in chars or -1 if it's null terminated.
467 After a call it's updated with actual new length if it wasn't -1 initially.
468 */
469 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
470 {
471 static const WCHAR ltW[] = {'&','l','t',';'};
472 static const WCHAR ampW[] = {'&','a','m','p',';'};
473 static const WCHAR equotW[] = {'&','q','u','o','t',';'};
474 static const WCHAR gtW[] = {'&','g','t',';'};
475
476 const int default_alloc = 100;
477 const int grow_thresh = 10;
478 int p = *len, conv_len;
479 WCHAR *ptr, *ret;
480
481 /* default buffer size to something if length is unknown */
482 conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
483 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
484
485 while (*str && p)
486 {
487 if (ptr - ret > conv_len - grow_thresh)
488 {
489 int written = ptr - ret;
490 conv_len *= 2;
491 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
492 ptr += written;
493 }
494
495 switch (*str)
496 {
497 case '<':
498 memcpy(ptr, ltW, sizeof(ltW));
499 ptr += sizeof(ltW)/sizeof(WCHAR);
500 break;
501 case '&':
502 memcpy(ptr, ampW, sizeof(ampW));
503 ptr += sizeof(ampW)/sizeof(WCHAR);
504 break;
505 case '>':
506 memcpy(ptr, gtW, sizeof(gtW));
507 ptr += sizeof(gtW)/sizeof(WCHAR);
508 break;
509 case '"':
510 if (mode == EscapeValue)
511 {
512 memcpy(ptr, equotW, sizeof(equotW));
513 ptr += sizeof(equotW)/sizeof(WCHAR);
514 break;
515 }
516 /* fallthrough for text mode */
517 default:
518 *ptr++ = *str;
519 break;
520 }
521
522 str++;
523 if (*len != -1) p--;
524 }
525
526 if (*len != -1) *len = ptr-ret;
527 *++ptr = 0;
528
529 return ret;
530 }
531
532 static void write_prolog_buffer(mxwriter *writer)
533 {
534 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
535 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
536 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
537 static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
538 static const WCHAR noW[] = {'n','o','\"','?','>'};
539
540 /* version */
541 write_output_buffer(writer, versionW, sizeof(versionW)/sizeof(WCHAR));
542 write_output_buffer_quoted(writer, writer->version, -1);
543
544 /* encoding */
545 write_output_buffer(writer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
546
547 if (writer->dest)
548 write_output_buffer(writer, writer->encoding, -1);
549 else
550 write_output_buffer(writer, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
551 write_output_buffer(writer, quotW, 1);
552
553 /* standalone */
554 write_output_buffer(writer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
555 if (writer->props[MXWriter_Standalone] == VARIANT_TRUE)
556 write_output_buffer(writer, yesW, sizeof(yesW)/sizeof(WCHAR));
557 else
558 write_output_buffer(writer, noW, sizeof(noW)/sizeof(WCHAR));
559
560 write_output_buffer(writer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
561 writer->newline = TRUE;
562 }
563
564 /* Attempts to the write data from the mxwriter's buffer to
565 * the destination stream (if there is one).
566 */
567 static HRESULT write_data_to_stream(mxwriter *writer)
568 {
569 encoded_buffer *buffer = &writer->buffer.encoded;
570 ULONG written = 0;
571
572 if (!writer->dest)
573 return S_OK;
574
575 if (buffer->written == 0)
576 {
577 if (writer->xml_enc == XmlEncoding_UTF8)
578 IStream_Write(writer->dest, buffer->data, 0, &written);
579 }
580 else
581 {
582 IStream_Write(writer->dest, buffer->data, buffer->written, &written);
583 buffer->written = 0;
584 }
585
586 return S_OK;
587 }
588
589 /* Newly added element start tag left unclosed cause for empty elements
590 we have to close it differently. */
591 static void close_element_starttag(mxwriter *writer)
592 {
593 static const WCHAR gtW[] = {'>'};
594 if (!writer->element) return;
595 write_output_buffer(writer, gtW, 1);
596 }
597
598 static void write_node_indent(mxwriter *writer)
599 {
600 static const WCHAR tabW[] = {'\t'};
601 int indent = writer->indent;
602
603 if (!writer->props[MXWriter_Indent] || writer->text)
604 {
605 writer->text = FALSE;
606 return;
607 }
608
609 /* This is to workaround PI output logic that always puts newline chars,
610 document prolog PI does that too. */
611 if (!writer->newline)
612 write_output_buffer(writer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
613 while (indent--)
614 write_output_buffer(writer, tabW, 1);
615
616 writer->newline = FALSE;
617 writer->text = FALSE;
618 }
619
620 static inline void writer_inc_indent(mxwriter *This)
621 {
622 This->indent++;
623 }
624
625 static inline void writer_dec_indent(mxwriter *This)
626 {
627 if (This->indent) This->indent--;
628 /* depth is decreased only when element is closed, meaning it's not a text node
629 at this point */
630 This->text = FALSE;
631 }
632
633 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
634 {
635 SysFreeString(This->element);
636 if (name)
637 This->element = len != -1 ? SysAllocStringLen(name, len) : SysAllocString(name);
638 else
639 This->element = NULL;
640 }
641
642 static inline HRESULT flush_output_buffer(mxwriter *This)
643 {
644 close_element_starttag(This);
645 set_element_name(This, NULL, 0);
646 This->cdata = FALSE;
647 return write_data_to_stream(This);
648 }
649
650 /* Resets the mxwriter's output buffer by closing it, then creating a new
651 * output buffer using the given encoding.
652 */
653 static inline void reset_output_buffer(mxwriter *This)
654 {
655 close_output_buffer(This);
656 }
657
658 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
659 {
660 writer->props[property] = value;
661 writer->prop_changed = TRUE;
662 return S_OK;
663 }
664
665 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
666 {
667 if (!value) return E_POINTER;
668 *value = writer->props[property];
669 return S_OK;
670 }
671
672 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
673 {
674 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
675 }
676
677 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
678 {
679 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
680 }
681
682 static inline mxwriter *impl_from_IVBSAXContentHandler(IVBSAXContentHandler *iface)
683 {
684 return CONTAINING_RECORD(iface, mxwriter, IVBSAXContentHandler_iface);
685 }
686
687 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
688 {
689 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
690 }
691
692 static inline mxwriter *impl_from_IVBSAXLexicalHandler(IVBSAXLexicalHandler *iface)
693 {
694 return CONTAINING_RECORD(iface, mxwriter, IVBSAXLexicalHandler_iface);
695 }
696
697 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
698 {
699 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
700 }
701
702 static inline mxwriter *impl_from_IVBSAXDeclHandler(IVBSAXDeclHandler *iface)
703 {
704 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDeclHandler_iface);
705 }
706
707 static inline mxwriter *impl_from_ISAXDTDHandler(ISAXDTDHandler *iface)
708 {
709 return CONTAINING_RECORD(iface, mxwriter, ISAXDTDHandler_iface);
710 }
711
712 static inline mxwriter *impl_from_IVBSAXDTDHandler(IVBSAXDTDHandler *iface)
713 {
714 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDTDHandler_iface);
715 }
716
717 static inline mxwriter *impl_from_ISAXErrorHandler(ISAXErrorHandler *iface)
718 {
719 return CONTAINING_RECORD(iface, mxwriter, ISAXErrorHandler_iface);
720 }
721
722 static inline mxwriter *impl_from_IVBSAXErrorHandler(IVBSAXErrorHandler *iface)
723 {
724 return CONTAINING_RECORD(iface, mxwriter, IVBSAXErrorHandler_iface);
725 }
726
727 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
728 {
729 mxwriter *This = impl_from_IMXWriter( iface );
730
731 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
732
733 *obj = NULL;
734
735 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
736 IsEqualGUID( riid, &IID_IDispatch ) ||
737 IsEqualGUID( riid, &IID_IUnknown ) )
738 {
739 *obj = &This->IMXWriter_iface;
740 }
741 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
742 {
743 *obj = &This->ISAXContentHandler_iface;
744 }
745 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
746 {
747 *obj = &This->ISAXLexicalHandler_iface;
748 }
749 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
750 {
751 *obj = &This->ISAXDeclHandler_iface;
752 }
753 else if ( IsEqualGUID( riid, &IID_ISAXDTDHandler ) )
754 {
755 *obj = &This->ISAXDTDHandler_iface;
756 }
757 else if ( IsEqualGUID( riid, &IID_ISAXErrorHandler ) )
758 {
759 *obj = &This->ISAXErrorHandler_iface;
760 }
761 else if ( IsEqualGUID( riid, &IID_IVBSAXDeclHandler ) )
762 {
763 *obj = &This->IVBSAXDeclHandler_iface;
764 }
765 else if ( IsEqualGUID( riid, &IID_IVBSAXLexicalHandler ) )
766 {
767 *obj = &This->IVBSAXLexicalHandler_iface;
768 }
769 else if ( IsEqualGUID( riid, &IID_IVBSAXContentHandler ) )
770 {
771 *obj = &This->IVBSAXContentHandler_iface;
772 }
773 else if ( IsEqualGUID( riid, &IID_IVBSAXDTDHandler ) )
774 {
775 *obj = &This->IVBSAXDTDHandler_iface;
776 }
777 else if ( IsEqualGUID( riid, &IID_IVBSAXErrorHandler ) )
778 {
779 *obj = &This->IVBSAXErrorHandler_iface;
780 }
781 else if (dispex_query_interface(&This->dispex, riid, obj))
782 {
783 return *obj ? S_OK : E_NOINTERFACE;
784 }
785 else
786 {
787 ERR("interface %s not implemented\n", debugstr_guid(riid));
788 *obj = NULL;
789 return E_NOINTERFACE;
790 }
791
792 IMXWriter_AddRef(iface);
793 return S_OK;
794 }
795
796 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
797 {
798 mxwriter *This = impl_from_IMXWriter( iface );
799 LONG ref = InterlockedIncrement(&This->ref);
800
801 TRACE("(%p)->(%d)\n", This, ref);
802
803 return ref;
804 }
805
806 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
807 {
808 mxwriter *This = impl_from_IMXWriter( iface );
809 ULONG ref = InterlockedDecrement(&This->ref);
810
811 TRACE("(%p)->(%d)\n", This, ref);
812
813 if(!ref)
814 {
815 /* Windows flushes the buffer when the interface is destroyed. */
816 flush_output_buffer(This);
817 free_output_buffer(&This->buffer);
818
819 if (This->dest) IStream_Release(This->dest);
820 SysFreeString(This->version);
821 SysFreeString(This->encoding);
822
823 SysFreeString(This->element);
824 heap_free(This);
825 }
826
827 return ref;
828 }
829
830 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
831 {
832 mxwriter *This = impl_from_IMXWriter( iface );
833 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
834 }
835
836 static HRESULT WINAPI mxwriter_GetTypeInfo(
837 IMXWriter *iface,
838 UINT iTInfo, LCID lcid,
839 ITypeInfo** ppTInfo )
840 {
841 mxwriter *This = impl_from_IMXWriter( iface );
842 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
843 iTInfo, lcid, ppTInfo);
844 }
845
846 static HRESULT WINAPI mxwriter_GetIDsOfNames(
847 IMXWriter *iface,
848 REFIID riid, LPOLESTR* rgszNames,
849 UINT cNames, LCID lcid, DISPID* rgDispId )
850 {
851 mxwriter *This = impl_from_IMXWriter( iface );
852 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
853 riid, rgszNames, cNames, lcid, rgDispId);
854 }
855
856 static HRESULT WINAPI mxwriter_Invoke(
857 IMXWriter *iface,
858 DISPID dispIdMember, REFIID riid, LCID lcid,
859 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
860 EXCEPINFO* pExcepInfo, UINT* puArgErr )
861 {
862 mxwriter *This = impl_from_IMXWriter( iface );
863 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
864 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
865 }
866
867 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
868 {
869 mxwriter *This = impl_from_IMXWriter( iface );
870 HRESULT hr;
871
872 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
873
874 hr = flush_output_buffer(This);
875 if (FAILED(hr))
876 return hr;
877
878 switch (V_VT(&dest))
879 {
880 case VT_EMPTY:
881 {
882 if (This->dest) IStream_Release(This->dest);
883 This->dest = NULL;
884 reset_output_buffer(This);
885 break;
886 }
887 case VT_UNKNOWN:
888 {
889 IStream *stream;
890
891 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
892 if (hr == S_OK)
893 {
894 /* Recreate the output buffer to make sure it's using the correct encoding. */
895 reset_output_buffer(This);
896
897 if (This->dest) IStream_Release(This->dest);
898 This->dest = stream;
899 break;
900 }
901
902 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
903 return E_NOTIMPL;
904 }
905 default:
906 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
907 return E_NOTIMPL;
908 }
909
910 return S_OK;
911 }
912
913 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
914 {
915 mxwriter *This = impl_from_IMXWriter( iface );
916
917 TRACE("(%p)->(%p)\n", This, dest);
918
919 if (!dest) return E_POINTER;
920
921 if (This->dest)
922 {
923 /* we only support IStream output so far */
924 V_VT(dest) = VT_UNKNOWN;
925 V_UNKNOWN(dest) = (IUnknown*)This->dest;
926 IStream_AddRef(This->dest);
927 }
928 else
929 {
930 encoded_buffer *buff;
931 char *dest_ptr;
932 HRESULT hr;
933
934 hr = flush_output_buffer(This);
935 if (FAILED(hr))
936 return hr;
937
938 V_VT(dest) = VT_BSTR;
939 V_BSTR(dest) = SysAllocStringLen(NULL, This->buffer.utf16_total / sizeof(WCHAR));
940 if (!V_BSTR(dest))
941 return E_OUTOFMEMORY;
942
943 dest_ptr = (char*)V_BSTR(dest);
944 buff = &This->buffer.encoded;
945
946 if (buff->written)
947 {
948 memcpy(dest_ptr, buff->data, buff->written);
949 dest_ptr += buff->written;
950 }
951
952 LIST_FOR_EACH_ENTRY(buff, &This->buffer.blocks, encoded_buffer, entry)
953 {
954 memcpy(dest_ptr, buff->data, buff->written);
955 dest_ptr += buff->written;
956 }
957 }
958
959 return S_OK;
960 }
961
962 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
963 {
964 mxwriter *This = impl_from_IMXWriter( iface );
965 xml_encoding enc;
966 HRESULT hr;
967
968 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
969
970 enc = parse_encoding_name(encoding);
971 if (enc == XmlEncoding_Unknown)
972 {
973 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
974 return E_INVALIDARG;
975 }
976
977 hr = flush_output_buffer(This);
978 if (FAILED(hr))
979 return hr;
980
981 SysReAllocString(&This->encoding, encoding);
982 This->xml_enc = enc;
983
984 TRACE("got encoding %d\n", This->xml_enc);
985 reset_output_buffer(This);
986 return S_OK;
987 }
988
989 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
990 {
991 mxwriter *This = impl_from_IMXWriter( iface );
992
993 TRACE("(%p)->(%p)\n", This, encoding);
994
995 if (!encoding) return E_POINTER;
996
997 *encoding = SysAllocString(This->encoding);
998 if (!*encoding) return E_OUTOFMEMORY;
999
1000 return S_OK;
1001 }
1002
1003 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
1004 {
1005 mxwriter *This = impl_from_IMXWriter( iface );
1006
1007 TRACE("(%p)->(%d)\n", This, value);
1008 return writer_set_property(This, MXWriter_BOM, value);
1009 }
1010
1011 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
1012 {
1013 mxwriter *This = impl_from_IMXWriter( iface );
1014
1015 TRACE("(%p)->(%p)\n", This, value);
1016 return writer_get_property(This, MXWriter_BOM, value);
1017 }
1018
1019 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
1020 {
1021 mxwriter *This = impl_from_IMXWriter( iface );
1022
1023 TRACE("(%p)->(%d)\n", This, value);
1024 return writer_set_property(This, MXWriter_Indent, value);
1025 }
1026
1027 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
1028 {
1029 mxwriter *This = impl_from_IMXWriter( iface );
1030
1031 TRACE("(%p)->(%p)\n", This, value);
1032 return writer_get_property(This, MXWriter_Indent, value);
1033 }
1034
1035 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
1036 {
1037 mxwriter *This = impl_from_IMXWriter( iface );
1038
1039 TRACE("(%p)->(%d)\n", This, value);
1040 return writer_set_property(This, MXWriter_Standalone, value);
1041 }
1042
1043 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
1044 {
1045 mxwriter *This = impl_from_IMXWriter( iface );
1046
1047 TRACE("(%p)->(%p)\n", This, value);
1048 return writer_get_property(This, MXWriter_Standalone, value);
1049 }
1050
1051 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
1052 {
1053 mxwriter *This = impl_from_IMXWriter( iface );
1054
1055 TRACE("(%p)->(%d)\n", This, value);
1056 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
1057 }
1058
1059 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
1060 {
1061 mxwriter *This = impl_from_IMXWriter( iface );
1062
1063 TRACE("(%p)->(%p)\n", This, value);
1064 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
1065 }
1066
1067 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
1068 {
1069 mxwriter *This = impl_from_IMXWriter( iface );
1070
1071 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
1072
1073 if (!version) return E_INVALIDARG;
1074
1075 SysFreeString(This->version);
1076 This->version = SysAllocString(version);
1077
1078 return S_OK;
1079 }
1080
1081 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
1082 {
1083 mxwriter *This = impl_from_IMXWriter( iface );
1084
1085 TRACE("(%p)->(%p)\n", This, version);
1086
1087 if (!version) return E_POINTER;
1088
1089 return return_bstr(This->version, version);
1090 }
1091
1092 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
1093 {
1094 mxwriter *This = impl_from_IMXWriter( iface );
1095
1096 TRACE("(%p)->(%d)\n", This, value);
1097 return writer_set_property(This, MXWriter_DisableEscaping, value);
1098 }
1099
1100 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
1101 {
1102 mxwriter *This = impl_from_IMXWriter( iface );
1103
1104 TRACE("(%p)->(%p)\n", This, value);
1105 return writer_get_property(This, MXWriter_DisableEscaping, value);
1106 }
1107
1108 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
1109 {
1110 mxwriter *This = impl_from_IMXWriter( iface );
1111 TRACE("(%p)\n", This);
1112 return flush_output_buffer(This);
1113 }
1114
1115 static const struct IMXWriterVtbl MXWriterVtbl =
1116 {
1117 mxwriter_QueryInterface,
1118 mxwriter_AddRef,
1119 mxwriter_Release,
1120 mxwriter_GetTypeInfoCount,
1121 mxwriter_GetTypeInfo,
1122 mxwriter_GetIDsOfNames,
1123 mxwriter_Invoke,
1124 mxwriter_put_output,
1125 mxwriter_get_output,
1126 mxwriter_put_encoding,
1127 mxwriter_get_encoding,
1128 mxwriter_put_byteOrderMark,
1129 mxwriter_get_byteOrderMark,
1130 mxwriter_put_indent,
1131 mxwriter_get_indent,
1132 mxwriter_put_standalone,
1133 mxwriter_get_standalone,
1134 mxwriter_put_omitXMLDeclaration,
1135 mxwriter_get_omitXMLDeclaration,
1136 mxwriter_put_version,
1137 mxwriter_get_version,
1138 mxwriter_put_disableOutputEscaping,
1139 mxwriter_get_disableOutputEscaping,
1140 mxwriter_flush
1141 };
1142
1143 /*** ISAXContentHandler ***/
1144 static HRESULT WINAPI SAXContentHandler_QueryInterface(
1145 ISAXContentHandler *iface,
1146 REFIID riid,
1147 void **obj)
1148 {
1149 mxwriter *This = impl_from_ISAXContentHandler( iface );
1150 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1151 }
1152
1153 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
1154 {
1155 mxwriter *This = impl_from_ISAXContentHandler( iface );
1156 return IMXWriter_AddRef(&This->IMXWriter_iface);
1157 }
1158
1159 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
1160 {
1161 mxwriter *This = impl_from_ISAXContentHandler( iface );
1162 return IMXWriter_Release(&This->IMXWriter_iface);
1163 }
1164
1165 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
1166 ISAXContentHandler *iface,
1167 ISAXLocator *locator)
1168 {
1169 mxwriter *This = impl_from_ISAXContentHandler( iface );
1170 FIXME("(%p)->(%p)\n", This, locator);
1171 return E_NOTIMPL;
1172 }
1173
1174 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
1175 {
1176 mxwriter *This = impl_from_ISAXContentHandler( iface );
1177
1178 TRACE("(%p)\n", This);
1179
1180 /* If properties have been changed since the last "endDocument" call
1181 * we need to reset the output buffer. If we don't the output buffer
1182 * could end up with multiple XML documents in it, plus this seems to
1183 * be how Windows works.
1184 */
1185 if (This->prop_changed) {
1186 reset_output_buffer(This);
1187 This->prop_changed = FALSE;
1188 }
1189
1190 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
1191
1192 write_prolog_buffer(This);
1193
1194 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
1195 static const char utf16BOM[] = {0xff,0xfe};
1196
1197 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
1198 /* Windows passes a NULL pointer as the pcbWritten parameter and
1199 * ignores any error codes returned from this Write call.
1200 */
1201 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
1202 }
1203
1204 return S_OK;
1205 }
1206
1207 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
1208 {
1209 mxwriter *This = impl_from_ISAXContentHandler( iface );
1210 TRACE("(%p)\n", This);
1211 This->prop_changed = FALSE;
1212 return flush_output_buffer(This);
1213 }
1214
1215 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
1216 ISAXContentHandler *iface,
1217 const WCHAR *prefix,
1218 int nprefix,
1219 const WCHAR *uri,
1220 int nuri)
1221 {
1222 mxwriter *This = impl_from_ISAXContentHandler( iface );
1223 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
1224 return S_OK;
1225 }
1226
1227 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
1228 ISAXContentHandler *iface,
1229 const WCHAR *prefix,
1230 int nprefix)
1231 {
1232 mxwriter *This = impl_from_ISAXContentHandler( iface );
1233 TRACE("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
1234 return S_OK;
1235 }
1236
1237 static void mxwriter_write_attribute(mxwriter *writer, const WCHAR *qname, int qname_len,
1238 const WCHAR *value, int value_len, BOOL escape)
1239 {
1240 static const WCHAR eqW[] = {'='};
1241
1242 /* space separator in front of every attribute */
1243 write_output_buffer(writer, spaceW, 1);
1244 write_output_buffer(writer, qname, qname_len);
1245 write_output_buffer(writer, eqW, 1);
1246
1247 if (escape)
1248 {
1249 WCHAR *escaped = get_escaped_string(value, EscapeValue, &value_len);
1250 write_output_buffer_quoted(writer, escaped, value_len);
1251 heap_free(escaped);
1252 }
1253 else
1254 write_output_buffer_quoted(writer, value, value_len);
1255 }
1256
1257 static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int len)
1258 {
1259 static const WCHAR ltW[] = {'<'};
1260
1261 close_element_starttag(writer);
1262 set_element_name(writer, qname ? qname : emptyW, qname ? len : 0);
1263
1264 write_node_indent(writer);
1265
1266 write_output_buffer(writer, ltW, 1);
1267 write_output_buffer(writer, qname ? qname : emptyW, qname ? len : 0);
1268 writer_inc_indent(writer);
1269 }
1270
1271 static HRESULT WINAPI SAXContentHandler_startElement(
1272 ISAXContentHandler *iface,
1273 const WCHAR *namespaceUri,
1274 int nnamespaceUri,
1275 const WCHAR *local_name,
1276 int nlocal_name,
1277 const WCHAR *QName,
1278 int nQName,
1279 ISAXAttributes *attr)
1280 {
1281 mxwriter *This = impl_from_ISAXContentHandler( iface );
1282
1283 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
1284 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
1285
1286 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1287 (nQName == -1 && This->class_version == MSXML6))
1288 return E_INVALIDARG;
1289
1290 mxwriter_write_starttag(This, QName, nQName);
1291
1292 if (attr)
1293 {
1294 int length, i, escape;
1295 HRESULT hr;
1296
1297 hr = ISAXAttributes_getLength(attr, &length);
1298 if (FAILED(hr)) return hr;
1299
1300 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
1301 (This->class_version == MSXML4 || This->class_version == MSXML6);
1302
1303 for (i = 0; i < length; i++)
1304 {
1305 int qname_len = 0, value_len = 0;
1306 const WCHAR *qname, *value;
1307
1308 hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len);
1309 if (FAILED(hr)) return hr;
1310
1311 hr = ISAXAttributes_getValue(attr, i, &value, &value_len);
1312 if (FAILED(hr)) return hr;
1313
1314 mxwriter_write_attribute(This, qname, qname_len, value, value_len, escape);
1315 }
1316 }
1317
1318 return S_OK;
1319 }
1320
1321 static HRESULT WINAPI SAXContentHandler_endElement(
1322 ISAXContentHandler *iface,
1323 const WCHAR *namespaceUri,
1324 int nnamespaceUri,
1325 const WCHAR * local_name,
1326 int nlocal_name,
1327 const WCHAR *QName,
1328 int nQName)
1329 {
1330 mxwriter *This = impl_from_ISAXContentHandler( iface );
1331
1332 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1333 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1334
1335 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1336 (nQName == -1 && This->class_version == MSXML6))
1337 return E_INVALIDARG;
1338
1339 writer_dec_indent(This);
1340
1341 if (This->element)
1342 {
1343 static const WCHAR closeW[] = {'/','>'};
1344 write_output_buffer(This, closeW, 2);
1345 }
1346 else
1347 {
1348 static const WCHAR closetagW[] = {'<','/'};
1349 static const WCHAR gtW[] = {'>'};
1350
1351 write_node_indent(This);
1352 write_output_buffer(This, closetagW, 2);
1353 write_output_buffer(This, QName, nQName);
1354 write_output_buffer(This, gtW, 1);
1355 }
1356
1357 set_element_name(This, NULL, 0);
1358
1359 return S_OK;
1360 }
1361
1362 static HRESULT WINAPI SAXContentHandler_characters(
1363 ISAXContentHandler *iface,
1364 const WCHAR *chars,
1365 int nchars)
1366 {
1367 mxwriter *This = impl_from_ISAXContentHandler( iface );
1368
1369 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1370
1371 if (!chars) return E_INVALIDARG;
1372
1373 close_element_starttag(This);
1374 set_element_name(This, NULL, 0);
1375
1376 if (!This->cdata)
1377 This->text = TRUE;
1378
1379 if (nchars)
1380 {
1381 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
1382 write_output_buffer(This, chars, nchars);
1383 else
1384 {
1385 int len = nchars;
1386 WCHAR *escaped;
1387
1388 escaped = get_escaped_string(chars, EscapeText, &len);
1389 write_output_buffer(This, escaped, len);
1390 heap_free(escaped);
1391 }
1392 }
1393
1394 return S_OK;
1395 }
1396
1397 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1398 ISAXContentHandler *iface,
1399 const WCHAR *chars,
1400 int nchars)
1401 {
1402 mxwriter *This = impl_from_ISAXContentHandler( iface );
1403
1404 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1405
1406 if (!chars) return E_INVALIDARG;
1407
1408 write_output_buffer(This, chars, nchars);
1409
1410 return S_OK;
1411 }
1412
1413 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1414 ISAXContentHandler *iface,
1415 const WCHAR *target,
1416 int ntarget,
1417 const WCHAR *data,
1418 int ndata)
1419 {
1420 mxwriter *This = impl_from_ISAXContentHandler( iface );
1421 static const WCHAR openpiW[] = {'<','?'};
1422 static const WCHAR closepiW[] = {'?','>','\r','\n'};
1423
1424 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1425
1426 if (!target) return E_INVALIDARG;
1427
1428 write_node_indent(This);
1429 write_output_buffer(This, openpiW, sizeof(openpiW)/sizeof(WCHAR));
1430
1431 if (*target)
1432 write_output_buffer(This, target, ntarget);
1433
1434 if (data && *data && ndata)
1435 {
1436 write_output_buffer(This, spaceW, 1);
1437 write_output_buffer(This, data, ndata);
1438 }
1439
1440 write_output_buffer(This, closepiW, sizeof(closepiW)/sizeof(WCHAR));
1441 This->newline = TRUE;
1442
1443 return S_OK;
1444 }
1445
1446 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1447 ISAXContentHandler *iface,
1448 const WCHAR *name,
1449 int nname)
1450 {
1451 mxwriter *This = impl_from_ISAXContentHandler( iface );
1452 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1453 return E_NOTIMPL;
1454 }
1455
1456 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1457 {
1458 SAXContentHandler_QueryInterface,
1459 SAXContentHandler_AddRef,
1460 SAXContentHandler_Release,
1461 SAXContentHandler_putDocumentLocator,
1462 SAXContentHandler_startDocument,
1463 SAXContentHandler_endDocument,
1464 SAXContentHandler_startPrefixMapping,
1465 SAXContentHandler_endPrefixMapping,
1466 SAXContentHandler_startElement,
1467 SAXContentHandler_endElement,
1468 SAXContentHandler_characters,
1469 SAXContentHandler_ignorableWhitespace,
1470 SAXContentHandler_processingInstruction,
1471 SAXContentHandler_skippedEntity
1472 };
1473
1474 /*** ISAXLexicalHandler ***/
1475 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1476 REFIID riid, void **obj)
1477 {
1478 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1479 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1480 }
1481
1482 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1483 {
1484 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1485 return IMXWriter_AddRef(&This->IMXWriter_iface);
1486 }
1487
1488 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1489 {
1490 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1491 return IMXWriter_Release(&This->IMXWriter_iface);
1492 }
1493
1494 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1495 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1496 const WCHAR *systemId, int systemId_len)
1497 {
1498 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1499 static const WCHAR openintW[] = {'[','\r','\n'};
1500
1501 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1502
1503 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1504 debugstr_wn(systemId, systemId_len));
1505
1506 if (!name) return E_INVALIDARG;
1507
1508 write_output_buffer(This, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1509
1510 if (*name)
1511 {
1512 write_output_buffer(This, name, name_len);
1513 write_output_buffer(This, spaceW, 1);
1514 }
1515
1516 if (publicId)
1517 {
1518 write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
1519 write_output_buffer_quoted(This, publicId, publicId_len);
1520
1521 if (!systemId) return E_INVALIDARG;
1522
1523 if (*publicId)
1524 write_output_buffer(This, spaceW, 1);
1525
1526 write_output_buffer_quoted(This, systemId, systemId_len);
1527
1528 if (*systemId)
1529 write_output_buffer(This, spaceW, 1);
1530 }
1531 else if (systemId)
1532 {
1533 write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
1534 write_output_buffer_quoted(This, systemId, systemId_len);
1535 if (*systemId)
1536 write_output_buffer(This, spaceW, 1);
1537 }
1538
1539 write_output_buffer(This, openintW, sizeof(openintW)/sizeof(WCHAR));
1540
1541 return S_OK;
1542 }
1543
1544 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1545 {
1546 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1547 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1548
1549 TRACE("(%p)\n", This);
1550
1551 write_output_buffer(This, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1552
1553 return S_OK;
1554 }
1555
1556 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1557 {
1558 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1559 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1560 return E_NOTIMPL;
1561 }
1562
1563 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1564 {
1565 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1566 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1567 return E_NOTIMPL;
1568 }
1569
1570 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1571 {
1572 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1573 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1574
1575 TRACE("(%p)\n", This);
1576
1577 write_node_indent(This);
1578 write_output_buffer(This, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1579 This->cdata = TRUE;
1580
1581 return S_OK;
1582 }
1583
1584 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1585 {
1586 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1587 static const WCHAR ecdataW[] = {']',']','>'};
1588
1589 TRACE("(%p)\n", This);
1590
1591 write_output_buffer(This, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1592 This->cdata = FALSE;
1593
1594 return S_OK;
1595 }
1596
1597 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1598 {
1599 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1600 static const WCHAR copenW[] = {'<','!','-','-'};
1601 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1602
1603 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1604
1605 if (!chars) return E_INVALIDARG;
1606
1607 close_element_starttag(This);
1608 write_node_indent(This);
1609
1610 write_output_buffer(This, copenW, sizeof(copenW)/sizeof(WCHAR));
1611 if (nchars)
1612 write_output_buffer(This, chars, nchars);
1613 write_output_buffer(This, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1614
1615 return S_OK;
1616 }
1617
1618 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1619 {
1620 SAXLexicalHandler_QueryInterface,
1621 SAXLexicalHandler_AddRef,
1622 SAXLexicalHandler_Release,
1623 SAXLexicalHandler_startDTD,
1624 SAXLexicalHandler_endDTD,
1625 SAXLexicalHandler_startEntity,
1626 SAXLexicalHandler_endEntity,
1627 SAXLexicalHandler_startCDATA,
1628 SAXLexicalHandler_endCDATA,
1629 SAXLexicalHandler_comment
1630 };
1631
1632 /*** ISAXDeclHandler ***/
1633 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1634 REFIID riid, void **obj)
1635 {
1636 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1637 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1638 }
1639
1640 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1641 {
1642 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1643 return IMXWriter_AddRef(&This->IMXWriter_iface);
1644 }
1645
1646 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1647 {
1648 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1649 return IMXWriter_Release(&This->IMXWriter_iface);
1650 }
1651
1652 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1653 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1654 {
1655 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1656 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1657
1658 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1659 debugstr_wn(model, n_model), n_model);
1660
1661 if (!name || !model) return E_INVALIDARG;
1662
1663 write_output_buffer(This, elementW, sizeof(elementW)/sizeof(WCHAR));
1664 if (n_name) {
1665 write_output_buffer(This, name, n_name);
1666 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1667 }
1668 if (n_model)
1669 write_output_buffer(This, model, n_model);
1670 write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1671
1672 return S_OK;
1673 }
1674
1675 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1676 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1677 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1678 const WCHAR *value, int n_value)
1679 {
1680 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1681 static const WCHAR attlistW[] = {'<','!','A','T','T','L','I','S','T',' '};
1682 static const WCHAR closetagW[] = {'>','\r','\n'};
1683
1684 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element,
1685 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1686 debugstr_wn(value, n_value), n_value);
1687
1688 write_output_buffer(This, attlistW, sizeof(attlistW)/sizeof(WCHAR));
1689 if (n_element) {
1690 write_output_buffer(This, element, n_element);
1691 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1692 }
1693
1694 if (n_attr) {
1695 write_output_buffer(This, attr, n_attr);
1696 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1697 }
1698
1699 if (n_type) {
1700 write_output_buffer(This, type, n_type);
1701 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1702 }
1703
1704 if (n_default) {
1705 write_output_buffer(This, Default, n_default);
1706 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1707 }
1708
1709 if (n_value)
1710 write_output_buffer_quoted(This, value, n_value);
1711
1712 write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1713
1714 return S_OK;
1715 }
1716
1717 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1718 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1719 {
1720 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1721
1722 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1723 debugstr_wn(value, n_value), n_value);
1724
1725 if (!name || !value) return E_INVALIDARG;
1726
1727 write_output_buffer(This, entityW, sizeof(entityW)/sizeof(WCHAR));
1728 if (n_name) {
1729 write_output_buffer(This, name, n_name);
1730 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1731 }
1732
1733 if (n_value)
1734 write_output_buffer_quoted(This, value, n_value);
1735
1736 write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1737
1738 return S_OK;
1739 }
1740
1741 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1742 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1743 const WCHAR *systemId, int n_systemId)
1744 {
1745 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1746
1747 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1748 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1749
1750 if (!name || !systemId) return E_INVALIDARG;
1751
1752 write_output_buffer(This, entityW, sizeof(entityW)/sizeof(WCHAR));
1753 if (n_name) {
1754 write_output_buffer(This, name, n_name);
1755 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1756 }
1757
1758 if (publicId)
1759 {
1760 write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
1761 write_output_buffer_quoted(This, publicId, n_publicId);
1762 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1763 write_output_buffer_quoted(This, systemId, n_systemId);
1764 }
1765 else
1766 {
1767 write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
1768 write_output_buffer_quoted(This, systemId, n_systemId);
1769 }
1770
1771 write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1772
1773 return S_OK;
1774 }
1775
1776 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1777 SAXDeclHandler_QueryInterface,
1778 SAXDeclHandler_AddRef,
1779 SAXDeclHandler_Release,
1780 SAXDeclHandler_elementDecl,
1781 SAXDeclHandler_attributeDecl,
1782 SAXDeclHandler_internalEntityDecl,
1783 SAXDeclHandler_externalEntityDecl
1784 };
1785
1786 /*** IVBSAXDeclHandler ***/
1787 static HRESULT WINAPI VBSAXDeclHandler_QueryInterface(IVBSAXDeclHandler *iface,
1788 REFIID riid, void **obj)
1789 {
1790 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1791 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1792 }
1793
1794 static ULONG WINAPI VBSAXDeclHandler_AddRef(IVBSAXDeclHandler *iface)
1795 {
1796 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1797 return IMXWriter_AddRef(&This->IMXWriter_iface);
1798 }
1799
1800 static ULONG WINAPI VBSAXDeclHandler_Release(IVBSAXDeclHandler *iface)
1801 {
1802 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1803 return IMXWriter_Release(&This->IMXWriter_iface);
1804 }
1805
1806 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfoCount(IVBSAXDeclHandler *iface, UINT* pctinfo)
1807 {
1808 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1809 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
1810 }
1811
1812 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfo(IVBSAXDeclHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1813 {
1814 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1815 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
1816 }
1817
1818 static HRESULT WINAPI VBSAXDeclHandler_GetIDsOfNames(IVBSAXDeclHandler *iface, REFIID riid, LPOLESTR* rgszNames,
1819 UINT cNames, LCID lcid, DISPID* rgDispId )
1820 {
1821 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1822 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
1823 }
1824
1825 static HRESULT WINAPI VBSAXDeclHandler_Invoke(IVBSAXDeclHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1826 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
1827 {
1828 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1829 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
1830 pExcepInfo, puArgErr);
1831 }
1832
1833 static HRESULT WINAPI VBSAXDeclHandler_elementDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *model)
1834 {
1835 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1836
1837 TRACE("(%p)->(%p %p)\n", This, name, model);
1838
1839 if (!name || !model)
1840 return E_POINTER;
1841
1842 return ISAXDeclHandler_elementDecl(&This->ISAXDeclHandler_iface, *name, -1, *model, -1);
1843 }
1844
1845 static HRESULT WINAPI VBSAXDeclHandler_attributeDecl(IVBSAXDeclHandler *iface,
1846 BSTR *element, BSTR *attr, BSTR *type, BSTR *default_value, BSTR *value)
1847 {
1848 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1849
1850 TRACE("(%p)->(%p %p %p %p %p)\n", This, element, attr, type, default_value, value);
1851
1852 if (!element || !attr || !type || !default_value || !value)
1853 return E_POINTER;
1854
1855 return ISAXDeclHandler_attributeDecl(&This->ISAXDeclHandler_iface, *element, -1, *attr, -1, *type, -1,
1856 *default_value, -1, *value, -1);
1857 }
1858
1859 static HRESULT WINAPI VBSAXDeclHandler_internalEntityDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *value)
1860 {
1861 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1862
1863 TRACE("(%p)->(%p %p)\n", This, name, value);
1864
1865 if (!name || !value)
1866 return E_POINTER;
1867
1868 return ISAXDeclHandler_internalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *value, -1);
1869 }
1870
1871 static HRESULT WINAPI VBSAXDeclHandler_externalEntityDecl(IVBSAXDeclHandler *iface,
1872 BSTR *name, BSTR *publicid, BSTR *systemid)
1873 {
1874 mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
1875
1876 TRACE("(%p)->(%p %p %p)\n", This, name, publicid, systemid);
1877
1878 if (!name || !publicid || !systemid)
1879 return E_POINTER;
1880
1881 return ISAXDeclHandler_externalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *publicid, -1, *systemid, -1);
1882 }
1883
1884 static const IVBSAXDeclHandlerVtbl VBSAXDeclHandlerVtbl = {
1885 VBSAXDeclHandler_QueryInterface,
1886 VBSAXDeclHandler_AddRef,
1887 VBSAXDeclHandler_Release,
1888 VBSAXDeclHandler_GetTypeInfoCount,
1889 VBSAXDeclHandler_GetTypeInfo,
1890 VBSAXDeclHandler_GetIDsOfNames,
1891 VBSAXDeclHandler_Invoke,
1892 VBSAXDeclHandler_elementDecl,
1893 VBSAXDeclHandler_attributeDecl,
1894 VBSAXDeclHandler_internalEntityDecl,
1895 VBSAXDeclHandler_externalEntityDecl
1896 };
1897
1898 /*** IVBSAXLexicalHandler ***/
1899 static HRESULT WINAPI VBSAXLexicalHandler_QueryInterface(IVBSAXLexicalHandler *iface,
1900 REFIID riid, void **obj)
1901 {
1902 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1903 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1904 }
1905
1906 static ULONG WINAPI VBSAXLexicalHandler_AddRef(IVBSAXLexicalHandler *iface)
1907 {
1908 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1909 return IMXWriter_AddRef(&This->IMXWriter_iface);
1910 }
1911
1912 static ULONG WINAPI VBSAXLexicalHandler_Release(IVBSAXLexicalHandler *iface)
1913 {
1914 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1915 return IMXWriter_Release(&This->IMXWriter_iface);
1916 }
1917
1918 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfoCount(IVBSAXLexicalHandler *iface, UINT* pctinfo)
1919 {
1920 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1921 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
1922 }
1923
1924 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfo(IVBSAXLexicalHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1925 {
1926 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1927 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
1928 }
1929
1930 static HRESULT WINAPI VBSAXLexicalHandler_GetIDsOfNames(IVBSAXLexicalHandler *iface, REFIID riid, LPOLESTR* rgszNames,
1931 UINT cNames, LCID lcid, DISPID* rgDispId )
1932 {
1933 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1934 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
1935 }
1936
1937 static HRESULT WINAPI VBSAXLexicalHandler_Invoke(IVBSAXLexicalHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1938 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
1939 {
1940 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1941 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
1942 pExcepInfo, puArgErr);
1943 }
1944
1945 static HRESULT WINAPI VBSAXLexicalHandler_startDTD(IVBSAXLexicalHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
1946 {
1947 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1948
1949 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
1950
1951 if (!name || !publicId || !systemId)
1952 return E_POINTER;
1953
1954 return ISAXLexicalHandler_startDTD(&This->ISAXLexicalHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
1955 }
1956
1957 static HRESULT WINAPI VBSAXLexicalHandler_endDTD(IVBSAXLexicalHandler *iface)
1958 {
1959 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1960 return ISAXLexicalHandler_endDTD(&This->ISAXLexicalHandler_iface);
1961 }
1962
1963 static HRESULT WINAPI VBSAXLexicalHandler_startEntity(IVBSAXLexicalHandler *iface, BSTR *name)
1964 {
1965 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1966
1967 TRACE("(%p)->(%p)\n", This, name);
1968
1969 if (!name)
1970 return E_POINTER;
1971
1972 return ISAXLexicalHandler_startEntity(&This->ISAXLexicalHandler_iface, *name, -1);
1973 }
1974
1975 static HRESULT WINAPI VBSAXLexicalHandler_endEntity(IVBSAXLexicalHandler *iface, BSTR *name)
1976 {
1977 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1978
1979 TRACE("(%p)->(%p)\n", This, name);
1980
1981 if (!name)
1982 return E_POINTER;
1983
1984 return ISAXLexicalHandler_endEntity(&This->ISAXLexicalHandler_iface, *name, -1);
1985 }
1986
1987 static HRESULT WINAPI VBSAXLexicalHandler_startCDATA(IVBSAXLexicalHandler *iface)
1988 {
1989 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1990 return ISAXLexicalHandler_startCDATA(&This->ISAXLexicalHandler_iface);
1991 }
1992
1993 static HRESULT WINAPI VBSAXLexicalHandler_endCDATA(IVBSAXLexicalHandler *iface)
1994 {
1995 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
1996 return ISAXLexicalHandler_endCDATA(&This->ISAXLexicalHandler_iface);
1997 }
1998
1999 static HRESULT WINAPI VBSAXLexicalHandler_comment(IVBSAXLexicalHandler *iface, BSTR *chars)
2000 {
2001 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
2002
2003 TRACE("(%p)->(%p)\n", This, chars);
2004
2005 if (!chars)
2006 return E_POINTER;
2007
2008 return ISAXLexicalHandler_comment(&This->ISAXLexicalHandler_iface, *chars, -1);
2009 }
2010
2011 static const IVBSAXLexicalHandlerVtbl VBSAXLexicalHandlerVtbl = {
2012 VBSAXLexicalHandler_QueryInterface,
2013 VBSAXLexicalHandler_AddRef,
2014 VBSAXLexicalHandler_Release,
2015 VBSAXLexicalHandler_GetTypeInfoCount,
2016 VBSAXLexicalHandler_GetTypeInfo,
2017 VBSAXLexicalHandler_GetIDsOfNames,
2018 VBSAXLexicalHandler_Invoke,
2019 VBSAXLexicalHandler_startDTD,
2020 VBSAXLexicalHandler_endDTD,
2021 VBSAXLexicalHandler_startEntity,
2022 VBSAXLexicalHandler_endEntity,
2023 VBSAXLexicalHandler_startCDATA,
2024 VBSAXLexicalHandler_endCDATA,
2025 VBSAXLexicalHandler_comment
2026 };
2027
2028 /*** IVBSAXContentHandler ***/
2029 static HRESULT WINAPI VBSAXContentHandler_QueryInterface(IVBSAXContentHandler *iface, REFIID riid, void **obj)
2030 {
2031 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2032 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2033 }
2034
2035 static ULONG WINAPI VBSAXContentHandler_AddRef(IVBSAXContentHandler *iface)
2036 {
2037 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2038 return IMXWriter_AddRef(&This->IMXWriter_iface);
2039 }
2040
2041 static ULONG WINAPI VBSAXContentHandler_Release(IVBSAXContentHandler *iface)
2042 {
2043 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2044 return IMXWriter_Release(&This->IMXWriter_iface);
2045 }
2046
2047 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfoCount(IVBSAXContentHandler *iface, UINT* pctinfo)
2048 {
2049 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2050 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
2051 }
2052
2053 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfo(IVBSAXContentHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2054 {
2055 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2056 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
2057 }
2058
2059 static HRESULT WINAPI VBSAXContentHandler_GetIDsOfNames(IVBSAXContentHandler *iface, REFIID riid, LPOLESTR* rgszNames,
2060 UINT cNames, LCID lcid, DISPID* rgDispId )
2061 {
2062 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2063 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
2064 }
2065
2066 static HRESULT WINAPI VBSAXContentHandler_Invoke(IVBSAXContentHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
2067 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
2068 {
2069 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2070 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
2071 pExcepInfo, puArgErr);
2072 }
2073
2074 static HRESULT WINAPI VBSAXContentHandler_putref_documentLocator(IVBSAXContentHandler *iface, IVBSAXLocator *locator)
2075 {
2076 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2077 TRACE("(%p)->(%p)\n", This, locator);
2078 return S_OK;
2079 }
2080
2081 static HRESULT WINAPI VBSAXContentHandler_startDocument(IVBSAXContentHandler *iface)
2082 {
2083 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2084 return ISAXContentHandler_startDocument(&This->ISAXContentHandler_iface);
2085 }
2086
2087 static HRESULT WINAPI VBSAXContentHandler_endDocument(IVBSAXContentHandler *iface)
2088 {
2089 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2090 return ISAXContentHandler_endDocument(&This->ISAXContentHandler_iface);
2091 }
2092
2093 static HRESULT WINAPI VBSAXContentHandler_startPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix, BSTR *uri)
2094 {
2095 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2096
2097 TRACE("(%p)->(%p %p)\n", This, prefix, uri);
2098
2099 if (!prefix || !uri)
2100 return E_POINTER;
2101
2102 return ISAXContentHandler_startPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1, *uri, -1);
2103 }
2104
2105 static HRESULT WINAPI VBSAXContentHandler_endPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix)
2106 {
2107 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2108
2109 TRACE("(%p)->(%p)\n", This, prefix);
2110
2111 if (!prefix)
2112 return E_POINTER;
2113
2114 return ISAXContentHandler_endPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1);
2115 }
2116
2117 static HRESULT WINAPI VBSAXContentHandler_startElement(IVBSAXContentHandler *iface,
2118 BSTR *namespaceURI, BSTR *localName, BSTR *QName, IVBSAXAttributes *attrs)
2119 {
2120 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2121
2122 TRACE("(%p)->(%p %p %p %p)\n", This, namespaceURI, localName, QName, attrs);
2123
2124 if (!namespaceURI || !localName || !QName)
2125 return E_POINTER;
2126
2127 TRACE("(%s %s %s)\n", debugstr_w(*namespaceURI), debugstr_w(*localName), debugstr_w(*QName));
2128
2129 mxwriter_write_starttag(This, *QName, SysStringLen(*QName));
2130
2131 if (attrs)
2132 {
2133 int length, i, escape;
2134 HRESULT hr;
2135
2136 hr = IVBSAXAttributes_get_length(attrs, &length);
2137 if (FAILED(hr)) return hr;
2138
2139 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
2140 (This->class_version == MSXML4 || This->class_version == MSXML6);
2141
2142 for (i = 0; i < length; i++)
2143 {
2144 BSTR qname, value;
2145
2146 hr = IVBSAXAttributes_getQName(attrs, i, &qname);
2147 if (FAILED(hr)) return hr;
2148
2149 hr = IVBSAXAttributes_getValue(attrs, i, &value);
2150 if (FAILED(hr))
2151 {
2152 SysFreeString(qname);
2153 return hr;
2154 }
2155
2156 mxwriter_write_attribute(This, qname, SysStringLen(qname), value, SysStringLen(value), escape);
2157 SysFreeString(qname);
2158 SysFreeString(value);
2159 }
2160 }
2161
2162 return S_OK;
2163 }
2164
2165 static HRESULT WINAPI VBSAXContentHandler_endElement(IVBSAXContentHandler *iface, BSTR *namespaceURI,
2166 BSTR *localName, BSTR *QName)
2167 {
2168 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2169
2170 TRACE("(%p)->(%p %p %p)\n", This, namespaceURI, localName, QName);
2171
2172 if (!namespaceURI || !localName || !QName)
2173 return E_POINTER;
2174
2175 return ISAXContentHandler_endElement(&This->ISAXContentHandler_iface,
2176 *namespaceURI, SysStringLen(*namespaceURI),
2177 *localName, SysStringLen(*localName),
2178 *QName, SysStringLen(*QName));
2179 }
2180
2181 static HRESULT WINAPI VBSAXContentHandler_characters(IVBSAXContentHandler *iface, BSTR *chars)
2182 {
2183 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2184
2185 TRACE("(%p)->(%p)\n", This, chars);
2186
2187 if (!chars)
2188 return E_POINTER;
2189
2190 return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, -1);
2191 }
2192
2193 static HRESULT WINAPI VBSAXContentHandler_ignorableWhitespace(IVBSAXContentHandler *iface, BSTR *chars)
2194 {
2195 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2196
2197 TRACE("(%p)->(%p)\n", This, chars);
2198
2199 if (!chars)
2200 return E_POINTER;
2201
2202 return ISAXContentHandler_ignorableWhitespace(&This->ISAXContentHandler_iface, *chars, -1);
2203 }
2204
2205 static HRESULT WINAPI VBSAXContentHandler_processingInstruction(IVBSAXContentHandler *iface,
2206 BSTR *target, BSTR *data)
2207 {
2208 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2209
2210 TRACE("(%p)->(%p %p)\n", This, target, data);
2211
2212 if (!target || !data)
2213 return E_POINTER;
2214
2215 return ISAXContentHandler_processingInstruction(&This->ISAXContentHandler_iface, *target, -1, *data, -1);
2216 }
2217
2218 static HRESULT WINAPI VBSAXContentHandler_skippedEntity(IVBSAXContentHandler *iface, BSTR *name)
2219 {
2220 mxwriter *This = impl_from_IVBSAXContentHandler( iface );
2221
2222 TRACE("(%p)->(%p)\n", This, name);
2223
2224 if (!name)
2225 return E_POINTER;
2226
2227 return ISAXContentHandler_skippedEntity(&This->ISAXContentHandler_iface, *name, -1);
2228 }
2229
2230 static const IVBSAXContentHandlerVtbl VBSAXContentHandlerVtbl = {
2231 VBSAXContentHandler_QueryInterface,
2232 VBSAXContentHandler_AddRef,
2233 VBSAXContentHandler_Release,
2234 VBSAXContentHandler_GetTypeInfoCount,
2235 VBSAXContentHandler_GetTypeInfo,
2236 VBSAXContentHandler_GetIDsOfNames,
2237 VBSAXContentHandler_Invoke,
2238 VBSAXContentHandler_putref_documentLocator,
2239 VBSAXContentHandler_startDocument,
2240 VBSAXContentHandler_endDocument,
2241 VBSAXContentHandler_startPrefixMapping,
2242 VBSAXContentHandler_endPrefixMapping,
2243 VBSAXContentHandler_startElement,
2244 VBSAXContentHandler_endElement,
2245 VBSAXContentHandler_characters,
2246 VBSAXContentHandler_ignorableWhitespace,
2247 VBSAXContentHandler_processingInstruction,
2248 VBSAXContentHandler_skippedEntity
2249 };
2250
2251 static HRESULT WINAPI SAXDTDHandler_QueryInterface(ISAXDTDHandler *iface, REFIID riid, void **obj)
2252 {
2253 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2254 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2255 }
2256
2257 static ULONG WINAPI SAXDTDHandler_AddRef(ISAXDTDHandler *iface)
2258 {
2259 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2260 return IMXWriter_AddRef(&This->IMXWriter_iface);
2261 }
2262
2263 static ULONG WINAPI SAXDTDHandler_Release(ISAXDTDHandler *iface)
2264 {
2265 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2266 return IMXWriter_Release(&This->IMXWriter_iface);
2267 }
2268
2269 static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
2270 const WCHAR *name, INT n_name,
2271 const WCHAR *publicid, INT n_publicid,
2272 const WCHAR *systemid, INT n_systemid)
2273 {
2274 static const WCHAR notationW[] = {'<','!','N','O','T','A','T','I','O','N',' '};
2275 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2276
2277 TRACE("(%p)->(%s:%d, %s:%d, %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
2278 debugstr_wn(publicid, n_publicid), n_publicid, debugstr_wn(systemid, n_systemid), n_systemid);
2279
2280 if (!name || !n_name)
2281 return E_INVALIDARG;
2282
2283 write_output_buffer(This, notationW, sizeof(notationW)/sizeof(WCHAR));
2284 write_output_buffer(This, name, n_name);
2285
2286 if (!publicid && !systemid)
2287 return E_INVALIDARG;
2288
2289 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
2290 if (publicid)
2291 {
2292 write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
2293 write_output_buffer_quoted(This, publicid, n_publicid);
2294 if (systemid)
2295 {
2296 write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
2297 write_output_buffer_quoted(This, systemid, n_systemid);
2298 }
2299 }
2300 else
2301 {
2302 write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
2303 write_output_buffer_quoted(This, systemid, n_systemid);
2304 }
2305
2306 write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
2307
2308 return S_OK;
2309 }
2310
2311 static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface,
2312 const WCHAR *name, INT nname,
2313 const WCHAR *publicid, INT npublicid,
2314 const WCHAR *systemid, INT nsystemid,
2315 const WCHAR *notation, INT nnotation)
2316 {
2317 mxwriter *This = impl_from_ISAXDTDHandler( iface );
2318 FIXME("(%p)->(%s:%d, %s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname,
2319 debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid,
2320 debugstr_wn(notation, nnotation), nnotation);
2321 return E_NOTIMPL;
2322 }
2323
2324 static const ISAXDTDHandlerVtbl SAXDTDHandlerVtbl = {
2325 SAXDTDHandler_QueryInterface,
2326 SAXDTDHandler_AddRef,
2327 SAXDTDHandler_Release,
2328 SAXDTDHandler_notationDecl,
2329 SAXDTDHandler_unparsedEntityDecl
2330 };
2331
2332 /*** IVBSAXDTDHandler ***/
2333 static HRESULT WINAPI VBSAXDTDHandler_QueryInterface(IVBSAXDTDHandler *iface, REFIID riid, void **obj)
2334 {
2335 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2336 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2337 }
2338
2339 static ULONG WINAPI VBSAXDTDHandler_AddRef(IVBSAXDTDHandler *iface)
2340 {
2341 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2342 return IMXWriter_AddRef(&This->IMXWriter_iface);
2343 }
2344
2345 static ULONG WINAPI VBSAXDTDHandler_Release(IVBSAXDTDHandler *iface)
2346 {
2347 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2348 return IMXWriter_Release(&This->IMXWriter_iface);
2349 }
2350
2351 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfoCount(IVBSAXDTDHandler *iface, UINT* pctinfo)
2352 {
2353 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2354 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
2355 }
2356
2357 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfo(IVBSAXDTDHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2358 {
2359 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2360 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
2361 }
2362
2363 static HRESULT WINAPI VBSAXDTDHandler_GetIDsOfNames(IVBSAXDTDHandler *iface, REFIID riid, LPOLESTR* rgszNames,
2364 UINT cNames, LCID lcid, DISPID* rgDispId )
2365 {
2366 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2367 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
2368 }
2369
2370 static HRESULT WINAPI VBSAXDTDHandler_Invoke(IVBSAXDTDHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
2371 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
2372 {
2373 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2374 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
2375 pExcepInfo, puArgErr);
2376 }
2377
2378 static HRESULT WINAPI VBSAXDTDHandler_notationDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
2379 {
2380 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2381
2382 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
2383
2384 if (!name || !publicId || !systemId)
2385 return E_POINTER;
2386
2387 return ISAXDTDHandler_notationDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
2388 }
2389
2390 static HRESULT WINAPI VBSAXDTDHandler_unparsedEntityDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId,
2391 BSTR *systemId, BSTR *notation)
2392 {
2393 mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
2394
2395 TRACE("(%p)->(%p %p %p %p)\n", This, name, publicId, systemId, notation);
2396
2397 if (!name || !publicId || !systemId || !notation)
2398 return E_POINTER;
2399
2400 return ISAXDTDHandler_unparsedEntityDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1,
2401 *systemId, -1, *notation, -1);
2402 }
2403
2404 static const IVBSAXDTDHandlerVtbl VBSAXDTDHandlerVtbl = {
2405 VBSAXDTDHandler_QueryInterface,
2406 VBSAXDTDHandler_AddRef,
2407 VBSAXDTDHandler_Release,
2408 VBSAXDTDHandler_GetTypeInfoCount,
2409 VBSAXDTDHandler_GetTypeInfo,
2410 VBSAXDTDHandler_GetIDsOfNames,
2411 VBSAXDTDHandler_Invoke,
2412 VBSAXDTDHandler_notationDecl,
2413 VBSAXDTDHandler_unparsedEntityDecl
2414 };
2415
2416 /* ISAXErrorHandler */
2417 static HRESULT WINAPI SAXErrorHandler_QueryInterface(ISAXErrorHandler *iface, REFIID riid, void **obj)
2418 {
2419 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2420 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2421 }
2422
2423 static ULONG WINAPI SAXErrorHandler_AddRef(ISAXErrorHandler *iface)
2424 {
2425 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2426 return IMXWriter_AddRef(&This->IMXWriter_iface);
2427 }
2428
2429 static ULONG WINAPI SAXErrorHandler_Release(ISAXErrorHandler *iface)
2430 {
2431 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2432 return IMXWriter_Release(&This->IMXWriter_iface);
2433 }
2434
2435 static HRESULT WINAPI SAXErrorHandler_error(ISAXErrorHandler *iface,
2436 ISAXLocator *locator, const WCHAR *message, HRESULT hr)
2437 {
2438 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2439
2440 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
2441
2442 return E_NOTIMPL;
2443 }
2444
2445 static HRESULT WINAPI SAXErrorHandler_fatalError(ISAXErrorHandler *iface,
2446 ISAXLocator *locator, const WCHAR *message, HRESULT hr)
2447 {
2448 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2449
2450 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
2451
2452 return E_NOTIMPL;
2453 }
2454
2455 static HRESULT WINAPI SAXErrorHandler_ignorableWarning(ISAXErrorHandler *iface,
2456 ISAXLocator *locator, const WCHAR *message, HRESULT hr)
2457 {
2458 mxwriter *This = impl_from_ISAXErrorHandler( iface );
2459
2460 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
2461
2462 return E_NOTIMPL;
2463 }
2464
2465 static const ISAXErrorHandlerVtbl SAXErrorHandlerVtbl = {
2466 SAXErrorHandler_QueryInterface,
2467 SAXErrorHandler_AddRef,
2468 SAXErrorHandler_Release,
2469 SAXErrorHandler_error,
2470 SAXErrorHandler_fatalError,
2471 SAXErrorHandler_ignorableWarning
2472 };
2473
2474 /*** IVBSAXErrorHandler ***/
2475 static HRESULT WINAPI VBSAXErrorHandler_QueryInterface(IVBSAXErrorHandler *iface, REFIID riid, void **obj)
2476 {
2477 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2478 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
2479 }
2480
2481 static ULONG WINAPI VBSAXErrorHandler_AddRef(IVBSAXErrorHandler *iface)
2482 {
2483 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2484 return IMXWriter_AddRef(&This->IMXWriter_iface);
2485 }
2486
2487 static ULONG WINAPI VBSAXErrorHandler_Release(IVBSAXErrorHandler *iface)
2488 {
2489 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2490 return IMXWriter_Release(&This->IMXWriter_iface);
2491 }
2492
2493 static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfoCount(IVBSAXErrorHandler *iface, UINT* pctinfo)
2494 {
2495 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2496 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
2497 }
2498
2499 static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfo(IVBSAXErrorHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2500 {
2501 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2502 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
2503 }
2504
2505 static HRESULT WINAPI VBSAXErrorHandler_GetIDsOfNames(IVBSAXErrorHandler *iface, REFIID riid, LPOLESTR* rgszNames,
2506 UINT cNames, LCID lcid, DISPID* rgDispId )
2507 {
2508 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2509 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
2510 }
2511
2512 static HRESULT WINAPI VBSAXErrorHandler_Invoke(IVBSAXErrorHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
2513 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
2514 {
2515 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2516 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
2517 pExcepInfo, puArgErr);
2518 }
2519
2520 static HRESULT WINAPI VBSAXErrorHandler_error(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
2521 {
2522 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2523 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
2524 return E_NOTIMPL;
2525 }
2526
2527 static HRESULT WINAPI VBSAXErrorHandler_fatalError(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
2528 {
2529 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2530 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
2531 return E_NOTIMPL;
2532 }
2533
2534 static HRESULT WINAPI VBSAXErrorHandler_ignorableWarning(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
2535 {
2536 mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
2537 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
2538 return E_NOTIMPL;
2539 }
2540
2541 static const IVBSAXErrorHandlerVtbl VBSAXErrorHandlerVtbl = {
2542 VBSAXErrorHandler_QueryInterface,
2543 VBSAXErrorHandler_AddRef,
2544 VBSAXErrorHandler_Release,
2545 VBSAXErrorHandler_GetTypeInfoCount,
2546 VBSAXErrorHandler_GetTypeInfo,
2547 VBSAXErrorHandler_GetIDsOfNames,
2548 VBSAXErrorHandler_Invoke,
2549 VBSAXErrorHandler_error,
2550 VBSAXErrorHandler_fatalError,
2551 VBSAXErrorHandler_ignorableWarning
2552 };
2553
2554 static const tid_t mxwriter_iface_tids[] = {
2555 IMXWriter_tid,
2556 0
2557 };
2558
2559 static dispex_static_data_t mxwriter_dispex = {
2560 NULL,
2561 IMXWriter_tid,
2562 NULL,
2563 mxwriter_iface_tids
2564 };
2565
2566 HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj)
2567 {
2568 static const WCHAR version10W[] = {'1','.','0',0};
2569 mxwriter *This;
2570 HRESULT hr;
2571
2572 TRACE("(%p)\n", ppObj);
2573
2574 This = heap_alloc( sizeof (*This) );
2575 if(!This)
2576 return E_OUTOFMEMORY;
2577
2578 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
2579 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
2580 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
2581 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
2582 This->ISAXDTDHandler_iface.lpVtbl = &SAXDTDHandlerVtbl;
2583 This->ISAXErrorHandler_iface.lpVtbl = &SAXErrorHandlerVtbl;
2584 This->IVBSAXDeclHandler_iface.lpVtbl = &VBSAXDeclHandlerVtbl;
2585 This->IVBSAXLexicalHandler_iface.lpVtbl = &VBSAXLexicalHandlerVtbl;
2586 This->IVBSAXContentHandler_iface.lpVtbl = &VBSAXContentHandlerVtbl;
2587 This->IVBSAXDTDHandler_iface.lpVtbl = &VBSAXDTDHandlerVtbl;
2588 This->IVBSAXErrorHandler_iface.lpVtbl = &VBSAXErrorHandlerVtbl;
2589 This->ref = 1;
2590 This->class_version = version;
2591
2592 This->props[MXWriter_BOM] = VARIANT_TRUE;
2593 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
2594 This->props[MXWriter_Indent] = VARIANT_FALSE;
2595 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
2596 This->props[MXWriter_Standalone] = VARIANT_FALSE;
2597 This->prop_changed = FALSE;
2598 This->encoding = SysAllocString(utf16W);
2599 This->version = SysAllocString(version10W);
2600 This->xml_enc = XmlEncoding_UTF16;
2601
2602 This->element = NULL;
2603 This->cdata = FALSE;
2604 This->indent = 0;
2605 This->text = FALSE;
2606 This->newline = FALSE;
2607
2608 This->dest = NULL;
2609
2610 hr = init_output_buffer(This->xml_enc, &This->buffer);
2611 if (hr != S_OK) {
2612 SysFreeString(This->encoding);
2613 SysFreeString(This->version);
2614 heap_free(This);
2615 return hr;
2616 }
2617
2618 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
2619
2620 *ppObj = &This->IMXWriter_iface;
2621
2622 TRACE("returning iface %p\n", *ppObj);
2623
2624 return S_OK;
2625 }
2626
2627 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
2628 {
2629 mxattributes *This = impl_from_IMXAttributes( iface );
2630
2631 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
2632
2633 *ppObj = NULL;
2634
2635 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
2636 IsEqualGUID( riid, &IID_IDispatch ) ||
2637 IsEqualGUID( riid, &IID_IMXAttributes ))
2638 {
2639 *ppObj = iface;
2640 }
2641 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
2642 {
2643 *ppObj = &This->ISAXAttributes_iface;
2644 }
2645 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
2646 {
2647 *ppObj = &This->IVBSAXAttributes_iface;
2648 }
2649 else if (dispex_query_interface(&This->dispex, riid, ppObj))
2650 {
2651 return *ppObj ? S_OK : E_NOINTERFACE;
2652 }
2653 else
2654 {
2655 FIXME("interface %s not implemented\n", debugstr_guid(riid));
2656 return E_NOINTERFACE;
2657 }
2658
2659 IMXAttributes_AddRef( iface );
2660
2661 return S_OK;
2662 }
2663
2664 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface)
2665 {
2666 mxattributes *This = impl_from_IMXAttributes( iface );
2667 ULONG ref = InterlockedIncrement( &This->ref );
2668 TRACE("(%p)->(%d)\n", This, ref );
2669 return ref;
2670 }
2671
2672 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface)
2673 {
2674 mxattributes *This = impl_from_IMXAttributes( iface );
2675 LONG ref = InterlockedDecrement( &This->ref );
2676
2677 TRACE("(%p)->(%d)\n", This, ref);
2678
2679 if (ref == 0)
2680 {
2681 int i;
2682
2683 for (i = 0; i < This->length; i++)
2684 {
2685 SysFreeString(This->attr[i].qname);
2686 SysFreeString(This->attr[i].local);
2687 SysFreeString(This->attr[i].uri);
2688 SysFreeString(This->attr[i].type);
2689 SysFreeString(This->attr[i].value);
2690 }
2691
2692 heap_free(This->attr);
2693 heap_free(This);
2694 }
2695
2696 return ref;
2697 }
2698
2699 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo)
2700 {
2701 mxattributes *This = impl_from_IMXAttributes( iface );
2702 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2703 }
2704
2705 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
2706 {
2707 mxattributes *This = impl_from_IMXAttributes( iface );
2708 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2709 }
2710
2711 static HRESULT WINAPI MXAttributes_GetIDsOfNames(
2712 IMXAttributes *iface,
2713 REFIID riid,
2714 LPOLESTR* rgszNames,
2715 UINT cNames,
2716 LCID lcid,
2717 DISPID* rgDispId)
2718 {
2719 mxattributes *This = impl_from_IMXAttributes( iface );
2720 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
2721 riid, rgszNames, cNames, lcid, rgDispId);
2722 }
2723
2724 static HRESULT WINAPI MXAttributes_Invoke(
2725 IMXAttributes *iface,
2726 DISPID dispIdMember,
2727 REFIID riid,
2728 LCID lcid,
2729 WORD wFlags,
2730 DISPPARAMS* pDispParams,
2731 VARIANT* pVarResult,
2732 EXCEPINFO* pExcepInfo,
2733 UINT* puArgErr)
2734 {
2735 mxattributes *This = impl_from_IMXAttributes( iface );
2736 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
2737 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2738 }
2739
2740 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface,
2741 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
2742 {
2743 mxattributes *This = impl_from_IMXAttributes( iface );
2744 mxattribute *attr;
2745 HRESULT hr;
2746
2747 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName),
2748 debugstr_w(QName), debugstr_w(type), debugstr_w(value));
2749
2750 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6)
2751 return E_INVALIDARG;
2752
2753 /* ensure array is large enough */
2754 hr = mxattributes_grow(This);
2755 if (hr != S_OK) return hr;
2756
2757 attr = &This->attr[This->length];
2758
2759 attr->qname = SysAllocString(QName);
2760 attr->local = SysAllocString(localName);
2761 attr->uri = SysAllocString(uri);
2762 attr->type = SysAllocString(type ? type : emptyW);
2763 attr->value = SysAllocString(value);
2764 This->length++;
2765
2766 return S_OK;
2767 }
2768
2769 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface,
2770 VARIANT atts, int index)
2771 {
2772 mxattributes *This = impl_from_IMXAttributes( iface );
2773 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index);
2774 return E_NOTIMPL;
2775 }
2776
2777 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface)
2778 {
2779 mxattributes *This = impl_from_IMXAttributes( iface );
2780 int i;
2781
2782 TRACE("(%p)\n", This);
2783
2784 for (i = 0; i < This->length; i++)
2785 {
2786 SysFreeString(This->attr[i].qname);
2787 SysFreeString(This->attr[i].local);
2788 SysFreeString(This->attr[i].uri);
2789 SysFreeString(This->attr[i].type);
2790 SysFreeString(This->attr[i].value);
2791 memset(&This->attr[i], 0, sizeof(mxattribute));
2792 }
2793
2794 This->length = 0;
2795
2796 return S_OK;
2797 }
2798
2799 static mxattribute *get_attribute_byindex(mxattributes *attrs, int index)
2800 {
2801 if (index < 0 || index >= attrs->length) return NULL;
2802 return &attrs->attr[index];
2803 }
2804
2805 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
2806 {
2807 mxattributes *This = impl_from_IMXAttributes( iface );
2808 mxattribute *dst;
2809
2810 TRACE("(%p)->(%d)\n", This, index);
2811
2812 if (!(dst = get_attribute_byindex(This, index))) return E_INVALIDARG;
2813
2814 /* no need to remove last attribute, just make it inaccessible */
2815 if (index + 1 == This->length)
2816 {
2817 This->length--;
2818 return S_OK;
2819 }
2820
2821 memmove(dst, dst + 1, (This->length-index-1)*sizeof(*dst));
2822 This->length--;
2823
2824 return S_OK;
2825 }
2826
2827 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
2828 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
2829 {
2830 mxattributes *This = impl_from_IMXAttributes( iface );
2831 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri),
2832 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value));
2833 return E_NOTIMPL;
2834 }
2835
2836 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts)
2837 {
2838 mxattributes *This = impl_from_IMXAttributes( iface );
2839 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts));
2840 return E_NOTIMPL;
2841 }
2842
2843 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index,
2844 BSTR localName)
2845 {
2846 mxattributes *This = impl_from_IMXAttributes( iface );
2847 mxattribute *attr;
2848
2849 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(localName));
2850
2851 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2852
2853 SysFreeString(attr->local);
2854 attr->local = SysAllocString(localName);
2855
2856 return S_OK;
2857 }
2858
2859 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
2860 {
2861 mxattributes *This = impl_from_IMXAttributes( iface );
2862 mxattribute *attr;
2863
2864 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(QName));
2865
2866 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2867
2868 SysFreeString(attr->qname);
2869 attr->qname = SysAllocString(QName);
2870
2871 return S_OK;
2872 }
2873
2874 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
2875 {
2876 mxattributes *This = impl_from_IMXAttributes( iface );
2877 mxattribute *attr;
2878
2879 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(uri));
2880
2881 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2882
2883 SysFreeString(attr->uri);
2884 attr->uri = SysAllocString(uri);
2885
2886 return S_OK;
2887 }
2888
2889 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
2890 {
2891 mxattributes *This = impl_from_IMXAttributes( iface );
2892 mxattribute *attr;
2893
2894 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(value));
2895
2896 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
2897
2898 SysFreeString(attr->value);
2899 attr->value = SysAllocString(value);
2900
2901 return S_OK;
2902 }
2903
2904 static const IMXAttributesVtbl MXAttributesVtbl = {
2905 MXAttributes_QueryInterface,
2906 MXAttributes_AddRef,
2907 MXAttributes_Release,
2908 MXAttributes_GetTypeInfoCount,
2909 MXAttributes_GetTypeInfo,
2910 MXAttributes_GetIDsOfNames,
2911 MXAttributes_Invoke,
2912 MXAttributes_addAttribute,
2913 MXAttributes_addAttributeFromIndex,
2914 MXAttributes_clear,
2915 MXAttributes_removeAttribute,
2916 MXAttributes_setAttribute,
2917 MXAttributes_setAttributes,
2918 MXAttributes_setLocalName,
2919 MXAttributes_setQName,
2920 MXAttributes_setURI,
2921 MXAttributes_setValue
2922 };
2923
2924 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj)
2925 {
2926 mxattributes *This = impl_from_ISAXAttributes( iface );
2927 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj);
2928 }
2929
2930 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface)
2931 {
2932 mxattributes *This = impl_from_ISAXAttributes( iface );
2933 return IMXAttributes_AddRef(&This->IMXAttributes_iface);
2934 }
2935
2936 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface)
2937 {
2938 mxattributes *This = impl_from_ISAXAttributes( iface );
2939 return IMXAttributes_Release(&This->IMXAttributes_iface);
2940 }
2941
2942 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length)
2943 {
2944 mxattributes *This = impl_from_ISAXAttributes( iface );
2945 TRACE("(%p)->(%p)\n", This, length);
2946
2947 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2948 return E_POINTER;
2949
2950 *length = This->length;
2951
2952 return S_OK;
2953 }
2954
2955 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri,
2956 int *len)
2957 {
2958 mxattributes *This = impl_from_ISAXAttributes( iface );
2959
2960 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len);
2961
2962 if (index >= This->length || index < 0) return E_INVALIDARG;
2963 if (!uri || !len) return E_POINTER;
2964
2965 *len = SysStringLen(This->attr[index].uri);
2966 *uri = This->attr[index].uri;
2967
2968 return S_OK;
2969 }
2970
2971 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name,
2972 int *len)
2973 {
2974 mxattributes *This = impl_from_ISAXAttributes( iface );
2975
2976 TRACE("(%p)->(%d %p %p)\n", This, index, name, len);
2977
2978 if (index >= This->length || index < 0) return E_INVALIDARG;
2979 if (!name || !len) return E_POINTER;
2980
2981 *len = SysStringLen(This->attr[index].local);
2982 *name = This->attr[index].local;
2983
2984 return S_OK;
2985 }
2986
2987 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length)
2988 {
2989 mxattributes *This = impl_from_ISAXAttributes( iface );
2990
2991 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length);
2992
2993 if (index >= This->length) return E_INVALIDARG;
2994 if (!qname || !length) return E_POINTER;
2995
2996 *qname = This->attr[index].qname;
2997 *length = SysStringLen(This->attr[index].qname);
2998
2999 return S_OK;
3000 }
3001
3002 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len,
3003 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len)
3004 {
3005 mxattributes *This = impl_from_ISAXAttributes( iface );
3006
3007 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len);
3008
3009 if (index >= This->length || index < 0)
3010 return E_INVALIDARG;
3011
3012 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len)
3013 return E_POINTER;
3014
3015 *uri_len = SysStringLen(This->attr[index].uri);
3016 *uri = This->attr[index].uri;
3017
3018 *local_len = SysStringLen(This->attr[index].local);
3019 *local = This->attr[index].local;
3020
3021 *qname_len = SysStringLen(This->attr[index].qname);
3022 *qname = This->attr[index].qname;
3023
3024 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname));
3025
3026 return S_OK;
3027 }
3028
3029 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len,
3030 const WCHAR *name, int len, int *index)
3031 {
3032 mxattributes *This = impl_from_ISAXAttributes( iface );
3033 int i;
3034
3035 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
3036 debugstr_wn(name, len), len, index);
3037
3038 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
3039 return E_POINTER;
3040
3041 if (!uri || !name || !index) return E_INVALIDARG;
3042
3043 for (i = 0; i < This->length; i++)
3044 {
3045 if (uri_len != SysStringLen(This->attr[i].uri)) continue;
3046 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue;
3047
3048 if (len != SysStringLen(This->attr[i].local)) continue;
3049 if (strncmpW(name, This->attr[i].local, len)) continue;
3050
3051 *index = i;
3052 return S_OK;
3053 }
3054
3055 return E_INVALIDARG;
3056 }
3057
3058 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname,
3059 int len, int *index)
3060 {
3061 mxattributes *This = impl_from_ISAXAttributes( iface );
3062 int i;
3063
3064 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index);
3065
3066 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
3067 return E_POINTER;
3068
3069 if (!qname || !index || !len) return E_INVALIDARG;
3070
3071 for (i = 0; i < This->length; i++)
3072 {
3073 if (len != SysStringLen(This->attr[i].qname)) continue;
3074 if (strncmpW(qname, This->attr[i].qname, len)) continue;
3075
3076 *index = i;
3077 return S_OK;
3078 }
3079
3080 return E_INVALIDARG;
3081 }
3082
3083 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type,
3084 int *len)
3085 {
3086 mxattributes *This = impl_from_ISAXAttributes( iface );
3087
3088 TRACE("(%p)->(%d %p %p)\n", This, index, type, len);
3089
3090 if (index >= This->length) return E_INVALIDARG;
3091
3092 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
3093 return E_POINTER;
3094
3095 *type = This->attr[index].type;
3096 *len = SysStringLen(This->attr[index].type);
3097
3098 return S_OK;
3099 }
3100
3101 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri,
3102 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType)
3103 {
3104 mxattributes *This = impl_from_ISAXAttributes( iface );
3105 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri,
3106 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType);
3107 return E_NOTIMPL;
3108 }
3109
3110 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName,
3111 int nQName, const WCHAR ** pType, int * nType)
3112 {
3113 mxattributes *This = impl_from_ISAXAttributes( iface );
3114 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType);
3115 return E_NOTIMPL;
3116 }
3117
3118 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value,
3119 int *len)
3120 {
3121 mxattributes *This = impl_from_ISAXAttributes( iface );
3122
3123 TRACE("(%p)->(%d %p %p)\n", This, index, value, len);
3124
3125 if (index >= This->length) return E_INVALIDARG;
3126
3127 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
3128 return E_POINTER;
3129
3130 *value = This->attr[index].value;
3131 *len = SysStringLen(This->attr[index].value);
3132
3133 return S_OK;
3134 }
3135
3136 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri,
3137 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len)
3138 {
3139 mxattributes *This = impl_from_ISAXAttributes( iface );
3140 HRESULT hr;
3141 int index;
3142
3143 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
3144 debugstr_wn(name, name_len), name_len, value, value_len);
3145
3146 if (!uri || !name || !value || !value_len)
3147 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
3148
3149 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index);
3150 if (hr == S_OK)
3151 hr = ISAXAttributes_getValue(iface, index, value, value_len);
3152
3153 return hr;
3154 }
3155
3156 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname,
3157 int qname_len, const WCHAR **value, int *value_len)
3158 {
3159 mxattributes *This = impl_from_ISAXAttributes( iface );
3160 HRESULT hr;
3161 int index;
3162
3163 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len);
3164
3165 if (!qname || !value || !value_len)
3166 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
3167
3168 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index);
3169 if (hr == S_OK)
3170 hr = ISAXAttributes_getValue(iface, index, value, value_len);
3171
3172 return hr;
3173 }
3174
3175 static const ISAXAttributesVtbl SAXAttributesVtbl = {
3176 SAXAttributes_QueryInterface,
3177 SAXAttributes_AddRef,
3178 SAXAttributes_Release,
3179 SAXAttributes_getLength,
3180 SAXAttributes_getURI,
3181 SAXAttributes_getLocalName,
3182 SAXAttributes_getQName,
3183 SAXAttributes_getName,
3184 SAXAttributes_getIndexFromName,
3185 SAXAttributes_getIndexFromQName,
3186 SAXAttributes_getType,
3187 SAXAttributes_getTypeFromName,
3188 SAXAttributes_getTypeFromQName,
3189 SAXAttributes_getValue,
3190 SAXAttributes_getValueFromName,
3191 SAXAttributes_getValueFromQName
3192 };
3193
3194 static HRESULT WINAPI VBSAXAttributes_QueryInterface(
3195 IVBSAXAttributes* iface,
3196 REFIID riid,
3197 void **ppvObject)
3198 {
3199 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3200 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
3201 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject);
3202 }
3203
3204 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface)
3205 {
3206 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3207 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface);
3208 }
3209
3210 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface)
3211 {
3212 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3213 return ISAXAttributes_Release(&This->ISAXAttributes_iface);
3214 }
3215
3216 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
3217 {
3218 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3219
3220 TRACE("(%p)->(%p)\n", This, pctinfo);
3221
3222 *pctinfo = 1;
3223
3224 return S_OK;
3225 }
3226
3227 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo(
3228 IVBSAXAttributes *iface,
3229 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
3230 {
3231 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3232 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
3233 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
3234 }
3235
3236 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames(
3237 IVBSAXAttributes *iface,
3238 REFIID riid,
3239 LPOLESTR* rgszNames,
3240 UINT cNames,
3241 LCID lcid,
3242 DISPID* rgDispId)
3243 {
3244 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3245 ITypeInfo *typeinfo;
3246 HRESULT hr;
3247
3248 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
3249 lcid, rgDispId);
3250
3251 if(!rgszNames || cNames == 0 || !rgDispId)
3252 return E_INVALIDARG;
3253
3254 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
3255 if(SUCCEEDED(hr))
3256 {
3257 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
3258 ITypeInfo_Release(typeinfo);
3259 }
3260
3261 return hr;
3262 }
3263
3264 static HRESULT WINAPI VBSAXAttributes_Invoke(
3265 IVBSAXAttributes *iface,
3266 DISPID dispIdMember,
3267 REFIID riid,
3268 LCID lcid,
3269 WORD wFlags,
3270 DISPPARAMS* pDispParams,
3271 VARIANT* pVarResult,
3272 EXCEPINFO* pExcepInfo,
3273 UINT* puArgErr)
3274 {
3275 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3276 ITypeInfo *typeinfo;
3277 HRESULT hr;
3278
3279 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
3280 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
3281
3282 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
3283 if(SUCCEEDED(hr))
3284 {
3285 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
3286 pDispParams, pVarResult, pExcepInfo, puArgErr);
3287 ITypeInfo_Release(typeinfo);
3288 }
3289
3290 return hr;
3291 }
3292
3293 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len)
3294 {
3295 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3296 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len);
3297 }
3298
3299 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
3300 {
3301 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3302 const WCHAR *uriW;
3303 HRESULT hr;
3304 int len;
3305
3306 TRACE("(%p)->(%d %p)\n", This, index, uri);
3307
3308 if (!uri)
3309 return E_POINTER;
3310
3311 *uri = NULL;
3312 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, &uriW, &len);
3313 if (FAILED(hr))
3314 return hr;
3315
3316 return return_bstrn(uriW, len, uri);
3317 }
3318
3319 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
3320 {
3321 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3322 const WCHAR *nameW;
3323 HRESULT hr;
3324 int len;
3325
3326 TRACE("(%p)->(%d %p)\n", This, index, name);
3327
3328 if (!name)
3329 return E_POINTER;
3330
3331 *name = NULL;
3332 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, &nameW, &len);
3333 if (FAILED(hr))
3334 return hr;
3335
3336 return return_bstrn(nameW, len, name);
3337 }
3338
3339 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
3340 {
3341 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3342 const WCHAR *qnameW;
3343 HRESULT hr;
3344 int len;
3345
3346 TRACE("(%p)->(%d %p)\n", This, index, qname);
3347
3348 if (!qname)
3349 return E_POINTER;
3350
3351 *qname = NULL;
3352 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, &qnameW, &len);
3353 if (FAILED(hr))
3354 return hr;
3355
3356 return return_bstrn(qnameW, len, qname);
3357 }
3358
3359 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
3360 {
3361 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3362 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3363 name, SysStringLen(name), index);
3364 }
3365
3366 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index)
3367 {
3368 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3369 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname,
3370 SysStringLen(qname), index);
3371 }
3372
3373 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index, BSTR *type)
3374 {
3375 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3376 const WCHAR *typeW;
3377 HRESULT hr;
3378 int len;
3379
3380 TRACE("(%p)->(%d %p)\n", This, index, type);
3381
3382 if (!type)
3383 return E_POINTER;
3384
3385 *type = NULL;
3386 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, index, &typeW, &len);
3387 if (FAILED(hr))
3388 return hr;
3389
3390 return return_bstrn(typeW, len, type);
3391 }
3392
3393 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
3394 BSTR name, BSTR *type)
3395 {
3396 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3397 const WCHAR *typeW;
3398 HRESULT hr;
3399 int len;
3400
3401 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), type);
3402
3403 if (!type)
3404 return E_POINTER;
3405
3406 *type = NULL;
3407 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3408 name, SysStringLen(name), &typeW, &len);
3409 if (FAILED(hr))
3410 return hr;
3411
3412 return return_bstrn(typeW, len, type);
3413 }
3414
3415 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
3416 {
3417 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3418 const WCHAR *typeW;
3419 HRESULT hr;
3420 int len;
3421
3422 TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), type);
3423
3424 if (!type)
3425 return E_POINTER;
3426
3427 *type = NULL;
3428 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
3429 &typeW, &len);
3430 if (FAILED(hr))
3431 return hr;
3432
3433 return return_bstrn(typeW, len, type);
3434 }
3435
3436 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
3437 {
3438 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3439 const WCHAR *valueW;
3440 HRESULT hr;
3441 int len;
3442
3443 TRACE("(%p)->(%d %p)\n", This, index, value);
3444
3445 if (!value)
3446 return E_POINTER;
3447
3448 *value = NULL;
3449 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, &valueW, &len);
3450 if (FAILED(hr))
3451 return hr;
3452
3453 return return_bstrn(valueW, len, value);
3454 }
3455
3456 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
3457 BSTR *value)
3458 {
3459 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3460 const WCHAR *valueW;
3461 HRESULT hr;
3462 int len;
3463
3464 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), value);
3465
3466 if (!value)
3467 return E_POINTER;
3468
3469 *value = NULL;
3470 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
3471 name, SysStringLen(name), &valueW, &len);
3472 if (FAILED(hr))
3473 return hr;
3474
3475 return return_bstrn(valueW, len, value);
3476 }
3477
3478 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
3479 {
3480 mxattributes *This = impl_from_IVBSAXAttributes( iface );
3481 const WCHAR *valueW;
3482 HRESULT hr;
3483 int len;
3484
3485 TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), value);
3486
3487 if (!value)
3488 return E_POINTER;
3489
3490 *value = NULL;
3491 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
3492 &valueW, &len);
3493 if (FAILED(hr))
3494 return hr;
3495
3496 return return_bstrn(valueW, len, value);
3497 }
3498
3499 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
3500 {
3501 VBSAXAttributes_QueryInterface,
3502 VBSAXAttributes_AddRef,
3503 VBSAXAttributes_Release,
3504 VBSAXAttributes_GetTypeInfoCount,
3505 VBSAXAttributes_GetTypeInfo,
3506 VBSAXAttributes_GetIDsOfNames,
3507 VBSAXAttributes_Invoke,
3508 VBSAXAttributes_get_length,
3509 VBSAXAttributes_getURI,
3510 VBSAXAttributes_getLocalName,
3511 VBSAXAttributes_getQName,
3512 VBSAXAttributes_getIndexFromName,
3513 VBSAXAttributes_getIndexFromQName,
3514 VBSAXAttributes_getType,
3515 VBSAXAttributes_getTypeFromName,
3516 VBSAXAttributes_getTypeFromQName,
3517 VBSAXAttributes_getValue,
3518 VBSAXAttributes_getValueFromName,
3519 VBSAXAttributes_getValueFromQName
3520 };
3521
3522 static const tid_t mxattrs_iface_tids[] = {
3523 IMXAttributes_tid,
3524 0
3525 };
3526
3527 static dispex_static_data_t mxattrs_dispex = {
3528 NULL,
3529 IMXAttributes_tid,
3530 NULL,
3531 mxattrs_iface_tids
3532 };
3533
3534 HRESULT SAXAttributes_create(MSXML_VERSION version, void **ppObj)
3535 {
3536 static const int default_count = 10;
3537 mxattributes *This;
3538
3539 TRACE("(%p)\n", ppObj);
3540
3541 This = heap_alloc( sizeof (*This) );
3542 if( !This )
3543 return E_OUTOFMEMORY;
3544
3545 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl;
3546 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl;
3547 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl;
3548 This->ref = 1;
3549
3550 This->class_version = version;
3551
3552 This->attr = heap_alloc(default_count*sizeof(mxattribute));
3553 This->length = 0;
3554 This->allocated = default_count;
3555
3556 *ppObj = &This->IMXAttributes_iface;
3557
3558 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex);
3559
3560 TRACE("returning iface %p\n", *ppObj);
3561
3562 return S_OK;
3563 }