/*
* MXWriter implementation
*
- * Copyright 2011-2012 Nikolay Sivov for CodeWeavers
+ * Copyright 2011-2014, 2016 Nikolay Sivov for CodeWeavers
* Copyright 2011 Thomas Mullaly
*
* This library is free software; you can redistribute it and/or
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define WIN32_NO_STATUS
-#define _INC_WINDOWS
-
#define COBJMACROS
-#include <config.h>
+#include "config.h"
-//#include <stdarg.h>
+#include <stdarg.h>
#ifdef HAVE_LIBXML2
# include <libxml/parser.h>
#endif
-#include <windef.h>
-#include <winbase.h>
-#include <ole2.h>
+#include "windef.h"
+#include "winbase.h"
+#include "ole2.h"
-#include <msxml6.h>
+#include "msxml6.h"
-#include <wine/debug.h>
+#include "wine/debug.h"
+#include "wine/list.h"
#include "msxml_private.h"
static const WCHAR spaceW[] = {' '};
static const WCHAR quotW[] = {'\"'};
static const WCHAR closetagW[] = {'>','\r','\n'};
+static const WCHAR crlfW[] = {'\r','\n'};
+static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
+static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
+static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
/* should be ordered as encoding names are sorted */
typedef enum
{ utf8W, XmlEncoding_UTF8, CP_UTF8 }
};
-typedef enum
-{
- OutputBuffer_Native = 0x001,
- OutputBuffer_Encoded = 0x010,
- OutputBuffer_Both = 0x100
-} output_mode;
-
typedef enum
{
MXWriter_BOM = 0,
typedef struct
{
+ struct list entry;
char *data;
unsigned int allocated;
unsigned int written;
typedef struct
{
- encoded_buffer utf16;
encoded_buffer encoded;
UINT code_page;
+ UINT utf16_total; /* total number of bytes written since last buffer reinitialization */
+ struct list blocks; /* only used when output was not set, for BSTR case */
} output_buffer;
typedef struct
ISAXContentHandler ISAXContentHandler_iface;
ISAXLexicalHandler ISAXLexicalHandler_iface;
ISAXDeclHandler ISAXDeclHandler_iface;
+ ISAXDTDHandler ISAXDTDHandler_iface;
+ ISAXErrorHandler ISAXErrorHandler_iface;
+ IVBSAXDeclHandler IVBSAXDeclHandler_iface;
+ IVBSAXLexicalHandler IVBSAXLexicalHandler_iface;
+ IVBSAXContentHandler IVBSAXContentHandler_iface;
+ IVBSAXDTDHandler IVBSAXDTDHandler_iface;
+ IVBSAXErrorHandler IVBSAXErrorHandler_iface;
LONG ref;
MSXML_VERSION class_version;
BOOL prop_changed;
BOOL cdata;
+ BOOL text; /* last node was text node, so we shouldn't indent next node */
+ BOOL newline; /* newline was already added as a part of previous call */
+ UINT indent; /* indentation level for next node */
+
BSTR version;
BSTR encoding; /* exact property value */
BSTR element;
IStream *dest;
- ULONG dest_written;
- output_buffer *buffer;
+ output_buffer buffer;
} mxwriter;
typedef struct
int min, max, n, c;
min = 0;
- max = sizeof(xml_encoding_map)/sizeof(struct xml_encoding_data) - 1;
+ max = ARRAY_SIZE(xml_encoding_map) - 1;
while (min <= max)
{
static HRESULT init_encoded_buffer(encoded_buffer *buffer)
{
- const int initial_len = 0x2000;
+ const int initial_len = 0x1000;
buffer->data = heap_alloc(initial_len);
if (!buffer->data) return E_OUTOFMEMORY;
return S_OK;
}
-static HRESULT alloc_output_buffer(xml_encoding encoding, output_buffer **buffer)
+static HRESULT init_output_buffer(xml_encoding encoding, output_buffer *buffer)
{
- output_buffer *ret;
HRESULT hr;
- ret = heap_alloc(sizeof(*ret));
- if (!ret) return E_OUTOFMEMORY;
-
- hr = get_code_page(encoding, &ret->code_page);
- if (hr != S_OK) {
- heap_free(ret);
+ hr = get_code_page(encoding, &buffer->code_page);
+ if (hr != S_OK)
return hr;
- }
- hr = init_encoded_buffer(&ret->utf16);
- if (hr != S_OK) {
- heap_free(ret);
+ hr = init_encoded_buffer(&buffer->encoded);
+ if (hr != S_OK)
return hr;
- }
-
- /* currently we always create a default output buffer that is UTF-16 only,
- but it's possible to allocate with specific encoding too */
- if (encoding != XmlEncoding_UTF16) {
- hr = init_encoded_buffer(&ret->encoded);
- if (hr != S_OK) {
- free_encoded_buffer(&ret->utf16);
- heap_free(ret);
- return hr;
- }
- }
- else
- memset(&ret->encoded, 0, sizeof(ret->encoded));
- *buffer = ret;
+ list_init(&buffer->blocks);
+ buffer->utf16_total = 0;
return S_OK;
}
static void free_output_buffer(output_buffer *buffer)
{
+ encoded_buffer *cur, *cur2;
+
free_encoded_buffer(&buffer->encoded);
- free_encoded_buffer(&buffer->utf16);
- heap_free(buffer);
-}
-static void grow_buffer(encoded_buffer *buffer, int length)
-{
- /* grow if needed, plus 4 bytes to be sure null terminator will fit in */
- if (buffer->allocated < buffer->written + length + 4)
+ LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &buffer->blocks, encoded_buffer, entry)
{
- int grown_size = max(2*buffer->allocated, buffer->allocated + length);
- buffer->data = heap_realloc(buffer->data, grown_size);
- buffer->allocated = grown_size;
+ list_remove(&cur->entry);
+ free_encoded_buffer(cur);
+ heap_free(cur);
}
}
-static HRESULT write_output_buffer_mode(output_buffer *buffer, output_mode mode, const WCHAR *data, int len)
+static HRESULT write_output_buffer(mxwriter *writer, const WCHAR *data, int len)
{
- int length;
- char *ptr;
+ output_buffer *buffer = &writer->buffer;
+ encoded_buffer *buff;
+ unsigned int written;
+ int src_len;
+
+ if (!len || !*data)
+ return S_OK;
+
+ src_len = len == -1 ? strlenW(data) : len;
+ if (writer->dest)
+ {
+ buff = &buffer->encoded;
- if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
- if (buffer->code_page != ~0)
+ if (buffer->code_page == ~0)
+ {
+ unsigned int avail = buff->allocated - buff->written;
+
+ src_len *= sizeof(WCHAR);
+ written = min(avail, src_len);
+
+ /* fill internal buffer first */
+ if (avail)
+ {
+ memcpy(buff->data + buff->written, data, written);
+ data += written / sizeof(WCHAR);
+ buff->written += written;
+ avail -= written;
+ src_len -= written;
+ }
+
+ if (!avail)
+ {
+ IStream_Write(writer->dest, buff->data, buff->written, &written);
+ buff->written = 0;
+ if (src_len >= buff->allocated)
+ IStream_Write(writer->dest, data, src_len, &written);
+ else if (src_len)
+ {
+ memcpy(buff->data, data, src_len);
+ buff->written += src_len;
+ }
+ }
+ }
+ else
{
- length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
- grow_buffer(&buffer->encoded, length);
- ptr = buffer->encoded.data + buffer->encoded.written;
- length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
- buffer->encoded.written += len == -1 ? length-1 : length;
+ unsigned int avail = buff->allocated - buff->written;
+ int length;
+
+ length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, NULL, 0, NULL, NULL);
+ if (avail >= length)
+ {
+ length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL);
+ buff->written += length;
+ }
+ else
+ {
+ /* drain what we go so far */
+ if (buff->written)
+ {
+ IStream_Write(writer->dest, buff->data, buff->written, &written);
+ buff->written = 0;
+ avail = buff->allocated;
+ }
+
+ if (avail >= length)
+ {
+ length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL);
+ buff->written += length;
+ }
+ else
+ {
+ char *mb;
+
+ /* if current chunk is larger than total buffer size, convert it at once using temporary allocated buffer */
+ mb = heap_alloc(length);
+ if (!mb)
+ return E_OUTOFMEMORY;
+
+ length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, mb, length, NULL, NULL);
+ IStream_Write(writer->dest, mb, length, &written);
+ heap_free(mb);
+ }
+ }
}
}
+ /* When writer has no output set we have to accumulate everything to return it later in a form of BSTR.
+ To achieve that:
+
+ - fill a buffer already allocated as part of output buffer;
+ - when current buffer is full, allocate another one and switch to it; buffers themselves never grow,
+ but are linked together, with head pointing to first allocated buffer after initial one got filled;
+ - later during get_output() contents are concatenated by copying one after another to destination BSTR buffer,
+ that's returned to the client. */
+ else
+ {
+ /* select last used block */
+ if (list_empty(&buffer->blocks))
+ buff = &buffer->encoded;
+ else
+ buff = LIST_ENTRY(list_tail(&buffer->blocks), encoded_buffer, entry);
- if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
- /* WCHAR data just copied */
- length = len == -1 ? strlenW(data) : len;
- if (length)
+ src_len *= sizeof(WCHAR);
+ while (src_len)
{
- length *= sizeof(WCHAR);
+ unsigned int avail = buff->allocated - buff->written;
+ unsigned int written = min(avail, src_len);
+
+ if (avail)
+ {
+ memcpy(buff->data + buff->written, data, written);
+ buff->written += written;
+ buffer->utf16_total += written;
+ src_len -= written;
+ }
+
+ /* alloc new block if needed and retry */
+ if (src_len)
+ {
+ encoded_buffer *next = heap_alloc(sizeof(*next));
+ HRESULT hr;
- grow_buffer(&buffer->utf16, length);
- ptr = buffer->utf16.data + buffer->utf16.written;
+ if (FAILED(hr = init_encoded_buffer(next))) {
+ heap_free(next);
+ return hr;
+ }
- memcpy(ptr, data, length);
- buffer->utf16.written += length;
- ptr += length;
- /* null termination */
- memset(ptr, 0, sizeof(WCHAR));
+ list_add_tail(&buffer->blocks, &next->entry);
+ buff = next;
+ }
}
}
return S_OK;
}
-static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
-{
- return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
-}
-
-static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
+static HRESULT write_output_buffer_quoted(mxwriter *writer, const WCHAR *data, int len)
{
- write_output_buffer(buffer, quotW, 1);
- write_output_buffer(buffer, data, len);
- write_output_buffer(buffer, quotW, 1);
+ write_output_buffer(writer, quotW, 1);
+ write_output_buffer(writer, data, len);
+ write_output_buffer(writer, quotW, 1);
return S_OK;
}
/* frees buffer data, reallocates with a default lengths */
-static void close_output_buffer(mxwriter *This)
+static void close_output_buffer(mxwriter *writer)
{
- heap_free(This->buffer->utf16.data);
- heap_free(This->buffer->encoded.data);
- init_encoded_buffer(&This->buffer->utf16);
- init_encoded_buffer(&This->buffer->encoded);
- get_code_page(This->xml_enc, &This->buffer->code_page);
+ encoded_buffer *cur, *cur2;
+
+ heap_free(writer->buffer.encoded.data);
+
+ LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &writer->buffer.blocks, encoded_buffer, entry)
+ {
+ list_remove(&cur->entry);
+ free_encoded_buffer(cur);
+ heap_free(cur);
+ }
+
+ init_encoded_buffer(&writer->buffer.encoded);
+ get_code_page(writer->xml_enc, &writer->buffer.code_page);
+ writer->buffer.utf16_total = 0;
+ list_init(&writer->buffer.blocks);
}
-/* escapes special characters like:
+/* Escapes special characters like:
'<' -> "<"
'&' -> "&"
'"' -> """
'>' -> ">"
+
+ On call 'len' contains a length of 'str' in chars or -1 if it's null terminated.
+ After a call it's updated with actual new length if it wasn't -1 initially.
*/
static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
{
WCHAR *ptr, *ret;
/* default buffer size to something if length is unknown */
- conv_len = *len == -1 ? default_alloc : max(2**len, default_alloc);
+ conv_len = max(2**len, default_alloc);
ptr = ret = heap_alloc(conv_len*sizeof(WCHAR));
- while (*str && p)
+ while (p)
{
if (ptr - ret > conv_len - grow_thresh)
{
{
case '<':
memcpy(ptr, ltW, sizeof(ltW));
- ptr += sizeof(ltW)/sizeof(WCHAR);
+ ptr += ARRAY_SIZE(ltW);
break;
case '&':
memcpy(ptr, ampW, sizeof(ampW));
- ptr += sizeof(ampW)/sizeof(WCHAR);
+ ptr += ARRAY_SIZE(ampW);
break;
case '>':
memcpy(ptr, gtW, sizeof(gtW));
- ptr += sizeof(gtW)/sizeof(WCHAR);
+ ptr += ARRAY_SIZE(gtW);
break;
case '"':
if (mode == EscapeValue)
{
memcpy(ptr, equotW, sizeof(equotW));
- ptr += sizeof(equotW)/sizeof(WCHAR);
+ ptr += ARRAY_SIZE(equotW);
break;
}
/* fallthrough for text mode */
}
str++;
- if (*len != -1) p--;
+ p--;
}
- if (*len != -1) *len = ptr-ret;
+ *len = ptr-ret;
*++ptr = 0;
return ret;
}
-static void write_prolog_buffer(const mxwriter *This)
+static void write_prolog_buffer(mxwriter *writer)
{
static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='};
static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'};
static const WCHAR yesW[] = {'y','e','s','\"','?','>'};
static const WCHAR noW[] = {'n','o','\"','?','>'};
- static const WCHAR crlfW[] = {'\r','\n'};
/* version */
- write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
- write_output_buffer_quoted(This->buffer, This->version, -1);
+ write_output_buffer(writer, versionW, ARRAY_SIZE(versionW));
+ write_output_buffer_quoted(writer, writer->version, -1);
/* encoding */
- write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
+ write_output_buffer(writer, encodingW, ARRAY_SIZE(encodingW));
- /* always write UTF-16 to WCHAR buffer */
- write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
- write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
- write_output_buffer(This->buffer, quotW, 1);
+ if (writer->dest)
+ write_output_buffer(writer, writer->encoding, -1);
+ else
+ write_output_buffer(writer, utf16W, ARRAY_SIZE(utf16W) - 1);
+ write_output_buffer(writer, quotW, 1);
/* standalone */
- write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
- if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
- write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
+ write_output_buffer(writer, standaloneW, ARRAY_SIZE(standaloneW));
+ if (writer->props[MXWriter_Standalone] == VARIANT_TRUE)
+ write_output_buffer(writer, yesW, ARRAY_SIZE(yesW));
else
- write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
+ write_output_buffer(writer, noW, ARRAY_SIZE(noW));
- write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
+ write_output_buffer(writer, crlfW, ARRAY_SIZE(crlfW));
+ writer->newline = TRUE;
}
/* Attempts to the write data from the mxwriter's buffer to
* the destination stream (if there is one).
*/
-static HRESULT write_data_to_stream(mxwriter *This)
+static HRESULT write_data_to_stream(mxwriter *writer)
{
- encoded_buffer *buffer;
+ encoded_buffer *buffer = &writer->buffer.encoded;
ULONG written = 0;
- HRESULT hr;
- if (!This->dest)
+ if (!writer->dest)
return S_OK;
- if (This->xml_enc != XmlEncoding_UTF16)
- buffer = &This->buffer->encoded;
+ if (buffer->written == 0)
+ {
+ if (writer->xml_enc == XmlEncoding_UTF8)
+ IStream_Write(writer->dest, buffer->data, 0, &written);
+ }
else
- buffer = &This->buffer->utf16;
-
- if (This->dest_written > buffer->written) {
- ERR("Failed sanity check! Not sure what to do... (%d > %d)\n", This->dest_written, buffer->written);
- return E_FAIL;
- } else if (This->dest_written == buffer->written && This->xml_enc != XmlEncoding_UTF8)
- /* Windows seems to make an empty write call when the encoding is UTF-8 and
- * all the data has been written to the stream. It doesn't seem make this call
- * for any other encodings.
- */
- return S_OK;
-
- /* Write the current content from the output buffer into 'dest'.
- * TODO: Check what Windows does if the IStream doesn't write all of
- * the data we give it at once.
- */
- hr = IStream_Write(This->dest, buffer->data+This->dest_written,
- buffer->written-This->dest_written, &written);
- if (FAILED(hr)) {
- WARN("Failed to write data to IStream (0x%08x)\n", hr);
- return hr;
+ {
+ IStream_Write(writer->dest, buffer->data, buffer->written, &written);
+ buffer->written = 0;
}
- This->dest_written += written;
- return hr;
+ return S_OK;
}
/* Newly added element start tag left unclosed cause for empty elements
we have to close it differently. */
-static void close_element_starttag(const mxwriter *This)
+static void close_element_starttag(mxwriter *writer)
{
static const WCHAR gtW[] = {'>'};
- if (!This->element) return;
- write_output_buffer(This->buffer, gtW, 1);
+ if (!writer->element) return;
+ write_output_buffer(writer, gtW, 1);
+}
+
+static void write_node_indent(mxwriter *writer)
+{
+ static const WCHAR tabW[] = {'\t'};
+ int indent = writer->indent;
+
+ if (!writer->props[MXWriter_Indent] || writer->text)
+ {
+ writer->text = FALSE;
+ return;
+ }
+
+ /* This is to workaround PI output logic that always puts newline chars,
+ document prolog PI does that too. */
+ if (!writer->newline)
+ write_output_buffer(writer, crlfW, ARRAY_SIZE(crlfW));
+ while (indent--)
+ write_output_buffer(writer, tabW, 1);
+
+ writer->newline = FALSE;
+ writer->text = FALSE;
+}
+
+static inline void writer_inc_indent(mxwriter *This)
+{
+ This->indent++;
+}
+
+static inline void writer_dec_indent(mxwriter *This)
+{
+ if (This->indent) This->indent--;
+ /* depth is decreased only when element is closed, meaning it's not a text node
+ at this point */
+ This->text = FALSE;
}
static void set_element_name(mxwriter *This, const WCHAR *name, int len)
static inline void reset_output_buffer(mxwriter *This)
{
close_output_buffer(This);
- This->dest_written = 0;
}
static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface);
}
+static inline mxwriter *impl_from_IVBSAXContentHandler(IVBSAXContentHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, IVBSAXContentHandler_iface);
+}
+
static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface)
{
return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface);
}
+static inline mxwriter *impl_from_IVBSAXLexicalHandler(IVBSAXLexicalHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, IVBSAXLexicalHandler_iface);
+}
+
static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface)
{
return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface);
}
+static inline mxwriter *impl_from_IVBSAXDeclHandler(IVBSAXDeclHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, IVBSAXDeclHandler_iface);
+}
+
+static inline mxwriter *impl_from_ISAXDTDHandler(ISAXDTDHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, ISAXDTDHandler_iface);
+}
+
+static inline mxwriter *impl_from_IVBSAXDTDHandler(IVBSAXDTDHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, IVBSAXDTDHandler_iface);
+}
+
+static inline mxwriter *impl_from_ISAXErrorHandler(ISAXErrorHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, ISAXErrorHandler_iface);
+}
+
+static inline mxwriter *impl_from_IVBSAXErrorHandler(IVBSAXErrorHandler *iface)
+{
+ return CONTAINING_RECORD(iface, mxwriter, IVBSAXErrorHandler_iface);
+}
+
static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj)
{
mxwriter *This = impl_from_IMXWriter( iface );
{
*obj = &This->ISAXDeclHandler_iface;
}
+ else if ( IsEqualGUID( riid, &IID_ISAXDTDHandler ) )
+ {
+ *obj = &This->ISAXDTDHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_ISAXErrorHandler ) )
+ {
+ *obj = &This->ISAXErrorHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_IVBSAXDeclHandler ) )
+ {
+ *obj = &This->IVBSAXDeclHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_IVBSAXLexicalHandler ) )
+ {
+ *obj = &This->IVBSAXLexicalHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_IVBSAXContentHandler ) )
+ {
+ *obj = &This->IVBSAXContentHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_IVBSAXDTDHandler ) )
+ {
+ *obj = &This->IVBSAXDTDHandler_iface;
+ }
+ else if ( IsEqualGUID( riid, &IID_IVBSAXErrorHandler ) )
+ {
+ *obj = &This->IVBSAXErrorHandler_iface;
+ }
else if (dispex_query_interface(&This->dispex, riid, obj))
{
return *obj ? S_OK : E_NOINTERFACE;
{
/* Windows flushes the buffer when the interface is destroyed. */
flush_output_buffer(This);
- free_output_buffer(This->buffer);
+ free_output_buffer(&This->buffer);
if (This->dest) IStream_Release(This->dest);
SysFreeString(This->version);
SysFreeString(This->encoding);
SysFreeString(This->element);
- release_dispex(&This->dispex);
heap_free(This);
}
if (!dest) return E_POINTER;
- if (!This->dest)
+ if (This->dest)
+ {
+ /* we only support IStream output so far */
+ V_VT(dest) = VT_UNKNOWN;
+ V_UNKNOWN(dest) = (IUnknown*)This->dest;
+ IStream_AddRef(This->dest);
+ }
+ else
{
- HRESULT hr = flush_output_buffer(This);
+ encoded_buffer *buff;
+ char *dest_ptr;
+ HRESULT hr;
+
+ hr = flush_output_buffer(This);
if (FAILED(hr))
return hr;
V_VT(dest) = VT_BSTR;
- V_BSTR(dest) = SysAllocString((WCHAR*)This->buffer->utf16.data);
+ V_BSTR(dest) = SysAllocStringLen(NULL, This->buffer.utf16_total / sizeof(WCHAR));
+ if (!V_BSTR(dest))
+ return E_OUTOFMEMORY;
- return S_OK;
- }
+ dest_ptr = (char*)V_BSTR(dest);
+ buff = &This->buffer.encoded;
+
+ if (buff->written)
+ {
+ memcpy(dest_ptr, buff->data, buff->written);
+ dest_ptr += buff->written;
+ }
- /* we only support IStream output so far */
- V_VT(dest) = VT_UNKNOWN;
- V_UNKNOWN(dest) = (IUnknown*)This->dest;
- IStream_AddRef(This->dest);
+ LIST_FOR_EACH_ENTRY(buff, &This->buffer.blocks, encoded_buffer, entry)
+ {
+ memcpy(dest_ptr, buff->data, buff->written);
+ dest_ptr += buff->written;
+ }
+ }
return S_OK;
}
int nuri)
{
mxwriter *This = impl_from_ISAXContentHandler( iface );
- FIXME("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
- return E_NOTIMPL;
+ TRACE("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri));
+ return S_OK;
}
static HRESULT WINAPI SAXContentHandler_endPrefixMapping(
int nprefix)
{
mxwriter *This = impl_from_ISAXContentHandler( iface );
- FIXME("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
- return E_NOTIMPL;
+ TRACE("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix));
+ return S_OK;
+}
+
+static void mxwriter_write_attribute(mxwriter *writer, const WCHAR *qname, int qname_len,
+ const WCHAR *value, int value_len, BOOL escape)
+{
+ static const WCHAR eqW[] = {'='};
+
+ /* space separator in front of every attribute */
+ write_output_buffer(writer, spaceW, 1);
+ write_output_buffer(writer, qname, qname_len);
+ write_output_buffer(writer, eqW, 1);
+
+ if (escape)
+ {
+ WCHAR *escaped = get_escaped_string(value, EscapeValue, &value_len);
+ write_output_buffer_quoted(writer, escaped, value_len);
+ heap_free(escaped);
+ }
+ else
+ write_output_buffer_quoted(writer, value, value_len);
+}
+
+static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int len)
+{
+ static const WCHAR ltW[] = {'<'};
+
+ close_element_starttag(writer);
+ set_element_name(writer, qname ? qname : emptyW, qname ? len : 0);
+
+ write_node_indent(writer);
+
+ write_output_buffer(writer, ltW, 1);
+ write_output_buffer(writer, qname ? qname : emptyW, qname ? len : 0);
+ writer_inc_indent(writer);
}
static HRESULT WINAPI SAXContentHandler_startElement(
ISAXAttributes *attr)
{
mxwriter *This = impl_from_ISAXContentHandler( iface );
- static const WCHAR ltW[] = {'<'};
TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri),
debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr);
(nQName == -1 && This->class_version == MSXML6))
return E_INVALIDARG;
- close_element_starttag(This);
- set_element_name(This, QName ? QName : emptyW,
- QName ? nQName : 0);
-
- write_output_buffer(This->buffer, ltW, 1);
- write_output_buffer(This->buffer, QName, nQName);
+ mxwriter_write_starttag(This, QName, nQName);
if (attr)
{
for (i = 0; i < length; i++)
{
- static const WCHAR eqW[] = {'='};
- const WCHAR *str;
- int len = 0;
+ int qname_len = 0, value_len = 0;
+ const WCHAR *qname, *value;
- hr = ISAXAttributes_getQName(attr, i, &str, &len);
+ hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len);
if (FAILED(hr)) return hr;
- /* space separator in front of every attribute */
- write_output_buffer(This->buffer, spaceW, 1);
- write_output_buffer(This->buffer, str, len);
-
- write_output_buffer(This->buffer, eqW, 1);
-
- len = 0;
- hr = ISAXAttributes_getValue(attr, i, &str, &len);
+ hr = ISAXAttributes_getValue(attr, i, &value, &value_len);
if (FAILED(hr)) return hr;
- if (escape)
- {
- WCHAR *escaped = get_escaped_string(str, EscapeValue, &len);
- write_output_buffer_quoted(This->buffer, escaped, len);
- heap_free(escaped);
- }
- else
- write_output_buffer_quoted(This->buffer, str, len);
+ mxwriter_write_attribute(This, qname, qname_len, value, value_len, escape);
}
}
(nQName == -1 && This->class_version == MSXML6))
return E_INVALIDARG;
+ writer_dec_indent(This);
+
if (This->element)
{
static const WCHAR closeW[] = {'/','>'};
- write_output_buffer(This->buffer, closeW, 2);
+ write_output_buffer(This, closeW, 2);
}
else
{
static const WCHAR closetagW[] = {'<','/'};
static const WCHAR gtW[] = {'>'};
- write_output_buffer(This->buffer, closetagW, 2);
- write_output_buffer(This->buffer, QName, nQName);
- write_output_buffer(This->buffer, gtW, 1);
+ write_node_indent(This);
+ write_output_buffer(This, closetagW, 2);
+ write_output_buffer(This, QName, nQName);
+ write_output_buffer(This, gtW, 1);
}
set_element_name(This, NULL, 0);
close_element_starttag(This);
set_element_name(This, NULL, 0);
+ if (!This->cdata)
+ This->text = TRUE;
+
if (nchars)
{
if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
- write_output_buffer(This->buffer, chars, nchars);
+ write_output_buffer(This, chars, nchars);
else
{
int len = nchars;
WCHAR *escaped;
escaped = get_escaped_string(chars, EscapeText, &len);
- write_output_buffer(This->buffer, escaped, len);
+ write_output_buffer(This, escaped, len);
heap_free(escaped);
}
}
if (!chars) return E_INVALIDARG;
- write_output_buffer(This->buffer, chars, nchars);
+ write_output_buffer(This, chars, nchars);
return S_OK;
}
if (!target) return E_INVALIDARG;
- write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
+ write_node_indent(This);
+ write_output_buffer(This, openpiW, ARRAY_SIZE(openpiW));
if (*target)
- write_output_buffer(This->buffer, target, ntarget);
+ write_output_buffer(This, target, ntarget);
if (data && *data && ndata)
{
- write_output_buffer(This->buffer, spaceW, 1);
- write_output_buffer(This->buffer, data, ndata);
+ write_output_buffer(This, spaceW, 1);
+ write_output_buffer(This, data, ndata);
}
- write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
+ write_output_buffer(This, closepiW, ARRAY_SIZE(closepiW));
+ This->newline = TRUE;
return S_OK;
}
if (!name) return E_INVALIDARG;
- write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
+ write_output_buffer(This, doctypeW, ARRAY_SIZE(doctypeW));
if (*name)
{
- write_output_buffer(This->buffer, name, name_len);
- write_output_buffer(This->buffer, spaceW, 1);
+ write_output_buffer(This, name, name_len);
+ write_output_buffer(This, spaceW, 1);
}
if (publicId)
{
- static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
-
- write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
- write_output_buffer_quoted(This->buffer, publicId, publicId_len);
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicId, publicId_len);
if (!systemId) return E_INVALIDARG;
if (*publicId)
- write_output_buffer(This->buffer, spaceW, 1);
+ write_output_buffer(This, spaceW, 1);
- write_output_buffer_quoted(This->buffer, systemId, systemId_len);
+ write_output_buffer_quoted(This, systemId, systemId_len);
if (*systemId)
- write_output_buffer(This->buffer, spaceW, 1);
+ write_output_buffer(This, spaceW, 1);
}
else if (systemId)
{
- static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
-
- write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
- write_output_buffer_quoted(This->buffer, systemId, systemId_len);
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
+ write_output_buffer_quoted(This, systemId, systemId_len);
if (*systemId)
- write_output_buffer(This->buffer, spaceW, 1);
+ write_output_buffer(This, spaceW, 1);
}
- write_output_buffer(This->buffer, openintW, sizeof(openintW)/sizeof(WCHAR));
+ write_output_buffer(This, openintW, ARRAY_SIZE(openintW));
return S_OK;
}
TRACE("(%p)\n", This);
- write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
+ write_output_buffer(This, closedtdW, ARRAY_SIZE(closedtdW));
return S_OK;
}
TRACE("(%p)\n", This);
- write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
+ write_node_indent(This);
+ write_output_buffer(This, scdataW, ARRAY_SIZE(scdataW));
This->cdata = TRUE;
return S_OK;
TRACE("(%p)\n", This);
- write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
+ write_output_buffer(This, ecdataW, ARRAY_SIZE(ecdataW));
This->cdata = FALSE;
return S_OK;
if (!chars) return E_INVALIDARG;
close_element_starttag(This);
+ write_node_indent(This);
- write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
+ write_output_buffer(This, copenW, ARRAY_SIZE(copenW));
if (nchars)
- write_output_buffer(This->buffer, chars, nchars);
- write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
+ write_output_buffer(This, chars, nchars);
+ write_output_buffer(This, ccloseW, ARRAY_SIZE(ccloseW));
return S_OK;
}
if (!name || !model) return E_INVALIDARG;
- write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
+ write_output_buffer(This, elementW, ARRAY_SIZE(elementW));
if (n_name) {
- write_output_buffer(This->buffer, name, n_name);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_model)
- write_output_buffer(This->buffer, model, n_model);
- write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
+ write_output_buffer(This, model, n_model);
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
return S_OK;
}
debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
debugstr_wn(value, n_value), n_value);
- write_output_buffer(This->buffer, attlistW, sizeof(attlistW)/sizeof(WCHAR));
+ write_output_buffer(This, attlistW, ARRAY_SIZE(attlistW));
if (n_element) {
- write_output_buffer(This->buffer, element, n_element);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, element, n_element);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_attr) {
- write_output_buffer(This->buffer, attr, n_attr);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, attr, n_attr);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_type) {
- write_output_buffer(This->buffer, type, n_type);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, type, n_type);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_default) {
- write_output_buffer(This->buffer, Default, n_default);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, Default, n_default);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_value)
- write_output_buffer_quoted(This->buffer, value, n_value);
+ write_output_buffer_quoted(This, value, n_value);
- write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
return S_OK;
}
const WCHAR *name, int n_name, const WCHAR *value, int n_value)
{
mxwriter *This = impl_from_ISAXDeclHandler( iface );
- static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
debugstr_wn(value, n_value), n_value);
if (!name || !value) return E_INVALIDARG;
- write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
+ write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
if (n_name) {
- write_output_buffer(This->buffer, name, n_name);
- write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
}
if (n_value)
- write_output_buffer_quoted(This->buffer, value, n_value);
+ write_output_buffer_quoted(This, value, n_value);
- write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
return S_OK;
}
const WCHAR *systemId, int n_systemId)
{
mxwriter *This = impl_from_ISAXDeclHandler( iface );
- FIXME("(%p)->(%s:%d %s:%d %s:%d): stub\n", This, debugstr_wn(name, n_name), n_name,
+
+ TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
- return E_NOTIMPL;
+
+ if (!name || !systemId) return E_INVALIDARG;
+
+ write_output_buffer(This, entityW, ARRAY_SIZE(entityW));
+ if (n_name) {
+ write_output_buffer(This, name, n_name);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ }
+
+ if (publicId)
+ {
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicId, n_publicId);
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ write_output_buffer_quoted(This, systemId, n_systemId);
+ }
+ else
+ {
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
+ write_output_buffer_quoted(This, systemId, n_systemId);
+ }
+
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+
+ return S_OK;
}
static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = {
SAXDeclHandler_externalEntityDecl
};
-static const tid_t mxwriter_iface_tids[] = {
- IMXWriter_tid,
- 0
-};
+/*** IVBSAXDeclHandler ***/
+static HRESULT WINAPI VBSAXDeclHandler_QueryInterface(IVBSAXDeclHandler *iface,
+ REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
-static dispex_static_data_t mxwriter_dispex = {
- NULL,
- IMXWriter_tid,
- NULL,
- mxwriter_iface_tids
-};
+static ULONG WINAPI VBSAXDeclHandler_AddRef(IVBSAXDeclHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
-HRESULT MXWriter_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
+static ULONG WINAPI VBSAXDeclHandler_Release(IVBSAXDeclHandler *iface)
{
- static const WCHAR version10W[] = {'1','.','0',0};
- mxwriter *This;
- HRESULT hr;
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
- TRACE("(%p, %p)\n", outer, ppObj);
+static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfoCount(IVBSAXDeclHandler *iface, UINT* pctinfo)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
+}
- if (outer) FIXME("support aggregation, outer\n");
+static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfo(IVBSAXDeclHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
+}
- This = heap_alloc( sizeof (*This) );
- if(!This)
- return E_OUTOFMEMORY;
+static HRESULT WINAPI VBSAXDeclHandler_GetIDsOfNames(IVBSAXDeclHandler *iface, REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispId )
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
+}
- This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
- This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
- This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
- This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
- This->ref = 1;
- This->class_version = version;
+static HRESULT WINAPI VBSAXDeclHandler_Invoke(IVBSAXDeclHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+ return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
+ pExcepInfo, puArgErr);
+}
- This->props[MXWriter_BOM] = VARIANT_TRUE;
- This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
- This->props[MXWriter_Indent] = VARIANT_FALSE;
- This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
- This->props[MXWriter_Standalone] = VARIANT_FALSE;
- This->prop_changed = FALSE;
- This->encoding = SysAllocString(utf16W);
- This->version = SysAllocString(version10W);
- This->xml_enc = XmlEncoding_UTF16;
+static HRESULT WINAPI VBSAXDeclHandler_elementDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *model)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
- This->element = NULL;
- This->cdata = FALSE;
+ TRACE("(%p)->(%p %p)\n", This, name, model);
- This->dest = NULL;
- This->dest_written = 0;
+ if (!name || !model)
+ return E_POINTER;
- hr = alloc_output_buffer(This->xml_enc, &This->buffer);
- if (hr != S_OK) {
- SysFreeString(This->encoding);
- SysFreeString(This->version);
- heap_free(This);
- return hr;
- }
+ return ISAXDeclHandler_elementDecl(&This->ISAXDeclHandler_iface, *name, -1, *model, -1);
+}
- init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
+static HRESULT WINAPI VBSAXDeclHandler_attributeDecl(IVBSAXDeclHandler *iface,
+ BSTR *element, BSTR *attr, BSTR *type, BSTR *default_value, BSTR *value)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
- *ppObj = &This->IMXWriter_iface;
+ TRACE("(%p)->(%p %p %p %p %p)\n", This, element, attr, type, default_value, value);
- TRACE("returning iface %p\n", *ppObj);
+ if (!element || !attr || !type || !default_value || !value)
+ return E_POINTER;
- return S_OK;
+ return ISAXDeclHandler_attributeDecl(&This->ISAXDeclHandler_iface, *element, -1, *attr, -1, *type, -1,
+ *default_value, -1, *value, -1);
}
-static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
+static HRESULT WINAPI VBSAXDeclHandler_internalEntityDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *value)
{
- mxattributes *This = impl_from_IMXAttributes( iface );
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
+ TRACE("(%p)->(%p %p)\n", This, name, value);
- *ppObj = NULL;
+ if (!name || !value)
+ return E_POINTER;
- if ( IsEqualGUID( riid, &IID_IUnknown ) ||
- IsEqualGUID( riid, &IID_IDispatch ) ||
- IsEqualGUID( riid, &IID_IMXAttributes ))
- {
- *ppObj = iface;
- }
+ return ISAXDeclHandler_internalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *value, -1);
+}
+
+static HRESULT WINAPI VBSAXDeclHandler_externalEntityDecl(IVBSAXDeclHandler *iface,
+ BSTR *name, BSTR *publicid, BSTR *systemid)
+{
+ mxwriter *This = impl_from_IVBSAXDeclHandler( iface );
+
+ TRACE("(%p)->(%p %p %p)\n", This, name, publicid, systemid);
+
+ if (!name || !publicid || !systemid)
+ return E_POINTER;
+
+ return ISAXDeclHandler_externalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *publicid, -1, *systemid, -1);
+}
+
+static const IVBSAXDeclHandlerVtbl VBSAXDeclHandlerVtbl = {
+ VBSAXDeclHandler_QueryInterface,
+ VBSAXDeclHandler_AddRef,
+ VBSAXDeclHandler_Release,
+ VBSAXDeclHandler_GetTypeInfoCount,
+ VBSAXDeclHandler_GetTypeInfo,
+ VBSAXDeclHandler_GetIDsOfNames,
+ VBSAXDeclHandler_Invoke,
+ VBSAXDeclHandler_elementDecl,
+ VBSAXDeclHandler_attributeDecl,
+ VBSAXDeclHandler_internalEntityDecl,
+ VBSAXDeclHandler_externalEntityDecl
+};
+
+/*** IVBSAXLexicalHandler ***/
+static HRESULT WINAPI VBSAXLexicalHandler_QueryInterface(IVBSAXLexicalHandler *iface,
+ REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI VBSAXLexicalHandler_AddRef(IVBSAXLexicalHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI VBSAXLexicalHandler_Release(IVBSAXLexicalHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfoCount(IVBSAXLexicalHandler *iface, UINT* pctinfo)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfo(IVBSAXLexicalHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_GetIDsOfNames(IVBSAXLexicalHandler *iface, REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispId )
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_Invoke(IVBSAXLexicalHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
+ pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_startDTD(IVBSAXLexicalHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+
+ TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
+
+ if (!name || !publicId || !systemId)
+ return E_POINTER;
+
+ return ISAXLexicalHandler_startDTD(&This->ISAXLexicalHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_endDTD(IVBSAXLexicalHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return ISAXLexicalHandler_endDTD(&This->ISAXLexicalHandler_iface);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_startEntity(IVBSAXLexicalHandler *iface, BSTR *name)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, name);
+
+ if (!name)
+ return E_POINTER;
+
+ return ISAXLexicalHandler_startEntity(&This->ISAXLexicalHandler_iface, *name, -1);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_endEntity(IVBSAXLexicalHandler *iface, BSTR *name)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, name);
+
+ if (!name)
+ return E_POINTER;
+
+ return ISAXLexicalHandler_endEntity(&This->ISAXLexicalHandler_iface, *name, -1);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_startCDATA(IVBSAXLexicalHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return ISAXLexicalHandler_startCDATA(&This->ISAXLexicalHandler_iface);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_endCDATA(IVBSAXLexicalHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+ return ISAXLexicalHandler_endCDATA(&This->ISAXLexicalHandler_iface);
+}
+
+static HRESULT WINAPI VBSAXLexicalHandler_comment(IVBSAXLexicalHandler *iface, BSTR *chars)
+{
+ mxwriter *This = impl_from_IVBSAXLexicalHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, chars);
+
+ if (!chars)
+ return E_POINTER;
+
+ return ISAXLexicalHandler_comment(&This->ISAXLexicalHandler_iface, *chars, -1);
+}
+
+static const IVBSAXLexicalHandlerVtbl VBSAXLexicalHandlerVtbl = {
+ VBSAXLexicalHandler_QueryInterface,
+ VBSAXLexicalHandler_AddRef,
+ VBSAXLexicalHandler_Release,
+ VBSAXLexicalHandler_GetTypeInfoCount,
+ VBSAXLexicalHandler_GetTypeInfo,
+ VBSAXLexicalHandler_GetIDsOfNames,
+ VBSAXLexicalHandler_Invoke,
+ VBSAXLexicalHandler_startDTD,
+ VBSAXLexicalHandler_endDTD,
+ VBSAXLexicalHandler_startEntity,
+ VBSAXLexicalHandler_endEntity,
+ VBSAXLexicalHandler_startCDATA,
+ VBSAXLexicalHandler_endCDATA,
+ VBSAXLexicalHandler_comment
+};
+
+/*** IVBSAXContentHandler ***/
+static HRESULT WINAPI VBSAXContentHandler_QueryInterface(IVBSAXContentHandler *iface, REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI VBSAXContentHandler_AddRef(IVBSAXContentHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI VBSAXContentHandler_Release(IVBSAXContentHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_GetTypeInfoCount(IVBSAXContentHandler *iface, UINT* pctinfo)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_GetTypeInfo(IVBSAXContentHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_GetIDsOfNames(IVBSAXContentHandler *iface, REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispId )
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_Invoke(IVBSAXContentHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
+ pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_putref_documentLocator(IVBSAXContentHandler *iface, IVBSAXLocator *locator)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ TRACE("(%p)->(%p)\n", This, locator);
+ return S_OK;
+}
+
+static HRESULT WINAPI VBSAXContentHandler_startDocument(IVBSAXContentHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return ISAXContentHandler_startDocument(&This->ISAXContentHandler_iface);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_endDocument(IVBSAXContentHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+ return ISAXContentHandler_endDocument(&This->ISAXContentHandler_iface);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_startPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix, BSTR *uri)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p %p)\n", This, prefix, uri);
+
+ if (!prefix || !uri)
+ return E_POINTER;
+
+ return ISAXContentHandler_startPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1, *uri, -1);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_endPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, prefix);
+
+ if (!prefix)
+ return E_POINTER;
+
+ return ISAXContentHandler_endPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_startElement(IVBSAXContentHandler *iface,
+ BSTR *namespaceURI, BSTR *localName, BSTR *QName, IVBSAXAttributes *attrs)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p %p %p %p)\n", This, namespaceURI, localName, QName, attrs);
+
+ if (!namespaceURI || !localName || !QName)
+ return E_POINTER;
+
+ TRACE("(%s %s %s)\n", debugstr_w(*namespaceURI), debugstr_w(*localName), debugstr_w(*QName));
+
+ mxwriter_write_starttag(This, *QName, SysStringLen(*QName));
+
+ if (attrs)
+ {
+ int length, i, escape;
+ HRESULT hr;
+
+ hr = IVBSAXAttributes_get_length(attrs, &length);
+ if (FAILED(hr)) return hr;
+
+ escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE ||
+ (This->class_version == MSXML4 || This->class_version == MSXML6);
+
+ for (i = 0; i < length; i++)
+ {
+ BSTR qname, value;
+
+ hr = IVBSAXAttributes_getQName(attrs, i, &qname);
+ if (FAILED(hr)) return hr;
+
+ hr = IVBSAXAttributes_getValue(attrs, i, &value);
+ if (FAILED(hr))
+ {
+ SysFreeString(qname);
+ return hr;
+ }
+
+ mxwriter_write_attribute(This, qname, SysStringLen(qname), value, SysStringLen(value), escape);
+ SysFreeString(qname);
+ SysFreeString(value);
+ }
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VBSAXContentHandler_endElement(IVBSAXContentHandler *iface, BSTR *namespaceURI,
+ BSTR *localName, BSTR *QName)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p %p %p)\n", This, namespaceURI, localName, QName);
+
+ if (!namespaceURI || !localName || !QName)
+ return E_POINTER;
+
+ return ISAXContentHandler_endElement(&This->ISAXContentHandler_iface,
+ *namespaceURI, SysStringLen(*namespaceURI),
+ *localName, SysStringLen(*localName),
+ *QName, SysStringLen(*QName));
+}
+
+static HRESULT WINAPI VBSAXContentHandler_characters(IVBSAXContentHandler *iface, BSTR *chars)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, chars);
+
+ if (!chars)
+ return E_POINTER;
+
+ return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, SysStringLen(*chars));
+}
+
+static HRESULT WINAPI VBSAXContentHandler_ignorableWhitespace(IVBSAXContentHandler *iface, BSTR *chars)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, chars);
+
+ if (!chars)
+ return E_POINTER;
+
+ return ISAXContentHandler_ignorableWhitespace(&This->ISAXContentHandler_iface, *chars, -1);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_processingInstruction(IVBSAXContentHandler *iface,
+ BSTR *target, BSTR *data)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p %p)\n", This, target, data);
+
+ if (!target || !data)
+ return E_POINTER;
+
+ return ISAXContentHandler_processingInstruction(&This->ISAXContentHandler_iface, *target, -1, *data, -1);
+}
+
+static HRESULT WINAPI VBSAXContentHandler_skippedEntity(IVBSAXContentHandler *iface, BSTR *name)
+{
+ mxwriter *This = impl_from_IVBSAXContentHandler( iface );
+
+ TRACE("(%p)->(%p)\n", This, name);
+
+ if (!name)
+ return E_POINTER;
+
+ return ISAXContentHandler_skippedEntity(&This->ISAXContentHandler_iface, *name, -1);
+}
+
+static const IVBSAXContentHandlerVtbl VBSAXContentHandlerVtbl = {
+ VBSAXContentHandler_QueryInterface,
+ VBSAXContentHandler_AddRef,
+ VBSAXContentHandler_Release,
+ VBSAXContentHandler_GetTypeInfoCount,
+ VBSAXContentHandler_GetTypeInfo,
+ VBSAXContentHandler_GetIDsOfNames,
+ VBSAXContentHandler_Invoke,
+ VBSAXContentHandler_putref_documentLocator,
+ VBSAXContentHandler_startDocument,
+ VBSAXContentHandler_endDocument,
+ VBSAXContentHandler_startPrefixMapping,
+ VBSAXContentHandler_endPrefixMapping,
+ VBSAXContentHandler_startElement,
+ VBSAXContentHandler_endElement,
+ VBSAXContentHandler_characters,
+ VBSAXContentHandler_ignorableWhitespace,
+ VBSAXContentHandler_processingInstruction,
+ VBSAXContentHandler_skippedEntity
+};
+
+static HRESULT WINAPI SAXDTDHandler_QueryInterface(ISAXDTDHandler *iface, REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_ISAXDTDHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI SAXDTDHandler_AddRef(ISAXDTDHandler *iface)
+{
+ mxwriter *This = impl_from_ISAXDTDHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI SAXDTDHandler_Release(ISAXDTDHandler *iface)
+{
+ mxwriter *This = impl_from_ISAXDTDHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
+ const WCHAR *name, INT n_name,
+ const WCHAR *publicid, INT n_publicid,
+ const WCHAR *systemid, INT n_systemid)
+{
+ static const WCHAR notationW[] = {'<','!','N','O','T','A','T','I','O','N',' '};
+ mxwriter *This = impl_from_ISAXDTDHandler( iface );
+
+ TRACE("(%p)->(%s:%d, %s:%d, %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
+ debugstr_wn(publicid, n_publicid), n_publicid, debugstr_wn(systemid, n_systemid), n_systemid);
+
+ if (!name || !n_name)
+ return E_INVALIDARG;
+
+ write_output_buffer(This, notationW, ARRAY_SIZE(notationW));
+ write_output_buffer(This, name, n_name);
+
+ if (!publicid && !systemid)
+ return E_INVALIDARG;
+
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ if (publicid)
+ {
+ write_output_buffer(This, publicW, ARRAY_SIZE(publicW));
+ write_output_buffer_quoted(This, publicid, n_publicid);
+ if (systemid)
+ {
+ write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW));
+ write_output_buffer_quoted(This, systemid, n_systemid);
+ }
+ }
+ else
+ {
+ write_output_buffer(This, systemW, ARRAY_SIZE(systemW));
+ write_output_buffer_quoted(This, systemid, n_systemid);
+ }
+
+ write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW));
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface,
+ const WCHAR *name, INT nname,
+ const WCHAR *publicid, INT npublicid,
+ const WCHAR *systemid, INT nsystemid,
+ const WCHAR *notation, INT nnotation)
+{
+ mxwriter *This = impl_from_ISAXDTDHandler( iface );
+ FIXME("(%p)->(%s:%d, %s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname,
+ debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid,
+ debugstr_wn(notation, nnotation), nnotation);
+ return E_NOTIMPL;
+}
+
+static const ISAXDTDHandlerVtbl SAXDTDHandlerVtbl = {
+ SAXDTDHandler_QueryInterface,
+ SAXDTDHandler_AddRef,
+ SAXDTDHandler_Release,
+ SAXDTDHandler_notationDecl,
+ SAXDTDHandler_unparsedEntityDecl
+};
+
+/*** IVBSAXDTDHandler ***/
+static HRESULT WINAPI VBSAXDTDHandler_QueryInterface(IVBSAXDTDHandler *iface, REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI VBSAXDTDHandler_AddRef(IVBSAXDTDHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI VBSAXDTDHandler_Release(IVBSAXDTDHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfoCount(IVBSAXDTDHandler *iface, UINT* pctinfo)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfo(IVBSAXDTDHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_GetIDsOfNames(IVBSAXDTDHandler *iface, REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispId )
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_Invoke(IVBSAXDTDHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+ return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
+ pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_notationDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+
+ TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId);
+
+ if (!name || !publicId || !systemId)
+ return E_POINTER;
+
+ return ISAXDTDHandler_notationDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1, *systemId, -1);
+}
+
+static HRESULT WINAPI VBSAXDTDHandler_unparsedEntityDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId,
+ BSTR *systemId, BSTR *notation)
+{
+ mxwriter *This = impl_from_IVBSAXDTDHandler( iface );
+
+ TRACE("(%p)->(%p %p %p %p)\n", This, name, publicId, systemId, notation);
+
+ if (!name || !publicId || !systemId || !notation)
+ return E_POINTER;
+
+ return ISAXDTDHandler_unparsedEntityDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1,
+ *systemId, -1, *notation, -1);
+}
+
+static const IVBSAXDTDHandlerVtbl VBSAXDTDHandlerVtbl = {
+ VBSAXDTDHandler_QueryInterface,
+ VBSAXDTDHandler_AddRef,
+ VBSAXDTDHandler_Release,
+ VBSAXDTDHandler_GetTypeInfoCount,
+ VBSAXDTDHandler_GetTypeInfo,
+ VBSAXDTDHandler_GetIDsOfNames,
+ VBSAXDTDHandler_Invoke,
+ VBSAXDTDHandler_notationDecl,
+ VBSAXDTDHandler_unparsedEntityDecl
+};
+
+/* ISAXErrorHandler */
+static HRESULT WINAPI SAXErrorHandler_QueryInterface(ISAXErrorHandler *iface, REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI SAXErrorHandler_AddRef(ISAXErrorHandler *iface)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI SAXErrorHandler_Release(ISAXErrorHandler *iface)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI SAXErrorHandler_error(ISAXErrorHandler *iface,
+ ISAXLocator *locator, const WCHAR *message, HRESULT hr)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+
+ FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAXErrorHandler_fatalError(ISAXErrorHandler *iface,
+ ISAXLocator *locator, const WCHAR *message, HRESULT hr)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+
+ FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAXErrorHandler_ignorableWarning(ISAXErrorHandler *iface,
+ ISAXLocator *locator, const WCHAR *message, HRESULT hr)
+{
+ mxwriter *This = impl_from_ISAXErrorHandler( iface );
+
+ FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr);
+
+ return E_NOTIMPL;
+}
+
+static const ISAXErrorHandlerVtbl SAXErrorHandlerVtbl = {
+ SAXErrorHandler_QueryInterface,
+ SAXErrorHandler_AddRef,
+ SAXErrorHandler_Release,
+ SAXErrorHandler_error,
+ SAXErrorHandler_fatalError,
+ SAXErrorHandler_ignorableWarning
+};
+
+/*** IVBSAXErrorHandler ***/
+static HRESULT WINAPI VBSAXErrorHandler_QueryInterface(IVBSAXErrorHandler *iface, REFIID riid, void **obj)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj);
+}
+
+static ULONG WINAPI VBSAXErrorHandler_AddRef(IVBSAXErrorHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_AddRef(&This->IMXWriter_iface);
+}
+
+static ULONG WINAPI VBSAXErrorHandler_Release(IVBSAXErrorHandler *iface)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_Release(&This->IMXWriter_iface);
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfoCount(IVBSAXErrorHandler *iface, UINT* pctinfo)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo);
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfo(IVBSAXErrorHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_GetIDsOfNames(IVBSAXErrorHandler *iface, REFIID riid, LPOLESTR* rgszNames,
+ UINT cNames, LCID lcid, DISPID* rgDispId )
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_Invoke(IVBSAXErrorHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+ WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr )
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult,
+ pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_error(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_fatalError(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI VBSAXErrorHandler_ignorableWarning(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code)
+{
+ mxwriter *This = impl_from_IVBSAXErrorHandler( iface );
+ FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code);
+ return E_NOTIMPL;
+}
+
+static const IVBSAXErrorHandlerVtbl VBSAXErrorHandlerVtbl = {
+ VBSAXErrorHandler_QueryInterface,
+ VBSAXErrorHandler_AddRef,
+ VBSAXErrorHandler_Release,
+ VBSAXErrorHandler_GetTypeInfoCount,
+ VBSAXErrorHandler_GetTypeInfo,
+ VBSAXErrorHandler_GetIDsOfNames,
+ VBSAXErrorHandler_Invoke,
+ VBSAXErrorHandler_error,
+ VBSAXErrorHandler_fatalError,
+ VBSAXErrorHandler_ignorableWarning
+};
+
+static const tid_t mxwriter_iface_tids[] = {
+ IMXWriter_tid,
+ 0
+};
+
+static dispex_static_data_t mxwriter_dispex = {
+ NULL,
+ IMXWriter_tid,
+ NULL,
+ mxwriter_iface_tids
+};
+
+HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj)
+{
+ static const WCHAR version10W[] = {'1','.','0',0};
+ mxwriter *This;
+ HRESULT hr;
+
+ TRACE("(%p)\n", ppObj);
+
+ This = heap_alloc( sizeof (*This) );
+ if(!This)
+ return E_OUTOFMEMORY;
+
+ This->IMXWriter_iface.lpVtbl = &MXWriterVtbl;
+ This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl;
+ This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl;
+ This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl;
+ This->ISAXDTDHandler_iface.lpVtbl = &SAXDTDHandlerVtbl;
+ This->ISAXErrorHandler_iface.lpVtbl = &SAXErrorHandlerVtbl;
+ This->IVBSAXDeclHandler_iface.lpVtbl = &VBSAXDeclHandlerVtbl;
+ This->IVBSAXLexicalHandler_iface.lpVtbl = &VBSAXLexicalHandlerVtbl;
+ This->IVBSAXContentHandler_iface.lpVtbl = &VBSAXContentHandlerVtbl;
+ This->IVBSAXDTDHandler_iface.lpVtbl = &VBSAXDTDHandlerVtbl;
+ This->IVBSAXErrorHandler_iface.lpVtbl = &VBSAXErrorHandlerVtbl;
+ This->ref = 1;
+ This->class_version = version;
+
+ This->props[MXWriter_BOM] = VARIANT_TRUE;
+ This->props[MXWriter_DisableEscaping] = VARIANT_FALSE;
+ This->props[MXWriter_Indent] = VARIANT_FALSE;
+ This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE;
+ This->props[MXWriter_Standalone] = VARIANT_FALSE;
+ This->prop_changed = FALSE;
+ This->encoding = SysAllocString(utf16W);
+ This->version = SysAllocString(version10W);
+ This->xml_enc = XmlEncoding_UTF16;
+
+ This->element = NULL;
+ This->cdata = FALSE;
+ This->indent = 0;
+ This->text = FALSE;
+ This->newline = FALSE;
+
+ This->dest = NULL;
+
+ hr = init_output_buffer(This->xml_enc, &This->buffer);
+ if (hr != S_OK) {
+ SysFreeString(This->encoding);
+ SysFreeString(This->version);
+ heap_free(This);
+ return hr;
+ }
+
+ init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex);
+
+ *ppObj = &This->IMXWriter_iface;
+
+ TRACE("returning iface %p\n", *ppObj);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj)
+{
+ mxattributes *This = impl_from_IMXAttributes( iface );
+
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj);
+
+ *ppObj = NULL;
+
+ if ( IsEqualGUID( riid, &IID_IUnknown ) ||
+ IsEqualGUID( riid, &IID_IDispatch ) ||
+ IsEqualGUID( riid, &IID_IMXAttributes ))
+ {
+ *ppObj = iface;
+ }
else if ( IsEqualGUID( riid, &IID_ISAXAttributes ))
{
*ppObj = &This->ISAXAttributes_iface;
SysFreeString(This->attr[i].value);
}
- release_dispex(&This->dispex);
heap_free(This->attr);
heap_free(This);
}
return S_OK;
}
+static mxattribute *get_attribute_byindex(mxattributes *attrs, int index)
+{
+ if (index < 0 || index >= attrs->length) return NULL;
+ return &attrs->attr[index];
+}
+
static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index)
{
mxattributes *This = impl_from_IMXAttributes( iface );
- FIXME("(%p)->(%d): stub\n", This, index);
- return E_NOTIMPL;
+ mxattribute *dst;
+
+ TRACE("(%p)->(%d)\n", This, index);
+
+ if (!(dst = get_attribute_byindex(This, index))) return E_INVALIDARG;
+
+ /* no need to remove last attribute, just make it inaccessible */
+ if (index + 1 == This->length)
+ {
+ This->length--;
+ return S_OK;
+ }
+
+ memmove(dst, dst + 1, (This->length-index-1)*sizeof(*dst));
+ This->length--;
+
+ return S_OK;
}
static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index,
BSTR localName)
{
mxattributes *This = impl_from_IMXAttributes( iface );
- FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(localName));
- return E_NOTIMPL;
+ mxattribute *attr;
+
+ TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(localName));
+
+ if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
+
+ SysFreeString(attr->local);
+ attr->local = SysAllocString(localName);
+
+ return S_OK;
}
static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName)
{
mxattributes *This = impl_from_IMXAttributes( iface );
- FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(QName));
- return E_NOTIMPL;
+ mxattribute *attr;
+
+ TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(QName));
+
+ if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
+
+ SysFreeString(attr->qname);
+ attr->qname = SysAllocString(QName);
+
+ return S_OK;
}
static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri)
{
mxattributes *This = impl_from_IMXAttributes( iface );
- FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(uri));
- return E_NOTIMPL;
+ mxattribute *attr;
+
+ TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(uri));
+
+ if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
+
+ SysFreeString(attr->uri);
+ attr->uri = SysAllocString(uri);
+
+ return S_OK;
}
static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value)
{
mxattributes *This = impl_from_IMXAttributes( iface );
- FIXME("(%p)->(%d %s): stub\n", This, index, debugstr_w(value));
- return E_NOTIMPL;
+ mxattribute *attr;
+
+ TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(value));
+
+ if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG;
+
+ SysFreeString(attr->value);
+ attr->value = SysAllocString(value);
+
+ return S_OK;
}
static const IMXAttributesVtbl MXAttributesVtbl = {
static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *uriW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, (const WCHAR**)uri, &len);
+ TRACE("(%p)->(%d %p)\n", This, index, uri);
+
+ if (!uri)
+ return E_POINTER;
+
+ *uri = NULL;
+ hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, &uriW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(uriW, len, uri);
}
static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *nameW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, (const WCHAR**)name, &len);
+ TRACE("(%p)->(%d %p)\n", This, index, name);
+
+ if (!name)
+ return E_POINTER;
+
+ *name = NULL;
+ hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, &nameW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(nameW, len, name);
}
static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *qnameW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, (const WCHAR**)qname, &len);
+ TRACE("(%p)->(%d %p)\n", This, index, qname);
+
+ if (!qname)
+ return E_POINTER;
+
+ *qname = NULL;
+ hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, &qnameW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(qnameW, len, qname);
}
static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index)
SysStringLen(qname), index);
}
-static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index,BSTR *type)
+static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index, BSTR *type)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *typeW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getType(&This->ISAXAttributes_iface, index, (const WCHAR**)type, &len);
+ TRACE("(%p)->(%d %p)\n", This, index, type);
+
+ if (!type)
+ return E_POINTER;
+
+ *type = NULL;
+ hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, index, &typeW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(typeW, len, type);
}
static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri,
BSTR name, BSTR *type)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *typeW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
- name, SysStringLen(name), (const WCHAR**)type, &len);
+ TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), type);
+
+ if (!type)
+ return E_POINTER;
+
+ *type = NULL;
+ hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
+ name, SysStringLen(name), &typeW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(typeW, len, type);
}
static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *typeW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
- (const WCHAR**)type, &len);
+ TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), type);
+
+ if (!type)
+ return E_POINTER;
+
+ *type = NULL;
+ hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
+ &typeW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(typeW, len, type);
}
static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *valueW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, (const WCHAR**)value, &len);
+ TRACE("(%p)->(%d %p)\n", This, index, value);
+
+ if (!value)
+ return E_POINTER;
+
+ *value = NULL;
+ hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, &valueW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(valueW, len, value);
}
static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name,
BSTR *value)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *valueW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
- name, SysStringLen(name), (const WCHAR**)value, &len);
+ TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), value);
+
+ if (!value)
+ return E_POINTER;
+
+ *value = NULL;
+ hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
+ name, SysStringLen(name), &valueW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(valueW, len, value);
}
static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value)
{
mxattributes *This = impl_from_IVBSAXAttributes( iface );
+ const WCHAR *valueW;
+ HRESULT hr;
int len;
- return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
- (const WCHAR**)value, &len);
+ TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), value);
+
+ if (!value)
+ return E_POINTER;
+
+ *value = NULL;
+ hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname),
+ &valueW, &len);
+ if (FAILED(hr))
+ return hr;
+
+ return return_bstrn(valueW, len, value);
}
static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl =
mxattrs_iface_tids
};
-HRESULT SAXAttributes_create(MSXML_VERSION version, IUnknown *outer, void **ppObj)
+HRESULT SAXAttributes_create(MSXML_VERSION version, void **ppObj)
{
static const int default_count = 10;
mxattributes *This;
- TRACE("(%p, %p)\n", outer, ppObj);
+ TRACE("(%p)\n", ppObj);
This = heap_alloc( sizeof (*This) );
if( !This )