diff --git a/dlls/msxml3/tests/schema.c b/dlls/msxml3/tests/schema.c
index d1622ffc7da..f4bff68aaeb 100644
--- a/dlls/msxml3/tests/schema.c
+++ b/dlls/msxml3/tests/schema.c
@@ -1012,6 +1012,180 @@ static void test_collection_content(void)
free_bstrs();
}
+static HRESULT validate_regex(const WCHAR *regex, const WCHAR *input)
+{
+ static const WCHAR regex_doc[] =
+L""
+""
+"%s";
+
+ static const WCHAR regex_schema[] =
+L""
+""
+" "
+" "
+" "
+" "
+" "
+" "
+" "
+"";
+
+ IXMLDOMDocument2 *doc;
+ IXMLDOMDocument2 *schema;
+ IXMLDOMSchemaCollection *cache;
+ IXMLDOMParseError* err;
+ WCHAR buffer[1024];
+ BSTR namespace;
+ BSTR bstr;
+ VARIANT v;
+ VARIANT_BOOL b;
+ HRESULT hr;
+
+ doc = create_document_version(60, &IID_IXMLDOMDocument2);
+ ok(doc != NULL, "Failed to create a document.\n");
+
+ schema = create_document_version(60, &IID_IXMLDOMDocument2);
+ ok(schema != NULL, "Failed to create a document.\n");
+
+ cache = create_cache_version(60, &IID_IXMLDOMSchemaCollection);
+ ok(cache != NULL, "Failed to create schema collection.\n");
+
+ if (!doc || !schema || !cache)
+ {
+ if (doc)
+ IXMLDOMDocument2_Release(doc);
+ if (schema)
+ IXMLDOMDocument2_Release(schema);
+ if (cache)
+ IXMLDOMSchemaCollection_Release(cache);
+ return E_OUTOFMEMORY;
+ }
+
+ VariantInit(&v);
+
+ swprintf(buffer, ARRAY_SIZE(buffer), regex_doc, input);
+ bstr = SysAllocString(buffer);
+ ole_check(IXMLDOMDocument2_loadXML(doc, bstr, &b));
+ ok(b == VARIANT_TRUE, "failed to load XML\n");
+ SysFreeString(bstr);
+
+ swprintf(buffer, ARRAY_SIZE(buffer), regex_schema, regex);
+ bstr = SysAllocString(buffer);
+ ole_check(IXMLDOMDocument2_loadXML(schema, bstr, &b));
+ ok(b == VARIANT_TRUE, "failed to load XML\n");
+ SysFreeString(bstr);
+
+ /* add the schema to the cache */
+ V_VT(&v) = VT_DISPATCH;
+ 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");
+ namespace = alloc_str_from_narrow("urn:test");
+ hr = IXMLDOMSchemaCollection_add(cache, namespace, v);
+ SysFreeString(namespace);
+ VariantClear(&v);
+ if (FAILED(hr))
+ goto end;
+
+ /* associate the cache to the doc */
+ V_VT(&v) = VT_DISPATCH;
+ V_DISPATCH(&v) = NULL;
+ ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
+ ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
+ ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
+ VariantClear(&v);
+
+ /* validate the doc
+ * only declared elements in the declared order
+ * this is fine */
+ err = NULL;
+ bstr = NULL;
+ hr = IXMLDOMDocument2_validate(doc, &err);
+ ok(err != NULL, "domdoc_validate() should always set err\n");
+ if (IXMLDOMParseError_get_reason(err, &bstr) != S_FALSE)
+ trace("got error: %s\n", wine_dbgstr_w(bstr));
+ SysFreeString(bstr);
+ IXMLDOMParseError_Release(err);
+
+end:
+ IXMLDOMDocument2_Release(doc);
+ IXMLDOMDocument2_Release(schema);
+ IXMLDOMSchemaCollection_Release(cache);
+
+ return hr;
+}
+
+static void test_nonstandard_regex(void)
+{
+ HRESULT hr;
+
+ hr = validate_regex(L"\\!", L"!");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\\"", L"\"");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\#", L"#");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"$", L"$");
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = validate_regex(L"\\$", L"$");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\%", L"%");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\,", L",");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"/", L"/");
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = validate_regex(L"\\/", L"/");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\:", L":");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\;", L";");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\=", L"=");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\>", L">");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\@", L"@");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\`", L"`");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\~", L"~");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = validate_regex(L"\\uCAFE", L"\xCAFE");
+todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+}
+
static void test_XDR_schemas(void)
{
IXMLDOMDocument2 *doc, *schema;
@@ -1669,6 +1843,7 @@ START_TEST(schema)
test_collection_refs();
test_length();
test_collection_content();
+ test_nonstandard_regex();
test_XDR_schemas();
test_XDR_datatypes();
test_validate_on_load();