diff --git a/modules/rostests/winetests/CMakeLists.txt b/modules/rostests/winetests/CMakeLists.txt index 17537d206e3..9b07246507e 100644 --- a/modules/rostests/winetests/CMakeLists.txt +++ b/modules/rostests/winetests/CMakeLists.txt @@ -76,6 +76,7 @@ add_subdirectory(msvcrt) add_subdirectory(msvcrtd) add_subdirectory(msvfw32) add_subdirectory(msxml3) +add_subdirectory(msxml4) add_subdirectory(netapi32) add_subdirectory(netcfgx) add_subdirectory(ntdll) diff --git a/modules/rostests/winetests/msxml4/CMakeLists.txt b/modules/rostests/winetests/msxml4/CMakeLists.txt new file mode 100644 index 00000000000..cf4883b3bb7 --- /dev/null +++ b/modules/rostests/winetests/msxml4/CMakeLists.txt @@ -0,0 +1,25 @@ + +remove_definitions(-D_CRT_NON_CONFORMING_SWPRINTFS) + +add_definitions(-DUSE_WINE_TODOS) + +list(APPEND SOURCE + domdoc.c + schema.c) + +list(APPEND PCH_SKIP_SOURCE + guid.c + testlist.c) + +add_executable(msxml4_winetest + ${SOURCE} + ${PCH_SKIP_SOURCE}) + +set_module_type(msxml4_winetest win32cui) +add_importlibs(msxml4_winetest ole32 oleaut32 msvcrt kernel32) + +if(MSVC) + add_importlibs(msxml4_winetest ntdll) +endif() + +add_rostests_file(TARGET msxml4_winetest) diff --git a/modules/rostests/winetests/msxml4/domdoc.c b/modules/rostests/winetests/msxml4/domdoc.c new file mode 100644 index 00000000000..1a3a663d359 --- /dev/null +++ b/modules/rostests/winetests/msxml4/domdoc.c @@ -0,0 +1,344 @@ +/* + * XML test + * + * Copyright 2005 Mike McCormack for CodeWeavers + * Copyright 2007-2008 Alistair Leslie-Hughes + * Copyright 2010-2011 Adam Martinson for CodeWeavers + * Copyright 2010-2013 Nikolay Sivov for CodeWeavers + * Copyright 2023 Daniel Lehman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + + +#define COBJMACROS +#define CONST_VTABLE + +#include +#include + +#include "windows.h" + +#include "initguid.h" +#include "msxml2.h" + +#include "wine/test.h" + +static BSTR alloced_bstrs[256]; +static int alloced_bstrs_count; + +static BSTR _bstr_(const WCHAR *str) +{ + assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs)); + alloced_bstrs[alloced_bstrs_count] = SysAllocString(str); + return alloced_bstrs[alloced_bstrs_count++]; +} + +static void free_bstrs(void) +{ + int i; + for (i = 0; i < alloced_bstrs_count; i++) + SysFreeString(alloced_bstrs[i]); + alloced_bstrs_count = 0; +} + +struct attrtest_t { + const WCHAR *name; + const WCHAR *uri; + const WCHAR *prefix; + const WCHAR *href; +}; + +static struct attrtest_t attrtests[] = { + { L"xmlns", L"http://www.w3.org/2000/xmlns/", L"xmlns", L"xmlns" }, + { L"xmlns", L"nondefaulturi", L"xmlns", L"xmlns" }, + { L"c", L"http://www.w3.org/2000/xmlns/", NULL, L"http://www.w3.org/2000/xmlns/" }, + { L"c", L"nsref1", NULL, L"nsref1" }, + { L"ns:c", L"nsref1", L"ns", L"nsref1" }, + { L"xmlns:c", L"http://www.w3.org/2000/xmlns/", L"xmlns", L"" }, + { L"xmlns:c", L"nondefaulturi", L"xmlns", L"" }, + { 0 } +}; + +/* see dlls/msxml[36]/tests/domdoc.c */ +static void test_create_attribute(void) +{ + struct attrtest_t *ptr = attrtests; + IXMLDOMElement *el; + IXMLDOMDocument2 *doc; + IXMLDOMNode *node; + VARIANT var; + HRESULT hr; + int i = 0; + BSTR str; + + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); + ok(hr == S_OK, "Failed to create DOMDocument40, hr %#lx.\n", hr); + + while (ptr->name) + { + V_VT(&var) = VT_I1; + V_I1(&var) = NODE_ATTRIBUTE; + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + str = NULL; + hr = IXMLDOMNode_get_prefix(node, &str); + if (ptr->prefix) + { + /* MSXML4 can report different results with different service packs */ + ok(hr == S_OK || broken(hr == S_FALSE), "Failed to get prefix, hr %#lx.\n", hr); + ok(!lstrcmpW(str, _bstr_(ptr->prefix)) || broken(!str), "got %s\n", wine_dbgstr_w(str)); + } + else + { + ok(hr == S_FALSE, "%d: unexpected hr %#lx\n", i, hr); + ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str)); + } + SysFreeString(str); + + str = NULL; + hr = IXMLDOMNode_get_namespaceURI(node, &str); + ok(hr == S_OK, "%d: unexpected hr %#lx\n", i, hr); + ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", + i, wine_dbgstr_w(str), wine_dbgstr_w(ptr->href)); + SysFreeString(str); + + IXMLDOMNode_Release(node); + free_bstrs(); + + i++; + ptr++; + } + + V_VT(&var) = VT_I1; + V_I1(&var) = NODE_ELEMENT; + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(L"e"), NULL, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&el); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IXMLDOMNode_Release(node); + + V_VT(&var) = VT_I1; + V_I1(&var) = NODE_ATTRIBUTE; + hr = IXMLDOMDocument2_createNode(doc, var, _bstr_(L"xmlns:a"), + _bstr_(L"http://www.w3.org/2000/xmlns/"), &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + /* for some reason default namespace uri is not reported */ + hr = IXMLDOMNode_get_namespaceURI(node, &str); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(str, L""), "got uri %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IXMLDOMNode_Release(node); + IXMLDOMElement_Release(el); + IXMLDOMDocument2_Release(doc); + free_bstrs(); +} + +/* see dlls/msxml[36]/tests/domdoc.c */ +static void test_namespaces_as_attributes(void) +{ + struct test + { + const WCHAR *xml; + int explen; + const WCHAR *names[3]; + const WCHAR *prefixes[3]; + const WCHAR *basenames[3]; + const WCHAR *uris[3]; + const WCHAR *texts[3]; + const WCHAR *xmls[3]; + }; + static const struct test tests[] = + { + { + L"", 3, + { L"ns:b", L"d", L"xmlns:ns" }, /* nodeName */ + { L"ns", NULL, L"xmlns" }, /* prefix */ + { L"b", L"d", L"ns" }, /* baseName */ + { L"nshref", NULL, L"" }, /* namespaceURI */ + { L"b attr", L"d attr", L"nshref" }, /* text */ + { L"ns:b=\"b attr\"", L"d=\"d attr\"", L"xmlns:ns=\"nshref\"" }, /* xml */ + }, + /* property only */ + { + L"", 1, + { L"d" }, /* nodeName */ + { NULL }, /* prefix */ + { L"d" }, /* baseName */ + { NULL }, /* namespaceURI */ + { L"d attr" }, /* text */ + { L"d=\"d attr\"" }, /* xml */ + }, + /* namespace only */ + { + L"", 1, + { L"xmlns:ns" }, /* nodeName */ + { L"xmlns" }, /* prefix */ + { L"ns" }, /* baseName */ + { L"" }, /* namespaceURI */ + { L"nshref" }, /* text */ + { L"xmlns:ns=\"nshref\"" }, /* xml */ + }, + /* default namespace */ + { + L"", 1, + { L"xmlns" }, /* nodeName */ + { L"xmlns" }, /* prefix */ + { L"" }, /* baseName */ + { L"" }, /* namespaceURI */ + { L"nshref" }, /* text */ + { L"xmlns=\"nshref\"" }, /* xml */ + }, + /* no properties or namespaces */ + { + L"", 0, + }, + + { NULL } + }; + const struct test *test; + IXMLDOMNamedNodeMap *map; + IXMLDOMNode *node, *item; + IXMLDOMDocument2 *doc; + VARIANT_BOOL b; + LONG len, i; + HRESULT hr; + BSTR str; + + test = tests; + while (test->xml) + { + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(test->xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + node = NULL; + hr = IXMLDOMDocument2_get_firstChild(doc, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMNode_get_attributes(node, &map); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + len = -1; + hr = IXMLDOMNamedNodeMap_get_length(map, &len); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(len == test->explen, "got %ld\n", len); + + item = NULL; + hr = IXMLDOMNamedNodeMap_get_item(map, test->explen+1, &item); + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); + ok(!item, "Item should be NULL\n"); + + for (i = 0; i < len; i++) + { + item = NULL; + hr = IXMLDOMNamedNodeMap_get_item(map, i, &item); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + str = NULL; + hr = IXMLDOMNode_get_nodeName(item, &str); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(str, test->names[i]), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = NULL; + hr = IXMLDOMNode_get_prefix(item, &str); + if (test->prefixes[i]) + { + /* MSXML4 can report different results with different service packs */ + ok(hr == S_OK || broken(hr == S_FALSE), "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(str, test->prefixes[i]) || broken(!str), + "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + } + else + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr ); + + str = NULL; + hr = IXMLDOMNode_get_baseName(item, &str); + /* MSXML4 can report different results with different service packs */ + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(str, test->basenames[i]) || broken(!lstrcmpW(str, L"xmlns")), + "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = NULL; + hr = IXMLDOMNode_get_namespaceURI(item, &str); + if (test->uris[i]) + { + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (test->prefixes[i] && !lstrcmpW(test->prefixes[i], L"xmlns")) + ok(!lstrcmpW(str, L""), "got %s\n", wine_dbgstr_w(str)); + else + ok(!lstrcmpW(str, test->uris[i]), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + } + else + ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr ); + + str = NULL; + hr = IXMLDOMNode_get_text(item, &str); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(str, test->texts[i]), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + str = NULL; + hr = IXMLDOMNode_get_xml(item, &str); + ok(SUCCEEDED(hr), "Failed to get node xml, hr %#lx.\n", hr); + ok(!lstrcmpW(str, test->xmls[i]), "got %s\n", wine_dbgstr_w(str)); + SysFreeString(str); + + IXMLDOMNode_Release(item); + } + + IXMLDOMNamedNodeMap_Release(map); + IXMLDOMNode_Release(node); + IXMLDOMDocument2_Release(doc); + + test++; + } + free_bstrs(); +} + +START_TEST(domdoc) +{ + HRESULT hr; + IXMLDOMDocument2 *doc; + + hr = CoInitialize(NULL); + ok(hr == S_OK, "failed to init com\n"); + + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc); + if (hr != S_OK) + { + win_skip("class &CLSID_DOMDocument40 not supported\n"); + return; + } + IXMLDOMDocument2_Release(doc); + + test_namespaces_as_attributes(); + test_create_attribute(); + + CoUninitialize(); +} diff --git a/modules/rostests/winetests/msxml4/guid.c b/modules/rostests/winetests/msxml4/guid.c new file mode 100644 index 00000000000..a66c206038d --- /dev/null +++ b/modules/rostests/winetests/msxml4/guid.c @@ -0,0 +1,11 @@ +/* DO NOT USE THE PRECOMPILED HEADER FOR THIS FILE! */ + +#define WIN32_NO_STATUS +#define _INC_WINDOWS + +#include +#include +#include +#include + +/* NO CODE HERE, THIS IS JUST REQUIRED FOR THE GUID DEFINITIONS */ diff --git a/modules/rostests/winetests/msxml4/schema.c b/modules/rostests/winetests/msxml4/schema.c new file mode 100644 index 00000000000..fad36cca4d9 --- /dev/null +++ b/modules/rostests/winetests/msxml4/schema.c @@ -0,0 +1,490 @@ +/* + * Schema test + * + * Copyright 2007 Huw Davies + * Copyright 2010 Adam Martinson for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#define COBJMACROS + +#include "ole2.h" +#include "msxml2.h" + +#include "wine/test.h" + +static const WCHAR xsd_schema1_uri[] = L"x-schema:test1.xsd"; +static const WCHAR xsd_schema1_xml[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +""; + +static const WCHAR xsd_schema2_uri[] = L"x-schema:test2.xsd"; +static const WCHAR xsd_schema2_xml[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +""; + +static const WCHAR xsd_schema3_uri[] = L"x-schema:test3.xsd"; +static const WCHAR xsd_schema3_xml[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +""; + +static const WCHAR xdr_schema1_uri[] = L"x-schema:test1.xdr"; +static const WCHAR xdr_schema1_xml[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +static const WCHAR xdr_schema2_uri[] = L"x-schema:test2.xdr"; +static const WCHAR xdr_schema2_xml[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +" " +""; + +static BSTR alloced_bstrs[256]; +static int alloced_bstrs_count; + +static BSTR _bstr_(const WCHAR *str) +{ + assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs)); + alloced_bstrs[alloced_bstrs_count] = SysAllocString(str); + return alloced_bstrs[alloced_bstrs_count++]; +} + +static void free_bstrs(void) +{ + int i; + for (i = 0; i < alloced_bstrs_count; i++) + SysFreeString(alloced_bstrs[i]); + alloced_bstrs_count = 0; +} + +static VARIANT _variantdoc_(void* doc) +{ + VARIANT v; + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)doc; + return v; +} + +static IXMLDOMDocument2 *create_document(void) +{ + IXMLDOMDocument2 *obj = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&obj); + ok(hr == S_OK, "Failed to create a document object, hr %#lx.\n", hr); + + return obj; +} + +static void *create_cache(REFIID riid) +{ + void *obj = NULL; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_XMLSchemaCache40, NULL, CLSCTX_INPROC_SERVER, riid, &obj); + ok(hr == S_OK, "Failed to create a document object, hr %#lx.\n", hr); + + return obj; +} + +static HRESULT validate_regex_document(IXMLDOMDocument2 *doc, IXMLDOMDocument2 *schema, IXMLDOMSchemaCollection* cache, + const WCHAR *regex, const WCHAR *input) +{ + static const WCHAR regex_doc[] = +L"" +"" +"%s"; + + static const WCHAR regex_schema[] = +L"" +"" +" " +" " +" " +" " +" " +" " +" " +""; + + WCHAR buffer[1024]; + IXMLDOMParseError* err; + BSTR namespace, bstr; + VARIANT_BOOL b; + HRESULT hr; + VARIANT v; + + VariantInit(&v); + + swprintf(buffer, ARRAY_SIZE(buffer), regex_doc, input); + bstr = SysAllocString(buffer); + hr = IXMLDOMDocument2_loadXML(doc, bstr, &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + SysFreeString(bstr); + + swprintf(buffer, ARRAY_SIZE(buffer), regex_schema, regex); + bstr = SysAllocString(buffer); + hr = IXMLDOMDocument2_loadXML(schema, bstr, &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + 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; + hr = IXMLDOMDocument2_QueryInterface(schema, &IID_IDispatch, (void**)&V_DISPATCH(&v)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n"); + namespace = SysAllocString(L"urn:test"); + hr = IXMLDOMSchemaCollection_add(cache, namespace, v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + SysFreeString(namespace); + VariantClear(&v); +/* + if (FAILED(hr)) + return hr; +*/ + /* associate the cache to the doc */ + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = NULL; + hr = IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n"); + hr = IXMLDOMDocument2_putref_schemas(doc, v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + 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); + + return hr; +} + +static void test_regex(void) +{ + static const struct regex_test + { + const WCHAR *regex; + const WCHAR *input; + } + tests[] = + { + { L"\\!", L"!" }, + { L"\\\"", L"\"" }, + { L"\\#", L"#" }, + { L"\\$", L"$" }, + { L"\\%", L"%" }, + { L"\\,", L"," }, + { L"\\/", L"/" }, + { L"\\:", L":" }, + { L"\\;", L";" }, + { L"\\=", L"=" }, + { L"\\>", L">" }, + { L"\\@", L"@" }, + { L"\\`", L"`" }, + { L"\\~", L"~" }, + { L"\\uCAFE", L"\xCAFE" }, + /* non-BMP character in surrogate pairs: */ + { L"\\uD83D\\uDE00", L"\xD83D\xDE00" }, + /* "x{,2}" is non-standard and only works on libxml2 <= v2.9.10 */ + { L"x{0,2}", L"x" } + }; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + const struct regex_test *test = &tests[i]; + IXMLDOMDocument2 *doc, *schema; + IXMLDOMSchemaCollection *cache; + HRESULT hr; + + winetest_push_context("Test %s", wine_dbgstr_w(test->regex)); + + doc = create_document(); + schema = create_document(); + cache = create_cache(&IID_IXMLDOMSchemaCollection); + + hr = validate_regex_document(doc, schema, cache, tests->regex, tests->input); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + if (doc) + IXMLDOMDocument2_Release(doc); + if (schema) + IXMLDOMDocument2_Release(schema); + if (cache) + IXMLDOMSchemaCollection_Release(cache); + + winetest_pop_context(); + } +} + +static void test_get(void) +{ + IXMLDOMSchemaCollection2 *cache; + IXMLDOMNode *node; + HRESULT hr; + + cache = create_cache(&IID_IXMLDOMSchemaCollection2); + + hr = IXMLDOMSchemaCollection2_get(cache, NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMSchemaCollection2_get(cache, _bstr_(L"uri"), &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IXMLDOMSchemaCollection2_Release(cache); + free_bstrs(); +} + +static void test_remove(void) +{ + IXMLDOMSchemaCollection2 *cache; + IXMLDOMDocument2 *doc; + VARIANT_BOOL b; + HRESULT hr; + VARIANT v; + LONG len; + + /* ::remove() works for version 4 */ + cache = create_cache(&IID_IXMLDOMSchemaCollection2); + + doc = create_document(); + ok(doc != NULL, "got %p\n", doc); + + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(xsd_schema1_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + V_VT(&v) = VT_DISPATCH; + V_DISPATCH(&v) = (IDispatch*)doc; + hr = IXMLDOMSchemaCollection2_add(cache, _bstr_(xsd_schema1_uri), v); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + len = -1; + hr = IXMLDOMSchemaCollection2_get_length(cache, &len); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(len == 1, "Unexpected length %ld.\n", len); + + hr = IXMLDOMSchemaCollection2_remove(cache, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_(L"invaliduri")); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + len = -1; + hr = IXMLDOMSchemaCollection2_get_length(cache, &len); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(len == 1, "Unexpected length %ld.\n", len); + + hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_(xsd_schema1_uri)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + len = -1; + hr = IXMLDOMSchemaCollection2_get_length(cache, &len); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(len == 0, "Unexpected length %ld.\n", len); + + IXMLDOMDocument2_Release(doc); + IXMLDOMSchemaCollection2_Release(cache); + + free_bstrs(); +} + +static void test_validate_on_load(void) +{ + IXMLDOMSchemaCollection2 *cache; + VARIANT_BOOL b; + HRESULT hr; + + cache = create_cache(&IID_IXMLDOMSchemaCollection2); + + hr = IXMLDOMSchemaCollection2_get_validateOnLoad(cache, NULL); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + b = VARIANT_FALSE; + hr = IXMLDOMSchemaCollection2_get_validateOnLoad(cache, &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "got %d\n", b); + + IXMLDOMSchemaCollection2_Release(cache); +} + +static void test_collection_content(void) +{ + IXMLDOMDocument2 *schema1, *schema2, *schema3, *schema4, *schema5; + IXMLDOMSchemaCollection *cache; + BSTR content[5] = { 0 }; + VARIANT_BOOL b; + LONG length; + HRESULT hr; + BSTR bstr; + int i, j; + + schema1 = create_document(); + schema2 = create_document(); + schema3 = create_document(); + schema4 = create_document(); + schema5 = create_document(); + cache = create_cache(&IID_IXMLDOMSchemaCollection); + + hr = IXMLDOMDocument2_loadXML(schema1, _bstr_(xdr_schema1_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + hr = IXMLDOMDocument2_loadXML(schema2, _bstr_(xdr_schema2_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + hr = IXMLDOMDocument2_loadXML(schema3, _bstr_(xsd_schema1_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + hr = IXMLDOMDocument2_loadXML(schema4, _bstr_(xsd_schema2_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + hr = IXMLDOMDocument2_loadXML(schema5, _bstr_(xsd_schema3_xml), &b); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(b == VARIANT_TRUE, "failed to load XML\n"); + + /* combining XDR and XSD schemas in the same cache is fine */ + hr = IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXMLDOMSchemaCollection_add(cache, _bstr_(xsd_schema1_uri), _variantdoc_(schema3)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXMLDOMSchemaCollection_add(cache, _bstr_(xsd_schema2_uri), _variantdoc_(schema4)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IXMLDOMSchemaCollection_add(cache, _bstr_(xsd_schema3_uri), _variantdoc_(schema5)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + length = -1; + hr = IXMLDOMSchemaCollection_get_length(cache, &length); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(length == 5, "Unexpected length %ld.\n", length); + + for (i = 0; i < 5; ++i) + { + bstr = NULL; + hr = IXMLDOMSchemaCollection_get_namespaceURI(cache, i, &bstr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(bstr != NULL && *bstr, "expected non-empty string\n"); + + for (j = 0; j < i; ++j) + ok(wcscmp(content[j], bstr), "got duplicate entry\n"); + content[i] = bstr; + } + + for (i = 0; i < 5; ++i) + { + SysFreeString(content[i]); + content[i] = NULL; + } + + IXMLDOMDocument2_Release(schema1); + IXMLDOMDocument2_Release(schema2); + IXMLDOMDocument2_Release(schema3); + IXMLDOMDocument2_Release(schema4); + IXMLDOMDocument2_Release(schema5); + + IXMLDOMSchemaCollection_Release(cache); + free_bstrs(); +} + +START_TEST(schema) +{ + IUnknown *obj; + HRESULT hr; + + hr = CoInitialize(NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = CoCreateInstance(&CLSID_DOMDocument40, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&obj); + if (FAILED(hr)) + { + win_skip("DOMDocument40 is not supported.\n"); + CoUninitialize(); + return; + } + IUnknown_Release(obj); + + test_regex(); + test_get(); + test_remove(); + test_validate_on_load(); + test_collection_content(); + + CoUninitialize(); +} diff --git a/modules/rostests/winetests/msxml4/testlist.c b/modules/rostests/winetests/msxml4/testlist.c new file mode 100644 index 00000000000..95e8d3bdca5 --- /dev/null +++ b/modules/rostests/winetests/msxml4/testlist.c @@ -0,0 +1,14 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define STANDALONE +#include + +extern void func_domdoc(void); +extern void func_schema(void); + +const struct test winetest_testlist[] = +{ + { "domdoc", func_domdoc }, + { "schema", func_schema }, + { 0, 0 } +};