dsound: Add eax properties
[wine/multimedia.git] / dlls / msxml3 / mxwriter.c
blobf03ceb07fab521901f9b5472f6fe59ad5aaefc38
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 if (ret->code_page == CP_UTF8) {
292 hr = init_encoded_buffer(&ret->encoded);
293 if (hr != S_OK) {
294 free_encoded_buffer(&ret->utf16);
295 heap_free(ret);
296 return hr;
299 else
300 memset(&ret->encoded, 0, sizeof(ret->encoded));
302 *buffer = ret;
304 return S_OK;
307 static void free_output_buffer(output_buffer *buffer)
309 free_encoded_buffer(&buffer->encoded);
310 free_encoded_buffer(&buffer->utf16);
311 heap_free(buffer);
314 static void grow_buffer(encoded_buffer *buffer, int length)
316 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
317 if (buffer->allocated < buffer->written + length + 4)
319 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
320 buffer->data = heap_realloc(buffer->data, grown_size);
321 buffer->allocated = grown_size;
325 static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
327 int length;
328 char *ptr;
330 if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
331 if (buffer->code_page != ~0)
333 length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
334 grow_buffer(&buffer->encoded, length);
335 ptr = buffer->encoded.data + buffer->encoded.written;
336 length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
337 buffer->encoded.written += len == -1 ? length-1 : length;
341 if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
342 /* WCHAR data just copied */
343 length = len == -1 ? strlenW(data) : len;
344 if (length)
346 length *= sizeof(WCHAR);
348 grow_buffer(&buffer->utf16, length);
349 ptr = buffer->utf16.data + buffer->utf16.written;
351 memcpy(ptr, data, length);
352 buffer->utf16.written += length;
353 ptr += length;
354 /* null termination */
355 memset(ptr, 0, sizeof(WCHAR));
359 return S_OK;
362 static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
364 return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
367 static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
369 write_output_buffer(buffer, quotW, 1);
370 write_output_buffer(buffer, data, len);
371 write_output_buffer(buffer, quotW, 1);
373 return S_OK;
376 /* frees buffer data, reallocates with a default lengths */
377 static void close_output_buffer(mxwriter *This)
379 heap_free(This->buffer->utf16.data);
380 heap_free(This->buffer->encoded.data);
381 init_encoded_buffer(&This->buffer->utf16);
382 init_encoded_buffer(&This->buffer->encoded);
383 get_code_page(This->xml_enc, &This->buffer->code_page);
386 /* escapes special characters like:
387 '<' -> "&lt;"
388 '&' -> "&amp;"
389 '"' -> "&quot;"
390 '>' -> "&gt;"
392 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
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',';'};
399 const int default_alloc = 100;
400 const int grow_thresh = 10;
401 int p = *len, conv_len;
402 WCHAR *ptr, *ret;
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));
408 while (*str && p)
410 if (ptr - ret > conv_len - grow_thresh)
412 int written = ptr - ret;
413 conv_len *= 2;
414 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
415 ptr += written;
418 switch (*str)
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)
435 memcpy(ptr, equotW, sizeof(equotW));
436 ptr += sizeof(equotW)/sizeof(WCHAR);
437 break;
439 /* fallthrough for text mode */
440 default:
441 *ptr++ = *str;
442 break;
445 str++;
446 if (*len != -1) p--;
449 if (*len != -1) *len = ptr-ret;
450 *++ptr = 0;
452 return ret;
455 static void write_prolog_buffer(const mxwriter *This)
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 static const WCHAR crlfW[] = {'\r','\n'};
464 /* version */
465 write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
466 write_output_buffer_quoted(This->buffer, This->version, -1);
468 /* encoding */
469 write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
471 /* always write UTF-16 to WCHAR buffer */
472 write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
473 write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
474 write_output_buffer(This->buffer, quotW, 1);
476 /* standalone */
477 write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
478 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
479 write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
480 else
481 write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
483 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
486 /* Attempts to the write data from the mxwriter's buffer to
487 * the destination stream (if there is one).
489 static HRESULT write_data_to_stream(mxwriter *This)
491 encoded_buffer *buffer;
492 ULONG written = 0;
493 HRESULT hr;
495 if (!This->dest)
496 return S_OK;
498 if (This->xml_enc != XmlEncoding_UTF16)
499 buffer = &This->buffer->encoded;
500 else
501 buffer = &This->buffer->utf16;
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.
511 return S_OK;
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.
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;
524 This->dest_written += written;
525 return hr;
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)
532 static const WCHAR gtW[] = {'>'};
533 if (!This->element) return;
534 write_output_buffer(This->buffer, gtW, 1);
537 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
539 SysFreeString(This->element);
540 if (name)
541 This->element = len != -1 ? SysAllocStringLen(name, len) : SysAllocString(name);
542 else
543 This->element = NULL;
546 static inline HRESULT flush_output_buffer(mxwriter *This)
548 close_element_starttag(This);
549 set_element_name(This, NULL, 0);
550 This->cdata = FALSE;
551 return write_data_to_stream(This);
554 /* Resets the mxwriter's output buffer by closing it, then creating a new
555 * output buffer using the given encoding.
557 static inline void reset_output_buffer(mxwriter *This)
559 close_output_buffer(This);
560 This->dest_written = 0;
563 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
565 writer->props[property] = value;
566 writer->prop_changed = TRUE;
567 return S_OK;
570 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
572 if (!value) return E_POINTER;
573 *value = writer->props[property];
574 return S_OK;
577 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
579 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
582 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
584 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
587 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
589 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
592 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
594 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
597 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
599 mxwriter *This = impl_from_IMXWriter( iface );
601 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
603 *obj = NULL;
605 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
606 IsEqualGUID( riid, &IID_IDispatch ) ||
607 IsEqualGUID( riid, &IID_IUnknown ) )
609 *obj = &This->IMXWriter_iface;
611 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
613 *obj = &This->ISAXContentHandler_iface;
615 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
617 *obj = &This->ISAXLexicalHandler_iface;
619 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
621 *obj = &This->ISAXDeclHandler_iface;
623 else if (dispex_query_interface(&This->dispex, riid, obj))
625 return *obj ? S_OK : E_NOINTERFACE;
627 else
629 ERR("interface %s not implemented\n", debugstr_guid(riid));
630 *obj = NULL;
631 return E_NOINTERFACE;
634 IMXWriter_AddRef(iface);
635 return S_OK;
638 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
640 mxwriter *This = impl_from_IMXWriter( iface );
641 LONG ref = InterlockedIncrement(&This->ref);
643 TRACE("(%p)->(%d)\n", This, ref);
645 return ref;
648 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
650 mxwriter *This = impl_from_IMXWriter( iface );
651 ULONG ref = InterlockedDecrement(&This->ref);
653 TRACE("(%p)->(%d)\n", This, ref);
655 if(!ref)
657 /* Windows flushes the buffer when the interface is destroyed. */
658 flush_output_buffer(This);
659 free_output_buffer(This->buffer);
661 if (This->dest) IStream_Release(This->dest);
662 SysFreeString(This->version);
663 SysFreeString(This->encoding);
665 SysFreeString(This->element);
666 release_dispex(&This->dispex);
667 heap_free(This);
670 return ref;
673 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
675 mxwriter *This = impl_from_IMXWriter( iface );
676 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
679 static HRESULT WINAPI mxwriter_GetTypeInfo(
680 IMXWriter *iface,
681 UINT iTInfo, LCID lcid,
682 ITypeInfo** ppTInfo )
684 mxwriter *This = impl_from_IMXWriter( iface );
685 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
686 iTInfo, lcid, ppTInfo);
689 static HRESULT WINAPI mxwriter_GetIDsOfNames(
690 IMXWriter *iface,
691 REFIID riid, LPOLESTR* rgszNames,
692 UINT cNames, LCID lcid, DISPID* rgDispId )
694 mxwriter *This = impl_from_IMXWriter( iface );
695 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
696 riid, rgszNames, cNames, lcid, rgDispId);
699 static HRESULT WINAPI mxwriter_Invoke(
700 IMXWriter *iface,
701 DISPID dispIdMember, REFIID riid, LCID lcid,
702 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
703 EXCEPINFO* pExcepInfo, UINT* puArgErr )
705 mxwriter *This = impl_from_IMXWriter( iface );
706 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
707 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
710 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
712 mxwriter *This = impl_from_IMXWriter( iface );
713 HRESULT hr;
715 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
717 hr = flush_output_buffer(This);
718 if (FAILED(hr))
719 return hr;
721 switch (V_VT(&dest))
723 case VT_EMPTY:
725 if (This->dest) IStream_Release(This->dest);
726 This->dest = NULL;
727 reset_output_buffer(This);
728 break;
730 case VT_UNKNOWN:
732 IStream *stream;
734 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
735 if (hr == S_OK)
737 /* Recreate the output buffer to make sure it's using the correct encoding. */
738 reset_output_buffer(This);
740 if (This->dest) IStream_Release(This->dest);
741 This->dest = stream;
742 break;
745 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
746 return E_NOTIMPL;
748 default:
749 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
750 return E_NOTIMPL;
753 return S_OK;
756 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
758 mxwriter *This = impl_from_IMXWriter( iface );
760 TRACE("(%p)->(%p)\n", This, dest);
762 if (!dest) return E_POINTER;
764 if (!This->dest)
766 HRESULT hr = flush_output_buffer(This);
767 if (FAILED(hr))
768 return hr;
770 V_VT(dest) = VT_BSTR;
771 V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
773 return S_OK;
776 /* we only support IStream output so far */
777 V_VT(dest) = VT_UNKNOWN;
778 V_UNKNOWN(dest) = (IUnknown*)This->dest;
779 IStream_AddRef(This->dest);
781 return S_OK;
784 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
786 mxwriter *This = impl_from_IMXWriter( iface );
787 xml_encoding enc;
788 HRESULT hr;
790 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
792 enc = parse_encoding_name(encoding);
793 if (enc == XmlEncoding_Unknown)
795 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
796 return E_INVALIDARG;
799 hr = flush_output_buffer(This);
800 if (FAILED(hr))
801 return hr;
803 SysReAllocString(&This->encoding, encoding);
804 This->xml_enc = enc;
806 TRACE("got encoding %d\n", This->xml_enc);
807 reset_output_buffer(This);
808 return S_OK;
811 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
813 mxwriter *This = impl_from_IMXWriter( iface );
815 TRACE("(%p)->(%p)\n", This, encoding);
817 if (!encoding) return E_POINTER;
819 *encoding = SysAllocString(This->encoding);
820 if (!*encoding) return E_OUTOFMEMORY;
822 return S_OK;
825 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
827 mxwriter *This = impl_from_IMXWriter( iface );
829 TRACE("(%p)->(%d)\n", This, value);
830 return writer_set_property(This, MXWriter_BOM, value);
833 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
835 mxwriter *This = impl_from_IMXWriter( iface );
837 TRACE("(%p)->(%p)\n", This, value);
838 return writer_get_property(This, MXWriter_BOM, value);
841 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
843 mxwriter *This = impl_from_IMXWriter( iface );
845 TRACE("(%p)->(%d)\n", This, value);
846 return writer_set_property(This, MXWriter_Indent, value);
849 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
851 mxwriter *This = impl_from_IMXWriter( iface );
853 TRACE("(%p)->(%p)\n", This, value);
854 return writer_get_property(This, MXWriter_Indent, value);
857 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
859 mxwriter *This = impl_from_IMXWriter( iface );
861 TRACE("(%p)->(%d)\n", This, value);
862 return writer_set_property(This, MXWriter_Standalone, value);
865 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
867 mxwriter *This = impl_from_IMXWriter( iface );
869 TRACE("(%p)->(%p)\n", This, value);
870 return writer_get_property(This, MXWriter_Standalone, value);
873 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
875 mxwriter *This = impl_from_IMXWriter( iface );
877 TRACE("(%p)->(%d)\n", This, value);
878 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
881 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
883 mxwriter *This = impl_from_IMXWriter( iface );
885 TRACE("(%p)->(%p)\n", This, value);
886 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
889 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
891 mxwriter *This = impl_from_IMXWriter( iface );
893 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
895 if (!version) return E_INVALIDARG;
897 SysFreeString(This->version);
898 This->version = SysAllocString(version);
900 return S_OK;
903 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
905 mxwriter *This = impl_from_IMXWriter( iface );
907 TRACE("(%p)->(%p)\n", This, version);
909 if (!version) return E_POINTER;
911 return return_bstr(This->version, version);
914 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
916 mxwriter *This = impl_from_IMXWriter( iface );
918 TRACE("(%p)->(%d)\n", This, value);
919 return writer_set_property(This, MXWriter_DisableEscaping, value);
922 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
924 mxwriter *This = impl_from_IMXWriter( iface );
926 TRACE("(%p)->(%p)\n", This, value);
927 return writer_get_property(This, MXWriter_DisableEscaping, value);
930 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
932 mxwriter *This = impl_from_IMXWriter( iface );
933 TRACE("(%p)\n", This);
934 return flush_output_buffer(This);
937 static const struct IMXWriterVtbl MXWriterVtbl =
939 mxwriter_QueryInterface,
940 mxwriter_AddRef,
941 mxwriter_Release,
942 mxwriter_GetTypeInfoCount,
943 mxwriter_GetTypeInfo,
944 mxwriter_GetIDsOfNames,
945 mxwriter_Invoke,
946 mxwriter_put_output,
947 mxwriter_get_output,
948 mxwriter_put_encoding,
949 mxwriter_get_encoding,
950 mxwriter_put_byteOrderMark,
951 mxwriter_get_byteOrderMark,
952 mxwriter_put_indent,
953 mxwriter_get_indent,
954 mxwriter_put_standalone,
955 mxwriter_get_standalone,
956 mxwriter_put_omitXMLDeclaration,
957 mxwriter_get_omitXMLDeclaration,
958 mxwriter_put_version,
959 mxwriter_get_version,
960 mxwriter_put_disableOutputEscaping,
961 mxwriter_get_disableOutputEscaping,
962 mxwriter_flush
965 /*** ISAXContentHandler ***/
966 static HRESULT WINAPI SAXContentHandler_QueryInterface(
967 ISAXContentHandler *iface,
968 REFIID riid,
969 void **obj)
971 mxwriter *This = impl_from_ISAXContentHandler( iface );
972 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
975 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
977 mxwriter *This = impl_from_ISAXContentHandler( iface );
978 return IMXWriter_AddRef(&This->IMXWriter_iface);
981 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
983 mxwriter *This = impl_from_ISAXContentHandler( iface );
984 return IMXWriter_Release(&This->IMXWriter_iface);
987 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
988 ISAXContentHandler *iface,
989 ISAXLocator *locator)
991 mxwriter *This = impl_from_ISAXContentHandler( iface );
992 FIXME("(%p)->(%p)\n", This, locator);
993 return E_NOTIMPL;
996 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
998 mxwriter *This = impl_from_ISAXContentHandler( iface );
1000 TRACE("(%p)\n", This);
1002 /* If properties have been changed since the last "endDocument" call
1003 * we need to reset the output buffer. If we don't the output buffer
1004 * could end up with multiple XML documents in it, plus this seems to
1005 * be how Windows works.
1007 if (This->prop_changed) {
1008 reset_output_buffer(This);
1009 This->prop_changed = FALSE;
1012 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
1014 write_prolog_buffer(This);
1016 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
1017 static const char utf16BOM[] = {0xff,0xfe};
1019 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
1020 /* Windows passes a NULL pointer as the pcbWritten parameter and
1021 * ignores any error codes returned from this Write call.
1023 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
1026 return S_OK;
1029 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
1031 mxwriter *This = impl_from_ISAXContentHandler( iface );
1032 TRACE("(%p)\n", This);
1033 This->prop_changed = FALSE;
1034 return flush_output_buffer(This);
1037 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
1038 ISAXContentHandler *iface,
1039 const WCHAR *prefix,
1040 int nprefix,
1041 const WCHAR *uri,
1042 int nuri)
1044 mxwriter *This = impl_from_ISAXContentHandler( iface );
1045 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
1046 return E_NOTIMPL;
1049 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
1050 ISAXContentHandler *iface,
1051 const WCHAR *prefix,
1052 int nprefix)
1054 mxwriter *This = impl_from_ISAXContentHandler( iface );
1055 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
1056 return E_NOTIMPL;
1059 static HRESULT WINAPI SAXContentHandler_startElement(
1060 ISAXContentHandler *iface,
1061 const WCHAR *namespaceUri,
1062 int nnamespaceUri,
1063 const WCHAR *local_name,
1064 int nlocal_name,
1065 const WCHAR *QName,
1066 int nQName,
1067 ISAXAttributes *attr)
1069 mxwriter *This = impl_from_ISAXContentHandler( iface );
1070 static const WCHAR ltW[] = {'<'};
1072 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
1073 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
1075 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1076 (nQName == -1 && This->class_version == MSXML6))
1077 return E_INVALIDARG;
1079 close_element_starttag(This);
1080 set_element_name(This, QName ? QName : emptyW,
1081 QName ? nQName : 0);
1083 write_output_buffer(This->buffer, ltW, 1);
1084 write_output_buffer(This->buffer, QName, nQName);
1086 if (attr)
1088 int length, i, escape;
1089 HRESULT hr;
1091 hr = ISAXAttributes_getLength(attr, &length);
1092 if (FAILED(hr)) return hr;
1094 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
1095 (This->class_version == MSXML4 || This->class_version == MSXML6);
1097 for (i = 0; i < length; i++)
1099 static const WCHAR eqW[] = {'='};
1100 const WCHAR *str;
1101 int len = 0;
1103 hr = ISAXAttributes_getQName(attr, i, &str, &len);
1104 if (FAILED(hr)) return hr;
1106 /* space separator in front of every attribute */
1107 write_output_buffer(This->buffer, spaceW, 1);
1108 write_output_buffer(This->buffer, str, len);
1110 write_output_buffer(This->buffer, eqW, 1);
1112 len = 0;
1113 hr = ISAXAttributes_getValue(attr, i, &str, &len);
1114 if (FAILED(hr)) return hr;
1116 if (escape)
1118 WCHAR *escaped = get_escaped_string(str, EscapeValue, &len);
1119 write_output_buffer_quoted(This->buffer, escaped, len);
1120 heap_free(escaped);
1122 else
1123 write_output_buffer_quoted(This->buffer, str, len);
1127 return S_OK;
1130 static HRESULT WINAPI SAXContentHandler_endElement(
1131 ISAXContentHandler *iface,
1132 const WCHAR *namespaceUri,
1133 int nnamespaceUri,
1134 const WCHAR * local_name,
1135 int nlocal_name,
1136 const WCHAR *QName,
1137 int nQName)
1139 mxwriter *This = impl_from_ISAXContentHandler( iface );
1141 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1142 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1144 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) ||
1145 (nQName == -1 && This->class_version == MSXML6))
1146 return E_INVALIDARG;
1148 if (This->element)
1150 static const WCHAR closeW[] = {'/','>'};
1151 write_output_buffer(This->buffer, closeW, 2);
1153 else
1155 static const WCHAR closetagW[] = {'<','/'};
1156 static const WCHAR gtW[] = {'>'};
1158 write_output_buffer(This->buffer, closetagW, 2);
1159 write_output_buffer(This->buffer, QName, nQName);
1160 write_output_buffer(This->buffer, gtW, 1);
1163 set_element_name(This, NULL, 0);
1165 return S_OK;
1168 static HRESULT WINAPI SAXContentHandler_characters(
1169 ISAXContentHandler *iface,
1170 const WCHAR *chars,
1171 int nchars)
1173 mxwriter *This = impl_from_ISAXContentHandler( iface );
1175 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1177 if (!chars) return E_INVALIDARG;
1179 close_element_starttag(This);
1180 set_element_name(This, NULL, 0);
1182 if (nchars)
1184 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
1185 write_output_buffer(This->buffer, chars, nchars);
1186 else
1188 int len = nchars;
1189 WCHAR *escaped;
1191 escaped = get_escaped_string(chars, EscapeText, &len);
1192 write_output_buffer(This->buffer, escaped, len);
1193 heap_free(escaped);
1197 return S_OK;
1200 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1201 ISAXContentHandler *iface,
1202 const WCHAR *chars,
1203 int nchars)
1205 mxwriter *This = impl_from_ISAXContentHandler( iface );
1207 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1209 if (!chars) return E_INVALIDARG;
1211 write_output_buffer(This->buffer, chars, nchars);
1213 return S_OK;
1216 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1217 ISAXContentHandler *iface,
1218 const WCHAR *target,
1219 int ntarget,
1220 const WCHAR *data,
1221 int ndata)
1223 mxwriter *This = impl_from_ISAXContentHandler( iface );
1224 static const WCHAR openpiW[] = {'<','?'};
1225 static const WCHAR closepiW[] = {'?','>','\r','\n'};
1227 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1229 if (!target) return E_INVALIDARG;
1231 write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
1233 if (*target)
1234 write_output_buffer(This->buffer, target, ntarget);
1236 if (data && *data && ndata)
1238 write_output_buffer(This->buffer, spaceW, 1);
1239 write_output_buffer(This->buffer, data, ndata);
1242 write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
1244 return S_OK;
1247 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1248 ISAXContentHandler *iface,
1249 const WCHAR *name,
1250 int nname)
1252 mxwriter *This = impl_from_ISAXContentHandler( iface );
1253 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1254 return E_NOTIMPL;
1257 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1259 SAXContentHandler_QueryInterface,
1260 SAXContentHandler_AddRef,
1261 SAXContentHandler_Release,
1262 SAXContentHandler_putDocumentLocator,
1263 SAXContentHandler_startDocument,
1264 SAXContentHandler_endDocument,
1265 SAXContentHandler_startPrefixMapping,
1266 SAXContentHandler_endPrefixMapping,
1267 SAXContentHandler_startElement,
1268 SAXContentHandler_endElement,
1269 SAXContentHandler_characters,
1270 SAXContentHandler_ignorableWhitespace,
1271 SAXContentHandler_processingInstruction,
1272 SAXContentHandler_skippedEntity
1275 /*** ISAXLexicalHandler ***/
1276 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1277 REFIID riid, void **obj)
1279 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1280 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1283 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1285 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1286 return IMXWriter_AddRef(&This->IMXWriter_iface);
1289 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1291 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1292 return IMXWriter_Release(&This->IMXWriter_iface);
1295 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1296 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1297 const WCHAR *systemId, int systemId_len)
1299 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1300 static const WCHAR openintW[] = {'[','\r','\n'};
1302 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1304 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1305 debugstr_wn(systemId, systemId_len));
1307 if (!name) return E_INVALIDARG;
1309 write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1311 if (*name)
1313 write_output_buffer(This->buffer, name, name_len);
1314 write_output_buffer(This->buffer, spaceW, 1);
1317 if (publicId)
1319 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1321 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1322 write_output_buffer_quoted(This->buffer, publicId, publicId_len);
1324 if (!systemId) return E_INVALIDARG;
1326 if (*publicId)
1327 write_output_buffer(This->buffer, spaceW, 1);
1329 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1331 if (*systemId)
1332 write_output_buffer(This->buffer, spaceW, 1);
1334 else if (systemId)
1336 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1338 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1339 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1340 if (*systemId)
1341 write_output_buffer(This->buffer, spaceW, 1);
1344 write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
1346 return S_OK;
1349 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1351 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1352 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1354 TRACE("(%p)\n", This);
1356 write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1358 return S_OK;
1361 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1363 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1364 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1365 return E_NOTIMPL;
1368 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1370 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1371 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1372 return E_NOTIMPL;
1375 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1377 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1378 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1380 TRACE("(%p)\n", This);
1382 write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1383 This->cdata = TRUE;
1385 return S_OK;
1388 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1390 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1391 static const WCHAR ecdataW[] = {']',']','>'};
1393 TRACE("(%p)\n", This);
1395 write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1396 This->cdata = FALSE;
1398 return S_OK;
1401 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1403 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1404 static const WCHAR copenW[] = {'<','!','-','-'};
1405 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1407 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1409 if (!chars) return E_INVALIDARG;
1411 close_element_starttag(This);
1413 write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
1414 if (nchars)
1415 write_output_buffer(This->buffer, chars, nchars);
1416 write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1418 return S_OK;
1421 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1423 SAXLexicalHandler_QueryInterface,
1424 SAXLexicalHandler_AddRef,
1425 SAXLexicalHandler_Release,
1426 SAXLexicalHandler_startDTD,
1427 SAXLexicalHandler_endDTD,
1428 SAXLexicalHandler_startEntity,
1429 SAXLexicalHandler_endEntity,
1430 SAXLexicalHandler_startCDATA,
1431 SAXLexicalHandler_endCDATA,
1432 SAXLexicalHandler_comment
1435 /*** ISAXDeclHandler ***/
1436 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1437 REFIID riid, void **obj)
1439 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1440 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1443 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1445 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1446 return IMXWriter_AddRef(&This->IMXWriter_iface);
1449 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1451 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1452 return IMXWriter_Release(&This->IMXWriter_iface);
1455 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1456 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1458 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1459 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1461 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1462 debugstr_wn(model, n_model), n_model);
1464 if (!name || !model) return E_INVALIDARG;
1466 write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
1467 if (n_name) {
1468 write_output_buffer(This->buffer, name, n_name);
1469 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1471 if (n_model)
1472 write_output_buffer(This->buffer, model, n_model);
1473 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1475 return S_OK;
1478 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1479 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1480 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1481 const WCHAR *value, int n_value)
1483 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1484 static const WCHAR attlistW[] = {'<','!','A','T','T','L','I','S','T',' '};
1485 static const WCHAR closetagW[] = {'>','\r','\n'};
1487 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element,
1488 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1489 debugstr_wn(value, n_value), n_value);
1491 write_output_buffer(This->buffer, attlistW, sizeof(attlistW)/sizeof(WCHAR));
1492 if (n_element) {
1493 write_output_buffer(This->buffer, element, n_element);
1494 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1497 if (n_attr) {
1498 write_output_buffer(This->buffer, attr, n_attr);
1499 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1502 if (n_type) {
1503 write_output_buffer(This->buffer, type, n_type);
1504 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1507 if (n_default) {
1508 write_output_buffer(This->buffer, Default, n_default);
1509 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1512 if (n_value)
1513 write_output_buffer_quoted(This->buffer, value, n_value);
1515 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1517 return S_OK;
1520 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1521 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1523 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1524 static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
1526 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1527 debugstr_wn(value, n_value), n_value);
1529 if (!name || !value) return E_INVALIDARG;
1531 write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
1532 if (n_name) {
1533 write_output_buffer(This->buffer, name, n_name);
1534 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1537 if (n_value)
1538 write_output_buffer_quoted(This->buffer, value, n_value);
1540 write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
1542 return S_OK;
1545 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1546 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1547 const WCHAR *systemId, int n_systemId)
1549 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1550 FIXME("(%p)->(%s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1551 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1552 return E_NOTIMPL;
1555 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1556 SAXDeclHandler_QueryInterface,
1557 SAXDeclHandler_AddRef,
1558 SAXDeclHandler_Release,
1559 SAXDeclHandler_elementDecl,
1560 SAXDeclHandler_attributeDecl,
1561 SAXDeclHandler_internalEntityDecl,
1562 SAXDeclHandler_externalEntityDecl
1565 static const tid_t mxwriter_iface_tids[] = {
1566 IMXWriter_tid,
1570 static dispex_static_data_t mxwriter_dispex = {
1571 NULL,
1572 IMXWriter_tid,
1573 NULL,
1574 mxwriter_iface_tids
1577 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
1579 static const WCHAR version10W[] = {'1','.','0',0};
1580 mxwriter *This;
1581 HRESULT hr;
1583 TRACE("(%p, %p)\n", outer, ppObj);
1585 if (outer) FIXME("support aggregation, outer\n");
1587 This = heap_alloc( sizeof (*This) );
1588 if(!This)
1589 return E_OUTOFMEMORY;
1591 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
1592 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
1593 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
1594 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
1595 This->ref = 1;
1596 This->class_version = version;
1598 This->props[MXWriter_BOM] = VARIANT_TRUE;
1599 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
1600 This->props[MXWriter_Indent] = VARIANT_FALSE;
1601 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
1602 This->props[MXWriter_Standalone] = VARIANT_FALSE;
1603 This->prop_changed = FALSE;
1604 This->encoding = SysAllocString(utf16W);
1605 This->version = SysAllocString(version10W);
1606 This->xml_enc = XmlEncoding_UTF16;
1608 This->element = NULL;
1609 This->cdata = FALSE;
1611 This->dest = NULL;
1612 This->dest_written = 0;
1614 hr = alloc_output_buffer(This->xml_enc, &This->buffer);
1615 if (hr != S_OK) {
1616 SysFreeString(This->encoding);
1617 SysFreeString(This->version);
1618 heap_free(This);
1619 return hr;
1622 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
1624 *ppObj = &This->IMXWriter_iface;
1626 TRACE("returning iface %p\n", *ppObj);
1628 return S_OK;
1631 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
1633 mxattributes *This = impl_from_IMXAttributes( iface );
1635 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
1637 *ppObj = NULL;
1639 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1640 IsEqualGUID( riid, &IID_IDispatch ) ||
1641 IsEqualGUID( riid, &IID_IMXAttributes ))
1643 *ppObj = iface;
1645 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
1647 *ppObj = &This->ISAXAttributes_iface;
1649 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
1651 *ppObj = &This->IVBSAXAttributes_iface;
1653 else if (dispex_query_interface(&This->dispex, riid, ppObj))
1655 return *ppObj ? S_OK : E_NOINTERFACE;
1657 else
1659 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1660 return E_NOINTERFACE;
1663 IMXAttributes_AddRef( iface );
1665 return S_OK;
1668 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface)
1670 mxattributes *This = impl_from_IMXAttributes( iface );
1671 ULONG ref = InterlockedIncrement( &This->ref );
1672 TRACE("(%p)->(%d)\n", This, ref );
1673 return ref;
1676 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface)
1678 mxattributes *This = impl_from_IMXAttributes( iface );
1679 LONG ref = InterlockedDecrement( &This->ref );
1681 TRACE("(%p)->(%d)\n", This, ref);
1683 if (ref == 0)
1685 int i;
1687 for (i = 0; i < This->length; i++)
1689 SysFreeString(This->attr[i].qname);
1690 SysFreeString(This->attr[i].local);
1691 SysFreeString(This->attr[i].uri);
1692 SysFreeString(This->attr[i].type);
1693 SysFreeString(This->attr[i].value);
1696 release_dispex(&This->dispex);
1697 heap_free(This->attr);
1698 heap_free(This);
1701 return ref;
1704 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo)
1706 mxattributes *This = impl_from_IMXAttributes( iface );
1707 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1710 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1712 mxattributes *This = impl_from_IMXAttributes( iface );
1713 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1716 static HRESULT WINAPI MXAttributes_GetIDsOfNames(
1717 IMXAttributes *iface,
1718 REFIID riid,
1719 LPOLESTR* rgszNames,
1720 UINT cNames,
1721 LCID lcid,
1722 DISPID* rgDispId)
1724 mxattributes *This = impl_from_IMXAttributes( iface );
1725 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
1726 riid, rgszNames, cNames, lcid, rgDispId);
1729 static HRESULT WINAPI MXAttributes_Invoke(
1730 IMXAttributes *iface,
1731 DISPID dispIdMember,
1732 REFIID riid,
1733 LCID lcid,
1734 WORD wFlags,
1735 DISPPARAMS* pDispParams,
1736 VARIANT* pVarResult,
1737 EXCEPINFO* pExcepInfo,
1738 UINT* puArgErr)
1740 mxattributes *This = impl_from_IMXAttributes( iface );
1741 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
1742 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1745 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface,
1746 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1748 mxattributes *This = impl_from_IMXAttributes( iface );
1749 mxattribute *attr;
1750 HRESULT hr;
1752 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName),
1753 debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1755 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6)
1756 return E_INVALIDARG;
1758 /* ensure array is large enough */
1759 hr = mxattributes_grow(This);
1760 if (hr != S_OK) return hr;
1762 attr = &This->attr[This->length];
1764 attr->qname = SysAllocString(QName);
1765 attr->local = SysAllocString(localName);
1766 attr->uri = SysAllocString(uri);
1767 attr->type = SysAllocString(type ? type : emptyW);
1768 attr->value = SysAllocString(value);
1769 This->length++;
1771 return S_OK;
1774 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface,
1775 VARIANT atts, int index)
1777 mxattributes *This = impl_from_IMXAttributes( iface );
1778 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index);
1779 return E_NOTIMPL;
1782 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface)
1784 mxattributes *This = impl_from_IMXAttributes( iface );
1785 int i;
1787 TRACE("(%p)\n", This);
1789 for (i = 0; i < This->length; i++)
1791 SysFreeString(This->attr[i].qname);
1792 SysFreeString(This->attr[i].local);
1793 SysFreeString(This->attr[i].uri);
1794 SysFreeString(This->attr[i].type);
1795 SysFreeString(This->attr[i].value);
1796 memset(&This->attr[i], 0, sizeof(mxattribute));
1799 This->length = 0;
1801 return S_OK;
1804 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
1806 mxattributes *This = impl_from_IMXAttributes( iface );
1807 FIXME("(%p)->(%d): stub\n", This, index);
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
1812 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1814 mxattributes *This = impl_from_IMXAttributes( iface );
1815 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri),
1816 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1817 return E_NOTIMPL;
1820 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts)
1822 mxattributes *This = impl_from_IMXAttributes( iface );
1823 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts));
1824 return E_NOTIMPL;
1827 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index,
1828 BSTR localName)
1830 mxattributes *This = impl_from_IMXAttributes( iface );
1831 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(localName));
1832 return E_NOTIMPL;
1835 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
1837 mxattributes *This = impl_from_IMXAttributes( iface );
1838 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(QName));
1839 return E_NOTIMPL;
1842 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
1844 mxattributes *This = impl_from_IMXAttributes( iface );
1845 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(uri));
1846 return E_NOTIMPL;
1849 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
1851 mxattributes *This = impl_from_IMXAttributes( iface );
1852 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(value));
1853 return E_NOTIMPL;
1856 static const IMXAttributesVtbl MXAttributesVtbl = {
1857 MXAttributes_QueryInterface,
1858 MXAttributes_AddRef,
1859 MXAttributes_Release,
1860 MXAttributes_GetTypeInfoCount,
1861 MXAttributes_GetTypeInfo,
1862 MXAttributes_GetIDsOfNames,
1863 MXAttributes_Invoke,
1864 MXAttributes_addAttribute,
1865 MXAttributes_addAttributeFromIndex,
1866 MXAttributes_clear,
1867 MXAttributes_removeAttribute,
1868 MXAttributes_setAttribute,
1869 MXAttributes_setAttributes,
1870 MXAttributes_setLocalName,
1871 MXAttributes_setQName,
1872 MXAttributes_setURI,
1873 MXAttributes_setValue
1876 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj)
1878 mxattributes *This = impl_from_ISAXAttributes( iface );
1879 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj);
1882 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface)
1884 mxattributes *This = impl_from_ISAXAttributes( iface );
1885 return IMXAttributes_AddRef(&This->IMXAttributes_iface);
1888 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface)
1890 mxattributes *This = impl_from_ISAXAttributes( iface );
1891 return IMXAttributes_Release(&This->IMXAttributes_iface);
1894 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length)
1896 mxattributes *This = impl_from_ISAXAttributes( iface );
1897 TRACE("(%p)->(%p)\n", This, length);
1899 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1900 return E_POINTER;
1902 *length = This->length;
1904 return S_OK;
1907 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri,
1908 int *len)
1910 mxattributes *This = impl_from_ISAXAttributes( iface );
1912 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len);
1914 if (index >= This->length || index < 0) return E_INVALIDARG;
1915 if (!uri || !len) return E_POINTER;
1917 *len = SysStringLen(This->attr[index].uri);
1918 *uri = This->attr[index].uri;
1920 return S_OK;
1923 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name,
1924 int *len)
1926 mxattributes *This = impl_from_ISAXAttributes( iface );
1928 TRACE("(%p)->(%d %p %p)\n", This, index, name, len);
1930 if (index >= This->length || index < 0) return E_INVALIDARG;
1931 if (!name || !len) return E_POINTER;
1933 *len = SysStringLen(This->attr[index].local);
1934 *name = This->attr[index].local;
1936 return S_OK;
1939 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length)
1941 mxattributes *This = impl_from_ISAXAttributes( iface );
1943 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length);
1945 if (index >= This->length) return E_INVALIDARG;
1946 if (!qname || !length) return E_POINTER;
1948 *qname = This->attr[index].qname;
1949 *length = SysStringLen(This->attr[index].qname);
1951 return S_OK;
1954 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len,
1955 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len)
1957 mxattributes *This = impl_from_ISAXAttributes( iface );
1959 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len);
1961 if (index >= This->length || index < 0)
1962 return E_INVALIDARG;
1964 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len)
1965 return E_POINTER;
1967 *uri_len = SysStringLen(This->attr[index].uri);
1968 *uri = This->attr[index].uri;
1970 *local_len = SysStringLen(This->attr[index].local);
1971 *local = This->attr[index].local;
1973 *qname_len = SysStringLen(This->attr[index].qname);
1974 *qname = This->attr[index].qname;
1976 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname));
1978 return S_OK;
1981 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len,
1982 const WCHAR *name, int len, int *index)
1984 mxattributes *This = impl_from_ISAXAttributes( iface );
1985 int i;
1987 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
1988 debugstr_wn(name, len), len, index);
1990 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1991 return E_POINTER;
1993 if (!uri || !name || !index) return E_INVALIDARG;
1995 for (i = 0; i < This->length; i++)
1997 if (uri_len != SysStringLen(This->attr[i].uri)) continue;
1998 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue;
2000 if (len != SysStringLen(This->attr[i].local)) continue;
2001 if (strncmpW(name, This->attr[i].local, len)) continue;
2003 *index = i;
2004 return S_OK;
2007 return E_INVALIDARG;
2010 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname,
2011 int len, int *index)
2013 mxattributes *This = impl_from_ISAXAttributes( iface );
2014 int i;
2016 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index);
2018 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2019 return E_POINTER;
2021 if (!qname || !index || !len) return E_INVALIDARG;
2023 for (i = 0; i < This->length; i++)
2025 if (len != SysStringLen(This->attr[i].qname)) continue;
2026 if (strncmpW(qname, This->attr[i].qname, len)) continue;
2028 *index = i;
2029 return S_OK;
2032 return E_INVALIDARG;
2035 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type,
2036 int *len)
2038 mxattributes *This = impl_from_ISAXAttributes( iface );
2040 TRACE("(%p)->(%d %p %p)\n", This, index, type, len);
2042 if (index >= This->length) return E_INVALIDARG;
2044 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2045 return E_POINTER;
2047 *type = This->attr[index].type;
2048 *len = SysStringLen(This->attr[index].type);
2050 return S_OK;
2053 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri,
2054 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType)
2056 mxattributes *This = impl_from_ISAXAttributes( iface );
2057 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri,
2058 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType);
2059 return E_NOTIMPL;
2062 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName,
2063 int nQName, const WCHAR ** pType, int * nType)
2065 mxattributes *This = impl_from_ISAXAttributes( iface );
2066 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType);
2067 return E_NOTIMPL;
2070 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value,
2071 int *len)
2073 mxattributes *This = impl_from_ISAXAttributes( iface );
2075 TRACE("(%p)->(%d %p %p)\n", This, index, value, len);
2077 if (index >= This->length) return E_INVALIDARG;
2079 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2080 return E_POINTER;
2082 *value = This->attr[index].value;
2083 *len = SysStringLen(This->attr[index].value);
2085 return S_OK;
2088 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri,
2089 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len)
2091 mxattributes *This = impl_from_ISAXAttributes( iface );
2092 HRESULT hr;
2093 int index;
2095 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
2096 debugstr_wn(name, name_len), name_len, value, value_len);
2098 if (!uri || !name || !value || !value_len)
2099 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2101 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index);
2102 if (hr == S_OK)
2103 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2105 return hr;
2108 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname,
2109 int qname_len, const WCHAR **value, int *value_len)
2111 mxattributes *This = impl_from_ISAXAttributes( iface );
2112 HRESULT hr;
2113 int index;
2115 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len);
2117 if (!qname || !value || !value_len)
2118 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2120 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index);
2121 if (hr == S_OK)
2122 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2124 return hr;
2127 static const ISAXAttributesVtbl SAXAttributesVtbl = {
2128 SAXAttributes_QueryInterface,
2129 SAXAttributes_AddRef,
2130 SAXAttributes_Release,
2131 SAXAttributes_getLength,
2132 SAXAttributes_getURI,
2133 SAXAttributes_getLocalName,
2134 SAXAttributes_getQName,
2135 SAXAttributes_getName,
2136 SAXAttributes_getIndexFromName,
2137 SAXAttributes_getIndexFromQName,
2138 SAXAttributes_getType,
2139 SAXAttributes_getTypeFromName,
2140 SAXAttributes_getTypeFromQName,
2141 SAXAttributes_getValue,
2142 SAXAttributes_getValueFromName,
2143 SAXAttributes_getValueFromQName
2146 static HRESULT WINAPI VBSAXAttributes_QueryInterface(
2147 IVBSAXAttributes* iface,
2148 REFIID riid,
2149 void **ppvObject)
2151 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2152 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
2153 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject);
2156 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface)
2158 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2159 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface);
2162 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface)
2164 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2165 return ISAXAttributes_Release(&This->ISAXAttributes_iface);
2168 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
2170 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2172 TRACE("(%p)->(%p)\n", This, pctinfo);
2174 *pctinfo = 1;
2176 return S_OK;
2179 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo(
2180 IVBSAXAttributes *iface,
2181 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2183 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2184 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2185 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
2188 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames(
2189 IVBSAXAttributes *iface,
2190 REFIID riid,
2191 LPOLESTR* rgszNames,
2192 UINT cNames,
2193 LCID lcid,
2194 DISPID* rgDispId)
2196 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2197 ITypeInfo *typeinfo;
2198 HRESULT hr;
2200 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2201 lcid, rgDispId);
2203 if(!rgszNames || cNames == 0 || !rgDispId)
2204 return E_INVALIDARG;
2206 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2207 if(SUCCEEDED(hr))
2209 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2210 ITypeInfo_Release(typeinfo);
2213 return hr;
2216 static HRESULT WINAPI VBSAXAttributes_Invoke(
2217 IVBSAXAttributes *iface,
2218 DISPID dispIdMember,
2219 REFIID riid,
2220 LCID lcid,
2221 WORD wFlags,
2222 DISPPARAMS* pDispParams,
2223 VARIANT* pVarResult,
2224 EXCEPINFO* pExcepInfo,
2225 UINT* puArgErr)
2227 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2228 ITypeInfo *typeinfo;
2229 HRESULT hr;
2231 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2232 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2234 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2235 if(SUCCEEDED(hr))
2237 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
2238 pDispParams, pVarResult, pExcepInfo, puArgErr);
2239 ITypeInfo_Release(typeinfo);
2242 return hr;
2245 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len)
2247 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2248 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len);
2251 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
2253 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2254 int len;
2256 return ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, (const WCHAR**)uri, &len);
2259 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
2261 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2262 int len;
2264 return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, (const WCHAR**)name, &len);
2267 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
2269 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2270 int len;
2272 return ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, (const WCHAR**)qname, &len);
2275 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
2277 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2278 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2279 name, SysStringLen(name), index);
2282 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index)
2284 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2285 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname,
2286 SysStringLen(qname), index);
2289 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index,BSTR *type)
2291 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2292 int len;
2294 return ISAXAttributes_getType(&This->ISAXAttributes_iface, index, (const WCHAR**)type, &len);
2297 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
2298 BSTR name, BSTR *type)
2300 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2301 int len;
2303 return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2304 name, SysStringLen(name), (const WCHAR**)type, &len);
2307 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
2309 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2310 int len;
2312 return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2313 (const WCHAR**)type, &len);
2316 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
2318 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2319 int len;
2321 return ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, (const WCHAR**)value, &len);
2324 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
2325 BSTR *value)
2327 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2328 int len;
2330 return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2331 name, SysStringLen(name), (const WCHAR**)value, &len);
2334 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
2336 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2337 int len;
2339 return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2340 (const WCHAR**)value, &len);
2343 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
2345 VBSAXAttributes_QueryInterface,
2346 VBSAXAttributes_AddRef,
2347 VBSAXAttributes_Release,
2348 VBSAXAttributes_GetTypeInfoCount,
2349 VBSAXAttributes_GetTypeInfo,
2350 VBSAXAttributes_GetIDsOfNames,
2351 VBSAXAttributes_Invoke,
2352 VBSAXAttributes_get_length,
2353 VBSAXAttributes_getURI,
2354 VBSAXAttributes_getLocalName,
2355 VBSAXAttributes_getQName,
2356 VBSAXAttributes_getIndexFromName,
2357 VBSAXAttributes_getIndexFromQName,
2358 VBSAXAttributes_getType,
2359 VBSAXAttributes_getTypeFromName,
2360 VBSAXAttributes_getTypeFromQName,
2361 VBSAXAttributes_getValue,
2362 VBSAXAttributes_getValueFromName,
2363 VBSAXAttributes_getValueFromQName
2366 static const tid_t mxattrs_iface_tids[] = {
2367 IMXAttributes_tid,
2371 static dispex_static_data_t mxattrs_dispex = {
2372 NULL,
2373 IMXAttributes_tid,
2374 NULL,
2375 mxattrs_iface_tids
2378 HRESULT SAXAttributes_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
2380 static const int default_count = 10;
2381 mxattributes *This;
2383 TRACE("(%p, %p)\n", outer, ppObj);
2385 This = heap_alloc( sizeof (*This) );
2386 if( !This )
2387 return E_OUTOFMEMORY;
2389 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl;
2390 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl;
2391 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl;
2392 This->ref = 1;
2394 This->class_version = version;
2396 This->attr = heap_alloc(default_count*sizeof(mxattribute));
2397 This->length = 0;
2398 This->allocated = default_count;
2400 *ppObj = &This->IMXAttributes_iface;
2402 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex);
2404 TRACE("returning iface %p\n", *ppObj);
2406 return S_OK;