po: Update Japanese translation.
[wine/multimedia.git] / dlls / msxml3 / mxwriter.c
blob81d498e80a922556739ffab133fc2d700c0bc794
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[] = {'\"'};
46 /* should be ordered as encoding names are sorted */
47 typedef enum
49 XmlEncoding_ISO_8859_1 = 0,
50 XmlEncoding_ISO_8859_13,
51 XmlEncoding_ISO_8859_15,
52 XmlEncoding_ISO_8859_2,
53 XmlEncoding_ISO_8859_3,
54 XmlEncoding_ISO_8859_4,
55 XmlEncoding_ISO_8859_5,
56 XmlEncoding_ISO_8859_7,
57 XmlEncoding_ISO_8859_9,
58 XmlEncoding_UTF16,
59 XmlEncoding_UTF8,
60 XmlEncoding_Unknown
61 } xml_encoding;
63 struct xml_encoding_data
65 const WCHAR *encoding;
66 xml_encoding enc;
67 UINT cp;
70 static const WCHAR iso_8859_1W[] = {'i','s','o','-','8','8','5','9','-','1',0};
71 static const WCHAR iso_8859_2W[] = {'i','s','o','-','8','8','5','9','-','2',0};
72 static const WCHAR iso_8859_3W[] = {'i','s','o','-','8','8','5','9','-','3',0};
73 static const WCHAR iso_8859_4W[] = {'i','s','o','-','8','8','5','9','-','4',0};
74 static const WCHAR iso_8859_5W[] = {'i','s','o','-','8','8','5','9','-','5',0};
75 static const WCHAR iso_8859_7W[] = {'i','s','o','-','8','8','5','9','-','7',0};
76 static const WCHAR iso_8859_9W[] = {'i','s','o','-','8','8','5','9','-','9',0};
77 static const WCHAR iso_8859_13W[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
78 static const WCHAR iso_8859_15W[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
79 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0};
80 static const WCHAR utf8W[] = {'U','T','F','-','8',0};
82 static const struct xml_encoding_data xml_encoding_map[] = {
83 { iso_8859_1W, XmlEncoding_ISO_8859_1, 28591 },
84 { iso_8859_13W, XmlEncoding_ISO_8859_13, 28603 },
85 { iso_8859_15W, XmlEncoding_ISO_8859_15, 28605 },
86 { iso_8859_2W, XmlEncoding_ISO_8859_2, 28592 },
87 { iso_8859_3W, XmlEncoding_ISO_8859_3, 28593 },
88 { iso_8859_4W, XmlEncoding_ISO_8859_4, 28594 },
89 { iso_8859_5W, XmlEncoding_ISO_8859_5, 28595 },
90 { iso_8859_7W, XmlEncoding_ISO_8859_7, 28597 },
91 { iso_8859_9W, XmlEncoding_ISO_8859_9, 28599 },
92 { utf16W, XmlEncoding_UTF16, ~0 },
93 { utf8W, XmlEncoding_UTF8, CP_UTF8 }
96 typedef enum
98 OutputBuffer_Native = 0x001,
99 OutputBuffer_Encoded = 0x010,
100 OutputBuffer_Both = 0x100
101 } output_mode;
103 typedef enum
105 MXWriter_BOM = 0,
106 MXWriter_DisableEscaping,
107 MXWriter_Indent,
108 MXWriter_OmitXmlDecl,
109 MXWriter_Standalone,
110 MXWriter_LastProp
111 } mxwriter_prop;
113 typedef enum
115 EscapeValue,
116 EscapeText
117 } escape_mode;
119 typedef struct
121 char *data;
122 unsigned int allocated;
123 unsigned int written;
124 } encoded_buffer;
126 typedef struct
128 encoded_buffer utf16;
129 encoded_buffer encoded;
130 UINT code_page;
131 } output_buffer;
133 typedef struct
135 DispatchEx dispex;
136 IMXWriter IMXWriter_iface;
137 ISAXContentHandler ISAXContentHandler_iface;
138 ISAXLexicalHandler ISAXLexicalHandler_iface;
139 ISAXDeclHandler ISAXDeclHandler_iface;
141 LONG ref;
142 MSXML_VERSION class_version;
144 VARIANT_BOOL props[MXWriter_LastProp];
145 BOOL prop_changed;
146 BOOL cdata;
148 BSTR version;
150 BSTR encoding; /* exact property value */
151 xml_encoding xml_enc;
153 /* contains a pending (or not closed yet) element name or NULL if
154 we don't have to close */
155 BSTR element;
157 IStream *dest;
158 ULONG dest_written;
160 output_buffer *buffer;
161 } mxwriter;
163 typedef struct
165 BSTR qname;
166 BSTR local;
167 BSTR uri;
168 BSTR type;
169 BSTR value;
170 } mxattribute;
172 typedef struct
174 DispatchEx dispex;
175 IMXAttributes IMXAttributes_iface;
176 ISAXAttributes ISAXAttributes_iface;
177 IVBSAXAttributes IVBSAXAttributes_iface;
178 LONG ref;
180 MSXML_VERSION class_version;
182 mxattribute *attr;
183 int length;
184 int allocated;
185 } mxattributes;
187 static inline mxattributes *impl_from_IMXAttributes( IMXAttributes *iface )
189 return CONTAINING_RECORD(iface, mxattributes, IMXAttributes_iface);
192 static inline mxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface )
194 return CONTAINING_RECORD(iface, mxattributes, ISAXAttributes_iface);
197 static inline mxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface )
199 return CONTAINING_RECORD(iface, mxattributes, IVBSAXAttributes_iface);
202 static HRESULT mxattributes_grow(mxattributes *This)
204 if (This->length < This->allocated) return S_OK;
206 This->allocated *= 2;
207 This->attr = heap_realloc(This->attr, This->allocated*sizeof(mxattribute));
209 return This->attr ? S_OK : E_OUTOFMEMORY;
212 static xml_encoding parse_encoding_name(const WCHAR *encoding)
214 int min, max, n, c;
216 min = 0;
217 max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
219 while (min <= max)
221 n = (min+max)/2;
223 c = strcmpiW(xml_encoding_map[n].encoding, encoding);
224 if (!c)
225 return xml_encoding_map[n].enc;
227 if (c > 0)
228 max = n-1;
229 else
230 min = n+1;
233 return XmlEncoding_Unknown;
236 static HRESULT init_encoded_buffer(encoded_buffer *buffer)
238 const int initial_len = 0x2000;
239 buffer->data = heap_alloc(initial_len);
240 if (!buffer->data) return E_OUTOFMEMORY;
242 memset(buffer->data, 0, 4);
243 buffer->allocated = initial_len;
244 buffer->written = 0;
246 return S_OK;
249 static void free_encoded_buffer(encoded_buffer *buffer)
251 heap_free(buffer->data);
254 static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
256 const struct xml_encoding_data *data;
258 if (encoding == XmlEncoding_Unknown)
260 FIXME("unsupported encoding %d\n", encoding);
261 return E_NOTIMPL;
264 data = &xml_encoding_map[encoding];
265 *cp = data->cp;
267 return S_OK;
270 static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer)
272 output_buffer *ret;
273 HRESULT hr;
275 ret = heap_alloc(sizeof(*ret));
276 if (!ret) return E_OUTOFMEMORY;
278 hr = get_code_page(encoding, &ret->code_page);
279 if (hr != S_OK) {
280 heap_free(ret);
281 return hr;
284 hr = init_encoded_buffer(&ret->utf16);
285 if (hr != S_OK) {
286 heap_free(ret);
287 return hr;
290 if (ret->code_page == CP_UTF8) {
291 hr = init_encoded_buffer(&ret->encoded);
292 if (hr != S_OK) {
293 free_encoded_buffer(&ret->utf16);
294 heap_free(ret);
295 return hr;
298 else
299 memset(&ret->encoded, 0, sizeof(ret->encoded));
301 *buffer = ret;
303 return S_OK;
306 static void free_output_buffer(output_buffer *buffer)
308 free_encoded_buffer(&buffer->encoded);
309 free_encoded_buffer(&buffer->utf16);
310 heap_free(buffer);
313 static void grow_buffer(encoded_buffer *buffer, int length)
315 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
316 if (buffer->allocated < buffer->written + length + 4)
318 int grown_size = max(2*buffer->allocated, buffer->allocated + length);
319 buffer->data = heap_realloc(buffer->data, grown_size);
320 buffer->allocated = grown_size;
324 static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
326 int length;
327 char *ptr;
329 if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
330 if (buffer->code_page != ~0)
332 length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
333 grow_buffer(&buffer->encoded, length);
334 ptr = buffer->encoded.data + buffer->encoded.written;
335 length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
336 buffer->encoded.written += len == -1 ? length-1 : length;
340 if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
341 /* WCHAR data just copied */
342 length = len == -1 ? strlenW(data) : len;
343 if (length)
345 length *= sizeof(WCHAR);
347 grow_buffer(&buffer->utf16, length);
348 ptr = buffer->utf16.data + buffer->utf16.written;
350 memcpy(ptr, data, length);
351 buffer->utf16.written += length;
352 ptr += length;
353 /* null termination */
354 memset(ptr, 0, sizeof(WCHAR));
358 return S_OK;
361 static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
363 return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
366 static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
368 write_output_buffer(buffer, quotW, 1);
369 write_output_buffer(buffer, data, len);
370 write_output_buffer(buffer, quotW, 1);
372 return S_OK;
375 /* frees buffer data, reallocates with a default lengths */
376 static void close_output_buffer(mxwriter *This)
378 heap_free(This->buffer->utf16.data);
379 heap_free(This->buffer->encoded.data);
380 init_encoded_buffer(&This->buffer->utf16);
381 init_encoded_buffer(&This->buffer->encoded);
382 get_code_page(This->xml_enc, &This->buffer->code_page);
385 /* escapes special characters like:
386 '<' -> "&lt;"
387 '&' -> "&amp;"
388 '"' -> "&quot;"
389 '>' -> "&gt;"
391 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
393 static const WCHAR ltW[] = {'&','l','t',';'};
394 static const WCHAR ampW[] = {'&','a','m','p',';'};
395 static const WCHAR equotW[] = {'&','q','u','o','t',';'};
396 static const WCHAR gtW[] = {'&','g','t',';'};
398 const int default_alloc = 100;
399 const int grow_thresh = 10;
400 int p = *len, conv_len;
401 WCHAR *ptr, *ret;
403 /* default buffer size to something if length is unknown */
404 conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
405 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
407 while (*str && p)
409 if (ptr - ret > conv_len - grow_thresh)
411 int written = ptr - ret;
412 conv_len *= 2;
413 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR));
414 ptr += written;
417 switch (*str)
419 case '<':
420 memcpy(ptr, ltW, sizeof(ltW));
421 ptr += sizeof(ltW)/sizeof(WCHAR);
422 break;
423 case '&':
424 memcpy(ptr, ampW, sizeof(ampW));
425 ptr += sizeof(ampW)/sizeof(WCHAR);
426 break;
427 case '>':
428 memcpy(ptr, gtW, sizeof(gtW));
429 ptr += sizeof(gtW)/sizeof(WCHAR);
430 break;
431 case '"':
432 if (mode == EscapeValue)
434 memcpy(ptr, equotW, sizeof(equotW));
435 ptr += sizeof(equotW)/sizeof(WCHAR);
436 break;
438 /* fallthrough for text mode */
439 default:
440 *ptr++ = *str;
441 break;
444 str++;
445 if (*len != -1) p--;
448 if (*len != -1) *len = ptr-ret;
449 *++ptr = 0;
451 return ret;
454 static void write_prolog_buffer(const mxwriter *This)
456 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
457 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
458 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
459 static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
460 static const WCHAR noW[] = {'n','o','\"','?','>'};
461 static const WCHAR crlfW[] = {'\r','\n'};
463 /* version */
464 write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
465 write_output_buffer_quoted(This->buffer, This->version, -1);
467 /* encoding */
468 write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
470 /* always write UTF-16 to WCHAR buffer */
471 write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
472 write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
473 write_output_buffer(This->buffer, quotW, 1);
475 /* standalone */
476 write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
477 if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
478 write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
479 else
480 write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
482 write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
485 /* Attempts to the write data from the mxwriter's buffer to
486 * the destination stream (if there is one).
488 static HRESULT write_data_to_stream(mxwriter *This)
490 encoded_buffer *buffer;
491 ULONG written = 0;
492 HRESULT hr;
494 if (!This->dest)
495 return S_OK;
497 if (This->xml_enc != XmlEncoding_UTF16)
498 buffer = &This->buffer->encoded;
499 else
500 buffer = &This->buffer->utf16;
502 if (This->dest_written > buffer->written) {
503 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->written);
504 return E_FAIL;
505 } else if (This->dest_written == buffer->written && This->xml_enc != XmlEncoding_UTF8)
506 /* Windows seems to make an empty write call when the encoding is UTF-8 and
507 * all the data has been written to the stream. It doesn't seem make this call
508 * for any other encodings.
510 return S_OK;
512 /* Write the current content from the output buffer into 'dest'.
513 * TODO: Check what Windows does if the IStream doesn't write all of
514 * the data we give it at once.
516 hr = IStream_Write(This->dest, buffer->data+This->dest_written,
517 buffer->written-This->dest_written, &written);
518 if (FAILED(hr)) {
519 WARN("Failed to write data to IStream (0x%08x)\n", hr);
520 return hr;
523 This->dest_written += written;
524 return hr;
527 /* Newly added element start tag left unclosed cause for empty elements
528 we have to close it differently. */
529 static void close_element_starttag(const mxwriter *This)
531 static const WCHAR gtW[] = {'>'};
532 if (!This->element) return;
533 write_output_buffer(This->buffer, gtW, 1);
536 static void set_element_name(mxwriter *This, const WCHAR *name, int len)
538 SysFreeString(This->element);
539 This->element = name ? SysAllocStringLen(name, len) : NULL;
542 static inline HRESULT flush_output_buffer(mxwriter *This)
544 close_element_starttag(This);
545 set_element_name(This, NULL, 0);
546 This->cdata = FALSE;
547 return write_data_to_stream(This);
550 /* Resets the mxwriter's output buffer by closing it, then creating a new
551 * output buffer using the given encoding.
553 static inline void reset_output_buffer(mxwriter *This)
555 close_output_buffer(This);
556 This->dest_written = 0;
559 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
561 writer->props[property] = value;
562 writer->prop_changed = TRUE;
563 return S_OK;
566 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value)
568 if (!value) return E_POINTER;
569 *value = writer->props[property];
570 return S_OK;
573 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface)
575 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface);
578 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface)
580 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
583 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
585 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
588 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
590 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
593 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
595 mxwriter *This = impl_from_IMXWriter( iface );
597 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
599 *obj = NULL;
601 if ( IsEqualGUID( riid, &IID_IMXWriter ) ||
602 IsEqualGUID( riid, &IID_IDispatch ) ||
603 IsEqualGUID( riid, &IID_IUnknown ) )
605 *obj = &This->IMXWriter_iface;
607 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) )
609 *obj = &This->ISAXContentHandler_iface;
611 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) )
613 *obj = &This->ISAXLexicalHandler_iface;
615 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) )
617 *obj = &This->ISAXDeclHandler_iface;
619 else if (dispex_query_interface(&This->dispex, riid, obj))
621 return *obj ? S_OK : E_NOINTERFACE;
623 else
625 ERR("interface %s not implemented\n", debugstr_guid(riid));
626 *obj = NULL;
627 return E_NOINTERFACE;
630 IMXWriter_AddRef(iface);
631 return S_OK;
634 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface)
636 mxwriter *This = impl_from_IMXWriter( iface );
637 LONG ref = InterlockedIncrement(&This->ref);
639 TRACE("(%p)->(%d)\n", This, ref);
641 return ref;
644 static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
646 mxwriter *This = impl_from_IMXWriter( iface );
647 ULONG ref = InterlockedDecrement(&This->ref);
649 TRACE("(%p)->(%d)\n", This, ref);
651 if(!ref)
653 /* Windows flushes the buffer when the interface is destroyed. */
654 flush_output_buffer(This);
655 free_output_buffer(This->buffer);
657 if (This->dest) IStream_Release(This->dest);
658 SysFreeString(This->version);
659 SysFreeString(This->encoding);
661 SysFreeString(This->element);
662 release_dispex(&This->dispex);
663 heap_free(This);
666 return ref;
669 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo)
671 mxwriter *This = impl_from_IMXWriter( iface );
672 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
675 static HRESULT WINAPI mxwriter_GetTypeInfo(
676 IMXWriter *iface,
677 UINT iTInfo, LCID lcid,
678 ITypeInfo** ppTInfo )
680 mxwriter *This = impl_from_IMXWriter( iface );
681 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
682 iTInfo, lcid, ppTInfo);
685 static HRESULT WINAPI mxwriter_GetIDsOfNames(
686 IMXWriter *iface,
687 REFIID riid, LPOLESTR* rgszNames,
688 UINT cNames, LCID lcid, DISPID* rgDispId )
690 mxwriter *This = impl_from_IMXWriter( iface );
691 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
692 riid, rgszNames, cNames, lcid, rgDispId);
695 static HRESULT WINAPI mxwriter_Invoke(
696 IMXWriter *iface,
697 DISPID dispIdMember, REFIID riid, LCID lcid,
698 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
699 EXCEPINFO* pExcepInfo, UINT* puArgErr )
701 mxwriter *This = impl_from_IMXWriter( iface );
702 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
703 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
706 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest)
708 mxwriter *This = impl_from_IMXWriter( iface );
709 HRESULT hr;
711 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest));
713 hr = flush_output_buffer(This);
714 if (FAILED(hr))
715 return hr;
717 switch (V_VT(&dest))
719 case VT_EMPTY:
721 if (This->dest) IStream_Release(This->dest);
722 This->dest = NULL;
723 reset_output_buffer(This);
724 break;
726 case VT_UNKNOWN:
728 IStream *stream;
730 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream);
731 if (hr == S_OK)
733 /* Recreate the output buffer to make sure it's using the correct encoding. */
734 reset_output_buffer(This);
736 if (This->dest) IStream_Release(This->dest);
737 This->dest = stream;
738 break;
741 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
742 return E_NOTIMPL;
744 default:
745 FIXME("unhandled destination type %s\n", debugstr_variant(&dest));
746 return E_NOTIMPL;
749 return S_OK;
752 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
754 mxwriter *This = impl_from_IMXWriter( iface );
756 TRACE("(%p)->(%p)\n", This, dest);
758 if (!This->dest)
760 HRESULT hr = flush_output_buffer(This);
761 if (FAILED(hr))
762 return hr;
764 V_VT(dest) = VT_BSTR;
765 V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
767 return S_OK;
769 else
770 FIXME("not implemented when stream is set up\n");
772 return E_NOTIMPL;
775 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding)
777 mxwriter *This = impl_from_IMXWriter( iface );
778 xml_encoding enc;
779 HRESULT hr;
781 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding));
783 enc = parse_encoding_name(encoding);
784 if (enc == XmlEncoding_Unknown)
786 FIXME("unsupported encoding %s\n", debugstr_w(encoding));
787 return E_INVALIDARG;
790 hr = flush_output_buffer(This);
791 if (FAILED(hr))
792 return hr;
794 SysReAllocString(&This->encoding, encoding);
795 This->xml_enc = enc;
797 TRACE("got encoding %d\n", This->xml_enc);
798 reset_output_buffer(This);
799 return S_OK;
802 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding)
804 mxwriter *This = impl_from_IMXWriter( iface );
806 TRACE("(%p)->(%p)\n", This, encoding);
808 if (!encoding) return E_POINTER;
810 *encoding = SysAllocString(This->encoding);
811 if (!*encoding) return E_OUTOFMEMORY;
813 return S_OK;
816 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value)
818 mxwriter *This = impl_from_IMXWriter( iface );
820 TRACE("(%p)->(%d)\n", This, value);
821 return writer_set_property(This, MXWriter_BOM, value);
824 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value)
826 mxwriter *This = impl_from_IMXWriter( iface );
828 TRACE("(%p)->(%p)\n", This, value);
829 return writer_get_property(This, MXWriter_BOM, value);
832 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value)
834 mxwriter *This = impl_from_IMXWriter( iface );
836 TRACE("(%p)->(%d)\n", This, value);
837 return writer_set_property(This, MXWriter_Indent, value);
840 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value)
842 mxwriter *This = impl_from_IMXWriter( iface );
844 TRACE("(%p)->(%p)\n", This, value);
845 return writer_get_property(This, MXWriter_Indent, value);
848 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value)
850 mxwriter *This = impl_from_IMXWriter( iface );
852 TRACE("(%p)->(%d)\n", This, value);
853 return writer_set_property(This, MXWriter_Standalone, value);
856 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value)
858 mxwriter *This = impl_from_IMXWriter( iface );
860 TRACE("(%p)->(%p)\n", This, value);
861 return writer_get_property(This, MXWriter_Standalone, value);
864 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value)
866 mxwriter *This = impl_from_IMXWriter( iface );
868 TRACE("(%p)->(%d)\n", This, value);
869 return writer_set_property(This, MXWriter_OmitXmlDecl, value);
872 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value)
874 mxwriter *This = impl_from_IMXWriter( iface );
876 TRACE("(%p)->(%p)\n", This, value);
877 return writer_get_property(This, MXWriter_OmitXmlDecl, value);
880 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version)
882 mxwriter *This = impl_from_IMXWriter( iface );
884 TRACE("(%p)->(%s)\n", This, debugstr_w(version));
886 if (!version) return E_INVALIDARG;
888 SysFreeString(This->version);
889 This->version = SysAllocString(version);
891 return S_OK;
894 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version)
896 mxwriter *This = impl_from_IMXWriter( iface );
898 TRACE("(%p)->(%p)\n", This, version);
900 if (!version) return E_POINTER;
902 return return_bstr(This->version, version);
905 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value)
907 mxwriter *This = impl_from_IMXWriter( iface );
909 TRACE("(%p)->(%d)\n", This, value);
910 return writer_set_property(This, MXWriter_DisableEscaping, value);
913 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value)
915 mxwriter *This = impl_from_IMXWriter( iface );
917 TRACE("(%p)->(%p)\n", This, value);
918 return writer_get_property(This, MXWriter_DisableEscaping, value);
921 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface)
923 mxwriter *This = impl_from_IMXWriter( iface );
924 TRACE("(%p)\n", This);
925 return flush_output_buffer(This);
928 static const struct IMXWriterVtbl MXWriterVtbl =
930 mxwriter_QueryInterface,
931 mxwriter_AddRef,
932 mxwriter_Release,
933 mxwriter_GetTypeInfoCount,
934 mxwriter_GetTypeInfo,
935 mxwriter_GetIDsOfNames,
936 mxwriter_Invoke,
937 mxwriter_put_output,
938 mxwriter_get_output,
939 mxwriter_put_encoding,
940 mxwriter_get_encoding,
941 mxwriter_put_byteOrderMark,
942 mxwriter_get_byteOrderMark,
943 mxwriter_put_indent,
944 mxwriter_get_indent,
945 mxwriter_put_standalone,
946 mxwriter_get_standalone,
947 mxwriter_put_omitXMLDeclaration,
948 mxwriter_get_omitXMLDeclaration,
949 mxwriter_put_version,
950 mxwriter_get_version,
951 mxwriter_put_disableOutputEscaping,
952 mxwriter_get_disableOutputEscaping,
953 mxwriter_flush
956 /*** ISAXContentHandler ***/
957 static HRESULT WINAPI SAXContentHandler_QueryInterface(
958 ISAXContentHandler *iface,
959 REFIID riid,
960 void **obj)
962 mxwriter *This = impl_from_ISAXContentHandler( iface );
963 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
966 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface)
968 mxwriter *This = impl_from_ISAXContentHandler( iface );
969 return IMXWriter_AddRef(&This->IMXWriter_iface);
972 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface)
974 mxwriter *This = impl_from_ISAXContentHandler( iface );
975 return IMXWriter_Release(&This->IMXWriter_iface);
978 static HRESULT WINAPI SAXContentHandler_putDocumentLocator(
979 ISAXContentHandler *iface,
980 ISAXLocator *locator)
982 mxwriter *This = impl_from_ISAXContentHandler( iface );
983 FIXME("(%p)->(%p)\n", This, locator);
984 return E_NOTIMPL;
987 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface)
989 mxwriter *This = impl_from_ISAXContentHandler( iface );
991 TRACE("(%p)\n", This);
993 /* If properties have been changed since the last "endDocument" call
994 * we need to reset the output buffer. If we don't the output buffer
995 * could end up with multiple XML documents in it, plus this seems to
996 * be how Windows works.
998 if (This->prop_changed) {
999 reset_output_buffer(This);
1000 This->prop_changed = FALSE;
1003 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK;
1005 write_prolog_buffer(This);
1007 if (This->dest && This->xml_enc == XmlEncoding_UTF16) {
1008 static const char utf16BOM[] = {0xff,0xfe};
1010 if (This->props[MXWriter_BOM] == VARIANT_TRUE)
1011 /* Windows passes a NULL pointer as the pcbWritten parameter and
1012 * ignores any error codes returned from this Write call.
1014 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL);
1017 return S_OK;
1020 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface)
1022 mxwriter *This = impl_from_ISAXContentHandler( iface );
1023 TRACE("(%p)\n", This);
1024 This->prop_changed = FALSE;
1025 return flush_output_buffer(This);
1028 static HRESULT WINAPI SAXContentHandler_startPrefixMapping(
1029 ISAXContentHandler *iface,
1030 const WCHAR *prefix,
1031 int nprefix,
1032 const WCHAR *uri,
1033 int nuri)
1035 mxwriter *This = impl_from_ISAXContentHandler( iface );
1036 FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
1037 return E_NOTIMPL;
1040 static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
1041 ISAXContentHandler *iface,
1042 const WCHAR *prefix,
1043 int nprefix)
1045 mxwriter *This = impl_from_ISAXContentHandler( iface );
1046 FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
1047 return E_NOTIMPL;
1050 static HRESULT WINAPI SAXContentHandler_startElement(
1051 ISAXContentHandler *iface,
1052 const WCHAR *namespaceUri,
1053 int nnamespaceUri,
1054 const WCHAR *local_name,
1055 int nlocal_name,
1056 const WCHAR *QName,
1057 int nQName,
1058 ISAXAttributes *attr)
1060 mxwriter *This = impl_from_ISAXContentHandler( iface );
1061 static const WCHAR ltW[] = {'<'};
1063 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
1064 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
1066 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
1067 return E_INVALIDARG;
1069 close_element_starttag(This);
1070 set_element_name(This, QName ? QName : emptyW,
1071 QName ? nQName : 0);
1073 write_output_buffer(This->buffer, ltW, 1);
1074 write_output_buffer(This->buffer, QName, nQName);
1076 if (attr)
1078 int length, i, escape;
1079 HRESULT hr;
1081 hr = ISAXAttributes_getLength(attr, &length);
1082 if (FAILED(hr)) return hr;
1084 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
1085 (This->class_version == MSXML4 || This->class_version == MSXML6);
1087 for (i = 0; i < length; i++)
1089 static const WCHAR eqW[] = {'='};
1090 const WCHAR *str;
1091 int len = 0;
1093 hr = ISAXAttributes_getQName(attr, i, &str, &len);
1094 if (FAILED(hr)) return hr;
1096 /* space separator in front of every attribute */
1097 write_output_buffer(This->buffer, spaceW, 1);
1098 write_output_buffer(This->buffer, str, len);
1100 write_output_buffer(This->buffer, eqW, 1);
1102 len = 0;
1103 hr = ISAXAttributes_getValue(attr, i, &str, &len);
1104 if (FAILED(hr)) return hr;
1106 if (escape)
1108 WCHAR *escaped = get_escaped_string(str, EscapeValue, &len);
1109 write_output_buffer_quoted(This->buffer, escaped, len);
1110 heap_free(escaped);
1112 else
1113 write_output_buffer_quoted(This->buffer, str, len);
1117 return S_OK;
1120 static HRESULT WINAPI SAXContentHandler_endElement(
1121 ISAXContentHandler *iface,
1122 const WCHAR *namespaceUri,
1123 int nnamespaceUri,
1124 const WCHAR * local_name,
1125 int nlocal_name,
1126 const WCHAR *QName,
1127 int nQName)
1129 mxwriter *This = impl_from_ISAXContentHandler( iface );
1131 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri,
1132 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName);
1134 if ((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6)
1135 return E_INVALIDARG;
1137 if (This->element && QName && !strncmpW(This->element, QName, nQName))
1139 static const WCHAR closeW[] = {'/','>'};
1141 write_output_buffer(This->buffer, closeW, 2);
1143 else
1145 static const WCHAR closetagW[] = {'<','/'};
1146 static const WCHAR gtW[] = {'>'};
1148 write_output_buffer(This->buffer, closetagW, 2);
1149 write_output_buffer(This->buffer, QName, nQName);
1150 write_output_buffer(This->buffer, gtW, 1);
1153 set_element_name(This, NULL, 0);
1155 return S_OK;
1158 static HRESULT WINAPI SAXContentHandler_characters(
1159 ISAXContentHandler *iface,
1160 const WCHAR *chars,
1161 int nchars)
1163 mxwriter *This = impl_from_ISAXContentHandler( iface );
1165 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1167 if (!chars) return E_INVALIDARG;
1169 close_element_starttag(This);
1170 set_element_name(This, NULL, 0);
1172 if (nchars)
1174 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
1175 write_output_buffer(This->buffer, chars, nchars);
1176 else
1178 int len = nchars;
1179 WCHAR *escaped;
1181 escaped = get_escaped_string(chars, EscapeText, &len);
1182 write_output_buffer(This->buffer, escaped, len);
1183 heap_free(escaped);
1187 return S_OK;
1190 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
1191 ISAXContentHandler *iface,
1192 const WCHAR *chars,
1193 int nchars)
1195 mxwriter *This = impl_from_ISAXContentHandler( iface );
1197 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars));
1199 if (!chars) return E_INVALIDARG;
1201 write_output_buffer(This->buffer, chars, nchars);
1203 return S_OK;
1206 static HRESULT WINAPI SAXContentHandler_processingInstruction(
1207 ISAXContentHandler *iface,
1208 const WCHAR *target,
1209 int ntarget,
1210 const WCHAR *data,
1211 int ndata)
1213 mxwriter *This = impl_from_ISAXContentHandler( iface );
1214 static const WCHAR openpiW[] = {'<','?'};
1215 static const WCHAR closepiW[] = {'?','>','\r','\n'};
1217 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata));
1219 if (!target) return E_INVALIDARG;
1221 write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
1223 if (*target)
1224 write_output_buffer(This->buffer, target, ntarget);
1226 if (data && *data && ndata)
1228 write_output_buffer(This->buffer, spaceW, 1);
1229 write_output_buffer(This->buffer, data, ndata);
1232 write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
1234 return S_OK;
1237 static HRESULT WINAPI SAXContentHandler_skippedEntity(
1238 ISAXContentHandler *iface,
1239 const WCHAR *name,
1240 int nname)
1242 mxwriter *This = impl_from_ISAXContentHandler( iface );
1243 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname));
1244 return E_NOTIMPL;
1247 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl =
1249 SAXContentHandler_QueryInterface,
1250 SAXContentHandler_AddRef,
1251 SAXContentHandler_Release,
1252 SAXContentHandler_putDocumentLocator,
1253 SAXContentHandler_startDocument,
1254 SAXContentHandler_endDocument,
1255 SAXContentHandler_startPrefixMapping,
1256 SAXContentHandler_endPrefixMapping,
1257 SAXContentHandler_startElement,
1258 SAXContentHandler_endElement,
1259 SAXContentHandler_characters,
1260 SAXContentHandler_ignorableWhitespace,
1261 SAXContentHandler_processingInstruction,
1262 SAXContentHandler_skippedEntity
1265 /*** ISAXLexicalHandler ***/
1266 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface,
1267 REFIID riid, void **obj)
1269 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1270 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1273 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface)
1275 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1276 return IMXWriter_AddRef(&This->IMXWriter_iface);
1279 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface)
1281 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1282 return IMXWriter_Release(&This->IMXWriter_iface);
1285 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
1286 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len,
1287 const WCHAR *systemId, int systemId_len)
1289 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
1290 static const WCHAR openintW[] = {'[','\r','\n'};
1292 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1294 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len),
1295 debugstr_wn(systemId, systemId_len));
1297 if (!name) return E_INVALIDARG;
1299 write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
1301 if (*name)
1303 write_output_buffer(This->buffer, name, name_len);
1304 write_output_buffer(This->buffer, spaceW, 1);
1307 if (publicId)
1309 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
1311 write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
1312 write_output_buffer_quoted(This->buffer, publicId, publicId_len);
1314 if (!systemId) return E_INVALIDARG;
1316 if (*publicId)
1317 write_output_buffer(This->buffer, spaceW, 1);
1319 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1321 if (*systemId)
1322 write_output_buffer(This->buffer, spaceW, 1);
1324 else if (systemId)
1326 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
1328 write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
1329 write_output_buffer_quoted(This->buffer, systemId, systemId_len);
1330 if (*systemId)
1331 write_output_buffer(This->buffer, spaceW, 1);
1334 write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
1336 return S_OK;
1339 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
1341 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1342 static const WCHAR closedtdW[] = {']','>','\r','\n'};
1344 TRACE("(%p)\n", This);
1346 write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
1348 return S_OK;
1351 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1353 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1354 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len)
1360 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1361 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len));
1362 return E_NOTIMPL;
1365 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
1367 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['};
1368 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1370 TRACE("(%p)\n", This);
1372 write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
1373 This->cdata = TRUE;
1375 return S_OK;
1378 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
1380 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1381 static const WCHAR ecdataW[] = {']',']','>'};
1383 TRACE("(%p)\n", This);
1385 write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
1386 This->cdata = FALSE;
1388 return S_OK;
1391 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars)
1393 mxwriter *This = impl_from_ISAXLexicalHandler( iface );
1394 static const WCHAR copenW[] = {'<','!','-','-'};
1395 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'};
1397 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars);
1399 if (!chars) return E_INVALIDARG;
1401 close_element_starttag(This);
1403 write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
1404 if (nchars)
1405 write_output_buffer(This->buffer, chars, nchars);
1406 write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
1408 return S_OK;
1411 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl =
1413 SAXLexicalHandler_QueryInterface,
1414 SAXLexicalHandler_AddRef,
1415 SAXLexicalHandler_Release,
1416 SAXLexicalHandler_startDTD,
1417 SAXLexicalHandler_endDTD,
1418 SAXLexicalHandler_startEntity,
1419 SAXLexicalHandler_endEntity,
1420 SAXLexicalHandler_startCDATA,
1421 SAXLexicalHandler_endCDATA,
1422 SAXLexicalHandler_comment
1425 /*** ISAXDeclHandler ***/
1426 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface,
1427 REFIID riid, void **obj)
1429 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1430 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
1433 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface)
1435 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1436 return IMXWriter_AddRef(&This->IMXWriter_iface);
1439 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface)
1441 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1442 return IMXWriter_Release(&This->IMXWriter_iface);
1445 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
1446 const WCHAR *name, int n_name, const WCHAR *model, int n_model)
1448 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '};
1449 static const WCHAR closeelementW[] = {'>','\r','\n'};
1450 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1452 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
1453 debugstr_wn(model, n_model), n_model);
1455 if (!name || !model) return E_INVALIDARG;
1457 write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
1458 if (n_name) {
1459 write_output_buffer(This->buffer, name, n_name);
1460 write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
1462 if (n_model)
1463 write_output_buffer(This->buffer, model, n_model);
1464 write_output_buffer(This->buffer, closeelementW, sizeof(closeelementW)/sizeof(WCHAR));
1466 return S_OK;
1469 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
1470 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr,
1471 const WCHAR *type, int n_type, const WCHAR *Default, int n_default,
1472 const WCHAR *value, int n_value)
1474 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1475 FIXME("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(element, n_element), n_element,
1476 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
1477 debugstr_wn(value, n_value), n_value);
1478 return E_NOTIMPL;
1481 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
1482 const WCHAR *name, int n_name, const WCHAR *value, int n_value)
1484 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1485 FIXME("(%p)->(%s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1486 debugstr_wn(value, n_value), n_value);
1487 return E_NOTIMPL;
1490 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
1491 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
1492 const WCHAR *systemId, int n_systemId)
1494 mxwriter *This = impl_from_ISAXDeclHandler( iface );
1495 FIXME("(%p)->(%s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
1496 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
1497 return E_NOTIMPL;
1500 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
1501 SAXDeclHandler_QueryInterface,
1502 SAXDeclHandler_AddRef,
1503 SAXDeclHandler_Release,
1504 SAXDeclHandler_elementDecl,
1505 SAXDeclHandler_attributeDecl,
1506 SAXDeclHandler_internalEntityDecl,
1507 SAXDeclHandler_externalEntityDecl
1510 static const tid_t mxwriter_iface_tids[] = {
1511 IMXWriter_tid,
1515 static dispex_static_data_t mxwriter_dispex = {
1516 NULL,
1517 IMXWriter_tid,
1518 NULL,
1519 mxwriter_iface_tids
1522 HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
1524 static const WCHAR version10W[] = {'1','.','0',0};
1525 mxwriter *This;
1526 HRESULT hr;
1528 TRACE("(%p, %p)\n", outer, ppObj);
1530 if (outer) FIXME("support aggregation, outer\n");
1532 This = heap_alloc( sizeof (*This) );
1533 if(!This)
1534 return E_OUTOFMEMORY;
1536 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
1537 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
1538 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
1539 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
1540 This->ref = 1;
1541 This->class_version = version;
1543 This->props[MXWriter_BOM] = VARIANT_TRUE;
1544 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
1545 This->props[MXWriter_Indent] = VARIANT_FALSE;
1546 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
1547 This->props[MXWriter_Standalone] = VARIANT_FALSE;
1548 This->prop_changed = FALSE;
1549 This->encoding = SysAllocString(utf16W);
1550 This->version = SysAllocString(version10W);
1551 This->xml_enc = XmlEncoding_UTF16;
1553 This->element = NULL;
1554 This->cdata = FALSE;
1556 This->dest = NULL;
1557 This->dest_written = 0;
1559 hr = alloc_output_buffer(This->xml_enc, &This->buffer);
1560 if (hr != S_OK) {
1561 SysFreeString(This->encoding);
1562 SysFreeString(This->version);
1563 heap_free(This);
1564 return hr;
1567 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
1569 *ppObj = &This->IMXWriter_iface;
1571 TRACE("returning iface %p\n", *ppObj);
1573 return S_OK;
1576 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
1578 mxattributes *This = impl_from_IMXAttributes( iface );
1580 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
1582 *ppObj = NULL;
1584 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
1585 IsEqualGUID( riid, &IID_IDispatch ) ||
1586 IsEqualGUID( riid, &IID_IMXAttributes ))
1588 *ppObj = iface;
1590 else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
1592 *ppObj = &This->ISAXAttributes_iface;
1594 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes ))
1596 *ppObj = &This->IVBSAXAttributes_iface;
1598 else if (dispex_query_interface(&This->dispex, riid, ppObj))
1600 return *ppObj ? S_OK : E_NOINTERFACE;
1602 else
1604 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1605 return E_NOINTERFACE;
1608 IMXAttributes_AddRef( iface );
1610 return S_OK;
1613 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface)
1615 mxattributes *This = impl_from_IMXAttributes( iface );
1616 ULONG ref = InterlockedIncrement( &This->ref );
1617 TRACE("(%p)->(%d)\n", This, ref );
1618 return ref;
1621 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface)
1623 mxattributes *This = impl_from_IMXAttributes( iface );
1624 LONG ref = InterlockedDecrement( &This->ref );
1626 TRACE("(%p)->(%d)\n", This, ref);
1628 if (ref == 0)
1630 int i;
1632 for (i = 0; i < This->length; i++)
1634 SysFreeString(This->attr[i].qname);
1635 SysFreeString(This->attr[i].local);
1636 SysFreeString(This->attr[i].uri);
1637 SysFreeString(This->attr[i].type);
1638 SysFreeString(This->attr[i].value);
1641 release_dispex(&This->dispex);
1642 heap_free(This->attr);
1643 heap_free(This);
1646 return ref;
1649 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo)
1651 mxattributes *This = impl_from_IMXAttributes( iface );
1652 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1655 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
1657 mxattributes *This = impl_from_IMXAttributes( iface );
1658 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1661 static HRESULT WINAPI MXAttributes_GetIDsOfNames(
1662 IMXAttributes *iface,
1663 REFIID riid,
1664 LPOLESTR* rgszNames,
1665 UINT cNames,
1666 LCID lcid,
1667 DISPID* rgDispId)
1669 mxattributes *This = impl_from_IMXAttributes( iface );
1670 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
1671 riid, rgszNames, cNames, lcid, rgDispId);
1674 static HRESULT WINAPI MXAttributes_Invoke(
1675 IMXAttributes *iface,
1676 DISPID dispIdMember,
1677 REFIID riid,
1678 LCID lcid,
1679 WORD wFlags,
1680 DISPPARAMS* pDispParams,
1681 VARIANT* pVarResult,
1682 EXCEPINFO* pExcepInfo,
1683 UINT* puArgErr)
1685 mxattributes *This = impl_from_IMXAttributes( iface );
1686 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
1687 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1690 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface,
1691 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1693 mxattributes *This = impl_from_IMXAttributes( iface );
1694 mxattribute *attr;
1695 HRESULT hr;
1697 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName),
1698 debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1700 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6)
1701 return E_INVALIDARG;
1703 /* ensure array is large enough */
1704 hr = mxattributes_grow(This);
1705 if (hr != S_OK) return hr;
1707 attr = &This->attr[This->length];
1709 attr->qname = SysAllocString(QName);
1710 attr->local = SysAllocString(localName);
1711 attr->uri = SysAllocString(uri);
1712 attr->type = SysAllocString(type ? type : emptyW);
1713 attr->value = SysAllocString(value);
1714 This->length++;
1716 return S_OK;
1719 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface,
1720 VARIANT atts, int index)
1722 mxattributes *This = impl_from_IMXAttributes( iface );
1723 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index);
1724 return E_NOTIMPL;
1727 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface)
1729 mxattributes *This = impl_from_IMXAttributes( iface );
1730 int i;
1732 TRACE("(%p)\n", This);
1734 for (i = 0; i < This->length; i++)
1736 SysFreeString(This->attr[i].qname);
1737 SysFreeString(This->attr[i].local);
1738 SysFreeString(This->attr[i].uri);
1739 SysFreeString(This->attr[i].type);
1740 SysFreeString(This->attr[i].value);
1741 memset(&This->attr[i], 0, sizeof(mxattribute));
1744 This->length = 0;
1746 return S_OK;
1749 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
1751 mxattributes *This = impl_from_IMXAttributes( iface );
1752 FIXME("(%p)->(%d): stub\n", This, index);
1753 return E_NOTIMPL;
1756 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
1757 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value)
1759 mxattributes *This = impl_from_IMXAttributes( iface );
1760 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri),
1761 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value));
1762 return E_NOTIMPL;
1765 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts)
1767 mxattributes *This = impl_from_IMXAttributes( iface );
1768 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts));
1769 return E_NOTIMPL;
1772 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index,
1773 BSTR localName)
1775 mxattributes *This = impl_from_IMXAttributes( iface );
1776 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(localName));
1777 return E_NOTIMPL;
1780 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
1782 mxattributes *This = impl_from_IMXAttributes( iface );
1783 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(QName));
1784 return E_NOTIMPL;
1787 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
1789 mxattributes *This = impl_from_IMXAttributes( iface );
1790 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(uri));
1791 return E_NOTIMPL;
1794 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
1796 mxattributes *This = impl_from_IMXAttributes( iface );
1797 FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(value));
1798 return E_NOTIMPL;
1801 static const IMXAttributesVtbl MXAttributesVtbl = {
1802 MXAttributes_QueryInterface,
1803 MXAttributes_AddRef,
1804 MXAttributes_Release,
1805 MXAttributes_GetTypeInfoCount,
1806 MXAttributes_GetTypeInfo,
1807 MXAttributes_GetIDsOfNames,
1808 MXAttributes_Invoke,
1809 MXAttributes_addAttribute,
1810 MXAttributes_addAttributeFromIndex,
1811 MXAttributes_clear,
1812 MXAttributes_removeAttribute,
1813 MXAttributes_setAttribute,
1814 MXAttributes_setAttributes,
1815 MXAttributes_setLocalName,
1816 MXAttributes_setQName,
1817 MXAttributes_setURI,
1818 MXAttributes_setValue
1821 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj)
1823 mxattributes *This = impl_from_ISAXAttributes( iface );
1824 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj);
1827 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface)
1829 mxattributes *This = impl_from_ISAXAttributes( iface );
1830 return IMXAttributes_AddRef(&This->IMXAttributes_iface);
1833 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface)
1835 mxattributes *This = impl_from_ISAXAttributes( iface );
1836 return IMXAttributes_Release(&This->IMXAttributes_iface);
1839 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length)
1841 mxattributes *This = impl_from_ISAXAttributes( iface );
1842 TRACE("(%p)->(%p)\n", This, length);
1844 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1845 return E_POINTER;
1847 *length = This->length;
1849 return S_OK;
1852 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri,
1853 int *len)
1855 mxattributes *This = impl_from_ISAXAttributes( iface );
1857 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len);
1859 if (index >= This->length || index < 0) return E_INVALIDARG;
1860 if (!uri || !len) return E_POINTER;
1862 *len = SysStringLen(This->attr[index].uri);
1863 *uri = This->attr[index].uri;
1865 return S_OK;
1868 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name,
1869 int *len)
1871 mxattributes *This = impl_from_ISAXAttributes( iface );
1873 TRACE("(%p)->(%d %p %p)\n", This, index, name, len);
1875 if (index >= This->length || index < 0) return E_INVALIDARG;
1876 if (!name || !len) return E_POINTER;
1878 *len = SysStringLen(This->attr[index].local);
1879 *name = This->attr[index].local;
1881 return S_OK;
1884 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length)
1886 mxattributes *This = impl_from_ISAXAttributes( iface );
1888 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length);
1890 if (index >= This->length) return E_INVALIDARG;
1891 if (!qname || !length) return E_POINTER;
1893 *qname = This->attr[index].qname;
1894 *length = SysStringLen(This->attr[index].qname);
1896 return S_OK;
1899 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len,
1900 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len)
1902 mxattributes *This = impl_from_ISAXAttributes( iface );
1904 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len);
1906 if (index >= This->length || index < 0)
1907 return E_INVALIDARG;
1909 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len)
1910 return E_POINTER;
1912 *uri_len = SysStringLen(This->attr[index].uri);
1913 *uri = This->attr[index].uri;
1915 *local_len = SysStringLen(This->attr[index].local);
1916 *local = This->attr[index].local;
1918 *qname_len = SysStringLen(This->attr[index].qname);
1919 *qname = This->attr[index].qname;
1921 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname));
1923 return S_OK;
1926 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len,
1927 const WCHAR *name, int len, int *index)
1929 mxattributes *This = impl_from_ISAXAttributes( iface );
1930 int i;
1932 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
1933 debugstr_wn(name, len), len, index);
1935 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1936 return E_POINTER;
1938 if (!uri || !name || !index) return E_INVALIDARG;
1940 for (i = 0; i < This->length; i++)
1942 if (uri_len != SysStringLen(This->attr[i].uri)) continue;
1943 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue;
1945 if (len != SysStringLen(This->attr[i].local)) continue;
1946 if (strncmpW(name, This->attr[i].local, len)) continue;
1948 *index = i;
1949 return S_OK;
1952 return E_INVALIDARG;
1955 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname,
1956 int len, int *index)
1958 mxattributes *This = impl_from_ISAXAttributes( iface );
1959 int i;
1961 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index);
1963 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1964 return E_POINTER;
1966 if (!qname || !index || !len) return E_INVALIDARG;
1968 for (i = 0; i < This->length; i++)
1970 if (len != SysStringLen(This->attr[i].qname)) continue;
1971 if (strncmpW(qname, This->attr[i].qname, len)) continue;
1973 *index = i;
1974 return S_OK;
1977 return E_INVALIDARG;
1980 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type,
1981 int *len)
1983 mxattributes *This = impl_from_ISAXAttributes( iface );
1985 TRACE("(%p)->(%d %p %p)\n", This, index, type, len);
1987 if (index >= This->length) return E_INVALIDARG;
1989 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
1990 return E_POINTER;
1992 *type = This->attr[index].type;
1993 *len = SysStringLen(This->attr[index].type);
1995 return S_OK;
1998 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri,
1999 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType)
2001 mxattributes *This = impl_from_ISAXAttributes( iface );
2002 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri,
2003 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType);
2004 return E_NOTIMPL;
2007 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName,
2008 int nQName, const WCHAR ** pType, int * nType)
2010 mxattributes *This = impl_from_ISAXAttributes( iface );
2011 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType);
2012 return E_NOTIMPL;
2015 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value,
2016 int *len)
2018 mxattributes *This = impl_from_ISAXAttributes( iface );
2020 TRACE("(%p)->(%d %p %p)\n", This, index, value, len);
2022 if (index >= This->length) return E_INVALIDARG;
2024 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3))
2025 return E_POINTER;
2027 *value = This->attr[index].value;
2028 *len = SysStringLen(This->attr[index].value);
2030 return S_OK;
2033 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri,
2034 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len)
2036 mxattributes *This = impl_from_ISAXAttributes( iface );
2037 HRESULT hr;
2038 int index;
2040 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len,
2041 debugstr_wn(name, name_len), name_len, value, value_len);
2043 if (!uri || !name || !value || !value_len)
2044 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2046 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index);
2047 if (hr == S_OK)
2048 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2050 return hr;
2053 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname,
2054 int qname_len, const WCHAR **value, int *value_len)
2056 mxattributes *This = impl_from_ISAXAttributes( iface );
2057 HRESULT hr;
2058 int index;
2060 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len);
2062 if (!qname || !value || !value_len)
2063 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG;
2065 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index);
2066 if (hr == S_OK)
2067 hr = ISAXAttributes_getValue(iface, index, value, value_len);
2069 return hr;
2072 static const ISAXAttributesVtbl SAXAttributesVtbl = {
2073 SAXAttributes_QueryInterface,
2074 SAXAttributes_AddRef,
2075 SAXAttributes_Release,
2076 SAXAttributes_getLength,
2077 SAXAttributes_getURI,
2078 SAXAttributes_getLocalName,
2079 SAXAttributes_getQName,
2080 SAXAttributes_getName,
2081 SAXAttributes_getIndexFromName,
2082 SAXAttributes_getIndexFromQName,
2083 SAXAttributes_getType,
2084 SAXAttributes_getTypeFromName,
2085 SAXAttributes_getTypeFromQName,
2086 SAXAttributes_getValue,
2087 SAXAttributes_getValueFromName,
2088 SAXAttributes_getValueFromQName
2091 static HRESULT WINAPI VBSAXAttributes_QueryInterface(
2092 IVBSAXAttributes* iface,
2093 REFIID riid,
2094 void **ppvObject)
2096 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2097 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject);
2098 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject);
2101 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface)
2103 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2104 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface);
2107 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface)
2109 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2110 return ISAXAttributes_Release(&This->ISAXAttributes_iface);
2113 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
2115 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2117 TRACE("(%p)->(%p)\n", This, pctinfo);
2119 *pctinfo = 1;
2121 return S_OK;
2124 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo(
2125 IVBSAXAttributes *iface,
2126 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
2128 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2129 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
2130 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
2133 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames(
2134 IVBSAXAttributes *iface,
2135 REFIID riid,
2136 LPOLESTR* rgszNames,
2137 UINT cNames,
2138 LCID lcid,
2139 DISPID* rgDispId)
2141 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2142 ITypeInfo *typeinfo;
2143 HRESULT hr;
2145 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
2146 lcid, rgDispId);
2148 if(!rgszNames || cNames == 0 || !rgDispId)
2149 return E_INVALIDARG;
2151 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2152 if(SUCCEEDED(hr))
2154 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
2155 ITypeInfo_Release(typeinfo);
2158 return hr;
2161 static HRESULT WINAPI VBSAXAttributes_Invoke(
2162 IVBSAXAttributes *iface,
2163 DISPID dispIdMember,
2164 REFIID riid,
2165 LCID lcid,
2166 WORD wFlags,
2167 DISPPARAMS* pDispParams,
2168 VARIANT* pVarResult,
2169 EXCEPINFO* pExcepInfo,
2170 UINT* puArgErr)
2172 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2173 ITypeInfo *typeinfo;
2174 HRESULT hr;
2176 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
2177 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2179 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo);
2180 if(SUCCEEDED(hr))
2182 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags,
2183 pDispParams, pVarResult, pExcepInfo, puArgErr);
2184 ITypeInfo_Release(typeinfo);
2187 return hr;
2190 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len)
2192 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2193 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len);
2196 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
2198 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2199 int len;
2201 return ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, (const WCHAR**)uri, &len);
2204 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
2206 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2207 int len;
2209 return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, (const WCHAR**)name, &len);
2212 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
2214 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2215 int len;
2217 return ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, (const WCHAR**)qname, &len);
2220 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
2222 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2223 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2224 name, SysStringLen(name), index);
2227 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index)
2229 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2230 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname,
2231 SysStringLen(qname), index);
2234 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index,BSTR *type)
2236 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2237 int len;
2239 return ISAXAttributes_getType(&This->ISAXAttributes_iface, index, (const WCHAR**)type, &len);
2242 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
2243 BSTR name, BSTR *type)
2245 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2246 int len;
2248 return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2249 name, SysStringLen(name), (const WCHAR**)type, &len);
2252 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
2254 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2255 int len;
2257 return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2258 (const WCHAR**)type, &len);
2261 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
2263 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2264 int len;
2266 return ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, (const WCHAR**)value, &len);
2269 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
2270 BSTR *value)
2272 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2273 int len;
2275 return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
2276 name, SysStringLen(name), (const WCHAR**)value, &len);
2279 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
2281 mxattributes *This = impl_from_IVBSAXAttributes( iface );
2282 int len;
2284 return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
2285 (const WCHAR**)value, &len);
2288 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
2290 VBSAXAttributes_QueryInterface,
2291 VBSAXAttributes_AddRef,
2292 VBSAXAttributes_Release,
2293 VBSAXAttributes_GetTypeInfoCount,
2294 VBSAXAttributes_GetTypeInfo,
2295 VBSAXAttributes_GetIDsOfNames,
2296 VBSAXAttributes_Invoke,
2297 VBSAXAttributes_get_length,
2298 VBSAXAttributes_getURI,
2299 VBSAXAttributes_getLocalName,
2300 VBSAXAttributes_getQName,
2301 VBSAXAttributes_getIndexFromName,
2302 VBSAXAttributes_getIndexFromQName,
2303 VBSAXAttributes_getType,
2304 VBSAXAttributes_getTypeFromName,
2305 VBSAXAttributes_getTypeFromQName,
2306 VBSAXAttributes_getValue,
2307 VBSAXAttributes_getValueFromName,
2308 VBSAXAttributes_getValueFromQName
2311 static const tid_t mxattrs_iface_tids[] = {
2312 IMXAttributes_tid,
2316 static dispex_static_data_t mxattrs_dispex = {
2317 NULL,
2318 IMXAttributes_tid,
2319 NULL,
2320 mxattrs_iface_tids
2323 HRESULT SAXAttributes_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
2325 static const int default_count = 10;
2326 mxattributes *This;
2328 TRACE("(%p, %p)\n", outer, ppObj);
2330 This = heap_alloc( sizeof (*This) );
2331 if( !This )
2332 return E_OUTOFMEMORY;
2334 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl;
2335 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl;
2336 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl;
2337 This->ref = 1;
2339 This->class_version = version;
2341 This->attr = heap_alloc(default_count*sizeof(mxattribute));
2342 This->length = 0;
2343 This->allocated = default_count;
2345 *ppObj = &This->IMXAttributes_iface;
2347 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex);
2349 TRACE("returning iface %p\n", *ppObj);
2351 return S_OK;