msxml3: Fix indexed access to schema collection namespace uris

Nikolay Sivov nsivov at codeweavers.com
Thu Nov 1 05:17:32 CDT 2012


Fix indexed access to schema collection namespace uris
-------------- next part --------------
>From cc19be7268799470a29ba8be2ee5117e4d015ba7 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov at codeweavers.com>
Date: Thu, 1 Nov 2012 13:13:02 -0400
Subject: [PATCH 2/2] Fix indexed access to schema collection namespace uris

---
 dlls/msxml3/msxml_private.h |   15 +++++++
 dlls/msxml3/schema.c        |  105 ++++++++++++++++++++++++++++++-------------
 2 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 8468e55..cc6b52d 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -200,6 +200,21 @@ static inline LPWSTR heap_strdupW(LPCWSTR str)
     return ret;
 }
 
+static inline xmlChar *heap_strdupxmlChar(const xmlChar *str)
+{
+    xmlChar *ret = NULL;
+
+    if(str) {
+        DWORD size;
+
+        size = (xmlStrlen(str)+1)*sizeof(xmlChar);
+        ret = heap_alloc(size);
+        memcpy(ret, str, size);
+    }
+
+    return ret;
+}
+
 static inline LPSTR heap_strdupWtoA(LPCWSTR str)
 {
     LPSTR ret = NULL;
diff --git a/dlls/msxml3/schema.c b/dlls/msxml3/schema.c
index 5d971f9..5626464 100644
--- a/dlls/msxml3/schema.c
+++ b/dlls/msxml3/schema.c
@@ -100,6 +100,9 @@ typedef struct
 
     MSXML_VERSION version;
     xmlHashTablePtr cache;
+    xmlChar **uris;
+    int allocated;
+    int count;
 
     VARIANT_BOOL validateOnLoad;
     int read_only;
@@ -113,12 +116,6 @@ typedef struct
     LONG ref;
 } cache_entry;
 
-typedef struct
-{
-    LONG index;
-    BSTR* out;
-} cache_index_data;
-
 /* datatypes lookup stuff
  * generated with help from gperf */
 #define DT_MIN_STR_LEN 2
@@ -982,6 +979,55 @@ static void cache_free(void* data, xmlChar* name /* ignored */)
     cache_entry_release((cache_entry*)data);
 }
 
+/* returns index or -1 if not found */
+static int cache_free_uri(schema_cache *cache, const xmlChar *uri)
+{
+    int i;
+
+    for (i = 0; i < cache->count; i++)
+        if (xmlStrEqual(cache->uris[i], uri))
+        {
+            heap_free(cache->uris[i]);
+            return i;
+        }
+
+    return -1;
+}
+
+static void cache_add_entry(schema_cache *cache, const xmlChar *uri, cache_entry *entry)
+{
+    int i;
+
+    /* meaning no entry found with this name */
+    if (xmlHashRemoveEntry(cache->cache, uri, cache_free))
+    {
+        if (cache->count == cache->allocated)
+        {
+            cache->allocated *= 2;
+            cache->uris = heap_realloc(cache->uris, cache->allocated*sizeof(xmlChar*));
+        }
+        i = cache->count++;
+    }
+    else
+        i = cache_free_uri(cache, uri);
+
+    cache->uris[i] = heap_strdupxmlChar(uri);
+    xmlHashAddEntry(cache->cache, uri, entry);
+}
+
+static void cache_remove_entry(schema_cache *cache, const xmlChar *uri)
+{
+    /* adjust index if entry was really removed */
+    if (xmlHashRemoveEntry(cache->cache, uri, cache_free) == 0)
+    {
+        int i = cache_free_uri(cache, uri);
+        if (i == -1) return;
+        /* shift array */
+        if (i != --cache->count)
+            memmove(&cache->uris[i], &cache->uris[i+1], (cache->count-i)*sizeof(xmlChar*));
+    }
+}
+
 /* This one adds all namespaces defined in document to a cache, without anything
    associated with uri obviously.
    Unfortunately namespace:: axis implementation in libxml2 differs from what we need,
@@ -1030,8 +1076,7 @@ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node)
                 entry->schema = NULL;
                 entry->doc = NULL;
 
-                xmlHashRemoveEntry(This->cache, ns->href, cache_free);
-                xmlHashAddEntry(This->cache, ns->href, entry);
+                cache_add_entry(This, ns->href, entry);
             }
             pos++;
         }
@@ -1088,6 +1133,11 @@ static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface)
 
     if (ref == 0)
     {
+        int i;
+
+        for (i = 0; i < This->count; i++)
+            heap_free(This->uris[i]);
+        heap_free(This->uris);
         xmlHashFree(This->cache, cache_free);
         release_dispex(&This->dispex);
         heap_free(This);
@@ -1143,7 +1193,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
     {
         case VT_NULL:
             {
-                xmlHashRemoveEntry(This->cache, name, cache_free);
+                cache_remove_entry(This, name);
             }
             break;
 
@@ -1161,8 +1211,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
                     return E_FAIL;
                 }
 
-                xmlHashRemoveEntry(This->cache, name, cache_free);
-                xmlHashAddEntry(This->cache, name, entry);
+                cache_add_entry(This, name, entry);
             }
             break;
 
@@ -1211,8 +1260,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
                     return E_FAIL;
                 }
 
-                xmlHashRemoveEntry(This->cache, name, cache_free);
-                xmlHashAddEntry(This->cache, name, entry);
+                cache_add_entry(This, name, entry);
             }
             break;
 
@@ -1260,7 +1308,7 @@ static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR
 
     if (This->version == MSXML6) return E_NOTIMPL;
 
-    xmlHashRemoveEntry(This->cache, name, cache_free);
+    cache_remove_entry(This, name);
     heap_free(name);
     return S_OK;
 }
@@ -1272,33 +1320,25 @@ static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, L
 
     if (!length)
         return E_POINTER;
-    *length = xmlHashSize(This->cache);
-    return S_OK;
-}
 
-static void cache_index(void* data /* ignored */, void* index, xmlChar* name)
-{
-    cache_index_data* index_data = (cache_index_data*)index;
-
-    if (index_data->index-- == 0)
-        *index_data->out = bstr_from_xmlChar(name);
+    *length = This->count;
+    return S_OK;
 }
 
 static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface,
-                                                    LONG index, BSTR* len)
+                                                    LONG index, BSTR* uri)
 {
     schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface);
-    cache_index_data data = {index, len};
-    TRACE("(%p)->(%i %p)\n", This, index, len);
 
-    if (!len)
+    TRACE("(%p)->(%i %p)\n", This, index, uri);
+
+    if (!uri)
         return E_POINTER;
 
-    if (index >= xmlHashSize(This->cache))
+    if (index >= This->count)
         return E_FAIL;
 
-    *len = NULL;
-    xmlHashScan(This->cache, cache_index, &data);
+    *uri = bstr_from_xmlChar(This->uris[index]);
     return S_OK;
 }
 
@@ -1310,7 +1350,7 @@ static void cache_copy(void* data, void* dest, xmlChar* name)
     if (xmlHashLookup(This->cache, name) == NULL)
     {
         cache_entry_add_ref(entry);
-        xmlHashAddEntry(This->cache, name, entry);
+        cache_add_entry(This, name, entry);
     }
 }
 
@@ -1528,6 +1568,9 @@ HRESULT SchemaCache_create(MSXML_VERSION version, IUnknown* outer, void** obj)
 
     This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl;
     This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE);
+    This->allocated = 10;
+    This->count = 0;
+    This->uris = heap_alloc(This->allocated*sizeof(xmlChar*));
     This->ref = 1;
     This->version = version;
     This->validateOnLoad = VARIANT_TRUE;
-- 
1.7.10.4



More information about the wine-patches mailing list