[PATCH 8/8] msxml3: Use built-in urn:schemas-microsoft-com:datatypes schema for validation

Adam Martinson amartinson at codeweavers.com
Fri Nov 12 08:33:17 CST 2010


---
 dlls/msxml3/main.c          |    2 +
 dlls/msxml3/msxml_private.h |    3 +
 dlls/msxml3/schema.c        |  106 +++++++++++++++++++++++++++++++++++++++++++
 dlls/msxml3/tests/domdoc.c  |    8 ++--
 dlls/msxml3/tests/schema.c  |   50 ++++++++++----------
 5 files changed, 140 insertions(+), 29 deletions(-)

diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c
index 8e612b7..49ef6fa 100644
--- a/dlls/msxml3/main.c
+++ b/dlls/msxml3/main.c
@@ -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;
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index 08c2c97..3de258c 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -112,6 +112,9 @@ BOOL dispex_query_interface(DispatchEx*,REFIID,void**);
 
 #include <libxml/xmlerror.h>
 
+extern void schemasInit(void);
+extern void schemasCleanup(void);
+
 #ifndef HAVE_XMLFIRSTELEMENTCHILD
     static inline xmlNodePtr xmlFirstElementChild(xmlNodePtr parent)
     {
diff --git a/dlls/msxml3/schema.c b/dlls/msxml3/schema.c
index de41bd0..3be5a12 100644
--- a/dlls/msxml3/schema.c
+++ b/dlls/msxml3/schema.c
@@ -52,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);
 
@@ -59,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
@@ -93,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);
@@ -153,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));
@@ -191,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;
@@ -220,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);
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 7f9f761..07821b8 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -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);
 
diff --git a/dlls/msxml3/tests/schema.c b/dlls/msxml3/tests/schema.c
index ca2e5a3..189451e 100644
--- a/dlls/msxml3/tests/schema.c
+++ b/dlls/msxml3/tests/schema.c
@@ -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)
         {
-- 
1.7.2.3


--------------050805080806040801060808--



More information about the wine-patches mailing list