1 /*
2  * Schema test
3  *
4  * Copyright 2007 Huw Davies
5  * Copyright 2010 Adam Martinson for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #include "precomp.h"
23 
24 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
25 
26 #define EXPECT_HR(hr,hr_exp) \
27     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
28 
29 static const WCHAR xdr_schema_uri[] = {'x','-','s','c','h','e','m','a',':','t','e','s','t','.','x','m','l',0};
30 
31 static const WCHAR xdr_schema_xml[] = {
32     '<','S','c','h','e','m','a',' ','x','m','l','n','s','=','\"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','x','m','l','-','d','a','t','a','\"','\n',
33     'x','m','l','n','s',':','d','t','=','\"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','d','a','t','a','t','y','p','e','s','\"','>','\n',
34     '<','/','S','c','h','e','m','a','>','\n',0
35 };
36 
37 static const CHAR xdr_schema1_uri[] = "x-schema:test1.xdr";
38 static const CHAR xdr_schema1_xml[] =
39 "<?xml version='1.0'?>"
40 "<Schema xmlns='urn:schemas-microsoft-com:xml-data'"
41 "        xmlns:dt='urn:schemas-microsoft-com:datatypes'"
42 "        name='test1.xdr'>"
43 "   <ElementType name='x' dt:type='boolean'/>"
44 "   <ElementType name='y'>"
45 "       <datatype dt:type='int'/>"
46 "   </ElementType>"
47 "   <ElementType name='z'/>"
48 "   <ElementType name='root' content='eltOnly' model='open' order='seq'>"
49 "       <element type='x'/>"
50 "       <element type='y'/>"
51 "       <element type='z'/>"
52 "   </ElementType>"
53 "</Schema>";
54 
55 static const CHAR xdr_schema2_uri[] = "x-schema:test2.xdr";
56 static const CHAR xdr_schema2_xml[] =
57 "<?xml version='1.0'?>"
58 "<Schema xmlns='urn:schemas-microsoft-com:xml-data'"
59 "        xmlns:dt='urn:schemas-microsoft-com:datatypes'"
60 "        name='test2.xdr'>"
61 "   <ElementType name='x' dt:type='bin.base64'/>"
62 "   <ElementType name='y' dt:type='uuid'/>"
63 "   <ElementType name='z'/>"
64 "   <ElementType name='root' content='eltOnly' model='closed' order='one'>"
65 "       <element type='x'/>"
66 "       <element type='y'/>"
67 "       <element type='z'/>"
68 "   </ElementType>"
69 "</Schema>";
70 
71 static const CHAR xdr_schema3_uri[] = "x-schema:test3.xdr";
72 static const CHAR xdr_schema3_xml[] =
73 "<?xml version='1.0'?>"
74 "<Schema xmlns='urn:schemas-microsoft-com:xml-data'"
75 "        xmlns:dt='urn:schemas-microsoft-com:datatypes'"
76 "        name='test3.xdr'>"
77 "   <ElementType name='root' content='textOnly' model='open'>"
78 "       <AttributeType name='x' dt:type='int'/>"
79 "       <AttributeType name='y' dt:type='enumeration' dt:values='a b c'/>"
80 "       <AttributeType name='z' dt:type='uuid'/>"
81 "       <attribute type='x'/>"
82 "       <attribute type='y'/>"
83 "       <attribute type='z'/>"
84 "   </ElementType>"
85 "</Schema>";
86 
87 static const CHAR xsd_schema1_uri[] = "x-schema:test1.xsd";
88 static const CHAR xsd_schema1_xml[] =
89 "<?xml version='1.0'?>"
90 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
91 "            targetNamespace='x-schema:test1.xsd'>"
92 "   <element name='root'>"
93 "       <complexType>"
94 "           <sequence maxOccurs='unbounded'>"
95 "               <any/>"
96 "           </sequence>"
97 "       </complexType>"
98 "   </element>"
99 "</schema>";
100 
101 static const CHAR xsd_schema2_uri[] = "x-schema:test2.xsd";
102 static const CHAR xsd_schema2_xml[] =
103 "<?xml version='1.0'?>"
104 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
105 "            targetNamespace='x-schema:test2.xsd'>"
106 "   <element name='root'>"
107 "       <complexType>"
108 "           <sequence maxOccurs='unbounded'>"
109 "               <any/>"
110 "           </sequence>"
111 "       </complexType>"
112 "   </element>"
113 "</schema>";
114 
115 static const CHAR xsd_schema3_uri[] = "x-schema:test3.xsd";
116 static const CHAR xsd_schema3_xml[] =
117 "<?xml version='1.0'?>"
118 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
119 "            targetNamespace='x-schema:test3.xsd'>"
120 "   <element name='root'>"
121 "       <complexType>"
122 "           <sequence maxOccurs='unbounded'>"
123 "               <any/>"
124 "           </sequence>"
125 "       </complexType>"
126 "   </element>"
127 "</schema>";
128 
129 static const CHAR szDatatypeXDR[] =
130 "<Schema xmlns='urn:schemas-microsoft-com:xml-data'\n"
131 "        xmlns:dt='urn:schemas-microsoft-com:datatypes'>\n"
132 "   <ElementType name='base64Data' content='textOnly' dt:type='bin.base64'/>\n"
133 "   <ElementType name='hexData' content='textOnly' dt:type='bin.hex'/>\n"
134 "   <ElementType name='boolData' content='textOnly' dt:type='boolean'/>\n"
135 "   <ElementType name='charData' content='textOnly' dt:type='char'/>\n"
136 "   <ElementType name='dateData' content='textOnly' dt:type='date'/>\n"
137 "   <ElementType name='dateTimeData' content='textOnly' dt:type='dateTime'/>\n"
138 "   <ElementType name='dateTimeTzData' content='textOnly' dt:type='dateTime.tz'/>\n"
139 "   <ElementType name='entityData' content='textOnly' dt:type='entity'/>\n"
140 "   <ElementType name='entitiesData' content='textOnly' dt:type='entities'/>\n"
141 "   <ElementType name='fixedData' content='textOnly' dt:type='fixed.14.4'/>\n"
142 "   <ElementType name='floatData' content='textOnly' dt:type='float'/>\n"
143 "   <ElementType name='i1Data' content='textOnly' dt:type='i1'/>\n"
144 "   <ElementType name='i2Data' content='textOnly' dt:type='i2'/>\n"
145 "   <ElementType name='i4Data' content='textOnly' dt:type='i4'/>\n"
146 "   <ElementType name='i8Data' content='textOnly' dt:type='i8'/>\n"
147 "   <ElementType name='intData' content='textOnly' dt:type='int'/>\n"
148 "   <ElementType name='nmtokData' content='textOnly' dt:type='nmtoken'/>\n"
149 "   <ElementType name='nmtoksData' content='textOnly' dt:type='nmtokens'/>\n"
150 "   <ElementType name='numData' content='textOnly' dt:type='number'/>\n"
151 "   <ElementType name='r4Data' content='textOnly' dt:type='r4'/>\n"
152 "   <ElementType name='r8Data' content='textOnly' dt:type='r8'/>\n"
153 "   <ElementType name='stringData' content='textOnly' dt:type='string'/>\n"
154 "   <ElementType name='timeData' content='textOnly' dt:type='time'/>\n"
155 "   <ElementType name='timeTzData' content='textOnly' dt:type='time.tz'/>\n"
156 "   <ElementType name='u1Data' content='textOnly' dt:type='ui1'/>\n"
157 "   <ElementType name='u2Data' content='textOnly' dt:type='ui2'/>\n"
158 "   <ElementType name='u4Data' content='textOnly' dt:type='ui4'/>\n"
159 "   <ElementType name='u8Data' content='textOnly' dt:type='ui8'/>\n"
160 "   <ElementType name='uriData' content='textOnly' dt:type='uri'/>\n"
161 "   <ElementType name='uuidData' content='textOnly' dt:type='uuid'/>\n"
162 "\n"
163 "   <ElementType name='Name' content='textOnly' dt:type='nmtoken'/>\n"
164 "   <ElementType name='Value' content='eltOnly' order='many'>\n"
165 "       <element type='base64Data'/>\n"
166 "       <element type='hexData'/>\n"
167 "       <element type='boolData'/>\n"
168 "       <element type='charData'/>\n"
169 "       <element type='dateData'/>\n"
170 "       <element type='dateTimeData'/>\n"
171 "       <element type='dateTimeTzData'/>\n"
172 "       <element type='entityData'/>\n"
173 "       <element type='entitiesData'/>\n"
174 "       <element type='fixedData'/>\n"
175 "       <element type='floatData'/>\n"
176 "       <element type='i1Data'/>\n"
177 "       <element type='i2Data'/>\n"
178 "       <element type='i4Data'/>\n"
179 "       <element type='i8Data'/>\n"
180 "       <element type='intData'/>\n"
181 "       <element type='nmtokData'/>\n"
182 "       <element type='nmtoksData'/>\n"
183 "       <element type='numData'/>\n"
184 "       <element type='r4Data'/>\n"
185 "       <element type='r8Data'/>\n"
186 "       <element type='stringData'/>\n"
187 "       <element type='timeData'/>\n"
188 "       <element type='timeTzData'/>\n"
189 "       <element type='u1Data'/>\n"
190 "       <element type='u2Data'/>\n"
191 "       <element type='u4Data'/>\n"
192 "       <element type='u8Data'/>\n"
193 "       <element type='uriData'/>\n"
194 "       <element type='uuidData'/>\n"
195 "   </ElementType>\n"
196 "   <ElementType name='Property' content='eltOnly' order='seq'>\n"
197 "       <element type='Name'/>\n"
198 "       <element type='Value'/>\n"
199 "   </ElementType>\n"
200 "   <ElementType name='Properties' content='eltOnly'>\n"
201 "       <element type='Property' minOccurs='0' maxOccurs='*'/>\n"
202 "   </ElementType>\n"
203 "</Schema>";
204 
205 static const CHAR szDatatypeXML[] =
206 "<?xml version='1.0'?>\n"
207 "<Properties xmlns='urn:x-schema:datatype-test-xdr'>\n"
208 "   <Property>\n"
209 "       <Name>testBase64</Name>\n"
210 "       <Value>\n"
211 "           <base64Data>+HugeNumber+</base64Data>\n"
212 "       </Value>\n"
213 "   </Property>\n"
214 "   <Property>\n"
215 "       <Name>testHex</Name>\n"
216 "       <Value>\n"
217 "           <hexData>deadbeef</hexData>\n"
218 "       </Value>\n"
219 "   </Property>\n"
220 "   <Property>\n"
221 "       <Name>testBool</Name>\n"
222 "       <Value>\n"
223 "           <boolData>1</boolData>\n"
224 "       </Value>\n"
225 "   </Property>\n"
226 "   <Property>\n"
227 "       <Name>testChar</Name>\n"
228 "       <Value>\n"
229 "           <charData>u</charData>\n"
230 "       </Value>\n"
231 "   </Property>\n"
232 "   <Property>\n"
233 "       <Name>testDate</Name>\n"
234 "       <Value>\n"
235 "           <dateData>1998-02-01</dateData>\n"
236 "       </Value>\n"
237 "   </Property>\n"
238 "   <Property>\n"
239 "       <Name>testDateTime</Name>\n"
240 "       <Value>\n"
241 "           <dateTimeData>1998-02-01T12:34:56</dateTimeData>\n"
242 "       </Value>\n"
243 "   </Property>\n"
244 "   <Property>\n"
245 "       <Name>testDateTimeTz</Name>\n"
246 "       <Value>\n"
247 "           <dateTimeTzData>1998-02-01T12:34:56-06:00</dateTimeTzData>\n"
248 "       </Value>\n"
249 "   </Property>\n"
250 "   <Property>\n"
251 "       <Name>testFixed</Name>\n"
252 "       <Value>\n"
253 "           <fixedData>3.1416</fixedData>\n"
254 "       </Value>\n"
255 "   </Property>\n"
256 "   <Property>\n"
257 "       <Name>testFloat</Name>\n"
258 "       <Value>\n"
259 "           <floatData>3.14159</floatData>\n"
260 "       </Value>\n"
261 "   </Property>\n"
262 "   <Property>\n"
263 "       <Name>testI1</Name>\n"
264 "       <Value>\n"
265 "           <i1Data>42</i1Data>\n"
266 "       </Value>\n"
267 "   </Property>\n"
268 "   <Property>\n"
269 "       <Name>testI2</Name>\n"
270 "       <Value>\n"
271 "           <i2Data>420</i2Data>\n"
272 "       </Value>\n"
273 "   </Property>\n"
274 "   <Property>\n"
275 "       <Name>testI4</Name>\n"
276 "       <Value>\n"
277 "           <i4Data>-420000000</i4Data>\n"
278 "       </Value>\n"
279 "   </Property>\n"
280 "   <Property>\n"
281 "       <Name>testI8</Name>\n"
282 "       <Value>\n"
283 "           <i8Data>-4200000000</i8Data>\n"
284 "       </Value>\n"
285 "   </Property>\n"
286 "   <Property>\n"
287 "       <Name>testInt</Name>\n"
288 "       <Value>\n"
289 "           <intData>42</intData>\n"
290 "       </Value>\n"
291 "   </Property>\n"
292 "   <Property>\n"
293 "       <Name>testNmtoken</Name>\n"
294 "       <Value>\n"
295 "           <nmtokData>tok1</nmtokData>\n"
296 "       </Value>\n"
297 "   </Property>\n"
298 "   <Property>\n"
299 "       <Name>testNmtokens</Name>\n"
300 "       <Value>\n"
301 "           <nmtoksData>tok1 tok2 tok3</nmtoksData>\n"
302 "       </Value>\n"
303 "   </Property>\n"
304 "   <Property>\n"
305 "       <Name>testNumber</Name>\n"
306 "       <Value>\n"
307 "           <numData>3.14159</numData>\n"
308 "       </Value>\n"
309 "   </Property>\n"
310 "   <Property>\n"
311 "       <Name>testR4</Name>\n"
312 "       <Value>\n"
313 "           <r4Data>3.14159265</r4Data>\n"
314 "       </Value>\n"
315 "   </Property>\n"
316 "   <Property>\n"
317 "       <Name>testR8</Name>\n"
318 "       <Value>\n"
319 "           <r8Data>3.14159265358979323846</r8Data>\n"
320 "       </Value>\n"
321 "   </Property>\n"
322 "   <Property>\n"
323 "       <Name>testString</Name>\n"
324 "       <Value>\n"
325 "           <stringData>foo bar</stringData>\n"
326 "       </Value>\n"
327 "   </Property>\n"
328 "   <Property>\n"
329 "       <Name>testTime</Name>\n"
330 "       <Value>\n"
331 "           <timeData>12:34:56</timeData>\n"
332 "       </Value>\n"
333 "   </Property>\n"
334 "   <Property>\n"
335 "       <Name>testTimeTz</Name>\n"
336 "       <Value>\n"
337 "           <timeTzData>12:34:56-06:00</timeTzData>\n"
338 "       </Value>\n"
339 "   </Property>\n"
340 "   <Property>\n"
341 "       <Name>testU1</Name>\n"
342 "       <Value>\n"
343 "           <u1Data>255</u1Data>\n"
344 "       </Value>\n"
345 "   </Property>\n"
346 "   <Property>\n"
347 "       <Name>testU2</Name>\n"
348 "       <Value>\n"
349 "           <u2Data>65535</u2Data>\n"
350 "       </Value>\n"
351 "   </Property>\n"
352 "   <Property>\n"
353 "       <Name>testU4</Name>\n"
354 "       <Value>\n"
355 "           <u4Data>4294967295</u4Data>\n"
356 "       </Value>\n"
357 "   </Property>\n"
358 "   <Property>\n"
359 "       <Name>testU8</Name>\n"
360 "       <Value>\n"
361 "           <u8Data>18446744073709551615</u8Data>\n"
362 "       </Value>\n"
363 "   </Property>\n"
364 "   <Property>\n"
365 "       <Name>testURI</Name>\n"
366 "       <Value>\n"
367 "           <uriData>urn:schemas-microsoft-com:datatypes</uriData>\n"
368 "       </Value>\n"
369 "   </Property>\n"
370 "   <Property>\n"
371 "       <Name>testUUID</Name>\n"
372 "       <Value>\n"
373 "           <uuidData>2933BF81-7B36-11D2-B20E-00C04F983E60</uuidData>\n"
374 "       </Value>\n"
375 "   </Property>\n"
376 "</Properties>";
377 
378 static const CHAR szOpenSeqXDR[] =
379 "<Schema xmlns='urn:schemas-microsoft-com:xml-data'>\n"
380 "   <ElementType name='w' content='empty' model='closed'/>\n"
381 "   <ElementType name='x' content='empty' model='closed'/>\n"
382 "   <ElementType name='y' content='empty' model='closed'/>\n"
383 "   <ElementType name='z' content='empty' model='closed'/>\n"
384 "   <ElementType name='test' content='eltOnly' model='open' order='seq'>\n"
385 "       <element type='x'/>\n"
386 "       <group order='seq'>\n"
387 "           <element type='x'/>\n"
388 "           <element type='y'/>\n"
389 "           <element type='z'/>\n"
390 "       </group>\n"
391 "       <element type='z'/>\n"
392 "   </ElementType>\n"
393 "</Schema>";
394 
395 static const CHAR szOpenSeqXML1[] = "<test><x/><x/><y/><z/><z/></test>";
396 static const CHAR szOpenSeqXML2[] = "<test><x/><x/><y/><z/><z/><w/></test>";
397 static const CHAR szOpenSeqXML3[] = "<test><w/><x/><x/><y/><z/><z/></test>";
398 static const CHAR szOpenSeqXML4[] = "<test><x/><x/><y/><z/><z/><v/></test>";
399 
400 #define check_ref_expr(expr, n) { \
401     LONG ref = expr; \
402     ok(ref == n, "expected %i refs, got %i\n", n, ref); \
403 }
404 
405 #define check_refs(iface, obj, n) { \
406     LONG ref = iface ## _AddRef(obj); \
407     ok(ref == n+1, "expected %i refs, got %i\n", n+1, ref); \
408     ref = iface ## _Release(obj); \
409     ok(ref == n, "expected %i refs, got %i\n", n, ref); \
410 }
411 
412 #define ole_check(expr) { \
413     HRESULT r = expr; \
414     ok(r == S_OK, #expr " returned %x\n", r); \
415 }
416 
417 #define ole_expect(expr, expect) { \
418     HRESULT r = expr; \
419     ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
420 }
421 
422 #define _expect64(expr, str, base, TYPE, CONV) { \
423     TYPE v1 = expr; \
424     TYPE v2 = CONV(str, NULL, base); \
425     ok(v1 == v2, #expr "returned %s, expected %s\n", \
426                   wine_dbgstr_longlong(v1), wine_dbgstr_longlong(v2)); \
427 }
428 
429 #define expect_int64(expr, x, base) _expect64(expr, #x, base, LONG64, _strtoi64)
430 #define expect_uint64(expr, x, base) _expect64(expr, #x, base, ULONG64, _strtoui64)
431 
432 static BSTR alloced_bstrs[256];
433 static int alloced_bstrs_count;
434 
435 static BSTR alloc_str_from_narrow(const char *str)
436 {
437     int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
438     BSTR ret = SysAllocStringLen(NULL, len - 1);  /* NUL character added automatically */
439     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
440     return ret;
441 }
442 
443 static BSTR _bstr_(const char *str)
444 {
445     assert(alloced_bstrs_count < sizeof(alloced_bstrs)/sizeof(alloced_bstrs[0]));
446     alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
447     return alloced_bstrs[alloced_bstrs_count++];
448 }
449 
450 static void free_bstrs(void)
451 {
452     int i;
453     for (i = 0; i < alloced_bstrs_count; i++)
454         SysFreeString(alloced_bstrs[i]);
455     alloced_bstrs_count = 0;
456 }
457 
458 static VARIANT _variantdoc_(void* doc)
459 {
460     VARIANT v;
461     V_VT(&v) = VT_DISPATCH;
462     V_DISPATCH(&v) = (IDispatch*)doc;
463     return v;
464 }
465 
466 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
467 {
468     void *obj = NULL;
469     HRESULT hr;
470 
471     hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
472     if (hr != S_OK)
473         win_skip_(__FILE__,line)("failed to create %s instance: 0x%08x\n", name, hr);
474 
475     return obj;
476 }
477 
478 #define _create(cls) cls, #cls
479 
480 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument), iid, __LINE__)
481 
482 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
483 
484 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
485 
486 #define create_cache_version(v, iid) _create_object(&_create(CLSID_XMLSchemaCache ## v), iid, __LINE__)
487 
488 static void test_schema_refs(void)
489 {
490     static const WCHAR emptyW[] = {0};
491     IXMLDOMDocument2 *doc;
492     IXMLDOMNode *node;
493     IXMLDOMSchemaCollection *cache;
494     VARIANT v;
495     VARIANT_BOOL b;
496     BSTR str;
497     LONG len;
498     HRESULT hr;
499 
500     doc = create_document(&IID_IXMLDOMDocument2);
501     if (!doc)
502         return;
503 
504     cache = create_cache(&IID_IXMLDOMSchemaCollection);
505     if(!cache)
506     {
507         IXMLDOMDocument2_Release(doc);
508         return;
509     }
510 
511     VariantInit(&v);
512     str = SysAllocString(xdr_schema_xml);
513     ole_check(IXMLDOMDocument2_loadXML(doc, str, &b));
514     ok(b == VARIANT_TRUE, "b %04x\n", b);
515     SysFreeString(str);
516 
517     node = (void*)0xdeadbeef;
518     ole_check(IXMLDOMSchemaCollection_get(cache, NULL, &node));
519     ok(node == NULL, "%p\n", node);
520 
521     /* NULL uri pointer, still adds a document */
522     ole_check(IXMLDOMSchemaCollection_add(cache, NULL, _variantdoc_(doc)));
523     len = -1;
524     ole_check(IXMLDOMSchemaCollection_get_length(cache, &len));
525     ok(len == 1, "got %d\n", len);
526     /* read back - empty valid BSTR */
527     str = NULL;
528     ole_check(IXMLDOMSchemaCollection_get_namespaceURI(cache, 0, &str));
529     ok(str && *str == 0, "got %p\n", str);
530     SysFreeString(str);
531 
532     node = NULL;
533     ole_check(IXMLDOMSchemaCollection_get(cache, NULL, &node));
534     ok(node != NULL, "%p\n", node);
535     IXMLDOMNode_Release(node);
536 
537     node = NULL;
538     str = SysAllocString(emptyW);
539     ole_check(IXMLDOMSchemaCollection_get(cache, str, &node));
540     ok(node != NULL, "%p\n", node);
541     IXMLDOMNode_Release(node);
542     SysFreeString(str);
543 
544     /* remove with NULL uri */
545     ole_check(IXMLDOMSchemaCollection_remove(cache, NULL));
546     len = -1;
547     ole_check(IXMLDOMSchemaCollection_get_length(cache, &len));
548     ok(len == 0, "got %d\n", len);
549 
550     /* same, but with VT_UNKNOWN type */
551     V_VT(&v) = VT_UNKNOWN;
552     V_UNKNOWN(&v) = (IUnknown*)doc;
553     hr = IXMLDOMSchemaCollection_add(cache, NULL, v);
554     ok(hr == S_OK, "got 0x%08x\n", hr);
555 
556     len = -1;
557     hr = IXMLDOMSchemaCollection_get_length(cache, &len);
558     ok(hr == S_OK, "got 0x%08x\n", hr);
559     ok(len == 1, "got %d\n", len);
560 
561     hr = IXMLDOMSchemaCollection_remove(cache, NULL);
562     ok(hr == S_OK, "got 0x%08x\n", hr);
563     len = -1;
564     hr = IXMLDOMSchemaCollection_get_length(cache, &len);
565     ok(hr == S_OK, "got 0x%08x\n", hr);
566     ok(len == 0, "got %d\n", len);
567 
568     str = SysAllocString(xdr_schema_uri);
569     ole_check(IXMLDOMSchemaCollection_add(cache, str, _variantdoc_(doc)));
570 
571     /* IXMLDOMSchemaCollection_add doesn't add a ref on doc */
572     check_refs(IXMLDOMDocument2, doc, 1);
573 
574     SysFreeString(str);
575 
576     V_VT(&v) = VT_INT;
577     ole_expect(IXMLDOMDocument2_get_schemas(doc, &v), S_FALSE);
578     ok(V_VT(&v) == VT_NULL, "vt %x\n", V_VT(&v));
579 
580     check_ref_expr(IXMLDOMSchemaCollection_AddRef(cache), 2);
581     V_VT(&v) = VT_DISPATCH;
582     V_DISPATCH(&v) = (IDispatch*)cache;
583 
584     /* check that putref_schemas takes a ref */
585     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
586     check_refs(IXMLDOMSchemaCollection, cache, 3);
587 
588     VariantClear(&v); /* refs now 2 */
589 
590     V_VT(&v) = VT_INT;
591     /* check that get_schemas adds a ref */
592     ole_check(IXMLDOMDocument2_get_schemas(doc, &v));
593     ok(V_VT(&v) == VT_DISPATCH, "vt %x\n", V_VT(&v));
594     check_refs(IXMLDOMSchemaCollection, cache, 3);
595 
596     /* get_schemas doesn't release a ref if passed VT_DISPATCH - ie it doesn't call VariantClear() */
597     ole_check(IXMLDOMDocument2_get_schemas(doc, &v));
598     ok(V_VT(&v) == VT_DISPATCH, "vt %x\n", V_VT(&v));
599     check_refs(IXMLDOMSchemaCollection, cache, 4);
600 
601     /* release the two refs returned by get_schemas */
602     check_ref_expr(IXMLDOMSchemaCollection_Release(cache), 3);
603     check_ref_expr(IXMLDOMSchemaCollection_Release(cache), 2);
604 
605     /* check that taking another ref on the document doesn't change the schema's ref count */
606     check_ref_expr(IXMLDOMDocument2_AddRef(doc), 2);
607     check_refs(IXMLDOMSchemaCollection, cache, 2);
608     check_ref_expr(IXMLDOMDocument2_Release(doc), 1);
609 
610     /* call putref_schema with some odd variants */
611     V_VT(&v) = VT_INT;
612     ole_expect(IXMLDOMDocument2_putref_schemas(doc, v), E_FAIL);
613     check_refs(IXMLDOMSchemaCollection, cache, 2);
614 
615     /* calling with VT_EMPTY releases the schema */
616     V_VT(&v) = VT_EMPTY;
617     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
618     check_refs(IXMLDOMSchemaCollection, cache, 1);
619 
620     /* try setting with VT_UNKNOWN */
621     check_ref_expr(IXMLDOMSchemaCollection_AddRef(cache), 2);
622     V_VT(&v) = VT_UNKNOWN;
623     V_UNKNOWN(&v) = (IUnknown*)cache;
624     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
625     check_refs(IXMLDOMSchemaCollection, cache, 3);
626 
627     VariantClear(&v); /* refs now 2 */
628 
629     /* calling with VT_NULL releases the schema */
630     V_VT(&v) = VT_NULL;
631     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
632     check_refs(IXMLDOMSchemaCollection, cache, 1);
633 
634     /* refs now 1 */
635     /* set again */
636     check_ref_expr(IXMLDOMSchemaCollection_AddRef(cache), 2);
637     V_VT(&v) = VT_UNKNOWN;
638     V_UNKNOWN(&v) = (IUnknown*)cache;
639     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
640     check_refs(IXMLDOMSchemaCollection, cache, 3);
641 
642     VariantClear(&v); /* refs now 2 */
643 
644     /* release the final ref on the doc which should release its ref on the schema */
645     check_ref_expr(IXMLDOMDocument2_Release(doc), 0);
646 
647     check_refs(IXMLDOMSchemaCollection, cache, 1);
648     check_ref_expr(IXMLDOMSchemaCollection_Release(cache), 0);
649 }
650 
651 static void test_collection_refs(void)
652 {
653     IXMLDOMDocument2 *schema1, *schema2, *schema3;
654     IXMLDOMSchemaCollection *cache1, *cache2, *cache3;
655     VARIANT_BOOL b;
656     LONG length;
657 
658     schema1 = create_document(&IID_IXMLDOMDocument2);
659     schema2 = create_document(&IID_IXMLDOMDocument2);
660     schema3 = create_document(&IID_IXMLDOMDocument2);
661 
662     cache1 = create_cache(&IID_IXMLDOMSchemaCollection);
663     cache2 = create_cache(&IID_IXMLDOMSchemaCollection);
664     cache3 = create_cache(&IID_IXMLDOMSchemaCollection);
665 
666     if (!schema1 || !schema2 || !schema3 || !cache1 || !cache2 || !cache3)
667     {
668         if (schema1) IXMLDOMDocument2_Release(schema1);
669         if (schema2) IXMLDOMDocument2_Release(schema2);
670         if (schema3) IXMLDOMDocument2_Release(schema3);
671 
672         if (cache1) IXMLDOMSchemaCollection_Release(cache1);
673         if (cache2) IXMLDOMSchemaCollection_Release(cache2);
674         if (cache3) IXMLDOMSchemaCollection_Release(cache2);
675 
676         return;
677     }
678 
679     ole_check(IXMLDOMDocument2_loadXML(schema1, _bstr_(xdr_schema1_xml), &b));
680     ok(b == VARIANT_TRUE, "failed to load XML\n");
681 
682     ole_check(IXMLDOMDocument2_loadXML(schema2, _bstr_(xdr_schema2_xml), &b));
683     ok(b == VARIANT_TRUE, "failed to load XML\n");
684 
685     ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xdr_schema3_xml), &b));
686     ok(b == VARIANT_TRUE, "failed to load XML\n");
687 
688     ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
689     ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
690     ole_check(IXMLDOMSchemaCollection_add(cache3, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
691 
692     check_ref_expr(IXMLDOMDocument2_Release(schema1), 0);
693     check_ref_expr(IXMLDOMDocument2_Release(schema2), 0);
694     check_ref_expr(IXMLDOMDocument2_Release(schema3), 0);
695     schema1 = NULL;
696     schema2 = NULL;
697     schema3 = NULL;
698 
699     /* releasing the original doc does not affect the schema cache */
700     ole_check(IXMLDOMSchemaCollection_get(cache1, _bstr_(xdr_schema1_uri), (IXMLDOMNode**)&schema1));
701     ole_check(IXMLDOMSchemaCollection_get(cache2, _bstr_(xdr_schema2_uri), (IXMLDOMNode**)&schema2));
702     ole_check(IXMLDOMSchemaCollection_get(cache3, _bstr_(xdr_schema3_uri), (IXMLDOMNode**)&schema3));
703 
704     /* we get a read-only domdoc interface, created just for us */
705     if (schema1) check_refs(IXMLDOMDocument2, schema1, 1);
706     if (schema2) check_refs(IXMLDOMDocument2, schema2, 1);
707     if (schema3) check_refs(IXMLDOMDocument2, schema3, 1);
708 
709     ole_expect(IXMLDOMSchemaCollection_addCollection(cache1, NULL), E_POINTER);
710     ole_check(IXMLDOMSchemaCollection_addCollection(cache2, cache1));
711     ole_check(IXMLDOMSchemaCollection_addCollection(cache3, cache2));
712 
713     length = -1;
714     ole_check(IXMLDOMSchemaCollection_get_length(cache1, &length));
715     ok(length == 1, "expected length 1, got %i\n", length);
716 
717     length = -1;
718     ole_check(IXMLDOMSchemaCollection_get_length(cache2, &length));
719     ok(length == 2, "expected length 2, got %i\n", length);
720 
721     length = -1;
722     ole_check(IXMLDOMSchemaCollection_get_length(cache3, &length));
723     ok(length == 3, "expected length 3, got %i\n", length);
724 
725 
726     /* merging collections does not affect the ref count */
727     check_refs(IXMLDOMSchemaCollection, cache1, 1);
728     check_refs(IXMLDOMSchemaCollection, cache2, 1);
729     check_refs(IXMLDOMSchemaCollection, cache3, 1);
730 
731     /* nor does it affect the domdoc instances */
732     if (schema1) check_refs(IXMLDOMDocument2, schema1, 1);
733     if (schema2) check_refs(IXMLDOMDocument2, schema2, 1);
734     if (schema3) check_refs(IXMLDOMDocument2, schema3, 1);
735 
736     if (schema1) check_ref_expr(IXMLDOMDocument2_Release(schema1), 0);
737     if (schema2) check_ref_expr(IXMLDOMDocument2_Release(schema2), 0);
738     if (schema3) check_ref_expr(IXMLDOMDocument2_Release(schema3), 0);
739     schema1 = NULL;
740     schema2 = NULL;
741     schema3 = NULL;
742 
743     /* releasing the domdoc instances doesn't change the cache */
744     ole_check(IXMLDOMSchemaCollection_get(cache1, _bstr_(xdr_schema1_uri), (IXMLDOMNode**)&schema1));
745     ole_check(IXMLDOMSchemaCollection_get(cache2, _bstr_(xdr_schema2_uri), (IXMLDOMNode**)&schema2));
746     ole_check(IXMLDOMSchemaCollection_get(cache3, _bstr_(xdr_schema3_uri), (IXMLDOMNode**)&schema3));
747 
748     /* we can just get them again */
749     if (schema1) check_refs(IXMLDOMDocument2, schema1, 1);
750     if (schema2) check_refs(IXMLDOMDocument2, schema2, 1);
751     if (schema3) check_refs(IXMLDOMDocument2, schema3, 1);
752 
753     /* releasing the caches does not affect the domdoc instances */
754     check_ref_expr(IXMLDOMSchemaCollection_Release(cache1), 0);
755     check_ref_expr(IXMLDOMSchemaCollection_Release(cache2), 0);
756     check_ref_expr(IXMLDOMSchemaCollection_Release(cache3), 0);
757 
758     /* they're just for us */
759     if (schema1) check_refs(IXMLDOMDocument2, schema1, 1);
760     if (schema2) check_refs(IXMLDOMDocument2, schema2, 1);
761     if (schema3) check_refs(IXMLDOMDocument2, schema3, 1);
762 
763     if (schema1) check_ref_expr(IXMLDOMDocument2_Release(schema1), 0);
764     if (schema2) check_ref_expr(IXMLDOMDocument2_Release(schema2), 0);
765     if (schema3) check_ref_expr(IXMLDOMDocument2_Release(schema3), 0);
766 
767     free_bstrs();
768 }
769 
770 static void test_length(void)
771 {
772     IXMLDOMDocument2 *schema1, *schema2, *schema3;
773     IXMLDOMSchemaCollection *cache;
774     VARIANT_BOOL b;
775     VARIANT v;
776     LONG length;
777 
778     schema1 = create_document(&IID_IXMLDOMDocument2);
779     schema2 = create_document(&IID_IXMLDOMDocument2);
780     schema3 = create_document(&IID_IXMLDOMDocument2);
781 
782     cache = create_cache(&IID_IXMLDOMSchemaCollection);
783 
784     if (!schema1 || !schema2 || !schema3 || !cache)
785     {
786         if (schema1) IXMLDOMDocument2_Release(schema1);
787         if (schema2) IXMLDOMDocument2_Release(schema2);
788         if (schema3) IXMLDOMDocument2_Release(schema3);
789 
790         if (cache) IXMLDOMSchemaCollection_Release(cache);
791 
792         return;
793     }
794 
795     VariantInit(&v);
796 
797     ole_check(IXMLDOMDocument2_loadXML(schema1, _bstr_(xdr_schema1_xml), &b));
798     ok(b == VARIANT_TRUE, "failed to load XML\n");
799 
800     ole_check(IXMLDOMDocument2_loadXML(schema2, _bstr_(xdr_schema2_xml), &b));
801     ok(b == VARIANT_TRUE, "failed to load XML\n");
802 
803     ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xdr_schema3_xml), &b));
804     ok(b == VARIANT_TRUE, "failed to load XML\n");
805 
806     ole_expect(IXMLDOMSchemaCollection_get_length(cache, NULL), E_POINTER);
807 
808     /* MSDN lies; removing a nonexistent entry produces no error */
809     ole_check(IXMLDOMSchemaCollection_remove(cache, NULL));
810     ole_check(IXMLDOMSchemaCollection_remove(cache, _bstr_(xdr_schema1_uri)));
811 
812     length = -1;
813     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
814     ok(length == 0, "expected length 0, got %i\n", length);
815 
816     ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
817 
818     length = -1;
819     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
820     ok(length == 1, "expected length 1, got %i\n", length);
821 
822     ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
823 
824     length = -1;
825     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
826     ok(length == 2, "expected length 2, got %i\n", length);
827 
828     ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
829 
830     length = -1;
831     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
832     ok(length == 3, "expected length 3, got %i\n", length);
833 
834     /* adding with VT_NULL is the same as removing */
835     V_VT(&v) = VT_NULL;
836     ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(xdr_schema1_uri), v));
837 
838     length = -1;
839     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
840     ok(length == 2, "expected length 2, got %i\n", length);
841 
842     ole_check(IXMLDOMSchemaCollection_remove(cache, _bstr_(xdr_schema2_uri)));
843 
844     length = -1;
845     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
846     ok(length == 1, "expected length 1, got %i\n", length);
847 
848     ole_check(IXMLDOMSchemaCollection_remove(cache, _bstr_(xdr_schema3_uri)));
849 
850     length = -1;
851     ole_check(IXMLDOMSchemaCollection_get_length(cache, &length));
852     ok(length == 0, "expected length 0, got %i\n", length);
853 
854     IXMLDOMDocument2_Release(schema1);
855     IXMLDOMDocument2_Release(schema2);
856     IXMLDOMDocument2_Release(schema3);
857     IXMLDOMSchemaCollection_Release(cache);
858 
859     free_bstrs();
860 }
861 
862 static void test_collection_content(void)
863 {
864     IXMLDOMDocument2 *schema1, *schema2, *schema3, *schema4, *schema5;
865     BSTR content[5] = {NULL, NULL, NULL, NULL, NULL};
866     IXMLDOMSchemaCollection *cache1, *cache2;
867     VARIANT_BOOL b;
868     LONG length;
869     HRESULT hr;
870     BSTR bstr;
871     int i, j;
872 
873     schema1 = create_document_version(30, &IID_IXMLDOMDocument2);
874     schema2 = create_document_version(30, &IID_IXMLDOMDocument2);
875     schema3 = create_document_version(30, &IID_IXMLDOMDocument2);
876 
877     cache1 = create_cache_version(30, &IID_IXMLDOMSchemaCollection);
878     cache2 = create_cache_version(40, &IID_IXMLDOMSchemaCollection);
879 
880     if (!schema1 || !schema2 || !schema3 || !cache1)
881     {
882         if (schema1) IXMLDOMDocument2_Release(schema1);
883         if (schema2) IXMLDOMDocument2_Release(schema2);
884         if (schema3) IXMLDOMDocument2_Release(schema3);
885 
886         if (cache1) IXMLDOMSchemaCollection_Release(cache1);
887 
888         return;
889     }
890 
891     ole_check(IXMLDOMDocument2_loadXML(schema1, _bstr_(xdr_schema1_xml), &b));
892     ok(b == VARIANT_TRUE, "failed to load XML\n");
893 
894     ole_check(IXMLDOMDocument2_loadXML(schema2, _bstr_(xdr_schema2_xml), &b));
895     ok(b == VARIANT_TRUE, "failed to load XML\n");
896 
897     ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xdr_schema3_xml), &b));
898     ok(b == VARIANT_TRUE, "failed to load XML\n");
899 
900     ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
901     ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
902     ole_check(IXMLDOMSchemaCollection_add(cache1, _bstr_(xdr_schema3_uri), _variantdoc_(schema3)));
903 
904     length = -1;
905     ole_check(IXMLDOMSchemaCollection_get_length(cache1, &length));
906     ok(length == 3, "expected length 3, got %i\n", length);
907 
908     IXMLDOMDocument2_Release(schema1);
909     IXMLDOMDocument2_Release(schema2);
910     IXMLDOMDocument2_Release(schema3);
911 
912     if (cache2)
913     {
914         schema1 = create_document_version(40, &IID_IXMLDOMDocument2);
915         schema2 = create_document_version(40, &IID_IXMLDOMDocument2);
916         schema3 = create_document_version(40, &IID_IXMLDOMDocument2);
917         schema4 = create_document_version(40, &IID_IXMLDOMDocument2);
918         schema5 = create_document_version(40, &IID_IXMLDOMDocument2);
919         ole_check(IXMLDOMDocument2_loadXML(schema1, _bstr_(xdr_schema1_xml), &b));
920         ok(b == VARIANT_TRUE, "failed to load XML\n");
921         ole_check(IXMLDOMDocument2_loadXML(schema2, _bstr_(xdr_schema2_xml), &b));
922         ok(b == VARIANT_TRUE, "failed to load XML\n");
923         ole_check(IXMLDOMDocument2_loadXML(schema3, _bstr_(xsd_schema1_xml), &b));
924         ok(b == VARIANT_TRUE, "failed to load XML\n");
925         ole_check(IXMLDOMDocument2_loadXML(schema4, _bstr_(xsd_schema2_xml), &b));
926         ok(b == VARIANT_TRUE, "failed to load XML\n");
927         ole_check(IXMLDOMDocument2_loadXML(schema5, _bstr_(xsd_schema3_xml), &b));
928         ok(b == VARIANT_TRUE, "failed to load XML\n");
929 
930         /* combining XDR and XSD schemas in the same cache is fine */
931         ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema1_uri), _variantdoc_(schema1)));
932         ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xdr_schema2_uri), _variantdoc_(schema2)));
933         ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema1_uri), _variantdoc_(schema3)));
934         ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema2_uri), _variantdoc_(schema4)));
935         ole_check(IXMLDOMSchemaCollection_add(cache2, _bstr_(xsd_schema3_uri), _variantdoc_(schema5)));
936 
937         length = -1;
938         ole_check(IXMLDOMSchemaCollection_get_length(cache2, &length));
939         ok(length == 5, "expected length 5, got %i\n", length);
940 
941         IXMLDOMDocument2_Release(schema1);
942         IXMLDOMDocument2_Release(schema2);
943         IXMLDOMDocument2_Release(schema3);
944         IXMLDOMDocument2_Release(schema4);
945         IXMLDOMDocument2_Release(schema5);
946     }
947 
948     bstr = (void*)0xdeadbeef;
949     /* error if index is out of range */
950     hr = IXMLDOMSchemaCollection_get_namespaceURI(cache1, 3, &bstr);
951     EXPECT_HR(hr, E_FAIL);
952     ok(bstr == (void*)0xdeadbeef, "got %p\n", bstr);
953     /* error if return pointer is NULL */
954     ole_expect(IXMLDOMSchemaCollection_get_namespaceURI(cache1, 0, NULL), E_POINTER);
955     /* pointer is checked first */
956     ole_expect(IXMLDOMSchemaCollection_get_namespaceURI(cache1, 3, NULL), E_POINTER);
957 
958     schema1 = NULL;
959     /* no error if ns uri does not exist */
960     ole_check(IXMLDOMSchemaCollection_get(cache1, _bstr_(xsd_schema1_uri), (IXMLDOMNode**)&schema1));
961     ok(!schema1, "expected NULL\n");
962     /* a NULL bstr corresponds to no-uri ns */
963     ole_check(IXMLDOMSchemaCollection_get(cache1, NULL, (IXMLDOMNode**)&schema1));
964     ok(!schema1, "expected NULL\n");
965     /* error if return pointer is NULL */
966     ole_expect(IXMLDOMSchemaCollection_get(cache1, _bstr_(xdr_schema1_uri), NULL), E_POINTER);
967 
968     for (i = 0; i < 3; ++i)
969     {
970         bstr = NULL;
971         ole_check(IXMLDOMSchemaCollection_get_namespaceURI(cache1, i, &bstr));
972         ok(bstr != NULL && *bstr, "expected non-empty string\n");
973         content[i] = bstr;
974 
975         for (j = 0; j < i; ++j)
976             ok(winetest_strcmpW(content[j], bstr), "got duplicate entry\n");
977     }
978 
979     for (i = 0; i < 3; ++i)
980     {
981         SysFreeString(content[i]);
982         content[i] = NULL;
983     }
984 
985     if (cache2)
986     {
987         for (i = 0; i < 5; ++i)
988         {
989             bstr = NULL;
990             ole_check(IXMLDOMSchemaCollection_get_namespaceURI(cache2, i, &bstr));
991             ok(bstr != NULL && *bstr, "expected non-empty string\n");
992 
993             for (j = 0; j < i; ++j)
994                 ok(winetest_strcmpW(content[j], bstr), "got duplicate entry\n");
995             content[i] = bstr;
996         }
997 
998         for (i = 0; i < 5; ++i)
999         {
1000             SysFreeString(content[i]);
1001             content[i] = NULL;
1002         }
1003     }
1004 
1005     IXMLDOMSchemaCollection_Release(cache1);
1006     if (cache2) IXMLDOMSchemaCollection_Release(cache2);
1007 
1008     free_bstrs();
1009 }
1010 
1011 static void test_XDR_schemas(void)
1012 {
1013     IXMLDOMDocument2 *doc, *schema;
1014     IXMLDOMSchemaCollection* cache;
1015     IXMLDOMParseError* err;
1016     VARIANT_BOOL b;
1017     VARIANT v;
1018     BSTR bstr;
1019 
1020     doc = create_document(&IID_IXMLDOMDocument2);
1021     schema = create_document(&IID_IXMLDOMDocument2);
1022     cache = create_cache(&IID_IXMLDOMSchemaCollection);
1023 
1024     if (!doc || !schema || !cache)
1025     {
1026         if (doc)    IXMLDOMDocument2_Release(doc);
1027         if (schema) IXMLDOMDocument2_Release(schema);
1028         if (cache)  IXMLDOMSchemaCollection_Release(cache);
1029 
1030         return;
1031     }
1032 
1033     VariantInit(&v);
1034 
1035     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szOpenSeqXML1), &b));
1036     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1037 
1038     ole_check(IXMLDOMDocument2_loadXML(schema, _bstr_(szOpenSeqXDR), &b));
1039     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1040 
1041     /* load the schema */
1042     V_VT(&v) = VT_DISPATCH;
1043     V_DISPATCH(&v) = NULL;
1044     ole_check(IXMLDOMDocument2_QueryInterface(schema, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
1045     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1046     ole_check(IXMLDOMSchemaCollection_add(cache, _bstr_(""), v));
1047     VariantClear(&v);
1048 
1049     /* associate the cache to the doc */
1050     V_VT(&v) = VT_DISPATCH;
1051     V_DISPATCH(&v) = NULL;
1052     ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
1053     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1054     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
1055     VariantClear(&v);
1056 
1057     /* validate the doc
1058      * only declared elements in the declared order
1059      * this is fine */
1060     err = NULL;
1061     bstr = NULL;
1062     ole_check(IXMLDOMDocument2_validate(doc, &err));
1063     ok(err != NULL, "domdoc_validate() should always set err\n");
1064     ole_expect(IXMLDOMParseError_get_reason(err, &bstr), S_FALSE);
1065     ok(IXMLDOMParseError_get_reason(err, &bstr) == S_FALSE, "got error: %s\n", wine_dbgstr_w(bstr));
1066     SysFreeString(bstr);
1067     IXMLDOMParseError_Release(err);
1068 
1069     /* load the next doc */
1070     IXMLDOMDocument2_Release(doc);
1071     doc = create_document(&IID_IXMLDOMDocument2);
1072     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szOpenSeqXML2), &b));
1073     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1074 
1075     /* associate the cache to the doc */
1076     V_VT(&v) = VT_DISPATCH;
1077     V_DISPATCH(&v) = NULL;
1078     ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
1079     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1080     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
1081     VariantClear(&v);
1082 
1083     /* validate the doc
1084      * declared elements in the declared order, with an extra declared element at the end
1085      * this is fine */
1086     err = NULL;
1087     bstr = NULL;
1088     ole_check(IXMLDOMDocument2_validate(doc, &err));
1089     ok(err != NULL, "domdoc_validate() should always set err\n");
1090     ole_expect(IXMLDOMParseError_get_reason(err, &bstr), S_FALSE);
1091     ok(IXMLDOMParseError_get_reason(err, &bstr) == S_FALSE, "got error: %s\n", wine_dbgstr_w(bstr));
1092     SysFreeString(bstr);
1093     IXMLDOMParseError_Release(err);
1094 
1095     /* load the next doc */
1096     IXMLDOMDocument2_Release(doc);
1097     doc = create_document(&IID_IXMLDOMDocument2);
1098     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szOpenSeqXML3), &b));
1099     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1100 
1101     /* associate the cache to the doc */
1102     V_VT(&v) = VT_DISPATCH;
1103     V_DISPATCH(&v) = NULL;
1104     ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
1105     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1106     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
1107     VariantClear(&v);
1108 
1109     /* validate the doc
1110      * fails, extra elements are only allowed at the end */
1111     err = NULL;
1112     bstr = NULL;
1113     ole_expect(IXMLDOMDocument2_validate(doc, &err), S_FALSE);
1114     ok(err != NULL, "domdoc_validate() should always set err\n");
1115     todo_wine ok(IXMLDOMParseError_get_reason(err, &bstr) == S_OK, "got error: %s\n", wine_dbgstr_w(bstr));
1116     SysFreeString(bstr);
1117     IXMLDOMParseError_Release(err);
1118 
1119     /* load the next doc */
1120     IXMLDOMDocument2_Release(doc);
1121     doc = create_document(&IID_IXMLDOMDocument2);
1122     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(szOpenSeqXML4), &b));
1123     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1124 
1125     /* associate the cache to the doc */
1126     V_VT(&v) = VT_DISPATCH;
1127     V_DISPATCH(&v) = NULL;
1128     ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v)));
1129     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1130     ole_check(IXMLDOMDocument2_putref_schemas(doc, v));
1131     VariantClear(&v);
1132 
1133     /* validate the doc
1134      * fails, undeclared elements are not allowed */
1135     err = NULL;
1136     bstr = NULL;
1137     ole_expect(IXMLDOMDocument2_validate(doc, &err), S_FALSE);
1138     ok(err != NULL, "domdoc_validate() should always set err\n");
1139     todo_wine ok(IXMLDOMParseError_get_reason(err, &bstr) == S_OK, "got error: %s\n", wine_dbgstr_w(bstr));
1140     SysFreeString(bstr);
1141     IXMLDOMParseError_Release(err);
1142 
1143     IXMLDOMDocument2_Release(doc);
1144     IXMLDOMDocument2_Release(schema);
1145     IXMLDOMSchemaCollection_Release(cache);
1146 
1147     free_bstrs();
1148 }
1149 
1150 typedef struct {
1151     const char *query;
1152     enum VARENUM type_schema;
1153     const char *typename;
1154     BOOL todo;
1155 } xdr_datatypes;
1156 
1157 static const xdr_datatypes xdr_datatypes_data[] = {
1158     { "//Property[Name!text()='testBase64']/Value/base64Data",         VT_ARRAY|VT_UI1, "bin.base64" },
1159     { "//Property[Name!text()='testHex']/Value/hexData",               VT_ARRAY|VT_UI1, "bin.hex" },
1160     { "//Property[Name!text()='testBool']/Value/boolData",             VT_BOOL, "boolean" },
1161     { "//Property[Name!text()='testChar']/Value/charData",             VT_I4,   "char", TRUE },
1162     { "//Property[Name!text()='testDate']/Value/dateData",             VT_DATE, "date" },
1163     { "//Property[Name!text()='testDateTime']/Value/dateTimeData",     VT_DATE, "dateTime" },
1164     { "//Property[Name!text()='testDateTimeTz']/Value/dateTimeTzData", VT_DATE, "dateTime.tz" },
1165     { "//Property[Name!text()='testFixed']/Value/fixedData",           VT_CY,   "fixed.14.4" },
1166     { "//Property[Name!text()='testFloat']/Value/floatData",           VT_R8,   "float" },
1167     { "//Property[Name!text()='testI1']/Value/i1Data",                 VT_I1,   "i1" },
1168     { "//Property[Name!text()='testI2']/Value/i2Data",                 VT_I2,   "i2" },
1169     { "//Property[Name!text()='testI4']/Value/i4Data",                 VT_I4,   "i4" },
1170     { "//Property[Name!text()='testI8']/Value/i8Data",                 VT_NULL, "i8", TRUE },
1171     { "//Property[Name!text()='testInt']/Value/intData",               VT_I4,   "int" },
1172     { "//Property[Name!text()='testNmtoken']/Value/nmtokData",         VT_BSTR, NULL },
1173     { "//Property[Name!text()='testNmtokens']/Value/nmtoksData",       VT_BSTR, NULL },
1174     { "//Property[Name!text()='testNumber']/Value/numData",            VT_BSTR, "number" },
1175     { "//Property[Name!text()='testR4']/Value/r4Data",                 VT_R4,   "r4" },
1176     { "//Property[Name!text()='testR8']/Value/r8Data",                 VT_R8,   "r8" },
1177     { "//Property[Name!text()='testString']/Value/stringData",         VT_BSTR, NULL },
1178     { "//Property[Name!text()='testTime']/Value/timeData",             VT_DATE, "time" },
1179     { "//Property[Name!text()='testTimeTz']/Value/timeTzData",         VT_DATE, "time.tz" },
1180     { "//Property[Name!text()='testU1']/Value/u1Data",                 VT_UI1,  "ui1" },
1181     { "//Property[Name!text()='testU2']/Value/u2Data",                 VT_UI2,  "ui2" },
1182     { "//Property[Name!text()='testU4']/Value/u4Data",                 VT_UI4,  "ui4" },
1183     { "//Property[Name!text()='testU8']/Value/u8Data",                 VT_NULL, "ui8", TRUE },
1184     { "//Property[Name!text()='testURI']/Value/uriData",               VT_BSTR, "uri" },
1185     { "//Property[Name!text()='testUUID']/Value/uuidData",             VT_BSTR, "uuid" },
1186     { NULL }
1187 };
1188 
1189 static void test_XDR_datatypes(void)
1190 {
1191     IXMLDOMDocument2 *doc, *schema, *doc2;
1192     IXMLDOMSchemaCollection* cache;
1193     const xdr_datatypes *ptr;
1194     IXMLDOMParseError* err;
1195     VARIANT_BOOL b;
1196     HRESULT hr;
1197     VARIANT v;
1198     BSTR bstr;
1199     LONG l;
1200 
1201     VariantInit(&v);
1202 
1203     doc = create_document(&IID_IXMLDOMDocument2);
1204     doc2 = create_document(&IID_IXMLDOMDocument2);
1205     schema = create_document(&IID_IXMLDOMDocument2);
1206     cache = create_cache(&IID_IXMLDOMSchemaCollection);
1207 
1208     if (!doc || !doc2 || !schema || !cache)
1209     {
1210         if (doc)    IXMLDOMDocument2_Release(doc);
1211         if (doc2)   IXMLDOMDocument2_Release(doc2);
1212         if (schema) IXMLDOMDocument2_Release(schema);
1213         if (cache)  IXMLDOMSchemaCollection_Release(cache);
1214         return;
1215     }
1216 
1217     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szDatatypeXML), &b);
1218     EXPECT_HR(hr, S_OK);
1219     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1220 
1221     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(szDatatypeXML), &b);
1222     EXPECT_HR(hr, S_OK);
1223     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1224 
1225     hr = IXMLDOMDocument2_loadXML(schema, _bstr_(szDatatypeXDR), &b);
1226     EXPECT_HR(hr, S_OK);
1227     ok(b == VARIANT_TRUE, "failed to load XML string\n");
1228 
1229     err = NULL;
1230     hr = IXMLDOMDocument2_validate(doc, &err);
1231     EXPECT_HR(hr, S_FALSE);
1232     ok(err != NULL, "domdoc_validate() should always set err\n");
1233     hr = IXMLDOMParseError_get_errorCode(err, &l);
1234     EXPECT_HR(hr, S_OK);
1235     ok(l == E_XML_NODTD, "got %08x\n", l);
1236     IXMLDOMParseError_Release(err);
1237 
1238     err = NULL;
1239     hr = IXMLDOMDocument2_validate(doc2, &err);
1240     EXPECT_HR(hr, S_FALSE);
1241     ok(err != NULL, "domdoc_validate() should always set err\n");
1242     hr = IXMLDOMParseError_get_errorCode(err, &l);
1243     EXPECT_HR(hr, S_OK);
1244     ok(l == E_XML_NODTD, "got %08x\n", l);
1245     IXMLDOMParseError_Release(err);
1246 
1247     /* now load the schema */
1248     V_VT(&v) = VT_DISPATCH;
1249     V_DISPATCH(&v) = NULL;
1250     hr = IXMLDOMDocument2_QueryInterface(schema, &IID_IDispatch, (void**)&V_DISPATCH(&v));
1251     EXPECT_HR(hr, S_OK);
1252     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1253     hr = IXMLDOMSchemaCollection_add(cache, _bstr_("urn:x-schema:datatype-test-xdr"), v);
1254     EXPECT_HR(hr, S_OK);
1255     VariantClear(&v);
1256 
1257     /* associate the cache to the doc */
1258     V_VT(&v) = VT_DISPATCH;
1259     V_DISPATCH(&v) = NULL;
1260     hr = IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&v));
1261     EXPECT_HR(hr, S_OK);
1262     ok(V_DISPATCH(&v) != NULL, "failed to get IDispatch interface\n");
1263     hr = IXMLDOMDocument2_putref_schemas(doc2, v);
1264     EXPECT_HR(hr, S_OK);
1265     VariantClear(&v);
1266 
1267     /* validate the doc */
1268     err = NULL;
1269     l = 0;
1270     bstr = NULL;
1271     hr = IXMLDOMDocument2_validate(doc2, &err);
1272     EXPECT_HR(hr, S_OK);
1273     ok(err != NULL, "domdoc_validate() should always set err\n");
1274     hr = IXMLDOMParseError_get_errorCode(err, &l);
1275     EXPECT_HR(hr, S_FALSE);
1276     hr = IXMLDOMParseError_get_reason(err, &bstr);
1277     EXPECT_HR(hr, S_FALSE);
1278     ok(l == 0, "got %08x : %s\n", l, wine_dbgstr_w(bstr));
1279     SysFreeString(bstr);
1280     IXMLDOMParseError_Release(err);
1281 
1282     ptr = xdr_datatypes_data;
1283     while (ptr->query)
1284     {
1285         IXMLDOMNode* node = NULL;
1286         VARIANT type;
1287 
1288         /* check data types without the schema */
1289         hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_(ptr->query), &node);
1290         EXPECT_HR(hr, S_OK);
1291         ok(node != NULL, "expected node\n");
1292 
1293         V_VT(&type) = VT_EMPTY;
1294         V_BSTR(&type) = (void*)-1;
1295         hr = IXMLDOMNode_get_dataType(node, &type);
1296         EXPECT_HR(hr, S_FALSE);
1297         ok(V_VT(&type) == VT_NULL, "got type %i\n", V_VT(&type));
1298         /* when returning VT_NULL, the pointer is set to NULL */
1299         ok(V_BSTR(&type) == NULL, "got %p\n", V_BSTR(&type));
1300 
1301         VariantClear(&type);
1302         hr = IXMLDOMNode_get_nodeTypedValue(node, &type);
1303         EXPECT_HR(hr, S_OK);
1304         ok(V_VT(&type) == VT_BSTR, "got variant type %i\n", V_VT(&v));
1305         VariantClear(&type);
1306         IXMLDOMNode_Release(node);
1307 
1308         /* check the data with schema */
1309         node = NULL;
1310         hr = IXMLDOMDocument2_selectSingleNode(doc2, _bstr_(ptr->query), &node);
1311         EXPECT_HR(hr, S_OK);
1312         ok(node != NULL, "expected node\n");
1313 
1314         V_VT(&type) = VT_EMPTY;
1315         hr = IXMLDOMNode_get_dataType(node, &type);
1316         if (ptr->typename)
1317         {
1318             EXPECT_HR(hr, S_OK);
1319             ok(V_VT(&type) == VT_BSTR, "got type %i\n", V_VT(&type));
1320             ok(!lstrcmpW(V_BSTR(&type), _bstr_(ptr->typename)), "got %s\n", wine_dbgstr_w(V_BSTR(&type)));
1321         }
1322         else
1323         {
1324             EXPECT_HR(hr, S_FALSE);
1325             ok(V_VT(&type) == VT_NULL, "%s: got type %i\n", ptr->query, V_VT(&type));
1326         }
1327         VariantClear(&type);
1328 
1329         VariantClear(&v);
1330         hr = IXMLDOMNode_get_nodeTypedValue(node, &v);
1331         EXPECT_HR(hr, S_OK);
1332 
1333         todo_wine_if(ptr->todo)
1334             ok(V_VT(&v) == ptr->type_schema, "%s: got variant type %i\n", ptr->query, V_VT(&v));
1335 
1336         switch (ptr->type_schema)
1337         {
1338         case VT_BOOL:
1339             ok(V_BOOL(&v) == VARIANT_TRUE, "got %x\n", V_BOOL(&v));
1340             break;
1341         case VT_I1:
1342             ok(V_I1(&v) == 42, "got %i\n", V_I1(&v));
1343             break;
1344         case VT_I2:
1345             ok(V_I2(&v) == 420, "got %i\n", V_I2(&v));
1346             break;
1347         case VT_I4:
1348             if (!strcmp(ptr->typename, "int"))
1349                 ok(V_I4(&v) == 42, "got %i\n", V_I4(&v));
1350             else if (!strcmp(ptr->typename, "char"))
1351             todo_wine
1352                 ok(V_I4(&v) == 'u', "got %x\n", V_I4(&v));
1353             else
1354                 ok(V_I4(&v) == -420000000, "got %i\n", V_I4(&v));
1355             break;
1356         case VT_I8:
1357             expect_int64(V_I8(&v), -4200000000, 10);
1358             break;
1359         case VT_R4:
1360             ok(V_R4(&v) == (float)3.14159265, "got %f\n", V_R4(&v));
1361             break;
1362         case VT_R8:
1363             if (!strcmp(ptr->typename, "float"))
1364                 ok(V_R8(&v) == (double)3.14159, "got %f\n", V_R8(&v));
1365             else
1366             todo_wine
1367                 ok(V_R8(&v) == (double)3.14159265358979323846, "got %.20f\n", V_R8(&v));
1368             break;
1369         case VT_UI1:
1370             ok(V_UI1(&v) == 0xFF, "got %02x\n", V_UI1(&v));
1371             break;
1372         case VT_UI2:
1373             ok(V_UI2(&v) == 0xFFFF, "got %04x\n", V_UI2(&v));
1374             break;
1375         case VT_UI4:
1376             ok(V_UI4(&v) == 0xFFFFFFFF, "got %08x\n", V_UI4(&v));
1377             break;
1378         case VT_UI8:
1379             expect_uint64(V_UI8(&v), 0xFFFFFFFFFFFFFFFF, 16);
1380             break;
1381         default:
1382             ;
1383         }
1384 
1385         VariantClear(&v);
1386 
1387         IXMLDOMNode_Release(node);
1388 
1389         ptr++;
1390     }
1391 
1392     IXMLDOMDocument2_Release(schema);
1393     IXMLDOMDocument2_Release(doc);
1394     IXMLDOMDocument2_Release(doc2);
1395     IXMLDOMSchemaCollection_Release(cache);
1396 
1397     free_bstrs();
1398 }
1399 
1400 static void test_validate_on_load(void)
1401 {
1402     IXMLDOMSchemaCollection2 *cache;
1403     VARIANT_BOOL b;
1404     HRESULT hr;
1405 
1406     cache = create_cache_version(40, &IID_IXMLDOMSchemaCollection2);
1407     if (!cache) return;
1408 
1409     hr = IXMLDOMSchemaCollection2_get_validateOnLoad(cache, NULL);
1410     EXPECT_HR(hr, E_POINTER);
1411 
1412     b = VARIANT_FALSE;
1413     hr = IXMLDOMSchemaCollection2_get_validateOnLoad(cache, &b);
1414     EXPECT_HR(hr, S_OK);
1415     ok(b == VARIANT_TRUE, "got %d\n", b);
1416 
1417     IXMLDOMSchemaCollection2_Release(cache);
1418 }
1419 
1420 static void test_obj_dispex(IUnknown *obj)
1421 {
1422     static const WCHAR testW[] = {'t','e','s','t','p','r','o','p',0};
1423     static const WCHAR starW[] = {'*',0};
1424     DISPID dispid = DISPID_SAX_XMLREADER_GETFEATURE;
1425     IDispatchEx *dispex;
1426     IUnknown *unk;
1427     DWORD props;
1428     UINT ticnt;
1429     HRESULT hr;
1430     BSTR name;
1431 
1432     hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
1433     EXPECT_HR(hr, S_OK);
1434     if (FAILED(hr)) return;
1435 
1436     ticnt = 0;
1437     hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
1438     EXPECT_HR(hr, S_OK);
1439     ok(ticnt == 1, "ticnt=%u\n", ticnt);
1440 
1441     name = SysAllocString(starW);
1442     hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
1443     EXPECT_HR(hr, E_NOTIMPL);
1444     SysFreeString(name);
1445 
1446     hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
1447     EXPECT_HR(hr, E_NOTIMPL);
1448 
1449     props = 0;
1450     hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
1451     EXPECT_HR(hr, E_NOTIMPL);
1452     ok(props == 0, "expected 0 got %d\n", props);
1453 
1454     hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
1455     EXPECT_HR(hr, E_NOTIMPL);
1456     if (SUCCEEDED(hr)) SysFreeString(name);
1457 
1458     hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_SCHEMACOLLECTION_ADD, &dispid);
1459     EXPECT_HR(hr, E_NOTIMPL);
1460 
1461     unk = (IUnknown*)0xdeadbeef;
1462     hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
1463     EXPECT_HR(hr, E_NOTIMPL);
1464     ok(unk == (IUnknown*)0xdeadbeef, "got %p\n", unk);
1465 
1466     name = SysAllocString(testW);
1467     hr = IDispatchEx_GetDispID(dispex, name, fdexNameEnsure, &dispid);
1468     ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
1469     SysFreeString(name);
1470 
1471     IDispatchEx_Release(dispex);
1472 }
1473 
1474 static void test_dispex(void)
1475 {
1476     IXMLDOMSchemaCollection *cache;
1477     IDispatchEx *dispex;
1478     IUnknown *unk;
1479     HRESULT hr;
1480     DISPPARAMS dispparams;
1481     VARIANT arg, ret;
1482 
1483     cache = create_cache(&IID_IXMLDOMSchemaCollection);
1484     if (!cache) return;
1485 
1486     hr = IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IUnknown, (void**)&unk);
1487     EXPECT_HR(hr, S_OK);
1488     test_obj_dispex(unk);
1489     IUnknown_Release(unk);
1490 
1491     hr = IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatchEx, (void**)&dispex);
1492     ok(hr == S_OK, "got 0x%08x\n", hr);
1493 
1494     V_VT(&arg) = VT_I4;
1495     V_I4(&arg) = 0;
1496     dispparams.cArgs = 1;
1497     dispparams.cNamedArgs = 0;
1498     dispparams.rgdispidNamedArgs = NULL;
1499     dispparams.rgvarg = &arg;
1500 
1501     V_VT(&ret) = VT_EMPTY;
1502     V_DISPATCH(&ret) = (void*)0x1;
1503     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
1504     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
1505     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
1506     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
1507 
1508     IDispatchEx_Release(dispex);
1509     IXMLDOMSchemaCollection_Release(cache);
1510 
1511     cache = create_cache_version(60, &IID_IXMLDOMSchemaCollection);
1512     if (cache)
1513     {
1514         test_obj_dispex((IUnknown*)cache);
1515         IXMLDOMSchemaCollection_Release(cache);
1516     }
1517 }
1518 
1519 static void test_get(void)
1520 {
1521     IXMLDOMSchemaCollection2 *cache;
1522     IXMLDOMNode *node;
1523     HRESULT hr;
1524 
1525     cache = create_cache_version(60, &IID_IXMLDOMSchemaCollection2);
1526     if (!cache) return;
1527 
1528     hr = IXMLDOMSchemaCollection2_get(cache, NULL, NULL);
1529     ok(hr == E_NOTIMPL || hr == E_POINTER /* win8 */, "got %08x\n", hr);
1530 
1531     hr = IXMLDOMSchemaCollection2_get(cache, _bstr_("uri"), &node);
1532     EXPECT_HR(hr, E_NOTIMPL);
1533 
1534     IXMLDOMSchemaCollection2_Release(cache);
1535 
1536     cache = create_cache_version(40, &IID_IXMLDOMSchemaCollection2);
1537     if (!cache) return;
1538 
1539     hr = IXMLDOMSchemaCollection2_get(cache, NULL, NULL);
1540     EXPECT_HR(hr, E_POINTER);
1541 
1542     hr = IXMLDOMSchemaCollection2_get(cache, _bstr_("uri"), &node);
1543     EXPECT_HR(hr, S_OK);
1544 
1545     IXMLDOMSchemaCollection2_Release(cache);
1546     free_bstrs();
1547 }
1548 
1549 static void test_remove(void)
1550 {
1551     IXMLDOMSchemaCollection2 *cache;
1552     IXMLDOMDocument *doc;
1553     VARIANT_BOOL b;
1554     HRESULT hr;
1555     VARIANT v;
1556     LONG len;
1557 
1558     cache = create_cache_version(60, &IID_IXMLDOMSchemaCollection2);
1559     if (!cache) return;
1560 
1561     doc = create_document_version(60, &IID_IXMLDOMDocument);
1562     ok(doc != NULL, "got %p\n", doc);
1563 
1564     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsd_schema1_xml), &b);
1565     EXPECT_HR(hr, S_OK);
1566 
1567     V_VT(&v) = VT_DISPATCH;
1568     V_DISPATCH(&v) = (IDispatch*)doc;
1569     hr = IXMLDOMSchemaCollection2_add(cache, _bstr_(xsd_schema1_uri), v);
1570     EXPECT_HR(hr, S_OK);
1571 
1572     len = -1;
1573     hr = IXMLDOMSchemaCollection2_get_length(cache, &len);
1574     EXPECT_HR(hr, S_OK);
1575     ok(len == 1, "got %d\n", len);
1576 
1577     /* ::remove() is a stub for version 6 */
1578     hr = IXMLDOMSchemaCollection2_remove(cache, NULL);
1579     EXPECT_HR(hr, E_NOTIMPL);
1580 
1581     hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_("invaliduri"));
1582     EXPECT_HR(hr, E_NOTIMPL);
1583 
1584     hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_(xsd_schema1_uri));
1585     EXPECT_HR(hr, E_NOTIMPL);
1586 
1587     len = -1;
1588     hr = IXMLDOMSchemaCollection2_get_length(cache, &len);
1589     EXPECT_HR(hr, S_OK);
1590     ok(len == 1, "got %d\n", len);
1591 
1592     IXMLDOMDocument_Release(doc);
1593     IXMLDOMSchemaCollection2_Release(cache);
1594     free_bstrs();
1595 
1596     /* ::remove() works for version 4 */
1597     cache = create_cache_version(40, &IID_IXMLDOMSchemaCollection2);
1598     if (!cache) return;
1599 
1600     doc = create_document_version(40, &IID_IXMLDOMDocument);
1601     ok(doc != NULL, "got %p\n", doc);
1602 
1603     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsd_schema1_xml), &b);
1604     EXPECT_HR(hr, S_OK);
1605 
1606     V_VT(&v) = VT_DISPATCH;
1607     V_DISPATCH(&v) = (IDispatch*)doc;
1608     hr = IXMLDOMSchemaCollection2_add(cache, _bstr_(xsd_schema1_uri), v);
1609     EXPECT_HR(hr, S_OK);
1610 
1611     len = -1;
1612     hr = IXMLDOMSchemaCollection2_get_length(cache, &len);
1613     EXPECT_HR(hr, S_OK);
1614     ok(len == 1, "got %d\n", len);
1615 
1616     hr = IXMLDOMSchemaCollection2_remove(cache, NULL);
1617     EXPECT_HR(hr, S_OK);
1618 
1619     hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_("invaliduri"));
1620     EXPECT_HR(hr, S_OK);
1621 
1622     len = -1;
1623     hr = IXMLDOMSchemaCollection2_get_length(cache, &len);
1624     EXPECT_HR(hr, S_OK);
1625     ok(len == 1, "got %d\n", len);
1626 
1627     hr = IXMLDOMSchemaCollection2_remove(cache, _bstr_(xsd_schema1_uri));
1628     EXPECT_HR(hr, S_OK);
1629 
1630     len = -1;
1631     hr = IXMLDOMSchemaCollection2_get_length(cache, &len);
1632     EXPECT_HR(hr, S_OK);
1633     ok(len == 0, "got %d\n", len);
1634 
1635     IXMLDOMDocument_Release(doc);
1636     IXMLDOMSchemaCollection2_Release(cache);
1637 
1638     free_bstrs();
1639 }
1640 
1641 static void test_ifaces(void)
1642 {
1643     IXMLDOMSchemaCollection2 *cache;
1644     IUnknown *unk;
1645     HRESULT hr;
1646 
1647     cache = create_cache_version(60, &IID_IXMLDOMSchemaCollection2);
1648     if (!cache) return;
1649 
1650     /* CLSID_XMLSchemaCache60 is returned as an interface (the same as IXMLDOMSchemaCollection2). */
1651     hr = IXMLDOMSchemaCollection2_QueryInterface(cache, &CLSID_XMLSchemaCache60, (void**)&unk);
1652     ok (hr == S_OK, "Could not get CLSID_XMLSchemaCache60 iface: %08x\n", hr);
1653     ok (unk == (IUnknown*)cache, "unk != cache\n");
1654 
1655     IUnknown_Release(unk);
1656     IXMLDOMSchemaCollection2_Release(cache);
1657 }
1658 
1659 START_TEST(schema)
1660 {
1661     HRESULT r;
1662 
1663     r = CoInitialize( NULL );
1664     ok( r == S_OK, "failed to init com\n");
1665 
1666     test_schema_refs();
1667     test_collection_refs();
1668     test_length();
1669     test_collection_content();
1670     test_XDR_schemas();
1671     test_XDR_datatypes();
1672     test_validate_on_load();
1673     test_dispex();
1674     test_get();
1675     test_remove();
1676     test_ifaces();
1677 
1678     CoUninitialize();
1679 }
1680