2 * MXWriter implementation
4 * Copyright 2011-2013 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 WIN32_NO_STATUS
30 # include <libxml/parser.h>
39 #include <wine/debug.h>
41 #include "msxml_private.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msxml
);
45 static const WCHAR emptyW
[] = {0};
46 static const WCHAR spaceW
[] = {' '};
47 static const WCHAR quotW
[] = {'\"'};
48 static const WCHAR closetagW
[] = {'>','\r','\n'};
49 static const WCHAR crlfW
[] = {'\r','\n'};
50 static const WCHAR entityW
[] = {'<','!','E','N','T','I','T','Y',' '};
52 /* should be ordered as encoding names are sorted */
55 XmlEncoding_ISO_8859_1
= 0,
56 XmlEncoding_ISO_8859_13
,
57 XmlEncoding_ISO_8859_15
,
58 XmlEncoding_ISO_8859_2
,
59 XmlEncoding_ISO_8859_3
,
60 XmlEncoding_ISO_8859_4
,
61 XmlEncoding_ISO_8859_5
,
62 XmlEncoding_ISO_8859_7
,
63 XmlEncoding_ISO_8859_9
,
69 struct xml_encoding_data
71 const WCHAR
*encoding
;
76 static const WCHAR iso_8859_1W
[] = {'i','s','o','-','8','8','5','9','-','1',0};
77 static const WCHAR iso_8859_2W
[] = {'i','s','o','-','8','8','5','9','-','2',0};
78 static const WCHAR iso_8859_3W
[] = {'i','s','o','-','8','8','5','9','-','3',0};
79 static const WCHAR iso_8859_4W
[] = {'i','s','o','-','8','8','5','9','-','4',0};
80 static const WCHAR iso_8859_5W
[] = {'i','s','o','-','8','8','5','9','-','5',0};
81 static const WCHAR iso_8859_7W
[] = {'i','s','o','-','8','8','5','9','-','7',0};
82 static const WCHAR iso_8859_9W
[] = {'i','s','o','-','8','8','5','9','-','9',0};
83 static const WCHAR iso_8859_13W
[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
84 static const WCHAR iso_8859_15W
[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
85 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
86 static const WCHAR utf8W
[] = {'U','T','F','-','8',0};
88 static const struct xml_encoding_data xml_encoding_map
[] = {
89 { iso_8859_1W
, XmlEncoding_ISO_8859_1
, 28591 },
90 { iso_8859_13W
, XmlEncoding_ISO_8859_13
, 28603 },
91 { iso_8859_15W
, XmlEncoding_ISO_8859_15
, 28605 },
92 { iso_8859_2W
, XmlEncoding_ISO_8859_2
, 28592 },
93 { iso_8859_3W
, XmlEncoding_ISO_8859_3
, 28593 },
94 { iso_8859_4W
, XmlEncoding_ISO_8859_4
, 28594 },
95 { iso_8859_5W
, XmlEncoding_ISO_8859_5
, 28595 },
96 { iso_8859_7W
, XmlEncoding_ISO_8859_7
, 28597 },
97 { iso_8859_9W
, XmlEncoding_ISO_8859_9
, 28599 },
98 { utf16W
, XmlEncoding_UTF16
, ~0 },
99 { utf8W
, XmlEncoding_UTF8
, CP_UTF8
}
104 OutputBuffer_Native
= 0x001,
105 OutputBuffer_Encoded
= 0x010,
106 OutputBuffer_Both
= 0x100
112 MXWriter_DisableEscaping
,
114 MXWriter_OmitXmlDecl
,
128 unsigned int allocated
;
129 unsigned int written
;
134 encoded_buffer utf16
;
135 encoded_buffer encoded
;
142 IMXWriter IMXWriter_iface
;
143 ISAXContentHandler ISAXContentHandler_iface
;
144 ISAXLexicalHandler ISAXLexicalHandler_iface
;
145 ISAXDeclHandler ISAXDeclHandler_iface
;
148 MSXML_VERSION class_version
;
150 VARIANT_BOOL props
[MXWriter_LastProp
];
154 BOOL text
; /* last node was text node, so we shouldn't indent next node */
155 BOOL newline
; /* newline was already added as a part of previous call */
156 UINT indent
; /* indentation level for next node */
160 BSTR encoding
; /* exact property value */
161 xml_encoding xml_enc
;
163 /* contains a pending (or not closed yet) element name or NULL if
164 we don't have to close */
170 output_buffer
*buffer
;
185 IMXAttributes IMXAttributes_iface
;
186 ISAXAttributes ISAXAttributes_iface
;
187 IVBSAXAttributes IVBSAXAttributes_iface
;
190 MSXML_VERSION class_version
;
197 static inline mxattributes
*impl_from_IMXAttributes( IMXAttributes
*iface
)
199 return CONTAINING_RECORD(iface
, mxattributes
, IMXAttributes_iface
);
202 static inline mxattributes
*impl_from_ISAXAttributes( ISAXAttributes
*iface
)
204 return CONTAINING_RECORD(iface
, mxattributes
, ISAXAttributes_iface
);
207 static inline mxattributes
*impl_from_IVBSAXAttributes( IVBSAXAttributes
*iface
)
209 return CONTAINING_RECORD(iface
, mxattributes
, IVBSAXAttributes_iface
);
212 static HRESULT
mxattributes_grow(mxattributes
*This
)
214 if (This
->length
< This
->allocated
) return S_OK
;
216 This
->allocated
*= 2;
217 This
->attr
= heap_realloc(This
->attr
, This
->allocated
*sizeof(mxattribute
));
219 return This
->attr
? S_OK
: E_OUTOFMEMORY
;
222 static xml_encoding
parse_encoding_name(const WCHAR
*encoding
)
227 max
= sizeof(xml_encoding_map
)/sizeof(struct xml_encoding_data
) - 1;
233 c
= strcmpiW(xml_encoding_map
[n
].encoding
, encoding
);
235 return xml_encoding_map
[n
].enc
;
243 return XmlEncoding_Unknown
;
246 static HRESULT
init_encoded_buffer(encoded_buffer
*buffer
)
248 const int initial_len
= 0x2000;
249 buffer
->data
= heap_alloc(initial_len
);
250 if (!buffer
->data
) return E_OUTOFMEMORY
;
252 memset(buffer
->data
, 0, 4);
253 buffer
->allocated
= initial_len
;
259 static void free_encoded_buffer(encoded_buffer
*buffer
)
261 heap_free(buffer
->data
);
264 static HRESULT
get_code_page(xml_encoding encoding
, UINT
*cp
)
266 const struct xml_encoding_data
*data
;
268 if (encoding
== XmlEncoding_Unknown
)
270 FIXME("unsupported encoding %d\n", encoding
);
274 data
= &xml_encoding_map
[encoding
];
280 static HRESULT
alloc_output_buffer(xml_encoding encoding
, output_buffer
**buffer
)
285 ret
= heap_alloc(sizeof(*ret
));
286 if (!ret
) return E_OUTOFMEMORY
;
288 hr
= get_code_page(encoding
, &ret
->code_page
);
294 hr
= init_encoded_buffer(&ret
->utf16
);
300 /* currently we always create a default output buffer that is UTF-16 only,
301 but it's possible to allocate with specific encoding too */
302 if (encoding
!= XmlEncoding_UTF16
) {
303 hr
= init_encoded_buffer(&ret
->encoded
);
305 free_encoded_buffer(&ret
->utf16
);
311 memset(&ret
->encoded
, 0, sizeof(ret
->encoded
));
318 static void free_output_buffer(output_buffer
*buffer
)
320 free_encoded_buffer(&buffer
->encoded
);
321 free_encoded_buffer(&buffer
->utf16
);
325 static void grow_buffer(encoded_buffer
*buffer
, int length
)
327 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
328 if (buffer
->allocated
< buffer
->written
+ length
+ 4)
330 int grown_size
= max(2*buffer
->allocated
, buffer
->allocated
+ length
);
331 buffer
->data
= heap_realloc(buffer
->data
, grown_size
);
332 buffer
->allocated
= grown_size
;
336 static HRESULT
write_output_buffer_mode(output_buffer
*buffer
, output_mode mode
, const WCHAR
*data
, int len
)
341 if (mode
& (OutputBuffer_Encoded
| OutputBuffer_Both
)) {
342 if (buffer
->code_page
!= ~0)
344 length
= WideCharToMultiByte(buffer
->code_page
, 0, data
, len
, NULL
, 0, NULL
, NULL
);
345 grow_buffer(&buffer
->encoded
, length
);
346 ptr
= buffer
->encoded
.data
+ buffer
->encoded
.written
;
347 length
= WideCharToMultiByte(buffer
->code_page
, 0, data
, len
, ptr
, length
, NULL
, NULL
);
348 buffer
->encoded
.written
+= len
== -1 ? length
-1 : length
;
352 if (mode
& (OutputBuffer_Native
| OutputBuffer_Both
)) {
353 /* WCHAR data just copied */
354 length
= len
== -1 ? strlenW(data
) : len
;
357 length
*= sizeof(WCHAR
);
359 grow_buffer(&buffer
->utf16
, length
);
360 ptr
= buffer
->utf16
.data
+ buffer
->utf16
.written
;
362 memcpy(ptr
, data
, length
);
363 buffer
->utf16
.written
+= length
;
365 /* null termination */
366 memset(ptr
, 0, sizeof(WCHAR
));
373 static HRESULT
write_output_buffer(output_buffer
*buffer
, const WCHAR
*data
, int len
)
375 return write_output_buffer_mode(buffer
, OutputBuffer_Both
, data
, len
);
378 static HRESULT
write_output_buffer_quoted(output_buffer
*buffer
, const WCHAR
*data
, int len
)
380 write_output_buffer(buffer
, quotW
, 1);
381 write_output_buffer(buffer
, data
, len
);
382 write_output_buffer(buffer
, quotW
, 1);
387 /* frees buffer data, reallocates with a default lengths */
388 static void close_output_buffer(mxwriter
*This
)
390 heap_free(This
->buffer
->utf16
.data
);
391 heap_free(This
->buffer
->encoded
.data
);
392 init_encoded_buffer(&This
->buffer
->utf16
);
393 init_encoded_buffer(&This
->buffer
->encoded
);
394 get_code_page(This
->xml_enc
, &This
->buffer
->code_page
);
397 /* escapes special characters like:
403 static WCHAR
*get_escaped_string(const WCHAR
*str
, escape_mode mode
, int *len
)
405 static const WCHAR ltW
[] = {'&','l','t',';'};
406 static const WCHAR ampW
[] = {'&','a','m','p',';'};
407 static const WCHAR equotW
[] = {'&','q','u','o','t',';'};
408 static const WCHAR gtW
[] = {'&','g','t',';'};
410 const int default_alloc
= 100;
411 const int grow_thresh
= 10;
412 int p
= *len
, conv_len
;
415 /* default buffer size to something if length is unknown */
416 conv_len
= *len
== -1 ? default_alloc
: max(2**len
, default_alloc
);
417 ptr
= ret
= heap_alloc(conv_len
*sizeof(WCHAR
));
421 if (ptr
- ret
> conv_len
- grow_thresh
)
423 int written
= ptr
- ret
;
425 ptr
= ret
= heap_realloc(ret
, conv_len
*sizeof(WCHAR
));
432 memcpy(ptr
, ltW
, sizeof(ltW
));
433 ptr
+= sizeof(ltW
)/sizeof(WCHAR
);
436 memcpy(ptr
, ampW
, sizeof(ampW
));
437 ptr
+= sizeof(ampW
)/sizeof(WCHAR
);
440 memcpy(ptr
, gtW
, sizeof(gtW
));
441 ptr
+= sizeof(gtW
)/sizeof(WCHAR
);
444 if (mode
== EscapeValue
)
446 memcpy(ptr
, equotW
, sizeof(equotW
));
447 ptr
+= sizeof(equotW
)/sizeof(WCHAR
);
450 /* fallthrough for text mode */
460 if (*len
!= -1) *len
= ptr
-ret
;
466 static void write_prolog_buffer(mxwriter
*This
)
468 static const WCHAR versionW
[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
469 static const WCHAR encodingW
[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
470 static const WCHAR standaloneW
[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
471 static const WCHAR yesW
[] = {'y','e','s','\"','?','>'};
472 static const WCHAR noW
[] = {'n','o','\"','?','>'};
475 write_output_buffer(This
->buffer
, versionW
, sizeof(versionW
)/sizeof(WCHAR
));
476 write_output_buffer_quoted(This
->buffer
, This
->version
, -1);
479 write_output_buffer(This
->buffer
, encodingW
, sizeof(encodingW
)/sizeof(WCHAR
));
481 /* always write UTF-16 to WCHAR buffer */
482 write_output_buffer_mode(This
->buffer
, OutputBuffer_Native
, utf16W
, sizeof(utf16W
)/sizeof(WCHAR
) - 1);
483 write_output_buffer_mode(This
->buffer
, OutputBuffer_Encoded
, This
->encoding
, -1);
484 write_output_buffer(This
->buffer
, quotW
, 1);
487 write_output_buffer(This
->buffer
, standaloneW
, sizeof(standaloneW
)/sizeof(WCHAR
));
488 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
489 write_output_buffer(This
->buffer
, yesW
, sizeof(yesW
)/sizeof(WCHAR
));
491 write_output_buffer(This
->buffer
, noW
, sizeof(noW
)/sizeof(WCHAR
));
493 write_output_buffer(This
->buffer
, crlfW
, sizeof(crlfW
)/sizeof(WCHAR
));
494 This
->newline
= TRUE
;
497 /* Attempts to the write data from the mxwriter's buffer to
498 * the destination stream (if there is one).
500 static HRESULT
write_data_to_stream(mxwriter
*This
)
502 encoded_buffer
*buffer
;
509 if (This
->xml_enc
!= XmlEncoding_UTF16
)
510 buffer
= &This
->buffer
->encoded
;
512 buffer
= &This
->buffer
->utf16
;
514 if (This
->dest_written
> buffer
->written
) {
515 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This
->dest_written
, buffer
->written
);
517 } else if (This
->dest_written
== buffer
->written
&& This
->xml_enc
!= XmlEncoding_UTF8
)
518 /* Windows seems to make an empty write call when the encoding is UTF-8 and
519 * all the data has been written to the stream. It doesn't seem make this call
520 * for any other encodings.
524 /* Write the current content from the output buffer into 'dest'.
525 * TODO: Check what Windows does if the IStream doesn't write all of
526 * the data we give it at once.
528 hr
= IStream_Write(This
->dest
, buffer
->data
+This
->dest_written
,
529 buffer
->written
-This
->dest_written
, &written
);
531 WARN("Failed to write data to IStream (0x%08x)\n", hr
);
535 This
->dest_written
+= written
;
539 /* Newly added element start tag left unclosed cause for empty elements
540 we have to close it differently. */
541 static void close_element_starttag(const mxwriter
*This
)
543 static const WCHAR gtW
[] = {'>'};
544 if (!This
->element
) return;
545 write_output_buffer(This
->buffer
, gtW
, 1);
548 static void write_node_indent(mxwriter
*This
)
550 static const WCHAR tabW
[] = {'\t'};
551 int indent
= This
->indent
;
553 if (!This
->props
[MXWriter_Indent
] || This
->text
)
559 /* This is to workaround PI output logic that always puts newline chars,
560 document prolog PI does that too. */
562 write_output_buffer(This
->buffer
, crlfW
, sizeof(crlfW
)/sizeof(WCHAR
));
564 write_output_buffer(This
->buffer
, tabW
, 1);
566 This
->newline
= FALSE
;
570 static inline void writer_inc_indent(mxwriter
*This
)
575 static inline void writer_dec_indent(mxwriter
*This
)
577 if (This
->indent
) This
->indent
--;
578 /* depth is decreased only when element is closed, meaning it's not a text node
583 static void set_element_name(mxwriter
*This
, const WCHAR
*name
, int len
)
585 SysFreeString(This
->element
);
587 This
->element
= len
!= -1 ? SysAllocStringLen(name
, len
) : SysAllocString(name
);
589 This
->element
= NULL
;
592 static inline HRESULT
flush_output_buffer(mxwriter
*This
)
594 close_element_starttag(This
);
595 set_element_name(This
, NULL
, 0);
597 return write_data_to_stream(This
);
600 /* Resets the mxwriter's output buffer by closing it, then creating a new
601 * output buffer using the given encoding.
603 static inline void reset_output_buffer(mxwriter
*This
)
605 close_output_buffer(This
);
606 This
->dest_written
= 0;
609 static HRESULT
writer_set_property(mxwriter
*writer
, mxwriter_prop property
, VARIANT_BOOL value
)
611 writer
->props
[property
] = value
;
612 writer
->prop_changed
= TRUE
;
616 static HRESULT
writer_get_property(const mxwriter
*writer
, mxwriter_prop property
, VARIANT_BOOL
*value
)
618 if (!value
) return E_POINTER
;
619 *value
= writer
->props
[property
];
623 static inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
625 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
628 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
630 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
633 static inline mxwriter
*impl_from_ISAXLexicalHandler(ISAXLexicalHandler
*iface
)
635 return CONTAINING_RECORD(iface
, mxwriter
, ISAXLexicalHandler_iface
);
638 static inline mxwriter
*impl_from_ISAXDeclHandler(ISAXDeclHandler
*iface
)
640 return CONTAINING_RECORD(iface
, mxwriter
, ISAXDeclHandler_iface
);
643 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
645 mxwriter
*This
= impl_from_IMXWriter( iface
);
647 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
651 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
652 IsEqualGUID( riid
, &IID_IDispatch
) ||
653 IsEqualGUID( riid
, &IID_IUnknown
) )
655 *obj
= &This
->IMXWriter_iface
;
657 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
659 *obj
= &This
->ISAXContentHandler_iface
;
661 else if ( IsEqualGUID( riid
, &IID_ISAXLexicalHandler
) )
663 *obj
= &This
->ISAXLexicalHandler_iface
;
665 else if ( IsEqualGUID( riid
, &IID_ISAXDeclHandler
) )
667 *obj
= &This
->ISAXDeclHandler_iface
;
669 else if (dispex_query_interface(&This
->dispex
, riid
, obj
))
671 return *obj
? S_OK
: E_NOINTERFACE
;
675 ERR("interface %s not implemented\n", debugstr_guid(riid
));
677 return E_NOINTERFACE
;
680 IMXWriter_AddRef(iface
);
684 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
686 mxwriter
*This
= impl_from_IMXWriter( iface
);
687 LONG ref
= InterlockedIncrement(&This
->ref
);
689 TRACE("(%p)->(%d)\n", This
, ref
);
694 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
696 mxwriter
*This
= impl_from_IMXWriter( iface
);
697 ULONG ref
= InterlockedDecrement(&This
->ref
);
699 TRACE("(%p)->(%d)\n", This
, ref
);
703 /* Windows flushes the buffer when the interface is destroyed. */
704 flush_output_buffer(This
);
705 free_output_buffer(This
->buffer
);
707 if (This
->dest
) IStream_Release(This
->dest
);
708 SysFreeString(This
->version
);
709 SysFreeString(This
->encoding
);
711 SysFreeString(This
->element
);
712 release_dispex(&This
->dispex
);
719 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
721 mxwriter
*This
= impl_from_IMXWriter( iface
);
722 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
725 static HRESULT WINAPI
mxwriter_GetTypeInfo(
727 UINT iTInfo
, LCID lcid
,
728 ITypeInfo
** ppTInfo
)
730 mxwriter
*This
= impl_from_IMXWriter( iface
);
731 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
732 iTInfo
, lcid
, ppTInfo
);
735 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
737 REFIID riid
, LPOLESTR
* rgszNames
,
738 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
740 mxwriter
*This
= impl_from_IMXWriter( iface
);
741 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
742 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
745 static HRESULT WINAPI
mxwriter_Invoke(
747 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
748 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
749 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
751 mxwriter
*This
= impl_from_IMXWriter( iface
);
752 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
753 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
756 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
758 mxwriter
*This
= impl_from_IMXWriter( iface
);
761 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
763 hr
= flush_output_buffer(This
);
771 if (This
->dest
) IStream_Release(This
->dest
);
773 reset_output_buffer(This
);
780 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
783 /* Recreate the output buffer to make sure it's using the correct encoding. */
784 reset_output_buffer(This
);
786 if (This
->dest
) IStream_Release(This
->dest
);
791 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
795 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
802 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
804 mxwriter
*This
= impl_from_IMXWriter( iface
);
806 TRACE("(%p)->(%p)\n", This
, dest
);
808 if (!dest
) return E_POINTER
;
812 HRESULT hr
= flush_output_buffer(This
);
816 V_VT(dest
) = VT_BSTR
;
817 V_BSTR(dest
) = SysAllocString((WCHAR
*)This
->buffer
->utf16
.data
);
822 /* we only support IStream output so far */
823 V_VT(dest
) = VT_UNKNOWN
;
824 V_UNKNOWN(dest
) = (IUnknown
*)This
->dest
;
825 IStream_AddRef(This
->dest
);
830 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
832 mxwriter
*This
= impl_from_IMXWriter( iface
);
836 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
838 enc
= parse_encoding_name(encoding
);
839 if (enc
== XmlEncoding_Unknown
)
841 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
845 hr
= flush_output_buffer(This
);
849 SysReAllocString(&This
->encoding
, encoding
);
852 TRACE("got encoding %d\n", This
->xml_enc
);
853 reset_output_buffer(This
);
857 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
859 mxwriter
*This
= impl_from_IMXWriter( iface
);
861 TRACE("(%p)->(%p)\n", This
, encoding
);
863 if (!encoding
) return E_POINTER
;
865 *encoding
= SysAllocString(This
->encoding
);
866 if (!*encoding
) return E_OUTOFMEMORY
;
871 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
873 mxwriter
*This
= impl_from_IMXWriter( iface
);
875 TRACE("(%p)->(%d)\n", This
, value
);
876 return writer_set_property(This
, MXWriter_BOM
, value
);
879 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
881 mxwriter
*This
= impl_from_IMXWriter( iface
);
883 TRACE("(%p)->(%p)\n", This
, value
);
884 return writer_get_property(This
, MXWriter_BOM
, value
);
887 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
889 mxwriter
*This
= impl_from_IMXWriter( iface
);
891 TRACE("(%p)->(%d)\n", This
, value
);
892 return writer_set_property(This
, MXWriter_Indent
, value
);
895 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
897 mxwriter
*This
= impl_from_IMXWriter( iface
);
899 TRACE("(%p)->(%p)\n", This
, value
);
900 return writer_get_property(This
, MXWriter_Indent
, value
);
903 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
905 mxwriter
*This
= impl_from_IMXWriter( iface
);
907 TRACE("(%p)->(%d)\n", This
, value
);
908 return writer_set_property(This
, MXWriter_Standalone
, value
);
911 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
913 mxwriter
*This
= impl_from_IMXWriter( iface
);
915 TRACE("(%p)->(%p)\n", This
, value
);
916 return writer_get_property(This
, MXWriter_Standalone
, value
);
919 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
921 mxwriter
*This
= impl_from_IMXWriter( iface
);
923 TRACE("(%p)->(%d)\n", This
, value
);
924 return writer_set_property(This
, MXWriter_OmitXmlDecl
, value
);
927 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
929 mxwriter
*This
= impl_from_IMXWriter( iface
);
931 TRACE("(%p)->(%p)\n", This
, value
);
932 return writer_get_property(This
, MXWriter_OmitXmlDecl
, value
);
935 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
937 mxwriter
*This
= impl_from_IMXWriter( iface
);
939 TRACE("(%p)->(%s)\n", This
, debugstr_w(version
));
941 if (!version
) return E_INVALIDARG
;
943 SysFreeString(This
->version
);
944 This
->version
= SysAllocString(version
);
949 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
951 mxwriter
*This
= impl_from_IMXWriter( iface
);
953 TRACE("(%p)->(%p)\n", This
, version
);
955 if (!version
) return E_POINTER
;
957 return return_bstr(This
->version
, version
);
960 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
962 mxwriter
*This
= impl_from_IMXWriter( iface
);
964 TRACE("(%p)->(%d)\n", This
, value
);
965 return writer_set_property(This
, MXWriter_DisableEscaping
, value
);
968 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
970 mxwriter
*This
= impl_from_IMXWriter( iface
);
972 TRACE("(%p)->(%p)\n", This
, value
);
973 return writer_get_property(This
, MXWriter_DisableEscaping
, value
);
976 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
978 mxwriter
*This
= impl_from_IMXWriter( iface
);
979 TRACE("(%p)\n", This
);
980 return flush_output_buffer(This
);
983 static const struct IMXWriterVtbl MXWriterVtbl
=
985 mxwriter_QueryInterface
,
988 mxwriter_GetTypeInfoCount
,
989 mxwriter_GetTypeInfo
,
990 mxwriter_GetIDsOfNames
,
994 mxwriter_put_encoding
,
995 mxwriter_get_encoding
,
996 mxwriter_put_byteOrderMark
,
997 mxwriter_get_byteOrderMark
,
1000 mxwriter_put_standalone
,
1001 mxwriter_get_standalone
,
1002 mxwriter_put_omitXMLDeclaration
,
1003 mxwriter_get_omitXMLDeclaration
,
1004 mxwriter_put_version
,
1005 mxwriter_get_version
,
1006 mxwriter_put_disableOutputEscaping
,
1007 mxwriter_get_disableOutputEscaping
,
1011 /*** ISAXContentHandler ***/
1012 static HRESULT WINAPI
SAXContentHandler_QueryInterface(
1013 ISAXContentHandler
*iface
,
1017 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1018 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1021 static ULONG WINAPI
SAXContentHandler_AddRef(ISAXContentHandler
*iface
)
1023 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1024 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1027 static ULONG WINAPI
SAXContentHandler_Release(ISAXContentHandler
*iface
)
1029 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1030 return IMXWriter_Release(&This
->IMXWriter_iface
);
1033 static HRESULT WINAPI
SAXContentHandler_putDocumentLocator(
1034 ISAXContentHandler
*iface
,
1035 ISAXLocator
*locator
)
1037 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1038 FIXME("(%p)->(%p)\n", This
, locator
);
1042 static HRESULT WINAPI
SAXContentHandler_startDocument(ISAXContentHandler
*iface
)
1044 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1046 TRACE("(%p)\n", This
);
1048 /* If properties have been changed since the last "endDocument" call
1049 * we need to reset the output buffer. If we don't the output buffer
1050 * could end up with multiple XML documents in it, plus this seems to
1051 * be how Windows works.
1053 if (This
->prop_changed
) {
1054 reset_output_buffer(This
);
1055 This
->prop_changed
= FALSE
;
1058 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
1060 write_prolog_buffer(This
);
1062 if (This
->dest
&& This
->xml_enc
== XmlEncoding_UTF16
) {
1063 static const char utf16BOM
[] = {0xff,0xfe};
1065 if (This
->props
[MXWriter_BOM
] == VARIANT_TRUE
)
1066 /* Windows passes a NULL pointer as the pcbWritten parameter and
1067 * ignores any error codes returned from this Write call.
1069 IStream_Write(This
->dest
, utf16BOM
, sizeof(utf16BOM
), NULL
);
1075 static HRESULT WINAPI
SAXContentHandler_endDocument(ISAXContentHandler
*iface
)
1077 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1078 TRACE("(%p)\n", This
);
1079 This
->prop_changed
= FALSE
;
1080 return flush_output_buffer(This
);
1083 static HRESULT WINAPI
SAXContentHandler_startPrefixMapping(
1084 ISAXContentHandler
*iface
,
1085 const WCHAR
*prefix
,
1090 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1091 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
1095 static HRESULT WINAPI
SAXContentHandler_endPrefixMapping(
1096 ISAXContentHandler
*iface
,
1097 const WCHAR
*prefix
,
1100 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1101 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
1105 static HRESULT WINAPI
SAXContentHandler_startElement(
1106 ISAXContentHandler
*iface
,
1107 const WCHAR
*namespaceUri
,
1109 const WCHAR
*local_name
,
1113 ISAXAttributes
*attr
)
1115 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1116 static const WCHAR ltW
[] = {'<'};
1118 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
1119 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
1121 if (((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
) ||
1122 (nQName
== -1 && This
->class_version
== MSXML6
))
1123 return E_INVALIDARG
;
1125 close_element_starttag(This
);
1126 set_element_name(This
, QName
? QName
: emptyW
,
1127 QName
? nQName
: 0);
1129 write_node_indent(This
);
1131 write_output_buffer(This
->buffer
, ltW
, 1);
1132 write_output_buffer(This
->buffer
, QName
, nQName
);
1133 writer_inc_indent(This
);
1137 int length
, i
, escape
;
1140 hr
= ISAXAttributes_getLength(attr
, &length
);
1141 if (FAILED(hr
)) return hr
;
1143 escape
= This
->props
[MXWriter_DisableEscaping
] == VARIANT_FALSE
||
1144 (This
->class_version
== MSXML4
|| This
->class_version
== MSXML6
);
1146 for (i
= 0; i
< length
; i
++)
1148 static const WCHAR eqW
[] = {'='};
1152 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
1153 if (FAILED(hr
)) return hr
;
1155 /* space separator in front of every attribute */
1156 write_output_buffer(This
->buffer
, spaceW
, 1);
1157 write_output_buffer(This
->buffer
, str
, len
);
1159 write_output_buffer(This
->buffer
, eqW
, 1);
1162 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
1163 if (FAILED(hr
)) return hr
;
1167 WCHAR
*escaped
= get_escaped_string(str
, EscapeValue
, &len
);
1168 write_output_buffer_quoted(This
->buffer
, escaped
, len
);
1172 write_output_buffer_quoted(This
->buffer
, str
, len
);
1179 static HRESULT WINAPI
SAXContentHandler_endElement(
1180 ISAXContentHandler
*iface
,
1181 const WCHAR
*namespaceUri
,
1183 const WCHAR
* local_name
,
1188 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1190 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
), nnamespaceUri
,
1191 debugstr_wn(local_name
, nlocal_name
), nlocal_name
, debugstr_wn(QName
, nQName
), nQName
);
1193 if (((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
) ||
1194 (nQName
== -1 && This
->class_version
== MSXML6
))
1195 return E_INVALIDARG
;
1197 writer_dec_indent(This
);
1201 static const WCHAR closeW
[] = {'/','>'};
1202 write_output_buffer(This
->buffer
, closeW
, 2);
1206 static const WCHAR closetagW
[] = {'<','/'};
1207 static const WCHAR gtW
[] = {'>'};
1209 write_node_indent(This
);
1210 write_output_buffer(This
->buffer
, closetagW
, 2);
1211 write_output_buffer(This
->buffer
, QName
, nQName
);
1212 write_output_buffer(This
->buffer
, gtW
, 1);
1215 set_element_name(This
, NULL
, 0);
1220 static HRESULT WINAPI
SAXContentHandler_characters(
1221 ISAXContentHandler
*iface
,
1225 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1227 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
1229 if (!chars
) return E_INVALIDARG
;
1231 close_element_starttag(This
);
1232 set_element_name(This
, NULL
, 0);
1239 if (This
->cdata
|| This
->props
[MXWriter_DisableEscaping
] == VARIANT_TRUE
)
1240 write_output_buffer(This
->buffer
, chars
, nchars
);
1246 escaped
= get_escaped_string(chars
, EscapeText
, &len
);
1247 write_output_buffer(This
->buffer
, escaped
, len
);
1255 static HRESULT WINAPI
SAXContentHandler_ignorableWhitespace(
1256 ISAXContentHandler
*iface
,
1260 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1262 TRACE("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
1264 if (!chars
) return E_INVALIDARG
;
1266 write_output_buffer(This
->buffer
, chars
, nchars
);
1271 static HRESULT WINAPI
SAXContentHandler_processingInstruction(
1272 ISAXContentHandler
*iface
,
1273 const WCHAR
*target
,
1278 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1279 static const WCHAR openpiW
[] = {'<','?'};
1280 static const WCHAR closepiW
[] = {'?','>','\r','\n'};
1282 TRACE("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
1284 if (!target
) return E_INVALIDARG
;
1286 write_node_indent(This
);
1287 write_output_buffer(This
->buffer
, openpiW
, sizeof(openpiW
)/sizeof(WCHAR
));
1290 write_output_buffer(This
->buffer
, target
, ntarget
);
1292 if (data
&& *data
&& ndata
)
1294 write_output_buffer(This
->buffer
, spaceW
, 1);
1295 write_output_buffer(This
->buffer
, data
, ndata
);
1298 write_output_buffer(This
->buffer
, closepiW
, sizeof(closepiW
)/sizeof(WCHAR
));
1299 This
->newline
= TRUE
;
1304 static HRESULT WINAPI
SAXContentHandler_skippedEntity(
1305 ISAXContentHandler
*iface
,
1309 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1310 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
1314 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl
=
1316 SAXContentHandler_QueryInterface
,
1317 SAXContentHandler_AddRef
,
1318 SAXContentHandler_Release
,
1319 SAXContentHandler_putDocumentLocator
,
1320 SAXContentHandler_startDocument
,
1321 SAXContentHandler_endDocument
,
1322 SAXContentHandler_startPrefixMapping
,
1323 SAXContentHandler_endPrefixMapping
,
1324 SAXContentHandler_startElement
,
1325 SAXContentHandler_endElement
,
1326 SAXContentHandler_characters
,
1327 SAXContentHandler_ignorableWhitespace
,
1328 SAXContentHandler_processingInstruction
,
1329 SAXContentHandler_skippedEntity
1332 /*** ISAXLexicalHandler ***/
1333 static HRESULT WINAPI
SAXLexicalHandler_QueryInterface(ISAXLexicalHandler
*iface
,
1334 REFIID riid
, void **obj
)
1336 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1337 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1340 static ULONG WINAPI
SAXLexicalHandler_AddRef(ISAXLexicalHandler
*iface
)
1342 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1343 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1346 static ULONG WINAPI
SAXLexicalHandler_Release(ISAXLexicalHandler
*iface
)
1348 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1349 return IMXWriter_Release(&This
->IMXWriter_iface
);
1352 static HRESULT WINAPI
SAXLexicalHandler_startDTD(ISAXLexicalHandler
*iface
,
1353 const WCHAR
*name
, int name_len
, const WCHAR
*publicId
, int publicId_len
,
1354 const WCHAR
*systemId
, int systemId_len
)
1356 static const WCHAR doctypeW
[] = {'<','!','D','O','C','T','Y','P','E',' '};
1357 static const WCHAR openintW
[] = {'[','\r','\n'};
1359 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1361 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_wn(name
, name_len
), debugstr_wn(publicId
, publicId_len
),
1362 debugstr_wn(systemId
, systemId_len
));
1364 if (!name
) return E_INVALIDARG
;
1366 write_output_buffer(This
->buffer
, doctypeW
, sizeof(doctypeW
)/sizeof(WCHAR
));
1370 write_output_buffer(This
->buffer
, name
, name_len
);
1371 write_output_buffer(This
->buffer
, spaceW
, 1);
1376 static const WCHAR publicW
[] = {'P','U','B','L','I','C',' '};
1378 write_output_buffer(This
->buffer
, publicW
, sizeof(publicW
)/sizeof(WCHAR
));
1379 write_output_buffer_quoted(This
->buffer
, publicId
, publicId_len
);
1381 if (!systemId
) return E_INVALIDARG
;
1384 write_output_buffer(This
->buffer
, spaceW
, 1);
1386 write_output_buffer_quoted(This
->buffer
, systemId
, systemId_len
);
1389 write_output_buffer(This
->buffer
, spaceW
, 1);
1393 static const WCHAR systemW
[] = {'S','Y','S','T','E','M',' '};
1395 write_output_buffer(This
->buffer
, systemW
, sizeof(systemW
)/sizeof(WCHAR
));
1396 write_output_buffer_quoted(This
->buffer
, systemId
, systemId_len
);
1398 write_output_buffer(This
->buffer
, spaceW
, 1);
1401 write_output_buffer(This
->buffer
, openintW
, sizeof(openintW
)/sizeof(WCHAR
));
1406 static HRESULT WINAPI
SAXLexicalHandler_endDTD(ISAXLexicalHandler
*iface
)
1408 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1409 static const WCHAR closedtdW
[] = {']','>','\r','\n'};
1411 TRACE("(%p)\n", This
);
1413 write_output_buffer(This
->buffer
, closedtdW
, sizeof(closedtdW
)/sizeof(WCHAR
));
1418 static HRESULT WINAPI
SAXLexicalHandler_startEntity(ISAXLexicalHandler
*iface
, const WCHAR
*name
, int len
)
1420 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1421 FIXME("(%p)->(%s): stub\n", This
, debugstr_wn(name
, len
));
1425 static HRESULT WINAPI
SAXLexicalHandler_endEntity(ISAXLexicalHandler
*iface
, const WCHAR
*name
, int len
)
1427 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1428 FIXME("(%p)->(%s): stub\n", This
, debugstr_wn(name
, len
));
1432 static HRESULT WINAPI
SAXLexicalHandler_startCDATA(ISAXLexicalHandler
*iface
)
1434 static const WCHAR scdataW
[] = {'<','!','[','C','D','A','T','A','['};
1435 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1437 TRACE("(%p)\n", This
);
1439 write_node_indent(This
);
1440 write_output_buffer(This
->buffer
, scdataW
, sizeof(scdataW
)/sizeof(WCHAR
));
1446 static HRESULT WINAPI
SAXLexicalHandler_endCDATA(ISAXLexicalHandler
*iface
)
1448 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1449 static const WCHAR ecdataW
[] = {']',']','>'};
1451 TRACE("(%p)\n", This
);
1453 write_output_buffer(This
->buffer
, ecdataW
, sizeof(ecdataW
)/sizeof(WCHAR
));
1454 This
->cdata
= FALSE
;
1459 static HRESULT WINAPI
SAXLexicalHandler_comment(ISAXLexicalHandler
*iface
, const WCHAR
*chars
, int nchars
)
1461 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1462 static const WCHAR copenW
[] = {'<','!','-','-'};
1463 static const WCHAR ccloseW
[] = {'-','-','>','\r','\n'};
1465 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
1467 if (!chars
) return E_INVALIDARG
;
1469 close_element_starttag(This
);
1470 write_node_indent(This
);
1472 write_output_buffer(This
->buffer
, copenW
, sizeof(copenW
)/sizeof(WCHAR
));
1474 write_output_buffer(This
->buffer
, chars
, nchars
);
1475 write_output_buffer(This
->buffer
, ccloseW
, sizeof(ccloseW
)/sizeof(WCHAR
));
1480 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1482 SAXLexicalHandler_QueryInterface
,
1483 SAXLexicalHandler_AddRef
,
1484 SAXLexicalHandler_Release
,
1485 SAXLexicalHandler_startDTD
,
1486 SAXLexicalHandler_endDTD
,
1487 SAXLexicalHandler_startEntity
,
1488 SAXLexicalHandler_endEntity
,
1489 SAXLexicalHandler_startCDATA
,
1490 SAXLexicalHandler_endCDATA
,
1491 SAXLexicalHandler_comment
1494 /*** ISAXDeclHandler ***/
1495 static HRESULT WINAPI
SAXDeclHandler_QueryInterface(ISAXDeclHandler
*iface
,
1496 REFIID riid
, void **obj
)
1498 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1499 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1502 static ULONG WINAPI
SAXDeclHandler_AddRef(ISAXDeclHandler
*iface
)
1504 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1505 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1508 static ULONG WINAPI
SAXDeclHandler_Release(ISAXDeclHandler
*iface
)
1510 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1511 return IMXWriter_Release(&This
->IMXWriter_iface
);
1514 static HRESULT WINAPI
SAXDeclHandler_elementDecl(ISAXDeclHandler
*iface
,
1515 const WCHAR
*name
, int n_name
, const WCHAR
*model
, int n_model
)
1517 static const WCHAR elementW
[] = {'<','!','E','L','E','M','E','N','T',' '};
1518 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1520 TRACE("(%p)->(%s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1521 debugstr_wn(model
, n_model
), n_model
);
1523 if (!name
|| !model
) return E_INVALIDARG
;
1525 write_output_buffer(This
->buffer
, elementW
, sizeof(elementW
)/sizeof(WCHAR
));
1527 write_output_buffer(This
->buffer
, name
, n_name
);
1528 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1531 write_output_buffer(This
->buffer
, model
, n_model
);
1532 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1537 static HRESULT WINAPI
SAXDeclHandler_attributeDecl(ISAXDeclHandler
*iface
,
1538 const WCHAR
*element
, int n_element
, const WCHAR
*attr
, int n_attr
,
1539 const WCHAR
*type
, int n_type
, const WCHAR
*Default
, int n_default
,
1540 const WCHAR
*value
, int n_value
)
1542 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1543 static const WCHAR attlistW
[] = {'<','!','A','T','T','L','I','S','T',' '};
1544 static const WCHAR closetagW
[] = {'>','\r','\n'};
1546 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This
, debugstr_wn(element
, n_element
), n_element
,
1547 debugstr_wn(attr
, n_attr
), n_attr
, debugstr_wn(type
, n_type
), n_type
, debugstr_wn(Default
, n_default
), n_default
,
1548 debugstr_wn(value
, n_value
), n_value
);
1550 write_output_buffer(This
->buffer
, attlistW
, sizeof(attlistW
)/sizeof(WCHAR
));
1552 write_output_buffer(This
->buffer
, element
, n_element
);
1553 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1557 write_output_buffer(This
->buffer
, attr
, n_attr
);
1558 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1562 write_output_buffer(This
->buffer
, type
, n_type
);
1563 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1567 write_output_buffer(This
->buffer
, Default
, n_default
);
1568 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1572 write_output_buffer_quoted(This
->buffer
, value
, n_value
);
1574 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1579 static HRESULT WINAPI
SAXDeclHandler_internalEntityDecl(ISAXDeclHandler
*iface
,
1580 const WCHAR
*name
, int n_name
, const WCHAR
*value
, int n_value
)
1582 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1584 TRACE("(%p)->(%s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1585 debugstr_wn(value
, n_value
), n_value
);
1587 if (!name
|| !value
) return E_INVALIDARG
;
1589 write_output_buffer(This
->buffer
, entityW
, sizeof(entityW
)/sizeof(WCHAR
));
1591 write_output_buffer(This
->buffer
, name
, n_name
);
1592 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1596 write_output_buffer_quoted(This
->buffer
, value
, n_value
);
1598 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1603 static HRESULT WINAPI
SAXDeclHandler_externalEntityDecl(ISAXDeclHandler
*iface
,
1604 const WCHAR
*name
, int n_name
, const WCHAR
*publicId
, int n_publicId
,
1605 const WCHAR
*systemId
, int n_systemId
)
1607 static const WCHAR publicW
[] = {'P','U','B','L','I','C',' '};
1608 static const WCHAR systemW
[] = {'S','Y','S','T','E','M',' '};
1609 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1611 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1612 debugstr_wn(publicId
, n_publicId
), n_publicId
, debugstr_wn(systemId
, n_systemId
), n_systemId
);
1614 if (!name
) return E_INVALIDARG
;
1615 if (publicId
&& !systemId
) return E_INVALIDARG
;
1616 if (!publicId
&& !systemId
) return E_INVALIDARG
;
1618 write_output_buffer(This
->buffer
, entityW
, sizeof(entityW
)/sizeof(WCHAR
));
1620 write_output_buffer(This
->buffer
, name
, n_name
);
1621 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1626 write_output_buffer(This
->buffer
, publicW
, sizeof(publicW
)/sizeof(WCHAR
));
1627 write_output_buffer_quoted(This
->buffer
, publicId
, n_publicId
);
1628 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1629 write_output_buffer_quoted(This
->buffer
, systemId
, n_systemId
);
1633 write_output_buffer(This
->buffer
, systemW
, sizeof(systemW
)/sizeof(WCHAR
));
1634 write_output_buffer_quoted(This
->buffer
, systemId
, n_systemId
);
1637 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1642 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
= {
1643 SAXDeclHandler_QueryInterface
,
1644 SAXDeclHandler_AddRef
,
1645 SAXDeclHandler_Release
,
1646 SAXDeclHandler_elementDecl
,
1647 SAXDeclHandler_attributeDecl
,
1648 SAXDeclHandler_internalEntityDecl
,
1649 SAXDeclHandler_externalEntityDecl
1652 static const tid_t mxwriter_iface_tids
[] = {
1657 static dispex_static_data_t mxwriter_dispex
= {
1664 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*outer
, void **ppObj
)
1666 static const WCHAR version10W
[] = {'1','.','0',0};
1670 TRACE("(%p, %p)\n", outer
, ppObj
);
1672 if (outer
) FIXME("support aggregation, outer\n");
1674 This
= heap_alloc( sizeof (*This
) );
1676 return E_OUTOFMEMORY
;
1678 This
->IMXWriter_iface
.lpVtbl
= &MXWriterVtbl
;
1679 This
->ISAXContentHandler_iface
.lpVtbl
= &SAXContentHandlerVtbl
;
1680 This
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1681 This
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1683 This
->class_version
= version
;
1685 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
1686 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
1687 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
1688 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
1689 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
1690 This
->prop_changed
= FALSE
;
1691 This
->encoding
= SysAllocString(utf16W
);
1692 This
->version
= SysAllocString(version10W
);
1693 This
->xml_enc
= XmlEncoding_UTF16
;
1695 This
->element
= NULL
;
1696 This
->cdata
= FALSE
;
1699 This
->newline
= FALSE
;
1702 This
->dest_written
= 0;
1704 hr
= alloc_output_buffer(This
->xml_enc
, &This
->buffer
);
1706 SysFreeString(This
->encoding
);
1707 SysFreeString(This
->version
);
1712 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IMXWriter_iface
, &mxwriter_dispex
);
1714 *ppObj
= &This
->IMXWriter_iface
;
1716 TRACE("returning iface %p\n", *ppObj
);
1721 static HRESULT WINAPI
MXAttributes_QueryInterface(IMXAttributes
*iface
, REFIID riid
, void **ppObj
)
1723 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1725 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppObj
);
1729 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
1730 IsEqualGUID( riid
, &IID_IDispatch
) ||
1731 IsEqualGUID( riid
, &IID_IMXAttributes
))
1735 else if ( IsEqualGUID( riid
, &IID_ISAXAttributes
))
1737 *ppObj
= &This
->ISAXAttributes_iface
;
1739 else if ( IsEqualGUID( riid
, &IID_IVBSAXAttributes
))
1741 *ppObj
= &This
->IVBSAXAttributes_iface
;
1743 else if (dispex_query_interface(&This
->dispex
, riid
, ppObj
))
1745 return *ppObj
? S_OK
: E_NOINTERFACE
;
1749 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1750 return E_NOINTERFACE
;
1753 IMXAttributes_AddRef( iface
);
1758 static ULONG WINAPI
MXAttributes_AddRef(IMXAttributes
*iface
)
1760 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1761 ULONG ref
= InterlockedIncrement( &This
->ref
);
1762 TRACE("(%p)->(%d)\n", This
, ref
);
1766 static ULONG WINAPI
MXAttributes_Release(IMXAttributes
*iface
)
1768 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1769 LONG ref
= InterlockedDecrement( &This
->ref
);
1771 TRACE("(%p)->(%d)\n", This
, ref
);
1777 for (i
= 0; i
< This
->length
; i
++)
1779 SysFreeString(This
->attr
[i
].qname
);
1780 SysFreeString(This
->attr
[i
].local
);
1781 SysFreeString(This
->attr
[i
].uri
);
1782 SysFreeString(This
->attr
[i
].type
);
1783 SysFreeString(This
->attr
[i
].value
);
1786 release_dispex(&This
->dispex
);
1787 heap_free(This
->attr
);
1794 static HRESULT WINAPI
MXAttributes_GetTypeInfoCount(IMXAttributes
*iface
, UINT
* pctinfo
)
1796 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1797 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1800 static HRESULT WINAPI
MXAttributes_GetTypeInfo(IMXAttributes
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
1802 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1803 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1806 static HRESULT WINAPI
MXAttributes_GetIDsOfNames(
1807 IMXAttributes
*iface
,
1809 LPOLESTR
* rgszNames
,
1814 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1815 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
1816 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1819 static HRESULT WINAPI
MXAttributes_Invoke(
1820 IMXAttributes
*iface
,
1821 DISPID dispIdMember
,
1825 DISPPARAMS
* pDispParams
,
1826 VARIANT
* pVarResult
,
1827 EXCEPINFO
* pExcepInfo
,
1830 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1831 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
1832 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1835 static HRESULT WINAPI
MXAttributes_addAttribute(IMXAttributes
*iface
,
1836 BSTR uri
, BSTR localName
, BSTR QName
, BSTR type
, BSTR value
)
1838 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1842 TRACE("(%p)->(%s %s %s %s %s)\n", This
, debugstr_w(uri
), debugstr_w(localName
),
1843 debugstr_w(QName
), debugstr_w(type
), debugstr_w(value
));
1845 if ((!uri
|| !localName
|| !QName
|| !type
|| !value
) && This
->class_version
!= MSXML6
)
1846 return E_INVALIDARG
;
1848 /* ensure array is large enough */
1849 hr
= mxattributes_grow(This
);
1850 if (hr
!= S_OK
) return hr
;
1852 attr
= &This
->attr
[This
->length
];
1854 attr
->qname
= SysAllocString(QName
);
1855 attr
->local
= SysAllocString(localName
);
1856 attr
->uri
= SysAllocString(uri
);
1857 attr
->type
= SysAllocString(type
? type
: emptyW
);
1858 attr
->value
= SysAllocString(value
);
1864 static HRESULT WINAPI
MXAttributes_addAttributeFromIndex(IMXAttributes
*iface
,
1865 VARIANT atts
, int index
)
1867 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1868 FIXME("(%p)->(%s %d): stub\n", This
, debugstr_variant(&atts
), index
);
1872 static HRESULT WINAPI
MXAttributes_clear(IMXAttributes
*iface
)
1874 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1877 TRACE("(%p)\n", This
);
1879 for (i
= 0; i
< This
->length
; i
++)
1881 SysFreeString(This
->attr
[i
].qname
);
1882 SysFreeString(This
->attr
[i
].local
);
1883 SysFreeString(This
->attr
[i
].uri
);
1884 SysFreeString(This
->attr
[i
].type
);
1885 SysFreeString(This
->attr
[i
].value
);
1886 memset(&This
->attr
[i
], 0, sizeof(mxattribute
));
1894 static mxattribute
*get_attribute_byindex(mxattributes
*attrs
, int index
)
1896 if (index
< 0 || index
>= attrs
->length
) return NULL
;
1897 return &attrs
->attr
[index
];
1900 static HRESULT WINAPI
MXAttributes_removeAttribute(IMXAttributes
*iface
, int index
)
1902 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1905 TRACE("(%p)->(%d)\n", This
, index
);
1907 if (!(dst
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1909 /* no need to remove last attribute, just make it inaccessible */
1910 if (index
+ 1 == This
->length
)
1916 memmove(dst
, dst
+ 1, (This
->length
-index
-1)*sizeof(*dst
));
1922 static HRESULT WINAPI
MXAttributes_setAttribute(IMXAttributes
*iface
, int index
,
1923 BSTR uri
, BSTR localName
, BSTR QName
, BSTR type
, BSTR value
)
1925 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1926 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This
, index
, debugstr_w(uri
),
1927 debugstr_w(localName
), debugstr_w(QName
), debugstr_w(type
), debugstr_w(value
));
1931 static HRESULT WINAPI
MXAttributes_setAttributes(IMXAttributes
*iface
, VARIANT atts
)
1933 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1934 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&atts
));
1938 static HRESULT WINAPI
MXAttributes_setLocalName(IMXAttributes
*iface
, int index
,
1941 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1944 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(localName
));
1946 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1948 SysFreeString(attr
->local
);
1949 attr
->local
= SysAllocString(localName
);
1954 static HRESULT WINAPI
MXAttributes_setQName(IMXAttributes
*iface
, int index
, BSTR QName
)
1956 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1959 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(QName
));
1961 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1963 SysFreeString(attr
->qname
);
1964 attr
->qname
= SysAllocString(QName
);
1969 static HRESULT WINAPI
MXAttributes_setURI(IMXAttributes
*iface
, int index
, BSTR uri
)
1971 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1974 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(uri
));
1976 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1978 SysFreeString(attr
->uri
);
1979 attr
->uri
= SysAllocString(uri
);
1984 static HRESULT WINAPI
MXAttributes_setValue(IMXAttributes
*iface
, int index
, BSTR value
)
1986 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1989 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(value
));
1991 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1993 SysFreeString(attr
->value
);
1994 attr
->value
= SysAllocString(value
);
1999 static const IMXAttributesVtbl MXAttributesVtbl
= {
2000 MXAttributes_QueryInterface
,
2001 MXAttributes_AddRef
,
2002 MXAttributes_Release
,
2003 MXAttributes_GetTypeInfoCount
,
2004 MXAttributes_GetTypeInfo
,
2005 MXAttributes_GetIDsOfNames
,
2006 MXAttributes_Invoke
,
2007 MXAttributes_addAttribute
,
2008 MXAttributes_addAttributeFromIndex
,
2010 MXAttributes_removeAttribute
,
2011 MXAttributes_setAttribute
,
2012 MXAttributes_setAttributes
,
2013 MXAttributes_setLocalName
,
2014 MXAttributes_setQName
,
2015 MXAttributes_setURI
,
2016 MXAttributes_setValue
2019 static HRESULT WINAPI
SAXAttributes_QueryInterface(ISAXAttributes
*iface
, REFIID riid
, void **ppObj
)
2021 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2022 return IMXAttributes_QueryInterface(&This
->IMXAttributes_iface
, riid
, ppObj
);
2025 static ULONG WINAPI
SAXAttributes_AddRef(ISAXAttributes
*iface
)
2027 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2028 return IMXAttributes_AddRef(&This
->IMXAttributes_iface
);
2031 static ULONG WINAPI
SAXAttributes_Release(ISAXAttributes
*iface
)
2033 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2034 return IMXAttributes_Release(&This
->IMXAttributes_iface
);
2037 static HRESULT WINAPI
SAXAttributes_getLength(ISAXAttributes
*iface
, int *length
)
2039 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2040 TRACE("(%p)->(%p)\n", This
, length
);
2042 if (!length
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2045 *length
= This
->length
;
2050 static HRESULT WINAPI
SAXAttributes_getURI(ISAXAttributes
*iface
, int index
, const WCHAR
**uri
,
2053 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2055 TRACE("(%p)->(%d %p %p)\n", This
, index
, uri
, len
);
2057 if (index
>= This
->length
|| index
< 0) return E_INVALIDARG
;
2058 if (!uri
|| !len
) return E_POINTER
;
2060 *len
= SysStringLen(This
->attr
[index
].uri
);
2061 *uri
= This
->attr
[index
].uri
;
2066 static HRESULT WINAPI
SAXAttributes_getLocalName(ISAXAttributes
*iface
, int index
, const WCHAR
**name
,
2069 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2071 TRACE("(%p)->(%d %p %p)\n", This
, index
, name
, len
);
2073 if (index
>= This
->length
|| index
< 0) return E_INVALIDARG
;
2074 if (!name
|| !len
) return E_POINTER
;
2076 *len
= SysStringLen(This
->attr
[index
].local
);
2077 *name
= This
->attr
[index
].local
;
2082 static HRESULT WINAPI
SAXAttributes_getQName(ISAXAttributes
*iface
, int index
, const WCHAR
**qname
, int *length
)
2084 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2086 TRACE("(%p)->(%d %p %p)\n", This
, index
, qname
, length
);
2088 if (index
>= This
->length
) return E_INVALIDARG
;
2089 if (!qname
|| !length
) return E_POINTER
;
2091 *qname
= This
->attr
[index
].qname
;
2092 *length
= SysStringLen(This
->attr
[index
].qname
);
2097 static HRESULT WINAPI
SAXAttributes_getName(ISAXAttributes
*iface
, int index
, const WCHAR
**uri
, int *uri_len
,
2098 const WCHAR
**local
, int *local_len
, const WCHAR
**qname
, int *qname_len
)
2100 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2102 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This
, index
, uri
, uri_len
, local
, local_len
, qname
, qname_len
);
2104 if (index
>= This
->length
|| index
< 0)
2105 return E_INVALIDARG
;
2107 if (!uri
|| !uri_len
|| !local
|| !local_len
|| !qname
|| !qname_len
)
2110 *uri_len
= SysStringLen(This
->attr
[index
].uri
);
2111 *uri
= This
->attr
[index
].uri
;
2113 *local_len
= SysStringLen(This
->attr
[index
].local
);
2114 *local
= This
->attr
[index
].local
;
2116 *qname_len
= SysStringLen(This
->attr
[index
].qname
);
2117 *qname
= This
->attr
[index
].qname
;
2119 TRACE("(%s, %s, %s)\n", debugstr_w(*uri
), debugstr_w(*local
), debugstr_w(*qname
));
2124 static HRESULT WINAPI
SAXAttributes_getIndexFromName(ISAXAttributes
*iface
, const WCHAR
*uri
, int uri_len
,
2125 const WCHAR
*name
, int len
, int *index
)
2127 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2130 TRACE("(%p)->(%s:%d %s:%d %p)\n", This
, debugstr_wn(uri
, uri_len
), uri_len
,
2131 debugstr_wn(name
, len
), len
, index
);
2133 if (!index
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2136 if (!uri
|| !name
|| !index
) return E_INVALIDARG
;
2138 for (i
= 0; i
< This
->length
; i
++)
2140 if (uri_len
!= SysStringLen(This
->attr
[i
].uri
)) continue;
2141 if (strncmpW(uri
, This
->attr
[i
].uri
, uri_len
)) continue;
2143 if (len
!= SysStringLen(This
->attr
[i
].local
)) continue;
2144 if (strncmpW(name
, This
->attr
[i
].local
, len
)) continue;
2150 return E_INVALIDARG
;
2153 static HRESULT WINAPI
SAXAttributes_getIndexFromQName(ISAXAttributes
*iface
, const WCHAR
*qname
,
2154 int len
, int *index
)
2156 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2159 TRACE("(%p)->(%s:%d %p)\n", This
, debugstr_wn(qname
, len
), len
, index
);
2161 if (!index
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2164 if (!qname
|| !index
|| !len
) return E_INVALIDARG
;
2166 for (i
= 0; i
< This
->length
; i
++)
2168 if (len
!= SysStringLen(This
->attr
[i
].qname
)) continue;
2169 if (strncmpW(qname
, This
->attr
[i
].qname
, len
)) continue;
2175 return E_INVALIDARG
;
2178 static HRESULT WINAPI
SAXAttributes_getType(ISAXAttributes
*iface
, int index
, const WCHAR
**type
,
2181 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2183 TRACE("(%p)->(%d %p %p)\n", This
, index
, type
, len
);
2185 if (index
>= This
->length
) return E_INVALIDARG
;
2187 if ((!type
|| !len
) && (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2190 *type
= This
->attr
[index
].type
;
2191 *len
= SysStringLen(This
->attr
[index
].type
);
2196 static HRESULT WINAPI
SAXAttributes_getTypeFromName(ISAXAttributes
*iface
, const WCHAR
* pUri
, int nUri
,
2197 const WCHAR
* pLocalName
, int nLocalName
, const WCHAR
** pType
, int * nType
)
2199 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2200 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This
, debugstr_wn(pUri
, nUri
), nUri
,
2201 debugstr_wn(pLocalName
, nLocalName
), nLocalName
, pType
, nType
);
2205 static HRESULT WINAPI
SAXAttributes_getTypeFromQName(ISAXAttributes
*iface
, const WCHAR
* pQName
,
2206 int nQName
, const WCHAR
** pType
, int * nType
)
2208 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2209 FIXME("(%p)->(%s:%d %p %p): stub\n", This
, debugstr_wn(pQName
, nQName
), nQName
, pType
, nType
);
2213 static HRESULT WINAPI
SAXAttributes_getValue(ISAXAttributes
*iface
, int index
, const WCHAR
**value
,
2216 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2218 TRACE("(%p)->(%d %p %p)\n", This
, index
, value
, len
);
2220 if (index
>= This
->length
) return E_INVALIDARG
;
2222 if ((!value
|| !len
) && (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2225 *value
= This
->attr
[index
].value
;
2226 *len
= SysStringLen(This
->attr
[index
].value
);
2231 static HRESULT WINAPI
SAXAttributes_getValueFromName(ISAXAttributes
*iface
, const WCHAR
*uri
,
2232 int uri_len
, const WCHAR
*name
, int name_len
, const WCHAR
**value
, int *value_len
)
2234 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2238 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This
, debugstr_wn(uri
, uri_len
), uri_len
,
2239 debugstr_wn(name
, name_len
), name_len
, value
, value_len
);
2241 if (!uri
|| !name
|| !value
|| !value_len
)
2242 return (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
) ? E_POINTER
: E_INVALIDARG
;
2244 hr
= ISAXAttributes_getIndexFromName(iface
, uri
, uri_len
, name
, name_len
, &index
);
2246 hr
= ISAXAttributes_getValue(iface
, index
, value
, value_len
);
2251 static HRESULT WINAPI
SAXAttributes_getValueFromQName(ISAXAttributes
*iface
, const WCHAR
*qname
,
2252 int qname_len
, const WCHAR
**value
, int *value_len
)
2254 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2258 TRACE("(%p)->(%s:%d %p %p)\n", This
, debugstr_wn(qname
, qname_len
), qname_len
, value
, value_len
);
2260 if (!qname
|| !value
|| !value_len
)
2261 return (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
) ? E_POINTER
: E_INVALIDARG
;
2263 hr
= ISAXAttributes_getIndexFromQName(iface
, qname
, qname_len
, &index
);
2265 hr
= ISAXAttributes_getValue(iface
, index
, value
, value_len
);
2270 static const ISAXAttributesVtbl SAXAttributesVtbl
= {
2271 SAXAttributes_QueryInterface
,
2272 SAXAttributes_AddRef
,
2273 SAXAttributes_Release
,
2274 SAXAttributes_getLength
,
2275 SAXAttributes_getURI
,
2276 SAXAttributes_getLocalName
,
2277 SAXAttributes_getQName
,
2278 SAXAttributes_getName
,
2279 SAXAttributes_getIndexFromName
,
2280 SAXAttributes_getIndexFromQName
,
2281 SAXAttributes_getType
,
2282 SAXAttributes_getTypeFromName
,
2283 SAXAttributes_getTypeFromQName
,
2284 SAXAttributes_getValue
,
2285 SAXAttributes_getValueFromName
,
2286 SAXAttributes_getValueFromQName
2289 static HRESULT WINAPI
VBSAXAttributes_QueryInterface(
2290 IVBSAXAttributes
* iface
,
2294 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2295 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
2296 return ISAXAttributes_QueryInterface(&This
->ISAXAttributes_iface
, riid
, ppvObject
);
2299 static ULONG WINAPI
VBSAXAttributes_AddRef(IVBSAXAttributes
* iface
)
2301 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2302 return ISAXAttributes_AddRef(&This
->ISAXAttributes_iface
);
2305 static ULONG WINAPI
VBSAXAttributes_Release(IVBSAXAttributes
* iface
)
2307 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2308 return ISAXAttributes_Release(&This
->ISAXAttributes_iface
);
2311 static HRESULT WINAPI
VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes
*iface
, UINT
* pctinfo
)
2313 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2315 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2322 static HRESULT WINAPI
VBSAXAttributes_GetTypeInfo(
2323 IVBSAXAttributes
*iface
,
2324 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
2326 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2327 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2328 return get_typeinfo(IVBSAXAttributes_tid
, ppTInfo
);
2331 static HRESULT WINAPI
VBSAXAttributes_GetIDsOfNames(
2332 IVBSAXAttributes
*iface
,
2334 LPOLESTR
* rgszNames
,
2339 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2340 ITypeInfo
*typeinfo
;
2343 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
2346 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
2347 return E_INVALIDARG
;
2349 hr
= get_typeinfo(IVBSAXAttributes_tid
, &typeinfo
);
2352 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2353 ITypeInfo_Release(typeinfo
);
2359 static HRESULT WINAPI
VBSAXAttributes_Invoke(
2360 IVBSAXAttributes
*iface
,
2361 DISPID dispIdMember
,
2365 DISPPARAMS
* pDispParams
,
2366 VARIANT
* pVarResult
,
2367 EXCEPINFO
* pExcepInfo
,
2370 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2371 ITypeInfo
*typeinfo
;
2374 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2375 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2377 hr
= get_typeinfo(IVBSAXAttributes_tid
, &typeinfo
);
2380 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IVBSAXAttributes_iface
, dispIdMember
, wFlags
,
2381 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2382 ITypeInfo_Release(typeinfo
);
2388 static HRESULT WINAPI
VBSAXAttributes_get_length(IVBSAXAttributes
* iface
, int *len
)
2390 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2391 return ISAXAttributes_getLength(&This
->ISAXAttributes_iface
, len
);
2394 static HRESULT WINAPI
VBSAXAttributes_getURI(IVBSAXAttributes
* iface
, int index
, BSTR
*uri
)
2396 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2399 return ISAXAttributes_getURI(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)uri
, &len
);
2402 static HRESULT WINAPI
VBSAXAttributes_getLocalName(IVBSAXAttributes
* iface
, int index
, BSTR
*name
)
2404 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2407 return ISAXAttributes_getLocalName(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)name
, &len
);
2410 static HRESULT WINAPI
VBSAXAttributes_getQName(IVBSAXAttributes
* iface
, int index
, BSTR
*qname
)
2412 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2415 return ISAXAttributes_getQName(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)qname
, &len
);
2418 static HRESULT WINAPI
VBSAXAttributes_getIndexFromName(IVBSAXAttributes
* iface
, BSTR uri
, BSTR name
, int *index
)
2420 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2421 return ISAXAttributes_getIndexFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2422 name
, SysStringLen(name
), index
);
2425 static HRESULT WINAPI
VBSAXAttributes_getIndexFromQName(IVBSAXAttributes
* iface
, BSTR qname
, int *index
)
2427 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2428 return ISAXAttributes_getIndexFromQName(&This
->ISAXAttributes_iface
, qname
,
2429 SysStringLen(qname
), index
);
2432 static HRESULT WINAPI
VBSAXAttributes_getType(IVBSAXAttributes
* iface
, int index
,BSTR
*type
)
2434 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2437 return ISAXAttributes_getType(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)type
, &len
);
2440 static HRESULT WINAPI
VBSAXAttributes_getTypeFromName(IVBSAXAttributes
* iface
, BSTR uri
,
2441 BSTR name
, BSTR
*type
)
2443 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2446 return ISAXAttributes_getTypeFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2447 name
, SysStringLen(name
), (const WCHAR
**)type
, &len
);
2450 static HRESULT WINAPI
VBSAXAttributes_getTypeFromQName(IVBSAXAttributes
* iface
, BSTR qname
, BSTR
*type
)
2452 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2455 return ISAXAttributes_getTypeFromQName(&This
->ISAXAttributes_iface
, qname
, SysStringLen(qname
),
2456 (const WCHAR
**)type
, &len
);
2459 static HRESULT WINAPI
VBSAXAttributes_getValue(IVBSAXAttributes
* iface
, int index
, BSTR
*value
)
2461 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2464 return ISAXAttributes_getValue(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)value
, &len
);
2467 static HRESULT WINAPI
VBSAXAttributes_getValueFromName(IVBSAXAttributes
* iface
, BSTR uri
, BSTR name
,
2470 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2473 return ISAXAttributes_getValueFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2474 name
, SysStringLen(name
), (const WCHAR
**)value
, &len
);
2477 static HRESULT WINAPI
VBSAXAttributes_getValueFromQName(IVBSAXAttributes
* iface
, BSTR qname
, BSTR
*value
)
2479 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2482 return ISAXAttributes_getValueFromQName(&This
->ISAXAttributes_iface
, qname
, SysStringLen(qname
),
2483 (const WCHAR
**)value
, &len
);
2486 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl
=
2488 VBSAXAttributes_QueryInterface
,
2489 VBSAXAttributes_AddRef
,
2490 VBSAXAttributes_Release
,
2491 VBSAXAttributes_GetTypeInfoCount
,
2492 VBSAXAttributes_GetTypeInfo
,
2493 VBSAXAttributes_GetIDsOfNames
,
2494 VBSAXAttributes_Invoke
,
2495 VBSAXAttributes_get_length
,
2496 VBSAXAttributes_getURI
,
2497 VBSAXAttributes_getLocalName
,
2498 VBSAXAttributes_getQName
,
2499 VBSAXAttributes_getIndexFromName
,
2500 VBSAXAttributes_getIndexFromQName
,
2501 VBSAXAttributes_getType
,
2502 VBSAXAttributes_getTypeFromName
,
2503 VBSAXAttributes_getTypeFromQName
,
2504 VBSAXAttributes_getValue
,
2505 VBSAXAttributes_getValueFromName
,
2506 VBSAXAttributes_getValueFromQName
2509 static const tid_t mxattrs_iface_tids
[] = {
2514 static dispex_static_data_t mxattrs_dispex
= {
2521 HRESULT
SAXAttributes_create(MSXML_VERSION version
, IUnknown
*outer
, void **ppObj
)
2523 static const int default_count
= 10;
2526 TRACE("(%p, %p)\n", outer
, ppObj
);
2528 This
= heap_alloc( sizeof (*This
) );
2530 return E_OUTOFMEMORY
;
2532 This
->IMXAttributes_iface
.lpVtbl
= &MXAttributesVtbl
;
2533 This
->ISAXAttributes_iface
.lpVtbl
= &SAXAttributesVtbl
;
2534 This
->IVBSAXAttributes_iface
.lpVtbl
= &VBSAXAttributesVtbl
;
2537 This
->class_version
= version
;
2539 This
->attr
= heap_alloc(default_count
*sizeof(mxattribute
));
2541 This
->allocated
= default_count
;
2543 *ppObj
= &This
->IMXAttributes_iface
;
2545 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IMXAttributes_iface
, &mxattrs_dispex
);
2547 TRACE("returning iface %p\n", *ppObj
);