1 /*
2  * XML test
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2007-2008 Alistair Leslie-Hughes
6  * Copyright 2010-2011 Adam Martinson for CodeWeavers
7  * Copyright 2010-2013 Nikolay Sivov for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 
25 #define COBJMACROS
26 #define CONST_VTABLE
27 
28 #include <stdio.h>
29 #include <assert.h>
30 
31 #include "windows.h"
32 
33 #include "msxml.h"
34 #include "msxml2.h"
35 #include "msxml2did.h"
36 #include "ole2.h"
37 #include "dispex.h"
38 #include "objsafe.h"
39 #include "mshtml.h"
40 #include "initguid.h"
41 #include "asptlb.h"
42 
43 #include "wine/heap.h"
44 #include "wine/test.h"
45 
46 /* undef the #define in msxml2 so that we can access all versions */
47 #undef CLSID_DOMDocument
48 
49 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
50 DEFINE_GUID(IID_transformdest_unknown,0xf5078f3a,0xc551,0x11d3,0x89,0xb9,0x00,0x00,0xf8,0x1f,0xe2,0x21);
51 
52 static int g_unexpectedcall, g_expectedcall;
53 
54 struct msxmlsupported_data_t
55 {
56     const GUID *clsid;
57     const char *name;
58     const IID  *ifaces[3];
59     BOOL        supported[3];
60 };
61 
62 static struct msxmlsupported_data_t domdoc_support_data[] =
63 {
64     { &CLSID_DOMDocument,   "DOMDocument",   {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
65     { &CLSID_DOMDocument2,  "DOMDocument2",  {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
66     { &CLSID_DOMDocument30, "DOMDocument30", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
67     { &CLSID_DOMDocument40, "DOMDocument40", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
68     { &CLSID_DOMDocument60, "DOMDocument60", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3} },
69     { &CLSID_FreeThreadedDOMDocument, "FreeThreadedDOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
70     { &CLSID_XMLSchemaCache, "XMLSchemaCache", {&IID_IXMLDOMSchemaCollection} },
71     { &CLSID_XSLTemplate,    "XSLTemplate", {&IID_IXSLTemplate} },
72     { &CLSID_MXNamespaceManager40, "MXNamespaceManager40", {&IID_IMXNamespaceManager} },
73     { NULL }
74 };
75 
76 static const char *debugstr_msxml_guid(REFIID riid)
77 {
78     if(!riid)
79         return "(null)";
80 
81     if (IsEqualIID(&IID_IXMLDOMDocument, riid))
82         return "IXMLDOMDocument";
83     else if (IsEqualIID(&IID_IXMLDOMDocument2, riid))
84         return "IXMLDOMDocument2";
85     else if (IsEqualIID(&IID_IXMLDOMDocument3, riid))
86         return "IXMLDOMDocument3";
87     else if (IsEqualIID(&IID_IXMLDOMSchemaCollection, riid))
88         return "IXMLDOMSchemaCollection";
89     else if (IsEqualIID(&IID_IXSLTemplate, riid))
90         return "IXSLTemplate";
91     else if (IsEqualIID(&IID_IMXNamespaceManager, riid))
92         return "IMXNamespaceManager";
93     else
94         return wine_dbgstr_guid(riid);
95 }
96 
97 static void get_class_support_data(struct msxmlsupported_data_t *table)
98 {
99     while (table->clsid)
100     {
101         IUnknown *unk;
102         HRESULT hr;
103         int i;
104 
105         for (i = 0; i < ARRAY_SIZE(table->ifaces) && table->ifaces[i] != NULL; i++)
106         {
107             hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, table->ifaces[i], (void**)&unk);
108             if (hr == S_OK) IUnknown_Release(unk);
109 
110             table->supported[i] = hr == S_OK;
111             if (hr != S_OK) win_skip("class %s, iface %s not supported\n", table->name, debugstr_msxml_guid(table->ifaces[i]));
112         }
113 
114         table++;
115     }
116 }
117 
118 static BOOL is_clsid_supported(const GUID *clsid, REFIID riid)
119 {
120     const struct msxmlsupported_data_t *table = domdoc_support_data;
121     while (table->clsid)
122     {
123         if (table->clsid == clsid)
124         {
125             int i;
126 
127             for (i = 0; i < ARRAY_SIZE(table->ifaces) && table->ifaces[i] != NULL; i++)
128                 if (table->ifaces[i] == riid) return table->supported[i];
129         }
130 
131         table++;
132     }
133     return FALSE;
134 }
135 
136 typedef struct
137 {
138     IDispatch IDispatch_iface;
139     LONG ref;
140 } dispevent;
141 
142 static inline dispevent *impl_from_IDispatch( IDispatch *iface )
143 {
144     return CONTAINING_RECORD(iface, dispevent, IDispatch_iface);
145 }
146 
147 static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
148 {
149     *ppvObject = NULL;
150 
151     if ( IsEqualGUID( riid, &IID_IDispatch) ||
152          IsEqualGUID( riid, &IID_IUnknown) )
153     {
154         *ppvObject = iface;
155     }
156     else
157         return E_NOINTERFACE;
158 
159     IDispatch_AddRef( iface );
160 
161     return S_OK;
162 }
163 
164 static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
165 {
166     dispevent *This = impl_from_IDispatch( iface );
167     return InterlockedIncrement( &This->ref );
168 }
169 
170 static ULONG WINAPI dispevent_Release(IDispatch *iface)
171 {
172     dispevent *This = impl_from_IDispatch( iface );
173     ULONG ref = InterlockedDecrement( &This->ref );
174 
175     if (ref == 0)
176         heap_free(This);
177 
178     return ref;
179 }
180 
181 static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
182 {
183     g_unexpectedcall++;
184     *pctinfo = 0;
185     return S_OK;
186 }
187 
188 static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
189         LCID lcid, ITypeInfo **ppTInfo)
190 {
191     g_unexpectedcall++;
192     return S_OK;
193 }
194 
195 static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
196         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
197 {
198     g_unexpectedcall++;
199     return S_OK;
200 }
201 
202 static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
203         LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
204         EXCEPINFO *excepInfo, UINT *argErr)
205 {
206     ok(member == 0, "expected 0 member, got %d\n", member);
207     ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
208     ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
209 
210     ok(params->cArgs == 0, "got %d\n", params->cArgs);
211     ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
212     ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
213     ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
214 
215     ok(result == NULL, "got %p\n", result);
216     ok(excepInfo == NULL, "got %p\n", excepInfo);
217     ok(argErr == NULL, "got %p\n", argErr);
218 
219     g_expectedcall++;
220     return E_FAIL;
221 }
222 
223 static const IDispatchVtbl dispeventVtbl =
224 {
225     dispevent_QueryInterface,
226     dispevent_AddRef,
227     dispevent_Release,
228     dispevent_GetTypeInfoCount,
229     dispevent_GetTypeInfo,
230     dispevent_GetIDsOfNames,
231     dispevent_Invoke
232 };
233 
234 static IDispatch* create_dispevent(void)
235 {
236     dispevent *event = heap_alloc(sizeof(*event));
237 
238     event->IDispatch_iface.lpVtbl = &dispeventVtbl;
239     event->ref = 1;
240 
241     return (IDispatch*)&event->IDispatch_iface;
242 }
243 
244 /* IStream */
245 static HRESULT WINAPI istream_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
246 {
247     *ppvObject = NULL;
248 
249     if (IsEqualGUID(riid, &IID_IStream) ||
250         IsEqualGUID(riid, &IID_IUnknown))
251         *ppvObject = iface;
252     else
253         return E_NOINTERFACE;
254 
255     return S_OK;
256 }
257 
258 static ULONG WINAPI istream_AddRef(IStream *iface)
259 {
260     return 2;
261 }
262 
263 static ULONG WINAPI istream_Release(IStream *iface)
264 {
265     return 1;
266 }
267 
268 static HRESULT WINAPI istream_Read(IStream *iface, void *ptr, ULONG len, ULONG *pread)
269 {
270     ok(0, "unexpected call\n");
271     return E_NOTIMPL;
272 }
273 
274 static HRESULT WINAPI istream_Write(IStream *iface, const void *ptr, ULONG len, ULONG *written)
275 {
276     *written = len/2;
277     return S_OK;
278 }
279 
280 static HRESULT WINAPI istream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
281 {
282     ok(0, "unexpected call\n");
283     return E_NOTIMPL;
284 }
285 
286 static HRESULT WINAPI istream_SetSize(IStream *iface, ULARGE_INTEGER size)
287 {
288     ok(0, "unexpected call\n");
289     return E_NOTIMPL;
290 }
291 
292 static HRESULT WINAPI istream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len,
293         ULARGE_INTEGER *pread, ULARGE_INTEGER *written)
294 {
295     ok(0, "unexpected call\n");
296     return E_NOTIMPL;
297 }
298 
299 static HRESULT WINAPI istream_Commit(IStream *iface, DWORD flags)
300 {
301     ok(0, "unexpected call\n");
302     return E_NOTIMPL;
303 }
304 
305 static HRESULT WINAPI istream_Revert(IStream *iface)
306 {
307     ok(0, "unexpected call\n");
308     return E_NOTIMPL;
309 }
310 
311 static HRESULT WINAPI istream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
312         ULARGE_INTEGER len, DWORD locktype)
313 {
314     ok(0, "unexpected call\n");
315     return E_NOTIMPL;
316 }
317 
318 static HRESULT WINAPI istream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
319         ULARGE_INTEGER len, DWORD locktype)
320 {
321     ok(0, "unexpected call\n");
322     return E_NOTIMPL;
323 }
324 
325 static HRESULT WINAPI istream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flag)
326 {
327     ok(0, "unexpected call\n");
328     return E_NOTIMPL;
329 }
330 
331 static HRESULT WINAPI istream_Clone(IStream *iface, IStream **stream)
332 {
333     ok(0, "unexpected call\n");
334     return E_NOTIMPL;
335 }
336 
337 static const IStreamVtbl StreamVtbl = {
338     istream_QueryInterface,
339     istream_AddRef,
340     istream_Release,
341     istream_Read,
342     istream_Write,
343     istream_Seek,
344     istream_SetSize,
345     istream_CopyTo,
346     istream_Commit,
347     istream_Revert,
348     istream_LockRegion,
349     istream_UnlockRegion,
350     istream_Stat,
351     istream_Clone
352 };
353 
354 static IStream savestream = { &StreamVtbl };
355 
356 static HRESULT WINAPI response_QI(IResponse *iface, REFIID riid, void **obj)
357 {
358     if (IsEqualIID(&IID_IResponse, riid) ||
359             IsEqualIID(&IID_IDispatch, riid) ||
360             IsEqualIID(&IID_IUnknown, riid))
361     {
362         *obj = iface;
363         return S_OK;
364     }
365 
366     if (!IsEqualIID(&IID_IStream, riid) && !IsEqualIID(&IID_ISequentialStream, riid))
367         ok(0, "unexpected call\n");
368     return E_NOINTERFACE;
369 }
370 
371 static ULONG WINAPI response_AddRef(IResponse *iface)
372 {
373     return 2;
374 }
375 
376 static ULONG WINAPI response_Release(IResponse *iface)
377 {
378     return 1;
379 }
380 
381 static HRESULT WINAPI response_GetTypeInfoCount(IResponse *iface, UINT *count)
382 {
383     ok(0, "unexpected call\n");
384     return E_NOTIMPL;
385 }
386 
387 static HRESULT WINAPI response_GetTypeInfo(IResponse *iface, UINT ti, LCID lcid, ITypeInfo **tinfo)
388 {
389     ok(0, "unexpected call\n");
390     return E_NOTIMPL;
391 }
392 
393 static HRESULT WINAPI response_GetIDsOfNames(IResponse *iface, REFIID riid, LPOLESTR *names,
394         UINT cnames, LCID lcid, DISPID *rgDispId)
395 {
396     ok(0, "unexpected call\n");
397     return E_NOTIMPL;
398 }
399 
400 static HRESULT WINAPI response_Invoke(IResponse *iface, DISPID dispid, REFIID riid, LCID lcid,
401     WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
402 {
403     ok(0, "unexpected call\n");
404     return E_NOTIMPL;
405 }
406 
407 static HRESULT WINAPI response_get_Buffer(IResponse *iface, VARIANT_BOOL *fIsBuffering)
408 {
409     ok(0, "unexpected call\n");
410     return E_NOTIMPL;
411 }
412 
413 static HRESULT WINAPI response_put_Buffer(IResponse *iface, VARIANT_BOOL fIsBuffering)
414 {
415     ok(0, "unexpected call\n");
416     return E_NOTIMPL;
417 }
418 
419 static HRESULT WINAPI response_get_ContentType(IResponse *iface, BSTR *pbstrContentTypeRet)
420 {
421     ok(0, "unexpected call\n");
422     return E_NOTIMPL;
423 }
424 
425 static HRESULT WINAPI response_put_ContentType(IResponse *iface, BSTR bstrContentType)
426 {
427     ok(0, "unexpected call\n");
428     return E_NOTIMPL;
429 }
430 
431 static HRESULT WINAPI response_get_Expires(IResponse *iface, VARIANT *pvarExpiresMinutesRet)
432 {
433     ok(0, "unexpected call\n");
434     return E_NOTIMPL;
435 }
436 
437 static HRESULT WINAPI response_put_Expires(IResponse *iface, LONG lExpiresMinutes)
438 {
439     ok(0, "unexpected call\n");
440     return E_NOTIMPL;
441 }
442 
443 static HRESULT WINAPI response_get_ExpiresAbsolute(IResponse *iface, VARIANT *pvarExpiresRet)
444 {
445     ok(0, "unexpected call\n");
446     return E_NOTIMPL;
447 }
448 
449 static HRESULT WINAPI response_put_ExpiresAbsolute(IResponse *iface, DATE dtExpires)
450 {
451     ok(0, "unexpected call\n");
452     return E_NOTIMPL;
453 }
454 
455 static HRESULT WINAPI response_get_Cookies(IResponse *iface, IRequestDictionary **ppCookies)
456 {
457     ok(0, "unexpected call\n");
458     return E_NOTIMPL;
459 }
460 
461 static HRESULT WINAPI response_get_Status(IResponse *iface, BSTR *pbstrStatusRet)
462 {
463     ok(0, "unexpected call\n");
464     return E_NOTIMPL;
465 }
466 
467 static HRESULT WINAPI response_put_Status(IResponse *iface, BSTR bstrStatus)
468 {
469     ok(0, "unexpected call\n");
470     return E_NOTIMPL;
471 }
472 
473 static HRESULT WINAPI response_Add(IResponse *iface, BSTR bstrHeaderValue, BSTR bstrHeaderName)
474 {
475     ok(0, "unexpected call\n");
476     return E_NOTIMPL;
477 }
478 
479 static HRESULT WINAPI response_AddHeader(IResponse *iface, BSTR bstrHeaderName, BSTR bstrHeaderValue)
480 {
481     ok(0, "unexpected call\n");
482     return E_NOTIMPL;
483 }
484 
485 static HRESULT WINAPI response_AppendToLog(IResponse *iface, BSTR bstrLogEntry)
486 {
487     ok(0, "unexpected call\n");
488     return E_NOTIMPL;
489 }
490 
491 static HRESULT WINAPI response_BinaryWrite(IResponse *iface, VARIANT input)
492 {
493     HRESULT hr;
494     LONG bound;
495     UINT dim;
496 
497     ok(V_VT(&input) == (VT_ARRAY | VT_UI1), "got wrong input type %x\n", V_VT(&input));
498 
499     dim = SafeArrayGetDim(V_ARRAY(&input));
500     ok(dim == 1, "got wrong array dimensions %u\n", dim);
501 
502     bound = 1;
503     hr = SafeArrayGetLBound(V_ARRAY(&input), 1, &bound);
504     ok(hr == S_OK, "got %#x\n", hr);
505     ok(bound == 0, "wrong array low bound %d\n", bound);
506 
507     bound = 0;
508     hr = SafeArrayGetUBound(V_ARRAY(&input), 1, &bound);
509     ok(hr == S_OK, "got %#x\n", hr);
510     ok(bound > 0, "wrong array high bound %d\n", bound);
511 
512     return E_NOTIMPL;
513 }
514 
515 static HRESULT WINAPI response_Clear(IResponse *iface)
516 {
517     ok(0, "unexpected call\n");
518     return E_NOTIMPL;
519 }
520 
521 static HRESULT WINAPI response_End(IResponse *iface)
522 {
523     ok(0, "unexpected call\n");
524     return E_NOTIMPL;
525 }
526 
527 static HRESULT WINAPI response_Flush(IResponse *iface)
528 {
529     ok(0, "unexpected call\n");
530     return E_NOTIMPL;
531 }
532 
533 static HRESULT WINAPI response_Redirect(IResponse *iface, BSTR bstrURL)
534 {
535     ok(0, "unexpected call\n");
536     return E_NOTIMPL;
537 }
538 
539 static HRESULT WINAPI response_Write(IResponse *iface, VARIANT varText)
540 {
541     ok(0, "unexpected call\n");
542     return E_NOTIMPL;
543 }
544 
545 static HRESULT WINAPI response_WriteBlock(IResponse *iface, short iBlockNumber)
546 {
547     ok(0, "unexpected call\n");
548     return E_NOTIMPL;
549 }
550 
551 static HRESULT WINAPI response_IsClientConnected(IResponse *iface, VARIANT_BOOL *pfIsClientConnected)
552 {
553     ok(0, "unexpected call\n");
554     return E_NOTIMPL;
555 }
556 
557 static HRESULT WINAPI response_get_CharSet(IResponse *iface, BSTR *pbstrCharSetRet)
558 {
559     ok(0, "unexpected call\n");
560     return E_NOTIMPL;
561 }
562 
563 static HRESULT WINAPI response_put_CharSet(IResponse *iface, BSTR bstrCharSet)
564 {
565     ok(0, "unexpected call\n");
566     return E_NOTIMPL;
567 }
568 
569 static HRESULT WINAPI response_Pics(IResponse *iface, BSTR bstrHeaderValue)
570 {
571     ok(0, "unexpected call\n");
572     return E_NOTIMPL;
573 }
574 
575 static HRESULT WINAPI response_get_CacheControl(IResponse *iface, BSTR *pbstrCacheControl)
576 {
577     ok(0, "unexpected call\n");
578     return E_NOTIMPL;
579 }
580 
581 static HRESULT WINAPI response_put_CacheControl(IResponse *iface, BSTR bstrCacheControl)
582 {
583     ok(0, "unexpected call\n");
584     return E_NOTIMPL;
585 }
586 
587 static HRESULT WINAPI response_get_CodePage(IResponse *iface, LONG *plvar)
588 {
589     ok(0, "unexpected call\n");
590     return E_NOTIMPL;
591 }
592 
593 static HRESULT WINAPI response_put_CodePage(IResponse *iface, LONG codepage)
594 {
595     ok(0, "unexpected call\n");
596     return E_NOTIMPL;
597 }
598 
599 static HRESULT WINAPI response_get_LCID(IResponse *iface, LONG *lcid)
600 {
601     ok(0, "unexpected call\n");
602     return E_NOTIMPL;
603 }
604 
605 static HRESULT WINAPI response_put_LCID(IResponse *iface, LONG lcid)
606 {
607     ok(0, "unexpected call\n");
608     return E_NOTIMPL;
609 }
610 
611 static const IResponseVtbl testresponsevtbl =
612 {
613     response_QI,
614     response_AddRef,
615     response_Release,
616     response_GetTypeInfoCount,
617     response_GetTypeInfo,
618     response_GetIDsOfNames,
619     response_Invoke,
620     response_get_Buffer,
621     response_put_Buffer,
622     response_get_ContentType,
623     response_put_ContentType,
624     response_get_Expires,
625     response_put_Expires,
626     response_get_ExpiresAbsolute,
627     response_put_ExpiresAbsolute,
628     response_get_Cookies,
629     response_get_Status,
630     response_put_Status,
631     response_Add,
632     response_AddHeader,
633     response_AppendToLog,
634     response_BinaryWrite,
635     response_Clear,
636     response_End,
637     response_Flush,
638     response_Redirect,
639     response_Write,
640     response_WriteBlock,
641     response_IsClientConnected,
642     response_get_CharSet,
643     response_put_CharSet,
644     response_Pics,
645     response_get_CacheControl,
646     response_put_CacheControl,
647     response_get_CodePage,
648     response_put_CodePage,
649     response_get_LCID,
650     response_put_LCID,
651 };
652 
653 static IResponse testresponse = { &testresponsevtbl };
654 
655 #define EXPECT_CHILDREN(node) _expect_children((IXMLDOMNode*)node, __LINE__)
656 static void _expect_children(IXMLDOMNode *node, int line)
657 {
658     VARIANT_BOOL b;
659     HRESULT hr;
660 
661     b = VARIANT_FALSE;
662     hr = IXMLDOMNode_hasChildNodes(node, &b);
663     ok_(__FILE__,line)(hr == S_OK, "hasChildNodes() failed, 0x%08x\n", hr);
664     ok_(__FILE__,line)(b == VARIANT_TRUE, "no children, %d\n", b);
665 }
666 
667 #define EXPECT_NO_CHILDREN(node) _expect_no_children((IXMLDOMNode*)node, __LINE__)
668 static void _expect_no_children(IXMLDOMNode *node, int line)
669 {
670     VARIANT_BOOL b;
671     HRESULT hr;
672 
673     b = VARIANT_TRUE;
674     hr = IXMLDOMNode_hasChildNodes(node, &b);
675     ok_(__FILE__,line)(hr == S_FALSE, "hasChildNodes() failed, 0x%08x\n", hr);
676     ok_(__FILE__,line)(b == VARIANT_FALSE, "no children, %d\n", b);
677 }
678 
679 #define EXPECT_REF(node,ref) _expect_ref((IUnknown*)node, ref, __LINE__)
680 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
681 {
682     ULONG rc;
683     IUnknown_AddRef(obj);
684     rc = IUnknown_Release(obj);
685     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
686 }
687 
688 #define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
689 static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
690 {
691     LONG length;
692     HRESULT hr;
693 
694     length = 0;
695     hr = IXMLDOMNodeList_get_length(list, &length);
696     ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
697     ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
698 }
699 
700 #define EXPECT_HR(hr,hr_exp) \
701     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
702 
703 #ifdef __REACTOS__
704 #define EXPECT_NOT_HR(hr,hr_exp) \
705     ok(hr != hr_exp, "got 0x%08x, expected not 0x%08x\n", hr, hr_exp)
706 #endif
707 
708 static const WCHAR szEmpty[] = { 0 };
709 static const WCHAR szIncomplete[] = {
710     '<','?','x','m','l',' ',
711     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
712 };
713 static const WCHAR szComplete1[] = {
714     '<','?','x','m','l',' ',
715     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
716     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
717 };
718 static const WCHAR szComplete2[] = {
719     '<','?','x','m','l',' ',
720     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
721     '<','a','>','<','/','a','>','\n',0
722 };
723 static const char complete4A[] =
724     "<?xml version=\'1.0\'?>\n"
725     "<lc dl=\'str1\'>\n"
726         "<bs vr=\'str2\' sz=\'1234\'>"
727             "fn1.txt\n"
728         "</bs>\n"
729         "<pr id=\'str3\' vr=\'1.2.3\' pn=\'wine 20050804\'>\n"
730             "fn2.txt\n"
731         "</pr>\n"
732         "<empty></empty>\n"
733         "<fo>\n"
734             "<ba>\n"
735                 "f1\n"
736             "</ba>\n"
737         "</fo>\n"
738     "</lc>\n";
739 
740 static const WCHAR szComplete5[] = {
741     '<','S',':','s','e','a','r','c','h',' ','x','m','l','n','s',':','D','=','"','D','A','V',':','"',' ',
742     'x','m','l','n','s',':','C','=','"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','o','f','f','i','c','e',':','c','l','i','p','g','a','l','l','e','r','y','"',
743     ' ','x','m','l','n','s',':','S','=','"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','o','f','f','i','c','e',':','c','l','i','p','g','a','l','l','e','r','y',':','s','e','a','r','c','h','"','>',
744         '<','S',':','s','c','o','p','e','>',
745             '<','S',':','d','e','e','p','>','/','<','/','S',':','d','e','e','p','>',
746         '<','/','S',':','s','c','o','p','e','>',
747         '<','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
748             '<','C',':','t','e','x','t','o','r','p','r','o','p','e','r','t','y','/','>',
749             'c','o','m','p','u','t','e','r',
750         '<','/','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
751     '<','/','S',':','s','e','a','r','c','h','>',0
752 };
753 
754 static const WCHAR szComplete6[] = {
755     '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'',' ',
756     'e','n','c','o','d','i','n','g','=','\'','W','i','n','d','o','w','s','-','1','2','5','2','\'','?','>','\n',
757     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
758 };
759 
760 static const char complete7[] = {
761     "<?xml version=\"1.0\"?>\n\t"
762     "<root>\n"
763     "\t<a/>\n"
764     "\t<b/>\n"
765     "\t<c/>\n"
766     "</root>"
767 };
768 
769 #define DECL_WIN_1252 \
770 "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
771 
772 static const char win1252xml[] =
773 DECL_WIN_1252
774 "<open></open>";
775 
776 static const char win1252decl[] =
777 DECL_WIN_1252
778 ;
779 
780 static const char nocontent[] = "no xml content here";
781 
782 static const char szExampleXML[] =
783 "<?xml version='1.0' encoding='utf-8'?>\n"
784 "<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' a=\"attr a\" foo:b=\"attr b\" >\n"
785 "    <elem>\n"
786 "        <a>A1 field</a>\n"
787 "        <b>B1 field</b>\n"
788 "        <c>C1 field</c>\n"
789 "        <d>D1 field</d>\n"
790 "        <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
791 "            <html xmlns='http://www.w3.org/1999/xhtml'>\n"
792 "                <![CDATA[]]> This is<strong> a</strong>  <i>description</i><dot>. </dot><bar:x/>\n"
793 "            </html>\n"
794 "            <html xml:space='preserve' xmlns='http://www.w3.org/1999/xhtml'>\n"
795 "                This is <strong>a</strong> <i>description</i> with preserved whitespace. <bar:x/>\n"
796 "            </html>\n"
797 "        </description>\n"
798 "    </elem>\n"
799 "\n"
800 "    <elem a='a'>\n"
801 "        <a>A2 field</a>\n"
802 "        <b>B2 field</b>\n"
803 "        <c type=\"old\">C2 field</c>\n"
804 "        <d>D2 field</d>\n"
805 "    </elem>\n"
806 "\n"
807 "    <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
808 "        <a>A3 field</a>\n"
809 "        <b>B3 field</b>\n"
810 "        <c>C3 field</c>\n"
811 "    </elem>\n"
812 "\n"
813 "    <elem>\n"
814 "        <a>A4 field</a>\n"
815 "        <b>B4 field</b>\n"
816 "        <foo:c>C4 field</foo:c>\n"
817 "        <d>D4 field</d>\n"
818 "    </elem>\n"
819 "</root>\n";
820 
821 static const char charrefsxml[] =
822 "<?xml version='1.0'?>"
823 "<a>"
824 "<b1> Text &#65; end </b1>"
825 "<b2>&#65;&#66; &#67; </b2>"
826 "</a>";
827 
828 static const CHAR szNodeTypesXML[] =
829 "<?xml version='1.0'?>"
830 "<!-- comment node 0 -->"
831 "<root id='0' depth='0'>"
832 "   <!-- comment node 1 -->"
833 "   text node 0"
834 "   <x id='1' depth='1'>"
835 "       <?foo value='PI for x'?>"
836 "       <!-- comment node 2 -->"
837 "       text node 1"
838 "       <a id='3' depth='2'/>"
839 "       <b id='4' depth='2'/>"
840 "       <c id='5' depth='2'/>"
841 "   </x>"
842 "   <y id='2' depth='1'>"
843 "       <?bar value='PI for y'?>"
844 "       <!-- comment node 3 -->"
845 "       text node 2"
846 "       <a id='6' depth='2'/>"
847 "       <b id='7' depth='2'/>"
848 "       <c id='8' depth='2'/>"
849 "   </y>"
850 "</root>";
851 
852 static const CHAR szTransformXML[] =
853 "<?xml version=\"1.0\"?>\n"
854 "<greeting>\n"
855 "Hello World\n"
856 "</greeting>";
857 
858 static  const CHAR szTransformSSXML[] =
859 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
860 "   <xsl:output method=\"html\"/>\n"
861 "   <xsl:template match=\"/\">\n"
862 "       <xsl:apply-templates select=\"greeting\"/>\n"
863 "   </xsl:template>\n"
864 "   <xsl:template match=\"greeting\">\n"
865 "       <html>\n"
866 "           <body>\n"
867 "               <h1>\n"
868 "                   <xsl:value-of select=\".\"/>\n"
869 "               </h1>\n"
870 "           </body>\n"
871 "       </html>\n"
872 "   </xsl:template>\n"
873 "</xsl:stylesheet>";
874 
875 static  const CHAR szTransformOutput[] =
876 "<html><body><h1>"
877 "Hello World"
878 "</h1></body></html>";
879 
880 static const CHAR szTypeValueXML[] =
881 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
882 "<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
883 "   <string>Wine</string>\n"
884 "   <string2 dt:dt=\"string\">String</string2>\n"
885 "   <number dt:dt=\"number\">12.44</number>\n"
886 "   <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
887 "   <int dt:dt=\"int\">-13</int>\n"
888 "   <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
889 "   <bool dt:dt=\"boolean\">1</bool>\n"
890 "   <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
891 "   <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
892 "   <date dt:dt=\"date\">3721-11-01</date>\n"
893 "   <time dt:dt=\"time\">13:57:12.31321</time>\n"
894 "   <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
895 "   <i1 dt:dt=\"i1\">-13</i1>\n"
896 "   <i2 dt:dt=\"i2\">31915</i2>\n"
897 "   <i4 dt:dt=\"i4\">-312232</i4>\n"
898 "   <ui1 dt:dt=\"ui1\">123</ui1>\n"
899 "   <ui2 dt:dt=\"ui2\">48282</ui2>\n"
900 "   <ui4 dt:dt=\"ui4\">949281</ui4>\n"
901 "   <r4 dt:dt=\"r4\">213124.0</r4>\n"
902 "   <r8 dt:dt=\"r8\">0.412</r8>\n"
903 "   <float dt:dt=\"float\">41221.421</float>\n"
904 "   <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
905 "   <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
906 "   <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
907 "   <binbase64_1 dt:dt=\"bin.base64\">\nYmFzZTY0\nIHRlc3Q=\n</binbase64_1>\n"
908 "   <binbase64_2 dt:dt=\"bin.base64\">\nYmF\r\t z  ZTY0\nIHRlc3Q=\n</binbase64_2>\n"
909 "</root>";
910 
911 static const CHAR szBasicTransformSSXMLPart1[] =
912 "<?xml version=\"1.0\"?>"
913 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
914 "<xsl:output method=\"html\"/>\n"
915 "<xsl:template match=\"/\">"
916 "<HTML><BODY><TABLE>"
917 "        <xsl:apply-templates select='document(\"";
918 
919 static const CHAR szBasicTransformSSXMLPart2[] =
920 "\")/bottle/wine'>"
921 "           <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
922 "        </xsl:apply-templates>"
923 "</TABLE></BODY></HTML>"
924 "</xsl:template>"
925 "<xsl:template match=\"bottle\">"
926 "   <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
927 "</xsl:template>"
928 "<xsl:template match=\"name\">"
929 "   <TD><xsl:apply-templates /></TD>"
930 "</xsl:template>"
931 "<xsl:template match=\"cost\">"
932 "   <TD><xsl:apply-templates /></TD>"
933 "</xsl:template>"
934 "</xsl:stylesheet>";
935 
936 static const CHAR szBasicTransformXML[] =
937 "<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
938 
939 static const CHAR szBasicTransformOutput[] =
940 "<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
941 
942 #define SZ_EMAIL_DTD \
943 "<!DOCTYPE email ["\
944 "   <!ELEMENT email         (recipients,from,reply-to?,subject,body,attachment*)>"\
945 "       <!ATTLIST email attachments IDREFS #REQUIRED>"\
946 "       <!ATTLIST email sent (yes|no) \"no\">"\
947 "   <!ELEMENT recipients    (to+,cc*)>"\
948 "   <!ELEMENT to            (#PCDATA)>"\
949 "       <!ATTLIST to name CDATA #IMPLIED>"\
950 "   <!ELEMENT cc            (#PCDATA)>"\
951 "       <!ATTLIST cc name CDATA #IMPLIED>"\
952 "   <!ELEMENT from          (#PCDATA)>"\
953 "       <!ATTLIST from name CDATA #IMPLIED>"\
954 "   <!ELEMENT reply-to      (#PCDATA)>"\
955 "       <!ATTLIST reply-to name CDATA #IMPLIED>"\
956 "   <!ELEMENT subject       ANY>"\
957 "   <!ELEMENT body          ANY>"\
958 "       <!ATTLIST body enc CDATA #FIXED \"UTF-8\">"\
959 "   <!ELEMENT attachment    (#PCDATA)>"\
960 "       <!ATTLIST attachment id ID #REQUIRED>"\
961 "]>"
962 
963 static const CHAR szEmailXML[] =
964 "<?xml version=\"1.0\"?>"
965 SZ_EMAIL_DTD
966 "<email attachments=\"patch1\">"
967 "   <recipients>"
968 "       <to>wine-patches@winehq.org</to>"
969 "   </recipients>"
970 "   <from name=\"Anonymous\">user@localhost</from>"
971 "   <subject>msxml3/tests: DTD validation (try 87)</subject>"
972 "   <body>"
973 "       It no longer causes spontaneous combustion..."
974 "   </body>"
975 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
976 "</email>";
977 
978 static const CHAR szEmailXML_0D[] =
979 "<?xml version=\"1.0\"?>"
980 SZ_EMAIL_DTD
981 "<email attachments=\"patch1\">"
982 "   <recipients>"
983 "       <to>wine-patches@winehq.org</to>"
984 "   </recipients>"
985 "   <from name=\"Anonymous\">user@localhost</from>"
986 "   <subject>msxml3/tests: DTD validation (try 88)</subject>"
987 "   <body>"
988 "       <undecl />"
989 "       XML_ELEMENT_UNDECLARED 0xC00CE00D"
990 "   </body>"
991 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
992 "</email>";
993 
994 static const CHAR szEmailXML_0E[] =
995 "<?xml version=\"1.0\"?>"
996 SZ_EMAIL_DTD
997 "<email attachments=\"patch1\">"
998 "   <recipients>"
999 "       <to>wine-patches@winehq.org</to>"
1000 "   </recipients>"
1001 "   <from name=\"Anonymous\">user@localhost</from>"
1002 "   <subject>msxml3/tests: DTD validation (try 89)</subject>"
1003 "   <body>"
1004 "       XML_ELEMENT_ID_NOT_FOUND 0xC00CE00E"
1005 "   </body>"
1006 "   <attachment id=\"patch\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1007 "</email>";
1008 
1009 static const CHAR szEmailXML_11[] =
1010 "<?xml version=\"1.0\"?>"
1011 SZ_EMAIL_DTD
1012 "<email attachments=\"patch1\">"
1013 "   <recipients>"
1014 "   </recipients>"
1015 "   <from name=\"Anonymous\">user@localhost</from>"
1016 "   <subject>msxml3/tests: DTD validation (try 90)</subject>"
1017 "   <body>"
1018 "       XML_EMPTY_NOT_ALLOWED 0xC00CE011"
1019 "   </body>"
1020 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1021 "</email>";
1022 
1023 static const CHAR szEmailXML_13[] =
1024 "<?xml version=\"1.0\"?>"
1025 SZ_EMAIL_DTD
1026 "<msg attachments=\"patch1\">"
1027 "   <recipients>"
1028 "       <to>wine-patches@winehq.org</to>"
1029 "   </recipients>"
1030 "   <from name=\"Anonymous\">user@localhost</from>"
1031 "   <subject>msxml3/tests: DTD validation (try 91)</subject>"
1032 "   <body>"
1033 "       XML_ROOT_NAME_MISMATCH 0xC00CE013"
1034 "   </body>"
1035 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1036 "</msg>";
1037 
1038 static const CHAR szEmailXML_14[] =
1039 "<?xml version=\"1.0\"?>"
1040 SZ_EMAIL_DTD
1041 "<email attachments=\"patch1\">"
1042 "   <to>wine-patches@winehq.org</to>"
1043 "   <from name=\"Anonymous\">user@localhost</from>"
1044 "   <subject>msxml3/tests: DTD validation (try 92)</subject>"
1045 "   <body>"
1046 "       XML_INVALID_CONTENT 0xC00CE014"
1047 "   </body>"
1048 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1049 "</email>";
1050 
1051 static const CHAR szEmailXML_15[] =
1052 "<?xml version=\"1.0\"?>"
1053 SZ_EMAIL_DTD
1054 "<email attachments=\"patch1\" ip=\"127.0.0.1\">"
1055 "   <recipients>"
1056 "       <to>wine-patches@winehq.org</to>"
1057 "   </recipients>"
1058 "   <from name=\"Anonymous\">user@localhost</from>"
1059 "   <subject>msxml3/tests: DTD validation (try 93)</subject>"
1060 "   <body>"
1061 "       XML_ATTRIBUTE_NOT_DEFINED 0xC00CE015"
1062 "   </body>"
1063 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1064 "</email>";
1065 
1066 static const CHAR szEmailXML_16[] =
1067 "<?xml version=\"1.0\"?>"
1068 SZ_EMAIL_DTD
1069 "<email attachments=\"patch1\">"
1070 "   <recipients>"
1071 "       <to>wine-patches@winehq.org</to>"
1072 "   </recipients>"
1073 "   <from name=\"Anonymous\">user@localhost</from>"
1074 "   <subject>msxml3/tests: DTD validation (try 94)</subject>"
1075 "   <body enc=\"ASCII\">"
1076 "       XML_ATTRIBUTE_FIXED 0xC00CE016"
1077 "   </body>"
1078 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1079 "</email>";
1080 
1081 static const CHAR szEmailXML_17[] =
1082 "<?xml version=\"1.0\"?>"
1083 SZ_EMAIL_DTD
1084 "<email attachments=\"patch1\" sent=\"true\">"
1085 "   <recipients>"
1086 "       <to>wine-patches@winehq.org</to>"
1087 "   </recipients>"
1088 "   <from name=\"Anonymous\">user@localhost</from>"
1089 "   <subject>msxml3/tests: DTD validation (try 95)</subject>"
1090 "   <body>"
1091 "       XML_ATTRIBUTE_VALUE 0xC00CE017"
1092 "   </body>"
1093 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1094 "</email>";
1095 
1096 static const CHAR szEmailXML_18[] =
1097 "<?xml version=\"1.0\"?>"
1098 SZ_EMAIL_DTD
1099 "<email attachments=\"patch1\">"
1100 "   oops"
1101 "   <recipients>"
1102 "       <to>wine-patches@winehq.org</to>"
1103 "   </recipients>"
1104 "   <from name=\"Anonymous\">user@localhost</from>"
1105 "   <subject>msxml3/tests: DTD validation (try 96)</subject>"
1106 "   <body>"
1107 "       XML_ILLEGAL_TEXT 0xC00CE018"
1108 "   </body>"
1109 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1110 "</email>";
1111 
1112 static const CHAR szEmailXML_20[] =
1113 "<?xml version=\"1.0\"?>"
1114 SZ_EMAIL_DTD
1115 "<email>"
1116 "   <recipients>"
1117 "       <to>wine-patches@winehq.org</to>"
1118 "   </recipients>"
1119 "   <from name=\"Anonymous\">user@localhost</from>"
1120 "   <subject>msxml3/tests: DTD validation (try 97)</subject>"
1121 "   <body>"
1122 "       XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020"
1123 "   </body>"
1124 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1125 "</email>";
1126 
1127 static const char xpath_simple_list[] =
1128 "<?xml version=\"1.0\"?>"
1129 "<root>"
1130 "   <a attr1=\"1\" attr2=\"2\" />"
1131 "   <b/>"
1132 "   <c/>"
1133 "   <d/>"
1134 "</root>";
1135 
1136 static const char default_ns_doc[] = {
1137     "<?xml version=\"1.0\"?>"
1138     "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
1139     "    d=\"d attr\" />"
1140 };
1141 
1142 static const char attributes_map[] = {
1143     "<?xml version=\"1.0\"?>"
1144     "<a attr1=\"value1\" attr2=\"value2\" attr3=\"value3\" attr4=\"value4\" />"
1145 };
1146 
1147 static const WCHAR nonexistent_fileW[] = {
1148     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
1149 };
1150 static const WCHAR nonexistent_attrW[] = {
1151     'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
1152 };
1153 static const WCHAR szDocument[] = {
1154     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
1155 };
1156 
1157 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
1158 static const WCHAR szdl[] = { 'd','l',0 };
1159 static const WCHAR szvr[] = { 'v','r',0 };
1160 static const WCHAR szlc[] = { 'l','c',0 };
1161 static const WCHAR szbs[] = { 'b','s',0 };
1162 static const WCHAR szstr1[] = { 's','t','r','1',0 };
1163 static const WCHAR szstr2[] = { 's','t','r','2',0 };
1164 static const WCHAR szstar[] = { '*',0 };
1165 static const WCHAR szfn1_txt[] = {'f','n','1','.','t','x','t',0};
1166 
1167 static const WCHAR szComment[] = {'A',' ','C','o','m','m','e','n','t',0 };
1168 static const WCHAR szCommentXML[] = {'<','!','-','-','A',' ','C','o','m','m','e','n','t','-','-','>',0 };
1169 static const WCHAR szCommentNodeText[] = {'#','c','o','m','m','e','n','t',0 };
1170 
1171 static WCHAR szElement[] = {'E','l','e','T','e','s','t', 0 };
1172 static const WCHAR szElementXML[]  = {'<','E','l','e','T','e','s','t','/','>',0 };
1173 static const WCHAR szElementXML2[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','/','>',0 };
1174 static const WCHAR szElementXML3[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1175                                       'T','e','s','t','i','n','g','N','o','d','e','<','/','E','l','e','T','e','s','t','>',0 };
1176 static const WCHAR szElementXML4[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1177                                       '&','a','m','p',';','x',' ',0x2103,'<','/','E','l','e','T','e','s','t','>',0 };
1178 
1179 static const WCHAR szAttribute[] = {'A','t','t','r',0 };
1180 static const WCHAR szAttributeXML[] = {'A','t','t','r','=','"','"',0 };
1181 
1182 static const WCHAR szCData[] = {'[','1',']','*','2','=','3',';',' ','&','g','e','e',' ','t','h','a','t','s',
1183                                 ' ','n','o','t',' ','r','i','g','h','t','!', 0};
1184 static const WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*','2','=','3',';',' ','&',
1185                                    'g','e','e',' ','t','h','a','t','s',' ','n','o','t',' ','r','i','g','h','t',
1186                                    '!',']',']','>',0};
1187 static const WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 };
1188 static const WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 };
1189 
1190 static const WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 };
1191 static const WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 };
1192 static const WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
1193 
1194 #define expect_bstr_eq_and_free(bstr, expect) { \
1195     BSTR bstrExp = alloc_str_from_narrow(expect); \
1196     ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \
1197     SysFreeString(bstr); \
1198     SysFreeString(bstrExp); \
1199 }
1200 
1201 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
1202 
1203 #define ole_check(expr) { \
1204     HRESULT r = expr; \
1205     ok(r == S_OK, #expr " returned %x\n", r); \
1206 }
1207 
1208 #define ole_expect(expr, expect) { \
1209     HRESULT r = expr; \
1210     ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
1211 }
1212 
1213 #define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
1214 
1215 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
1216 {
1217     void *obj = NULL;
1218     HRESULT hr;
1219 
1220     hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
1221     ok(hr == S_OK, "failed to create %s instance: 0x%08x\n", name, hr);
1222 
1223     return obj;
1224 }
1225 
1226 #define _create(cls) cls, #cls
1227 
1228 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
1229 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
1230 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
1231 #define create_xsltemplate(iid) _create_object(&_create(CLSID_XSLTemplate), iid, __LINE__)
1232 
1233 static BSTR alloc_str_from_narrow(const char *str)
1234 {
1235     int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1236     BSTR ret = SysAllocStringLen(NULL, len - 1);  /* NUL character added automatically */
1237     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
1238     return ret;
1239 }
1240 
1241 static BSTR alloced_bstrs[256];
1242 static int alloced_bstrs_count;
1243 
1244 static BSTR _bstr_(const char *str)
1245 {
1246     assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs));
1247     alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
1248     return alloced_bstrs[alloced_bstrs_count++];
1249 }
1250 
1251 static void free_bstrs(void)
1252 {
1253     int i;
1254     for (i = 0; i < alloced_bstrs_count; i++)
1255         SysFreeString(alloced_bstrs[i]);
1256     alloced_bstrs_count = 0;
1257 }
1258 
1259 static VARIANT _variantbstr_(const char *str)
1260 {
1261     VARIANT v;
1262     V_VT(&v) = VT_BSTR;
1263     V_BSTR(&v) = _bstr_(str);
1264     return v;
1265 }
1266 
1267 static BOOL compareIgnoreReturns(BSTR sLeft, BSTR sRight)
1268 {
1269     for (;;)
1270     {
1271         while (*sLeft == '\r' || *sLeft == '\n') sLeft++;
1272         while (*sRight == '\r' || *sRight == '\n') sRight++;
1273         if (*sLeft != *sRight) return FALSE;
1274         if (!*sLeft) return TRUE;
1275         sLeft++;
1276         sRight++;
1277     }
1278 }
1279 
1280 static void get_str_for_type(DOMNodeType type, char *buf)
1281 {
1282     switch (type)
1283     {
1284         case NODE_ATTRIBUTE:
1285             strcpy(buf, "A");
1286             break;
1287         case NODE_ELEMENT:
1288             strcpy(buf, "E");
1289             break;
1290         case NODE_DOCUMENT:
1291             strcpy(buf, "D");
1292             break;
1293         case NODE_TEXT:
1294             strcpy(buf, "T");
1295             break;
1296         case NODE_COMMENT:
1297             strcpy(buf, "C");
1298             break;
1299         case NODE_PROCESSING_INSTRUCTION:
1300             strcpy(buf, "P");
1301             break;
1302         default:
1303             wsprintfA(buf, "[%d]", type);
1304     }
1305 }
1306 
1307 static int get_node_position(IXMLDOMNode *node)
1308 {
1309     HRESULT r;
1310     int pos = 0;
1311 
1312     IXMLDOMNode_AddRef(node);
1313     do
1314     {
1315         IXMLDOMNode *new_node;
1316 
1317         pos++;
1318         r = IXMLDOMNode_get_previousSibling(node, &new_node);
1319         ok(SUCCEEDED(r), "get_previousSibling failed\n");
1320         IXMLDOMNode_Release(node);
1321         node = new_node;
1322     } while (r == S_OK);
1323     return pos;
1324 }
1325 
1326 static void node_to_string(IXMLDOMNode *node, char *buf)
1327 {
1328     HRESULT r = S_OK;
1329     DOMNodeType type;
1330 
1331     if (node == NULL)
1332     {
1333         lstrcpyA(buf, "(null)");
1334         return;
1335     }
1336 
1337     IXMLDOMNode_AddRef(node);
1338     while (r == S_OK)
1339     {
1340         IXMLDOMNode *new_node;
1341 
1342         ole_check(IXMLDOMNode_get_nodeType(node, &type));
1343         get_str_for_type(type, buf);
1344         buf+=strlen(buf);
1345 
1346         if (type == NODE_ATTRIBUTE)
1347         {
1348             BSTR bstr;
1349             ole_check(IXMLDOMNode_get_nodeName(node, &bstr));
1350             *(buf++) = '\'';
1351             wsprintfA(buf, "%ws", bstr);
1352             buf += strlen(buf);
1353             *(buf++) = '\'';
1354             SysFreeString(bstr);
1355 
1356             r = IXMLDOMNode_selectSingleNode(node, _bstr_(".."), &new_node);
1357         }
1358         else
1359         {
1360             r = IXMLDOMNode_get_parentNode(node, &new_node);
1361             sprintf(buf, "%d", get_node_position(node));
1362             buf += strlen(buf);
1363         }
1364 
1365         ok(SUCCEEDED(r), "get_parentNode failed (%08x)\n", r);
1366         IXMLDOMNode_Release(node);
1367         node = new_node;
1368         if (r == S_OK)
1369             *(buf++) = '.';
1370     }
1371 
1372     *buf = 0;
1373 }
1374 
1375 static char *list_to_string(IXMLDOMNodeList *list)
1376 {
1377     static char buf[4096];
1378     char *pos = buf;
1379     LONG len = 0;
1380     HRESULT hr;
1381     int i;
1382 
1383     if (list == NULL)
1384     {
1385         strcpy(buf, "(null)");
1386         return buf;
1387     }
1388     hr = IXMLDOMNodeList_get_length(list, &len);
1389     ok(hr == S_OK, "got 0x%08x\n", hr);
1390     for (i = 0; i < len; i++)
1391     {
1392         IXMLDOMNode *node;
1393         if (i > 0)
1394             *(pos++) = ' ';
1395         ole_check(IXMLDOMNodeList_nextNode(list, &node));
1396         node_to_string(node, pos);
1397         pos += strlen(pos);
1398         IXMLDOMNode_Release(node);
1399     }
1400     *pos = 0;
1401     return buf;
1402 }
1403 
1404 #define expect_node(node, expstr) { char str[4096]; node_to_string(node, str); ok(strcmp(str, expstr)==0, "Invalid node: %s, expected %s\n", str, expstr); }
1405 #define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, expected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
1406 
1407 struct docload_ret_t {
1408     VARIANT_BOOL b;
1409     HRESULT hr;
1410 };
1411 
1412 struct leading_spaces_t {
1413     const CLSID *clsid;
1414     const char *name;
1415     struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1416 };
1417 
1418 static const struct leading_spaces_t leading_spaces_classdata[] = {
1419     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1420     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1421     { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1422     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1423     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1424     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1425     { NULL }
1426 };
1427 
1428 static const char* leading_spaces_xmldata[] = {
1429     "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1430     " <?xml version=\"1.0\"?><root/>",
1431     "\n<?xml version=\"1.0\"?><root/>",
1432     "\t<?xml version=\"1.0\"?><root/>",
1433     "\r\n<?xml version=\"1.0\"?><root/>",
1434     "\r<?xml version=\"1.0\"?><root/>",
1435     "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1436     0
1437 };
1438 
1439 static void test_domdoc( void )
1440 {
1441     HRESULT r, hr;
1442     IXMLDOMDocument *doc;
1443     IXMLDOMParseError *error;
1444     IXMLDOMElement *element = NULL;
1445     IXMLDOMNode *node;
1446     IXMLDOMText *nodetext = NULL;
1447     IXMLDOMComment *node_comment = NULL;
1448     IXMLDOMAttribute *node_attr = NULL;
1449     IXMLDOMNode *nodeChild = NULL;
1450     IXMLDOMProcessingInstruction *nodePI = NULL;
1451     const struct leading_spaces_t *class_ptr;
1452     const char **data_ptr;
1453     VARIANT_BOOL b;
1454     VARIANT var;
1455     BSTR str;
1456     LONG code, ref;
1457     LONG nLength = 0;
1458     WCHAR buff[100];
1459     char path[MAX_PATH];
1460     int index;
1461 
1462     GetTempPathA(MAX_PATH, path);
1463     strcat(path, "leading_spaces.xml");
1464 
1465     /* Load document with leading spaces
1466      *
1467      * Test all CLSIDs with all test data XML strings
1468      */
1469     class_ptr = leading_spaces_classdata;
1470     index = 0;
1471     while (class_ptr->clsid)
1472     {
1473         HRESULT hr;
1474         int i;
1475 
1476         if (is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
1477         {
1478             hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
1479         }
1480         else
1481         {
1482             class_ptr++;
1483             index++;
1484             continue;
1485         }
1486 
1487         data_ptr = leading_spaces_xmldata;
1488         i = 0;
1489         while (*data_ptr) {
1490             BSTR data = _bstr_(*data_ptr);
1491             DWORD written;
1492             HANDLE file;
1493 
1494             file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1495             ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1496 
1497             WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1498             CloseHandle(file);
1499 
1500             b = 0xc;
1501             V_VT(&var) = VT_BSTR;
1502             V_BSTR(&var) = _bstr_(path);
1503             hr = IXMLDOMDocument_load(doc, var, &b);
1504             EXPECT_HR(hr, class_ptr->ret[0].hr);
1505             ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1506 
1507             DeleteFileA(path);
1508 
1509             b = 0xc;
1510             hr = IXMLDOMDocument_loadXML(doc, data, &b);
1511             EXPECT_HR(hr, class_ptr->ret[1].hr);
1512             ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1513 
1514             data_ptr++;
1515             i++;
1516         }
1517 
1518         class_ptr++;
1519         index++;
1520         free_bstrs();
1521     }
1522 
1523     doc = create_document(&IID_IXMLDOMDocument);
1524     if (!doc) return;
1525 
1526 if (0)
1527 {
1528     /* crashes on native */
1529     IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1530 }
1531 
1532     /* try some stupid things */
1533     hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1534     EXPECT_HR(hr, S_FALSE);
1535 
1536     b = VARIANT_TRUE;
1537     hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1538     EXPECT_HR(hr, S_FALSE);
1539     ok( b == VARIANT_FALSE, "failed to load XML string\n");
1540 
1541     /* try to load a document from a nonexistent file */
1542     b = VARIANT_TRUE;
1543     str = SysAllocString( nonexistent_fileW );
1544     VariantInit(&var);
1545     V_VT(&var) = VT_BSTR;
1546     V_BSTR(&var) = str;
1547 
1548     r = IXMLDOMDocument_load( doc, var, &b);
1549     ok( r == S_FALSE, "loadXML succeeded\n");
1550     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1551     SysFreeString( str );
1552 
1553     str = (void *)0xdeadbeef;
1554     hr = IXMLDOMDocument_get_url(doc, &str);
1555     ok(hr == S_FALSE, "got 0x%08x\n", hr);
1556     ok(str == NULL, "got %p\n", str);
1557 
1558     /* try load an empty document */
1559     b = VARIANT_TRUE;
1560     str = SysAllocString( szEmpty );
1561     r = IXMLDOMDocument_loadXML( doc, str, &b );
1562     ok( r == S_FALSE, "loadXML succeeded\n");
1563     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1564     SysFreeString( str );
1565 
1566     r = IXMLDOMDocument_get_async( doc, &b );
1567     ok( r == S_OK, "get_async failed (%08x)\n", r);
1568     ok( b == VARIANT_TRUE, "Wrong default value\n");
1569 
1570     /* check that there's no document element */
1571     element = NULL;
1572     r = IXMLDOMDocument_get_documentElement( doc, &element );
1573     ok( r == S_FALSE, "should be no document element\n");
1574 
1575     /* try finding a node */
1576     node = NULL;
1577     str = SysAllocString( szstr1 );
1578     r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1579     ok( r == S_FALSE, "ret %08x\n", r );
1580     SysFreeString( str );
1581 
1582     b = VARIANT_TRUE;
1583     str = SysAllocString( szIncomplete );
1584     r = IXMLDOMDocument_loadXML( doc, str, &b );
1585     ok( r == S_FALSE, "loadXML succeeded\n");
1586     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1587     SysFreeString( str );
1588 
1589     /* check that there's no document element */
1590     element = (IXMLDOMElement*)1;
1591     r = IXMLDOMDocument_get_documentElement( doc, &element );
1592     ok( r == S_FALSE, "should be no document element\n");
1593     ok( element == NULL, "Element should be NULL\n");
1594 
1595     /* test for BSTR handling, pass broken BSTR */
1596     memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1597     /* just a big length */
1598     *(DWORD*)buff = 0xf0f0;
1599     b = VARIANT_FALSE;
1600     r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1601     ok( r == S_OK, "loadXML failed\n");
1602     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1603 
1604     /* loadXML ignores the encoding attribute and always expects Unicode */
1605     b = VARIANT_FALSE;
1606     str = SysAllocString( szComplete6 );
1607     r = IXMLDOMDocument_loadXML( doc, str, &b );
1608     ok( r == S_OK, "loadXML failed\n");
1609     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1610     SysFreeString( str );
1611 
1612     /* try a BSTR containing a Windows-1252 document */
1613     b = VARIANT_TRUE;
1614     str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1615     r = IXMLDOMDocument_loadXML( doc, str, &b );
1616     ok( r == S_FALSE, "loadXML succeeded\n");
1617     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1618     SysFreeString( str );
1619 
1620     /* try to load something valid */
1621     b = VARIANT_FALSE;
1622     str = SysAllocString( szComplete1 );
1623     r = IXMLDOMDocument_loadXML( doc, str, &b );
1624     ok( r == S_OK, "loadXML failed\n");
1625     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1626     SysFreeString( str );
1627 
1628     /* check if nodename is correct */
1629     r = IXMLDOMDocument_get_nodeName( doc, NULL );
1630     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1631 
1632     str = (void *)0xdeadbeef;
1633     r = IXMLDOMDocument_get_baseName( doc, &str );
1634     ok ( r == S_FALSE, "got 0x%08x\n", r);
1635     ok (str == NULL, "got %p\n", str);
1636 
1637     /* content doesn't matter here */
1638     str = NULL;
1639     r = IXMLDOMDocument_get_nodeName( doc, &str );
1640     ok ( r == S_OK, "get_nodeName wrong code\n");
1641     ok ( str != NULL, "str is null\n");
1642     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1643     SysFreeString( str );
1644 
1645     /* test put_text */
1646     r = IXMLDOMDocument_put_text( doc, _bstr_("Should fail") );
1647     ok( r == E_FAIL, "ret %08x\n", r );
1648 
1649     /* check that there's a document element */
1650     element = NULL;
1651     r = IXMLDOMDocument_get_documentElement( doc, &element );
1652     ok( r == S_OK, "should be a document element\n");
1653     if( element )
1654     {
1655         IObjectIdentity *ident;
1656 
1657         r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1658         ok( r == E_NOINTERFACE, "ret %08x\n", r);
1659 
1660         IXMLDOMElement_Release( element );
1661         element = NULL;
1662     }
1663 
1664     /* as soon as we call loadXML again, the document element will disappear */
1665     b = 2;
1666     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1667     ok( r == S_FALSE, "loadXML failed\n");
1668     ok( b == 2, "variant modified\n");
1669     r = IXMLDOMDocument_get_documentElement( doc, &element );
1670     ok( r == S_FALSE, "should be no document element\n");
1671 
1672     /* try to load something else simple and valid */
1673     b = VARIANT_FALSE;
1674     str = SysAllocString( szComplete2 );
1675     r = IXMLDOMDocument_loadXML( doc, str, &b );
1676     ok( r == S_OK, "loadXML failed\n");
1677     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1678     SysFreeString( str );
1679 
1680     /* try something a little more complicated */
1681     b = FALSE;
1682     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1683     ok( r == S_OK, "loadXML failed\n");
1684     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1685 
1686     r = IXMLDOMDocument_get_parseError( doc, &error );
1687     ok( r == S_OK, "returns %08x\n", r );
1688 
1689     r = IXMLDOMParseError_get_errorCode( error, &code );
1690     ok( r == S_FALSE, "returns %08x\n", r );
1691     ok( code == 0, "code %d\n", code );
1692     IXMLDOMParseError_Release( error );
1693 
1694     /* test createTextNode */
1695     r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1696     ok( r == S_OK, "returns %08x\n", r );
1697     IXMLDOMText_Release(nodetext);
1698 
1699     str = SysAllocString( szOpen );
1700     r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1701     ok( r == E_INVALIDARG, "returns %08x\n", r );
1702     r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1703     ok( r == S_OK, "returns %08x\n", r );
1704     SysFreeString( str );
1705     if(nodetext)
1706     {
1707         r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1708         ok(r == E_NOINTERFACE, "ret %08x\n", r );
1709 
1710         /* Text Last Child Checks */
1711         r = IXMLDOMText_get_lastChild(nodetext, NULL);
1712         ok(r == E_INVALIDARG, "ret %08x\n", r );
1713 
1714         nodeChild = (IXMLDOMNode*)0x1;
1715         r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1716         ok(r == S_FALSE, "ret %08x\n", r );
1717         ok(nodeChild == NULL, "nodeChild not NULL\n");
1718 
1719         /* test length property */
1720         r = IXMLDOMText_get_length(nodetext, NULL);
1721         ok(r == E_INVALIDARG, "ret %08x\n", r );
1722 
1723         r = IXMLDOMText_get_length(nodetext, &nLength);
1724         ok(r == S_OK, "ret %08x\n", r );
1725         ok(nLength == 4, "expected 4 got %d\n", nLength);
1726 
1727         /* put data Tests */
1728         r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1729         ok(r == S_OK, "ret %08x\n", r );
1730 
1731         /* get data Tests */
1732         r = IXMLDOMText_get_data(nodetext, &str);
1733         ok(r == S_OK, "ret %08x\n", r );
1734         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1735         SysFreeString(str);
1736 
1737         /* Confirm XML text is good */
1738         r = IXMLDOMText_get_xml(nodetext, &str);
1739         ok(r == S_OK, "ret %08x\n", r );
1740         ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1741         SysFreeString(str);
1742 
1743         /* Confirm we get the put_data Text back */
1744         r = IXMLDOMText_get_text(nodetext, &str);
1745         ok(r == S_OK, "ret %08x\n", r );
1746         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1747         SysFreeString(str);
1748 
1749         /* test substringData */
1750         r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1751         ok(r == E_INVALIDARG, "ret %08x\n", r );
1752 
1753         /* test substringData - Invalid offset */
1754         str = (void *)0xdeadbeef;
1755         r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1756         ok(r == E_INVALIDARG, "ret %08x\n", r );
1757         ok( str == NULL, "incorrect string\n");
1758 
1759         /* test substringData - Invalid offset */
1760         str = (void *)0xdeadbeef;
1761         r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1762         ok(r == S_FALSE, "ret %08x\n", r );
1763         ok( str == NULL, "incorrect string\n");
1764 
1765         /* test substringData - Invalid size */
1766         str = (void *)0xdeadbeef;
1767         r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1768         ok(r == E_INVALIDARG, "ret %08x\n", r );
1769         ok( str == NULL, "incorrect string\n");
1770 
1771         /* test substringData - Invalid size */
1772         str = (void *)0xdeadbeef;
1773         r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1774         ok(r == S_FALSE, "ret %08x\n", r );
1775         ok( str == NULL, "incorrect string\n");
1776 
1777         /* test substringData - Start of string */
1778         r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1779         ok(r == S_OK, "ret %08x\n", r );
1780         ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1781         SysFreeString(str);
1782 
1783         /* test substringData - Middle of string */
1784         r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1785         ok(r == S_OK, "ret %08x\n", r );
1786         ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1787         SysFreeString(str);
1788 
1789         /* test substringData - End of string */
1790         r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1791         ok(r == S_OK, "ret %08x\n", r );
1792         ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1793         SysFreeString(str);
1794 
1795         /* test appendData */
1796         r = IXMLDOMText_appendData(nodetext, NULL);
1797         ok(r == S_OK, "ret %08x\n", r );
1798 
1799         r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1800         ok(r == S_OK, "ret %08x\n", r );
1801 
1802         r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1803         ok(r == S_OK, "ret %08x\n", r );
1804 
1805         r = IXMLDOMText_get_text(nodetext, &str);
1806         ok(r == S_OK, "ret %08x\n", r );
1807         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1808         SysFreeString(str);
1809 
1810         /* test insertData */
1811         str = SysAllocStringLen(NULL, 0);
1812         r = IXMLDOMText_insertData(nodetext, -1, str);
1813         ok(r == S_OK, "ret %08x\n", r );
1814 
1815         r = IXMLDOMText_insertData(nodetext, -1, NULL);
1816         ok(r == S_OK, "ret %08x\n", r );
1817 
1818         r = IXMLDOMText_insertData(nodetext, 1000, str);
1819         ok(r == S_OK, "ret %08x\n", r );
1820 
1821         r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1822         ok(r == S_OK, "ret %08x\n", r );
1823 
1824         r = IXMLDOMText_insertData(nodetext, 0, NULL);
1825         ok(r == S_OK, "ret %08x\n", r );
1826 
1827         r = IXMLDOMText_insertData(nodetext, 0, str);
1828         ok(r == S_OK, "ret %08x\n", r );
1829         SysFreeString(str);
1830 
1831         r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1832         ok(r == E_INVALIDARG, "ret %08x\n", r );
1833 
1834         r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1835         ok(r == E_INVALIDARG, "ret %08x\n", r );
1836 
1837         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1838         ok(r == S_OK, "ret %08x\n", r );
1839 
1840         r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1841         ok(r == S_OK, "ret %08x\n", r );
1842 
1843         r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1844         ok(r == S_OK, "ret %08x\n", r );
1845 
1846         r = IXMLDOMText_get_text(nodetext, &str);
1847         ok(r == S_OK, "ret %08x\n", r );
1848         ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1849         SysFreeString(str);
1850 
1851         /* delete data */
1852         /* invalid arguments */
1853         r = IXMLDOMText_deleteData(nodetext, -1, 1);
1854         ok(r == E_INVALIDARG, "ret %08x\n", r );
1855 
1856         r = IXMLDOMText_deleteData(nodetext, 0, 0);
1857         ok(r == S_OK, "ret %08x\n", r );
1858 
1859         r = IXMLDOMText_deleteData(nodetext, 0, -1);
1860         ok(r == E_INVALIDARG, "ret %08x\n", r );
1861 
1862         r = IXMLDOMText_get_length(nodetext, &nLength);
1863         ok(r == S_OK, "ret %08x\n", r );
1864         ok(nLength == 43, "expected 43 got %d\n", nLength);
1865 
1866         r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1867         ok(r == S_OK, "ret %08x\n", r );
1868 
1869         r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1870         ok(r == E_INVALIDARG, "ret %08x\n", r );
1871 
1872         /* delete from start */
1873         r = IXMLDOMText_deleteData(nodetext, 0, 5);
1874         ok(r == S_OK, "ret %08x\n", r );
1875 
1876         r = IXMLDOMText_get_length(nodetext, &nLength);
1877         ok(r == S_OK, "ret %08x\n", r );
1878         ok(nLength == 38, "expected 38 got %d\n", nLength);
1879 
1880         r = IXMLDOMText_get_text(nodetext, &str);
1881         ok(r == S_OK, "ret %08x\n", r );
1882         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1883         SysFreeString(str);
1884 
1885         /* delete from end */
1886         r = IXMLDOMText_deleteData(nodetext, 35, 3);
1887         ok(r == S_OK, "ret %08x\n", r );
1888 
1889         r = IXMLDOMText_get_length(nodetext, &nLength);
1890         ok(r == S_OK, "ret %08x\n", r );
1891         ok(nLength == 35, "expected 35 got %d\n", nLength);
1892 
1893         r = IXMLDOMText_get_text(nodetext, &str);
1894         ok(r == S_OK, "ret %08x\n", r );
1895         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1896         SysFreeString(str);
1897 
1898         /* delete from inside */
1899         r = IXMLDOMText_deleteData(nodetext, 1, 33);
1900         ok(r == S_OK, "ret %08x\n", r );
1901 
1902         r = IXMLDOMText_get_length(nodetext, &nLength);
1903         ok(r == S_OK, "ret %08x\n", r );
1904         ok(nLength == 2, "expected 2 got %d\n", nLength);
1905 
1906         r = IXMLDOMText_get_text(nodetext, &str);
1907         ok(r == S_OK, "ret %08x\n", r );
1908         ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1909         SysFreeString(str);
1910 
1911         /* delete whole data ... */
1912         r = IXMLDOMText_get_length(nodetext, &nLength);
1913         ok(r == S_OK, "ret %08x\n", r );
1914 
1915         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1916         ok(r == S_OK, "ret %08x\n", r );
1917         /* ... and try again with empty string */
1918         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1919         ok(r == S_OK, "ret %08x\n", r );
1920 
1921         /* test put_data */
1922         V_VT(&var) = VT_BSTR;
1923         V_BSTR(&var) = SysAllocString(szstr1);
1924         r = IXMLDOMText_put_nodeValue(nodetext, var);
1925         ok(r == S_OK, "ret %08x\n", r );
1926         VariantClear(&var);
1927 
1928         r = IXMLDOMText_get_text(nodetext, &str);
1929         ok(r == S_OK, "ret %08x\n", r );
1930         ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1931         SysFreeString(str);
1932 
1933         /* test put_data */
1934         V_VT(&var) = VT_I4;
1935         V_I4(&var) = 99;
1936         r = IXMLDOMText_put_nodeValue(nodetext, var);
1937         ok(r == S_OK, "ret %08x\n", r );
1938         VariantClear(&var);
1939 
1940         r = IXMLDOMText_get_text(nodetext, &str);
1941         ok(r == S_OK, "ret %08x\n", r );
1942         ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1943         SysFreeString(str);
1944 
1945         /* ::replaceData() */
1946         V_VT(&var) = VT_BSTR;
1947         V_BSTR(&var) = SysAllocString(szstr1);
1948         r = IXMLDOMText_put_nodeValue(nodetext, var);
1949         ok(r == S_OK, "ret %08x\n", r );
1950         VariantClear(&var);
1951 
1952         r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1953         ok(r == E_INVALIDARG, "ret %08x\n", r );
1954         r = IXMLDOMText_get_text(nodetext, &str);
1955         ok(r == S_OK, "ret %08x\n", r );
1956         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1957         SysFreeString(str);
1958 
1959         r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1960         ok(r == S_OK, "ret %08x\n", r );
1961         r = IXMLDOMText_get_text(nodetext, &str);
1962         ok(r == S_OK, "ret %08x\n", r );
1963         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1964         SysFreeString(str);
1965 
1966         /* NULL pointer means delete */
1967         r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1968         ok(r == S_OK, "ret %08x\n", r );
1969         r = IXMLDOMText_get_text(nodetext, &str);
1970         ok(r == S_OK, "ret %08x\n", r );
1971         ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1972         SysFreeString(str);
1973 
1974         /* empty string means delete */
1975         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1976         ok(r == S_OK, "ret %08x\n", r );
1977         r = IXMLDOMText_get_text(nodetext, &str);
1978         ok(r == S_OK, "ret %08x\n", r );
1979         ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1980         SysFreeString(str);
1981 
1982         /* zero count means insert */
1983         r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1984         ok(r == S_OK, "ret %08x\n", r );
1985         r = IXMLDOMText_get_text(nodetext, &str);
1986         ok(r == S_OK, "ret %08x\n", r );
1987         ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1988         SysFreeString(str);
1989 
1990         r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1991         ok(r == S_OK, "ret %08x\n", r );
1992 
1993         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1994         ok(r == S_OK, "ret %08x\n", r );
1995         r = IXMLDOMText_get_text(nodetext, &str);
1996         ok(r == S_OK, "ret %08x\n", r );
1997         ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1998         SysFreeString(str);
1999 
2000         /* nonempty string, count greater than its length */
2001         r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
2002         ok(r == S_OK, "ret %08x\n", r );
2003         r = IXMLDOMText_get_text(nodetext, &str);
2004         ok(r == S_OK, "ret %08x\n", r );
2005         ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
2006         SysFreeString(str);
2007 
2008         /* nonempty string, count less than its length */
2009         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
2010         ok(r == S_OK, "ret %08x\n", r );
2011         r = IXMLDOMText_get_text(nodetext, &str);
2012         ok(r == S_OK, "ret %08x\n", r );
2013         ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
2014         SysFreeString(str);
2015 
2016         IXMLDOMText_Release( nodetext );
2017     }
2018 
2019     /* test Create Comment */
2020     r = IXMLDOMDocument_createComment(doc, NULL, NULL);
2021     ok( r == E_INVALIDARG, "returns %08x\n", r );
2022     node_comment = (IXMLDOMComment*)0x1;
2023 
2024     /* empty comment */
2025     r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
2026     ok( r == S_OK, "returns %08x\n", r );
2027     str = NULL;
2028     r = IXMLDOMComment_get_data(node_comment, &str);
2029     ok( r == S_OK, "returns %08x\n", r );
2030     ok( str && SysStringLen(str) == 0, "expected empty string data\n");
2031     IXMLDOMComment_Release(node_comment);
2032     SysFreeString(str);
2033 
2034     r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
2035     ok( r == S_OK, "returns %08x\n", r );
2036     str = NULL;
2037     r = IXMLDOMComment_get_data(node_comment, &str);
2038     ok( r == S_OK, "returns %08x\n", r );
2039     ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
2040     IXMLDOMComment_Release(node_comment);
2041     SysFreeString(str);
2042 
2043     str = SysAllocString(szComment);
2044     r = IXMLDOMDocument_createComment(doc, str, &node_comment);
2045     SysFreeString(str);
2046     ok( r == S_OK, "returns %08x\n", r );
2047     if(node_comment)
2048     {
2049         /* Last Child Checks */
2050         r = IXMLDOMComment_get_lastChild(node_comment, NULL);
2051         ok(r == E_INVALIDARG, "ret %08x\n", r );
2052 
2053         nodeChild = (IXMLDOMNode*)0x1;
2054         r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
2055         ok(r == S_FALSE, "ret %08x\n", r );
2056         ok(nodeChild == NULL, "pLastChild not NULL\n");
2057 
2058         /* baseName */
2059         str = (void *)0xdeadbeef;
2060         r = IXMLDOMComment_get_baseName(node_comment, &str);
2061         ok(r == S_FALSE, "ret %08x\n", r );
2062         ok(str == NULL, "Expected NULL\n");
2063 
2064         IXMLDOMComment_Release( node_comment );
2065     }
2066 
2067     /* test Create Attribute */
2068     str = SysAllocString(szAttribute);
2069     r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
2070     ok( r == E_INVALIDARG, "returns %08x\n", r );
2071     r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
2072     ok( r == S_OK, "returns %08x\n", r );
2073     IXMLDOMAttribute_Release( node_attr);
2074     SysFreeString(str);
2075 
2076     /* test Processing Instruction */
2077     str = SysAllocStringLen(NULL, 0);
2078     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
2079     ok( r == E_INVALIDARG, "returns %08x\n", r );
2080     r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
2081     ok( r == E_FAIL, "returns %08x\n", r );
2082     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
2083     ok( r == E_FAIL, "returns %08x\n", r );
2084     SysFreeString(str);
2085 
2086     r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
2087     ok( r == S_OK, "returns %08x\n", r );
2088     if(nodePI)
2089     {
2090         /* Last Child Checks */
2091         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
2092         ok(r == E_INVALIDARG, "ret %08x\n", r );
2093 
2094         nodeChild = (IXMLDOMNode*)0x1;
2095         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
2096         ok(r == S_FALSE, "ret %08x\n", r );
2097         ok(nodeChild == NULL, "nodeChild not NULL\n");
2098 
2099         /* test nodeName */
2100         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2101         ok(r == S_OK, "ret %08x\n", r );
2102         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2103         SysFreeString(str);
2104 
2105         /* test baseName */
2106         str = NULL;
2107         r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
2108         ok(r == S_OK, "ret %08x\n", r );
2109         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2110         SysFreeString(str);
2111 
2112         /* test Target */
2113         r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
2114         ok(r == S_OK, "ret %08x\n", r );
2115         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
2116         SysFreeString(str);
2117 
2118         /* test get_data */
2119         r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
2120         ok(r == S_OK, "ret %08x\n", r );
2121         ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
2122         SysFreeString(str);
2123 
2124         /* test put_data */
2125         r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
2126         ok(r == E_FAIL, "ret %08x\n", r );
2127 
2128         /* test put_data */
2129         V_VT(&var) = VT_BSTR;
2130         V_BSTR(&var) = SysAllocString(szOpen);  /* Doesn't matter what the string is, cannot set an xml node. */
2131         r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
2132         ok(r == E_FAIL, "ret %08x\n", r );
2133         VariantClear(&var);
2134 
2135         /* test get nodeName */
2136         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2137         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2138         ok(r == S_OK, "ret %08x\n", r );
2139         SysFreeString(str);
2140 
2141         IXMLDOMProcessingInstruction_Release(nodePI);
2142     }
2143 
2144     ref = IXMLDOMDocument_Release( doc );
2145     ok( ref == 0, "got %d\n", ref);
2146 
2147     free_bstrs();
2148 }
2149 
2150 static void test_persiststream(void)
2151 {
2152     IPersistStreamInit *streaminit;
2153     IPersistStream *stream;
2154     IXMLDOMDocument *doc;
2155     ULARGE_INTEGER size;
2156     IPersist *persist;
2157     HRESULT hr;
2158     CLSID clsid;
2159 
2160     doc = create_document(&IID_IXMLDOMDocument);
2161 
2162     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
2163     ok(hr == S_OK, "got 0x%08x\n", hr);
2164 
2165     hr = IPersistStreamInit_InitNew(streaminit);
2166     ok(hr == S_OK, "got 0x%08x\n", hr);
2167 
2168     hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
2169     ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
2170 
2171     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStream, (void **)&stream);
2172     ok(hr == S_OK, "got 0x%08x\n", hr);
2173     ok((IUnknown *)stream == (IUnknown *)streaminit, "got %p, %p\n", stream, streaminit);
2174 
2175     hr = IPersistStream_QueryInterface(stream, &IID_IPersist, (void **)&persist);
2176     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2177 
2178     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersist, (void **)&persist);
2179     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2180 
2181     hr = IPersistStreamInit_GetClassID(streaminit, NULL);
2182     ok(hr == E_POINTER, "got 0x%08x\n", hr);
2183 
2184     memset(&clsid, 0, sizeof(clsid));
2185     hr = IPersistStreamInit_GetClassID(streaminit, &clsid);
2186     ok(hr == S_OK, "got 0x%08x\n", hr);
2187     ok(IsEqualGUID(&clsid, &CLSID_DOMDocument2), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
2188 
2189     IPersistStream_Release(stream);
2190     IPersistStreamInit_Release(streaminit);
2191     IXMLDOMDocument_Release(doc);
2192 }
2193 
2194 static void test_domnode( void )
2195 {
2196     HRESULT r;
2197     IXMLDOMDocument *doc, *owner = NULL;
2198     IXMLDOMElement *element = NULL;
2199     IXMLDOMNamedNodeMap *map = NULL;
2200     IXMLDOMNode *node = NULL, *next = NULL;
2201     IXMLDOMNodeList *list = NULL;
2202     IXMLDOMAttribute *attr = NULL;
2203     DOMNodeType type = NODE_INVALID;
2204     VARIANT_BOOL b;
2205     BSTR str;
2206     VARIANT var;
2207     LONG count;
2208 
2209     doc = create_document(&IID_IXMLDOMDocument);
2210 
2211     b = FALSE;
2212     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2213     ok( r == S_OK, "loadXML failed\n");
2214     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2215 
2216     EXPECT_CHILDREN(doc);
2217 
2218     r = IXMLDOMDocument_get_documentElement( doc, &element );
2219     ok( r == S_OK, "should be a document element\n");
2220     ok( element != NULL, "should be an element\n");
2221 
2222     VariantInit(&var);
2223     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
2224 
2225     r = IXMLDOMDocument_get_nodeValue( doc, NULL );
2226     ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
2227 
2228     r = IXMLDOMDocument_get_nodeValue( doc, &var );
2229     ok( r == S_FALSE, "nextNode returned wrong code\n");
2230     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
2231     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
2232 
2233     if (element)
2234     {
2235         owner = NULL;
2236         r = IXMLDOMElement_get_ownerDocument( element, &owner );
2237         ok( r == S_OK, "get_ownerDocument return code\n");
2238         ok( owner != doc, "get_ownerDocument return\n");
2239         IXMLDOMDocument_Release(owner);
2240 
2241         type = NODE_INVALID;
2242         r = IXMLDOMElement_get_nodeType( element, &type);
2243         ok( r == S_OK, "got %08x\n", r);
2244         ok( type == NODE_ELEMENT, "node not an element\n");
2245 
2246         str = NULL;
2247         r = IXMLDOMElement_get_baseName( element, &str );
2248         ok( r == S_OK, "get_baseName returned wrong code\n");
2249         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
2250         SysFreeString(str);
2251 
2252         /* check if nodename is correct */
2253         r = IXMLDOMElement_get_nodeName( element, NULL );
2254         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2255 
2256         /* content doesn't matter here */
2257         str = NULL;
2258         r = IXMLDOMElement_get_nodeName( element, &str );
2259         ok ( r == S_OK, "get_nodeName wrong code\n");
2260         ok ( str != NULL, "str is null\n");
2261         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
2262         SysFreeString( str );
2263 
2264         str = SysAllocString( nonexistent_fileW );
2265         V_VT(&var) = VT_I4;
2266         V_I4(&var) = 0x1234;
2267         r = IXMLDOMElement_getAttribute( element, str, &var );
2268         ok( r == E_FAIL, "getAttribute ret %08x\n", r );
2269         ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
2270         VariantClear(&var);
2271         SysFreeString(str);
2272 
2273         str = SysAllocString( szdl );
2274         V_VT(&var) = VT_I4;
2275         V_I4(&var) = 0x1234;
2276         r = IXMLDOMElement_getAttribute( element, str, &var );
2277         ok( r == S_OK, "getAttribute ret %08x\n", r );
2278         ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
2279         ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
2280         VariantClear( &var );
2281 
2282         r = IXMLDOMElement_getAttribute( element, NULL, &var );
2283         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2284 
2285         r = IXMLDOMElement_getAttribute( element, str, NULL );
2286         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2287 
2288         attr = NULL;
2289         r = IXMLDOMElement_getAttributeNode( element, str, &attr);
2290         ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
2291         ok( attr != NULL, "getAttributeNode returned NULL\n" );
2292         if (attr)
2293         {
2294             r = IXMLDOMAttribute_get_parentNode( attr, NULL );
2295             ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
2296 
2297             /* attribute doesn't have a parent in msxml interpretation */
2298             node = (IXMLDOMNode*)0xdeadbeef;
2299             r = IXMLDOMAttribute_get_parentNode( attr, &node );
2300             ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
2301             ok( node == NULL, "Expected NULL, got %p\n", node );
2302 
2303             IXMLDOMAttribute_Release(attr);
2304         }
2305 
2306         SysFreeString( str );
2307 
2308         r = IXMLDOMElement_get_attributes( element, &map );
2309         ok( r == S_OK, "get_attributes returned wrong code\n");
2310         ok( map != NULL, "should be attributes\n");
2311 
2312         EXPECT_CHILDREN(element);
2313     }
2314     else
2315         ok( FALSE, "no element\n");
2316 
2317     if (map)
2318     {
2319         str = SysAllocString( szdl );
2320         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2321         ok( r == S_OK, "getNamedItem returned wrong code\n");
2322         ok( node != NULL, "should be attributes\n");
2323         IXMLDOMNode_Release(node);
2324         SysFreeString( str );
2325 
2326         str = SysAllocString( szdl );
2327         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
2328         ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
2329         SysFreeString( str );
2330 
2331         /* something that isn't in complete4A */
2332         str = SysAllocString( szOpen );
2333         node = (IXMLDOMNode *) 1;
2334         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2335         ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
2336         ok( node == NULL, "getNamedItem should have returned NULL\n");
2337         SysFreeString( str );
2338 
2339 	/* test indexed access of attributes */
2340         r = IXMLDOMNamedNodeMap_get_length( map, NULL );
2341         ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
2342 
2343         r = IXMLDOMNamedNodeMap_get_length( map, &count );
2344         ok ( r == S_OK, "get_length wrong code\n");
2345         ok ( count == 1, "get_length != 1\n");
2346 
2347         node = NULL;
2348         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
2349         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
2350         ok ( node == NULL, "there is no node\n");
2351 
2352         node = NULL;
2353         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
2354         ok ( r == S_FALSE, "get_item (1) wrong code\n");
2355         ok ( node == NULL, "there is no attribute\n");
2356 
2357         node = NULL;
2358         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
2359         ok ( r == S_OK, "get_item (0) wrong code\n");
2360         ok ( node != NULL, "should be attribute\n");
2361 
2362         r = IXMLDOMNode_get_nodeName( node, NULL );
2363         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2364 
2365         /* content doesn't matter here */
2366         str = NULL;
2367         r = IXMLDOMNode_get_nodeName( node, &str );
2368         ok ( r == S_OK, "get_nodeName wrong code\n");
2369         ok ( str != NULL, "str is null\n");
2370         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
2371         SysFreeString( str );
2372         IXMLDOMNode_Release( node );
2373 
2374         /* test sequential access of attributes */
2375         node = NULL;
2376         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2377         ok ( r == S_OK, "nextNode (first time) wrong code\n");
2378         ok ( node != NULL, "nextNode, should be attribute\n");
2379         IXMLDOMNode_Release( node );
2380 
2381         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2382         ok ( r != S_OK, "nextNode (second time) wrong code\n");
2383         ok ( node == NULL, "nextNode, there is no attribute\n");
2384 
2385         r = IXMLDOMNamedNodeMap_reset( map );
2386         ok ( r == S_OK, "reset should return S_OK\n");
2387 
2388         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2389         ok ( r == S_OK, "nextNode (third time) wrong code\n");
2390         ok ( node != NULL, "nextNode, should be attribute\n");
2391     }
2392     else
2393         ok( FALSE, "no map\n");
2394 
2395     if (node)
2396     {
2397         type = NODE_INVALID;
2398         r = IXMLDOMNode_get_nodeType( node, &type);
2399         ok( r == S_OK, "getNamedItem returned wrong code\n");
2400         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
2401 
2402         str = NULL;
2403         r = IXMLDOMNode_get_baseName( node, NULL );
2404         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
2405 
2406         str = NULL;
2407         r = IXMLDOMNode_get_baseName( node, &str );
2408         ok( r == S_OK, "get_baseName returned wrong code\n");
2409         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
2410         SysFreeString( str );
2411 
2412         r = IXMLDOMNode_get_childNodes( node, NULL );
2413         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
2414 
2415         r = IXMLDOMNode_get_childNodes( node, &list );
2416         ok( r == S_OK, "get_childNodes returned wrong code\n");
2417 
2418         if (list)
2419         {
2420             r = IXMLDOMNodeList_nextNode( list, &next );
2421             ok( r == S_OK, "nextNode returned wrong code\n");
2422         }
2423         else
2424             ok( FALSE, "no childlist\n");
2425 
2426         if (next)
2427         {
2428             EXPECT_NO_CHILDREN(next);
2429 
2430             type = NODE_INVALID;
2431             r = IXMLDOMNode_get_nodeType( next, &type);
2432             ok( r == S_OK, "getNamedItem returned wrong code\n");
2433             ok( type == NODE_TEXT, "node not text\n");
2434 
2435             str = (void *)0xdeadbeef;
2436             r = IXMLDOMNode_get_baseName( next, &str );
2437             ok( r == S_FALSE, "get_baseName returned wrong code\n");
2438             ok( str == NULL, "basename was wrong\n");
2439             SysFreeString(str);
2440         }
2441         else
2442             ok( FALSE, "no next\n");
2443 
2444         if (next)
2445             IXMLDOMNode_Release( next );
2446         next = NULL;
2447         if (list)
2448             IXMLDOMNodeList_Release( list );
2449         list = NULL;
2450         if (node)
2451             IXMLDOMNode_Release( node );
2452     }
2453     else
2454         ok( FALSE, "no node\n");
2455     node = NULL;
2456 
2457     if (map)
2458         IXMLDOMNamedNodeMap_Release( map );
2459 
2460     /* now traverse the tree from the root element */
2461     if (element)
2462     {
2463         r = IXMLDOMElement_get_childNodes( element, &list );
2464         ok( r == S_OK, "get_childNodes returned wrong code\n");
2465 
2466         /* using get_item for child list doesn't advance the position */
2467         ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2468         expect_node(node, "E2.E2.D1");
2469         IXMLDOMNode_Release(node);
2470         ole_check(IXMLDOMNodeList_nextNode(list, &node));
2471         expect_node(node, "E1.E2.D1");
2472         IXMLDOMNode_Release(node);
2473         ole_check(IXMLDOMNodeList_reset(list));
2474 
2475         IXMLDOMNodeList_AddRef(list);
2476         expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2477         ole_check(IXMLDOMNodeList_reset(list));
2478 
2479         node = (void*)0xdeadbeef;
2480         str = SysAllocString(szdl);
2481         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2482         SysFreeString(str);
2483         ok( r == S_FALSE, "ret %08x\n", r );
2484         ok( node == NULL, "node %p\n", node );
2485 
2486         str = SysAllocString(szbs);
2487         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2488         SysFreeString(str);
2489         ok( r == S_OK, "ret %08x\n", r );
2490         r = IXMLDOMNode_Release( node );
2491         ok( r == 0, "ret %08x\n", r );
2492     }
2493     else
2494         ok( FALSE, "no element\n");
2495 
2496     if (list)
2497     {
2498         r = IXMLDOMNodeList_get_item(list, 0, NULL);
2499         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2500 
2501         r = IXMLDOMNodeList_get_length(list, NULL);
2502         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2503 
2504         r = IXMLDOMNodeList_get_length( list, &count );
2505         ok( r == S_OK, "get_length returns %08x\n", r );
2506         ok( count == 4, "get_length got %d\n", count );
2507 
2508         r = IXMLDOMNodeList_nextNode(list, NULL);
2509         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2510 
2511         r = IXMLDOMNodeList_nextNode( list, &node );
2512         ok( r == S_OK, "nextNode returned wrong code\n");
2513     }
2514     else
2515         ok( FALSE, "no list\n");
2516 
2517     if (node)
2518     {
2519         type = NODE_INVALID;
2520         r = IXMLDOMNode_get_nodeType( node, &type);
2521         ok( r == S_OK, "getNamedItem returned wrong code\n");
2522         ok( type == NODE_ELEMENT, "node not text\n");
2523 
2524         r = IXMLDOMNode_hasChildNodes( node, NULL );
2525         ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2526 
2527         EXPECT_CHILDREN(node);
2528 
2529         str = NULL;
2530         r = IXMLDOMNode_get_baseName( node, &str );
2531         ok( r == S_OK, "get_baseName returned wrong code\n");
2532         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2533         SysFreeString(str);
2534     }
2535     else
2536         ok( FALSE, "no node\n");
2537 
2538     if (node)
2539         IXMLDOMNode_Release( node );
2540     if (list)
2541         IXMLDOMNodeList_Release( list );
2542     if (element)
2543         IXMLDOMElement_Release( element );
2544 
2545     b = FALSE;
2546     str = SysAllocString( szComplete5 );
2547     r = IXMLDOMDocument_loadXML( doc, str, &b );
2548     ok( r == S_OK, "loadXML failed\n");
2549     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2550     SysFreeString( str );
2551 
2552     EXPECT_CHILDREN(doc);
2553 
2554     r = IXMLDOMDocument_get_documentElement( doc, &element );
2555     ok( r == S_OK, "should be a document element\n");
2556     ok( element != NULL, "should be an element\n");
2557 
2558     if (element)
2559     {
2560         static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2561         BSTR tag = NULL;
2562 
2563         /* check if the tag is correct */
2564         r = IXMLDOMElement_get_tagName( element, &tag );
2565         ok( r == S_OK, "couldn't get tag name\n");
2566         ok( tag != NULL, "tag was null\n");
2567         ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2568         SysFreeString( tag );
2569 
2570         IXMLDOMElement_Release( element );
2571     }
2572     ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2573 
2574     free_bstrs();
2575 }
2576 
2577 typedef struct {
2578     DOMNodeType type;
2579     REFIID iid;
2580 } refcount_test_t;
2581 
2582 static const refcount_test_t refcount_test[] = {
2583     { NODE_ELEMENT,                &IID_IXMLDOMElement },
2584     { NODE_ATTRIBUTE,              &IID_IXMLDOMAttribute },
2585     { NODE_TEXT,                   &IID_IXMLDOMText },
2586     { NODE_CDATA_SECTION,          &IID_IXMLDOMCDATASection },
2587     { NODE_ENTITY_REFERENCE,       &IID_IXMLDOMEntityReference },
2588     { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2589     { NODE_COMMENT,                &IID_IXMLDOMComment },
2590     { NODE_DOCUMENT_FRAGMENT,      &IID_IXMLDOMDocumentFragment },
2591     { NODE_INVALID,                &IID_NULL }
2592 };
2593 
2594 static void test_refs(void)
2595 {
2596     IXMLDOMImplementation *impl, *impl2;
2597     IXMLDOMElement *element, *elem2;
2598     IXMLDOMNodeList *node_list = NULL;
2599     IXMLDOMNode *node, *node2, *node3;
2600     const refcount_test_t *ptr;
2601     IXMLDOMDocument *doc;
2602     IUnknown *unk, *unk2;
2603     VARIANT_BOOL b;
2604     HRESULT hr;
2605     LONG ref;
2606 
2607     doc = create_document(&IID_IXMLDOMDocument);
2608 
2609     ptr = refcount_test;
2610     while (ptr->type != NODE_INVALID)
2611     {
2612         IUnknown *node_typed, *node_typed2;
2613         IDispatchEx *dispex, *dispex2;
2614         IDispatch *disp, *disp2;
2615         VARIANT type;
2616 
2617         V_VT(&type) = VT_I1;
2618         V_I1(&type) = ptr->type;
2619 
2620         EXPECT_REF(doc, 1);
2621         hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2622         EXPECT_HR(hr, S_OK);
2623         EXPECT_REF(doc, 1);
2624         EXPECT_REF(node, 1);
2625 
2626         /* try IDispatch and IUnknown from IXMLDOMNode */
2627         hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2628         EXPECT_HR(hr, S_OK);
2629         EXPECT_REF(unk, 2);
2630 todo_wine {
2631         EXPECT_REF(node, 1);
2632         ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2633 }
2634         EXPECT_REF(unk, 2);
2635         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2636         EXPECT_HR(hr, S_OK);
2637         todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2638         EXPECT_REF(unk, 3);
2639         todo_wine EXPECT_REF(disp, 1);
2640 
2641         EXPECT_REF(unk, 3);
2642         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2643         EXPECT_HR(hr, S_OK);
2644         todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2645         EXPECT_REF(unk, 4);
2646         todo_wine EXPECT_REF(disp2, 1);
2647 
2648         IDispatch_Release(disp);
2649         IDispatch_Release(disp2);
2650 
2651         /* get IXMLDOMNode from this IUnknown */
2652         EXPECT_REF(unk, 2);
2653         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2654         EXPECT_HR(hr, S_OK);
2655         todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2656         EXPECT_REF(unk, 3);
2657         todo_wine EXPECT_REF(node2, 1);
2658 
2659         EXPECT_REF(unk, 3);
2660         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2661         EXPECT_HR(hr, S_OK);
2662         todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2663         EXPECT_REF(unk, 4);
2664         todo_wine EXPECT_REF(node3, 1);
2665 
2666         IXMLDOMNode_Release(node2);
2667         IXMLDOMNode_Release(node3);
2668 
2669         /* try IDispatchEx from IUnknown */
2670         EXPECT_REF(unk, 2);
2671         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2672         EXPECT_HR(hr, S_OK);
2673         ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2674         EXPECT_REF(unk, 3);
2675         todo_wine EXPECT_REF(dispex, 1);
2676 
2677         EXPECT_REF(unk, 3);
2678         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2679         EXPECT_HR(hr, S_OK);
2680         todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2681         EXPECT_REF(unk, 4);
2682         todo_wine EXPECT_REF(dispex2, 1);
2683 
2684         IDispatchEx_Release(dispex);
2685         IDispatchEx_Release(dispex2);
2686 
2687         /* try corresponding IXMLDOM* */
2688         EXPECT_REF(unk, 2);
2689         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2690         EXPECT_HR(hr, S_OK);
2691         EXPECT_REF(unk, 3);
2692         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2693         EXPECT_HR(hr, S_OK);
2694         EXPECT_REF(unk, 4);
2695         todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2696         IUnknown_Release(node_typed);
2697         IUnknown_Release(node_typed2);
2698 
2699         /* try invalid IXMLDOM* */
2700         hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2701         EXPECT_HR(hr, E_NOINTERFACE);
2702 
2703         IUnknown_Release(unk);
2704 
2705         EXPECT_REF(node, 1);
2706         hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2707         EXPECT_HR(hr, S_OK);
2708         EXPECT_REF(node, 2);
2709         ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2710 
2711         EXPECT_REF(node, 2);
2712         hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2713         EXPECT_HR(hr, S_OK);
2714         EXPECT_REF(node, 3);
2715 todo_wine {
2716         EXPECT_REF(node_typed, 2);
2717         ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2718 }
2719         IUnknown_Release(node_typed);
2720 
2721         IXMLDOMNode_Release(node2);
2722         IXMLDOMNode_Release(node);
2723 
2724         ptr++;
2725     }
2726 
2727     EXPECT_REF(doc, 1);
2728     ref = IXMLDOMDocument_Release(doc);
2729     ok( ref == 0, "ref %d\n", ref);
2730 
2731     /* check IUnknown after releasing DOM iface */
2732     doc = create_document(&IID_IXMLDOMDocument);
2733     EXPECT_REF(doc, 1);
2734     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2735     EXPECT_HR(hr, S_OK);
2736 todo_wine {
2737     EXPECT_REF(unk, 3);
2738     EXPECT_REF(doc, 1);
2739 }
2740     IXMLDOMDocument_Release(doc);
2741     EXPECT_REF(unk, 1);
2742     IUnknown_Release(unk);
2743 
2744     doc = create_document(&IID_IXMLDOMDocument);
2745 
2746     EXPECT_REF(doc, 1);
2747     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2748     EXPECT_HR(hr, S_OK);
2749 todo_wine {
2750     EXPECT_REF(unk, 3);
2751     EXPECT_REF(doc, 1);
2752 }
2753     IUnknown_Release(unk);
2754 
2755     /* IXMLDOMImplementation */
2756     EXPECT_REF(doc, 1);
2757     hr = IXMLDOMDocument_get_implementation(doc, &impl);
2758     EXPECT_HR(hr, S_OK);
2759     EXPECT_REF(doc, 1);
2760     EXPECT_REF(impl, 1);
2761     hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2762     EXPECT_HR(hr, S_OK);
2763     EXPECT_REF(doc, 1);
2764     EXPECT_REF(impl2, 1);
2765     ok(impl != impl2, "got %p, %p\n", impl, impl2);
2766     IXMLDOMImplementation_Release(impl);
2767     IXMLDOMImplementation_Release(impl2);
2768 
2769     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2770     EXPECT_HR(hr, S_OK);
2771     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2772 
2773     EXPECT_REF(doc, 1);
2774     IXMLDOMDocument_AddRef( doc );
2775     EXPECT_REF(doc, 2);
2776     IXMLDOMDocument_AddRef( doc );
2777     EXPECT_REF(doc, 3);
2778 
2779     IXMLDOMDocument_Release( doc );
2780     IXMLDOMDocument_Release( doc );
2781 
2782     EXPECT_REF(doc, 1);
2783     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2784     EXPECT_HR(hr, S_OK);
2785 todo_wine {
2786     EXPECT_REF(unk, 3);
2787     EXPECT_REF(doc, 1);
2788 }
2789     hr = IXMLDOMDocument_get_documentElement(doc, &element);
2790     EXPECT_HR(hr, S_OK);
2791 todo_wine {
2792     EXPECT_REF(doc, 1);
2793     EXPECT_REF(element, 2);
2794 }
2795     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2796     EXPECT_HR(hr, S_OK);
2797 
2798 todo_wine {
2799     EXPECT_REF(doc, 1);
2800     EXPECT_REF(element, 2);
2801     EXPECT_REF(elem2, 2);
2802 }
2803     IXMLDOMElement_AddRef(element);
2804     todo_wine EXPECT_REF(element, 3);
2805     IXMLDOMElement_Release(element);
2806 
2807     /* get IUnknown from a node doesn't touch node instance refcount */
2808     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2809     EXPECT_HR(hr, S_OK);
2810     EXPECT_REF(element, 2);
2811 todo_wine {
2812     EXPECT_REF(unk, 4);
2813     EXPECT_REF(elem2, 2);
2814 }
2815     hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2816     EXPECT_HR(hr, S_OK);
2817 todo_wine {
2818     EXPECT_REF(unk, 5);
2819     EXPECT_REF(unk2, 5);
2820 }
2821     EXPECT_REF(element, 2);
2822     EXPECT_REF(elem2, 2);
2823 
2824     todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2825     IUnknown_Release(unk);
2826 
2827     /* IUnknown refcount is not affected by node refcount */
2828     todo_wine EXPECT_REF(unk2, 4);
2829     IXMLDOMElement_AddRef(elem2);
2830     todo_wine EXPECT_REF(unk2, 4);
2831     IXMLDOMElement_Release(elem2);
2832 
2833     IXMLDOMElement_Release(elem2);
2834     todo_wine EXPECT_REF(unk2, 3);
2835 
2836     IUnknown_Release(unk2);
2837 
2838     hr = IXMLDOMElement_get_childNodes( element, &node_list );
2839     EXPECT_HR(hr, S_OK);
2840 
2841     todo_wine EXPECT_REF(element, 2);
2842     EXPECT_REF(node_list, 1);
2843 
2844     hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2845     EXPECT_HR(hr, S_OK);
2846     EXPECT_REF(node_list, 1);
2847     EXPECT_REF(node, 1);
2848 
2849     hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2850     EXPECT_HR(hr, S_OK);
2851     EXPECT_REF(node_list, 1);
2852     EXPECT_REF(node2, 1);
2853 
2854     ref = IXMLDOMNode_Release( node );
2855     ok( ref == 0, "ref %d\n", ref );
2856     ref = IXMLDOMNode_Release( node2 );
2857     ok( ref == 0, "ref %d\n", ref );
2858 
2859     ref = IXMLDOMNodeList_Release( node_list );
2860     ok( ref == 0, "ref %d\n", ref );
2861 
2862     ok( node != node2, "node %p node2 %p\n", node, node2 );
2863 
2864     ref = IXMLDOMDocument_Release( doc );
2865     todo_wine ok( ref == 0, "ref %d\n", ref );
2866 
2867     todo_wine EXPECT_REF(element, 2);
2868 
2869     /* IUnknown must be unique however we obtain it */
2870     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2871     EXPECT_HR(hr, S_OK);
2872     EXPECT_REF(element, 2);
2873     hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2874     EXPECT_HR(hr, S_OK);
2875     todo_wine EXPECT_REF(element, 2);
2876     hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2877     EXPECT_HR(hr, S_OK);
2878     todo_wine EXPECT_REF(element, 2);
2879     ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2880     todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2881 
2882     IUnknown_Release( unk2 );
2883     IUnknown_Release( unk );
2884     IXMLDOMNode_Release( node );
2885     todo_wine EXPECT_REF(element, 2);
2886 
2887     IXMLDOMElement_Release( element );
2888 
2889     free_bstrs();
2890 }
2891 
2892 static void test_create(void)
2893 {
2894     static const WCHAR szOne[] = {'1',0};
2895     static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2896     HRESULT r;
2897     VARIANT var;
2898     BSTR str, name;
2899     IXMLDOMDocument *doc;
2900     IXMLDOMElement *element;
2901     IXMLDOMComment *comment;
2902     IXMLDOMText *text;
2903     IXMLDOMCDATASection *cdata;
2904     IXMLDOMNode *root, *node, *child;
2905     IXMLDOMNamedNodeMap *attr_map;
2906     IUnknown *unk;
2907     LONG ref;
2908     LONG num;
2909 
2910     doc = create_document(&IID_IXMLDOMDocument);
2911 
2912     EXPECT_REF(doc, 1);
2913 
2914     /* types not supported for creation */
2915     V_VT(&var) = VT_I1;
2916     V_I1(&var) = NODE_DOCUMENT;
2917     node = (IXMLDOMNode*)0x1;
2918     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2919     ok( r == E_INVALIDARG, "returns %08x\n", r );
2920     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2921 
2922     V_VT(&var) = VT_I1;
2923     V_I1(&var) = NODE_DOCUMENT_TYPE;
2924     node = (IXMLDOMNode*)0x1;
2925     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2926     ok( r == E_INVALIDARG, "returns %08x\n", r );
2927     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2928 
2929     V_VT(&var) = VT_I1;
2930     V_I1(&var) = NODE_ENTITY;
2931     node = (IXMLDOMNode*)0x1;
2932     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2933     ok( r == E_INVALIDARG, "returns %08x\n", r );
2934     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2935 
2936     V_VT(&var) = VT_I1;
2937     V_I1(&var) = NODE_NOTATION;
2938     node = (IXMLDOMNode*)0x1;
2939     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2940     ok( r == E_INVALIDARG, "returns %08x\n", r );
2941     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2942 
2943     /* NODE_COMMENT */
2944     V_VT(&var) = VT_I1;
2945     V_I1(&var) = NODE_COMMENT;
2946     node = NULL;
2947     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2948     ok( r == S_OK, "returns %08x\n", r );
2949     ok( node != NULL, "\n");
2950 
2951     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2952     ok( r == S_OK, "returns %08x\n", r );
2953     IXMLDOMNode_Release(node);
2954 
2955     str = NULL;
2956     r = IXMLDOMComment_get_data(comment, &str);
2957     ok( r == S_OK, "returns %08x\n", r );
2958     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2959     IXMLDOMComment_Release(comment);
2960     SysFreeString(str);
2961 
2962     node = (IXMLDOMNode*)0x1;
2963     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2964     ok( r == S_OK, "returns %08x\n", r );
2965 
2966     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2967     ok( r == S_OK, "returns %08x\n", r );
2968     IXMLDOMNode_Release(node);
2969 
2970     str = NULL;
2971     r = IXMLDOMComment_get_data(comment, &str);
2972     ok( r == S_OK, "returns %08x\n", r );
2973     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2974     IXMLDOMComment_Release(comment);
2975     SysFreeString(str);
2976 
2977     node = (IXMLDOMNode*)0x1;
2978     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2979     ok( r == S_OK, "returns %08x\n", r );
2980 
2981     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2982     ok( r == S_OK, "returns %08x\n", r );
2983     IXMLDOMNode_Release(node);
2984 
2985     str = NULL;
2986     r = IXMLDOMComment_get_data(comment, &str);
2987     ok( r == S_OK, "returns %08x\n", r );
2988     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2989     IXMLDOMComment_Release(comment);
2990     SysFreeString(str);
2991 
2992     /* NODE_TEXT */
2993     V_VT(&var) = VT_I1;
2994     V_I1(&var) = NODE_TEXT;
2995     node = NULL;
2996     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2997     ok( r == S_OK, "returns %08x\n", r );
2998     ok( node != NULL, "\n");
2999 
3000     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3001     ok( r == S_OK, "returns %08x\n", r );
3002     IXMLDOMNode_Release(node);
3003 
3004     str = NULL;
3005     r = IXMLDOMText_get_data(text, &str);
3006     ok( r == S_OK, "returns %08x\n", r );
3007     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3008     IXMLDOMText_Release(text);
3009     SysFreeString(str);
3010 
3011     node = (IXMLDOMNode*)0x1;
3012     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3013     ok( r == S_OK, "returns %08x\n", r );
3014 
3015     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3016     ok( r == S_OK, "returns %08x\n", r );
3017     IXMLDOMNode_Release(node);
3018 
3019     str = NULL;
3020     r = IXMLDOMText_get_data(text, &str);
3021     ok( r == S_OK, "returns %08x\n", r );
3022     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3023     IXMLDOMText_Release(text);
3024     SysFreeString(str);
3025 
3026     node = (IXMLDOMNode*)0x1;
3027     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3028     ok( r == S_OK, "returns %08x\n", r );
3029 
3030     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3031     ok( r == S_OK, "returns %08x\n", r );
3032     IXMLDOMNode_Release(node);
3033 
3034     str = NULL;
3035     r = IXMLDOMText_get_data(text, &str);
3036     ok( r == S_OK, "returns %08x\n", r );
3037     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3038     IXMLDOMText_Release(text);
3039     SysFreeString(str);
3040 
3041     /* NODE_CDATA_SECTION */
3042     V_VT(&var) = VT_I1;
3043     V_I1(&var) = NODE_CDATA_SECTION;
3044     node = NULL;
3045     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3046     ok( r == S_OK, "returns %08x\n", r );
3047     ok( node != NULL, "\n");
3048 
3049     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3050     ok( r == S_OK, "returns %08x\n", r );
3051     IXMLDOMNode_Release(node);
3052 
3053     str = NULL;
3054     r = IXMLDOMCDATASection_get_data(cdata, &str);
3055     ok( r == S_OK, "returns %08x\n", r );
3056     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3057     IXMLDOMCDATASection_Release(cdata);
3058     SysFreeString(str);
3059 
3060     node = (IXMLDOMNode*)0x1;
3061     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3062     ok( r == S_OK, "returns %08x\n", r );
3063 
3064     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3065     ok( r == S_OK, "returns %08x\n", r );
3066     IXMLDOMNode_Release(node);
3067 
3068     str = NULL;
3069     r = IXMLDOMCDATASection_get_data(cdata, &str);
3070     ok( r == S_OK, "returns %08x\n", r );
3071     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3072     IXMLDOMCDATASection_Release(cdata);
3073     SysFreeString(str);
3074 
3075     node = (IXMLDOMNode*)0x1;
3076     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3077     ok( r == S_OK, "returns %08x\n", r );
3078 
3079     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3080     ok( r == S_OK, "returns %08x\n", r );
3081     IXMLDOMNode_Release(node);
3082 
3083     str = NULL;
3084     r = IXMLDOMCDATASection_get_data(cdata, &str);
3085     ok( r == S_OK, "returns %08x\n", r );
3086     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3087     IXMLDOMCDATASection_Release(cdata);
3088     SysFreeString(str);
3089 
3090     /* NODE_ATTRIBUTE */
3091     V_VT(&var) = VT_I1;
3092     V_I1(&var) = NODE_ATTRIBUTE;
3093     node = (IXMLDOMNode*)0x1;
3094     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3095     ok( r == E_FAIL, "returns %08x\n", r );
3096     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3097 
3098     V_VT(&var) = VT_I1;
3099     V_I1(&var) = NODE_ATTRIBUTE;
3100     node = (IXMLDOMNode*)0x1;
3101     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3102     ok( r == E_FAIL, "returns %08x\n", r );
3103     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3104 
3105     V_VT(&var) = VT_I1;
3106     V_I1(&var) = NODE_ATTRIBUTE;
3107     str = SysAllocString( szlc );
3108     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3109     ok( r == S_OK, "returns %08x\n", r );
3110     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3111     SysFreeString(str);
3112 
3113     /* a name is required for attribute, try a BSTR with first null wchar */
3114     V_VT(&var) = VT_I1;
3115     V_I1(&var) = NODE_ATTRIBUTE;
3116     str = SysAllocString( szstr1 );
3117     str[0] = 0;
3118     node = (IXMLDOMNode*)0x1;
3119     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3120     ok( r == E_FAIL, "returns %08x\n", r );
3121     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3122     SysFreeString(str);
3123 
3124     /* NODE_PROCESSING_INSTRUCTION */
3125     V_VT(&var) = VT_I1;
3126     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3127     node = (IXMLDOMNode*)0x1;
3128     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3129     ok( r == E_FAIL, "returns %08x\n", r );
3130     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3131 
3132     V_VT(&var) = VT_I1;
3133     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3134     node = (IXMLDOMNode*)0x1;
3135     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3136     ok( r == E_FAIL, "returns %08x\n", r );
3137     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3138 
3139     V_VT(&var) = VT_I1;
3140     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3141     r = IXMLDOMDocument_createNode( doc, var, _bstr_("pi"), NULL, NULL );
3142     ok( r == E_INVALIDARG, "returns %08x\n", r );
3143 
3144     /* NODE_ENTITY_REFERENCE */
3145     V_VT(&var) = VT_I1;
3146     V_I1(&var) = NODE_ENTITY_REFERENCE;
3147     node = (IXMLDOMNode*)0x1;
3148     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3149     ok( r == E_FAIL, "returns %08x\n", r );
3150     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3151 
3152     V_VT(&var) = VT_I1;
3153     V_I1(&var) = NODE_ENTITY_REFERENCE;
3154     node = (IXMLDOMNode*)0x1;
3155     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3156     ok( r == E_FAIL, "returns %08x\n", r );
3157     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3158 
3159     /* NODE_ELEMENT */
3160     V_VT(&var) = VT_I1;
3161     V_I1(&var) = NODE_ELEMENT;
3162     node = (IXMLDOMNode*)0x1;
3163     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3164     ok( r == E_FAIL, "returns %08x\n", r );
3165     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3166 
3167     V_VT(&var) = VT_I1;
3168     V_I1(&var) = NODE_ELEMENT;
3169     node = (IXMLDOMNode*)0x1;
3170     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3171     ok( r == E_FAIL, "returns %08x\n", r );
3172     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3173 
3174     V_VT(&var) = VT_I1;
3175     V_I1(&var) = NODE_ELEMENT;
3176     str = SysAllocString( szlc );
3177     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3178     ok( r == S_OK, "returns %08x\n", r );
3179     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3180 
3181     V_VT(&var) = VT_I1;
3182     V_I1(&var) = NODE_ELEMENT;
3183     r = IXMLDOMDocument_createNode( doc, var, str, NULL, NULL );
3184     ok( r == E_INVALIDARG, "returns %08x\n", r );
3185 
3186     V_VT(&var) = VT_R4;
3187     V_R4(&var) = NODE_ELEMENT;
3188     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3189     ok( r == S_OK, "returns %08x\n", r );
3190     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3191 
3192     V_VT(&var) = VT_BSTR;
3193     V_BSTR(&var) = SysAllocString( szOne );
3194     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3195     ok( r == S_OK, "returns %08x\n", r );
3196     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3197     VariantClear(&var);
3198 
3199     V_VT(&var) = VT_BSTR;
3200     V_BSTR(&var) = SysAllocString( szOneGarbage );
3201     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3202     ok( r == E_INVALIDARG, "returns %08x\n", r );
3203     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3204     VariantClear(&var);
3205 
3206     V_VT(&var) = VT_I4;
3207     V_I4(&var) = NODE_ELEMENT;
3208     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3209     ok( r == S_OK, "returns %08x\n", r );
3210 
3211     EXPECT_REF(doc, 1);
3212     r = IXMLDOMDocument_appendChild( doc, node, &root );
3213     ok( r == S_OK, "returns %08x\n", r );
3214     ok( node == root, "%p %p\n", node, root );
3215     EXPECT_REF(doc, 1);
3216 
3217     EXPECT_REF(node, 2);
3218 
3219     ref = IXMLDOMNode_Release( node );
3220     ok(ref == 1, "ref %d\n", ref);
3221     SysFreeString( str );
3222 
3223     V_VT(&var) = VT_I4;
3224     V_I4(&var) = NODE_ELEMENT;
3225     str = SysAllocString( szbs );
3226     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3227     ok( r == S_OK, "returns %08x\n", r );
3228     SysFreeString( str );
3229 
3230     EXPECT_REF(node, 1);
3231 
3232     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk );
3233     ok( r == S_OK, "returns %08x\n", r );
3234 
3235     EXPECT_REF(unk, 2);
3236 
3237     V_VT(&var) = VT_EMPTY;
3238     child = NULL;
3239     r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
3240     ok( r == S_OK, "returns %08x\n", r );
3241     ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
3242 
3243     todo_wine EXPECT_REF(unk, 4);
3244 
3245     IXMLDOMNode_Release( child );
3246     IUnknown_Release( unk );
3247 
3248     V_VT(&var) = VT_NULL;
3249     V_DISPATCH(&var) = (IDispatch*)node;
3250     r = IXMLDOMNode_insertBefore( root, node, var, &child );
3251     ok( r == S_OK, "returns %08x\n", r );
3252     ok( node == child, "%p %p\n", node, child );
3253     IXMLDOMNode_Release( child );
3254 
3255     V_VT(&var) = VT_NULL;
3256     V_DISPATCH(&var) = (IDispatch*)node;
3257     r = IXMLDOMNode_insertBefore( root, node, var, NULL );
3258     ok( r == S_OK, "returns %08x\n", r );
3259     IXMLDOMNode_Release( node );
3260 
3261     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (void**)&element );
3262     ok( r == S_OK, "returns %08x\n", r );
3263 
3264     r = IXMLDOMElement_get_attributes( element, &attr_map );
3265     ok( r == S_OK, "returns %08x\n", r );
3266     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3267     ok( r == S_OK, "returns %08x\n", r );
3268     ok( num == 0, "num %d\n", num );
3269     IXMLDOMNamedNodeMap_Release( attr_map );
3270 
3271     V_VT(&var) = VT_BSTR;
3272     V_BSTR(&var) = SysAllocString( szstr1 );
3273     name = SysAllocString( szdl );
3274     r = IXMLDOMElement_setAttribute( element, name, var );
3275     ok( r == S_OK, "returns %08x\n", r );
3276     r = IXMLDOMElement_get_attributes( element, &attr_map );
3277     ok( r == S_OK, "returns %08x\n", r );
3278     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3279     ok( r == S_OK, "returns %08x\n", r );
3280     ok( num == 1, "num %d\n", num );
3281     IXMLDOMNamedNodeMap_Release( attr_map );
3282     VariantClear(&var);
3283 
3284     V_VT(&var) = VT_BSTR;
3285     V_BSTR(&var) = SysAllocString( szstr2 );
3286     r = IXMLDOMElement_setAttribute( element, name, var );
3287     ok( r == S_OK, "returns %08x\n", r );
3288     r = IXMLDOMElement_get_attributes( element, &attr_map );
3289     ok( r == S_OK, "returns %08x\n", r );
3290     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3291     ok( r == S_OK, "returns %08x\n", r );
3292     ok( num == 1, "num %d\n", num );
3293     IXMLDOMNamedNodeMap_Release( attr_map );
3294     VariantClear(&var);
3295     r = IXMLDOMElement_getAttribute( element, name, &var );
3296     ok( r == S_OK, "returns %08x\n", r );
3297     ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
3298     VariantClear(&var);
3299     SysFreeString(name);
3300 
3301     V_VT(&var) = VT_BSTR;
3302     V_BSTR(&var) = SysAllocString( szstr1 );
3303     name = SysAllocString( szlc );
3304     r = IXMLDOMElement_setAttribute( element, name, var );
3305     ok( r == S_OK, "returns %08x\n", r );
3306     r = IXMLDOMElement_get_attributes( element, &attr_map );
3307     ok( r == S_OK, "returns %08x\n", r );
3308     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3309     ok( r == S_OK, "returns %08x\n", r );
3310     ok( num == 2, "num %d\n", num );
3311     IXMLDOMNamedNodeMap_Release( attr_map );
3312     VariantClear(&var);
3313     SysFreeString(name);
3314 
3315     V_VT(&var) = VT_I4;
3316     V_I4(&var) = 10;
3317     name = SysAllocString( szbs );
3318     r = IXMLDOMElement_setAttribute( element, name, var );
3319     ok( r == S_OK, "returns %08x\n", r );
3320     VariantClear(&var);
3321     r = IXMLDOMElement_getAttribute( element, name, &var );
3322     ok( r == S_OK, "returns %08x\n", r );
3323     ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
3324     VariantClear(&var);
3325     SysFreeString(name);
3326 
3327     /* Create an Attribute */
3328     V_VT(&var) = VT_I4;
3329     V_I4(&var) = NODE_ATTRIBUTE;
3330     str = SysAllocString( szAttribute );
3331     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3332     ok( r == S_OK, "returns %08x\n", r );
3333     ok( node != NULL, "node was null\n");
3334     SysFreeString(str);
3335 
3336     IXMLDOMElement_Release( element );
3337     IXMLDOMNode_Release( root );
3338     IXMLDOMDocument_Release( doc );
3339 }
3340 
3341 struct queryresult_t {
3342     const char *query;
3343     const char *result;
3344     int len;
3345 };
3346 
3347 static const struct queryresult_t elementsbytagname[] = {
3348     { "",    "P1.D1 E2.D1 E1.E2.D1 T1.E1.E2.D1 E2.E2.D1 T1.E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1 T1.E1.E4.E2.D1", 10 },
3349     { "*",   "E2.D1 E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1", 6 },
3350     { "bs",  "E1.E2.D1", 1 },
3351     { "dl",  "", 0 },
3352     { "str1","", 0 },
3353     { NULL }
3354 };
3355 
3356 static void test_getElementsByTagName(void)
3357 {
3358     const struct queryresult_t *ptr = elementsbytagname;
3359     IXMLDOMNodeList *node_list;
3360     IXMLDOMDocument *doc;
3361     IXMLDOMElement *elem;
3362     WCHAR buff[100];
3363     VARIANT_BOOL b;
3364     HRESULT r;
3365     LONG len;
3366     BSTR str;
3367 
3368     doc = create_document(&IID_IXMLDOMDocument);
3369 
3370     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3371     ok( r == S_OK, "loadXML failed\n");
3372     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3373 
3374     /* null arguments cases */
3375     r = IXMLDOMDocument_getElementsByTagName(doc, NULL, &node_list);
3376     ok( r == E_INVALIDARG, "ret %08x\n", r );
3377     r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), NULL);
3378     ok( r == E_INVALIDARG, "ret %08x\n", r );
3379 
3380     while (ptr->query)
3381     {
3382         r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_(ptr->query), &node_list);
3383         ok(r == S_OK, "ret %08x\n", r);
3384         r = IXMLDOMNodeList_get_length(node_list, &len);
3385         ok(r == S_OK, "ret %08x\n", r);
3386         ok(len == ptr->len, "%s: got len %d, expected %d\n", ptr->query, len, ptr->len);
3387         expect_list_and_release(node_list, ptr->result);
3388 
3389         free_bstrs();
3390         ptr++;
3391     }
3392 
3393     /* broken query BSTR */
3394     memcpy(&buff[2], szstar, sizeof(szstar));
3395     /* just a big length */
3396     *(DWORD*)buff = 0xf0f0;
3397     r = IXMLDOMDocument_getElementsByTagName(doc, &buff[2], &node_list);
3398     ok( r == S_OK, "ret %08x\n", r );
3399     r = IXMLDOMNodeList_get_length( node_list, &len );
3400     ok( r == S_OK, "ret %08x\n", r );
3401     ok( len == 6, "len %d\n", len );
3402     IXMLDOMNodeList_Release( node_list );
3403 
3404     /* test for element */
3405     r = IXMLDOMDocument_get_documentElement(doc, &elem);
3406     ok( r == S_OK, "ret %08x\n", r );
3407 
3408     str = SysAllocString( szstar );
3409 
3410     /* null arguments cases */
3411     r = IXMLDOMElement_getElementsByTagName(elem, NULL, &node_list);
3412     ok( r == E_INVALIDARG, "ret %08x\n", r );
3413     r = IXMLDOMElement_getElementsByTagName(elem, str, NULL);
3414     ok( r == E_INVALIDARG, "ret %08x\n", r );
3415 
3416     r = IXMLDOMElement_getElementsByTagName(elem, str, &node_list);
3417     ok( r == S_OK, "ret %08x\n", r );
3418     r = IXMLDOMNodeList_get_length( node_list, &len );
3419     ok( r == S_OK, "ret %08x\n", r );
3420     ok( len == 5, "len %d\n", len );
3421     expect_list_and_release(node_list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1");
3422     SysFreeString( str );
3423 
3424     /* broken query BSTR */
3425     memcpy(&buff[2], szstar, sizeof(szstar));
3426     /* just a big length */
3427     *(DWORD*)buff = 0xf0f0;
3428     r = IXMLDOMElement_getElementsByTagName(elem, &buff[2], &node_list);
3429     ok( r == S_OK, "ret %08x\n", r );
3430     r = IXMLDOMNodeList_get_length( node_list, &len );
3431     ok( r == S_OK, "ret %08x\n", r );
3432     ok( len == 5, "len %d\n", len );
3433     IXMLDOMNodeList_Release( node_list );
3434 
3435     IXMLDOMElement_Release(elem);
3436 
3437     IXMLDOMDocument_Release( doc );
3438 
3439     free_bstrs();
3440 }
3441 
3442 static void test_get_text(void)
3443 {
3444     HRESULT r;
3445     BSTR str;
3446     VARIANT_BOOL b;
3447     IXMLDOMDocument *doc;
3448     IXMLDOMNode *node, *node2, *node3;
3449     IXMLDOMNode *nodeRoot;
3450     IXMLDOMNodeList *node_list;
3451     IXMLDOMNamedNodeMap *node_map;
3452     LONG len;
3453 
3454     doc = create_document(&IID_IXMLDOMDocument);
3455 
3456     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3457     ok( r == S_OK, "loadXML failed\n");
3458     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3459 
3460     str = SysAllocString( szbs );
3461     r = IXMLDOMDocument_getElementsByTagName( doc, str, &node_list );
3462     ok( r == S_OK, "ret %08x\n", r );
3463     SysFreeString(str);
3464 
3465     /* Test to get all child node text. */
3466     r = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&nodeRoot);
3467     ok( r == S_OK, "ret %08x\n", r );
3468     if(r == S_OK)
3469     {
3470         r = IXMLDOMNode_get_text( nodeRoot, &str );
3471         ok( r == S_OK, "ret %08x\n", r );
3472         expect_bstr_eq_and_free(str, "fn1.txt\n \nfn2.txt\n \nf1");
3473 
3474         IXMLDOMNode_Release(nodeRoot);
3475     }
3476 
3477     r = IXMLDOMNodeList_get_length( node_list, NULL );
3478     ok( r == E_INVALIDARG, "ret %08x\n", r );
3479 
3480     r = IXMLDOMNodeList_get_length( node_list, &len );
3481     ok( r == S_OK, "ret %08x\n", r );
3482     ok( len == 1, "expect 1 got %d\n", len );
3483 
3484     r = IXMLDOMNodeList_get_item( node_list, 0, NULL );
3485     ok( r == E_INVALIDARG, "ret %08x\n", r );
3486 
3487     r = IXMLDOMNodeList_nextNode( node_list, NULL );
3488     ok( r == E_INVALIDARG, "ret %08x\n", r );
3489 
3490     r = IXMLDOMNodeList_get_item( node_list, 0, &node );
3491     ok( r == S_OK, "ret %08x\n", r );
3492     IXMLDOMNodeList_Release( node_list );
3493 
3494     /* Invalid output parameter*/
3495     r = IXMLDOMNode_get_text( node, NULL );
3496     ok( r == E_INVALIDARG, "ret %08x\n", r );
3497 
3498     r = IXMLDOMNode_get_text( node, &str );
3499     ok( r == S_OK, "ret %08x\n", r );
3500     ok( !memcmp(str, szfn1_txt, lstrlenW(szfn1_txt) ), "wrong string\n" );
3501     SysFreeString(str);
3502 
3503     r = IXMLDOMNode_get_attributes( node, &node_map );
3504     ok( r == S_OK, "ret %08x\n", r );
3505 
3506     str = SysAllocString( szvr );
3507     r = IXMLDOMNamedNodeMap_getNamedItem( node_map, str, &node2 );
3508     ok( r == S_OK, "ret %08x\n", r );
3509     SysFreeString(str);
3510 
3511     r = IXMLDOMNode_get_text( node2, &str );
3512     ok( r == S_OK, "ret %08x\n", r );
3513     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3514     SysFreeString(str);
3515 
3516     r = IXMLDOMNode_get_firstChild( node2, &node3 );
3517     ok( r == S_OK, "ret %08x\n", r );
3518 
3519     r = IXMLDOMNode_get_text( node3, &str );
3520     ok( r == S_OK, "ret %08x\n", r );
3521     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3522     SysFreeString(str);
3523 
3524 
3525     IXMLDOMNode_Release( node3 );
3526     IXMLDOMNode_Release( node2 );
3527     IXMLDOMNamedNodeMap_Release( node_map );
3528     IXMLDOMNode_Release( node );
3529     IXMLDOMDocument_Release( doc );
3530 
3531     free_bstrs();
3532 }
3533 
3534 #ifdef __REACTOS__
3535 /*
3536  * This function is to display that xmlnodelist_QueryInterface
3537  * generates SEGV for these conditions, and once fixed make sure
3538  * it never does it again.
3539  */
3540 static void verify_nodelist_query_interface(IXMLDOMNodeList *node_list)
3541 {
3542     HRESULT hr;
3543     /*
3544      * NOTE: The following calls are supposed to test wine's
3545      * xmlnodelist_QueryInterface behaving properly.
3546      * While we should be able to expect E_POINTER (due to the NULL pointer),
3547      * it seems MS' own implementation(s) violate the spec and return
3548      * E_INVALIDARG. To not get cought be a potentially correct implementation
3549      * in the future, we check for NOT S_OK.
3550      */
3551     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, NULL);
3552     EXPECT_NOT_HR(hr, S_OK);
3553     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatch, NULL);
3554     EXPECT_NOT_HR(hr, S_OK);
3555     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IXMLDOMNodeList, NULL);
3556     EXPECT_NOT_HR(hr, S_OK);
3557 }
3558 #endif
3559 
3560 static void test_get_childNodes(void)
3561 {
3562     IXMLDOMNodeList *node_list, *node_list2;
3563     IEnumVARIANT *enum1, *enum2, *enum3;
3564     VARIANT_BOOL b;
3565     IXMLDOMDocument *doc;
3566     IXMLDOMNode *node, *node2;
3567     IXMLDOMElement *element;
3568     IUnknown *unk1, *unk2;
3569     HRESULT hr;
3570     VARIANT v;
3571     BSTR str;
3572     LONG len;
3573 
3574     doc = create_document(&IID_IXMLDOMDocument);
3575 
3576     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3577     EXPECT_HR(hr, S_OK);
3578     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3579 
3580     hr = IXMLDOMDocument_get_documentElement( doc, &element );
3581     EXPECT_HR(hr, S_OK);
3582 
3583     hr = IXMLDOMElement_get_childNodes( element, &node_list );
3584     EXPECT_HR(hr, S_OK);
3585 
3586 #ifdef __REACTOS__
3587     verify_nodelist_query_interface(node_list);
3588 #endif
3589 
3590     hr = IXMLDOMNodeList_get_length( node_list, &len );
3591     EXPECT_HR(hr, S_OK);
3592     ok( len == 4, "len %d\n", len);
3593 
3594     /* refcount tests for IEnumVARIANT support */
3595     EXPECT_REF(node_list, 1);
3596     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1);
3597     EXPECT_HR(hr, S_OK);
3598     EXPECT_REF(node_list, 1);
3599     EXPECT_REF(enum1, 2);
3600 
3601     EXPECT_REF(node_list, 1);
3602     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum2);
3603     EXPECT_HR(hr, S_OK);
3604     EXPECT_REF(node_list, 1);
3605     ok(enum2 == enum1, "got %p, %p\n", enum2, enum1);
3606     IEnumVARIANT_Release(enum2);
3607 
3608     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3609     EXPECT_HR(hr, S_OK);
3610     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
3611     EXPECT_HR(hr, S_OK);
3612     EXPECT_REF(node_list, 3);
3613     EXPECT_REF(enum1, 2);
3614     ok(unk1 == unk2, "got %p, %p\n", unk1, unk2);
3615     IUnknown_Release(unk1);
3616     IUnknown_Release(unk2);
3617 
3618     EXPECT_REF(node_list, 1);
3619     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum2);
3620     EXPECT_HR(hr, S_OK);
3621     EXPECT_REF(node_list, 2);
3622     EXPECT_REF(enum2, 1);
3623     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
3624 
3625     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
3626     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3627     EXPECT_HR(hr, S_OK);
3628     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
3629     EXPECT_HR(hr, S_OK);
3630     EXPECT_REF(node_list, 3);
3631     EXPECT_REF(enum2, 2);
3632     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
3633     IUnknown_Release(unk1);
3634     IUnknown_Release(unk2);
3635 
3636     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum3);
3637     EXPECT_HR(hr, S_OK);
3638     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
3639     IEnumVARIANT_Release(enum3);
3640     IEnumVARIANT_Release(enum2);
3641 
3642     /* iteration tests */
3643     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
3644     EXPECT_HR(hr, S_OK);
3645     hr = IXMLDOMNode_get_nodeName(node, &str);
3646     EXPECT_HR(hr, S_OK);
3647     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3648     SysFreeString(str);
3649     IXMLDOMNode_Release(node);
3650 
3651     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3652     EXPECT_HR(hr, S_OK);
3653     hr = IXMLDOMNode_get_nodeName(node, &str);
3654     EXPECT_HR(hr, S_OK);
3655     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3656     SysFreeString(str);
3657     IXMLDOMNode_Release(node);
3658 
3659     V_VT(&v) = VT_EMPTY;
3660     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
3661     EXPECT_HR(hr, S_OK);
3662     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
3663     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
3664     EXPECT_HR(hr, S_OK);
3665     hr = IXMLDOMNode_get_nodeName(node, &str);
3666     EXPECT_HR(hr, S_OK);
3667     ok(!lstrcmpW(str, _bstr_("bs")), "got node name %s\n", wine_dbgstr_w(str));
3668     SysFreeString(str);
3669     IXMLDOMNode_Release(node);
3670     VariantClear(&v);
3671 
3672     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3673     EXPECT_HR(hr, S_OK);
3674     hr = IXMLDOMNode_get_nodeName(node, &str);
3675     EXPECT_HR(hr, S_OK);
3676     ok(!lstrcmpW(str, _bstr_("pr")), "got %s\n", wine_dbgstr_w(str));
3677     SysFreeString(str);
3678     IXMLDOMNode_Release(node);
3679 
3680     IEnumVARIANT_Release(enum1);
3681 
3682     hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
3683     EXPECT_HR(hr, S_OK);
3684 
3685     hr = IXMLDOMNode_get_childNodes( node, &node_list2 );
3686     EXPECT_HR(hr, S_OK);
3687 
3688     hr = IXMLDOMNodeList_get_length( node_list2, &len );
3689     EXPECT_HR(hr, S_OK);
3690     ok( len == 0, "len %d\n", len);
3691 
3692     hr = IXMLDOMNodeList_get_item( node_list2, 0, &node2);
3693     EXPECT_HR(hr, S_FALSE);
3694 
3695     IXMLDOMNodeList_Release( node_list2 );
3696     IXMLDOMNode_Release( node );
3697     IXMLDOMNodeList_Release( node_list );
3698     IXMLDOMElement_Release( element );
3699 
3700     /* test for children of <?xml ..?> node */
3701     hr = IXMLDOMDocument_get_firstChild(doc, &node);
3702     EXPECT_HR(hr, S_OK);
3703 
3704     str = NULL;
3705     hr = IXMLDOMNode_get_nodeName(node, &str);
3706     EXPECT_HR(hr, S_OK);
3707     ok(!lstrcmpW(str, _bstr_("xml")), "got %s\n", wine_dbgstr_w(str));
3708     SysFreeString(str);
3709 
3710     /* it returns empty but valid node list */
3711     node_list = (void*)0xdeadbeef;
3712     hr = IXMLDOMNode_get_childNodes(node, &node_list);
3713     EXPECT_HR(hr, S_OK);
3714 
3715     len = -1;
3716     hr = IXMLDOMNodeList_get_length(node_list, &len);
3717     EXPECT_HR(hr, S_OK);
3718     ok(len == 0, "got %d\n", len);
3719 
3720     IXMLDOMNodeList_Release( node_list );
3721     IXMLDOMNode_Release(node);
3722 
3723     IXMLDOMDocument_Release( doc );
3724     free_bstrs();
3725 }
3726 
3727 static void test_get_firstChild(void)
3728 {
3729     static const WCHAR xmlW[] = {'x','m','l',0};
3730     IXMLDOMDocument *doc;
3731     IXMLDOMNode *node;
3732     VARIANT_BOOL b;
3733     HRESULT r;
3734     BSTR str;
3735 
3736     doc = create_document(&IID_IXMLDOMDocument);
3737 
3738     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3739     ok( r == S_OK, "loadXML failed\n");
3740     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3741 
3742     r = IXMLDOMDocument_get_firstChild( doc, &node );
3743     ok( r == S_OK, "ret %08x\n", r);
3744 
3745     r = IXMLDOMNode_get_nodeName( node, &str );
3746     ok( r == S_OK, "ret %08x\n", r);
3747 
3748     ok(!lstrcmpW(str, xmlW), "expected \"xml\" node name, got %s\n", wine_dbgstr_w(str));
3749 
3750     SysFreeString(str);
3751     IXMLDOMNode_Release( node );
3752     IXMLDOMDocument_Release( doc );
3753 
3754     free_bstrs();
3755 }
3756 
3757 static void test_get_lastChild(void)
3758 {
3759     static const WCHAR lcW[] = {'l','c',0};
3760     static const WCHAR foW[] = {'f','o',0};
3761     IXMLDOMDocument *doc;
3762     IXMLDOMNode *node, *child;
3763     VARIANT_BOOL b;
3764     HRESULT r;
3765     BSTR str;
3766 
3767     doc = create_document(&IID_IXMLDOMDocument);
3768 
3769     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3770     ok( r == S_OK, "loadXML failed\n");
3771     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3772 
3773     r = IXMLDOMDocument_get_lastChild( doc, &node );
3774     ok( r == S_OK, "ret %08x\n", r);
3775 
3776     r = IXMLDOMNode_get_nodeName( node, &str );
3777     ok( r == S_OK, "ret %08x\n", r);
3778 
3779     ok(memcmp(str, lcW, sizeof(lcW)) == 0, "expected \"lc\" node name\n");
3780     SysFreeString(str);
3781 
3782     r = IXMLDOMNode_get_lastChild( node, &child );
3783     ok( r == S_OK, "ret %08x\n", r);
3784 
3785     r = IXMLDOMNode_get_nodeName( child, &str );
3786     ok( r == S_OK, "ret %08x\n", r);
3787 
3788     ok(memcmp(str, foW, sizeof(foW)) == 0, "expected \"fo\" node name\n");
3789     SysFreeString(str);
3790 
3791     IXMLDOMNode_Release( child );
3792     IXMLDOMNode_Release( node );
3793     IXMLDOMDocument_Release( doc );
3794 
3795     free_bstrs();
3796 }
3797 
3798 static void test_removeChild(void)
3799 {
3800     HRESULT r;
3801     VARIANT_BOOL b;
3802     IXMLDOMDocument *doc;
3803     IXMLDOMElement *element, *lc_element;
3804     IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node, *lc_node;
3805     IXMLDOMNodeList *root_list, *fo_list;
3806 
3807     doc = create_document(&IID_IXMLDOMDocument);
3808 
3809     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3810     ok( r == S_OK, "loadXML failed\n");
3811     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3812 
3813     r = IXMLDOMDocument_get_documentElement( doc, &element );
3814     ok( r == S_OK, "ret %08x\n", r);
3815     todo_wine EXPECT_REF(element, 2);
3816 
3817     r = IXMLDOMElement_get_childNodes( element, &root_list );
3818     ok( r == S_OK, "ret %08x\n", r);
3819     EXPECT_REF(root_list, 1);
3820 
3821     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3822     ok( r == S_OK, "ret %08x\n", r);
3823     EXPECT_REF(fo_node, 1);
3824 
3825     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3826     ok( r == S_OK, "ret %08x\n", r);
3827     EXPECT_REF(fo_list, 1);
3828 
3829     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3830     ok( r == S_OK, "ret %08x\n", r);
3831     EXPECT_REF(ba_node, 1);
3832 
3833     /* invalid parameter: NULL ptr */
3834     removed_node = (void*)0xdeadbeef;
3835     r = IXMLDOMElement_removeChild( element, NULL, &removed_node );
3836     ok( r == E_INVALIDARG, "ret %08x\n", r );
3837     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3838 
3839     /* ba_node is a descendant of element, but not a direct child. */
3840     removed_node = (void*)0xdeadbeef;
3841     EXPECT_REF(ba_node, 1);
3842     EXPECT_CHILDREN(fo_node);
3843     r = IXMLDOMElement_removeChild( element, ba_node, &removed_node );
3844     ok( r == E_INVALIDARG, "ret %08x\n", r );
3845     ok( removed_node == NULL, "%p\n", removed_node );
3846     EXPECT_REF(ba_node, 1);
3847     EXPECT_CHILDREN(fo_node);
3848 
3849     EXPECT_REF(ba_node, 1);
3850     EXPECT_REF(fo_node, 1);
3851     r = IXMLDOMElement_removeChild( element, fo_node, &removed_node );
3852     ok( r == S_OK, "ret %08x\n", r);
3853     ok( fo_node == removed_node, "node %p node2 %p\n", fo_node, removed_node );
3854     EXPECT_REF(fo_node, 2);
3855     EXPECT_REF(ba_node, 1);
3856 
3857     /* try removing already removed child */
3858     temp_node = (void*)0xdeadbeef;
3859     r = IXMLDOMElement_removeChild( element, fo_node, &temp_node );
3860     ok( r == E_INVALIDARG, "ret %08x\n", r);
3861     ok( temp_node == NULL, "%p\n", temp_node );
3862     IXMLDOMNode_Release( fo_node );
3863 
3864     /* the removed node has no parent anymore */
3865     r = IXMLDOMNode_get_parentNode( removed_node, &temp_node );
3866     ok( r == S_FALSE, "ret %08x\n", r);
3867     ok( temp_node == NULL, "%p\n", temp_node );
3868 
3869     IXMLDOMNode_Release( removed_node );
3870     IXMLDOMNode_Release( ba_node );
3871     IXMLDOMNodeList_Release( fo_list );
3872 
3873     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3874     ok( r == S_OK, "ret %08x\n", r);
3875 
3876     r = IXMLDOMNode_QueryInterface( lc_node, &IID_IXMLDOMElement, (void**)&lc_element );
3877     ok( r == S_OK, "ret %08x\n", r);
3878 
3879     /* MS quirk: passing wrong interface pointer works, too */
3880     r = IXMLDOMElement_removeChild( element, (IXMLDOMNode*)lc_element, NULL );
3881     ok( r == S_OK, "ret %08x\n", r);
3882     IXMLDOMElement_Release( lc_element );
3883 
3884     temp_node = (void*)0xdeadbeef;
3885     r = IXMLDOMNode_get_parentNode( lc_node, &temp_node );
3886     ok( r == S_FALSE, "ret %08x\n", r);
3887     ok( temp_node == NULL, "%p\n", temp_node );
3888 
3889     IXMLDOMNode_Release( lc_node );
3890     IXMLDOMNodeList_Release( root_list );
3891     IXMLDOMElement_Release( element );
3892     IXMLDOMDocument_Release( doc );
3893 
3894     free_bstrs();
3895 }
3896 
3897 static void test_replaceChild(void)
3898 {
3899     HRESULT r;
3900     VARIANT_BOOL b;
3901     IXMLDOMDocument *doc;
3902     IXMLDOMElement *element, *ba_element;
3903     IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
3904     IXMLDOMNodeList *root_list, *fo_list;
3905     IUnknown * unk1, *unk2;
3906     LONG len;
3907 
3908     doc = create_document(&IID_IXMLDOMDocument);
3909 
3910     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3911     ok( r == S_OK, "loadXML failed\n");
3912     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3913 
3914     r = IXMLDOMDocument_get_documentElement( doc, &element );
3915     ok( r == S_OK, "ret %08x\n", r);
3916 
3917     r = IXMLDOMElement_get_childNodes( element, &root_list );
3918     ok( r == S_OK, "ret %08x\n", r);
3919 
3920     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3921     ok( r == S_OK, "ret %08x\n", r);
3922 
3923     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3924     ok( r == S_OK, "ret %08x\n", r);
3925 
3926     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3927     ok( r == S_OK, "ret %08x\n", r);
3928 
3929     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3930     ok( r == S_OK, "ret %08x\n", r);
3931 
3932     IXMLDOMNodeList_Release( fo_list );
3933 
3934     /* invalid parameter: NULL ptr for element to remove */
3935     removed_node = (void*)0xdeadbeef;
3936     r = IXMLDOMElement_replaceChild( element, ba_node, NULL, &removed_node );
3937     ok( r == E_INVALIDARG, "ret %08x\n", r );
3938     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3939 
3940     /* invalid parameter: NULL for replacement element. (Sic!) */
3941     removed_node = (void*)0xdeadbeef;
3942     r = IXMLDOMElement_replaceChild( element, NULL, fo_node, &removed_node );
3943     ok( r == E_INVALIDARG, "ret %08x\n", r );
3944     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3945 
3946     /* invalid parameter: OldNode is not a child */
3947     removed_node = (void*)0xdeadbeef;
3948     r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
3949     ok( r == E_INVALIDARG, "ret %08x\n", r );
3950     ok( removed_node == NULL, "%p\n", removed_node );
3951     IXMLDOMNode_Release( lc_node );
3952 
3953     /* invalid parameter: would create loop */
3954     removed_node = (void*)0xdeadbeef;
3955     r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
3956     ok( r == E_FAIL, "ret %08x\n", r );
3957     ok( removed_node == NULL, "%p\n", removed_node );
3958 
3959     r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
3960     ok( r == S_OK, "ret %08x\n", r );
3961 
3962     r = IXMLDOMNodeList_get_item( root_list, 3, &temp_node );
3963     ok( r == S_OK, "ret %08x\n", r );
3964 
3965     /* ba_node and temp_node refer to the same node, yet they
3966        are different interface pointers */
3967     ok( ba_node != temp_node, "ba_node %p temp_node %p\n", ba_node, temp_node);
3968     r = IXMLDOMNode_QueryInterface( temp_node, &IID_IUnknown, (void**)&unk1);
3969     ok( r == S_OK, "ret %08x\n", r );
3970     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IUnknown, (void**)&unk2);
3971     ok( r == S_OK, "ret %08x\n", r );
3972     todo_wine ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
3973 
3974     IUnknown_Release( unk1 );
3975     IUnknown_Release( unk2 );
3976 
3977     /* ba_node should have been removed from below fo_node */
3978     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3979     ok( r == S_OK, "ret %08x\n", r );
3980 
3981     /* MS quirk: replaceChild also accepts elements instead of nodes */
3982     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IXMLDOMElement, (void**)&ba_element);
3983     ok( r == S_OK, "ret %08x\n", r );
3984     EXPECT_REF(ba_element, 2);
3985 
3986     removed_node = NULL;
3987     r = IXMLDOMElement_replaceChild( element, ba_node, (IXMLDOMNode*)ba_element, &removed_node );
3988     ok( r == S_OK, "ret %08x\n", r );
3989     ok( removed_node != NULL, "got %p\n", removed_node);
3990     EXPECT_REF(ba_element, 3);
3991     IXMLDOMElement_Release( ba_element );
3992 
3993     r = IXMLDOMNodeList_get_length( fo_list, &len);
3994     ok( r == S_OK, "ret %08x\n", r );
3995     ok( len == 0, "len %d\n", len);
3996 
3997     IXMLDOMNodeList_Release( fo_list );
3998 
3999     IXMLDOMNode_Release(ba_node);
4000     IXMLDOMNode_Release(fo_node);
4001     IXMLDOMNode_Release(temp_node);
4002     IXMLDOMNodeList_Release( root_list );
4003     IXMLDOMElement_Release( element );
4004     IXMLDOMDocument_Release( doc );
4005 
4006     free_bstrs();
4007 }
4008 
4009 static void test_removeNamedItem(void)
4010 {
4011     IXMLDOMDocument *doc;
4012     IXMLDOMElement *element;
4013     IXMLDOMNode *pr_node, *removed_node, *removed_node2;
4014     IXMLDOMNodeList *root_list;
4015     IXMLDOMNamedNodeMap * pr_attrs;
4016     VARIANT_BOOL b;
4017     BSTR str;
4018     LONG len;
4019     HRESULT r;
4020 
4021     doc = create_document(&IID_IXMLDOMDocument);
4022 
4023     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
4024     ok( r == S_OK, "loadXML failed\n");
4025     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4026 
4027     r = IXMLDOMDocument_get_documentElement( doc, &element );
4028     ok( r == S_OK, "ret %08x\n", r);
4029 
4030     r = IXMLDOMElement_get_childNodes( element, &root_list );
4031     ok( r == S_OK, "ret %08x\n", r);
4032 
4033     r = IXMLDOMNodeList_get_item( root_list, 1, &pr_node );
4034     ok( r == S_OK, "ret %08x\n", r);
4035 
4036     r = IXMLDOMNode_get_attributes( pr_node, &pr_attrs );
4037     ok( r == S_OK, "ret %08x\n", r);
4038 
4039     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4040     ok( r == S_OK, "ret %08x\n", r);
4041     ok( len == 3, "length %d\n", len);
4042 
4043     removed_node = (void*)0xdeadbeef;
4044     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, NULL, &removed_node);
4045     ok ( r == E_INVALIDARG, "ret %08x\n", r);
4046     ok ( removed_node == (void*)0xdeadbeef, "got %p\n", removed_node);
4047 
4048     removed_node = (void*)0xdeadbeef;
4049     str = SysAllocString(szvr);
4050     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node);
4051     ok ( r == S_OK, "ret %08x\n", r);
4052 
4053     removed_node2 = (void*)0xdeadbeef;
4054     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node2);
4055     ok ( r == S_FALSE, "ret %08x\n", r);
4056     ok ( removed_node2 == NULL, "got %p\n", removed_node2 );
4057 
4058     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4059     ok( r == S_OK, "ret %08x\n", r);
4060     ok( len == 2, "length %d\n", len);
4061 
4062     r = IXMLDOMNamedNodeMap_setNamedItem( pr_attrs, removed_node, NULL);
4063     ok ( r == S_OK, "ret %08x\n", r);
4064     IXMLDOMNode_Release(removed_node);
4065 
4066     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4067     ok( r == S_OK, "ret %08x\n", r);
4068     ok( len == 3, "length %d\n", len);
4069 
4070     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4071     ok ( r == S_OK, "ret %08x\n", r);
4072 
4073     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4074     ok( r == S_OK, "ret %08x\n", r);
4075     ok( len == 2, "length %d\n", len);
4076 
4077     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4078     ok ( r == S_FALSE, "ret %08x\n", r);
4079 
4080     SysFreeString(str);
4081 
4082     IXMLDOMNamedNodeMap_Release( pr_attrs );
4083     IXMLDOMNode_Release( pr_node );
4084     IXMLDOMNodeList_Release( root_list );
4085     IXMLDOMElement_Release( element );
4086     IXMLDOMDocument_Release( doc );
4087 
4088     free_bstrs();
4089 }
4090 
4091 #define test_IObjectSafety_set(p, r, r2, s, m, e, e2) _test_IObjectSafety_set(__LINE__,p, r, r2, s, m, e, e2)
4092 static void _test_IObjectSafety_set(unsigned line, IObjectSafety *safety, HRESULT result,
4093                                     HRESULT result2, DWORD set, DWORD mask, DWORD expected,
4094                                     DWORD expected2)
4095 {
4096     DWORD enabled, supported;
4097     HRESULT hr;
4098 
4099     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL, set, mask);
4100     if (result == result2)
4101         ok_(__FILE__,line)(hr == result, "SetInterfaceSafetyOptions: expected %08x, returned %08x\n", result, hr );
4102     else
4103         ok_(__FILE__,line)(broken(hr == result) || hr == result2,
4104            "SetInterfaceSafetyOptions: expected %08x, got %08x\n", result2, hr );
4105 
4106     supported = enabled = 0xCAFECAFE;
4107     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4108     ok(hr == S_OK, "ret %08x\n", hr );
4109     if (expected == expected2)
4110         ok_(__FILE__,line)(enabled == expected, "Expected %08x, got %08x\n", expected, enabled);
4111     else
4112         ok_(__FILE__,line)(broken(enabled == expected) || enabled == expected2,
4113            "Expected %08x, got %08x\n", expected2, enabled);
4114 
4115     /* reset the safety options */
4116 
4117     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4118             INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER,
4119             0);
4120     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4121 
4122     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4123     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4124     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4125 }
4126 
4127 #define test_IObjectSafety_common(s) _test_IObjectSafety_common(__LINE__,s)
4128 static void _test_IObjectSafety_common(unsigned line, IObjectSafety *safety)
4129 {
4130     DWORD enabled = 0, supported = 0;
4131     HRESULT hr;
4132 
4133     /* get */
4134     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, NULL, &enabled);
4135     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4136     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, NULL);
4137     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4138 
4139     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4140     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4141     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4142        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4143         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4144              "got %08x\n", supported);
4145     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4146 
4147     /* set -- individual flags */
4148 
4149     test_IObjectSafety_set(safety, S_OK, S_OK,
4150         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4151         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4152 
4153     test_IObjectSafety_set(safety, S_OK, S_OK,
4154         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA,
4155         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA);
4156 
4157     test_IObjectSafety_set(safety, S_OK, S_OK,
4158         INTERFACE_USES_SECURITY_MANAGER, INTERFACE_USES_SECURITY_MANAGER,
4159         0, INTERFACE_USES_SECURITY_MANAGER /* msxml3 SP8+ */);
4160 
4161     /* set INTERFACE_USES_DISPEX  */
4162 
4163     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4164         INTERFACE_USES_DISPEX, INTERFACE_USES_DISPEX,
4165         0, 0);
4166 
4167     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4168         INTERFACE_USES_DISPEX, 0,
4169         0, 0);
4170 
4171     test_IObjectSafety_set(safety, S_OK, S_OK /* msxml3 SP8+ */,
4172         0, INTERFACE_USES_DISPEX,
4173         0, 0);
4174 
4175     /* set option masking */
4176 
4177     test_IObjectSafety_set(safety, S_OK, S_OK,
4178         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4179         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4180         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4181         INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4182 
4183     test_IObjectSafety_set(safety, S_OK, S_OK,
4184         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4185         INTERFACESAFE_FOR_UNTRUSTED_DATA,
4186         INTERFACESAFE_FOR_UNTRUSTED_DATA,
4187         INTERFACESAFE_FOR_UNTRUSTED_DATA);
4188 
4189     test_IObjectSafety_set(safety, S_OK, S_OK,
4190         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4191         INTERFACE_USES_SECURITY_MANAGER,
4192         0,
4193         0);
4194 
4195     /* set -- inheriting previous settings */
4196 
4197     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4198                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4199                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4200     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4201     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4202     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4203     ok_(__FILE__,line)(enabled == INTERFACESAFE_FOR_UNTRUSTED_CALLER, "Expected INTERFACESAFE_FOR_UNTRUSTED_CALLER got %08x\n", enabled);
4204     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4205        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4206         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4207              "got %08x\n", supported);
4208 
4209     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4210                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA,
4211                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA);
4212     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4213     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4214     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4215     ok_(__FILE__,line)(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_DATA) ||
4216                        enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA),
4217                        "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) got %08x\n", enabled);
4218     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4219        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4220         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4221              "got %08x\n", supported);
4222 }
4223 
4224 static void test_IXMLDOMDocument2(void)
4225 {
4226     static const WCHAR emptyW[] = {0};
4227     IXMLDOMDocument2 *doc2, *dtddoc2;
4228     IXMLDOMDocument *doc;
4229     IXMLDOMParseError* err;
4230     IDispatchEx *dispex;
4231     VARIANT_BOOL b;
4232     VARIANT var;
4233     HRESULT r;
4234     LONG res;
4235 
4236     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4237 
4238     doc = create_document(&IID_IXMLDOMDocument);
4239     dtddoc2 = create_document(&IID_IXMLDOMDocument2);
4240 
4241     r = IXMLDOMDocument_QueryInterface( doc, &IID_IXMLDOMDocument2, (void**)&doc2 );
4242     ok( r == S_OK, "ret %08x\n", r );
4243     ok( doc == (IXMLDOMDocument*)doc2, "interfaces differ\n");
4244 
4245     ole_expect(IXMLDOMDocument2_get_readyState(doc2, NULL), E_INVALIDARG);
4246     ole_check(IXMLDOMDocument2_get_readyState(doc2, &res));
4247     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4248 
4249     err = NULL;
4250     ole_expect(IXMLDOMDocument2_validate(doc2, NULL), S_FALSE);
4251     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4252     ok(err != NULL, "expected a pointer\n");
4253     if (err)
4254     {
4255         res = 0;
4256         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4257         /* XML_E_NOTWF */
4258         ok(res == E_XML_NOTWF, "got %08x\n", res);
4259         IXMLDOMParseError_Release(err);
4260     }
4261 
4262     r = IXMLDOMDocument2_loadXML( doc2, _bstr_(complete4A), &b );
4263     ok( r == S_OK, "loadXML failed\n");
4264     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4265 
4266     ole_check(IXMLDOMDocument_get_readyState(doc, &res));
4267     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4268 
4269     err = NULL;
4270     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4271     ok(err != NULL, "expected a pointer\n");
4272     if (err)
4273     {
4274         res = 0;
4275         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4276         /* XML_E_NODTD */
4277         ok(res == E_XML_NODTD, "got %08x\n", res);
4278         IXMLDOMParseError_Release(err);
4279     }
4280 
4281     r = IXMLDOMDocument_QueryInterface( doc, &IID_IDispatchEx, (void**)&dispex );
4282     ok( r == S_OK, "ret %08x\n", r );
4283     if(r == S_OK)
4284     {
4285         IDispatchEx_Release(dispex);
4286     }
4287 
4288     /* we will check if the variant got cleared */
4289     IXMLDOMDocument2_AddRef(doc2);
4290     EXPECT_REF(doc2, 3); /* doc, doc2, AddRef*/
4291 
4292     V_VT(&var) = VT_UNKNOWN;
4293     V_UNKNOWN(&var) = (IUnknown *)doc2;
4294 
4295     /* invalid calls */
4296     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("askldhfaklsdf"), &var), E_FAIL);
4297     expect_eq(V_VT(&var), VT_UNKNOWN, int, "%x");
4298     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), NULL), E_INVALIDARG);
4299 
4300     /* valid call */
4301     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4302     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4303     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4304     V_VT(&var) = VT_R4;
4305 
4306     /* the variant didn't get cleared*/
4307     expect_eq(IXMLDOMDocument2_Release(doc2), 2, int, "%d");
4308 
4309     /* setProperty tests */
4310     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("askldhfaklsdf"), var), E_FAIL);
4311     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), var), E_FAIL);
4312     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("alskjdh faklsjd hfk")), E_FAIL);
4313     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4314     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4315     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4316 
4317     V_VT(&var) = VT_BSTR;
4318     V_BSTR(&var) = SysAllocString(emptyW);
4319     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4320     ok(r == S_OK, "got 0x%08x\n", r);
4321     VariantClear(&var);
4322 
4323     V_VT(&var) = VT_I2;
4324     V_I2(&var) = 0;
4325     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4326     ok(r == E_FAIL, "got 0x%08x\n", r);
4327 
4328     /* contrary to what MSDN claims you can switch back from XPath to XSLPattern */
4329     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4330     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4331     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4332 
4333     IXMLDOMDocument2_Release( doc2 );
4334     IXMLDOMDocument_Release( doc );
4335 
4336     /* DTD validation */
4337     ole_check(IXMLDOMDocument2_put_validateOnParse(dtddoc2, VARIANT_FALSE));
4338     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML), &b));
4339     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4340     err = NULL;
4341     ole_check(IXMLDOMDocument2_validate(dtddoc2, &err));
4342     ok(err != NULL, "expected pointer\n");
4343     if (err)
4344     {
4345         res = 0;
4346         ole_expect(IXMLDOMParseError_get_errorCode(err, &res), S_FALSE);
4347         ok(res == 0, "got %08x\n", res);
4348         IXMLDOMParseError_Release(err);
4349     }
4350 
4351     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0D), &b));
4352     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4353     err = NULL;
4354     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4355     ok(err != NULL, "expected pointer\n");
4356     if (err)
4357     {
4358         res = 0;
4359         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4360         /* XML_ELEMENT_UNDECLARED */
4361         todo_wine ok(res == 0xC00CE00D, "got %08x\n", res);
4362         IXMLDOMParseError_Release(err);
4363     }
4364 
4365     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0E), &b));
4366     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4367     err = NULL;
4368     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4369     ok(err != NULL, "expected pointer\n");
4370     if (err)
4371     {
4372         res = 0;
4373         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4374         /* XML_ELEMENT_ID_NOT_FOUND */
4375         todo_wine ok(res == 0xC00CE00E, "got %08x\n", res);
4376         IXMLDOMParseError_Release(err);
4377     }
4378 
4379     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_11), &b));
4380     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4381     err = NULL;
4382     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4383     ok(err != NULL, "expected pointer\n");
4384     if (err)
4385     {
4386         res = 0;
4387         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4388         /* XML_EMPTY_NOT_ALLOWED */
4389         todo_wine ok(res == 0xC00CE011, "got %08x\n", res);
4390         IXMLDOMParseError_Release(err);
4391     }
4392 
4393     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_13), &b));
4394     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4395     err = NULL;
4396     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4397     ok(err != NULL, "expected pointer\n");
4398     if (err)
4399     {
4400         res = 0;
4401         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4402         /* XML_ROOT_NAME_MISMATCH */
4403         todo_wine ok(res == 0xC00CE013, "got %08x\n", res);
4404         IXMLDOMParseError_Release(err);
4405     }
4406 
4407     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_14), &b));
4408     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4409     err = NULL;
4410     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4411     ok(err != NULL, "expected pointer\n");
4412     if (err)
4413     {
4414         res = 0;
4415         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4416         /* XML_INVALID_CONTENT */
4417         todo_wine ok(res == 0xC00CE014, "got %08x\n", res);
4418         IXMLDOMParseError_Release(err);
4419     }
4420 
4421     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_15), &b));
4422     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4423     err = NULL;
4424     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4425     ok(err != NULL, "expected pointer\n");
4426     if (err)
4427     {
4428         res = 0;
4429         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4430         /* XML_ATTRIBUTE_NOT_DEFINED */
4431         todo_wine ok(res == 0xC00CE015, "got %08x\n", res);
4432         IXMLDOMParseError_Release(err);
4433     }
4434 
4435     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_16), &b));
4436     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4437     err = NULL;
4438     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4439     ok(err != NULL, "expected pointer\n");
4440     if (err)
4441     {
4442         res = 0;
4443         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4444         /* XML_ATTRIBUTE_FIXED */
4445         todo_wine ok(res == 0xC00CE016, "got %08x\n", res);
4446         IXMLDOMParseError_Release(err);
4447     }
4448 
4449     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_17), &b));
4450     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4451     err = NULL;
4452     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4453     ok(err != NULL, "expected pointer\n");
4454     if (err)
4455     {
4456         res = 0;
4457         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4458         /* XML_ATTRIBUTE_VALUE */
4459         todo_wine ok(res == 0xC00CE017, "got %08x\n", res);
4460         IXMLDOMParseError_Release(err);
4461     }
4462 
4463     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_18), &b));
4464     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4465     err = NULL;
4466     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4467     ok(err != NULL, "expected pointer\n");
4468     if (err)
4469     {
4470         res = 0;
4471         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4472         /* XML_ILLEGAL_TEXT */
4473         todo_wine ok(res == 0xC00CE018, "got %08x\n", res);
4474         IXMLDOMParseError_Release(err);
4475     }
4476 
4477     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_20), &b));
4478     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4479     err = NULL;
4480     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4481     ok(err != NULL, "expected pointer\n");
4482     if (err)
4483     {
4484         res = 0;
4485         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4486         /* XML_REQUIRED_ATTRIBUTE_MISSING */
4487         todo_wine ok(res == 0xC00CE020, "got %08x\n", res);
4488         IXMLDOMParseError_Release(err);
4489     }
4490 
4491     IXMLDOMDocument2_Release( dtddoc2 );
4492     free_bstrs();
4493 }
4494 
4495 #define helper_ole_check(expr) { \
4496     HRESULT r = expr; \
4497     ok_(__FILE__, line)(r == S_OK, "=> %i: " #expr " returned %08x\n", __LINE__, r); \
4498 }
4499 
4500 #define helper_ole_check_ver(expr) { \
4501     HRESULT r = expr; \
4502     ok_(__FILE__, line)(r == S_OK, "-> %i (%s): " #expr " returned %08x\n", __LINE__, ver, r); \
4503 }
4504 
4505 #define helper_expect_list_and_release(list, expstr) { \
4506     char *str = list_to_string(list); \
4507     ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i (%s): Invalid node list: %s, expected %s\n", __LINE__, ver, str, expstr); \
4508     if (list) IXMLDOMNodeList_Release(list); \
4509 }
4510 
4511 #define helper_expect_bstr_and_release(bstr, str) { \
4512     ok_(__FILE__, line)(lstrcmpW(bstr, _bstr_(str)) == 0, \
4513        "=> %i (%s): got %s\n", __LINE__, ver, wine_dbgstr_w(bstr)); \
4514     SysFreeString(bstr); \
4515 }
4516 
4517 #define check_ws_ignored(ver, doc, str) _check_ws_ignored(__LINE__, ver, doc, str)
4518 static inline void _check_ws_ignored(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4519 {
4520     IXMLDOMNode *node1, *node2;
4521     IXMLDOMNodeList *list;
4522     BSTR bstr;
4523 
4524     helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4525     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4526     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4527     helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4528     helper_expect_list_and_release(list, "E1.E5.E1.E2.D1 E2.E5.E1.E2.D1");
4529 
4530     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4531     helper_expect_list_and_release(list,
4532             "[4]1.E1.E5.E1.E2.D1 T2.E1.E5.E1.E2.D1 E3.E1.E5.E1.E2.D1 "
4533             "E4.E1.E5.E1.E2.D1 E5.E1.E5.E1.E2.D1 E6.E1.E5.E1.E2.D1");
4534     helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4535     if (str)
4536     {
4537         helper_expect_bstr_and_release(bstr, str);
4538     }
4539     else
4540     {
4541         helper_expect_bstr_and_release(bstr, " This is a description.");
4542     }
4543     IXMLDOMNode_Release(node1);
4544 
4545     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4546     helper_expect_list_and_release(list,
4547             "T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 "
4548             "E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
4549     helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4550     helper_expect_bstr_and_release(bstr,
4551             "\n                This is a description with preserved whitespace. \n            ");
4552     IXMLDOMNode_Release(node2);
4553 }
4554 
4555 #define check_ws_preserved(ver, doc, str) _check_ws_preserved(__LINE__, ver, doc, str)
4556 static inline void _check_ws_preserved(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4557 {
4558     IXMLDOMNode *node1, *node2;
4559     IXMLDOMNodeList *list;
4560     BSTR bstr;
4561 
4562     helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4563     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4564     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4565     helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4566     helper_expect_list_and_release(list, "E2.E10.E2.E2.D1 E4.E10.E2.E2.D1");
4567 
4568     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4569     helper_expect_list_and_release(list,
4570             "T1.E2.E10.E2.E2.D1 [4]2.E2.E10.E2.E2.D1 T3.E2.E10.E2.E2.D1 "
4571             "E4.E2.E10.E2.E2.D1 T5.E2.E10.E2.E2.D1 E6.E2.E10.E2.E2.D1 "
4572             "E7.E2.E10.E2.E2.D1 E8.E2.E10.E2.E2.D1 T9.E2.E10.E2.E2.D1");
4573     helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4574     if (str)
4575     {
4576         helper_expect_bstr_and_release(bstr, str);
4577     }
4578     else
4579     {
4580         helper_expect_bstr_and_release(bstr, "\n                 This is a  description. \n            ");
4581     }
4582     IXMLDOMNode_Release(node1);
4583 
4584     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4585     helper_expect_list_and_release(list,
4586             "T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 "
4587             "E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
4588     helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4589     helper_expect_bstr_and_release(bstr,
4590             "\n                This is a description with preserved whitespace. \n            ");
4591     IXMLDOMNode_Release(node2);
4592 }
4593 
4594 static void test_preserve_charref(IXMLDOMDocument2 *doc, VARIANT_BOOL preserve)
4595 {
4596     static const WCHAR b1_p[] = {' ','T','e','x','t',' ','A',' ','e','n','d',' ',0};
4597     static const WCHAR b1_i[] = {'T','e','x','t',' ','A',' ','e','n','d',0};
4598     static const WCHAR b2_p[] = {'A','B',' ','C',' ',0};
4599     static const WCHAR b2_i[] = {'A','B',' ','C',0};
4600     IXMLDOMNodeList *list;
4601     IXMLDOMElement *root;
4602     IXMLDOMNode *node;
4603     const WCHAR *text;
4604     VARIANT_BOOL b;
4605     HRESULT hr;
4606     BSTR s;
4607 
4608     hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc, preserve);
4609     ok(hr == S_OK, "got 0x%08x\n", hr);
4610 
4611     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(charrefsxml), &b);
4612     ok(hr == S_OK, "got 0x%08x\n", hr);
4613 
4614     hr = IXMLDOMDocument2_get_documentElement(doc, &root);
4615     ok(hr == S_OK, "got 0x%08x\n", hr);
4616 
4617     hr = IXMLDOMElement_get_childNodes(root, &list);
4618     ok(hr == S_OK, "got 0x%08x\n", hr);
4619     IXMLDOMElement_Release(root);
4620 
4621     text = preserve == VARIANT_TRUE ? b1_p : b1_i;
4622     hr = IXMLDOMNodeList_get_item(list, 0, &node);
4623     ok(hr == S_OK, "got 0x%08x\n", hr);
4624     hr = IXMLDOMNode_get_text(node, &s);
4625     ok(hr == S_OK, "got 0x%08x\n", hr);
4626     ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4627     SysFreeString(s);
4628     IXMLDOMNode_Release(node);
4629 
4630     text = preserve == VARIANT_TRUE ? b2_p : b2_i;
4631     hr = IXMLDOMNodeList_get_item(list, 1, &node);
4632     ok(hr == S_OK, "got 0x%08x\n", hr);
4633     hr = IXMLDOMNode_get_text(node, &s);
4634     ok(hr == S_OK, "got 0x%08x\n", hr);
4635     ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4636     SysFreeString(s);
4637     IXMLDOMNode_Release(node);
4638 
4639     IXMLDOMNodeList_Release(list);
4640 }
4641 
4642 struct whitespace_t {
4643     const CLSID *clsid;
4644     const char *name;
4645 };
4646 
4647 static const struct whitespace_t whitespace_test_data[] = {
4648     { &CLSID_DOMDocument,   "CLSID_DOMDocument"   },
4649     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2"  },
4650     { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
4651     { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
4652     { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
4653     { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
4654     { 0 }
4655 };
4656 
4657 static void test_whitespace(void)
4658 {
4659     const struct whitespace_t *class_ptr = whitespace_test_data;
4660 
4661     while (class_ptr->clsid)
4662     {
4663         IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
4664         IXMLDOMNodeList *list;
4665         IXMLDOMElement *root;
4666         VARIANT_BOOL b;
4667         HRESULT hr;
4668         LONG len;
4669 
4670         if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument2))
4671         {
4672             class_ptr++;
4673             continue;
4674         }
4675 
4676         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4677                 &IID_IXMLDOMDocument2, (void**)&doc1);
4678         ok(hr == S_OK, "got 0x%08x\n", hr);
4679 
4680         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4681                 &IID_IXMLDOMDocument2, (void**)&doc2);
4682         ok(hr == S_OK, "got 0x%08x\n", hr);
4683 
4684         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
4685         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4686         ok(b == VARIANT_FALSE, "expected false\n");
4687         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4688         ok(b == VARIANT_TRUE, "expected true\n");
4689 
4690         ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4691         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4692         ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4693         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4694 
4695         /* switch to XPath */
4696         ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4697         ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4698 
4699         check_ws_ignored(class_ptr->name, doc1, NULL);
4700         check_ws_preserved(class_ptr->name, doc2, NULL);
4701 
4702         /* new instances copy the property */
4703         ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
4704         ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
4705 
4706         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4707         ok(b == VARIANT_FALSE, "expected false\n");
4708         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4709         ok(b == VARIANT_TRUE, "expected true\n");
4710 
4711         check_ws_ignored(class_ptr->name, doc3, NULL);
4712         check_ws_preserved(class_ptr->name, doc4, NULL);
4713 
4714         /* setting after loading xml affects trimming of leading/trailing ws only */
4715         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
4716         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
4717 
4718         /* the trailing "\n            " isn't there, because it was ws-only node */
4719         check_ws_ignored(class_ptr->name, doc1, " This is a description. ");
4720         check_ws_preserved(class_ptr->name, doc2, " This is a description.");
4721 
4722         /* it takes effect on reload */
4723         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4724         ok(b == VARIANT_TRUE, "expected true\n");
4725         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4726         ok(b == VARIANT_FALSE, "expected false\n");
4727 
4728         ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4729         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4730         ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4731         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4732 
4733         check_ws_preserved(class_ptr->name, doc1, NULL);
4734         check_ws_ignored(class_ptr->name, doc2, NULL);
4735 
4736         /* other instances follow suit */
4737         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4738         ok(b == VARIANT_TRUE, "expected true\n");
4739         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4740         ok(b == VARIANT_FALSE, "expected false\n");
4741 
4742         check_ws_preserved(class_ptr->name, doc3, NULL);
4743         check_ws_ignored(class_ptr->name, doc4, NULL);
4744 
4745         IXMLDOMDocument2_Release(doc2);
4746         IXMLDOMDocument2_Release(doc3);
4747         IXMLDOMDocument2_Release(doc4);
4748 
4749         /* text with char references */
4750         test_preserve_charref(doc1, VARIANT_TRUE);
4751         test_preserve_charref(doc1, VARIANT_FALSE);
4752 
4753         /* formatting whitespaces */
4754         hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_FALSE);
4755         ok(hr == S_OK, "got 0x%08x\n", hr);
4756 
4757         hr = IXMLDOMDocument2_loadXML(doc1, _bstr_(complete7), &b);
4758         ok(hr == S_OK, "got 0x%08x\n", hr);
4759         ok(b == VARIANT_TRUE, "for %x\n", b);
4760 
4761         hr = IXMLDOMDocument2_get_documentElement(doc1, &root);
4762         ok(hr == S_OK, "got 0x%08x\n", hr);
4763         hr = IXMLDOMElement_get_childNodes(root, &list);
4764         ok(hr == S_OK, "got 0x%08x\n", hr);
4765         len = 0;
4766         hr = IXMLDOMNodeList_get_length(list, &len);
4767         ok(hr == S_OK, "got 0x%08x\n", hr);
4768         ok(len == 3, "got %d\n", len);
4769         IXMLDOMNodeList_Release(list);
4770         IXMLDOMElement_Release(root);
4771 
4772         IXMLDOMDocument2_Release(doc1);
4773 
4774         free_bstrs();
4775 
4776         class_ptr++;
4777     }
4778 }
4779 
4780 typedef struct {
4781     const GUID *clsid;
4782     const char *name;
4783     const char *ns;
4784     HRESULT hr;
4785 } selection_ns_t;
4786 
4787 /* supposed to be tested with szExampleXML */
4788 static const selection_ns_t selection_ns_data[] = {
4789     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4790     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4791     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4792     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4793 
4794     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4795     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4796     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4797     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4798 
4799     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4800     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4801     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4802     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4803 
4804     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4805     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4806     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4807     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4808 
4809     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4810     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4811     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4812     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4813 
4814     { NULL }
4815 };
4816 
4817 typedef struct {
4818     const char *query;
4819     const char *list;
4820 } xpath_test_t;
4821 
4822 static const xpath_test_t xpath_test[] = {
4823     { "*/a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4824     { "*/b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4825     { "*/c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4826     { "*/d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4827     { "//a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4828     { "//b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4829     { "//c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4830     { "//d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4831     { "//c[@type]", "E3.E2.E2.D1" },
4832     { "//c[@type]/ancestor::node()[1]", "E2.E2.D1" },
4833     { "//c[@type]/ancestor-or-self::node()[1]", "E3.E2.E2.D1" },
4834     { "//c[@type]/attribute::node()[1]", "A'type'.E3.E2.E2.D1" },
4835     { "//c[@type]/child::node()[1]", "T1.E3.E2.E2.D1"  },
4836     { "//c[@type]/descendant::node()[1]", "T1.E3.E2.E2.D1" },
4837     { "//c[@type]/descendant-or-self::node()[1]", "E3.E2.E2.D1" },
4838     { "//c[@type]/following::node()[1]", "E4.E2.E2.D1" },
4839     { "//c[@type]/following-sibling::node()[1]", "E4.E2.E2.D1" },
4840     { "//c[@type]/parent::node()[1]", "E2.E2.D1" },
4841     { "//c[@type]/preceding::node()[1]", "T1.E2.E2.E2.D1" },
4842     { "//c[@type]/self::node()[1]", "E3.E2.E2.D1" },
4843     { "child::*", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4844     { "child::node()", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4845     { "child::text()", "" },
4846     { "child::*/..", "E2.D1" },
4847     { "child::*//@*/..", "E2.E5.E1.E2.D1 E2.E2.D1 E3.E2.E2.D1" },
4848     { "self::node()", "E2.D1" },
4849     { "ancestor::node()", "D1" },
4850     { "elem[c][last()]/a", "E1.E2.E2.D1"},
4851     { "ancestor-or-self::node()[1]", "E2.D1" },
4852     { "((//a)[1])[last()]", "E1.E1.E2.D1" },
4853     { "//elem[@*]", "E2.E2.D1" },
4854     { NULL }
4855 };
4856 
4857 static void test_XPath(void)
4858 {
4859     const selection_ns_t *ptr = selection_ns_data;
4860     const xpath_test_t *xptest = xpath_test;
4861     VARIANT var;
4862     VARIANT_BOOL b;
4863     IXMLDOMDocument2 *doc;
4864     IXMLDOMDocument *doc2;
4865     IXMLDOMNode *rootNode;
4866     IXMLDOMNode *elem1Node;
4867     IXMLDOMNode *node;
4868     IXMLDOMNodeList *list;
4869     IXMLDOMElement *elem;
4870     IXMLDOMAttribute *attr;
4871     DOMNodeType type;
4872     HRESULT hr;
4873     LONG len;
4874     BSTR str;
4875 
4876     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4877     doc = create_document(&IID_IXMLDOMDocument2);
4878 
4879     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4880     EXPECT_HR(hr, S_OK);
4881     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4882 
4883     /* switch to XPath */
4884     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4885 
4886     /* some simple queries*/
4887     EXPECT_REF(doc, 1);
4888     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4889     EXPECT_HR(hr, S_OK);
4890     EXPECT_REF(doc, 1);
4891     EXPECT_LIST_LEN(list, 1);
4892 
4893     EXPECT_REF(list, 1);
4894     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4895     EXPECT_HR(hr, S_OK);
4896     EXPECT_REF(list, 1);
4897     EXPECT_REF(rootNode, 1);
4898 
4899     hr = IXMLDOMNodeList_reset(list);
4900     EXPECT_HR(hr, S_OK);
4901     expect_list_and_release(list, "E2.D1");
4902 
4903     /* peform xpath tests */
4904     for ( ; xptest->query ; xptest++ )
4905     {
4906         char *str;
4907 
4908         hr = IXMLDOMNode_selectNodes(rootNode, _bstr_(xptest->query), &list);
4909         ok(hr == S_OK, "query evaluation failed for query=%s\n", xptest->query);
4910 
4911         if (hr != S_OK)
4912             continue;
4913 
4914         str = list_to_string(list);
4915 
4916         ok(!strcmp(str, xptest->list), "query=%s, invalid node list: \"%s\", expected \"%s\"\n",
4917             xptest->query, str, xptest->list);
4918 
4919         if (list)
4920             IXMLDOMNodeList_Release(list);
4921     }
4922 
4923 if (0)
4924 {
4925     /* namespace:: axis test is disabled until namespace definitions
4926        are supported as attribute nodes, currently it's another node type */
4927     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("/root/namespace::*"), &list);
4928     EXPECT_HR(hr, S_OK);
4929     len = -1;
4930     hr = IXMLDOMNodeList_get_length(list, &len);
4931     EXPECT_HR(hr, S_OK);
4932     ok(len == 2, "got %d\n", len);
4933 
4934     hr = IXMLDOMNodeList_nextNode(list, &node);
4935     EXPECT_HR(hr, S_OK);
4936     type = NODE_INVALID;
4937     hr = IXMLDOMNode_get_nodeType(node, &type);
4938     EXPECT_HR(hr, S_OK);
4939     ok(type == NODE_ATTRIBUTE, "got %d\n", type);
4940     IXMLDOMNode_Release(node);
4941 
4942     IXMLDOMNodeList_Release(list);
4943 }
4944 
4945     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
4946     expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1");
4947 
4948     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//c[@type]"), &list));
4949     expect_list_and_release(list, "E3.E2.E2.D1");
4950 
4951     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
4952     /* using get_item for query results advances the position */
4953     ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
4954     expect_node(node, "E2.E2.D1");
4955     IXMLDOMNode_Release(node);
4956     ole_check(IXMLDOMNodeList_nextNode(list, &node));
4957     expect_node(node, "E4.E2.D1");
4958     IXMLDOMNode_Release(node);
4959     ole_check(IXMLDOMNodeList_reset(list));
4960     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E4.E2.D1");
4961 
4962     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("."), &list));
4963     expect_list_and_release(list, "E2.D1");
4964 
4965     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem[3]/preceding-sibling::*"), &list));
4966     ole_check(IXMLDOMNodeList_get_item(list, 0, &elem1Node));
4967     ole_check(IXMLDOMNodeList_reset(list));
4968     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1");
4969 
4970     /* select an attribute */
4971     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//@type"), &list));
4972     expect_list_and_release(list, "A'type'.E3.E2.E2.D1");
4973 
4974     /* would evaluate to a number */
4975     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("count(*)"), &list), E_FAIL);
4976     /* would evaluate to a boolean */
4977     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("position()>0"), &list), E_FAIL);
4978     /* would evaluate to a string */
4979     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("name()"), &list), E_FAIL);
4980 
4981     /* no results */
4982     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("c"), &list));
4983     expect_list_and_release(list, "");
4984     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("elem//c"), &list));
4985     expect_list_and_release(list, "");
4986     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem[4]"), &list));
4987     expect_list_and_release(list, "");
4988     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[0]"), &list));
4989     expect_list_and_release(list, "");
4990 
4991     /* foo undeclared in document node */
4992     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4993     /* undeclared in <root> node */
4994     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
4995     /* undeclared in <elem> node */
4996     ole_expect(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//foo:c"), &list), E_FAIL);
4997     /* but this trick can be used */
4998     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//*[name()='foo:c']"), &list));
4999     expect_list_and_release(list, "E3.E4.E2.D1");
5000 
5001     /* it has to be declared in SelectionNamespaces */
5002     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5003         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
5004 
5005     /* now the namespace can be used */
5006     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list));
5007     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5008     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
5009     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5010     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
5011     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5012     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
5013     expect_list_and_release(list, "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1");
5014 
5015     /* SelectionNamespaces syntax error - the namespaces doesn't work anymore but the value is stored */
5016     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5017         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL);
5018 
5019     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5020 
5021     VariantInit(&var);
5022     ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
5023     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
5024     if (V_VT(&var) == VT_BSTR)
5025         expect_bstr_eq_and_free(V_BSTR(&var), "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###");
5026 
5027     /* extra attributes - same thing*/
5028     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5029         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' param='test'")), E_FAIL);
5030     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5031 
5032     IXMLDOMNode_Release(rootNode);
5033     IXMLDOMNode_Release(elem1Node);
5034 
5035     /* alter document with already built list */
5036     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5037     EXPECT_HR(hr, S_OK);
5038     EXPECT_LIST_LEN(list, 1);
5039 
5040     hr = IXMLDOMDocument2_get_lastChild(doc, &rootNode);
5041     EXPECT_HR(hr, S_OK);
5042     EXPECT_REF(rootNode, 1);
5043     EXPECT_REF(doc, 1);
5044 
5045     hr = IXMLDOMDocument2_removeChild(doc, rootNode, NULL);
5046     EXPECT_HR(hr, S_OK);
5047     IXMLDOMNode_Release(rootNode);
5048 
5049     EXPECT_LIST_LEN(list, 1);
5050 
5051     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5052     EXPECT_HR(hr, S_OK);
5053     EXPECT_REF(rootNode, 1);
5054 
5055     IXMLDOMNodeList_Release(list);
5056 
5057     hr = IXMLDOMNode_get_nodeName(rootNode, &str);
5058     EXPECT_HR(hr, S_OK);
5059     ok(!lstrcmpW(str, _bstr_("root")), "got %s\n", wine_dbgstr_w(str));
5060     SysFreeString(str);
5061     IXMLDOMNode_Release(rootNode);
5062 
5063     /* alter node from list and get it another time */
5064     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5065     EXPECT_HR(hr, S_OK);
5066     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5067 
5068     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5069     EXPECT_HR(hr, S_OK);
5070     EXPECT_LIST_LEN(list, 1);
5071 
5072     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5073     EXPECT_HR(hr, S_OK);
5074 
5075     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5076     EXPECT_HR(hr, S_OK);
5077 
5078     V_VT(&var) = VT_I2;
5079     V_I2(&var) = 1;
5080     hr = IXMLDOMElement_setAttribute(elem, _bstr_("attrtest"), var);
5081     EXPECT_HR(hr, S_OK);
5082     IXMLDOMElement_Release(elem);
5083     IXMLDOMNode_Release(rootNode);
5084 
5085     /* now check attribute to be present */
5086     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5087     EXPECT_HR(hr, S_OK);
5088 
5089     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5090     EXPECT_HR(hr, S_OK);
5091 
5092     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5093     EXPECT_HR(hr, S_OK);
5094     IXMLDOMAttribute_Release(attr);
5095 
5096     IXMLDOMElement_Release(elem);
5097     IXMLDOMNode_Release(rootNode);
5098 
5099     /* and now check for attribute in original document */
5100     hr = IXMLDOMDocument2_get_documentElement(doc, &elem);
5101     EXPECT_HR(hr, S_OK);
5102 
5103     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5104     EXPECT_HR(hr, S_OK);
5105     IXMLDOMAttribute_Release(attr);
5106 
5107     IXMLDOMElement_Release(elem);
5108 
5109     /* attach node from list to another document */
5110     doc2 = create_document(&IID_IXMLDOMDocument);
5111 
5112     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5113     EXPECT_HR(hr, S_OK);
5114     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5115 
5116     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5117     EXPECT_HR(hr, S_OK);
5118     EXPECT_LIST_LEN(list, 1);
5119 
5120     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5121     EXPECT_HR(hr, S_OK);
5122     EXPECT_REF(rootNode, 1);
5123 
5124     hr = IXMLDOMDocument_appendChild(doc2, rootNode, NULL);
5125     EXPECT_HR(hr, S_OK);
5126     EXPECT_REF(rootNode, 1);
5127     EXPECT_REF(doc2, 1);
5128     EXPECT_REF(list, 1);
5129 
5130     EXPECT_LIST_LEN(list, 1);
5131 
5132     IXMLDOMNode_Release(rootNode);
5133     IXMLDOMNodeList_Release(list);
5134     IXMLDOMDocument_Release(doc2);
5135     IXMLDOMDocument2_Release(doc);
5136 
5137     while (ptr->clsid)
5138     {
5139         if (is_clsid_supported(ptr->clsid, &IID_IXMLDOMDocument2))
5140         {
5141             hr = CoCreateInstance(ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
5142             ok(hr == S_OK, "got 0x%08x\n", hr);
5143         }
5144         else
5145         {
5146             ptr++;
5147             continue;
5148         }
5149 
5150         hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5151         EXPECT_HR(hr, S_OK);
5152         ok(b == VARIANT_TRUE, "failed to load, %s\n", ptr->name);
5153 
5154         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath"));
5155         EXPECT_HR(hr, S_OK);
5156 
5157         V_VT(&var) = VT_BSTR;
5158         V_BSTR(&var) = _bstr_(ptr->ns);
5159 
5160         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var);
5161         ok(hr == ptr->hr, "got 0x%08x, for %s, %s\n", hr, ptr->name, ptr->ns);
5162 
5163         V_VT(&var) = VT_EMPTY;
5164         hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var);
5165         EXPECT_HR(hr, S_OK);
5166         ok(V_VT(&var) == VT_BSTR, "got wrong property type %d\n", V_VT(&var));
5167         ok(!lstrcmpW(V_BSTR(&var), _bstr_(ptr->ns)), "got wrong value %s\n", wine_dbgstr_w(V_BSTR(&var)));
5168         VariantClear(&var);
5169 
5170         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list);
5171         EXPECT_HR(hr, S_OK);
5172         if (hr == S_OK)
5173             expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5174 
5175         IXMLDOMDocument2_Release(doc);
5176         ptr++;
5177         free_bstrs();
5178     }
5179 
5180     free_bstrs();
5181 }
5182 
5183 static void test_cloneNode(void )
5184 {
5185     IXMLDOMDocument2 *doc, *doc_clone;
5186     IXMLDOMDocument *doc2;
5187     VARIANT_BOOL b;
5188     IXMLDOMNodeList *pList;
5189     IXMLDOMNamedNodeMap *mapAttr;
5190     LONG length, length1;
5191     LONG attr_cnt, attr_cnt1;
5192     IXMLDOMNode *node, *attr;
5193     IXMLDOMNode *node_clone;
5194     IXMLDOMNode *node_first;
5195     VARIANT v;
5196     HRESULT hr;
5197 
5198     doc = create_document(&IID_IXMLDOMDocument2);
5199 
5200     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b);
5201     ok(hr == S_OK, "got 0x%08x\n", hr);
5202     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5203 
5204     hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &v);
5205     ok(hr == S_OK, "got 0x%08x\n", hr);
5206     ok(!lstrcmpW(V_BSTR(&v), _bstr_("XSLPattern")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5207     VariantClear(&v);
5208 
5209     V_BSTR(&v) = _bstr_("XPath");
5210     V_VT(&v) = VT_BSTR;
5211     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), v);
5212     ok(hr == S_OK, "got 0x%08x\n", hr);
5213     VariantClear(&v);
5214 
5215     /* clone document node */
5216     hr = IXMLDOMDocument2_cloneNode(doc, VARIANT_TRUE, &node);
5217     ok( hr == S_OK, "ret %08x\n", hr );
5218     ok( node != NULL, "node %p\n", node );
5219 
5220     hr = IXMLDOMNode_get_childNodes(node, &pList);
5221     ok( hr == S_OK, "ret %08x\n", hr );
5222     length = 0;
5223     hr = IXMLDOMNodeList_get_length(pList, &length);
5224     ok( hr == S_OK, "ret %08x\n", hr );
5225     ok(length == 2, "got %d\n", length);
5226     IXMLDOMNodeList_Release(pList);
5227 
5228     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocument2, (void**)&doc_clone);
5229     ok(hr == S_OK, "got 0x%08x\n", hr);
5230 
5231     /* cloned document inherits properties */
5232     hr = IXMLDOMDocument2_getProperty(doc_clone, _bstr_("SelectionLanguage"), &v);
5233     ok(hr == S_OK, "got 0x%08x\n", hr);
5234     ok(!lstrcmpW(V_BSTR(&v), _bstr_("XPath")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5235     VariantClear(&v);
5236 
5237     IXMLDOMDocument2_Release(doc_clone);
5238     IXMLDOMNode_Release(node);
5239 
5240     hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("lc/pr"), &node);
5241     ok( hr == S_OK, "ret %08x\n", hr );
5242     ok( node != NULL, "node %p\n", node );
5243 
5244     /* Check invalid parameter */
5245     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, NULL);
5246     ok( hr == E_INVALIDARG, "ret %08x\n", hr );
5247 
5248     /* All Children */
5249     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, &node_clone);
5250     ok( hr == S_OK, "ret %08x\n", hr );
5251     ok( node_clone != NULL, "node %p\n", node );
5252 
5253     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5254     ok( hr == S_OK, "ret %08x\n", hr );
5255     hr = IXMLDOMNode_get_ownerDocument(node_clone, &doc2);
5256     ok( hr == S_OK, "ret %08x\n", hr );
5257     IXMLDOMDocument_Release(doc2);
5258     IXMLDOMNode_Release(node_first);
5259 
5260     hr = IXMLDOMNode_get_childNodes(node, &pList);
5261     ok( hr == S_OK, "ret %08x\n", hr );
5262     length = 0;
5263     hr = IXMLDOMNodeList_get_length(pList, &length);
5264     ok( hr == S_OK, "ret %08x\n", hr );
5265     ok(length == 1, "got %d\n", length);
5266     IXMLDOMNodeList_Release(pList);
5267 
5268     hr = IXMLDOMNode_get_attributes(node, &mapAttr);
5269     ok( hr == S_OK, "ret %08x\n", hr );
5270     attr_cnt = 0;
5271     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt);
5272     ok( hr == S_OK, "ret %08x\n", hr );
5273     ok(attr_cnt == 3, "got %d\n", attr_cnt);
5274     IXMLDOMNamedNodeMap_Release(mapAttr);
5275 
5276     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5277     ok( hr == S_OK, "ret %08x\n", hr );
5278     length1 = 0;
5279     hr = IXMLDOMNodeList_get_length(pList, &length1);
5280     ok(length1 == 1, "got %d\n", length1);
5281     ok( hr == S_OK, "ret %08x\n", hr );
5282     IXMLDOMNodeList_Release(pList);
5283 
5284     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5285     ok( hr == S_OK, "ret %08x\n", hr );
5286     attr_cnt1 = 0;
5287     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5288     ok( hr == S_OK, "ret %08x\n", hr );
5289     ok(attr_cnt1 == 3, "got %d\n", attr_cnt1);
5290     /* now really get some attributes from cloned element */
5291     attr = NULL;
5292     hr = IXMLDOMNamedNodeMap_getNamedItem(mapAttr, _bstr_("id"), &attr);
5293     ok(hr == S_OK, "ret %08x\n", hr);
5294     IXMLDOMNode_Release(attr);
5295     IXMLDOMNamedNodeMap_Release(mapAttr);
5296 
5297     ok(length == length1, "wrong Child count (%d, %d)\n", length, length1);
5298     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5299     IXMLDOMNode_Release(node_clone);
5300 
5301     /* No Children */
5302     hr = IXMLDOMNode_cloneNode(node, VARIANT_FALSE, &node_clone);
5303     ok( hr == S_OK, "ret %08x\n", hr );
5304     ok( node_clone != NULL, "node %p\n", node );
5305 
5306     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5307     ok(hr == S_FALSE, "ret %08x\n", hr );
5308 
5309     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5310     ok(hr == S_OK, "ret %08x\n", hr );
5311     hr = IXMLDOMNodeList_get_length(pList, &length1);
5312     ok(hr == S_OK, "ret %08x\n", hr );
5313     ok( length1 == 0, "Length should be 0 (%d)\n", length1);
5314     IXMLDOMNodeList_Release(pList);
5315 
5316     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5317     ok(hr == S_OK, "ret %08x\n", hr );
5318     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5319     ok(hr == S_OK, "ret %08x\n", hr );
5320     ok(attr_cnt1 == 3, "Attribute count should be 3 (%d)\n", attr_cnt1);
5321     IXMLDOMNamedNodeMap_Release(mapAttr);
5322 
5323     ok(length != length1, "wrong Child count (%d, %d)\n", length, length1);
5324     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5325     IXMLDOMNode_Release(node_clone);
5326 
5327     IXMLDOMNode_Release(node);
5328     IXMLDOMDocument2_Release(doc);
5329     free_bstrs();
5330 }
5331 
5332 static void test_xmlTypes(void)
5333 {
5334     IXMLDOMDocument *doc;
5335     IXMLDOMElement *pRoot;
5336     HRESULT hr;
5337     IXMLDOMComment *pComment;
5338     IXMLDOMElement *pElement;
5339     IXMLDOMAttribute *pAttribute;
5340     IXMLDOMNamedNodeMap *pAttribs;
5341     IXMLDOMCDATASection *pCDataSec;
5342     IXMLDOMImplementation *pIXMLDOMImplementation = NULL;
5343     IXMLDOMDocumentFragment *pDocFrag = NULL;
5344     IXMLDOMEntityReference *pEntityRef = NULL;
5345     BSTR str;
5346     IXMLDOMNode *pNextChild;
5347     VARIANT v;
5348     LONG len = 0;
5349 
5350     doc = create_document(&IID_IXMLDOMDocument);
5351 
5352     hr = IXMLDOMDocument_get_nextSibling(doc, NULL);
5353     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5354 
5355     pNextChild = (void*)0xdeadbeef;
5356     hr = IXMLDOMDocument_get_nextSibling(doc, &pNextChild);
5357     ok(hr == S_FALSE, "ret %08x\n", hr );
5358     ok(pNextChild == NULL, "pDocChild not NULL\n");
5359 
5360     /* test previous Sibling */
5361     hr = IXMLDOMDocument_get_previousSibling(doc, NULL);
5362     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5363 
5364     pNextChild = (void*)0xdeadbeef;
5365     hr = IXMLDOMDocument_get_previousSibling(doc, &pNextChild);
5366     ok(hr == S_FALSE, "ret %08x\n", hr );
5367     ok(pNextChild == NULL, "pNextChild not NULL\n");
5368 
5369     /* test get_dataType */
5370     V_VT(&v) = VT_EMPTY;
5371     hr = IXMLDOMDocument_get_dataType(doc, &v);
5372     ok(hr == S_FALSE, "ret %08x\n", hr );
5373     ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
5374     VariantClear(&v);
5375 
5376     /* test implementation */
5377     hr = IXMLDOMDocument_get_implementation(doc, NULL);
5378     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5379 
5380     hr = IXMLDOMDocument_get_implementation(doc, &pIXMLDOMImplementation);
5381     ok(hr == S_OK, "ret %08x\n", hr );
5382     if(hr == S_OK)
5383     {
5384         VARIANT_BOOL hasFeature = VARIANT_TRUE;
5385         BSTR sEmpty = SysAllocStringLen(NULL, 0);
5386 
5387         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, NULL, sEmpty, &hasFeature);
5388         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5389 
5390         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, NULL);
5391         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5392 
5393         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5394         ok(hr == S_OK, "ret %08x\n", hr );
5395         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5396 
5397         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, &hasFeature);
5398         ok(hr == S_OK, "ret %08x\n", hr );
5399         ok(hasFeature == VARIANT_FALSE, "hasFeature returned true\n");
5400 
5401         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), NULL, &hasFeature);
5402         ok(hr == S_OK, "ret %08x\n", hr );
5403         ok(hasFeature == VARIANT_TRUE, "hasFeature returned false\n");
5404 
5405         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5406         ok(hr == S_OK, "ret %08x\n", hr );
5407         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5408 
5409         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), _bstr_("1.0"), &hasFeature);
5410         ok(hr == S_OK, "ret %08x\n", hr );
5411         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5412 
5413         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("XML"), _bstr_("1.0"), &hasFeature);
5414         ok(hr == S_OK, "ret %08x\n", hr );
5415         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5416 
5417         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("MS-DOM"), _bstr_("1.0"), &hasFeature);
5418         ok(hr == S_OK, "ret %08x\n", hr );
5419         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5420 
5421         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("SSS"), NULL, &hasFeature);
5422         ok(hr == S_OK, "ret %08x\n", hr );
5423         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5424 
5425         SysFreeString(sEmpty);
5426         IXMLDOMImplementation_Release(pIXMLDOMImplementation);
5427     }
5428 
5429     pRoot = (IXMLDOMElement*)0x1;
5430     hr = IXMLDOMDocument_createElement(doc, NULL, &pRoot);
5431     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5432     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5433 
5434     pRoot = (IXMLDOMElement*)0x1;
5435     hr = IXMLDOMDocument_createElement(doc, _bstr_(""), &pRoot);
5436     ok(hr == E_FAIL, "ret %08x\n", hr );
5437     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5438 
5439     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
5440     ok(hr == S_OK, "ret %08x\n", hr );
5441     if(hr == S_OK)
5442     {
5443         hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)pRoot, NULL);
5444         ok(hr == S_OK, "ret %08x\n", hr );
5445         if(hr == S_OK)
5446         {
5447             /* Comment */
5448             str = SysAllocString(szComment);
5449             hr = IXMLDOMDocument_createComment(doc, str, &pComment);
5450             SysFreeString(str);
5451             ok(hr == S_OK, "ret %08x\n", hr );
5452             if(hr == S_OK)
5453             {
5454                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pComment, NULL);
5455                 ok(hr == S_OK, "ret %08x\n", hr );
5456 
5457                 hr = IXMLDOMComment_get_nodeName(pComment, &str);
5458                 ok(hr == S_OK, "ret %08x\n", hr );
5459                 ok( !lstrcmpW( str, szCommentNodeText ), "incorrect comment node Name\n");
5460                 SysFreeString(str);
5461 
5462                 hr = IXMLDOMComment_get_xml(pComment, &str);
5463                 ok(hr == S_OK, "ret %08x\n", hr );
5464                 ok( !lstrcmpW( str, szCommentXML ), "incorrect comment xml\n");
5465                 SysFreeString(str);
5466 
5467                 /* put data Tests */
5468                 hr = IXMLDOMComment_put_data(pComment, _bstr_("This &is a ; test <>\\"));
5469                 ok(hr == S_OK, "ret %08x\n", hr );
5470 
5471                 /* get data Tests */
5472                 hr = IXMLDOMComment_get_data(pComment, &str);
5473                 ok(hr == S_OK, "ret %08x\n", hr );
5474                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect get_data string\n");
5475                 SysFreeString(str);
5476 
5477                 /* Confirm XML text is good */
5478                 hr = IXMLDOMComment_get_xml(pComment, &str);
5479                 ok(hr == S_OK, "ret %08x\n", hr );
5480                 ok( !lstrcmpW( str, _bstr_("<!--This &is a ; test <>\\-->") ), "incorrect xml string\n");
5481                 SysFreeString(str);
5482 
5483                 /* Confirm we get the put_data Text back */
5484                 hr = IXMLDOMComment_get_text(pComment, &str);
5485                 ok(hr == S_OK, "ret %08x\n", hr );
5486                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
5487                 SysFreeString(str);
5488 
5489                 /* test length property */
5490                 hr = IXMLDOMComment_get_length(pComment, &len);
5491                 ok(hr == S_OK, "ret %08x\n", hr );
5492                 ok(len == 21, "expected 21 got %d\n", len);
5493 
5494                 /* test substringData */
5495                 hr = IXMLDOMComment_substringData(pComment, 0, 4, NULL);
5496                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5497 
5498                 /* test substringData - Invalid offset */
5499                 str = (void *)0xdeadbeef;
5500                 hr = IXMLDOMComment_substringData(pComment, -1, 4, &str);
5501                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5502                 ok( str == NULL, "incorrect string\n");
5503 
5504                 /* test substringData - Invalid offset */
5505                 str = (void *)0xdeadbeef;
5506                 hr = IXMLDOMComment_substringData(pComment, 30, 0, &str);
5507                 ok(hr == S_FALSE, "ret %08x\n", hr );
5508                 ok( str == NULL, "incorrect string\n");
5509 
5510                 /* test substringData - Invalid size */
5511                 str = (void *)0xdeadbeef;
5512                 hr = IXMLDOMComment_substringData(pComment, 0, -1, &str);
5513                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5514                 ok( str == NULL, "incorrect string\n");
5515 
5516                 /* test substringData - Invalid size */
5517                 str = (void *)0xdeadbeef;
5518                 hr = IXMLDOMComment_substringData(pComment, 2, 0, &str);
5519                 ok(hr == S_FALSE, "ret %08x\n", hr );
5520                 ok( str == NULL, "incorrect string\n");
5521 
5522                 /* test substringData - Start of string */
5523                 hr = IXMLDOMComment_substringData(pComment, 0, 4, &str);
5524                 ok(hr == S_OK, "ret %08x\n", hr );
5525                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5526                 SysFreeString(str);
5527 
5528                 /* test substringData - Middle of string */
5529                 hr = IXMLDOMComment_substringData(pComment, 13, 4, &str);
5530                 ok(hr == S_OK, "ret %08x\n", hr );
5531                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5532                 SysFreeString(str);
5533 
5534                 /* test substringData - End of string */
5535                 hr = IXMLDOMComment_substringData(pComment, 20, 4, &str);
5536                 ok(hr == S_OK, "ret %08x\n", hr );
5537                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5538                 SysFreeString(str);
5539 
5540                 /* test appendData */
5541                 hr = IXMLDOMComment_appendData(pComment, NULL);
5542                 ok(hr == S_OK, "ret %08x\n", hr );
5543 
5544                 hr = IXMLDOMComment_appendData(pComment, _bstr_(""));
5545                 ok(hr == S_OK, "ret %08x\n", hr );
5546 
5547                 hr = IXMLDOMComment_appendData(pComment, _bstr_("Append"));
5548                 ok(hr == S_OK, "ret %08x\n", hr );
5549 
5550                 hr = IXMLDOMComment_get_text(pComment, &str);
5551                 ok(hr == S_OK, "ret %08x\n", hr );
5552                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5553                 SysFreeString(str);
5554 
5555                 /* test insertData */
5556                 str = SysAllocStringLen(NULL, 0);
5557                 hr = IXMLDOMComment_insertData(pComment, -1, str);
5558                 ok(hr == S_OK, "ret %08x\n", hr );
5559 
5560                 hr = IXMLDOMComment_insertData(pComment, -1, NULL);
5561                 ok(hr == S_OK, "ret %08x\n", hr );
5562 
5563                 hr = IXMLDOMComment_insertData(pComment, 1000, str);
5564                 ok(hr == S_OK, "ret %08x\n", hr );
5565 
5566                 hr = IXMLDOMComment_insertData(pComment, 1000, NULL);
5567                 ok(hr == S_OK, "ret %08x\n", hr );
5568 
5569                 hr = IXMLDOMComment_insertData(pComment, 0, NULL);
5570                 ok(hr == S_OK, "ret %08x\n", hr );
5571 
5572                 hr = IXMLDOMComment_insertData(pComment, 0, str);
5573                 ok(hr == S_OK, "ret %08x\n", hr );
5574                 SysFreeString(str);
5575 
5576                 hr = IXMLDOMComment_insertData(pComment, -1, _bstr_("Inserting"));
5577                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5578 
5579                 hr = IXMLDOMComment_insertData(pComment, 1000, _bstr_("Inserting"));
5580                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5581 
5582                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("Begin "));
5583                 ok(hr == S_OK, "ret %08x\n", hr );
5584 
5585                 hr = IXMLDOMComment_insertData(pComment, 17, _bstr_("Middle"));
5586                 ok(hr == S_OK, "ret %08x\n", hr );
5587 
5588                 hr = IXMLDOMComment_insertData(pComment, 39, _bstr_(" End"));
5589                 ok(hr == S_OK, "ret %08x\n", hr );
5590 
5591                 hr = IXMLDOMComment_get_text(pComment, &str);
5592                 ok(hr == S_OK, "ret %08x\n", hr );
5593                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5594                 SysFreeString(str);
5595 
5596                 /* delete data */
5597                 /* invalid arguments */
5598                 hr = IXMLDOMComment_deleteData(pComment, -1, 1);
5599                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5600 
5601                 hr = IXMLDOMComment_deleteData(pComment, 0, 0);
5602                 ok(hr == S_OK, "ret %08x\n", hr );
5603 
5604                 hr = IXMLDOMComment_deleteData(pComment, 0, -1);
5605                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5606 
5607                 hr = IXMLDOMComment_get_length(pComment, &len);
5608                 ok(hr == S_OK, "ret %08x\n", hr );
5609                 ok(len == 43, "expected 43 got %d\n", len);
5610 
5611                 hr = IXMLDOMComment_deleteData(pComment, len, 1);
5612                 ok(hr == S_OK, "ret %08x\n", hr );
5613 
5614                 hr = IXMLDOMComment_deleteData(pComment, len+1, 1);
5615                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5616 
5617                 /* delete from start */
5618                 hr = IXMLDOMComment_deleteData(pComment, 0, 5);
5619                 ok(hr == S_OK, "ret %08x\n", hr );
5620 
5621                 hr = IXMLDOMComment_get_length(pComment, &len);
5622                 ok(hr == S_OK, "ret %08x\n", hr );
5623                 ok(len == 38, "expected 38 got %d\n", len);
5624 
5625                 hr = IXMLDOMComment_get_text(pComment, &str);
5626                 ok(hr == S_OK, "ret %08x\n", hr );
5627                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5628                 SysFreeString(str);
5629 
5630                 /* delete from end */
5631                 hr = IXMLDOMComment_deleteData(pComment, 35, 3);
5632                 ok(hr == S_OK, "ret %08x\n", hr );
5633 
5634                 hr = IXMLDOMComment_get_length(pComment, &len);
5635                 ok(hr == S_OK, "ret %08x\n", hr );
5636                 ok(len == 35, "expected 35 got %d\n", len);
5637 
5638                 hr = IXMLDOMComment_get_text(pComment, &str);
5639                 ok(hr == S_OK, "ret %08x\n", hr );
5640                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5641                 SysFreeString(str);
5642 
5643                 /* delete from inside */
5644                 hr = IXMLDOMComment_deleteData(pComment, 1, 33);
5645                 ok(hr == S_OK, "ret %08x\n", hr );
5646 
5647                 hr = IXMLDOMComment_get_length(pComment, &len);
5648                 ok(hr == S_OK, "ret %08x\n", hr );
5649                 ok(len == 2, "expected 2 got %d\n", len);
5650 
5651                 hr = IXMLDOMComment_get_text(pComment, &str);
5652                 ok(hr == S_OK, "ret %08x\n", hr );
5653                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5654                 SysFreeString(str);
5655 
5656                 /* delete whole data ... */
5657                 hr = IXMLDOMComment_get_length(pComment, &len);
5658                 ok(hr == S_OK, "ret %08x\n", hr );
5659 
5660                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5661                 ok(hr == S_OK, "ret %08x\n", hr );
5662                 /* ... and try again with empty string */
5663                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5664                 ok(hr == S_OK, "ret %08x\n", hr );
5665 
5666                 /* ::replaceData() */
5667                 V_VT(&v) = VT_BSTR;
5668                 V_BSTR(&v) = SysAllocString(szstr1);
5669                 hr = IXMLDOMComment_put_nodeValue(pComment, v);
5670                 ok(hr == S_OK, "ret %08x\n", hr );
5671                 VariantClear(&v);
5672 
5673                 hr = IXMLDOMComment_replaceData(pComment, 6, 0, NULL);
5674                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5675                 hr = IXMLDOMComment_get_text(pComment, &str);
5676                 ok(hr == S_OK, "ret %08x\n", hr );
5677                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5678                 SysFreeString(str);
5679 
5680                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, NULL);
5681                 ok(hr == S_OK, "ret %08x\n", hr );
5682                 hr = IXMLDOMComment_get_text(pComment, &str);
5683                 ok(hr == S_OK, "ret %08x\n", hr );
5684                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5685                 SysFreeString(str);
5686 
5687                 /* NULL pointer means delete */
5688                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, NULL);
5689                 ok(hr == S_OK, "ret %08x\n", hr );
5690                 hr = IXMLDOMComment_get_text(pComment, &str);
5691                 ok(hr == S_OK, "ret %08x\n", hr );
5692                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5693                 SysFreeString(str);
5694 
5695                 /* empty string means delete */
5696                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_(""));
5697                 ok(hr == S_OK, "ret %08x\n", hr );
5698                 hr = IXMLDOMComment_get_text(pComment, &str);
5699                 ok(hr == S_OK, "ret %08x\n", hr );
5700                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5701                 SysFreeString(str);
5702 
5703                 /* zero count means insert */
5704                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, _bstr_("a"));
5705                 ok(hr == S_OK, "ret %08x\n", hr );
5706                 hr = IXMLDOMComment_get_text(pComment, &str);
5707                 ok(hr == S_OK, "ret %08x\n", hr );
5708                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5709                 SysFreeString(str);
5710 
5711                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, NULL);
5712                 ok(hr == S_OK, "ret %08x\n", hr );
5713 
5714                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("m"));
5715                 ok(hr == S_OK, "ret %08x\n", hr );
5716                 hr = IXMLDOMComment_get_text(pComment, &str);
5717                 ok(hr == S_OK, "ret %08x\n", hr );
5718                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5719                 SysFreeString(str);
5720 
5721                 /* nonempty string, count greater than its length */
5722                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, _bstr_("a1.2"));
5723                 ok(hr == S_OK, "ret %08x\n", hr );
5724                 hr = IXMLDOMComment_get_text(pComment, &str);
5725                 ok(hr == S_OK, "ret %08x\n", hr );
5726                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5727                 SysFreeString(str);
5728 
5729                 /* nonempty string, count less than its length */
5730                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_("wine"));
5731                 ok(hr == S_OK, "ret %08x\n", hr );
5732                 hr = IXMLDOMComment_get_text(pComment, &str);
5733                 ok(hr == S_OK, "ret %08x\n", hr );
5734                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5735                 SysFreeString(str);
5736 
5737                 IXMLDOMComment_Release(pComment);
5738             }
5739 
5740             /* Element */
5741             str = SysAllocString(szElement);
5742             hr = IXMLDOMDocument_createElement(doc, str, &pElement);
5743             SysFreeString(str);
5744             ok(hr == S_OK, "ret %08x\n", hr );
5745             if(hr == S_OK)
5746             {
5747                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
5748                 ok(hr == S_OK, "ret %08x\n", hr );
5749 
5750                 hr = IXMLDOMElement_get_nodeName(pElement, &str);
5751                 ok(hr == S_OK, "ret %08x\n", hr );
5752                 ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
5753                 SysFreeString(str);
5754 
5755                 hr = IXMLDOMElement_get_xml(pElement, &str);
5756                 ok(hr == S_OK, "ret %08x\n", hr );
5757                 ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
5758                 SysFreeString(str);
5759 
5760                 /* Attribute */
5761                 pAttribute = (IXMLDOMAttribute*)0x1;
5762                 hr = IXMLDOMDocument_createAttribute(doc, NULL, &pAttribute);
5763                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5764                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5765 
5766                 pAttribute = (IXMLDOMAttribute*)0x1;
5767                 hr = IXMLDOMDocument_createAttribute(doc, _bstr_(""), &pAttribute);
5768                 ok(hr == E_FAIL, "ret %08x\n", hr );
5769                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5770 
5771                 str = SysAllocString(szAttribute);
5772                 hr = IXMLDOMDocument_createAttribute(doc, str, &pAttribute);
5773                 SysFreeString(str);
5774                 ok(hr == S_OK, "ret %08x\n", hr );
5775                 if(hr == S_OK)
5776                 {
5777                     IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
5778 
5779                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, NULL);
5780                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5781 
5782                     pNextChild = (IXMLDOMNode *)0x1;
5783                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, &pNextChild);
5784                     ok(hr == S_FALSE, "ret %08x\n", hr );
5785                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5786 
5787                     /* test Previous Sibling*/
5788                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, NULL);
5789                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5790 
5791                     pNextChild = (IXMLDOMNode *)0x1;
5792                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, &pNextChild);
5793                     ok(hr == S_FALSE, "ret %08x\n", hr );
5794                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5795 
5796                     hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttribute, &pNewChild);
5797                     ok(hr == E_FAIL, "ret %08x\n", hr );
5798                     ok(pNewChild == NULL, "pNewChild not NULL\n");
5799 
5800                     hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
5801                     ok(hr == S_OK, "ret %08x\n", hr );
5802                     if ( hr == S_OK )
5803                     {
5804                         hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttribute, NULL );
5805                         ok(hr == S_OK, "ret %08x\n", hr );
5806 
5807                         IXMLDOMNamedNodeMap_Release(pAttribs);
5808                     }
5809 
5810                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5811                     ok(hr == S_OK, "ret %08x\n", hr );
5812                     ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
5813                     SysFreeString(str);
5814 
5815                     /* test nodeName */
5816                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5817                     ok(hr == S_OK, "ret %08x\n", hr );
5818                     ok( !lstrcmpW( str, szAttribute ), "incorrect nodeName string\n");
5819                     SysFreeString(str);
5820 
5821                     /* test name property */
5822                     hr = IXMLDOMAttribute_get_name(pAttribute, &str);
5823                     ok(hr == S_OK, "ret %08x\n", hr );
5824                     ok( !lstrcmpW( str, szAttribute ), "incorrect name string\n");
5825                     SysFreeString(str);
5826 
5827                     hr = IXMLDOMAttribute_get_xml(pAttribute, &str);
5828                     ok(hr == S_OK, "ret %08x\n", hr );
5829                     ok( !lstrcmpW( str, szAttributeXML ), "incorrect attribute xml\n");
5830                     SysFreeString(str);
5831 
5832                     IXMLDOMAttribute_Release(pAttribute);
5833 
5834                     /* Check Element again with the Add Attribute*/
5835                     hr = IXMLDOMElement_get_xml(pElement, &str);
5836                     ok(hr == S_OK, "ret %08x\n", hr );
5837                     ok( !lstrcmpW( str, szElementXML2 ), "incorrect element xml\n");
5838                     SysFreeString(str);
5839                 }
5840 
5841                 hr = IXMLDOMElement_put_text(pElement, _bstr_("TestingNode"));
5842                 ok(hr == S_OK, "ret %08x\n", hr );
5843 
5844                 hr = IXMLDOMElement_get_xml(pElement, &str);
5845                 ok(hr == S_OK, "ret %08x\n", hr );
5846                 ok( !lstrcmpW( str, szElementXML3 ), "incorrect element xml\n");
5847                 SysFreeString(str);
5848 
5849                 /* Test for reversible escaping */
5850                 str = SysAllocString( szStrangeChars );
5851                 hr = IXMLDOMElement_put_text(pElement, str);
5852                 ok(hr == S_OK, "ret %08x\n", hr );
5853                 SysFreeString( str );
5854 
5855                 hr = IXMLDOMElement_get_xml(pElement, &str);
5856                 ok(hr == S_OK, "ret %08x\n", hr );
5857                 ok( !lstrcmpW( str, szElementXML4 ), "incorrect element xml\n");
5858                 SysFreeString(str);
5859 
5860                 hr = IXMLDOMElement_get_text(pElement, &str);
5861                 ok(hr == S_OK, "ret %08x\n", hr );
5862                 ok( !lstrcmpW( str, szStrangeChars ), "incorrect element text\n");
5863                 SysFreeString(str);
5864 
5865                 IXMLDOMElement_Release(pElement);
5866             }
5867 
5868             /* CData Section */
5869             str = SysAllocString(szCData);
5870             hr = IXMLDOMDocument_createCDATASection(doc, str, NULL);
5871             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5872 
5873             hr = IXMLDOMDocument_createCDATASection(doc, str, &pCDataSec);
5874             SysFreeString(str);
5875             ok(hr == S_OK, "ret %08x\n", hr );
5876             if(hr == S_OK)
5877             {
5878                 IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
5879                 VARIANT var;
5880 
5881                 VariantInit(&var);
5882 
5883                 hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (void**)&pElement);
5884                 ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
5885 
5886                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pCDataSec, NULL);
5887                 ok(hr == S_OK, "ret %08x\n", hr );
5888 
5889                 hr = IXMLDOMCDATASection_get_nodeName(pCDataSec, &str);
5890                 ok(hr == S_OK, "ret %08x\n", hr );
5891                 ok( !lstrcmpW( str, szCDataNodeText ), "incorrect cdata node Name\n");
5892                 SysFreeString(str);
5893 
5894                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5895                 ok(hr == S_OK, "ret %08x\n", hr );
5896                 ok( !lstrcmpW( str, szCDataXML ), "incorrect cdata xml\n");
5897                 SysFreeString(str);
5898 
5899                 /* test lastChild */
5900                 pNextChild = (IXMLDOMNode*)0x1;
5901                 hr = IXMLDOMCDATASection_get_lastChild(pCDataSec, &pNextChild);
5902                 ok(hr == S_FALSE, "ret %08x\n", hr );
5903                 ok(pNextChild == NULL, "pNextChild not NULL\n");
5904 
5905                 /* put data Tests */
5906                 hr = IXMLDOMCDATASection_put_data(pCDataSec, _bstr_("This &is a ; test <>\\"));
5907                 ok(hr == S_OK, "ret %08x\n", hr );
5908 
5909                 /* Confirm XML text is good */
5910                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5911                 ok(hr == S_OK, "ret %08x\n", hr );
5912                 ok( !lstrcmpW( str, _bstr_("<![CDATA[This &is a ; test <>\\]]>") ), "incorrect xml string\n");
5913                 SysFreeString(str);
5914 
5915                 /* Confirm we get the put_data Text back */
5916                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5917                 ok(hr == S_OK, "ret %08x\n", hr );
5918                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5919                 SysFreeString(str);
5920 
5921                 /* test length property */
5922                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5923                 ok(hr == S_OK, "ret %08x\n", hr );
5924                 ok(len == 21, "expected 21 got %d\n", len);
5925 
5926                 /* test get data */
5927                 hr = IXMLDOMCDATASection_get_data(pCDataSec, &str);
5928                 ok(hr == S_OK, "ret %08x\n", hr );
5929                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5930                 SysFreeString(str);
5931 
5932                 /* test substringData */
5933                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, NULL);
5934                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5935 
5936                 /* test substringData - Invalid offset */
5937                 str = (void *)0xdeadbeef;
5938                 hr = IXMLDOMCDATASection_substringData(pCDataSec, -1, 4, &str);
5939                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5940                 ok( str == NULL, "incorrect string\n");
5941 
5942                 /* test substringData - Invalid offset */
5943                 str = (void *)0xdeadbeef;
5944                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 30, 0, &str);
5945                 ok(hr == S_FALSE, "ret %08x\n", hr );
5946                 ok( str == NULL, "incorrect string\n");
5947 
5948                 /* test substringData - Invalid size */
5949                 str = (void *)0xdeadbeef;
5950                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, -1, &str);
5951                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5952                 ok( str == NULL, "incorrect string\n");
5953 
5954                 /* test substringData - Invalid size */
5955                 str = (void *)0xdeadbeef;
5956                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 2, 0, &str);
5957                 ok(hr == S_FALSE, "ret %08x\n", hr );
5958                 ok( str == NULL, "incorrect string\n");
5959 
5960                 /* test substringData - Start of string */
5961                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, &str);
5962                 ok(hr == S_OK, "ret %08x\n", hr );
5963                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5964                 SysFreeString(str);
5965 
5966                 /* test substringData - Middle of string */
5967                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 13, 4, &str);
5968                 ok(hr == S_OK, "ret %08x\n", hr );
5969                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5970                 SysFreeString(str);
5971 
5972                 /* test substringData - End of string */
5973                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 20, 4, &str);
5974                 ok(hr == S_OK, "ret %08x\n", hr );
5975                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5976                 SysFreeString(str);
5977 
5978                 /* test appendData */
5979                 hr = IXMLDOMCDATASection_appendData(pCDataSec, NULL);
5980                 ok(hr == S_OK, "ret %08x\n", hr );
5981 
5982                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_(""));
5983                 ok(hr == S_OK, "ret %08x\n", hr );
5984 
5985                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_("Append"));
5986                 ok(hr == S_OK, "ret %08x\n", hr );
5987 
5988                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5989                 ok(hr == S_OK, "ret %08x\n", hr );
5990                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5991                 SysFreeString(str);
5992 
5993                 /* test insertData */
5994                 str = SysAllocStringLen(NULL, 0);
5995                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, str);
5996                 ok(hr == S_OK, "ret %08x\n", hr );
5997 
5998                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, NULL);
5999                 ok(hr == S_OK, "ret %08x\n", hr );
6000 
6001                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, str);
6002                 ok(hr == S_OK, "ret %08x\n", hr );
6003 
6004                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, NULL);
6005                 ok(hr == S_OK, "ret %08x\n", hr );
6006 
6007                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, NULL);
6008                 ok(hr == S_OK, "ret %08x\n", hr );
6009 
6010                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, str);
6011                 ok(hr == S_OK, "ret %08x\n", hr );
6012                 SysFreeString(str);
6013 
6014                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, _bstr_("Inserting"));
6015                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6016 
6017                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, _bstr_("Inserting"));
6018                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6019 
6020                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("Begin "));
6021                 ok(hr == S_OK, "ret %08x\n", hr );
6022 
6023                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 17, _bstr_("Middle"));
6024                 ok(hr == S_OK, "ret %08x\n", hr );
6025 
6026                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 39, _bstr_(" End"));
6027                 ok(hr == S_OK, "ret %08x\n", hr );
6028 
6029                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6030                 ok(hr == S_OK, "ret %08x\n", hr );
6031                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6032                 SysFreeString(str);
6033 
6034                 /* delete data */
6035                 /* invalid arguments */
6036                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, -1, 1);
6037                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6038 
6039                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 0);
6040                 ok(hr == S_OK, "ret %08x\n", hr );
6041 
6042                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, -1);
6043                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6044 
6045                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6046                 ok(hr == S_OK, "ret %08x\n", hr );
6047                 ok(len == 43, "expected 43 got %d\n", len);
6048 
6049                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len, 1);
6050                 ok(hr == S_OK, "ret %08x\n", hr );
6051 
6052                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len+1, 1);
6053                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6054 
6055                 /* delete from start */
6056                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 5);
6057                 ok(hr == S_OK, "ret %08x\n", hr );
6058 
6059                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6060                 ok(hr == S_OK, "ret %08x\n", hr );
6061                 ok(len == 38, "expected 38 got %d\n", len);
6062 
6063                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6064                 ok(hr == S_OK, "ret %08x\n", hr );
6065                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6066                 SysFreeString(str);
6067 
6068                 /* delete from end */
6069                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 35, 3);
6070                 ok(hr == S_OK, "ret %08x\n", hr );
6071 
6072                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6073                 ok(hr == S_OK, "ret %08x\n", hr );
6074                 ok(len == 35, "expected 35 got %d\n", len);
6075 
6076                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6077                 ok(hr == S_OK, "ret %08x\n", hr );
6078                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6079                 SysFreeString(str);
6080 
6081                 /* delete from inside */
6082                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 1, 33);
6083                 ok(hr == S_OK, "ret %08x\n", hr );
6084 
6085                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6086                 ok(hr == S_OK, "ret %08x\n", hr );
6087                 ok(len == 2, "expected 2 got %d\n", len);
6088 
6089                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6090                 ok(hr == S_OK, "ret %08x\n", hr );
6091                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6092                 SysFreeString(str);
6093 
6094                 /* delete whole data ... */
6095                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6096                 ok(hr == S_OK, "ret %08x\n", hr );
6097 
6098                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6099                 ok(hr == S_OK, "ret %08x\n", hr );
6100 
6101                 /* ... and try again with empty string */
6102                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6103                 ok(hr == S_OK, "ret %08x\n", hr );
6104 
6105                 /* ::replaceData() */
6106                 V_VT(&v) = VT_BSTR;
6107                 V_BSTR(&v) = SysAllocString(szstr1);
6108                 hr = IXMLDOMCDATASection_put_nodeValue(pCDataSec, v);
6109                 ok(hr == S_OK, "ret %08x\n", hr );
6110                 VariantClear(&v);
6111 
6112                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 6, 0, NULL);
6113                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6114                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6115                 ok(hr == S_OK, "ret %08x\n", hr );
6116                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6117                 SysFreeString(str);
6118 
6119                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, NULL);
6120                 ok(hr == S_OK, "ret %08x\n", hr );
6121                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6122                 ok(hr == S_OK, "ret %08x\n", hr );
6123                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6124                 SysFreeString(str);
6125 
6126                 /* NULL pointer means delete */
6127                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, NULL);
6128                 ok(hr == S_OK, "ret %08x\n", hr );
6129                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6130                 ok(hr == S_OK, "ret %08x\n", hr );
6131                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6132                 SysFreeString(str);
6133 
6134                 /* empty string means delete */
6135                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_(""));
6136                 ok(hr == S_OK, "ret %08x\n", hr );
6137                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6138                 ok(hr == S_OK, "ret %08x\n", hr );
6139                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6140                 SysFreeString(str);
6141 
6142                 /* zero count means insert */
6143                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, _bstr_("a"));
6144                 ok(hr == S_OK, "ret %08x\n", hr );
6145                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6146                 ok(hr == S_OK, "ret %08x\n", hr );
6147                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6148                 SysFreeString(str);
6149 
6150                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, NULL);
6151                 ok(hr == S_OK, "ret %08x\n", hr );
6152 
6153                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("m"));
6154                 ok(hr == S_OK, "ret %08x\n", hr );
6155                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6156                 ok(hr == S_OK, "ret %08x\n", hr );
6157                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6158                 SysFreeString(str);
6159 
6160                 /* nonempty string, count greater than its length */
6161                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, _bstr_("a1.2"));
6162                 ok(hr == S_OK, "ret %08x\n", hr );
6163                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6164                 ok(hr == S_OK, "ret %08x\n", hr );
6165                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6166                 SysFreeString(str);
6167 
6168                 /* nonempty string, count less than its length */
6169                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_("wine"));
6170                 ok(hr == S_OK, "ret %08x\n", hr );
6171                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6172                 ok(hr == S_OK, "ret %08x\n", hr );
6173                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6174                 SysFreeString(str);
6175 
6176                 IXMLDOMCDATASection_Release(pCDataSec);
6177             }
6178 
6179             /* Document Fragments */
6180             hr = IXMLDOMDocument_createDocumentFragment(doc, NULL);
6181             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6182 
6183             hr = IXMLDOMDocument_createDocumentFragment(doc, &pDocFrag);
6184             ok(hr == S_OK, "ret %08x\n", hr );
6185             if(hr == S_OK)
6186             {
6187                 IXMLDOMNode *node;
6188 
6189                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, NULL);
6190                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6191 
6192                 node = (IXMLDOMNode *)0x1;
6193                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, &node);
6194                 ok(hr == S_FALSE, "ret %08x\n", hr );
6195                 ok(node == NULL, "expected NULL, got %p\n", node);
6196 
6197                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pDocFrag, NULL);
6198                 ok(hr == S_OK, "ret %08x\n", hr );
6199 
6200                 hr = IXMLDOMDocumentFragment_get_nodeName(pDocFrag, &str);
6201                 ok(hr == S_OK, "ret %08x\n", hr );
6202                 ok( !lstrcmpW( str, szDocFragmentText ), "incorrect docfragment node Name\n");
6203                 SysFreeString(str);
6204 
6205                 /* test next Sibling*/
6206                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, NULL);
6207                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6208 
6209                 node = (IXMLDOMNode *)0x1;
6210                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &node);
6211                 ok(hr == S_FALSE, "ret %08x\n", hr );
6212                 ok(node == NULL, "next sibling not NULL\n");
6213 
6214                 /* test Previous Sibling*/
6215                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, NULL);
6216                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6217 
6218                 node = (IXMLDOMNode *)0x1;
6219                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &node);
6220                 ok(hr == S_FALSE, "ret %08x\n", hr );
6221                 ok(node == NULL, "previous sibling not NULL\n");
6222 
6223                 IXMLDOMDocumentFragment_Release(pDocFrag);
6224             }
6225 
6226             /* Entity References */
6227             hr = IXMLDOMDocument_createEntityReference(doc, NULL, &pEntityRef);
6228             ok(hr == E_FAIL, "ret %08x\n", hr );
6229             hr = IXMLDOMDocument_createEntityReference(doc, _bstr_(""), &pEntityRef);
6230             ok(hr == E_FAIL, "ret %08x\n", hr );
6231 
6232             str = SysAllocString(szEntityRef);
6233             hr = IXMLDOMDocument_createEntityReference(doc, str, NULL);
6234             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6235 
6236             hr = IXMLDOMDocument_createEntityReference(doc, str, &pEntityRef);
6237             SysFreeString(str);
6238             ok(hr == S_OK, "ret %08x\n", hr );
6239             if(hr == S_OK)
6240             {
6241                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pEntityRef, NULL);
6242                 ok(hr == S_OK, "ret %08x\n", hr );
6243 
6244                 /* test get_xml*/
6245                 hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str);
6246                 ok(hr == S_OK, "ret %08x\n", hr );
6247                 ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n");
6248                 SysFreeString(str);
6249 
6250                 IXMLDOMEntityReference_Release(pEntityRef);
6251             }
6252 
6253             IXMLDOMElement_Release( pRoot );
6254         }
6255     }
6256 
6257     IXMLDOMDocument_Release(doc);
6258 
6259     free_bstrs();
6260 }
6261 
6262 typedef struct {
6263     const char *name;
6264     const char *type;
6265     HRESULT hr;
6266 } put_datatype_t;
6267 
6268 /* Type test for elements only. Name passed into put_dataType is case-insensitive.
6269    So many of the names have been changed to reflect this. */
6270 static put_datatype_t put_datatype_data[] = {
6271     { "test_inval",      "abcdefg",     E_FAIL },
6272     { "test_bool",       "Boolean",     S_OK },
6273     { "test_string",     "String",      S_OK },
6274     { "test_number",     "number",      S_OK },
6275     { "test_int",        "InT",         S_OK },
6276     { "test_fixed",      "fixed.14.4",  S_OK },
6277     { "test_datetime",   "DateTime",    S_OK },
6278     { "test_datetimetz", "DateTime.tz", S_OK },
6279     { "test_date",       "Date",        S_OK },
6280     { "test_time",       "Time",        S_OK },
6281     { "test_timetz",     "Time.tz",     S_OK },
6282     { "test_I1",         "I1",          S_OK },
6283     { "test_I2",         "I2",          S_OK },
6284     { "test_I4",         "I4",          S_OK },
6285     { "test_UI1",        "UI1",         S_OK },
6286     { "test_UI2",        "UI2",         S_OK },
6287     { "test_UI4",        "UI4",         S_OK },
6288     { "test_r4",         "r4",          S_OK },
6289     { "test_r8",         "r8",          S_OK },
6290     { "test_float",      "float",       S_OK },
6291     { "test_uuid",       "UuId",        S_OK },
6292     { "test_binhex",     "bin.hex",     S_OK },
6293     { "test_binbase64",  "bin.base64",  S_OK },
6294     { NULL }
6295 };
6296 
6297 typedef struct {
6298     DOMNodeType type;
6299     HRESULT hr;
6300 } put_datatype_notype_t;
6301 
6302 static put_datatype_notype_t put_dt_notype[] = {
6303     { NODE_PROCESSING_INSTRUCTION, E_FAIL },
6304     { NODE_DOCUMENT_FRAGMENT,      E_FAIL },
6305     { NODE_ENTITY_REFERENCE,       E_FAIL },
6306     { NODE_CDATA_SECTION,          E_FAIL },
6307     { NODE_COMMENT,                E_FAIL },
6308     { NODE_INVALID }
6309 };
6310 
6311 static void test_put_dataType( void )
6312 {
6313     const put_datatype_notype_t *ptr2 = put_dt_notype;
6314     const put_datatype_t *ptr = put_datatype_data;
6315     IXMLDOMElement *root, *element;
6316     BSTR nameW, type1W, type2W;
6317     IXMLDOMDocument *doc;
6318     HRESULT hr;
6319 
6320     doc = create_document(&IID_IXMLDOMDocument);
6321 
6322     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), NULL);
6323     EXPECT_HR(hr, E_INVALIDARG);
6324 
6325     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6326     EXPECT_HR(hr, S_OK);
6327 
6328     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6329     EXPECT_HR(hr, S_OK);
6330 
6331     hr = IXMLDOMElement_put_dataType(root, NULL);
6332     EXPECT_HR(hr, E_INVALIDARG);
6333 
6334     while (ptr->name)
6335     {
6336         hr = IXMLDOMDocument_createElement(doc, _bstr_(ptr->name), &element);
6337         EXPECT_HR(hr, S_OK);
6338         if(hr == S_OK)
6339         {
6340             hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6341             EXPECT_HR(hr, S_OK);
6342 
6343             hr = IXMLDOMElement_put_dataType(element, _bstr_(ptr->type));
6344             ok(hr == ptr->hr, "failed for %s:%s, 0x%08x\n", ptr->name, ptr->type, ptr->hr);
6345 
6346             IXMLDOMElement_Release(element);
6347         }
6348         ptr++;
6349     }
6350 
6351     /* check changing types */
6352     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Change"), &element);
6353     EXPECT_HR(hr, S_OK);
6354 
6355     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6356     EXPECT_HR(hr, S_OK);
6357 
6358     hr = IXMLDOMElement_put_dataType(element, _bstr_("DateTime.tz"));
6359     EXPECT_HR(hr, S_OK);
6360 
6361     hr = IXMLDOMElement_put_dataType(element, _bstr_("string"));
6362     EXPECT_HR(hr, S_OK);
6363 
6364     IXMLDOMElement_Release(element);
6365 
6366     /* try to set type for node without a type */
6367     nameW  = _bstr_("testname");
6368     type1W = _bstr_("string");
6369     type2W = _bstr_("number");
6370     while (ptr2->type != NODE_INVALID)
6371     {
6372         IXMLDOMNode *node;
6373         VARIANT type;
6374 
6375         V_VT(&type) = VT_I2;
6376         V_I2(&type) = ptr2->type;
6377 
6378         hr = IXMLDOMDocument_createNode(doc, type, nameW, NULL, &node);
6379         EXPECT_HR(hr, S_OK);
6380         if(hr == S_OK)
6381         {
6382             hr = IXMLDOMElement_appendChild(root, node, NULL);
6383             EXPECT_HR(hr, S_OK);
6384 
6385             hr = IXMLDOMNode_put_dataType(node, NULL);
6386             EXPECT_HR(hr, E_INVALIDARG);
6387 
6388             hr = IXMLDOMNode_put_dataType(node, type1W);
6389             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6390             hr = IXMLDOMNode_put_dataType(node, type2W);
6391             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6392 
6393             IXMLDOMNode_Release(node);
6394         }
6395         ptr2++;
6396     }
6397 
6398     IXMLDOMElement_Release(root);
6399     IXMLDOMDocument_Release(doc);
6400     free_bstrs();
6401 }
6402 
6403 static void test_save(void)
6404 {
6405     IXMLDOMDocument *doc, *doc2;
6406     IXMLDOMElement *root;
6407     BSTR sOrig, sNew, filename;
6408     char buffer[100];
6409     IStream *stream;
6410     HGLOBAL global;
6411     VARIANT_BOOL b;
6412     DWORD read = 0;
6413     VARIANT dest;
6414     HANDLE hfile;
6415     HRESULT hr;
6416     char *ptr;
6417 
6418     doc = create_document(&IID_IXMLDOMDocument);
6419     doc2 = create_document(&IID_IXMLDOMDocument);
6420 
6421     /* save to IXMLDOMDocument */
6422     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6423     EXPECT_HR(hr, S_OK);
6424 
6425     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6426     EXPECT_HR(hr, S_OK);
6427 
6428     V_VT(&dest) = VT_UNKNOWN;
6429     V_UNKNOWN(&dest) = (IUnknown*)doc2;
6430 
6431     hr = IXMLDOMDocument_save(doc, dest);
6432     EXPECT_HR(hr, S_OK);
6433 
6434     hr = IXMLDOMDocument_get_xml(doc, &sOrig);
6435     EXPECT_HR(hr, S_OK);
6436 
6437     hr = IXMLDOMDocument_get_xml(doc2, &sNew);
6438     EXPECT_HR(hr, S_OK);
6439 
6440     ok( !lstrcmpW( sOrig, sNew ), "New document is not the same as original\n");
6441 
6442     SysFreeString(sOrig);
6443     SysFreeString(sNew);
6444 
6445     IXMLDOMElement_Release(root);
6446     IXMLDOMDocument_Release(doc2);
6447 
6448     /* save to path */
6449     V_VT(&dest) = VT_BSTR;
6450     V_BSTR(&dest) = _bstr_("test.xml");
6451 
6452     hr = IXMLDOMDocument_save(doc, dest);
6453     EXPECT_HR(hr, S_OK);
6454 
6455     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6456     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6457     if(hfile == INVALID_HANDLE_VALUE) return;
6458 
6459     ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6460     ok(read != 0, "could not read file\n");
6461     ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6462 
6463     CloseHandle(hfile);
6464     DeleteFileA("test.xml");
6465 
6466     /* save to path VT_BSTR | VT_BYREF */
6467     filename = _bstr_("test.xml");
6468     V_VT(&dest) = VT_BSTR | VT_BYREF;
6469     V_BSTRREF(&dest) = &filename;
6470 
6471     hr = IXMLDOMDocument_save(doc, dest);
6472     EXPECT_HR(hr, S_OK);
6473 
6474     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6475     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6476     if(hfile == INVALID_HANDLE_VALUE) return;
6477 
6478     if (hfile != INVALID_HANDLE_VALUE)
6479     {
6480        ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6481        ok(read != 0, "could not read file\n");
6482        ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6483 
6484        CloseHandle(hfile);
6485        DeleteFileA("test.xml");
6486     }
6487 
6488     /* save to stream */
6489     V_VT(&dest) = VT_UNKNOWN;
6490     V_UNKNOWN(&dest) = (IUnknown*)&savestream;
6491 
6492     hr = IXMLDOMDocument_save(doc, dest);
6493     EXPECT_HR(hr, S_OK);
6494 
6495     /* loaded data contains xml declaration */
6496     hr = IXMLDOMDocument_loadXML(doc, _bstr_(win1252xml), &b);
6497     EXPECT_HR(hr, S_OK);
6498 
6499     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6500     ok(hr == S_OK, "got 0x%08x\n", hr);
6501     V_VT(&dest) = VT_UNKNOWN;
6502     V_UNKNOWN(&dest) = (IUnknown*)stream;
6503     hr = IXMLDOMDocument_save(doc, dest);
6504     EXPECT_HR(hr, S_OK);
6505 
6506     hr = GetHGlobalFromStream(stream, &global);
6507     EXPECT_HR(hr, S_OK);
6508     ptr = GlobalLock(global);
6509     ok(!memcmp(ptr, win1252decl, strlen(win1252decl)), "got wrong xml declaration\n");
6510     GlobalUnlock(global);
6511     IStream_Release(stream);
6512 
6513     /* loaded data without xml declaration */
6514     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<a/>"), &b);
6515     EXPECT_HR(hr, S_OK);
6516 
6517     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6518     ok(hr == S_OK, "got 0x%08x\n", hr);
6519     V_VT(&dest) = VT_UNKNOWN;
6520     V_UNKNOWN(&dest) = (IUnknown*)stream;
6521     hr = IXMLDOMDocument_save(doc, dest);
6522     EXPECT_HR(hr, S_OK);
6523 
6524     hr = GetHGlobalFromStream(stream, &global);
6525     EXPECT_HR(hr, S_OK);
6526     ptr = GlobalLock(global);
6527     ok(ptr[0] == '<' && ptr[1] != '?', "got wrong start tag %c%c\n", ptr[0], ptr[1]);
6528     GlobalUnlock(global);
6529     IStream_Release(stream);
6530 
6531     IXMLDOMDocument_Release(doc);
6532     free_bstrs();
6533 }
6534 
6535 static void test_testTransforms(void)
6536 {
6537     IXMLDOMDocument *doc, *docSS;
6538     IXMLDOMNode *pNode;
6539     VARIANT_BOOL bSucc;
6540     HRESULT hr;
6541 
6542     doc = create_document(&IID_IXMLDOMDocument);
6543     docSS = create_document(&IID_IXMLDOMDocument);
6544 
6545     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &bSucc);
6546     ok(hr == S_OK, "ret %08x\n", hr );
6547 
6548     hr = IXMLDOMDocument_loadXML(docSS, _bstr_(szTransformSSXML), &bSucc);
6549     ok(hr == S_OK, "ret %08x\n", hr );
6550 
6551     hr = IXMLDOMDocument_QueryInterface(docSS, &IID_IXMLDOMNode, (void**)&pNode );
6552     ok(hr == S_OK, "ret %08x\n", hr );
6553     if(hr == S_OK)
6554     {
6555         BSTR bOut;
6556 
6557         hr = IXMLDOMDocument_transformNode(doc, pNode, &bOut);
6558         ok(hr == S_OK, "ret %08x\n", hr );
6559         if(hr == S_OK)
6560         {
6561             ok( compareIgnoreReturns( bOut, _bstr_(szTransformOutput)), "got output %s\n", wine_dbgstr_w(bOut));
6562             SysFreeString(bOut);
6563         }
6564 
6565         IXMLDOMNode_Release(pNode);
6566     }
6567 
6568     IXMLDOMDocument_Release(docSS);
6569     IXMLDOMDocument_Release(doc);
6570 
6571     free_bstrs();
6572 }
6573 
6574 struct namespaces_change_t {
6575     const CLSID *clsid;
6576     const char *name;
6577 };
6578 
6579 static const struct namespaces_change_t namespaces_change_test_data[] = {
6580     { &CLSID_DOMDocument,   "CLSID_DOMDocument"   },
6581     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2"  },
6582     { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
6583     { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
6584     { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
6585     { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
6586     { 0 }
6587 };
6588 
6589 static void test_namespaces_change(void)
6590 {
6591     const struct namespaces_change_t *class_ptr = namespaces_change_test_data;
6592 
6593     while (class_ptr->clsid)
6594     {
6595         IXMLDOMDocument *doc = NULL;
6596         IXMLDOMElement *elem = NULL;
6597         IXMLDOMNode *node = NULL;
6598 
6599         VARIANT var;
6600         HRESULT hr;
6601         BSTR str;
6602 
6603         if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
6604         {
6605             class_ptr++;
6606             continue;
6607         }
6608 
6609         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
6610                               &IID_IXMLDOMDocument, (void**)&doc);
6611         ok(hr == S_OK, "got 0x%08x\n", hr);
6612 
6613         V_VT(&var) = VT_I2;
6614         V_I2(&var) = NODE_ELEMENT;
6615 
6616         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("ns:elem"), _bstr_("ns/uri"), &node);
6617         EXPECT_HR(hr, S_OK);
6618 
6619         hr = IXMLDOMDocument_appendChild(doc, node, NULL);
6620         EXPECT_HR(hr, S_OK);
6621 
6622         hr = IXMLDOMDocument_get_documentElement(doc, &elem);
6623         EXPECT_HR(hr, S_OK);
6624 
6625         /* try same prefix, different uri */
6626         V_VT(&var) = VT_BSTR;
6627         V_BSTR(&var) = _bstr_("ns/uri2");
6628 
6629         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6630         EXPECT_HR(hr, E_INVALIDARG);
6631 
6632         /* try same prefix and uri */
6633         V_VT(&var) = VT_BSTR;
6634         V_BSTR(&var) = _bstr_("ns/uri");
6635 
6636         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6637         EXPECT_HR(hr, S_OK);
6638 
6639         hr = IXMLDOMElement_get_xml(elem, &str);
6640         EXPECT_HR(hr, S_OK);
6641         ok(!lstrcmpW(str, _bstr_("<ns:elem xmlns:ns=\"ns/uri\"/>")), "got element %s for %s\n",
6642            wine_dbgstr_w(str), class_ptr->name);
6643         SysFreeString(str);
6644 
6645         IXMLDOMElement_Release(elem);
6646         IXMLDOMDocument_Release(doc);
6647 
6648         free_bstrs();
6649 
6650         class_ptr++;
6651     }
6652 }
6653 
6654 static void test_namespaces_basic(void)
6655 {
6656     static const CHAR namespaces_xmlA[] =
6657         "<?xml version=\"1.0\"?>\n"
6658         "<XMI xmi.version=\"1.1\" xmlns:Model=\"http://omg.org/mof.Model/1.3\">"
6659         "  <XMI.content>"
6660         "    <Model:Package name=\"WinePackage\" Model:name2=\"name2 attr\" />"
6661         "  </XMI.content>"
6662         "</XMI>";
6663 
6664     IXMLDOMDocument *doc;
6665     IXMLDOMElement *elem;
6666     IXMLDOMNode *node;
6667 
6668     VARIANT_BOOL b;
6669     HRESULT hr;
6670     BSTR str;
6671 
6672     doc = create_document(&IID_IXMLDOMDocument);
6673 
6674     hr = IXMLDOMDocument_loadXML(doc, _bstr_(namespaces_xmlA), &b);
6675     EXPECT_HR(hr, S_OK);
6676     ok(b == VARIANT_TRUE, "got %d\n", b);
6677 
6678     str = (void *)0xdeadbeef;
6679     hr = IXMLDOMDocument_get_namespaceURI(doc, &str);
6680     EXPECT_HR(hr, S_FALSE);
6681     ok(str == NULL, "got %p\n", str);
6682 
6683     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("//XMI.content"), &node );
6684     EXPECT_HR(hr, S_OK);
6685     if(hr == S_OK)
6686     {
6687         IXMLDOMAttribute *attr;
6688         IXMLDOMNode *node2;
6689 
6690         hr = IXMLDOMNode_get_firstChild(node, &node2);
6691         EXPECT_HR(hr, S_OK);
6692         ok(node2 != NULL, "got %p\n", node2);
6693 
6694         /* Test get_prefix */
6695         hr = IXMLDOMNode_get_prefix(node2, NULL);
6696         EXPECT_HR(hr, E_INVALIDARG);
6697         /* NOTE: Need to test that arg2 gets cleared on Error. */
6698 
6699         hr = IXMLDOMNode_get_prefix(node2, &str);
6700         EXPECT_HR(hr, S_OK);
6701         ok( !lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6702         SysFreeString(str);
6703 
6704         hr = IXMLDOMNode_get_nodeName(node2, &str);
6705         EXPECT_HR(hr, S_OK);
6706         ok(!lstrcmpW( str, _bstr_("Model:Package")), "got %s\n", wine_dbgstr_w(str));
6707         SysFreeString(str);
6708 
6709         /* Test get_namespaceURI */
6710         hr = IXMLDOMNode_get_namespaceURI(node2, NULL);
6711         EXPECT_HR(hr, E_INVALIDARG);
6712         /* NOTE: Need to test that arg2 gets cleared on Error. */
6713 
6714         hr = IXMLDOMNode_get_namespaceURI(node2, &str);
6715         EXPECT_HR(hr, S_OK);
6716         ok(!lstrcmpW( str, _bstr_("http://omg.org/mof.Model/1.3")), "got %s\n", wine_dbgstr_w(str));
6717         SysFreeString(str);
6718 
6719         hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&elem);
6720         EXPECT_HR(hr, S_OK);
6721 
6722         hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("Model:name2"), &attr);
6723         EXPECT_HR(hr, S_OK);
6724 
6725         hr = IXMLDOMAttribute_get_nodeName(attr, &str);
6726         EXPECT_HR(hr, S_OK);
6727         ok(!lstrcmpW( str, _bstr_("Model:name2")), "got %s\n", wine_dbgstr_w(str));
6728         SysFreeString(str);
6729 
6730         hr = IXMLDOMAttribute_get_prefix(attr, &str);
6731         EXPECT_HR(hr, S_OK);
6732         ok(!lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6733         SysFreeString(str);
6734 
6735         IXMLDOMAttribute_Release(attr);
6736         IXMLDOMElement_Release(elem);
6737 
6738         IXMLDOMNode_Release(node2);
6739         IXMLDOMNode_Release(node);
6740     }
6741 
6742     IXMLDOMDocument_Release(doc);
6743 
6744     free_bstrs();
6745 }
6746 
6747 static void test_FormattingXML(void)
6748 {
6749     IXMLDOMDocument *doc;
6750     IXMLDOMElement *pElement;
6751     VARIANT_BOOL bSucc;
6752     HRESULT hr;
6753     BSTR str;
6754     static const CHAR szLinefeedXML[] = "<?xml version=\"1.0\"?>\n<Root>\n\t<Sub val=\"A\" />\n</Root>";
6755     static const CHAR szLinefeedRootXML[] = "<Root>\r\n\t<Sub val=\"A\"/>\r\n</Root>";
6756 
6757     doc = create_document(&IID_IXMLDOMDocument);
6758 
6759     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szLinefeedXML), &bSucc);
6760     ok(hr == S_OK, "ret %08x\n", hr );
6761     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6762 
6763     if(bSucc == VARIANT_TRUE)
6764     {
6765         hr = IXMLDOMDocument_get_documentElement(doc, &pElement);
6766         ok(hr == S_OK, "ret %08x\n", hr );
6767         if(hr == S_OK)
6768         {
6769             hr = IXMLDOMElement_get_xml(pElement, &str);
6770             ok(hr == S_OK, "ret %08x\n", hr );
6771             ok( !lstrcmpW( str, _bstr_(szLinefeedRootXML) ), "incorrect element xml\n");
6772             SysFreeString(str);
6773 
6774             IXMLDOMElement_Release(pElement);
6775         }
6776     }
6777 
6778     IXMLDOMDocument_Release(doc);
6779 
6780     free_bstrs();
6781 }
6782 
6783 typedef struct _nodetypedvalue_t {
6784     const char *name;
6785     VARTYPE type;
6786     const char *value; /* value in string format */
6787 } nodetypedvalue_t;
6788 
6789 static const nodetypedvalue_t get_nodetypedvalue[] = {
6790     { "root/string",    VT_BSTR, "Wine" },
6791     { "root/string2",   VT_BSTR, "String" },
6792     { "root/number",    VT_BSTR, "12.44" },
6793     { "root/number2",   VT_BSTR, "-3.71e3" },
6794     { "root/int",       VT_I4,   "-13" },
6795     { "root/fixed",     VT_CY,   "7322.9371" },
6796     { "root/bool",      VT_BOOL, "-1" },
6797     { "root/datetime",  VT_DATE, "40135.14" },
6798     { "root/datetimetz",VT_DATE, "37813.59" },
6799     { "root/date",      VT_DATE, "665413" },
6800     { "root/time",      VT_DATE, "0.5813889" },
6801     { "root/timetz",    VT_DATE, "1.112512" },
6802     { "root/i1",        VT_I1,   "-13" },
6803     { "root/i2",        VT_I2,   "31915" },
6804     { "root/i4",        VT_I4,   "-312232" },
6805     { "root/ui1",       VT_UI1,  "123" },
6806     { "root/ui2",       VT_UI2,  "48282" },
6807     { "root/ui4",       VT_UI4,  "949281" },
6808     { "root/r4",        VT_R4,   "213124" },
6809     { "root/r8",        VT_R8,   "0.412" },
6810     { "root/float",     VT_R8,   "41221.421" },
6811     { "root/uuid",      VT_BSTR, "333C7BC4-460F-11D0-BC04-0080C7055a83" },
6812     { "root/binbase64", VT_ARRAY|VT_UI1, "base64 test" },
6813     { "root/binbase64_1", VT_ARRAY|VT_UI1, "base64 test" },
6814     { "root/binbase64_2", VT_ARRAY|VT_UI1, "base64 test" },
6815     { 0 }
6816 };
6817 
6818 static void test_nodeTypedValue(void)
6819 {
6820     const nodetypedvalue_t *entry = get_nodetypedvalue;
6821     IXMLDOMDocumentType *doctype, *doctype2;
6822     IXMLDOMProcessingInstruction *pi;
6823     IXMLDOMDocumentFragment *frag;
6824     IXMLDOMDocument *doc, *doc2;
6825     IXMLDOMCDATASection *cdata;
6826     IXMLDOMComment *comment;
6827     IXMLDOMNode *node;
6828     VARIANT_BOOL b;
6829     VARIANT value;
6830     HRESULT hr;
6831 
6832     doc = create_document(&IID_IXMLDOMDocument);
6833 
6834     b = VARIANT_FALSE;
6835     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &b);
6836     ok(hr == S_OK, "ret %08x\n", hr );
6837     ok(b == VARIANT_TRUE, "got %d\n", b);
6838 
6839     hr = IXMLDOMDocument_get_nodeValue(doc, NULL);
6840     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6841 
6842     V_VT(&value) = VT_BSTR;
6843     V_BSTR(&value) = NULL;
6844     hr = IXMLDOMDocument_get_nodeValue(doc, &value);
6845     ok(hr == S_FALSE, "ret %08x\n", hr );
6846     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6847 
6848     hr = IXMLDOMDocument_get_nodeTypedValue(doc, NULL);
6849     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6850 
6851     V_VT(&value) = VT_EMPTY;
6852     hr = IXMLDOMDocument_get_nodeTypedValue(doc, &value);
6853     ok(hr == S_FALSE, "ret %08x\n", hr );
6854     ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6855 
6856     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/string"), &node);
6857     ok(hr == S_OK, "ret %08x\n", hr );
6858 
6859     V_VT(&value) = VT_BSTR;
6860     V_BSTR(&value) = NULL;
6861     hr = IXMLDOMNode_get_nodeValue(node, &value);
6862     ok(hr == S_FALSE, "ret %08x\n", hr );
6863     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6864 
6865     hr = IXMLDOMNode_get_nodeTypedValue(node, NULL);
6866     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6867 
6868     IXMLDOMNode_Release(node);
6869 
6870     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/binhex"), &node);
6871     ok(hr == S_OK, "ret %08x\n", hr );
6872     {
6873         BYTE bytes[] = {0xff,0xfc,0xa0,0x12,0x00,0x3c};
6874 
6875         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6876         ok(hr == S_OK, "ret %08x\n", hr );
6877         ok(V_VT(&value) == (VT_ARRAY|VT_UI1), "incorrect type\n");
6878         ok(V_ARRAY(&value)->rgsabound[0].cElements == 6, "incorrect array size\n");
6879         if(V_ARRAY(&value)->rgsabound[0].cElements == 6)
6880             ok(!memcmp(bytes, V_ARRAY(&value)->pvData, sizeof(bytes)), "incorrect value\n");
6881         VariantClear(&value);
6882         IXMLDOMNode_Release(node);
6883     }
6884 
6885     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("foo"), _bstr_("value"), &pi);
6886     ok(hr == S_OK, "ret %08x\n", hr );
6887     {
6888         V_VT(&value) = VT_NULL;
6889         V_BSTR(&value) = (void*)0xdeadbeef;
6890         hr = IXMLDOMProcessingInstruction_get_nodeTypedValue(pi, &value);
6891         ok(hr == S_OK, "ret %08x\n", hr );
6892         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6893         ok(!lstrcmpW(V_BSTR(&value), _bstr_("value")), "got wrong value\n");
6894         IXMLDOMProcessingInstruction_Release(pi);
6895         VariantClear(&value);
6896     }
6897 
6898     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("[1]*2=3; &gee that's not right!"), &cdata);
6899     ok(hr == S_OK, "ret %08x\n", hr );
6900     {
6901         V_VT(&value) = VT_NULL;
6902         V_BSTR(&value) = (void*)0xdeadbeef;
6903         hr = IXMLDOMCDATASection_get_nodeTypedValue(cdata, &value);
6904         ok(hr == S_OK, "ret %08x\n", hr );
6905         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6906         ok(!lstrcmpW(V_BSTR(&value), _bstr_("[1]*2=3; &gee that's not right!")), "got wrong value\n");
6907         IXMLDOMCDATASection_Release(cdata);
6908         VariantClear(&value);
6909     }
6910 
6911     hr = IXMLDOMDocument_createComment(doc, _bstr_("comment"), &comment);
6912     ok(hr == S_OK, "ret %08x\n", hr );
6913     {
6914         V_VT(&value) = VT_NULL;
6915         V_BSTR(&value) = (void*)0xdeadbeef;
6916         hr = IXMLDOMComment_get_nodeTypedValue(comment, &value);
6917         ok(hr == S_OK, "ret %08x\n", hr );
6918         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6919         ok(!lstrcmpW(V_BSTR(&value), _bstr_("comment")), "got wrong value\n");
6920         IXMLDOMComment_Release(comment);
6921         VariantClear(&value);
6922     }
6923 
6924     hr = IXMLDOMDocument_createDocumentFragment(doc, &frag);
6925     ok(hr == S_OK, "ret %08x\n", hr );
6926     {
6927         V_VT(&value) = VT_EMPTY;
6928         hr = IXMLDOMDocumentFragment_get_nodeTypedValue(frag, &value);
6929         ok(hr == S_FALSE, "ret %08x\n", hr );
6930         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6931         IXMLDOMDocumentFragment_Release(frag);
6932     }
6933 
6934     doc2 = create_document(&IID_IXMLDOMDocument);
6935 
6936     b = VARIANT_FALSE;
6937     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szEmailXML), &b);
6938     ok(hr == S_OK, "ret %08x\n", hr );
6939     ok(b == VARIANT_TRUE, "got %d\n", b);
6940 
6941     EXPECT_REF(doc2, 1);
6942 
6943     hr = IXMLDOMDocument_get_doctype(doc2, &doctype);
6944     ok(hr == S_OK, "ret %08x\n", hr );
6945 
6946     EXPECT_REF(doc2, 1);
6947     todo_wine EXPECT_REF(doctype, 2);
6948 
6949     {
6950         V_VT(&value) = VT_EMPTY;
6951         hr = IXMLDOMDocumentType_get_nodeTypedValue(doctype, &value);
6952         ok(hr == S_FALSE, "ret %08x\n", hr );
6953         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6954     }
6955 
6956     hr = IXMLDOMDocument_get_doctype(doc2, &doctype2);
6957     ok(hr == S_OK, "ret %08x\n", hr );
6958     ok(doctype != doctype2, "got %p, was %p\n", doctype2, doctype);
6959 
6960     IXMLDOMDocumentType_Release(doctype2);
6961     IXMLDOMDocumentType_Release(doctype);
6962 
6963     IXMLDOMDocument_Release(doc2);
6964 
6965     while (entry->name)
6966     {
6967         hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_(entry->name), &node);
6968         ok(hr == S_OK, "ret %08x\n", hr );
6969 
6970         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6971         ok(hr == S_OK, "ret %08x\n", hr );
6972         ok(V_VT(&value) == entry->type, "incorrect type, expected %d, got %d\n", entry->type, V_VT(&value));
6973 
6974         if (entry->type == (VT_ARRAY|VT_UI1))
6975         {
6976             ok(V_ARRAY(&value)->rgsabound[0].cElements == strlen(entry->value),
6977                "incorrect array size %d\n", V_ARRAY(&value)->rgsabound[0].cElements);
6978         }
6979 
6980         if (entry->type != VT_BSTR)
6981         {
6982            if (entry->type == VT_DATE ||
6983                entry->type == VT_R8 ||
6984                entry->type == VT_CY)
6985            {
6986                if (entry->type == VT_DATE)
6987                {
6988                    hr = VariantChangeType(&value, &value, 0, VT_R4);
6989                    ok(hr == S_OK, "ret %08x\n", hr );
6990                }
6991                hr = VariantChangeTypeEx(&value, &value,
6992                                         MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT),
6993                                         VARIANT_NOUSEROVERRIDE, VT_BSTR);
6994                ok(hr == S_OK, "ret %08x\n", hr );
6995            }
6996            else
6997            {
6998                hr = VariantChangeType(&value, &value, 0, VT_BSTR);
6999                ok(hr == S_OK, "ret %08x\n", hr );
7000            }
7001 
7002            /* for byte array from VT_ARRAY|VT_UI1 it's not a WCHAR buffer */
7003            if (entry->type == (VT_ARRAY|VT_UI1))
7004            {
7005                ok(!memcmp( V_BSTR(&value), entry->value, strlen(entry->value)),
7006                   "expected %s\n", entry->value);
7007            }
7008            else
7009                ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
7010                   "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
7011         }
7012         else
7013            ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
7014                "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
7015 
7016         VariantClear( &value );
7017         IXMLDOMNode_Release(node);
7018 
7019         entry++;
7020     }
7021 
7022     IXMLDOMDocument_Release(doc);
7023     free_bstrs();
7024 }
7025 
7026 static void test_TransformWithLoadingLocalFile(void)
7027 {
7028     IXMLDOMDocument *doc;
7029     IXMLDOMDocument *xsl;
7030     IXMLDOMNode *pNode;
7031     VARIANT_BOOL bSucc;
7032     HRESULT hr;
7033     HANDLE file;
7034     DWORD dwWritten;
7035     char lpPathBuffer[MAX_PATH];
7036     int i;
7037 
7038     /* Create a Temp File. */
7039     GetTempPathA(MAX_PATH, lpPathBuffer);
7040     strcat(lpPathBuffer, "customers.xml" );
7041 
7042     file = CreateFileA(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
7043     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
7044     if(file == INVALID_HANDLE_VALUE)
7045         return;
7046 
7047     WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL);
7048     CloseHandle(file);
7049 
7050     /* Correct path to not include an escape character. */
7051     for(i=0; i < strlen(lpPathBuffer); i++)
7052     {
7053         if(lpPathBuffer[i] == '\\')
7054             lpPathBuffer[i] = '/';
7055     }
7056 
7057     doc = create_document(&IID_IXMLDOMDocument);
7058     xsl = create_document(&IID_IXMLDOMDocument);
7059 
7060     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &bSucc);
7061     ok(hr == S_OK, "ret %08x\n", hr );
7062     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7063     if(bSucc == VARIANT_TRUE)
7064     {
7065         BSTR sXSL;
7066         BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1);
7067         BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2);
7068         BSTR sFileName = _bstr_(lpPathBuffer);
7069         int nLength = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1;
7070 
7071         sXSL = SysAllocStringLen(NULL, nLength);
7072         lstrcpyW(sXSL, sPart1);
7073         lstrcatW(sXSL, sFileName);
7074         lstrcatW(sXSL, sPart2);
7075 
7076         hr = IXMLDOMDocument_loadXML(xsl, sXSL, &bSucc);
7077         ok(hr == S_OK, "ret %08x\n", hr );
7078         ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7079         if(bSucc == VARIANT_TRUE)
7080         {
7081             BSTR sResult;
7082 
7083             hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (void**)&pNode );
7084             ok(hr == S_OK, "ret %08x\n", hr );
7085             if(hr == S_OK)
7086             {
7087                 /* This will load the temp file via the XSL */
7088                 hr = IXMLDOMDocument_transformNode(doc, pNode, &sResult);
7089                 ok(hr == S_OK, "ret %08x\n", hr );
7090                 if(hr == S_OK)
7091                 {
7092                     ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n");
7093                     SysFreeString(sResult);
7094                 }
7095 
7096                 IXMLDOMNode_Release(pNode);
7097             }
7098         }
7099 
7100         SysFreeString(sXSL);
7101     }
7102 
7103     IXMLDOMDocument_Release(doc);
7104     IXMLDOMDocument_Release(xsl);
7105 
7106     DeleteFileA(lpPathBuffer);
7107     free_bstrs();
7108 }
7109 
7110 static void test_put_nodeValue(void)
7111 {
7112     static const WCHAR jeevesW[] = {'J','e','e','v','e','s',' ','&',' ','W','o','o','s','t','e','r',0};
7113     IXMLDOMDocument *doc;
7114     IXMLDOMText *text;
7115     IXMLDOMEntityReference *entityref;
7116     IXMLDOMAttribute *attr;
7117     IXMLDOMNode *node;
7118     HRESULT hr;
7119     VARIANT data, type;
7120 
7121     doc = create_document(&IID_IXMLDOMDocument);
7122 
7123     /* test for unsupported types */
7124     /* NODE_DOCUMENT */
7125     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&node);
7126     ok(hr == S_OK, "ret %08x\n", hr );
7127     V_VT(&data) = VT_BSTR;
7128     V_BSTR(&data) = _bstr_("one two three");
7129     hr = IXMLDOMNode_put_nodeValue(node, data);
7130     ok(hr == E_FAIL, "ret %08x\n", hr );
7131     IXMLDOMNode_Release(node);
7132 
7133     /* NODE_DOCUMENT_FRAGMENT */
7134     V_VT(&type) = VT_I1;
7135     V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
7136     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7137     ok(hr == S_OK, "ret %08x\n", hr );
7138     V_VT(&data) = VT_BSTR;
7139     V_BSTR(&data) = _bstr_("one two three");
7140     hr = IXMLDOMNode_put_nodeValue(node, data);
7141     ok(hr == E_FAIL, "ret %08x\n", hr );
7142     IXMLDOMNode_Release(node);
7143 
7144     /* NODE_ELEMENT */
7145     V_VT(&type) = VT_I1;
7146     V_I1(&type) = NODE_ELEMENT;
7147     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7148     ok(hr == S_OK, "ret %08x\n", hr );
7149     V_VT(&data) = VT_BSTR;
7150     V_BSTR(&data) = _bstr_("one two three");
7151     hr = IXMLDOMNode_put_nodeValue(node, data);
7152     ok(hr == E_FAIL, "ret %08x\n", hr );
7153     IXMLDOMNode_Release(node);
7154 
7155     /* NODE_ENTITY_REFERENCE */
7156     hr = IXMLDOMDocument_createEntityReference(doc, _bstr_("ref"), &entityref);
7157     ok(hr == S_OK, "ret %08x\n", hr );
7158 
7159     V_VT(&data) = VT_BSTR;
7160     V_BSTR(&data) = _bstr_("one two three");
7161     hr = IXMLDOMEntityReference_put_nodeValue(entityref, data);
7162     ok(hr == E_FAIL, "ret %08x\n", hr );
7163 
7164     hr = IXMLDOMEntityReference_QueryInterface(entityref, &IID_IXMLDOMNode, (void**)&node);
7165     ok(hr == S_OK, "ret %08x\n", hr );
7166     V_VT(&data) = VT_BSTR;
7167     V_BSTR(&data) = _bstr_("one two three");
7168     hr = IXMLDOMNode_put_nodeValue(node, data);
7169     ok(hr == E_FAIL, "ret %08x\n", hr );
7170     IXMLDOMNode_Release(node);
7171     IXMLDOMEntityReference_Release(entityref);
7172 
7173     /* supported types */
7174     hr = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &text);
7175     ok(hr == S_OK, "ret %08x\n", hr );
7176     V_VT(&data) = VT_BSTR;
7177     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7178     hr = IXMLDOMText_put_nodeValue(text, data);
7179     ok(hr == S_OK, "ret %08x\n", hr );
7180     IXMLDOMText_Release(text);
7181 
7182     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
7183     ok(hr == S_OK, "ret %08x\n", hr );
7184     V_VT(&data) = VT_BSTR;
7185     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7186     hr = IXMLDOMAttribute_put_nodeValue(attr, data);
7187     ok(hr == S_OK, "ret %08x\n", hr );
7188     hr = IXMLDOMAttribute_get_nodeValue(attr, &data);
7189     ok(hr == S_OK, "ret %08x\n", hr );
7190     ok(memcmp(V_BSTR(&data), jeevesW, sizeof(jeevesW)) == 0, "got %s\n",
7191         wine_dbgstr_w(V_BSTR(&data)));
7192     VariantClear(&data);
7193     IXMLDOMAttribute_Release(attr);
7194 
7195     free_bstrs();
7196 
7197     IXMLDOMDocument_Release(doc);
7198 }
7199 
7200 static void test_IObjectSafety(void)
7201 {
7202     IXMLDOMDocument *doc;
7203     IObjectSafety *safety;
7204     HRESULT hr;
7205 
7206     doc = create_document(&IID_IXMLDOMDocument);
7207 
7208     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IObjectSafety, (void**)&safety);
7209     ok(hr == S_OK, "ret %08x\n", hr );
7210 
7211     test_IObjectSafety_common(safety);
7212 
7213     IObjectSafety_Release(safety);
7214     IXMLDOMDocument_Release(doc);
7215 
7216     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
7217         &IID_IObjectSafety, (void**)&safety);
7218     ok(hr == S_OK, "Could not create XMLHTTPRequest instance: %08x\n", hr);
7219 
7220     test_IObjectSafety_common(safety);
7221 
7222     IObjectSafety_Release(safety);
7223 
7224 }
7225 
7226 typedef struct _property_test_t {
7227     const GUID *guid;
7228     const char *clsid;
7229     const char *property;
7230     const char *value;
7231 } property_test_t;
7232 
7233 static const property_test_t properties_test_data[] = {
7234     { &CLSID_DOMDocument,  "CLSID_DOMDocument" , "SelectionLanguage", "XSLPattern" },
7235     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2" , "SelectionLanguage", "XSLPattern" },
7236     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "SelectionLanguage", "XSLPattern" },
7237     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "SelectionLanguage", "XPath" },
7238     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "SelectionLanguage", "XPath" },
7239     { 0 }
7240 };
7241 
7242 static void test_default_properties(void)
7243 {
7244     const property_test_t *entry = properties_test_data;
7245 
7246     while (entry->guid)
7247     {
7248         IXMLDOMDocument2 *doc;
7249         VARIANT var;
7250         HRESULT hr;
7251 
7252         if (!is_clsid_supported(entry->guid, &IID_IXMLDOMDocument2))
7253         {
7254             entry++;
7255             continue;
7256         }
7257 
7258         hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
7259         ok(hr == S_OK, "got 0x%08x\n", hr);
7260 
7261         hr = IXMLDOMDocument2_getProperty(doc, _bstr_(entry->property), &var);
7262         ok(hr == S_OK, "got 0x%08x\n", hr);
7263         ok(lstrcmpW(V_BSTR(&var), _bstr_(entry->value)) == 0, "expected %s, for %s\n",
7264            entry->value, entry->clsid);
7265         VariantClear(&var);
7266 
7267         IXMLDOMDocument2_Release(doc);
7268 
7269         entry++;
7270     }
7271 }
7272 
7273 typedef struct {
7274     const char *query;
7275     const char *list;
7276     BOOL todo;
7277 } xslpattern_test_t;
7278 
7279 static const xslpattern_test_t xslpattern_test[] = {
7280     { "root//elem[0]", "E1.E2.D1" },
7281     { "root//elem[index()=1]", "E2.E2.D1" },
7282     { "root//elem[index() $eq$ 1]", "E2.E2.D1" },
7283     { "root//elem[end()]", "E4.E2.D1" },
7284     { "root//elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7285     { "root//elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7286     { "root//elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7287     { "root//elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7288     { "root//elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7289     { "root//elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7290     { "root//elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7291     { "root//elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7292     { "root//elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7293     { "root//elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7294     { "root//elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7295     { "root//elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7296     { "root//elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7297     { "root//elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7298     { "root//elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7299     { "root//elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7300     { "root//elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7301     { "root//elem[$any$ *='B2 field']", "E2.E2.D1" },
7302     { "root//elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7303     { "root//elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7304     { "root//elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7305     { "root//elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7306     { "root//elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7307     { "root//elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7308     { "root//elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7309     { "root/elem[0]", "E1.E2.D1" },
7310     { "root/elem[index()=1]", "E2.E2.D1" },
7311     { "root/elem[index() $eq$ 1]", "E2.E2.D1" },
7312     { "root/elem[end()]", "E4.E2.D1" },
7313     { "root/elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7314     { "root/elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7315     { "root/elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7316     { "root/elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7317     { "root/elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7318     { "root/elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7319     { "root/elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7320     { "root/elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7321     { "root/elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7322     { "root/elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7323     { "root/elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7324     { "root/elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7325     { "root/elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7326     { "root/elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7327     { "root/elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7328     { "root/elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7329     { "root/elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7330     { "root/elem[$any$ *='B2 field']", "E2.E2.D1" },
7331     { "root/elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7332     { "root/elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7333     { "root/elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7334     { "root/elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7335     { "root/elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7336     { "root/elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7337     { "root/elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7338     { "root/elem[d]", "E1.E2.D1 E2.E2.D1 E4.E2.D1" },
7339     { "root/elem[@*]", "E2.E2.D1 E3.E2.D1", TRUE },
7340     { NULL }
7341 };
7342 
7343 static const xslpattern_test_t xslpattern_test_no_ns[] = {
7344     /* prefixes don't need to be registered, you may use them as they are in the doc */
7345     { "//bar:x", "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1" },
7346     /* prefixes must be explicitly specified in the name */
7347     { "//foo:elem", "" },
7348     { "//foo:c", "E3.E4.E2.D1" },
7349     { NULL }
7350 };
7351 
7352 static const xslpattern_test_t xslpattern_test_func[] = {
7353     { "attribute()", "" },
7354     { "attribute('depth')", "" },
7355     { "root/attribute('depth')", "A'depth'.E3.D1" },
7356     { "//x/attribute()", "A'id'.E3.E3.D1 A'depth'.E3.E3.D1" },
7357     { "//x//attribute(id)", NULL },
7358     { "//x//attribute('id')", "A'id'.E3.E3.D1 A'id'.E4.E3.E3.D1 A'id'.E5.E3.E3.D1 A'id'.E6.E3.E3.D1" },
7359     { "comment()", "C2.D1" },
7360     { "//comment()", "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1" },
7361     { "element()", "E3.D1" },
7362     { "root/y/element()", "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1" },
7363     { "//element(a)", NULL },
7364     { "//element('a')", "E4.E3.E3.D1 E4.E4.E3.D1" },
7365     { "node()", "P1.D1 C2.D1 E3.D1" },
7366     { "//x/node()", "P1.E3.E3.D1 C2.E3.E3.D1 T3.E3.E3.D1 E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
7367     { "//x/node()[nodeType()=1]", "E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
7368     { "//x/node()[nodeType()=3]", "T3.E3.E3.D1" },
7369     { "//x/node()[nodeType()=7]", "P1.E3.E3.D1" },
7370     { "//x/node()[nodeType()=8]", "C2.E3.E3.D1" },
7371     { "pi()", "P1.D1" },
7372     { "//y/pi()", "P1.E4.E3.D1" },
7373     { "root/textnode()", "T2.E3.D1" },
7374     { "root/element()/textnode()", "T3.E3.E3.D1 T3.E4.E3.D1" },
7375     { NULL }
7376 };
7377 
7378 static void test_XSLPattern(void)
7379 {
7380     const xslpattern_test_t *ptr = xslpattern_test;
7381     IXMLDOMDocument2 *doc;
7382     IXMLDOMNodeList *list;
7383     VARIANT_BOOL b;
7384     HRESULT hr;
7385     LONG len;
7386 
7387     doc = create_document(&IID_IXMLDOMDocument2);
7388 
7389     b = VARIANT_FALSE;
7390     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
7391     EXPECT_HR(hr, S_OK);
7392     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7393 
7394     /* switch to XSLPattern */
7395     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern"));
7396     EXPECT_HR(hr, S_OK);
7397 
7398     /* XPath doesn't select elements with non-null default namespace with unqualified selectors, XSLPattern does */
7399     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem/c"), &list);
7400     EXPECT_HR(hr, S_OK);
7401 
7402     len = 0;
7403     hr = IXMLDOMNodeList_get_length(list, &len);
7404     EXPECT_HR(hr, S_OK);
7405     /* should select <elem><c> and <elem xmlns='...'><c> but not <elem><foo:c> */
7406     ok(len == 3, "expected 3 entries in list, got %d\n", len);
7407     IXMLDOMNodeList_Release(list);
7408 
7409     while (ptr->query)
7410     {
7411         list = NULL;
7412         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7413         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7414         len = 0;
7415         hr = IXMLDOMNodeList_get_length(list, &len);
7416         ok(len != 0, "query=%s, empty list\n", ptr->query);
7417         if (len) {
7418             if (ptr->todo) {
7419                 char *str = list_to_string(list);
7420             todo_wine
7421                 ok(!strcmp(str, ptr->list), "Invalid node list: %s, expected %s\n", str, ptr->list);
7422                 IXMLDOMNodeList_Release(list);
7423             }
7424             else
7425                 expect_list_and_release(list, ptr->list);
7426         }
7427 
7428         ptr++;
7429     }
7430 
7431     /* namespace handling */
7432     /* no registered namespaces */
7433     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_(""));
7434     EXPECT_HR(hr, S_OK);
7435 
7436     ptr = xslpattern_test_no_ns;
7437     while (ptr->query)
7438     {
7439         list = NULL;
7440         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7441         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7442 
7443         if (*ptr->list)
7444         {
7445             len = 0;
7446             hr = IXMLDOMNodeList_get_length(list, &len);
7447             EXPECT_HR(hr, S_OK);
7448             ok(len != 0, "query=%s, empty list\n", ptr->query);
7449         }
7450         else
7451         {
7452             len = 1;
7453             hr = IXMLDOMNodeList_get_length(list, &len);
7454             EXPECT_HR(hr, S_OK);
7455             ok(len == 0, "query=%s, empty list\n", ptr->query);
7456         }
7457         if (len)
7458             expect_list_and_release(list, ptr->list);
7459 
7460         ptr++;
7461     }
7462 
7463     /* explicitly register prefix foo */
7464     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
7465 
7466     /* now we get the same behavior as XPath */
7467     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7468     EXPECT_HR(hr, S_OK);
7469     len = 0;
7470     hr = IXMLDOMNodeList_get_length(list, &len);
7471     EXPECT_HR(hr, S_OK);
7472     ok(len != 0, "expected filled list\n");
7473     if (len)
7474         expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
7475 
7476     /* set prefix foo to some nonexistent namespace */
7477     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:nonexistent-foo'"));
7478     EXPECT_HR(hr, S_OK);
7479 
7480     /* the registered prefix takes precedence */
7481     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7482     EXPECT_HR(hr, S_OK);
7483     len = 0;
7484     hr = IXMLDOMNodeList_get_length(list, &len);
7485     EXPECT_HR(hr, S_OK);
7486     ok(len == 0, "expected empty list\n");
7487     IXMLDOMNodeList_Release(list);
7488 
7489     IXMLDOMDocument2_Release(doc);
7490 
7491     doc = create_document(&IID_IXMLDOMDocument2);
7492 
7493     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szNodeTypesXML), &b);
7494     EXPECT_HR(hr, S_OK);
7495     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7496 
7497     ptr = xslpattern_test_func;
7498     while (ptr->query)
7499     {
7500         list = NULL;
7501         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7502         if (ptr->list)
7503         {
7504             ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7505             len = 0;
7506             hr = IXMLDOMNodeList_get_length(list, &len);
7507             ok(hr == S_OK, "Failed to get list length, hr %#x.\n", hr);
7508             if (*ptr->list)
7509             {
7510                 ok(len != 0, "query=%s, empty list\n", ptr->query);
7511                 if (len)
7512                     expect_list_and_release(list, ptr->list);
7513             }
7514             else
7515                 ok(len == 0, "query=%s, filled list\n", ptr->query);
7516         }
7517         else
7518             ok(hr == E_FAIL, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7519 
7520         ptr++;
7521     }
7522 
7523     IXMLDOMDocument2_Release(doc);
7524     free_bstrs();
7525 }
7526 
7527 static void test_splitText(void)
7528 {
7529     IXMLDOMCDATASection *cdata;
7530     IXMLDOMElement *root;
7531     IXMLDOMDocument *doc;
7532     IXMLDOMText *text, *text2;
7533     IXMLDOMNode *node;
7534     VARIANT var;
7535     VARIANT_BOOL success;
7536     LONG length;
7537     HRESULT hr;
7538 
7539     doc = create_document(&IID_IXMLDOMDocument);
7540 
7541     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<root></root>"), &success);
7542     ok(hr == S_OK, "got 0x%08x\n", hr);
7543 
7544     hr = IXMLDOMDocument_get_documentElement(doc, &root);
7545     ok(hr == S_OK, "got 0x%08x\n", hr);
7546 
7547     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("beautiful plumage"), &cdata);
7548     ok(hr == S_OK, "got 0x%08x\n", hr);
7549 
7550     V_VT(&var) = VT_EMPTY;
7551     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)cdata, NULL);
7552     ok(hr == S_OK, "got 0x%08x\n", hr);
7553 
7554     length = 0;
7555     hr = IXMLDOMCDATASection_get_length(cdata, &length);
7556     ok(hr == S_OK, "got 0x%08x\n", hr);
7557     ok(length > 0, "got %d\n", length);
7558 
7559     hr = IXMLDOMCDATASection_splitText(cdata, 0, NULL);
7560     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7561 
7562     text = (void*)0xdeadbeef;
7563     /* negative offset */
7564     hr = IXMLDOMCDATASection_splitText(cdata, -1, &text);
7565     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7566     ok(text == (void*)0xdeadbeef, "got %p\n", text);
7567 
7568     text = (void*)0xdeadbeef;
7569     /* offset outside data */
7570     hr = IXMLDOMCDATASection_splitText(cdata, length + 1, &text);
7571     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7572     ok(text == 0, "got %p\n", text);
7573 
7574     text = (void*)0xdeadbeef;
7575     /* offset outside data */
7576     hr = IXMLDOMCDATASection_splitText(cdata, length, &text);
7577     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7578     ok(text == 0, "got %p\n", text);
7579 
7580     /* no empty node created */
7581     node = (void*)0xdeadbeef;
7582     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7583     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7584     ok(node == 0, "got %p\n", text);
7585 
7586     hr = IXMLDOMCDATASection_splitText(cdata, 10, &text);
7587     ok(hr == S_OK, "got 0x%08x\n", hr);
7588 
7589     length = 0;
7590     hr = IXMLDOMText_get_length(text, &length);
7591     ok(hr == S_OK, "got 0x%08x\n", hr);
7592     ok(length == 7, "got %d\n", length);
7593 
7594     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7595     ok(hr == S_OK, "got 0x%08x\n", hr);
7596     IXMLDOMNode_Release(node);
7597 
7598     /* split new text node */
7599     hr = IXMLDOMText_get_length(text, &length);
7600     ok(hr == S_OK, "got 0x%08x\n", hr);
7601 
7602     node = (void*)0xdeadbeef;
7603     hr = IXMLDOMText_get_nextSibling(text, &node);
7604     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7605     ok(node == 0, "got %p\n", text);
7606 
7607     hr = IXMLDOMText_splitText(text, 0, NULL);
7608     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7609 
7610     text2 = (void*)0xdeadbeef;
7611     /* negative offset */
7612     hr = IXMLDOMText_splitText(text, -1, &text2);
7613     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7614     ok(text2 == (void*)0xdeadbeef, "got %p\n", text2);
7615 
7616     text2 = (void*)0xdeadbeef;
7617     /* offset outside data */
7618     hr = IXMLDOMText_splitText(text, length + 1, &text2);
7619     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7620     ok(text2 == 0, "got %p\n", text2);
7621 
7622     text2 = (void*)0xdeadbeef;
7623     /* offset outside data */
7624     hr = IXMLDOMText_splitText(text, length, &text2);
7625     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7626     ok(text2 == 0, "got %p\n", text);
7627 
7628     text2 = 0;
7629     hr = IXMLDOMText_splitText(text, 4, &text2);
7630     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7631     if (text2) IXMLDOMText_Release(text2);
7632 
7633     node = 0;
7634     hr = IXMLDOMText_get_nextSibling(text, &node);
7635     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7636     if (node) IXMLDOMNode_Release(node);
7637 
7638     IXMLDOMText_Release(text);
7639     IXMLDOMElement_Release(root);
7640     IXMLDOMCDATASection_Release(cdata);
7641     free_bstrs();
7642 }
7643 
7644 typedef struct {
7645     const char *name;
7646     const char *uri;
7647     HRESULT hr;
7648 } ns_item_t;
7649 
7650 /* default_ns_doc used */
7651 static const ns_item_t qualified_item_tests[] = {
7652     { "xml:lang", NULL, S_FALSE },
7653     { "xml:lang", "http://www.w3.org/XML/1998/namespace", S_FALSE },
7654     { "lang", "http://www.w3.org/XML/1998/namespace", S_OK },
7655     { "ns:b", NULL, S_FALSE },
7656     { "ns:b", "nshref", S_FALSE },
7657     { "b", "nshref", S_OK },
7658     { "d", NULL, S_OK },
7659     { NULL }
7660 };
7661 
7662 static const ns_item_t named_item_tests[] = {
7663     { "xml:lang", NULL, S_OK },
7664     { "lang", NULL, S_FALSE },
7665     { "ns:b", NULL, S_OK },
7666     { "b", NULL, S_FALSE },
7667     { "d", NULL, S_OK },
7668     { NULL }
7669 };
7670 
7671 static void test_getQualifiedItem(void)
7672 {
7673     IXMLDOMNode *pr_node, *node;
7674     IXMLDOMNodeList *root_list;
7675     IXMLDOMNamedNodeMap *map;
7676     IXMLDOMElement *element;
7677     const ns_item_t* ptr;
7678     IXMLDOMDocument *doc;
7679     VARIANT_BOOL b;
7680     HRESULT hr;
7681     LONG len;
7682 
7683     doc = create_document(&IID_IXMLDOMDocument);
7684 
7685     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7686     EXPECT_HR(hr, S_OK);
7687     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7688 
7689     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7690     EXPECT_HR(hr, S_OK);
7691 
7692     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7693     EXPECT_HR(hr, S_OK);
7694 
7695     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7696     EXPECT_HR(hr, S_OK);
7697     IXMLDOMNodeList_Release(root_list);
7698 
7699     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7700     EXPECT_HR(hr, S_OK);
7701     IXMLDOMNode_Release(pr_node);
7702 
7703     len = 0;
7704     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7705     EXPECT_HR(hr, S_OK);
7706     ok( len == 3, "length %d\n", len);
7707 
7708     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, NULL);
7709     EXPECT_HR(hr, E_INVALIDARG);
7710 
7711     node = (void*)0xdeadbeef;
7712     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, &node);
7713     EXPECT_HR(hr, E_INVALIDARG);
7714     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7715 
7716     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, NULL);
7717     EXPECT_HR(hr, E_INVALIDARG);
7718 
7719     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, &node);
7720     EXPECT_HR(hr, S_OK);
7721 
7722     IXMLDOMNode_Release(node);
7723     IXMLDOMNamedNodeMap_Release(map);
7724     IXMLDOMElement_Release(element);
7725 
7726     hr = IXMLDOMDocument_loadXML(doc, _bstr_(default_ns_doc), &b);
7727     EXPECT_HR(hr, S_OK);
7728 
7729     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
7730     EXPECT_HR(hr, S_OK);
7731 
7732     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
7733     EXPECT_HR(hr, S_OK);
7734     IXMLDOMNode_Release(node);
7735 
7736     hr = IXMLDOMElement_get_attributes(element, &map);
7737     EXPECT_HR(hr, S_OK);
7738 
7739     ptr = qualified_item_tests;
7740     while (ptr->name)
7741     {
7742        node = (void*)0xdeadbeef;
7743        hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
7744        ok(hr == ptr->hr, "%s, %s: got 0x%08x, expected 0x%08x\n", ptr->name, ptr->uri, hr, ptr->hr);
7745        if (hr == S_OK)
7746            IXMLDOMNode_Release(node);
7747        else
7748            ok(node == NULL, "%s, %s: got %p\n", ptr->name, ptr->uri, node);
7749        ptr++;
7750     }
7751 
7752     ptr = named_item_tests;
7753     while (ptr->name)
7754     {
7755        node = (void*)0xdeadbeef;
7756        hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_(ptr->name), &node);
7757        ok(hr == ptr->hr, "%s: got 0x%08x, expected 0x%08x\n", ptr->name, hr, ptr->hr);
7758        if (hr == S_OK)
7759            IXMLDOMNode_Release(node);
7760        else
7761            ok(node == NULL, "%s: got %p\n", ptr->name, node);
7762        ptr++;
7763     }
7764 
7765     IXMLDOMNamedNodeMap_Release(map);
7766 
7767     IXMLDOMElement_Release(element);
7768     IXMLDOMDocument_Release(doc);
7769     free_bstrs();
7770 }
7771 
7772 static void test_removeQualifiedItem(void)
7773 {
7774     IXMLDOMDocument *doc;
7775     IXMLDOMElement *element;
7776     IXMLDOMNode *pr_node, *node;
7777     IXMLDOMNodeList *root_list;
7778     IXMLDOMNamedNodeMap *map;
7779     VARIANT_BOOL b;
7780     LONG len;
7781     HRESULT hr;
7782 
7783     doc = create_document(&IID_IXMLDOMDocument);
7784 
7785     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7786     ok( hr == S_OK, "loadXML failed\n");
7787     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7788 
7789     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7790     ok( hr == S_OK, "ret %08x\n", hr);
7791 
7792     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7793     ok( hr == S_OK, "ret %08x\n", hr);
7794 
7795     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7796     ok( hr == S_OK, "ret %08x\n", hr);
7797     IXMLDOMNodeList_Release(root_list);
7798 
7799     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7800     ok( hr == S_OK, "ret %08x\n", hr);
7801     IXMLDOMNode_Release(pr_node);
7802 
7803     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7804     ok( hr == S_OK, "ret %08x\n", hr);
7805     ok( len == 3, "length %d\n", len);
7806 
7807     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, NULL);
7808     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7809 
7810     node = (void*)0xdeadbeef;
7811     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, &node);
7812     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7813     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7814 
7815     /* out pointer is optional */
7816     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7817     ok( hr == S_OK, "ret %08x\n", hr);
7818 
7819     /* already removed */
7820     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7821     ok( hr == S_FALSE, "ret %08x\n", hr);
7822 
7823     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("vr"), NULL, &node);
7824     ok( hr == S_OK, "ret %08x\n", hr);
7825     IXMLDOMNode_Release(node);
7826 
7827     IXMLDOMNamedNodeMap_Release( map );
7828     IXMLDOMElement_Release( element );
7829     IXMLDOMDocument_Release( doc );
7830     free_bstrs();
7831 }
7832 
7833 #define check_default_props(doc) _check_default_props(__LINE__, doc)
7834 static inline void _check_default_props(int line, IXMLDOMDocument2* doc)
7835 {
7836     VARIANT_BOOL b;
7837     VARIANT var;
7838     HRESULT hr;
7839 
7840     VariantInit(&var);
7841     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7842     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XSLPattern")) == 0, "expected XSLPattern\n");
7843     VariantClear(&var);
7844 
7845     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7846     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("")) == 0, "expected empty string\n");
7847     VariantClear(&var);
7848 
7849     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7850     ok_(__FILE__, line)(b == VARIANT_FALSE, "expected FALSE\n");
7851 
7852     hr = IXMLDOMDocument2_get_schemas(doc, &var);
7853     ok_(__FILE__, line)(hr == S_FALSE, "got %08x\n", hr);
7854     VariantClear(&var);
7855 }
7856 
7857 #define check_set_props(doc) _check_set_props(__LINE__, doc)
7858 static inline void _check_set_props(int line, IXMLDOMDocument2* doc)
7859 {
7860     VARIANT_BOOL b;
7861     VARIANT var;
7862 
7863     VariantInit(&var);
7864     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7865     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XPath")) == 0, "expected XPath\n");
7866     VariantClear(&var);
7867 
7868     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7869     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
7870     VariantClear(&var);
7871 
7872     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7873     ok_(__FILE__, line)(b == VARIANT_TRUE, "expected TRUE\n");
7874 
7875     helper_ole_check(IXMLDOMDocument2_get_schemas(doc, &var));
7876     ok_(__FILE__, line)(V_VT(&var) != VT_NULL, "expected pointer\n");
7877     VariantClear(&var);
7878 }
7879 
7880 #define set_props(doc, cache) _set_props(__LINE__, doc, cache)
7881 static inline void _set_props(int line, IXMLDOMDocument2* doc, IXMLDOMSchemaCollection* cache)
7882 {
7883     VARIANT var;
7884 
7885     VariantInit(&var);
7886     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
7887     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:wi=\'www.winehq.org\'")));
7888     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_TRUE));
7889     V_VT(&var) = VT_DISPATCH;
7890     V_DISPATCH(&var) = NULL;
7891     helper_ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&var)));
7892     ok_(__FILE__, line)(V_DISPATCH(&var) != NULL, "expected pointer\n");
7893     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7894     VariantClear(&var);
7895 }
7896 
7897 #define unset_props(doc) _unset_props(__LINE__, doc)
7898 static inline void _unset_props(int line, IXMLDOMDocument2* doc)
7899 {
7900     VARIANT var;
7901 
7902     VariantInit(&var);
7903     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
7904     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("")));
7905     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_FALSE));
7906     V_VT(&var) = VT_NULL;
7907     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7908     VariantClear(&var);
7909 }
7910 
7911 static void test_get_ownerDocument(void)
7912 {
7913     IXMLDOMDocument *doc1, *doc2, *doc3;
7914     IXMLDOMDocument2 *doc, *doc_owner;
7915     IXMLDOMNode *node;
7916     IXMLDOMSchemaCollection *cache;
7917     VARIANT_BOOL b;
7918     VARIANT var;
7919     IXMLDOMElement *element;
7920     IXMLDOMNodeList *node_list;
7921     IXMLDOMAttribute *attr;
7922     LONG i, len;
7923     HRESULT hr;
7924     const CHAR nodeXML[] =
7925     "<root id='0'>"
7926     "   <!-- comment node 0 -->"
7927     "   text node 0"
7928     "   <x attr='val'></x>"
7929     "   <?foo value='PI for x'?>"
7930     "   <![CDATA[ cdata ]]>"
7931     "</root>";
7932 
7933     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
7934     if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
7935 
7936     doc = create_document(&IID_IXMLDOMDocument2);
7937     cache = create_cache(&IID_IXMLDOMSchemaCollection);
7938 
7939     VariantInit(&var);
7940 
7941     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7942     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7943 
7944     check_default_props(doc);
7945 
7946     /* set properties and check that new instances use them */
7947     set_props(doc, cache);
7948     check_set_props(doc);
7949 
7950     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7951     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc1));
7952 
7953     /* new interface keeps props */
7954     ole_check(IXMLDOMDocument_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7955     ok( doc_owner != doc, "got %p, doc %p\n", doc_owner, doc);
7956     check_set_props(doc_owner);
7957     IXMLDOMDocument2_Release(doc_owner);
7958 
7959     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc2));
7960     IXMLDOMNode_Release(node);
7961 
7962     ok(doc1 != doc2, "got %p, expected %p. original %p\n", doc2, doc1, doc);
7963 
7964     /* reload */
7965     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7966     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7967 
7968     /* properties retained even after reload */
7969     check_set_props(doc);
7970 
7971     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7972     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc3));
7973     IXMLDOMNode_Release(node);
7974 
7975     ole_check(IXMLDOMDocument_QueryInterface(doc3, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7976     ok(doc3 != doc1 && doc3 != doc2 && doc_owner != doc, "got %p, (%p, %p, %p)\n", doc3, doc, doc1, doc2);
7977     check_set_props(doc_owner);
7978 
7979     /* changing properties for one instance changes them for all */
7980     unset_props(doc_owner);
7981     check_default_props(doc_owner);
7982     check_default_props(doc);
7983 
7984     /* NULL check */
7985     hr = IXMLDOMDocument_loadXML(doc1, _bstr_(nodeXML), &b);
7986     EXPECT_HR(hr, S_OK);
7987     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7988 
7989     hr = IXMLDOMDocument_get_documentElement(doc1, &element);
7990     EXPECT_HR(hr, S_OK);
7991 
7992     hr = IXMLDOMElement_get_childNodes(element, &node_list);
7993     EXPECT_HR(hr, S_OK);
7994 
7995     hr = IXMLDOMNodeList_get_length(node_list, &len);
7996     EXPECT_HR(hr, S_OK);
7997 
7998     for(i = 0; i < len; i++) {
7999         hr = IXMLDOMNodeList_get_item(node_list, i, &node);
8000         EXPECT_HR(hr, S_OK);
8001 
8002         hr = IXMLDOMNode_get_ownerDocument(node, NULL);
8003         EXPECT_HR(hr, E_INVALIDARG);
8004 
8005         IXMLDOMNode_Release(node);
8006     }
8007     IXMLDOMElement_Release(element);
8008 
8009     /* Test Attribute Node */
8010     hr = IXMLDOMNodeList_get_item(node_list, 2, &node);
8011     EXPECT_HR(hr, S_OK);
8012     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
8013     EXPECT_HR(hr, S_OK);
8014     IXMLDOMNode_Release(node);
8015 
8016     hr = IXMLDOMElement_getAttributeNode(element, _bstr_("attr"), &attr);
8017     EXPECT_HR(hr, S_OK);
8018     ok(attr != NULL, "attr == NULL\n");
8019     IXMLDOMElement_Release(element);
8020     hr = IXMLDOMAttribute_get_ownerDocument(attr, NULL);
8021     EXPECT_HR(hr, E_INVALIDARG);
8022     IXMLDOMAttribute_Release(attr);
8023     IXMLDOMNodeList_Release(node_list);
8024 
8025     IXMLDOMSchemaCollection_Release(cache);
8026     IXMLDOMDocument_Release(doc1);
8027     IXMLDOMDocument_Release(doc2);
8028     IXMLDOMDocument_Release(doc3);
8029     IXMLDOMDocument2_Release(doc);
8030     //IXMLDOMDocument2_Release(doc_owner); FIXME: double-free!
8031     free_bstrs();
8032 }
8033 
8034 static void test_setAttributeNode(void)
8035 {
8036     IXMLDOMDocument *doc, *doc2;
8037     IXMLDOMElement *elem, *elem2;
8038     IXMLDOMAttribute *attr, *attr2, *ret_attr;
8039     VARIANT_BOOL b;
8040     HRESULT hr;
8041     VARIANT v;
8042     BSTR str;
8043     ULONG ref1, ref2;
8044 
8045     doc = create_document(&IID_IXMLDOMDocument);
8046 
8047     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8048     ok( hr == S_OK, "loadXML failed\n");
8049     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8050 
8051     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8052     ok( hr == S_OK, "got 0x%08x\n", hr);
8053 
8054     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
8055     ok( hr == S_OK, "got 0x%08x\n", hr);
8056     ok( elem2 != elem, "got same instance\n");
8057 
8058     ret_attr = (void*)0xdeadbeef;
8059     hr = IXMLDOMElement_setAttributeNode(elem, NULL, &ret_attr);
8060     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8061     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8062 
8063     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8064     ok( hr == S_OK, "got 0x%08x\n", hr);
8065 
8066     ref1 = IXMLDOMElement_AddRef(elem);
8067     IXMLDOMElement_Release(elem);
8068 
8069     ret_attr = (void*)0xdeadbeef;
8070     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8071     ok( hr == S_OK, "got 0x%08x\n", hr);
8072     ok( ret_attr == NULL, "got %p\n", ret_attr);
8073 
8074     /* no reference added */
8075     ref2 = IXMLDOMElement_AddRef(elem);
8076     IXMLDOMElement_Release(elem);
8077     ok(ref2 == ref1, "got %d, expected %d\n", ref2, ref1);
8078 
8079     EXPECT_CHILDREN(elem);
8080     EXPECT_CHILDREN(elem2);
8081 
8082     IXMLDOMElement_Release(elem2);
8083 
8084     attr2 = NULL;
8085     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attr"), &attr2);
8086     ok( hr == S_OK, "got 0x%08x\n", hr);
8087     ok( attr2 != attr, "got same instance %p\n", attr2);
8088     IXMLDOMAttribute_Release(attr2);
8089 
8090     /* try to add it another time */
8091     ret_attr = (void*)0xdeadbeef;
8092     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8093     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8094     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8095 
8096     IXMLDOMElement_Release(elem);
8097 
8098     /* initially used element is released, attribute still 'has' a container */
8099     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8100     ok( hr == S_OK, "got 0x%08x\n", hr);
8101     ret_attr = (void*)0xdeadbeef;
8102     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8103     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8104     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8105     IXMLDOMElement_Release(elem);
8106 
8107     /* add attribute already attached to another document */
8108     doc2 = create_document(&IID_IXMLDOMDocument);
8109 
8110     hr = IXMLDOMDocument_loadXML( doc2, _bstr_(complete4A), &b );
8111     ok( hr == S_OK, "loadXML failed\n");
8112     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8113 
8114     hr = IXMLDOMDocument_get_documentElement(doc2, &elem);
8115     ok( hr == S_OK, "got 0x%08x\n", hr);
8116     hr = IXMLDOMElement_setAttributeNode(elem, attr, NULL);
8117     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8118     IXMLDOMElement_Release(elem);
8119 
8120     IXMLDOMAttribute_Release(attr);
8121 
8122     /* create element, add attribute, see if it's copied or linked */
8123     hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
8124     ok( hr == S_OK, "got 0x%08x\n", hr);
8125 
8126     attr = NULL;
8127     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8128     ok(hr == S_OK, "got 0x%08x\n", hr);
8129     ok(attr != NULL, "got %p\n", attr);
8130 
8131     ref1 = IXMLDOMAttribute_AddRef(attr);
8132     IXMLDOMAttribute_Release(attr);
8133 
8134     V_VT(&v) = VT_BSTR;
8135     V_BSTR(&v) = _bstr_("attrvalue1");
8136     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8137     ok( hr == S_OK, "got 0x%08x\n", hr);
8138 
8139     str = NULL;
8140     hr = IXMLDOMAttribute_get_xml(attr, &str);
8141     ok( hr == S_OK, "got 0x%08x\n", hr);
8142     ok( lstrcmpW(str, _bstr_("attr=\"attrvalue1\"")) == 0,
8143         "got %s\n", wine_dbgstr_w(str));
8144     SysFreeString(str);
8145 
8146     ret_attr = (void*)0xdeadbeef;
8147     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8148     ok(hr == S_OK, "got 0x%08x\n", hr);
8149     ok(ret_attr == NULL, "got %p\n", ret_attr);
8150 
8151     /* attribute reference increased */
8152     ref2 = IXMLDOMAttribute_AddRef(attr);
8153     IXMLDOMAttribute_Release(attr);
8154     ok(ref1 == ref2, "got %d, expected %d\n", ref2, ref1);
8155 
8156     hr = IXMLDOMElement_get_xml(elem, &str);
8157     ok( hr == S_OK, "got 0x%08x\n", hr);
8158     ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue1\"/>")) == 0,
8159         "got %s\n", wine_dbgstr_w(str));
8160     SysFreeString(str);
8161 
8162     V_VT(&v) = VT_BSTR;
8163     V_BSTR(&v) = _bstr_("attrvalue2");
8164     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8165     ok( hr == S_OK, "got 0x%08x\n", hr);
8166 
8167     hr = IXMLDOMElement_get_xml(elem, &str);
8168     ok( hr == S_OK, "got 0x%08x\n", hr);
8169     todo_wine ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue2\"/>")) == 0,
8170         "got %s\n", wine_dbgstr_w(str));
8171     SysFreeString(str);
8172 
8173     IXMLDOMElement_Release(elem);
8174     IXMLDOMAttribute_Release(attr);
8175     IXMLDOMDocument_Release(doc2);
8176     IXMLDOMDocument_Release(doc);
8177     free_bstrs();
8178 }
8179 
8180 static void test_createNode(void)
8181 {
8182     IXMLDOMDocument *doc;
8183     IXMLDOMElement *elem;
8184     IXMLDOMNode *node;
8185     VARIANT v, var;
8186     BSTR prefix, str;
8187     HRESULT hr;
8188     ULONG ref;
8189 
8190     doc = create_document(&IID_IXMLDOMDocument);
8191 
8192     EXPECT_REF(doc, 1);
8193 
8194     /* reference count tests */
8195     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8196     ok( hr == S_OK, "got 0x%08x\n", hr);
8197 
8198     /* initial reference is 2 */
8199 todo_wine {
8200     EXPECT_REF(elem, 2);
8201     ref = IXMLDOMElement_Release(elem);
8202     ok(ref == 1, "got %d\n", ref);
8203     /* it's released already, attempt to release now will crash it */
8204 }
8205 
8206     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8207     ok( hr == S_OK, "got 0x%08x\n", hr);
8208     todo_wine EXPECT_REF(elem, 2);
8209     IXMLDOMDocument_Release(doc);
8210     todo_wine EXPECT_REF(elem, 2);
8211     IXMLDOMElement_Release(elem);
8212 
8213     doc = create_document(&IID_IXMLDOMDocument);
8214 
8215     /* NODE_ELEMENT nodes */
8216     /* 1. specified namespace */
8217     V_VT(&v) = VT_I4;
8218     V_I4(&v) = NODE_ELEMENT;
8219 
8220     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("ns1:test"), _bstr_("http://winehq.org"), &node);
8221     ok( hr == S_OK, "got 0x%08x\n", hr);
8222     prefix = NULL;
8223     hr = IXMLDOMNode_get_prefix(node, &prefix);
8224     ok( hr == S_OK, "got 0x%08x\n", hr);
8225     ok(lstrcmpW(prefix, _bstr_("ns1")) == 0, "wrong prefix\n");
8226     SysFreeString(prefix);
8227     IXMLDOMNode_Release(node);
8228 
8229     /* 2. default namespace */
8230     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("test"), _bstr_("http://winehq.org/default"), &node);
8231     ok( hr == S_OK, "got 0x%08x\n", hr);
8232     prefix = (void*)0xdeadbeef;
8233     hr = IXMLDOMNode_get_prefix(node, &prefix);
8234     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8235     ok(prefix == 0, "expected empty prefix, got %p\n", prefix);
8236     /* check dump */
8237     hr = IXMLDOMNode_get_xml(node, &str);
8238     ok( hr == S_OK, "got 0x%08x\n", hr);
8239     ok( lstrcmpW(str, _bstr_("<test xmlns=\"http://winehq.org/default\"/>")) == 0,
8240         "got %s\n", wine_dbgstr_w(str));
8241     SysFreeString(str);
8242 
8243     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
8244     ok( hr == S_OK, "got 0x%08x\n", hr);
8245 
8246     V_VT(&var) = VT_BSTR;
8247     hr = IXMLDOMElement_getAttribute(elem, _bstr_("xmlns"), &var);
8248     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8249     ok( V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
8250 
8251     str = NULL;
8252     hr = IXMLDOMElement_get_namespaceURI(elem, &str);
8253     ok( hr == S_OK, "got 0x%08x\n", hr);
8254     ok( lstrcmpW(str, _bstr_("http://winehq.org/default")) == 0, "expected default namespace\n");
8255     SysFreeString(str);
8256 
8257     IXMLDOMElement_Release(elem);
8258     IXMLDOMNode_Release(node);
8259 
8260     IXMLDOMDocument_Release(doc);
8261     free_bstrs();
8262 }
8263 
8264 static const char get_prefix_doc[] =
8265     "<?xml version=\"1.0\" ?>"
8266     "<a xmlns:ns1=\"ns1 href\" />";
8267 
8268 static void test_get_prefix(void)
8269 {
8270     IXMLDOMDocumentFragment *fragment;
8271     IXMLDOMCDATASection *cdata;
8272     IXMLDOMElement *element;
8273     IXMLDOMComment *comment;
8274     IXMLDOMDocument *doc;
8275     VARIANT_BOOL b;
8276     HRESULT hr;
8277     BSTR str;
8278 
8279     doc = create_document(&IID_IXMLDOMDocument);
8280 
8281     /* nodes that can't support prefix */
8282     /* 1. document */
8283     str = (void*)0xdeadbeef;
8284     hr = IXMLDOMDocument_get_prefix(doc, &str);
8285     EXPECT_HR(hr, S_FALSE);
8286     ok(str == NULL, "got %p\n", str);
8287 
8288     hr = IXMLDOMDocument_get_prefix(doc, NULL);
8289     EXPECT_HR(hr, E_INVALIDARG);
8290 
8291     /* 2. cdata */
8292     hr = IXMLDOMDocument_createCDATASection(doc, NULL, &cdata);
8293     ok(hr == S_OK, "got %08x\n", hr );
8294 
8295     str = (void*)0xdeadbeef;
8296     hr = IXMLDOMCDATASection_get_prefix(cdata, &str);
8297     ok(hr == S_FALSE, "got %08x\n", hr);
8298     ok( str == 0, "got %p\n", str);
8299 
8300     hr = IXMLDOMCDATASection_get_prefix(cdata, NULL);
8301     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8302     IXMLDOMCDATASection_Release(cdata);
8303 
8304     /* 3. comment */
8305     hr = IXMLDOMDocument_createComment(doc, NULL, &comment);
8306     ok(hr == S_OK, "got %08x\n", hr );
8307 
8308     str = (void*)0xdeadbeef;
8309     hr = IXMLDOMComment_get_prefix(comment, &str);
8310     ok(hr == S_FALSE, "got %08x\n", hr);
8311     ok( str == 0, "got %p\n", str);
8312 
8313     hr = IXMLDOMComment_get_prefix(comment, NULL);
8314     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8315     IXMLDOMComment_Release(comment);
8316 
8317     /* 4. fragment */
8318     hr = IXMLDOMDocument_createDocumentFragment(doc, &fragment);
8319     ok(hr == S_OK, "got %08x\n", hr );
8320 
8321     str = (void*)0xdeadbeef;
8322     hr = IXMLDOMDocumentFragment_get_prefix(fragment, &str);
8323     ok(hr == S_FALSE, "got %08x\n", hr);
8324     ok( str == 0, "got %p\n", str);
8325 
8326     hr = IXMLDOMDocumentFragment_get_prefix(fragment, NULL);
8327     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8328     IXMLDOMDocumentFragment_Release(fragment);
8329 
8330     /* no prefix */
8331     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &element);
8332     ok( hr == S_OK, "got 0x%08x\n", hr);
8333 
8334     hr = IXMLDOMElement_get_prefix(element, NULL);
8335     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8336 
8337     str = (void*)0xdeadbeef;
8338     hr = IXMLDOMElement_get_prefix(element, &str);
8339     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8340     ok( str == 0, "got %p\n", str);
8341 
8342     IXMLDOMElement_Release(element);
8343 
8344     /* with prefix */
8345     hr = IXMLDOMDocument_createElement(doc, _bstr_("a:elem"), &element);
8346     ok( hr == S_OK, "got 0x%08x\n", hr);
8347 
8348     str = (void*)0xdeadbeef;
8349     hr = IXMLDOMElement_get_prefix(element, &str);
8350     ok( hr == S_OK, "got 0x%08x\n", hr);
8351     ok( lstrcmpW(str, _bstr_("a")) == 0, "expected prefix \"a\"\n");
8352     SysFreeString(str);
8353 
8354     str = (void*)0xdeadbeef;
8355     hr = IXMLDOMElement_get_namespaceURI(element, &str);
8356     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8357     ok( str == 0, "got %p\n", str);
8358 
8359     IXMLDOMElement_Release(element);
8360 
8361     hr = IXMLDOMDocument_loadXML(doc, _bstr_(get_prefix_doc), &b);
8362     EXPECT_HR(hr, S_OK);
8363 
8364     hr = IXMLDOMDocument_get_documentElement(doc, &element);
8365     EXPECT_HR(hr, S_OK);
8366 
8367     str = (void*)0xdeadbeef;
8368     hr = IXMLDOMElement_get_prefix(element, &str);
8369     EXPECT_HR(hr, S_FALSE);
8370     ok(str == NULL, "got %p\n", str);
8371 
8372     str = (void*)0xdeadbeef;
8373     hr = IXMLDOMElement_get_namespaceURI(element, &str);
8374     EXPECT_HR(hr, S_FALSE);
8375     ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
8376 
8377     IXMLDOMDocument_Release(doc);
8378     free_bstrs();
8379 }
8380 
8381 static void test_selectSingleNode(void)
8382 {
8383     IXMLDOMDocument *doc;
8384     IXMLDOMNodeList *list;
8385     IXMLDOMNode *node;
8386     VARIANT_BOOL b;
8387     HRESULT hr;
8388     LONG len;
8389 
8390     doc = create_document(&IID_IXMLDOMDocument);
8391 
8392     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8393     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8394 
8395     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8396     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8397 
8398     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8399     ok( hr == S_OK, "loadXML failed\n");
8400     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8401 
8402     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8403     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8404 
8405     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8406     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8407 
8408     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), NULL);
8409     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8410 
8411     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), NULL);
8412     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8413 
8414     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), &node);
8415     ok(hr == S_OK, "got 0x%08x\n", hr);
8416     IXMLDOMNode_Release(node);
8417 
8418     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), &list);
8419     ok(hr == S_OK, "got 0x%08x\n", hr);
8420     IXMLDOMNodeList_Release(list);
8421 
8422     list = (void*)0xdeadbeef;
8423     hr = IXMLDOMDocument_selectNodes(doc, NULL, &list);
8424     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8425     ok(list == (void*)0xdeadbeef, "got %p\n", list);
8426 
8427     node = (void*)0xdeadbeef;
8428     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("nonexistent"), &node);
8429     ok(hr == S_FALSE, "got 0x%08x\n", hr);
8430     ok(node == 0, "got %p\n", node);
8431 
8432     list = (void*)0xdeadbeef;
8433     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("nonexistent"), &list);
8434     ok(hr == S_OK, "got 0x%08x\n", hr);
8435     len = 1;
8436     hr = IXMLDOMNodeList_get_length(list, &len);
8437     ok(hr == S_OK, "got 0x%08x\n", hr);
8438     ok(len == 0, "got %d\n", len);
8439     IXMLDOMNodeList_Release(list);
8440 
8441     IXMLDOMDocument_Release(doc);
8442     free_bstrs();
8443 }
8444 
8445 static void test_events(void)
8446 {
8447     IConnectionPointContainer *conn;
8448     IConnectionPoint *point;
8449     IXMLDOMDocument *doc;
8450     HRESULT hr;
8451     VARIANT v;
8452     IDispatch *event;
8453 
8454     doc = create_document(&IID_IXMLDOMDocument);
8455 
8456     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&conn);
8457     ok(hr == S_OK, "got 0x%08x\n", hr);
8458 
8459     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IDispatch, &point);
8460     ok(hr == S_OK, "got 0x%08x\n", hr);
8461     IConnectionPoint_Release(point);
8462     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IPropertyNotifySink, &point);
8463     ok(hr == S_OK, "got 0x%08x\n", hr);
8464     IConnectionPoint_Release(point);
8465     hr = IConnectionPointContainer_FindConnectionPoint(conn, &DIID_XMLDOMDocumentEvents, &point);
8466     ok(hr == S_OK, "got 0x%08x\n", hr);
8467     IConnectionPoint_Release(point);
8468 
8469     IConnectionPointContainer_Release(conn);
8470 
8471     /* ready state callback */
8472     VariantInit(&v);
8473     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8474     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8475 
8476     event = create_dispevent();
8477     V_VT(&v) = VT_UNKNOWN;
8478     V_UNKNOWN(&v) = (IUnknown*)event;
8479 
8480     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8481     ok(hr == S_OK, "got 0x%08x\n", hr);
8482     EXPECT_REF(event, 2);
8483 
8484     V_VT(&v) = VT_DISPATCH;
8485     V_DISPATCH(&v) = event;
8486 
8487     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8488     ok(hr == S_OK, "got 0x%08x\n", hr);
8489     EXPECT_REF(event, 2);
8490 
8491     /* VT_NULL doesn't reset event handler */
8492     V_VT(&v) = VT_NULL;
8493     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8494     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8495     EXPECT_REF(event, 2);
8496 
8497     V_VT(&v) = VT_DISPATCH;
8498     V_DISPATCH(&v) = NULL;
8499 
8500     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8501     ok(hr == S_OK, "got 0x%08x\n", hr);
8502     EXPECT_REF(event, 1);
8503 
8504     V_VT(&v) = VT_UNKNOWN;
8505     V_DISPATCH(&v) = NULL;
8506     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8507     ok(hr == S_OK, "got 0x%08x\n", hr);
8508 
8509     IDispatch_Release(event);
8510 
8511     IXMLDOMDocument_Release(doc);
8512 }
8513 
8514 static void test_createProcessingInstruction(void)
8515 {
8516     static const WCHAR bodyW[] = {'t','e','s','t',0};
8517     IXMLDOMProcessingInstruction *pi;
8518     IXMLDOMDocument *doc;
8519     WCHAR buff[10];
8520     HRESULT hr;
8521 
8522     doc = create_document(&IID_IXMLDOMDocument);
8523 
8524     /* test for BSTR handling, pass broken BSTR */
8525     memcpy(&buff[2], bodyW, sizeof(bodyW));
8526     /* just a big length */
8527     *(DWORD*)buff = 0xf0f0;
8528     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("test"), &buff[2], &pi);
8529     ok(hr == S_OK, "got 0x%08x\n", hr);
8530 
8531     IXMLDOMProcessingInstruction_Release(pi);
8532     IXMLDOMDocument_Release(doc);
8533 }
8534 
8535 static void test_put_nodeTypedValue(void)
8536 {
8537     static const BYTE binhexdata[16] =
8538         {0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf};
8539     IXMLDOMDocument *doc;
8540     IXMLDOMElement *elem;
8541     VARIANT type, value;
8542     LONG ubound, lbound;
8543     IXMLDOMNode *node;
8544     SAFEARRAY *array;
8545     HRESULT hr;
8546     BYTE *ptr;
8547     BSTR str;
8548 
8549     doc = create_document(&IID_IXMLDOMDocument);
8550 
8551     hr = IXMLDOMDocument_createElement(doc, _bstr_("Element"), &elem);
8552     EXPECT_HR(hr, S_OK);
8553 
8554     V_VT(&type) = VT_EMPTY;
8555     hr = IXMLDOMElement_get_dataType(elem, &type);
8556     EXPECT_HR(hr, S_FALSE);
8557     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8558 
8559     /* set typed value for untyped node */
8560     V_VT(&type) = VT_I1;
8561     V_I1(&type) = 1;
8562     hr = IXMLDOMElement_put_nodeTypedValue(elem, type);
8563     EXPECT_HR(hr, S_OK);
8564 
8565     V_VT(&type) = VT_EMPTY;
8566     hr = IXMLDOMElement_get_dataType(elem, &type);
8567     EXPECT_HR(hr, S_FALSE);
8568     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8569 
8570     /* no type info stored */
8571     V_VT(&type) = VT_EMPTY;
8572     hr = IXMLDOMElement_get_nodeTypedValue(elem, &type);
8573     EXPECT_HR(hr, S_OK);
8574     ok(V_VT(&type) == VT_BSTR, "got %d, expected VT_BSTR\n", V_VT(&type));
8575     ok(memcmp(V_BSTR(&type), _bstr_("1"), 2*sizeof(WCHAR)) == 0,
8576        "got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
8577     VariantClear(&type);
8578 
8579     hr = IXMLDOMElement_get_firstChild(elem, &node);
8580     EXPECT_HR(hr, S_OK);
8581     hr = IXMLDOMElement_removeChild(elem, node, NULL);
8582     EXPECT_HR(hr, S_OK);
8583     IXMLDOMNode_Release(node);
8584 
8585     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)elem, NULL);
8586     EXPECT_HR(hr, S_OK);
8587 
8588     /* bin.base64 */
8589     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.base64"));
8590     EXPECT_HR(hr, S_OK);
8591 
8592     V_VT(&value) = VT_BSTR;
8593     V_BSTR(&value) = _bstr_("ABCD");
8594     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8595     EXPECT_HR(hr, S_OK);
8596 
8597     V_VT(&value) = VT_EMPTY;
8598     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8599     EXPECT_HR(hr, S_OK);
8600     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8601     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8602     ubound = 0;
8603     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8604     EXPECT_HR(hr, S_OK);
8605     ok(ubound == 2, "got %d\n", ubound);
8606     lbound = 0;
8607     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8608     EXPECT_HR(hr, S_OK);
8609     ok(lbound == 0, "got %d\n", lbound);
8610     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8611     EXPECT_HR(hr, S_OK);
8612     ok(ptr[0] == 0, "got %x\n", ptr[0]);
8613     ok(ptr[1] == 0x10, "got %x\n", ptr[1]);
8614     ok(ptr[2] == 0x83, "got %x\n", ptr[2]);
8615     SafeArrayUnaccessData(V_ARRAY(&value));
8616     VariantClear(&value);
8617 
8618     /* when set as VT_BSTR it's stored as is */
8619     hr = IXMLDOMElement_get_firstChild(elem, &node);
8620     EXPECT_HR(hr, S_OK);
8621     hr = IXMLDOMNode_get_text(node, &str);
8622     EXPECT_HR(hr, S_OK);
8623     ok(!lstrcmpW(str, _bstr_("ABCD")), "%s\n", wine_dbgstr_w(str));
8624     IXMLDOMNode_Release(node);
8625     SysFreeString(str);
8626 
8627     array = SafeArrayCreateVector(VT_UI1, 0, 7);
8628     hr = SafeArrayAccessData(array, (void*)&ptr);
8629     EXPECT_HR(hr, S_OK);
8630     memcpy(ptr, "dGVzdA=", strlen("dGVzdA="));
8631     SafeArrayUnaccessData(array);
8632 
8633     V_VT(&value) = VT_UI1|VT_ARRAY;
8634     V_ARRAY(&value) = array;
8635     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8636     EXPECT_HR(hr, S_OK);
8637 
8638     V_VT(&value) = VT_EMPTY;
8639     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8640     EXPECT_HR(hr, S_OK);
8641     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8642     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8643     ubound = 0;
8644     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8645     EXPECT_HR(hr, S_OK);
8646     ok(ubound == 6, "got %d\n", ubound);
8647     lbound = 0;
8648     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8649     EXPECT_HR(hr, S_OK);
8650     ok(lbound == 0, "got %d\n", lbound);
8651     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8652     EXPECT_HR(hr, S_OK);
8653     ok(!memcmp(ptr, "dGVzdA=", strlen("dGVzdA=")), "got wrong data, %s\n", ptr);
8654     SafeArrayUnaccessData(V_ARRAY(&value));
8655     VariantClear(&value);
8656 
8657     /* if set with VT_UI1|VT_ARRAY it's encoded */
8658     hr = IXMLDOMElement_get_firstChild(elem, &node);
8659     EXPECT_HR(hr, S_OK);
8660     hr = IXMLDOMNode_get_text(node, &str);
8661     EXPECT_HR(hr, S_OK);
8662     ok(!lstrcmpW(str, _bstr_("ZEdWemRBPQ==")), "%s\n", wine_dbgstr_w(str));
8663     IXMLDOMNode_Release(node);
8664     SafeArrayDestroyData(array);
8665     SysFreeString(str);
8666 
8667     /* bin.hex */
8668     V_VT(&value) = VT_BSTR;
8669     V_BSTR(&value) = _bstr_("");
8670     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8671     EXPECT_HR(hr, S_OK);
8672 
8673     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.hex"));
8674     EXPECT_HR(hr, S_OK);
8675 
8676     array = SafeArrayCreateVector(VT_UI1, 0, 16);
8677     hr = SafeArrayAccessData(array, (void*)&ptr);
8678     EXPECT_HR(hr, S_OK);
8679     memcpy(ptr, binhexdata, sizeof(binhexdata));
8680     SafeArrayUnaccessData(array);
8681 
8682     V_VT(&value) = VT_UI1|VT_ARRAY;
8683     V_ARRAY(&value) = array;
8684     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8685     EXPECT_HR(hr, S_OK);
8686 
8687     V_VT(&value) = VT_EMPTY;
8688     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8689     EXPECT_HR(hr, S_OK);
8690     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8691     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8692     ubound = 0;
8693     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8694     EXPECT_HR(hr, S_OK);
8695     ok(ubound == 15, "got %d\n", ubound);
8696     lbound = 0;
8697     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8698     EXPECT_HR(hr, S_OK);
8699     ok(lbound == 0, "got %d\n", lbound);
8700     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8701     EXPECT_HR(hr, S_OK);
8702     ok(!memcmp(ptr, binhexdata, sizeof(binhexdata)), "got wrong data\n");
8703     SafeArrayUnaccessData(V_ARRAY(&value));
8704     VariantClear(&value);
8705 
8706     /* if set with VT_UI1|VT_ARRAY it's encoded */
8707     hr = IXMLDOMElement_get_firstChild(elem, &node);
8708     EXPECT_HR(hr, S_OK);
8709     hr = IXMLDOMNode_get_text(node, &str);
8710     EXPECT_HR(hr, S_OK);
8711     ok(!lstrcmpW(str, _bstr_("000102030405060708090a0b0c0d0e0f")), "%s\n", wine_dbgstr_w(str));
8712     IXMLDOMNode_Release(node);
8713     SafeArrayDestroyData(array);
8714     SysFreeString(str);
8715 
8716     IXMLDOMElement_Release(elem);
8717     IXMLDOMDocument_Release(doc);
8718     free_bstrs();
8719 }
8720 
8721 static void test_get_xml(void)
8722 {
8723     static const char xmlA[] = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<a>test</a>\r\n";
8724     static const char attrA[] = "attr=\"&quot;a &amp; b&quot;\"";
8725     static const char attr2A[] = "\"a & b\"";
8726     static const char attr3A[] = "attr=\"&amp;quot;a\"";
8727     static const char attr4A[] = "&quot;a";
8728     static const char fooA[] = "<foo/>";
8729     IXMLDOMProcessingInstruction *pi;
8730     IXMLDOMNode *first;
8731     IXMLDOMElement *elem = NULL;
8732     IXMLDOMAttribute *attr;
8733     IXMLDOMDocument *doc;
8734     VARIANT_BOOL b;
8735     VARIANT v;
8736     BSTR xml;
8737     HRESULT hr;
8738 
8739     doc = create_document(&IID_IXMLDOMDocument);
8740 
8741     b = VARIANT_TRUE;
8742     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8743     ok(hr == S_OK, "got 0x%08x\n", hr);
8744     ok( b == VARIANT_TRUE, "got %d\n", b);
8745 
8746     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"),
8747                              _bstr_("version=\"1.0\" encoding=\"UTF-16\""), &pi);
8748     ok(hr == S_OK, "got 0x%08x\n", hr);
8749 
8750     hr = IXMLDOMDocument_get_firstChild(doc, &first);
8751     ok(hr == S_OK, "got 0x%08x\n", hr);
8752 
8753     V_UNKNOWN(&v) = (IUnknown*)first;
8754     V_VT(&v) = VT_UNKNOWN;
8755 
8756     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)pi, v, NULL);
8757     ok(hr == S_OK, "got 0x%08x\n", hr);
8758 
8759     IXMLDOMProcessingInstruction_Release(pi);
8760     IXMLDOMNode_Release(first);
8761 
8762     hr = IXMLDOMDocument_get_xml(doc, &xml);
8763     ok(hr == S_OK, "got 0x%08x\n", hr);
8764 
8765     ok(memcmp(xml, _bstr_(xmlA), sizeof(xmlA)*sizeof(WCHAR)) == 0,
8766         "got %s, expected %s\n", wine_dbgstr_w(xml), xmlA);
8767     SysFreeString(xml);
8768 
8769     IXMLDOMDocument_Release(doc);
8770 
8771     doc = create_document(&IID_IXMLDOMDocument);
8772 
8773     hr = IXMLDOMDocument_createElement(doc, _bstr_("foo"), &elem);
8774     ok(hr == S_OK, "got 0x%08x\n", hr);
8775 
8776     hr = IXMLDOMDocument_putref_documentElement(doc, elem);
8777     ok(hr == S_OK, "got 0x%08x\n", hr);
8778 
8779     hr = IXMLDOMDocument_get_xml(doc, &xml);
8780     ok(hr == S_OK, "got 0x%08x\n", hr);
8781 
8782     ok(memcmp(xml, _bstr_(fooA), (sizeof(fooA)-1)*sizeof(WCHAR)) == 0,
8783         "got %s, expected %s\n", wine_dbgstr_w(xml), fooA);
8784     SysFreeString(xml);
8785 
8786     IXMLDOMElement_Release(elem);
8787 
8788     /* attribute node */
8789     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8790     ok(hr == S_OK, "got 0x%08x\n", hr);
8791 
8792     V_VT(&v) = VT_BSTR;
8793     V_BSTR(&v) = _bstr_("\"a & b\"");
8794     hr = IXMLDOMAttribute_put_value(attr, v);
8795     ok(hr == S_OK, "got 0x%08x\n", hr);
8796 
8797     xml = NULL;
8798     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8799     ok(hr == S_OK, "got 0x%08x\n", hr);
8800     ok(!memcmp(xml, _bstr_(attrA), (sizeof(attrA)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8801     SysFreeString(xml);
8802 
8803     VariantInit(&v);
8804     hr = IXMLDOMAttribute_get_value(attr, &v);
8805     ok(hr == S_OK, "got 0x%08x\n", hr);
8806     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8807     ok(!memcmp(V_BSTR(&v), _bstr_(attr2A), (sizeof(attr2A)-1)*sizeof(WCHAR)),
8808         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8809     VariantClear(&v);
8810 
8811     V_VT(&v) = VT_BSTR;
8812     V_BSTR(&v) = _bstr_("&quot;a");
8813     hr = IXMLDOMAttribute_put_value(attr, v);
8814     ok(hr == S_OK, "got 0x%08x\n", hr);
8815 
8816     xml = NULL;
8817     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8818     ok(hr == S_OK, "got 0x%08x\n", hr);
8819     ok(!memcmp(xml, _bstr_(attr3A), (sizeof(attr3A)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8820     SysFreeString(xml);
8821 
8822     VariantInit(&v);
8823     hr = IXMLDOMAttribute_get_value(attr, &v);
8824     ok(hr == S_OK, "got 0x%08x\n", hr);
8825     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8826     ok(!memcmp(V_BSTR(&v), _bstr_(attr4A), (sizeof(attr4A)-1)*sizeof(WCHAR)),
8827         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8828     VariantClear(&v);
8829 
8830     IXMLDOMAttribute_Release(attr);
8831 
8832     IXMLDOMDocument_Release(doc);
8833 
8834     free_bstrs();
8835 }
8836 
8837 static void test_xsltemplate(void)
8838 {
8839     IXMLDOMDocument *doc, *doc2, *doc3;
8840     IXSLTemplate *template;
8841     IXSLProcessor *processor;
8842     IStream *stream;
8843     VARIANT_BOOL b;
8844     HRESULT hr;
8845     ULONG ref1, ref2;
8846     VARIANT v;
8847     BSTR str;
8848 
8849     if (!is_clsid_supported(&CLSID_XSLTemplate, &IID_IXSLTemplate)) return;
8850     template = create_xsltemplate(&IID_IXSLTemplate);
8851 
8852     /* works as reset */
8853     hr = IXSLTemplate_putref_stylesheet(template, NULL);
8854     ok(hr == S_OK, "got 0x%08x\n", hr);
8855 
8856     doc = create_document(&IID_IXMLDOMDocument);
8857 
8858     b = VARIANT_TRUE;
8859     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8860     ok(hr == S_OK, "got 0x%08x\n", hr);
8861     ok( b == VARIANT_TRUE, "got %d\n", b);
8862 
8863     /* putref with non-xsl document */
8864     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8865     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8866 
8867     b = VARIANT_TRUE;
8868     hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8869     ok(hr == S_OK, "got 0x%08x\n", hr);
8870     ok( b == VARIANT_TRUE, "got %d\n", b);
8871 
8872     /* not a freethreaded document */
8873     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8874     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8875 
8876     IXMLDOMDocument_Release(doc);
8877 
8878     if (!is_clsid_supported(&CLSID_FreeThreadedDOMDocument, &IID_IXMLDOMDocument))
8879     {
8880         IXSLTemplate_Release(template);
8881         return;
8882     }
8883 
8884     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
8885     ok(hr == S_OK, "got 0x%08x\n", hr);
8886 
8887     b = VARIANT_TRUE;
8888     hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8889     ok(hr == S_OK, "got 0x%08x\n", hr);
8890     ok( b == VARIANT_TRUE, "got %d\n", b);
8891 
8892     /* freethreaded document */
8893     ref1 = IXMLDOMDocument_AddRef(doc);
8894     IXMLDOMDocument_Release(doc);
8895     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8896     ok(hr == S_OK, "got 0x%08x\n", hr);
8897     ref2 = IXMLDOMDocument_AddRef(doc);
8898     IXMLDOMDocument_Release(doc);
8899     ok(ref2 > ref1, "got %d\n", ref2);
8900 
8901     /* processor */
8902     hr = IXSLTemplate_createProcessor(template, NULL);
8903     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8904 
8905     EXPECT_REF(template, 1);
8906     hr = IXSLTemplate_createProcessor(template, &processor);
8907     ok(hr == S_OK, "got 0x%08x\n", hr);
8908     EXPECT_REF(template, 2);
8909 
8910     /* input no set yet */
8911     V_VT(&v) = VT_BSTR;
8912     V_BSTR(&v) = NULL;
8913     hr = IXSLProcessor_get_input(processor, &v);
8914 todo_wine {
8915     ok(hr == S_OK, "got 0x%08x\n", hr);
8916     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
8917 }
8918 
8919     hr = IXSLProcessor_get_output(processor, NULL);
8920     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8921 
8922     /* reset before it was set */
8923     V_VT(&v) = VT_EMPTY;
8924     hr = IXSLProcessor_put_output(processor, v);
8925     ok(hr == S_OK, "got 0x%08x\n", hr);
8926 
8927     V_VT(&v) = VT_UNKNOWN;
8928     V_UNKNOWN(&v) = NULL;
8929     hr = IXSLProcessor_put_output(processor, v);
8930     ok(hr == S_OK, "got 0x%08x\n", hr);
8931 
8932     V_VT(&v) = VT_UNKNOWN;
8933     V_DISPATCH(&v) = NULL;
8934     hr = IXSLProcessor_put_output(processor, v);
8935     ok(hr == S_OK, "got 0x%08x\n", hr);
8936 
8937     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
8938     ok(hr == S_OK, "got 0x%08x\n", hr);
8939     EXPECT_REF(stream, 1);
8940 
8941     V_VT(&v) = VT_UNKNOWN;
8942     V_UNKNOWN(&v) = (IUnknown*)stream;
8943     hr = IXSLProcessor_put_output(processor, v);
8944     ok(hr == S_OK, "got 0x%08x\n", hr);
8945 
8946     /* it seems processor grabs 2 references */
8947     todo_wine EXPECT_REF(stream, 3);
8948 
8949     V_VT(&v) = VT_EMPTY;
8950     hr = IXSLProcessor_get_output(processor, &v);
8951     ok(hr == S_OK, "got 0x%08x\n", hr);
8952     ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
8953     ok(V_UNKNOWN(&v) == (IUnknown*)stream, "got %p\n", V_UNKNOWN(&v));
8954 
8955     todo_wine EXPECT_REF(stream, 4);
8956     VariantClear(&v);
8957 
8958     hr = IXSLProcessor_transform(processor, NULL);
8959     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8960 
8961     /* reset and check stream refcount */
8962     V_VT(&v) = VT_EMPTY;
8963     hr = IXSLProcessor_put_output(processor, v);
8964     ok(hr == S_OK, "got 0x%08x\n", hr);
8965 
8966     EXPECT_REF(stream, 1);
8967 
8968     IStream_Release(stream);
8969 
8970     /* no output interface set, check output */
8971     doc2 = create_document(&IID_IXMLDOMDocument);
8972 
8973     b = VARIANT_FALSE;
8974     hr = IXMLDOMDocument_loadXML( doc2, _bstr_("<a>test</a>"), &b );
8975     ok(hr == S_OK, "got 0x%08x\n", hr);
8976     ok( b == VARIANT_TRUE, "got %d\n", b);
8977 
8978     V_VT(&v) = VT_UNKNOWN;
8979     V_UNKNOWN(&v) = (IUnknown*)doc2;
8980     hr = IXSLProcessor_put_input(processor, v);
8981     ok(hr == S_OK, "got 0x%08x\n", hr);
8982 
8983     hr = IXSLProcessor_transform(processor, &b);
8984     ok(hr == S_OK, "got 0x%08x\n", hr);
8985 
8986     V_VT(&v) = VT_EMPTY;
8987     hr = IXSLProcessor_get_output(processor, &v);
8988     ok(hr == S_OK, "got 0x%08x\n", hr);
8989     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8990     ok(*V_BSTR(&v) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8991     VariantClear(&v);
8992 
8993     /* transform to document */
8994     b = VARIANT_FALSE;
8995     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformXML), &b);
8996     ok(hr == S_OK, "got 0x%08x\n", hr);
8997     ok(b == VARIANT_TRUE, "got %d\n", b);
8998 
8999     V_VT(&v) = VT_UNKNOWN;
9000     V_UNKNOWN(&v) = (IUnknown*)doc2;
9001     hr = IXSLProcessor_put_input(processor, v);
9002     ok(hr == S_OK, "got 0x%08x\n", hr);
9003 
9004     doc3 = create_document(&IID_IXMLDOMDocument);
9005     V_VT(&v) = VT_UNKNOWN;
9006     V_UNKNOWN(&v) = (IUnknown *)doc3;
9007     hr = IXSLProcessor_put_output(processor, v);
9008     ok(hr == S_OK, "got 0x%08x\n", hr);
9009 
9010     hr = IXMLDOMDocument_get_xml(doc3, &str);
9011     ok(hr == S_OK, "got 0x%08x\n", hr);
9012     ok(!*str, "Expected empty document\n");
9013     SysFreeString(str);
9014 
9015     hr = IXSLProcessor_transform(processor, &b);
9016     ok(hr == S_OK, "got 0x%08x\n", hr);
9017 
9018     V_VT(&v) = VT_EMPTY;
9019     hr = IXSLProcessor_get_output(processor, &v);
9020     ok(hr == S_OK, "got 0x%08x\n", hr);
9021     ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
9022     VariantClear(&v);
9023 
9024     hr = IXMLDOMDocument_get_xml(doc3, &str);
9025     ok(hr == S_OK, "got 0x%08x\n", hr);
9026     ok(!!*str, "Expected document\n");
9027     SysFreeString(str);
9028 
9029     /* transform to IResponse */
9030     V_VT(&v) = VT_EMPTY;
9031     hr = IXSLProcessor_put_output(processor, v);
9032     ok(hr == S_OK, "got 0x%08x\n", hr);
9033 
9034     V_VT(&v) = VT_UNKNOWN;
9035     V_UNKNOWN(&v) = (IUnknown *)&testresponse;
9036     hr = IXSLProcessor_put_output(processor, v);
9037     ok(hr == S_OK, "got 0x%08x\n", hr);
9038 
9039     b = VARIANT_FALSE;
9040     hr = IXSLProcessor_transform(processor, &b);
9041     ok(hr == S_OK, "got 0x%08x\n", hr);
9042     ok(b == VARIANT_TRUE, "got %x\n", b);
9043 
9044     IXSLProcessor_Release(processor);
9045     IXMLDOMDocument_Release(doc2);
9046     IXMLDOMDocument_Release(doc3);
9047 
9048     /* drop reference */
9049     hr = IXSLTemplate_putref_stylesheet(template, NULL);
9050     ok(hr == S_OK, "got 0x%08x\n", hr);
9051     ref2 = IXMLDOMDocument_AddRef(doc);
9052     IXMLDOMDocument_Release(doc);
9053     ok(ref2 == ref1, "got %d\n", ref2);
9054 
9055     IXMLDOMDocument_Release(doc);
9056     IXSLTemplate_Release(template);
9057     free_bstrs();
9058 }
9059 
9060 static void test_insertBefore(void)
9061 {
9062     IXMLDOMDocument *doc, *doc2, *doc3;
9063     IXMLDOMAttribute *attr;
9064     IXMLDOMElement *elem1, *elem2, *elem3, *elem4, *elem5;
9065     IXMLDOMNode *node, *newnode, *cdata;
9066     HRESULT hr;
9067     VARIANT v;
9068     BSTR p;
9069 
9070     doc = create_document(&IID_IXMLDOMDocument);
9071     doc3 = create_document(&IID_IXMLDOMDocument);
9072 
9073     /* document to document */
9074     V_VT(&v) = VT_NULL;
9075     node = (void*)0xdeadbeef;
9076     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc3, v, &node);
9077     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9078     ok(node == NULL, "got %p\n", node);
9079 
9080     /* document to itself */
9081     V_VT(&v) = VT_NULL;
9082     node = (void*)0xdeadbeef;
9083     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc, v, &node);
9084     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9085     ok(node == NULL, "got %p\n", node);
9086 
9087     /* insertBefore behaviour for attribute node */
9088     V_VT(&v) = VT_I4;
9089     V_I4(&v) = NODE_ATTRIBUTE;
9090 
9091     attr = NULL;
9092     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr"), NULL, (IXMLDOMNode**)&attr);
9093     ok(hr == S_OK, "got 0x%08x\n", hr);
9094     ok(attr != NULL, "got %p\n", attr);
9095 
9096     /* attribute to document */
9097     V_VT(&v) = VT_NULL;
9098     node = (void*)0xdeadbeef;
9099     hr = IXMLDOMDocument_insertBefore(doc3, (IXMLDOMNode*)attr, v, &node);
9100     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9101     ok(node == NULL, "got %p\n", node);
9102 
9103     /* cdata to document */
9104     V_VT(&v) = VT_I4;
9105     V_I4(&v) = NODE_CDATA_SECTION;
9106 
9107     cdata = NULL;
9108     hr = IXMLDOMDocument_createNode(doc3, v, _bstr_("cdata"), NULL, &cdata);
9109     ok(hr == S_OK, "got 0x%08x\n", hr);
9110     ok(cdata != NULL, "got %p\n", cdata);
9111 
9112     EXPECT_NO_CHILDREN(cdata);
9113 
9114     /* attribute to cdata */
9115     V_VT(&v) = VT_NULL;
9116     node = (void*)0xdeadbeef;
9117     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)attr, v, &node);
9118     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9119     ok(node == NULL, "got %p\n", node);
9120 
9121     /* document to cdata */
9122     V_VT(&v) = VT_NULL;
9123     node = (void*)0xdeadbeef;
9124     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)doc, v, &node);
9125     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9126     ok(node == NULL, "got %p\n", node);
9127 
9128     V_VT(&v) = VT_NULL;
9129     node = (void*)0xdeadbeef;
9130     hr = IXMLDOMDocument_insertBefore(doc3, cdata, v, &node);
9131     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9132     ok(node == NULL, "got %p\n", node);
9133 
9134     IXMLDOMNode_Release(cdata);
9135     IXMLDOMDocument_Release(doc3);
9136 
9137     /* attribute to attribute */
9138     V_VT(&v) = VT_I4;
9139     V_I4(&v) = NODE_ATTRIBUTE;
9140     newnode = NULL;
9141     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr2"), NULL, &newnode);
9142     ok(hr == S_OK, "got 0x%08x\n", hr);
9143     ok(newnode != NULL, "got %p\n", newnode);
9144 
9145     V_VT(&v) = VT_NULL;
9146     node = (void*)0xdeadbeef;
9147     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9148     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9149     ok(node == NULL, "got %p\n", node);
9150 
9151     V_VT(&v) = VT_UNKNOWN;
9152     V_UNKNOWN(&v) = (IUnknown*)attr;
9153     node = (void*)0xdeadbeef;
9154     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9155     todo_wine ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9156     ok(node == NULL, "got %p\n", node);
9157     IXMLDOMNode_Release(newnode);
9158 
9159     /* cdata to attribute */
9160     V_VT(&v) = VT_I4;
9161     V_I4(&v) = NODE_CDATA_SECTION;
9162     newnode = NULL;
9163     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9164     ok(hr == S_OK, "got 0x%08x\n", hr);
9165     ok(newnode != NULL, "got %p\n", newnode);
9166 
9167     V_VT(&v) = VT_NULL;
9168     node = (void*)0xdeadbeef;
9169     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9170     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9171     ok(node == NULL, "got %p\n", node);
9172     IXMLDOMNode_Release(newnode);
9173 
9174     /* comment to attribute */
9175     V_VT(&v) = VT_I4;
9176     V_I4(&v) = NODE_COMMENT;
9177     newnode = NULL;
9178     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9179     ok(hr == S_OK, "got 0x%08x\n", hr);
9180     ok(newnode != NULL, "got %p\n", newnode);
9181 
9182     V_VT(&v) = VT_NULL;
9183     node = (void*)0xdeadbeef;
9184     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9185     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9186     ok(node == NULL, "got %p\n", node);
9187     IXMLDOMNode_Release(newnode);
9188 
9189     /* element to attribute */
9190     V_VT(&v) = VT_I4;
9191     V_I4(&v) = NODE_ELEMENT;
9192     newnode = NULL;
9193     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9194     ok(hr == S_OK, "got 0x%08x\n", hr);
9195     ok(newnode != NULL, "got %p\n", newnode);
9196 
9197     V_VT(&v) = VT_NULL;
9198     node = (void*)0xdeadbeef;
9199     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9200     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9201     ok(node == NULL, "got %p\n", node);
9202     IXMLDOMNode_Release(newnode);
9203 
9204     /* pi to attribute */
9205     V_VT(&v) = VT_I4;
9206     V_I4(&v) = NODE_PROCESSING_INSTRUCTION;
9207     newnode = NULL;
9208     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9209     ok(hr == S_OK, "got 0x%08x\n", hr);
9210     ok(newnode != NULL, "got %p\n", newnode);
9211 
9212     V_VT(&v) = VT_NULL;
9213     node = (void*)0xdeadbeef;
9214     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9215     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9216     ok(node == NULL, "got %p\n", node);
9217     IXMLDOMNode_Release(newnode);
9218     IXMLDOMAttribute_Release(attr);
9219 
9220     /* insertBefore for elements */
9221     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem1);
9222     ok(hr == S_OK, "got 0x%08x\n", hr);
9223 
9224     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem2"), &elem2);
9225     ok(hr == S_OK, "got 0x%08x\n", hr);
9226 
9227     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9228     ok(hr == S_OK, "got 0x%08x\n", hr);
9229 
9230     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9231     ok(hr == S_OK, "got 0x%08x\n", hr);
9232 
9233     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem4"), &elem4);
9234     ok(hr == S_OK, "got 0x%08x\n", hr);
9235 
9236     EXPECT_NO_CHILDREN(elem1);
9237     EXPECT_NO_CHILDREN(elem2);
9238     EXPECT_NO_CHILDREN(elem3);
9239 
9240     todo_wine EXPECT_REF(elem2, 2);
9241 
9242     /* document to element */
9243     V_VT(&v) = VT_DISPATCH;
9244     V_DISPATCH(&v) = NULL;
9245     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)doc, v, NULL);
9246     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9247 
9248     V_VT(&v) = VT_DISPATCH;
9249     V_DISPATCH(&v) = NULL;
9250     node = NULL;
9251     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem4, v, &node);
9252     ok(hr == S_OK, "got 0x%08x\n", hr);
9253     ok(node == (void*)elem4, "got %p\n", node);
9254 
9255     EXPECT_CHILDREN(elem1);
9256     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem4, NULL);
9257     EXPECT_HR(hr, S_OK);
9258     IXMLDOMElement_Release(elem4);
9259 
9260     EXPECT_NO_CHILDREN(elem1);
9261 
9262     V_VT(&v) = VT_NULL;
9263     node = NULL;
9264     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9265     ok(hr == S_OK, "got 0x%08x\n", hr);
9266     ok(node == (void*)elem2, "got %p\n", node);
9267 
9268     EXPECT_CHILDREN(elem1);
9269     todo_wine EXPECT_REF(elem2, 3);
9270     IXMLDOMNode_Release(node);
9271 
9272     /* again for already linked node */
9273     V_VT(&v) = VT_NULL;
9274     node = NULL;
9275     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9276     ok(hr == S_OK, "got 0x%08x\n", hr);
9277     ok(node == (void*)elem2, "got %p\n", node);
9278 
9279     EXPECT_CHILDREN(elem1);
9280 
9281     /* increments each time */
9282     todo_wine EXPECT_REF(elem2, 3);
9283     IXMLDOMNode_Release(node);
9284 
9285     /* try to add to another element */
9286     V_VT(&v) = VT_NULL;
9287     node = (void*)0xdeadbeef;
9288     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem2, v, &node);
9289     ok(hr == S_OK, "got 0x%08x\n", hr);
9290     ok(node == (void*)elem2, "got %p\n", node);
9291 
9292     EXPECT_CHILDREN(elem3);
9293     EXPECT_NO_CHILDREN(elem1);
9294 
9295     IXMLDOMNode_Release(node);
9296 
9297     /* cross document case - try to add as child to a node created with other doc */
9298     doc2 = create_document(&IID_IXMLDOMDocument);
9299 
9300     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem4);
9301     ok(hr == S_OK, "got 0x%08x\n", hr);
9302     todo_wine EXPECT_REF(elem4, 2);
9303 
9304     /* same name, another instance */
9305     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem5);
9306     ok(hr == S_OK, "got 0x%08x\n", hr);
9307     todo_wine EXPECT_REF(elem5, 2);
9308 
9309     todo_wine EXPECT_REF(elem3, 2);
9310     V_VT(&v) = VT_NULL;
9311     node = NULL;
9312     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem4, v, &node);
9313     ok(hr == S_OK, "got 0x%08x\n", hr);
9314     ok(node == (void*)elem4, "got %p\n", node);
9315     todo_wine EXPECT_REF(elem4, 3);
9316     todo_wine EXPECT_REF(elem3, 2);
9317     IXMLDOMNode_Release(node);
9318 
9319     V_VT(&v) = VT_NULL;
9320     node = NULL;
9321     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem5, v, &node);
9322     ok(hr == S_OK, "got 0x%08x\n", hr);
9323     ok(node == (void*)elem5, "got %p\n", node);
9324     todo_wine EXPECT_REF(elem4, 2);
9325     todo_wine EXPECT_REF(elem5, 3);
9326     IXMLDOMNode_Release(node);
9327 
9328     IXMLDOMDocument_Release(doc2);
9329 
9330     IXMLDOMElement_Release(elem1);
9331     IXMLDOMElement_Release(elem2);
9332     IXMLDOMElement_Release(elem3);
9333     IXMLDOMElement_Release(elem4);
9334     IXMLDOMElement_Release(elem5);
9335 
9336     /* elements with same default namespace */
9337     V_VT(&v) = VT_I4;
9338     V_I4(&v) = NODE_ELEMENT;
9339     elem1 = NULL;
9340     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9341     ok(hr == S_OK, "got 0x%08x\n", hr);
9342     ok(elem1 != NULL, "got %p\n", elem1);
9343 
9344     V_VT(&v) = VT_I4;
9345     V_I4(&v) = NODE_ELEMENT;
9346     elem2 = NULL;
9347     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem2);
9348     ok(hr == S_OK, "got 0x%08x\n", hr);
9349     ok(elem2 != NULL, "got %p\n", elem2);
9350 
9351     /* check contents so far */
9352     p = NULL;
9353     hr = IXMLDOMElement_get_xml(elem1, &p);
9354     ok(hr == S_OK, "got 0x%08x\n", hr);
9355     ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9356     SysFreeString(p);
9357 
9358     p = NULL;
9359     hr = IXMLDOMElement_get_xml(elem2, &p);
9360     ok(hr == S_OK, "got 0x%08x\n", hr);
9361     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9362     SysFreeString(p);
9363 
9364     V_VT(&v) = VT_NULL;
9365     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9366     ok(hr == S_OK, "got 0x%08x\n", hr);
9367 
9368     /* get_xml depends on context, for top node it omits child namespace attribute,
9369        but at child level it's still returned */
9370     p = NULL;
9371     hr = IXMLDOMElement_get_xml(elem1, &p);
9372     ok(hr == S_OK, "got 0x%08x\n", hr);
9373     todo_wine ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"><elem2/></elem1>")),
9374         "got %s\n", wine_dbgstr_w(p));
9375     SysFreeString(p);
9376 
9377     p = NULL;
9378     hr = IXMLDOMElement_get_xml(elem2, &p);
9379     ok(hr == S_OK, "got 0x%08x\n", hr);
9380     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9381     SysFreeString(p);
9382 
9383     IXMLDOMElement_Release(elem1);
9384     IXMLDOMElement_Release(elem2);
9385 
9386     /* child without default namespace added to node with default namespace */
9387     V_VT(&v) = VT_I4;
9388     V_I4(&v) = NODE_ELEMENT;
9389     elem1 = NULL;
9390     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9391     ok(hr == S_OK, "got 0x%08x\n", hr);
9392     ok(elem1 != NULL, "got %p\n", elem1);
9393 
9394     V_VT(&v) = VT_I4;
9395     V_I4(&v) = NODE_ELEMENT;
9396     elem2 = NULL;
9397     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), NULL, (IXMLDOMNode**)&elem2);
9398     ok(hr == S_OK, "got 0x%08x\n", hr);
9399     ok(elem2 != NULL, "got %p\n", elem2);
9400 
9401     EXPECT_REF(elem2, 1);
9402     V_VT(&v) = VT_NULL;
9403     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9404     ok(hr == S_OK, "got 0x%08x\n", hr);
9405     EXPECT_REF(elem2, 1);
9406 
9407     p = NULL;
9408     hr = IXMLDOMElement_get_xml(elem2, &p);
9409     ok(hr == S_OK, "got 0x%08x\n", hr);
9410     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9411     SysFreeString(p);
9412 
9413     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem2, NULL);
9414     ok(hr == S_OK, "got 0x%08x\n", hr);
9415 
9416     p = NULL;
9417     hr = IXMLDOMElement_get_xml(elem2, &p);
9418     ok(hr == S_OK, "got 0x%08x\n", hr);
9419     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9420     SysFreeString(p);
9421 
9422     IXMLDOMElement_Release(elem1);
9423     IXMLDOMElement_Release(elem2);
9424     IXMLDOMDocument_Release(doc);
9425 }
9426 
9427 static void test_appendChild(void)
9428 {
9429     IXMLDOMDocument *doc, *doc2;
9430     IXMLDOMElement *elem, *elem2;
9431     HRESULT hr;
9432 
9433     doc = create_document(&IID_IXMLDOMDocument);
9434     doc2 = create_document(&IID_IXMLDOMDocument);
9435 
9436     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
9437     ok(hr == S_OK, "got 0x%08x\n", hr);
9438 
9439     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
9440     ok(hr == S_OK, "got 0x%08x\n", hr);
9441 
9442     EXPECT_REF(doc, 1);
9443     todo_wine EXPECT_REF(elem, 2);
9444     EXPECT_REF(doc2, 1);
9445     todo_wine EXPECT_REF(elem2, 2);
9446     EXPECT_NO_CHILDREN(doc);
9447     EXPECT_NO_CHILDREN(doc2);
9448 
9449     hr = IXMLDOMDocument_appendChild(doc2, NULL, NULL);
9450     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9451 
9452     hr = IXMLDOMElement_appendChild(elem, NULL, NULL);
9453     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9454 
9455     /* append from another document */
9456     hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
9457     ok(hr == S_OK, "got 0x%08x\n", hr);
9458 
9459     EXPECT_REF(doc, 1);
9460     todo_wine EXPECT_REF(elem, 2);
9461     EXPECT_REF(doc2, 1);
9462     todo_wine EXPECT_REF(elem2, 2);
9463     EXPECT_NO_CHILDREN(doc);
9464     EXPECT_CHILDREN(doc2);
9465 
9466     IXMLDOMElement_Release(elem);
9467     IXMLDOMElement_Release(elem2);
9468     IXMLDOMDocument_Release(doc);
9469     IXMLDOMDocument_Release(doc2);
9470 }
9471 
9472 static void test_get_doctype(void)
9473 {
9474     static const WCHAR emailW[] = {'e','m','a','i','l',0};
9475     IXMLDOMDocumentType *doctype;
9476     IXMLDOMDocument *doc;
9477     VARIANT_BOOL b;
9478     HRESULT hr;
9479     BSTR s;
9480 
9481     doc = create_document(&IID_IXMLDOMDocument);
9482 
9483     hr = IXMLDOMDocument_get_doctype(doc, NULL);
9484     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9485 
9486     doctype = (void*)0xdeadbeef;
9487     hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9488     ok(hr == S_FALSE, "got 0x%08x\n", hr);
9489     ok(doctype == NULL, "got %p\n", doctype);
9490 
9491     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szEmailXML), &b);
9492     ok(hr == S_OK, "got 0x%08x\n", hr);
9493     ok(b == VARIANT_TRUE, "failed to load XML string\n");
9494 
9495     doctype = NULL;
9496     hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9497     ok(hr == S_OK, "got 0x%08x\n", hr);
9498     ok(doctype != NULL, "got %p\n", doctype);
9499 
9500     hr = IXMLDOMDocumentType_get_name(doctype, NULL);
9501     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9502 
9503     hr = IXMLDOMDocumentType_get_name(doctype, &s);
9504     ok(hr == S_OK, "got 0x%08x\n", hr);
9505     ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9506     SysFreeString(s);
9507 
9508     hr = IXMLDOMDocumentType_get_nodeName(doctype, &s);
9509     ok(hr == S_OK, "got 0x%08x\n", hr);
9510     ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9511     SysFreeString(s);
9512 
9513     IXMLDOMDocumentType_Release(doctype);
9514     IXMLDOMDocument_Release(doc);
9515 }
9516 
9517 static void test_get_tagName(void)
9518 {
9519     IXMLDOMDocument *doc;
9520     IXMLDOMElement *elem, *elem2;
9521     HRESULT hr;
9522     BSTR str;
9523 
9524     doc = create_document(&IID_IXMLDOMDocument);
9525 
9526     hr = IXMLDOMDocument_createElement(doc, _bstr_("element"), &elem);
9527     ok(hr == S_OK, "got 0x%08x\n", hr);
9528 
9529     hr = IXMLDOMElement_get_tagName(elem, NULL);
9530     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9531 
9532     str = NULL;
9533     hr = IXMLDOMElement_get_tagName(elem, &str);
9534     ok(hr == S_OK, "got 0x%08x\n", hr);
9535     ok(!lstrcmpW(str, _bstr_("element")), "got %s\n", wine_dbgstr_w(str));
9536     SysFreeString(str);
9537 
9538     hr = IXMLDOMDocument_createElement(doc, _bstr_("s:element"), &elem2);
9539     ok(hr == S_OK, "got 0x%08x\n", hr);
9540 
9541     str = NULL;
9542     hr = IXMLDOMElement_get_tagName(elem2, &str);
9543     ok(hr == S_OK, "got 0x%08x\n", hr);
9544     ok(!lstrcmpW(str, _bstr_("s:element")), "got %s\n", wine_dbgstr_w(str));
9545     SysFreeString(str);
9546 
9547     IXMLDOMElement_Release(elem);
9548     IXMLDOMElement_Release(elem2);
9549     IXMLDOMDocument_Release(doc);
9550     free_bstrs();
9551 }
9552 
9553 typedef struct {
9554     DOMNodeType type;
9555     const char *name;
9556     VARTYPE vt;
9557     HRESULT hr;
9558 } node_type_t;
9559 
9560 static const node_type_t get_datatype[] = {
9561     { NODE_ELEMENT,                "element",   VT_NULL, S_FALSE },
9562     { NODE_ATTRIBUTE,              "attr",      VT_NULL, S_FALSE },
9563     { NODE_TEXT,                   "text",      VT_NULL, S_FALSE },
9564     { NODE_CDATA_SECTION ,         "cdata",     VT_NULL, S_FALSE },
9565     { NODE_ENTITY_REFERENCE,       "entityref", VT_NULL, S_FALSE },
9566     { NODE_PROCESSING_INSTRUCTION, "pi",        VT_NULL, S_FALSE },
9567     { NODE_COMMENT,                "comment",   VT_NULL, S_FALSE },
9568     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   VT_NULL, S_FALSE },
9569     { 0 }
9570 };
9571 
9572 static void test_get_dataType(void)
9573 {
9574     const node_type_t *entry = get_datatype;
9575     IXMLDOMDocument *doc;
9576 
9577     doc = create_document(&IID_IXMLDOMDocument);
9578 
9579     while (entry->type)
9580     {
9581         IXMLDOMNode *node = NULL;
9582         VARIANT var, type;
9583         HRESULT hr;
9584 
9585         V_VT(&var) = VT_I4;
9586         V_I4(&var) = entry->type;
9587         hr = IXMLDOMDocument_createNode(doc, var, _bstr_(entry->name), NULL, &node);
9588         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9589 
9590         hr = IXMLDOMNode_get_dataType(node, NULL);
9591         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9592 
9593         VariantInit(&type);
9594         hr = IXMLDOMNode_get_dataType(node, &type);
9595         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9596             hr, entry->hr, entry->type);
9597         ok(V_VT(&type) == entry->vt, "got %d, expected %d. node type %d\n",
9598             V_VT(&type), entry->vt, entry->type);
9599         VariantClear(&type);
9600 
9601         IXMLDOMNode_Release(node);
9602 
9603         entry++;
9604     }
9605 
9606     IXMLDOMDocument_Release(doc);
9607     free_bstrs();
9608 }
9609 
9610 typedef struct _get_node_typestring_t {
9611     DOMNodeType type;
9612     const char *string;
9613 } get_node_typestring_t;
9614 
9615 static const get_node_typestring_t get_node_typestring[] = {
9616     { NODE_ELEMENT,                "element"               },
9617     { NODE_ATTRIBUTE,              "attribute"             },
9618     { NODE_TEXT,                   "text"                  },
9619     { NODE_CDATA_SECTION ,         "cdatasection"          },
9620     { NODE_ENTITY_REFERENCE,       "entityreference"       },
9621     { NODE_PROCESSING_INSTRUCTION, "processinginstruction" },
9622     { NODE_COMMENT,                "comment"               },
9623     { NODE_DOCUMENT_FRAGMENT,      "documentfragment"      },
9624     { 0 }
9625 };
9626 
9627 static void test_get_nodeTypeString(void)
9628 {
9629     const get_node_typestring_t *entry = get_node_typestring;
9630     IXMLDOMDocument *doc;
9631     HRESULT hr;
9632     BSTR str;
9633 
9634     doc = create_document(&IID_IXMLDOMDocument);
9635 
9636     hr = IXMLDOMDocument_get_nodeTypeString(doc, &str);
9637     ok(hr == S_OK, "got 0x%08x\n", hr);
9638     ok(!lstrcmpW(str, _bstr_("document")), "got string %s\n", wine_dbgstr_w(str));
9639     SysFreeString(str);
9640 
9641     while (entry->type)
9642     {
9643         IXMLDOMNode *node = NULL;
9644         VARIANT var;
9645 
9646         V_VT(&var) = VT_I4;
9647         V_I4(&var) = entry->type;
9648         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9649         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9650 
9651         hr = IXMLDOMNode_get_nodeTypeString(node, NULL);
9652         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9653 
9654         hr = IXMLDOMNode_get_nodeTypeString(node, &str);
9655         ok(hr == S_OK, "got 0x%08x\n", hr);
9656         ok(!lstrcmpW(str, _bstr_(entry->string)), "got string %s, expected %s. node type %d\n",
9657             wine_dbgstr_w(str), entry->string, entry->type);
9658         SysFreeString(str);
9659         IXMLDOMNode_Release(node);
9660 
9661         entry++;
9662     }
9663 
9664     IXMLDOMDocument_Release(doc);
9665     free_bstrs();
9666 }
9667 
9668 typedef struct _get_attributes_t {
9669     DOMNodeType type;
9670     HRESULT hr;
9671 } get_attributes_t;
9672 
9673 static const get_attributes_t get_attributes[] = {
9674     { NODE_ATTRIBUTE,              S_FALSE },
9675     { NODE_TEXT,                   S_FALSE },
9676     { NODE_CDATA_SECTION ,         S_FALSE },
9677     { NODE_ENTITY_REFERENCE,       S_FALSE },
9678     { NODE_PROCESSING_INSTRUCTION, S_FALSE },
9679     { NODE_COMMENT,                S_FALSE },
9680     { NODE_DOCUMENT_FRAGMENT,      S_FALSE },
9681     { 0 }
9682 };
9683 
9684 static void test_get_attributes(void)
9685 {
9686     const get_attributes_t *entry = get_attributes;
9687     IXMLDOMNamedNodeMap *map;
9688     IXMLDOMDocument *doc, *doc2;
9689     IXMLDOMNode *node, *node2;
9690     IXMLDOMElement *elem;
9691     VARIANT_BOOL b;
9692     HRESULT hr;
9693     VARIANT v;
9694     BSTR str;
9695     LONG length;
9696 
9697     doc = create_document(&IID_IXMLDOMDocument);
9698 
9699     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
9700     ok(hr == S_OK, "got %08x\n", hr);
9701 
9702     hr = IXMLDOMDocument_get_attributes(doc, NULL);
9703     ok(hr == E_INVALIDARG, "got %08x\n", hr);
9704 
9705     map = (void*)0xdeadbeef;
9706     hr = IXMLDOMDocument_get_attributes(doc, &map);
9707     ok(hr == S_FALSE, "got %08x\n", hr);
9708     ok(map == NULL, "got %p\n", map);
9709 
9710     /* first child is <?xml ?> */
9711     hr = IXMLDOMDocument_get_firstChild(doc, &node);
9712     ok(hr == S_OK, "got %08x\n", hr);
9713 
9714     hr = IXMLDOMNode_get_attributes(node, &map);
9715     ok(hr == S_OK, "got %08x\n", hr);
9716 
9717     node2 = (void*)0xdeadbeef;
9718     hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_("attr"), &node2);
9719     ok(hr == S_FALSE, "got %08x\n", hr);
9720     ok(node2 == NULL, "got %p\n", node2);
9721 
9722     length = -1;
9723     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9724     EXPECT_HR(hr, S_OK);
9725     todo_wine ok(length == 1, "got %d\n", length);
9726 
9727     if (hr == S_OK && length == 1)
9728     {
9729         IXMLDOMAttribute *attr;
9730         DOMNodeType type;
9731         VARIANT v;
9732 
9733         node2 = NULL;
9734         hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9735         EXPECT_HR(hr, S_OK);
9736         ok(node != NULL, "got %p\n", node2);
9737 
9738         hr = IXMLDOMNode_get_nodeName(node2, &str);
9739         EXPECT_HR(hr, S_OK);
9740         ok(!lstrcmpW(str, _bstr_("version")), "got %s\n", wine_dbgstr_w(str));
9741         SysFreeString(str);
9742 
9743         length = -1;
9744         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9745         EXPECT_HR(hr, S_OK);
9746         ok(length == 1, "got %d\n", length);
9747 
9748         type = -1;
9749         hr = IXMLDOMNode_get_nodeType(node2, &type);
9750         EXPECT_HR(hr, S_OK);
9751         ok(type == NODE_ATTRIBUTE, "got %d\n", type);
9752 
9753         hr = IXMLDOMNode_get_xml(node, &str);
9754         EXPECT_HR(hr, S_OK);
9755         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9756         SysFreeString(str);
9757 
9758         hr = IXMLDOMNode_get_text(node, &str);
9759         EXPECT_HR(hr, S_OK);
9760         ok(!lstrcmpW(str, _bstr_("version=\"1.0\"")), "got %s\n", wine_dbgstr_w(str));
9761         SysFreeString(str);
9762 
9763         hr = IXMLDOMNamedNodeMap_removeNamedItem(map, _bstr_("version"), NULL);
9764         EXPECT_HR(hr, S_OK);
9765 
9766         length = -1;
9767         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9768         EXPECT_HR(hr, S_OK);
9769         ok(length == 0, "got %d\n", length);
9770 
9771         hr = IXMLDOMNode_get_xml(node, &str);
9772         EXPECT_HR(hr, S_OK);
9773         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9774         SysFreeString(str);
9775 
9776         hr = IXMLDOMNode_get_text(node, &str);
9777         EXPECT_HR(hr, S_OK);
9778         ok(!lstrcmpW(str, _bstr_("")), "got %s\n", wine_dbgstr_w(str));
9779         SysFreeString(str);
9780 
9781         IXMLDOMNamedNodeMap_Release(map);
9782 
9783         hr = IXMLDOMNode_get_attributes(node, &map);
9784         ok(hr == S_OK, "got %08x\n", hr);
9785 
9786         length = -1;
9787         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9788         EXPECT_HR(hr, S_OK);
9789         ok(length == 0, "got %d\n", length);
9790 
9791         hr = IXMLDOMDocument_createAttribute(doc, _bstr_("encoding"), &attr);
9792         EXPECT_HR(hr, S_OK);
9793 
9794         V_VT(&v) = VT_BSTR;
9795         V_BSTR(&v) = _bstr_("UTF-8");
9796         hr = IXMLDOMAttribute_put_nodeValue(attr, v);
9797         EXPECT_HR(hr, S_OK);
9798 
9799         EXPECT_REF(attr, 2);
9800         hr = IXMLDOMNamedNodeMap_setNamedItem(map, (IXMLDOMNode*)attr, NULL);
9801         EXPECT_HR(hr, S_OK);
9802         EXPECT_REF(attr, 2);
9803 
9804         hr = IXMLDOMNode_get_attributes(node, &map);
9805         ok(hr == S_OK, "got %08x\n", hr);
9806 
9807         length = -1;
9808         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9809         EXPECT_HR(hr, S_OK);
9810         ok(length == 1, "got %d\n", length);
9811 
9812         hr = IXMLDOMNode_get_xml(node, &str);
9813         EXPECT_HR(hr, S_OK);
9814         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9815         SysFreeString(str);
9816 
9817         hr = IXMLDOMNode_get_text(node, &str);
9818         EXPECT_HR(hr, S_OK);
9819         ok(!lstrcmpW(str, _bstr_("encoding=\"UTF-8\"")), "got %s\n", wine_dbgstr_w(str));
9820         SysFreeString(str);
9821 
9822         IXMLDOMNamedNodeMap_Release(map);
9823         IXMLDOMNode_Release(node2);
9824     }
9825 
9826     IXMLDOMNode_Release(node);
9827 
9828     /* last child is element */
9829     EXPECT_REF(doc, 1);
9830     hr = IXMLDOMDocument_get_lastChild(doc, &node);
9831     ok(hr == S_OK, "got %08x\n", hr);
9832     EXPECT_REF(doc, 1);
9833 
9834     EXPECT_REF(node, 1);
9835     hr = IXMLDOMNode_get_attributes(node, &map);
9836     ok(hr == S_OK, "got %08x\n", hr);
9837     EXPECT_REF(node, 1);
9838     EXPECT_REF(doc, 1);
9839 
9840     EXPECT_REF(map, 1);
9841     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9842     ok(hr == S_OK, "got %08x\n", hr);
9843     EXPECT_REF(node, 1);
9844     EXPECT_REF(node2, 1);
9845     EXPECT_REF(map, 1);
9846     EXPECT_REF(doc, 1);
9847     IXMLDOMNode_Release(node2);
9848 
9849     /* release node before map release, map still works */
9850     IXMLDOMNode_Release(node);
9851 
9852     length = 0;
9853     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9854     ok(hr == S_OK, "got %08x\n", hr);
9855     ok(length == 1, "got %d\n", length);
9856 
9857     node2 = NULL;
9858     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9859     ok(hr == S_OK, "got %08x\n", hr);
9860     EXPECT_REF(node2, 1);
9861     IXMLDOMNode_Release(node2);
9862 
9863     IXMLDOMNamedNodeMap_Release(map);
9864 
9865     /* append created element a different document, map still works */
9866     hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
9867     ok(hr == S_OK, "createElement failed: %08x\n", hr);
9868 
9869     V_VT(&v) = VT_I4;
9870     V_I4(&v) = 1;
9871     hr = IXMLDOMElement_setAttribute(elem, _bstr_("testattr"), v);
9872     ok(hr == S_OK, "setAttribute failed: %08x\n", hr);
9873 
9874     hr = IXMLDOMElement_get_attributes(elem, &map);
9875     ok(hr == S_OK, "get_attributes failed: %08x\n", hr);
9876 
9877     length = 0;
9878     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9879     ok(hr == S_OK, "got %08x\n", hr);
9880     ok(length == 1, "got %d\n", length);
9881 
9882     doc2 = create_document(&IID_IXMLDOMDocument);
9883 
9884     hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, &node);
9885     ok(hr == S_OK, "appendChild failed: %08x\n", hr);
9886     ok(node == (IXMLDOMNode*)elem, "node != elem\n");
9887     IXMLDOMNode_Release(node);
9888     IXMLDOMElement_Release(elem);
9889     IXMLDOMDocument_Release(doc2);
9890 
9891     length = 0;
9892     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9893     ok(hr == S_OK, "got %08x\n", hr);
9894     ok(length == 1, "got %d\n", length);
9895 
9896     IXMLDOMNamedNodeMap_Release(map);
9897 
9898     while (entry->type)
9899     {
9900         VARIANT var;
9901 
9902         node = NULL;
9903 
9904         V_VT(&var) = VT_I4;
9905         V_I4(&var) = entry->type;
9906         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9907         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9908 
9909         hr = IXMLDOMNode_get_attributes(node, NULL);
9910         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9911 
9912         map = (void*)0xdeadbeef;
9913         hr = IXMLDOMNode_get_attributes(node, &map);
9914         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9915             hr, entry->hr, entry->type);
9916         ok(map == NULL, "got %p\n", map);
9917 
9918         IXMLDOMNode_Release(node);
9919 
9920         entry++;
9921     }
9922 
9923     IXMLDOMDocument_Release(doc);
9924     free_bstrs();
9925 }
9926 
9927 static void test_selection(void)
9928 {
9929     IXMLDOMSelection *selection, *selection2;
9930     IEnumVARIANT *enum1, *enum2, *enum3;
9931     IXMLDOMNodeList *list;
9932     IUnknown *unk1, *unk2;
9933     IXMLDOMDocument *doc;
9934     IDispatchEx *dispex;
9935     IXMLDOMNode *node;
9936     IDispatch *disp;
9937     VARIANT_BOOL b;
9938     HRESULT hr;
9939     DISPID did;
9940     VARIANT v;
9941     BSTR name;
9942     ULONG ret;
9943     LONG len;
9944 
9945     doc = create_document(&IID_IXMLDOMDocument);
9946 
9947     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
9948     EXPECT_HR(hr, S_OK);
9949 
9950     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list);
9951     EXPECT_HR(hr, S_OK);
9952 
9953     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9954     EXPECT_HR(hr, S_OK);
9955     IXMLDOMSelection_Release(selection);
9956 
9957     /* collection disp id */
9958     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IDispatchEx, (void**)&dispex);
9959     EXPECT_HR(hr, S_OK);
9960     did = 0;
9961     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
9962     EXPECT_HR(hr, S_OK);
9963     ok(did == DISPID_DOM_COLLECTION_BASE, "got %d\n", did);
9964     len = 0;
9965     hr = IXMLDOMSelection_get_length(selection, &len);
9966     EXPECT_HR(hr, S_OK);
9967     ok(len == 1, "got %d\n", len);
9968     hr = IDispatchEx_GetDispID(dispex, _bstr_("10"), 0, &did);
9969     EXPECT_HR(hr, S_OK);
9970     ok(did == DISPID_DOM_COLLECTION_BASE+10, "got %d\n", did);
9971     IDispatchEx_Release(dispex);
9972 
9973     /* IEnumVARIANT tests */
9974     enum1 = NULL;
9975     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum1);
9976     EXPECT_HR(hr, S_OK);
9977     ok(enum1 != NULL, "got %p\n", enum1);
9978     EXPECT_REF(enum1, 2);
9979 
9980     EXPECT_REF(selection, 1);
9981     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IUnknown, (void**)&unk1);
9982     EXPECT_HR(hr, S_OK);
9983     EXPECT_REF(selection, 2);
9984     EXPECT_REF(enum1, 2);
9985 
9986     /* enumerator and selection object return same IUnknown* */
9987     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
9988     EXPECT_HR(hr, S_OK);
9989     EXPECT_REF(selection, 3);
9990     EXPECT_REF(enum1, 2);
9991     ok(unk2 == unk1, "got %p, %p\n", unk1, unk2);
9992     IUnknown_Release(unk2);
9993 
9994     EXPECT_REF(selection, 2);
9995     IEnumVARIANT_AddRef(enum1);
9996     EXPECT_REF(selection, 2);
9997     IEnumVARIANT_Release(enum1);
9998 
9999     enum3 = NULL;
10000     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum3);
10001     EXPECT_HR(hr, S_OK);
10002     ok(enum3 != NULL, "got %p\n", enum3);
10003     ok(enum1 == enum3, "got %p and %p\n", enum1, enum3);
10004     EXPECT_REF(enum1, 3);
10005     IEnumVARIANT_Release(enum3);
10006 
10007     EXPECT_REF(selection, 2);
10008     EXPECT_REF(enum1, 2);
10009 
10010     enum2 = NULL;
10011     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
10012     EXPECT_HR(hr, S_OK);
10013     ok(enum2 != NULL, "got %p\n", enum2);
10014 
10015     EXPECT_REF(selection, 3);
10016     EXPECT_REF(enum1, 2);
10017     EXPECT_REF(enum2, 1);
10018 
10019     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10020 
10021     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
10022     EXPECT_HR(hr, S_OK);
10023     EXPECT_REF(selection, 3);
10024     EXPECT_REF(enum2, 2);
10025     ok(unk2 != unk1, "got %p, %p\n", unk1, unk2);
10026     IUnknown_Release(unk2);
10027     IUnknown_Release(unk1);
10028 
10029     selection2 = NULL;
10030     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IXMLDOMSelection, (void**)&selection2);
10031     EXPECT_HR(hr, S_OK);
10032     ok(selection2 == selection, "got %p and %p\n", selection, selection2);
10033     EXPECT_REF(selection, 3);
10034     EXPECT_REF(enum1, 2);
10035 
10036     IXMLDOMSelection_Release(selection2);
10037 
10038     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IDispatch, (void**)&disp);
10039     EXPECT_HR(hr, S_OK);
10040     EXPECT_REF(selection, 3);
10041     IDispatch_Release(disp);
10042 
10043     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enum3);
10044     EXPECT_HR(hr, S_OK);
10045     ok(enum3 == enum1, "got %p and %p\n", enum3, enum1);
10046     EXPECT_REF(selection, 2);
10047     EXPECT_REF(enum1, 3);
10048 
10049     IEnumVARIANT_Release(enum1);
10050     IEnumVARIANT_Release(enum2);
10051     IEnumVARIANT_Release(enum3);
10052 
10053     enum1 = NULL;
10054     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10055     EXPECT_HR(hr, S_OK);
10056     ok(enum1 != NULL, "got %p\n", enum1);
10057     EXPECT_REF(enum1, 1);
10058     EXPECT_REF(selection, 2);
10059 
10060     enum2 = NULL;
10061     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
10062     EXPECT_HR(hr, S_OK);
10063     ok(enum2 != NULL, "got %p\n", enum2);
10064     EXPECT_REF(enum2, 1);
10065     EXPECT_REF(selection, 3);
10066 
10067     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10068 
10069     IEnumVARIANT_AddRef(enum1);
10070     EXPECT_REF(selection, 3);
10071     EXPECT_REF(enum1, 2);
10072     EXPECT_REF(enum2, 1);
10073     IEnumVARIANT_Release(enum1);
10074 
10075     IEnumVARIANT_Release(enum1);
10076     IEnumVARIANT_Release(enum2);
10077 
10078     EXPECT_REF(selection, 1);
10079 
10080     IXMLDOMNodeList_Release(list);
10081 
10082     hr = IXMLDOMDocument_get_childNodes(doc, &list);
10083     EXPECT_HR(hr, S_OK);
10084 
10085     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10086     EXPECT_HR(hr, E_NOINTERFACE);
10087 
10088     IXMLDOMNodeList_Release(list);
10089 
10090     /* test if IEnumVARIANT touches selection context */
10091     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
10092     EXPECT_HR(hr, S_OK);
10093 
10094     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/*"), &list);
10095     EXPECT_HR(hr, S_OK);
10096 
10097     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10098     EXPECT_HR(hr, S_OK);
10099 
10100     len = 0;
10101     hr = IXMLDOMSelection_get_length(selection, &len);
10102     EXPECT_HR(hr, S_OK);
10103     ok(len == 4, "got %d\n", len);
10104 
10105     enum1 = NULL;
10106     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10107     EXPECT_HR(hr, S_OK);
10108 
10109     /* no-op if zero count */
10110     V_VT(&v) = VT_I2;
10111     hr = IEnumVARIANT_Next(enum1, 0, &v, NULL);
10112     EXPECT_HR(hr, S_OK);
10113     ok(V_VT(&v) == VT_I2, "got var type %d\n", V_VT(&v));
10114 
10115     /* positive count, null array pointer */
10116     hr = IEnumVARIANT_Next(enum1, 1, NULL, NULL);
10117     EXPECT_HR(hr, E_INVALIDARG);
10118 
10119     ret = 1;
10120     hr = IEnumVARIANT_Next(enum1, 1, NULL, &ret);
10121     EXPECT_HR(hr, E_INVALIDARG);
10122     ok(ret == 0, "got %d\n", ret);
10123 
10124     V_VT(&v) = VT_I2;
10125     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10126     EXPECT_HR(hr, S_OK);
10127     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10128 
10129     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10130     EXPECT_HR(hr, S_OK);
10131     hr = IXMLDOMNode_get_nodeName(node, &name);
10132     EXPECT_HR(hr, S_OK);
10133     ok(!lstrcmpW(name, _bstr_("a")), "got node name %s\n", wine_dbgstr_w(name));
10134     SysFreeString(name);
10135     IXMLDOMNode_Release(node);
10136     VariantClear(&v);
10137 
10138     /* list cursor is updated */
10139     hr = IXMLDOMSelection_nextNode(selection, &node);
10140     EXPECT_HR(hr, S_OK);
10141     hr = IXMLDOMNode_get_nodeName(node, &name);
10142     EXPECT_HR(hr, S_OK);
10143     ok(!lstrcmpW(name, _bstr_("c")), "got node name %s\n", wine_dbgstr_w(name));
10144     IXMLDOMNode_Release(node);
10145     SysFreeString(name);
10146 
10147     V_VT(&v) = VT_I2;
10148     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10149     EXPECT_HR(hr, S_OK);
10150     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10151     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10152     EXPECT_HR(hr, S_OK);
10153     hr = IXMLDOMNode_get_nodeName(node, &name);
10154     EXPECT_HR(hr, S_OK);
10155     ok(!lstrcmpW(name, _bstr_("b")), "got node name %s\n", wine_dbgstr_w(name));
10156     SysFreeString(name);
10157     IXMLDOMNode_Release(node);
10158     VariantClear(&v);
10159     IEnumVARIANT_Release(enum1);
10160 
10161     hr = IXMLDOMSelection_nextNode(selection, &node);
10162     EXPECT_HR(hr, S_OK);
10163     hr = IXMLDOMNode_get_nodeName(node, &name);
10164     EXPECT_HR(hr, S_OK);
10165     ok(!lstrcmpW(name, _bstr_("d")), "got node name %s\n", wine_dbgstr_w(name));
10166     IXMLDOMNode_Release(node);
10167     SysFreeString(name);
10168 
10169     IXMLDOMSelection_Release(selection);
10170     IXMLDOMNodeList_Release(list);
10171     IXMLDOMDocument_Release(doc);
10172 
10173     free_bstrs();
10174 }
10175 
10176 static void write_to_file(const char *name, const char *data)
10177 {
10178     DWORD written;
10179     HANDLE hfile;
10180     BOOL ret;
10181 
10182     hfile = CreateFileA(name, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
10183     ok(hfile != INVALID_HANDLE_VALUE, "failed to create test file: %s\n", name);
10184 
10185     ret = WriteFile(hfile, data, strlen(data), &written, NULL);
10186     ok(ret, "WriteFile failed: %s, %d\n", name, GetLastError());
10187 
10188     CloseHandle(hfile);
10189 }
10190 
10191 static void test_doc_load_from_path(IXMLDOMDocument *doc, const char *path)
10192 {
10193     IXMLDOMDocument *doc2;
10194     IXMLDOMElement *elem;
10195     BSTR url, url2;
10196     VARIANT_BOOL b;
10197     VARIANT src;
10198     HRESULT hr;
10199 
10200     url = _bstr_(path);
10201 
10202     V_VT(&src) = VT_BSTR;
10203     V_BSTR(&src) = url;
10204     hr = IXMLDOMDocument_load(doc, src, &b);
10205     ok(hr == S_OK, "Failed to load document, %#x.\n", hr);
10206     ok(b == VARIANT_TRUE, "got %d\n", b);
10207 
10208     V_VT(&src) = VT_BSTR | VT_BYREF;
10209     V_BSTRREF(&src) = &url;
10210     hr = IXMLDOMDocument_load(doc, src, &b);
10211     ok(hr == S_OK, "Failed to load document, %#x.\n", hr);
10212     ok(b == VARIANT_TRUE, "got %d\n", b);
10213 
10214     url = NULL;
10215     hr = IXMLDOMDocument_get_url(doc, &url);
10216     ok(hr == S_OK, "Failed to get document url, hr %#x.\n", hr);
10217 
10218     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10219     ok(hr == S_OK, "got 0x%08x\n", hr);
10220 
10221     /* Create another instance for the same document, check url */
10222     hr = IXMLDOMElement_get_ownerDocument(elem, &doc2);
10223     ok(hr == S_OK, "Failed to get owner document, hr %#x.\n", hr);
10224 
10225     hr = IXMLDOMDocument_get_url(doc2, &url2);
10226     ok(hr == S_OK, "Failed to get document url, hr %#x.\n", hr);
10227     ok(!lstrcmpW(url, url2), "Unexpected url %s.\n", wine_dbgstr_w(url2));
10228 
10229     IXMLDOMDocument_Release(doc2);
10230     IXMLDOMElement_Release(elem);
10231     SysFreeString(url2);
10232     SysFreeString(url);
10233 }
10234 
10235 static void url_forward_slash(char *url)
10236 {
10237     char *p = url;
10238 
10239     while (*p)
10240     {
10241         if (*p == '\\')
10242             *p = '/';
10243         p++;
10244     }
10245 }
10246 
10247 static void test_load(void)
10248 {
10249     char path[MAX_PATH], path2[MAX_PATH];
10250     IXMLDOMNodeList *list;
10251     IXMLDOMDocument *doc;
10252     BSTR bstr1, bstr2;
10253     VARIANT_BOOL b;
10254     VARIANT src;
10255     HRESULT hr;
10256     void* ptr;
10257 
10258     GetTempPathA(MAX_PATH, path);
10259     strcat(path, "winetest.xml");
10260 
10261     /* prepare a file */
10262     write_to_file(path, win1252xml);
10263 
10264     doc = create_document(&IID_IXMLDOMDocument);
10265 
10266     /* null pointer as input */
10267     V_VT(&src) = VT_UNKNOWN;
10268     V_UNKNOWN(&src) = NULL;
10269     hr = IXMLDOMDocument_load(doc, src, &b);
10270     EXPECT_HR(hr, E_INVALIDARG);
10271     ok(b == VARIANT_FALSE, "got %d\n", b);
10272 
10273     /* "file://" url */
10274     strcpy(path2, "file://");
10275     strcat(path2, path);
10276     test_doc_load_from_path(doc, path2);
10277 
10278     /* file:// url, forward slashes */
10279     url_forward_slash(path2);
10280     test_doc_load_from_path(doc, path2);
10281 
10282     /* "file:/" url */
10283     strcpy(path2, "file:/");
10284     strcat(path2, path);
10285     test_doc_load_from_path(doc, path);
10286 
10287     /* file:/ with forward slashes. */
10288     url_forward_slash(path2);
10289     test_doc_load_from_path(doc, path2);
10290 
10291     /* Regular local path. */
10292     test_doc_load_from_path(doc, path);
10293 
10294     /* load from a path: VT_BSTR|VT_BYREF, null ptr */
10295     V_VT(&src) = VT_BSTR | VT_BYREF;
10296     V_BSTRREF(&src) = NULL;
10297     hr = IXMLDOMDocument_load(doc, src, &b);
10298     EXPECT_HR(hr, E_INVALIDARG);
10299     ok(b == VARIANT_FALSE, "got %d\n", b);
10300 
10301     bstr1 = NULL;
10302     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10303     ok(hr == S_OK, "got 0x%08x\n", hr);
10304     SysFreeString(bstr1);
10305 
10306     DeleteFileA(path);
10307 
10308     /* load from existing path, no xml content */
10309     write_to_file(path, nocontent);
10310 
10311     V_VT(&src) = VT_BSTR;
10312     V_BSTR(&src) = _bstr_(path);
10313     b = VARIANT_TRUE;
10314     hr = IXMLDOMDocument_load(doc, src, &b);
10315     ok(hr == S_FALSE, "got 0x%08x\n", hr);
10316     ok(b == VARIANT_FALSE, "got %d\n", b);
10317 
10318     bstr1 = (void *)0xdeadbeef;
10319     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10320     ok(hr == S_FALSE, "got 0x%08x\n", hr);
10321     ok(bstr1 == NULL, "got %p\n", bstr1);
10322 
10323     DeleteFileA(path);
10324     IXMLDOMDocument_Release(doc);
10325 
10326     doc = create_document(&IID_IXMLDOMDocument);
10327 
10328     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
10329     EXPECT_HR(hr, S_OK);
10330     ok(b == VARIANT_TRUE, "got %d\n", b);
10331 
10332     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10333     EXPECT_HR(hr, S_OK);
10334     bstr1 = _bstr_(list_to_string(list));
10335 
10336     hr = IXMLDOMNodeList_reset(list);
10337     EXPECT_HR(hr, S_OK);
10338 
10339     IXMLDOMDocument_Release(doc);
10340 
10341     doc = create_document(&IID_IXMLDOMDocument);
10342 
10343     VariantInit(&src);
10344     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenA(szExampleXML));
10345     V_VT(&src) = VT_ARRAY|VT_UI1;
10346     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10347     ptr = NULL;
10348     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10349     EXPECT_HR(hr, S_OK);
10350     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10351 
10352     memcpy(ptr, szExampleXML, lstrlenA(szExampleXML));
10353     hr = SafeArrayUnlock(V_ARRAY(&src));
10354     EXPECT_HR(hr, S_OK);
10355 
10356     hr = IXMLDOMDocument_load(doc, src, &b);
10357     EXPECT_HR(hr, S_OK);
10358     ok(b == VARIANT_TRUE, "got %d\n", b);
10359 
10360     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10361     EXPECT_HR(hr, S_OK);
10362     bstr2 = _bstr_(list_to_string(list));
10363 
10364     hr = IXMLDOMNodeList_reset(list);
10365     EXPECT_HR(hr, S_OK);
10366 
10367     ok(lstrcmpW(bstr1, bstr2) == 0, "strings not equal: %s : %s\n",
10368        wine_dbgstr_w(bstr1), wine_dbgstr_w(bstr2));
10369 
10370     IXMLDOMDocument_Release(doc);
10371     IXMLDOMNodeList_Release(list);
10372     VariantClear(&src);
10373 
10374     /* UTF-16 isn't accepted */
10375     doc = create_document(&IID_IXMLDOMDocument);
10376 
10377     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenW(szComplete1) * sizeof(WCHAR));
10378     V_VT(&src) = VT_ARRAY|VT_UI1;
10379     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10380     ptr = NULL;
10381     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10382     EXPECT_HR(hr, S_OK);
10383     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10384 
10385     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10386     hr = SafeArrayUnlock(V_ARRAY(&src));
10387     EXPECT_HR(hr, S_OK);
10388 
10389     hr = IXMLDOMDocument_load(doc, src, &b);
10390     todo_wine EXPECT_HR(hr, S_FALSE);
10391     todo_wine ok(b == VARIANT_FALSE, "got %d\n", b);
10392 
10393     VariantClear(&src);
10394 
10395     /* it doesn't like it as a VT_ARRAY|VT_UI2 either */
10396     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI2, 0, lstrlenW(szComplete1));
10397     V_VT(&src) = VT_ARRAY|VT_UI2;
10398     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10399     ptr = NULL;
10400     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10401     EXPECT_HR(hr, S_OK);
10402     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10403 
10404     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10405     hr = SafeArrayUnlock(V_ARRAY(&src));
10406     EXPECT_HR(hr, S_OK);
10407 
10408     hr = IXMLDOMDocument_load(doc, src, &b);
10409     todo_wine EXPECT_HR(hr, E_INVALIDARG);
10410     ok(b == VARIANT_FALSE, "got %d\n", b);
10411 
10412     VariantClear(&src);
10413     IXMLDOMDocument_Release(doc);
10414 
10415     free_bstrs();
10416 }
10417 
10418 static void test_domobj_dispex(IUnknown *obj)
10419 {
10420     static const WCHAR testW[] = {'t','e','s','t','p','r','o','p',0};
10421     DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
10422     IDispatchEx *dispex;
10423     IUnknown *unk;
10424     DWORD props;
10425     UINT ticnt;
10426     HRESULT hr;
10427     BSTR name;
10428 
10429     hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
10430     EXPECT_HR(hr, S_OK);
10431     if (FAILED(hr)) return;
10432 
10433     ticnt = 0;
10434     hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
10435     EXPECT_HR(hr, S_OK);
10436     ok(ticnt == 1, "ticnt=%u\n", ticnt);
10437 
10438     name = SysAllocString(szstar);
10439     hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
10440     EXPECT_HR(hr, E_NOTIMPL);
10441     SysFreeString(name);
10442 
10443     hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
10444     EXPECT_HR(hr, E_NOTIMPL);
10445 
10446     props = 0;
10447     hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
10448     EXPECT_HR(hr, E_NOTIMPL);
10449     ok(props == 0, "expected 0 got %d\n", props);
10450 
10451     hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
10452     EXPECT_HR(hr, E_NOTIMPL);
10453     if (SUCCEEDED(hr)) SysFreeString(name);
10454 
10455     hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
10456     EXPECT_HR(hr, E_NOTIMPL);
10457 
10458     unk = (IUnknown*)0xdeadbeef;
10459     hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
10460     EXPECT_HR(hr, E_NOTIMPL);
10461     ok(unk == (IUnknown*)0xdeadbeef, "got %p\n", unk);
10462 
10463     name = SysAllocString(testW);
10464     hr = IDispatchEx_GetDispID(dispex, name, fdexNameEnsure, &dispid);
10465     ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
10466     SysFreeString(name);
10467 
10468     IDispatchEx_Release(dispex);
10469 }
10470 
10471 static void test_mxnamespacemanager(void)
10472 {
10473     static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
10474     IMXNamespacePrefixes *prefixes;
10475     IVBMXNamespaceManager *mgr2;
10476     IMXNamespaceManager *nsmgr;
10477     IUnknown *unk1, *unk2;
10478     WCHAR buffW[250];
10479     IDispatch *disp;
10480     IUnknown *unk;
10481     HRESULT hr;
10482     INT len;
10483 
10484     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10485         &IID_IMXNamespaceManager, (void**)&nsmgr);
10486     EXPECT_HR(hr, S_OK);
10487 
10488     /* IMXNamespaceManager inherits from IUnknown */
10489     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IDispatch, (void**)&disp);
10490     EXPECT_HR(hr, S_OK);
10491     IDispatch_Release(disp);
10492 
10493     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IVBMXNamespaceManager, (void**)&mgr2);
10494     EXPECT_HR(hr, S_OK);
10495 
10496     EXPECT_REF(nsmgr, 2);
10497     EXPECT_REF(mgr2, 2);
10498     prefixes = NULL;
10499     hr = IVBMXNamespaceManager_getDeclaredPrefixes(mgr2, &prefixes);
10500 todo_wine
10501     ok(hr == S_OK, "got 0x%08x\n", hr);
10502     if (hr == S_OK)
10503     {
10504         IDispatchEx *dispex;
10505         VARIANT arg, ret;
10506         DISPPARAMS dispparams;
10507 
10508         ok(prefixes != NULL, "got %p\n", prefixes);
10509         EXPECT_REF(nsmgr, 2);
10510         EXPECT_REF(mgr2, 2);
10511         EXPECT_REF(prefixes, 1);
10512 
10513         IVBMXNamespaceManager_QueryInterface(mgr2, &IID_IUnknown, (void**)&unk1);
10514         IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IUnknown, (void**)&unk2);
10515 
10516         EXPECT_REF(mgr2, 3);
10517         EXPECT_REF(prefixes, 2);
10518 
10519         IUnknown_Release(unk1);
10520         IUnknown_Release(unk2);
10521 
10522         hr = IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IDispatchEx, (void**)&dispex);
10523         ok(hr == S_OK, "got 0x%08x\n", hr);
10524 
10525         V_VT(&arg) = VT_I4;
10526         V_I4(&arg) = 0;
10527         dispparams.cArgs = 1;
10528         dispparams.cNamedArgs = 0;
10529         dispparams.rgdispidNamedArgs = NULL;
10530         dispparams.rgvarg = &arg;
10531 
10532         V_VT(&ret) = VT_EMPTY;
10533         V_DISPATCH(&ret) = (void*)0x1;
10534         hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10535         ok(hr == S_OK, "got 0x%08x\n", hr);
10536         ok(V_VT(&ret) == VT_BSTR, "got %d\n", V_VT(&ret));
10537         ok(V_BSTR(&ret) != NULL, "got %p\n", V_BSTR(&ret));
10538         VariantClear(&ret);
10539 
10540         IDispatchEx_Release(dispex);
10541         IMXNamespacePrefixes_Release(prefixes);
10542     }
10543     IVBMXNamespaceManager_Release(mgr2);
10544 
10545     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10546     EXPECT_HR(hr, S_OK);
10547 
10548     /* prefix already added */
10549     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10550     EXPECT_HR(hr, S_FALSE);
10551 
10552     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
10553     EXPECT_HR(hr, E_INVALIDARG);
10554 
10555     /* "xml" and "xmlns" are not allowed here */
10556     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xml"), _bstr_("uri1"));
10557     EXPECT_HR(hr, E_INVALIDARG);
10558 
10559     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
10560     EXPECT_HR(hr, E_INVALIDARG);
10561 todo_wine {
10562     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
10563     EXPECT_HR(hr, E_FAIL);
10564 }
10565     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
10566     EXPECT_HR(hr, E_POINTER);
10567 
10568     len = -1;
10569     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
10570     EXPECT_HR(hr, S_OK);
10571     ok(len == 3, "got %d\n", len);
10572 
10573     len = -1;
10574     buffW[0] = 0x1;
10575     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10576     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10577     ok(len == -1, "got %d\n", len);
10578     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10579 
10580     len = 10;
10581     buffW[0] = 0x1;
10582     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10583     EXPECT_HR(hr, S_OK);
10584     ok(len == 3, "got %d\n", len);
10585     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10586 
10587     /* getURI */
10588     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, NULL);
10589     EXPECT_HR(hr, E_INVALIDARG);
10590 
10591     len = -1;
10592     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, &len);
10593     EXPECT_HR(hr, E_INVALIDARG);
10594     ok(len == -1, "got %d\n", len);
10595 
10596     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, NULL);
10597     EXPECT_HR(hr, E_POINTER);
10598 
10599     len = -1;
10600     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, &len);
10601     EXPECT_HR(hr, S_OK);
10602     /* length of "xml" uri is constant */
10603     ok(len == strlen(xmluriA), "got %d\n", len);
10604 
10605     len = 100;
10606     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10607     EXPECT_HR(hr, S_OK);
10608     ok(len == strlen(xmluriA), "got %d\n", len);
10609     ok(!lstrcmpW(buffW, _bstr_(xmluriA)), "got prefix %s\n", wine_dbgstr_w(buffW));
10610 
10611     len = strlen(xmluriA)-1;
10612     buffW[0] = 0x1;
10613     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10614     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10615     ok(len == strlen(xmluriA)-1, "got %d\n", len);
10616     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10617 
10618     /* prefix xml1 not defined */
10619     len = -1;
10620     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, NULL, &len);
10621     EXPECT_HR(hr, S_FALSE);
10622     ok(len == 0, "got %d\n", len);
10623 
10624     len = 100;
10625     buffW[0] = 0x1;
10626     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, buffW, &len);
10627     EXPECT_HR(hr, S_FALSE);
10628     ok(buffW[0] == 0, "got %x\n", buffW[0]);
10629     ok(len == 0, "got %d\n", len);
10630 
10631     /* IDispatchEx tests */
10632     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IUnknown, (void**)&unk);
10633     EXPECT_HR(hr, S_OK);
10634     test_domobj_dispex(unk);
10635     IUnknown_Release(unk);
10636 
10637     IMXNamespaceManager_Release(nsmgr);
10638 
10639     /* ::getPrefix() */
10640     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10641         &IID_IMXNamespaceManager, (void**)&nsmgr);
10642     EXPECT_HR(hr, S_OK);
10643 
10644     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, NULL);
10645     EXPECT_HR(hr, E_INVALIDARG);
10646 
10647     len = -1;
10648     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, &len);
10649     EXPECT_HR(hr, E_INVALIDARG);
10650     ok(len == -1, "got %d\n", len);
10651 
10652     len = 100;
10653     buffW[0] = 0x1;
10654     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10655     EXPECT_HR(hr, E_FAIL);
10656     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10657     ok(len == 100, "got %d\n", len);
10658 
10659     len = 0;
10660     buffW[0] = 0x1;
10661     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10662     EXPECT_HR(hr, E_FAIL);
10663     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10664     ok(len == 0, "got %d\n", len);
10665 
10666     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10667     EXPECT_HR(hr, S_OK);
10668 
10669     len = 100;
10670     buffW[0] = 0x1;
10671     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10672     EXPECT_HR(hr, S_OK);
10673     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10674     ok(len == 3, "got %d\n", len);
10675 
10676     len = 100;
10677     buffW[0] = 0x1;
10678     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, buffW, &len);
10679     EXPECT_HR(hr, S_OK);
10680     ok(!lstrcmpW(buffW, _bstr_("xml")), "got %s\n", wine_dbgstr_w(buffW));
10681     ok(len == 3, "got %d\n", len);
10682 
10683     /* with null buffer it's possible to get required length */
10684     len = 100;
10685     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10686     EXPECT_HR(hr, S_OK);
10687     ok(len == 3, "got %d\n", len);
10688 
10689     len = 0;
10690     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10691     EXPECT_HR(hr, S_OK);
10692     ok(len == 3, "got %d\n", len);
10693 
10694     len = 100;
10695     buffW[0] = 0x1;
10696     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 1, buffW, &len);
10697     EXPECT_HR(hr, E_FAIL);
10698     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10699     ok(len == 100, "got %d\n", len);
10700 
10701     len = 100;
10702     buffW[0] = 0x1;
10703     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 2, buffW, &len);
10704     EXPECT_HR(hr, E_FAIL);
10705     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10706     ok(len == 100, "got %d\n", len);
10707 
10708     len = 100;
10709     buffW[0] = 0x1;
10710     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 0, buffW, &len);
10711     EXPECT_HR(hr, E_INVALIDARG);
10712     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10713     ok(len == 100, "got %d\n", len);
10714 
10715     len = 100;
10716     buffW[0] = 0x1;
10717     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10718     EXPECT_HR(hr, E_INVALIDARG);
10719     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10720     ok(len == 100, "got %d\n", len);
10721 
10722     len = 100;
10723     buffW[0] = 0x1;
10724     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, buffW, &len);
10725     EXPECT_HR(hr, E_INVALIDARG);
10726     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10727     ok(len == 100, "got %d\n", len);
10728 
10729     len = 100;
10730     buffW[0] = 0x1;
10731     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 1, buffW, &len);
10732     EXPECT_HR(hr, E_FAIL);
10733     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10734     ok(len == 100, "got %d\n", len);
10735 
10736     len = 100;
10737     buffW[0] = 0x1;
10738     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10739     EXPECT_HR(hr, E_INVALIDARG);
10740     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10741     ok(len == 100, "got %d\n", len);
10742 
10743     /* declare another one, indices are shifted */
10744     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10745     EXPECT_HR(hr, S_OK);
10746 
10747     len = 100;
10748     buffW[0] = 0x1;
10749     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10750     EXPECT_HR(hr, S_OK);
10751     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10752     ok(len == 3, "got %d\n", len);
10753 
10754     len = 100;
10755     buffW[0] = 0x1;
10756     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10757     EXPECT_HR(hr, S_OK);
10758     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10759     ok(len == 3, "got %d\n", len);
10760 
10761     len = 100;
10762     buffW[0] = 0x1;
10763     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 1, buffW, &len);
10764     EXPECT_HR(hr, E_FAIL);
10765     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10766     ok(len == 100, "got %d\n", len);
10767 
10768     len = 100;
10769     buffW[0] = 0x1;
10770     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10771     EXPECT_HR(hr, E_INVALIDARG);
10772     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10773     ok(len == 100, "got %d\n", len);
10774 
10775     IMXNamespaceManager_Release(nsmgr);
10776 
10777     /* push/pop tests */
10778     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10779         &IID_IMXNamespaceManager, (void**)&nsmgr);
10780     EXPECT_HR(hr, S_OK);
10781 
10782     /* pop with empty stack */
10783     hr = IMXNamespaceManager_popContext(nsmgr);
10784     EXPECT_HR(hr, E_FAIL);
10785 
10786     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10787     EXPECT_HR(hr, S_OK);
10788 
10789     len = 100;
10790     buffW[0] = 0x1;
10791     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10792     EXPECT_HR(hr, S_OK);
10793     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10794     ok(len == 3, "got %d\n", len);
10795 
10796     hr = IMXNamespaceManager_pushContext(nsmgr);
10797     EXPECT_HR(hr, S_OK);
10798 
10799     len = 100;
10800     buffW[0] = 0x1;
10801     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10802     EXPECT_HR(hr, S_OK);
10803     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10804     ok(len == 3, "got %d\n", len);
10805 
10806     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10807     EXPECT_HR(hr, S_OK);
10808 
10809     len = 100;
10810     buffW[0] = 0x1;
10811     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10812     EXPECT_HR(hr, S_OK);
10813     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10814     ok(len == 3, "got %d\n", len);
10815 
10816     hr = IMXNamespaceManager_pushContext(nsmgr);
10817     EXPECT_HR(hr, S_OK);
10818     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns3"), _bstr_("ns3 uri"));
10819     EXPECT_HR(hr, S_OK);
10820 
10821     len = 100;
10822     buffW[0] = 0x1;
10823     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10824     EXPECT_HR(hr, S_OK);
10825     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10826     ok(len == 3, "got %d\n", len);
10827 
10828     len = 100;
10829     buffW[0] = 0x1;
10830     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10831     EXPECT_HR(hr, S_OK);
10832     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10833     ok(len == 3, "got %d\n", len);
10834 
10835     hr = IMXNamespaceManager_popContext(nsmgr);
10836     EXPECT_HR(hr, S_OK);
10837 
10838     hr = IMXNamespaceManager_popContext(nsmgr);
10839     EXPECT_HR(hr, S_OK);
10840 
10841     len = 100;
10842     buffW[0] = 0x1;
10843     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10844     EXPECT_HR(hr, E_FAIL);
10845     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10846     ok(len == 100, "got %d\n", len);
10847 
10848     len = 100;
10849     buffW[0] = 0x1;
10850     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10851     EXPECT_HR(hr, S_OK);
10852     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10853     ok(len == 3, "got %d\n", len);
10854 
10855     IMXNamespaceManager_Release(nsmgr);
10856 
10857     free_bstrs();
10858 }
10859 
10860 static void test_mxnamespacemanager_override(void)
10861 {
10862     IMXNamespaceManager *nsmgr;
10863     WCHAR buffW[250];
10864     VARIANT_BOOL b;
10865     HRESULT hr;
10866     INT len;
10867 
10868     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10869         &IID_IMXNamespaceManager, (void**)&nsmgr);
10870     EXPECT_HR(hr, S_OK);
10871 
10872     len = ARRAY_SIZE(buffW);
10873     buffW[0] = 0;
10874     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10875     EXPECT_HR(hr, S_OK);
10876     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10877 
10878     len = ARRAY_SIZE(buffW);
10879     buffW[0] = 0;
10880     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10881     EXPECT_HR(hr, E_FAIL);
10882 
10883     hr = IMXNamespaceManager_getAllowOverride(nsmgr, NULL);
10884     EXPECT_HR(hr, E_POINTER);
10885 
10886     b = VARIANT_FALSE;
10887     hr = IMXNamespaceManager_getAllowOverride(nsmgr, &b);
10888     EXPECT_HR(hr, S_OK);
10889     ok(b == VARIANT_TRUE, "got %d\n", b);
10890 
10891     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_FALSE);
10892     EXPECT_HR(hr, S_OK);
10893 
10894     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10895     EXPECT_HR(hr, S_OK);
10896 
10897     len = ARRAY_SIZE(buffW);
10898     buffW[0] = 0;
10899     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10900     EXPECT_HR(hr, S_OK);
10901     ok(!lstrcmpW(buffW, _bstr_("ns0 uri")), "got uri %s\n", wine_dbgstr_w(buffW));
10902 
10903     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), _bstr_("ns0 uri"));
10904     EXPECT_HR(hr, S_OK);
10905 
10906     len = ARRAY_SIZE(buffW);
10907     buffW[0] = 0;
10908     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10909     EXPECT_HR(hr, S_OK);
10910     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10911 
10912     len = ARRAY_SIZE(buffW);
10913     buffW[0] = 0;
10914     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10915     EXPECT_HR(hr, S_OK);
10916     ok(!lstrcmpW(buffW, _bstr_("ns0")), "got prefix %s\n", wine_dbgstr_w(buffW));
10917 
10918     len = ARRAY_SIZE(buffW);
10919     buffW[0] = 0;
10920     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 2, buffW, &len);
10921     EXPECT_HR(hr, S_OK);
10922     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10923 
10924     /* new prefix placed at index 1 always */
10925     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10926     EXPECT_HR(hr, S_OK);
10927 
10928     len = ARRAY_SIZE(buffW);
10929     buffW[0] = 0;
10930     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10931     EXPECT_HR(hr, S_OK);
10932     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got prefix %s\n", wine_dbgstr_w(buffW));
10933 
10934     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_(""), NULL);
10935     todo_wine EXPECT_HR(hr, E_FAIL);
10936 
10937     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10938     EXPECT_HR(hr, E_FAIL);
10939 
10940     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10941     EXPECT_HR(hr, E_FAIL);
10942 
10943     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_TRUE);
10944     EXPECT_HR(hr, S_OK);
10945 
10946     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri override"));
10947     EXPECT_HR(hr, S_FALSE);
10948 
10949     len = ARRAY_SIZE(buffW);
10950     buffW[0] = 0;
10951     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10952     EXPECT_HR(hr, S_OK);
10953     ok(!lstrcmpW(buffW, _bstr_("ns0 uri override")), "got uri %s\n", wine_dbgstr_w(buffW));
10954 
10955     len = ARRAY_SIZE(buffW);
10956     buffW[0] = 0;
10957     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 3, buffW, &len);
10958     EXPECT_HR(hr, S_OK);
10959     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10960 
10961     IMXNamespaceManager_Release(nsmgr);
10962 
10963     free_bstrs();
10964 }
10965 
10966 static const DOMNodeType nodetypes_test[] =
10967 {
10968     NODE_ELEMENT,
10969     NODE_ATTRIBUTE,
10970     NODE_TEXT,
10971     NODE_CDATA_SECTION,
10972     NODE_ENTITY_REFERENCE,
10973     NODE_PROCESSING_INSTRUCTION,
10974     NODE_COMMENT,
10975     NODE_DOCUMENT_FRAGMENT,
10976     NODE_INVALID
10977 };
10978 
10979 static void test_dispex(void)
10980 {
10981     const DOMNodeType *type = nodetypes_test;
10982     IXMLDOMImplementation *impl;
10983     IXMLDOMNodeList *node_list;
10984     IXMLDOMParseError *error;
10985     IXMLDOMNamedNodeMap *map;
10986     IXSLProcessor *processor;
10987     IXSLTemplate *template;
10988     IXMLDOMDocument *doc;
10989     IXMLHTTPRequest *req;
10990     IXMLDOMElement *elem;
10991     IDispatchEx *dispex;
10992     DISPPARAMS dispparams;
10993     IXMLDOMNode *node;
10994     VARIANT arg, ret;
10995     VARIANT_BOOL b;
10996     IUnknown *unk;
10997     HRESULT hr;
10998     DISPID did;
10999 
11000     doc = create_document(&IID_IXMLDOMDocument);
11001 
11002     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
11003     ok(hr == S_OK, "got 0x%08x\n", hr);
11004     test_domobj_dispex(unk);
11005     IUnknown_Release(unk);
11006 
11007     for(; *type != NODE_INVALID; type++)
11008     {
11009         IXMLDOMNode *node;
11010         VARIANT v;
11011 
11012         V_VT(&v) = VT_I2;
11013         V_I2(&v) = *type;
11014 
11015         hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
11016         ok(hr == S_OK, "failed to create node type %d\n", *type);
11017 
11018         IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
11019 
11020         test_domobj_dispex(unk);
11021         IUnknown_Release(unk);
11022         IXMLDOMNode_Release(node);
11023     }
11024 
11025     /* IXMLDOMNodeList */
11026     hr = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), &node_list);
11027     EXPECT_HR(hr, S_OK);
11028     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
11029     ok(hr == S_OK, "got 0x%08x\n", hr);
11030     test_domobj_dispex(unk);
11031     IUnknown_Release(unk);
11032     IXMLDOMNodeList_Release(node_list);
11033 
11034     /* IXMLDOMNodeList for children list */
11035     hr = IXMLDOMDocument_get_childNodes(doc, &node_list);
11036     EXPECT_HR(hr, S_OK);
11037     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
11038     ok(hr == S_OK, "got 0x%08x\n", hr);
11039     test_domobj_dispex(unk);
11040     IUnknown_Release(unk);
11041 
11042     /* collection dispex test, empty collection */
11043     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatchEx, (void**)&dispex);
11044     EXPECT_HR(hr, S_OK);
11045     did = 0;
11046     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11047     EXPECT_HR(hr, S_OK);
11048     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11049     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
11050     EXPECT_HR(hr, S_OK);
11051     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
11052     IDispatchEx_Release(dispex);
11053 
11054     did = -1;
11055     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11056     ok(hr == S_OK, "got 0x%08x\n", hr);
11057     ok(did == DISPID_VALUE, "got %d\n", did);
11058 
11059     V_VT(&arg) = VT_I4;
11060     V_I4(&arg) = 0;
11061     dispparams.cArgs = 0;
11062     dispparams.cNamedArgs = 0;
11063     dispparams.rgdispidNamedArgs = NULL;
11064     dispparams.rgvarg = &arg;
11065 
11066     V_VT(&ret) = VT_EMPTY;
11067     V_DISPATCH(&ret) = (void*)0x1;
11068     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11069     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11070     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11071 todo_wine
11072     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11073 
11074     V_VT(&arg) = VT_I4;
11075     V_I4(&arg) = 0;
11076     dispparams.cArgs = 2;
11077     dispparams.cNamedArgs = 0;
11078     dispparams.rgdispidNamedArgs = NULL;
11079     dispparams.rgvarg = &arg;
11080 
11081     V_VT(&ret) = VT_EMPTY;
11082     V_DISPATCH(&ret) = (void*)0x1;
11083     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11084     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11085     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11086 todo_wine
11087     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11088 
11089     V_VT(&arg) = VT_I4;
11090     V_I4(&arg) = 0;
11091     dispparams.cArgs = 1;
11092     dispparams.cNamedArgs = 0;
11093     dispparams.rgdispidNamedArgs = NULL;
11094     dispparams.rgvarg = &arg;
11095 
11096     V_VT(&ret) = VT_EMPTY;
11097     V_DISPATCH(&ret) = (void*)0x1;
11098     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11099     ok(hr == S_OK, "got 0x%08x\n", hr);
11100     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11101     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11102 
11103     V_VT(&ret) = VT_EMPTY;
11104     V_DISPATCH(&ret) = (void*)0x1;
11105     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11106     ok(hr == S_OK, "got 0x%08x\n", hr);
11107     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11108     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11109 
11110     V_VT(&ret) = VT_EMPTY;
11111     V_DISPATCH(&ret) = (void*)0x1;
11112     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11113     ok(hr == S_OK, "got 0x%08x\n", hr);
11114     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11115     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11116 
11117     dispparams.cArgs = 0;
11118     dispparams.cNamedArgs = 0;
11119     dispparams.rgdispidNamedArgs = NULL;
11120     dispparams.rgvarg = NULL;
11121 
11122     V_VT(&ret) = VT_EMPTY;
11123     V_I4(&ret) = 1;
11124     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11125     ok(hr == S_OK, "got 0x%08x\n", hr);
11126     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11127     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11128 
11129     dispparams.cArgs = 0;
11130     dispparams.cNamedArgs = 0;
11131     dispparams.rgdispidNamedArgs = NULL;
11132     dispparams.rgvarg = NULL;
11133 
11134     V_VT(&ret) = VT_EMPTY;
11135     V_I4(&ret) = 1;
11136     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11137     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11138     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11139 todo_wine
11140     ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11141 
11142     IXMLDOMNodeList_Release(node_list);
11143 
11144     /* IXMLDOMParseError */
11145     hr = IXMLDOMDocument_get_parseError(doc, &error);
11146     EXPECT_HR(hr, S_OK);
11147     IXMLDOMParseError_QueryInterface(error, &IID_IUnknown, (void**)&unk);
11148     test_domobj_dispex(unk);
11149 
11150     hr = IXMLDOMParseError_QueryInterface(error, &IID_IDispatchEx, (void**)&dispex);
11151     ok(hr == S_OK, "got 0x%08x\n", hr);
11152 
11153     V_VT(&arg) = VT_I4;
11154     V_I4(&arg) = 0;
11155     dispparams.cArgs = 1;
11156     dispparams.cNamedArgs = 0;
11157     dispparams.rgdispidNamedArgs = NULL;
11158     dispparams.rgvarg = &arg;
11159 
11160     V_VT(&ret) = VT_EMPTY;
11161     V_DISPATCH(&ret) = (void*)0x1;
11162     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11163     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11164     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11165 todo_wine
11166     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11167 
11168     IDispatchEx_Release(dispex);
11169 
11170     IUnknown_Release(unk);
11171     IXMLDOMParseError_Release(error);
11172 
11173     /* IXMLDOMNamedNodeMap */
11174     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
11175     EXPECT_HR(hr, S_OK);
11176 
11177     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/a"), &node_list);
11178     EXPECT_HR(hr, S_OK);
11179     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11180     EXPECT_HR(hr, S_OK);
11181     IXMLDOMNodeList_Release(node_list);
11182 
11183     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11184     EXPECT_HR(hr, S_OK);
11185     IXMLDOMNode_Release(node);
11186     hr = IXMLDOMElement_get_attributes(elem, &map);
11187     EXPECT_HR(hr, S_OK);
11188     IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk);
11189     test_domobj_dispex(unk);
11190     IUnknown_Release(unk);
11191     /* collection dispex test */
11192     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11193     EXPECT_HR(hr, S_OK);
11194     did = 0;
11195     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11196     EXPECT_HR(hr, S_OK);
11197     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11198     IDispatchEx_Release(dispex);
11199     IXMLDOMNamedNodeMap_Release(map);
11200 
11201     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/b"), &node_list);
11202     EXPECT_HR(hr, S_OK);
11203     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11204     EXPECT_HR(hr, S_OK);
11205     IXMLDOMNodeList_Release(node_list);
11206     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11207     EXPECT_HR(hr, S_OK);
11208     IXMLDOMNode_Release(node);
11209     hr = IXMLDOMElement_get_attributes(elem, &map);
11210     EXPECT_HR(hr, S_OK);
11211     /* collection dispex test, empty collection */
11212     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11213     EXPECT_HR(hr, S_OK);
11214     did = 0;
11215     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11216     EXPECT_HR(hr, S_OK);
11217     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11218     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
11219     EXPECT_HR(hr, S_OK);
11220     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
11221     IXMLDOMNamedNodeMap_Release(map);
11222 
11223     did = -1;
11224     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11225     ok(hr == S_OK, "got 0x%08x\n", hr);
11226     ok(did == DISPID_VALUE, "got %d\n", did);
11227 
11228     V_VT(&arg) = VT_I4;
11229     V_I4(&arg) = 0;
11230     dispparams.cArgs = 0;
11231     dispparams.cNamedArgs = 0;
11232     dispparams.rgdispidNamedArgs = NULL;
11233     dispparams.rgvarg = &arg;
11234 
11235     V_VT(&ret) = VT_EMPTY;
11236     V_DISPATCH(&ret) = (void*)0x1;
11237     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11238 todo_wine {
11239     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11240     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11241 }
11242     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11243 
11244     V_VT(&arg) = VT_I4;
11245     V_I4(&arg) = 0;
11246     dispparams.cArgs = 2;
11247     dispparams.cNamedArgs = 0;
11248     dispparams.rgdispidNamedArgs = NULL;
11249     dispparams.rgvarg = &arg;
11250 
11251     V_VT(&ret) = VT_EMPTY;
11252     V_DISPATCH(&ret) = (void*)0x1;
11253     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11254 todo_wine {
11255     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11256     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11257 }
11258     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11259 
11260     V_VT(&arg) = VT_I4;
11261     V_I4(&arg) = 0;
11262     dispparams.cArgs = 1;
11263     dispparams.cNamedArgs = 0;
11264     dispparams.rgdispidNamedArgs = NULL;
11265     dispparams.rgvarg = &arg;
11266 
11267     V_VT(&ret) = VT_EMPTY;
11268     V_DISPATCH(&ret) = (void*)0x1;
11269     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11270 todo_wine
11271     ok(hr == S_OK, "got 0x%08x\n", hr);
11272     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11273     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11274 
11275     V_VT(&ret) = VT_EMPTY;
11276     V_DISPATCH(&ret) = (void*)0x1;
11277     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11278     ok(hr == S_OK, "got 0x%08x\n", hr);
11279     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11280     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11281 
11282     V_VT(&ret) = VT_EMPTY;
11283     V_DISPATCH(&ret) = (void*)0x1;
11284     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11285     ok(hr == S_OK, "got 0x%08x\n", hr);
11286     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11287     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11288 
11289     dispparams.cArgs = 0;
11290     dispparams.cNamedArgs = 0;
11291     dispparams.rgdispidNamedArgs = NULL;
11292     dispparams.rgvarg = NULL;
11293 
11294     V_VT(&ret) = VT_EMPTY;
11295     V_I4(&ret) = 1;
11296     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11297     ok(hr == S_OK, "got 0x%08x\n", hr);
11298     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11299     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11300 
11301     dispparams.cArgs = 0;
11302     dispparams.cNamedArgs = 0;
11303     dispparams.rgdispidNamedArgs = NULL;
11304     dispparams.rgvarg = NULL;
11305 
11306     V_VT(&ret) = VT_EMPTY;
11307     V_I4(&ret) = 1;
11308     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11309     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11310 todo_wine
11311     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11312     ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11313 
11314     IDispatchEx_Release(dispex);
11315     IXMLDOMElement_Release(elem);
11316 
11317     /* IXMLDOMImplementation */
11318     hr = IXMLDOMDocument_get_implementation(doc, &impl);
11319     EXPECT_HR(hr, S_OK);
11320 
11321     hr = IXMLDOMImplementation_QueryInterface(impl, &IID_IDispatchEx, (void**)&dispex);
11322     EXPECT_HR(hr, S_OK);
11323     IDispatchEx_Release(dispex);
11324     IXMLDOMImplementation_Release(impl);
11325 
11326     IXMLDOMDocument_Release(doc);
11327 
11328     /* IXMLHTTPRequest */
11329     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
11330         &IID_IXMLHttpRequest, (void**)&req);
11331     if (hr == S_OK)
11332     {
11333         hr = IXMLHTTPRequest_QueryInterface(req, &IID_IDispatchEx, (void**)&dispex);
11334         EXPECT_HR(hr, E_NOINTERFACE);
11335         IXMLHTTPRequest_Release(req);
11336     }
11337 
11338     /* IXSLTemplate */
11339     template = create_xsltemplate(&IID_IXSLTemplate);
11340     hr = IXSLTemplate_QueryInterface(template, &IID_IDispatchEx, (void**)&dispex);
11341     EXPECT_HR(hr, S_OK);
11342     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11343     EXPECT_HR(hr, S_OK);
11344     test_domobj_dispex(unk);
11345     IUnknown_Release(unk);
11346     IDispatchEx_Release(dispex);
11347 
11348     /* IXSLProcessor */
11349     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
11350     EXPECT_HR(hr, S_OK);
11351     b = VARIANT_FALSE;
11352     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformSSXML), &b);
11353     EXPECT_HR(hr, S_OK);
11354     ok(b == VARIANT_TRUE, "got %d\n", b);
11355 
11356     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
11357     EXPECT_HR(hr, S_OK);
11358     IXMLDOMDocument_Release(doc);
11359 
11360     hr = IXSLTemplate_createProcessor(template, &processor);
11361     EXPECT_HR(hr, S_OK);
11362     hr = IXSLProcessor_QueryInterface(processor, &IID_IDispatchEx, (void**)&dispex);
11363     EXPECT_HR(hr, S_OK);
11364     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11365     EXPECT_HR(hr, S_OK);
11366     test_domobj_dispex(unk);
11367     IUnknown_Release(unk);
11368     IDispatchEx_Release(dispex);
11369 
11370     IXSLProcessor_Release(processor);
11371     IXSLTemplate_Release(template);
11372 
11373     if (is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument))
11374     {
11375         doc = create_document_version(60, &IID_IXMLDOMDocument);
11376         test_domobj_dispex((IUnknown*)doc);
11377         IXMLDOMDocument_Release(doc);
11378     }
11379 
11380     free_bstrs();
11381 }
11382 
11383 static void test_parseerror(void)
11384 {
11385     IXMLDOMParseError2 *error2;
11386     IXMLDOMParseError *error;
11387     IXMLDOMDocument *doc;
11388     HRESULT hr;
11389 
11390     doc = create_document(&IID_IXMLDOMDocument);
11391 
11392     hr = IXMLDOMDocument_get_parseError(doc, &error);
11393     EXPECT_HR(hr, S_OK);
11394 
11395     hr = IXMLDOMParseError_get_line(error, NULL);
11396     EXPECT_HR(hr, E_INVALIDARG);
11397 
11398     hr = IXMLDOMParseError_get_srcText(error, NULL);
11399     EXPECT_HR(hr, E_INVALIDARG);
11400 
11401     hr = IXMLDOMParseError_get_linepos(error, NULL);
11402     EXPECT_HR(hr, E_INVALIDARG);
11403 
11404     IXMLDOMParseError_Release(error);
11405     IXMLDOMDocument_Release(doc);
11406 
11407     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument)) return;
11408     doc = create_document_version(60, &IID_IXMLDOMDocument);
11409 
11410     hr = IXMLDOMDocument_get_parseError(doc, &error);
11411     EXPECT_HR(hr, S_OK);
11412     hr = IXMLDOMParseError_QueryInterface(error, &IID_IXMLDOMParseError2, (void**)&error2);
11413     EXPECT_HR(hr, S_OK);
11414     IXMLDOMParseError2_Release(error2);
11415     IXMLDOMParseError_Release(error);
11416     IXMLDOMDocument_Release(doc);
11417 }
11418 
11419 static void test_getAttributeNode(void)
11420 {
11421     IXMLDOMAttribute *attr;
11422     IXMLDOMDocument *doc;
11423     IXMLDOMElement *elem;
11424     VARIANT_BOOL v;
11425     HRESULT hr;
11426     BSTR str;
11427 
11428     doc = create_document(&IID_IXMLDOMDocument);
11429 
11430     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11431     EXPECT_HR(hr, S_OK);
11432 
11433     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11434     EXPECT_HR(hr, S_OK);
11435 
11436     str = SysAllocString(nonexistent_fileW);
11437     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11438     EXPECT_HR(hr, E_FAIL);
11439 
11440     attr = (IXMLDOMAttribute*)0xdeadbeef;
11441     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11442     EXPECT_HR(hr, E_FAIL);
11443     ok(attr == NULL, "got %p\n", attr);
11444     SysFreeString(str);
11445 
11446     str = SysAllocString(nonexistent_attrW);
11447     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11448     EXPECT_HR(hr, S_FALSE);
11449 
11450     attr = (IXMLDOMAttribute*)0xdeadbeef;
11451     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11452     EXPECT_HR(hr, S_FALSE);
11453     ok(attr == NULL, "got %p\n", attr);
11454     SysFreeString(str);
11455 
11456     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("foo:b"), &attr);
11457     EXPECT_HR(hr, S_OK);
11458     IXMLDOMAttribute_Release(attr);
11459 
11460     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("b"), &attr);
11461     EXPECT_HR(hr, S_FALSE);
11462 
11463     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("a"), &attr);
11464     EXPECT_HR(hr, S_OK);
11465     IXMLDOMAttribute_Release(attr);
11466 
11467     IXMLDOMElement_Release(elem);
11468     IXMLDOMDocument_Release(doc);
11469     free_bstrs();
11470 }
11471 
11472 static void test_getAttribute(void)
11473 {
11474     IXMLDOMDocument *doc;
11475     IXMLDOMElement *elem;
11476     VARIANT_BOOL v;
11477     VARIANT var;
11478     HRESULT hr;
11479 
11480     doc = create_document(&IID_IXMLDOMDocument);
11481 
11482     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11483     EXPECT_HR(hr, S_OK);
11484 
11485     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11486     EXPECT_HR(hr, S_OK);
11487 
11488     VariantInit(&var);
11489     hr = IXMLDOMElement_getAttribute( elem, _bstr_("xmlns:foo"), &var );
11490     EXPECT_HR(hr, S_OK);
11491     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11492     ok( !lstrcmpW(V_BSTR(&var), _bstr_("urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11493     VariantClear(&var);
11494 
11495     hr = IXMLDOMElement_getAttribute( elem, _bstr_("a"), &var );
11496     EXPECT_HR(hr, S_OK);
11497     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11498     ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr a")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11499     VariantClear(&var);
11500 
11501     hr = IXMLDOMElement_getAttribute( elem, _bstr_("foo:b"), &var );
11502     EXPECT_HR(hr, S_OK);
11503     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11504     ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr b")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11505     VariantClear(&var);
11506 
11507     hr = IXMLDOMElement_getAttribute( elem, _bstr_("b"), &var );
11508     EXPECT_HR(hr, S_FALSE);
11509     ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11510     VariantClear(&var);
11511 
11512     hr = IXMLDOMElement_getAttribute( elem, _bstr_("non-existent"), &var );
11513     EXPECT_HR(hr, S_FALSE);
11514     ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11515     VariantClear(&var);
11516 
11517     IXMLDOMElement_Release(elem);
11518     IXMLDOMDocument_Release(doc);
11519     free_bstrs();
11520 }
11521 
11522 typedef struct {
11523     DOMNodeType type;
11524     const char *name;
11525     REFIID iids[3];
11526 } supporterror_t;
11527 
11528 static const supporterror_t supporterror_test[] = {
11529     { NODE_ELEMENT,                "element",   { &IID_IXMLDOMNode, &IID_IXMLDOMElement } },
11530     { NODE_ATTRIBUTE,              "attribute", { &IID_IXMLDOMNode, &IID_IXMLDOMAttribute } },
11531     { NODE_CDATA_SECTION,          "cdata",     { &IID_IXMLDOMNode, &IID_IXMLDOMCDATASection } },
11532     { NODE_ENTITY_REFERENCE,       "entityref", { &IID_IXMLDOMNode, &IID_IXMLDOMEntityReference } },
11533     { NODE_PROCESSING_INSTRUCTION, "pi",        { &IID_IXMLDOMNode, &IID_IXMLDOMProcessingInstruction } },
11534     { NODE_COMMENT,                "comment",   { &IID_IXMLDOMNode, &IID_IXMLDOMComment } },
11535     { NODE_DOCUMENT_FRAGMENT,      "fragment",  { &IID_IXMLDOMNode, &IID_IXMLDOMDocumentFragment } },
11536     { NODE_INVALID }
11537 };
11538 
11539 static void test_supporterrorinfo(void)
11540 {
11541     static REFIID iids[5] = { &IID_IXMLDOMNode, &IID_IXMLDOMDocument,
11542                               &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3 };
11543     const supporterror_t *ptr = supporterror_test;
11544     ISupportErrorInfo *errorinfo, *info2;
11545     IXMLDOMSchemaCollection *schemacache;
11546     IXMLDOMNamedNodeMap *map, *map2;
11547     IXMLDOMDocument *doc;
11548     IXMLDOMElement *elem;
11549     VARIANT_BOOL b;
11550     IUnknown *unk;
11551     REFIID *iid;
11552     void *dummy;
11553     HRESULT hr;
11554 
11555     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument3)) return;
11556     doc = create_document_version(60, &IID_IXMLDOMDocument3);
11557 
11558     EXPECT_REF(doc, 1);
11559     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&errorinfo);
11560     EXPECT_HR(hr, S_OK);
11561     EXPECT_REF(doc, 1);
11562     ISupportErrorInfo_AddRef(errorinfo);
11563     EXPECT_REF(errorinfo, 2);
11564     EXPECT_REF(doc, 1);
11565     ISupportErrorInfo_Release(errorinfo);
11566 
11567     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&info2);
11568     EXPECT_HR(hr, S_OK);
11569     ok(errorinfo != info2, "got %p, %p\n", info2, errorinfo);
11570 
11571     /* error interface can't be queried back for DOM interface */
11572     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMDocument, &dummy);
11573     EXPECT_HR(hr, E_NOINTERFACE);
11574     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMNode, &dummy);
11575     EXPECT_HR(hr, E_NOINTERFACE);
11576 
11577     ISupportErrorInfo_Release(info2);
11578 
11579     iid = iids;
11580     while (*iid)
11581     {
11582         hr = IXMLDOMDocument_QueryInterface(doc, *iid, (void**)&unk);
11583         EXPECT_HR(hr, S_OK);
11584         if (hr == S_OK)
11585         {
11586             hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11587             ok(hr == S_OK, "got 0x%08x for %s\n", hr, wine_dbgstr_guid(*iid));
11588             IUnknown_Release(unk);
11589         }
11590 
11591         iid++;
11592     }
11593 
11594     ISupportErrorInfo_Release(errorinfo);
11595 
11596     while (ptr->type != NODE_INVALID)
11597     {
11598         IXMLDOMNode *node;
11599         VARIANT type;
11600 
11601         V_VT(&type) = VT_I1;
11602         V_I1(&type) = ptr->type;
11603 
11604         hr = IXMLDOMDocument_createNode(doc, type, _bstr_(ptr->name), NULL, &node);
11605         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11606 
11607         EXPECT_REF(node, 1);
11608         hr = IXMLDOMNode_QueryInterface(node, &IID_ISupportErrorInfo, (void**)&errorinfo);
11609         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11610         EXPECT_REF(node, 1);
11611 
11612         hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNode, &dummy);
11613         ok(hr == E_NOINTERFACE, "%d: got 0x%08x\n", ptr->type, hr);
11614 
11615         iid = ptr->iids;
11616 
11617         while (*iid)
11618         {
11619             hr = IXMLDOMNode_QueryInterface(node, *iid, (void**)&unk);
11620             if (hr == S_OK)
11621             {
11622                 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11623                 ok(hr == S_OK, "%d: got 0x%08x for %s\n", ptr->type, hr, wine_dbgstr_guid(*iid));
11624                 IUnknown_Release(unk);
11625             }
11626 
11627             iid++;
11628         }
11629 
11630         ISupportErrorInfo_Release(errorinfo);
11631         IXMLDOMNode_Release(node);
11632         ptr++;
11633     }
11634 
11635     /* IXMLDOMNamedNodeMap */
11636     b = VARIANT_FALSE;
11637     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
11638     EXPECT_HR(hr, S_OK);
11639     ok(b == VARIANT_TRUE, "got %d\n", b);
11640 
11641     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11642     EXPECT_HR(hr, S_OK);
11643 
11644     hr = IXMLDOMElement_get_attributes(elem, &map);
11645     EXPECT_HR(hr, S_OK);
11646 
11647     EXPECT_REF(map, 1);
11648     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_ISupportErrorInfo, (void**)&errorinfo);
11649     EXPECT_HR(hr, S_OK);
11650     EXPECT_REF(map, 2);
11651 
11652     hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMNamedNodeMap);
11653     EXPECT_HR(hr, S_OK);
11654 
11655     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNamedNodeMap, (void**)&map2);
11656     EXPECT_HR(hr, S_OK);
11657     ok(map == map2, "got %p\n", map2);
11658     IXMLDOMNamedNodeMap_Release(map2);
11659 
11660     EXPECT_REF(errorinfo, 2);
11661     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IUnknown, (void**)&unk);
11662     EXPECT_HR(hr, S_OK);
11663     EXPECT_REF(errorinfo, 3);
11664     EXPECT_REF(map, 3);
11665     IUnknown_Release(unk);
11666 
11667     ISupportErrorInfo_Release(errorinfo);
11668     IXMLDOMNamedNodeMap_Release(map);
11669     IXMLDOMElement_Release(elem);
11670 
11671     IXMLDOMDocument_Release(doc);
11672 
11673     /* IXMLDOMSchemaCollection */
11674     hr = CoCreateInstance(&CLSID_XMLSchemaCache, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMSchemaCollection, (void**)&schemacache);
11675     ok(hr == S_OK, "failed to create schema collection, 0x%08x\n", hr);
11676 
11677     hr = IXMLDOMSchemaCollection_QueryInterface(schemacache, &IID_ISupportErrorInfo, (void**)&errorinfo);
11678     ok(hr == S_OK, "got 0x%08x\n", hr);
11679 
11680     hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMSchemaCollection);
11681     ok(hr == S_OK, "got 0x%08x\n", hr);
11682 
11683     ISupportErrorInfo_Release(errorinfo);
11684     IXMLDOMSchemaCollection_Release(schemacache);
11685 
11686     free_bstrs();
11687 }
11688 
11689 typedef struct {
11690     DOMNodeType type;
11691     const char *name;
11692     const char *put_content;
11693     HRESULT put_hr;
11694     VARTYPE get_vt;
11695     HRESULT get_hr;
11696 } node_value_t;
11697 
11698 static const node_value_t nodevalue_test[] = {
11699     { NODE_ELEMENT,                "element",   "",             E_FAIL, VT_NULL, S_FALSE },
11700     { NODE_ATTRIBUTE,              "attr",      "value",        S_OK,   VT_BSTR, S_OK },
11701     { NODE_TEXT,                   "text",      "textdata",     S_OK,   VT_BSTR, S_OK },
11702     { NODE_CDATA_SECTION ,         "cdata",     "cdata data",   S_OK,   VT_BSTR, S_OK },
11703     { NODE_ENTITY_REFERENCE,       "entityref", "ref",          E_FAIL, VT_NULL, S_FALSE },
11704     { NODE_PROCESSING_INSTRUCTION, "pi",        "instr",        S_OK,   VT_BSTR, S_OK },
11705     { NODE_COMMENT,                "comment",   "comment data", S_OK,   VT_BSTR, S_OK },
11706     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   "",             E_FAIL, VT_NULL, S_FALSE },
11707     { NODE_INVALID }
11708 };
11709 
11710 static void test_nodeValue(void)
11711 {
11712     const node_value_t *ptr = nodevalue_test;
11713     IXMLDOMDocument *doc;
11714     HRESULT hr;
11715 
11716     doc = create_document(&IID_IXMLDOMDocument);
11717 
11718     while (ptr->type != NODE_INVALID)
11719     {
11720         IXMLDOMNode *node;
11721         VARIANT v;
11722 
11723         V_VT(&v) = VT_I2;
11724         V_I2(&v) = ptr->type;
11725 
11726         hr = IXMLDOMDocument_createNode(doc, v, _bstr_(ptr->name), NULL, &node);
11727         ok(hr == S_OK, "failed to create node type %d\n", ptr->type);
11728 
11729         hr = IXMLDOMNode_get_nodeValue(node, NULL);
11730         ok(hr == E_INVALIDARG, "%d: got 0x%08x\n", ptr->type, hr);
11731 
11732         V_VT(&v) = VT_BSTR;
11733         V_BSTR(&v) = _bstr_(ptr->put_content);
11734         hr = IXMLDOMNode_put_nodeValue(node, v);
11735         ok(hr == ptr->put_hr, "%d: got 0x%08x\n", ptr->type, hr);
11736 
11737         V_VT(&v) = VT_EMPTY;
11738         hr = IXMLDOMNode_get_nodeValue(node, &v);
11739         ok(hr == ptr->get_hr, "%d: got 0x%08x, expected 0x%08x\n", ptr->type, hr, ptr->get_hr);
11740         ok(V_VT(&v) == ptr->get_vt, "%d: got %d, expected %d\n", ptr->type, V_VT(&v), ptr->get_vt);
11741         if (hr == S_OK)
11742             ok(!lstrcmpW(V_BSTR(&v), _bstr_(ptr->put_content)), "%d: got %s\n", ptr->type,
11743                 wine_dbgstr_w(V_BSTR(&v)));
11744         VariantClear(&v);
11745 
11746         IXMLDOMNode_Release(node);
11747 
11748         ptr++;
11749     }
11750 
11751     IXMLDOMDocument_Release(doc);
11752 }
11753 
11754 static void test_xmlns_attribute(void)
11755 {
11756     BSTR str;
11757     IXMLDOMDocument *doc;
11758     IXMLDOMElement *root;
11759     IXMLDOMAttribute *pAttribute;
11760     IXMLDOMElement *elem;
11761     HRESULT hr;
11762     VARIANT v;
11763 
11764     doc = create_document(&IID_IXMLDOMDocument);
11765 
11766     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
11767     EXPECT_HR(hr, S_OK);
11768 
11769     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
11770     EXPECT_HR(hr, S_OK);
11771 
11772     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("xmlns:dt"), &pAttribute);
11773     ok( hr == S_OK, "returns %08x\n", hr );
11774 
11775     V_VT(&v) = VT_BSTR;
11776     V_BSTR(&v) = _bstr_("urn:schemas-microsoft-com:datatypes");
11777     hr = IXMLDOMAttribute_put_nodeValue(pAttribute, v);
11778     ok(hr == S_OK, "ret %08x\n", hr );
11779 
11780     hr = IXMLDOMElement_setAttributeNode(root, pAttribute, NULL);
11781     ok(hr == S_OK, "ret %08x\n", hr );
11782 
11783     hr = IXMLDOMNode_put_dataType((IXMLDOMNode*)root, _bstr_("bin.base64"));
11784     ok(hr == S_OK, "ret %08x\n", hr );
11785 
11786     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11787     EXPECT_HR(hr, S_OK);
11788 
11789     str = NULL;
11790     hr = IXMLDOMElement_get_xml(elem, &str);
11791     ok( hr == S_OK, "got 0x%08x\n", hr);
11792     todo_wine ok( lstrcmpW(str, _bstr_("<Testing xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"bin.base64\"/>")) == 0,
11793     "got %s\n", wine_dbgstr_w(str));
11794     SysFreeString(str);
11795 
11796     IXMLDOMElement_Release(elem);
11797     IXMLDOMAttribute_Release( pAttribute);
11798 
11799     IXMLDOMDocument_Release(doc);
11800 
11801     free_bstrs();
11802 }
11803 
11804 static const char namespacesA[] =
11805 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
11806 "   <ns1:elem1 xmlns:ns1=\"http://blah.org\" b='1' >"
11807 "     <ns2:elem2 xmlns:ns2=\"http://blah.org\"/>"
11808 "     <ns1:elem3/>"
11809 "     <ns1:elem4/>"
11810 "     <elem5 xmlns=\"http://blahblah.org\"/>"
11811 "     <ns1:elem6>true</ns1:elem6>"
11812 "   </ns1:elem1>";
11813 
11814 static const char xsd_schema1_uri[] = "x-schema:test1.xsd";
11815 static const char xsd_schema1_xml[] =
11816 "<?xml version='1.0'?>"
11817 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
11818 "            targetNamespace='x-schema:test1.xsd'>"
11819 "   <element name='root'>"
11820 "       <complexType>"
11821 "           <sequence maxOccurs='unbounded'>"
11822 "               <any/>"
11823 "           </sequence>"
11824 "       </complexType>"
11825 "   </element>"
11826 "</schema>";
11827 
11828 static void test_get_namespaces(void)
11829 {
11830     IXMLDOMSchemaCollection *collection, *collection2;
11831     IXMLDOMDocument2 *doc, *doc2;
11832     IEnumVARIANT *enumv, *enum2;
11833     IUnknown *unk1, *unk2;
11834     IXMLDOMNode *node;
11835     VARIANT_BOOL b;
11836     HRESULT hr;
11837     VARIANT v;
11838     LONG len;
11839     BSTR s;
11840 
11841     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
11842     doc = create_document(&IID_IXMLDOMDocument2);
11843 
11844     /* null pointer */
11845     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11846     EXPECT_HR(hr, E_POINTER);
11847 
11848     /* no document loaded */
11849     collection = (void*)0xdeadbeef;
11850     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11851     EXPECT_HR(hr, S_OK);
11852     if (hr != S_OK)
11853     {
11854         IXMLDOMDocument2_Release(doc);
11855         return;
11856     }
11857     EXPECT_REF(collection, 2);
11858 
11859     collection2 = (void*)0xdeadbeef;
11860     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11861     EXPECT_HR(hr, S_OK);
11862     ok(collection == collection2, "got %p\n", collection2);
11863     EXPECT_REF(collection, 3);
11864     IXMLDOMSchemaCollection_Release(collection);
11865 
11866     len = -1;
11867     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11868     EXPECT_HR(hr, S_OK);
11869     ok(len == 0, "got %d\n", len);
11870     IXMLDOMSchemaCollection_Release(collection);
11871 
11872     /* now with document */
11873     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11874     EXPECT_HR(hr, S_OK);
11875 
11876     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11877     EXPECT_HR(hr, S_OK);
11878 
11879     len = -1;
11880     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11881     EXPECT_HR(hr, S_OK);
11882     ok(len == 2, "got %d\n", len);
11883 
11884     /* try to lookup some uris */
11885     node = (void*)0xdeadbeef;
11886     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
11887     EXPECT_HR(hr, S_OK);
11888     ok(node == NULL, "got %p\n", node);
11889 
11890     node = (void*)0xdeadbeef;
11891     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah1.org"), &node);
11892     EXPECT_HR(hr, S_OK);
11893     ok(node == NULL, "got %p\n", node);
11894 
11895     /* load schema and try to add it */
11896     doc2 = create_document(&IID_IXMLDOMDocument2);
11897     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
11898     EXPECT_HR(hr, S_OK);
11899 
11900     V_VT(&v) = VT_DISPATCH;
11901     V_DISPATCH(&v) = (IDispatch*)doc2;
11902     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
11903     EXPECT_HR(hr, E_FAIL);
11904 
11905     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
11906     EXPECT_HR(hr, S_OK);
11907     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
11908     SysFreeString(s);
11909 
11910     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
11911     EXPECT_HR(hr, S_OK);
11912     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
11913     SysFreeString(s);
11914 
11915     s = (void*)0xdeadbeef;
11916     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
11917     EXPECT_HR(hr, E_FAIL);
11918     ok(s == (void*)0xdeadbeef, "got %p\n", s);
11919 
11920     /* enumerate */
11921     enumv = (void*)0xdeadbeef;
11922     EXPECT_REF(collection, 2);
11923     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
11924     EXPECT_HR(hr, S_OK);
11925     EXPECT_REF(collection, 3);
11926     ok(enumv != NULL, "got %p\n", enumv);
11927 
11928     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IUnknown, (void**)&unk1);
11929     EXPECT_HR(hr, S_OK);
11930     hr = IEnumVARIANT_QueryInterface(enumv, &IID_IUnknown, (void**)&unk2);
11931     EXPECT_HR(hr, S_OK);
11932     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
11933     IUnknown_Release(unk1);
11934     IUnknown_Release(unk2);
11935 
11936     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IEnumVARIANT, (void**)&enum2);
11937     EXPECT_HR(hr, E_NOINTERFACE);
11938 
11939     V_VT(&v) = VT_EMPTY;
11940     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11941     EXPECT_HR(hr, S_OK);
11942     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11943     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11944     VariantClear(&v);
11945 
11946     V_VT(&v) = VT_EMPTY;
11947     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11948     EXPECT_HR(hr, S_OK);
11949     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11950     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11951     VariantClear(&v);
11952 
11953     V_VT(&v) = VT_NULL;
11954     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11955     EXPECT_HR(hr, S_FALSE);
11956     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
11957 
11958     IEnumVARIANT_Release(enumv);
11959     IXMLDOMSchemaCollection_Release(collection);
11960 
11961     IXMLDOMDocument2_Release(doc);
11962 
11963     /* now with CLSID_DOMDocument60 */
11964     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument2)) return;
11965     doc = create_document_version(60, &IID_IXMLDOMDocument2);
11966 
11967     /* null pointer */
11968     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11969     EXPECT_HR(hr, E_POINTER);
11970 
11971     /* no document loaded */
11972     collection = (void*)0xdeadbeef;
11973     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11974     EXPECT_HR(hr, S_OK);
11975     if (hr != S_OK)
11976     {
11977         IXMLDOMDocument2_Release(doc);
11978         return;
11979     }
11980     EXPECT_REF(collection, 2);
11981 
11982     collection2 = (void*)0xdeadbeef;
11983     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11984     EXPECT_HR(hr, S_OK);
11985     ok(collection == collection2, "got %p\n", collection2);
11986     EXPECT_REF(collection, 3);
11987     IXMLDOMSchemaCollection_Release(collection);
11988 
11989     len = -1;
11990     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11991     EXPECT_HR(hr, S_OK);
11992     ok(len == 0, "got %d\n", len);
11993     IXMLDOMSchemaCollection_Release(collection);
11994 
11995     /* now with document */
11996     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11997     EXPECT_HR(hr, S_OK);
11998 
11999     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
12000     EXPECT_HR(hr, S_OK);
12001 
12002     len = -1;
12003     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
12004     EXPECT_HR(hr, S_OK);
12005     ok(len == 2, "got %d\n", len);
12006 
12007     /* try to lookup some uris */
12008     node = (void*)0xdeadbeef;
12009     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
12010     EXPECT_HR(hr, E_NOTIMPL);
12011     ok(broken(node == (void*)0xdeadbeef) || (node == NULL), "got %p\n", node);
12012 
12013     /* load schema and try to add it */
12014     doc2 = create_document(&IID_IXMLDOMDocument2);
12015     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
12016     EXPECT_HR(hr, S_OK);
12017 
12018     V_VT(&v) = VT_DISPATCH;
12019     V_DISPATCH(&v) = (IDispatch*)doc2;
12020     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
12021     EXPECT_HR(hr, E_FAIL);
12022     IXMLDOMDocument2_Release(doc2);
12023 
12024     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
12025     EXPECT_HR(hr, S_OK);
12026     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
12027     SysFreeString(s);
12028 
12029     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
12030     EXPECT_HR(hr, S_OK);
12031     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
12032     SysFreeString(s);
12033 
12034     s = (void*)0xdeadbeef;
12035     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
12036     EXPECT_HR(hr, E_FAIL);
12037     ok(broken(s == (void*)0xdeadbeef) || (s == NULL), "got %p\n", s);
12038 
12039     /* enumerate */
12040     enumv = (void*)0xdeadbeef;
12041     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
12042     EXPECT_HR(hr, S_OK);
12043     ok(enumv != NULL, "got %p\n", enumv);
12044 
12045     V_VT(&v) = VT_EMPTY;
12046     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12047     EXPECT_HR(hr, S_OK);
12048     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
12049     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
12050     VariantClear(&v);
12051 
12052     V_VT(&v) = VT_EMPTY;
12053     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12054     EXPECT_HR(hr, S_OK);
12055     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
12056     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
12057     VariantClear(&v);
12058 
12059     V_VT(&v) = VT_NULL;
12060     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12061     EXPECT_HR(hr, S_FALSE);
12062     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
12063 
12064     IEnumVARIANT_Release(enumv);
12065     IXMLDOMSchemaCollection_Release(collection);
12066     IXMLDOMDocument2_Release(doc);
12067     free_bstrs();
12068 }
12069 
12070 static const DOMNodeType put_data_types[] = {
12071     NODE_TEXT,
12072     NODE_CDATA_SECTION,
12073     NODE_PROCESSING_INSTRUCTION,
12074     NODE_COMMENT,
12075     NODE_INVALID
12076 };
12077 
12078 static void test_put_data(void)
12079 {
12080     static const WCHAR test_data[] = {'t','e','s','t',' ','n','o','d','e',' ','d','a','t','a',0};
12081     WCHAR buff[100], *data;
12082     IXMLDOMDocument *doc;
12083     const DOMNodeType *type;
12084     IXMLDOMText *text;
12085     IXMLDOMNode *node;
12086     VARIANT v;
12087     BSTR get_data;
12088     HRESULT hr;
12089 
12090     doc = create_document(&IID_IXMLDOMDocument);
12091 
12092     memcpy(&buff[2], test_data, sizeof(test_data));
12093     /* just a big length */
12094     *(DWORD*)buff = 0xf0f0;
12095     data = &buff[2];
12096 
12097     type = put_data_types;
12098     while (*type != NODE_INVALID)
12099     {
12100        V_VT(&v) = VT_I2;
12101        V_I2(&v) = *type;
12102 
12103        hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12104        EXPECT_HR(hr, S_OK);
12105 
12106        /* put_data() is interface-specific */
12107        switch (*type)
12108        {
12109            case NODE_TEXT:
12110            {
12111               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12112               EXPECT_HR(hr, S_OK);
12113               hr = IXMLDOMText_put_data(text, data);
12114               EXPECT_HR(hr, S_OK);
12115 
12116               hr = IXMLDOMText_get_data(text, &get_data);
12117               EXPECT_HR(hr, S_OK);
12118 
12119               IXMLDOMText_Release(text);
12120               break;
12121            }
12122            case NODE_CDATA_SECTION:
12123            {
12124               IXMLDOMCDATASection *cdata;
12125 
12126               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
12127               EXPECT_HR(hr, S_OK);
12128               hr = IXMLDOMCDATASection_put_data(cdata, data);
12129               EXPECT_HR(hr, S_OK);
12130 
12131               hr = IXMLDOMCDATASection_get_data(cdata, &get_data);
12132               EXPECT_HR(hr, S_OK);
12133 
12134               IXMLDOMCDATASection_Release(cdata);
12135               break;
12136            }
12137            case NODE_PROCESSING_INSTRUCTION:
12138            {
12139               IXMLDOMProcessingInstruction *pi;
12140 
12141               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)&pi);
12142               EXPECT_HR(hr, S_OK);
12143               hr = IXMLDOMProcessingInstruction_put_data(pi, data);
12144               EXPECT_HR(hr, S_OK);
12145 
12146               hr = IXMLDOMProcessingInstruction_get_data(pi, &get_data);
12147               EXPECT_HR(hr, S_OK);
12148 
12149               IXMLDOMProcessingInstruction_Release(pi);
12150               break;
12151            }
12152            case NODE_COMMENT:
12153            {
12154               IXMLDOMComment *comment;
12155 
12156               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
12157               EXPECT_HR(hr, S_OK);
12158               hr = IXMLDOMComment_put_data(comment, data);
12159               EXPECT_HR(hr, S_OK);
12160 
12161               hr = IXMLDOMComment_get_data(comment, &get_data);
12162               EXPECT_HR(hr, S_OK);
12163 
12164               IXMLDOMComment_Release(comment);
12165               break;
12166            }
12167            default:
12168               get_data = NULL;
12169               break;
12170        }
12171 
12172        /* compare */
12173        ok(!lstrcmpW(data, get_data), "%d: got wrong data %s, expected %s\n", *type, wine_dbgstr_w(get_data),
12174            wine_dbgstr_w(data));
12175        SysFreeString(get_data);
12176 
12177        IXMLDOMNode_Release(node);
12178        type++;
12179     }
12180 
12181     IXMLDOMDocument_Release(doc);
12182     free_bstrs();
12183 }
12184 
12185 static void test_newline_normalization(void)
12186 {
12187     const struct msxmlsupported_data_t *table = domdoc_support_data;
12188     IXMLDOMDocument *doc;
12189     IXMLDOMText *text;
12190     IXMLDOMNode *node;
12191     VARIANT v;
12192     VARIANT_BOOL b;
12193     BSTR s;
12194     HRESULT hr;
12195     LONG length;
12196 
12197     V_VT(&v) = VT_I2;
12198     V_I2(&v) = NODE_TEXT;
12199 
12200     while (table->clsid)
12201     {
12202         if (!is_clsid_supported(table->clsid, &IID_IXMLDOMDocument))
12203         {
12204             table++;
12205             continue;
12206         }
12207 
12208         hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
12209         ok(hr == S_OK, "got 0x%08x\n", hr);
12210 
12211         hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12212         ok(hr == S_OK, "got 0x%08x\n", hr);
12213 
12214         IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12215 
12216         /* \r\n is normalized to \n and back to \r\n */
12217 
12218         hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
12219         ok(hr == S_OK, "got 0x%08x\n", hr);
12220 
12221         hr = IXMLDOMText_get_data(text, &s);
12222         ok(hr == S_OK, "got 0x%08x\n", hr);
12223         ok(!lstrcmpW(s, _bstr_("\n")), "got %s\n", wine_dbgstr_w(s));
12224         SysFreeString(s);
12225 
12226         hr = IXMLDOMText_get_length(text, &length);
12227         ok(hr == S_OK, "got 0x%08x\n", hr);
12228         ok(length == 1, "got %d, expected 1\n", length);
12229 
12230         hr = IXMLDOMText_get_xml(text, &s);
12231         ok(hr == S_OK, "got 0x%08x\n", hr);
12232         ok(!lstrcmpW(s, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(s));
12233         SysFreeString(s);
12234 
12235         /* \r\r\n is normalized to \n\n and back to \r\n\r\n */
12236 
12237         hr = IXMLDOMText_put_data(text, _bstr_("\r\r\n"));
12238         ok(hr == S_OK, "got 0x%08x\n", hr);
12239 
12240         hr = IXMLDOMText_get_data(text, &s);
12241         ok(hr == S_OK, "got 0x%08x\n", hr);
12242         ok(!lstrcmpW(s, _bstr_("\n\n")), "got %s\n", wine_dbgstr_w(s));
12243         SysFreeString(s);
12244 
12245         hr = IXMLDOMText_get_length(text, &length);
12246         ok(hr == S_OK, "got 0x%08x\n", hr);
12247         ok(length == 2, "got %d, expected 2\n", length);
12248 
12249         hr = IXMLDOMText_get_xml(text, &s);
12250         ok(hr == S_OK, "got 0x%08x\n", hr);
12251         ok(!lstrcmpW(s, _bstr_("\r\n\r\n")), "got %s\n", wine_dbgstr_w(s));
12252         SysFreeString(s);
12253 
12254         /* the same normalizations are applied when loading a document as a whole */
12255 
12256         hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?><root>foo\n\r\n\r\r\nbar</root>"), &b);
12257         ok(hr == S_OK, "got 0x%08x\n", hr);
12258 
12259         hr = IXMLDOMDocument_get_text(doc, &s);
12260         ok(hr == S_OK, "got 0x%08x\n", hr);
12261         ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12262         SysFreeString(s);
12263 
12264         hr = IXMLDOMDocument_get_xml(doc, &s);
12265         ok(hr == S_OK, "got 0x%08x\n", hr);
12266         ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n<root>foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12267            "got %s\n", wine_dbgstr_w(s));
12268         SysFreeString(s);
12269 
12270         /* even if xml:space="preserve" */
12271 
12272         hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?>"
12273                                                  "<root xml:space=\"preserve\">foo\n\r\n\r\r\nbar</root>"), &b);
12274         ok(hr == S_OK, "got 0x%08x\n", hr);
12275 
12276         hr = IXMLDOMDocument_get_text(doc, &s);
12277         ok(hr == S_OK, "got 0x%08x\n", hr);
12278         ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12279         SysFreeString(s);
12280 
12281         hr = IXMLDOMDocument_get_xml(doc, &s);
12282         ok(hr == S_OK, "got 0x%08x\n", hr);
12283         ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n"
12284                                "<root xml:space=\"preserve\">foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12285            "got %s\n", wine_dbgstr_w(s));
12286         SysFreeString(s);
12287 
12288         /* or preserveWhiteSpace is set */
12289 
12290         hr = IXMLDOMDocument_put_preserveWhiteSpace(doc, VARIANT_TRUE);
12291         ok(hr == S_OK, "got 0x%08x\n", hr);
12292 
12293         hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?><root>foo\n\r\n\r\r\nbar</root>"), &b);
12294         ok(hr == S_OK, "got 0x%08x\n", hr);
12295 
12296         hr = IXMLDOMDocument_get_text(doc, &s);
12297         ok(hr == S_OK, "got 0x%08x\n", hr);
12298         ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12299         SysFreeString(s);
12300 
12301         hr = IXMLDOMDocument_get_xml(doc, &s);
12302         ok(hr == S_OK, "got 0x%08x\n", hr);
12303         if (IsEqualGUID(table->clsid, &CLSID_DOMDocument60))
12304         {
12305             /* DOMDocument60 does the newline normalization but does not insert line breaks around the root node */
12306 todo_wine
12307             ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?><root>foo\r\n\r\n\r\n\r\nbar</root>")),
12308                "got %s\n", wine_dbgstr_w(s));
12309         }
12310         else
12311         {
12312             ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n<root>foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12313                "got %s\n", wine_dbgstr_w(s));
12314         }
12315         SysFreeString(s);
12316 
12317         IXMLDOMText_Release(text);
12318         IXMLDOMNode_Release(node);
12319         IXMLDOMDocument_Release(doc);
12320         free_bstrs();
12321         table++;
12322     }
12323 }
12324 
12325 static void test_putref_schemas(void)
12326 {
12327     IXMLDOMSchemaCollection *cache;
12328     IXMLDOMDocument2 *doc;
12329     VARIANT schema;
12330     HRESULT hr;
12331 
12332     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
12333     if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
12334 
12335     doc = create_document(&IID_IXMLDOMDocument2);
12336     cache = create_cache(&IID_IXMLDOMSchemaCollection);
12337 
12338     /* set to NULL iface when no schema is set */
12339     V_VT(&schema) = VT_DISPATCH;
12340     V_DISPATCH(&schema) = NULL;
12341     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12342     EXPECT_HR(hr, S_OK);
12343 
12344     V_VT(&schema) = VT_UNKNOWN;
12345     V_UNKNOWN(&schema) = NULL;
12346     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12347     EXPECT_HR(hr, S_OK);
12348 
12349     /* set as VT_DISPATCH, reset with it */
12350     V_VT(&schema) = VT_DISPATCH;
12351     V_DISPATCH(&schema) = (IDispatch*)cache;
12352     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12353     EXPECT_HR(hr, S_OK);
12354 
12355     V_DISPATCH(&schema) = NULL;
12356     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12357     EXPECT_HR(hr, S_OK);
12358     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12359 
12360     V_VT(&schema) = VT_DISPATCH;
12361     V_DISPATCH(&schema) = NULL;
12362     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12363     EXPECT_HR(hr, S_OK);
12364 
12365     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12366     V_VT(&schema) = VT_I2;
12367     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12368     EXPECT_HR(hr, S_FALSE);
12369     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12370     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12371 
12372     /* set as VT_UNKNOWN, reset with it */
12373     V_VT(&schema) = VT_UNKNOWN;
12374     V_UNKNOWN(&schema) = (IUnknown*)cache;
12375     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12376     EXPECT_HR(hr, S_OK);
12377 
12378     V_DISPATCH(&schema) = NULL;
12379     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12380     EXPECT_HR(hr, S_OK);
12381     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12382 
12383     V_VT(&schema) = VT_UNKNOWN;
12384     V_UNKNOWN(&schema) = NULL;
12385     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12386     EXPECT_HR(hr, S_OK);
12387 
12388     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12389     V_VT(&schema) = VT_I2;
12390     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12391     EXPECT_HR(hr, S_FALSE);
12392     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12393     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12394 
12395     IXMLDOMSchemaCollection_Release(cache);
12396     IXMLDOMDocument2_Release(doc);
12397 }
12398 
12399 static void test_namedmap_newenum(void)
12400 {
12401     IEnumVARIANT *enum1, *enum2, *enum3;
12402     IXMLDOMNamedNodeMap *map;
12403     IUnknown *unk1, *unk2;
12404     IXMLDOMDocument *doc;
12405     IXMLDOMElement *elem;
12406     IXMLDOMNode *node;
12407     VARIANT_BOOL b;
12408     HRESULT hr;
12409     VARIANT v;
12410     BSTR str;
12411 
12412     doc = create_document(&IID_IXMLDOMDocument);
12413 
12414     hr = IXMLDOMDocument_loadXML(doc, _bstr_(attributes_map), &b);
12415     EXPECT_HR(hr, S_OK);
12416 
12417     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
12418     EXPECT_HR(hr, S_OK);
12419 
12420     hr = IXMLDOMElement_get_attributes(elem, &map);
12421     EXPECT_HR(hr, S_OK);
12422     IXMLDOMElement_Release(elem);
12423 
12424     enum1 = NULL;
12425     EXPECT_REF(map, 1);
12426     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum1);
12427     EXPECT_HR(hr, S_OK);
12428     ok(enum1 != NULL, "got %p\n", enum1);
12429     EXPECT_REF(map, 1);
12430     EXPECT_REF(enum1, 2);
12431 
12432     enum2 = NULL;
12433     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum2);
12434     EXPECT_HR(hr, S_OK);
12435     ok(enum2 == enum1, "got %p\n", enum2);
12436 
12437     IEnumVARIANT_Release(enum2);
12438 
12439     EXPECT_REF(map, 1);
12440     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum2);
12441     EXPECT_HR(hr, S_OK);
12442     EXPECT_REF(map, 2);
12443     EXPECT_REF(enum2, 1);
12444     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
12445 
12446     IEnumVARIANT_Release(enum1);
12447 
12448     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
12449     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk1);
12450     EXPECT_HR(hr, S_OK);
12451     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
12452     EXPECT_HR(hr, S_OK);
12453     EXPECT_REF(map, 3);
12454     EXPECT_REF(enum2, 2);
12455     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
12456     IUnknown_Release(unk1);
12457     IUnknown_Release(unk2);
12458 
12459     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum3);
12460     EXPECT_HR(hr, S_OK);
12461     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
12462     IEnumVARIANT_Release(enum3);
12463 
12464     /* iteration tests */
12465     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node);
12466     EXPECT_HR(hr, S_OK);
12467     hr = IXMLDOMNode_get_nodeName(node, &str);
12468     EXPECT_HR(hr, S_OK);
12469     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12470     SysFreeString(str);
12471     IXMLDOMNode_Release(node);
12472 
12473     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12474     EXPECT_HR(hr, S_OK);
12475     hr = IXMLDOMNode_get_nodeName(node, &str);
12476     EXPECT_HR(hr, S_OK);
12477     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12478     SysFreeString(str);
12479     IXMLDOMNode_Release(node);
12480 
12481     V_VT(&v) = VT_EMPTY;
12482     hr = IEnumVARIANT_Next(enum2, 1, &v, NULL);
12483     EXPECT_HR(hr, S_OK);
12484     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
12485     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
12486     EXPECT_HR(hr, S_OK);
12487     hr = IXMLDOMNode_get_nodeName(node, &str);
12488     EXPECT_HR(hr, S_OK);
12489     ok(!lstrcmpW(str, _bstr_("attr1")), "got node name %s\n", wine_dbgstr_w(str));
12490     SysFreeString(str);
12491     IXMLDOMNode_Release(node);
12492     VariantClear(&v);
12493 
12494     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12495     EXPECT_HR(hr, S_OK);
12496     hr = IXMLDOMNode_get_nodeName(node, &str);
12497     EXPECT_HR(hr, S_OK);
12498     ok(!lstrcmpW(str, _bstr_("attr2")), "got %s\n", wine_dbgstr_w(str));
12499     SysFreeString(str);
12500     IXMLDOMNode_Release(node);
12501 
12502     IEnumVARIANT_Release(enum2);
12503     IXMLDOMNamedNodeMap_Release(map);
12504     IXMLDOMDocument_Release(doc);
12505 }
12506 
12507 static const char xsltext_xsl[] =
12508 "<?xml version=\"1.0\"?>"
12509 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12510 "<xsl:output method=\"html\" encoding=\"us-ascii\"/>"
12511 "<xsl:template match=\"/\">"
12512 "    <xsl:choose>"
12513 "        <xsl:when test=\"testkey\">"
12514 "            <xsl:text>testdata</xsl:text>"
12515 "        </xsl:when>"
12516 "    </xsl:choose>"
12517 "</xsl:template>"
12518 "</xsl:stylesheet>";
12519 
12520 static const char omitxmldecl_xsl[] =
12521 "<?xml version=\"1.0\"?>"
12522 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12523 "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\"/>"
12524 "<xsl:template match=\"/\">"
12525 "    <xsl:for-each select=\"/a/item\">"
12526 "        <xsl:element name=\"node\">"
12527 "            <xsl:value-of select=\"@name\"/>"
12528 "        </xsl:element>"
12529 "    </xsl:for-each>"
12530 "</xsl:template>"
12531 "</xsl:stylesheet>";
12532 
12533 static const char omitxmldecl_doc[] =
12534 "<?xml version=\"1.0\"?>"
12535 "<a>"
12536 "    <item name=\"item1\"/>"
12537 "    <item name=\"item2\"/>"
12538 "</a>";
12539 
12540 static void test_xsltext(void)
12541 {
12542     IXMLDOMDocument *doc, *doc2;
12543     VARIANT_BOOL b;
12544     HRESULT hr;
12545     BSTR ret;
12546 
12547     doc = create_document(&IID_IXMLDOMDocument);
12548     doc2 = create_document(&IID_IXMLDOMDocument);
12549 
12550     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsltext_xsl), &b);
12551     EXPECT_HR(hr, S_OK);
12552 
12553     hr = IXMLDOMDocument_loadXML(doc2, _bstr_("<testkey/>"), &b);
12554     EXPECT_HR(hr, S_OK);
12555 
12556     hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12557     EXPECT_HR(hr, S_OK);
12558     ok(!lstrcmpW(ret, _bstr_("testdata")), "transform result %s\n", wine_dbgstr_w(ret));
12559     SysFreeString(ret);
12560 
12561     /* omit-xml-declaration */
12562     hr = IXMLDOMDocument_loadXML(doc, _bstr_(omitxmldecl_xsl), &b);
12563     ok(hr == S_OK, "got 0x%08x\n", hr);
12564     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(omitxmldecl_doc), &b);
12565     ok(hr == S_OK, "got 0x%08x\n", hr);
12566 
12567     hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12568     ok(hr == S_OK, "got 0x%08x\n", hr);
12569     ok(!lstrcmpW(ret, _bstr_("<node>item1</node><node>item2</node>")), "transform result %s\n", wine_dbgstr_w(ret));
12570     SysFreeString(ret);
12571 
12572     IXMLDOMDocument_Release(doc2);
12573     IXMLDOMDocument_Release(doc);
12574     free_bstrs();
12575 }
12576 
12577 struct attrtest_t {
12578     const char *name;
12579     const char *uri;
12580     const char *prefix;
12581     const char *href;
12582 };
12583 
12584 static struct attrtest_t attrtests[] = {
12585     { "xmlns", "http://www.w3.org/2000/xmlns/", "xmlns", "xmlns" },
12586     { "xmlns", "nondefaulturi", "xmlns", "xmlns" },
12587     { "c", "http://www.w3.org/2000/xmlns/", NULL, "http://www.w3.org/2000/xmlns/" },
12588     { "c", "nsref1", NULL, "nsref1" },
12589     { "ns:c", "nsref1", "ns", "nsref1" },
12590     { "xmlns:c", "http://www.w3.org/2000/xmlns/", "xmlns", "" },
12591     { "xmlns:c", "nondefaulturi", "xmlns", "" },
12592     { 0 }
12593 };
12594 
12595 static void test_create_attribute(void)
12596 {
12597     struct attrtest_t *ptr = attrtests;
12598     IXMLDOMElement *el;
12599     IXMLDOMDocument *doc;
12600     IXMLDOMNode *node, *node2;
12601     VARIANT var;
12602     HRESULT hr;
12603     int i = 0;
12604     BSTR str;
12605 
12606     doc = create_document(&IID_IXMLDOMDocument);
12607 
12608     while (ptr->name)
12609     {
12610         V_VT(&var) = VT_I1;
12611         V_I1(&var) = NODE_ATTRIBUTE;
12612         hr = IXMLDOMDocument_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
12613         ok(hr == S_OK, "got 0x%08x\n", hr);
12614 
12615         str = NULL;
12616         hr = IXMLDOMNode_get_prefix(node, &str);
12617         if (ptr->prefix)
12618         {
12619             ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12620             ok(!lstrcmpW(str, _bstr_(ptr->prefix)), "%d: got prefix %s, expected %s\n", i, wine_dbgstr_w(str), ptr->prefix);
12621         }
12622         else
12623         {
12624             ok(hr == S_FALSE, "%d: got 0x%08x\n", i, hr);
12625             ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str));
12626         }
12627         SysFreeString(str);
12628 
12629         str = NULL;
12630         hr = IXMLDOMNode_get_namespaceURI(node, &str);
12631         ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12632         ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", i, wine_dbgstr_w(str), ptr->href);
12633         SysFreeString(str);
12634 
12635         IXMLDOMNode_Release(node);
12636         free_bstrs();
12637 
12638         i++;
12639         ptr++;
12640     }
12641 
12642     V_VT(&var) = VT_I1;
12643     V_I1(&var) = NODE_ELEMENT;
12644     hr = IXMLDOMDocument_createNode(doc, var, _bstr_("e"), NULL, &node2);
12645     ok(hr == S_OK, "got 0x%08x\n", hr);
12646 
12647     hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&el);
12648     ok(hr == S_OK, "got 0x%08x\n", hr);
12649     IXMLDOMNode_Release(node2);
12650 
12651     V_VT(&var) = VT_I1;
12652     V_I1(&var) = NODE_ATTRIBUTE;
12653     hr = IXMLDOMDocument_createNode(doc, var, _bstr_("xmlns:a"), _bstr_("http://www.w3.org/2000/xmlns/"), &node);
12654     ok(hr == S_OK, "got 0x%08x\n", hr);
12655 
12656     hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL);
12657     ok(hr == S_OK, "got 0x%08x\n", hr);
12658 
12659     /* for some reason default namespace uri is not reported */
12660     hr = IXMLDOMNode_get_namespaceURI(node, &str);
12661     ok(hr == S_OK, "got 0x%08x\n", hr);
12662     ok(!lstrcmpW(str, _bstr_("")), "got uri %s\n", wine_dbgstr_w(str));
12663     SysFreeString(str);
12664 
12665     IXMLDOMNode_Release(node);
12666     IXMLDOMElement_Release(el);
12667     IXMLDOMDocument_Release(doc);
12668     free_bstrs();
12669 }
12670 
12671 static void test_url(void)
12672 {
12673     IXMLDOMDocument *doc;
12674     HRESULT hr;
12675     BSTR s;
12676 
12677     doc = create_document(&IID_IXMLDOMDocument);
12678 
12679     hr = IXMLDOMDocument_get_url(doc, NULL);
12680     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
12681 
12682     s = (void *)0xdeadbeef;
12683     hr = IXMLDOMDocument_get_url(doc, &s);
12684     ok(hr == S_FALSE, "got 0x%08x\n", hr);
12685     ok(s == NULL, "got %s\n", wine_dbgstr_w(s));
12686 
12687     IXMLDOMDocument_Release(doc);
12688 }
12689 
12690 static void test_merging_text(void)
12691 {
12692     IXMLDOMText *nodetext;
12693     IXMLDOMText *newtext;
12694     IXMLDOMElement *root;
12695     IXMLDOMDocument *doc;
12696     IXMLDOMNode *first;
12697     HRESULT hr;
12698     VARIANT v;
12699     BSTR str;
12700     int i;
12701 
12702     doc = create_document(&IID_IXMLDOMDocument);
12703 
12704     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
12705     EXPECT_HR(hr, S_OK);
12706 
12707     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
12708     EXPECT_HR(hr, S_OK);
12709 
12710     /* test xmlAddChild */
12711     for (i = 0; i < 10; i++)
12712     {
12713         str = SysAllocString(szstr1);
12714         hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12715         SysFreeString(str);
12716         EXPECT_HR(hr, S_OK);
12717 
12718         newtext = NULL;
12719         hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)nodetext, (IXMLDOMNode**)&newtext);
12720         EXPECT_HR(hr, S_OK);
12721         ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12722 
12723         IXMLDOMText_Release(newtext);
12724         IXMLDOMText_Release(nodetext);
12725     }
12726 
12727     /* test xmlAddPrevSibling */
12728     hr = IXMLDOMElement_get_firstChild(root, &first);
12729     EXPECT_HR(hr, S_OK);
12730     V_VT(&v) = VT_UNKNOWN;
12731     V_UNKNOWN(&v) = (IUnknown*)first;
12732     for (i = 0; i < 10; i++)
12733     {
12734         str = SysAllocString(szstr2);
12735         hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12736         SysFreeString(str);
12737         EXPECT_HR(hr, S_OK);
12738 
12739         newtext = NULL;
12740         hr = IXMLDOMElement_insertBefore(root, (IXMLDOMNode*)nodetext, v, (IXMLDOMNode**)&newtext);
12741         EXPECT_HR(hr, S_OK);
12742         ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12743 
12744         IXMLDOMText_Release(newtext);
12745         IXMLDOMText_Release(nodetext);
12746     }
12747 
12748     IXMLDOMNode_Release(first);
12749     IXMLDOMElement_Release(root);
12750     IXMLDOMDocument_Release(doc);
12751 
12752     free_bstrs();
12753 }
12754 
12755 static HRESULT WINAPI transformdest_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
12756 {
12757     BOOL known_iid = IsEqualIID(riid, &IID_IHTMLObjectElement) ||
12758         IsEqualIID(riid, &IID_transformdest_unknown) ||
12759         IsEqualIID(riid, &IID_IServiceProvider) ||
12760         IsEqualIID(riid, &IID_IStream) ||
12761         IsEqualIID(riid, &IID_ISequentialStream) ||
12762         IsEqualIID(riid, &IID_IRequestDictionary);
12763 
12764 todo_wine_if(IsEqualIID(riid, &IID_IXMLDOMDocument))
12765     ok(known_iid, "Unexpected riid %s\n", wine_dbgstr_guid(riid));
12766 
12767     return E_NOINTERFACE;
12768 }
12769 
12770 static ULONG WINAPI transformdest_AddRef(IUnknown *iface)
12771 {
12772     return 2;
12773 }
12774 
12775 static ULONG WINAPI transformdest_Release(IUnknown *iface)
12776 {
12777     return 1;
12778 }
12779 
12780 static const IUnknownVtbl transformdestvtbl =
12781 {
12782     transformdest_QueryInterface,
12783     transformdest_AddRef,
12784     transformdest_Release,
12785 };
12786 
12787 static void test_transformNodeToObject(void)
12788 {
12789     IUnknown transformdest = { &transformdestvtbl };
12790     IXMLDOMDocument *doc, *doc2, *doc3;
12791     VARIANT_BOOL b;
12792     HRESULT hr;
12793     VARIANT v;
12794 
12795     doc = create_document(&IID_IXMLDOMDocument);
12796     doc2 = create_document(&IID_IXMLDOMDocument);
12797     doc3 = create_document(&IID_IXMLDOMDocument);
12798 
12799     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &b);
12800     ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12801     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformSSXML), &b);
12802     ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12803 
12804     V_VT(&v) = VT_UNKNOWN;
12805     V_UNKNOWN(&v) = &transformdest;
12806     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12807     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12808 
12809     V_VT(&v) = VT_UNKNOWN;
12810     V_UNKNOWN(&v) = NULL;
12811     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12812     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12813 
12814     V_VT(&v) = VT_DISPATCH;
12815     V_DISPATCH(&v) = NULL;
12816     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12817     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12818 
12819     V_VT(&v) = VT_DISPATCH;
12820     V_DISPATCH(&v) = (IDispatch *)doc3;
12821     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12822     ok(hr == S_OK, "Failed to transform node, hr %#x.\n", hr);
12823 
12824     IXMLDOMDocument_Release(doc3);
12825     IXMLDOMDocument_Release(doc2);
12826     IXMLDOMDocument_Release(doc);
12827     free_bstrs();
12828 }
12829 
12830 static void test_normalize_attribute_values(void)
12831 {
12832     IXMLDOMDocument2 *doc;
12833     VARIANT var;
12834     HRESULT hr;
12835 
12836     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument2))
12837     {
12838         win_skip("NormalizeAttributeValues is not supported.\n");
12839         return;
12840     }
12841 
12842     doc = create_document_version(60, &IID_IXMLDOMDocument2);
12843 
12844     V_VT(&var) = VT_I2;
12845     V_I2(&var) = 10;
12846     hr = IXMLDOMDocument2_getProperty(doc, _bstr_("NormalizeAttributeValues"), &var);
12847 todo_wine {
12848     ok(hr == S_OK, "Failed to get property value, hr %#x.\n", hr);
12849     ok(V_VT(&var) == VT_BOOL, "Unexpected property value type, vt %d.\n", V_VT(&var));
12850     ok(V_BOOL(&var) == VARIANT_FALSE, "Unexpected property value.\n");
12851 }
12852     V_VT(&var) = VT_BOOL;
12853     V_BOOL(&var) = VARIANT_TRUE;
12854     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("NormalizeAttributeValues"), var);
12855     ok(hr == S_OK, "Failed to set property, hr %#x.\n", hr);
12856 
12857     V_VT(&var) = VT_I2;
12858     V_I2(&var) = 10;
12859     hr = IXMLDOMDocument2_getProperty(doc, _bstr_("NormalizeAttributeValues"), &var);
12860 todo_wine {
12861     ok(hr == S_OK, "Failed to get property value, hr %#x.\n", hr);
12862     ok(V_VT(&var) == VT_BOOL, "Unexpected property value type, vt %d.\n", V_VT(&var));
12863     ok(V_BOOL(&var) == VARIANT_TRUE, "Unexpected property value.\n");
12864 }
12865     IXMLDOMDocument2_Release(doc);
12866 }
12867 
12868 typedef struct _namespace_as_attribute_t {
12869     const GUID *guid;
12870     const char *clsid;
12871     const char *xmlns_uri;
12872 } namespace_as_attribute_t;
12873 
12874 static const namespace_as_attribute_t namespace_as_attribute_test_data[] = {
12875     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "" },
12876     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "" },
12877     { &CLSID_DOMDocument26, "CLSID_DOMDocument26", "" },
12878     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "" },
12879     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "" },
12880     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "http://www.w3.org/2000/xmlns/" },
12881     { 0 }
12882 };
12883 
12884 static void test_namespaces_as_attributes(void)
12885 {
12886     const namespace_as_attribute_t *entry = namespace_as_attribute_test_data;
12887     struct test {
12888         const char *xml;
12889         int explen;
12890         const char *names[3];
12891         const char *prefixes[3];
12892         const char *basenames[3];
12893         const char *uris[3];
12894         const char *texts[3];
12895     };
12896     static const struct test tests[] = {
12897         {
12898             "<a ns:b=\"b attr\" d=\"d attr\" xmlns:ns=\"nshref\" />", 3,
12899             { "ns:b",   "d",     "xmlns:ns" },  /* nodeName */
12900             { "ns",     NULL,     "xmlns" },    /* prefix */
12901             { "b",      "d",      "ns" },       /* baseName */
12902             { "nshref", NULL,     "" },         /* namespaceURI */
12903             { "b attr", "d attr", "nshref" },   /* text */
12904         },
12905         /* property only */
12906         {
12907             "<a d=\"d attr\" />", 1,
12908             { "d" },        /* nodeName */
12909             { NULL },       /* prefix */
12910             { "d" },        /* baseName */
12911             { NULL },       /* namespaceURI */
12912             { "d attr" },   /* text */
12913         },
12914         /* namespace only */
12915         {
12916             "<a xmlns:ns=\"nshref\" />", 1,
12917             { "xmlns:ns" }, /* nodeName */
12918             { "xmlns" },    /* prefix */
12919             { "ns" },       /* baseName */
12920             { "" },         /* namespaceURI */
12921             { "nshref" },   /* text */
12922         },
12923         /* no properties or namespaces */
12924         {
12925             "<a />", 0,
12926         },
12927 
12928         { NULL }
12929     };
12930     const struct test *test;
12931     IXMLDOMNamedNodeMap *map;
12932     IXMLDOMNode *node, *item;
12933     IXMLDOMDocument *doc;
12934     VARIANT_BOOL b;
12935     LONG len, i;
12936     HRESULT hr;
12937     BSTR str;
12938 
12939     while (entry->guid)
12940     {
12941         if (!is_clsid_supported(entry->guid, &IID_IXMLDOMDocument2))
12942         {
12943             entry++;
12944             continue;
12945         }
12946 
12947         test = tests;
12948         while (test->xml) {
12949             hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc);
12950             ok(SUCCEEDED(hr), "Failed to create document %s, hr %#x.\n", wine_dbgstr_guid(entry->guid), hr);
12951 
12952             hr = IXMLDOMDocument_loadXML(doc, _bstr_(test->xml), &b);
12953             ok(hr == S_OK, "Failed to load xml, hr %#x.\n", hr);
12954 
12955             node = NULL;
12956             hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
12957             ok(SUCCEEDED(hr), "Failed to select a node, hr %#x.\n", hr);
12958 
12959             hr = IXMLDOMNode_get_attributes(node, &map);
12960             ok(SUCCEEDED(hr), "Failed to get attributes, hr %#x.\n", hr);
12961 
12962             len = -1;
12963             hr = IXMLDOMNamedNodeMap_get_length(map, &len);
12964             ok(SUCCEEDED(hr), "Failed to get map length, hr %#x.\n", hr);
12965             ok(len == test->explen, "got %d\n", len);
12966 
12967             item = NULL;
12968             hr = IXMLDOMNamedNodeMap_get_item(map, test->explen+1, &item);
12969             ok(hr == S_FALSE, "Failed to get item, hr %#x.\n", hr);
12970             ok(!item, "Item should be NULL\n");
12971 
12972             for (i = 0; i < len; i++)
12973             {
12974                 item = NULL;
12975                 hr = IXMLDOMNamedNodeMap_get_item(map, i, &item);
12976                 ok(SUCCEEDED(hr), "Failed to get item, hr %#x.\n", hr);
12977 
12978                 str = NULL;
12979                 hr = IXMLDOMNode_get_nodeName(item, &str);
12980                 ok(SUCCEEDED(hr), "Failed to get node name, hr %#x.\n", hr);
12981                 ok(!lstrcmpW(str, _bstr_(test->names[i])), "got %s\n", wine_dbgstr_w(str));
12982                 SysFreeString(str);
12983 
12984                 str = NULL;
12985                 hr = IXMLDOMNode_get_prefix(item, &str);
12986                 if (test->prefixes[i])
12987                 {
12988                     ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr);
12989                     ok(!lstrcmpW(str, _bstr_(test->prefixes[i])), "got %s\n", wine_dbgstr_w(str));
12990                     SysFreeString(str);
12991                 }
12992                 else
12993                     ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
12994 
12995                 str = NULL;
12996                 hr = IXMLDOMNode_get_baseName(item, &str);
12997                 ok(SUCCEEDED(hr), "Failed to get base name, hr %#x.\n", hr);
12998                 ok(!lstrcmpW(str, _bstr_(test->basenames[i])), "got %s\n", wine_dbgstr_w(str));
12999                 SysFreeString(str);
13000 
13001                 str = NULL;
13002                 hr = IXMLDOMNode_get_namespaceURI(item, &str);
13003                 if (test->uris[i])
13004                 {
13005                     ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr);
13006                     if (test->prefixes[i] && !strcmp(test->prefixes[i], "xmlns"))
13007                         ok(!lstrcmpW(str, _bstr_(entry->xmlns_uri)), "got %s\n", wine_dbgstr_w(str));
13008                     else
13009                         ok(!lstrcmpW(str, _bstr_(test->uris[i])), "got %s\n", wine_dbgstr_w(str));
13010                     SysFreeString(str);
13011                 }
13012                 else
13013                     ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
13014 
13015                 str = NULL;
13016                 hr = IXMLDOMNode_get_text(item, &str);
13017                 ok(SUCCEEDED(hr), "Failed to get node text, hr %#x.\n", hr);
13018                 ok(!lstrcmpW(str, _bstr_(test->texts[i])), "got %s\n", wine_dbgstr_w(str));
13019                 SysFreeString(str);
13020 
13021                 IXMLDOMNode_Release(item);
13022             }
13023 
13024             IXMLDOMNamedNodeMap_Release(map);
13025             IXMLDOMNode_Release(node);
13026             IXMLDOMDocument_Release(doc);
13027 
13028             test++;
13029         }
13030 
13031         entry++;
13032     }
13033     free_bstrs();
13034 }
13035 
13036 START_TEST(domdoc)
13037 {
13038     HRESULT hr;
13039 
13040     hr = CoInitialize( NULL );
13041     ok( hr == S_OK, "failed to init com\n");
13042     if (hr != S_OK) return;
13043 
13044     get_class_support_data(domdoc_support_data);
13045     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument))
13046     {
13047         win_skip("DOMDocument2 is not supported. Skipping all tests.\n");
13048         CoUninitialize();
13049         return;
13050     }
13051 
13052     test_domdoc();
13053     test_persiststream();
13054     test_domnode();
13055     test_refs();
13056     test_create();
13057     test_getElementsByTagName();
13058     test_get_text();
13059     test_get_childNodes();
13060     test_get_firstChild();
13061     test_get_lastChild();
13062     test_removeChild();
13063     test_replaceChild();
13064     test_removeNamedItem();
13065     test_IXMLDOMDocument2();
13066     test_whitespace();
13067     test_XPath();
13068     test_XSLPattern();
13069     test_cloneNode();
13070     test_xmlTypes();
13071     test_save();
13072     test_testTransforms();
13073     test_namespaces_basic();
13074     test_namespaces_change();
13075     test_FormattingXML();
13076     test_nodeTypedValue();
13077     test_TransformWithLoadingLocalFile();
13078     test_put_nodeValue();
13079     test_IObjectSafety();
13080     test_splitText();
13081     test_getQualifiedItem();
13082     test_removeQualifiedItem();
13083     test_get_ownerDocument();
13084     test_setAttributeNode();
13085     test_put_dataType();
13086     test_createNode();
13087     test_create_attribute();
13088     test_get_prefix();
13089     test_default_properties();
13090     test_selectSingleNode();
13091     test_events();
13092     test_createProcessingInstruction();
13093     test_put_nodeTypedValue();
13094     test_get_xml();
13095     test_insertBefore();
13096     test_appendChild();
13097     test_get_doctype();
13098     test_get_tagName();
13099     test_get_dataType();
13100     test_get_nodeTypeString();
13101     test_get_attributes();
13102     test_selection();
13103     test_load();
13104     test_dispex();
13105     test_parseerror();
13106     test_getAttributeNode();
13107     test_getAttribute();
13108     test_supporterrorinfo();
13109     test_nodeValue();
13110     test_get_namespaces();
13111     test_put_data();
13112     test_newline_normalization();
13113     test_putref_schemas();
13114     test_namedmap_newenum();
13115     test_xmlns_attribute();
13116     test_url();
13117     test_merging_text();
13118     test_transformNodeToObject();
13119     test_normalize_attribute_values();
13120     test_namespaces_as_attributes();
13121 
13122     test_xsltemplate();
13123     test_xsltext();
13124 
13125     if (is_clsid_supported(&CLSID_MXNamespaceManager40, &IID_IMXNamespaceManager))
13126     {
13127         test_mxnamespacemanager();
13128         test_mxnamespacemanager_override();
13129     }
13130 
13131     CoUninitialize();
13132 }
13133