>From 01f0a75d252e2777761596509d302ab9050facf7 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Sun, 18 Dec 2011 01:21:09 +0300
Subject: [PATCH 1/6] Skip leading space characters when loading from BSTR

---
 dlls/msxml3/domdoc.c        |   20 +++++---
 dlls/msxml3/factory.c       |   26 +++++-----
 dlls/msxml3/msxml_private.h |    8 ++-
 dlls/msxml3/tests/domdoc.c  |  107 +++++++++++++++++++++++++++++++++----------
 4 files changed, 114 insertions(+), 47 deletions(-)

diff --git a/dlls/msxml3/domdoc.c b/dlls/msxml3/domdoc.c
index 68f47a7..4bb4fa4 100644
--- a/dlls/msxml3/domdoc.c
+++ b/dlls/msxml3/domdoc.c
@@ -78,7 +78,7 @@ static const WCHAR PropertyResolveExternalsW[] = {'R','e','s','o','l','v','e','E
  * tests can go here (data shared between all instances).
  * We need to preserve this when reloading a document,
  * and also need access to it from the libxml backend. */
-typedef struct _domdoc_properties {
+typedef struct {
     MSXML_VERSION version;
     VARIANT_BOOL preserving;
     IXMLDOMSchemaCollection2* schemaCache;
@@ -285,7 +285,7 @@ static xmldoc_priv * create_priv(void)
     return priv;
 }
 
-static domdoc_properties * create_properties(MSXML_VERSION version)
+static domdoc_properties *create_properties(MSXML_VERSION version)
 {
     domdoc_properties *properties = heap_alloc(sizeof(domdoc_properties));
 
@@ -2230,18 +2230,17 @@ static HRESULT WINAPI domdoc_abort(
     return E_NOTIMPL;
 }
 
-
 /* don't rely on data to be in BSTR format, treat it as WCHAR string */
 static HRESULT WINAPI domdoc_loadXML(
     IXMLDOMDocument3 *iface,
-    BSTR bstrXML,
+    BSTR data,
     VARIANT_BOOL* isSuccessful )
 {
     domdoc *This = impl_from_IXMLDOMDocument3( iface );
     xmlDocPtr xmldoc = NULL;
     HRESULT hr = S_FALSE, hr2;
 
-    TRACE("(%p)->(%s %p)\n", This, debugstr_w( bstrXML ), isSuccessful );
+    TRACE("(%p)->(%s %p)\n", This, debugstr_w(data), isSuccessful );
 
     assert ( &This->node );
 
@@ -2249,9 +2248,16 @@ static HRESULT WINAPI domdoc_loadXML(
     {
         *isSuccessful = VARIANT_FALSE;
 
-        if ( bstrXML )
+        if (data)
         {
-            xmldoc = doparse(This, (LPCSTR)bstrXML, lstrlenW(bstrXML) * sizeof(*bstrXML), XML_CHAR_ENCODING_UTF16LE);
+            WCHAR *ptr = data;
+
+            /* skip leading spaces if needed */
+            if (This->properties->version == MSXML_DEFAULT || This->properties->version == MSXML26)
+                 while (*ptr)
+                    if (isspaceW(*ptr)) ptr++; else break;
+
+            xmldoc = doparse(This, (char*)ptr, strlenW(ptr)*sizeof(WCHAR), XML_CHAR_ENCODING_UTF16LE);
             if ( !xmldoc )
             {
                 This->error = E_FAIL;
diff --git a/dlls/msxml3/factory.c b/dlls/msxml3/factory.c
index 1192780..e3b910a 100644
--- a/dlls/msxml3/factory.c
+++ b/dlls/msxml3/factory.c
@@ -59,24 +59,24 @@ struct clsid_version_t
 static const struct clsid_version_t clsid_versions_table[] =
 {
     { &CLSID_DOMDocument,   MSXML_DEFAULT },
-    { &CLSID_DOMDocument2,  MSXML_DEFAULT },
-    { &CLSID_DOMDocument26, MSXML_DEFAULT },
-    { &CLSID_DOMDocument30, MSXML3 },
-    { &CLSID_DOMDocument40, MSXML4 },
-    { &CLSID_DOMDocument60, MSXML6 },
+    { &CLSID_DOMDocument2,  MSXML2  },
+    { &CLSID_DOMDocument26, MSXML26 },
+    { &CLSID_DOMDocument30, MSXML3  },
+    { &CLSID_DOMDocument40, MSXML4  },
+    { &CLSID_DOMDocument60, MSXML6  },
 
     { &CLSID_DOMFreeThreadedDocument,   MSXML_DEFAULT },
     { &CLSID_FreeThreadedDOMDocument,   MSXML_DEFAULT },
-    { &CLSID_FreeThreadedDOMDocument26, MSXML_DEFAULT },
-    { &CLSID_FreeThreadedDOMDocument30, MSXML3 },
-    { &CLSID_FreeThreadedDOMDocument40, MSXML4 },
-    { &CLSID_FreeThreadedDOMDocument60, MSXML6 },
+    { &CLSID_FreeThreadedDOMDocument26, MSXML26 },
+    { &CLSID_FreeThreadedDOMDocument30, MSXML3  },
+    { &CLSID_FreeThreadedDOMDocument40, MSXML4  },
+    { &CLSID_FreeThreadedDOMDocument60, MSXML6  },
 
     { &CLSID_XMLSchemaCache,   MSXML_DEFAULT },
-    { &CLSID_XMLSchemaCache26, MSXML_DEFAULT },
-    { &CLSID_XMLSchemaCache30, MSXML3 },
-    { &CLSID_XMLSchemaCache40, MSXML4 },
-    { &CLSID_XMLSchemaCache60, MSXML6 },
+    { &CLSID_XMLSchemaCache26, MSXML26 },
+    { &CLSID_XMLSchemaCache30, MSXML3  },
+    { &CLSID_XMLSchemaCache40, MSXML4  },
+    { &CLSID_XMLSchemaCache60, MSXML6  },
 
     { &CLSID_MXXMLWriter,   MSXML_DEFAULT },
     { &CLSID_MXXMLWriter30, MSXML3 },
diff --git a/dlls/msxml3/msxml_private.h b/dlls/msxml3/msxml_private.h
index ad9e5c0..141c08c 100644
--- a/dlls/msxml3/msxml_private.h
+++ b/dlls/msxml3/msxml_private.h
@@ -31,9 +31,11 @@
 
 typedef enum {
     MSXML_DEFAULT = 0,
-    MSXML3 = 30,
-    MSXML4 = 40,
-    MSXML6 = 60
+    MSXML2        = 20,
+    MSXML26       = 26,
+    MSXML3        = 30,
+    MSXML4        = 40,
+    MSXML6        = 60
 } MSXML_VERSION;
 
 /* typelibs */
diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c
index 32b1b2b..0a2dbcf 100644
--- a/dlls/msxml3/tests/domdoc.c
+++ b/dlls/msxml3/tests/domdoc.c
@@ -41,6 +41,9 @@
 
 #include "wine/test.h"
 
+/* undef the #define in msxml2 so that we can access all versions */
+#undef CLSID_DOMDocument
+
 DEFINE_GUID(SID_SContainerDispatch, 0xb722be00, 0x4e68, 0x101b, 0xa2, 0xbc, 0x00, 0xaa, 0x00, 0x40, 0x47, 0x70);
 DEFINE_GUID(SID_UnknownSID, 0x75dd09cb, 0x6c40, 0x11d5, 0x85, 0x43, 0x00, 0xc0, 0x4f, 0xa0, 0xfb, 0xa3);
 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
@@ -1737,15 +1740,6 @@ static const char xpath_simple_list[] =
 "   <d/>"
 "</root>";
 
-static const char* leading_spaces[] = {
-    "\n<?xml version=\"1.0\"?><root/>",
-    " <?xml version=\"1.0\"?><root/>",
-    "\t<?xml version=\"1.0\"?><root/>",
-    "\r\n<?xml version=\"1.0\"?><root/>",
-    "\r<?xml version=\"1.0\"?><root/>",
-    0
-};
-
 static const char default_ns_doc[] = {
     "<?xml version=\"1.0\"?>"
     "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
@@ -1834,7 +1828,7 @@ static void* _create_object(const GUID *clsid, const char *name, const IID *iid,
 
 #define _create(cls) cls, #cls
 
-#define create_document(iid) _create_object(&_create(CLSID_DOMDocument), iid, __LINE__)
+#define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
 #define create_cache_version(v, iid) _create_object(&_create(CLSID_XMLSchemaCache ## v), iid, __LINE__)
@@ -2012,6 +2006,38 @@ static char *list_to_string(IXMLDOMNodeList *list)
 #define expect_node(node, expstr) { char str[4096]; node_to_string(node, str); ok(strcmp(str, expstr)==0, "Invalid node: %s, expected %s\n", str, expstr); }
 #define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, expected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
 
+struct docload_ret_t {
+    VARIANT_BOOL b;
+    HRESULT hr;
+};
+
+struct leading_spaces_t {
+    const CLSID *clsid;
+    const char *name;
+    struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
+};
+
+static const struct leading_spaces_t leading_spaces_classdata[] = {
+    { &CLSID_DOMDocument,   "CLSID_DOMDocument",   {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
+    { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
+    { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
+    { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
+    { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
+    { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
+    { NULL }
+};
+
+static const char* leading_spaces_xmldata[] = {
+    "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
+    " <?xml version=\"1.0\"?><root/>",
+    "\n<?xml version=\"1.0\"?><root/>",
+    "\t<?xml version=\"1.0\"?><root/>",
+    "\r\n<?xml version=\"1.0\"?><root/>",
+    "\r<?xml version=\"1.0\"?><root/>",
+    "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
+    0
+};
+
 static void test_domdoc( void )
 {
     HRESULT r, hr;
@@ -2024,13 +2050,59 @@ static void test_domdoc( void )
     IXMLDOMAttribute *node_attr = NULL;
     IXMLDOMNode *nodeChild = NULL;
     IXMLDOMProcessingInstruction *nodePI = NULL;
+    const struct leading_spaces_t *class_ptr;
+    const char **data_ptr;
     VARIANT_BOOL b;
     VARIANT var;
     BSTR str;
     LONG code, ref;
     LONG nLength = 0;
     WCHAR buff[100];
-    const char **ptr;
+    int index;
+
+    /* Load document with leading spaces
+     *
+     * Test all CLSIDs with all test data XML strings
+     */
+    class_ptr = leading_spaces_classdata;
+    index = 0;
+    while (class_ptr->clsid)
+    {
+        HRESULT hr;
+        int i;
+
+        hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
+             &IID_IXMLDOMDocument, (void**)&doc);
+        if (hr != S_OK) {
+            win_skip("%d: failed to create class instance for %s\n", index, class_ptr->name);
+            class_ptr++;
+            index++;
+            continue;
+        }
+
+        data_ptr = leading_spaces_xmldata;
+        i = 0;
+        while (*data_ptr) {
+            BSTR data = _bstr_(*data_ptr);
+
+            b = 0xc;
+            V_VT(&var) = VT_BSTR;
+            V_BSTR(&var) = data;
+            hr = IXMLDOMDocument_load(doc, var, &b);
+            EXPECT_HR(hr, class_ptr->ret[0].hr);
+            ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
+
+            b = 0xc;
+            hr = IXMLDOMDocument_loadXML(doc, data, &b);
+            EXPECT_HR(hr, class_ptr->ret[1].hr);
+            ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
+
+            data_ptr++;
+            i++;
+        }
+        class_ptr++;
+        index++;
+    }
 
     doc = create_document(&IID_IXMLDOMDocument);
     if (!doc) return;
@@ -2050,19 +2122,6 @@ if (0)
     EXPECT_HR(hr, S_FALSE);
     ok( b == VARIANT_FALSE, "failed to load XML string\n");
 
-    /* load document with leading spaces */
-    ptr = leading_spaces;
-    while (*ptr)
-    {
-        b = VARIANT_TRUE;
-        V_VT(&var) = VT_BSTR;
-        V_BSTR(&var) = _bstr_(*ptr);
-        hr = IXMLDOMDocument_load( doc, var, &b);
-        EXPECT_HR(hr, S_FALSE);
-        ok( b == VARIANT_FALSE, "got %x\n", b);
-        ptr++;
-    }
-
     /* try to load a document from a nonexistent file */
     b = VARIANT_TRUE;
     str = SysAllocString( nonexistent_fileW );
-- 
1.5.6.5


