[MSXML3] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / win32 / msxml3 / saxreader.c
index dc38cb9..fc27260 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
+#define COBJMACROS
 
-#include "precomp.h"
+#include "config.h"
 
+#include <stdarg.h>
 #ifdef HAVE_LIBXML2
+# include <libxml/parser.h>
+# include <libxml/xmlerror.h>
+# include <libxml/SAX2.h>
 # include <libxml/parserInternals.h>
 #endif
 
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "ole2.h"
+#include "msxml6.h"
+#include "wininet.h"
+#include "urlmon.h"
+#include "winreg.h"
+#include "shlwapi.h"
+
+#include "wine/debug.h"
+
+#include "msxml_private.h"
+
 #ifdef HAVE_LIBXML2
 
+WINE_DEFAULT_DEBUG_CHANNEL(msxml);
+
 typedef enum
 {
     FeatureUnknown               = 0,
@@ -78,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;
@@ -85,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)
@@ -98,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)
     {
@@ -117,6 +149,8 @@ static saxreader_feature get_saxreader_feature(const WCHAR *name)
     return FeatureUnknown;
 }
 
+static const WCHAR empty_str;
+
 struct bstrpool
 {
     BSTR *pool;
@@ -279,8 +313,8 @@ typedef struct
     struct list elements;
 
     BSTR namespaceUri;
-    int attributesSize;
-    int nb_attributes;
+    int attr_alloc_count;
+    int attr_count;
     struct _attributes
     {
         BSTR szLocalname;
@@ -539,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;
 
@@ -548,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;
@@ -568,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;
@@ -646,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';
@@ -668,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
@@ -1084,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,
@@ -1098,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);
@@ -1111,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;
 }
@@ -1158,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;
 
@@ -1189,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))
@@ -1221,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;
@@ -1283,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);
@@ -1382,7 +1422,7 @@ static BSTR saxreader_get_unescaped_value(const xmlChar *buf, int len)
         WCHAR *src;
 
         /* leave first '&' from a reference as a value */
-        src = dest + (sizeof(ampescW)/sizeof(WCHAR) - 1);
+        src = dest + ARRAY_SIZE(ampescW) - 1;
         dest++;
 
         /* move together with null terminator */
@@ -1401,7 +1441,7 @@ static void free_attribute_values(saxlocator *locator)
 {
     int i;
 
-    for (i = 0; i < locator->nb_attributes; i++)
+    for (i = 0; i < locator->attr_count; i++)
     {
         SysFreeString(locator->attributes[i].szLocalname);
         locator->attributes[i].szLocalname = NULL;
@@ -1428,19 +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)
     {
-        int new_size = locator->attributesSize * 2;
+        int new_size = locator->attr_count * 2;
         attrs = heap_realloc_zero(locator->attributes, new_size * sizeof(struct _attributes));
         if(!attrs)
         {
             free_attribute_values(locator);
-            locator->nb_attributes = 0;
+            locator->attr_count = 0;
             return E_OUTOFMEMORY;
         }
         locator->attributes = attrs;
-        locator->attributesSize = new_size;
+        locator->attr_alloc_count = new_size;
     }
     else
     {
@@ -1627,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);
 
@@ -1684,7 +1724,7 @@ static void libxmlEndElementNS(
     if (!saxreader_has_handler(This, SAXContentHandler))
     {
         free_attribute_values(This);
-        This->nb_attributes = 0;
+        This->attr_count = 0;
         free_element_entry(element);
         return;
     }
@@ -1701,12 +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));
 
     free_attribute_values(This);
-    This->nb_attributes = 0;
+    This->attr_count = 0;
 
     if (sax_callback_failed(This, hr))
     {
@@ -1944,6 +1984,7 @@ static BSTR saxreader_get_cdata_chunk(const xmlChar *str, int len)
     BSTR bstr = bstr_from_xmlCharN(str, len), ret;
     WCHAR *ptr;
 
+    len = SysStringLen(bstr);
     ptr = bstr + len - 1;
     while ((*ptr == '\r' || *ptr == '\n') && ptr >= bstr)
         ptr--;
@@ -2010,7 +2051,7 @@ static void libxml_cdatablock(void *ctx, const xmlChar *value, int len)
             while (i < len)
             {
                 if (value[i] != '\r' && value[i] != '\n') break;
-                    i++;
+                i++;
             }
             end = &value[i];
 
@@ -2304,7 +2345,7 @@ static ULONG WINAPI isaxlocator_Release(
         SysFreeString(This->systemId);
         SysFreeString(This->namespaceUri);
 
-        for(index=0; index<This->attributesSize; index++)
+        for(index = 0; index < This->attr_alloc_count; index++)
         {
             SysFreeString(This->attributes[index].szLocalname);
             SysFreeString(This->attributes[index].szValue);
@@ -2440,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_zero(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);
@@ -2494,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);
@@ -2633,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)
             {
@@ -2650,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)
             {
@@ -3208,7 +3228,14 @@ static HRESULT WINAPI isaxxmlreader_getFeature(
     TRACE("(%p)->(%s %p)\n", This, debugstr_w(feature_name), value);
 
     feature = get_saxreader_feature(feature_name);
-    if (feature == Namespaces || feature == NamespacePrefixes)
+
+    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);
@@ -3228,15 +3255,18 @@ static HRESULT WINAPI isaxxmlreader_putFeature(
     feature = get_saxreader_feature(feature_name);
 
     /* accepted cases */
-    if ((feature == ExternalGeneralEntities   && value == VARIANT_FALSE) ||
-        (feature == ExternalParameterEntities && value == VARIANT_FALSE) ||
+    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)
+    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);