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 )
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)
......
......@@ -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;
......
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