[MSXML3] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / msxml3 / saxreader.c
index 9ebdc0f..fc27260 100644 (file)
 #include "shlwapi.h"
 
 #include "wine/debug.h"
-#include "wine/list.h"
 
 #include "msxml_private.h"
 
-WINE_DEFAULT_DEBUG_CHANNEL(msxml);
-
 #ifdef HAVE_LIBXML2
 
+WINE_DEFAULT_DEBUG_CHANNEL(msxml);
+
 typedef enum
 {
     FeatureUnknown               = 0,
@@ -101,6 +100,14 @@ static const WCHAR FeatureNamespacePrefixesW[] = {
     '/','n','a','m','e','s','p','a','c','e','-','p','r','e','f','i','x','e','s',0
 };
 
+static const WCHAR ExhaustiveErrorsW[] = {
+    'e','x','h','a','u','s','t','i','v','e','-','e','r','r','o','r','s',0
+};
+
+static const WCHAR SchemaValidationW[] = {
+    's','c','h','e','m','a','-','v','a','l','i','d','a','t','i','o','n',0
+};
+
 struct saxreader_feature_pair
 {
     saxreader_feature feature;
@@ -108,12 +115,14 @@ struct saxreader_feature_pair
 };
 
 static const struct saxreader_feature_pair saxreader_feature_map[] = {
+    { ExhaustiveErrors, ExhaustiveErrorsW },
     { ExternalGeneralEntities, FeatureExternalGeneralEntitiesW },
     { ExternalParameterEntities, FeatureExternalParameterEntitiesW },
     { LexicalHandlerParEntities, FeatureLexicalHandlerParEntitiesW },
     { NamespacePrefixes, FeatureNamespacePrefixesW },
     { Namespaces, FeatureNamespacesW },
-    { ProhibitDTD, FeatureProhibitDTDW }
+    { ProhibitDTD, FeatureProhibitDTDW },
+    { SchemaValidation, SchemaValidationW },
 };
 
 static saxreader_feature get_saxreader_feature(const WCHAR *name)
@@ -121,7 +130,7 @@ static saxreader_feature get_saxreader_feature(const WCHAR *name)
     int min, max, n, c;
 
     min = 0;
-    max = sizeof(saxreader_feature_map)/sizeof(struct saxreader_feature_pair) - 1;
+    max = ARRAY_SIZE(saxreader_feature_map) - 1;
 
     while (min <= max)
     {
@@ -140,6 +149,8 @@ static saxreader_feature get_saxreader_feature(const WCHAR *name)
     return FeatureUnknown;
 }
 
+static const WCHAR empty_str;
+
 struct bstrpool
 {
     BSTR *pool;
@@ -168,12 +179,13 @@ enum saxhandler_type
     SAXContentHandler = 0,
     SAXDeclHandler,
     SAXDTDHandler,
+    SAXEntityResolver,
     SAXErrorHandler,
     SAXLexicalHandler,
     SAXHandler_Last
 };
 
-struct saxhandler_iface
+struct saxanyhandler_iface
 {
     IUnknown *handler;
     IUnknown *vbhandler;
@@ -197,6 +209,23 @@ struct saxlexicalhandler_iface
     IVBSAXLexicalHandler *vbhandler;
 };
 
+struct saxentityresolver_iface
+{
+    ISAXEntityResolver *handler;
+    IVBSAXEntityResolver *vbhandler;
+};
+
+struct saxhandler_iface
+{
+    union {
+        struct saxcontenthandler_iface content;
+        struct saxentityresolver_iface entityresolver;
+        struct saxerrorhandler_iface error;
+        struct saxlexicalhandler_iface lexical;
+        struct saxanyhandler_iface anyhandler;
+    } u;
+};
+
 typedef struct
 {
     DispatchEx dispex;
@@ -215,7 +244,7 @@ typedef struct
 
 static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type type, void *ptr, BOOL vb)
 {
-    struct saxhandler_iface *iface = &reader->saxhandlers[type];
+    struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
     IUnknown *unk = (IUnknown*)ptr;
 
     if (unk)
@@ -234,7 +263,7 @@ static HRESULT saxreader_put_handler(saxreader *reader, enum saxhandler_type typ
 
 static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_type type, BOOL vb, void **ret)
 {
-    const struct saxhandler_iface *iface = &reader->saxhandlers[type];
+    const struct saxanyhandler_iface *iface = &reader->saxhandlers[type].u.anyhandler;
 
     if (!ret) return E_POINTER;
 
@@ -253,17 +282,17 @@ static HRESULT saxreader_get_handler(const saxreader *reader, enum saxhandler_ty
 
 static struct saxcontenthandler_iface *saxreader_get_contenthandler(saxreader *reader)
 {
-    return (struct saxcontenthandler_iface*)&reader->saxhandlers[SAXContentHandler];
+    return &reader->saxhandlers[SAXContentHandler].u.content;
 }
 
 static struct saxerrorhandler_iface *saxreader_get_errorhandler(saxreader *reader)
 {
-    return (struct saxerrorhandler_iface*)&reader->saxhandlers[SAXErrorHandler];
+    return &reader->saxhandlers[SAXErrorHandler].u.error;
 }
 
 static struct saxlexicalhandler_iface *saxreader_get_lexicalhandler(saxreader *reader)
 {
-    return (struct saxlexicalhandler_iface*)&reader->saxhandlers[SAXLexicalHandler];
+    return &reader->saxhandlers[SAXLexicalHandler].u.lexical;
 }
 
 typedef struct
@@ -276,16 +305,16 @@ typedef struct
     saxreader *saxreader;
     HRESULT ret;
     xmlParserCtxtPtr pParserCtxt;
-    WCHAR *publicId;
-    WCHAR *systemId;
+    BSTR publicId;
+    BSTR systemId;
     int line;
     int column;
     BOOL vbInterface;
     struct list elements;
 
     BSTR namespaceUri;
-    int attributesSize;
-    int nb_attributes;
+    int attr_alloc_count;
+    int attr_count;
     struct _attributes
     {
         BSTR szLocalname;
@@ -325,10 +354,25 @@ static inline saxlocator *impl_from_ISAXAttributes( ISAXAttributes *iface )
     return CONTAINING_RECORD(iface, saxlocator, ISAXAttributes_iface);
 }
 
-static inline int saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
+static inline BOOL saxreader_has_handler(const saxlocator *locator, enum saxhandler_type type)
 {
-    return (locator->vbInterface && locator->saxreader->saxhandlers[type].vbhandler) ||
-          (!locator->vbInterface && locator->saxreader->saxhandlers[type].handler);
+    struct saxanyhandler_iface *iface = &locator->saxreader->saxhandlers[type].u.anyhandler;
+    return (locator->vbInterface && iface->vbhandler) || (!locator->vbInterface && iface->handler);
+}
+
+static HRESULT saxreader_saxcharacters(saxlocator *locator, BSTR chars)
+{
+    struct saxcontenthandler_iface *content = saxreader_get_contenthandler(locator->saxreader);
+    HRESULT hr;
+
+    if (!saxreader_has_handler(locator, SAXContentHandler)) return S_OK;
+
+    if (locator->vbInterface)
+        hr = IVBSAXContentHandler_characters(content->vbhandler, &chars);
+    else
+        hr = ISAXContentHandler_characters(content->handler, chars, SysStringLen(chars));
+
+    return hr;
 }
 
 /* property names */
@@ -458,6 +502,7 @@ static void free_element_entry(element_entry *element)
 
     SysFreeString(element->prefix);
     SysFreeString(element->local);
+    SysFreeString(element->qname);
 
     heap_free(element->ns);
     heap_free(element);
@@ -528,7 +573,7 @@ static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
 {
     if (!pool->pool)
     {
-        pool->pool = HeapAlloc(GetProcessHeap(), 0, 16 * sizeof(*pool->pool));
+        pool->pool = heap_alloc(16 * sizeof(*pool->pool));
         if (!pool->pool)
             return FALSE;
 
@@ -537,7 +582,7 @@ static BOOL bstr_pool_insert(struct bstrpool *pool, BSTR pool_entry)
     }
     else if (pool->index == pool->len)
     {
-        BSTR *realloc = HeapReAlloc(GetProcessHeap(), 0, pool->pool, pool->len * 2 * sizeof(*realloc));
+        BSTR *realloc = heap_realloc(pool->pool, pool->len * 2 * sizeof(*realloc));
 
         if (!realloc)
             return FALSE;
@@ -557,7 +602,7 @@ static void free_bstr_pool(struct bstrpool *pool)
     for (i = 0; i < pool->index; i++)
         SysFreeString(pool->pool[i]);
 
-    HeapFree(GetProcessHeap(), 0, pool->pool);
+    heap_free(pool->pool);
 
     pool->pool = NULL;
     pool->index = pool->len = 0;
@@ -635,7 +680,7 @@ static void format_error_message_from_id(saxlocator *This, HRESULT hr)
     {
         WCHAR msg[1024];
         if(!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
-                    NULL, hr, 0, msg, sizeof(msg), NULL))
+                    NULL, hr, 0, msg, ARRAY_SIZE(msg), NULL))
         {
             FIXME("MSXML errors not yet supported.\n");
             msg[0] = '\0';
@@ -657,12 +702,13 @@ static void format_error_message_from_id(saxlocator *This, HRESULT hr)
 static void update_position(saxlocator *This, BOOL fix_column)
 {
     const xmlChar *p = This->pParserCtxt->input->cur-1;
+    const xmlChar *baseP = This->pParserCtxt->input->base;
 
     This->line = xmlSAX2GetLineNumber(This->pParserCtxt);
     if(fix_column)
     {
         This->column = 1;
-        for(; *p!='\n' && *p!='\r' && p>=This->pParserCtxt->input->base; p--)
+        for(;p>=baseP && *p!='\n' && *p!='\r'; p--)
             This->column++;
     }
     else
@@ -672,7 +718,6 @@ static void update_position(saxlocator *This, BOOL fix_column)
 }
 
 /*** IVBSAXAttributes interface ***/
-/*** IUnknown methods ***/
 static HRESULT WINAPI ivbsaxattributes_QueryInterface(
         IVBSAXAttributes* iface,
         REFIID riid,
@@ -686,16 +731,15 @@ static HRESULT WINAPI ivbsaxattributes_QueryInterface(
 static ULONG WINAPI ivbsaxattributes_AddRef(IVBSAXAttributes* iface)
 {
     saxlocator *This = impl_from_IVBSAXAttributes(iface);
-    return ISAXLocator_AddRef(&This->ISAXLocator_iface);
+    return IVBSAXLocator_AddRef(&This->IVBSAXLocator_iface);
 }
 
 static ULONG WINAPI ivbsaxattributes_Release(IVBSAXAttributes* iface)
 {
     saxlocator *This = impl_from_IVBSAXAttributes(iface);
-    return ISAXLocator_Release(&This->ISAXLocator_iface);
+    return IVBSAXLocator_Release(&This->IVBSAXLocator_iface);
 }
 
-/*** IDispatch methods ***/
 static HRESULT WINAPI ivbsaxattributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo )
 {
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
@@ -712,13 +756,10 @@ static HRESULT WINAPI ivbsaxattributes_GetTypeInfo(
     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
 {
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    HRESULT hr;
 
     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
 
-    hr = get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
-
-    return hr;
+    return get_typeinfo(IVBSAXAttributes_tid, ppTInfo);
 }
 
 static HRESULT WINAPI ivbsaxattributes_GetIDsOfNames(
@@ -792,20 +833,45 @@ static HRESULT WINAPI ivbsaxattributes_getURI(
         int nIndex,
         BSTR *uri)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)uri, &len);
+    const WCHAR *uriW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%d %p)\n", This, nIndex, uri);
+
+    if (!uri)
+        return E_POINTER;
+
+    *uri = NULL;
+    hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, nIndex, &uriW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(uriW, len, uri);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getLocalName(
         IVBSAXAttributes* iface,
         int nIndex,
-        BSTR *localName)
+        BSTR *name)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex,
-            (const WCHAR**)localName, &len);
+    const WCHAR *nameW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%d %p)\n", This, nIndex, name);
+
+    if (!name)
+        return E_POINTER;
+
+    *name = NULL;
+    hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(nameW, len, name);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getQName(
@@ -813,9 +879,22 @@ static HRESULT WINAPI ivbsaxattributes_getQName(
         int nIndex,
         BSTR *QName)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)QName, &len);
+    const WCHAR *nameW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%d %p)\n", This, nIndex, QName);
+
+    if (!QName)
+        return E_POINTER;
+
+    *QName = NULL;
+    hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, nIndex, &nameW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(nameW, len, QName);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getIndexFromName(
@@ -844,9 +923,22 @@ static HRESULT WINAPI ivbsaxattributes_getType(
         int nIndex,
         BSTR *type)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)type, &len);
+    const WCHAR *typeW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%d %p)\n", This, nIndex, type);
+
+    if (!type)
+        return E_POINTER;
+
+    *type = NULL;
+    hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, nIndex, &typeW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(typeW, len, type);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
@@ -855,10 +947,23 @@ static HRESULT WINAPI ivbsaxattributes_getTypeFromName(
         BSTR localName,
         BSTR *type)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
-            localName, SysStringLen(localName), (const WCHAR**)type, &len);
+    const WCHAR *typeW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), type);
+
+    if (!type)
+        return E_POINTER;
+
+    *type = NULL;
+    hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
+            localName, SysStringLen(localName), &typeW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(typeW, len, type);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
@@ -866,10 +971,23 @@ static HRESULT WINAPI ivbsaxattributes_getTypeFromQName(
         BSTR QName,
         BSTR *type)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, QName, SysStringLen(QName),
-            (const WCHAR**)type, &len);
+    const WCHAR *typeW;
+    HRESULT hr;
+    int 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 ivbsaxattributes_getValue(
@@ -877,9 +995,22 @@ static HRESULT WINAPI ivbsaxattributes_getValue(
         int nIndex,
         BSTR *value)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, (const WCHAR**)value, &len);
+    const WCHAR *valueW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%d %p)\n", This, nIndex, value);
+
+    if (!value)
+        return E_POINTER;
+
+    *value = NULL;
+    hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, nIndex, &valueW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(valueW, len, value);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getValueFromName(
@@ -888,10 +1019,23 @@ static HRESULT WINAPI ivbsaxattributes_getValueFromName(
         BSTR localName,
         BSTR *value)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
-            localName, SysStringLen(localName), (const WCHAR**)value, &len);
+    const WCHAR *valueW;
+    HRESULT hr;
+    int len;
+
+    TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(localName), value);
+
+    if (!value)
+        return E_POINTER;
+
+    *value = NULL;
+    hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri),
+            localName, SysStringLen(localName), &valueW, &len);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstrn(valueW, len, value);
 }
 
 static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
@@ -899,10 +1043,23 @@ static HRESULT WINAPI ivbsaxattributes_getValueFromQName(
         BSTR QName,
         BSTR *value)
 {
-    int len;
     saxlocator *This = impl_from_IVBSAXAttributes( iface );
-    return ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, QName,
-            SysStringLen(QName), (const WCHAR**)value, &len);
+    const WCHAR *valueW;
+    HRESULT hr;
+    int 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 ivbsaxattributes_vtbl =
@@ -962,11 +1119,16 @@ static HRESULT WINAPI isaxattributes_getLength(
 {
     saxlocator *This = impl_from_ISAXAttributes( iface );
 
-    *length = This->nb_attributes;
+    *length = This->attr_count;
     TRACE("Length set to %d\n", *length);
     return S_OK;
 }
 
+static inline BOOL is_valid_attr_index(const saxlocator *locator, int index)
+{
+    return index < locator->attr_count && index >= 0;
+}
+
 static HRESULT WINAPI isaxattributes_getURI(
         ISAXAttributes* iface,
         int index,
@@ -976,7 +1138,7 @@ static HRESULT WINAPI isaxattributes_getURI(
     saxlocator *This = impl_from_ISAXAttributes( iface );
     TRACE("(%p)->(%d)\n", This, index);
 
-    if(index >= This->nb_attributes || index < 0) return E_INVALIDARG;
+    if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
     if(!url || !size) return E_POINTER;
 
     *size = SysStringLen(This->attributes[index].szURI);
@@ -989,36 +1151,36 @@ static HRESULT WINAPI isaxattributes_getURI(
 
 static HRESULT WINAPI isaxattributes_getLocalName(
         ISAXAttributes* iface,
-        int nIndex,
+        int index,
         const WCHAR **pLocalName,
         int *pLocalNameLength)
 {
     saxlocator *This = impl_from_ISAXAttributes( iface );
-    TRACE("(%p)->(%d)\n", This, nIndex);
+    TRACE("(%p)->(%d)\n", This, index);
 
-    if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
+    if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
     if(!pLocalName || !pLocalNameLength) return E_POINTER;
 
-    *pLocalNameLength = SysStringLen(This->attributes[nIndex].szLocalname);
-    *pLocalName = This->attributes[nIndex].szLocalname;
+    *pLocalNameLength = SysStringLen(This->attributes[index].szLocalname);
+    *pLocalName = This->attributes[index].szLocalname;
 
     return S_OK;
 }
 
 static HRESULT WINAPI isaxattributes_getQName(
         ISAXAttributes* iface,
-        int nIndex,
+        int index,
         const WCHAR **pQName,
         int *pQNameLength)
 {
     saxlocator *This = impl_from_ISAXAttributes( iface );
-    TRACE("(%p)->(%d)\n", This, nIndex);
+    TRACE("(%p)->(%d)\n", This, index);
 
-    if(nIndex>=This->nb_attributes || nIndex<0) return E_INVALIDARG;
+    if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
     if(!pQName || !pQNameLength) return E_POINTER;
 
-    *pQNameLength = SysStringLen(This->attributes[nIndex].szQName);
-    *pQName = This->attributes[nIndex].szQName;
+    *pQNameLength = SysStringLen(This->attributes[index].szQName);
+    *pQName = This->attributes[index].szQName;
 
     return S_OK;
 }
@@ -1036,7 +1198,7 @@ static HRESULT WINAPI isaxattributes_getName(
     saxlocator *This = impl_from_ISAXAttributes( iface );
     TRACE("(%p)->(%d)\n", This, index);
 
-    if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
+    if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
     if(!uri || !pUriLength || !localName || !pLocalNameSize
             || !QName || !pQNameLength) return E_POINTER;
 
@@ -1067,7 +1229,7 @@ static HRESULT WINAPI isaxattributes_getIndexFromName(
 
     if(!pUri || !pLocalName || !index) return E_POINTER;
 
-    for(i=0; i<This->nb_attributes; i++)
+    for(i=0; i<This->attr_count; i++)
     {
         if(cUriLength!=SysStringLen(This->attributes[i].szURI)
                 || cocalNameLength!=SysStringLen(This->attributes[i].szLocalname))
@@ -1099,7 +1261,7 @@ static HRESULT WINAPI isaxattributes_getIndexFromQName(
     if(!pQName || !index) return E_POINTER;
     if(!nQNameLength) return E_INVALIDARG;
 
-    for(i=0; i<This->nb_attributes; i++)
+    for(i=0; i<This->attr_count; i++)
     {
         if(nQNameLength!=SysStringLen(This->attributes[i].szQName)) continue;
         if(memcmp(pQName, This->attributes[i].szQName, sizeof(WCHAR)*nQNameLength)) continue;
@@ -1161,7 +1323,7 @@ static HRESULT WINAPI isaxattributes_getValue(
     saxlocator *This = impl_from_ISAXAttributes( iface );
     TRACE("(%p)->(%d)\n", This, index);
 
-    if(index>=This->nb_attributes || index<0) return E_INVALIDARG;
+    if(!is_valid_attr_index(This, index)) return E_INVALIDARG;
     if(!value || !nValue) return E_POINTER;
 
     *nValue = SysStringLen(This->attributes[index].szValue);
@@ -1232,6 +1394,66 @@ static const struct ISAXAttributesVtbl isaxattributes_vtbl =
     isaxattributes_getValueFromQName
 };
 
+/* Libxml2 escapes '&' back to char reference '&#38;' in attribute value,
+   so when document has escaped value with '&amp;' it's parsed to '&' and then
+   escaped to '&#38;'. This function takes care of ampersands only. */
+static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
+{
+    static const WCHAR ampescW[] = {'&','#','3','8',';',0};
+    WCHAR *dest, *ptrW, *str;
+    DWORD str_len;
+    BSTR bstr;
+
+    if (!buf)
+        return NULL;
+
+    str_len = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, NULL, 0);
+    if (len != -1) str_len++;
+
+    str = heap_alloc(str_len*sizeof(WCHAR));
+    if (!str) return NULL;
+
+    MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)buf, len, str, str_len);
+    if (len != -1) str[str_len-1] = 0;
+
+    ptrW = str;
+    while ((dest = strstrW(ptrW, ampescW)))
+    {
+        WCHAR *src;
+
+        /* leave first '&' from a reference as a value */
+        src = dest + ARRAY_SIZE(ampescW) - 1;
+        dest++;
+
+        /* move together with null terminator */
+        memmove(dest, src, (strlenW(src) + 1)*sizeof(WCHAR));
+
+        ptrW++;
+    }
+
+    bstr = SysAllocString(str);
+    heap_free(str);
+
+    return bstr;
+}
+
+static void free_attribute_values(saxlocator *locator)
+{
+    int i;
+
+    for (i = 0; i < locator->attr_count; i++)
+    {
+        SysFreeString(locator->attributes[i].szLocalname);
+        locator->attributes[i].szLocalname = NULL;
+
+        SysFreeString(locator->attributes[i].szValue);
+        locator->attributes[i].szValue = NULL;
+
+        SysFreeString(locator->attributes[i].szQName);
+        locator->attributes[i].szQName = NULL;
+    }
+}
+
 static HRESULT SAXAttributes_populate(saxlocator *locator,
         int nb_namespaces, const xmlChar **xmlNamespaces,
         int nb_attributes, const xmlChar **xmlAttributes)
@@ -1246,16 +1468,19 @@ static HRESULT SAXAttributes_populate(saxlocator *locator,
     if ((locator->saxreader->features & NamespacePrefixes) == 0)
         nb_namespaces = 0;
 
-    locator->nb_attributes = nb_namespaces + nb_attributes;
-    if(locator->nb_attributes > locator->attributesSize)
+    locator->attr_count = nb_namespaces + nb_attributes;
+    if(locator->attr_count > locator->attr_alloc_count)
     {
-        attrs = heap_realloc(locator->attributes, sizeof(struct _attributes)*locator->nb_attributes*2);
+        int new_size = locator->attr_count * 2;
+        attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
         if(!attrs)
         {
-            locator->nb_attributes = 0;
+            free_attribute_values(locator);
+            locator->attr_count = 0;
             return E_OUTOFMEMORY;
         }
         locator->attributes = attrs;
+        locator->attr_alloc_count = new_size;
     }
     else
     {
@@ -1264,9 +1489,15 @@ static HRESULT SAXAttributes_populate(saxlocator *locator,
 
     for (i = 0; i < nb_namespaces; i++)
     {
+        SysFreeString(attrs[nb_attributes+i].szLocalname);
         attrs[nb_attributes+i].szLocalname = SysAllocStringLen(NULL, 0);
+
         attrs[nb_attributes+i].szURI = locator->namespaceUri;
+
+        SysFreeString(attrs[nb_attributes+i].szValue);
         attrs[nb_attributes+i].szValue = bstr_from_xmlChar(xmlNamespaces[2*i+1]);
+
+        SysFreeString(attrs[nb_attributes+i].szQName);
         if(!xmlNamespaces[2*i])
             attrs[nb_attributes+i].szQName = SysAllocString(xmlnsW);
         else
@@ -1283,11 +1514,14 @@ static HRESULT SAXAttributes_populate(saxlocator *locator,
             /* that's an important feature to keep same uri pointer for every reported attribute */
             attrs[i].szURI = find_element_uri(locator, xmlAttributes[i*5+2]);
 
+        SysFreeString(attrs[i].szLocalname);
         attrs[i].szLocalname = bstr_from_xmlChar(xmlAttributes[i*5]);
-        attrs[i].szValue = bstr_from_xmlCharN(xmlAttributes[i*5+3],
-                xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
-        attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1],
-                xmlAttributes[i*5]);
+
+        SysFreeString(attrs[i].szValue);
+        attrs[i].szValue = saxreader_get_unescaped_value(xmlAttributes[i*5+3], xmlAttributes[i*5+4]-xmlAttributes[i*5+3]);
+
+        SysFreeString(attrs[i].szQName);
+        attrs[i].szQName = QName_from_xmlChar(xmlAttributes[i*5+1], xmlAttributes[i*5]);
     }
 
     return S_OK;
@@ -1433,8 +1667,8 @@ static void libxmlStartElementNS(
                     &uri, &local, &element->qname, &This->IVBSAXAttributes_iface);
         else
             hr = ISAXContentHandler_startElement(handler->handler,
-                    uri, SysStringLen(uri),
-                    local, SysStringLen(local),
+                    uri ? uri : &empty_str, SysStringLen(uri),
+                    local ? local : &empty_str, SysStringLen(local),
                     element->qname, SysStringLen(element->qname),
                     &This->ISAXAttributes_iface);
 
@@ -1489,7 +1723,8 @@ static void libxmlEndElementNS(
 
     if (!saxreader_has_handler(This, SAXContentHandler))
     {
-        This->nb_attributes = 0;
+        free_attribute_values(This);
+        This->attr_count = 0;
         free_element_entry(element);
         return;
     }
@@ -1506,11 +1741,12 @@ static void libxmlEndElementNS(
     else
         hr = ISAXContentHandler_endElement(
                 handler->handler,
-                uri, SysStringLen(uri),
-                local, SysStringLen(local),
+                uri ? uri : &empty_str, SysStringLen(uri),
+                local ? local : &empty_str, SysStringLen(local),
                 element->qname, SysStringLen(element->qname));
 
-    This->nb_attributes = 0;
+    free_attribute_values(This);
+    This->attr_count = 0;
 
     if (sax_callback_failed(This, hr))
     {
@@ -1547,7 +1783,6 @@ static void libxmlCharacters(
         int len)
 {
     saxlocator *This = ctx;
-    struct saxcontenthandler_iface *handler = saxreader_get_contenthandler(This->saxreader);
     BSTR Chars;
     HRESULT hr;
     xmlChar *cur, *end;
@@ -1606,10 +1841,7 @@ static void libxmlCharacters(
         }
 
         Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur);
-        if(This->vbInterface)
-            hr = IVBSAXContentHandler_characters(handler->vbhandler, &Chars);
-        else
-            hr = ISAXContentHandler_characters(handler->handler, Chars, SysStringLen(Chars));
+        hr = saxreader_saxcharacters(This, Chars);
 
         if (sax_callback_failed(This, hr))
         {
@@ -1742,33 +1974,59 @@ static void libxmlFatalError(void *ctx, const char *msg, ...)
     This->ret = E_FAIL;
 }
 
-static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
+/* The only reason this helper exists is that CDATA section are reported by chunks,
+   newlines are used as delimiter. More than that, reader even alters input data before reporting.
+
+   This helper should be called for substring with trailing newlines.
+*/
+static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
 {
-    saxlocator *This = ctx;
-    struct saxcontenthandler_iface *content = saxreader_get_contenthandler(This->saxreader);
-    struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(This->saxreader);
-    HRESULT hr = S_OK;
-    xmlChar *beg = (xmlChar*)This->pParserCtxt->input->cur-len;
-    xmlChar *cur, *end;
-    int realLen;
-    BSTR Chars;
-    BOOL lastEvent = FALSE, change;
+    BSTR bstr = bstr_from_xmlCharN(str, len), ret;
+    WCHAR *ptr;
 
-    update_position(This, FALSE);
-    while(beg-9>=This->pParserCtxt->input->base
-            && memcmp(beg-9, "<![CDATA[", sizeof(char[9])))
+    len = SysStringLen(bstr);
+    ptr = bstr + len - 1;
+    while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
+        ptr--;
+
+    while (*++ptr)
     {
-        if(*beg=='\n' || (*beg=='\r' && *(beg+1)!='\n'))
-            This->line--;
-        beg--;
+        /* replace returns as:
+
+           - "\r<char>" -> "\n<char>"
+           - "\r\r" -> "\r"
+           - "\r\n" -> "\n"
+        */
+        if (*ptr == '\r')
+        {
+            if (*(ptr+1) == '\r' || *(ptr+1) == '\n')
+            {
+                /* shift tail */
+                memmove(ptr, ptr+1, len-- - (ptr-bstr));
+            }
+            else
+                *ptr = '\n';
+        }
     }
-    This->column = 0;
-    for(; beg>=This->pParserCtxt->input->base && *beg!='\n' && *beg!='\r'; beg--)
-        This->column++;
 
-    if (saxreader_has_handler(This, SAXLexicalHandler))
+    ret = SysAllocStringLen(bstr, len);
+    SysFreeString(bstr);
+    return ret;
+}
+
+static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
+{
+    const xmlChar *start, *end;
+    saxlocator *locator = ctx;
+    struct saxlexicalhandler_iface *lexical = saxreader_get_lexicalhandler(locator->saxreader);
+    HRESULT hr = S_OK;
+    BSTR chars;
+    int i;
+
+    update_position(locator, FALSE);
+    if (saxreader_has_handler(locator, SAXLexicalHandler))
     {
-       if (This->vbInterface)
+       if (locator->vbInterface)
            hr = IVBSAXLexicalHandler_startCDATA(lexical->vbhandler);
        else
            hr = ISAXLexicalHandler_startCDATA(lexical->handler);
@@ -1776,61 +2034,66 @@ static void libxmlCDataBlock(void *ctx, const xmlChar *value, int len)
 
     if(FAILED(hr))
     {
-        format_error_message_from_id(This, hr);
+        format_error_message_from_id(locator, hr);
         return;
     }
 
-    realLen = This->pParserCtxt->input->cur-beg-3;
-    cur = beg;
-    end = beg;
+    start = value;
+    end = NULL;
+    i = 0;
 
-    while(1)
+    while (i < len)
     {
-        while(end-beg<realLen && *end!='\r') end++;
-        if(end-beg==realLen)
+        /* scan for newlines */
+        if (value[i] == '\r' || value[i] == '\n')
         {
-            end--;
-            lastEvent = TRUE;
-        }
-        else if(end-beg==realLen-1 && *end=='\r' && *(end+1)=='\n')
-            lastEvent = TRUE;
-
-        if(*end == '\r') change = TRUE;
-        else change = FALSE;
+            /* skip newlines/linefeeds */
+            while (i < len)
+            {
+                if (value[i] != '\r' && value[i] != '\n') break;
+                i++;
+            }
+            end = &value[i];
 
-        if(change) *end = '\n';
+            /* report */
+            chars = saxreader_get_cdata_chunk(start, end-start);
+            TRACE("(chunk %s)\n", debugstr_w(chars));
+            hr = saxreader_saxcharacters(locator, chars);
+            SysFreeString(chars);
 
-        if (saxreader_has_handler(This, SAXContentHandler))
-        {
-            Chars = pooled_bstr_from_xmlCharN(&This->saxreader->pool, cur, end-cur+1);
-            if (This->vbInterface)
-                hr = IVBSAXContentHandler_characters(content->vbhandler, &Chars);
-            else
-                hr = ISAXContentHandler_characters(content->handler, Chars, SysStringLen(Chars));
+            start = &value[i];
+            end = NULL;
         }
+        i++;
+        locator->column++;
+    }
 
-        if(change) *end = '\r';
-
-        if(lastEvent)
-            break;
-
-        This->column += end-cur+2;
-        end += 2;
-        cur = end;
+    /* no newline chars (or last chunk) report as a whole */
+    if (!end && start == value)
+    {
+        /* report */
+        chars = bstr_from_xmlCharN(start, len-(start-value));
+        TRACE("(%s)\n", debugstr_w(chars));
+        hr = saxreader_saxcharacters(locator, chars);
+        SysFreeString(chars);
     }
 
-    if (saxreader_has_handler(This, SAXLexicalHandler))
+    if (saxreader_has_handler(locator, SAXLexicalHandler))
     {
-        if (This->vbInterface)
+        if (locator->vbInterface)
             hr = IVBSAXLexicalHandler_endCDATA(lexical->vbhandler);
         else
             hr = ISAXLexicalHandler_endCDATA(lexical->handler);
     }
 
     if(FAILED(hr))
-        format_error_message_from_id(This, hr);
+        format_error_message_from_id(locator, hr);
+}
 
-    This->column += 4+end-cur;
+static xmlParserInputPtr libxmlresolveentity(void *ctx, const xmlChar *publicid, const xmlChar *systemid)
+{
+    FIXME("entity resolving not implemented, %s, %s\n", publicid, systemid);
+    return xmlSAX2ResolveEntity(ctx, publicid, systemid);
 }
 
 /*** IVBSAXLocator interface ***/
@@ -1868,14 +2131,13 @@ static ULONG WINAPI ivbsaxlocator_AddRef(IVBSAXLocator* iface)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
     TRACE("%p\n", This );
-    return InterlockedIncrement( &This->ref );
+    return ISAXLocator_AddRef(&This->ISAXLocator_iface);
 }
 
-static ULONG WINAPI ivbsaxlocator_Release(
-        IVBSAXLocator* iface)
+static ULONG WINAPI ivbsaxlocator_Release(IVBSAXLocator* iface)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    return ISAXLocator_Release((ISAXLocator*)&This->IVBSAXLocator_iface);
+    return ISAXLocator_Release(&This->ISAXLocator_iface);
 }
 
 /*** IDispatch methods ***/
@@ -1895,13 +2157,10 @@ static HRESULT WINAPI ivbsaxlocator_GetTypeInfo(
     UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo )
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    HRESULT hr;
 
     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
 
-    hr = get_typeinfo(IVBSAXLocator_tid, ppTInfo);
-
-    return hr;
+    return get_typeinfo(IVBSAXLocator_tid, ppTInfo);
 }
 
 static HRESULT WINAPI ivbsaxlocator_GetIDsOfNames(
@@ -1967,7 +2226,7 @@ static HRESULT WINAPI ivbsaxlocator_get_columnNumber(
         int *pnColumn)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    return ISAXLocator_getColumnNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnColumn);
+    return ISAXLocator_getColumnNumber(&This->ISAXLocator_iface, pnColumn);
 }
 
 static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
@@ -1975,25 +2234,45 @@ static HRESULT WINAPI ivbsaxlocator_get_lineNumber(
         int *pnLine)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    return ISAXLocator_getLineNumber((ISAXLocator*)&This->IVBSAXLocator_iface, pnLine);
+    return ISAXLocator_getLineNumber(&This->ISAXLocator_iface, pnLine);
 }
 
-static HRESULT WINAPI ivbsaxlocator_get_publicId(
-        IVBSAXLocator* iface,
-        BSTR* publicId)
+static HRESULT WINAPI ivbsaxlocator_get_publicId(IVBSAXLocator* iface, BSTR *ret)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    return ISAXLocator_getPublicId((ISAXLocator*)&This->IVBSAXLocator_iface,
-            (const WCHAR**)publicId);
+    const WCHAR *publicidW;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", This, ret);
+
+    if (!ret)
+        return E_POINTER;
+
+    *ret = NULL;
+    hr = ISAXLocator_getPublicId(&This->ISAXLocator_iface, &publicidW);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstr(publicidW, ret);
 }
 
-static HRESULT WINAPI ivbsaxlocator_get_systemId(
-        IVBSAXLocator* iface,
-        BSTR* systemId)
+static HRESULT WINAPI ivbsaxlocator_get_systemId(IVBSAXLocator* iface, BSTR *ret)
 {
     saxlocator *This = impl_from_IVBSAXLocator( iface );
-    return ISAXLocator_getSystemId((ISAXLocator*)&This->IVBSAXLocator_iface,
-            (const WCHAR**)systemId);
+    const WCHAR *systemidW;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n", This, ret);
+
+    if (!ret)
+        return E_POINTER;
+
+    *ret = NULL;
+    hr = ISAXLocator_getSystemId(&This->ISAXLocator_iface, &systemidW);
+    if (FAILED(hr))
+        return hr;
+
+    return return_bstr(systemidW, ret);
 }
 
 static const struct IVBSAXLocatorVtbl VBSAXLocatorVtbl =
@@ -2066,7 +2345,7 @@ static ULONG WINAPI isaxlocator_Release(
         SysFreeString(This->systemId);
         SysFreeString(This->namespaceUri);
 
-        for(index=0; index<This->nb_attributes; index++)
+        for(index = 0; index < This->attr_alloc_count; index++)
         {
             SysFreeString(This->attributes[index].szLocalname);
             SysFreeString(This->attributes[index].szValue);
@@ -2120,7 +2399,7 @@ static HRESULT WINAPI isaxlocator_getPublicId(
 
     publicId = bstr_from_xmlChar(xmlSAX2GetPublicId(This->pParserCtxt));
     if(SysStringLen(publicId))
-        This->publicId = (WCHAR*)&publicId;
+        This->publicId = publicId;
     else
     {
         SysFreeString(publicId);
@@ -2142,7 +2421,7 @@ static HRESULT WINAPI isaxlocator_getSystemId(
 
     systemId = bstr_from_xmlChar(xmlSAX2GetSystemId(This->pParserCtxt));
     if(SysStringLen(systemId))
-        This->systemId = (WCHAR*)&systemId;
+        This->systemId = systemId;
     else
     {
         SysFreeString(systemId);
@@ -2202,9 +2481,9 @@ static HRESULT SAXLocator_create(saxreader *reader, saxlocator **ppsaxlocator, B
         return E_OUTOFMEMORY;
     }
 
-    locator->attributesSize = 8;
-    locator->nb_attributes = 0;
-    locator->attributes = heap_alloc(sizeof(struct _attributes)*locator->attributesSize);
+    locator->attr_alloc_count = 8;
+    locator->attr_count = 0;
+    locator->attributes = heap_alloc_zero(sizeof(struct _attributes)*locator->attr_alloc_count);
     if(!locator->attributes)
     {
         ISAXXMLReader_Release(&reader->ISAXXMLReader_iface);
@@ -2256,7 +2535,7 @@ static HRESULT internal_parseBuffer(saxreader *This, const char *buffer, int siz
     if (encoding == XML_CHAR_ENCODING_NONE)
     {
         const WCHAR *ptr = (WCHAR*)buffer;
-        /* xml declaration with possibly specfied encoding will be still handled by parser */
+        /* an xml declaration with optional encoding will still be handled by the parser */
         if ((size >= 2) && *ptr == '<' && ptr[1] != '?')
         {
             enc_name = (xmlChar*)xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF16LE);
@@ -2311,7 +2590,7 @@ static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream,
     saxlocator *locator;
     HRESULT hr;
     ULONG dataRead;
-    char data[1024];
+    char data[2048];
     int ret;
 
     dataRead = 0;
@@ -2332,32 +2611,21 @@ static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream,
 
     This->isParsing = TRUE;
 
-    if(dataRead != sizeof(data))
+    do {
+        dataRead = 0;
+        hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
+        if (FAILED(hr) || !dataRead) break;
+
+        ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
+        hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
+    }while(hr == S_OK);
+
+    if(SUCCEEDED(hr))
     {
         ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
         hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
     }
-    else
-    {
-        while(1)
-        {
-            dataRead = 0;
-            hr = ISequentialStream_Read(stream, data, sizeof(data), &dataRead);
-            if (FAILED(hr)) break;
-
-            ret = xmlParseChunk(locator->pParserCtxt, data, dataRead, 0);
-            hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
 
-            if (hr != S_OK) break;
-
-            if (dataRead != sizeof(data))
-            {
-                ret = xmlParseChunk(locator->pParserCtxt, data, 0, 1);
-                hr = ret!=XML_ERR_OK && locator->ret==S_OK ? E_FAIL : locator->ret;
-                break;
-            }
-        }
-    }
 
     This->isParsing = FALSE;
 
@@ -2367,24 +2635,6 @@ static HRESULT internal_parseStream(saxreader *This, ISequentialStream *stream,
     return hr;
 }
 
-static HRESULT internal_getEntityResolver(
-        saxreader *This,
-        void *pEntityResolver,
-        BOOL vbInterface)
-{
-    FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
-    return E_NOTIMPL;
-}
-
-static HRESULT internal_putEntityResolver(
-        saxreader *This,
-        void *pEntityResolver,
-        BOOL vbInterface)
-{
-    FIXME("(%p)->(%p) stub\n", This, pEntityResolver);
-    return E_NOTIMPL;
-}
-
 static HRESULT internal_parse(
         saxreader* This,
         VARIANT varInput,
@@ -2400,9 +2650,12 @@ static HRESULT internal_parse(
     switch(V_VT(&varInput))
     {
         case VT_BSTR:
-            hr = internal_parseBuffer(This, (const char*)V_BSTR(&varInput),
-                    strlenW(V_BSTR(&varInput))*sizeof(WCHAR), vbInterface);
+        case VT_BSTR|VT_BYREF:
+        {
+            BSTR str = V_ISBYREF(&varInput) ? *V_BSTRREF(&varInput) : V_BSTR(&varInput);
+            hr = internal_parseBuffer(This, (const char*)str, strlenW(str)*sizeof(WCHAR), vbInterface);
             break;
+        }
         case VT_ARRAY|VT_UI1: {
             void *pSAData;
             LONG lBound, uBound;
@@ -2421,10 +2674,12 @@ static HRESULT internal_parse(
         }
         case VT_UNKNOWN:
         case VT_DISPATCH: {
-            IPersistStream *persistStream;
             ISequentialStream *stream = NULL;
             IXMLDOMDocument *xmlDoc;
 
+            if (!V_UNKNOWN(&varInput))
+                return E_INVALIDARG;
+
             if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
                         &IID_IXMLDOMDocument, (void**)&xmlDoc) == S_OK)
             {
@@ -2438,34 +2693,11 @@ static HRESULT internal_parse(
                 break;
             }
 
-            if(IUnknown_QueryInterface(V_UNKNOWN(&varInput),
-                        &IID_IPersistStream, (void**)&persistStream) == S_OK)
-            {
-                IStream *stream_copy;
-
-                hr = CreateStreamOnHGlobal(NULL, TRUE, &stream_copy);
-                if(hr != S_OK)
-                {
-                    IPersistStream_Release(persistStream);
-                    return hr;
-                }
-
-                hr = IPersistStream_Save(persistStream, stream_copy, TRUE);
-                IPersistStream_Release(persistStream);
-                if(hr == S_OK)
-                    IStream_QueryInterface(stream_copy, &IID_ISequentialStream, (void**)&stream);
-
-                IStream_Release(stream_copy);
-            }
-
             /* try base interface first */
-            if(!stream)
-            {
-                IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
-                if (!stream)
-                    /* this should never happen if IStream is implemented properly, but just in case */
-                    IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
-            }
+            IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_ISequentialStream, (void**)&stream);
+            if (!stream)
+                /* this should never happen if IStream is implemented properly, but just in case */
+                IUnknown_QueryInterface(V_UNKNOWN(&varInput), &IID_IStream, (void**)&stream);
 
             if(stream)
             {
@@ -2527,99 +2759,85 @@ static HRESULT internal_parseURL(
     return detach_bsc(bsc);
 }
 
-static HRESULT internal_putProperty(
-    saxreader* This,
-    const WCHAR *prop,
-    VARIANT value,
-    BOOL vbInterface)
+static HRESULT saxreader_put_handler_from_variant(saxreader *This, enum saxhandler_type type, const VARIANT *v, BOOL vb)
 {
-    TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
-
-    if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
-    {
-        if(This->isParsing) return E_FAIL;
+    const IID *riid;
 
-        switch (V_VT(&value))
-        {
-        case VT_EMPTY:
-            saxreader_put_handler(This, SAXDeclHandler, NULL, vbInterface);
-            break;
-        case VT_UNKNOWN:
-        {
-            IUnknown *handler = NULL;
+    if (V_VT(v) == VT_EMPTY)
+        return saxreader_put_handler(This, type, NULL, vb);
 
-            if (V_UNKNOWN(&value))
-            {
-                HRESULT hr;
+    switch (type)
+    {
+    case SAXDeclHandler:
+        riid = vb ? &IID_IVBSAXDeclHandler : &IID_ISAXDeclHandler;
+        break;
+    case SAXLexicalHandler:
+        riid = vb ? &IID_IVBSAXLexicalHandler : &IID_ISAXLexicalHandler;
+        break;
+    default:
+        ERR("wrong handler type %d\n", type);
+        return E_FAIL;
+    }
 
-                if (vbInterface)
-                    hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXDeclHandler, (void**)&handler);
-                else
-                    hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_ISAXDeclHandler, (void**)&handler);
-                if (FAILED(hr)) return hr;
-            }
+    switch (V_VT(v))
+    {
+    case VT_DISPATCH:
+    case VT_UNKNOWN:
+    {
+        IUnknown *handler = NULL;
 
-            saxreader_put_handler(This, SAXDeclHandler, handler, vbInterface);
-            if (handler) IUnknown_Release(handler);
-            break;
-        }
-        default:
-            return E_INVALIDARG;
+        if (V_UNKNOWN(v))
+        {
+            HRESULT hr = IUnknown_QueryInterface(V_UNKNOWN(v), riid, (void**)&handler);
+            if (FAILED(hr)) return hr;
         }
 
-        return S_OK;
+        saxreader_put_handler(This, type, handler, vb);
+        if (handler) IUnknown_Release(handler);
+        break;
+    }
+    default:
+        ERR("value type %d not supported\n", V_VT(v));
+        return E_INVALIDARG;
     }
 
-    if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
-    {
-        if(This->isParsing) return E_FAIL;
+    return S_OK;
+}
 
-        switch (V_VT(&value))
-        {
-        case VT_EMPTY:
-            saxreader_put_handler(This, SAXLexicalHandler, NULL, vbInterface);
-            break;
-        case VT_UNKNOWN:
-        {
-            IUnknown *handler = NULL;
+static HRESULT internal_putProperty(
+    saxreader* This,
+    const WCHAR *prop,
+    VARIANT value,
+    BOOL vbInterface)
+{
+    VARIANT *v;
 
-            if (V_UNKNOWN(&value))
-            {
-                HRESULT hr;
+    TRACE("(%p)->(%s %s)\n", This, debugstr_w(prop), debugstr_variant(&value));
 
-                if (vbInterface)
-                    hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_IVBSAXLexicalHandler, (void**)&handler);
-                else
-                    hr = IUnknown_QueryInterface(V_UNKNOWN(&value), &IID_ISAXLexicalHandler, (void**)&handler);
-                if (FAILED(hr)) return hr;
-            }
+    if (This->isParsing) return E_FAIL;
 
-            saxreader_put_handler(This, SAXLexicalHandler, handler, vbInterface);
-            if (handler) IUnknown_Release(handler);
-            break;
-        }
-        default:
-            return E_INVALIDARG;
-        }
+    v = V_VT(&value) == (VT_VARIANT|VT_BYREF) ? V_VARIANTREF(&value) : &value;
+    if(!memcmp(prop, PropertyDeclHandlerW, sizeof(PropertyDeclHandlerW)))
+        return saxreader_put_handler_from_variant(This, SAXDeclHandler, v, vbInterface);
 
-        return S_OK;
-    }
+    if(!memcmp(prop, PropertyLexicalHandlerW, sizeof(PropertyLexicalHandlerW)))
+        return saxreader_put_handler_from_variant(This, SAXLexicalHandler, v, vbInterface);
 
     if(!memcmp(prop, PropertyMaxXMLSizeW, sizeof(PropertyMaxXMLSizeW)))
     {
-        if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
-        FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(&value));
+        if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
+        FIXME("(%p)->(%s): max-xml-size unsupported\n", This, debugstr_variant(v));
         return E_NOTIMPL;
     }
 
     if(!memcmp(prop, PropertyMaxElementDepthW, sizeof(PropertyMaxElementDepthW)))
     {
-        if (V_VT(&value) == VT_I4 && V_I4(&value) == 0) return S_OK;
-        FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(&value));
+        if (V_VT(v) == VT_I4 && V_I4(v) == 0) return S_OK;
+        FIXME("(%p)->(%s): max-element-depth unsupported\n", This, debugstr_variant(v));
         return E_NOTIMPL;
     }
 
-    FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(&value));
+    FIXME("(%p)->(%s:%s): unsupported property\n", This, debugstr_w(prop), debugstr_variant(v));
 
     if(!memcmp(prop, PropertyCharsetW, sizeof(PropertyCharsetW)))
         return E_NOTIMPL;
@@ -2734,19 +2952,18 @@ static ULONG WINAPI saxxmlreader_Release(
 
         for (i = 0; i < SAXHandler_Last; i++)
         {
-            struct saxhandler_iface *iface = &This->saxhandlers[i];
+            struct saxanyhandler_iface *saxiface = &This->saxhandlers[i].u.anyhandler;
 
-            if (iface->handler)
-                IUnknown_Release(iface->handler);
+            if (saxiface->handler)
+                IUnknown_Release(saxiface->handler);
 
-            if (iface->vbhandler)
-                IUnknown_Release(iface->vbhandler);
+            if (saxiface->vbhandler)
+                IUnknown_Release(saxiface->vbhandler);
         }
 
         SysFreeString(This->xmldecl_version);
         free_bstr_pool(&This->pool);
 
-        release_dispex(&This->dispex);
         heap_free( This );
     }
 
@@ -2800,56 +3017,25 @@ static HRESULT WINAPI saxxmlreader_Invoke(
 /*** IVBSAXXMLReader methods ***/
 static HRESULT WINAPI saxxmlreader_getFeature(
     IVBSAXXMLReader* iface,
-    const WCHAR *feature_name,
+    BSTR feature_name,
     VARIANT_BOOL *value)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-    saxreader_feature feature;
-
-    TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
-
-    feature = get_saxreader_feature(feature_name);
-    if (feature == Namespaces || feature == NamespacePrefixes)
-        return get_feature_value(This, feature, value);
-
-    FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
-    return E_NOTIMPL;
+    return ISAXXMLReader_getFeature(&This->ISAXXMLReader_iface, feature_name, value);
 }
 
 static HRESULT WINAPI saxxmlreader_putFeature(
     IVBSAXXMLReader* iface,
-    const WCHAR *feature_name,
+    BSTR feature_name,
     VARIANT_BOOL value)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-    saxreader_feature feature;
-
-    TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
-
-    feature = get_saxreader_feature(feature_name);
-
-    /* accepted cases */
-    if ((feature == ExternalGeneralEntities   && value == VARIANT_FALSE) ||
-        (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
-         feature == Namespaces ||
-         feature == NamespacePrefixes)
-    {
-        return set_feature_value(This, feature, value);
-    }
-
-    if (feature == LexicalHandlerParEntities || feature == ProhibitDTD)
-    {
-        FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
-        return set_feature_value(This, feature, value);
-    }
-
-    FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
-    return E_NOTIMPL;
+    return ISAXXMLReader_putFeature(&This->ISAXXMLReader_iface, feature_name, value);
 }
 
 static HRESULT WINAPI saxxmlreader_getProperty(
     IVBSAXXMLReader* iface,
-    const WCHAR *prop,
+    BSTR prop,
     VARIANT *value)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
@@ -2858,7 +3044,7 @@ static HRESULT WINAPI saxxmlreader_getProperty(
 
 static HRESULT WINAPI saxxmlreader_putProperty(
     IVBSAXXMLReader* iface,
-    const WCHAR *pProp,
+    BSTR pProp,
     VARIANT value)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
@@ -2867,18 +3053,18 @@ static HRESULT WINAPI saxxmlreader_putProperty(
 
 static HRESULT WINAPI saxxmlreader_get_entityResolver(
     IVBSAXXMLReader* iface,
-    IVBSAXEntityResolver **pEntityResolver)
+    IVBSAXEntityResolver **resolver)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-    return internal_getEntityResolver(This, pEntityResolver, TRUE);
+    return saxreader_get_handler(This, SAXEntityResolver, TRUE, (void**)resolver);
 }
 
 static HRESULT WINAPI saxxmlreader_put_entityResolver(
     IVBSAXXMLReader* iface,
-    IVBSAXEntityResolver *pEntityResolver)
+    IVBSAXEntityResolver *resolver)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-    return internal_putEntityResolver(This, pEntityResolver, TRUE);
+    return saxreader_put_handler(This, SAXEntityResolver, resolver, TRUE);
 }
 
 static HRESULT WINAPI saxxmlreader_get_contentHandler(
@@ -2931,7 +3117,7 @@ static HRESULT WINAPI saxxmlreader_put_errorHandler(
 
 static HRESULT WINAPI saxxmlreader_get_baseURL(
     IVBSAXXMLReader* iface,
-    const WCHAR **pBaseUrl)
+    BSTR *pBaseUrl)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
 
@@ -2941,17 +3127,15 @@ static HRESULT WINAPI saxxmlreader_get_baseURL(
 
 static HRESULT WINAPI saxxmlreader_put_baseURL(
     IVBSAXXMLReader* iface,
-    const WCHAR *pBaseUrl)
+    BSTR pBaseUrl)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-
-    FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
-    return E_NOTIMPL;
+    return ISAXXMLReader_putBaseURL(&This->ISAXXMLReader_iface, pBaseUrl);
 }
 
 static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
     IVBSAXXMLReader* iface,
-    const WCHAR **pSecureBaseUrl)
+    BSTR *pSecureBaseUrl)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
 
@@ -2959,15 +3143,12 @@ static HRESULT WINAPI saxxmlreader_get_secureBaseURL(
     return E_NOTIMPL;
 }
 
-
 static HRESULT WINAPI saxxmlreader_put_secureBaseURL(
     IVBSAXXMLReader* iface,
-    const WCHAR *secureBaseUrl)
+    BSTR secureBaseUrl)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
-
-    FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
-    return E_NOTIMPL;
+    return ISAXXMLReader_putSecureBaseURL(&This->ISAXXMLReader_iface, secureBaseUrl);
 }
 
 static HRESULT WINAPI saxxmlreader_parse(
@@ -2980,7 +3161,7 @@ static HRESULT WINAPI saxxmlreader_parse(
 
 static HRESULT WINAPI saxxmlreader_parseURL(
     IVBSAXXMLReader* iface,
-    const WCHAR *url)
+    BSTR url)
 {
     saxreader *This = impl_from_IVBSAXXMLReader( iface );
     return internal_parseURL(This, url, TRUE);
@@ -3020,38 +3201,79 @@ static const struct IVBSAXXMLReaderVtbl VBSAXXMLReaderVtbl =
 static HRESULT WINAPI isaxxmlreader_QueryInterface(ISAXXMLReader* iface, REFIID riid, void **ppvObject)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return saxxmlreader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
+    return IVBSAXXMLReader_QueryInterface(&This->IVBSAXXMLReader_iface, riid, ppvObject);
 }
 
 static ULONG WINAPI isaxxmlreader_AddRef(ISAXXMLReader* iface)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return saxxmlreader_AddRef(&This->IVBSAXXMLReader_iface);
+    return IVBSAXXMLReader_AddRef(&This->IVBSAXXMLReader_iface);
 }
 
 static ULONG WINAPI isaxxmlreader_Release(ISAXXMLReader* iface)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return saxxmlreader_Release(&This->IVBSAXXMLReader_iface);
+    return IVBSAXXMLReader_Release(&This->IVBSAXXMLReader_iface);
 }
 
 /*** ISAXXMLReader methods ***/
 static HRESULT WINAPI isaxxmlreader_getFeature(
         ISAXXMLReader* iface,
-        const WCHAR *pFeature,
-        VARIANT_BOOL *pValue)
+        const WCHAR *feature_name,
+        VARIANT_BOOL *value)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_getFeature(&This->IVBSAXXMLReader_iface, pFeature, pValue);
+    saxreader_feature feature;
+
+    TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
+
+    feature = get_saxreader_feature(feature_name);
+
+    if (This->version < MSXML4 && (feature == ExhaustiveErrors || feature == SchemaValidation))
+        return E_INVALIDARG;
+
+    if (feature == Namespaces ||
+            feature == NamespacePrefixes ||
+            feature == ExhaustiveErrors ||
+            feature == SchemaValidation)
+        return get_feature_value(This, feature, value);
+
+    FIXME("(%p)->(%s %p) stub\n", This, debugstr_w(feature_name), value);
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_putFeature(
         ISAXXMLReader* iface,
-        const WCHAR *pFeature,
-        VARIANT_BOOL vfValue)
+        const WCHAR *feature_name,
+        VARIANT_BOOL value)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_putFeature(&This->IVBSAXXMLReader_iface, pFeature, vfValue);
+    saxreader_feature feature;
+
+    TRACE("(%p)->(%s %x)\n", This, debugstr_w(feature_name), value);
+
+    feature = get_saxreader_feature(feature_name);
+
+    /* accepted cases */
+    if ((feature == ExhaustiveErrors && value == VARIANT_FALSE) ||
+        (feature == SchemaValidation && value == VARIANT_FALSE) ||
+         feature == Namespaces ||
+         feature == NamespacePrefixes)
+    {
+        return set_feature_value(This, feature, value);
+    }
+
+    if (feature == LexicalHandlerParEntities ||
+            feature == ProhibitDTD ||
+            feature == ExternalGeneralEntities ||
+            feature == ExternalParameterEntities)
+    {
+        FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
+        return set_feature_value(This, feature, value);
+    }
+
+    FIXME("(%p)->(%s %x) stub\n", This, debugstr_w(feature_name), value);
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_getProperty(
@@ -3074,18 +3296,18 @@ static HRESULT WINAPI isaxxmlreader_putProperty(
 
 static HRESULT WINAPI isaxxmlreader_getEntityResolver(
         ISAXXMLReader* iface,
-        ISAXEntityResolver **ppEntityResolver)
+        ISAXEntityResolver **resolver)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return internal_getEntityResolver(This, ppEntityResolver, FALSE);
+    return saxreader_get_handler(This, SAXEntityResolver, FALSE, (void**)resolver);
 }
 
 static HRESULT WINAPI isaxxmlreader_putEntityResolver(
         ISAXXMLReader* iface,
-        ISAXEntityResolver *pEntityResolver)
+        ISAXEntityResolver *resolver)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return internal_putEntityResolver(This, pEntityResolver, FALSE);
+    return saxreader_put_handler(This, SAXEntityResolver, resolver, FALSE);
 }
 
 static HRESULT WINAPI isaxxmlreader_getContentHandler(
@@ -3136,10 +3358,12 @@ static HRESULT WINAPI isaxxmlreader_putErrorHandler(ISAXXMLReader* iface, ISAXEr
 
 static HRESULT WINAPI isaxxmlreader_getBaseURL(
         ISAXXMLReader* iface,
-        const WCHAR **pBaseUrl)
+        const WCHAR **base_url)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_get_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
+
+    FIXME("(%p)->(%p) stub\n", This, base_url);
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_putBaseURL(
@@ -3147,7 +3371,9 @@ static HRESULT WINAPI isaxxmlreader_putBaseURL(
         const WCHAR *pBaseUrl)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_put_baseURL(&This->IVBSAXXMLReader_iface, pBaseUrl);
+
+    FIXME("(%p)->(%s) stub\n", This, debugstr_w(pBaseUrl));
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
@@ -3155,7 +3381,8 @@ static HRESULT WINAPI isaxxmlreader_getSecureBaseURL(
         const WCHAR **pSecureBaseUrl)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_get_secureBaseURL(&This->IVBSAXXMLReader_iface, pSecureBaseUrl);
+    FIXME("(%p)->(%p) stub\n", This, pSecureBaseUrl);
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
@@ -3163,7 +3390,9 @@ static HRESULT WINAPI isaxxmlreader_putSecureBaseURL(
         const WCHAR *secureBaseUrl)
 {
     saxreader *This = impl_from_ISAXXMLReader( iface );
-    return IVBSAXXMLReader_put_secureBaseURL(&This->IVBSAXXMLReader_iface, secureBaseUrl);
+
+    FIXME("(%p)->(%s) stub\n", This, debugstr_w(secureBaseUrl));
+    return E_NOTIMPL;
 }
 
 static HRESULT WINAPI isaxxmlreader_parse(
@@ -3218,11 +3447,11 @@ static dispex_static_data_t saxreader_dispex = {
     saxreader_iface_tids
 };
 
-HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppObj)
+HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
 {
     saxreader *reader;
 
-    TRACE("(%p, %p)\n", outer, ppObj);
+    TRACE("(%p)\n", ppObj);
 
     reader = heap_alloc( sizeof (*reader) );
     if( !reader )
@@ -3253,7 +3482,8 @@ HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppOb
     reader->sax.comment = libxmlComment;
     reader->sax.error = libxmlFatalError;
     reader->sax.fatalError = libxmlFatalError;
-    reader->sax.cdataBlock = libxmlCDataBlock;
+    reader->sax.cdataBlock = libxml_cdatablock;
+    reader->sax.resolveEntity = libxmlresolveentity;
 
     *ppObj = &reader->IVBSAXXMLReader_iface;
 
@@ -3264,7 +3494,7 @@ HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *outer, LPVOID *ppOb
 
 #else
 
-HRESULT SAXXMLReader_create(MSXML_VERSION version, IUnknown *pUnkOuter, LPVOID *ppObj)
+HRESULT SAXXMLReader_create(MSXML_VERSION version, LPVOID *ppObj)
 {
     MESSAGE("This program tried to use a SAX XML Reader object, but\n"
             "libxml2 support was not present at compile time.\n");