Commit 3d013afe authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

msxml3: Fix indexed access to schema collection namespace uris.

parent 4d2164c9
...@@ -404,6 +404,21 @@ static inline xmlChar *xmlchar_from_wchar( const WCHAR *str ) ...@@ -404,6 +404,21 @@ static inline xmlChar *xmlchar_from_wchar( const WCHAR *str )
return xmlchar_from_wcharn(str, -1); 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 #endif
static inline HRESULT return_bstr(const WCHAR *value, BSTR *p) static inline HRESULT return_bstr(const WCHAR *value, BSTR *p)
......
...@@ -100,6 +100,9 @@ typedef struct ...@@ -100,6 +100,9 @@ typedef struct
MSXML_VERSION version; MSXML_VERSION version;
xmlHashTablePtr cache; xmlHashTablePtr cache;
xmlChar **uris;
int allocated;
int count;
VARIANT_BOOL validateOnLoad; VARIANT_BOOL validateOnLoad;
int read_only; int read_only;
...@@ -113,12 +116,6 @@ typedef struct ...@@ -113,12 +116,6 @@ typedef struct
LONG ref; LONG ref;
} cache_entry; } cache_entry;
typedef struct
{
LONG index;
BSTR* out;
} cache_index_data;
/* datatypes lookup stuff /* datatypes lookup stuff
* generated with help from gperf */ * generated with help from gperf */
#define DT_MIN_STR_LEN 2 #define DT_MIN_STR_LEN 2
...@@ -982,6 +979,55 @@ static void cache_free(void* data, xmlChar* name /* ignored */) ...@@ -982,6 +979,55 @@ static void cache_free(void* data, xmlChar* name /* ignored */)
cache_entry_release((cache_entry*)data); 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 /* This one adds all namespaces defined in document to a cache, without anything
associated with uri obviously. associated with uri obviously.
Unfortunately namespace:: axis implementation in libxml2 differs from what we need, Unfortunately namespace:: axis implementation in libxml2 differs from what we need,
...@@ -1030,8 +1076,7 @@ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node) ...@@ -1030,8 +1076,7 @@ HRESULT cache_from_doc_ns(IXMLDOMSchemaCollection2 *iface, xmlnode *node)
entry->schema = NULL; entry->schema = NULL;
entry->doc = NULL; entry->doc = NULL;
xmlHashRemoveEntry(This->cache, ns->href, cache_free); cache_add_entry(This, ns->href, entry);
xmlHashAddEntry(This->cache, ns->href, entry);
} }
pos++; pos++;
} }
...@@ -1088,6 +1133,11 @@ static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface) ...@@ -1088,6 +1133,11 @@ static ULONG WINAPI schema_cache_Release(IXMLDOMSchemaCollection2* iface)
if (ref == 0) 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); xmlHashFree(This->cache, cache_free);
release_dispex(&This->dispex); release_dispex(&This->dispex);
heap_free(This); heap_free(This);
...@@ -1143,7 +1193,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri ...@@ -1143,7 +1193,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
{ {
case VT_NULL: case VT_NULL:
{ {
xmlHashRemoveEntry(This->cache, name, cache_free); cache_remove_entry(This, name);
} }
break; break;
...@@ -1161,8 +1211,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri ...@@ -1161,8 +1211,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
return E_FAIL; return E_FAIL;
} }
xmlHashRemoveEntry(This->cache, name, cache_free); cache_add_entry(This, name, entry);
xmlHashAddEntry(This->cache, name, entry);
} }
break; break;
...@@ -1211,8 +1260,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri ...@@ -1211,8 +1260,7 @@ static HRESULT WINAPI schema_cache_add(IXMLDOMSchemaCollection2* iface, BSTR uri
return E_FAIL; return E_FAIL;
} }
xmlHashRemoveEntry(This->cache, name, cache_free); cache_add_entry(This, name, entry);
xmlHashAddEntry(This->cache, name, entry);
} }
break; break;
...@@ -1260,7 +1308,7 @@ static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR ...@@ -1260,7 +1308,7 @@ static HRESULT WINAPI schema_cache_remove(IXMLDOMSchemaCollection2* iface, BSTR
if (This->version == MSXML6) return E_NOTIMPL; if (This->version == MSXML6) return E_NOTIMPL;
xmlHashRemoveEntry(This->cache, name, cache_free); cache_remove_entry(This, name);
heap_free(name); heap_free(name);
return S_OK; return S_OK;
} }
...@@ -1272,33 +1320,25 @@ static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, L ...@@ -1272,33 +1320,25 @@ static HRESULT WINAPI schema_cache_get_length(IXMLDOMSchemaCollection2* iface, L
if (!length) if (!length)
return E_POINTER; return E_POINTER;
*length = xmlHashSize(This->cache);
return S_OK;
}
static void cache_index(void* data /* ignored */, void* index, xmlChar* name) *length = This->count;
{ return S_OK;
cache_index_data* index_data = (cache_index_data*)index;
if (index_data->index-- == 0)
*index_data->out = bstr_from_xmlChar(name);
} }
static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface, static HRESULT WINAPI schema_cache_get_namespaceURI(IXMLDOMSchemaCollection2* iface,
LONG index, BSTR* len) LONG index, BSTR* uri)
{ {
schema_cache* This = impl_from_IXMLDOMSchemaCollection2(iface); 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; return E_POINTER;
if (index >= xmlHashSize(This->cache)) if (index >= This->count)
return E_FAIL; return E_FAIL;
*len = NULL; *uri = bstr_from_xmlChar(This->uris[index]);
xmlHashScan(This->cache, cache_index, &data);
return S_OK; return S_OK;
} }
...@@ -1310,7 +1350,7 @@ static void cache_copy(void* data, void* dest, xmlChar* name) ...@@ -1310,7 +1350,7 @@ static void cache_copy(void* data, void* dest, xmlChar* name)
if (xmlHashLookup(This->cache, name) == NULL) if (xmlHashLookup(This->cache, name) == NULL)
{ {
cache_entry_add_ref(entry); 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) ...@@ -1528,6 +1568,9 @@ HRESULT SchemaCache_create(MSXML_VERSION version, IUnknown* outer, void** obj)
This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl; This->IXMLDOMSchemaCollection2_iface.lpVtbl = &XMLDOMSchemaCollection2Vtbl;
This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE); This->cache = xmlHashCreate(DEFAULT_HASHTABLE_SIZE);
This->allocated = 10;
This->count = 0;
This->uris = heap_alloc(This->allocated*sizeof(xmlChar*));
This->ref = 1; This->ref = 1;
This->version = version; This->version = version;
This->validateOnLoad = VARIANT_TRUE; This->validateOnLoad = VARIANT_TRUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment