mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 09:33:20 +00:00
[MSXML3] Sync with Wine Staging 1.9.11. CORE-11368
svn path=/trunk/; revision=71576
This commit is contained in:
parent
64fbdcc0f4
commit
34ca173317
7 changed files with 367 additions and 248 deletions
|
@ -296,6 +296,8 @@ extern LONG xmldoc_add_ref( xmlDocPtr doc ) DECLSPEC_HIDDEN;
|
||||||
extern LONG xmldoc_release( xmlDocPtr doc ) DECLSPEC_HIDDEN;
|
extern LONG xmldoc_release( xmlDocPtr doc ) DECLSPEC_HIDDEN;
|
||||||
extern LONG xmldoc_add_refs( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
|
extern LONG xmldoc_add_refs( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
|
||||||
extern LONG xmldoc_release_refs ( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
|
extern LONG xmldoc_release_refs ( xmlDocPtr doc, LONG refs ) DECLSPEC_HIDDEN;
|
||||||
|
extern void xmlnode_add_ref(xmlNodePtr node) DECLSPEC_HIDDEN;
|
||||||
|
extern void xmlnode_release(xmlNodePtr node) DECLSPEC_HIDDEN;
|
||||||
extern int xmlnode_get_inst_cnt( xmlnode *node ) DECLSPEC_HIDDEN;
|
extern int xmlnode_get_inst_cnt( xmlnode *node ) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
|
extern HRESULT xmldoc_add_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
|
||||||
extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
|
extern HRESULT xmldoc_remove_orphan( xmlDocPtr doc, xmlNodePtr node ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* MXWriter implementation
|
* MXWriter implementation
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Nikolay Sivov for CodeWeavers
|
* Copyright 2011-2014, 2016 Nikolay Sivov for CodeWeavers
|
||||||
* Copyright 2011 Thomas Mullaly
|
* Copyright 2011 Thomas Mullaly
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -27,6 +27,8 @@ static const WCHAR quotW[] = {'\"'};
|
||||||
static const WCHAR closetagW[] = {'>','\r','\n'};
|
static const WCHAR closetagW[] = {'>','\r','\n'};
|
||||||
static const WCHAR crlfW[] = {'\r','\n'};
|
static const WCHAR crlfW[] = {'\r','\n'};
|
||||||
static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '};
|
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 */
|
/* should be ordered as encoding names are sorted */
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -78,13 +80,6 @@ static const struct xml_encoding_data xml_encoding_map[] = {
|
||||||
{ utf8W, XmlEncoding_UTF8, CP_UTF8 }
|
{ utf8W, XmlEncoding_UTF8, CP_UTF8 }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
OutputBuffer_Native = 0x001,
|
|
||||||
OutputBuffer_Encoded = 0x010,
|
|
||||||
OutputBuffer_Both = 0x100
|
|
||||||
} output_mode;
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
MXWriter_BOM = 0,
|
MXWriter_BOM = 0,
|
||||||
|
@ -103,6 +98,7 @@ typedef enum
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
struct list entry;
|
||||||
char *data;
|
char *data;
|
||||||
unsigned int allocated;
|
unsigned int allocated;
|
||||||
unsigned int written;
|
unsigned int written;
|
||||||
|
@ -110,9 +106,10 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
encoded_buffer utf16;
|
|
||||||
encoded_buffer encoded;
|
encoded_buffer encoded;
|
||||||
UINT code_page;
|
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;
|
} output_buffer;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -151,9 +148,8 @@ typedef struct
|
||||||
BSTR element;
|
BSTR element;
|
||||||
|
|
||||||
IStream *dest;
|
IStream *dest;
|
||||||
ULONG dest_written;
|
|
||||||
|
|
||||||
output_buffer *buffer;
|
output_buffer buffer;
|
||||||
} mxwriter;
|
} mxwriter;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -231,7 +227,7 @@ static xml_encoding parse_encoding_name(const WCHAR *encoding)
|
||||||
|
|
||||||
static HRESULT init_encoded_buffer(encoded_buffer *buffer)
|
static HRESULT init_encoded_buffer(encoded_buffer *buffer)
|
||||||
{
|
{
|
||||||
const int initial_len = 0x2000;
|
const int initial_len = 0x1000;
|
||||||
buffer->data = heap_alloc(initial_len);
|
buffer->data = heap_alloc(initial_len);
|
||||||
if (!buffer->data) return E_OUTOFMEMORY;
|
if (!buffer->data) return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
@ -263,121 +259,202 @@ static HRESULT get_code_page(xml_encoding encoding, UINT *cp)
|
||||||
return S_OK;
|
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;
|
HRESULT hr;
|
||||||
|
|
||||||
ret = heap_alloc(sizeof(*ret));
|
hr = get_code_page(encoding, &buffer->code_page);
|
||||||
if (!ret) return E_OUTOFMEMORY;
|
if (hr != S_OK)
|
||||||
|
|
||||||
hr = get_code_page(encoding, &ret->code_page);
|
|
||||||
if (hr != S_OK) {
|
|
||||||
heap_free(ret);
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
|
||||||
|
|
||||||
hr = init_encoded_buffer(&ret->utf16);
|
hr = init_encoded_buffer(&buffer->encoded);
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK)
|
||||||
heap_free(ret);
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
|
||||||
|
|
||||||
/* currently we always create a default output buffer that is UTF-16 only,
|
list_init(&buffer->blocks);
|
||||||
but it's possible to allocate with specific encoding too */
|
buffer->utf16_total = 0;
|
||||||
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;
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_output_buffer(output_buffer *buffer)
|
static void free_output_buffer(output_buffer *buffer)
|
||||||
{
|
{
|
||||||
free_encoded_buffer(&buffer->encoded);
|
encoded_buffer *cur, *cur2;
|
||||||
free_encoded_buffer(&buffer->utf16);
|
|
||||||
heap_free(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void grow_buffer(encoded_buffer *buffer, int length)
|
free_encoded_buffer(&buffer->encoded);
|
||||||
{
|
|
||||||
/* grow if needed, plus 4 bytes to be sure null terminator will fit in */
|
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &buffer->blocks, encoded_buffer, entry)
|
||||||
if (buffer->allocated < buffer->written + length + 4)
|
|
||||||
{
|
{
|
||||||
int grown_size = max(2*buffer->allocated, buffer->allocated + length);
|
list_remove(&cur->entry);
|
||||||
buffer->data = heap_realloc(buffer->data, grown_size);
|
free_encoded_buffer(cur);
|
||||||
buffer->allocated = grown_size;
|
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;
|
output_buffer *buffer = &writer->buffer;
|
||||||
char *ptr;
|
encoded_buffer *buff;
|
||||||
|
unsigned int written;
|
||||||
|
int src_len;
|
||||||
|
|
||||||
if (mode & (OutputBuffer_Encoded | OutputBuffer_Both)) {
|
if (!len || !*data)
|
||||||
if (buffer->code_page != ~0)
|
return S_OK;
|
||||||
|
|
||||||
|
src_len = len == -1 ? strlenW(data) : len;
|
||||||
|
if (writer->dest)
|
||||||
|
{
|
||||||
|
buff = &buffer->encoded;
|
||||||
|
|
||||||
|
if (buffer->code_page == ~0)
|
||||||
{
|
{
|
||||||
length = WideCharToMultiByte(buffer->code_page, 0, data, len, NULL, 0, NULL, NULL);
|
unsigned int avail = buff->allocated - buff->written;
|
||||||
grow_buffer(&buffer->encoded, length);
|
|
||||||
ptr = buffer->encoded.data + buffer->encoded.written;
|
src_len *= sizeof(WCHAR);
|
||||||
length = WideCharToMultiByte(buffer->code_page, 0, data, len, ptr, length, NULL, NULL);
|
written = min(avail, src_len);
|
||||||
buffer->encoded.written += len == -1 ? length-1 : length;
|
|
||||||
|
/* 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
|
||||||
|
{
|
||||||
|
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:
|
||||||
|
|
||||||
if (mode & (OutputBuffer_Native | OutputBuffer_Both)) {
|
- fill a buffer already allocated as part of output buffer;
|
||||||
/* WCHAR data just copied */
|
- when current buffer is full, allocate another one and switch to it; buffers themselves never grow,
|
||||||
length = len == -1 ? strlenW(data) : len;
|
but are linked together, with head pointing to first allocated buffer after initial one got filled;
|
||||||
if (length)
|
- 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);
|
||||||
|
|
||||||
|
src_len *= sizeof(WCHAR);
|
||||||
|
while (src_len)
|
||||||
{
|
{
|
||||||
length *= sizeof(WCHAR);
|
unsigned int avail = buff->allocated - buff->written;
|
||||||
|
unsigned int written = min(avail, src_len);
|
||||||
|
|
||||||
grow_buffer(&buffer->utf16, length);
|
if (avail)
|
||||||
ptr = buffer->utf16.data + buffer->utf16.written;
|
{
|
||||||
|
memcpy(buff->data + buff->written, data, written);
|
||||||
|
buff->written += written;
|
||||||
|
buffer->utf16_total += written;
|
||||||
|
src_len -= written;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(ptr, data, length);
|
/* alloc new block if needed and retry */
|
||||||
buffer->utf16.written += length;
|
if (src_len)
|
||||||
ptr += length;
|
{
|
||||||
/* null termination */
|
encoded_buffer *next = heap_alloc(sizeof(*next));
|
||||||
memset(ptr, 0, sizeof(WCHAR));
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = init_encoded_buffer(next))) {
|
||||||
|
heap_free(next);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_add_tail(&buffer->blocks, &next->entry);
|
||||||
|
buff = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT write_output_buffer(output_buffer *buffer, const WCHAR *data, int len)
|
static HRESULT write_output_buffer_quoted(mxwriter *writer, const WCHAR *data, int len)
|
||||||
{
|
{
|
||||||
return write_output_buffer_mode(buffer, OutputBuffer_Both, data, len);
|
write_output_buffer(writer, quotW, 1);
|
||||||
}
|
write_output_buffer(writer, data, len);
|
||||||
|
write_output_buffer(writer, quotW, 1);
|
||||||
static HRESULT write_output_buffer_quoted(output_buffer *buffer, const WCHAR *data, int len)
|
|
||||||
{
|
|
||||||
write_output_buffer(buffer, quotW, 1);
|
|
||||||
write_output_buffer(buffer, data, len);
|
|
||||||
write_output_buffer(buffer, quotW, 1);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* frees buffer data, reallocates with a default lengths */
|
/* 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);
|
encoded_buffer *cur, *cur2;
|
||||||
heap_free(This->buffer->encoded.data);
|
|
||||||
init_encoded_buffer(&This->buffer->utf16);
|
heap_free(writer->buffer.encoded.data);
|
||||||
init_encoded_buffer(&This->buffer->encoded);
|
|
||||||
get_code_page(This->xml_enc, &This->buffer->code_page);
|
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:
|
||||||
|
@ -452,7 +529,7 @@ static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_prolog_buffer(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 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 encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'};
|
||||||
|
@ -461,99 +538,83 @@ static void write_prolog_buffer(mxwriter *This)
|
||||||
static const WCHAR noW[] = {'n','o','\"','?','>'};
|
static const WCHAR noW[] = {'n','o','\"','?','>'};
|
||||||
|
|
||||||
/* version */
|
/* version */
|
||||||
write_output_buffer(This->buffer, versionW, sizeof(versionW)/sizeof(WCHAR));
|
write_output_buffer(writer, versionW, sizeof(versionW)/sizeof(WCHAR));
|
||||||
write_output_buffer_quoted(This->buffer, This->version, -1);
|
write_output_buffer_quoted(writer, writer->version, -1);
|
||||||
|
|
||||||
/* encoding */
|
/* encoding */
|
||||||
write_output_buffer(This->buffer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
|
write_output_buffer(writer, encodingW, sizeof(encodingW)/sizeof(WCHAR));
|
||||||
|
|
||||||
/* always write UTF-16 to WCHAR buffer */
|
if (writer->dest)
|
||||||
write_output_buffer_mode(This->buffer, OutputBuffer_Native, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
|
write_output_buffer(writer, writer->encoding, -1);
|
||||||
write_output_buffer_mode(This->buffer, OutputBuffer_Encoded, This->encoding, -1);
|
else
|
||||||
write_output_buffer(This->buffer, quotW, 1);
|
write_output_buffer(writer, utf16W, sizeof(utf16W)/sizeof(WCHAR) - 1);
|
||||||
|
write_output_buffer(writer, quotW, 1);
|
||||||
|
|
||||||
/* standalone */
|
/* standalone */
|
||||||
write_output_buffer(This->buffer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
|
write_output_buffer(writer, standaloneW, sizeof(standaloneW)/sizeof(WCHAR));
|
||||||
if (This->props[MXWriter_Standalone] == VARIANT_TRUE)
|
if (writer->props[MXWriter_Standalone] == VARIANT_TRUE)
|
||||||
write_output_buffer(This->buffer, yesW, sizeof(yesW)/sizeof(WCHAR));
|
write_output_buffer(writer, yesW, sizeof(yesW)/sizeof(WCHAR));
|
||||||
else
|
else
|
||||||
write_output_buffer(This->buffer, noW, sizeof(noW)/sizeof(WCHAR));
|
write_output_buffer(writer, noW, sizeof(noW)/sizeof(WCHAR));
|
||||||
|
|
||||||
write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
|
write_output_buffer(writer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
|
||||||
This->newline = TRUE;
|
writer->newline = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempts to the write data from the mxwriter's buffer to
|
/* Attempts to the write data from the mxwriter's buffer to
|
||||||
* the destination stream (if there is one).
|
* 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;
|
ULONG written = 0;
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (!This->dest)
|
if (!writer->dest)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
if (This->xml_enc != XmlEncoding_UTF16)
|
if (buffer->written == 0)
|
||||||
buffer = &This->buffer->encoded;
|
{
|
||||||
|
if (writer->xml_enc == XmlEncoding_UTF8)
|
||||||
|
IStream_Write(writer->dest, buffer->data, 0, &written);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
buffer = &This->buffer->utf16;
|
{
|
||||||
|
IStream_Write(writer->dest, buffer->data, buffer->written, &written);
|
||||||
if (This->dest_written > buffer->written) {
|
buffer->written = 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
This->dest_written += written;
|
return S_OK;
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Newly added element start tag left unclosed cause for empty elements
|
/* Newly added element start tag left unclosed cause for empty elements
|
||||||
we have to close it differently. */
|
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[] = {'>'};
|
static const WCHAR gtW[] = {'>'};
|
||||||
if (!This->element) return;
|
if (!writer->element) return;
|
||||||
write_output_buffer(This->buffer, gtW, 1);
|
write_output_buffer(writer, gtW, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_node_indent(mxwriter *This)
|
static void write_node_indent(mxwriter *writer)
|
||||||
{
|
{
|
||||||
static const WCHAR tabW[] = {'\t'};
|
static const WCHAR tabW[] = {'\t'};
|
||||||
int indent = This->indent;
|
int indent = writer->indent;
|
||||||
|
|
||||||
if (!This->props[MXWriter_Indent] || This->text)
|
if (!writer->props[MXWriter_Indent] || writer->text)
|
||||||
{
|
{
|
||||||
This->text = FALSE;
|
writer->text = FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is to workaround PI output logic that always puts newline chars,
|
/* This is to workaround PI output logic that always puts newline chars,
|
||||||
document prolog PI does that too. */
|
document prolog PI does that too. */
|
||||||
if (!This->newline)
|
if (!writer->newline)
|
||||||
write_output_buffer(This->buffer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
|
write_output_buffer(writer, crlfW, sizeof(crlfW)/sizeof(WCHAR));
|
||||||
while (indent--)
|
while (indent--)
|
||||||
write_output_buffer(This->buffer, tabW, 1);
|
write_output_buffer(writer, tabW, 1);
|
||||||
|
|
||||||
This->newline = FALSE;
|
writer->newline = FALSE;
|
||||||
This->text = FALSE;
|
writer->text = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void writer_inc_indent(mxwriter *This)
|
static inline void writer_inc_indent(mxwriter *This)
|
||||||
|
@ -592,7 +653,6 @@ static inline HRESULT flush_output_buffer(mxwriter *This)
|
||||||
static inline void reset_output_buffer(mxwriter *This)
|
static inline void reset_output_buffer(mxwriter *This)
|
||||||
{
|
{
|
||||||
close_output_buffer(This);
|
close_output_buffer(This);
|
||||||
This->dest_written = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
|
static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value)
|
||||||
|
@ -754,7 +814,7 @@ static ULONG WINAPI mxwriter_Release(IMXWriter *iface)
|
||||||
{
|
{
|
||||||
/* Windows flushes the buffer when the interface is destroyed. */
|
/* Windows flushes the buffer when the interface is destroyed. */
|
||||||
flush_output_buffer(This);
|
flush_output_buffer(This);
|
||||||
free_output_buffer(This->buffer);
|
free_output_buffer(&This->buffer);
|
||||||
|
|
||||||
if (This->dest) IStream_Release(This->dest);
|
if (This->dest) IStream_Release(This->dest);
|
||||||
SysFreeString(This->version);
|
SysFreeString(This->version);
|
||||||
|
@ -858,23 +918,44 @@ static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest)
|
||||||
|
|
||||||
if (!dest) return E_POINTER;
|
if (!dest) return E_POINTER;
|
||||||
|
|
||||||
if (!This->dest)
|
if (This->dest)
|
||||||
{
|
{
|
||||||
HRESULT hr = flush_output_buffer(This);
|
/* we only support IStream output so far */
|
||||||
|
V_VT(dest) = VT_UNKNOWN;
|
||||||
|
V_UNKNOWN(dest) = (IUnknown*)This->dest;
|
||||||
|
IStream_AddRef(This->dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
encoded_buffer *buff;
|
||||||
|
char *dest_ptr;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = flush_output_buffer(This);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
V_VT(dest) = VT_BSTR;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_FOR_EACH_ENTRY(buff, &This->buffer.blocks, encoded_buffer, entry)
|
||||||
|
{
|
||||||
|
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);
|
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,18 +1240,18 @@ static void mxwriter_write_attribute(mxwriter *writer, const WCHAR *qname, int q
|
||||||
static const WCHAR eqW[] = {'='};
|
static const WCHAR eqW[] = {'='};
|
||||||
|
|
||||||
/* space separator in front of every attribute */
|
/* space separator in front of every attribute */
|
||||||
write_output_buffer(writer->buffer, spaceW, 1);
|
write_output_buffer(writer, spaceW, 1);
|
||||||
write_output_buffer(writer->buffer, qname, qname_len);
|
write_output_buffer(writer, qname, qname_len);
|
||||||
write_output_buffer(writer->buffer, eqW, 1);
|
write_output_buffer(writer, eqW, 1);
|
||||||
|
|
||||||
if (escape)
|
if (escape)
|
||||||
{
|
{
|
||||||
WCHAR *escaped = get_escaped_string(value, EscapeValue, &value_len);
|
WCHAR *escaped = get_escaped_string(value, EscapeValue, &value_len);
|
||||||
write_output_buffer_quoted(writer->buffer, escaped, value_len);
|
write_output_buffer_quoted(writer, escaped, value_len);
|
||||||
heap_free(escaped);
|
heap_free(escaped);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
write_output_buffer_quoted(writer->buffer, value, value_len);
|
write_output_buffer_quoted(writer, value, value_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int len)
|
static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int len)
|
||||||
|
@ -1182,8 +1263,8 @@ static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int le
|
||||||
|
|
||||||
write_node_indent(writer);
|
write_node_indent(writer);
|
||||||
|
|
||||||
write_output_buffer(writer->buffer, ltW, 1);
|
write_output_buffer(writer, ltW, 1);
|
||||||
write_output_buffer(writer->buffer, qname ? qname : emptyW, qname ? len : 0);
|
write_output_buffer(writer, qname ? qname : emptyW, qname ? len : 0);
|
||||||
writer_inc_indent(writer);
|
writer_inc_indent(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,7 +1341,7 @@ static HRESULT WINAPI SAXContentHandler_endElement(
|
||||||
if (This->element)
|
if (This->element)
|
||||||
{
|
{
|
||||||
static const WCHAR closeW[] = {'/','>'};
|
static const WCHAR closeW[] = {'/','>'};
|
||||||
write_output_buffer(This->buffer, closeW, 2);
|
write_output_buffer(This, closeW, 2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1268,9 +1349,9 @@ static HRESULT WINAPI SAXContentHandler_endElement(
|
||||||
static const WCHAR gtW[] = {'>'};
|
static const WCHAR gtW[] = {'>'};
|
||||||
|
|
||||||
write_node_indent(This);
|
write_node_indent(This);
|
||||||
write_output_buffer(This->buffer, closetagW, 2);
|
write_output_buffer(This, closetagW, 2);
|
||||||
write_output_buffer(This->buffer, QName, nQName);
|
write_output_buffer(This, QName, nQName);
|
||||||
write_output_buffer(This->buffer, gtW, 1);
|
write_output_buffer(This, gtW, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_element_name(This, NULL, 0);
|
set_element_name(This, NULL, 0);
|
||||||
|
@ -1298,14 +1379,14 @@ static HRESULT WINAPI SAXContentHandler_characters(
|
||||||
if (nchars)
|
if (nchars)
|
||||||
{
|
{
|
||||||
if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
|
if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE)
|
||||||
write_output_buffer(This->buffer, chars, nchars);
|
write_output_buffer(This, chars, nchars);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int len = nchars;
|
int len = nchars;
|
||||||
WCHAR *escaped;
|
WCHAR *escaped;
|
||||||
|
|
||||||
escaped = get_escaped_string(chars, EscapeText, &len);
|
escaped = get_escaped_string(chars, EscapeText, &len);
|
||||||
write_output_buffer(This->buffer, escaped, len);
|
write_output_buffer(This, escaped, len);
|
||||||
heap_free(escaped);
|
heap_free(escaped);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1405,7 @@ static HRESULT WINAPI SAXContentHandler_ignorableWhitespace(
|
||||||
|
|
||||||
if (!chars) return E_INVALIDARG;
|
if (!chars) return E_INVALIDARG;
|
||||||
|
|
||||||
write_output_buffer(This->buffer, chars, nchars);
|
write_output_buffer(This, chars, nchars);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1345,18 +1426,18 @@ static HRESULT WINAPI SAXContentHandler_processingInstruction(
|
||||||
if (!target) return E_INVALIDARG;
|
if (!target) return E_INVALIDARG;
|
||||||
|
|
||||||
write_node_indent(This);
|
write_node_indent(This);
|
||||||
write_output_buffer(This->buffer, openpiW, sizeof(openpiW)/sizeof(WCHAR));
|
write_output_buffer(This, openpiW, sizeof(openpiW)/sizeof(WCHAR));
|
||||||
|
|
||||||
if (*target)
|
if (*target)
|
||||||
write_output_buffer(This->buffer, target, ntarget);
|
write_output_buffer(This, target, ntarget);
|
||||||
|
|
||||||
if (data && *data && ndata)
|
if (data && *data && ndata)
|
||||||
{
|
{
|
||||||
write_output_buffer(This->buffer, spaceW, 1);
|
write_output_buffer(This, spaceW, 1);
|
||||||
write_output_buffer(This->buffer, data, ndata);
|
write_output_buffer(This, data, ndata);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_output_buffer(This->buffer, closepiW, sizeof(closepiW)/sizeof(WCHAR));
|
write_output_buffer(This, closepiW, sizeof(closepiW)/sizeof(WCHAR));
|
||||||
This->newline = TRUE;
|
This->newline = TRUE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1424,42 +1505,38 @@ static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface,
|
||||||
|
|
||||||
if (!name) return E_INVALIDARG;
|
if (!name) return E_INVALIDARG;
|
||||||
|
|
||||||
write_output_buffer(This->buffer, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
|
write_output_buffer(This, doctypeW, sizeof(doctypeW)/sizeof(WCHAR));
|
||||||
|
|
||||||
if (*name)
|
if (*name)
|
||||||
{
|
{
|
||||||
write_output_buffer(This->buffer, name, name_len);
|
write_output_buffer(This, name, name_len);
|
||||||
write_output_buffer(This->buffer, spaceW, 1);
|
write_output_buffer(This, spaceW, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publicId)
|
if (publicId)
|
||||||
{
|
{
|
||||||
static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
|
write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer_quoted(This, publicId, publicId_len);
|
||||||
write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
|
|
||||||
write_output_buffer_quoted(This->buffer, publicId, publicId_len);
|
|
||||||
|
|
||||||
if (!systemId) return E_INVALIDARG;
|
if (!systemId) return E_INVALIDARG;
|
||||||
|
|
||||||
if (*publicId)
|
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)
|
if (*systemId)
|
||||||
write_output_buffer(This->buffer, spaceW, 1);
|
write_output_buffer(This, spaceW, 1);
|
||||||
}
|
}
|
||||||
else if (systemId)
|
else if (systemId)
|
||||||
{
|
{
|
||||||
static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
|
write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer_quoted(This, systemId, systemId_len);
|
||||||
write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
|
|
||||||
write_output_buffer_quoted(This->buffer, systemId, systemId_len);
|
|
||||||
if (*systemId)
|
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, sizeof(openintW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1471,7 +1548,7 @@ static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface)
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
write_output_buffer(This->buffer, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
|
write_output_buffer(This, closedtdW, sizeof(closedtdW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1498,7 +1575,7 @@ static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface)
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
write_node_indent(This);
|
write_node_indent(This);
|
||||||
write_output_buffer(This->buffer, scdataW, sizeof(scdataW)/sizeof(WCHAR));
|
write_output_buffer(This, scdataW, sizeof(scdataW)/sizeof(WCHAR));
|
||||||
This->cdata = TRUE;
|
This->cdata = TRUE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1511,7 +1588,7 @@ static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface)
|
||||||
|
|
||||||
TRACE("(%p)\n", This);
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
write_output_buffer(This->buffer, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
|
write_output_buffer(This, ecdataW, sizeof(ecdataW)/sizeof(WCHAR));
|
||||||
This->cdata = FALSE;
|
This->cdata = FALSE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1530,10 +1607,10 @@ static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const
|
||||||
close_element_starttag(This);
|
close_element_starttag(This);
|
||||||
write_node_indent(This);
|
write_node_indent(This);
|
||||||
|
|
||||||
write_output_buffer(This->buffer, copenW, sizeof(copenW)/sizeof(WCHAR));
|
write_output_buffer(This, copenW, sizeof(copenW)/sizeof(WCHAR));
|
||||||
if (nchars)
|
if (nchars)
|
||||||
write_output_buffer(This->buffer, chars, nchars);
|
write_output_buffer(This, chars, nchars);
|
||||||
write_output_buffer(This->buffer, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
|
write_output_buffer(This, ccloseW, sizeof(ccloseW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1583,14 +1660,14 @@ static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface,
|
||||||
|
|
||||||
if (!name || !model) return E_INVALIDARG;
|
if (!name || !model) return E_INVALIDARG;
|
||||||
|
|
||||||
write_output_buffer(This->buffer, elementW, sizeof(elementW)/sizeof(WCHAR));
|
write_output_buffer(This, elementW, sizeof(elementW)/sizeof(WCHAR));
|
||||||
if (n_name) {
|
if (n_name) {
|
||||||
write_output_buffer(This->buffer, name, n_name);
|
write_output_buffer(This, name, n_name);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
if (n_model)
|
if (n_model)
|
||||||
write_output_buffer(This->buffer, model, n_model);
|
write_output_buffer(This, model, n_model);
|
||||||
write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
|
write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1608,31 +1685,31 @@ static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface,
|
||||||
debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default,
|
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);
|
debugstr_wn(value, n_value), n_value);
|
||||||
|
|
||||||
write_output_buffer(This->buffer, attlistW, sizeof(attlistW)/sizeof(WCHAR));
|
write_output_buffer(This, attlistW, sizeof(attlistW)/sizeof(WCHAR));
|
||||||
if (n_element) {
|
if (n_element) {
|
||||||
write_output_buffer(This->buffer, element, n_element);
|
write_output_buffer(This, element, n_element);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_attr) {
|
if (n_attr) {
|
||||||
write_output_buffer(This->buffer, attr, n_attr);
|
write_output_buffer(This, attr, n_attr);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_type) {
|
if (n_type) {
|
||||||
write_output_buffer(This->buffer, type, n_type);
|
write_output_buffer(This, type, n_type);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_default) {
|
if (n_default) {
|
||||||
write_output_buffer(This->buffer, Default, n_default);
|
write_output_buffer(This, Default, n_default);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_value)
|
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, sizeof(closetagW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1647,16 +1724,16 @@ static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface,
|
||||||
|
|
||||||
if (!name || !value) return E_INVALIDARG;
|
if (!name || !value) return E_INVALIDARG;
|
||||||
|
|
||||||
write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
|
write_output_buffer(This, entityW, sizeof(entityW)/sizeof(WCHAR));
|
||||||
if (n_name) {
|
if (n_name) {
|
||||||
write_output_buffer(This->buffer, name, n_name);
|
write_output_buffer(This, name, n_name);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_value)
|
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, sizeof(closetagW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -1665,37 +1742,33 @@ static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface,
|
||||||
const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
|
const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId,
|
||||||
const WCHAR *systemId, int n_systemId)
|
const WCHAR *systemId, int n_systemId)
|
||||||
{
|
{
|
||||||
static const WCHAR publicW[] = {'P','U','B','L','I','C',' '};
|
|
||||||
static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '};
|
|
||||||
mxwriter *This = impl_from_ISAXDeclHandler( iface );
|
mxwriter *This = impl_from_ISAXDeclHandler( iface );
|
||||||
|
|
||||||
TRACE("(%p)->(%s:%d %s:%d %s:%d)\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);
|
debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId);
|
||||||
|
|
||||||
if (!name) return E_INVALIDARG;
|
if (!name || !systemId) return E_INVALIDARG;
|
||||||
if (publicId && !systemId) return E_INVALIDARG;
|
|
||||||
if (!publicId && !systemId) return E_INVALIDARG;
|
|
||||||
|
|
||||||
write_output_buffer(This->buffer, entityW, sizeof(entityW)/sizeof(WCHAR));
|
write_output_buffer(This, entityW, sizeof(entityW)/sizeof(WCHAR));
|
||||||
if (n_name) {
|
if (n_name) {
|
||||||
write_output_buffer(This->buffer, name, n_name);
|
write_output_buffer(This, name, n_name);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publicId)
|
if (publicId)
|
||||||
{
|
{
|
||||||
write_output_buffer(This->buffer, publicW, sizeof(publicW)/sizeof(WCHAR));
|
write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
|
||||||
write_output_buffer_quoted(This->buffer, publicId, n_publicId);
|
write_output_buffer_quoted(This, publicId, n_publicId);
|
||||||
write_output_buffer(This->buffer, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
write_output_buffer_quoted(This->buffer, systemId, n_systemId);
|
write_output_buffer_quoted(This, systemId, n_systemId);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_output_buffer(This->buffer, systemW, sizeof(systemW)/sizeof(WCHAR));
|
write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
|
||||||
write_output_buffer_quoted(This->buffer, systemId, n_systemId);
|
write_output_buffer_quoted(This, systemId, n_systemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
write_output_buffer(This->buffer, closetagW, sizeof(closetagW)/sizeof(WCHAR));
|
write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
@ -2194,14 +2267,45 @@ static ULONG WINAPI SAXDTDHandler_Release(ISAXDTDHandler *iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
|
static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface,
|
||||||
const WCHAR *name, INT nname,
|
const WCHAR *name, INT n_name,
|
||||||
const WCHAR *publicid, INT npublicid,
|
const WCHAR *publicid, INT n_publicid,
|
||||||
const WCHAR *systemid, INT nsystemid)
|
const WCHAR *systemid, INT n_systemid)
|
||||||
{
|
{
|
||||||
|
static const WCHAR notationW[] = {'<','!','N','O','T','A','T','I','O','N',' '};
|
||||||
mxwriter *This = impl_from_ISAXDTDHandler( iface );
|
mxwriter *This = impl_from_ISAXDTDHandler( iface );
|
||||||
FIXME("(%p)->(%s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname,
|
|
||||||
debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid);
|
TRACE("(%p)->(%s:%d, %s:%d, %s:%d)\n", This, debugstr_wn(name, n_name), n_name,
|
||||||
return E_NOTIMPL;
|
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, sizeof(notationW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer(This, name, n_name);
|
||||||
|
|
||||||
|
if (!publicid && !systemid)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
|
if (publicid)
|
||||||
|
{
|
||||||
|
write_output_buffer(This, publicW, sizeof(publicW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer_quoted(This, publicid, n_publicid);
|
||||||
|
if (systemid)
|
||||||
|
{
|
||||||
|
write_output_buffer(This, spaceW, sizeof(spaceW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer_quoted(This, systemid, n_systemid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_output_buffer(This, systemW, sizeof(systemW)/sizeof(WCHAR));
|
||||||
|
write_output_buffer_quoted(This, systemid, n_systemid);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_output_buffer(This, closetagW, sizeof(closetagW)/sizeof(WCHAR));
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface,
|
static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface,
|
||||||
|
@ -2502,9 +2606,8 @@ HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj)
|
||||||
This->newline = FALSE;
|
This->newline = FALSE;
|
||||||
|
|
||||||
This->dest = NULL;
|
This->dest = NULL;
|
||||||
This->dest_written = 0;
|
|
||||||
|
|
||||||
hr = alloc_output_buffer(This->xml_enc, &This->buffer);
|
hr = init_output_buffer(This->xml_enc, &This->buffer);
|
||||||
if (hr != S_OK) {
|
if (hr != S_OK) {
|
||||||
SysFreeString(This->encoding);
|
SysFreeString(This->encoding);
|
||||||
SysFreeString(This->version);
|
SysFreeString(This->version);
|
||||||
|
|
|
@ -412,13 +412,13 @@ int xmlnode_get_inst_cnt(xmlnode *node)
|
||||||
|
|
||||||
/* _private field holds a number of COM instances spawned from this libxml2 node
|
/* _private field holds a number of COM instances spawned from this libxml2 node
|
||||||
* most significant bits are used to store information about ignorrable whitespace nodes */
|
* most significant bits are used to store information about ignorrable whitespace nodes */
|
||||||
static void xmlnode_add_ref(xmlNodePtr node)
|
void xmlnode_add_ref(xmlNodePtr node)
|
||||||
{
|
{
|
||||||
if (node->type == XML_DOCUMENT_NODE) return;
|
if (node->type == XML_DOCUMENT_NODE) return;
|
||||||
InterlockedIncrement((LONG*)&node->_private);
|
InterlockedIncrement((LONG*)&node->_private);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xmlnode_release(xmlNodePtr node)
|
void xmlnode_release(xmlNodePtr node)
|
||||||
{
|
{
|
||||||
if (node->type == XML_DOCUMENT_NODE) return;
|
if (node->type == XML_DOCUMENT_NODE) return;
|
||||||
InterlockedDecrement((LONG*)&node->_private);
|
InterlockedDecrement((LONG*)&node->_private);
|
||||||
|
|
|
@ -120,6 +120,7 @@ static ULONG WINAPI xmlnodemap_Release(
|
||||||
TRACE("(%p)->(%d)\n", This, ref);
|
TRACE("(%p)->(%d)\n", This, ref);
|
||||||
if ( ref == 0 )
|
if ( ref == 0 )
|
||||||
{
|
{
|
||||||
|
xmlnode_release( This->node );
|
||||||
xmldoc_release( This->node->doc );
|
xmldoc_release( This->node->doc );
|
||||||
if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
|
if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
|
||||||
heap_free( This );
|
heap_free( This );
|
||||||
|
@ -430,6 +431,7 @@ IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs
|
||||||
|
|
||||||
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
|
init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
|
||||||
|
|
||||||
|
xmlnode_add_ref(node);
|
||||||
xmldoc_add_ref(node->doc);
|
xmldoc_add_ref(node->doc);
|
||||||
|
|
||||||
return &This->IXMLDOMNamedNodeMap_iface;
|
return &This->IXMLDOMNamedNodeMap_iface;
|
||||||
|
|
|
@ -2500,7 +2500,7 @@ static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int siz
|
||||||
if (encoding == XML_CHAR_ENCODING_NONE)
|
if (encoding == XML_CHAR_ENCODING_NONE)
|
||||||
{
|
{
|
||||||
const WCHAR *ptr = (WCHAR*)buffer;
|
const WCHAR *ptr = (WCHAR*)buffer;
|
||||||
/* xml declaration with possibly specfied encoding will be still handled by parser */
|
/* xml declaration with possibly specified encoding will be still handled by parser */
|
||||||
if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
|
if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
|
||||||
{
|
{
|
||||||
enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
|
enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
|
||||||
|
|
|
@ -789,7 +789,7 @@ static inline schema_cache* impl_from_IXMLDOMSchemaCollection2(IXMLDOMSchemaColl
|
||||||
|
|
||||||
static inline schema_cache* impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection* iface)
|
static inline schema_cache* impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection* iface)
|
||||||
{
|
{
|
||||||
return CONTAINING_RECORD(iface, schema_cache, IXMLDOMSchemaCollection2_iface);
|
return CONTAINING_RECORD((IXMLDOMSchemaCollection2 *)iface, schema_cache, IXMLDOMSchemaCollection2_iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline schema_cache* unsafe_impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection *iface)
|
static inline schema_cache* unsafe_impl_from_IXMLDOMSchemaCollection(IXMLDOMSchemaCollection *iface)
|
||||||
|
@ -1085,6 +1085,18 @@ static HRESULT WINAPI schema_cache_QueryInterface(IXMLDOMSchemaCollection2* ifac
|
||||||
{
|
{
|
||||||
*ppvObject = iface;
|
*ppvObject = iface;
|
||||||
}
|
}
|
||||||
|
else if(This->version == MSXML6 && IsEqualIID(riid, &CLSID_XMLSchemaCache60))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Version 6 can be queried for an interface with IID equal to CLSID.
|
||||||
|
* There is no public interface with that IID and returned pointer
|
||||||
|
* is equal to returned IXMLDOMSchemaCollection2 iface. We assume
|
||||||
|
* that it's just another way for querying IXMLDOMSchemaCollection2
|
||||||
|
* interface. Office 2013 ClickToRun installer uses this.
|
||||||
|
*/
|
||||||
|
WARN("riid CLSID_XMLSchemaCache60, returning IXMLDOMSchemaCollection2 interface.\n");
|
||||||
|
*ppvObject = iface;
|
||||||
|
}
|
||||||
else if (dispex_query_interface(&This->dispex, riid, ppvObject))
|
else if (dispex_query_interface(&This->dispex, riid, ppvObject))
|
||||||
{
|
{
|
||||||
return *ppvObject ? S_OK : E_NOINTERFACE;
|
return *ppvObject ? S_OK : E_NOINTERFACE;
|
||||||
|
@ -1206,12 +1218,13 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VT_DISPATCH:
|
case VT_DISPATCH:
|
||||||
|
case VT_UNKNOWN:
|
||||||
{
|
{
|
||||||
xmlDocPtr doc = NULL;
|
xmlDocPtr doc = NULL;
|
||||||
cache_entry* entry;
|
cache_entry* entry;
|
||||||
CacheEntryType type;
|
CacheEntryType type;
|
||||||
IXMLDOMNode* domnode = NULL;
|
IXMLDOMNode* domnode = NULL;
|
||||||
IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLDOMNode, (void**)&domnode);
|
IUnknown_QueryInterface(V_UNKNOWN(&var), &IID_IXMLDOMNode, (void**)&domnode);
|
||||||
|
|
||||||
if (domnode)
|
if (domnode)
|
||||||
doc = xmlNodePtr_from_domnode(domnode, XML_DOCUMENT_NODE)->doc;
|
doc = xmlNodePtr_from_domnode(domnode, XML_DOCUMENT_NODE)->doc;
|
||||||
|
@ -1255,10 +1268,9 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
FIXME("arg type is not supported, %s\n", debugstr_variant(&var));
|
||||||
heap_free(name);
|
heap_free(name);
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
heap_free(name);
|
heap_free(name);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -131,7 +131,7 @@ reactos/dll/win32/msvfw32 # Synced to WineStaging-1.9.11
|
||||||
reactos/dll/win32/msvidc32 # Synced to WineStaging-1.9.11
|
reactos/dll/win32/msvidc32 # Synced to WineStaging-1.9.11
|
||||||
reactos/dll/win32/msxml # Synced to WineStaging-1.9.4
|
reactos/dll/win32/msxml # Synced to WineStaging-1.9.4
|
||||||
reactos/dll/win32/msxml2 # Synced to WineStaging-1.9.4
|
reactos/dll/win32/msxml2 # Synced to WineStaging-1.9.4
|
||||||
reactos/dll/win32/msxml3 # Synced to WineStaging-1.9.4
|
reactos/dll/win32/msxml3 # Synced to WineStaging-1.9.11
|
||||||
reactos/dll/win32/msxml4 # Synced to WineStaging-1.9.4
|
reactos/dll/win32/msxml4 # Synced to WineStaging-1.9.4
|
||||||
reactos/dll/win32/msxml6 # Synced to WineStaging-1.9.4
|
reactos/dll/win32/msxml6 # Synced to WineStaging-1.9.4
|
||||||
reactos/dll/win32/nddeapi # Synced to WineStaging-1.9.4
|
reactos/dll/win32/nddeapi # Synced to WineStaging-1.9.4
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue