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