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
24 static const WCHAR emptyW
[] = {0};
25 static const WCHAR spaceW
[] = {' '};
26 static const WCHAR quotW
[] = {'\"'};
27 static const WCHAR closetagW
[] = {'>','\r','\n'};
28 static const WCHAR crlfW
[] = {'\r','\n'};
29 static const WCHAR entityW
[] = {'<','!','E','N','T','I','T','Y',' '};
31 /* should be ordered as encoding names are sorted */
34 XmlEncoding_ISO_8859_1
= 0,
35 XmlEncoding_ISO_8859_13
,
36 XmlEncoding_ISO_8859_15
,
37 XmlEncoding_ISO_8859_2
,
38 XmlEncoding_ISO_8859_3
,
39 XmlEncoding_ISO_8859_4
,
40 XmlEncoding_ISO_8859_5
,
41 XmlEncoding_ISO_8859_7
,
42 XmlEncoding_ISO_8859_9
,
48 struct xml_encoding_data
50 const WCHAR
*encoding
;
55 static const WCHAR iso_8859_1W
[] = {'i','s','o','-','8','8','5','9','-','1',0};
56 static const WCHAR iso_8859_2W
[] = {'i','s','o','-','8','8','5','9','-','2',0};
57 static const WCHAR iso_8859_3W
[] = {'i','s','o','-','8','8','5','9','-','3',0};
58 static const WCHAR iso_8859_4W
[] = {'i','s','o','-','8','8','5','9','-','4',0};
59 static const WCHAR iso_8859_5W
[] = {'i','s','o','-','8','8','5','9','-','5',0};
60 static const WCHAR iso_8859_7W
[] = {'i','s','o','-','8','8','5','9','-','7',0};
61 static const WCHAR iso_8859_9W
[] = {'i','s','o','-','8','8','5','9','-','9',0};
62 static const WCHAR iso_8859_13W
[] = {'i','s','o','-','8','8','5','9','-','1','3',0};
63 static const WCHAR iso_8859_15W
[] = {'i','s','o','-','8','8','5','9','-','1','5',0};
64 static const WCHAR utf16W
[] = {'U','T','F','-','1','6',0};
65 static const WCHAR utf8W
[] = {'U','T','F','-','8',0};
67 static const struct xml_encoding_data xml_encoding_map
[] = {
68 { iso_8859_1W
, XmlEncoding_ISO_8859_1
, 28591 },
69 { iso_8859_13W
, XmlEncoding_ISO_8859_13
, 28603 },
70 { iso_8859_15W
, XmlEncoding_ISO_8859_15
, 28605 },
71 { iso_8859_2W
, XmlEncoding_ISO_8859_2
, 28592 },
72 { iso_8859_3W
, XmlEncoding_ISO_8859_3
, 28593 },
73 { iso_8859_4W
, XmlEncoding_ISO_8859_4
, 28594 },
74 { iso_8859_5W
, XmlEncoding_ISO_8859_5
, 28595 },
75 { iso_8859_7W
, XmlEncoding_ISO_8859_7
, 28597 },
76 { iso_8859_9W
, XmlEncoding_ISO_8859_9
, 28599 },
77 { utf16W
, XmlEncoding_UTF16
, ~0 },
78 { utf8W
, XmlEncoding_UTF8
, CP_UTF8
}
83 OutputBuffer_Native
= 0x001,
84 OutputBuffer_Encoded
= 0x010,
85 OutputBuffer_Both
= 0x100
91 MXWriter_DisableEscaping
,
107 unsigned int allocated
;
108 unsigned int written
;
113 encoded_buffer utf16
;
114 encoded_buffer encoded
;
121 IMXWriter IMXWriter_iface
;
122 ISAXContentHandler ISAXContentHandler_iface
;
123 ISAXLexicalHandler ISAXLexicalHandler_iface
;
124 ISAXDeclHandler ISAXDeclHandler_iface
;
127 MSXML_VERSION class_version
;
129 VARIANT_BOOL props
[MXWriter_LastProp
];
133 BOOL text
; /* last node was text node, so we shouldn't indent next node */
134 BOOL newline
; /* newline was already added as a part of previous call */
135 UINT indent
; /* indentation level for next node */
139 BSTR encoding
; /* exact property value */
140 xml_encoding xml_enc
;
142 /* contains a pending (or not closed yet) element name or NULL if
143 we don't have to close */
149 output_buffer
*buffer
;
164 IMXAttributes IMXAttributes_iface
;
165 ISAXAttributes ISAXAttributes_iface
;
166 IVBSAXAttributes IVBSAXAttributes_iface
;
169 MSXML_VERSION class_version
;
176 static inline mxattributes
*impl_from_IMXAttributes( IMXAttributes
*iface
)
178 return CONTAINING_RECORD(iface
, mxattributes
, IMXAttributes_iface
);
181 static inline mxattributes
*impl_from_ISAXAttributes( ISAXAttributes
*iface
)
183 return CONTAINING_RECORD(iface
, mxattributes
, ISAXAttributes_iface
);
186 static inline mxattributes
*impl_from_IVBSAXAttributes( IVBSAXAttributes
*iface
)
188 return CONTAINING_RECORD(iface
, mxattributes
, IVBSAXAttributes_iface
);
191 static HRESULT
mxattributes_grow(mxattributes
*This
)
193 if (This
->length
< This
->allocated
) return S_OK
;
195 This
->allocated
*= 2;
196 This
->attr
= heap_realloc(This
->attr
, This
->allocated
*sizeof(mxattribute
));
198 return This
->attr
? S_OK
: E_OUTOFMEMORY
;
201 static xml_encoding
parse_encoding_name(const WCHAR
*encoding
)
206 max
= sizeof(xml_encoding_map
)/sizeof(struct xml_encoding_data
) - 1;
212 c
= strcmpiW(xml_encoding_map
[n
].encoding
, encoding
);
214 return xml_encoding_map
[n
].enc
;
222 return XmlEncoding_Unknown
;
225 static HRESULT
init_encoded_buffer(encoded_buffer
*buffer
)
227 const int initial_len
= 0x2000;
228 buffer
->data
= heap_alloc(initial_len
);
229 if (!buffer
->data
) return E_OUTOFMEMORY
;
231 memset(buffer
->data
, 0, 4);
232 buffer
->allocated
= initial_len
;
238 static void free_encoded_buffer(encoded_buffer
*buffer
)
240 heap_free(buffer
->data
);
243 static HRESULT
get_code_page(xml_encoding encoding
, UINT
*cp
)
245 const struct xml_encoding_data
*data
;
247 if (encoding
== XmlEncoding_Unknown
)
249 FIXME("unsupported encoding %d\n", encoding
);
253 data
= &xml_encoding_map
[encoding
];
259 static HRESULT
alloc_output_buffer(xml_encoding encoding
, output_buffer
**buffer
)
264 ret
= heap_alloc(sizeof(*ret
));
265 if (!ret
) return E_OUTOFMEMORY
;
267 hr
= get_code_page(encoding
, &ret
->code_page
);
273 hr
= init_encoded_buffer(&ret
->utf16
);
279 /* currently we always create a default output buffer that is UTF-16 only,
280 but it's possible to allocate with specific encoding too */
281 if (encoding
!= XmlEncoding_UTF16
) {
282 hr
= init_encoded_buffer(&ret
->encoded
);
284 free_encoded_buffer(&ret
->utf16
);
290 memset(&ret
->encoded
, 0, sizeof(ret
->encoded
));
297 static void free_output_buffer(output_buffer
*buffer
)
299 free_encoded_buffer(&buffer
->encoded
);
300 free_encoded_buffer(&buffer
->utf16
);
304 static void grow_buffer(encoded_buffer
*buffer
, int length
)
306 /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
307 if (buffer
->allocated
< buffer
->written
+ length
+ 4)
309 int grown_size
= max(2*buffer
->allocated
, buffer
->allocated
+ length
);
310 buffer
->data
= heap_realloc(buffer
->data
, grown_size
);
311 buffer
->allocated
= grown_size
;
315 static HRESULT
write_output_buffer_mode(output_buffer
*buffer
, output_mode mode
, const WCHAR
*data
, int len
)
320 if (mode
& (OutputBuffer_Encoded
| OutputBuffer_Both
)) {
321 if (buffer
->code_page
!= ~0)
323 length
= WideCharToMultiByte(buffer
->code_page
, 0, data
, len
, NULL
, 0, NULL
, NULL
);
324 grow_buffer(&buffer
->encoded
, length
);
325 ptr
= buffer
->encoded
.data
+ buffer
->encoded
.written
;
326 length
= WideCharToMultiByte(buffer
->code_page
, 0, data
, len
, ptr
, length
, NULL
, NULL
);
327 buffer
->encoded
.written
+= len
== -1 ? length
-1 : length
;
331 if (mode
& (OutputBuffer_Native
| OutputBuffer_Both
)) {
332 /* WCHAR data just copied */
333 length
= len
== -1 ? strlenW(data
) : len
;
336 length
*= sizeof(WCHAR
);
338 grow_buffer(&buffer
->utf16
, length
);
339 ptr
= buffer
->utf16
.data
+ buffer
->utf16
.written
;
341 memcpy(ptr
, data
, length
);
342 buffer
->utf16
.written
+= length
;
344 /* null termination */
345 memset(ptr
, 0, sizeof(WCHAR
));
352 static HRESULT
write_output_buffer(output_buffer
*buffer
, const WCHAR
*data
, int len
)
354 return write_output_buffer_mode(buffer
, OutputBuffer_Both
, data
, len
);
357 static HRESULT
write_output_buffer_quoted(output_buffer
*buffer
, const WCHAR
*data
, int len
)
359 write_output_buffer(buffer
, quotW
, 1);
360 write_output_buffer(buffer
, data
, len
);
361 write_output_buffer(buffer
, quotW
, 1);
366 /* frees buffer data, reallocates with a default lengths */
367 static void close_output_buffer(mxwriter
*This
)
369 heap_free(This
->buffer
->utf16
.data
);
370 heap_free(This
->buffer
->encoded
.data
);
371 init_encoded_buffer(&This
->buffer
->utf16
);
372 init_encoded_buffer(&This
->buffer
->encoded
);
373 get_code_page(This
->xml_enc
, &This
->buffer
->code_page
);
376 /* escapes special characters like:
382 static WCHAR
*get_escaped_string(const WCHAR
*str
, escape_mode mode
, int *len
)
384 static const WCHAR ltW
[] = {'&','l','t',';'};
385 static const WCHAR ampW
[] = {'&','a','m','p',';'};
386 static const WCHAR equotW
[] = {'&','q','u','o','t',';'};
387 static const WCHAR gtW
[] = {'&','g','t',';'};
389 const int default_alloc
= 100;
390 const int grow_thresh
= 10;
391 int p
= *len
, conv_len
;
394 /* default buffer size to something if length is unknown */
395 conv_len
= *len
== -1 ? default_alloc
: max(2**len
, default_alloc
);
396 ptr
= ret
= heap_alloc(conv_len
*sizeof(WCHAR
));
400 if (ptr
- ret
> conv_len
- grow_thresh
)
402 int written
= ptr
- ret
;
404 ptr
= ret
= heap_realloc(ret
, conv_len
*sizeof(WCHAR
));
411 memcpy(ptr
, ltW
, sizeof(ltW
));
412 ptr
+= sizeof(ltW
)/sizeof(WCHAR
);
415 memcpy(ptr
, ampW
, sizeof(ampW
));
416 ptr
+= sizeof(ampW
)/sizeof(WCHAR
);
419 memcpy(ptr
, gtW
, sizeof(gtW
));
420 ptr
+= sizeof(gtW
)/sizeof(WCHAR
);
423 if (mode
== EscapeValue
)
425 memcpy(ptr
, equotW
, sizeof(equotW
));
426 ptr
+= sizeof(equotW
)/sizeof(WCHAR
);
429 /* fallthrough for text mode */
439 if (*len
!= -1) *len
= ptr
-ret
;
445 static void write_prolog_buffer(mxwriter
*This
)
447 static const WCHAR versionW
[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
448 static const WCHAR encodingW
[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
449 static const WCHAR standaloneW
[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
450 static const WCHAR yesW
[] = {'y','e','s','\"','?','>'};
451 static const WCHAR noW
[] = {'n','o','\"','?','>'};
454 write_output_buffer(This
->buffer
, versionW
, sizeof(versionW
)/sizeof(WCHAR
));
455 write_output_buffer_quoted(This
->buffer
, This
->version
, -1);
458 write_output_buffer(This
->buffer
, encodingW
, sizeof(encodingW
)/sizeof(WCHAR
));
460 /* always write UTF-16 to WCHAR buffer */
461 write_output_buffer_mode(This
->buffer
, OutputBuffer_Native
, utf16W
, sizeof(utf16W
)/sizeof(WCHAR
) - 1);
462 write_output_buffer_mode(This
->buffer
, OutputBuffer_Encoded
, This
->encoding
, -1);
463 write_output_buffer(This
->buffer
, quotW
, 1);
466 write_output_buffer(This
->buffer
, standaloneW
, sizeof(standaloneW
)/sizeof(WCHAR
));
467 if (This
->props
[MXWriter_Standalone
] == VARIANT_TRUE
)
468 write_output_buffer(This
->buffer
, yesW
, sizeof(yesW
)/sizeof(WCHAR
));
470 write_output_buffer(This
->buffer
, noW
, sizeof(noW
)/sizeof(WCHAR
));
472 write_output_buffer(This
->buffer
, crlfW
, sizeof(crlfW
)/sizeof(WCHAR
));
473 This
->newline
= TRUE
;
476 /* Attempts to the write data from the mxwriter's buffer to
477 * the destination stream (if there is one).
479 static HRESULT
write_data_to_stream(mxwriter
*This
)
481 encoded_buffer
*buffer
;
488 if (This
->xml_enc
!= XmlEncoding_UTF16
)
489 buffer
= &This
->buffer
->encoded
;
491 buffer
= &This
->buffer
->utf16
;
493 if (This
->dest_written
> buffer
->written
) {
494 ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This
->dest_written
, buffer
->written
);
496 } else if (This
->dest_written
== buffer
->written
&& This
->xml_enc
!= XmlEncoding_UTF8
)
497 /* Windows seems to make an empty write call when the encoding is UTF-8 and
498 * all the data has been written to the stream. It doesn't seem make this call
499 * for any other encodings.
503 /* Write the current content from the output buffer into 'dest'.
504 * TODO: Check what Windows does if the IStream doesn't write all of
505 * the data we give it at once.
507 hr
= IStream_Write(This
->dest
, buffer
->data
+This
->dest_written
,
508 buffer
->written
-This
->dest_written
, &written
);
510 WARN("Failed to write data to IStream (0x%08x)\n", hr
);
514 This
->dest_written
+= written
;
518 /* Newly added element start tag left unclosed cause for empty elements
519 we have to close it differently. */
520 static void close_element_starttag(const mxwriter
*This
)
522 static const WCHAR gtW
[] = {'>'};
523 if (!This
->element
) return;
524 write_output_buffer(This
->buffer
, gtW
, 1);
527 static void write_node_indent(mxwriter
*This
)
529 static const WCHAR tabW
[] = {'\t'};
530 int indent
= This
->indent
;
532 if (!This
->props
[MXWriter_Indent
] || This
->text
)
538 /* This is to workaround PI output logic that always puts newline chars,
539 document prolog PI does that too. */
541 write_output_buffer(This
->buffer
, crlfW
, sizeof(crlfW
)/sizeof(WCHAR
));
543 write_output_buffer(This
->buffer
, tabW
, 1);
545 This
->newline
= FALSE
;
549 static inline void writer_inc_indent(mxwriter
*This
)
554 static inline void writer_dec_indent(mxwriter
*This
)
556 if (This
->indent
) This
->indent
--;
557 /* depth is decreased only when element is closed, meaning it's not a text node
562 static void set_element_name(mxwriter
*This
, const WCHAR
*name
, int len
)
564 SysFreeString(This
->element
);
566 This
->element
= len
!= -1 ? SysAllocStringLen(name
, len
) : SysAllocString(name
);
568 This
->element
= NULL
;
571 static inline HRESULT
flush_output_buffer(mxwriter
*This
)
573 close_element_starttag(This
);
574 set_element_name(This
, NULL
, 0);
576 return write_data_to_stream(This
);
579 /* Resets the mxwriter's output buffer by closing it, then creating a new
580 * output buffer using the given encoding.
582 static inline void reset_output_buffer(mxwriter
*This
)
584 close_output_buffer(This
);
585 This
->dest_written
= 0;
588 static HRESULT
writer_set_property(mxwriter
*writer
, mxwriter_prop property
, VARIANT_BOOL value
)
590 writer
->props
[property
] = value
;
591 writer
->prop_changed
= TRUE
;
595 static HRESULT
writer_get_property(const mxwriter
*writer
, mxwriter_prop property
, VARIANT_BOOL
*value
)
597 if (!value
) return E_POINTER
;
598 *value
= writer
->props
[property
];
602 static inline mxwriter
*impl_from_IMXWriter(IMXWriter
*iface
)
604 return CONTAINING_RECORD(iface
, mxwriter
, IMXWriter_iface
);
607 static inline mxwriter
*impl_from_ISAXContentHandler(ISAXContentHandler
*iface
)
609 return CONTAINING_RECORD(iface
, mxwriter
, ISAXContentHandler_iface
);
612 static inline mxwriter
*impl_from_ISAXLexicalHandler(ISAXLexicalHandler
*iface
)
614 return CONTAINING_RECORD(iface
, mxwriter
, ISAXLexicalHandler_iface
);
617 static inline mxwriter
*impl_from_ISAXDeclHandler(ISAXDeclHandler
*iface
)
619 return CONTAINING_RECORD(iface
, mxwriter
, ISAXDeclHandler_iface
);
622 static HRESULT WINAPI
mxwriter_QueryInterface(IMXWriter
*iface
, REFIID riid
, void **obj
)
624 mxwriter
*This
= impl_from_IMXWriter( iface
);
626 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), obj
);
630 if ( IsEqualGUID( riid
, &IID_IMXWriter
) ||
631 IsEqualGUID( riid
, &IID_IDispatch
) ||
632 IsEqualGUID( riid
, &IID_IUnknown
) )
634 *obj
= &This
->IMXWriter_iface
;
636 else if ( IsEqualGUID( riid
, &IID_ISAXContentHandler
) )
638 *obj
= &This
->ISAXContentHandler_iface
;
640 else if ( IsEqualGUID( riid
, &IID_ISAXLexicalHandler
) )
642 *obj
= &This
->ISAXLexicalHandler_iface
;
644 else if ( IsEqualGUID( riid
, &IID_ISAXDeclHandler
) )
646 *obj
= &This
->ISAXDeclHandler_iface
;
648 else if (dispex_query_interface(&This
->dispex
, riid
, obj
))
650 return *obj
? S_OK
: E_NOINTERFACE
;
654 ERR("interface %s not implemented\n", debugstr_guid(riid
));
656 return E_NOINTERFACE
;
659 IMXWriter_AddRef(iface
);
663 static ULONG WINAPI
mxwriter_AddRef(IMXWriter
*iface
)
665 mxwriter
*This
= impl_from_IMXWriter( iface
);
666 LONG ref
= InterlockedIncrement(&This
->ref
);
668 TRACE("(%p)->(%d)\n", This
, ref
);
673 static ULONG WINAPI
mxwriter_Release(IMXWriter
*iface
)
675 mxwriter
*This
= impl_from_IMXWriter( iface
);
676 ULONG ref
= InterlockedDecrement(&This
->ref
);
678 TRACE("(%p)->(%d)\n", This
, ref
);
682 /* Windows flushes the buffer when the interface is destroyed. */
683 flush_output_buffer(This
);
684 free_output_buffer(This
->buffer
);
686 if (This
->dest
) IStream_Release(This
->dest
);
687 SysFreeString(This
->version
);
688 SysFreeString(This
->encoding
);
690 SysFreeString(This
->element
);
691 release_dispex(&This
->dispex
);
698 static HRESULT WINAPI
mxwriter_GetTypeInfoCount(IMXWriter
*iface
, UINT
* pctinfo
)
700 mxwriter
*This
= impl_from_IMXWriter( iface
);
701 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
704 static HRESULT WINAPI
mxwriter_GetTypeInfo(
706 UINT iTInfo
, LCID lcid
,
707 ITypeInfo
** ppTInfo
)
709 mxwriter
*This
= impl_from_IMXWriter( iface
);
710 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
,
711 iTInfo
, lcid
, ppTInfo
);
714 static HRESULT WINAPI
mxwriter_GetIDsOfNames(
716 REFIID riid
, LPOLESTR
* rgszNames
,
717 UINT cNames
, LCID lcid
, DISPID
* rgDispId
)
719 mxwriter
*This
= impl_from_IMXWriter( iface
);
720 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
721 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
724 static HRESULT WINAPI
mxwriter_Invoke(
726 DISPID dispIdMember
, REFIID riid
, LCID lcid
,
727 WORD wFlags
, DISPPARAMS
* pDispParams
, VARIANT
* pVarResult
,
728 EXCEPINFO
* pExcepInfo
, UINT
* puArgErr
)
730 mxwriter
*This
= impl_from_IMXWriter( iface
);
731 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
732 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
735 static HRESULT WINAPI
mxwriter_put_output(IMXWriter
*iface
, VARIANT dest
)
737 mxwriter
*This
= impl_from_IMXWriter( iface
);
740 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&dest
));
742 hr
= flush_output_buffer(This
);
750 if (This
->dest
) IStream_Release(This
->dest
);
752 reset_output_buffer(This
);
759 hr
= IUnknown_QueryInterface(V_UNKNOWN(&dest
), &IID_IStream
, (void**)&stream
);
762 /* Recreate the output buffer to make sure it's using the correct encoding. */
763 reset_output_buffer(This
);
765 if (This
->dest
) IStream_Release(This
->dest
);
770 FIXME("unhandled interface type for VT_UNKNOWN destination\n");
774 FIXME("unhandled destination type %s\n", debugstr_variant(&dest
));
781 static HRESULT WINAPI
mxwriter_get_output(IMXWriter
*iface
, VARIANT
*dest
)
783 mxwriter
*This
= impl_from_IMXWriter( iface
);
785 TRACE("(%p)->(%p)\n", This
, dest
);
787 if (!dest
) return E_POINTER
;
791 HRESULT hr
= flush_output_buffer(This
);
795 V_VT(dest
) = VT_BSTR
;
796 V_BSTR(dest
) = SysAllocString((WCHAR
*)This
->buffer
->utf16
.data
);
801 /* we only support IStream output so far */
802 V_VT(dest
) = VT_UNKNOWN
;
803 V_UNKNOWN(dest
) = (IUnknown
*)This
->dest
;
804 IStream_AddRef(This
->dest
);
809 static HRESULT WINAPI
mxwriter_put_encoding(IMXWriter
*iface
, BSTR encoding
)
811 mxwriter
*This
= impl_from_IMXWriter( iface
);
815 TRACE("(%p)->(%s)\n", This
, debugstr_w(encoding
));
817 enc
= parse_encoding_name(encoding
);
818 if (enc
== XmlEncoding_Unknown
)
820 FIXME("unsupported encoding %s\n", debugstr_w(encoding
));
824 hr
= flush_output_buffer(This
);
828 SysReAllocString(&This
->encoding
, encoding
);
831 TRACE("got encoding %d\n", This
->xml_enc
);
832 reset_output_buffer(This
);
836 static HRESULT WINAPI
mxwriter_get_encoding(IMXWriter
*iface
, BSTR
*encoding
)
838 mxwriter
*This
= impl_from_IMXWriter( iface
);
840 TRACE("(%p)->(%p)\n", This
, encoding
);
842 if (!encoding
) return E_POINTER
;
844 *encoding
= SysAllocString(This
->encoding
);
845 if (!*encoding
) return E_OUTOFMEMORY
;
850 static HRESULT WINAPI
mxwriter_put_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL value
)
852 mxwriter
*This
= impl_from_IMXWriter( iface
);
854 TRACE("(%p)->(%d)\n", This
, value
);
855 return writer_set_property(This
, MXWriter_BOM
, value
);
858 static HRESULT WINAPI
mxwriter_get_byteOrderMark(IMXWriter
*iface
, VARIANT_BOOL
*value
)
860 mxwriter
*This
= impl_from_IMXWriter( iface
);
862 TRACE("(%p)->(%p)\n", This
, value
);
863 return writer_get_property(This
, MXWriter_BOM
, value
);
866 static HRESULT WINAPI
mxwriter_put_indent(IMXWriter
*iface
, VARIANT_BOOL value
)
868 mxwriter
*This
= impl_from_IMXWriter( iface
);
870 TRACE("(%p)->(%d)\n", This
, value
);
871 return writer_set_property(This
, MXWriter_Indent
, value
);
874 static HRESULT WINAPI
mxwriter_get_indent(IMXWriter
*iface
, VARIANT_BOOL
*value
)
876 mxwriter
*This
= impl_from_IMXWriter( iface
);
878 TRACE("(%p)->(%p)\n", This
, value
);
879 return writer_get_property(This
, MXWriter_Indent
, value
);
882 static HRESULT WINAPI
mxwriter_put_standalone(IMXWriter
*iface
, VARIANT_BOOL value
)
884 mxwriter
*This
= impl_from_IMXWriter( iface
);
886 TRACE("(%p)->(%d)\n", This
, value
);
887 return writer_set_property(This
, MXWriter_Standalone
, value
);
890 static HRESULT WINAPI
mxwriter_get_standalone(IMXWriter
*iface
, VARIANT_BOOL
*value
)
892 mxwriter
*This
= impl_from_IMXWriter( iface
);
894 TRACE("(%p)->(%p)\n", This
, value
);
895 return writer_get_property(This
, MXWriter_Standalone
, value
);
898 static HRESULT WINAPI
mxwriter_put_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL value
)
900 mxwriter
*This
= impl_from_IMXWriter( iface
);
902 TRACE("(%p)->(%d)\n", This
, value
);
903 return writer_set_property(This
, MXWriter_OmitXmlDecl
, value
);
906 static HRESULT WINAPI
mxwriter_get_omitXMLDeclaration(IMXWriter
*iface
, VARIANT_BOOL
*value
)
908 mxwriter
*This
= impl_from_IMXWriter( iface
);
910 TRACE("(%p)->(%p)\n", This
, value
);
911 return writer_get_property(This
, MXWriter_OmitXmlDecl
, value
);
914 static HRESULT WINAPI
mxwriter_put_version(IMXWriter
*iface
, BSTR version
)
916 mxwriter
*This
= impl_from_IMXWriter( iface
);
918 TRACE("(%p)->(%s)\n", This
, debugstr_w(version
));
920 if (!version
) return E_INVALIDARG
;
922 SysFreeString(This
->version
);
923 This
->version
= SysAllocString(version
);
928 static HRESULT WINAPI
mxwriter_get_version(IMXWriter
*iface
, BSTR
*version
)
930 mxwriter
*This
= impl_from_IMXWriter( iface
);
932 TRACE("(%p)->(%p)\n", This
, version
);
934 if (!version
) return E_POINTER
;
936 return return_bstr(This
->version
, version
);
939 static HRESULT WINAPI
mxwriter_put_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL value
)
941 mxwriter
*This
= impl_from_IMXWriter( iface
);
943 TRACE("(%p)->(%d)\n", This
, value
);
944 return writer_set_property(This
, MXWriter_DisableEscaping
, value
);
947 static HRESULT WINAPI
mxwriter_get_disableOutputEscaping(IMXWriter
*iface
, VARIANT_BOOL
*value
)
949 mxwriter
*This
= impl_from_IMXWriter( iface
);
951 TRACE("(%p)->(%p)\n", This
, value
);
952 return writer_get_property(This
, MXWriter_DisableEscaping
, value
);
955 static HRESULT WINAPI
mxwriter_flush(IMXWriter
*iface
)
957 mxwriter
*This
= impl_from_IMXWriter( iface
);
958 TRACE("(%p)\n", This
);
959 return flush_output_buffer(This
);
962 static const struct IMXWriterVtbl MXWriterVtbl
=
964 mxwriter_QueryInterface
,
967 mxwriter_GetTypeInfoCount
,
968 mxwriter_GetTypeInfo
,
969 mxwriter_GetIDsOfNames
,
973 mxwriter_put_encoding
,
974 mxwriter_get_encoding
,
975 mxwriter_put_byteOrderMark
,
976 mxwriter_get_byteOrderMark
,
979 mxwriter_put_standalone
,
980 mxwriter_get_standalone
,
981 mxwriter_put_omitXMLDeclaration
,
982 mxwriter_get_omitXMLDeclaration
,
983 mxwriter_put_version
,
984 mxwriter_get_version
,
985 mxwriter_put_disableOutputEscaping
,
986 mxwriter_get_disableOutputEscaping
,
990 /*** ISAXContentHandler ***/
991 static HRESULT WINAPI
SAXContentHandler_QueryInterface(
992 ISAXContentHandler
*iface
,
996 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
997 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1000 static ULONG WINAPI
SAXContentHandler_AddRef(ISAXContentHandler
*iface
)
1002 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1003 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1006 static ULONG WINAPI
SAXContentHandler_Release(ISAXContentHandler
*iface
)
1008 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1009 return IMXWriter_Release(&This
->IMXWriter_iface
);
1012 static HRESULT WINAPI
SAXContentHandler_putDocumentLocator(
1013 ISAXContentHandler
*iface
,
1014 ISAXLocator
*locator
)
1016 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1017 FIXME("(%p)->(%p)\n", This
, locator
);
1021 static HRESULT WINAPI
SAXContentHandler_startDocument(ISAXContentHandler
*iface
)
1023 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1025 TRACE("(%p)\n", This
);
1027 /* If properties have been changed since the last "endDocument" call
1028 * we need to reset the output buffer. If we don't the output buffer
1029 * could end up with multiple XML documents in it, plus this seems to
1030 * be how Windows works.
1032 if (This
->prop_changed
) {
1033 reset_output_buffer(This
);
1034 This
->prop_changed
= FALSE
;
1037 if (This
->props
[MXWriter_OmitXmlDecl
] == VARIANT_TRUE
) return S_OK
;
1039 write_prolog_buffer(This
);
1041 if (This
->dest
&& This
->xml_enc
== XmlEncoding_UTF16
) {
1042 static const char utf16BOM
[] = {0xff,0xfe};
1044 if (This
->props
[MXWriter_BOM
] == VARIANT_TRUE
)
1045 /* Windows passes a NULL pointer as the pcbWritten parameter and
1046 * ignores any error codes returned from this Write call.
1048 IStream_Write(This
->dest
, utf16BOM
, sizeof(utf16BOM
), NULL
);
1054 static HRESULT WINAPI
SAXContentHandler_endDocument(ISAXContentHandler
*iface
)
1056 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1057 TRACE("(%p)\n", This
);
1058 This
->prop_changed
= FALSE
;
1059 return flush_output_buffer(This
);
1062 static HRESULT WINAPI
SAXContentHandler_startPrefixMapping(
1063 ISAXContentHandler
*iface
,
1064 const WCHAR
*prefix
,
1069 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1070 FIXME("(%p)->(%s %s)\n", This
, debugstr_wn(prefix
, nprefix
), debugstr_wn(uri
, nuri
));
1074 static HRESULT WINAPI
SAXContentHandler_endPrefixMapping(
1075 ISAXContentHandler
*iface
,
1076 const WCHAR
*prefix
,
1079 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1080 FIXME("(%p)->(%s)\n", This
, debugstr_wn(prefix
, nprefix
));
1084 static HRESULT WINAPI
SAXContentHandler_startElement(
1085 ISAXContentHandler
*iface
,
1086 const WCHAR
*namespaceUri
,
1088 const WCHAR
*local_name
,
1092 ISAXAttributes
*attr
)
1094 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1095 static const WCHAR ltW
[] = {'<'};
1097 TRACE("(%p)->(%s %s %s %p)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
),
1098 debugstr_wn(local_name
, nlocal_name
), debugstr_wn(QName
, nQName
), attr
);
1100 if (((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
) ||
1101 (nQName
== -1 && This
->class_version
== MSXML6
))
1102 return E_INVALIDARG
;
1104 close_element_starttag(This
);
1105 set_element_name(This
, QName
? QName
: emptyW
,
1106 QName
? nQName
: 0);
1108 write_node_indent(This
);
1110 write_output_buffer(This
->buffer
, ltW
, 1);
1111 write_output_buffer(This
->buffer
, QName
, nQName
);
1112 writer_inc_indent(This
);
1116 int length
, i
, escape
;
1119 hr
= ISAXAttributes_getLength(attr
, &length
);
1120 if (FAILED(hr
)) return hr
;
1122 escape
= This
->props
[MXWriter_DisableEscaping
] == VARIANT_FALSE
||
1123 (This
->class_version
== MSXML4
|| This
->class_version
== MSXML6
);
1125 for (i
= 0; i
< length
; i
++)
1127 static const WCHAR eqW
[] = {'='};
1131 hr
= ISAXAttributes_getQName(attr
, i
, &str
, &len
);
1132 if (FAILED(hr
)) return hr
;
1134 /* space separator in front of every attribute */
1135 write_output_buffer(This
->buffer
, spaceW
, 1);
1136 write_output_buffer(This
->buffer
, str
, len
);
1138 write_output_buffer(This
->buffer
, eqW
, 1);
1141 hr
= ISAXAttributes_getValue(attr
, i
, &str
, &len
);
1142 if (FAILED(hr
)) return hr
;
1146 WCHAR
*escaped
= get_escaped_string(str
, EscapeValue
, &len
);
1147 write_output_buffer_quoted(This
->buffer
, escaped
, len
);
1151 write_output_buffer_quoted(This
->buffer
, str
, len
);
1158 static HRESULT WINAPI
SAXContentHandler_endElement(
1159 ISAXContentHandler
*iface
,
1160 const WCHAR
*namespaceUri
,
1162 const WCHAR
* local_name
,
1167 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1169 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This
, debugstr_wn(namespaceUri
, nnamespaceUri
), nnamespaceUri
,
1170 debugstr_wn(local_name
, nlocal_name
), nlocal_name
, debugstr_wn(QName
, nQName
), nQName
);
1172 if (((!namespaceUri
|| !local_name
|| !QName
) && This
->class_version
!= MSXML6
) ||
1173 (nQName
== -1 && This
->class_version
== MSXML6
))
1174 return E_INVALIDARG
;
1176 writer_dec_indent(This
);
1180 static const WCHAR closeW
[] = {'/','>'};
1181 write_output_buffer(This
->buffer
, closeW
, 2);
1185 static const WCHAR closetagW
[] = {'<','/'};
1186 static const WCHAR gtW
[] = {'>'};
1188 write_node_indent(This
);
1189 write_output_buffer(This
->buffer
, closetagW
, 2);
1190 write_output_buffer(This
->buffer
, QName
, nQName
);
1191 write_output_buffer(This
->buffer
, gtW
, 1);
1194 set_element_name(This
, NULL
, 0);
1199 static HRESULT WINAPI
SAXContentHandler_characters(
1200 ISAXContentHandler
*iface
,
1204 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1206 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
1208 if (!chars
) return E_INVALIDARG
;
1210 close_element_starttag(This
);
1211 set_element_name(This
, NULL
, 0);
1218 if (This
->cdata
|| This
->props
[MXWriter_DisableEscaping
] == VARIANT_TRUE
)
1219 write_output_buffer(This
->buffer
, chars
, nchars
);
1225 escaped
= get_escaped_string(chars
, EscapeText
, &len
);
1226 write_output_buffer(This
->buffer
, escaped
, len
);
1234 static HRESULT WINAPI
SAXContentHandler_ignorableWhitespace(
1235 ISAXContentHandler
*iface
,
1239 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1241 TRACE("(%p)->(%s)\n", This
, debugstr_wn(chars
, nchars
));
1243 if (!chars
) return E_INVALIDARG
;
1245 write_output_buffer(This
->buffer
, chars
, nchars
);
1250 static HRESULT WINAPI
SAXContentHandler_processingInstruction(
1251 ISAXContentHandler
*iface
,
1252 const WCHAR
*target
,
1257 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1258 static const WCHAR openpiW
[] = {'<','?'};
1259 static const WCHAR closepiW
[] = {'?','>','\r','\n'};
1261 TRACE("(%p)->(%s %s)\n", This
, debugstr_wn(target
, ntarget
), debugstr_wn(data
, ndata
));
1263 if (!target
) return E_INVALIDARG
;
1265 write_node_indent(This
);
1266 write_output_buffer(This
->buffer
, openpiW
, sizeof(openpiW
)/sizeof(WCHAR
));
1269 write_output_buffer(This
->buffer
, target
, ntarget
);
1271 if (data
&& *data
&& ndata
)
1273 write_output_buffer(This
->buffer
, spaceW
, 1);
1274 write_output_buffer(This
->buffer
, data
, ndata
);
1277 write_output_buffer(This
->buffer
, closepiW
, sizeof(closepiW
)/sizeof(WCHAR
));
1278 This
->newline
= TRUE
;
1283 static HRESULT WINAPI
SAXContentHandler_skippedEntity(
1284 ISAXContentHandler
*iface
,
1288 mxwriter
*This
= impl_from_ISAXContentHandler( iface
);
1289 FIXME("(%p)->(%s)\n", This
, debugstr_wn(name
, nname
));
1293 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl
=
1295 SAXContentHandler_QueryInterface
,
1296 SAXContentHandler_AddRef
,
1297 SAXContentHandler_Release
,
1298 SAXContentHandler_putDocumentLocator
,
1299 SAXContentHandler_startDocument
,
1300 SAXContentHandler_endDocument
,
1301 SAXContentHandler_startPrefixMapping
,
1302 SAXContentHandler_endPrefixMapping
,
1303 SAXContentHandler_startElement
,
1304 SAXContentHandler_endElement
,
1305 SAXContentHandler_characters
,
1306 SAXContentHandler_ignorableWhitespace
,
1307 SAXContentHandler_processingInstruction
,
1308 SAXContentHandler_skippedEntity
1311 /*** ISAXLexicalHandler ***/
1312 static HRESULT WINAPI
SAXLexicalHandler_QueryInterface(ISAXLexicalHandler
*iface
,
1313 REFIID riid
, void **obj
)
1315 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1316 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1319 static ULONG WINAPI
SAXLexicalHandler_AddRef(ISAXLexicalHandler
*iface
)
1321 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1322 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1325 static ULONG WINAPI
SAXLexicalHandler_Release(ISAXLexicalHandler
*iface
)
1327 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1328 return IMXWriter_Release(&This
->IMXWriter_iface
);
1331 static HRESULT WINAPI
SAXLexicalHandler_startDTD(ISAXLexicalHandler
*iface
,
1332 const WCHAR
*name
, int name_len
, const WCHAR
*publicId
, int publicId_len
,
1333 const WCHAR
*systemId
, int systemId_len
)
1335 static const WCHAR doctypeW
[] = {'<','!','D','O','C','T','Y','P','E',' '};
1336 static const WCHAR openintW
[] = {'[','\r','\n'};
1338 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1340 TRACE("(%p)->(%s %s %s)\n", This
, debugstr_wn(name
, name_len
), debugstr_wn(publicId
, publicId_len
),
1341 debugstr_wn(systemId
, systemId_len
));
1343 if (!name
) return E_INVALIDARG
;
1345 write_output_buffer(This
->buffer
, doctypeW
, sizeof(doctypeW
)/sizeof(WCHAR
));
1349 write_output_buffer(This
->buffer
, name
, name_len
);
1350 write_output_buffer(This
->buffer
, spaceW
, 1);
1355 static const WCHAR publicW
[] = {'P','U','B','L','I','C',' '};
1357 write_output_buffer(This
->buffer
, publicW
, sizeof(publicW
)/sizeof(WCHAR
));
1358 write_output_buffer_quoted(This
->buffer
, publicId
, publicId_len
);
1360 if (!systemId
) return E_INVALIDARG
;
1363 write_output_buffer(This
->buffer
, spaceW
, 1);
1365 write_output_buffer_quoted(This
->buffer
, systemId
, systemId_len
);
1368 write_output_buffer(This
->buffer
, spaceW
, 1);
1372 static const WCHAR systemW
[] = {'S','Y','S','T','E','M',' '};
1374 write_output_buffer(This
->buffer
, systemW
, sizeof(systemW
)/sizeof(WCHAR
));
1375 write_output_buffer_quoted(This
->buffer
, systemId
, systemId_len
);
1377 write_output_buffer(This
->buffer
, spaceW
, 1);
1380 write_output_buffer(This
->buffer
, openintW
, sizeof(openintW
)/sizeof(WCHAR
));
1385 static HRESULT WINAPI
SAXLexicalHandler_endDTD(ISAXLexicalHandler
*iface
)
1387 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1388 static const WCHAR closedtdW
[] = {']','>','\r','\n'};
1390 TRACE("(%p)\n", This
);
1392 write_output_buffer(This
->buffer
, closedtdW
, sizeof(closedtdW
)/sizeof(WCHAR
));
1397 static HRESULT WINAPI
SAXLexicalHandler_startEntity(ISAXLexicalHandler
*iface
, const WCHAR
*name
, int len
)
1399 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1400 FIXME("(%p)->(%s): stub\n", This
, debugstr_wn(name
, len
));
1404 static HRESULT WINAPI
SAXLexicalHandler_endEntity(ISAXLexicalHandler
*iface
, const WCHAR
*name
, int len
)
1406 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1407 FIXME("(%p)->(%s): stub\n", This
, debugstr_wn(name
, len
));
1411 static HRESULT WINAPI
SAXLexicalHandler_startCDATA(ISAXLexicalHandler
*iface
)
1413 static const WCHAR scdataW
[] = {'<','!','[','C','D','A','T','A','['};
1414 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1416 TRACE("(%p)\n", This
);
1418 write_node_indent(This
);
1419 write_output_buffer(This
->buffer
, scdataW
, sizeof(scdataW
)/sizeof(WCHAR
));
1425 static HRESULT WINAPI
SAXLexicalHandler_endCDATA(ISAXLexicalHandler
*iface
)
1427 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1428 static const WCHAR ecdataW
[] = {']',']','>'};
1430 TRACE("(%p)\n", This
);
1432 write_output_buffer(This
->buffer
, ecdataW
, sizeof(ecdataW
)/sizeof(WCHAR
));
1433 This
->cdata
= FALSE
;
1438 static HRESULT WINAPI
SAXLexicalHandler_comment(ISAXLexicalHandler
*iface
, const WCHAR
*chars
, int nchars
)
1440 mxwriter
*This
= impl_from_ISAXLexicalHandler( iface
);
1441 static const WCHAR copenW
[] = {'<','!','-','-'};
1442 static const WCHAR ccloseW
[] = {'-','-','>','\r','\n'};
1444 TRACE("(%p)->(%s:%d)\n", This
, debugstr_wn(chars
, nchars
), nchars
);
1446 if (!chars
) return E_INVALIDARG
;
1448 close_element_starttag(This
);
1449 write_node_indent(This
);
1451 write_output_buffer(This
->buffer
, copenW
, sizeof(copenW
)/sizeof(WCHAR
));
1453 write_output_buffer(This
->buffer
, chars
, nchars
);
1454 write_output_buffer(This
->buffer
, ccloseW
, sizeof(ccloseW
)/sizeof(WCHAR
));
1459 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl
=
1461 SAXLexicalHandler_QueryInterface
,
1462 SAXLexicalHandler_AddRef
,
1463 SAXLexicalHandler_Release
,
1464 SAXLexicalHandler_startDTD
,
1465 SAXLexicalHandler_endDTD
,
1466 SAXLexicalHandler_startEntity
,
1467 SAXLexicalHandler_endEntity
,
1468 SAXLexicalHandler_startCDATA
,
1469 SAXLexicalHandler_endCDATA
,
1470 SAXLexicalHandler_comment
1473 /*** ISAXDeclHandler ***/
1474 static HRESULT WINAPI
SAXDeclHandler_QueryInterface(ISAXDeclHandler
*iface
,
1475 REFIID riid
, void **obj
)
1477 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1478 return IMXWriter_QueryInterface(&This
->IMXWriter_iface
, riid
, obj
);
1481 static ULONG WINAPI
SAXDeclHandler_AddRef(ISAXDeclHandler
*iface
)
1483 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1484 return IMXWriter_AddRef(&This
->IMXWriter_iface
);
1487 static ULONG WINAPI
SAXDeclHandler_Release(ISAXDeclHandler
*iface
)
1489 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1490 return IMXWriter_Release(&This
->IMXWriter_iface
);
1493 static HRESULT WINAPI
SAXDeclHandler_elementDecl(ISAXDeclHandler
*iface
,
1494 const WCHAR
*name
, int n_name
, const WCHAR
*model
, int n_model
)
1496 static const WCHAR elementW
[] = {'<','!','E','L','E','M','E','N','T',' '};
1497 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1499 TRACE("(%p)->(%s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1500 debugstr_wn(model
, n_model
), n_model
);
1502 if (!name
|| !model
) return E_INVALIDARG
;
1504 write_output_buffer(This
->buffer
, elementW
, sizeof(elementW
)/sizeof(WCHAR
));
1506 write_output_buffer(This
->buffer
, name
, n_name
);
1507 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1510 write_output_buffer(This
->buffer
, model
, n_model
);
1511 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1516 static HRESULT WINAPI
SAXDeclHandler_attributeDecl(ISAXDeclHandler
*iface
,
1517 const WCHAR
*element
, int n_element
, const WCHAR
*attr
, int n_attr
,
1518 const WCHAR
*type
, int n_type
, const WCHAR
*Default
, int n_default
,
1519 const WCHAR
*value
, int n_value
)
1521 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1522 static const WCHAR attlistW
[] = {'<','!','A','T','T','L','I','S','T',' '};
1523 static const WCHAR closetagW
[] = {'>','\r','\n'};
1525 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This
, debugstr_wn(element
, n_element
), n_element
,
1526 debugstr_wn(attr
, n_attr
), n_attr
, debugstr_wn(type
, n_type
), n_type
, debugstr_wn(Default
, n_default
), n_default
,
1527 debugstr_wn(value
, n_value
), n_value
);
1529 write_output_buffer(This
->buffer
, attlistW
, sizeof(attlistW
)/sizeof(WCHAR
));
1531 write_output_buffer(This
->buffer
, element
, n_element
);
1532 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1536 write_output_buffer(This
->buffer
, attr
, n_attr
);
1537 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1541 write_output_buffer(This
->buffer
, type
, n_type
);
1542 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1546 write_output_buffer(This
->buffer
, Default
, n_default
);
1547 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1551 write_output_buffer_quoted(This
->buffer
, value
, n_value
);
1553 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1558 static HRESULT WINAPI
SAXDeclHandler_internalEntityDecl(ISAXDeclHandler
*iface
,
1559 const WCHAR
*name
, int n_name
, const WCHAR
*value
, int n_value
)
1561 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1563 TRACE("(%p)->(%s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1564 debugstr_wn(value
, n_value
), n_value
);
1566 if (!name
|| !value
) return E_INVALIDARG
;
1568 write_output_buffer(This
->buffer
, entityW
, sizeof(entityW
)/sizeof(WCHAR
));
1570 write_output_buffer(This
->buffer
, name
, n_name
);
1571 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1575 write_output_buffer_quoted(This
->buffer
, value
, n_value
);
1577 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1582 static HRESULT WINAPI
SAXDeclHandler_externalEntityDecl(ISAXDeclHandler
*iface
,
1583 const WCHAR
*name
, int n_name
, const WCHAR
*publicId
, int n_publicId
,
1584 const WCHAR
*systemId
, int n_systemId
)
1586 static const WCHAR publicW
[] = {'P','U','B','L','I','C',' '};
1587 static const WCHAR systemW
[] = {'S','Y','S','T','E','M',' '};
1588 mxwriter
*This
= impl_from_ISAXDeclHandler( iface
);
1590 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This
, debugstr_wn(name
, n_name
), n_name
,
1591 debugstr_wn(publicId
, n_publicId
), n_publicId
, debugstr_wn(systemId
, n_systemId
), n_systemId
);
1593 if (!name
) return E_INVALIDARG
;
1594 if (publicId
&& !systemId
) return E_INVALIDARG
;
1595 if (!publicId
&& !systemId
) return E_INVALIDARG
;
1597 write_output_buffer(This
->buffer
, entityW
, sizeof(entityW
)/sizeof(WCHAR
));
1599 write_output_buffer(This
->buffer
, name
, n_name
);
1600 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1605 write_output_buffer(This
->buffer
, publicW
, sizeof(publicW
)/sizeof(WCHAR
));
1606 write_output_buffer_quoted(This
->buffer
, publicId
, n_publicId
);
1607 write_output_buffer(This
->buffer
, spaceW
, sizeof(spaceW
)/sizeof(WCHAR
));
1608 write_output_buffer_quoted(This
->buffer
, systemId
, n_systemId
);
1612 write_output_buffer(This
->buffer
, systemW
, sizeof(systemW
)/sizeof(WCHAR
));
1613 write_output_buffer_quoted(This
->buffer
, systemId
, n_systemId
);
1616 write_output_buffer(This
->buffer
, closetagW
, sizeof(closetagW
)/sizeof(WCHAR
));
1621 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl
= {
1622 SAXDeclHandler_QueryInterface
,
1623 SAXDeclHandler_AddRef
,
1624 SAXDeclHandler_Release
,
1625 SAXDeclHandler_elementDecl
,
1626 SAXDeclHandler_attributeDecl
,
1627 SAXDeclHandler_internalEntityDecl
,
1628 SAXDeclHandler_externalEntityDecl
1631 static const tid_t mxwriter_iface_tids
[] = {
1636 static dispex_static_data_t mxwriter_dispex
= {
1643 HRESULT
MXWriter_create(MSXML_VERSION version
, IUnknown
*outer
, void **ppObj
)
1645 static const WCHAR version10W
[] = {'1','.','0',0};
1649 TRACE("(%p, %p)\n", outer
, ppObj
);
1651 if (outer
) FIXME("support aggregation, outer\n");
1653 This
= heap_alloc( sizeof (*This
) );
1655 return E_OUTOFMEMORY
;
1657 This
->IMXWriter_iface
.lpVtbl
= &MXWriterVtbl
;
1658 This
->ISAXContentHandler_iface
.lpVtbl
= &SAXContentHandlerVtbl
;
1659 This
->ISAXLexicalHandler_iface
.lpVtbl
= &SAXLexicalHandlerVtbl
;
1660 This
->ISAXDeclHandler_iface
.lpVtbl
= &SAXDeclHandlerVtbl
;
1662 This
->class_version
= version
;
1664 This
->props
[MXWriter_BOM
] = VARIANT_TRUE
;
1665 This
->props
[MXWriter_DisableEscaping
] = VARIANT_FALSE
;
1666 This
->props
[MXWriter_Indent
] = VARIANT_FALSE
;
1667 This
->props
[MXWriter_OmitXmlDecl
] = VARIANT_FALSE
;
1668 This
->props
[MXWriter_Standalone
] = VARIANT_FALSE
;
1669 This
->prop_changed
= FALSE
;
1670 This
->encoding
= SysAllocString(utf16W
);
1671 This
->version
= SysAllocString(version10W
);
1672 This
->xml_enc
= XmlEncoding_UTF16
;
1674 This
->element
= NULL
;
1675 This
->cdata
= FALSE
;
1678 This
->newline
= FALSE
;
1681 This
->dest_written
= 0;
1683 hr
= alloc_output_buffer(This
->xml_enc
, &This
->buffer
);
1685 SysFreeString(This
->encoding
);
1686 SysFreeString(This
->version
);
1691 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IMXWriter_iface
, &mxwriter_dispex
);
1693 *ppObj
= &This
->IMXWriter_iface
;
1695 TRACE("returning iface %p\n", *ppObj
);
1700 static HRESULT WINAPI
MXAttributes_QueryInterface(IMXAttributes
*iface
, REFIID riid
, void **ppObj
)
1702 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1704 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid( riid
), ppObj
);
1708 if ( IsEqualGUID( riid
, &IID_IUnknown
) ||
1709 IsEqualGUID( riid
, &IID_IDispatch
) ||
1710 IsEqualGUID( riid
, &IID_IMXAttributes
))
1714 else if ( IsEqualGUID( riid
, &IID_ISAXAttributes
))
1716 *ppObj
= &This
->ISAXAttributes_iface
;
1718 else if ( IsEqualGUID( riid
, &IID_IVBSAXAttributes
))
1720 *ppObj
= &This
->IVBSAXAttributes_iface
;
1722 else if (dispex_query_interface(&This
->dispex
, riid
, ppObj
))
1724 return *ppObj
? S_OK
: E_NOINTERFACE
;
1728 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
1729 return E_NOINTERFACE
;
1732 IMXAttributes_AddRef( iface
);
1737 static ULONG WINAPI
MXAttributes_AddRef(IMXAttributes
*iface
)
1739 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1740 ULONG ref
= InterlockedIncrement( &This
->ref
);
1741 TRACE("(%p)->(%d)\n", This
, ref
);
1745 static ULONG WINAPI
MXAttributes_Release(IMXAttributes
*iface
)
1747 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1748 LONG ref
= InterlockedDecrement( &This
->ref
);
1750 TRACE("(%p)->(%d)\n", This
, ref
);
1756 for (i
= 0; i
< This
->length
; i
++)
1758 SysFreeString(This
->attr
[i
].qname
);
1759 SysFreeString(This
->attr
[i
].local
);
1760 SysFreeString(This
->attr
[i
].uri
);
1761 SysFreeString(This
->attr
[i
].type
);
1762 SysFreeString(This
->attr
[i
].value
);
1765 release_dispex(&This
->dispex
);
1766 heap_free(This
->attr
);
1773 static HRESULT WINAPI
MXAttributes_GetTypeInfoCount(IMXAttributes
*iface
, UINT
* pctinfo
)
1775 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1776 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
1779 static HRESULT WINAPI
MXAttributes_GetTypeInfo(IMXAttributes
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
1781 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1782 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
1785 static HRESULT WINAPI
MXAttributes_GetIDsOfNames(
1786 IMXAttributes
*iface
,
1788 LPOLESTR
* rgszNames
,
1793 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1794 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
,
1795 riid
, rgszNames
, cNames
, lcid
, rgDispId
);
1798 static HRESULT WINAPI
MXAttributes_Invoke(
1799 IMXAttributes
*iface
,
1800 DISPID dispIdMember
,
1804 DISPPARAMS
* pDispParams
,
1805 VARIANT
* pVarResult
,
1806 EXCEPINFO
* pExcepInfo
,
1809 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1810 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
,
1811 dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
1814 static HRESULT WINAPI
MXAttributes_addAttribute(IMXAttributes
*iface
,
1815 BSTR uri
, BSTR localName
, BSTR QName
, BSTR type
, BSTR value
)
1817 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1821 TRACE("(%p)->(%s %s %s %s %s)\n", This
, debugstr_w(uri
), debugstr_w(localName
),
1822 debugstr_w(QName
), debugstr_w(type
), debugstr_w(value
));
1824 if ((!uri
|| !localName
|| !QName
|| !type
|| !value
) && This
->class_version
!= MSXML6
)
1825 return E_INVALIDARG
;
1827 /* ensure array is large enough */
1828 hr
= mxattributes_grow(This
);
1829 if (hr
!= S_OK
) return hr
;
1831 attr
= &This
->attr
[This
->length
];
1833 attr
->qname
= SysAllocString(QName
);
1834 attr
->local
= SysAllocString(localName
);
1835 attr
->uri
= SysAllocString(uri
);
1836 attr
->type
= SysAllocString(type
? type
: emptyW
);
1837 attr
->value
= SysAllocString(value
);
1843 static HRESULT WINAPI
MXAttributes_addAttributeFromIndex(IMXAttributes
*iface
,
1844 VARIANT atts
, int index
)
1846 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1847 FIXME("(%p)->(%s %d): stub\n", This
, debugstr_variant(&atts
), index
);
1851 static HRESULT WINAPI
MXAttributes_clear(IMXAttributes
*iface
)
1853 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1856 TRACE("(%p)\n", This
);
1858 for (i
= 0; i
< This
->length
; i
++)
1860 SysFreeString(This
->attr
[i
].qname
);
1861 SysFreeString(This
->attr
[i
].local
);
1862 SysFreeString(This
->attr
[i
].uri
);
1863 SysFreeString(This
->attr
[i
].type
);
1864 SysFreeString(This
->attr
[i
].value
);
1865 memset(&This
->attr
[i
], 0, sizeof(mxattribute
));
1873 static mxattribute
*get_attribute_byindex(mxattributes
*attrs
, int index
)
1875 if (index
< 0 || index
>= attrs
->length
) return NULL
;
1876 return &attrs
->attr
[index
];
1879 static HRESULT WINAPI
MXAttributes_removeAttribute(IMXAttributes
*iface
, int index
)
1881 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1884 TRACE("(%p)->(%d)\n", This
, index
);
1886 if (!(dst
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1888 /* no need to remove last attribute, just make it inaccessible */
1889 if (index
+ 1 == This
->length
)
1895 memmove(dst
, dst
+ 1, (This
->length
-index
-1)*sizeof(*dst
));
1901 static HRESULT WINAPI
MXAttributes_setAttribute(IMXAttributes
*iface
, int index
,
1902 BSTR uri
, BSTR localName
, BSTR QName
, BSTR type
, BSTR value
)
1904 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1905 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This
, index
, debugstr_w(uri
),
1906 debugstr_w(localName
), debugstr_w(QName
), debugstr_w(type
), debugstr_w(value
));
1910 static HRESULT WINAPI
MXAttributes_setAttributes(IMXAttributes
*iface
, VARIANT atts
)
1912 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1913 FIXME("(%p)->(%s): stub\n", This
, debugstr_variant(&atts
));
1917 static HRESULT WINAPI
MXAttributes_setLocalName(IMXAttributes
*iface
, int index
,
1920 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1923 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(localName
));
1925 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1927 SysFreeString(attr
->local
);
1928 attr
->local
= SysAllocString(localName
);
1933 static HRESULT WINAPI
MXAttributes_setQName(IMXAttributes
*iface
, int index
, BSTR QName
)
1935 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1938 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(QName
));
1940 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1942 SysFreeString(attr
->qname
);
1943 attr
->qname
= SysAllocString(QName
);
1948 static HRESULT WINAPI
MXAttributes_setURI(IMXAttributes
*iface
, int index
, BSTR uri
)
1950 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1953 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(uri
));
1955 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1957 SysFreeString(attr
->uri
);
1958 attr
->uri
= SysAllocString(uri
);
1963 static HRESULT WINAPI
MXAttributes_setValue(IMXAttributes
*iface
, int index
, BSTR value
)
1965 mxattributes
*This
= impl_from_IMXAttributes( iface
);
1968 TRACE("(%p)->(%d %s)\n", This
, index
, debugstr_w(value
));
1970 if (!(attr
= get_attribute_byindex(This
, index
))) return E_INVALIDARG
;
1972 SysFreeString(attr
->value
);
1973 attr
->value
= SysAllocString(value
);
1978 static const IMXAttributesVtbl MXAttributesVtbl
= {
1979 MXAttributes_QueryInterface
,
1980 MXAttributes_AddRef
,
1981 MXAttributes_Release
,
1982 MXAttributes_GetTypeInfoCount
,
1983 MXAttributes_GetTypeInfo
,
1984 MXAttributes_GetIDsOfNames
,
1985 MXAttributes_Invoke
,
1986 MXAttributes_addAttribute
,
1987 MXAttributes_addAttributeFromIndex
,
1989 MXAttributes_removeAttribute
,
1990 MXAttributes_setAttribute
,
1991 MXAttributes_setAttributes
,
1992 MXAttributes_setLocalName
,
1993 MXAttributes_setQName
,
1994 MXAttributes_setURI
,
1995 MXAttributes_setValue
1998 static HRESULT WINAPI
SAXAttributes_QueryInterface(ISAXAttributes
*iface
, REFIID riid
, void **ppObj
)
2000 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2001 return IMXAttributes_QueryInterface(&This
->IMXAttributes_iface
, riid
, ppObj
);
2004 static ULONG WINAPI
SAXAttributes_AddRef(ISAXAttributes
*iface
)
2006 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2007 return IMXAttributes_AddRef(&This
->IMXAttributes_iface
);
2010 static ULONG WINAPI
SAXAttributes_Release(ISAXAttributes
*iface
)
2012 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2013 return IMXAttributes_Release(&This
->IMXAttributes_iface
);
2016 static HRESULT WINAPI
SAXAttributes_getLength(ISAXAttributes
*iface
, int *length
)
2018 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2019 TRACE("(%p)->(%p)\n", This
, length
);
2021 if (!length
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2024 *length
= This
->length
;
2029 static HRESULT WINAPI
SAXAttributes_getURI(ISAXAttributes
*iface
, int index
, const WCHAR
**uri
,
2032 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2034 TRACE("(%p)->(%d %p %p)\n", This
, index
, uri
, len
);
2036 if (index
>= This
->length
|| index
< 0) return E_INVALIDARG
;
2037 if (!uri
|| !len
) return E_POINTER
;
2039 *len
= SysStringLen(This
->attr
[index
].uri
);
2040 *uri
= This
->attr
[index
].uri
;
2045 static HRESULT WINAPI
SAXAttributes_getLocalName(ISAXAttributes
*iface
, int index
, const WCHAR
**name
,
2048 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2050 TRACE("(%p)->(%d %p %p)\n", This
, index
, name
, len
);
2052 if (index
>= This
->length
|| index
< 0) return E_INVALIDARG
;
2053 if (!name
|| !len
) return E_POINTER
;
2055 *len
= SysStringLen(This
->attr
[index
].local
);
2056 *name
= This
->attr
[index
].local
;
2061 static HRESULT WINAPI
SAXAttributes_getQName(ISAXAttributes
*iface
, int index
, const WCHAR
**qname
, int *length
)
2063 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2065 TRACE("(%p)->(%d %p %p)\n", This
, index
, qname
, length
);
2067 if (index
>= This
->length
) return E_INVALIDARG
;
2068 if (!qname
|| !length
) return E_POINTER
;
2070 *qname
= This
->attr
[index
].qname
;
2071 *length
= SysStringLen(This
->attr
[index
].qname
);
2076 static HRESULT WINAPI
SAXAttributes_getName(ISAXAttributes
*iface
, int index
, const WCHAR
**uri
, int *uri_len
,
2077 const WCHAR
**local
, int *local_len
, const WCHAR
**qname
, int *qname_len
)
2079 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2081 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This
, index
, uri
, uri_len
, local
, local_len
, qname
, qname_len
);
2083 if (index
>= This
->length
|| index
< 0)
2084 return E_INVALIDARG
;
2086 if (!uri
|| !uri_len
|| !local
|| !local_len
|| !qname
|| !qname_len
)
2089 *uri_len
= SysStringLen(This
->attr
[index
].uri
);
2090 *uri
= This
->attr
[index
].uri
;
2092 *local_len
= SysStringLen(This
->attr
[index
].local
);
2093 *local
= This
->attr
[index
].local
;
2095 *qname_len
= SysStringLen(This
->attr
[index
].qname
);
2096 *qname
= This
->attr
[index
].qname
;
2098 TRACE("(%s, %s, %s)\n", debugstr_w(*uri
), debugstr_w(*local
), debugstr_w(*qname
));
2103 static HRESULT WINAPI
SAXAttributes_getIndexFromName(ISAXAttributes
*iface
, const WCHAR
*uri
, int uri_len
,
2104 const WCHAR
*name
, int len
, int *index
)
2106 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2109 TRACE("(%p)->(%s:%d %s:%d %p)\n", This
, debugstr_wn(uri
, uri_len
), uri_len
,
2110 debugstr_wn(name
, len
), len
, index
);
2112 if (!index
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2115 if (!uri
|| !name
|| !index
) return E_INVALIDARG
;
2117 for (i
= 0; i
< This
->length
; i
++)
2119 if (uri_len
!= SysStringLen(This
->attr
[i
].uri
)) continue;
2120 if (strncmpW(uri
, This
->attr
[i
].uri
, uri_len
)) continue;
2122 if (len
!= SysStringLen(This
->attr
[i
].local
)) continue;
2123 if (strncmpW(name
, This
->attr
[i
].local
, len
)) continue;
2129 return E_INVALIDARG
;
2132 static HRESULT WINAPI
SAXAttributes_getIndexFromQName(ISAXAttributes
*iface
, const WCHAR
*qname
,
2133 int len
, int *index
)
2135 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2138 TRACE("(%p)->(%s:%d %p)\n", This
, debugstr_wn(qname
, len
), len
, index
);
2140 if (!index
&& (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2143 if (!qname
|| !index
|| !len
) return E_INVALIDARG
;
2145 for (i
= 0; i
< This
->length
; i
++)
2147 if (len
!= SysStringLen(This
->attr
[i
].qname
)) continue;
2148 if (strncmpW(qname
, This
->attr
[i
].qname
, len
)) continue;
2154 return E_INVALIDARG
;
2157 static HRESULT WINAPI
SAXAttributes_getType(ISAXAttributes
*iface
, int index
, const WCHAR
**type
,
2160 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2162 TRACE("(%p)->(%d %p %p)\n", This
, index
, type
, len
);
2164 if (index
>= This
->length
) return E_INVALIDARG
;
2166 if ((!type
|| !len
) && (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2169 *type
= This
->attr
[index
].type
;
2170 *len
= SysStringLen(This
->attr
[index
].type
);
2175 static HRESULT WINAPI
SAXAttributes_getTypeFromName(ISAXAttributes
*iface
, const WCHAR
* pUri
, int nUri
,
2176 const WCHAR
* pLocalName
, int nLocalName
, const WCHAR
** pType
, int * nType
)
2178 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2179 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This
, debugstr_wn(pUri
, nUri
), nUri
,
2180 debugstr_wn(pLocalName
, nLocalName
), nLocalName
, pType
, nType
);
2184 static HRESULT WINAPI
SAXAttributes_getTypeFromQName(ISAXAttributes
*iface
, const WCHAR
* pQName
,
2185 int nQName
, const WCHAR
** pType
, int * nType
)
2187 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2188 FIXME("(%p)->(%s:%d %p %p): stub\n", This
, debugstr_wn(pQName
, nQName
), nQName
, pType
, nType
);
2192 static HRESULT WINAPI
SAXAttributes_getValue(ISAXAttributes
*iface
, int index
, const WCHAR
**value
,
2195 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2197 TRACE("(%p)->(%d %p %p)\n", This
, index
, value
, len
);
2199 if (index
>= This
->length
) return E_INVALIDARG
;
2201 if ((!value
|| !len
) && (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
))
2204 *value
= This
->attr
[index
].value
;
2205 *len
= SysStringLen(This
->attr
[index
].value
);
2210 static HRESULT WINAPI
SAXAttributes_getValueFromName(ISAXAttributes
*iface
, const WCHAR
*uri
,
2211 int uri_len
, const WCHAR
*name
, int name_len
, const WCHAR
**value
, int *value_len
)
2213 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2217 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This
, debugstr_wn(uri
, uri_len
), uri_len
,
2218 debugstr_wn(name
, name_len
), name_len
, value
, value_len
);
2220 if (!uri
|| !name
|| !value
|| !value_len
)
2221 return (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
) ? E_POINTER
: E_INVALIDARG
;
2223 hr
= ISAXAttributes_getIndexFromName(iface
, uri
, uri_len
, name
, name_len
, &index
);
2225 hr
= ISAXAttributes_getValue(iface
, index
, value
, value_len
);
2230 static HRESULT WINAPI
SAXAttributes_getValueFromQName(ISAXAttributes
*iface
, const WCHAR
*qname
,
2231 int qname_len
, const WCHAR
**value
, int *value_len
)
2233 mxattributes
*This
= impl_from_ISAXAttributes( iface
);
2237 TRACE("(%p)->(%s:%d %p %p)\n", This
, debugstr_wn(qname
, qname_len
), qname_len
, value
, value_len
);
2239 if (!qname
|| !value
|| !value_len
)
2240 return (This
->class_version
== MSXML_DEFAULT
|| This
->class_version
== MSXML3
) ? E_POINTER
: E_INVALIDARG
;
2242 hr
= ISAXAttributes_getIndexFromQName(iface
, qname
, qname_len
, &index
);
2244 hr
= ISAXAttributes_getValue(iface
, index
, value
, value_len
);
2249 static const ISAXAttributesVtbl SAXAttributesVtbl
= {
2250 SAXAttributes_QueryInterface
,
2251 SAXAttributes_AddRef
,
2252 SAXAttributes_Release
,
2253 SAXAttributes_getLength
,
2254 SAXAttributes_getURI
,
2255 SAXAttributes_getLocalName
,
2256 SAXAttributes_getQName
,
2257 SAXAttributes_getName
,
2258 SAXAttributes_getIndexFromName
,
2259 SAXAttributes_getIndexFromQName
,
2260 SAXAttributes_getType
,
2261 SAXAttributes_getTypeFromName
,
2262 SAXAttributes_getTypeFromQName
,
2263 SAXAttributes_getValue
,
2264 SAXAttributes_getValueFromName
,
2265 SAXAttributes_getValueFromQName
2268 static HRESULT WINAPI
VBSAXAttributes_QueryInterface(
2269 IVBSAXAttributes
* iface
,
2273 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2274 TRACE("%p %s %p\n", This
, debugstr_guid(riid
), ppvObject
);
2275 return ISAXAttributes_QueryInterface(&This
->ISAXAttributes_iface
, riid
, ppvObject
);
2278 static ULONG WINAPI
VBSAXAttributes_AddRef(IVBSAXAttributes
* iface
)
2280 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2281 return ISAXAttributes_AddRef(&This
->ISAXAttributes_iface
);
2284 static ULONG WINAPI
VBSAXAttributes_Release(IVBSAXAttributes
* iface
)
2286 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2287 return ISAXAttributes_Release(&This
->ISAXAttributes_iface
);
2290 static HRESULT WINAPI
VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes
*iface
, UINT
* pctinfo
)
2292 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2294 TRACE("(%p)->(%p)\n", This
, pctinfo
);
2301 static HRESULT WINAPI
VBSAXAttributes_GetTypeInfo(
2302 IVBSAXAttributes
*iface
,
2303 UINT iTInfo
, LCID lcid
, ITypeInfo
** ppTInfo
)
2305 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2306 TRACE("(%p)->(%u %u %p)\n", This
, iTInfo
, lcid
, ppTInfo
);
2307 return get_typeinfo(IVBSAXAttributes_tid
, ppTInfo
);
2310 static HRESULT WINAPI
VBSAXAttributes_GetIDsOfNames(
2311 IVBSAXAttributes
*iface
,
2313 LPOLESTR
* rgszNames
,
2318 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2319 ITypeInfo
*typeinfo
;
2322 TRACE("(%p)->(%s %p %u %u %p)\n", This
, debugstr_guid(riid
), rgszNames
, cNames
,
2325 if(!rgszNames
|| cNames
== 0 || !rgDispId
)
2326 return E_INVALIDARG
;
2328 hr
= get_typeinfo(IVBSAXAttributes_tid
, &typeinfo
);
2331 hr
= ITypeInfo_GetIDsOfNames(typeinfo
, rgszNames
, cNames
, rgDispId
);
2332 ITypeInfo_Release(typeinfo
);
2338 static HRESULT WINAPI
VBSAXAttributes_Invoke(
2339 IVBSAXAttributes
*iface
,
2340 DISPID dispIdMember
,
2344 DISPPARAMS
* pDispParams
,
2345 VARIANT
* pVarResult
,
2346 EXCEPINFO
* pExcepInfo
,
2349 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2350 ITypeInfo
*typeinfo
;
2353 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This
, dispIdMember
, debugstr_guid(riid
),
2354 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2356 hr
= get_typeinfo(IVBSAXAttributes_tid
, &typeinfo
);
2359 hr
= ITypeInfo_Invoke(typeinfo
, &This
->IVBSAXAttributes_iface
, dispIdMember
, wFlags
,
2360 pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
2361 ITypeInfo_Release(typeinfo
);
2367 static HRESULT WINAPI
VBSAXAttributes_get_length(IVBSAXAttributes
* iface
, int *len
)
2369 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2370 return ISAXAttributes_getLength(&This
->ISAXAttributes_iface
, len
);
2373 static HRESULT WINAPI
VBSAXAttributes_getURI(IVBSAXAttributes
* iface
, int index
, BSTR
*uri
)
2375 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2378 return ISAXAttributes_getURI(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)uri
, &len
);
2381 static HRESULT WINAPI
VBSAXAttributes_getLocalName(IVBSAXAttributes
* iface
, int index
, BSTR
*name
)
2383 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2386 return ISAXAttributes_getLocalName(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)name
, &len
);
2389 static HRESULT WINAPI
VBSAXAttributes_getQName(IVBSAXAttributes
* iface
, int index
, BSTR
*qname
)
2391 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2394 return ISAXAttributes_getQName(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)qname
, &len
);
2397 static HRESULT WINAPI
VBSAXAttributes_getIndexFromName(IVBSAXAttributes
* iface
, BSTR uri
, BSTR name
, int *index
)
2399 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2400 return ISAXAttributes_getIndexFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2401 name
, SysStringLen(name
), index
);
2404 static HRESULT WINAPI
VBSAXAttributes_getIndexFromQName(IVBSAXAttributes
* iface
, BSTR qname
, int *index
)
2406 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2407 return ISAXAttributes_getIndexFromQName(&This
->ISAXAttributes_iface
, qname
,
2408 SysStringLen(qname
), index
);
2411 static HRESULT WINAPI
VBSAXAttributes_getType(IVBSAXAttributes
* iface
, int index
,BSTR
*type
)
2413 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2416 return ISAXAttributes_getType(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)type
, &len
);
2419 static HRESULT WINAPI
VBSAXAttributes_getTypeFromName(IVBSAXAttributes
* iface
, BSTR uri
,
2420 BSTR name
, BSTR
*type
)
2422 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2425 return ISAXAttributes_getTypeFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2426 name
, SysStringLen(name
), (const WCHAR
**)type
, &len
);
2429 static HRESULT WINAPI
VBSAXAttributes_getTypeFromQName(IVBSAXAttributes
* iface
, BSTR qname
, BSTR
*type
)
2431 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2434 return ISAXAttributes_getTypeFromQName(&This
->ISAXAttributes_iface
, qname
, SysStringLen(qname
),
2435 (const WCHAR
**)type
, &len
);
2438 static HRESULT WINAPI
VBSAXAttributes_getValue(IVBSAXAttributes
* iface
, int index
, BSTR
*value
)
2440 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2443 return ISAXAttributes_getValue(&This
->ISAXAttributes_iface
, index
, (const WCHAR
**)value
, &len
);
2446 static HRESULT WINAPI
VBSAXAttributes_getValueFromName(IVBSAXAttributes
* iface
, BSTR uri
, BSTR name
,
2449 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2452 return ISAXAttributes_getValueFromName(&This
->ISAXAttributes_iface
, uri
, SysStringLen(uri
),
2453 name
, SysStringLen(name
), (const WCHAR
**)value
, &len
);
2456 static HRESULT WINAPI
VBSAXAttributes_getValueFromQName(IVBSAXAttributes
* iface
, BSTR qname
, BSTR
*value
)
2458 mxattributes
*This
= impl_from_IVBSAXAttributes( iface
);
2461 return ISAXAttributes_getValueFromQName(&This
->ISAXAttributes_iface
, qname
, SysStringLen(qname
),
2462 (const WCHAR
**)value
, &len
);
2465 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl
=
2467 VBSAXAttributes_QueryInterface
,
2468 VBSAXAttributes_AddRef
,
2469 VBSAXAttributes_Release
,
2470 VBSAXAttributes_GetTypeInfoCount
,
2471 VBSAXAttributes_GetTypeInfo
,
2472 VBSAXAttributes_GetIDsOfNames
,
2473 VBSAXAttributes_Invoke
,
2474 VBSAXAttributes_get_length
,
2475 VBSAXAttributes_getURI
,
2476 VBSAXAttributes_getLocalName
,
2477 VBSAXAttributes_getQName
,
2478 VBSAXAttributes_getIndexFromName
,
2479 VBSAXAttributes_getIndexFromQName
,
2480 VBSAXAttributes_getType
,
2481 VBSAXAttributes_getTypeFromName
,
2482 VBSAXAttributes_getTypeFromQName
,
2483 VBSAXAttributes_getValue
,
2484 VBSAXAttributes_getValueFromName
,
2485 VBSAXAttributes_getValueFromQName
2488 static const tid_t mxattrs_iface_tids
[] = {
2493 static dispex_static_data_t mxattrs_dispex
= {
2500 HRESULT
SAXAttributes_create(MSXML_VERSION version
, IUnknown
*outer
, void **ppObj
)
2502 static const int default_count
= 10;
2505 TRACE("(%p, %p)\n", outer
, ppObj
);
2507 This
= heap_alloc( sizeof (*This
) );
2509 return E_OUTOFMEMORY
;
2511 This
->IMXAttributes_iface
.lpVtbl
= &MXAttributesVtbl
;
2512 This
->ISAXAttributes_iface
.lpVtbl
= &SAXAttributesVtbl
;
2513 This
->IVBSAXAttributes_iface
.lpVtbl
= &VBSAXAttributesVtbl
;
2516 This
->class_version
= version
;
2518 This
->attr
= heap_alloc(default_count
*sizeof(mxattribute
));
2520 This
->allocated
= default_count
;
2522 *ppObj
= &This
->IMXAttributes_iface
;
2524 init_dispex(&This
->dispex
, (IUnknown
*)&This
->IMXAttributes_iface
, &mxattrs_dispex
);
2526 TRACE("returning iface %p\n", *ppObj
);