Module: wine Branch: master Commit: 3d013afec7aad964224030c3832779185ae599a9 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3d013afec7aad964224030c383...
Author: Nikolay Sivov nsivov@codeweavers.com Date: Thu Nov 1 13:13:02 2012 -0400
msxml3: 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..503a580 100644 --- a/dlls/msxml3/msxml_private.h +++ b/dlls/msxml3/msxml_private.h @@ -404,6 +404,21 @@ static inline xmlChar *xmlchar_from_wchar( const WCHAR *str ) return xmlchar_from_wcharn(str, -1); }
+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; +} + #endif
static inline HRESULT return_bstr(const WCHAR *value, BSTR *p) 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;