user32/tests: Test MDI child order changing caused by WM_MDINEXT.
[wine/multimedia.git] / dlls / msxml3 / mxwriter.c
blobd62e6a3057b891a8a45362380208314989de9e44
1 /*
2 * MXWriter implementation
4 * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
5 * Copyright 2011 Thomas Mullaly
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
23 #include "config.h"
25 #include <stdarg.h>
26 #ifdef HAVE_LIBXML2
27 # include <libxml/parser.h>
28 #endif
30 #include "windef.h"
31 #include "winbase.h"
32 #include "ole2.h"
34 #include "msxml6.h"
36 #include "wine/debug.h"
38 #include "msxml_private.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
42 static const WCHAR emptyW[] = {0};
43 static const WCHAR spaceW[] = {' '};
44 static const WCHAR quotW[] = {'\"'};
45 static const WCHAR closetagW[] = {'>','\r','\n'};
47 /* should be ordered as encoding names are sorted */
48 typedef enum
50 XmlEncoding_ISO_8859_1 = 0,
51 XmlEncoding_ISO_8859_13,
52 XmlEncoding_ISO_8859_15,
53 XmlEncoding_ISO_8859_2,
54 XmlEncoding_ISO_8859_3,
55 XmlEncoding_ISO_8859_4,
56 XmlEncoding_ISO_8859_5,
57 XmlEncoding_ISO_8859_7,
58 XmlEncoding_ISO_8859_9,
59 XmlEncoding_UTF16,
60 XmlEncoding_UTF8,
61 XmlEncoding_Unknown
62 } xml_encoding;
64 struct xml_encoding_data
66 const WCHAR *encoding;
67 xml_encoding enc;
68 UINT cp;
71 static const WCHAR iso_8859_1W[] = {'i','s','o','-','8','8','5','9','-','1',0};
72 static const WCHAR iso_8859_2W[] = {'i','s','o','-','8','8','5','9','-','2',0};
73 static const WCHAR iso_8859_3W[] = {'i','s','o','-','8','8','5','9','-','3',0};
74 static const WCHAR iso_8859_4W[] = {'i','s','o','-','8','8','5','9','-','4',0};
75 static const WCHAR iso_8859_5W[] = {'i','s','o','-','8','8','5','9','-','5',0};
76 static const WCHAR iso_8859_7W[] = {'i','s','o','-','8','8','5','9','-','7',0};
77 static const WCHAR iso_8859_9W[] = {'i','s','o','-','8','8','5','9','-','9',0};
78 static const WCHAR iso_8859_13W[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
79 static const WCHAR iso_8859_15W[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
80 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
81 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
83 static const struct xml_encoding_data xml_encoding_map[] = {
84 { iso_8859_1W, XmlEncoding_ISO_8859_1, 28591 },
85 { iso_8859_13W, XmlEncoding_ISO_8859_13, 28603 },
86 { iso_8859_15W, XmlEncoding_ISO_8859_15, 28605 },
87 { iso_8859_2W, XmlEncoding_ISO_8859_2, 28592 },
88 { iso_8859_3W, XmlEncoding_ISO_8859_3, 28593 },
89 { iso_8859_4W, XmlEncoding_ISO_8859_4, 28594 },
90 { iso_8859_5W, XmlEncoding_ISO_8859_5, 28595 },
91 { iso_8859_7W, XmlEncoding_ISO_8859_7, 28597 },
92 { iso_8859_9W, XmlEncoding_ISO_8859_9, 28599 },
93 { utf16W, XmlEncoding_UTF16, ~0 },
94 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
97 typedef enum
99 OutputBuffer_Native = 0x001,
100 OutputBuffer_Encoded = 0x010,
101 OutputBuffer_Both = 0x100
102 } output_mode;
104 typedef enum
106 MXWriter_BOM = 0,
107 MXWriter_DisableEscaping,
108 MXWriter_Indent,
109 MXWriter_OmitXmlDecl,
110 MXWriter_Standalone,
111 MXWriter_LastProp
112 } mxwriter_prop;
114 typedef enum
116 EscapeValue,
117 EscapeText
118 } escape_mode;
120 typedef struct
122 char *data;
123 unsigned int allocated;
124 unsigned int written;
125 } encoded_buffer;
127 typedef struct
129 encoded_buffer utf16;
130 encoded_buffer encoded;
131 UINT code_page;
132 } output_buffer;
134 typedef struct
136 DispatchEx dispex;
137 IMXWriter IMXWriter_iface;
138 ISAXContentHandler ISAXContentHandler_iface;
139 ISAXLexicalHandler ISAXLexicalHandler_iface;
140 ISAXDeclHandler ISAXDeclHandler_iface;
142 LONG ref;
143 MSXML_VERSION class_version;
145 VARIANT_BOOL props[MXWriter_LastProp];
146 BOOL prop_changed;
147 BOOL cdata;
149 BSTR version;
151 BSTR encoding; /* exact property value */
152 xml_encoding xml_enc;
154 /* contains a pending (or not closed yet) element name or NULL if
155 we don't have to close */
156 BSTR element;
158 IStream *dest;
159 ULONG dest_written;
161 output_buffer *buffer;
162 } mxwriter;
164 typedef struct
166 BSTR qname;
167 BSTR local;
168 BSTR uri;
169 BSTR type;
170 BSTR value;
171 } mxattribute;
173 typedef struct
175 DispatchEx dispex;
176 IMXAttributes IMXAttributes_iface;
177 ISAXAttributes ISAXAttributes_iface;
178 IVBSAXAttributes IVBSAXAttributes_iface;
179 LONG ref;
181 MSXML_VERSION class_version;
183 mxattribute *attr;
184 int length;
185 int allocated;
186 } mxattributes;
188 static inline mxattributes *impl_from_IMXAttributes( IMXAttributes *iface )
190 return CONTAINING_RECORD(iface, mxattributes, IMXAttributes_iface);
193 static inline mxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
195 return CONTAINING_RECORD(iface, mxattributes, ISAXAttributes_iface);
198 static inline mxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
200 return CONTAINING_RECORD(iface, mxattributes, IVBSAXAttributes_iface);
203 static HRESULT mxattributes_grow(mxattributes *This)
205 if (This->length < This->allocated) return S_OK;
207 This->allocated *= 2;
208 This->attr = heap_realloc(This->attr, This->allocated*sizeof(mxattribute));
210 return This->attr ? S_OK : E_OUTOFMEMORY;
213 static xml_encoding parse_encoding_name(const WCHAR *encoding)
215 int min, max, n, c;
217 min = 0;
218 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
220 while (min <= max)
222 n = (min+max)/2;
224 c = strcmpiW(xml_encoding_map[n].encoding, encoding);
225 if (!c)
226 return xml_encoding_map[n].enc;
228 if (c > 0)
229 max = n-1;
230 else
231 min = n+1;
234 return XmlEncoding_Unknown;
237 static HRESULT init_encoded_buffer(encoded_buffer *buffer)
239 const int initial_len = 0x2000;
240 buffer->data = heap_alloc(initial_len);
241 if (!buffer->data) return E_OUTOFMEMORY;
243 memset(buffer->data, 0, 4);
244 buffer->allocated = initial_len;
245 buffer->written = 0;
247 return S_OK;
250 static void free_encoded_buffer(encoded_buffer *buffer)
252 heap_free(buffer->data);
255 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
257 const struct xml_encoding_data *data;
259 if (encoding == XmlEncoding_Unknown)
261 FIXME("unsupported encoding %d\n", encoding);
262 return E_NOTIMPL;
265 data = &xml_encoding_map[encoding];
266 *cp = data->cp;
268 return S_OK;
271 static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer)
273 output_buffer *ret;
274 HRESULT hr;
276 ret = heap_alloc(sizeof(*ret));
277 if (!ret) return E_OUTOFMEMORY;
279 hr = get_code_page(encoding, &ret->code_page);
280 if (hr != S_OK) {
281 heap_free(ret);
282 return hr;
285 hr = init_encoded_buffer(&ret->utf16);
286 if (hr != S_OK) {
287 heap_free(ret);
288 return hr;
291 /* currently we always create a default output buffer that is UTF-16 only,
292 but it's possible to allocate with specific encoding too */
293 if (encoding != XmlEncoding_UTF16) {
294 hr = init_encoded_buffer(&ret->encoded);
295 if (hr != S_OK) {
296 free_encoded_buffer(&ret->utf16);
297 heap_free(ret);
298 return hr;
301 else
302 memset(&ret->encoded, 0, sizeof(ret->encoded));
304 *buffer = ret;
306 return S_OK;
309 static void free_output_buffer(output_buffer *buffer)
311 free_encoded_buffer(&buffer->encoded);
312 free_encoded_buffer(&buffer->utf16);
313 heap_free(buffer);
316 static void grow_buffer(encoded_buffer *buffer, int length)
318 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
319 if (buffer->allocated < buffer->written + length + 4)
321 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
322 buffer->data = heap_realloc(buffer->data, grown_size);
323 buffer->allocated = grown_size;
327 static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
329 int length;
330 char *ptr;
332 if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
333 if (buffer->code_page != ~0)
335 length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
336 grow_buffer(&buffer->encoded, length);
337 ptr = buffer->encoded.data + buffer->encoded.written;
338 length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
339 buffer->encoded.written += len == -1 ? length-1 : length;
343 if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
344 /* WCHAR data just copied */
345 length = len == -1 ? strlenW(data) : len;
346 if (length)
348 length *= sizeof(WCHAR);
350 grow_buffer(&buffer->utf16, length);
351 ptr = buffer->utf16.data + buffer->utf16.written;
353 memcpy(ptr, data, length);
354 buffer->utf16.written += length;
355 ptr += length;
356 /* null termination */
357 memset(ptr, 0, sizeof(WCHAR));
361 return S_OK;
364 static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
366 return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
369 static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
371 write_output_buffer(buffer, quotW, 1);
372 write_output_buffer(buffer, data, len);
373 write_output_buffer(buffer, quotW, 1);
375 return S_OK;
378 /* frees buffer data, reallocates with a default lengths */
379 static void close_output_buffer(mxwriter *This)
381 heap_free(This->buffer->utf16.data);
382 heap_free(This->buffer->encoded.data);
383 init_encoded_buffer(&This->buffer->utf16);
384 init_encoded_buffer(&This->buffer->encoded);
385 get_code_page(This->xml_enc, &This->buffer->code_page);
388 /* escapes special characters like:
389 '<' -> "&lt;"
390 '&' -> "&amp;"
391 '"' -> "&quot;"
392 '>' -> "&gt;"
394 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
396 static const WCHAR ltW[] = {'&','l','t',';'};
397 static const WCHAR ampW[] = {'&','a','m','p',';'};
398 static const WCHAR equotW[] = {'&','q','u','o','t',';'};
399 static const WCHAR gtW[] = {'&','g','t',';'};
401 const int default_alloc = 100;
402 const int grow_thresh = 10;
403 int p = *len, conv_len;
404 WCHAR *ptr, *ret;
406 /* default buffer size to something if length is unknown */
407 conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
408 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
410 while (*str && p)
412 if (ptr - ret > conv_len - grow_thresh)
414 int written = ptr - ret;
415 conv_len *= 2;
416 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
417 ptr += written;
420 switch (*str)
422 case '<':
423 memcpy(ptr, ltW, sizeof(ltW));
424 ptr += sizeof(ltW)/sizeof(WCHAR);
425 break;
426 case '&':
427 memcpy(ptr, ampW, sizeof(ampW));
428 ptr += sizeof(ampW)/sizeof(WCHAR);
429 break;
430 case '>':
431 memcpy(ptr, gtW, sizeof(gtW));
432 ptr += sizeof(gtW)/sizeof(WCHAR);
433 break;
434 case '"':
435 if (mode == EscapeValue)
437 memcpy(ptr, equotW, sizeof(equotW));
438 ptr += sizeof(equotW)/sizeof(WCHAR);
439 break;
441 /* fallthrough for text mode */
442 default:
443 *ptr++ = *str;
444 break;
447 str++;
448 if (*len != -1) p--;
451 if (*len != -1) *len = ptr-ret;
452 *++ptr = 0;
454 return ret;
457 static void write_prolog_buffer(const mxwriter *This)
459 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
460 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
461 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
462 static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
463 static const WCHAR noW[] = {'n','o','\"','?','>'};
464 static const WCHAR crlfW[] = {'\r','\n'};
466 /* version */
467 write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
468 write_output_buffer_quoted(This->buffer, This->version, -1);
470 /* encoding */
471 write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
473 /* always write UTF-16 to WCHAR buffer */
474 write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
475 write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
476 write_output_buffer(This->buffer, quotW, 1);
478 /* standalone */
479 write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
480 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
481 write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
482 else
483 write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
485 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
488 /* Attempts to the write data from the mxwriter's buffer to
489 * the destination stream (if there is one).
491 static HRESULT write_data_to_stream(mxwriter *This)
493 encoded_buffer *buffer;
494 ULONG written = 0;
495 HRESULT hr;
497 if (!This->dest)
498 return S_OK;
500 if (This->xml_enc != XmlEncoding_UTF16)
501 buffer = &This->buffer->encoded;
502 else
503 buffer = &This->buffer->utf16;
505 if (This->dest_written > buffer->written) {
506 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->written);
507 return E_FAIL;
508 } else if (This->dest_written == buffer->written && This->xml_enc != XmlEncoding_UTF8)
509 /* Windows seems to make an empty write call when the encoding is UTF-8 and
510 * all the data has been written to the stream. It doesn't seem make this call
511 * for any other encodings.
513 return S_OK;
515 /* Write the current content from the output buffer into 'dest'.
516 * TODO: Check what Windows does if the IStream doesn't write all of
517 * the data we give it at once.
519 hr = IStream_Write(This->dest, buffer->data+This->dest_written,
520 buffer->written-This->dest_written, &written);
521 if (FAILED(hr)) {
522 WARN("Failed to write data to IStream (0x%08x)\n", hr);
523 return hr;
526 This->dest_written += written;
527 return hr;
530 /* Newly added element start tag left unclosed cause for empty elements
531 we have to close it differently. */
532 static void close_element_starttag(const mxwriter *This)
534 static const WCHAR gtW[] = {'>'};
535 if (!This->element) return;
536 write_output_buffer(This->buffer, gtW, 1);
539 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
541 SysFreeString(This->element);
542 if (name)
543 This->element = len != -1 ? SysAllocStringLen(name, len) : SysAllocString(name);
544 else
545 This->element = NULL;
548 static inline HRESULT flush_output_buffer(mxwriter *This)
550 close_element_starttag(This);
551 set_element_name(This, NULL, 0);
552 This->cdata = FALSE;
553 return write_data_to_stream(This);
556 /* Resets the mxwriter's output buffer by closing it, then creating a new
557 * output buffer using the given encoding.
559 static inline void reset_output_buffer(mxwriter *This)
561 close_output_buffer(This);
562 This->dest_written = 0;
565 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
567 writer->props[property] = value;
568 writer->prop_changed = TRUE;
569 return S_OK;
572 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
574 if (!value) return E_POINTER;
575 *value = writer->props[property];
576 return S_OK;
579 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
581 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
584 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
586 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
589 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
591 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
594 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
596 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
599 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
601 mxwriter *This = impl_from_IMXWriter( iface );
603 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
605 *obj = NULL;
607 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
608 IsEqualGUID( riid, &IID_IDispatch ) ||
609 IsEqualGUID( riid, &IID_IUnknown ) )
611 *obj = &This->IMXWriter_iface;
613 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
615 *obj = &This->ISAXContentHandler_iface;
617 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
619 *obj = &This->ISAXLexicalHandler_iface;
621 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
623 *obj = &This->ISAXDeclHandler_iface;
625 else if (dispex_query_interface(&This->dispex, riid, obj))
627 return *obj ? S_OK : E_NOINTERFACE;
629 else
631 ERR("interface %s not implemented\n", debugstr_guid(riid));
632 *obj = NULL;
633 return E_NOINTERFACE;
636 IMXWriter_AddRef(iface);
637 return S_OK;
640 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
642 mxwriter *This = impl_from_IMXWriter( iface );
643 LONG ref = InterlockedIncrement(&This->ref);
645 TRACE("(%p)->(%d)\n", This, ref);
647 return ref;
650 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
652 mxwriter *This = impl_from_IMXWriter( iface );
653 ULONG ref = InterlockedDecrement(&This->ref);
655 TRACE("(%p)->(%d)\n", This, ref);
657 if(!ref)
659 /* Windows flushes the buffer when the interface is destroyed. */
660 flush_output_buffer(This);
661 free_output_buffer(This->buffer);
663 if (This->dest) IStream_Release(This->dest);
664 SysFreeString(This->version);
665 SysFreeString(This->encoding);
667 SysFreeString(This->element);
668 release_dispex(&This->dispex);
669 heap_free(This);
672 return ref;
675 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
677 mxwriter *This = impl_from_IMXWriter( iface );
678 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
681 static HRESULT WINAPI mxwriter_GetTypeInfo(
682 IMXWriter *iface,
683 UINT iTInfo, LCID lcid,
684 ITypeInfo** ppTInfo )
686 mxwriter *This = impl_from_IMXWriter( iface );
687 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
688 iTInfo, lcid, ppTInfo);
691 static HRESULT WINAPI mxwriter_GetIDsOfNames(
692 IMXWriter *iface,
693 REFIID riid, LPOLESTR* rgszNames,
694 UINT cNames, LCID lcid, DISPID* rgDispId )
696 mxwriter *This = impl_from_IMXWriter( iface );
697 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
698 riid, rgszNames, cNames, lcid, rgDispId);
701 static HRESULT WINAPI mxwriter_Invoke(
702 IMXWriter *iface,
703 DISPID dispIdMember, REFIID riid, LCID lcid,
704 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
705 EXCEPINFO* pExcepInfo, UINT* puArgErr )
707 mxwriter *This = impl_from_IMXWriter( iface );
708 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
709 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
712 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
714 mxwriter *This = impl_from_IMXWriter( iface );
715 HRESULT hr;
717 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
719 hr = flush_output_buffer(This);
720 if (FAILED(hr))
721 return hr;
723 switch (V_VT(&dest))
725 case VT_EMPTY:
727 if (This->dest) IStream_Release(This->dest);
728 This->dest = NULL;
729 reset_output_buffer(This);
730 break;
732 case VT_UNKNOWN:
734 IStream *stream;
736 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
737 if (hr == S_OK)
739 /* Recreate the output buffer to make sure it's using the correct encoding. */
740 reset_output_buffer(This);
742 if (This->dest) IStream_Release(This->dest);
743 This->dest = stream;
744 break;
747 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
748 return E_NOTIMPL;
750 default:
751 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
752 return E_NOTIMPL;
755 return S_OK;
758 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
760 mxwriter *This = impl_from_IMXWriter( iface );
762 TRACE("(%p)->(%p)\n", This, dest);
764 if (!dest) return E_POINTER;
766 if (!This->dest)
768 HRESULT hr = flush_output_buffer(This);
769 if (FAILED(hr))
770 return hr;
772 V_VT(dest) = VT_BSTR;
773 V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
775 return S_OK;
778 /* we only support IStream output so far */
779 V_VT(dest) = VT_UNKNOWN;
780 V_UNKNOWN(dest) = (IUnknown*)This->dest;
781 IStream_AddRef(This->dest);
783 return S_OK;
786 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
788 mxwriter *This = impl_from_IMXWriter( iface );
789 xml_encoding enc;
790 HRESULT hr;
792 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
794 enc = parse_encoding_name(encoding);
795 if (enc == XmlEncoding_Unknown)
797 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
798 return E_INVALIDARG;
801 hr = flush_output_buffer(This);
802 if (FAILED(hr))
803 return hr;
805 SysReAllocString(&This->encoding, encoding);
806 This->xml_enc = enc;
808 TRACE("got encoding %d\n", This->xml_enc);
809 reset_output_buffer(This);
810 return S_OK;
813 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
815 mxwriter *This = impl_from_IMXWriter( iface );
817 TRACE("(%p)->(%p)\n", This, encoding);
819 if (!encoding) return E_POINTER;
821 *encoding = SysAllocString(This->encoding);
822 if (!*encoding) return E_OUTOFMEMORY;
824 return S_OK;
827 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
829 mxwriter *This = impl_from_IMXWriter( iface );
831 TRACE("(%p)->(%d)\n", This, value);
832 return writer_set_property(This, MXWriter_BOM, value);
835 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
837 mxwriter *This = impl_from_IMXWriter( iface );
839 TRACE("(%p)->(%p)\n", This, value);
840 return writer_get_property(This, MXWriter_BOM, value);
843 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
845 mxwriter *This = impl_from_IMXWriter( iface );
847 TRACE("(%p)->(%d)\n", This, value);
848 return writer_set_property(This, MXWriter_Indent, value);
851 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
853 mxwriter *This = impl_from_IMXWriter( iface );
855 TRACE("(%p)->(%p)\n", This, value);
856 return writer_get_property(This, MXWriter_Indent, value);
859 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
861 mxwriter *This = impl_from_IMXWriter( iface );
863 TRACE("(%p)->(%d)\n", This, value);
864 return writer_set_property(This, MXWriter_Standalone, value);
867 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
869 mxwriter *This = impl_from_IMXWriter( iface );
871 TRACE("(%p)->(%p)\n", This, value);
872 return writer_get_property(This, MXWriter_Standalone, value);
875 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
877 mxwriter *This = impl_from_IMXWriter( iface );
879 TRACE("(%p)->(%d)\n", This, value);
880 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
883 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
885 mxwriter *This = impl_from_IMXWriter( iface );
887 TRACE("(%p)->(%p)\n", This, value);
888 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
891 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
893 mxwriter *This = impl_from_IMXWriter( iface );
895 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
897 if (!version) return E_INVALIDARG;
899 SysFreeString(This->version);
900 This->version = SysAllocString(version);
902 return S_OK;
905 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
907 mxwriter *This = impl_from_IMXWriter( iface );
909 TRACE("(%p)->(%p)\n", This, version);
911 if (!version) return E_POINTER;
913 return return_bstr(This->version, version);
916 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
918 mxwriter *This = impl_from_IMXWriter( iface );
920 TRACE("(%p)->(%d)\n", This, value);
921 return writer_set_property(This, MXWriter_DisableEscaping, value);
924 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
926 mxwriter *This = impl_from_IMXWriter( iface );
928 TRACE("(%p)->(%p)\n", This, value);
929 return writer_get_property(This, MXWriter_DisableEscaping, value);
932 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
934 mxwriter *This = impl_from_IMXWriter( iface );
935 TRACE("(%p)\n", This);
936 return flush_output_buffer(This);
939 static const struct IMXWriterVtbl MXWriterVtbl =
941 mxwriter_QueryInterface,
942 mxwriter_AddRef,
943 mxwriter_Release,
944 mxwriter_GetTypeInfoCount,
945 mxwriter_GetTypeInfo,
946 mxwriter_GetIDsOfNames,
947 mxwriter_Invoke,
948 mxwriter_put_output,
949 mxwriter_get_output,
950 mxwriter_put_encoding,
951 mxwriter_get_encoding,
952 mxwriter_put_byteOrderMark,
953 mxwriter_get_byteOrderMark,
954 mxwriter_put_indent,
955 mxwriter_get_indent,
956 mxwriter_put_standalone,
957 mxwriter_get_standalone,
958 mxwriter_put_omitXMLDeclaration,
959 mxwriter_get_omitXMLDeclaration,
960 mxwriter_put_version,
961 mxwriter_get_version,
962 mxwriter_put_disableOutputEscaping,
963 mxwriter_get_disableOutputEscaping,
964 mxwriter_flush
967 /*** ISAXContentHandler ***/
968 static HRESULT WINAPI SAXContentHandler_QueryInterface(
969 ISAXContentHandler *iface,
970 REFIID riid,
971 void **obj)
973 mxwriter *This = impl_from_ISAXContentHandler( iface );
974 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
977 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
979 mxwriter *This = impl_from_ISAXContentHandler( iface );
980 return IMXWriter_AddRef(&This->IMXWriter_iface);
983 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
985 mxwriter *This = impl_from_ISAXContentHandler( iface );
986 return IMXWriter_Release(&This->IMXWriter_iface);
989 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
990 ISAXContentHandler *iface,
991 ISAXLocator *locator)
993 mxwriter *This = impl_from_ISAXContentHandler( iface );
994 FIXME("(%p)->(%p)\n", This, locator);
995 return E_NOTIMPL;
998 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
1000 mxwriter *This = impl_from_ISAXContentHandler( iface );
1002 TRACE("(%p)\n", This);
1004 /* If properties have been changed since the last "endDocument" call
1005 * we need to reset the output buffer. If we don't the output buffer
1006 * could end up with multiple XML documents in it, plus this seems to
1007 * be how Windows works.
1009 if (This->prop_changed) {
1010 reset_output_buffer(This);
1011 This->prop_changed = FALSE;
1014 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
1016 write_prolog_buffer(This);
1018 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
1019 static const char utf16BOM[] = {0xff,0xfe};
1021 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
1022 /* Windows passes a NULL pointer as the pcbWritten parameter and
1023 * ignores any error codes returned from this Write call.
1025 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
1028 return S_OK;
1031 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
1033 mxwriter *This = impl_from_ISAXContentHandler( iface );
1034 TRACE("(%p)\n", This);
1035 This->prop_changed = FALSE;
1036 return flush_output_buffer(This);
1039 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
1040 ISAXContentHandler *iface,
1041 const WCHAR *prefix,
1042 int nprefix,
1043 const WCHAR *uri,
1044 int nuri)
1046 mxwriter *This = impl_from_ISAXContentHandler( iface );
1047 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
1048 return E_NOTIMPL;
1051 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
1052 ISAXContentHandler *iface,
1053 const WCHAR *prefix,
1054 int nprefix)
1056 mxwriter *This = impl_from_ISAXContentHandler( iface );
1057 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
1058 return E_NOTIMPL;
1061 static HRESULT WINAPI SAXContentHandler_startElement(
1062 ISAXContentHandler *iface,
1063 const WCHAR *namespaceUri,
1064 int nnamespaceUri,
1065 const WCHAR *local_name,
1066 int nlocal_name,
1067 const WCHAR *QName,
1068 int nQName,
1069 ISAXAttributes *attr)
1071 mxwriter *This = impl_from_ISAXContentHandler( iface );
1072 static const WCHAR ltW[] = {'<'};
1074 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
1075 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
1077 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1078 (nQName == -1 && This->class_version == MSXML6))
1079 return E_INVALIDARG;
1081 close_element_starttag(This);
1082 set_element_name(This, QName ? QName : emptyW,
1083 QName ? nQName : 0);
1085 write_output_buffer(This->buffer, ltW, 1);
1086 write_output_buffer(This->buffer, QName, nQName);
1088 if (attr)
1090 int length, i, escape;
1091 HRESULT hr;
1093 hr = ISAXAttributes_getLength(attr, &length);
1094 if (FAILED(hr)) return hr;
1096 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
1097 (This->class_version == MSXML4 || This->class_version == MSXML6);
1099 for (i = 0; i < length; i++)
1101 static const WCHAR eqW[] = {'='};
1102 const WCHAR *str;
1103 int len = 0;
1105 hr = ISAXAttributes_getQName(attr, i, &str, &len);
1106 if (FAILED(hr)) return hr;
1108 /* space separator in front of every attribute */
1109 write_output_buffer(This->buffer, spaceW, 1);
1110 write_output_buffer(This->buffer, str, len);
1112 write_output_buffer(This->buffer, eqW, 1);
1114 len = 0;
1115 hr = ISAXAttributes_getValue(attr, i, &str, &len);
1116 if (FAILED(hr)) return hr;
1118 if (escape)
1120 WCHAR *escaped = get_escaped_string(str, EscapeValue, &len);
1121 write_output_buffer_quoted(This->buffer, escaped, len);
1122 heap_free(escaped);
1124 else
1125 write_output_buffer_quoted(This->buffer, str, len);
1129 return S_OK;
1132 static HRESULT WINAPI SAXContentHandler_endElement(
1133 ISAXContentHandler *iface,
1134 const WCHAR *namespaceUri,
1135 int nnamespaceUri,
1136 const WCHAR * local_name,
1137 int nlocal_name,
1138 const WCHAR *QName,
1139 int nQName)
1141 mxwriter *This = impl_from_ISAXContentHandler( iface );
1143 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1144 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1146 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1147 (nQName == -1 && This->class_version == MSXML6))
1148 return E_INVALIDARG;
1150 if (This->element)
1152 static const WCHAR closeW[] = {'/','>'};
1153 write_output_buffer(This->buffer, closeW, 2);
1155 else
1157 static const WCHAR closetagW[] = {'<','/'};
1158 static const WCHAR gtW[] = {'>'};
1160 write_output_buffer(This->buffer, closetagW, 2);
1161 write_output_buffer(This->buffer, QName, nQName);
1162 write_output_buffer(This->buffer, gtW, 1);
1165 set_element_name(This, NULL, 0);
1167 return S_OK;
1170 static HRESULT WINAPI SAXContentHandler_characters(
1171 ISAXContentHandler *iface,
1172 const WCHAR *chars,
1173 int nchars)
1175 mxwriter *This = impl_from_ISAXContentHandler( iface );
1177 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1179 if (!chars) return E_INVALIDARG;
1181 close_element_starttag(This);
1182 set_element_name(This, NULL, 0);
1184 if (nchars)
1186 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
1187 write_output_buffer(This->buffer, chars, nchars);
1188 else
1190 int len = nchars;
1191 WCHAR *escaped;
1193 escaped = get_escaped_string(chars, EscapeText, &len);
1194 write_output_buffer(This->buffer, escaped, len);
1195 heap_free(escaped);
1199 return S_OK;
1202 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1203 ISAXContentHandler *iface,
1204 const WCHAR *chars,
1205 int nchars)
1207 mxwriter *This = impl_from_ISAXContentHandler( iface );
1209 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1211 if (!chars) return E_INVALIDARG;
1213 write_output_buffer(This->buffer, chars, nchars);
1215 return S_OK;
1218 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1219 ISAXContentHandler *iface,
1220 const WCHAR *target,
1221 int ntarget,
1222 const WCHAR *data,
1223 int ndata)
1225 mxwriter *This = impl_from_ISAXContentHandler( iface );
1226 static const WCHAR openpiW[] = {'<','?'};
1227 static const WCHAR closepiW[] = {'?','>','\r','\n'};
1229 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1231 if (!target) return E_INVALIDARG;
1233 write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
1235 if (*target)
1236 write_output_buffer(This->buffer, target, ntarget);
1238 if (data && *data && ndata)
1240 write_output_buffer(This->buffer, spaceW, 1);
1241 write_output_buffer(This->buffer, data, ndata);
1244 write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
1246 return S_OK;
1249 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1250 ISAXContentHandler *iface,
1251 const WCHAR *name,
1252 int nname)
1254 mxwriter *This = impl_from_ISAXContentHandler( iface );
1255 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1256 return E_NOTIMPL;
1259 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1261 SAXContentHandler_QueryInterface,
1262 SAXContentHandler_AddRef,
1263 SAXContentHandler_Release,
1264 SAXContentHandler_putDocumentLocator,
1265 SAXContentHandler_startDocument,
1266 SAXContentHandler_endDocument,
1267 SAXContentHandler_startPrefixMapping,
1268 SAXContentHandler_endPrefixMapping,
1269 SAXContentHandler_startElement,
1270 SAXContentHandler_endElement,
1271 SAXContentHandler_characters,
1272 SAXContentHandler_ignorableWhitespace,
1273 SAXContentHandler_processingInstruction,
1274 SAXContentHandler_skippedEntity
1277 /*** ISAXLexicalHandler ***/
1278 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1279 REFIID riid, void **obj)
1281 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1282 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1285 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1287 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1288 return IMXWriter_AddRef(&This->IMXWriter_iface);
1291 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1293 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1294 return IMXWriter_Release(&This->IMXWriter_iface);
1297 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1298 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1299 const WCHAR *systemId, int systemId_len)
1301 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1302 static const WCHAR openintW[] = {'[','\r','\n'};
1304 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1306 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1307 debugstr_wn(systemId, systemId_len));
1309 if (!name) return E_INVALIDARG;
1311 write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1313 if (*name)
1315 write_output_buffer(This->buffer, name, name_len);
1316 write_output_buffer(This->buffer, spaceW, 1);
1319 if (publicId)
1321 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1323 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1324 write_output_buffer_quoted(This->buffer, publicId, publicId_len);
1326 if (!systemId) return E_INVALIDARG;
1328 if (*publicId)
1329 write_output_buffer(This->buffer, spaceW, 1);
1331 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1333 if (*systemId)
1334 write_output_buffer(This->buffer, spaceW, 1);
1336 else if (systemId)
1338 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1340 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1341 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1342 if (*systemId)
1343 write_output_buffer(This->buffer, spaceW, 1);
1346 write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
1348 return S_OK;
1351 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1353 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1354 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1356 TRACE("(%p)\n", This);
1358 write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1360 return S_OK;
1363 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1365 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1366 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1367 return E_NOTIMPL;
1370 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1372 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1373 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1374 return E_NOTIMPL;
1377 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1379 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1380 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1382 TRACE("(%p)\n", This);
1384 write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1385 This->cdata = TRUE;
1387 return S_OK;
1390 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1392 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1393 static const WCHAR ecdataW[] = {']',']','>'};
1395 TRACE("(%p)\n", This);
1397 write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1398 This->cdata = FALSE;
1400 return S_OK;
1403 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1405 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1406 static const WCHAR copenW[] = {'<','!','-','-'};
1407 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1409 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1411 if (!chars) return E_INVALIDARG;
1413 close_element_starttag(This);
1415 write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
1416 if (nchars)
1417 write_output_buffer(This->buffer, chars, nchars);
1418 write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1420 return S_OK;
1423 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1425 SAXLexicalHandler_QueryInterface,
1426 SAXLexicalHandler_AddRef,
1427 SAXLexicalHandler_Release,
1428 SAXLexicalHandler_startDTD,
1429 SAXLexicalHandler_endDTD,
1430 SAXLexicalHandler_startEntity,
1431 SAXLexicalHandler_endEntity,
1432 SAXLexicalHandler_startCDATA,
1433 SAXLexicalHandler_endCDATA,
1434 SAXLexicalHandler_comment
1437 /*** ISAXDeclHandler ***/
1438 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1439 REFIID riid, void **obj)
1441 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1442 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1445 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1447 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1448 return IMXWriter_AddRef(&This->IMXWriter_iface);
1451 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1453 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1454 return IMXWriter_Release(&This->IMXWriter_iface);
1457 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1458 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1460 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1461 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1463 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1464 debugstr_wn(model, n_model), n_model);
1466 if (!name || !model) return E_INVALIDARG;
1468 write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
1469 if (n_name) {
1470 write_output_buffer(This->buffer, name, n_name);
1471 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1473 if (n_model)
1474 write_output_buffer(This->buffer, model, n_model);
1475 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1477 return S_OK;
1480 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1481 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1482 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1483 const WCHAR *value, int n_value)
1485 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1486 static const WCHAR attlistW[] = {'<','!','A','T','T','L','I','S','T',' '};
1487 static const WCHAR closetagW[] = {'>','\r','\n'};
1489 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element,
1490 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1491 debugstr_wn(value, n_value), n_value);
1493 write_output_buffer(This->buffer, attlistW, sizeof(attlistW)/sizeof(WCHAR));
1494 if (n_element) {
1495 write_output_buffer(This->buffer, element, n_element);
1496 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1499 if (n_attr) {
1500 write_output_buffer(This->buffer, attr, n_attr);
1501 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1504 if (n_type) {
1505 write_output_buffer(This->buffer, type, n_type);
1506 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1509 if (n_default) {
1510 write_output_buffer(This->buffer, Default, n_default);
1511 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1514 if (n_value)
1515 write_output_buffer_quoted(This->buffer, value, n_value);
1517 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1519 return S_OK;
1522 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1523 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1525 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1526 static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
1528 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1529 debugstr_wn(value, n_value), n_value);
1531 if (!name || !value) return E_INVALIDARG;
1533 write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
1534 if (n_name) {
1535 write_output_buffer(This->buffer, name, n_name);
1536 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1539 if (n_value)
1540 write_output_buffer_quoted(This->buffer, value, n_value);
1542 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1544 return S_OK;
1547 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1548 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1549 const WCHAR *systemId, int n_systemId)
1551 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1552 FIXME("(%p)->(%s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1553 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1554 return E_NOTIMPL;
1557 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1558 SAXDeclHandler_QueryInterface,
1559 SAXDeclHandler_AddRef,
1560 SAXDeclHandler_Release,
1561 SAXDeclHandler_elementDecl,
1562 SAXDeclHandler_attributeDecl,
1563 SAXDeclHandler_internalEntityDecl,
1564 SAXDeclHandler_externalEntityDecl
1567 static const tid_t mxwriter_iface_tids[] = {
1568 IMXWriter_tid,
1572 static dispex_static_data_t mxwriter_dispex = {
1573 NULL,
1574 IMXWriter_tid,
1575 NULL,
1576 mxwriter_iface_tids
1579 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
1581 static const WCHAR version10W[] = {'1','.','0',0};
1582 mxwriter *This;
1583 HRESULT hr;
1585 TRACE("(%p, %p)\n", outer, ppObj);
1587 if (outer) FIXME("support aggregation, outer\n");
1589 This = heap_alloc( sizeof (*This) );
1590 if(!This)
1591 return E_OUTOFMEMORY;
1593 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
1594 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
1595 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
1596 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
1597 This->ref = 1;
1598 This->class_version = version;
1600 This->props[MXWriter_BOM] = VARIANT_TRUE;
1601 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
1602 This->props[MXWriter_Indent] = VARIANT_FALSE;
1603 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
1604 This->props[MXWriter_Standalone] = VARIANT_FALSE;
1605 This->prop_changed = FALSE;
1606 This->encoding = SysAllocString(utf16W);
1607 This->version = SysAllocString(version10W);
1608 This->xml_enc = XmlEncoding_UTF16;
1610 This->element = NULL;
1611 This->cdata = FALSE;
1613 This->dest = NULL;
1614 This->dest_written = 0;
1616 hr = alloc_output_buffer(This->xml_enc, &This->buffer);
1617 if (hr != S_OK) {
1618 SysFreeString(This->encoding);
1619 SysFreeString(This->version);
1620 heap_free(This);
1621 return hr;
1624 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
1626 *ppObj = &This->IMXWriter_iface;
1628 TRACE("returning iface %p\n", *ppObj);
1630 return S_OK;
1633 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
1635 mxattributes *This = impl_from_IMXAttributes( iface );
1637 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
1639 *ppObj = NULL;
1641 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1642 IsEqualGUID( riid, &IID_IDispatch ) ||
1643 IsEqualGUID( riid, &IID_IMXAttributes ))
1645 *ppObj = iface;
1647 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
1649 *ppObj = &This->ISAXAttributes_iface;
1651 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
1653 *ppObj = &This->IVBSAXAttributes_iface;
1655 else if (dispex_query_interface(&This->dispex, riid, ppObj))
1657 return *ppObj ? S_OK : E_NOINTERFACE;
1659 else
1661 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1662 return E_NOINTERFACE;
1665 IMXAttributes_AddRef( iface );
1667 return S_OK;
1670 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface)
1672 mxattributes *This = impl_from_IMXAttributes( iface );
1673 ULONG ref = InterlockedIncrement( &This->ref );
1674 TRACE("(%p)->(%d)\n", This, ref );
1675 return ref;
1678 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface)
1680 mxattributes *This = impl_from_IMXAttributes( iface );
1681 LONG ref = InterlockedDecrement( &This->ref );
1683 TRACE("(%p)->(%d)\n", This, ref);
1685 if (ref == 0)
1687 int i;
1689 for (i = 0; i < This->length; i++)
1691 SysFreeString(This->attr[i].qname);
1692 SysFreeString(This->attr[i].local);
1693 SysFreeString(This->attr[i].uri);
1694 SysFreeString(This->attr[i].type);
1695 SysFreeString(This->attr[i].value);
1698 release_dispex(&This->dispex);
1699 heap_free(This->attr);
1700 heap_free(This);
1703 return ref;
1706 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo)
1708 mxattributes *This = impl_from_IMXAttributes( iface );
1709 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1712 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1714 mxattributes *This = impl_from_IMXAttributes( iface );
1715 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1718 static HRESULT WINAPI MXAttributes_GetIDsOfNames(
1719 IMXAttributes *iface,
1720 REFIID riid,
1721 LPOLESTR* rgszNames,
1722 UINT cNames,
1723 LCID lcid,
1724 DISPID* rgDispId)
1726 mxattributes *This = impl_from_IMXAttributes( iface );
1727 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
1728 riid, rgszNames, cNames, lcid, rgDispId);
1731 static HRESULT WINAPI MXAttributes_Invoke(
1732 IMXAttributes *iface,
1733 DISPID dispIdMember,
1734 REFIID riid,
1735 LCID lcid,
1736 WORD wFlags,
1737 DISPPARAMS* pDispParams,
1738 VARIANT* pVarResult,
1739 EXCEPINFO* pExcepInfo,
1740 UINT* puArgErr)
1742 mxattributes *This = impl_from_IMXAttributes( iface );
1743 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
1744 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1747 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface,
1748 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1750 mxattributes *This = impl_from_IMXAttributes( iface );
1751 mxattribute *attr;
1752 HRESULT hr;
1754 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName),
1755 debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1757 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6)
1758 return E_INVALIDARG;
1760 /* ensure array is large enough */
1761 hr = mxattributes_grow(This);
1762 if (hr != S_OK) return hr;
1764 attr = &This->attr[This->length];
1766 attr->qname = SysAllocString(QName);
1767 attr->local = SysAllocString(localName);
1768 attr->uri = SysAllocString(uri);
1769 attr->type = SysAllocString(type ? type : emptyW);
1770 attr->value = SysAllocString(value);
1771 This->length++;
1773 return S_OK;
1776 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface,
1777 VARIANT atts, int index)
1779 mxattributes *This = impl_from_IMXAttributes( iface );
1780 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index);
1781 return E_NOTIMPL;
1784 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface)
1786 mxattributes *This = impl_from_IMXAttributes( iface );
1787 int i;
1789 TRACE("(%p)\n", This);
1791 for (i = 0; i < This->length; i++)
1793 SysFreeString(This->attr[i].qname);
1794 SysFreeString(This->attr[i].local);
1795 SysFreeString(This->attr[i].uri);
1796 SysFreeString(This->attr[i].type);
1797 SysFreeString(This->attr[i].value);
1798 memset(&This->attr[i], 0, sizeof(mxattribute));
1801 This->length = 0;
1803 return S_OK;
1806 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
1808 mxattributes *This = impl_from_IMXAttributes( iface );
1809 FIXME("(%p)->(%d): stub\n", This, index);
1810 return E_NOTIMPL;
1813 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
1814 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1816 mxattributes *This = impl_from_IMXAttributes( iface );
1817 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri),
1818 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1819 return E_NOTIMPL;
1822 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts)
1824 mxattributes *This = impl_from_IMXAttributes( iface );
1825 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts));
1826 return E_NOTIMPL;
1829 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index,
1830 BSTR localName)
1832 mxattributes *This = impl_from_IMXAttributes( iface );
1833 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(localName));
1834 return E_NOTIMPL;
1837 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
1839 mxattributes *This = impl_from_IMXAttributes( iface );
1840 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(QName));
1841 return E_NOTIMPL;
1844 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
1846 mxattributes *This = impl_from_IMXAttributes( iface );
1847 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(uri));
1848 return E_NOTIMPL;
1851 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
1853 mxattributes *This = impl_from_IMXAttributes( iface );
1854 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(value));
1855 return E_NOTIMPL;
1858 static const IMXAttributesVtbl MXAttributesVtbl = {
1859 MXAttributes_QueryInterface,
1860 MXAttributes_AddRef,
1861 MXAttributes_Release,
1862 MXAttributes_GetTypeInfoCount,
1863 MXAttributes_GetTypeInfo,
1864 MXAttributes_GetIDsOfNames,
1865 MXAttributes_Invoke,
1866 MXAttributes_addAttribute,
1867 MXAttributes_addAttributeFromIndex,
1868 MXAttributes_clear,
1869 MXAttributes_removeAttribute,
1870 MXAttributes_setAttribute,
1871 MXAttributes_setAttributes,
1872 MXAttributes_setLocalName,
1873 MXAttributes_setQName,
1874 MXAttributes_setURI,
1875 MXAttributes_setValue
1878 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj)
1880 mxattributes *This = impl_from_ISAXAttributes( iface );
1881 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj);
1884 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface)
1886 mxattributes *This = impl_from_ISAXAttributes( iface );
1887 return IMXAttributes_AddRef(&This->IMXAttributes_iface);
1890 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface)
1892 mxattributes *This = impl_from_ISAXAttributes( iface );
1893 return IMXAttributes_Release(&This->IMXAttributes_iface);
1896 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length)
1898 mxattributes *This = impl_from_ISAXAttributes( iface );
1899 TRACE("(%p)->(%p)\n", This, length);
1901 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1902 return E_POINTER;
1904 *length = This->length;
1906 return S_OK;
1909 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri,
1910 int *len)
1912 mxattributes *This = impl_from_ISAXAttributes( iface );
1914 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len);
1916 if (index >= This->length || index < 0) return E_INVALIDARG;
1917 if (!uri || !len) return E_POINTER;
1919 *len = SysStringLen(This->attr[index].uri);
1920 *uri = This->attr[index].uri;
1922 return S_OK;
1925 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name,
1926 int *len)
1928 mxattributes *This = impl_from_ISAXAttributes( iface );
1930 TRACE("(%p)->(%d %p %p)\n", This, index, name, len);
1932 if (index >= This->length || index < 0) return E_INVALIDARG;
1933 if (!name || !len) return E_POINTER;
1935 *len = SysStringLen(This->attr[index].local);
1936 *name = This->attr[index].local;
1938 return S_OK;
1941 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length)
1943 mxattributes *This = impl_from_ISAXAttributes( iface );
1945 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length);
1947 if (index >= This->length) return E_INVALIDARG;
1948 if (!qname || !length) return E_POINTER;
1950 *qname = This->attr[index].qname;
1951 *length = SysStringLen(This->attr[index].qname);
1953 return S_OK;
1956 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len,
1957 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len)
1959 mxattributes *This = impl_from_ISAXAttributes( iface );
1961 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len);
1963 if (index >= This->length || index < 0)
1964 return E_INVALIDARG;
1966 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len)
1967 return E_POINTER;
1969 *uri_len = SysStringLen(This->attr[index].uri);
1970 *uri = This->attr[index].uri;
1972 *local_len = SysStringLen(This->attr[index].local);
1973 *local = This->attr[index].local;
1975 *qname_len = SysStringLen(This->attr[index].qname);
1976 *qname = This->attr[index].qname;
1978 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname));
1980 return S_OK;
1983 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len,
1984 const WCHAR *name, int len, int *index)
1986 mxattributes *This = impl_from_ISAXAttributes( iface );
1987 int i;
1989 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
1990 debugstr_wn(name, len), len, index);
1992 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1993 return E_POINTER;
1995 if (!uri || !name || !index) return E_INVALIDARG;
1997 for (i = 0; i < This->length; i++)
1999 if (uri_len != SysStringLen(This->attr[i].uri)) continue;
2000 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue;
2002 if (len != SysStringLen(This->attr[i].local)) continue;
2003 if (strncmpW(name, This->attr[i].local, len)) continue;
2005 *index = i;
2006 return S_OK;
2009 return E_INVALIDARG;
2012 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname,
2013 int len, int *index)
2015 mxattributes *This = impl_from_ISAXAttributes( iface );
2016 int i;
2018 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index);
2020 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2021 return E_POINTER;
2023 if (!qname || !index || !len) return E_INVALIDARG;
2025 for (i = 0; i < This->length; i++)
2027 if (len != SysStringLen(This->attr[i].qname)) continue;
2028 if (strncmpW(qname, This->attr[i].qname, len)) continue;
2030 *index = i;
2031 return S_OK;
2034 return E_INVALIDARG;
2037 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type,
2038 int *len)
2040 mxattributes *This = impl_from_ISAXAttributes( iface );
2042 TRACE("(%p)->(%d %p %p)\n", This, index, type, len);
2044 if (index >= This->length) return E_INVALIDARG;
2046 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2047 return E_POINTER;
2049 *type = This->attr[index].type;
2050 *len = SysStringLen(This->attr[index].type);
2052 return S_OK;
2055 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri,
2056 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType)
2058 mxattributes *This = impl_from_ISAXAttributes( iface );
2059 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri,
2060 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType);
2061 return E_NOTIMPL;
2064 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName,
2065 int nQName, const WCHAR ** pType, int * nType)
2067 mxattributes *This = impl_from_ISAXAttributes( iface );
2068 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType);
2069 return E_NOTIMPL;
2072 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value,
2073 int *len)
2075 mxattributes *This = impl_from_ISAXAttributes( iface );
2077 TRACE("(%p)->(%d %p %p)\n", This, index, value, len);
2079 if (index >= This->length) return E_INVALIDARG;
2081 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2082 return E_POINTER;
2084 *value = This->attr[index].value;
2085 *len = SysStringLen(This->attr[index].value);
2087 return S_OK;
2090 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri,
2091 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len)
2093 mxattributes *This = impl_from_ISAXAttributes( iface );
2094 HRESULT hr;
2095 int index;
2097 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
2098 debugstr_wn(name, name_len), name_len, value, value_len);
2100 if (!uri || !name || !value || !value_len)
2101 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2103 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index);
2104 if (hr == S_OK)
2105 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2107 return hr;
2110 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname,
2111 int qname_len, const WCHAR **value, int *value_len)
2113 mxattributes *This = impl_from_ISAXAttributes( iface );
2114 HRESULT hr;
2115 int index;
2117 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len);
2119 if (!qname || !value || !value_len)
2120 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2122 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index);
2123 if (hr == S_OK)
2124 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2126 return hr;
2129 static const ISAXAttributesVtbl SAXAttributesVtbl = {
2130 SAXAttributes_QueryInterface,
2131 SAXAttributes_AddRef,
2132 SAXAttributes_Release,
2133 SAXAttributes_getLength,
2134 SAXAttributes_getURI,
2135 SAXAttributes_getLocalName,
2136 SAXAttributes_getQName,
2137 SAXAttributes_getName,
2138 SAXAttributes_getIndexFromName,
2139 SAXAttributes_getIndexFromQName,
2140 SAXAttributes_getType,
2141 SAXAttributes_getTypeFromName,
2142 SAXAttributes_getTypeFromQName,
2143 SAXAttributes_getValue,
2144 SAXAttributes_getValueFromName,
2145 SAXAttributes_getValueFromQName
2148 static HRESULT WINAPI VBSAXAttributes_QueryInterface(
2149 IVBSAXAttributes* iface,
2150 REFIID riid,
2151 void **ppvObject)
2153 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2154 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
2155 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject);
2158 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface)
2160 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2161 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface);
2164 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface)
2166 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2167 return ISAXAttributes_Release(&This->ISAXAttributes_iface);
2170 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
2172 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2174 TRACE("(%p)->(%p)\n", This, pctinfo);
2176 *pctinfo = 1;
2178 return S_OK;
2181 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo(
2182 IVBSAXAttributes *iface,
2183 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2185 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2186 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2187 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
2190 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames(
2191 IVBSAXAttributes *iface,
2192 REFIID riid,
2193 LPOLESTR* rgszNames,
2194 UINT cNames,
2195 LCID lcid,
2196 DISPID* rgDispId)
2198 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2199 ITypeInfo *typeinfo;
2200 HRESULT hr;
2202 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2203 lcid, rgDispId);
2205 if(!rgszNames || cNames == 0 || !rgDispId)
2206 return E_INVALIDARG;
2208 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2209 if(SUCCEEDED(hr))
2211 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2212 ITypeInfo_Release(typeinfo);
2215 return hr;
2218 static HRESULT WINAPI VBSAXAttributes_Invoke(
2219 IVBSAXAttributes *iface,
2220 DISPID dispIdMember,
2221 REFIID riid,
2222 LCID lcid,
2223 WORD wFlags,
2224 DISPPARAMS* pDispParams,
2225 VARIANT* pVarResult,
2226 EXCEPINFO* pExcepInfo,
2227 UINT* puArgErr)
2229 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2230 ITypeInfo *typeinfo;
2231 HRESULT hr;
2233 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2234 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2236 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2237 if(SUCCEEDED(hr))
2239 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
2240 pDispParams, pVarResult, pExcepInfo, puArgErr);
2241 ITypeInfo_Release(typeinfo);
2244 return hr;
2247 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len)
2249 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2250 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len);
2253 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
2255 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2256 int len;
2258 return ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, (const WCHAR**)uri, &len);
2261 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
2263 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2264 int len;
2266 return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, (const WCHAR**)name, &len);
2269 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
2271 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2272 int len;
2274 return ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, (const WCHAR**)qname, &len);
2277 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
2279 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2280 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2281 name, SysStringLen(name), index);
2284 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index)
2286 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2287 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname,
2288 SysStringLen(qname), index);
2291 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index,BSTR *type)
2293 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2294 int len;
2296 return ISAXAttributes_getType(&This->ISAXAttributes_iface, index, (const WCHAR**)type, &len);
2299 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
2300 BSTR name, BSTR *type)
2302 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2303 int len;
2305 return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2306 name, SysStringLen(name), (const WCHAR**)type, &len);
2309 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
2311 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2312 int len;
2314 return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2315 (const WCHAR**)type, &len);
2318 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
2320 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2321 int len;
2323 return ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, (const WCHAR**)value, &len);
2326 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
2327 BSTR *value)
2329 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2330 int len;
2332 return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2333 name, SysStringLen(name), (const WCHAR**)value, &len);
2336 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
2338 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2339 int len;
2341 return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2342 (const WCHAR**)value, &len);
2345 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
2347 VBSAXAttributes_QueryInterface,
2348 VBSAXAttributes_AddRef,
2349 VBSAXAttributes_Release,
2350 VBSAXAttributes_GetTypeInfoCount,
2351 VBSAXAttributes_GetTypeInfo,
2352 VBSAXAttributes_GetIDsOfNames,
2353 VBSAXAttributes_Invoke,
2354 VBSAXAttributes_get_length,
2355 VBSAXAttributes_getURI,
2356 VBSAXAttributes_getLocalName,
2357 VBSAXAttributes_getQName,
2358 VBSAXAttributes_getIndexFromName,
2359 VBSAXAttributes_getIndexFromQName,
2360 VBSAXAttributes_getType,
2361 VBSAXAttributes_getTypeFromName,
2362 VBSAXAttributes_getTypeFromQName,
2363 VBSAXAttributes_getValue,
2364 VBSAXAttributes_getValueFromName,
2365 VBSAXAttributes_getValueFromQName
2368 static const tid_t mxattrs_iface_tids[] = {
2369 IMXAttributes_tid,
2373 static dispex_static_data_t mxattrs_dispex = {
2374 NULL,
2375 IMXAttributes_tid,
2376 NULL,
2377 mxattrs_iface_tids
2380 HRESULT SAXAttributes_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
2382 static const int default_count = 10;
2383 mxattributes *This;
2385 TRACE("(%p, %p)\n", outer, ppObj);
2387 This = heap_alloc( sizeof (*This) );
2388 if( !This )
2389 return E_OUTOFMEMORY;
2391 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl;
2392 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl;
2393 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl;
2394 This->ref = 1;
2396 This->class_version = version;
2398 This->attr = heap_alloc(default_count*sizeof(mxattribute));
2399 This->length = 0;
2400 This->allocated = default_count;
2402 *ppObj = &This->IMXAttributes_iface;
2404 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex);
2406 TRACE("returning iface %p\n", *ppObj);
2408 return S_OK;