msxml3: Use built-in urn:schemas-microsoft-com:datatypes schema for validation.
This commit is contained in:
parent
5fc439a7f8
commit
2c451f869a
|
@ -210,6 +210,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|||
wineXmlReadCallback, wineXmlFileCloseCallback) == -1)
|
||||
WARN("Failed to register callbacks\n");
|
||||
|
||||
schemasInit();
|
||||
#endif
|
||||
init_libxslt();
|
||||
DisableThreadLibraryCalls(hInstDLL);
|
||||
|
@ -229,6 +230,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|||
xmlRegisterDefaultInputCallbacks();
|
||||
|
||||
xmlCleanupParser();
|
||||
schemasCleanup();
|
||||
#endif
|
||||
release_typelib();
|
||||
break;
|
||||
|
|
|
@ -110,11 +110,15 @@ BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
|
|||
#endif
|
||||
|
||||
|
||||
|
||||
#include <libxml/xmlerror.h>
|
||||
|
||||
extern void schemasInit(void);
|
||||
extern void schemasCleanup(void);
|
||||
|
||||
#ifndef HAVE_XMLFIRSTELEMENTCHILD
|
||||
static inline xmlNodePtr xmlFirstElementChild(xmlNodePtr parent)
|
||||
{
|
||||
static inline xmlNodePtr xmlFirstElementChild(xmlNodePtr parent)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
for (child = parent->children; child != NULL; child = child->next)
|
||||
if (child->type == XML_ELEMENT_NODE)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
@ -51,6 +52,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml);
|
|||
#include <libxml/xmlschemas.h>
|
||||
#include <libxml/schemasInternals.h>
|
||||
#include <libxml/hash.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/parserInternals.h>
|
||||
#include <libxml/xmlIO.h>
|
||||
|
||||
xmlDocPtr XDR_to_XSD_doc(xmlDocPtr xdr_doc, xmlChar const* nsURI);
|
||||
|
||||
|
@ -58,6 +62,11 @@ static const xmlChar XSD_schema[] = "schema";
|
|||
static const xmlChar XSD_nsURI[] = "http://www.w3.org/2001/XMLSchema";
|
||||
static const xmlChar XDR_schema[] = "Schema";
|
||||
static const xmlChar XDR_nsURI[] = "urn:schemas-microsoft-com:xml-data";
|
||||
static const xmlChar DT_nsURI[] = "urn:schemas-microsoft-com:datatypes";
|
||||
|
||||
static xmlChar const* datatypes_schema = NULL;
|
||||
static HGLOBAL datatypes_handle = NULL;
|
||||
static HRSRC datatypes_rsrc = NULL;
|
||||
|
||||
/* Supported Types:
|
||||
* msxml3 - XDR only
|
||||
|
@ -92,6 +101,72 @@ typedef struct _cache_index_data
|
|||
BSTR* out;
|
||||
} cache_index_data;
|
||||
|
||||
xmlExternalEntityLoader _external_entity_loader = NULL;
|
||||
|
||||
static xmlParserInputPtr external_entity_loader(const char *URL, const char *ID,
|
||||
xmlParserCtxtPtr ctxt)
|
||||
{
|
||||
xmlParserInputPtr input;
|
||||
|
||||
TRACE("(%s, %s, %p)\n", wine_dbgstr_a(URL), wine_dbgstr_a(ID), ctxt);
|
||||
|
||||
assert(MSXML_hInstance != NULL);
|
||||
assert(datatypes_rsrc != NULL);
|
||||
assert(datatypes_handle != NULL);
|
||||
assert(datatypes_schema != NULL);
|
||||
|
||||
/* TODO: if the desired schema is in the cache, load it from there */
|
||||
if (lstrcmpA(URL, "urn:schemas-microsoft-com:datatypes") == 0)
|
||||
{
|
||||
TRACE("loading built-in schema for %s\n", URL);
|
||||
input = xmlNewStringInputStream(ctxt, datatypes_schema);
|
||||
}
|
||||
else
|
||||
{
|
||||
input = _external_entity_loader(URL, ID, ctxt);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
void schemasInit(void)
|
||||
{
|
||||
int len;
|
||||
char* buf;
|
||||
if (!(datatypes_rsrc = FindResourceA(MSXML_hInstance, "DATATYPES", "XML")))
|
||||
{
|
||||
FIXME("failed to find resource for %s\n", DT_nsURI);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(datatypes_handle = LoadResource(MSXML_hInstance, datatypes_rsrc)))
|
||||
{
|
||||
FIXME("failed to load resource for %s\n", DT_nsURI);
|
||||
return;
|
||||
}
|
||||
buf = LockResource(datatypes_handle);
|
||||
len = SizeofResource(MSXML_hInstance, datatypes_rsrc) - 1;
|
||||
|
||||
/* Resource is loaded as raw data,
|
||||
* need a null-terminated string */
|
||||
while (buf[len] != '>')
|
||||
buf[len--] = 0;
|
||||
datatypes_schema = BAD_CAST buf;
|
||||
|
||||
if ((void*)xmlGetExternalEntityLoader() != (void*)external_entity_loader)
|
||||
{
|
||||
_external_entity_loader = xmlGetExternalEntityLoader();
|
||||
xmlSetExternalEntityLoader(external_entity_loader);
|
||||
}
|
||||
}
|
||||
|
||||
void schemasCleanup(void)
|
||||
{
|
||||
if (datatypes_handle)
|
||||
FreeResource(datatypes_handle);
|
||||
xmlSetExternalEntityLoader(_external_entity_loader);
|
||||
}
|
||||
|
||||
static LONG cache_entry_add_ref(cache_entry* entry)
|
||||
{
|
||||
LONG ref = InterlockedIncrement(&entry->ref);
|
||||
|
@ -152,6 +227,34 @@ static inline SCHEMA_TYPE schema_type_from_xmlDocPtr(xmlDocPtr schema)
|
|||
return SCHEMA_TYPE_INVALID;
|
||||
}
|
||||
|
||||
static BOOL link_datatypes(xmlDocPtr schema)
|
||||
{
|
||||
xmlNodePtr root, next, child;
|
||||
xmlNsPtr ns;
|
||||
|
||||
assert((void*)xmlGetExternalEntityLoader() == (void*)external_entity_loader);
|
||||
root = xmlDocGetRootElement(schema);
|
||||
if (!root)
|
||||
return FALSE;
|
||||
|
||||
for (ns = root->nsDef; ns != NULL; ns = ns->next)
|
||||
{
|
||||
if (xmlStrEqual(ns->href, DT_nsURI))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ns)
|
||||
return FALSE;
|
||||
|
||||
next = xmlFirstElementChild(root);
|
||||
child = xmlNewChild(root, NULL, BAD_CAST "import", NULL);
|
||||
if (next) child = xmlAddPrevSibling(next, child);
|
||||
xmlSetProp(child, BAD_CAST "namespace", DT_nsURI);
|
||||
xmlSetProp(child, BAD_CAST "schemaLocation", DT_nsURI);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cache_entry* cache_entry_from_url(char const* url, xmlChar const* nsURI)
|
||||
{
|
||||
cache_entry* entry = heap_alloc(sizeof(cache_entry));
|
||||
|
@ -190,6 +293,8 @@ static cache_entry* cache_entry_from_xsd_doc(xmlDocPtr doc, xmlChar const* nsURI
|
|||
xmlSchemaParserCtxtPtr spctx;
|
||||
xmlDocPtr new_doc = xmlCopyDoc(doc, 1);
|
||||
|
||||
link_datatypes(new_doc);
|
||||
|
||||
/* TODO: if the nsURI is different from the default xmlns or targetNamespace,
|
||||
* do we need to do something special here? */
|
||||
entry->type = SCHEMA_TYPE_XSD;
|
||||
|
@ -219,6 +324,8 @@ static cache_entry* cache_entry_from_xdr_doc(xmlDocPtr doc, xmlChar const* nsURI
|
|||
xmlSchemaParserCtxtPtr spctx;
|
||||
xmlDocPtr new_doc = xmlCopyDoc(doc, 1), xsd_doc = XDR_to_XSD_doc(doc, nsURI);
|
||||
|
||||
link_datatypes(xsd_doc);
|
||||
|
||||
entry->type = SCHEMA_TYPE_XDR;
|
||||
entry->ref = 0;
|
||||
spctx = xmlSchemaNewDocParserCtxt(xsd_doc);
|
||||
|
|
|
@ -7946,7 +7946,7 @@ static void test_get_dataType(void)
|
|||
V_DISPATCH(&v) = NULL;
|
||||
ole_check(IXMLDOMDocument2_QueryInterface(schema, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
|
||||
ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_("urn:x-schema:datatype-test-xdr"), v));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_("urn:x-schema:datatype-test-xdr"), v));
|
||||
VariantClear(&v);
|
||||
|
||||
/* associate the cache to the doc */
|
||||
|
@ -7961,11 +7961,11 @@ static void test_get_dataType(void)
|
|||
err = NULL;
|
||||
l = 0;
|
||||
bstr = NULL;
|
||||
todo_wine ole_check(IXMLDOMDocument2_validate(doc, &err));
|
||||
ole_check(IXMLDOMDocument2_validate(doc, &err));
|
||||
ok(err != NULL, "domdoc_validate() should always set err\n");
|
||||
todo_wine ole_expect(IXMLDOMParseError_get_errorCode(err, &l), S_FALSE);
|
||||
ole_expect(IXMLDOMParseError_get_errorCode(err, &l), S_FALSE);
|
||||
ole_expect(IXMLDOMParseError_get_reason(err, &bstr), S_FALSE);
|
||||
todo_wine ok(l == 0, "got %08x : %s\n", l, wine_dbgstr_w(bstr));
|
||||
ok(l == 0, "got %08x : %s\n", l, wine_dbgstr_w(bstr));
|
||||
if (bstr) SysFreeString(bstr);
|
||||
IXMLDOMParseError_Release(err);
|
||||
|
||||
|
|
|
@ -356,9 +356,9 @@ static void test_collection_refs(void)
|
|||
ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xdr_schema3_xml), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML\n");
|
||||
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache3, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache3, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
|
||||
check_ref_expr(IXMLDOMDocument2_Release(schema1), 0);
|
||||
check_ref_expr(IXMLDOMDocument2_Release(schema2), 0);
|
||||
|
@ -383,15 +383,15 @@ static void test_collection_refs(void)
|
|||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache1, &length));
|
||||
todo_wine ok(length == 1, "expected length 1, got %i\n", length);
|
||||
ok(length == 1, "expected length 1, got %i\n", length);
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache2, &length));
|
||||
todo_wine ok(length == 2, "expected length 2, got %i\n", length);
|
||||
ok(length == 2, "expected length 2, got %i\n", length);
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache3, &length));
|
||||
todo_wine ok(length == 3, "expected length 3, got %i\n", length);
|
||||
ok(length == 3, "expected length 3, got %i\n", length);
|
||||
|
||||
|
||||
/* merging collections does not affect the ref count */
|
||||
|
@ -484,23 +484,23 @@ static void test_length(void)
|
|||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
ok(length == 0, "expected length 0, got %i\n", length);
|
||||
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
todo_wine ok(length == 1, "expected length 1, got %i\n", length);
|
||||
ok(length == 1, "expected length 1, got %i\n", length);
|
||||
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
todo_wine ok(length == 2, "expected length 2, got %i\n", length);
|
||||
ok(length == 2, "expected length 2, got %i\n", length);
|
||||
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
todo_wine ok(length == 3, "expected length 3, got %i\n", length);
|
||||
ok(length == 3, "expected length 3, got %i\n", length);
|
||||
|
||||
/* adding with VT_NULL is the same as removing */
|
||||
V_VT(&v) = VT_NULL;
|
||||
|
@ -508,13 +508,13 @@ static void test_length(void)
|
|||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
todo_wine ok(length == 2, "expected length 2, got %i\n", length);
|
||||
ok(length == 2, "expected length 2, got %i\n", length);
|
||||
|
||||
ole_check(IXMLDOMSchemaCollection_remove(cache, _bstr_(xdr_schema2_uri)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
|
||||
todo_wine ok(length == 1, "expected length 1, got %i\n", length);
|
||||
ok(length == 1, "expected length 1, got %i\n", length);
|
||||
|
||||
ole_check(IXMLDOMSchemaCollection_remove(cache, _bstr_(xdr_schema3_uri)));
|
||||
|
||||
|
@ -567,13 +567,13 @@ static void test_collection_content(void)
|
|||
ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xdr_schema3_xml), &b));
|
||||
ok(b == VARIANT_TRUE, "failed to load XML\n");
|
||||
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache1, &length));
|
||||
todo_wine ok(length == 3, "expected length 3, got %i\n", length);
|
||||
ok(length == 3, "expected length 3, got %i\n", length);
|
||||
|
||||
IXMLDOMDocument2_Release(schema1);
|
||||
IXMLDOMDocument2_Release(schema2);
|
||||
|
@ -598,15 +598,15 @@ static void test_collection_content(void)
|
|||
ok(b == VARIANT_TRUE, "failed to load XML\n");
|
||||
|
||||
/* combining XDR and XSD schemas in the same cache is fine */
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema1_uri), _variantdoc_(schema3)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema2_uri), _variantdoc_(schema4)));
|
||||
ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema3_uri), _variantdoc_(schema5)));
|
||||
|
||||
length = -1;
|
||||
ole_check(IXMLDOMSchemaCollection_get_length(cache2, &length));
|
||||
todo_wine ok(length == 5, "expected length 5, got %i\n", length);
|
||||
ok(length == 5, "expected length 5, got %i\n", length);
|
||||
|
||||
IXMLDOMDocument2_Release(schema1);
|
||||
IXMLDOMDocument2_Release(schema2);
|
||||
|
@ -637,12 +637,12 @@ static void test_collection_content(void)
|
|||
for (i = 0; i < 3; ++i)
|
||||
{
|
||||
bstr = NULL;
|
||||
todo_wine ole_check(IXMLDOMSchemaCollection_get_namespaceURI(cache1, i, &bstr));
|
||||
todo_wine ok(bstr != NULL && *bstr, "expected non-empty string\n");
|
||||
ole_check(IXMLDOMSchemaCollection_get_namespaceURI(cache1, i, &bstr));
|
||||
ok(bstr != NULL && *bstr, "expected non-empty string\n");
|
||||
content[i] = bstr;
|
||||
|
||||
for (j = 0; j < i; ++j)
|
||||
todo_wine ok(lstrcmpW(content[j], bstr), "got duplicate entry\n");
|
||||
ok(lstrcmpW(content[j], bstr), "got duplicate entry\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i)
|
||||
|
@ -651,7 +651,7 @@ static void test_collection_content(void)
|
|||
content[i] = NULL;
|
||||
}
|
||||
|
||||
if (FALSE && cache2)
|
||||
if (cache2)
|
||||
{
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue