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 #include "precomp.h"
25 
26 #include <asptlb.h>
27 
28 /* undef the #define in msxml2 so that we can access all versions */
29 #undef CLSID_DOMDocument
30 
31 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
32 DEFINE_GUID(IID_transformdest_unknown,0xf5078f3a,0xc551,0x11d3,0x89,0xb9,0x00,0x00,0xf8,0x1f,0xe2,0x21);
33 
34 static int g_unexpectedcall, g_expectedcall;
35 
36 struct msxmlsupported_data_t
37 {
38     const GUID *clsid;
39     const char *name;
40     const IID  *ifaces[3];
41     BOOL        supported[3];
42 };
43 
44 static struct msxmlsupported_data_t domdoc_support_data[] =
45 {
46     { &CLSID_DOMDocument,   "DOMDocument",   {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
47     { &CLSID_DOMDocument2,  "DOMDocument2",  {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
48     { &CLSID_DOMDocument30, "DOMDocument30", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
49     { &CLSID_DOMDocument40, "DOMDocument40", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
50     { &CLSID_DOMDocument60, "DOMDocument60", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3} },
51     { &CLSID_FreeThreadedDOMDocument, "FreeThreadedDOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
52     { &CLSID_XMLSchemaCache, "XMLSchemaCache", {&IID_IXMLDOMSchemaCollection} },
53     { &CLSID_XSLTemplate,    "XSLTemplate", {&IID_IXSLTemplate} },
54     { &CLSID_MXNamespaceManager40, "MXNamespaceManager40", {&IID_IMXNamespaceManager} },
55     { NULL }
56 };
57 
58 static const char *debugstr_msxml_guid(REFIID riid)
59 {
60     if(!riid)
61         return "(null)";
62 
63     if (IsEqualIID(&IID_IXMLDOMDocument, riid))
64         return "IXMLDOMDocument";
65     else if (IsEqualIID(&IID_IXMLDOMDocument2, riid))
66         return "IXMLDOMDocument2";
67     else if (IsEqualIID(&IID_IXMLDOMDocument3, riid))
68         return "IXMLDOMDocument3";
69     else if (IsEqualIID(&IID_IXMLDOMSchemaCollection, riid))
70         return "IXMLDOMSchemaCollection";
71     else if (IsEqualIID(&IID_IXSLTemplate, riid))
72         return "IXSLTemplate";
73     else if (IsEqualIID(&IID_IMXNamespaceManager, riid))
74         return "IMXNamespaceManager";
75     else
76         return wine_dbgstr_guid(riid);
77 }
78 
79 static void get_class_support_data(struct msxmlsupported_data_t *table)
80 {
81     while (table->clsid)
82     {
83         IUnknown *unk;
84         HRESULT hr;
85         int i;
86 
87         for (i = 0; i < sizeof(table->ifaces)/sizeof(table->ifaces[0]) && table->ifaces[i] != NULL; i++)
88         {
89             hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, table->ifaces[i], (void**)&unk);
90             if (hr == S_OK) IUnknown_Release(unk);
91 
92             table->supported[i] = hr == S_OK;
93             if (hr != S_OK) win_skip("class %s, iface %s not supported\n", table->name, debugstr_msxml_guid(table->ifaces[i]));
94         }
95 
96         table++;
97     }
98 }
99 
100 static BOOL is_clsid_supported(const GUID *clsid, REFIID riid)
101 {
102     const struct msxmlsupported_data_t *table = domdoc_support_data;
103     while (table->clsid)
104     {
105         if (table->clsid == clsid)
106         {
107             int i;
108 
109             for (i = 0; i < sizeof(table->ifaces)/sizeof(table->ifaces[0]) && table->ifaces[i] != NULL; i++)
110                 if (table->ifaces[i] == riid) return table->supported[i];
111         }
112 
113         table++;
114     }
115     return FALSE;
116 }
117 
118 typedef struct
119 {
120     IDispatch IDispatch_iface;
121     LONG ref;
122 } dispevent;
123 
124 static inline dispevent *impl_from_IDispatch( IDispatch *iface )
125 {
126     return CONTAINING_RECORD(iface, dispevent, IDispatch_iface);
127 }
128 
129 static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
130 {
131     *ppvObject = NULL;
132 
133     if ( IsEqualGUID( riid, &IID_IDispatch) ||
134          IsEqualGUID( riid, &IID_IUnknown) )
135     {
136         *ppvObject = iface;
137     }
138     else
139         return E_NOINTERFACE;
140 
141     IDispatch_AddRef( iface );
142 
143     return S_OK;
144 }
145 
146 static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
147 {
148     dispevent *This = impl_from_IDispatch( iface );
149     return InterlockedIncrement( &This->ref );
150 }
151 
152 static ULONG WINAPI dispevent_Release(IDispatch *iface)
153 {
154     dispevent *This = impl_from_IDispatch( iface );
155     ULONG ref = InterlockedDecrement( &This->ref );
156 
157     if (ref == 0)
158         HeapFree(GetProcessHeap(), 0, This);
159 
160     return ref;
161 }
162 
163 static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
164 {
165     g_unexpectedcall++;
166     *pctinfo = 0;
167     return S_OK;
168 }
169 
170 static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
171         LCID lcid, ITypeInfo **ppTInfo)
172 {
173     g_unexpectedcall++;
174     return S_OK;
175 }
176 
177 static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
178         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
179 {
180     g_unexpectedcall++;
181     return S_OK;
182 }
183 
184 static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
185         LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
186         EXCEPINFO *excepInfo, UINT *argErr)
187 {
188     ok(member == 0, "expected 0 member, got %d\n", member);
189     ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
190     ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
191 
192     ok(params->cArgs == 0, "got %d\n", params->cArgs);
193     ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
194     ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
195     ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
196 
197     ok(result == NULL, "got %p\n", result);
198     ok(excepInfo == NULL, "got %p\n", excepInfo);
199     ok(argErr == NULL, "got %p\n", argErr);
200 
201     g_expectedcall++;
202     return E_FAIL;
203 }
204 
205 static const IDispatchVtbl dispeventVtbl =
206 {
207     dispevent_QueryInterface,
208     dispevent_AddRef,
209     dispevent_Release,
210     dispevent_GetTypeInfoCount,
211     dispevent_GetTypeInfo,
212     dispevent_GetIDsOfNames,
213     dispevent_Invoke
214 };
215 
216 static IDispatch* create_dispevent(void)
217 {
218     dispevent *event = HeapAlloc(GetProcessHeap(), 0, sizeof(*event));
219 
220     event->IDispatch_iface.lpVtbl = &dispeventVtbl;
221     event->ref = 1;
222 
223     return (IDispatch*)&event->IDispatch_iface;
224 }
225 
226 /* IStream */
227 static HRESULT WINAPI istream_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
228 {
229     *ppvObject = NULL;
230 
231     if (IsEqualGUID(riid, &IID_IStream) ||
232         IsEqualGUID(riid, &IID_IUnknown))
233         *ppvObject = iface;
234     else
235         return E_NOINTERFACE;
236 
237     return S_OK;
238 }
239 
240 static ULONG WINAPI istream_AddRef(IStream *iface)
241 {
242     return 2;
243 }
244 
245 static ULONG WINAPI istream_Release(IStream *iface)
246 {
247     return 1;
248 }
249 
250 static HRESULT WINAPI istream_Read(IStream *iface, void *ptr, ULONG len, ULONG *pread)
251 {
252     ok(0, "unexpected call\n");
253     return E_NOTIMPL;
254 }
255 
256 static HRESULT WINAPI istream_Write(IStream *iface, const void *ptr, ULONG len, ULONG *written)
257 {
258     *written = len/2;
259     return S_OK;
260 }
261 
262 static HRESULT WINAPI istream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
263 {
264     ok(0, "unexpected call\n");
265     return E_NOTIMPL;
266 }
267 
268 static HRESULT WINAPI istream_SetSize(IStream *iface, ULARGE_INTEGER size)
269 {
270     ok(0, "unexpected call\n");
271     return E_NOTIMPL;
272 }
273 
274 static HRESULT WINAPI istream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len,
275         ULARGE_INTEGER *pread, ULARGE_INTEGER *written)
276 {
277     ok(0, "unexpected call\n");
278     return E_NOTIMPL;
279 }
280 
281 static HRESULT WINAPI istream_Commit(IStream *iface, DWORD flags)
282 {
283     ok(0, "unexpected call\n");
284     return E_NOTIMPL;
285 }
286 
287 static HRESULT WINAPI istream_Revert(IStream *iface)
288 {
289     ok(0, "unexpected call\n");
290     return E_NOTIMPL;
291 }
292 
293 static HRESULT WINAPI istream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
294         ULARGE_INTEGER len, DWORD locktype)
295 {
296     ok(0, "unexpected call\n");
297     return E_NOTIMPL;
298 }
299 
300 static HRESULT WINAPI istream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
301         ULARGE_INTEGER len, DWORD locktype)
302 {
303     ok(0, "unexpected call\n");
304     return E_NOTIMPL;
305 }
306 
307 static HRESULT WINAPI istream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flag)
308 {
309     ok(0, "unexpected call\n");
310     return E_NOTIMPL;
311 }
312 
313 static HRESULT WINAPI istream_Clone(IStream *iface, IStream **stream)
314 {
315     ok(0, "unexpected call\n");
316     return E_NOTIMPL;
317 }
318 
319 static const IStreamVtbl StreamVtbl = {
320     istream_QueryInterface,
321     istream_AddRef,
322     istream_Release,
323     istream_Read,
324     istream_Write,
325     istream_Seek,
326     istream_SetSize,
327     istream_CopyTo,
328     istream_Commit,
329     istream_Revert,
330     istream_LockRegion,
331     istream_UnlockRegion,
332     istream_Stat,
333     istream_Clone
334 };
335 
336 static IStream savestream = { &StreamVtbl };
337 
338 static HRESULT WINAPI response_QI(IResponse *iface, REFIID riid, void **obj)
339 {
340     if (IsEqualIID(&IID_IResponse, riid) ||
341             IsEqualIID(&IID_IDispatch, riid) ||
342             IsEqualIID(&IID_IUnknown, riid))
343     {
344         *obj = iface;
345         return S_OK;
346     }
347 
348     if (!IsEqualIID(&IID_IStream, riid) && !IsEqualIID(&IID_ISequentialStream, riid))
349         ok(0, "unexpected call\n");
350     return E_NOINTERFACE;
351 }
352 
353 static ULONG WINAPI response_AddRef(IResponse *iface)
354 {
355     return 2;
356 }
357 
358 static ULONG WINAPI response_Release(IResponse *iface)
359 {
360     return 1;
361 }
362 
363 static HRESULT WINAPI response_GetTypeInfoCount(IResponse *iface, UINT *count)
364 {
365     ok(0, "unexpected call\n");
366     return E_NOTIMPL;
367 }
368 
369 static HRESULT WINAPI response_GetTypeInfo(IResponse *iface, UINT ti, LCID lcid, ITypeInfo **tinfo)
370 {
371     ok(0, "unexpected call\n");
372     return E_NOTIMPL;
373 }
374 
375 static HRESULT WINAPI response_GetIDsOfNames(IResponse *iface, REFIID riid, LPOLESTR *names,
376         UINT cnames, LCID lcid, DISPID *rgDispId)
377 {
378     ok(0, "unexpected call\n");
379     return E_NOTIMPL;
380 }
381 
382 static HRESULT WINAPI response_Invoke(IResponse *iface, DISPID dispid, REFIID riid, LCID lcid,
383     WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
384 {
385     ok(0, "unexpected call\n");
386     return E_NOTIMPL;
387 }
388 
389 static HRESULT WINAPI response_get_Buffer(IResponse *iface, VARIANT_BOOL *fIsBuffering)
390 {
391     ok(0, "unexpected call\n");
392     return E_NOTIMPL;
393 }
394 
395 static HRESULT WINAPI response_put_Buffer(IResponse *iface, VARIANT_BOOL fIsBuffering)
396 {
397     ok(0, "unexpected call\n");
398     return E_NOTIMPL;
399 }
400 
401 static HRESULT WINAPI response_get_ContentType(IResponse *iface, BSTR *pbstrContentTypeRet)
402 {
403     ok(0, "unexpected call\n");
404     return E_NOTIMPL;
405 }
406 
407 static HRESULT WINAPI response_put_ContentType(IResponse *iface, BSTR bstrContentType)
408 {
409     ok(0, "unexpected call\n");
410     return E_NOTIMPL;
411 }
412 
413 static HRESULT WINAPI response_get_Expires(IResponse *iface, VARIANT *pvarExpiresMinutesRet)
414 {
415     ok(0, "unexpected call\n");
416     return E_NOTIMPL;
417 }
418 
419 static HRESULT WINAPI response_put_Expires(IResponse *iface, LONG lExpiresMinutes)
420 {
421     ok(0, "unexpected call\n");
422     return E_NOTIMPL;
423 }
424 
425 static HRESULT WINAPI response_get_ExpiresAbsolute(IResponse *iface, VARIANT *pvarExpiresRet)
426 {
427     ok(0, "unexpected call\n");
428     return E_NOTIMPL;
429 }
430 
431 static HRESULT WINAPI response_put_ExpiresAbsolute(IResponse *iface, DATE dtExpires)
432 {
433     ok(0, "unexpected call\n");
434     return E_NOTIMPL;
435 }
436 
437 static HRESULT WINAPI response_get_Cookies(IResponse *iface, IRequestDictionary **ppCookies)
438 {
439     ok(0, "unexpected call\n");
440     return E_NOTIMPL;
441 }
442 
443 static HRESULT WINAPI response_get_Status(IResponse *iface, BSTR *pbstrStatusRet)
444 {
445     ok(0, "unexpected call\n");
446     return E_NOTIMPL;
447 }
448 
449 static HRESULT WINAPI response_put_Status(IResponse *iface, BSTR bstrStatus)
450 {
451     ok(0, "unexpected call\n");
452     return E_NOTIMPL;
453 }
454 
455 static HRESULT WINAPI response_Add(IResponse *iface, BSTR bstrHeaderValue, BSTR bstrHeaderName)
456 {
457     ok(0, "unexpected call\n");
458     return E_NOTIMPL;
459 }
460 
461 static HRESULT WINAPI response_AddHeader(IResponse *iface, BSTR bstrHeaderName, BSTR bstrHeaderValue)
462 {
463     ok(0, "unexpected call\n");
464     return E_NOTIMPL;
465 }
466 
467 static HRESULT WINAPI response_AppendToLog(IResponse *iface, BSTR bstrLogEntry)
468 {
469     ok(0, "unexpected call\n");
470     return E_NOTIMPL;
471 }
472 
473 static HRESULT WINAPI response_BinaryWrite(IResponse *iface, VARIANT input)
474 {
475     HRESULT hr;
476     LONG bound;
477     UINT dim;
478 
479     ok(V_VT(&input) == (VT_ARRAY | VT_UI1), "got wrong input type %x\n", V_VT(&input));
480 
481     dim = SafeArrayGetDim(V_ARRAY(&input));
482     ok(dim == 1, "got wrong array dimensions %u\n", dim);
483 
484     bound = 1;
485     hr = SafeArrayGetLBound(V_ARRAY(&input), 1, &bound);
486     ok(hr == S_OK, "got %#x\n", hr);
487     ok(bound == 0, "wrong array low bound %d\n", bound);
488 
489     bound = 0;
490     hr = SafeArrayGetUBound(V_ARRAY(&input), 1, &bound);
491     ok(hr == S_OK, "got %#x\n", hr);
492     ok(bound > 0, "wrong array high bound %d\n", bound);
493 
494     return E_NOTIMPL;
495 }
496 
497 static HRESULT WINAPI response_Clear(IResponse *iface)
498 {
499     ok(0, "unexpected call\n");
500     return E_NOTIMPL;
501 }
502 
503 static HRESULT WINAPI response_End(IResponse *iface)
504 {
505     ok(0, "unexpected call\n");
506     return E_NOTIMPL;
507 }
508 
509 static HRESULT WINAPI response_Flush(IResponse *iface)
510 {
511     ok(0, "unexpected call\n");
512     return E_NOTIMPL;
513 }
514 
515 static HRESULT WINAPI response_Redirect(IResponse *iface, BSTR bstrURL)
516 {
517     ok(0, "unexpected call\n");
518     return E_NOTIMPL;
519 }
520 
521 static HRESULT WINAPI response_Write(IResponse *iface, VARIANT varText)
522 {
523     ok(0, "unexpected call\n");
524     return E_NOTIMPL;
525 }
526 
527 static HRESULT WINAPI response_WriteBlock(IResponse *iface, short iBlockNumber)
528 {
529     ok(0, "unexpected call\n");
530     return E_NOTIMPL;
531 }
532 
533 static HRESULT WINAPI response_IsClientConnected(IResponse *iface, VARIANT_BOOL *pfIsClientConnected)
534 {
535     ok(0, "unexpected call\n");
536     return E_NOTIMPL;
537 }
538 
539 static HRESULT WINAPI response_get_CharSet(IResponse *iface, BSTR *pbstrCharSetRet)
540 {
541     ok(0, "unexpected call\n");
542     return E_NOTIMPL;
543 }
544 
545 static HRESULT WINAPI response_put_CharSet(IResponse *iface, BSTR bstrCharSet)
546 {
547     ok(0, "unexpected call\n");
548     return E_NOTIMPL;
549 }
550 
551 static HRESULT WINAPI response_Pics(IResponse *iface, BSTR bstrHeaderValue)
552 {
553     ok(0, "unexpected call\n");
554     return E_NOTIMPL;
555 }
556 
557 static HRESULT WINAPI response_get_CacheControl(IResponse *iface, BSTR *pbstrCacheControl)
558 {
559     ok(0, "unexpected call\n");
560     return E_NOTIMPL;
561 }
562 
563 static HRESULT WINAPI response_put_CacheControl(IResponse *iface, BSTR bstrCacheControl)
564 {
565     ok(0, "unexpected call\n");
566     return E_NOTIMPL;
567 }
568 
569 static HRESULT WINAPI response_get_CodePage(IResponse *iface, LONG *plvar)
570 {
571     ok(0, "unexpected call\n");
572     return E_NOTIMPL;
573 }
574 
575 static HRESULT WINAPI response_put_CodePage(IResponse *iface, LONG codepage)
576 {
577     ok(0, "unexpected call\n");
578     return E_NOTIMPL;
579 }
580 
581 static HRESULT WINAPI response_get_LCID(IResponse *iface, LONG *lcid)
582 {
583     ok(0, "unexpected call\n");
584     return E_NOTIMPL;
585 }
586 
587 static HRESULT WINAPI response_put_LCID(IResponse *iface, LONG lcid)
588 {
589     ok(0, "unexpected call\n");
590     return E_NOTIMPL;
591 }
592 
593 static const IResponseVtbl testresponsevtbl =
594 {
595     response_QI,
596     response_AddRef,
597     response_Release,
598     response_GetTypeInfoCount,
599     response_GetTypeInfo,
600     response_GetIDsOfNames,
601     response_Invoke,
602     response_get_Buffer,
603     response_put_Buffer,
604     response_get_ContentType,
605     response_put_ContentType,
606     response_get_Expires,
607     response_put_Expires,
608     response_get_ExpiresAbsolute,
609     response_put_ExpiresAbsolute,
610     response_get_Cookies,
611     response_get_Status,
612     response_put_Status,
613     response_Add,
614     response_AddHeader,
615     response_AppendToLog,
616     response_BinaryWrite,
617     response_Clear,
618     response_End,
619     response_Flush,
620     response_Redirect,
621     response_Write,
622     response_WriteBlock,
623     response_IsClientConnected,
624     response_get_CharSet,
625     response_put_CharSet,
626     response_Pics,
627     response_get_CacheControl,
628     response_put_CacheControl,
629     response_get_CodePage,
630     response_put_CodePage,
631     response_get_LCID,
632     response_put_LCID,
633 };
634 
635 static IResponse testresponse = { &testresponsevtbl };
636 
637 #define EXPECT_CHILDREN(node) _expect_children((IXMLDOMNode*)node, __LINE__)
638 static void _expect_children(IXMLDOMNode *node, int line)
639 {
640     VARIANT_BOOL b;
641     HRESULT hr;
642 
643     b = VARIANT_FALSE;
644     hr = IXMLDOMNode_hasChildNodes(node, &b);
645     ok_(__FILE__,line)(hr == S_OK, "hasChildNodes() failed, 0x%08x\n", hr);
646     ok_(__FILE__,line)(b == VARIANT_TRUE, "no children, %d\n", b);
647 }
648 
649 #define EXPECT_NO_CHILDREN(node) _expect_no_children((IXMLDOMNode*)node, __LINE__)
650 static void _expect_no_children(IXMLDOMNode *node, int line)
651 {
652     VARIANT_BOOL b;
653     HRESULT hr;
654 
655     b = VARIANT_TRUE;
656     hr = IXMLDOMNode_hasChildNodes(node, &b);
657     ok_(__FILE__,line)(hr == S_FALSE, "hasChildNodes() failed, 0x%08x\n", hr);
658     ok_(__FILE__,line)(b == VARIANT_FALSE, "no children, %d\n", b);
659 }
660 
661 #define EXPECT_REF(node,ref) _expect_ref((IUnknown*)node, ref, __LINE__)
662 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
663 {
664     ULONG rc;
665     IUnknown_AddRef(obj);
666     rc = IUnknown_Release(obj);
667     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
668 }
669 
670 #define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
671 static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
672 {
673     LONG length;
674     HRESULT hr;
675 
676     length = 0;
677     hr = IXMLDOMNodeList_get_length(list, &length);
678     ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
679     ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
680 }
681 
682 #define EXPECT_HR(hr,hr_exp) \
683     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
684 
685 #define EXPECT_NOT_HR(hr,hr_exp) \
686     ok(hr != hr_exp, "got 0x%08x, expected not 0x%08x\n", hr, hr_exp)
687 
688 static const WCHAR szEmpty[] = { 0 };
689 static const WCHAR szIncomplete[] = {
690     '<','?','x','m','l',' ',
691     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
692 };
693 static const WCHAR szComplete1[] = {
694     '<','?','x','m','l',' ',
695     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
696     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
697 };
698 static const WCHAR szComplete2[] = {
699     '<','?','x','m','l',' ',
700     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
701     '<','a','>','<','/','a','>','\n',0
702 };
703 static const char complete4A[] =
704     "<?xml version=\'1.0\'?>\n"
705     "<lc dl=\'str1\'>\n"
706         "<bs vr=\'str2\' sz=\'1234\'>"
707             "fn1.txt\n"
708         "</bs>\n"
709         "<pr id=\'str3\' vr=\'1.2.3\' pn=\'wine 20050804\'>\n"
710             "fn2.txt\n"
711         "</pr>\n"
712         "<empty></empty>\n"
713         "<fo>\n"
714             "<ba>\n"
715                 "f1\n"
716             "</ba>\n"
717         "</fo>\n"
718     "</lc>\n";
719 
720 static const WCHAR szComplete5[] = {
721     '<','S',':','s','e','a','r','c','h',' ','x','m','l','n','s',':','D','=','"','D','A','V',':','"',' ',
722     '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','"',
723     ' ','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','"','>',
724         '<','S',':','s','c','o','p','e','>',
725             '<','S',':','d','e','e','p','>','/','<','/','S',':','d','e','e','p','>',
726         '<','/','S',':','s','c','o','p','e','>',
727         '<','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
728             '<','C',':','t','e','x','t','o','r','p','r','o','p','e','r','t','y','/','>',
729             'c','o','m','p','u','t','e','r',
730         '<','/','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
731     '<','/','S',':','s','e','a','r','c','h','>',0
732 };
733 
734 static const WCHAR szComplete6[] = {
735     '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'',' ',
736     'e','n','c','o','d','i','n','g','=','\'','W','i','n','d','o','w','s','-','1','2','5','2','\'','?','>','\n',
737     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
738 };
739 
740 static const char complete7[] = {
741     "<?xml version=\"1.0\"?>\n\t"
742     "<root>\n"
743     "\t<a/>\n"
744     "\t<b/>\n"
745     "\t<c/>\n"
746     "</root>"
747 };
748 
749 #define DECL_WIN_1252 \
750 "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
751 
752 static const char win1252xml[] =
753 DECL_WIN_1252
754 "<open></open>";
755 
756 static const char win1252decl[] =
757 DECL_WIN_1252
758 ;
759 
760 static const char nocontent[] = "no xml content here";
761 
762 static const char szExampleXML[] =
763 "<?xml version='1.0' encoding='utf-8'?>\n"
764 "<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' a=\"attr a\" foo:b=\"attr b\" >\n"
765 "    <elem>\n"
766 "        <a>A1 field</a>\n"
767 "        <b>B1 field</b>\n"
768 "        <c>C1 field</c>\n"
769 "        <d>D1 field</d>\n"
770 "        <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
771 "            <html xmlns='http://www.w3.org/1999/xhtml'>\n"
772 "                <![CDATA[]]> This is<strong> a</strong>  <i>description</i><dot>. </dot><bar:x/>\n"
773 "            </html>\n"
774 "            <html xml:space='preserve' xmlns='http://www.w3.org/1999/xhtml'>\n"
775 "                This is <strong>a</strong> <i>description</i> with preserved whitespace. <bar:x/>\n"
776 "            </html>\n"
777 "        </description>\n"
778 "    </elem>\n"
779 "\n"
780 "    <elem a='a'>\n"
781 "        <a>A2 field</a>\n"
782 "        <b>B2 field</b>\n"
783 "        <c type=\"old\">C2 field</c>\n"
784 "        <d>D2 field</d>\n"
785 "    </elem>\n"
786 "\n"
787 "    <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
788 "        <a>A3 field</a>\n"
789 "        <b>B3 field</b>\n"
790 "        <c>C3 field</c>\n"
791 "    </elem>\n"
792 "\n"
793 "    <elem>\n"
794 "        <a>A4 field</a>\n"
795 "        <b>B4 field</b>\n"
796 "        <foo:c>C4 field</foo:c>\n"
797 "        <d>D4 field</d>\n"
798 "    </elem>\n"
799 "</root>\n";
800 
801 static const char charrefsxml[] =
802 "<?xml version='1.0'?>"
803 "<a>"
804 "<b1> Text &#65; end </b1>"
805 "<b2>&#65;&#66; &#67; </b2>"
806 "</a>";
807 
808 static const CHAR szNodeTypesXML[] =
809 "<?xml version='1.0'?>"
810 "<!-- comment node 0 -->"
811 "<root id='0' depth='0'>"
812 "   <!-- comment node 1 -->"
813 "   text node 0"
814 "   <x id='1' depth='1'>"
815 "       <?foo value='PI for x'?>"
816 "       <!-- comment node 2 -->"
817 "       text node 1"
818 "       <a id='3' depth='2'/>"
819 "       <b id='4' depth='2'/>"
820 "       <c id='5' depth='2'/>"
821 "   </x>"
822 "   <y id='2' depth='1'>"
823 "       <?bar value='PI for y'?>"
824 "       <!-- comment node 3 -->"
825 "       text node 2"
826 "       <a id='6' depth='2'/>"
827 "       <b id='7' depth='2'/>"
828 "       <c id='8' depth='2'/>"
829 "   </y>"
830 "</root>";
831 
832 static const CHAR szTransformXML[] =
833 "<?xml version=\"1.0\"?>\n"
834 "<greeting>\n"
835 "Hello World\n"
836 "</greeting>";
837 
838 static  const CHAR szTransformSSXML[] =
839 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
840 "   <xsl:output method=\"html\"/>\n"
841 "   <xsl:template match=\"/\">\n"
842 "       <xsl:apply-templates select=\"greeting\"/>\n"
843 "   </xsl:template>\n"
844 "   <xsl:template match=\"greeting\">\n"
845 "       <html>\n"
846 "           <body>\n"
847 "               <h1>\n"
848 "                   <xsl:value-of select=\".\"/>\n"
849 "               </h1>\n"
850 "           </body>\n"
851 "       </html>\n"
852 "   </xsl:template>\n"
853 "</xsl:stylesheet>";
854 
855 static  const CHAR szTransformOutput[] =
856 "<html><body><h1>"
857 "Hello World"
858 "</h1></body></html>";
859 
860 static const CHAR szTypeValueXML[] =
861 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
862 "<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
863 "   <string>Wine</string>\n"
864 "   <string2 dt:dt=\"string\">String</string2>\n"
865 "   <number dt:dt=\"number\">12.44</number>\n"
866 "   <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
867 "   <int dt:dt=\"int\">-13</int>\n"
868 "   <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
869 "   <bool dt:dt=\"boolean\">1</bool>\n"
870 "   <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
871 "   <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
872 "   <date dt:dt=\"date\">3721-11-01</date>\n"
873 "   <time dt:dt=\"time\">13:57:12.31321</time>\n"
874 "   <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
875 "   <i1 dt:dt=\"i1\">-13</i1>\n"
876 "   <i2 dt:dt=\"i2\">31915</i2>\n"
877 "   <i4 dt:dt=\"i4\">-312232</i4>\n"
878 "   <ui1 dt:dt=\"ui1\">123</ui1>\n"
879 "   <ui2 dt:dt=\"ui2\">48282</ui2>\n"
880 "   <ui4 dt:dt=\"ui4\">949281</ui4>\n"
881 "   <r4 dt:dt=\"r4\">213124.0</r4>\n"
882 "   <r8 dt:dt=\"r8\">0.412</r8>\n"
883 "   <float dt:dt=\"float\">41221.421</float>\n"
884 "   <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
885 "   <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
886 "   <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
887 "   <binbase64_1 dt:dt=\"bin.base64\">\nYmFzZTY0\nIHRlc3Q=\n</binbase64_1>\n"
888 "   <binbase64_2 dt:dt=\"bin.base64\">\nYmF\r\t z  ZTY0\nIHRlc3Q=\n</binbase64_2>\n"
889 "</root>";
890 
891 static const CHAR szBasicTransformSSXMLPart1[] =
892 "<?xml version=\"1.0\"?>"
893 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
894 "<xsl:output method=\"html\"/>\n"
895 "<xsl:template match=\"/\">"
896 "<HTML><BODY><TABLE>"
897 "        <xsl:apply-templates select='document(\"";
898 
899 static const CHAR szBasicTransformSSXMLPart2[] =
900 "\")/bottle/wine'>"
901 "           <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
902 "        </xsl:apply-templates>"
903 "</TABLE></BODY></HTML>"
904 "</xsl:template>"
905 "<xsl:template match=\"bottle\">"
906 "   <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
907 "</xsl:template>"
908 "<xsl:template match=\"name\">"
909 "   <TD><xsl:apply-templates /></TD>"
910 "</xsl:template>"
911 "<xsl:template match=\"cost\">"
912 "   <TD><xsl:apply-templates /></TD>"
913 "</xsl:template>"
914 "</xsl:stylesheet>";
915 
916 static const CHAR szBasicTransformXML[] =
917 "<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
918 
919 static const CHAR szBasicTransformOutput[] =
920 "<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
921 
922 #define SZ_EMAIL_DTD \
923 "<!DOCTYPE email ["\
924 "   <!ELEMENT email         (recipients,from,reply-to?,subject,body,attachment*)>"\
925 "       <!ATTLIST email attachments IDREFS #REQUIRED>"\
926 "       <!ATTLIST email sent (yes|no) \"no\">"\
927 "   <!ELEMENT recipients    (to+,cc*)>"\
928 "   <!ELEMENT to            (#PCDATA)>"\
929 "       <!ATTLIST to name CDATA #IMPLIED>"\
930 "   <!ELEMENT cc            (#PCDATA)>"\
931 "       <!ATTLIST cc name CDATA #IMPLIED>"\
932 "   <!ELEMENT from          (#PCDATA)>"\
933 "       <!ATTLIST from name CDATA #IMPLIED>"\
934 "   <!ELEMENT reply-to      (#PCDATA)>"\
935 "       <!ATTLIST reply-to name CDATA #IMPLIED>"\
936 "   <!ELEMENT subject       ANY>"\
937 "   <!ELEMENT body          ANY>"\
938 "       <!ATTLIST body enc CDATA #FIXED \"UTF-8\">"\
939 "   <!ELEMENT attachment    (#PCDATA)>"\
940 "       <!ATTLIST attachment id ID #REQUIRED>"\
941 "]>"
942 
943 static const CHAR szEmailXML[] =
944 "<?xml version=\"1.0\"?>"
945 SZ_EMAIL_DTD
946 "<email attachments=\"patch1\">"
947 "   <recipients>"
948 "       <to>wine-patches@winehq.org</to>"
949 "   </recipients>"
950 "   <from name=\"Anonymous\">user@localhost</from>"
951 "   <subject>msxml3/tests: DTD validation (try 87)</subject>"
952 "   <body>"
953 "       It no longer causes spontaneous combustion..."
954 "   </body>"
955 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
956 "</email>";
957 
958 static const CHAR szEmailXML_0D[] =
959 "<?xml version=\"1.0\"?>"
960 SZ_EMAIL_DTD
961 "<email attachments=\"patch1\">"
962 "   <recipients>"
963 "       <to>wine-patches@winehq.org</to>"
964 "   </recipients>"
965 "   <from name=\"Anonymous\">user@localhost</from>"
966 "   <subject>msxml3/tests: DTD validation (try 88)</subject>"
967 "   <body>"
968 "       <undecl />"
969 "       XML_ELEMENT_UNDECLARED 0xC00CE00D"
970 "   </body>"
971 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
972 "</email>";
973 
974 static const CHAR szEmailXML_0E[] =
975 "<?xml version=\"1.0\"?>"
976 SZ_EMAIL_DTD
977 "<email attachments=\"patch1\">"
978 "   <recipients>"
979 "       <to>wine-patches@winehq.org</to>"
980 "   </recipients>"
981 "   <from name=\"Anonymous\">user@localhost</from>"
982 "   <subject>msxml3/tests: DTD validation (try 89)</subject>"
983 "   <body>"
984 "       XML_ELEMENT_ID_NOT_FOUND 0xC00CE00E"
985 "   </body>"
986 "   <attachment id=\"patch\">0001-msxml3-tests-DTD-validation.patch</attachment>"
987 "</email>";
988 
989 static const CHAR szEmailXML_11[] =
990 "<?xml version=\"1.0\"?>"
991 SZ_EMAIL_DTD
992 "<email attachments=\"patch1\">"
993 "   <recipients>"
994 "   </recipients>"
995 "   <from name=\"Anonymous\">user@localhost</from>"
996 "   <subject>msxml3/tests: DTD validation (try 90)</subject>"
997 "   <body>"
998 "       XML_EMPTY_NOT_ALLOWED 0xC00CE011"
999 "   </body>"
1000 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1001 "</email>";
1002 
1003 static const CHAR szEmailXML_13[] =
1004 "<?xml version=\"1.0\"?>"
1005 SZ_EMAIL_DTD
1006 "<msg attachments=\"patch1\">"
1007 "   <recipients>"
1008 "       <to>wine-patches@winehq.org</to>"
1009 "   </recipients>"
1010 "   <from name=\"Anonymous\">user@localhost</from>"
1011 "   <subject>msxml3/tests: DTD validation (try 91)</subject>"
1012 "   <body>"
1013 "       XML_ROOT_NAME_MISMATCH 0xC00CE013"
1014 "   </body>"
1015 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1016 "</msg>";
1017 
1018 static const CHAR szEmailXML_14[] =
1019 "<?xml version=\"1.0\"?>"
1020 SZ_EMAIL_DTD
1021 "<email attachments=\"patch1\">"
1022 "   <to>wine-patches@winehq.org</to>"
1023 "   <from name=\"Anonymous\">user@localhost</from>"
1024 "   <subject>msxml3/tests: DTD validation (try 92)</subject>"
1025 "   <body>"
1026 "       XML_INVALID_CONTENT 0xC00CE014"
1027 "   </body>"
1028 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1029 "</email>";
1030 
1031 static const CHAR szEmailXML_15[] =
1032 "<?xml version=\"1.0\"?>"
1033 SZ_EMAIL_DTD
1034 "<email attachments=\"patch1\" ip=\"127.0.0.1\">"
1035 "   <recipients>"
1036 "       <to>wine-patches@winehq.org</to>"
1037 "   </recipients>"
1038 "   <from name=\"Anonymous\">user@localhost</from>"
1039 "   <subject>msxml3/tests: DTD validation (try 93)</subject>"
1040 "   <body>"
1041 "       XML_ATTRIBUTE_NOT_DEFINED 0xC00CE015"
1042 "   </body>"
1043 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1044 "</email>";
1045 
1046 static const CHAR szEmailXML_16[] =
1047 "<?xml version=\"1.0\"?>"
1048 SZ_EMAIL_DTD
1049 "<email attachments=\"patch1\">"
1050 "   <recipients>"
1051 "       <to>wine-patches@winehq.org</to>"
1052 "   </recipients>"
1053 "   <from name=\"Anonymous\">user@localhost</from>"
1054 "   <subject>msxml3/tests: DTD validation (try 94)</subject>"
1055 "   <body enc=\"ASCII\">"
1056 "       XML_ATTRIBUTE_FIXED 0xC00CE016"
1057 "   </body>"
1058 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1059 "</email>";
1060 
1061 static const CHAR szEmailXML_17[] =
1062 "<?xml version=\"1.0\"?>"
1063 SZ_EMAIL_DTD
1064 "<email attachments=\"patch1\" sent=\"true\">"
1065 "   <recipients>"
1066 "       <to>wine-patches@winehq.org</to>"
1067 "   </recipients>"
1068 "   <from name=\"Anonymous\">user@localhost</from>"
1069 "   <subject>msxml3/tests: DTD validation (try 95)</subject>"
1070 "   <body>"
1071 "       XML_ATTRIBUTE_VALUE 0xC00CE017"
1072 "   </body>"
1073 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1074 "</email>";
1075 
1076 static const CHAR szEmailXML_18[] =
1077 "<?xml version=\"1.0\"?>"
1078 SZ_EMAIL_DTD
1079 "<email attachments=\"patch1\">"
1080 "   oops"
1081 "   <recipients>"
1082 "       <to>wine-patches@winehq.org</to>"
1083 "   </recipients>"
1084 "   <from name=\"Anonymous\">user@localhost</from>"
1085 "   <subject>msxml3/tests: DTD validation (try 96)</subject>"
1086 "   <body>"
1087 "       XML_ILLEGAL_TEXT 0xC00CE018"
1088 "   </body>"
1089 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1090 "</email>";
1091 
1092 static const CHAR szEmailXML_20[] =
1093 "<?xml version=\"1.0\"?>"
1094 SZ_EMAIL_DTD
1095 "<email>"
1096 "   <recipients>"
1097 "       <to>wine-patches@winehq.org</to>"
1098 "   </recipients>"
1099 "   <from name=\"Anonymous\">user@localhost</from>"
1100 "   <subject>msxml3/tests: DTD validation (try 97)</subject>"
1101 "   <body>"
1102 "       XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020"
1103 "   </body>"
1104 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1105 "</email>";
1106 
1107 static const char xpath_simple_list[] =
1108 "<?xml version=\"1.0\"?>"
1109 "<root>"
1110 "   <a attr1=\"1\" attr2=\"2\" />"
1111 "   <b/>"
1112 "   <c/>"
1113 "   <d/>"
1114 "</root>";
1115 
1116 static const char default_ns_doc[] = {
1117     "<?xml version=\"1.0\"?>"
1118     "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
1119     "    d=\"d attr\" />"
1120 };
1121 
1122 static const char attributes_map[] = {
1123     "<?xml version=\"1.0\"?>"
1124     "<a attr1=\"value1\" attr2=\"value2\" attr3=\"value3\" attr4=\"value4\" />"
1125 };
1126 
1127 static const WCHAR nonexistent_fileW[] = {
1128     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
1129 };
1130 static const WCHAR nonexistent_attrW[] = {
1131     'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
1132 };
1133 static const WCHAR szDocument[] = {
1134     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
1135 };
1136 
1137 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
1138 static const WCHAR szdl[] = { 'd','l',0 };
1139 static const WCHAR szvr[] = { 'v','r',0 };
1140 static const WCHAR szlc[] = { 'l','c',0 };
1141 static const WCHAR szbs[] = { 'b','s',0 };
1142 static const WCHAR szstr1[] = { 's','t','r','1',0 };
1143 static const WCHAR szstr2[] = { 's','t','r','2',0 };
1144 static const WCHAR szstar[] = { '*',0 };
1145 static const WCHAR szfn1_txt[] = {'f','n','1','.','t','x','t',0};
1146 
1147 static const WCHAR szComment[] = {'A',' ','C','o','m','m','e','n','t',0 };
1148 static const WCHAR szCommentXML[] = {'<','!','-','-','A',' ','C','o','m','m','e','n','t','-','-','>',0 };
1149 static const WCHAR szCommentNodeText[] = {'#','c','o','m','m','e','n','t',0 };
1150 
1151 static WCHAR szElement[] = {'E','l','e','T','e','s','t', 0 };
1152 static const WCHAR szElementXML[]  = {'<','E','l','e','T','e','s','t','/','>',0 };
1153 static const WCHAR szElementXML2[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','/','>',0 };
1154 static const WCHAR szElementXML3[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1155                                       'T','e','s','t','i','n','g','N','o','d','e','<','/','E','l','e','T','e','s','t','>',0 };
1156 static const WCHAR szElementXML4[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1157                                       '&','a','m','p',';','x',' ',0x2103,'<','/','E','l','e','T','e','s','t','>',0 };
1158 
1159 static const WCHAR szAttribute[] = {'A','t','t','r',0 };
1160 static const WCHAR szAttributeXML[] = {'A','t','t','r','=','"','"',0 };
1161 
1162 static const WCHAR szCData[] = {'[','1',']','*','2','=','3',';',' ','&','g','e','e',' ','t','h','a','t','s',
1163                                 ' ','n','o','t',' ','r','i','g','h','t','!', 0};
1164 static const WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*','2','=','3',';',' ','&',
1165                                    'g','e','e',' ','t','h','a','t','s',' ','n','o','t',' ','r','i','g','h','t',
1166                                    '!',']',']','>',0};
1167 static const WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 };
1168 static const WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 };
1169 
1170 static const WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 };
1171 static const WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 };
1172 static const WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
1173 
1174 #define expect_bstr_eq_and_free(bstr, expect) { \
1175     BSTR bstrExp = alloc_str_from_narrow(expect); \
1176     ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \
1177     SysFreeString(bstr); \
1178     SysFreeString(bstrExp); \
1179 }
1180 
1181 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
1182 
1183 #define ole_check(expr) { \
1184     HRESULT r = expr; \
1185     ok(r == S_OK, #expr " returned %x\n", r); \
1186 }
1187 
1188 #define ole_expect(expr, expect) { \
1189     HRESULT r = expr; \
1190     ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
1191 }
1192 
1193 #define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
1194 
1195 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
1196 {
1197     void *obj = NULL;
1198     HRESULT hr;
1199 
1200     hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
1201     ok(hr == S_OK, "failed to create %s instance: 0x%08x\n", name, hr);
1202 
1203     return obj;
1204 }
1205 
1206 #define _create(cls) cls, #cls
1207 
1208 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
1209 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
1210 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
1211 #define create_xsltemplate(iid) _create_object(&_create(CLSID_XSLTemplate), iid, __LINE__)
1212 
1213 static BSTR alloc_str_from_narrow(const char *str)
1214 {
1215     int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1216     BSTR ret = SysAllocStringLen(NULL, len - 1);  /* NUL character added automatically */
1217     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
1218     return ret;
1219 }
1220 
1221 static BSTR alloced_bstrs[256];
1222 static int alloced_bstrs_count;
1223 
1224 static BSTR _bstr_(const char *str)
1225 {
1226     assert(alloced_bstrs_count < sizeof(alloced_bstrs)/sizeof(alloced_bstrs[0]));
1227     alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
1228     return alloced_bstrs[alloced_bstrs_count++];
1229 }
1230 
1231 static void free_bstrs(void)
1232 {
1233     int i;
1234     for (i = 0; i < alloced_bstrs_count; i++)
1235         SysFreeString(alloced_bstrs[i]);
1236     alloced_bstrs_count = 0;
1237 }
1238 
1239 static VARIANT _variantbstr_(const char *str)
1240 {
1241     VARIANT v;
1242     V_VT(&v) = VT_BSTR;
1243     V_BSTR(&v) = _bstr_(str);
1244     return v;
1245 }
1246 
1247 static BOOL compareIgnoreReturns(BSTR sLeft, BSTR sRight)
1248 {
1249     for (;;)
1250     {
1251         while (*sLeft == '\r' || *sLeft == '\n') sLeft++;
1252         while (*sRight == '\r' || *sRight == '\n') sRight++;
1253         if (*sLeft != *sRight) return FALSE;
1254         if (!*sLeft) return TRUE;
1255         sLeft++;
1256         sRight++;
1257     }
1258 }
1259 
1260 static void get_str_for_type(DOMNodeType type, char *buf)
1261 {
1262     switch (type)
1263     {
1264         case NODE_ATTRIBUTE:
1265             strcpy(buf, "A");
1266             break;
1267         case NODE_ELEMENT:
1268             strcpy(buf, "E");
1269             break;
1270         case NODE_DOCUMENT:
1271             strcpy(buf, "D");
1272             break;
1273         case NODE_TEXT:
1274             strcpy(buf, "T");
1275             break;
1276         case NODE_COMMENT:
1277             strcpy(buf, "C");
1278             break;
1279         case NODE_PROCESSING_INSTRUCTION:
1280             strcpy(buf, "P");
1281             break;
1282         default:
1283             wsprintfA(buf, "[%d]", type);
1284     }
1285 }
1286 
1287 static int get_node_position(IXMLDOMNode *node)
1288 {
1289     HRESULT r;
1290     int pos = 0;
1291 
1292     IXMLDOMNode_AddRef(node);
1293     do
1294     {
1295         IXMLDOMNode *new_node;
1296 
1297         pos++;
1298         r = IXMLDOMNode_get_previousSibling(node, &new_node);
1299         ok(SUCCEEDED(r), "get_previousSibling failed\n");
1300         IXMLDOMNode_Release(node);
1301         node = new_node;
1302     } while (r == S_OK);
1303     return pos;
1304 }
1305 
1306 static void node_to_string(IXMLDOMNode *node, char *buf)
1307 {
1308     HRESULT r = S_OK;
1309     DOMNodeType type;
1310 
1311     if (node == NULL)
1312     {
1313         lstrcpyA(buf, "(null)");
1314         return;
1315     }
1316 
1317     IXMLDOMNode_AddRef(node);
1318     while (r == S_OK)
1319     {
1320         IXMLDOMNode *new_node;
1321 
1322         ole_check(IXMLDOMNode_get_nodeType(node, &type));
1323         get_str_for_type(type, buf);
1324         buf+=strlen(buf);
1325 
1326         if (type == NODE_ATTRIBUTE)
1327         {
1328             BSTR bstr;
1329             ole_check(IXMLDOMNode_get_nodeName(node, &bstr));
1330             *(buf++) = '\'';
1331             wsprintfA(buf, "%ws", bstr);
1332             buf += strlen(buf);
1333             *(buf++) = '\'';
1334             SysFreeString(bstr);
1335 
1336             r = IXMLDOMNode_selectSingleNode(node, _bstr_(".."), &new_node);
1337         }
1338         else
1339         {
1340             r = IXMLDOMNode_get_parentNode(node, &new_node);
1341             sprintf(buf, "%d", get_node_position(node));
1342             buf += strlen(buf);
1343         }
1344 
1345         ok(SUCCEEDED(r), "get_parentNode failed (%08x)\n", r);
1346         IXMLDOMNode_Release(node);
1347         node = new_node;
1348         if (r == S_OK)
1349             *(buf++) = '.';
1350     }
1351 
1352     *buf = 0;
1353 }
1354 
1355 static char *list_to_string(IXMLDOMNodeList *list)
1356 {
1357     static char buf[4096];
1358     char *pos = buf;
1359     LONG len = 0;
1360     HRESULT hr;
1361     int i;
1362 
1363     if (list == NULL)
1364     {
1365         strcpy(buf, "(null)");
1366         return buf;
1367     }
1368     hr = IXMLDOMNodeList_get_length(list, &len);
1369     ok(hr == S_OK, "got 0x%08x\n", hr);
1370     for (i = 0; i < len; i++)
1371     {
1372         IXMLDOMNode *node;
1373         if (i > 0)
1374             *(pos++) = ' ';
1375         ole_check(IXMLDOMNodeList_nextNode(list, &node));
1376         node_to_string(node, pos);
1377         pos += strlen(pos);
1378         IXMLDOMNode_Release(node);
1379     }
1380     *pos = 0;
1381     return buf;
1382 }
1383 
1384 #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); }
1385 #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); }
1386 
1387 struct docload_ret_t {
1388     VARIANT_BOOL b;
1389     HRESULT hr;
1390 };
1391 
1392 struct leading_spaces_t {
1393     const CLSID *clsid;
1394     const char *name;
1395     struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1396 };
1397 
1398 static const struct leading_spaces_t leading_spaces_classdata[] = {
1399     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1400     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1401     { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1402     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1403     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1404     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1405     { NULL }
1406 };
1407 
1408 static const char* leading_spaces_xmldata[] = {
1409     "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1410     " <?xml version=\"1.0\"?><root/>",
1411     "\n<?xml version=\"1.0\"?><root/>",
1412     "\t<?xml version=\"1.0\"?><root/>",
1413     "\r\n<?xml version=\"1.0\"?><root/>",
1414     "\r<?xml version=\"1.0\"?><root/>",
1415     "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1416     0
1417 };
1418 
1419 static void test_domdoc( void )
1420 {
1421     HRESULT r, hr;
1422     IXMLDOMDocument *doc;
1423     IXMLDOMParseError *error;
1424     IXMLDOMElement *element = NULL;
1425     IXMLDOMNode *node;
1426     IXMLDOMText *nodetext = NULL;
1427     IXMLDOMComment *node_comment = NULL;
1428     IXMLDOMAttribute *node_attr = NULL;
1429     IXMLDOMNode *nodeChild = NULL;
1430     IXMLDOMProcessingInstruction *nodePI = NULL;
1431     const struct leading_spaces_t *class_ptr;
1432     const char **data_ptr;
1433     VARIANT_BOOL b;
1434     VARIANT var;
1435     BSTR str;
1436     LONG code, ref;
1437     LONG nLength = 0;
1438     WCHAR buff[100];
1439     char path[MAX_PATH];
1440     int index;
1441 
1442     GetTempPathA(MAX_PATH, path);
1443     strcat(path, "leading_spaces.xml");
1444 
1445     /* Load document with leading spaces
1446      *
1447      * Test all CLSIDs with all test data XML strings
1448      */
1449     class_ptr = leading_spaces_classdata;
1450     index = 0;
1451     while (class_ptr->clsid)
1452     {
1453         HRESULT hr;
1454         int i;
1455 
1456         if (is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
1457         {
1458             hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
1459         }
1460         else
1461         {
1462             class_ptr++;
1463             index++;
1464             continue;
1465         }
1466 
1467         data_ptr = leading_spaces_xmldata;
1468         i = 0;
1469         while (*data_ptr) {
1470             BSTR data = _bstr_(*data_ptr);
1471             DWORD written;
1472             HANDLE file;
1473 
1474             file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1475             ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1476 
1477             WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1478             CloseHandle(file);
1479 
1480             b = 0xc;
1481             V_VT(&var) = VT_BSTR;
1482             V_BSTR(&var) = _bstr_(path);
1483             hr = IXMLDOMDocument_load(doc, var, &b);
1484             EXPECT_HR(hr, class_ptr->ret[0].hr);
1485             ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1486 
1487             DeleteFileA(path);
1488 
1489             b = 0xc;
1490             hr = IXMLDOMDocument_loadXML(doc, data, &b);
1491             EXPECT_HR(hr, class_ptr->ret[1].hr);
1492             ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1493 
1494             data_ptr++;
1495             i++;
1496         }
1497 
1498         class_ptr++;
1499         index++;
1500         free_bstrs();
1501     }
1502 
1503     doc = create_document(&IID_IXMLDOMDocument);
1504     if (!doc) return;
1505 
1506 if (0)
1507 {
1508     /* crashes on native */
1509     IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1510 }
1511 
1512     /* try some stupid things */
1513     hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1514     EXPECT_HR(hr, S_FALSE);
1515 
1516     b = VARIANT_TRUE;
1517     hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1518     EXPECT_HR(hr, S_FALSE);
1519     ok( b == VARIANT_FALSE, "failed to load XML string\n");
1520 
1521     /* try to load a document from a nonexistent file */
1522     b = VARIANT_TRUE;
1523     str = SysAllocString( nonexistent_fileW );
1524     VariantInit(&var);
1525     V_VT(&var) = VT_BSTR;
1526     V_BSTR(&var) = str;
1527 
1528     r = IXMLDOMDocument_load( doc, var, &b);
1529     ok( r == S_FALSE, "loadXML succeeded\n");
1530     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1531     SysFreeString( str );
1532 
1533     str = (void *)0xdeadbeef;
1534     hr = IXMLDOMDocument_get_url(doc, &str);
1535     ok(hr == S_FALSE, "got 0x%08x\n", hr);
1536     ok(str == NULL, "got %p\n", str);
1537 
1538     /* try load an empty document */
1539     b = VARIANT_TRUE;
1540     str = SysAllocString( szEmpty );
1541     r = IXMLDOMDocument_loadXML( doc, str, &b );
1542     ok( r == S_FALSE, "loadXML succeeded\n");
1543     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1544     SysFreeString( str );
1545 
1546     r = IXMLDOMDocument_get_async( doc, &b );
1547     ok( r == S_OK, "get_async failed (%08x)\n", r);
1548     ok( b == VARIANT_TRUE, "Wrong default value\n");
1549 
1550     /* check that there's no document element */
1551     element = NULL;
1552     r = IXMLDOMDocument_get_documentElement( doc, &element );
1553     ok( r == S_FALSE, "should be no document element\n");
1554 
1555     /* try finding a node */
1556     node = NULL;
1557     str = SysAllocString( szstr1 );
1558     r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1559     ok( r == S_FALSE, "ret %08x\n", r );
1560     SysFreeString( str );
1561 
1562     b = VARIANT_TRUE;
1563     str = SysAllocString( szIncomplete );
1564     r = IXMLDOMDocument_loadXML( doc, str, &b );
1565     ok( r == S_FALSE, "loadXML succeeded\n");
1566     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1567     SysFreeString( str );
1568 
1569     /* check that there's no document element */
1570     element = (IXMLDOMElement*)1;
1571     r = IXMLDOMDocument_get_documentElement( doc, &element );
1572     ok( r == S_FALSE, "should be no document element\n");
1573     ok( element == NULL, "Element should be NULL\n");
1574 
1575     /* test for BSTR handling, pass broken BSTR */
1576     memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1577     /* just a big length */
1578     *(DWORD*)buff = 0xf0f0;
1579     b = VARIANT_FALSE;
1580     r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1581     ok( r == S_OK, "loadXML failed\n");
1582     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1583 
1584     /* loadXML ignores the encoding attribute and always expects Unicode */
1585     b = VARIANT_FALSE;
1586     str = SysAllocString( szComplete6 );
1587     r = IXMLDOMDocument_loadXML( doc, str, &b );
1588     ok( r == S_OK, "loadXML failed\n");
1589     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1590     SysFreeString( str );
1591 
1592     /* try a BSTR containing a Windows-1252 document */
1593     b = VARIANT_TRUE;
1594     str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1595     r = IXMLDOMDocument_loadXML( doc, str, &b );
1596     ok( r == S_FALSE, "loadXML succeeded\n");
1597     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1598     SysFreeString( str );
1599 
1600     /* try to load something valid */
1601     b = VARIANT_FALSE;
1602     str = SysAllocString( szComplete1 );
1603     r = IXMLDOMDocument_loadXML( doc, str, &b );
1604     ok( r == S_OK, "loadXML failed\n");
1605     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1606     SysFreeString( str );
1607 
1608     /* check if nodename is correct */
1609     r = IXMLDOMDocument_get_nodeName( doc, NULL );
1610     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1611 
1612     str = (void *)0xdeadbeef;
1613     r = IXMLDOMDocument_get_baseName( doc, &str );
1614     ok ( r == S_FALSE, "got 0x%08x\n", r);
1615     ok (str == NULL, "got %p\n", str);
1616 
1617     /* content doesn't matter here */
1618     str = NULL;
1619     r = IXMLDOMDocument_get_nodeName( doc, &str );
1620     ok ( r == S_OK, "get_nodeName wrong code\n");
1621     ok ( str != NULL, "str is null\n");
1622     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1623     SysFreeString( str );
1624 
1625     /* test put_text */
1626     r = IXMLDOMDocument_put_text( doc, _bstr_("Should fail") );
1627     ok( r == E_FAIL, "ret %08x\n", r );
1628 
1629     /* check that there's a document element */
1630     element = NULL;
1631     r = IXMLDOMDocument_get_documentElement( doc, &element );
1632     ok( r == S_OK, "should be a document element\n");
1633     if( element )
1634     {
1635         IObjectIdentity *ident;
1636 
1637         r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1638         ok( r == E_NOINTERFACE, "ret %08x\n", r);
1639 
1640         IXMLDOMElement_Release( element );
1641         element = NULL;
1642     }
1643 
1644     /* as soon as we call loadXML again, the document element will disappear */
1645     b = 2;
1646     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1647     ok( r == S_FALSE, "loadXML failed\n");
1648     ok( b == 2, "variant modified\n");
1649     r = IXMLDOMDocument_get_documentElement( doc, &element );
1650     ok( r == S_FALSE, "should be no document element\n");
1651 
1652     /* try to load something else simple and valid */
1653     b = VARIANT_FALSE;
1654     str = SysAllocString( szComplete2 );
1655     r = IXMLDOMDocument_loadXML( doc, str, &b );
1656     ok( r == S_OK, "loadXML failed\n");
1657     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1658     SysFreeString( str );
1659 
1660     /* try something a little more complicated */
1661     b = FALSE;
1662     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1663     ok( r == S_OK, "loadXML failed\n");
1664     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1665 
1666     r = IXMLDOMDocument_get_parseError( doc, &error );
1667     ok( r == S_OK, "returns %08x\n", r );
1668 
1669     r = IXMLDOMParseError_get_errorCode( error, &code );
1670     ok( r == S_FALSE, "returns %08x\n", r );
1671     ok( code == 0, "code %d\n", code );
1672     IXMLDOMParseError_Release( error );
1673 
1674     /* test createTextNode */
1675     r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1676     ok( r == S_OK, "returns %08x\n", r );
1677     IXMLDOMText_Release(nodetext);
1678 
1679     str = SysAllocString( szOpen );
1680     r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1681     ok( r == E_INVALIDARG, "returns %08x\n", r );
1682     r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1683     ok( r == S_OK, "returns %08x\n", r );
1684     SysFreeString( str );
1685     if(nodetext)
1686     {
1687         r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1688         ok(r == E_NOINTERFACE, "ret %08x\n", r );
1689 
1690         /* Text Last Child Checks */
1691         r = IXMLDOMText_get_lastChild(nodetext, NULL);
1692         ok(r == E_INVALIDARG, "ret %08x\n", r );
1693 
1694         nodeChild = (IXMLDOMNode*)0x1;
1695         r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1696         ok(r == S_FALSE, "ret %08x\n", r );
1697         ok(nodeChild == NULL, "nodeChild not NULL\n");
1698 
1699         /* test length property */
1700         r = IXMLDOMText_get_length(nodetext, NULL);
1701         ok(r == E_INVALIDARG, "ret %08x\n", r );
1702 
1703         r = IXMLDOMText_get_length(nodetext, &nLength);
1704         ok(r == S_OK, "ret %08x\n", r );
1705         ok(nLength == 4, "expected 4 got %d\n", nLength);
1706 
1707         /* put data Tests */
1708         r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1709         ok(r == S_OK, "ret %08x\n", r );
1710 
1711         /* get data Tests */
1712         r = IXMLDOMText_get_data(nodetext, &str);
1713         ok(r == S_OK, "ret %08x\n", r );
1714         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1715         SysFreeString(str);
1716 
1717         /* Confirm XML text is good */
1718         r = IXMLDOMText_get_xml(nodetext, &str);
1719         ok(r == S_OK, "ret %08x\n", r );
1720         ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1721         SysFreeString(str);
1722 
1723         /* Confirm we get the put_data Text back */
1724         r = IXMLDOMText_get_text(nodetext, &str);
1725         ok(r == S_OK, "ret %08x\n", r );
1726         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1727         SysFreeString(str);
1728 
1729         /* test substringData */
1730         r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1731         ok(r == E_INVALIDARG, "ret %08x\n", r );
1732 
1733         /* test substringData - Invalid offset */
1734         str = (void *)0xdeadbeef;
1735         r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1736         ok(r == E_INVALIDARG, "ret %08x\n", r );
1737         ok( str == NULL, "incorrect string\n");
1738 
1739         /* test substringData - Invalid offset */
1740         str = (void *)0xdeadbeef;
1741         r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1742         ok(r == S_FALSE, "ret %08x\n", r );
1743         ok( str == NULL, "incorrect string\n");
1744 
1745         /* test substringData - Invalid size */
1746         str = (void *)0xdeadbeef;
1747         r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1748         ok(r == E_INVALIDARG, "ret %08x\n", r );
1749         ok( str == NULL, "incorrect string\n");
1750 
1751         /* test substringData - Invalid size */
1752         str = (void *)0xdeadbeef;
1753         r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1754         ok(r == S_FALSE, "ret %08x\n", r );
1755         ok( str == NULL, "incorrect string\n");
1756 
1757         /* test substringData - Start of string */
1758         r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1759         ok(r == S_OK, "ret %08x\n", r );
1760         ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1761         SysFreeString(str);
1762 
1763         /* test substringData - Middle of string */
1764         r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1765         ok(r == S_OK, "ret %08x\n", r );
1766         ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1767         SysFreeString(str);
1768 
1769         /* test substringData - End of string */
1770         r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1771         ok(r == S_OK, "ret %08x\n", r );
1772         ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1773         SysFreeString(str);
1774 
1775         /* test appendData */
1776         r = IXMLDOMText_appendData(nodetext, NULL);
1777         ok(r == S_OK, "ret %08x\n", r );
1778 
1779         r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1780         ok(r == S_OK, "ret %08x\n", r );
1781 
1782         r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1783         ok(r == S_OK, "ret %08x\n", r );
1784 
1785         r = IXMLDOMText_get_text(nodetext, &str);
1786         ok(r == S_OK, "ret %08x\n", r );
1787         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1788         SysFreeString(str);
1789 
1790         /* test insertData */
1791         str = SysAllocStringLen(NULL, 0);
1792         r = IXMLDOMText_insertData(nodetext, -1, str);
1793         ok(r == S_OK, "ret %08x\n", r );
1794 
1795         r = IXMLDOMText_insertData(nodetext, -1, NULL);
1796         ok(r == S_OK, "ret %08x\n", r );
1797 
1798         r = IXMLDOMText_insertData(nodetext, 1000, str);
1799         ok(r == S_OK, "ret %08x\n", r );
1800 
1801         r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1802         ok(r == S_OK, "ret %08x\n", r );
1803 
1804         r = IXMLDOMText_insertData(nodetext, 0, NULL);
1805         ok(r == S_OK, "ret %08x\n", r );
1806 
1807         r = IXMLDOMText_insertData(nodetext, 0, str);
1808         ok(r == S_OK, "ret %08x\n", r );
1809         SysFreeString(str);
1810 
1811         r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1812         ok(r == E_INVALIDARG, "ret %08x\n", r );
1813 
1814         r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1815         ok(r == E_INVALIDARG, "ret %08x\n", r );
1816 
1817         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1818         ok(r == S_OK, "ret %08x\n", r );
1819 
1820         r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1821         ok(r == S_OK, "ret %08x\n", r );
1822 
1823         r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1824         ok(r == S_OK, "ret %08x\n", r );
1825 
1826         r = IXMLDOMText_get_text(nodetext, &str);
1827         ok(r == S_OK, "ret %08x\n", r );
1828         ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1829         SysFreeString(str);
1830 
1831         /* delete data */
1832         /* invalid arguments */
1833         r = IXMLDOMText_deleteData(nodetext, -1, 1);
1834         ok(r == E_INVALIDARG, "ret %08x\n", r );
1835 
1836         r = IXMLDOMText_deleteData(nodetext, 0, 0);
1837         ok(r == S_OK, "ret %08x\n", r );
1838 
1839         r = IXMLDOMText_deleteData(nodetext, 0, -1);
1840         ok(r == E_INVALIDARG, "ret %08x\n", r );
1841 
1842         r = IXMLDOMText_get_length(nodetext, &nLength);
1843         ok(r == S_OK, "ret %08x\n", r );
1844         ok(nLength == 43, "expected 43 got %d\n", nLength);
1845 
1846         r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1847         ok(r == S_OK, "ret %08x\n", r );
1848 
1849         r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1850         ok(r == E_INVALIDARG, "ret %08x\n", r );
1851 
1852         /* delete from start */
1853         r = IXMLDOMText_deleteData(nodetext, 0, 5);
1854         ok(r == S_OK, "ret %08x\n", r );
1855 
1856         r = IXMLDOMText_get_length(nodetext, &nLength);
1857         ok(r == S_OK, "ret %08x\n", r );
1858         ok(nLength == 38, "expected 38 got %d\n", nLength);
1859 
1860         r = IXMLDOMText_get_text(nodetext, &str);
1861         ok(r == S_OK, "ret %08x\n", r );
1862         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1863         SysFreeString(str);
1864 
1865         /* delete from end */
1866         r = IXMLDOMText_deleteData(nodetext, 35, 3);
1867         ok(r == S_OK, "ret %08x\n", r );
1868 
1869         r = IXMLDOMText_get_length(nodetext, &nLength);
1870         ok(r == S_OK, "ret %08x\n", r );
1871         ok(nLength == 35, "expected 35 got %d\n", nLength);
1872 
1873         r = IXMLDOMText_get_text(nodetext, &str);
1874         ok(r == S_OK, "ret %08x\n", r );
1875         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1876         SysFreeString(str);
1877 
1878         /* delete from inside */
1879         r = IXMLDOMText_deleteData(nodetext, 1, 33);
1880         ok(r == S_OK, "ret %08x\n", r );
1881 
1882         r = IXMLDOMText_get_length(nodetext, &nLength);
1883         ok(r == S_OK, "ret %08x\n", r );
1884         ok(nLength == 2, "expected 2 got %d\n", nLength);
1885 
1886         r = IXMLDOMText_get_text(nodetext, &str);
1887         ok(r == S_OK, "ret %08x\n", r );
1888         ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1889         SysFreeString(str);
1890 
1891         /* delete whole data ... */
1892         r = IXMLDOMText_get_length(nodetext, &nLength);
1893         ok(r == S_OK, "ret %08x\n", r );
1894 
1895         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1896         ok(r == S_OK, "ret %08x\n", r );
1897         /* ... and try again with empty string */
1898         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1899         ok(r == S_OK, "ret %08x\n", r );
1900 
1901         /* test put_data */
1902         V_VT(&var) = VT_BSTR;
1903         V_BSTR(&var) = SysAllocString(szstr1);
1904         r = IXMLDOMText_put_nodeValue(nodetext, var);
1905         ok(r == S_OK, "ret %08x\n", r );
1906         VariantClear(&var);
1907 
1908         r = IXMLDOMText_get_text(nodetext, &str);
1909         ok(r == S_OK, "ret %08x\n", r );
1910         ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1911         SysFreeString(str);
1912 
1913         /* test put_data */
1914         V_VT(&var) = VT_I4;
1915         V_I4(&var) = 99;
1916         r = IXMLDOMText_put_nodeValue(nodetext, var);
1917         ok(r == S_OK, "ret %08x\n", r );
1918         VariantClear(&var);
1919 
1920         r = IXMLDOMText_get_text(nodetext, &str);
1921         ok(r == S_OK, "ret %08x\n", r );
1922         ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1923         SysFreeString(str);
1924 
1925         /* ::replaceData() */
1926         V_VT(&var) = VT_BSTR;
1927         V_BSTR(&var) = SysAllocString(szstr1);
1928         r = IXMLDOMText_put_nodeValue(nodetext, var);
1929         ok(r == S_OK, "ret %08x\n", r );
1930         VariantClear(&var);
1931 
1932         r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1933         ok(r == E_INVALIDARG, "ret %08x\n", r );
1934         r = IXMLDOMText_get_text(nodetext, &str);
1935         ok(r == S_OK, "ret %08x\n", r );
1936         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1937         SysFreeString(str);
1938 
1939         r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1940         ok(r == S_OK, "ret %08x\n", r );
1941         r = IXMLDOMText_get_text(nodetext, &str);
1942         ok(r == S_OK, "ret %08x\n", r );
1943         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1944         SysFreeString(str);
1945 
1946         /* NULL pointer means delete */
1947         r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1948         ok(r == S_OK, "ret %08x\n", r );
1949         r = IXMLDOMText_get_text(nodetext, &str);
1950         ok(r == S_OK, "ret %08x\n", r );
1951         ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1952         SysFreeString(str);
1953 
1954         /* empty string means delete */
1955         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1956         ok(r == S_OK, "ret %08x\n", r );
1957         r = IXMLDOMText_get_text(nodetext, &str);
1958         ok(r == S_OK, "ret %08x\n", r );
1959         ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1960         SysFreeString(str);
1961 
1962         /* zero count means insert */
1963         r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1964         ok(r == S_OK, "ret %08x\n", r );
1965         r = IXMLDOMText_get_text(nodetext, &str);
1966         ok(r == S_OK, "ret %08x\n", r );
1967         ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1968         SysFreeString(str);
1969 
1970         r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1971         ok(r == S_OK, "ret %08x\n", r );
1972 
1973         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1974         ok(r == S_OK, "ret %08x\n", r );
1975         r = IXMLDOMText_get_text(nodetext, &str);
1976         ok(r == S_OK, "ret %08x\n", r );
1977         ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1978         SysFreeString(str);
1979 
1980         /* nonempty string, count greater than its length */
1981         r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
1982         ok(r == S_OK, "ret %08x\n", r );
1983         r = IXMLDOMText_get_text(nodetext, &str);
1984         ok(r == S_OK, "ret %08x\n", r );
1985         ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1986         SysFreeString(str);
1987 
1988         /* nonempty string, count less than its length */
1989         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
1990         ok(r == S_OK, "ret %08x\n", r );
1991         r = IXMLDOMText_get_text(nodetext, &str);
1992         ok(r == S_OK, "ret %08x\n", r );
1993         ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1994         SysFreeString(str);
1995 
1996         IXMLDOMText_Release( nodetext );
1997     }
1998 
1999     /* test Create Comment */
2000     r = IXMLDOMDocument_createComment(doc, NULL, NULL);
2001     ok( r == E_INVALIDARG, "returns %08x\n", r );
2002     node_comment = (IXMLDOMComment*)0x1;
2003 
2004     /* empty comment */
2005     r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
2006     ok( r == S_OK, "returns %08x\n", r );
2007     str = NULL;
2008     r = IXMLDOMComment_get_data(node_comment, &str);
2009     ok( r == S_OK, "returns %08x\n", r );
2010     ok( str && SysStringLen(str) == 0, "expected empty string data\n");
2011     IXMLDOMComment_Release(node_comment);
2012     SysFreeString(str);
2013 
2014     r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
2015     ok( r == S_OK, "returns %08x\n", r );
2016     str = NULL;
2017     r = IXMLDOMComment_get_data(node_comment, &str);
2018     ok( r == S_OK, "returns %08x\n", r );
2019     ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
2020     IXMLDOMComment_Release(node_comment);
2021     SysFreeString(str);
2022 
2023     str = SysAllocString(szComment);
2024     r = IXMLDOMDocument_createComment(doc, str, &node_comment);
2025     SysFreeString(str);
2026     ok( r == S_OK, "returns %08x\n", r );
2027     if(node_comment)
2028     {
2029         /* Last Child Checks */
2030         r = IXMLDOMComment_get_lastChild(node_comment, NULL);
2031         ok(r == E_INVALIDARG, "ret %08x\n", r );
2032 
2033         nodeChild = (IXMLDOMNode*)0x1;
2034         r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
2035         ok(r == S_FALSE, "ret %08x\n", r );
2036         ok(nodeChild == NULL, "pLastChild not NULL\n");
2037 
2038         /* baseName */
2039         str = (void *)0xdeadbeef;
2040         r = IXMLDOMComment_get_baseName(node_comment, &str);
2041         ok(r == S_FALSE, "ret %08x\n", r );
2042         ok(str == NULL, "Expected NULL\n");
2043 
2044         IXMLDOMComment_Release( node_comment );
2045     }
2046 
2047     /* test Create Attribute */
2048     str = SysAllocString(szAttribute);
2049     r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
2050     ok( r == E_INVALIDARG, "returns %08x\n", r );
2051     r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
2052     ok( r == S_OK, "returns %08x\n", r );
2053     IXMLDOMAttribute_Release( node_attr);
2054     SysFreeString(str);
2055 
2056     /* test Processing Instruction */
2057     str = SysAllocStringLen(NULL, 0);
2058     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
2059     ok( r == E_INVALIDARG, "returns %08x\n", r );
2060     r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
2061     ok( r == E_FAIL, "returns %08x\n", r );
2062     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
2063     ok( r == E_FAIL, "returns %08x\n", r );
2064     SysFreeString(str);
2065 
2066     r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
2067     ok( r == S_OK, "returns %08x\n", r );
2068     if(nodePI)
2069     {
2070         /* Last Child Checks */
2071         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
2072         ok(r == E_INVALIDARG, "ret %08x\n", r );
2073 
2074         nodeChild = (IXMLDOMNode*)0x1;
2075         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
2076         ok(r == S_FALSE, "ret %08x\n", r );
2077         ok(nodeChild == NULL, "nodeChild not NULL\n");
2078 
2079         /* test nodeName */
2080         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2081         ok(r == S_OK, "ret %08x\n", r );
2082         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2083         SysFreeString(str);
2084 
2085         /* test baseName */
2086         str = NULL;
2087         r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
2088         ok(r == S_OK, "ret %08x\n", r );
2089         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2090         SysFreeString(str);
2091 
2092         /* test Target */
2093         r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
2094         ok(r == S_OK, "ret %08x\n", r );
2095         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
2096         SysFreeString(str);
2097 
2098         /* test get_data */
2099         r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
2100         ok(r == S_OK, "ret %08x\n", r );
2101         ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
2102         SysFreeString(str);
2103 
2104         /* test put_data */
2105         r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
2106         ok(r == E_FAIL, "ret %08x\n", r );
2107 
2108         /* test put_data */
2109         V_VT(&var) = VT_BSTR;
2110         V_BSTR(&var) = SysAllocString(szOpen);  /* Doesn't matter what the string is, cannot set an xml node. */
2111         r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
2112         ok(r == E_FAIL, "ret %08x\n", r );
2113         VariantClear(&var);
2114 
2115         /* test get nodeName */
2116         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2117         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2118         ok(r == S_OK, "ret %08x\n", r );
2119         SysFreeString(str);
2120 
2121         IXMLDOMProcessingInstruction_Release(nodePI);
2122     }
2123 
2124     ref = IXMLDOMDocument_Release( doc );
2125     ok( ref == 0, "got %d\n", ref);
2126 
2127     free_bstrs();
2128 }
2129 
2130 static void test_persiststream(void)
2131 {
2132     IPersistStreamInit *streaminit;
2133     IPersistStream *stream;
2134     IXMLDOMDocument *doc;
2135     ULARGE_INTEGER size;
2136     IPersist *persist;
2137     HRESULT hr;
2138     CLSID clsid;
2139 
2140     doc = create_document(&IID_IXMLDOMDocument);
2141 
2142     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
2143     ok(hr == S_OK, "got 0x%08x\n", hr);
2144 
2145     hr = IPersistStreamInit_InitNew(streaminit);
2146     ok(hr == S_OK, "got 0x%08x\n", hr);
2147 
2148     hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
2149     ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
2150 
2151     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStream, (void **)&stream);
2152     ok(hr == S_OK, "got 0x%08x\n", hr);
2153     ok((IUnknown *)stream == (IUnknown *)streaminit, "got %p, %p\n", stream, streaminit);
2154 
2155     hr = IPersistStream_QueryInterface(stream, &IID_IPersist, (void **)&persist);
2156     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2157 
2158     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersist, (void **)&persist);
2159     ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2160 
2161     hr = IPersistStreamInit_GetClassID(streaminit, NULL);
2162     ok(hr == E_POINTER, "got 0x%08x\n", hr);
2163 
2164     memset(&clsid, 0, sizeof(clsid));
2165     hr = IPersistStreamInit_GetClassID(streaminit, &clsid);
2166     ok(hr == S_OK, "got 0x%08x\n", hr);
2167     ok(IsEqualGUID(&clsid, &CLSID_DOMDocument2), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
2168 
2169     IPersistStream_Release(stream);
2170     IPersistStreamInit_Release(streaminit);
2171     IXMLDOMDocument_Release(doc);
2172 }
2173 
2174 static void test_domnode( void )
2175 {
2176     HRESULT r;
2177     IXMLDOMDocument *doc, *owner = NULL;
2178     IXMLDOMElement *element = NULL;
2179     IXMLDOMNamedNodeMap *map = NULL;
2180     IXMLDOMNode *node = NULL, *next = NULL;
2181     IXMLDOMNodeList *list = NULL;
2182     IXMLDOMAttribute *attr = NULL;
2183     DOMNodeType type = NODE_INVALID;
2184     VARIANT_BOOL b;
2185     BSTR str;
2186     VARIANT var;
2187     LONG count;
2188 
2189     doc = create_document(&IID_IXMLDOMDocument);
2190 
2191     b = FALSE;
2192     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2193     ok( r == S_OK, "loadXML failed\n");
2194     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2195 
2196     EXPECT_CHILDREN(doc);
2197 
2198     r = IXMLDOMDocument_get_documentElement( doc, &element );
2199     ok( r == S_OK, "should be a document element\n");
2200     ok( element != NULL, "should be an element\n");
2201 
2202     VariantInit(&var);
2203     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
2204 
2205     r = IXMLDOMDocument_get_nodeValue( doc, NULL );
2206     ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
2207 
2208     r = IXMLDOMDocument_get_nodeValue( doc, &var );
2209     ok( r == S_FALSE, "nextNode returned wrong code\n");
2210     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
2211     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
2212 
2213     if (element)
2214     {
2215         owner = NULL;
2216         r = IXMLDOMElement_get_ownerDocument( element, &owner );
2217         ok( r == S_OK, "get_ownerDocument return code\n");
2218         ok( owner != doc, "get_ownerDocument return\n");
2219         IXMLDOMDocument_Release(owner);
2220 
2221         type = NODE_INVALID;
2222         r = IXMLDOMElement_get_nodeType( element, &type);
2223         ok( r == S_OK, "got %08x\n", r);
2224         ok( type == NODE_ELEMENT, "node not an element\n");
2225 
2226         str = NULL;
2227         r = IXMLDOMElement_get_baseName( element, &str );
2228         ok( r == S_OK, "get_baseName returned wrong code\n");
2229         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
2230         SysFreeString(str);
2231 
2232         /* check if nodename is correct */
2233         r = IXMLDOMElement_get_nodeName( element, NULL );
2234         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2235 
2236         /* content doesn't matter here */
2237         str = NULL;
2238         r = IXMLDOMElement_get_nodeName( element, &str );
2239         ok ( r == S_OK, "get_nodeName wrong code\n");
2240         ok ( str != NULL, "str is null\n");
2241         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
2242         SysFreeString( str );
2243 
2244         str = SysAllocString( nonexistent_fileW );
2245         V_VT(&var) = VT_I4;
2246         V_I4(&var) = 0x1234;
2247         r = IXMLDOMElement_getAttribute( element, str, &var );
2248         ok( r == E_FAIL, "getAttribute ret %08x\n", r );
2249         ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
2250         VariantClear(&var);
2251         SysFreeString(str);
2252 
2253         str = SysAllocString( szdl );
2254         V_VT(&var) = VT_I4;
2255         V_I4(&var) = 0x1234;
2256         r = IXMLDOMElement_getAttribute( element, str, &var );
2257         ok( r == S_OK, "getAttribute ret %08x\n", r );
2258         ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
2259         ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
2260         VariantClear( &var );
2261 
2262         r = IXMLDOMElement_getAttribute( element, NULL, &var );
2263         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2264 
2265         r = IXMLDOMElement_getAttribute( element, str, NULL );
2266         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2267 
2268         attr = NULL;
2269         r = IXMLDOMElement_getAttributeNode( element, str, &attr);
2270         ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
2271         ok( attr != NULL, "getAttributeNode returned NULL\n" );
2272         if (attr)
2273         {
2274             r = IXMLDOMAttribute_get_parentNode( attr, NULL );
2275             ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
2276 
2277             /* attribute doesn't have a parent in msxml interpretation */
2278             node = (IXMLDOMNode*)0xdeadbeef;
2279             r = IXMLDOMAttribute_get_parentNode( attr, &node );
2280             ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
2281             ok( node == NULL, "Expected NULL, got %p\n", node );
2282 
2283             IXMLDOMAttribute_Release(attr);
2284         }
2285 
2286         SysFreeString( str );
2287 
2288         r = IXMLDOMElement_get_attributes( element, &map );
2289         ok( r == S_OK, "get_attributes returned wrong code\n");
2290         ok( map != NULL, "should be attributes\n");
2291 
2292         EXPECT_CHILDREN(element);
2293     }
2294     else
2295         ok( FALSE, "no element\n");
2296 
2297     if (map)
2298     {
2299         str = SysAllocString( szdl );
2300         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2301         ok( r == S_OK, "getNamedItem returned wrong code\n");
2302         ok( node != NULL, "should be attributes\n");
2303         IXMLDOMNode_Release(node);
2304         SysFreeString( str );
2305 
2306         str = SysAllocString( szdl );
2307         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
2308         ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
2309         SysFreeString( str );
2310 
2311         /* something that isn't in complete4A */
2312         str = SysAllocString( szOpen );
2313         node = (IXMLDOMNode *) 1;
2314         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2315         ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
2316         ok( node == NULL, "getNamedItem should have returned NULL\n");
2317         SysFreeString( str );
2318 
2319 	/* test indexed access of attributes */
2320         r = IXMLDOMNamedNodeMap_get_length( map, NULL );
2321         ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
2322 
2323         r = IXMLDOMNamedNodeMap_get_length( map, &count );
2324         ok ( r == S_OK, "get_length wrong code\n");
2325         ok ( count == 1, "get_length != 1\n");
2326 
2327         node = NULL;
2328         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
2329         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
2330         ok ( node == NULL, "there is no node\n");
2331 
2332         node = NULL;
2333         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
2334         ok ( r == S_FALSE, "get_item (1) wrong code\n");
2335         ok ( node == NULL, "there is no attribute\n");
2336 
2337         node = NULL;
2338         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
2339         ok ( r == S_OK, "get_item (0) wrong code\n");
2340         ok ( node != NULL, "should be attribute\n");
2341 
2342         r = IXMLDOMNode_get_nodeName( node, NULL );
2343         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2344 
2345         /* content doesn't matter here */
2346         str = NULL;
2347         r = IXMLDOMNode_get_nodeName( node, &str );
2348         ok ( r == S_OK, "get_nodeName wrong code\n");
2349         ok ( str != NULL, "str is null\n");
2350         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
2351         SysFreeString( str );
2352         IXMLDOMNode_Release( node );
2353 
2354         /* test sequential access of attributes */
2355         node = NULL;
2356         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2357         ok ( r == S_OK, "nextNode (first time) wrong code\n");
2358         ok ( node != NULL, "nextNode, should be attribute\n");
2359         IXMLDOMNode_Release( node );
2360 
2361         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2362         ok ( r != S_OK, "nextNode (second time) wrong code\n");
2363         ok ( node == NULL, "nextNode, there is no attribute\n");
2364 
2365         r = IXMLDOMNamedNodeMap_reset( map );
2366         ok ( r == S_OK, "reset should return S_OK\n");
2367 
2368         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2369         ok ( r == S_OK, "nextNode (third time) wrong code\n");
2370         ok ( node != NULL, "nextNode, should be attribute\n");
2371     }
2372     else
2373         ok( FALSE, "no map\n");
2374 
2375     if (node)
2376     {
2377         type = NODE_INVALID;
2378         r = IXMLDOMNode_get_nodeType( node, &type);
2379         ok( r == S_OK, "getNamedItem returned wrong code\n");
2380         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
2381 
2382         str = NULL;
2383         r = IXMLDOMNode_get_baseName( node, NULL );
2384         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
2385 
2386         str = NULL;
2387         r = IXMLDOMNode_get_baseName( node, &str );
2388         ok( r == S_OK, "get_baseName returned wrong code\n");
2389         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
2390         SysFreeString( str );
2391 
2392         r = IXMLDOMNode_get_childNodes( node, NULL );
2393         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
2394 
2395         r = IXMLDOMNode_get_childNodes( node, &list );
2396         ok( r == S_OK, "get_childNodes returned wrong code\n");
2397 
2398         if (list)
2399         {
2400             r = IXMLDOMNodeList_nextNode( list, &next );
2401             ok( r == S_OK, "nextNode returned wrong code\n");
2402         }
2403         else
2404             ok( FALSE, "no childlist\n");
2405 
2406         if (next)
2407         {
2408             EXPECT_NO_CHILDREN(next);
2409 
2410             type = NODE_INVALID;
2411             r = IXMLDOMNode_get_nodeType( next, &type);
2412             ok( r == S_OK, "getNamedItem returned wrong code\n");
2413             ok( type == NODE_TEXT, "node not text\n");
2414 
2415             str = (void *)0xdeadbeef;
2416             r = IXMLDOMNode_get_baseName( next, &str );
2417             ok( r == S_FALSE, "get_baseName returned wrong code\n");
2418             ok( str == NULL, "basename was wrong\n");
2419             SysFreeString(str);
2420         }
2421         else
2422             ok( FALSE, "no next\n");
2423 
2424         if (next)
2425             IXMLDOMNode_Release( next );
2426         next = NULL;
2427         if (list)
2428             IXMLDOMNodeList_Release( list );
2429         list = NULL;
2430         if (node)
2431             IXMLDOMNode_Release( node );
2432     }
2433     else
2434         ok( FALSE, "no node\n");
2435     node = NULL;
2436 
2437     if (map)
2438         IXMLDOMNamedNodeMap_Release( map );
2439 
2440     /* now traverse the tree from the root element */
2441     if (element)
2442     {
2443         r = IXMLDOMElement_get_childNodes( element, &list );
2444         ok( r == S_OK, "get_childNodes returned wrong code\n");
2445 
2446         /* using get_item for child list doesn't advance the position */
2447         ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2448         expect_node(node, "E2.E2.D1");
2449         IXMLDOMNode_Release(node);
2450         ole_check(IXMLDOMNodeList_nextNode(list, &node));
2451         expect_node(node, "E1.E2.D1");
2452         IXMLDOMNode_Release(node);
2453         ole_check(IXMLDOMNodeList_reset(list));
2454 
2455         IXMLDOMNodeList_AddRef(list);
2456         expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2457         ole_check(IXMLDOMNodeList_reset(list));
2458 
2459         node = (void*)0xdeadbeef;
2460         str = SysAllocString(szdl);
2461         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2462         SysFreeString(str);
2463         ok( r == S_FALSE, "ret %08x\n", r );
2464         ok( node == NULL, "node %p\n", node );
2465 
2466         str = SysAllocString(szbs);
2467         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2468         SysFreeString(str);
2469         ok( r == S_OK, "ret %08x\n", r );
2470         r = IXMLDOMNode_Release( node );
2471         ok( r == 0, "ret %08x\n", r );
2472     }
2473     else
2474         ok( FALSE, "no element\n");
2475 
2476     if (list)
2477     {
2478         r = IXMLDOMNodeList_get_item(list, 0, NULL);
2479         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2480 
2481         r = IXMLDOMNodeList_get_length(list, NULL);
2482         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2483 
2484         r = IXMLDOMNodeList_get_length( list, &count );
2485         ok( r == S_OK, "get_length returns %08x\n", r );
2486         ok( count == 4, "get_length got %d\n", count );
2487 
2488         r = IXMLDOMNodeList_nextNode(list, NULL);
2489         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2490 
2491         r = IXMLDOMNodeList_nextNode( list, &node );
2492         ok( r == S_OK, "nextNode returned wrong code\n");
2493     }
2494     else
2495         ok( FALSE, "no list\n");
2496 
2497     if (node)
2498     {
2499         type = NODE_INVALID;
2500         r = IXMLDOMNode_get_nodeType( node, &type);
2501         ok( r == S_OK, "getNamedItem returned wrong code\n");
2502         ok( type == NODE_ELEMENT, "node not text\n");
2503 
2504         r = IXMLDOMNode_hasChildNodes( node, NULL );
2505         ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2506 
2507         EXPECT_CHILDREN(node);
2508 
2509         str = NULL;
2510         r = IXMLDOMNode_get_baseName( node, &str );
2511         ok( r == S_OK, "get_baseName returned wrong code\n");
2512         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2513         SysFreeString(str);
2514     }
2515     else
2516         ok( FALSE, "no node\n");
2517 
2518     if (node)
2519         IXMLDOMNode_Release( node );
2520     if (list)
2521         IXMLDOMNodeList_Release( list );
2522     if (element)
2523         IXMLDOMElement_Release( element );
2524 
2525     b = FALSE;
2526     str = SysAllocString( szComplete5 );
2527     r = IXMLDOMDocument_loadXML( doc, str, &b );
2528     ok( r == S_OK, "loadXML failed\n");
2529     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2530     SysFreeString( str );
2531 
2532     EXPECT_CHILDREN(doc);
2533 
2534     r = IXMLDOMDocument_get_documentElement( doc, &element );
2535     ok( r == S_OK, "should be a document element\n");
2536     ok( element != NULL, "should be an element\n");
2537 
2538     if (element)
2539     {
2540         static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2541         BSTR tag = NULL;
2542 
2543         /* check if the tag is correct */
2544         r = IXMLDOMElement_get_tagName( element, &tag );
2545         ok( r == S_OK, "couldn't get tag name\n");
2546         ok( tag != NULL, "tag was null\n");
2547         ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2548         SysFreeString( tag );
2549 
2550         IXMLDOMElement_Release( element );
2551     }
2552     ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2553 
2554     free_bstrs();
2555 }
2556 
2557 typedef struct {
2558     DOMNodeType type;
2559     REFIID iid;
2560 } refcount_test_t;
2561 
2562 static const refcount_test_t refcount_test[] = {
2563     { NODE_ELEMENT,                &IID_IXMLDOMElement },
2564     { NODE_ATTRIBUTE,              &IID_IXMLDOMAttribute },
2565     { NODE_TEXT,                   &IID_IXMLDOMText },
2566     { NODE_CDATA_SECTION,          &IID_IXMLDOMCDATASection },
2567     { NODE_ENTITY_REFERENCE,       &IID_IXMLDOMEntityReference },
2568     { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2569     { NODE_COMMENT,                &IID_IXMLDOMComment },
2570     { NODE_DOCUMENT_FRAGMENT,      &IID_IXMLDOMDocumentFragment },
2571     { NODE_INVALID,                &IID_NULL }
2572 };
2573 
2574 static void test_refs(void)
2575 {
2576     IXMLDOMImplementation *impl, *impl2;
2577     IXMLDOMElement *element, *elem2;
2578     IXMLDOMNodeList *node_list = NULL;
2579     IXMLDOMNode *node, *node2, *node3;
2580     const refcount_test_t *ptr;
2581     IXMLDOMDocument *doc;
2582     IUnknown *unk, *unk2;
2583     VARIANT_BOOL b;
2584     HRESULT hr;
2585     LONG ref;
2586 
2587     doc = create_document(&IID_IXMLDOMDocument);
2588 
2589     ptr = refcount_test;
2590     while (ptr->type != NODE_INVALID)
2591     {
2592         IUnknown *node_typed, *node_typed2;
2593         IDispatchEx *dispex, *dispex2;
2594         IDispatch *disp, *disp2;
2595         VARIANT type;
2596 
2597         V_VT(&type) = VT_I1;
2598         V_I1(&type) = ptr->type;
2599 
2600         EXPECT_REF(doc, 1);
2601         hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2602         EXPECT_HR(hr, S_OK);
2603         EXPECT_REF(doc, 1);
2604         EXPECT_REF(node, 1);
2605 
2606         /* try IDispatch and IUnknown from IXMLDOMNode */
2607         hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2608         EXPECT_HR(hr, S_OK);
2609         EXPECT_REF(unk, 2);
2610 todo_wine {
2611         EXPECT_REF(node, 1);
2612         ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2613 }
2614         EXPECT_REF(unk, 2);
2615         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2616         EXPECT_HR(hr, S_OK);
2617         todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2618         EXPECT_REF(unk, 3);
2619         todo_wine EXPECT_REF(disp, 1);
2620 
2621         EXPECT_REF(unk, 3);
2622         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2623         EXPECT_HR(hr, S_OK);
2624         todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2625         EXPECT_REF(unk, 4);
2626         todo_wine EXPECT_REF(disp2, 1);
2627 
2628         IDispatch_Release(disp);
2629         IDispatch_Release(disp2);
2630 
2631         /* get IXMLDOMNode from this IUnknown */
2632         EXPECT_REF(unk, 2);
2633         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2634         EXPECT_HR(hr, S_OK);
2635         todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2636         EXPECT_REF(unk, 3);
2637         todo_wine EXPECT_REF(node2, 1);
2638 
2639         EXPECT_REF(unk, 3);
2640         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2641         EXPECT_HR(hr, S_OK);
2642         todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2643         EXPECT_REF(unk, 4);
2644         todo_wine EXPECT_REF(node3, 1);
2645 
2646         IXMLDOMNode_Release(node2);
2647         IXMLDOMNode_Release(node3);
2648 
2649         /* try IDispatchEx from IUnknown */
2650         EXPECT_REF(unk, 2);
2651         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2652         EXPECT_HR(hr, S_OK);
2653         ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2654         EXPECT_REF(unk, 3);
2655         todo_wine EXPECT_REF(dispex, 1);
2656 
2657         EXPECT_REF(unk, 3);
2658         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2659         EXPECT_HR(hr, S_OK);
2660         todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2661         EXPECT_REF(unk, 4);
2662         todo_wine EXPECT_REF(dispex2, 1);
2663 
2664         IDispatchEx_Release(dispex);
2665         IDispatchEx_Release(dispex2);
2666 
2667         /* try corresponding IXMLDOM* */
2668         EXPECT_REF(unk, 2);
2669         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2670         EXPECT_HR(hr, S_OK);
2671         EXPECT_REF(unk, 3);
2672         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2673         EXPECT_HR(hr, S_OK);
2674         EXPECT_REF(unk, 4);
2675         todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2676         IUnknown_Release(node_typed);
2677         IUnknown_Release(node_typed2);
2678 
2679         /* try invalid IXMLDOM* */
2680         hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2681         EXPECT_HR(hr, E_NOINTERFACE);
2682 
2683         IUnknown_Release(unk);
2684 
2685         EXPECT_REF(node, 1);
2686         hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2687         EXPECT_HR(hr, S_OK);
2688         EXPECT_REF(node, 2);
2689         ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2690 
2691         EXPECT_REF(node, 2);
2692         hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2693         EXPECT_HR(hr, S_OK);
2694         EXPECT_REF(node, 3);
2695 todo_wine {
2696         EXPECT_REF(node_typed, 2);
2697         ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2698 }
2699         IUnknown_Release(node_typed);
2700 
2701         IXMLDOMNode_Release(node2);
2702         IXMLDOMNode_Release(node);
2703 
2704         ptr++;
2705     }
2706 
2707     EXPECT_REF(doc, 1);
2708     ref = IXMLDOMDocument_Release(doc);
2709     ok( ref == 0, "ref %d\n", ref);
2710 
2711     /* check IUnknown after releasing DOM iface */
2712     doc = create_document(&IID_IXMLDOMDocument);
2713     EXPECT_REF(doc, 1);
2714     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2715     EXPECT_HR(hr, S_OK);
2716 todo_wine {
2717     EXPECT_REF(unk, 3);
2718     EXPECT_REF(doc, 1);
2719 }
2720     IXMLDOMDocument_Release(doc);
2721     EXPECT_REF(unk, 1);
2722     IUnknown_Release(unk);
2723 
2724     doc = create_document(&IID_IXMLDOMDocument);
2725 
2726     EXPECT_REF(doc, 1);
2727     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2728     EXPECT_HR(hr, S_OK);
2729 todo_wine {
2730     EXPECT_REF(unk, 3);
2731     EXPECT_REF(doc, 1);
2732 }
2733     IUnknown_Release(unk);
2734 
2735     /* IXMLDOMImplementation */
2736     EXPECT_REF(doc, 1);
2737     hr = IXMLDOMDocument_get_implementation(doc, &impl);
2738     EXPECT_HR(hr, S_OK);
2739     EXPECT_REF(doc, 1);
2740     EXPECT_REF(impl, 1);
2741     hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2742     EXPECT_HR(hr, S_OK);
2743     EXPECT_REF(doc, 1);
2744     EXPECT_REF(impl2, 1);
2745     ok(impl != impl2, "got %p, %p\n", impl, impl2);
2746     IXMLDOMImplementation_Release(impl);
2747     IXMLDOMImplementation_Release(impl2);
2748 
2749     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2750     EXPECT_HR(hr, S_OK);
2751     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2752 
2753     EXPECT_REF(doc, 1);
2754     IXMLDOMDocument_AddRef( doc );
2755     EXPECT_REF(doc, 2);
2756     IXMLDOMDocument_AddRef( doc );
2757     EXPECT_REF(doc, 3);
2758 
2759     IXMLDOMDocument_Release( doc );
2760     IXMLDOMDocument_Release( doc );
2761 
2762     EXPECT_REF(doc, 1);
2763     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2764     EXPECT_HR(hr, S_OK);
2765 todo_wine {
2766     EXPECT_REF(unk, 3);
2767     EXPECT_REF(doc, 1);
2768 }
2769     hr = IXMLDOMDocument_get_documentElement(doc, &element);
2770     EXPECT_HR(hr, S_OK);
2771 todo_wine {
2772     EXPECT_REF(doc, 1);
2773     EXPECT_REF(element, 2);
2774 }
2775     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2776     EXPECT_HR(hr, S_OK);
2777 
2778 todo_wine {
2779     EXPECT_REF(doc, 1);
2780     EXPECT_REF(element, 2);
2781     EXPECT_REF(elem2, 2);
2782 }
2783     IXMLDOMElement_AddRef(element);
2784     todo_wine EXPECT_REF(element, 3);
2785     IXMLDOMElement_Release(element);
2786 
2787     /* get IUnknown from a node doesn't touch node instance refcount */
2788     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2789     EXPECT_HR(hr, S_OK);
2790     EXPECT_REF(element, 2);
2791 todo_wine {
2792     EXPECT_REF(unk, 4);
2793     EXPECT_REF(elem2, 2);
2794 }
2795     hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2796     EXPECT_HR(hr, S_OK);
2797 todo_wine {
2798     EXPECT_REF(unk, 5);
2799     EXPECT_REF(unk2, 5);
2800 }
2801     EXPECT_REF(element, 2);
2802     EXPECT_REF(elem2, 2);
2803 
2804     todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2805     IUnknown_Release(unk);
2806 
2807     /* IUnknown refcount is not affected by node refcount */
2808     todo_wine EXPECT_REF(unk2, 4);
2809     IXMLDOMElement_AddRef(elem2);
2810     todo_wine EXPECT_REF(unk2, 4);
2811     IXMLDOMElement_Release(elem2);
2812 
2813     IXMLDOMElement_Release(elem2);
2814     todo_wine EXPECT_REF(unk2, 3);
2815 
2816     IUnknown_Release(unk2);
2817 
2818     hr = IXMLDOMElement_get_childNodes( element, &node_list );
2819     EXPECT_HR(hr, S_OK);
2820 
2821     todo_wine EXPECT_REF(element, 2);
2822     EXPECT_REF(node_list, 1);
2823 
2824     hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2825     EXPECT_HR(hr, S_OK);
2826     EXPECT_REF(node_list, 1);
2827     EXPECT_REF(node, 1);
2828 
2829     hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2830     EXPECT_HR(hr, S_OK);
2831     EXPECT_REF(node_list, 1);
2832     EXPECT_REF(node2, 1);
2833 
2834     ref = IXMLDOMNode_Release( node );
2835     ok( ref == 0, "ref %d\n", ref );
2836     ref = IXMLDOMNode_Release( node2 );
2837     ok( ref == 0, "ref %d\n", ref );
2838 
2839     ref = IXMLDOMNodeList_Release( node_list );
2840     ok( ref == 0, "ref %d\n", ref );
2841 
2842     ok( node != node2, "node %p node2 %p\n", node, node2 );
2843 
2844     ref = IXMLDOMDocument_Release( doc );
2845     todo_wine ok( ref == 0, "ref %d\n", ref );
2846 
2847     todo_wine EXPECT_REF(element, 2);
2848 
2849     /* IUnknown must be unique however we obtain it */
2850     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2851     EXPECT_HR(hr, S_OK);
2852     EXPECT_REF(element, 2);
2853     hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2854     EXPECT_HR(hr, S_OK);
2855     todo_wine EXPECT_REF(element, 2);
2856     hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2857     EXPECT_HR(hr, S_OK);
2858     todo_wine EXPECT_REF(element, 2);
2859     ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2860     todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2861 
2862     IUnknown_Release( unk2 );
2863     IUnknown_Release( unk );
2864     IXMLDOMNode_Release( node );
2865     todo_wine EXPECT_REF(element, 2);
2866 
2867     IXMLDOMElement_Release( element );
2868 
2869     free_bstrs();
2870 }
2871 
2872 static void test_create(void)
2873 {
2874     static const WCHAR szOne[] = {'1',0};
2875     static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2876     HRESULT r;
2877     VARIANT var;
2878     BSTR str, name;
2879     IXMLDOMDocument *doc;
2880     IXMLDOMElement *element;
2881     IXMLDOMComment *comment;
2882     IXMLDOMText *text;
2883     IXMLDOMCDATASection *cdata;
2884     IXMLDOMNode *root, *node, *child;
2885     IXMLDOMNamedNodeMap *attr_map;
2886     IUnknown *unk;
2887     LONG ref;
2888     LONG num;
2889 
2890     doc = create_document(&IID_IXMLDOMDocument);
2891 
2892     EXPECT_REF(doc, 1);
2893 
2894     /* types not supported for creation */
2895     V_VT(&var) = VT_I1;
2896     V_I1(&var) = NODE_DOCUMENT;
2897     node = (IXMLDOMNode*)0x1;
2898     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2899     ok( r == E_INVALIDARG, "returns %08x\n", r );
2900     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2901 
2902     V_VT(&var) = VT_I1;
2903     V_I1(&var) = NODE_DOCUMENT_TYPE;
2904     node = (IXMLDOMNode*)0x1;
2905     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2906     ok( r == E_INVALIDARG, "returns %08x\n", r );
2907     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2908 
2909     V_VT(&var) = VT_I1;
2910     V_I1(&var) = NODE_ENTITY;
2911     node = (IXMLDOMNode*)0x1;
2912     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2913     ok( r == E_INVALIDARG, "returns %08x\n", r );
2914     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2915 
2916     V_VT(&var) = VT_I1;
2917     V_I1(&var) = NODE_NOTATION;
2918     node = (IXMLDOMNode*)0x1;
2919     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2920     ok( r == E_INVALIDARG, "returns %08x\n", r );
2921     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2922 
2923     /* NODE_COMMENT */
2924     V_VT(&var) = VT_I1;
2925     V_I1(&var) = NODE_COMMENT;
2926     node = NULL;
2927     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2928     ok( r == S_OK, "returns %08x\n", r );
2929     ok( node != NULL, "\n");
2930 
2931     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2932     ok( r == S_OK, "returns %08x\n", r );
2933     IXMLDOMNode_Release(node);
2934 
2935     str = NULL;
2936     r = IXMLDOMComment_get_data(comment, &str);
2937     ok( r == S_OK, "returns %08x\n", r );
2938     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2939     IXMLDOMComment_Release(comment);
2940     SysFreeString(str);
2941 
2942     node = (IXMLDOMNode*)0x1;
2943     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2944     ok( r == S_OK, "returns %08x\n", r );
2945 
2946     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2947     ok( r == S_OK, "returns %08x\n", r );
2948     IXMLDOMNode_Release(node);
2949 
2950     str = NULL;
2951     r = IXMLDOMComment_get_data(comment, &str);
2952     ok( r == S_OK, "returns %08x\n", r );
2953     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2954     IXMLDOMComment_Release(comment);
2955     SysFreeString(str);
2956 
2957     node = (IXMLDOMNode*)0x1;
2958     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2959     ok( r == S_OK, "returns %08x\n", r );
2960 
2961     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2962     ok( r == S_OK, "returns %08x\n", r );
2963     IXMLDOMNode_Release(node);
2964 
2965     str = NULL;
2966     r = IXMLDOMComment_get_data(comment, &str);
2967     ok( r == S_OK, "returns %08x\n", r );
2968     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2969     IXMLDOMComment_Release(comment);
2970     SysFreeString(str);
2971 
2972     /* NODE_TEXT */
2973     V_VT(&var) = VT_I1;
2974     V_I1(&var) = NODE_TEXT;
2975     node = NULL;
2976     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2977     ok( r == S_OK, "returns %08x\n", r );
2978     ok( node != NULL, "\n");
2979 
2980     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2981     ok( r == S_OK, "returns %08x\n", r );
2982     IXMLDOMNode_Release(node);
2983 
2984     str = NULL;
2985     r = IXMLDOMText_get_data(text, &str);
2986     ok( r == S_OK, "returns %08x\n", r );
2987     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2988     IXMLDOMText_Release(text);
2989     SysFreeString(str);
2990 
2991     node = (IXMLDOMNode*)0x1;
2992     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2993     ok( r == S_OK, "returns %08x\n", r );
2994 
2995     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2996     ok( r == S_OK, "returns %08x\n", r );
2997     IXMLDOMNode_Release(node);
2998 
2999     str = NULL;
3000     r = IXMLDOMText_get_data(text, &str);
3001     ok( r == S_OK, "returns %08x\n", r );
3002     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3003     IXMLDOMText_Release(text);
3004     SysFreeString(str);
3005 
3006     node = (IXMLDOMNode*)0x1;
3007     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3008     ok( r == S_OK, "returns %08x\n", r );
3009 
3010     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3011     ok( r == S_OK, "returns %08x\n", r );
3012     IXMLDOMNode_Release(node);
3013 
3014     str = NULL;
3015     r = IXMLDOMText_get_data(text, &str);
3016     ok( r == S_OK, "returns %08x\n", r );
3017     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3018     IXMLDOMText_Release(text);
3019     SysFreeString(str);
3020 
3021     /* NODE_CDATA_SECTION */
3022     V_VT(&var) = VT_I1;
3023     V_I1(&var) = NODE_CDATA_SECTION;
3024     node = NULL;
3025     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3026     ok( r == S_OK, "returns %08x\n", r );
3027     ok( node != NULL, "\n");
3028 
3029     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3030     ok( r == S_OK, "returns %08x\n", r );
3031     IXMLDOMNode_Release(node);
3032 
3033     str = NULL;
3034     r = IXMLDOMCDATASection_get_data(cdata, &str);
3035     ok( r == S_OK, "returns %08x\n", r );
3036     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3037     IXMLDOMCDATASection_Release(cdata);
3038     SysFreeString(str);
3039 
3040     node = (IXMLDOMNode*)0x1;
3041     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3042     ok( r == S_OK, "returns %08x\n", r );
3043 
3044     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3045     ok( r == S_OK, "returns %08x\n", r );
3046     IXMLDOMNode_Release(node);
3047 
3048     str = NULL;
3049     r = IXMLDOMCDATASection_get_data(cdata, &str);
3050     ok( r == S_OK, "returns %08x\n", r );
3051     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3052     IXMLDOMCDATASection_Release(cdata);
3053     SysFreeString(str);
3054 
3055     node = (IXMLDOMNode*)0x1;
3056     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3057     ok( r == S_OK, "returns %08x\n", r );
3058 
3059     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3060     ok( r == S_OK, "returns %08x\n", r );
3061     IXMLDOMNode_Release(node);
3062 
3063     str = NULL;
3064     r = IXMLDOMCDATASection_get_data(cdata, &str);
3065     ok( r == S_OK, "returns %08x\n", r );
3066     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3067     IXMLDOMCDATASection_Release(cdata);
3068     SysFreeString(str);
3069 
3070     /* NODE_ATTRIBUTE */
3071     V_VT(&var) = VT_I1;
3072     V_I1(&var) = NODE_ATTRIBUTE;
3073     node = (IXMLDOMNode*)0x1;
3074     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3075     ok( r == E_FAIL, "returns %08x\n", r );
3076     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3077 
3078     V_VT(&var) = VT_I1;
3079     V_I1(&var) = NODE_ATTRIBUTE;
3080     node = (IXMLDOMNode*)0x1;
3081     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3082     ok( r == E_FAIL, "returns %08x\n", r );
3083     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3084 
3085     V_VT(&var) = VT_I1;
3086     V_I1(&var) = NODE_ATTRIBUTE;
3087     str = SysAllocString( szlc );
3088     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3089     ok( r == S_OK, "returns %08x\n", r );
3090     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3091     SysFreeString(str);
3092 
3093     /* a name is required for attribute, try a BSTR with first null wchar */
3094     V_VT(&var) = VT_I1;
3095     V_I1(&var) = NODE_ATTRIBUTE;
3096     str = SysAllocString( szstr1 );
3097     str[0] = 0;
3098     node = (IXMLDOMNode*)0x1;
3099     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3100     ok( r == E_FAIL, "returns %08x\n", r );
3101     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3102     SysFreeString(str);
3103 
3104     /* NODE_PROCESSING_INSTRUCTION */
3105     V_VT(&var) = VT_I1;
3106     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3107     node = (IXMLDOMNode*)0x1;
3108     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3109     ok( r == E_FAIL, "returns %08x\n", r );
3110     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3111 
3112     V_VT(&var) = VT_I1;
3113     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3114     node = (IXMLDOMNode*)0x1;
3115     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3116     ok( r == E_FAIL, "returns %08x\n", r );
3117     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3118 
3119     V_VT(&var) = VT_I1;
3120     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3121     r = IXMLDOMDocument_createNode( doc, var, _bstr_("pi"), NULL, NULL );
3122     ok( r == E_INVALIDARG, "returns %08x\n", r );
3123 
3124     /* NODE_ENTITY_REFERENCE */
3125     V_VT(&var) = VT_I1;
3126     V_I1(&var) = NODE_ENTITY_REFERENCE;
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_ENTITY_REFERENCE;
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     /* NODE_ELEMENT */
3140     V_VT(&var) = VT_I1;
3141     V_I1(&var) = NODE_ELEMENT;
3142     node = (IXMLDOMNode*)0x1;
3143     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3144     ok( r == E_FAIL, "returns %08x\n", r );
3145     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3146 
3147     V_VT(&var) = VT_I1;
3148     V_I1(&var) = NODE_ELEMENT;
3149     node = (IXMLDOMNode*)0x1;
3150     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3151     ok( r == E_FAIL, "returns %08x\n", r );
3152     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3153 
3154     V_VT(&var) = VT_I1;
3155     V_I1(&var) = NODE_ELEMENT;
3156     str = SysAllocString( szlc );
3157     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3158     ok( r == S_OK, "returns %08x\n", r );
3159     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3160 
3161     V_VT(&var) = VT_I1;
3162     V_I1(&var) = NODE_ELEMENT;
3163     r = IXMLDOMDocument_createNode( doc, var, str, NULL, NULL );
3164     ok( r == E_INVALIDARG, "returns %08x\n", r );
3165 
3166     V_VT(&var) = VT_R4;
3167     V_R4(&var) = NODE_ELEMENT;
3168     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3169     ok( r == S_OK, "returns %08x\n", r );
3170     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3171 
3172     V_VT(&var) = VT_BSTR;
3173     V_BSTR(&var) = SysAllocString( szOne );
3174     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3175     ok( r == S_OK, "returns %08x\n", r );
3176     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3177     VariantClear(&var);
3178 
3179     V_VT(&var) = VT_BSTR;
3180     V_BSTR(&var) = SysAllocString( szOneGarbage );
3181     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3182     ok( r == E_INVALIDARG, "returns %08x\n", r );
3183     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3184     VariantClear(&var);
3185 
3186     V_VT(&var) = VT_I4;
3187     V_I4(&var) = NODE_ELEMENT;
3188     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3189     ok( r == S_OK, "returns %08x\n", r );
3190 
3191     EXPECT_REF(doc, 1);
3192     r = IXMLDOMDocument_appendChild( doc, node, &root );
3193     ok( r == S_OK, "returns %08x\n", r );
3194     ok( node == root, "%p %p\n", node, root );
3195     EXPECT_REF(doc, 1);
3196 
3197     EXPECT_REF(node, 2);
3198 
3199     ref = IXMLDOMNode_Release( node );
3200     ok(ref == 1, "ref %d\n", ref);
3201     SysFreeString( str );
3202 
3203     V_VT(&var) = VT_I4;
3204     V_I4(&var) = NODE_ELEMENT;
3205     str = SysAllocString( szbs );
3206     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3207     ok( r == S_OK, "returns %08x\n", r );
3208     SysFreeString( str );
3209 
3210     EXPECT_REF(node, 1);
3211 
3212     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk );
3213     ok( r == S_OK, "returns %08x\n", r );
3214 
3215     EXPECT_REF(unk, 2);
3216 
3217     V_VT(&var) = VT_EMPTY;
3218     child = NULL;
3219     r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
3220     ok( r == S_OK, "returns %08x\n", r );
3221     ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
3222 
3223     todo_wine EXPECT_REF(unk, 4);
3224 
3225     IXMLDOMNode_Release( child );
3226     IUnknown_Release( unk );
3227 
3228     V_VT(&var) = VT_NULL;
3229     V_DISPATCH(&var) = (IDispatch*)node;
3230     r = IXMLDOMNode_insertBefore( root, node, var, &child );
3231     ok( r == S_OK, "returns %08x\n", r );
3232     ok( node == child, "%p %p\n", node, child );
3233     IXMLDOMNode_Release( child );
3234 
3235     V_VT(&var) = VT_NULL;
3236     V_DISPATCH(&var) = (IDispatch*)node;
3237     r = IXMLDOMNode_insertBefore( root, node, var, NULL );
3238     ok( r == S_OK, "returns %08x\n", r );
3239     IXMLDOMNode_Release( node );
3240 
3241     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (void**)&element );
3242     ok( r == S_OK, "returns %08x\n", r );
3243 
3244     r = IXMLDOMElement_get_attributes( element, &attr_map );
3245     ok( r == S_OK, "returns %08x\n", r );
3246     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3247     ok( r == S_OK, "returns %08x\n", r );
3248     ok( num == 0, "num %d\n", num );
3249     IXMLDOMNamedNodeMap_Release( attr_map );
3250 
3251     V_VT(&var) = VT_BSTR;
3252     V_BSTR(&var) = SysAllocString( szstr1 );
3253     name = SysAllocString( szdl );
3254     r = IXMLDOMElement_setAttribute( element, name, var );
3255     ok( r == S_OK, "returns %08x\n", r );
3256     r = IXMLDOMElement_get_attributes( element, &attr_map );
3257     ok( r == S_OK, "returns %08x\n", r );
3258     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3259     ok( r == S_OK, "returns %08x\n", r );
3260     ok( num == 1, "num %d\n", num );
3261     IXMLDOMNamedNodeMap_Release( attr_map );
3262     VariantClear(&var);
3263 
3264     V_VT(&var) = VT_BSTR;
3265     V_BSTR(&var) = SysAllocString( szstr2 );
3266     r = IXMLDOMElement_setAttribute( element, name, var );
3267     ok( r == S_OK, "returns %08x\n", r );
3268     r = IXMLDOMElement_get_attributes( element, &attr_map );
3269     ok( r == S_OK, "returns %08x\n", r );
3270     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3271     ok( r == S_OK, "returns %08x\n", r );
3272     ok( num == 1, "num %d\n", num );
3273     IXMLDOMNamedNodeMap_Release( attr_map );
3274     VariantClear(&var);
3275     r = IXMLDOMElement_getAttribute( element, name, &var );
3276     ok( r == S_OK, "returns %08x\n", r );
3277     ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
3278     VariantClear(&var);
3279     SysFreeString(name);
3280 
3281     V_VT(&var) = VT_BSTR;
3282     V_BSTR(&var) = SysAllocString( szstr1 );
3283     name = SysAllocString( szlc );
3284     r = IXMLDOMElement_setAttribute( element, name, var );
3285     ok( r == S_OK, "returns %08x\n", r );
3286     r = IXMLDOMElement_get_attributes( element, &attr_map );
3287     ok( r == S_OK, "returns %08x\n", r );
3288     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3289     ok( r == S_OK, "returns %08x\n", r );
3290     ok( num == 2, "num %d\n", num );
3291     IXMLDOMNamedNodeMap_Release( attr_map );
3292     VariantClear(&var);
3293     SysFreeString(name);
3294 
3295     V_VT(&var) = VT_I4;
3296     V_I4(&var) = 10;
3297     name = SysAllocString( szbs );
3298     r = IXMLDOMElement_setAttribute( element, name, var );
3299     ok( r == S_OK, "returns %08x\n", r );
3300     VariantClear(&var);
3301     r = IXMLDOMElement_getAttribute( element, name, &var );
3302     ok( r == S_OK, "returns %08x\n", r );
3303     ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
3304     VariantClear(&var);
3305     SysFreeString(name);
3306 
3307     /* Create an Attribute */
3308     V_VT(&var) = VT_I4;
3309     V_I4(&var) = NODE_ATTRIBUTE;
3310     str = SysAllocString( szAttribute );
3311     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3312     ok( r == S_OK, "returns %08x\n", r );
3313     ok( node != NULL, "node was null\n");
3314     SysFreeString(str);
3315 
3316     IXMLDOMElement_Release( element );
3317     IXMLDOMNode_Release( root );
3318     IXMLDOMDocument_Release( doc );
3319 }
3320 
3321 struct queryresult_t {
3322     const char *query;
3323     const char *result;
3324     int len;
3325 };
3326 
3327 static const struct queryresult_t elementsbytagname[] = {
3328     { "",    "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 },
3329     { "*",   "E2.D1 E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1", 6 },
3330     { "bs",  "E1.E2.D1", 1 },
3331     { "dl",  "", 0 },
3332     { "str1","", 0 },
3333     { NULL }
3334 };
3335 
3336 static void test_getElementsByTagName(void)
3337 {
3338     const struct queryresult_t *ptr = elementsbytagname;
3339     IXMLDOMNodeList *node_list;
3340     IXMLDOMDocument *doc;
3341     IXMLDOMElement *elem;
3342     WCHAR buff[100];
3343     VARIANT_BOOL b;
3344     HRESULT r;
3345     LONG len;
3346     BSTR str;
3347 
3348     doc = create_document(&IID_IXMLDOMDocument);
3349 
3350     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3351     ok( r == S_OK, "loadXML failed\n");
3352     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3353 
3354     /* null arguments cases */
3355     r = IXMLDOMDocument_getElementsByTagName(doc, NULL, &node_list);
3356     ok( r == E_INVALIDARG, "ret %08x\n", r );
3357     r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), NULL);
3358     ok( r == E_INVALIDARG, "ret %08x\n", r );
3359 
3360     while (ptr->query)
3361     {
3362         r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_(ptr->query), &node_list);
3363         ok(r == S_OK, "ret %08x\n", r);
3364         r = IXMLDOMNodeList_get_length(node_list, &len);
3365         ok(r == S_OK, "ret %08x\n", r);
3366         ok(len == ptr->len, "%s: got len %d, expected %d\n", ptr->query, len, ptr->len);
3367         expect_list_and_release(node_list, ptr->result);
3368 
3369         free_bstrs();
3370         ptr++;
3371     }
3372 
3373     /* broken query BSTR */
3374     memcpy(&buff[2], szstar, sizeof(szstar));
3375     /* just a big length */
3376     *(DWORD*)buff = 0xf0f0;
3377     r = IXMLDOMDocument_getElementsByTagName(doc, &buff[2], &node_list);
3378     ok( r == S_OK, "ret %08x\n", r );
3379     r = IXMLDOMNodeList_get_length( node_list, &len );
3380     ok( r == S_OK, "ret %08x\n", r );
3381     ok( len == 6, "len %d\n", len );
3382     IXMLDOMNodeList_Release( node_list );
3383 
3384     /* test for element */
3385     r = IXMLDOMDocument_get_documentElement(doc, &elem);
3386     ok( r == S_OK, "ret %08x\n", r );
3387 
3388     str = SysAllocString( szstar );
3389 
3390     /* null arguments cases */
3391     r = IXMLDOMElement_getElementsByTagName(elem, NULL, &node_list);
3392     ok( r == E_INVALIDARG, "ret %08x\n", r );
3393     r = IXMLDOMElement_getElementsByTagName(elem, str, NULL);
3394     ok( r == E_INVALIDARG, "ret %08x\n", r );
3395 
3396     r = IXMLDOMElement_getElementsByTagName(elem, str, &node_list);
3397     ok( r == S_OK, "ret %08x\n", r );
3398     r = IXMLDOMNodeList_get_length( node_list, &len );
3399     ok( r == S_OK, "ret %08x\n", r );
3400     ok( len == 5, "len %d\n", len );
3401     expect_list_and_release(node_list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1");
3402     SysFreeString( str );
3403 
3404     /* broken query BSTR */
3405     memcpy(&buff[2], szstar, sizeof(szstar));
3406     /* just a big length */
3407     *(DWORD*)buff = 0xf0f0;
3408     r = IXMLDOMElement_getElementsByTagName(elem, &buff[2], &node_list);
3409     ok( r == S_OK, "ret %08x\n", r );
3410     r = IXMLDOMNodeList_get_length( node_list, &len );
3411     ok( r == S_OK, "ret %08x\n", r );
3412     ok( len == 5, "len %d\n", len );
3413     IXMLDOMNodeList_Release( node_list );
3414 
3415     IXMLDOMElement_Release(elem);
3416 
3417     IXMLDOMDocument_Release( doc );
3418 
3419     free_bstrs();
3420 }
3421 
3422 static void test_get_text(void)
3423 {
3424     HRESULT r;
3425     BSTR str;
3426     VARIANT_BOOL b;
3427     IXMLDOMDocument *doc;
3428     IXMLDOMNode *node, *node2, *node3;
3429     IXMLDOMNode *nodeRoot;
3430     IXMLDOMNodeList *node_list;
3431     IXMLDOMNamedNodeMap *node_map;
3432     LONG len;
3433 
3434     doc = create_document(&IID_IXMLDOMDocument);
3435 
3436     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3437     ok( r == S_OK, "loadXML failed\n");
3438     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3439 
3440     str = SysAllocString( szbs );
3441     r = IXMLDOMDocument_getElementsByTagName( doc, str, &node_list );
3442     ok( r == S_OK, "ret %08x\n", r );
3443     SysFreeString(str);
3444 
3445     /* Test to get all child node text. */
3446     r = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&nodeRoot);
3447     ok( r == S_OK, "ret %08x\n", r );
3448     if(r == S_OK)
3449     {
3450         r = IXMLDOMNode_get_text( nodeRoot, &str );
3451         ok( r == S_OK, "ret %08x\n", r );
3452         expect_bstr_eq_and_free(str, "fn1.txt\n \nfn2.txt\n \nf1");
3453 
3454         IXMLDOMNode_Release(nodeRoot);
3455     }
3456 
3457     r = IXMLDOMNodeList_get_length( node_list, NULL );
3458     ok( r == E_INVALIDARG, "ret %08x\n", r );
3459 
3460     r = IXMLDOMNodeList_get_length( node_list, &len );
3461     ok( r == S_OK, "ret %08x\n", r );
3462     ok( len == 1, "expect 1 got %d\n", len );
3463 
3464     r = IXMLDOMNodeList_get_item( node_list, 0, NULL );
3465     ok( r == E_INVALIDARG, "ret %08x\n", r );
3466 
3467     r = IXMLDOMNodeList_nextNode( node_list, NULL );
3468     ok( r == E_INVALIDARG, "ret %08x\n", r );
3469 
3470     r = IXMLDOMNodeList_get_item( node_list, 0, &node );
3471     ok( r == S_OK, "ret %08x\n", r );
3472     IXMLDOMNodeList_Release( node_list );
3473 
3474     /* Invalid output parameter*/
3475     r = IXMLDOMNode_get_text( node, NULL );
3476     ok( r == E_INVALIDARG, "ret %08x\n", r );
3477 
3478     r = IXMLDOMNode_get_text( node, &str );
3479     ok( r == S_OK, "ret %08x\n", r );
3480     ok( !memcmp(str, szfn1_txt, lstrlenW(szfn1_txt) ), "wrong string\n" );
3481     SysFreeString(str);
3482 
3483     r = IXMLDOMNode_get_attributes( node, &node_map );
3484     ok( r == S_OK, "ret %08x\n", r );
3485 
3486     str = SysAllocString( szvr );
3487     r = IXMLDOMNamedNodeMap_getNamedItem( node_map, str, &node2 );
3488     ok( r == S_OK, "ret %08x\n", r );
3489     SysFreeString(str);
3490 
3491     r = IXMLDOMNode_get_text( node2, &str );
3492     ok( r == S_OK, "ret %08x\n", r );
3493     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3494     SysFreeString(str);
3495 
3496     r = IXMLDOMNode_get_firstChild( node2, &node3 );
3497     ok( r == S_OK, "ret %08x\n", r );
3498 
3499     r = IXMLDOMNode_get_text( node3, &str );
3500     ok( r == S_OK, "ret %08x\n", r );
3501     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3502     SysFreeString(str);
3503 
3504 
3505     IXMLDOMNode_Release( node3 );
3506     IXMLDOMNode_Release( node2 );
3507     IXMLDOMNamedNodeMap_Release( node_map );
3508     IXMLDOMNode_Release( node );
3509     IXMLDOMDocument_Release( doc );
3510 
3511     free_bstrs();
3512 }
3513 
3514 #ifdef __REACTOS__
3515 /*
3516  * This function is to display that xmlnodelist_QueryInterface
3517  * generates SEGV for these conditions, and once fixed make sure
3518  * it never does it again.
3519  */
3520 static void verify_nodelist_query_interface(IXMLDOMNodeList *node_list)
3521 {
3522     HRESULT hr;
3523     /*
3524      * NOTE: The following calls are supposed to test wine's
3525      * xmlnodelist_QueryInterface behaving properly.
3526      * While we should be able to expect E_POINTER (due to the NULL pointer),
3527      * it seems MS' own implementation(s) violate the spec and return
3528      * E_INVALIDARG. To not get cought be a potentially correct implementation
3529      * in the future, we check for NOT S_OK.
3530      */
3531     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, NULL);
3532     EXPECT_NOT_HR(hr, S_OK);
3533     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatch, NULL);
3534     EXPECT_NOT_HR(hr, S_OK);
3535     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IXMLDOMNodeList, NULL);
3536     EXPECT_NOT_HR(hr, S_OK);
3537 }
3538 #endif
3539 
3540 static void test_get_childNodes(void)
3541 {
3542     IXMLDOMNodeList *node_list, *node_list2;
3543     IEnumVARIANT *enum1, *enum2, *enum3;
3544     VARIANT_BOOL b;
3545     IXMLDOMDocument *doc;
3546     IXMLDOMNode *node, *node2;
3547     IXMLDOMElement *element;
3548     IUnknown *unk1, *unk2;
3549     HRESULT hr;
3550     VARIANT v;
3551     BSTR str;
3552     LONG len;
3553 
3554     doc = create_document(&IID_IXMLDOMDocument);
3555 
3556     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3557     EXPECT_HR(hr, S_OK);
3558     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3559 
3560     hr = IXMLDOMDocument_get_documentElement( doc, &element );
3561     EXPECT_HR(hr, S_OK);
3562 
3563     hr = IXMLDOMElement_get_childNodes( element, &node_list );
3564     EXPECT_HR(hr, S_OK);
3565 
3566 #ifdef __REACTOS__
3567     verify_nodelist_query_interface(node_list);
3568 #endif
3569 
3570     hr = IXMLDOMNodeList_get_length( node_list, &len );
3571     EXPECT_HR(hr, S_OK);
3572     ok( len == 4, "len %d\n", len);
3573 
3574     /* refcount tests for IEnumVARIANT support */
3575     EXPECT_REF(node_list, 1);
3576     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1);
3577     EXPECT_HR(hr, S_OK);
3578     EXPECT_REF(node_list, 1);
3579     EXPECT_REF(enum1, 2);
3580 
3581     EXPECT_REF(node_list, 1);
3582     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum2);
3583     EXPECT_HR(hr, S_OK);
3584     EXPECT_REF(node_list, 1);
3585     ok(enum2 == enum1, "got %p, %p\n", enum2, enum1);
3586     IEnumVARIANT_Release(enum2);
3587 
3588     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3589     EXPECT_HR(hr, S_OK);
3590     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
3591     EXPECT_HR(hr, S_OK);
3592     EXPECT_REF(node_list, 3);
3593     EXPECT_REF(enum1, 2);
3594     ok(unk1 == unk2, "got %p, %p\n", unk1, unk2);
3595     IUnknown_Release(unk1);
3596     IUnknown_Release(unk2);
3597 
3598     EXPECT_REF(node_list, 1);
3599     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum2);
3600     EXPECT_HR(hr, S_OK);
3601     EXPECT_REF(node_list, 2);
3602     EXPECT_REF(enum2, 1);
3603     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
3604 
3605     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
3606     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3607     EXPECT_HR(hr, S_OK);
3608     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
3609     EXPECT_HR(hr, S_OK);
3610     EXPECT_REF(node_list, 3);
3611     EXPECT_REF(enum2, 2);
3612     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
3613     IUnknown_Release(unk1);
3614     IUnknown_Release(unk2);
3615 
3616     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum3);
3617     EXPECT_HR(hr, S_OK);
3618     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
3619     IEnumVARIANT_Release(enum3);
3620     IEnumVARIANT_Release(enum2);
3621 
3622     /* iteration tests */
3623     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
3624     EXPECT_HR(hr, S_OK);
3625     hr = IXMLDOMNode_get_nodeName(node, &str);
3626     EXPECT_HR(hr, S_OK);
3627     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3628     SysFreeString(str);
3629     IXMLDOMNode_Release(node);
3630 
3631     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3632     EXPECT_HR(hr, S_OK);
3633     hr = IXMLDOMNode_get_nodeName(node, &str);
3634     EXPECT_HR(hr, S_OK);
3635     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3636     SysFreeString(str);
3637     IXMLDOMNode_Release(node);
3638 
3639     V_VT(&v) = VT_EMPTY;
3640     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
3641     EXPECT_HR(hr, S_OK);
3642     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
3643     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&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 node name %s\n", wine_dbgstr_w(str));
3648     SysFreeString(str);
3649     IXMLDOMNode_Release(node);
3650     VariantClear(&v);
3651 
3652     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3653     EXPECT_HR(hr, S_OK);
3654     hr = IXMLDOMNode_get_nodeName(node, &str);
3655     EXPECT_HR(hr, S_OK);
3656     ok(!lstrcmpW(str, _bstr_("pr")), "got %s\n", wine_dbgstr_w(str));
3657     SysFreeString(str);
3658     IXMLDOMNode_Release(node);
3659 
3660     IEnumVARIANT_Release(enum1);
3661 
3662     hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
3663     EXPECT_HR(hr, S_OK);
3664 
3665     hr = IXMLDOMNode_get_childNodes( node, &node_list2 );
3666     EXPECT_HR(hr, S_OK);
3667 
3668     hr = IXMLDOMNodeList_get_length( node_list2, &len );
3669     EXPECT_HR(hr, S_OK);
3670     ok( len == 0, "len %d\n", len);
3671 
3672     hr = IXMLDOMNodeList_get_item( node_list2, 0, &node2);
3673     EXPECT_HR(hr, S_FALSE);
3674 
3675     IXMLDOMNodeList_Release( node_list2 );
3676     IXMLDOMNode_Release( node );
3677     IXMLDOMNodeList_Release( node_list );
3678     IXMLDOMElement_Release( element );
3679 
3680     /* test for children of <?xml ..?> node */
3681     hr = IXMLDOMDocument_get_firstChild(doc, &node);
3682     EXPECT_HR(hr, S_OK);
3683 
3684     str = NULL;
3685     hr = IXMLDOMNode_get_nodeName(node, &str);
3686     EXPECT_HR(hr, S_OK);
3687     ok(!lstrcmpW(str, _bstr_("xml")), "got %s\n", wine_dbgstr_w(str));
3688     SysFreeString(str);
3689 
3690     /* it returns empty but valid node list */
3691     node_list = (void*)0xdeadbeef;
3692     hr = IXMLDOMNode_get_childNodes(node, &node_list);
3693     EXPECT_HR(hr, S_OK);
3694 
3695     len = -1;
3696     hr = IXMLDOMNodeList_get_length(node_list, &len);
3697     EXPECT_HR(hr, S_OK);
3698     ok(len == 0, "got %d\n", len);
3699 
3700     IXMLDOMNodeList_Release( node_list );
3701     IXMLDOMNode_Release(node);
3702 
3703     IXMLDOMDocument_Release( doc );
3704     free_bstrs();
3705 }
3706 
3707 static void test_get_firstChild(void)
3708 {
3709     static const WCHAR xmlW[] = {'x','m','l',0};
3710     IXMLDOMDocument *doc;
3711     IXMLDOMNode *node;
3712     VARIANT_BOOL b;
3713     HRESULT r;
3714     BSTR str;
3715 
3716     doc = create_document(&IID_IXMLDOMDocument);
3717 
3718     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3719     ok( r == S_OK, "loadXML failed\n");
3720     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3721 
3722     r = IXMLDOMDocument_get_firstChild( doc, &node );
3723     ok( r == S_OK, "ret %08x\n", r);
3724 
3725     r = IXMLDOMNode_get_nodeName( node, &str );
3726     ok( r == S_OK, "ret %08x\n", r);
3727 
3728     ok(!lstrcmpW(str, xmlW), "expected \"xml\" node name, got %s\n", wine_dbgstr_w(str));
3729 
3730     SysFreeString(str);
3731     IXMLDOMNode_Release( node );
3732     IXMLDOMDocument_Release( doc );
3733 
3734     free_bstrs();
3735 }
3736 
3737 static void test_get_lastChild(void)
3738 {
3739     static const WCHAR lcW[] = {'l','c',0};
3740     static const WCHAR foW[] = {'f','o',0};
3741     IXMLDOMDocument *doc;
3742     IXMLDOMNode *node, *child;
3743     VARIANT_BOOL b;
3744     HRESULT r;
3745     BSTR str;
3746 
3747     doc = create_document(&IID_IXMLDOMDocument);
3748 
3749     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3750     ok( r == S_OK, "loadXML failed\n");
3751     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3752 
3753     r = IXMLDOMDocument_get_lastChild( doc, &node );
3754     ok( r == S_OK, "ret %08x\n", r);
3755 
3756     r = IXMLDOMNode_get_nodeName( node, &str );
3757     ok( r == S_OK, "ret %08x\n", r);
3758 
3759     ok(memcmp(str, lcW, sizeof(lcW)) == 0, "expected \"lc\" node name\n");
3760     SysFreeString(str);
3761 
3762     r = IXMLDOMNode_get_lastChild( node, &child );
3763     ok( r == S_OK, "ret %08x\n", r);
3764 
3765     r = IXMLDOMNode_get_nodeName( child, &str );
3766     ok( r == S_OK, "ret %08x\n", r);
3767 
3768     ok(memcmp(str, foW, sizeof(foW)) == 0, "expected \"fo\" node name\n");
3769     SysFreeString(str);
3770 
3771     IXMLDOMNode_Release( child );
3772     IXMLDOMNode_Release( node );
3773     IXMLDOMDocument_Release( doc );
3774 
3775     free_bstrs();
3776 }
3777 
3778 static void test_removeChild(void)
3779 {
3780     HRESULT r;
3781     VARIANT_BOOL b;
3782     IXMLDOMDocument *doc;
3783     IXMLDOMElement *element, *lc_element;
3784     IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node, *lc_node;
3785     IXMLDOMNodeList *root_list, *fo_list;
3786 
3787     doc = create_document(&IID_IXMLDOMDocument);
3788 
3789     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3790     ok( r == S_OK, "loadXML failed\n");
3791     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3792 
3793     r = IXMLDOMDocument_get_documentElement( doc, &element );
3794     ok( r == S_OK, "ret %08x\n", r);
3795     todo_wine EXPECT_REF(element, 2);
3796 
3797     r = IXMLDOMElement_get_childNodes( element, &root_list );
3798     ok( r == S_OK, "ret %08x\n", r);
3799     EXPECT_REF(root_list, 1);
3800 
3801     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3802     ok( r == S_OK, "ret %08x\n", r);
3803     EXPECT_REF(fo_node, 1);
3804 
3805     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3806     ok( r == S_OK, "ret %08x\n", r);
3807     EXPECT_REF(fo_list, 1);
3808 
3809     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3810     ok( r == S_OK, "ret %08x\n", r);
3811     EXPECT_REF(ba_node, 1);
3812 
3813     /* invalid parameter: NULL ptr */
3814     removed_node = (void*)0xdeadbeef;
3815     r = IXMLDOMElement_removeChild( element, NULL, &removed_node );
3816     ok( r == E_INVALIDARG, "ret %08x\n", r );
3817     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3818 
3819     /* ba_node is a descendant of element, but not a direct child. */
3820     removed_node = (void*)0xdeadbeef;
3821     EXPECT_REF(ba_node, 1);
3822     EXPECT_CHILDREN(fo_node);
3823     r = IXMLDOMElement_removeChild( element, ba_node, &removed_node );
3824     ok( r == E_INVALIDARG, "ret %08x\n", r );
3825     ok( removed_node == NULL, "%p\n", removed_node );
3826     EXPECT_REF(ba_node, 1);
3827     EXPECT_CHILDREN(fo_node);
3828 
3829     EXPECT_REF(ba_node, 1);
3830     EXPECT_REF(fo_node, 1);
3831     r = IXMLDOMElement_removeChild( element, fo_node, &removed_node );
3832     ok( r == S_OK, "ret %08x\n", r);
3833     ok( fo_node == removed_node, "node %p node2 %p\n", fo_node, removed_node );
3834     EXPECT_REF(fo_node, 2);
3835     EXPECT_REF(ba_node, 1);
3836 
3837     /* try removing already removed child */
3838     temp_node = (void*)0xdeadbeef;
3839     r = IXMLDOMElement_removeChild( element, fo_node, &temp_node );
3840     ok( r == E_INVALIDARG, "ret %08x\n", r);
3841     ok( temp_node == NULL, "%p\n", temp_node );
3842     IXMLDOMNode_Release( fo_node );
3843 
3844     /* the removed node has no parent anymore */
3845     r = IXMLDOMNode_get_parentNode( removed_node, &temp_node );
3846     ok( r == S_FALSE, "ret %08x\n", r);
3847     ok( temp_node == NULL, "%p\n", temp_node );
3848 
3849     IXMLDOMNode_Release( removed_node );
3850     IXMLDOMNode_Release( ba_node );
3851     IXMLDOMNodeList_Release( fo_list );
3852 
3853     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3854     ok( r == S_OK, "ret %08x\n", r);
3855 
3856     r = IXMLDOMNode_QueryInterface( lc_node, &IID_IXMLDOMElement, (void**)&lc_element );
3857     ok( r == S_OK, "ret %08x\n", r);
3858 
3859     /* MS quirk: passing wrong interface pointer works, too */
3860     r = IXMLDOMElement_removeChild( element, (IXMLDOMNode*)lc_element, NULL );
3861     ok( r == S_OK, "ret %08x\n", r);
3862     IXMLDOMElement_Release( lc_element );
3863 
3864     temp_node = (void*)0xdeadbeef;
3865     r = IXMLDOMNode_get_parentNode( lc_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( lc_node );
3870     IXMLDOMNodeList_Release( root_list );
3871     IXMLDOMElement_Release( element );
3872     IXMLDOMDocument_Release( doc );
3873 
3874     free_bstrs();
3875 }
3876 
3877 static void test_replaceChild(void)
3878 {
3879     HRESULT r;
3880     VARIANT_BOOL b;
3881     IXMLDOMDocument *doc;
3882     IXMLDOMElement *element, *ba_element;
3883     IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
3884     IXMLDOMNodeList *root_list, *fo_list;
3885     IUnknown * unk1, *unk2;
3886     LONG len;
3887 
3888     doc = create_document(&IID_IXMLDOMDocument);
3889 
3890     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3891     ok( r == S_OK, "loadXML failed\n");
3892     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3893 
3894     r = IXMLDOMDocument_get_documentElement( doc, &element );
3895     ok( r == S_OK, "ret %08x\n", r);
3896 
3897     r = IXMLDOMElement_get_childNodes( element, &root_list );
3898     ok( r == S_OK, "ret %08x\n", r);
3899 
3900     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3901     ok( r == S_OK, "ret %08x\n", r);
3902 
3903     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3904     ok( r == S_OK, "ret %08x\n", r);
3905 
3906     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3907     ok( r == S_OK, "ret %08x\n", r);
3908 
3909     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3910     ok( r == S_OK, "ret %08x\n", r);
3911 
3912     IXMLDOMNodeList_Release( fo_list );
3913 
3914     /* invalid parameter: NULL ptr for element to remove */
3915     removed_node = (void*)0xdeadbeef;
3916     r = IXMLDOMElement_replaceChild( element, ba_node, NULL, &removed_node );
3917     ok( r == E_INVALIDARG, "ret %08x\n", r );
3918     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3919 
3920     /* invalid parameter: NULL for replacement element. (Sic!) */
3921     removed_node = (void*)0xdeadbeef;
3922     r = IXMLDOMElement_replaceChild( element, NULL, fo_node, &removed_node );
3923     ok( r == E_INVALIDARG, "ret %08x\n", r );
3924     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3925 
3926     /* invalid parameter: OldNode is not a child */
3927     removed_node = (void*)0xdeadbeef;
3928     r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
3929     ok( r == E_INVALIDARG, "ret %08x\n", r );
3930     ok( removed_node == NULL, "%p\n", removed_node );
3931     IXMLDOMNode_Release( lc_node );
3932 
3933     /* invalid parameter: would create loop */
3934     removed_node = (void*)0xdeadbeef;
3935     r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
3936     ok( r == E_FAIL, "ret %08x\n", r );
3937     ok( removed_node == NULL, "%p\n", removed_node );
3938 
3939     r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
3940     ok( r == S_OK, "ret %08x\n", r );
3941 
3942     r = IXMLDOMNodeList_get_item( root_list, 3, &temp_node );
3943     ok( r == S_OK, "ret %08x\n", r );
3944 
3945     /* ba_node and temp_node refer to the same node, yet they
3946        are different interface pointers */
3947     ok( ba_node != temp_node, "ba_node %p temp_node %p\n", ba_node, temp_node);
3948     r = IXMLDOMNode_QueryInterface( temp_node, &IID_IUnknown, (void**)&unk1);
3949     ok( r == S_OK, "ret %08x\n", r );
3950     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IUnknown, (void**)&unk2);
3951     ok( r == S_OK, "ret %08x\n", r );
3952     todo_wine ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
3953 
3954     IUnknown_Release( unk1 );
3955     IUnknown_Release( unk2 );
3956 
3957     /* ba_node should have been removed from below fo_node */
3958     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3959     ok( r == S_OK, "ret %08x\n", r );
3960 
3961     /* MS quirk: replaceChild also accepts elements instead of nodes */
3962     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IXMLDOMElement, (void**)&ba_element);
3963     ok( r == S_OK, "ret %08x\n", r );
3964     EXPECT_REF(ba_element, 2);
3965 
3966     removed_node = NULL;
3967     r = IXMLDOMElement_replaceChild( element, ba_node, (IXMLDOMNode*)ba_element, &removed_node );
3968     ok( r == S_OK, "ret %08x\n", r );
3969     ok( removed_node != NULL, "got %p\n", removed_node);
3970     EXPECT_REF(ba_element, 3);
3971     IXMLDOMElement_Release( ba_element );
3972 
3973     r = IXMLDOMNodeList_get_length( fo_list, &len);
3974     ok( r == S_OK, "ret %08x\n", r );
3975     ok( len == 0, "len %d\n", len);
3976 
3977     IXMLDOMNodeList_Release( fo_list );
3978 
3979     IXMLDOMNode_Release(ba_node);
3980     IXMLDOMNode_Release(fo_node);
3981     IXMLDOMNode_Release(temp_node);
3982     IXMLDOMNodeList_Release( root_list );
3983     IXMLDOMElement_Release( element );
3984     IXMLDOMDocument_Release( doc );
3985 
3986     free_bstrs();
3987 }
3988 
3989 static void test_removeNamedItem(void)
3990 {
3991     IXMLDOMDocument *doc;
3992     IXMLDOMElement *element;
3993     IXMLDOMNode *pr_node, *removed_node, *removed_node2;
3994     IXMLDOMNodeList *root_list;
3995     IXMLDOMNamedNodeMap * pr_attrs;
3996     VARIANT_BOOL b;
3997     BSTR str;
3998     LONG len;
3999     HRESULT r;
4000 
4001     doc = create_document(&IID_IXMLDOMDocument);
4002 
4003     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
4004     ok( r == S_OK, "loadXML failed\n");
4005     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4006 
4007     r = IXMLDOMDocument_get_documentElement( doc, &element );
4008     ok( r == S_OK, "ret %08x\n", r);
4009 
4010     r = IXMLDOMElement_get_childNodes( element, &root_list );
4011     ok( r == S_OK, "ret %08x\n", r);
4012 
4013     r = IXMLDOMNodeList_get_item( root_list, 1, &pr_node );
4014     ok( r == S_OK, "ret %08x\n", r);
4015 
4016     r = IXMLDOMNode_get_attributes( pr_node, &pr_attrs );
4017     ok( r == S_OK, "ret %08x\n", r);
4018 
4019     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4020     ok( r == S_OK, "ret %08x\n", r);
4021     ok( len == 3, "length %d\n", len);
4022 
4023     removed_node = (void*)0xdeadbeef;
4024     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, NULL, &removed_node);
4025     ok ( r == E_INVALIDARG, "ret %08x\n", r);
4026     ok ( removed_node == (void*)0xdeadbeef, "got %p\n", removed_node);
4027 
4028     removed_node = (void*)0xdeadbeef;
4029     str = SysAllocString(szvr);
4030     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node);
4031     ok ( r == S_OK, "ret %08x\n", r);
4032 
4033     removed_node2 = (void*)0xdeadbeef;
4034     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node2);
4035     ok ( r == S_FALSE, "ret %08x\n", r);
4036     ok ( removed_node2 == NULL, "got %p\n", removed_node2 );
4037 
4038     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4039     ok( r == S_OK, "ret %08x\n", r);
4040     ok( len == 2, "length %d\n", len);
4041 
4042     r = IXMLDOMNamedNodeMap_setNamedItem( pr_attrs, removed_node, NULL);
4043     ok ( r == S_OK, "ret %08x\n", r);
4044     IXMLDOMNode_Release(removed_node);
4045 
4046     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4047     ok( r == S_OK, "ret %08x\n", r);
4048     ok( len == 3, "length %d\n", len);
4049 
4050     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4051     ok ( r == S_OK, "ret %08x\n", r);
4052 
4053     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4054     ok( r == S_OK, "ret %08x\n", r);
4055     ok( len == 2, "length %d\n", len);
4056 
4057     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4058     ok ( r == S_FALSE, "ret %08x\n", r);
4059 
4060     SysFreeString(str);
4061 
4062     IXMLDOMNamedNodeMap_Release( pr_attrs );
4063     IXMLDOMNode_Release( pr_node );
4064     IXMLDOMNodeList_Release( root_list );
4065     IXMLDOMElement_Release( element );
4066     IXMLDOMDocument_Release( doc );
4067 
4068     free_bstrs();
4069 }
4070 
4071 #define test_IObjectSafety_set(p, r, r2, s, m, e, e2) _test_IObjectSafety_set(__LINE__,p, r, r2, s, m, e, e2)
4072 static void _test_IObjectSafety_set(unsigned line, IObjectSafety *safety, HRESULT result,
4073                                     HRESULT result2, DWORD set, DWORD mask, DWORD expected,
4074                                     DWORD expected2)
4075 {
4076     DWORD enabled, supported;
4077     HRESULT hr;
4078 
4079     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL, set, mask);
4080     if (result == result2)
4081         ok_(__FILE__,line)(hr == result, "SetInterfaceSafetyOptions: expected %08x, returned %08x\n", result, hr );
4082     else
4083         ok_(__FILE__,line)(broken(hr == result) || hr == result2,
4084            "SetInterfaceSafetyOptions: expected %08x, got %08x\n", result2, hr );
4085 
4086     supported = enabled = 0xCAFECAFE;
4087     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4088     ok(hr == S_OK, "ret %08x\n", hr );
4089     if (expected == expected2)
4090         ok_(__FILE__,line)(enabled == expected, "Expected %08x, got %08x\n", expected, enabled);
4091     else
4092         ok_(__FILE__,line)(broken(enabled == expected) || enabled == expected2,
4093            "Expected %08x, got %08x\n", expected2, enabled);
4094 
4095     /* reset the safety options */
4096 
4097     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4098             INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER,
4099             0);
4100     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4101 
4102     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4103     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4104     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4105 }
4106 
4107 #define test_IObjectSafety_common(s) _test_IObjectSafety_common(__LINE__,s)
4108 static void _test_IObjectSafety_common(unsigned line, IObjectSafety *safety)
4109 {
4110     DWORD enabled = 0, supported = 0;
4111     HRESULT hr;
4112 
4113     /* get */
4114     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, NULL, &enabled);
4115     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4116     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, NULL);
4117     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4118 
4119     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4120     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4121     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4122        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4123         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4124              "got %08x\n", supported);
4125     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4126 
4127     /* set -- individual flags */
4128 
4129     test_IObjectSafety_set(safety, S_OK, S_OK,
4130         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4131         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4132 
4133     test_IObjectSafety_set(safety, S_OK, S_OK,
4134         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA,
4135         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA);
4136 
4137     test_IObjectSafety_set(safety, S_OK, S_OK,
4138         INTERFACE_USES_SECURITY_MANAGER, INTERFACE_USES_SECURITY_MANAGER,
4139         0, INTERFACE_USES_SECURITY_MANAGER /* msxml3 SP8+ */);
4140 
4141     /* set INTERFACE_USES_DISPEX  */
4142 
4143     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4144         INTERFACE_USES_DISPEX, INTERFACE_USES_DISPEX,
4145         0, 0);
4146 
4147     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4148         INTERFACE_USES_DISPEX, 0,
4149         0, 0);
4150 
4151     test_IObjectSafety_set(safety, S_OK, S_OK /* msxml3 SP8+ */,
4152         0, INTERFACE_USES_DISPEX,
4153         0, 0);
4154 
4155     /* set option masking */
4156 
4157     test_IObjectSafety_set(safety, S_OK, S_OK,
4158         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4159         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4160         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4161         INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4162 
4163     test_IObjectSafety_set(safety, S_OK, S_OK,
4164         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4165         INTERFACESAFE_FOR_UNTRUSTED_DATA,
4166         INTERFACESAFE_FOR_UNTRUSTED_DATA,
4167         INTERFACESAFE_FOR_UNTRUSTED_DATA);
4168 
4169     test_IObjectSafety_set(safety, S_OK, S_OK,
4170         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4171         INTERFACE_USES_SECURITY_MANAGER,
4172         0,
4173         0);
4174 
4175     /* set -- inheriting previous settings */
4176 
4177     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4178                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4179                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4180     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4181     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4182     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4183     ok_(__FILE__,line)(enabled == INTERFACESAFE_FOR_UNTRUSTED_CALLER, "Expected INTERFACESAFE_FOR_UNTRUSTED_CALLER got %08x\n", enabled);
4184     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4185        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4186         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4187              "got %08x\n", supported);
4188 
4189     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4190                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA,
4191                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA);
4192     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4193     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4194     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4195     ok_(__FILE__,line)(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_DATA) ||
4196                        enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA),
4197                        "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) got %08x\n", enabled);
4198     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4199        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4200         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4201              "got %08x\n", supported);
4202 }
4203 
4204 static void test_IXMLDOMDocument2(void)
4205 {
4206     static const WCHAR emptyW[] = {0};
4207     IXMLDOMDocument2 *doc2, *dtddoc2;
4208     IXMLDOMDocument *doc;
4209     IXMLDOMParseError* err;
4210     IDispatchEx *dispex;
4211     VARIANT_BOOL b;
4212     VARIANT var;
4213     HRESULT r;
4214     LONG res;
4215 
4216     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4217 
4218     doc = create_document(&IID_IXMLDOMDocument);
4219     dtddoc2 = create_document(&IID_IXMLDOMDocument2);
4220 
4221     r = IXMLDOMDocument_QueryInterface( doc, &IID_IXMLDOMDocument2, (void**)&doc2 );
4222     ok( r == S_OK, "ret %08x\n", r );
4223     ok( doc == (IXMLDOMDocument*)doc2, "interfaces differ\n");
4224 
4225     ole_expect(IXMLDOMDocument2_get_readyState(doc2, NULL), E_INVALIDARG);
4226     ole_check(IXMLDOMDocument2_get_readyState(doc2, &res));
4227     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4228 
4229     err = NULL;
4230     ole_expect(IXMLDOMDocument2_validate(doc2, NULL), S_FALSE);
4231     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4232     ok(err != NULL, "expected a pointer\n");
4233     if (err)
4234     {
4235         res = 0;
4236         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4237         /* XML_E_NOTWF */
4238         ok(res == E_XML_NOTWF, "got %08x\n", res);
4239         IXMLDOMParseError_Release(err);
4240     }
4241 
4242     r = IXMLDOMDocument2_loadXML( doc2, _bstr_(complete4A), &b );
4243     ok( r == S_OK, "loadXML failed\n");
4244     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4245 
4246     ole_check(IXMLDOMDocument_get_readyState(doc, &res));
4247     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4248 
4249     err = NULL;
4250     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4251     ok(err != NULL, "expected a pointer\n");
4252     if (err)
4253     {
4254         res = 0;
4255         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4256         /* XML_E_NODTD */
4257         ok(res == E_XML_NODTD, "got %08x\n", res);
4258         IXMLDOMParseError_Release(err);
4259     }
4260 
4261     r = IXMLDOMDocument_QueryInterface( doc, &IID_IDispatchEx, (void**)&dispex );
4262     ok( r == S_OK, "ret %08x\n", r );
4263     if(r == S_OK)
4264     {
4265         IDispatchEx_Release(dispex);
4266     }
4267 
4268     /* we will check if the variant got cleared */
4269     IXMLDOMDocument2_AddRef(doc2);
4270     EXPECT_REF(doc2, 3); /* doc, doc2, AddRef*/
4271 
4272     V_VT(&var) = VT_UNKNOWN;
4273     V_UNKNOWN(&var) = (IUnknown *)doc2;
4274 
4275     /* invalid calls */
4276     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("askldhfaklsdf"), &var), E_FAIL);
4277     expect_eq(V_VT(&var), VT_UNKNOWN, int, "%x");
4278     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), NULL), E_INVALIDARG);
4279 
4280     /* valid call */
4281     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4282     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4283     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4284     V_VT(&var) = VT_R4;
4285 
4286     /* the variant didn't get cleared*/
4287     expect_eq(IXMLDOMDocument2_Release(doc2), 2, int, "%d");
4288 
4289     /* setProperty tests */
4290     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("askldhfaklsdf"), var), E_FAIL);
4291     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), var), E_FAIL);
4292     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("alskjdh faklsjd hfk")), E_FAIL);
4293     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4294     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4295     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4296 
4297     V_VT(&var) = VT_BSTR;
4298     V_BSTR(&var) = SysAllocString(emptyW);
4299     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4300     ok(r == S_OK, "got 0x%08x\n", r);
4301     VariantClear(&var);
4302 
4303     V_VT(&var) = VT_I2;
4304     V_I2(&var) = 0;
4305     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4306     ok(r == E_FAIL, "got 0x%08x\n", r);
4307 
4308     /* contrary to what MSDN claims you can switch back from XPath to XSLPattern */
4309     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4310     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4311     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4312 
4313     IXMLDOMDocument2_Release( doc2 );
4314     IXMLDOMDocument_Release( doc );
4315 
4316     /* DTD validation */
4317     ole_check(IXMLDOMDocument2_put_validateOnParse(dtddoc2, VARIANT_FALSE));
4318     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML), &b));
4319     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4320     err = NULL;
4321     ole_check(IXMLDOMDocument2_validate(dtddoc2, &err));
4322     ok(err != NULL, "expected pointer\n");
4323     if (err)
4324     {
4325         res = 0;
4326         ole_expect(IXMLDOMParseError_get_errorCode(err, &res), S_FALSE);
4327         ok(res == 0, "got %08x\n", res);
4328         IXMLDOMParseError_Release(err);
4329     }
4330 
4331     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0D), &b));
4332     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4333     err = NULL;
4334     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4335     ok(err != NULL, "expected pointer\n");
4336     if (err)
4337     {
4338         res = 0;
4339         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4340         /* XML_ELEMENT_UNDECLARED */
4341         todo_wine ok(res == 0xC00CE00D, "got %08x\n", res);
4342         IXMLDOMParseError_Release(err);
4343     }
4344 
4345     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0E), &b));
4346     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4347     err = NULL;
4348     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4349     ok(err != NULL, "expected pointer\n");
4350     if (err)
4351     {
4352         res = 0;
4353         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4354         /* XML_ELEMENT_ID_NOT_FOUND */
4355         todo_wine ok(res == 0xC00CE00E, "got %08x\n", res);
4356         IXMLDOMParseError_Release(err);
4357     }
4358 
4359     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_11), &b));
4360     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4361     err = NULL;
4362     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4363     ok(err != NULL, "expected pointer\n");
4364     if (err)
4365     {
4366         res = 0;
4367         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4368         /* XML_EMPTY_NOT_ALLOWED */
4369         todo_wine ok(res == 0xC00CE011, "got %08x\n", res);
4370         IXMLDOMParseError_Release(err);
4371     }
4372 
4373     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_13), &b));
4374     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4375     err = NULL;
4376     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4377     ok(err != NULL, "expected pointer\n");
4378     if (err)
4379     {
4380         res = 0;
4381         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4382         /* XML_ROOT_NAME_MISMATCH */
4383         todo_wine ok(res == 0xC00CE013, "got %08x\n", res);
4384         IXMLDOMParseError_Release(err);
4385     }
4386 
4387     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_14), &b));
4388     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4389     err = NULL;
4390     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4391     ok(err != NULL, "expected pointer\n");
4392     if (err)
4393     {
4394         res = 0;
4395         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4396         /* XML_INVALID_CONTENT */
4397         todo_wine ok(res == 0xC00CE014, "got %08x\n", res);
4398         IXMLDOMParseError_Release(err);
4399     }
4400 
4401     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_15), &b));
4402     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4403     err = NULL;
4404     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4405     ok(err != NULL, "expected pointer\n");
4406     if (err)
4407     {
4408         res = 0;
4409         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4410         /* XML_ATTRIBUTE_NOT_DEFINED */
4411         todo_wine ok(res == 0xC00CE015, "got %08x\n", res);
4412         IXMLDOMParseError_Release(err);
4413     }
4414 
4415     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_16), &b));
4416     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4417     err = NULL;
4418     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4419     ok(err != NULL, "expected pointer\n");
4420     if (err)
4421     {
4422         res = 0;
4423         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4424         /* XML_ATTRIBUTE_FIXED */
4425         todo_wine ok(res == 0xC00CE016, "got %08x\n", res);
4426         IXMLDOMParseError_Release(err);
4427     }
4428 
4429     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_17), &b));
4430     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4431     err = NULL;
4432     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4433     ok(err != NULL, "expected pointer\n");
4434     if (err)
4435     {
4436         res = 0;
4437         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4438         /* XML_ATTRIBUTE_VALUE */
4439         todo_wine ok(res == 0xC00CE017, "got %08x\n", res);
4440         IXMLDOMParseError_Release(err);
4441     }
4442 
4443     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_18), &b));
4444     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4445     err = NULL;
4446     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4447     ok(err != NULL, "expected pointer\n");
4448     if (err)
4449     {
4450         res = 0;
4451         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4452         /* XML_ILLEGAL_TEXT */
4453         todo_wine ok(res == 0xC00CE018, "got %08x\n", res);
4454         IXMLDOMParseError_Release(err);
4455     }
4456 
4457     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_20), &b));
4458     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4459     err = NULL;
4460     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4461     ok(err != NULL, "expected pointer\n");
4462     if (err)
4463     {
4464         res = 0;
4465         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4466         /* XML_REQUIRED_ATTRIBUTE_MISSING */
4467         todo_wine ok(res == 0xC00CE020, "got %08x\n", res);
4468         IXMLDOMParseError_Release(err);
4469     }
4470 
4471     IXMLDOMDocument2_Release( dtddoc2 );
4472     free_bstrs();
4473 }
4474 
4475 #define helper_ole_check(expr) { \
4476     HRESULT r = expr; \
4477     ok_(__FILE__, line)(r == S_OK, "=> %i: " #expr " returned %08x\n", __LINE__, r); \
4478 }
4479 
4480 #define helper_ole_check_ver(expr) { \
4481     HRESULT r = expr; \
4482     ok_(__FILE__, line)(r == S_OK, "-> %i (%s): " #expr " returned %08x\n", __LINE__, ver, r); \
4483 }
4484 
4485 #define helper_expect_list_and_release(list, expstr) { \
4486     char *str = list_to_string(list); \
4487     ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i (%s): Invalid node list: %s, expected %s\n", __LINE__, ver, str, expstr); \
4488     if (list) IXMLDOMNodeList_Release(list); \
4489 }
4490 
4491 #define helper_expect_bstr_and_release(bstr, str) { \
4492     ok_(__FILE__, line)(lstrcmpW(bstr, _bstr_(str)) == 0, \
4493        "=> %i (%s): got %s\n", __LINE__, ver, wine_dbgstr_w(bstr)); \
4494     SysFreeString(bstr); \
4495 }
4496 
4497 #define check_ws_ignored(ver, doc, str) _check_ws_ignored(__LINE__, ver, doc, str)
4498 static inline void _check_ws_ignored(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4499 {
4500     IXMLDOMNode *node1, *node2;
4501     IXMLDOMNodeList *list;
4502     BSTR bstr;
4503 
4504     helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4505     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4506     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4507     helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4508     helper_expect_list_and_release(list, "E1.E5.E1.E2.D1 E2.E5.E1.E2.D1");
4509 
4510     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4511     helper_expect_list_and_release(list,
4512             "[4]1.E1.E5.E1.E2.D1 T2.E1.E5.E1.E2.D1 E3.E1.E5.E1.E2.D1 "
4513             "E4.E1.E5.E1.E2.D1 E5.E1.E5.E1.E2.D1 E6.E1.E5.E1.E2.D1");
4514     helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4515     if (str)
4516     {
4517         helper_expect_bstr_and_release(bstr, str);
4518     }
4519     else
4520     {
4521         helper_expect_bstr_and_release(bstr, " This is a description.");
4522     }
4523     IXMLDOMNode_Release(node1);
4524 
4525     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4526     helper_expect_list_and_release(list,
4527             "T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 "
4528             "E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
4529     helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4530     helper_expect_bstr_and_release(bstr,
4531             "\n                This is a description with preserved whitespace. \n            ");
4532     IXMLDOMNode_Release(node2);
4533 }
4534 
4535 #define check_ws_preserved(ver, doc, str) _check_ws_preserved(__LINE__, ver, doc, str)
4536 static inline void _check_ws_preserved(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4537 {
4538     IXMLDOMNode *node1, *node2;
4539     IXMLDOMNodeList *list;
4540     BSTR bstr;
4541 
4542     helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4543     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4544     helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4545     helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4546     helper_expect_list_and_release(list, "E2.E10.E2.E2.D1 E4.E10.E2.E2.D1");
4547 
4548     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4549     helper_expect_list_and_release(list,
4550             "T1.E2.E10.E2.E2.D1 [4]2.E2.E10.E2.E2.D1 T3.E2.E10.E2.E2.D1 "
4551             "E4.E2.E10.E2.E2.D1 T5.E2.E10.E2.E2.D1 E6.E2.E10.E2.E2.D1 "
4552             "E7.E2.E10.E2.E2.D1 E8.E2.E10.E2.E2.D1 T9.E2.E10.E2.E2.D1");
4553     helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4554     if (str)
4555     {
4556         helper_expect_bstr_and_release(bstr, str);
4557     }
4558     else
4559     {
4560         helper_expect_bstr_and_release(bstr, "\n                 This is a  description. \n            ");
4561     }
4562     IXMLDOMNode_Release(node1);
4563 
4564     helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4565     helper_expect_list_and_release(list,
4566             "T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 "
4567             "E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
4568     helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4569     helper_expect_bstr_and_release(bstr,
4570             "\n                This is a description with preserved whitespace. \n            ");
4571     IXMLDOMNode_Release(node2);
4572 }
4573 
4574 static void test_preserve_charref(IXMLDOMDocument2 *doc, VARIANT_BOOL preserve)
4575 {
4576     static const WCHAR b1_p[] = {' ','T','e','x','t',' ','A',' ','e','n','d',' ',0};
4577     static const WCHAR b1_i[] = {'T','e','x','t',' ','A',' ','e','n','d',0};
4578     static const WCHAR b2_p[] = {'A','B',' ','C',' ',0};
4579     static const WCHAR b2_i[] = {'A','B',' ','C',0};
4580     IXMLDOMNodeList *list;
4581     IXMLDOMElement *root;
4582     IXMLDOMNode *node;
4583     const WCHAR *text;
4584     VARIANT_BOOL b;
4585     HRESULT hr;
4586     BSTR s;
4587 
4588     hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc, preserve);
4589     ok(hr == S_OK, "got 0x%08x\n", hr);
4590 
4591     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(charrefsxml), &b);
4592     ok(hr == S_OK, "got 0x%08x\n", hr);
4593 
4594     hr = IXMLDOMDocument2_get_documentElement(doc, &root);
4595     ok(hr == S_OK, "got 0x%08x\n", hr);
4596 
4597     hr = IXMLDOMElement_get_childNodes(root, &list);
4598     ok(hr == S_OK, "got 0x%08x\n", hr);
4599     IXMLDOMElement_Release(root);
4600 
4601     text = preserve == VARIANT_TRUE ? b1_p : b1_i;
4602     hr = IXMLDOMNodeList_get_item(list, 0, &node);
4603     ok(hr == S_OK, "got 0x%08x\n", hr);
4604     hr = IXMLDOMNode_get_text(node, &s);
4605     ok(hr == S_OK, "got 0x%08x\n", hr);
4606     ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4607     SysFreeString(s);
4608     IXMLDOMNode_Release(node);
4609 
4610     text = preserve == VARIANT_TRUE ? b2_p : b2_i;
4611     hr = IXMLDOMNodeList_get_item(list, 1, &node);
4612     ok(hr == S_OK, "got 0x%08x\n", hr);
4613     hr = IXMLDOMNode_get_text(node, &s);
4614     ok(hr == S_OK, "got 0x%08x\n", hr);
4615     ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4616     SysFreeString(s);
4617     IXMLDOMNode_Release(node);
4618 
4619     IXMLDOMNodeList_Release(list);
4620 }
4621 
4622 struct whitespace_t {
4623     const CLSID *clsid;
4624     const char *name;
4625 };
4626 
4627 static const struct whitespace_t whitespace_test_data[] = {
4628     { &CLSID_DOMDocument,   "CLSID_DOMDocument"   },
4629     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2"  },
4630     { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
4631     { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
4632     { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
4633     { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
4634     { 0 }
4635 };
4636 
4637 static void test_whitespace(void)
4638 {
4639     const struct whitespace_t *class_ptr = whitespace_test_data;
4640 
4641     while (class_ptr->clsid)
4642     {
4643         IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
4644         IXMLDOMNodeList *list;
4645         IXMLDOMElement *root;
4646         VARIANT_BOOL b;
4647         HRESULT hr;
4648         LONG len;
4649 
4650         if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument2))
4651         {
4652             class_ptr++;
4653             continue;
4654         }
4655 
4656         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4657                 &IID_IXMLDOMDocument2, (void**)&doc1);
4658         ok(hr == S_OK, "got 0x%08x\n", hr);
4659 
4660         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4661                 &IID_IXMLDOMDocument2, (void**)&doc2);
4662         ok(hr == S_OK, "got 0x%08x\n", hr);
4663 
4664         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
4665         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4666         ok(b == VARIANT_FALSE, "expected false\n");
4667         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4668         ok(b == VARIANT_TRUE, "expected true\n");
4669 
4670         ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4671         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4672         ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4673         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4674 
4675         /* switch to XPath */
4676         ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4677         ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4678 
4679         check_ws_ignored(class_ptr->name, doc1, NULL);
4680         check_ws_preserved(class_ptr->name, doc2, NULL);
4681 
4682         /* new instances copy the property */
4683         ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
4684         ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
4685 
4686         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4687         ok(b == VARIANT_FALSE, "expected false\n");
4688         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4689         ok(b == VARIANT_TRUE, "expected true\n");
4690 
4691         check_ws_ignored(class_ptr->name, doc3, NULL);
4692         check_ws_preserved(class_ptr->name, doc4, NULL);
4693 
4694         /* setting after loading xml affects trimming of leading/trailing ws only */
4695         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
4696         ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
4697 
4698         /* the trailing "\n            " isn't there, because it was ws-only node */
4699         check_ws_ignored(class_ptr->name, doc1, " This is a description. ");
4700         check_ws_preserved(class_ptr->name, doc2, " This is a description.");
4701 
4702         /* it takes effect on reload */
4703         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4704         ok(b == VARIANT_TRUE, "expected true\n");
4705         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4706         ok(b == VARIANT_FALSE, "expected false\n");
4707 
4708         ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4709         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4710         ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4711         ok(b == VARIANT_TRUE, "failed to load XML string\n");
4712 
4713         check_ws_preserved(class_ptr->name, doc1, NULL);
4714         check_ws_ignored(class_ptr->name, doc2, NULL);
4715 
4716         /* other instances follow suit */
4717         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4718         ok(b == VARIANT_TRUE, "expected true\n");
4719         ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4720         ok(b == VARIANT_FALSE, "expected false\n");
4721 
4722         check_ws_preserved(class_ptr->name, doc3, NULL);
4723         check_ws_ignored(class_ptr->name, doc4, NULL);
4724 
4725         IXMLDOMDocument2_Release(doc2);
4726         IXMLDOMDocument2_Release(doc3);
4727         IXMLDOMDocument2_Release(doc4);
4728 
4729         /* text with char references */
4730         test_preserve_charref(doc1, VARIANT_TRUE);
4731         test_preserve_charref(doc1, VARIANT_FALSE);
4732 
4733         /* formatting whitespaces */
4734         hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_FALSE);
4735         ok(hr == S_OK, "got 0x%08x\n", hr);
4736 
4737         hr = IXMLDOMDocument2_loadXML(doc1, _bstr_(complete7), &b);
4738         ok(hr == S_OK, "got 0x%08x\n", hr);
4739         ok(b == VARIANT_TRUE, "for %x\n", b);
4740 
4741         hr = IXMLDOMDocument2_get_documentElement(doc1, &root);
4742         ok(hr == S_OK, "got 0x%08x\n", hr);
4743         hr = IXMLDOMElement_get_childNodes(root, &list);
4744         ok(hr == S_OK, "got 0x%08x\n", hr);
4745         len = 0;
4746         hr = IXMLDOMNodeList_get_length(list, &len);
4747         ok(hr == S_OK, "got 0x%08x\n", hr);
4748         ok(len == 3, "got %d\n", len);
4749         IXMLDOMNodeList_Release(list);
4750         IXMLDOMElement_Release(root);
4751 
4752         IXMLDOMDocument2_Release(doc1);
4753 
4754         free_bstrs();
4755 
4756         class_ptr++;
4757     }
4758 }
4759 
4760 typedef struct {
4761     const GUID *clsid;
4762     const char *name;
4763     const char *ns;
4764     HRESULT hr;
4765 } selection_ns_t;
4766 
4767 /* supposed to be tested with szExampleXML */
4768 static const selection_ns_t selection_ns_data[] = {
4769     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4770     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4771     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4772     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4773 
4774     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4775     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4776     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4777     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4778 
4779     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4780     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4781     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4782     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4783 
4784     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4785     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4786     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4787     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4788 
4789     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4790     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4791     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4792     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4793 
4794     { NULL }
4795 };
4796 
4797 typedef struct {
4798     const char *query;
4799     const char *list;
4800 } xpath_test_t;
4801 
4802 static const xpath_test_t xpath_test[] = {
4803     { "*/a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4804     { "*/b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4805     { "*/c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4806     { "*/d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4807     { "//a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4808     { "//b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4809     { "//c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4810     { "//d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4811     { "//c[@type]", "E3.E2.E2.D1" },
4812     { "//c[@type]/ancestor::node()[1]", "E2.E2.D1" },
4813     { "//c[@type]/ancestor-or-self::node()[1]", "E3.E2.E2.D1" },
4814     { "//c[@type]/attribute::node()[1]", "A'type'.E3.E2.E2.D1" },
4815     { "//c[@type]/child::node()[1]", "T1.E3.E2.E2.D1"  },
4816     { "//c[@type]/descendant::node()[1]", "T1.E3.E2.E2.D1" },
4817     { "//c[@type]/descendant-or-self::node()[1]", "E3.E2.E2.D1" },
4818     { "//c[@type]/following::node()[1]", "E4.E2.E2.D1" },
4819     { "//c[@type]/following-sibling::node()[1]", "E4.E2.E2.D1" },
4820     { "//c[@type]/parent::node()[1]", "E2.E2.D1" },
4821     { "//c[@type]/preceding::node()[1]", "T1.E2.E2.E2.D1" },
4822     { "//c[@type]/self::node()[1]", "E3.E2.E2.D1" },
4823     { "child::*", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4824     { "child::node()", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4825     { "child::text()", "" },
4826     { "child::*/..", "E2.D1" },
4827     { "child::*//@*/..", "E2.E5.E1.E2.D1 E2.E2.D1 E3.E2.E2.D1" },
4828     { "self::node()", "E2.D1" },
4829     { "ancestor::node()", "D1" },
4830     { "elem[c][last()]/a", "E1.E2.E2.D1"},
4831     { "ancestor-or-self::node()[1]", "E2.D1" },
4832     { "((//a)[1])[last()]", "E1.E1.E2.D1" },
4833     { "//elem[@*]", "E2.E2.D1" },
4834     { NULL }
4835 };
4836 
4837 static void test_XPath(void)
4838 {
4839     const selection_ns_t *ptr = selection_ns_data;
4840     const xpath_test_t *xptest = xpath_test;
4841     VARIANT var;
4842     VARIANT_BOOL b;
4843     IXMLDOMDocument2 *doc;
4844     IXMLDOMDocument *doc2;
4845     IXMLDOMNode *rootNode;
4846     IXMLDOMNode *elem1Node;
4847     IXMLDOMNode *node;
4848     IXMLDOMNodeList *list;
4849     IXMLDOMElement *elem;
4850     IXMLDOMAttribute *attr;
4851     DOMNodeType type;
4852     HRESULT hr;
4853     LONG len;
4854     BSTR str;
4855 
4856     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4857     doc = create_document(&IID_IXMLDOMDocument2);
4858 
4859     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4860     EXPECT_HR(hr, S_OK);
4861     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4862 
4863     /* switch to XPath */
4864     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4865 
4866     /* some simple queries*/
4867     EXPECT_REF(doc, 1);
4868     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4869     EXPECT_HR(hr, S_OK);
4870     EXPECT_REF(doc, 1);
4871     EXPECT_LIST_LEN(list, 1);
4872 
4873     EXPECT_REF(list, 1);
4874     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4875     EXPECT_HR(hr, S_OK);
4876     EXPECT_REF(list, 1);
4877     EXPECT_REF(rootNode, 1);
4878 
4879     hr = IXMLDOMNodeList_reset(list);
4880     EXPECT_HR(hr, S_OK);
4881     expect_list_and_release(list, "E2.D1");
4882 
4883     /* peform xpath tests */
4884     for ( ; xptest->query ; xptest++ )
4885     {
4886         char *str;
4887 
4888         hr = IXMLDOMNode_selectNodes(rootNode, _bstr_(xptest->query), &list);
4889         ok(hr == S_OK, "query evaluation failed for query=%s\n", xptest->query);
4890 
4891         if (hr != S_OK)
4892             continue;
4893 
4894         str = list_to_string(list);
4895 
4896         ok(!strcmp(str, xptest->list), "query=%s, invalid node list: \"%s\", expected \"%s\"\n",
4897             xptest->query, str, xptest->list);
4898 
4899         if (list)
4900             IXMLDOMNodeList_Release(list);
4901     }
4902 
4903 if (0)
4904 {
4905     /* namespace:: axis test is disabled until namespace definitions
4906        are supported as attribute nodes, currently it's another node type */
4907     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("/root/namespace::*"), &list);
4908     EXPECT_HR(hr, S_OK);
4909     len = -1;
4910     hr = IXMLDOMNodeList_get_length(list, &len);
4911     EXPECT_HR(hr, S_OK);
4912     ok(len == 2, "got %d\n", len);
4913 
4914     hr = IXMLDOMNodeList_nextNode(list, &node);
4915     EXPECT_HR(hr, S_OK);
4916     type = NODE_INVALID;
4917     hr = IXMLDOMNode_get_nodeType(node, &type);
4918     EXPECT_HR(hr, S_OK);
4919     ok(type == NODE_ATTRIBUTE, "got %d\n", type);
4920     IXMLDOMNode_Release(node);
4921 
4922     IXMLDOMNodeList_Release(list);
4923 }
4924 
4925     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
4926     expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1");
4927 
4928     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//c[@type]"), &list));
4929     expect_list_and_release(list, "E3.E2.E2.D1");
4930 
4931     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
4932     /* using get_item for query results advances the position */
4933     ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
4934     expect_node(node, "E2.E2.D1");
4935     IXMLDOMNode_Release(node);
4936     ole_check(IXMLDOMNodeList_nextNode(list, &node));
4937     expect_node(node, "E4.E2.D1");
4938     IXMLDOMNode_Release(node);
4939     ole_check(IXMLDOMNodeList_reset(list));
4940     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E4.E2.D1");
4941 
4942     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("."), &list));
4943     expect_list_and_release(list, "E2.D1");
4944 
4945     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem[3]/preceding-sibling::*"), &list));
4946     ole_check(IXMLDOMNodeList_get_item(list, 0, &elem1Node));
4947     ole_check(IXMLDOMNodeList_reset(list));
4948     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1");
4949 
4950     /* select an attribute */
4951     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//@type"), &list));
4952     expect_list_and_release(list, "A'type'.E3.E2.E2.D1");
4953 
4954     /* would evaluate to a number */
4955     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("count(*)"), &list), E_FAIL);
4956     /* would evaluate to a boolean */
4957     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("position()>0"), &list), E_FAIL);
4958     /* would evaluate to a string */
4959     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("name()"), &list), E_FAIL);
4960 
4961     /* no results */
4962     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("c"), &list));
4963     expect_list_and_release(list, "");
4964     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("elem//c"), &list));
4965     expect_list_and_release(list, "");
4966     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem[4]"), &list));
4967     expect_list_and_release(list, "");
4968     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[0]"), &list));
4969     expect_list_and_release(list, "");
4970 
4971     /* foo undeclared in document node */
4972     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4973     /* undeclared in <root> node */
4974     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
4975     /* undeclared in <elem> node */
4976     ole_expect(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//foo:c"), &list), E_FAIL);
4977     /* but this trick can be used */
4978     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//*[name()='foo:c']"), &list));
4979     expect_list_and_release(list, "E3.E4.E2.D1");
4980 
4981     /* it has to be declared in SelectionNamespaces */
4982     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
4983         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
4984 
4985     /* now the namespace can be used */
4986     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list));
4987     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4988     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
4989     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4990     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
4991     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4992     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
4993     expect_list_and_release(list, "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1");
4994 
4995     /* SelectionNamespaces syntax error - the namespaces doesn't work anymore but the value is stored */
4996     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
4997         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL);
4998 
4999     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5000 
5001     VariantInit(&var);
5002     ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
5003     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
5004     if (V_VT(&var) == VT_BSTR)
5005         expect_bstr_eq_and_free(V_BSTR(&var), "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###");
5006 
5007     /* extra attributes - same thing*/
5008     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5009         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' param='test'")), E_FAIL);
5010     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5011 
5012     IXMLDOMNode_Release(rootNode);
5013     IXMLDOMNode_Release(elem1Node);
5014 
5015     /* alter document with already built list */
5016     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5017     EXPECT_HR(hr, S_OK);
5018     EXPECT_LIST_LEN(list, 1);
5019 
5020     hr = IXMLDOMDocument2_get_lastChild(doc, &rootNode);
5021     EXPECT_HR(hr, S_OK);
5022     EXPECT_REF(rootNode, 1);
5023     EXPECT_REF(doc, 1);
5024 
5025     hr = IXMLDOMDocument2_removeChild(doc, rootNode, NULL);
5026     EXPECT_HR(hr, S_OK);
5027     IXMLDOMNode_Release(rootNode);
5028 
5029     EXPECT_LIST_LEN(list, 1);
5030 
5031     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5032     EXPECT_HR(hr, S_OK);
5033     EXPECT_REF(rootNode, 1);
5034 
5035     IXMLDOMNodeList_Release(list);
5036 
5037     hr = IXMLDOMNode_get_nodeName(rootNode, &str);
5038     EXPECT_HR(hr, S_OK);
5039     ok(!lstrcmpW(str, _bstr_("root")), "got %s\n", wine_dbgstr_w(str));
5040     SysFreeString(str);
5041     IXMLDOMNode_Release(rootNode);
5042 
5043     /* alter node from list and get it another time */
5044     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5045     EXPECT_HR(hr, S_OK);
5046     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5047 
5048     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5049     EXPECT_HR(hr, S_OK);
5050     EXPECT_LIST_LEN(list, 1);
5051 
5052     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5053     EXPECT_HR(hr, S_OK);
5054 
5055     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5056     EXPECT_HR(hr, S_OK);
5057 
5058     V_VT(&var) = VT_I2;
5059     V_I2(&var) = 1;
5060     hr = IXMLDOMElement_setAttribute(elem, _bstr_("attrtest"), var);
5061     EXPECT_HR(hr, S_OK);
5062     IXMLDOMElement_Release(elem);
5063     IXMLDOMNode_Release(rootNode);
5064 
5065     /* now check attribute to be present */
5066     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5067     EXPECT_HR(hr, S_OK);
5068 
5069     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5070     EXPECT_HR(hr, S_OK);
5071 
5072     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5073     EXPECT_HR(hr, S_OK);
5074     IXMLDOMAttribute_Release(attr);
5075 
5076     IXMLDOMElement_Release(elem);
5077     IXMLDOMNode_Release(rootNode);
5078 
5079     /* and now check for attribute in original document */
5080     hr = IXMLDOMDocument2_get_documentElement(doc, &elem);
5081     EXPECT_HR(hr, S_OK);
5082 
5083     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5084     EXPECT_HR(hr, S_OK);
5085     IXMLDOMAttribute_Release(attr);
5086 
5087     IXMLDOMElement_Release(elem);
5088 
5089     /* attach node from list to another document */
5090     doc2 = create_document(&IID_IXMLDOMDocument);
5091 
5092     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5093     EXPECT_HR(hr, S_OK);
5094     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5095 
5096     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5097     EXPECT_HR(hr, S_OK);
5098     EXPECT_LIST_LEN(list, 1);
5099 
5100     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5101     EXPECT_HR(hr, S_OK);
5102     EXPECT_REF(rootNode, 1);
5103 
5104     hr = IXMLDOMDocument_appendChild(doc2, rootNode, NULL);
5105     EXPECT_HR(hr, S_OK);
5106     EXPECT_REF(rootNode, 1);
5107     EXPECT_REF(doc2, 1);
5108     EXPECT_REF(list, 1);
5109 
5110     EXPECT_LIST_LEN(list, 1);
5111 
5112     IXMLDOMNode_Release(rootNode);
5113     IXMLDOMNodeList_Release(list);
5114     IXMLDOMDocument_Release(doc2);
5115     IXMLDOMDocument2_Release(doc);
5116 
5117     while (ptr->clsid)
5118     {
5119         if (is_clsid_supported(ptr->clsid, &IID_IXMLDOMDocument2))
5120         {
5121             hr = CoCreateInstance(ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
5122             ok(hr == S_OK, "got 0x%08x\n", hr);
5123         }
5124         else
5125         {
5126             ptr++;
5127             continue;
5128         }
5129 
5130         hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5131         EXPECT_HR(hr, S_OK);
5132         ok(b == VARIANT_TRUE, "failed to load, %s\n", ptr->name);
5133 
5134         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath"));
5135         EXPECT_HR(hr, S_OK);
5136 
5137         V_VT(&var) = VT_BSTR;
5138         V_BSTR(&var) = _bstr_(ptr->ns);
5139 
5140         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var);
5141         ok(hr == ptr->hr, "got 0x%08x, for %s, %s\n", hr, ptr->name, ptr->ns);
5142 
5143         V_VT(&var) = VT_EMPTY;
5144         hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var);
5145         EXPECT_HR(hr, S_OK);
5146         ok(V_VT(&var) == VT_BSTR, "got wrong property type %d\n", V_VT(&var));
5147         ok(!lstrcmpW(V_BSTR(&var), _bstr_(ptr->ns)), "got wrong value %s\n", wine_dbgstr_w(V_BSTR(&var)));
5148         VariantClear(&var);
5149 
5150         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list);
5151         EXPECT_HR(hr, S_OK);
5152         if (hr == S_OK)
5153             expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5154 
5155         IXMLDOMDocument2_Release(doc);
5156         ptr++;
5157         free_bstrs();
5158     }
5159 
5160     free_bstrs();
5161 }
5162 
5163 static void test_cloneNode(void )
5164 {
5165     IXMLDOMDocument2 *doc, *doc_clone;
5166     IXMLDOMDocument *doc2;
5167     VARIANT_BOOL b;
5168     IXMLDOMNodeList *pList;
5169     IXMLDOMNamedNodeMap *mapAttr;
5170     LONG length, length1;
5171     LONG attr_cnt, attr_cnt1;
5172     IXMLDOMNode *node, *attr;
5173     IXMLDOMNode *node_clone;
5174     IXMLDOMNode *node_first;
5175     VARIANT v;
5176     HRESULT hr;
5177 
5178     doc = create_document(&IID_IXMLDOMDocument2);
5179 
5180     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b);
5181     ok(hr == S_OK, "got 0x%08x\n", hr);
5182     ok(b == VARIANT_TRUE, "failed to load XML string\n");
5183 
5184     hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &v);
5185     ok(hr == S_OK, "got 0x%08x\n", hr);
5186     ok(!lstrcmpW(V_BSTR(&v), _bstr_("XSLPattern")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5187     VariantClear(&v);
5188 
5189     V_BSTR(&v) = _bstr_("XPath");
5190     V_VT(&v) = VT_BSTR;
5191     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), v);
5192     ok(hr == S_OK, "got 0x%08x\n", hr);
5193     VariantClear(&v);
5194 
5195     /* clone document node */
5196     hr = IXMLDOMDocument2_cloneNode(doc, VARIANT_TRUE, &node);
5197     ok( hr == S_OK, "ret %08x\n", hr );
5198     ok( node != NULL, "node %p\n", node );
5199 
5200     hr = IXMLDOMNode_get_childNodes(node, &pList);
5201     ok( hr == S_OK, "ret %08x\n", hr );
5202     length = 0;
5203     hr = IXMLDOMNodeList_get_length(pList, &length);
5204     ok( hr == S_OK, "ret %08x\n", hr );
5205     ok(length == 2, "got %d\n", length);
5206     IXMLDOMNodeList_Release(pList);
5207 
5208     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocument2, (void**)&doc_clone);
5209     ok(hr == S_OK, "got 0x%08x\n", hr);
5210 
5211     /* cloned document inherits properties */
5212     hr = IXMLDOMDocument2_getProperty(doc_clone, _bstr_("SelectionLanguage"), &v);
5213     ok(hr == S_OK, "got 0x%08x\n", hr);
5214     ok(!lstrcmpW(V_BSTR(&v), _bstr_("XPath")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5215     VariantClear(&v);
5216 
5217     IXMLDOMDocument2_Release(doc_clone);
5218     IXMLDOMNode_Release(node);
5219 
5220     hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("lc/pr"), &node);
5221     ok( hr == S_OK, "ret %08x\n", hr );
5222     ok( node != NULL, "node %p\n", node );
5223 
5224     /* Check invalid parameter */
5225     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, NULL);
5226     ok( hr == E_INVALIDARG, "ret %08x\n", hr );
5227 
5228     /* All Children */
5229     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, &node_clone);
5230     ok( hr == S_OK, "ret %08x\n", hr );
5231     ok( node_clone != NULL, "node %p\n", node );
5232 
5233     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5234     ok( hr == S_OK, "ret %08x\n", hr );
5235     hr = IXMLDOMNode_get_ownerDocument(node_clone, &doc2);
5236     ok( hr == S_OK, "ret %08x\n", hr );
5237     IXMLDOMDocument_Release(doc2);
5238     IXMLDOMNode_Release(node_first);
5239 
5240     hr = IXMLDOMNode_get_childNodes(node, &pList);
5241     ok( hr == S_OK, "ret %08x\n", hr );
5242     length = 0;
5243     hr = IXMLDOMNodeList_get_length(pList, &length);
5244     ok( hr == S_OK, "ret %08x\n", hr );
5245     ok(length == 1, "got %d\n", length);
5246     IXMLDOMNodeList_Release(pList);
5247 
5248     hr = IXMLDOMNode_get_attributes(node, &mapAttr);
5249     ok( hr == S_OK, "ret %08x\n", hr );
5250     attr_cnt = 0;
5251     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt);
5252     ok( hr == S_OK, "ret %08x\n", hr );
5253     ok(attr_cnt == 3, "got %d\n", attr_cnt);
5254     IXMLDOMNamedNodeMap_Release(mapAttr);
5255 
5256     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5257     ok( hr == S_OK, "ret %08x\n", hr );
5258     length1 = 0;
5259     hr = IXMLDOMNodeList_get_length(pList, &length1);
5260     ok(length1 == 1, "got %d\n", length1);
5261     ok( hr == S_OK, "ret %08x\n", hr );
5262     IXMLDOMNodeList_Release(pList);
5263 
5264     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5265     ok( hr == S_OK, "ret %08x\n", hr );
5266     attr_cnt1 = 0;
5267     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5268     ok( hr == S_OK, "ret %08x\n", hr );
5269     ok(attr_cnt1 == 3, "got %d\n", attr_cnt1);
5270     /* now really get some attributes from cloned element */
5271     attr = NULL;
5272     hr = IXMLDOMNamedNodeMap_getNamedItem(mapAttr, _bstr_("id"), &attr);
5273     ok(hr == S_OK, "ret %08x\n", hr);
5274     IXMLDOMNode_Release(attr);
5275     IXMLDOMNamedNodeMap_Release(mapAttr);
5276 
5277     ok(length == length1, "wrong Child count (%d, %d)\n", length, length1);
5278     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5279     IXMLDOMNode_Release(node_clone);
5280 
5281     /* No Children */
5282     hr = IXMLDOMNode_cloneNode(node, VARIANT_FALSE, &node_clone);
5283     ok( hr == S_OK, "ret %08x\n", hr );
5284     ok( node_clone != NULL, "node %p\n", node );
5285 
5286     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5287     ok(hr == S_FALSE, "ret %08x\n", hr );
5288 
5289     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5290     ok(hr == S_OK, "ret %08x\n", hr );
5291     hr = IXMLDOMNodeList_get_length(pList, &length1);
5292     ok(hr == S_OK, "ret %08x\n", hr );
5293     ok( length1 == 0, "Length should be 0 (%d)\n", length1);
5294     IXMLDOMNodeList_Release(pList);
5295 
5296     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5297     ok(hr == S_OK, "ret %08x\n", hr );
5298     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5299     ok(hr == S_OK, "ret %08x\n", hr );
5300     ok(attr_cnt1 == 3, "Attribute count should be 3 (%d)\n", attr_cnt1);
5301     IXMLDOMNamedNodeMap_Release(mapAttr);
5302 
5303     ok(length != length1, "wrong Child count (%d, %d)\n", length, length1);
5304     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5305     IXMLDOMNode_Release(node_clone);
5306 
5307     IXMLDOMNode_Release(node);
5308     IXMLDOMDocument2_Release(doc);
5309     free_bstrs();
5310 }
5311 
5312 static void test_xmlTypes(void)
5313 {
5314     IXMLDOMDocument *doc;
5315     IXMLDOMElement *pRoot;
5316     HRESULT hr;
5317     IXMLDOMComment *pComment;
5318     IXMLDOMElement *pElement;
5319     IXMLDOMAttribute *pAttribute;
5320     IXMLDOMNamedNodeMap *pAttribs;
5321     IXMLDOMCDATASection *pCDataSec;
5322     IXMLDOMImplementation *pIXMLDOMImplementation = NULL;
5323     IXMLDOMDocumentFragment *pDocFrag = NULL;
5324     IXMLDOMEntityReference *pEntityRef = NULL;
5325     BSTR str;
5326     IXMLDOMNode *pNextChild;
5327     VARIANT v;
5328     LONG len = 0;
5329 
5330     doc = create_document(&IID_IXMLDOMDocument);
5331 
5332     hr = IXMLDOMDocument_get_nextSibling(doc, NULL);
5333     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5334 
5335     pNextChild = (void*)0xdeadbeef;
5336     hr = IXMLDOMDocument_get_nextSibling(doc, &pNextChild);
5337     ok(hr == S_FALSE, "ret %08x\n", hr );
5338     ok(pNextChild == NULL, "pDocChild not NULL\n");
5339 
5340     /* test previous Sibling */
5341     hr = IXMLDOMDocument_get_previousSibling(doc, NULL);
5342     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5343 
5344     pNextChild = (void*)0xdeadbeef;
5345     hr = IXMLDOMDocument_get_previousSibling(doc, &pNextChild);
5346     ok(hr == S_FALSE, "ret %08x\n", hr );
5347     ok(pNextChild == NULL, "pNextChild not NULL\n");
5348 
5349     /* test get_dataType */
5350     V_VT(&v) = VT_EMPTY;
5351     hr = IXMLDOMDocument_get_dataType(doc, &v);
5352     ok(hr == S_FALSE, "ret %08x\n", hr );
5353     ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
5354     VariantClear(&v);
5355 
5356     /* test implementation */
5357     hr = IXMLDOMDocument_get_implementation(doc, NULL);
5358     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5359 
5360     hr = IXMLDOMDocument_get_implementation(doc, &pIXMLDOMImplementation);
5361     ok(hr == S_OK, "ret %08x\n", hr );
5362     if(hr == S_OK)
5363     {
5364         VARIANT_BOOL hasFeature = VARIANT_TRUE;
5365         BSTR sEmpty = SysAllocStringLen(NULL, 0);
5366 
5367         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, NULL, sEmpty, &hasFeature);
5368         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5369 
5370         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, NULL);
5371         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5372 
5373         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5374         ok(hr == S_OK, "ret %08x\n", hr );
5375         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5376 
5377         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, &hasFeature);
5378         ok(hr == S_OK, "ret %08x\n", hr );
5379         ok(hasFeature == VARIANT_FALSE, "hasFeature returned true\n");
5380 
5381         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), NULL, &hasFeature);
5382         ok(hr == S_OK, "ret %08x\n", hr );
5383         ok(hasFeature == VARIANT_TRUE, "hasFeature returned false\n");
5384 
5385         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5386         ok(hr == S_OK, "ret %08x\n", hr );
5387         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5388 
5389         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), _bstr_("1.0"), &hasFeature);
5390         ok(hr == S_OK, "ret %08x\n", hr );
5391         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5392 
5393         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("XML"), _bstr_("1.0"), &hasFeature);
5394         ok(hr == S_OK, "ret %08x\n", hr );
5395         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5396 
5397         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("MS-DOM"), _bstr_("1.0"), &hasFeature);
5398         ok(hr == S_OK, "ret %08x\n", hr );
5399         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5400 
5401         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("SSS"), NULL, &hasFeature);
5402         ok(hr == S_OK, "ret %08x\n", hr );
5403         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5404 
5405         SysFreeString(sEmpty);
5406         IXMLDOMImplementation_Release(pIXMLDOMImplementation);
5407     }
5408 
5409     pRoot = (IXMLDOMElement*)0x1;
5410     hr = IXMLDOMDocument_createElement(doc, NULL, &pRoot);
5411     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5412     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5413 
5414     pRoot = (IXMLDOMElement*)0x1;
5415     hr = IXMLDOMDocument_createElement(doc, _bstr_(""), &pRoot);
5416     ok(hr == E_FAIL, "ret %08x\n", hr );
5417     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5418 
5419     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
5420     ok(hr == S_OK, "ret %08x\n", hr );
5421     if(hr == S_OK)
5422     {
5423         hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)pRoot, NULL);
5424         ok(hr == S_OK, "ret %08x\n", hr );
5425         if(hr == S_OK)
5426         {
5427             /* Comment */
5428             str = SysAllocString(szComment);
5429             hr = IXMLDOMDocument_createComment(doc, str, &pComment);
5430             SysFreeString(str);
5431             ok(hr == S_OK, "ret %08x\n", hr );
5432             if(hr == S_OK)
5433             {
5434                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pComment, NULL);
5435                 ok(hr == S_OK, "ret %08x\n", hr );
5436 
5437                 hr = IXMLDOMComment_get_nodeName(pComment, &str);
5438                 ok(hr == S_OK, "ret %08x\n", hr );
5439                 ok( !lstrcmpW( str, szCommentNodeText ), "incorrect comment node Name\n");
5440                 SysFreeString(str);
5441 
5442                 hr = IXMLDOMComment_get_xml(pComment, &str);
5443                 ok(hr == S_OK, "ret %08x\n", hr );
5444                 ok( !lstrcmpW( str, szCommentXML ), "incorrect comment xml\n");
5445                 SysFreeString(str);
5446 
5447                 /* put data Tests */
5448                 hr = IXMLDOMComment_put_data(pComment, _bstr_("This &is a ; test <>\\"));
5449                 ok(hr == S_OK, "ret %08x\n", hr );
5450 
5451                 /* get data Tests */
5452                 hr = IXMLDOMComment_get_data(pComment, &str);
5453                 ok(hr == S_OK, "ret %08x\n", hr );
5454                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect get_data string\n");
5455                 SysFreeString(str);
5456 
5457                 /* Confirm XML text is good */
5458                 hr = IXMLDOMComment_get_xml(pComment, &str);
5459                 ok(hr == S_OK, "ret %08x\n", hr );
5460                 ok( !lstrcmpW( str, _bstr_("<!--This &is a ; test <>\\-->") ), "incorrect xml string\n");
5461                 SysFreeString(str);
5462 
5463                 /* Confirm we get the put_data Text back */
5464                 hr = IXMLDOMComment_get_text(pComment, &str);
5465                 ok(hr == S_OK, "ret %08x\n", hr );
5466                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
5467                 SysFreeString(str);
5468 
5469                 /* test length property */
5470                 hr = IXMLDOMComment_get_length(pComment, &len);
5471                 ok(hr == S_OK, "ret %08x\n", hr );
5472                 ok(len == 21, "expected 21 got %d\n", len);
5473 
5474                 /* test substringData */
5475                 hr = IXMLDOMComment_substringData(pComment, 0, 4, NULL);
5476                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5477 
5478                 /* test substringData - Invalid offset */
5479                 str = (void *)0xdeadbeef;
5480                 hr = IXMLDOMComment_substringData(pComment, -1, 4, &str);
5481                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5482                 ok( str == NULL, "incorrect string\n");
5483 
5484                 /* test substringData - Invalid offset */
5485                 str = (void *)0xdeadbeef;
5486                 hr = IXMLDOMComment_substringData(pComment, 30, 0, &str);
5487                 ok(hr == S_FALSE, "ret %08x\n", hr );
5488                 ok( str == NULL, "incorrect string\n");
5489 
5490                 /* test substringData - Invalid size */
5491                 str = (void *)0xdeadbeef;
5492                 hr = IXMLDOMComment_substringData(pComment, 0, -1, &str);
5493                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5494                 ok( str == NULL, "incorrect string\n");
5495 
5496                 /* test substringData - Invalid size */
5497                 str = (void *)0xdeadbeef;
5498                 hr = IXMLDOMComment_substringData(pComment, 2, 0, &str);
5499                 ok(hr == S_FALSE, "ret %08x\n", hr );
5500                 ok( str == NULL, "incorrect string\n");
5501 
5502                 /* test substringData - Start of string */
5503                 hr = IXMLDOMComment_substringData(pComment, 0, 4, &str);
5504                 ok(hr == S_OK, "ret %08x\n", hr );
5505                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5506                 SysFreeString(str);
5507 
5508                 /* test substringData - Middle of string */
5509                 hr = IXMLDOMComment_substringData(pComment, 13, 4, &str);
5510                 ok(hr == S_OK, "ret %08x\n", hr );
5511                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5512                 SysFreeString(str);
5513 
5514                 /* test substringData - End of string */
5515                 hr = IXMLDOMComment_substringData(pComment, 20, 4, &str);
5516                 ok(hr == S_OK, "ret %08x\n", hr );
5517                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5518                 SysFreeString(str);
5519 
5520                 /* test appendData */
5521                 hr = IXMLDOMComment_appendData(pComment, NULL);
5522                 ok(hr == S_OK, "ret %08x\n", hr );
5523 
5524                 hr = IXMLDOMComment_appendData(pComment, _bstr_(""));
5525                 ok(hr == S_OK, "ret %08x\n", hr );
5526 
5527                 hr = IXMLDOMComment_appendData(pComment, _bstr_("Append"));
5528                 ok(hr == S_OK, "ret %08x\n", hr );
5529 
5530                 hr = IXMLDOMComment_get_text(pComment, &str);
5531                 ok(hr == S_OK, "ret %08x\n", hr );
5532                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5533                 SysFreeString(str);
5534 
5535                 /* test insertData */
5536                 str = SysAllocStringLen(NULL, 0);
5537                 hr = IXMLDOMComment_insertData(pComment, -1, str);
5538                 ok(hr == S_OK, "ret %08x\n", hr );
5539 
5540                 hr = IXMLDOMComment_insertData(pComment, -1, NULL);
5541                 ok(hr == S_OK, "ret %08x\n", hr );
5542 
5543                 hr = IXMLDOMComment_insertData(pComment, 1000, str);
5544                 ok(hr == S_OK, "ret %08x\n", hr );
5545 
5546                 hr = IXMLDOMComment_insertData(pComment, 1000, NULL);
5547                 ok(hr == S_OK, "ret %08x\n", hr );
5548 
5549                 hr = IXMLDOMComment_insertData(pComment, 0, NULL);
5550                 ok(hr == S_OK, "ret %08x\n", hr );
5551 
5552                 hr = IXMLDOMComment_insertData(pComment, 0, str);
5553                 ok(hr == S_OK, "ret %08x\n", hr );
5554                 SysFreeString(str);
5555 
5556                 hr = IXMLDOMComment_insertData(pComment, -1, _bstr_("Inserting"));
5557                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5558 
5559                 hr = IXMLDOMComment_insertData(pComment, 1000, _bstr_("Inserting"));
5560                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5561 
5562                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("Begin "));
5563                 ok(hr == S_OK, "ret %08x\n", hr );
5564 
5565                 hr = IXMLDOMComment_insertData(pComment, 17, _bstr_("Middle"));
5566                 ok(hr == S_OK, "ret %08x\n", hr );
5567 
5568                 hr = IXMLDOMComment_insertData(pComment, 39, _bstr_(" End"));
5569                 ok(hr == S_OK, "ret %08x\n", hr );
5570 
5571                 hr = IXMLDOMComment_get_text(pComment, &str);
5572                 ok(hr == S_OK, "ret %08x\n", hr );
5573                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5574                 SysFreeString(str);
5575 
5576                 /* delete data */
5577                 /* invalid arguments */
5578                 hr = IXMLDOMComment_deleteData(pComment, -1, 1);
5579                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5580 
5581                 hr = IXMLDOMComment_deleteData(pComment, 0, 0);
5582                 ok(hr == S_OK, "ret %08x\n", hr );
5583 
5584                 hr = IXMLDOMComment_deleteData(pComment, 0, -1);
5585                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5586 
5587                 hr = IXMLDOMComment_get_length(pComment, &len);
5588                 ok(hr == S_OK, "ret %08x\n", hr );
5589                 ok(len == 43, "expected 43 got %d\n", len);
5590 
5591                 hr = IXMLDOMComment_deleteData(pComment, len, 1);
5592                 ok(hr == S_OK, "ret %08x\n", hr );
5593 
5594                 hr = IXMLDOMComment_deleteData(pComment, len+1, 1);
5595                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5596 
5597                 /* delete from start */
5598                 hr = IXMLDOMComment_deleteData(pComment, 0, 5);
5599                 ok(hr == S_OK, "ret %08x\n", hr );
5600 
5601                 hr = IXMLDOMComment_get_length(pComment, &len);
5602                 ok(hr == S_OK, "ret %08x\n", hr );
5603                 ok(len == 38, "expected 38 got %d\n", len);
5604 
5605                 hr = IXMLDOMComment_get_text(pComment, &str);
5606                 ok(hr == S_OK, "ret %08x\n", hr );
5607                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5608                 SysFreeString(str);
5609 
5610                 /* delete from end */
5611                 hr = IXMLDOMComment_deleteData(pComment, 35, 3);
5612                 ok(hr == S_OK, "ret %08x\n", hr );
5613 
5614                 hr = IXMLDOMComment_get_length(pComment, &len);
5615                 ok(hr == S_OK, "ret %08x\n", hr );
5616                 ok(len == 35, "expected 35 got %d\n", len);
5617 
5618                 hr = IXMLDOMComment_get_text(pComment, &str);
5619                 ok(hr == S_OK, "ret %08x\n", hr );
5620                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5621                 SysFreeString(str);
5622 
5623                 /* delete from inside */
5624                 hr = IXMLDOMComment_deleteData(pComment, 1, 33);
5625                 ok(hr == S_OK, "ret %08x\n", hr );
5626 
5627                 hr = IXMLDOMComment_get_length(pComment, &len);
5628                 ok(hr == S_OK, "ret %08x\n", hr );
5629                 ok(len == 2, "expected 2 got %d\n", len);
5630 
5631                 hr = IXMLDOMComment_get_text(pComment, &str);
5632                 ok(hr == S_OK, "ret %08x\n", hr );
5633                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5634                 SysFreeString(str);
5635 
5636                 /* delete whole data ... */
5637                 hr = IXMLDOMComment_get_length(pComment, &len);
5638                 ok(hr == S_OK, "ret %08x\n", hr );
5639 
5640                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5641                 ok(hr == S_OK, "ret %08x\n", hr );
5642                 /* ... and try again with empty string */
5643                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5644                 ok(hr == S_OK, "ret %08x\n", hr );
5645 
5646                 /* ::replaceData() */
5647                 V_VT(&v) = VT_BSTR;
5648                 V_BSTR(&v) = SysAllocString(szstr1);
5649                 hr = IXMLDOMComment_put_nodeValue(pComment, v);
5650                 ok(hr == S_OK, "ret %08x\n", hr );
5651                 VariantClear(&v);
5652 
5653                 hr = IXMLDOMComment_replaceData(pComment, 6, 0, NULL);
5654                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5655                 hr = IXMLDOMComment_get_text(pComment, &str);
5656                 ok(hr == S_OK, "ret %08x\n", hr );
5657                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5658                 SysFreeString(str);
5659 
5660                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, NULL);
5661                 ok(hr == S_OK, "ret %08x\n", hr );
5662                 hr = IXMLDOMComment_get_text(pComment, &str);
5663                 ok(hr == S_OK, "ret %08x\n", hr );
5664                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5665                 SysFreeString(str);
5666 
5667                 /* NULL pointer means delete */
5668                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, NULL);
5669                 ok(hr == S_OK, "ret %08x\n", hr );
5670                 hr = IXMLDOMComment_get_text(pComment, &str);
5671                 ok(hr == S_OK, "ret %08x\n", hr );
5672                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5673                 SysFreeString(str);
5674 
5675                 /* empty string means delete */
5676                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_(""));
5677                 ok(hr == S_OK, "ret %08x\n", hr );
5678                 hr = IXMLDOMComment_get_text(pComment, &str);
5679                 ok(hr == S_OK, "ret %08x\n", hr );
5680                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5681                 SysFreeString(str);
5682 
5683                 /* zero count means insert */
5684                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, _bstr_("a"));
5685                 ok(hr == S_OK, "ret %08x\n", hr );
5686                 hr = IXMLDOMComment_get_text(pComment, &str);
5687                 ok(hr == S_OK, "ret %08x\n", hr );
5688                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5689                 SysFreeString(str);
5690 
5691                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, NULL);
5692                 ok(hr == S_OK, "ret %08x\n", hr );
5693 
5694                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("m"));
5695                 ok(hr == S_OK, "ret %08x\n", hr );
5696                 hr = IXMLDOMComment_get_text(pComment, &str);
5697                 ok(hr == S_OK, "ret %08x\n", hr );
5698                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5699                 SysFreeString(str);
5700 
5701                 /* nonempty string, count greater than its length */
5702                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, _bstr_("a1.2"));
5703                 ok(hr == S_OK, "ret %08x\n", hr );
5704                 hr = IXMLDOMComment_get_text(pComment, &str);
5705                 ok(hr == S_OK, "ret %08x\n", hr );
5706                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5707                 SysFreeString(str);
5708 
5709                 /* nonempty string, count less than its length */
5710                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_("wine"));
5711                 ok(hr == S_OK, "ret %08x\n", hr );
5712                 hr = IXMLDOMComment_get_text(pComment, &str);
5713                 ok(hr == S_OK, "ret %08x\n", hr );
5714                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5715                 SysFreeString(str);
5716 
5717                 IXMLDOMComment_Release(pComment);
5718             }
5719 
5720             /* Element */
5721             str = SysAllocString(szElement);
5722             hr = IXMLDOMDocument_createElement(doc, str, &pElement);
5723             SysFreeString(str);
5724             ok(hr == S_OK, "ret %08x\n", hr );
5725             if(hr == S_OK)
5726             {
5727                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
5728                 ok(hr == S_OK, "ret %08x\n", hr );
5729 
5730                 hr = IXMLDOMElement_get_nodeName(pElement, &str);
5731                 ok(hr == S_OK, "ret %08x\n", hr );
5732                 ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
5733                 SysFreeString(str);
5734 
5735                 hr = IXMLDOMElement_get_xml(pElement, &str);
5736                 ok(hr == S_OK, "ret %08x\n", hr );
5737                 ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
5738                 SysFreeString(str);
5739 
5740                 /* Attribute */
5741                 pAttribute = (IXMLDOMAttribute*)0x1;
5742                 hr = IXMLDOMDocument_createAttribute(doc, NULL, &pAttribute);
5743                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5744                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5745 
5746                 pAttribute = (IXMLDOMAttribute*)0x1;
5747                 hr = IXMLDOMDocument_createAttribute(doc, _bstr_(""), &pAttribute);
5748                 ok(hr == E_FAIL, "ret %08x\n", hr );
5749                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5750 
5751                 str = SysAllocString(szAttribute);
5752                 hr = IXMLDOMDocument_createAttribute(doc, str, &pAttribute);
5753                 SysFreeString(str);
5754                 ok(hr == S_OK, "ret %08x\n", hr );
5755                 if(hr == S_OK)
5756                 {
5757                     IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
5758 
5759                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, NULL);
5760                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5761 
5762                     pNextChild = (IXMLDOMNode *)0x1;
5763                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, &pNextChild);
5764                     ok(hr == S_FALSE, "ret %08x\n", hr );
5765                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5766 
5767                     /* test Previous Sibling*/
5768                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, NULL);
5769                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5770 
5771                     pNextChild = (IXMLDOMNode *)0x1;
5772                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, &pNextChild);
5773                     ok(hr == S_FALSE, "ret %08x\n", hr );
5774                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5775 
5776                     hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttribute, &pNewChild);
5777                     ok(hr == E_FAIL, "ret %08x\n", hr );
5778                     ok(pNewChild == NULL, "pNewChild not NULL\n");
5779 
5780                     hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
5781                     ok(hr == S_OK, "ret %08x\n", hr );
5782                     if ( hr == S_OK )
5783                     {
5784                         hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttribute, NULL );
5785                         ok(hr == S_OK, "ret %08x\n", hr );
5786 
5787                         IXMLDOMNamedNodeMap_Release(pAttribs);
5788                     }
5789 
5790                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5791                     ok(hr == S_OK, "ret %08x\n", hr );
5792                     ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
5793                     SysFreeString(str);
5794 
5795                     /* test nodeName */
5796                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5797                     ok(hr == S_OK, "ret %08x\n", hr );
5798                     ok( !lstrcmpW( str, szAttribute ), "incorrect nodeName string\n");
5799                     SysFreeString(str);
5800 
5801                     /* test name property */
5802                     hr = IXMLDOMAttribute_get_name(pAttribute, &str);
5803                     ok(hr == S_OK, "ret %08x\n", hr );
5804                     ok( !lstrcmpW( str, szAttribute ), "incorrect name string\n");
5805                     SysFreeString(str);
5806 
5807                     hr = IXMLDOMAttribute_get_xml(pAttribute, &str);
5808                     ok(hr == S_OK, "ret %08x\n", hr );
5809                     ok( !lstrcmpW( str, szAttributeXML ), "incorrect attribute xml\n");
5810                     SysFreeString(str);
5811 
5812                     IXMLDOMAttribute_Release(pAttribute);
5813 
5814                     /* Check Element again with the Add Attribute*/
5815                     hr = IXMLDOMElement_get_xml(pElement, &str);
5816                     ok(hr == S_OK, "ret %08x\n", hr );
5817                     ok( !lstrcmpW( str, szElementXML2 ), "incorrect element xml\n");
5818                     SysFreeString(str);
5819                 }
5820 
5821                 hr = IXMLDOMElement_put_text(pElement, _bstr_("TestingNode"));
5822                 ok(hr == S_OK, "ret %08x\n", hr );
5823 
5824                 hr = IXMLDOMElement_get_xml(pElement, &str);
5825                 ok(hr == S_OK, "ret %08x\n", hr );
5826                 ok( !lstrcmpW( str, szElementXML3 ), "incorrect element xml\n");
5827                 SysFreeString(str);
5828 
5829                 /* Test for reversible escaping */
5830                 str = SysAllocString( szStrangeChars );
5831                 hr = IXMLDOMElement_put_text(pElement, str);
5832                 ok(hr == S_OK, "ret %08x\n", hr );
5833                 SysFreeString( str );
5834 
5835                 hr = IXMLDOMElement_get_xml(pElement, &str);
5836                 ok(hr == S_OK, "ret %08x\n", hr );
5837                 ok( !lstrcmpW( str, szElementXML4 ), "incorrect element xml\n");
5838                 SysFreeString(str);
5839 
5840                 hr = IXMLDOMElement_get_text(pElement, &str);
5841                 ok(hr == S_OK, "ret %08x\n", hr );
5842                 ok( !lstrcmpW( str, szStrangeChars ), "incorrect element text\n");
5843                 SysFreeString(str);
5844 
5845                 IXMLDOMElement_Release(pElement);
5846             }
5847 
5848             /* CData Section */
5849             str = SysAllocString(szCData);
5850             hr = IXMLDOMDocument_createCDATASection(doc, str, NULL);
5851             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5852 
5853             hr = IXMLDOMDocument_createCDATASection(doc, str, &pCDataSec);
5854             SysFreeString(str);
5855             ok(hr == S_OK, "ret %08x\n", hr );
5856             if(hr == S_OK)
5857             {
5858                 IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
5859                 VARIANT var;
5860 
5861                 VariantInit(&var);
5862 
5863                 hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (void**)&pElement);
5864                 ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
5865 
5866                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pCDataSec, NULL);
5867                 ok(hr == S_OK, "ret %08x\n", hr );
5868 
5869                 hr = IXMLDOMCDATASection_get_nodeName(pCDataSec, &str);
5870                 ok(hr == S_OK, "ret %08x\n", hr );
5871                 ok( !lstrcmpW( str, szCDataNodeText ), "incorrect cdata node Name\n");
5872                 SysFreeString(str);
5873 
5874                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5875                 ok(hr == S_OK, "ret %08x\n", hr );
5876                 ok( !lstrcmpW( str, szCDataXML ), "incorrect cdata xml\n");
5877                 SysFreeString(str);
5878 
5879                 /* test lastChild */
5880                 pNextChild = (IXMLDOMNode*)0x1;
5881                 hr = IXMLDOMCDATASection_get_lastChild(pCDataSec, &pNextChild);
5882                 ok(hr == S_FALSE, "ret %08x\n", hr );
5883                 ok(pNextChild == NULL, "pNextChild not NULL\n");
5884 
5885                 /* put data Tests */
5886                 hr = IXMLDOMCDATASection_put_data(pCDataSec, _bstr_("This &is a ; test <>\\"));
5887                 ok(hr == S_OK, "ret %08x\n", hr );
5888 
5889                 /* Confirm XML text is good */
5890                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5891                 ok(hr == S_OK, "ret %08x\n", hr );
5892                 ok( !lstrcmpW( str, _bstr_("<![CDATA[This &is a ; test <>\\]]>") ), "incorrect xml string\n");
5893                 SysFreeString(str);
5894 
5895                 /* Confirm we get the put_data Text back */
5896                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5897                 ok(hr == S_OK, "ret %08x\n", hr );
5898                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5899                 SysFreeString(str);
5900 
5901                 /* test length property */
5902                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5903                 ok(hr == S_OK, "ret %08x\n", hr );
5904                 ok(len == 21, "expected 21 got %d\n", len);
5905 
5906                 /* test get data */
5907                 hr = IXMLDOMCDATASection_get_data(pCDataSec, &str);
5908                 ok(hr == S_OK, "ret %08x\n", hr );
5909                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5910                 SysFreeString(str);
5911 
5912                 /* test substringData */
5913                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, NULL);
5914                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5915 
5916                 /* test substringData - Invalid offset */
5917                 str = (void *)0xdeadbeef;
5918                 hr = IXMLDOMCDATASection_substringData(pCDataSec, -1, 4, &str);
5919                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5920                 ok( str == NULL, "incorrect string\n");
5921 
5922                 /* test substringData - Invalid offset */
5923                 str = (void *)0xdeadbeef;
5924                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 30, 0, &str);
5925                 ok(hr == S_FALSE, "ret %08x\n", hr );
5926                 ok( str == NULL, "incorrect string\n");
5927 
5928                 /* test substringData - Invalid size */
5929                 str = (void *)0xdeadbeef;
5930                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, -1, &str);
5931                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5932                 ok( str == NULL, "incorrect string\n");
5933 
5934                 /* test substringData - Invalid size */
5935                 str = (void *)0xdeadbeef;
5936                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 2, 0, &str);
5937                 ok(hr == S_FALSE, "ret %08x\n", hr );
5938                 ok( str == NULL, "incorrect string\n");
5939 
5940                 /* test substringData - Start of string */
5941                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, &str);
5942                 ok(hr == S_OK, "ret %08x\n", hr );
5943                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5944                 SysFreeString(str);
5945 
5946                 /* test substringData - Middle of string */
5947                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 13, 4, &str);
5948                 ok(hr == S_OK, "ret %08x\n", hr );
5949                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5950                 SysFreeString(str);
5951 
5952                 /* test substringData - End of string */
5953                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 20, 4, &str);
5954                 ok(hr == S_OK, "ret %08x\n", hr );
5955                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5956                 SysFreeString(str);
5957 
5958                 /* test appendData */
5959                 hr = IXMLDOMCDATASection_appendData(pCDataSec, NULL);
5960                 ok(hr == S_OK, "ret %08x\n", hr );
5961 
5962                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_(""));
5963                 ok(hr == S_OK, "ret %08x\n", hr );
5964 
5965                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_("Append"));
5966                 ok(hr == S_OK, "ret %08x\n", hr );
5967 
5968                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5969                 ok(hr == S_OK, "ret %08x\n", hr );
5970                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5971                 SysFreeString(str);
5972 
5973                 /* test insertData */
5974                 str = SysAllocStringLen(NULL, 0);
5975                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, str);
5976                 ok(hr == S_OK, "ret %08x\n", hr );
5977 
5978                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, NULL);
5979                 ok(hr == S_OK, "ret %08x\n", hr );
5980 
5981                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, str);
5982                 ok(hr == S_OK, "ret %08x\n", hr );
5983 
5984                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, NULL);
5985                 ok(hr == S_OK, "ret %08x\n", hr );
5986 
5987                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, NULL);
5988                 ok(hr == S_OK, "ret %08x\n", hr );
5989 
5990                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, str);
5991                 ok(hr == S_OK, "ret %08x\n", hr );
5992                 SysFreeString(str);
5993 
5994                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, _bstr_("Inserting"));
5995                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5996 
5997                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, _bstr_("Inserting"));
5998                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5999 
6000                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("Begin "));
6001                 ok(hr == S_OK, "ret %08x\n", hr );
6002 
6003                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 17, _bstr_("Middle"));
6004                 ok(hr == S_OK, "ret %08x\n", hr );
6005 
6006                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 39, _bstr_(" End"));
6007                 ok(hr == S_OK, "ret %08x\n", hr );
6008 
6009                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6010                 ok(hr == S_OK, "ret %08x\n", hr );
6011                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6012                 SysFreeString(str);
6013 
6014                 /* delete data */
6015                 /* invalid arguments */
6016                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, -1, 1);
6017                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6018 
6019                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 0);
6020                 ok(hr == S_OK, "ret %08x\n", hr );
6021 
6022                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, -1);
6023                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6024 
6025                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6026                 ok(hr == S_OK, "ret %08x\n", hr );
6027                 ok(len == 43, "expected 43 got %d\n", len);
6028 
6029                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len, 1);
6030                 ok(hr == S_OK, "ret %08x\n", hr );
6031 
6032                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len+1, 1);
6033                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6034 
6035                 /* delete from start */
6036                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 5);
6037                 ok(hr == S_OK, "ret %08x\n", hr );
6038 
6039                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6040                 ok(hr == S_OK, "ret %08x\n", hr );
6041                 ok(len == 38, "expected 38 got %d\n", len);
6042 
6043                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6044                 ok(hr == S_OK, "ret %08x\n", hr );
6045                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6046                 SysFreeString(str);
6047 
6048                 /* delete from end */
6049                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 35, 3);
6050                 ok(hr == S_OK, "ret %08x\n", hr );
6051 
6052                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6053                 ok(hr == S_OK, "ret %08x\n", hr );
6054                 ok(len == 35, "expected 35 got %d\n", len);
6055 
6056                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6057                 ok(hr == S_OK, "ret %08x\n", hr );
6058                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6059                 SysFreeString(str);
6060 
6061                 /* delete from inside */
6062                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 1, 33);
6063                 ok(hr == S_OK, "ret %08x\n", hr );
6064 
6065                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6066                 ok(hr == S_OK, "ret %08x\n", hr );
6067                 ok(len == 2, "expected 2 got %d\n", len);
6068 
6069                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6070                 ok(hr == S_OK, "ret %08x\n", hr );
6071                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6072                 SysFreeString(str);
6073 
6074                 /* delete whole data ... */
6075                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6076                 ok(hr == S_OK, "ret %08x\n", hr );
6077 
6078                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6079                 ok(hr == S_OK, "ret %08x\n", hr );
6080 
6081                 /* ... and try again with empty string */
6082                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6083                 ok(hr == S_OK, "ret %08x\n", hr );
6084 
6085                 /* ::replaceData() */
6086                 V_VT(&v) = VT_BSTR;
6087                 V_BSTR(&v) = SysAllocString(szstr1);
6088                 hr = IXMLDOMCDATASection_put_nodeValue(pCDataSec, v);
6089                 ok(hr == S_OK, "ret %08x\n", hr );
6090                 VariantClear(&v);
6091 
6092                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 6, 0, NULL);
6093                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6094                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6095                 ok(hr == S_OK, "ret %08x\n", hr );
6096                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6097                 SysFreeString(str);
6098 
6099                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, NULL);
6100                 ok(hr == S_OK, "ret %08x\n", hr );
6101                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6102                 ok(hr == S_OK, "ret %08x\n", hr );
6103                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6104                 SysFreeString(str);
6105 
6106                 /* NULL pointer means delete */
6107                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, NULL);
6108                 ok(hr == S_OK, "ret %08x\n", hr );
6109                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6110                 ok(hr == S_OK, "ret %08x\n", hr );
6111                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6112                 SysFreeString(str);
6113 
6114                 /* empty string means delete */
6115                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_(""));
6116                 ok(hr == S_OK, "ret %08x\n", hr );
6117                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6118                 ok(hr == S_OK, "ret %08x\n", hr );
6119                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6120                 SysFreeString(str);
6121 
6122                 /* zero count means insert */
6123                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, _bstr_("a"));
6124                 ok(hr == S_OK, "ret %08x\n", hr );
6125                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6126                 ok(hr == S_OK, "ret %08x\n", hr );
6127                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6128                 SysFreeString(str);
6129 
6130                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, NULL);
6131                 ok(hr == S_OK, "ret %08x\n", hr );
6132 
6133                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("m"));
6134                 ok(hr == S_OK, "ret %08x\n", hr );
6135                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6136                 ok(hr == S_OK, "ret %08x\n", hr );
6137                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6138                 SysFreeString(str);
6139 
6140                 /* nonempty string, count greater than its length */
6141                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, _bstr_("a1.2"));
6142                 ok(hr == S_OK, "ret %08x\n", hr );
6143                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6144                 ok(hr == S_OK, "ret %08x\n", hr );
6145                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6146                 SysFreeString(str);
6147 
6148                 /* nonempty string, count less than its length */
6149                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_("wine"));
6150                 ok(hr == S_OK, "ret %08x\n", hr );
6151                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6152                 ok(hr == S_OK, "ret %08x\n", hr );
6153                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6154                 SysFreeString(str);
6155 
6156                 IXMLDOMCDATASection_Release(pCDataSec);
6157             }
6158 
6159             /* Document Fragments */
6160             hr = IXMLDOMDocument_createDocumentFragment(doc, NULL);
6161             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6162 
6163             hr = IXMLDOMDocument_createDocumentFragment(doc, &pDocFrag);
6164             ok(hr == S_OK, "ret %08x\n", hr );
6165             if(hr == S_OK)
6166             {
6167                 IXMLDOMNode *node;
6168 
6169                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, NULL);
6170                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6171 
6172                 node = (IXMLDOMNode *)0x1;
6173                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, &node);
6174                 ok(hr == S_FALSE, "ret %08x\n", hr );
6175                 ok(node == NULL, "expected NULL, got %p\n", node);
6176 
6177                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pDocFrag, NULL);
6178                 ok(hr == S_OK, "ret %08x\n", hr );
6179 
6180                 hr = IXMLDOMDocumentFragment_get_nodeName(pDocFrag, &str);
6181                 ok(hr == S_OK, "ret %08x\n", hr );
6182                 ok( !lstrcmpW( str, szDocFragmentText ), "incorrect docfragment node Name\n");
6183                 SysFreeString(str);
6184 
6185                 /* test next Sibling*/
6186                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, NULL);
6187                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6188 
6189                 node = (IXMLDOMNode *)0x1;
6190                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &node);
6191                 ok(hr == S_FALSE, "ret %08x\n", hr );
6192                 ok(node == NULL, "next sibling not NULL\n");
6193 
6194                 /* test Previous Sibling*/
6195                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, NULL);
6196                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6197 
6198                 node = (IXMLDOMNode *)0x1;
6199                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &node);
6200                 ok(hr == S_FALSE, "ret %08x\n", hr );
6201                 ok(node == NULL, "previous sibling not NULL\n");
6202 
6203                 IXMLDOMDocumentFragment_Release(pDocFrag);
6204             }
6205 
6206             /* Entity References */
6207             hr = IXMLDOMDocument_createEntityReference(doc, NULL, &pEntityRef);
6208             ok(hr == E_FAIL, "ret %08x\n", hr );
6209             hr = IXMLDOMDocument_createEntityReference(doc, _bstr_(""), &pEntityRef);
6210             ok(hr == E_FAIL, "ret %08x\n", hr );
6211 
6212             str = SysAllocString(szEntityRef);
6213             hr = IXMLDOMDocument_createEntityReference(doc, str, NULL);
6214             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6215 
6216             hr = IXMLDOMDocument_createEntityReference(doc, str, &pEntityRef);
6217             SysFreeString(str);
6218             ok(hr == S_OK, "ret %08x\n", hr );
6219             if(hr == S_OK)
6220             {
6221                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pEntityRef, NULL);
6222                 ok(hr == S_OK, "ret %08x\n", hr );
6223 
6224                 /* test get_xml*/
6225                 hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str);
6226                 ok(hr == S_OK, "ret %08x\n", hr );
6227                 ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n");
6228                 SysFreeString(str);
6229 
6230                 IXMLDOMEntityReference_Release(pEntityRef);
6231             }
6232 
6233             IXMLDOMElement_Release( pRoot );
6234         }
6235     }
6236 
6237     IXMLDOMDocument_Release(doc);
6238 
6239     free_bstrs();
6240 }
6241 
6242 typedef struct {
6243     const char *name;
6244     const char *type;
6245     HRESULT hr;
6246 } put_datatype_t;
6247 
6248 /* Type test for elements only. Name passed into put_dataType is case-insensitive.
6249    So many of the names have been changed to reflect this. */
6250 static put_datatype_t put_datatype_data[] = {
6251     { "test_inval",      "abcdefg",     E_FAIL },
6252     { "test_bool",       "Boolean",     S_OK },
6253     { "test_string",     "String",      S_OK },
6254     { "test_number",     "number",      S_OK },
6255     { "test_int",        "InT",         S_OK },
6256     { "test_fixed",      "fixed.14.4",  S_OK },
6257     { "test_datetime",   "DateTime",    S_OK },
6258     { "test_datetimetz", "DateTime.tz", S_OK },
6259     { "test_date",       "Date",        S_OK },
6260     { "test_time",       "Time",        S_OK },
6261     { "test_timetz",     "Time.tz",     S_OK },
6262     { "test_I1",         "I1",          S_OK },
6263     { "test_I2",         "I2",          S_OK },
6264     { "test_I4",         "I4",          S_OK },
6265     { "test_UI1",        "UI1",         S_OK },
6266     { "test_UI2",        "UI2",         S_OK },
6267     { "test_UI4",        "UI4",         S_OK },
6268     { "test_r4",         "r4",          S_OK },
6269     { "test_r8",         "r8",          S_OK },
6270     { "test_float",      "float",       S_OK },
6271     { "test_uuid",       "UuId",        S_OK },
6272     { "test_binhex",     "bin.hex",     S_OK },
6273     { "test_binbase64",  "bin.base64",  S_OK },
6274     { NULL }
6275 };
6276 
6277 typedef struct {
6278     DOMNodeType type;
6279     HRESULT hr;
6280 } put_datatype_notype_t;
6281 
6282 static put_datatype_notype_t put_dt_notype[] = {
6283     { NODE_PROCESSING_INSTRUCTION, E_FAIL },
6284     { NODE_DOCUMENT_FRAGMENT,      E_FAIL },
6285     { NODE_ENTITY_REFERENCE,       E_FAIL },
6286     { NODE_CDATA_SECTION,          E_FAIL },
6287     { NODE_COMMENT,                E_FAIL },
6288     { NODE_INVALID }
6289 };
6290 
6291 static void test_put_dataType( void )
6292 {
6293     const put_datatype_notype_t *ptr2 = put_dt_notype;
6294     const put_datatype_t *ptr = put_datatype_data;
6295     IXMLDOMElement *root, *element;
6296     BSTR nameW, type1W, type2W;
6297     IXMLDOMDocument *doc;
6298     HRESULT hr;
6299 
6300     doc = create_document(&IID_IXMLDOMDocument);
6301 
6302     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), NULL);
6303     EXPECT_HR(hr, E_INVALIDARG);
6304 
6305     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6306     EXPECT_HR(hr, S_OK);
6307 
6308     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6309     EXPECT_HR(hr, S_OK);
6310 
6311     hr = IXMLDOMElement_put_dataType(root, NULL);
6312     EXPECT_HR(hr, E_INVALIDARG);
6313 
6314     while (ptr->name)
6315     {
6316         hr = IXMLDOMDocument_createElement(doc, _bstr_(ptr->name), &element);
6317         EXPECT_HR(hr, S_OK);
6318         if(hr == S_OK)
6319         {
6320             hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6321             EXPECT_HR(hr, S_OK);
6322 
6323             hr = IXMLDOMElement_put_dataType(element, _bstr_(ptr->type));
6324             ok(hr == ptr->hr, "failed for %s:%s, 0x%08x\n", ptr->name, ptr->type, ptr->hr);
6325 
6326             IXMLDOMElement_Release(element);
6327         }
6328         ptr++;
6329     }
6330 
6331     /* check changing types */
6332     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Change"), &element);
6333     EXPECT_HR(hr, S_OK);
6334 
6335     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6336     EXPECT_HR(hr, S_OK);
6337 
6338     hr = IXMLDOMElement_put_dataType(element, _bstr_("DateTime.tz"));
6339     EXPECT_HR(hr, S_OK);
6340 
6341     hr = IXMLDOMElement_put_dataType(element, _bstr_("string"));
6342     EXPECT_HR(hr, S_OK);
6343 
6344     IXMLDOMElement_Release(element);
6345 
6346     /* try to set type for node without a type */
6347     nameW  = _bstr_("testname");
6348     type1W = _bstr_("string");
6349     type2W = _bstr_("number");
6350     while (ptr2->type != NODE_INVALID)
6351     {
6352         IXMLDOMNode *node;
6353         VARIANT type;
6354 
6355         V_VT(&type) = VT_I2;
6356         V_I2(&type) = ptr2->type;
6357 
6358         hr = IXMLDOMDocument_createNode(doc, type, nameW, NULL, &node);
6359         EXPECT_HR(hr, S_OK);
6360         if(hr == S_OK)
6361         {
6362             hr = IXMLDOMElement_appendChild(root, node, NULL);
6363             EXPECT_HR(hr, S_OK);
6364 
6365             hr = IXMLDOMNode_put_dataType(node, NULL);
6366             EXPECT_HR(hr, E_INVALIDARG);
6367 
6368             hr = IXMLDOMNode_put_dataType(node, type1W);
6369             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6370             hr = IXMLDOMNode_put_dataType(node, type2W);
6371             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6372 
6373             IXMLDOMNode_Release(node);
6374         }
6375         ptr2++;
6376     }
6377 
6378     IXMLDOMElement_Release(root);
6379     IXMLDOMDocument_Release(doc);
6380     free_bstrs();
6381 }
6382 
6383 static void test_save(void)
6384 {
6385     IXMLDOMDocument *doc, *doc2;
6386     IXMLDOMElement *root;
6387     BSTR sOrig, sNew, filename;
6388     char buffer[100];
6389     IStream *stream;
6390     HGLOBAL global;
6391     VARIANT_BOOL b;
6392     DWORD read = 0;
6393     VARIANT dest;
6394     HANDLE hfile;
6395     HRESULT hr;
6396     char *ptr;
6397 
6398     doc = create_document(&IID_IXMLDOMDocument);
6399     doc2 = create_document(&IID_IXMLDOMDocument);
6400 
6401     /* save to IXMLDOMDocument */
6402     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6403     EXPECT_HR(hr, S_OK);
6404 
6405     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6406     EXPECT_HR(hr, S_OK);
6407 
6408     V_VT(&dest) = VT_UNKNOWN;
6409     V_UNKNOWN(&dest) = (IUnknown*)doc2;
6410 
6411     hr = IXMLDOMDocument_save(doc, dest);
6412     EXPECT_HR(hr, S_OK);
6413 
6414     hr = IXMLDOMDocument_get_xml(doc, &sOrig);
6415     EXPECT_HR(hr, S_OK);
6416 
6417     hr = IXMLDOMDocument_get_xml(doc2, &sNew);
6418     EXPECT_HR(hr, S_OK);
6419 
6420     ok( !lstrcmpW( sOrig, sNew ), "New document is not the same as original\n");
6421 
6422     SysFreeString(sOrig);
6423     SysFreeString(sNew);
6424 
6425     IXMLDOMElement_Release(root);
6426     IXMLDOMDocument_Release(doc2);
6427 
6428     /* save to path */
6429     V_VT(&dest) = VT_BSTR;
6430     V_BSTR(&dest) = _bstr_("test.xml");
6431 
6432     hr = IXMLDOMDocument_save(doc, dest);
6433     EXPECT_HR(hr, S_OK);
6434 
6435     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6436     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6437     if(hfile == INVALID_HANDLE_VALUE) return;
6438 
6439     ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6440     ok(read != 0, "could not read file\n");
6441     ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6442 
6443     CloseHandle(hfile);
6444     DeleteFileA("test.xml");
6445 
6446     /* save to path VT_BSTR | VT_BYREF */
6447     filename = _bstr_("test.xml");
6448     V_VT(&dest) = VT_BSTR | VT_BYREF;
6449     V_BSTRREF(&dest) = &filename;
6450 
6451     hr = IXMLDOMDocument_save(doc, dest);
6452     EXPECT_HR(hr, S_OK);
6453 
6454     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6455     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6456     if(hfile == INVALID_HANDLE_VALUE) return;
6457 
6458     if (hfile != INVALID_HANDLE_VALUE)
6459     {
6460        ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6461        ok(read != 0, "could not read file\n");
6462        ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6463 
6464        CloseHandle(hfile);
6465        DeleteFileA("test.xml");
6466     }
6467 
6468     /* save to stream */
6469     V_VT(&dest) = VT_UNKNOWN;
6470     V_UNKNOWN(&dest) = (IUnknown*)&savestream;
6471 
6472     hr = IXMLDOMDocument_save(doc, dest);
6473     EXPECT_HR(hr, S_OK);
6474 
6475     /* loaded data contains xml declaration */
6476     hr = IXMLDOMDocument_loadXML(doc, _bstr_(win1252xml), &b);
6477     EXPECT_HR(hr, S_OK);
6478 
6479     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6480     ok(hr == S_OK, "got 0x%08x\n", hr);
6481     V_VT(&dest) = VT_UNKNOWN;
6482     V_UNKNOWN(&dest) = (IUnknown*)stream;
6483     hr = IXMLDOMDocument_save(doc, dest);
6484     EXPECT_HR(hr, S_OK);
6485 
6486     hr = GetHGlobalFromStream(stream, &global);
6487     EXPECT_HR(hr, S_OK);
6488     ptr = GlobalLock(global);
6489     ok(!memcmp(ptr, win1252decl, strlen(win1252decl)), "got wrong xml declaration\n");
6490     GlobalUnlock(global);
6491     IStream_Release(stream);
6492 
6493     /* loaded data without xml declaration */
6494     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<a/>"), &b);
6495     EXPECT_HR(hr, S_OK);
6496 
6497     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6498     ok(hr == S_OK, "got 0x%08x\n", hr);
6499     V_VT(&dest) = VT_UNKNOWN;
6500     V_UNKNOWN(&dest) = (IUnknown*)stream;
6501     hr = IXMLDOMDocument_save(doc, dest);
6502     EXPECT_HR(hr, S_OK);
6503 
6504     hr = GetHGlobalFromStream(stream, &global);
6505     EXPECT_HR(hr, S_OK);
6506     ptr = GlobalLock(global);
6507     ok(ptr[0] == '<' && ptr[1] != '?', "got wrong start tag %c%c\n", ptr[0], ptr[1]);
6508     GlobalUnlock(global);
6509     IStream_Release(stream);
6510 
6511     IXMLDOMDocument_Release(doc);
6512     free_bstrs();
6513 }
6514 
6515 static void test_testTransforms(void)
6516 {
6517     IXMLDOMDocument *doc, *docSS;
6518     IXMLDOMNode *pNode;
6519     VARIANT_BOOL bSucc;
6520     HRESULT hr;
6521 
6522     doc = create_document(&IID_IXMLDOMDocument);
6523     docSS = create_document(&IID_IXMLDOMDocument);
6524 
6525     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &bSucc);
6526     ok(hr == S_OK, "ret %08x\n", hr );
6527 
6528     hr = IXMLDOMDocument_loadXML(docSS, _bstr_(szTransformSSXML), &bSucc);
6529     ok(hr == S_OK, "ret %08x\n", hr );
6530 
6531     hr = IXMLDOMDocument_QueryInterface(docSS, &IID_IXMLDOMNode, (void**)&pNode );
6532     ok(hr == S_OK, "ret %08x\n", hr );
6533     if(hr == S_OK)
6534     {
6535         BSTR bOut;
6536 
6537         hr = IXMLDOMDocument_transformNode(doc, pNode, &bOut);
6538         ok(hr == S_OK, "ret %08x\n", hr );
6539         if(hr == S_OK)
6540         {
6541             ok( compareIgnoreReturns( bOut, _bstr_(szTransformOutput)), "got output %s\n", wine_dbgstr_w(bOut));
6542             SysFreeString(bOut);
6543         }
6544 
6545         IXMLDOMNode_Release(pNode);
6546     }
6547 
6548     IXMLDOMDocument_Release(docSS);
6549     IXMLDOMDocument_Release(doc);
6550 
6551     free_bstrs();
6552 }
6553 
6554 struct namespaces_change_t {
6555     const CLSID *clsid;
6556     const char *name;
6557 };
6558 
6559 static const struct namespaces_change_t namespaces_change_test_data[] = {
6560     { &CLSID_DOMDocument,   "CLSID_DOMDocument"   },
6561     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2"  },
6562     { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
6563     { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
6564     { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
6565     { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
6566     { 0 }
6567 };
6568 
6569 static void test_namespaces_change(void)
6570 {
6571     const struct namespaces_change_t *class_ptr = namespaces_change_test_data;
6572 
6573     while (class_ptr->clsid)
6574     {
6575         IXMLDOMDocument *doc = NULL;
6576         IXMLDOMElement *elem = NULL;
6577         IXMLDOMNode *node = NULL;
6578 
6579         VARIANT var;
6580         HRESULT hr;
6581         BSTR str;
6582 
6583         if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
6584         {
6585             class_ptr++;
6586             continue;
6587         }
6588 
6589         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
6590                               &IID_IXMLDOMDocument, (void**)&doc);
6591         ok(hr == S_OK, "got 0x%08x\n", hr);
6592 
6593         V_VT(&var) = VT_I2;
6594         V_I2(&var) = NODE_ELEMENT;
6595 
6596         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("ns:elem"), _bstr_("ns/uri"), &node);
6597         EXPECT_HR(hr, S_OK);
6598 
6599         hr = IXMLDOMDocument_appendChild(doc, node, NULL);
6600         EXPECT_HR(hr, S_OK);
6601 
6602         hr = IXMLDOMDocument_get_documentElement(doc, &elem);
6603         EXPECT_HR(hr, S_OK);
6604 
6605         /* try same prefix, different uri */
6606         V_VT(&var) = VT_BSTR;
6607         V_BSTR(&var) = _bstr_("ns/uri2");
6608 
6609         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6610         EXPECT_HR(hr, E_INVALIDARG);
6611 
6612         /* try same prefix and uri */
6613         V_VT(&var) = VT_BSTR;
6614         V_BSTR(&var) = _bstr_("ns/uri");
6615 
6616         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6617         EXPECT_HR(hr, S_OK);
6618 
6619         hr = IXMLDOMElement_get_xml(elem, &str);
6620         EXPECT_HR(hr, S_OK);
6621         ok(!lstrcmpW(str, _bstr_("<ns:elem xmlns:ns=\"ns/uri\"/>")), "got element %s for %s\n",
6622            wine_dbgstr_w(str), class_ptr->name);
6623         SysFreeString(str);
6624 
6625         IXMLDOMElement_Release(elem);
6626         IXMLDOMDocument_Release(doc);
6627 
6628         free_bstrs();
6629 
6630         class_ptr++;
6631     }
6632 }
6633 
6634 static void test_namespaces_basic(void)
6635 {
6636     static const CHAR namespaces_xmlA[] =
6637         "<?xml version=\"1.0\"?>\n"
6638         "<XMI xmi.version=\"1.1\" xmlns:Model=\"http://omg.org/mof.Model/1.3\">"
6639         "  <XMI.content>"
6640         "    <Model:Package name=\"WinePackage\" Model:name2=\"name2 attr\" />"
6641         "  </XMI.content>"
6642         "</XMI>";
6643 
6644     IXMLDOMDocument *doc;
6645     IXMLDOMElement *elem;
6646     IXMLDOMNode *node;
6647 
6648     VARIANT_BOOL b;
6649     HRESULT hr;
6650     BSTR str;
6651 
6652     doc = create_document(&IID_IXMLDOMDocument);
6653 
6654     hr = IXMLDOMDocument_loadXML(doc, _bstr_(namespaces_xmlA), &b);
6655     EXPECT_HR(hr, S_OK);
6656     ok(b == VARIANT_TRUE, "got %d\n", b);
6657 
6658     str = (void *)0xdeadbeef;
6659     hr = IXMLDOMDocument_get_namespaceURI(doc, &str);
6660     EXPECT_HR(hr, S_FALSE);
6661     ok(str == NULL, "got %p\n", str);
6662 
6663     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("//XMI.content"), &node );
6664     EXPECT_HR(hr, S_OK);
6665     if(hr == S_OK)
6666     {
6667         IXMLDOMAttribute *attr;
6668         IXMLDOMNode *node2;
6669 
6670         hr = IXMLDOMNode_get_firstChild(node, &node2);
6671         EXPECT_HR(hr, S_OK);
6672         ok(node2 != NULL, "got %p\n", node2);
6673 
6674         /* Test get_prefix */
6675         hr = IXMLDOMNode_get_prefix(node2, NULL);
6676         EXPECT_HR(hr, E_INVALIDARG);
6677         /* NOTE: Need to test that arg2 gets cleared on Error. */
6678 
6679         hr = IXMLDOMNode_get_prefix(node2, &str);
6680         EXPECT_HR(hr, S_OK);
6681         ok( !lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6682         SysFreeString(str);
6683 
6684         hr = IXMLDOMNode_get_nodeName(node2, &str);
6685         EXPECT_HR(hr, S_OK);
6686         ok(!lstrcmpW( str, _bstr_("Model:Package")), "got %s\n", wine_dbgstr_w(str));
6687         SysFreeString(str);
6688 
6689         /* Test get_namespaceURI */
6690         hr = IXMLDOMNode_get_namespaceURI(node2, NULL);
6691         EXPECT_HR(hr, E_INVALIDARG);
6692         /* NOTE: Need to test that arg2 gets cleared on Error. */
6693 
6694         hr = IXMLDOMNode_get_namespaceURI(node2, &str);
6695         EXPECT_HR(hr, S_OK);
6696         ok(!lstrcmpW( str, _bstr_("http://omg.org/mof.Model/1.3")), "got %s\n", wine_dbgstr_w(str));
6697         SysFreeString(str);
6698 
6699         hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&elem);
6700         EXPECT_HR(hr, S_OK);
6701 
6702         hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("Model:name2"), &attr);
6703         EXPECT_HR(hr, S_OK);
6704 
6705         hr = IXMLDOMAttribute_get_nodeName(attr, &str);
6706         EXPECT_HR(hr, S_OK);
6707         ok(!lstrcmpW( str, _bstr_("Model:name2")), "got %s\n", wine_dbgstr_w(str));
6708         SysFreeString(str);
6709 
6710         hr = IXMLDOMAttribute_get_prefix(attr, &str);
6711         EXPECT_HR(hr, S_OK);
6712         ok(!lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6713         SysFreeString(str);
6714 
6715         IXMLDOMAttribute_Release(attr);
6716         IXMLDOMElement_Release(elem);
6717 
6718         IXMLDOMNode_Release(node2);
6719         IXMLDOMNode_Release(node);
6720     }
6721 
6722     IXMLDOMDocument_Release(doc);
6723 
6724     free_bstrs();
6725 }
6726 
6727 static void test_FormattingXML(void)
6728 {
6729     IXMLDOMDocument *doc;
6730     IXMLDOMElement *pElement;
6731     VARIANT_BOOL bSucc;
6732     HRESULT hr;
6733     BSTR str;
6734     static const CHAR szLinefeedXML[] = "<?xml version=\"1.0\"?>\n<Root>\n\t<Sub val=\"A\" />\n</Root>";
6735     static const CHAR szLinefeedRootXML[] = "<Root>\r\n\t<Sub val=\"A\"/>\r\n</Root>";
6736 
6737     doc = create_document(&IID_IXMLDOMDocument);
6738 
6739     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szLinefeedXML), &bSucc);
6740     ok(hr == S_OK, "ret %08x\n", hr );
6741     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6742 
6743     if(bSucc == VARIANT_TRUE)
6744     {
6745         hr = IXMLDOMDocument_get_documentElement(doc, &pElement);
6746         ok(hr == S_OK, "ret %08x\n", hr );
6747         if(hr == S_OK)
6748         {
6749             hr = IXMLDOMElement_get_xml(pElement, &str);
6750             ok(hr == S_OK, "ret %08x\n", hr );
6751             ok( !lstrcmpW( str, _bstr_(szLinefeedRootXML) ), "incorrect element xml\n");
6752             SysFreeString(str);
6753 
6754             IXMLDOMElement_Release(pElement);
6755         }
6756     }
6757 
6758     IXMLDOMDocument_Release(doc);
6759 
6760     free_bstrs();
6761 }
6762 
6763 typedef struct _nodetypedvalue_t {
6764     const char *name;
6765     VARTYPE type;
6766     const char *value; /* value in string format */
6767 } nodetypedvalue_t;
6768 
6769 static const nodetypedvalue_t get_nodetypedvalue[] = {
6770     { "root/string",    VT_BSTR, "Wine" },
6771     { "root/string2",   VT_BSTR, "String" },
6772     { "root/number",    VT_BSTR, "12.44" },
6773     { "root/number2",   VT_BSTR, "-3.71e3" },
6774     { "root/int",       VT_I4,   "-13" },
6775     { "root/fixed",     VT_CY,   "7322.9371" },
6776     { "root/bool",      VT_BOOL, "-1" },
6777     { "root/datetime",  VT_DATE, "40135.14" },
6778     { "root/datetimetz",VT_DATE, "37813.59" },
6779     { "root/date",      VT_DATE, "665413" },
6780     { "root/time",      VT_DATE, "0.5813889" },
6781     { "root/timetz",    VT_DATE, "1.112512" },
6782     { "root/i1",        VT_I1,   "-13" },
6783     { "root/i2",        VT_I2,   "31915" },
6784     { "root/i4",        VT_I4,   "-312232" },
6785     { "root/ui1",       VT_UI1,  "123" },
6786     { "root/ui2",       VT_UI2,  "48282" },
6787     { "root/ui4",       VT_UI4,  "949281" },
6788     { "root/r4",        VT_R4,   "213124" },
6789     { "root/r8",        VT_R8,   "0.412" },
6790     { "root/float",     VT_R8,   "41221.421" },
6791     { "root/uuid",      VT_BSTR, "333C7BC4-460F-11D0-BC04-0080C7055a83" },
6792     { "root/binbase64", VT_ARRAY|VT_UI1, "base64 test" },
6793     { "root/binbase64_1", VT_ARRAY|VT_UI1, "base64 test" },
6794     { "root/binbase64_2", VT_ARRAY|VT_UI1, "base64 test" },
6795     { 0 }
6796 };
6797 
6798 static void test_nodeTypedValue(void)
6799 {
6800     const nodetypedvalue_t *entry = get_nodetypedvalue;
6801     IXMLDOMDocumentType *doctype, *doctype2;
6802     IXMLDOMProcessingInstruction *pi;
6803     IXMLDOMDocumentFragment *frag;
6804     IXMLDOMDocument *doc, *doc2;
6805     IXMLDOMCDATASection *cdata;
6806     IXMLDOMComment *comment;
6807     IXMLDOMNode *node;
6808     VARIANT_BOOL b;
6809     VARIANT value;
6810     HRESULT hr;
6811 
6812     doc = create_document(&IID_IXMLDOMDocument);
6813 
6814     b = VARIANT_FALSE;
6815     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &b);
6816     ok(hr == S_OK, "ret %08x\n", hr );
6817     ok(b == VARIANT_TRUE, "got %d\n", b);
6818 
6819     hr = IXMLDOMDocument_get_nodeValue(doc, NULL);
6820     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6821 
6822     V_VT(&value) = VT_BSTR;
6823     V_BSTR(&value) = NULL;
6824     hr = IXMLDOMDocument_get_nodeValue(doc, &value);
6825     ok(hr == S_FALSE, "ret %08x\n", hr );
6826     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6827 
6828     hr = IXMLDOMDocument_get_nodeTypedValue(doc, NULL);
6829     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6830 
6831     V_VT(&value) = VT_EMPTY;
6832     hr = IXMLDOMDocument_get_nodeTypedValue(doc, &value);
6833     ok(hr == S_FALSE, "ret %08x\n", hr );
6834     ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6835 
6836     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/string"), &node);
6837     ok(hr == S_OK, "ret %08x\n", hr );
6838 
6839     V_VT(&value) = VT_BSTR;
6840     V_BSTR(&value) = NULL;
6841     hr = IXMLDOMNode_get_nodeValue(node, &value);
6842     ok(hr == S_FALSE, "ret %08x\n", hr );
6843     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6844 
6845     hr = IXMLDOMNode_get_nodeTypedValue(node, NULL);
6846     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6847 
6848     IXMLDOMNode_Release(node);
6849 
6850     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/binhex"), &node);
6851     ok(hr == S_OK, "ret %08x\n", hr );
6852     {
6853         BYTE bytes[] = {0xff,0xfc,0xa0,0x12,0x00,0x3c};
6854 
6855         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6856         ok(hr == S_OK, "ret %08x\n", hr );
6857         ok(V_VT(&value) == (VT_ARRAY|VT_UI1), "incorrect type\n");
6858         ok(V_ARRAY(&value)->rgsabound[0].cElements == 6, "incorrect array size\n");
6859         if(V_ARRAY(&value)->rgsabound[0].cElements == 6)
6860             ok(!memcmp(bytes, V_ARRAY(&value)->pvData, sizeof(bytes)), "incorrect value\n");
6861         VariantClear(&value);
6862         IXMLDOMNode_Release(node);
6863     }
6864 
6865     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("foo"), _bstr_("value"), &pi);
6866     ok(hr == S_OK, "ret %08x\n", hr );
6867     {
6868         V_VT(&value) = VT_NULL;
6869         V_BSTR(&value) = (void*)0xdeadbeef;
6870         hr = IXMLDOMProcessingInstruction_get_nodeTypedValue(pi, &value);
6871         ok(hr == S_OK, "ret %08x\n", hr );
6872         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6873         ok(!lstrcmpW(V_BSTR(&value), _bstr_("value")), "got wrong value\n");
6874         IXMLDOMProcessingInstruction_Release(pi);
6875         VariantClear(&value);
6876     }
6877 
6878     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("[1]*2=3; &gee that's not right!"), &cdata);
6879     ok(hr == S_OK, "ret %08x\n", hr );
6880     {
6881         V_VT(&value) = VT_NULL;
6882         V_BSTR(&value) = (void*)0xdeadbeef;
6883         hr = IXMLDOMCDATASection_get_nodeTypedValue(cdata, &value);
6884         ok(hr == S_OK, "ret %08x\n", hr );
6885         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6886         ok(!lstrcmpW(V_BSTR(&value), _bstr_("[1]*2=3; &gee that's not right!")), "got wrong value\n");
6887         IXMLDOMCDATASection_Release(cdata);
6888         VariantClear(&value);
6889     }
6890 
6891     hr = IXMLDOMDocument_createComment(doc, _bstr_("comment"), &comment);
6892     ok(hr == S_OK, "ret %08x\n", hr );
6893     {
6894         V_VT(&value) = VT_NULL;
6895         V_BSTR(&value) = (void*)0xdeadbeef;
6896         hr = IXMLDOMComment_get_nodeTypedValue(comment, &value);
6897         ok(hr == S_OK, "ret %08x\n", hr );
6898         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6899         ok(!lstrcmpW(V_BSTR(&value), _bstr_("comment")), "got wrong value\n");
6900         IXMLDOMComment_Release(comment);
6901         VariantClear(&value);
6902     }
6903 
6904     hr = IXMLDOMDocument_createDocumentFragment(doc, &frag);
6905     ok(hr == S_OK, "ret %08x\n", hr );
6906     {
6907         V_VT(&value) = VT_EMPTY;
6908         hr = IXMLDOMDocumentFragment_get_nodeTypedValue(frag, &value);
6909         ok(hr == S_FALSE, "ret %08x\n", hr );
6910         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6911         IXMLDOMDocumentFragment_Release(frag);
6912     }
6913 
6914     doc2 = create_document(&IID_IXMLDOMDocument);
6915 
6916     b = VARIANT_FALSE;
6917     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szEmailXML), &b);
6918     ok(hr == S_OK, "ret %08x\n", hr );
6919     ok(b == VARIANT_TRUE, "got %d\n", b);
6920 
6921     EXPECT_REF(doc2, 1);
6922 
6923     hr = IXMLDOMDocument_get_doctype(doc2, &doctype);
6924     ok(hr == S_OK, "ret %08x\n", hr );
6925 
6926     EXPECT_REF(doc2, 1);
6927     todo_wine EXPECT_REF(doctype, 2);
6928 
6929     {
6930         V_VT(&value) = VT_EMPTY;
6931         hr = IXMLDOMDocumentType_get_nodeTypedValue(doctype, &value);
6932         ok(hr == S_FALSE, "ret %08x\n", hr );
6933         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6934     }
6935 
6936     hr = IXMLDOMDocument_get_doctype(doc2, &doctype2);
6937     ok(hr == S_OK, "ret %08x\n", hr );
6938     ok(doctype != doctype2, "got %p, was %p\n", doctype2, doctype);
6939 
6940     IXMLDOMDocumentType_Release(doctype2);
6941     IXMLDOMDocumentType_Release(doctype);
6942 
6943     IXMLDOMDocument_Release(doc2);
6944 
6945     while (entry->name)
6946     {
6947         hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_(entry->name), &node);
6948         ok(hr == S_OK, "ret %08x\n", hr );
6949 
6950         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6951         ok(hr == S_OK, "ret %08x\n", hr );
6952         ok(V_VT(&value) == entry->type, "incorrect type, expected %d, got %d\n", entry->type, V_VT(&value));
6953 
6954         if (entry->type == (VT_ARRAY|VT_UI1))
6955         {
6956             ok(V_ARRAY(&value)->rgsabound[0].cElements == strlen(entry->value),
6957                "incorrect array size %d\n", V_ARRAY(&value)->rgsabound[0].cElements);
6958         }
6959 
6960         if (entry->type != VT_BSTR)
6961         {
6962            if (entry->type == VT_DATE ||
6963                entry->type == VT_R8 ||
6964                entry->type == VT_CY)
6965            {
6966                if (entry->type == VT_DATE)
6967                {
6968                    hr = VariantChangeType(&value, &value, 0, VT_R4);
6969                    ok(hr == S_OK, "ret %08x\n", hr );
6970                }
6971                hr = VariantChangeTypeEx(&value, &value,
6972                                         MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT),
6973                                         VARIANT_NOUSEROVERRIDE, VT_BSTR);
6974                ok(hr == S_OK, "ret %08x\n", hr );
6975            }
6976            else
6977            {
6978                hr = VariantChangeType(&value, &value, 0, VT_BSTR);
6979                ok(hr == S_OK, "ret %08x\n", hr );
6980            }
6981 
6982            /* for byte array from VT_ARRAY|VT_UI1 it's not a WCHAR buffer */
6983            if (entry->type == (VT_ARRAY|VT_UI1))
6984            {
6985                ok(!memcmp( V_BSTR(&value), entry->value, strlen(entry->value)),
6986                   "expected %s\n", entry->value);
6987            }
6988            else
6989                ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
6990                   "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
6991         }
6992         else
6993            ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
6994                "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
6995 
6996         VariantClear( &value );
6997         IXMLDOMNode_Release(node);
6998 
6999         entry++;
7000     }
7001 
7002     IXMLDOMDocument_Release(doc);
7003     free_bstrs();
7004 }
7005 
7006 static void test_TransformWithLoadingLocalFile(void)
7007 {
7008     IXMLDOMDocument *doc;
7009     IXMLDOMDocument *xsl;
7010     IXMLDOMNode *pNode;
7011     VARIANT_BOOL bSucc;
7012     HRESULT hr;
7013     HANDLE file;
7014     DWORD dwWritten;
7015     char lpPathBuffer[MAX_PATH];
7016     int i;
7017 
7018     /* Create a Temp File. */
7019     GetTempPathA(MAX_PATH, lpPathBuffer);
7020     strcat(lpPathBuffer, "customers.xml" );
7021 
7022     file = CreateFileA(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
7023     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
7024     if(file == INVALID_HANDLE_VALUE)
7025         return;
7026 
7027     WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL);
7028     CloseHandle(file);
7029 
7030     /* Correct path to not include an escape character. */
7031     for(i=0; i < strlen(lpPathBuffer); i++)
7032     {
7033         if(lpPathBuffer[i] == '\\')
7034             lpPathBuffer[i] = '/';
7035     }
7036 
7037     doc = create_document(&IID_IXMLDOMDocument);
7038     xsl = create_document(&IID_IXMLDOMDocument);
7039 
7040     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &bSucc);
7041     ok(hr == S_OK, "ret %08x\n", hr );
7042     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7043     if(bSucc == VARIANT_TRUE)
7044     {
7045         BSTR sXSL;
7046         BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1);
7047         BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2);
7048         BSTR sFileName = _bstr_(lpPathBuffer);
7049         int nLength = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1;
7050 
7051         sXSL = SysAllocStringLen(NULL, nLength);
7052         lstrcpyW(sXSL, sPart1);
7053         lstrcatW(sXSL, sFileName);
7054         lstrcatW(sXSL, sPart2);
7055 
7056         hr = IXMLDOMDocument_loadXML(xsl, sXSL, &bSucc);
7057         ok(hr == S_OK, "ret %08x\n", hr );
7058         ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7059         if(bSucc == VARIANT_TRUE)
7060         {
7061             BSTR sResult;
7062 
7063             hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (void**)&pNode );
7064             ok(hr == S_OK, "ret %08x\n", hr );
7065             if(hr == S_OK)
7066             {
7067                 /* This will load the temp file via the XSL */
7068                 hr = IXMLDOMDocument_transformNode(doc, pNode, &sResult);
7069                 ok(hr == S_OK, "ret %08x\n", hr );
7070                 if(hr == S_OK)
7071                 {
7072                     ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n");
7073                     SysFreeString(sResult);
7074                 }
7075 
7076                 IXMLDOMNode_Release(pNode);
7077             }
7078         }
7079 
7080         SysFreeString(sXSL);
7081     }
7082 
7083     IXMLDOMDocument_Release(doc);
7084     IXMLDOMDocument_Release(xsl);
7085 
7086     DeleteFileA(lpPathBuffer);
7087     free_bstrs();
7088 }
7089 
7090 static void test_put_nodeValue(void)
7091 {
7092     static const WCHAR jeevesW[] = {'J','e','e','v','e','s',' ','&',' ','W','o','o','s','t','e','r',0};
7093     IXMLDOMDocument *doc;
7094     IXMLDOMText *text;
7095     IXMLDOMEntityReference *entityref;
7096     IXMLDOMAttribute *attr;
7097     IXMLDOMNode *node;
7098     HRESULT hr;
7099     VARIANT data, type;
7100 
7101     doc = create_document(&IID_IXMLDOMDocument);
7102 
7103     /* test for unsupported types */
7104     /* NODE_DOCUMENT */
7105     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&node);
7106     ok(hr == S_OK, "ret %08x\n", hr );
7107     V_VT(&data) = VT_BSTR;
7108     V_BSTR(&data) = _bstr_("one two three");
7109     hr = IXMLDOMNode_put_nodeValue(node, data);
7110     ok(hr == E_FAIL, "ret %08x\n", hr );
7111     IXMLDOMNode_Release(node);
7112 
7113     /* NODE_DOCUMENT_FRAGMENT */
7114     V_VT(&type) = VT_I1;
7115     V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
7116     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7117     ok(hr == S_OK, "ret %08x\n", hr );
7118     V_VT(&data) = VT_BSTR;
7119     V_BSTR(&data) = _bstr_("one two three");
7120     hr = IXMLDOMNode_put_nodeValue(node, data);
7121     ok(hr == E_FAIL, "ret %08x\n", hr );
7122     IXMLDOMNode_Release(node);
7123 
7124     /* NODE_ELEMENT */
7125     V_VT(&type) = VT_I1;
7126     V_I1(&type) = NODE_ELEMENT;
7127     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7128     ok(hr == S_OK, "ret %08x\n", hr );
7129     V_VT(&data) = VT_BSTR;
7130     V_BSTR(&data) = _bstr_("one two three");
7131     hr = IXMLDOMNode_put_nodeValue(node, data);
7132     ok(hr == E_FAIL, "ret %08x\n", hr );
7133     IXMLDOMNode_Release(node);
7134 
7135     /* NODE_ENTITY_REFERENCE */
7136     hr = IXMLDOMDocument_createEntityReference(doc, _bstr_("ref"), &entityref);
7137     ok(hr == S_OK, "ret %08x\n", hr );
7138 
7139     V_VT(&data) = VT_BSTR;
7140     V_BSTR(&data) = _bstr_("one two three");
7141     hr = IXMLDOMEntityReference_put_nodeValue(entityref, data);
7142     ok(hr == E_FAIL, "ret %08x\n", hr );
7143 
7144     hr = IXMLDOMEntityReference_QueryInterface(entityref, &IID_IXMLDOMNode, (void**)&node);
7145     ok(hr == S_OK, "ret %08x\n", hr );
7146     V_VT(&data) = VT_BSTR;
7147     V_BSTR(&data) = _bstr_("one two three");
7148     hr = IXMLDOMNode_put_nodeValue(node, data);
7149     ok(hr == E_FAIL, "ret %08x\n", hr );
7150     IXMLDOMNode_Release(node);
7151     IXMLDOMEntityReference_Release(entityref);
7152 
7153     /* supported types */
7154     hr = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &text);
7155     ok(hr == S_OK, "ret %08x\n", hr );
7156     V_VT(&data) = VT_BSTR;
7157     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7158     hr = IXMLDOMText_put_nodeValue(text, data);
7159     ok(hr == S_OK, "ret %08x\n", hr );
7160     IXMLDOMText_Release(text);
7161 
7162     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
7163     ok(hr == S_OK, "ret %08x\n", hr );
7164     V_VT(&data) = VT_BSTR;
7165     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7166     hr = IXMLDOMAttribute_put_nodeValue(attr, data);
7167     ok(hr == S_OK, "ret %08x\n", hr );
7168     hr = IXMLDOMAttribute_get_nodeValue(attr, &data);
7169     ok(hr == S_OK, "ret %08x\n", hr );
7170     ok(memcmp(V_BSTR(&data), jeevesW, sizeof(jeevesW)) == 0, "got %s\n",
7171         wine_dbgstr_w(V_BSTR(&data)));
7172     VariantClear(&data);
7173     IXMLDOMAttribute_Release(attr);
7174 
7175     free_bstrs();
7176 
7177     IXMLDOMDocument_Release(doc);
7178 }
7179 
7180 static void test_IObjectSafety(void)
7181 {
7182     IXMLDOMDocument *doc;
7183     IObjectSafety *safety;
7184     HRESULT hr;
7185 
7186     doc = create_document(&IID_IXMLDOMDocument);
7187 
7188     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IObjectSafety, (void**)&safety);
7189     ok(hr == S_OK, "ret %08x\n", hr );
7190 
7191     test_IObjectSafety_common(safety);
7192 
7193     IObjectSafety_Release(safety);
7194     IXMLDOMDocument_Release(doc);
7195 
7196     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
7197         &IID_IObjectSafety, (void**)&safety);
7198     ok(hr == S_OK, "Could not create XMLHTTPRequest instance: %08x\n", hr);
7199 
7200     test_IObjectSafety_common(safety);
7201 
7202     IObjectSafety_Release(safety);
7203 
7204 }
7205 
7206 typedef struct _property_test_t {
7207     const GUID *guid;
7208     const char *clsid;
7209     const char *property;
7210     const char *value;
7211 } property_test_t;
7212 
7213 static const property_test_t properties_test_data[] = {
7214     { &CLSID_DOMDocument,  "CLSID_DOMDocument" , "SelectionLanguage", "XSLPattern" },
7215     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2" , "SelectionLanguage", "XSLPattern" },
7216     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "SelectionLanguage", "XSLPattern" },
7217     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "SelectionLanguage", "XPath" },
7218     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "SelectionLanguage", "XPath" },
7219     { 0 }
7220 };
7221 
7222 static void test_default_properties(void)
7223 {
7224     const property_test_t *entry = properties_test_data;
7225 
7226     while (entry->guid)
7227     {
7228         IXMLDOMDocument2 *doc;
7229         VARIANT var;
7230         HRESULT hr;
7231 
7232         if (!is_clsid_supported(entry->guid, &IID_IXMLDOMDocument2))
7233         {
7234             entry++;
7235             continue;
7236         }
7237 
7238         hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
7239         ok(hr == S_OK, "got 0x%08x\n", hr);
7240 
7241         hr = IXMLDOMDocument2_getProperty(doc, _bstr_(entry->property), &var);
7242         ok(hr == S_OK, "got 0x%08x\n", hr);
7243         ok(lstrcmpW(V_BSTR(&var), _bstr_(entry->value)) == 0, "expected %s, for %s\n",
7244            entry->value, entry->clsid);
7245         VariantClear(&var);
7246 
7247         IXMLDOMDocument2_Release(doc);
7248 
7249         entry++;
7250     }
7251 }
7252 
7253 typedef struct {
7254     const char *query;
7255     const char *list;
7256     BOOL todo;
7257 } xslpattern_test_t;
7258 
7259 static const xslpattern_test_t xslpattern_test[] = {
7260     { "root//elem[0]", "E1.E2.D1" },
7261     { "root//elem[index()=1]", "E2.E2.D1" },
7262     { "root//elem[index() $eq$ 1]", "E2.E2.D1" },
7263     { "root//elem[end()]", "E4.E2.D1" },
7264     { "root//elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7265     { "root//elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7266     { "root//elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7267     { "root//elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7268     { "root//elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7269     { "root//elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7270     { "root//elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7271     { "root//elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7272     { "root//elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7273     { "root//elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7274     { "root//elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7275     { "root//elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7276     { "root//elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7277     { "root//elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7278     { "root//elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7279     { "root//elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7280     { "root//elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7281     { "root//elem[$any$ *='B2 field']", "E2.E2.D1" },
7282     { "root//elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7283     { "root//elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7284     { "root//elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7285     { "root//elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7286     { "root//elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7287     { "root//elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7288     { "root//elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7289     { "root/elem[0]", "E1.E2.D1" },
7290     { "root/elem[index()=1]", "E2.E2.D1" },
7291     { "root/elem[index() $eq$ 1]", "E2.E2.D1" },
7292     { "root/elem[end()]", "E4.E2.D1" },
7293     { "root/elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7294     { "root/elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7295     { "root/elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7296     { "root/elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7297     { "root/elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7298     { "root/elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7299     { "root/elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7300     { "root/elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7301     { "root/elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7302     { "root/elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7303     { "root/elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7304     { "root/elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7305     { "root/elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7306     { "root/elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7307     { "root/elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7308     { "root/elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7309     { "root/elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7310     { "root/elem[$any$ *='B2 field']", "E2.E2.D1" },
7311     { "root/elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7312     { "root/elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7313     { "root/elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7314     { "root/elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7315     { "root/elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7316     { "root/elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7317     { "root/elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7318     { "root/elem[d]", "E1.E2.D1 E2.E2.D1 E4.E2.D1" },
7319     { "root/elem[@*]", "E2.E2.D1 E3.E2.D1", TRUE },
7320     { NULL }
7321 };
7322 
7323 static const xslpattern_test_t xslpattern_test_no_ns[] = {
7324     /* prefixes don't need to be registered, you may use them as they are in the doc */
7325     { "//bar:x", "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1" },
7326     /* prefixes must be explicitly specified in the name */
7327     { "//foo:elem", "" },
7328     { "//foo:c", "E3.E4.E2.D1" },
7329     { NULL }
7330 };
7331 
7332 static const xslpattern_test_t xslpattern_test_func[] = {
7333     { "attribute()", "" },
7334     { "attribute('depth')", "" },
7335     { "root/attribute('depth')", "A'depth'.E3.D1" },
7336     { "//x/attribute()", "A'id'.E3.E3.D1 A'depth'.E3.E3.D1" },
7337     { "//x//attribute(id)", NULL },
7338     { "//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" },
7339     { "comment()", "C2.D1" },
7340     { "//comment()", "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1" },
7341     { "element()", "E3.D1" },
7342     { "root/y/element()", "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1" },
7343     { "//element(a)", NULL },
7344     { "//element('a')", "E4.E3.E3.D1 E4.E4.E3.D1" },
7345     { "node()", "P1.D1 C2.D1 E3.D1" },
7346     { "//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" },
7347     { "//x/node()[nodeType()=1]", "E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
7348     { "//x/node()[nodeType()=3]", "T3.E3.E3.D1" },
7349     { "//x/node()[nodeType()=7]", "P1.E3.E3.D1" },
7350     { "//x/node()[nodeType()=8]", "C2.E3.E3.D1" },
7351     { "pi()", "P1.D1" },
7352     { "//y/pi()", "P1.E4.E3.D1" },
7353     { "root/textnode()", "T2.E3.D1" },
7354     { "root/element()/textnode()", "T3.E3.E3.D1 T3.E4.E3.D1" },
7355     { NULL }
7356 };
7357 
7358 static void test_XSLPattern(void)
7359 {
7360     const xslpattern_test_t *ptr = xslpattern_test;
7361     IXMLDOMDocument2 *doc;
7362     IXMLDOMNodeList *list;
7363     VARIANT_BOOL b;
7364     HRESULT hr;
7365     LONG len;
7366 
7367     doc = create_document(&IID_IXMLDOMDocument2);
7368 
7369     b = VARIANT_FALSE;
7370     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
7371     EXPECT_HR(hr, S_OK);
7372     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7373 
7374     /* switch to XSLPattern */
7375     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern"));
7376     EXPECT_HR(hr, S_OK);
7377 
7378     /* XPath doesn't select elements with non-null default namespace with unqualified selectors, XSLPattern does */
7379     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem/c"), &list);
7380     EXPECT_HR(hr, S_OK);
7381 
7382     len = 0;
7383     hr = IXMLDOMNodeList_get_length(list, &len);
7384     EXPECT_HR(hr, S_OK);
7385     /* should select <elem><c> and <elem xmlns='...'><c> but not <elem><foo:c> */
7386     ok(len == 3, "expected 3 entries in list, got %d\n", len);
7387     IXMLDOMNodeList_Release(list);
7388 
7389     while (ptr->query)
7390     {
7391         list = NULL;
7392         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7393         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7394         len = 0;
7395         hr = IXMLDOMNodeList_get_length(list, &len);
7396         ok(len != 0, "query=%s, empty list\n", ptr->query);
7397         if (len) {
7398             if (ptr->todo) {
7399                 char *str = list_to_string(list);
7400             todo_wine
7401                 ok(!strcmp(str, ptr->list), "Invalid node list: %s, expected %s\n", str, ptr->list);
7402                 IXMLDOMNodeList_Release(list);
7403             }
7404             else
7405                 expect_list_and_release(list, ptr->list);
7406         }
7407 
7408         ptr++;
7409     }
7410 
7411     /* namespace handling */
7412     /* no registered namespaces */
7413     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_(""));
7414     EXPECT_HR(hr, S_OK);
7415 
7416     ptr = xslpattern_test_no_ns;
7417     while (ptr->query)
7418     {
7419         list = NULL;
7420         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7421         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7422 
7423         if (*ptr->list)
7424         {
7425             len = 0;
7426             hr = IXMLDOMNodeList_get_length(list, &len);
7427             EXPECT_HR(hr, S_OK);
7428             ok(len != 0, "query=%s, empty list\n", ptr->query);
7429         }
7430         else
7431         {
7432             len = 1;
7433             hr = IXMLDOMNodeList_get_length(list, &len);
7434             EXPECT_HR(hr, S_OK);
7435             ok(len == 0, "query=%s, empty list\n", ptr->query);
7436         }
7437         if (len)
7438             expect_list_and_release(list, ptr->list);
7439 
7440         ptr++;
7441     }
7442 
7443     /* explicitly register prefix foo */
7444     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
7445 
7446     /* now we get the same behavior as XPath */
7447     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7448     EXPECT_HR(hr, S_OK);
7449     len = 0;
7450     hr = IXMLDOMNodeList_get_length(list, &len);
7451     EXPECT_HR(hr, S_OK);
7452     ok(len != 0, "expected filled list\n");
7453     if (len)
7454         expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
7455 
7456     /* set prefix foo to some nonexistent namespace */
7457     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:nonexistent-foo'"));
7458     EXPECT_HR(hr, S_OK);
7459 
7460     /* the registered prefix takes precedence */
7461     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7462     EXPECT_HR(hr, S_OK);
7463     len = 0;
7464     hr = IXMLDOMNodeList_get_length(list, &len);
7465     EXPECT_HR(hr, S_OK);
7466     ok(len == 0, "expected empty list\n");
7467     IXMLDOMNodeList_Release(list);
7468 
7469     IXMLDOMDocument2_Release(doc);
7470 
7471     doc = create_document(&IID_IXMLDOMDocument2);
7472 
7473     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szNodeTypesXML), &b);
7474     EXPECT_HR(hr, S_OK);
7475     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7476 
7477     ptr = xslpattern_test_func;
7478     while (ptr->query)
7479     {
7480         list = NULL;
7481         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7482         if (ptr->list)
7483         {
7484             ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7485             len = 0;
7486             hr = IXMLDOMNodeList_get_length(list, &len);
7487             ok(hr == S_OK, "Failed to get list length, hr %#x.\n", hr);
7488             if (*ptr->list)
7489             {
7490                 ok(len != 0, "query=%s, empty list\n", ptr->query);
7491                 if (len)
7492                     expect_list_and_release(list, ptr->list);
7493             }
7494             else
7495                 ok(len == 0, "query=%s, filled list\n", ptr->query);
7496         }
7497         else
7498             ok(hr == E_FAIL, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7499 
7500         ptr++;
7501     }
7502 
7503     IXMLDOMDocument2_Release(doc);
7504     free_bstrs();
7505 }
7506 
7507 static void test_splitText(void)
7508 {
7509     IXMLDOMCDATASection *cdata;
7510     IXMLDOMElement *root;
7511     IXMLDOMDocument *doc;
7512     IXMLDOMText *text, *text2;
7513     IXMLDOMNode *node;
7514     VARIANT var;
7515     VARIANT_BOOL success;
7516     LONG length;
7517     HRESULT hr;
7518 
7519     doc = create_document(&IID_IXMLDOMDocument);
7520 
7521     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<root></root>"), &success);
7522     ok(hr == S_OK, "got 0x%08x\n", hr);
7523 
7524     hr = IXMLDOMDocument_get_documentElement(doc, &root);
7525     ok(hr == S_OK, "got 0x%08x\n", hr);
7526 
7527     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("beautiful plumage"), &cdata);
7528     ok(hr == S_OK, "got 0x%08x\n", hr);
7529 
7530     V_VT(&var) = VT_EMPTY;
7531     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)cdata, NULL);
7532     ok(hr == S_OK, "got 0x%08x\n", hr);
7533 
7534     length = 0;
7535     hr = IXMLDOMCDATASection_get_length(cdata, &length);
7536     ok(hr == S_OK, "got 0x%08x\n", hr);
7537     ok(length > 0, "got %d\n", length);
7538 
7539     hr = IXMLDOMCDATASection_splitText(cdata, 0, NULL);
7540     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7541 
7542     text = (void*)0xdeadbeef;
7543     /* negative offset */
7544     hr = IXMLDOMCDATASection_splitText(cdata, -1, &text);
7545     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7546     ok(text == (void*)0xdeadbeef, "got %p\n", text);
7547 
7548     text = (void*)0xdeadbeef;
7549     /* offset outside data */
7550     hr = IXMLDOMCDATASection_splitText(cdata, length + 1, &text);
7551     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7552     ok(text == 0, "got %p\n", text);
7553 
7554     text = (void*)0xdeadbeef;
7555     /* offset outside data */
7556     hr = IXMLDOMCDATASection_splitText(cdata, length, &text);
7557     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7558     ok(text == 0, "got %p\n", text);
7559 
7560     /* no empty node created */
7561     node = (void*)0xdeadbeef;
7562     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7563     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7564     ok(node == 0, "got %p\n", text);
7565 
7566     hr = IXMLDOMCDATASection_splitText(cdata, 10, &text);
7567     ok(hr == S_OK, "got 0x%08x\n", hr);
7568 
7569     length = 0;
7570     hr = IXMLDOMText_get_length(text, &length);
7571     ok(hr == S_OK, "got 0x%08x\n", hr);
7572     ok(length == 7, "got %d\n", length);
7573 
7574     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7575     ok(hr == S_OK, "got 0x%08x\n", hr);
7576     IXMLDOMNode_Release(node);
7577 
7578     /* split new text node */
7579     hr = IXMLDOMText_get_length(text, &length);
7580     ok(hr == S_OK, "got 0x%08x\n", hr);
7581 
7582     node = (void*)0xdeadbeef;
7583     hr = IXMLDOMText_get_nextSibling(text, &node);
7584     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7585     ok(node == 0, "got %p\n", text);
7586 
7587     hr = IXMLDOMText_splitText(text, 0, NULL);
7588     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7589 
7590     text2 = (void*)0xdeadbeef;
7591     /* negative offset */
7592     hr = IXMLDOMText_splitText(text, -1, &text2);
7593     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7594     ok(text2 == (void*)0xdeadbeef, "got %p\n", text2);
7595 
7596     text2 = (void*)0xdeadbeef;
7597     /* offset outside data */
7598     hr = IXMLDOMText_splitText(text, length + 1, &text2);
7599     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7600     ok(text2 == 0, "got %p\n", text2);
7601 
7602     text2 = (void*)0xdeadbeef;
7603     /* offset outside data */
7604     hr = IXMLDOMText_splitText(text, length, &text2);
7605     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7606     ok(text2 == 0, "got %p\n", text);
7607 
7608     text2 = 0;
7609     hr = IXMLDOMText_splitText(text, 4, &text2);
7610     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7611     if (text2) IXMLDOMText_Release(text2);
7612 
7613     node = 0;
7614     hr = IXMLDOMText_get_nextSibling(text, &node);
7615     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7616     if (node) IXMLDOMNode_Release(node);
7617 
7618     IXMLDOMText_Release(text);
7619     IXMLDOMElement_Release(root);
7620     IXMLDOMCDATASection_Release(cdata);
7621     free_bstrs();
7622 }
7623 
7624 typedef struct {
7625     const char *name;
7626     const char *uri;
7627     HRESULT hr;
7628 } ns_item_t;
7629 
7630 /* default_ns_doc used */
7631 static const ns_item_t qualified_item_tests[] = {
7632     { "xml:lang", NULL, S_FALSE },
7633     { "xml:lang", "http://www.w3.org/XML/1998/namespace", S_FALSE },
7634     { "lang", "http://www.w3.org/XML/1998/namespace", S_OK },
7635     { "ns:b", NULL, S_FALSE },
7636     { "ns:b", "nshref", S_FALSE },
7637     { "b", "nshref", S_OK },
7638     { "d", NULL, S_OK },
7639     { NULL }
7640 };
7641 
7642 static const ns_item_t named_item_tests[] = {
7643     { "xml:lang", NULL, S_OK },
7644     { "lang", NULL, S_FALSE },
7645     { "ns:b", NULL, S_OK },
7646     { "b", NULL, S_FALSE },
7647     { "d", NULL, S_OK },
7648     { NULL }
7649 };
7650 
7651 static void test_getQualifiedItem(void)
7652 {
7653     IXMLDOMNode *pr_node, *node;
7654     IXMLDOMNodeList *root_list;
7655     IXMLDOMNamedNodeMap *map;
7656     IXMLDOMElement *element;
7657     const ns_item_t* ptr;
7658     IXMLDOMDocument *doc;
7659     VARIANT_BOOL b;
7660     HRESULT hr;
7661     LONG len;
7662 
7663     doc = create_document(&IID_IXMLDOMDocument);
7664 
7665     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7666     EXPECT_HR(hr, S_OK);
7667     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7668 
7669     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7670     EXPECT_HR(hr, S_OK);
7671 
7672     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7673     EXPECT_HR(hr, S_OK);
7674 
7675     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7676     EXPECT_HR(hr, S_OK);
7677     IXMLDOMNodeList_Release(root_list);
7678 
7679     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7680     EXPECT_HR(hr, S_OK);
7681     IXMLDOMNode_Release(pr_node);
7682 
7683     len = 0;
7684     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7685     EXPECT_HR(hr, S_OK);
7686     ok( len == 3, "length %d\n", len);
7687 
7688     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, NULL);
7689     EXPECT_HR(hr, E_INVALIDARG);
7690 
7691     node = (void*)0xdeadbeef;
7692     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, &node);
7693     EXPECT_HR(hr, E_INVALIDARG);
7694     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7695 
7696     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, NULL);
7697     EXPECT_HR(hr, E_INVALIDARG);
7698 
7699     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, &node);
7700     EXPECT_HR(hr, S_OK);
7701 
7702     IXMLDOMNode_Release(node);
7703     IXMLDOMNamedNodeMap_Release(map);
7704     IXMLDOMElement_Release(element);
7705 
7706     hr = IXMLDOMDocument_loadXML(doc, _bstr_(default_ns_doc), &b);
7707     EXPECT_HR(hr, S_OK);
7708 
7709     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
7710     EXPECT_HR(hr, S_OK);
7711 
7712     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
7713     EXPECT_HR(hr, S_OK);
7714     IXMLDOMNode_Release(node);
7715 
7716     hr = IXMLDOMElement_get_attributes(element, &map);
7717     EXPECT_HR(hr, S_OK);
7718 
7719     ptr = qualified_item_tests;
7720     while (ptr->name)
7721     {
7722        node = (void*)0xdeadbeef;
7723        hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
7724        ok(hr == ptr->hr, "%s, %s: got 0x%08x, expected 0x%08x\n", ptr->name, ptr->uri, hr, ptr->hr);
7725        if (hr == S_OK)
7726            IXMLDOMNode_Release(node);
7727        else
7728            ok(node == NULL, "%s, %s: got %p\n", ptr->name, ptr->uri, node);
7729        ptr++;
7730     }
7731 
7732     ptr = named_item_tests;
7733     while (ptr->name)
7734     {
7735        node = (void*)0xdeadbeef;
7736        hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_(ptr->name), &node);
7737        ok(hr == ptr->hr, "%s: got 0x%08x, expected 0x%08x\n", ptr->name, hr, ptr->hr);
7738        if (hr == S_OK)
7739            IXMLDOMNode_Release(node);
7740        else
7741            ok(node == NULL, "%s: got %p\n", ptr->name, node);
7742        ptr++;
7743     }
7744 
7745     IXMLDOMNamedNodeMap_Release(map);
7746 
7747     IXMLDOMElement_Release(element);
7748     IXMLDOMDocument_Release(doc);
7749     free_bstrs();
7750 }
7751 
7752 static void test_removeQualifiedItem(void)
7753 {
7754     IXMLDOMDocument *doc;
7755     IXMLDOMElement *element;
7756     IXMLDOMNode *pr_node, *node;
7757     IXMLDOMNodeList *root_list;
7758     IXMLDOMNamedNodeMap *map;
7759     VARIANT_BOOL b;
7760     LONG len;
7761     HRESULT hr;
7762 
7763     doc = create_document(&IID_IXMLDOMDocument);
7764 
7765     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7766     ok( hr == S_OK, "loadXML failed\n");
7767     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7768 
7769     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7770     ok( hr == S_OK, "ret %08x\n", hr);
7771 
7772     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7773     ok( hr == S_OK, "ret %08x\n", hr);
7774 
7775     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7776     ok( hr == S_OK, "ret %08x\n", hr);
7777     IXMLDOMNodeList_Release(root_list);
7778 
7779     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7780     ok( hr == S_OK, "ret %08x\n", hr);
7781     IXMLDOMNode_Release(pr_node);
7782 
7783     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7784     ok( hr == S_OK, "ret %08x\n", hr);
7785     ok( len == 3, "length %d\n", len);
7786 
7787     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, NULL);
7788     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7789 
7790     node = (void*)0xdeadbeef;
7791     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, &node);
7792     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7793     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7794 
7795     /* out pointer is optional */
7796     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7797     ok( hr == S_OK, "ret %08x\n", hr);
7798 
7799     /* already removed */
7800     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7801     ok( hr == S_FALSE, "ret %08x\n", hr);
7802 
7803     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("vr"), NULL, &node);
7804     ok( hr == S_OK, "ret %08x\n", hr);
7805     IXMLDOMNode_Release(node);
7806 
7807     IXMLDOMNamedNodeMap_Release( map );
7808     IXMLDOMElement_Release( element );
7809     IXMLDOMDocument_Release( doc );
7810     free_bstrs();
7811 }
7812 
7813 #define check_default_props(doc) _check_default_props(__LINE__, doc)
7814 static inline void _check_default_props(int line, IXMLDOMDocument2* doc)
7815 {
7816     VARIANT_BOOL b;
7817     VARIANT var;
7818     HRESULT hr;
7819 
7820     VariantInit(&var);
7821     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7822     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XSLPattern")) == 0, "expected XSLPattern\n");
7823     VariantClear(&var);
7824 
7825     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7826     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("")) == 0, "expected empty string\n");
7827     VariantClear(&var);
7828 
7829     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7830     ok_(__FILE__, line)(b == VARIANT_FALSE, "expected FALSE\n");
7831 
7832     hr = IXMLDOMDocument2_get_schemas(doc, &var);
7833     ok_(__FILE__, line)(hr == S_FALSE, "got %08x\n", hr);
7834     VariantClear(&var);
7835 }
7836 
7837 #define check_set_props(doc) _check_set_props(__LINE__, doc)
7838 static inline void _check_set_props(int line, IXMLDOMDocument2* doc)
7839 {
7840     VARIANT_BOOL b;
7841     VARIANT var;
7842 
7843     VariantInit(&var);
7844     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7845     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XPath")) == 0, "expected XPath\n");
7846     VariantClear(&var);
7847 
7848     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7849     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
7850     VariantClear(&var);
7851 
7852     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7853     ok_(__FILE__, line)(b == VARIANT_TRUE, "expected TRUE\n");
7854 
7855     helper_ole_check(IXMLDOMDocument2_get_schemas(doc, &var));
7856     ok_(__FILE__, line)(V_VT(&var) != VT_NULL, "expected pointer\n");
7857     VariantClear(&var);
7858 }
7859 
7860 #define set_props(doc, cache) _set_props(__LINE__, doc, cache)
7861 static inline void _set_props(int line, IXMLDOMDocument2* doc, IXMLDOMSchemaCollection* cache)
7862 {
7863     VARIANT var;
7864 
7865     VariantInit(&var);
7866     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
7867     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:wi=\'www.winehq.org\'")));
7868     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_TRUE));
7869     V_VT(&var) = VT_DISPATCH;
7870     V_DISPATCH(&var) = NULL;
7871     helper_ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&var)));
7872     ok_(__FILE__, line)(V_DISPATCH(&var) != NULL, "expected pointer\n");
7873     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7874     VariantClear(&var);
7875 }
7876 
7877 #define unset_props(doc) _unset_props(__LINE__, doc)
7878 static inline void _unset_props(int line, IXMLDOMDocument2* doc)
7879 {
7880     VARIANT var;
7881 
7882     VariantInit(&var);
7883     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
7884     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("")));
7885     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_FALSE));
7886     V_VT(&var) = VT_NULL;
7887     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7888     VariantClear(&var);
7889 }
7890 
7891 static void test_get_ownerDocument(void)
7892 {
7893     IXMLDOMDocument *doc1, *doc2, *doc3;
7894     IXMLDOMDocument2 *doc, *doc_owner;
7895     IXMLDOMNode *node;
7896     IXMLDOMSchemaCollection *cache;
7897     VARIANT_BOOL b;
7898     VARIANT var;
7899     IXMLDOMElement *element;
7900     IXMLDOMNodeList *node_list;
7901     IXMLDOMAttribute *attr;
7902     LONG i, len;
7903     HRESULT hr;
7904     const CHAR nodeXML[] =
7905     "<root id='0'>"
7906     "   <!-- comment node 0 -->"
7907     "   text node 0"
7908     "   <x attr='val'></x>"
7909     "   <?foo value='PI for x'?>"
7910     "   <![CDATA[ cdata ]]>"
7911     "</root>";
7912 
7913     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
7914     if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
7915 
7916     doc = create_document(&IID_IXMLDOMDocument2);
7917     cache = create_cache(&IID_IXMLDOMSchemaCollection);
7918 
7919     VariantInit(&var);
7920 
7921     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7922     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7923 
7924     check_default_props(doc);
7925 
7926     /* set properties and check that new instances use them */
7927     set_props(doc, cache);
7928     check_set_props(doc);
7929 
7930     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7931     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc1));
7932 
7933     /* new interface keeps props */
7934     ole_check(IXMLDOMDocument_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7935     ok( doc_owner != doc, "got %p, doc %p\n", doc_owner, doc);
7936     check_set_props(doc_owner);
7937     IXMLDOMDocument2_Release(doc_owner);
7938 
7939     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc2));
7940     IXMLDOMNode_Release(node);
7941 
7942     ok(doc1 != doc2, "got %p, expected %p. original %p\n", doc2, doc1, doc);
7943 
7944     /* reload */
7945     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7946     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7947 
7948     /* properties retained even after reload */
7949     check_set_props(doc);
7950 
7951     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7952     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc3));
7953     IXMLDOMNode_Release(node);
7954 
7955     ole_check(IXMLDOMDocument_QueryInterface(doc3, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7956     ok(doc3 != doc1 && doc3 != doc2 && doc_owner != doc, "got %p, (%p, %p, %p)\n", doc3, doc, doc1, doc2);
7957     check_set_props(doc_owner);
7958 
7959     /* changing properties for one instance changes them for all */
7960     unset_props(doc_owner);
7961     check_default_props(doc_owner);
7962     check_default_props(doc);
7963 
7964     /* NULL check */
7965     hr = IXMLDOMDocument_loadXML(doc1, _bstr_(nodeXML), &b);
7966     EXPECT_HR(hr, S_OK);
7967     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7968 
7969     hr = IXMLDOMDocument_get_documentElement(doc1, &element);
7970     EXPECT_HR(hr, S_OK);
7971 
7972     hr = IXMLDOMElement_get_childNodes(element, &node_list);
7973     EXPECT_HR(hr, S_OK);
7974 
7975     hr = IXMLDOMNodeList_get_length(node_list, &len);
7976     EXPECT_HR(hr, S_OK);
7977 
7978     for(i = 0; i < len; i++) {
7979         hr = IXMLDOMNodeList_get_item(node_list, i, &node);
7980         EXPECT_HR(hr, S_OK);
7981 
7982         hr = IXMLDOMNode_get_ownerDocument(node, NULL);
7983         EXPECT_HR(hr, E_INVALIDARG);
7984 
7985         IXMLDOMNode_Release(node);
7986     }
7987     IXMLDOMElement_Release(element);
7988 
7989     /* Test Attribute Node */
7990     hr = IXMLDOMNodeList_get_item(node_list, 2, &node);
7991     EXPECT_HR(hr, S_OK);
7992     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
7993     EXPECT_HR(hr, S_OK);
7994     IXMLDOMNode_Release(node);
7995 
7996     hr = IXMLDOMElement_getAttributeNode(element, _bstr_("attr"), &attr);
7997     EXPECT_HR(hr, S_OK);
7998     ok(attr != NULL, "attr == NULL\n");
7999     IXMLDOMElement_Release(element);
8000     hr = IXMLDOMAttribute_get_ownerDocument(attr, NULL);
8001     EXPECT_HR(hr, E_INVALIDARG);
8002     IXMLDOMAttribute_Release(attr);
8003     IXMLDOMNodeList_Release(node_list);
8004 
8005     IXMLDOMSchemaCollection_Release(cache);
8006     IXMLDOMDocument_Release(doc1);
8007     IXMLDOMDocument_Release(doc2);
8008     IXMLDOMDocument_Release(doc3);
8009     IXMLDOMDocument2_Release(doc);
8010     IXMLDOMDocument2_Release(doc_owner);
8011     free_bstrs();
8012 }
8013 
8014 static void test_setAttributeNode(void)
8015 {
8016     IXMLDOMDocument *doc, *doc2;
8017     IXMLDOMElement *elem, *elem2;
8018     IXMLDOMAttribute *attr, *attr2, *ret_attr;
8019     VARIANT_BOOL b;
8020     HRESULT hr;
8021     VARIANT v;
8022     BSTR str;
8023     ULONG ref1, ref2;
8024 
8025     doc = create_document(&IID_IXMLDOMDocument);
8026 
8027     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8028     ok( hr == S_OK, "loadXML failed\n");
8029     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8030 
8031     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8032     ok( hr == S_OK, "got 0x%08x\n", hr);
8033 
8034     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
8035     ok( hr == S_OK, "got 0x%08x\n", hr);
8036     ok( elem2 != elem, "got same instance\n");
8037 
8038     ret_attr = (void*)0xdeadbeef;
8039     hr = IXMLDOMElement_setAttributeNode(elem, NULL, &ret_attr);
8040     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8041     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8042 
8043     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8044     ok( hr == S_OK, "got 0x%08x\n", hr);
8045 
8046     ref1 = IXMLDOMElement_AddRef(elem);
8047     IXMLDOMElement_Release(elem);
8048 
8049     ret_attr = (void*)0xdeadbeef;
8050     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8051     ok( hr == S_OK, "got 0x%08x\n", hr);
8052     ok( ret_attr == NULL, "got %p\n", ret_attr);
8053 
8054     /* no reference added */
8055     ref2 = IXMLDOMElement_AddRef(elem);
8056     IXMLDOMElement_Release(elem);
8057     ok(ref2 == ref1, "got %d, expected %d\n", ref2, ref1);
8058 
8059     EXPECT_CHILDREN(elem);
8060     EXPECT_CHILDREN(elem2);
8061 
8062     IXMLDOMElement_Release(elem2);
8063 
8064     attr2 = NULL;
8065     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attr"), &attr2);
8066     ok( hr == S_OK, "got 0x%08x\n", hr);
8067     ok( attr2 != attr, "got same instance %p\n", attr2);
8068     IXMLDOMAttribute_Release(attr2);
8069 
8070     /* try to add it another time */
8071     ret_attr = (void*)0xdeadbeef;
8072     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8073     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8074     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8075 
8076     IXMLDOMElement_Release(elem);
8077 
8078     /* initially used element is released, attribute still 'has' a container */
8079     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8080     ok( hr == S_OK, "got 0x%08x\n", hr);
8081     ret_attr = (void*)0xdeadbeef;
8082     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8083     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8084     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8085     IXMLDOMElement_Release(elem);
8086 
8087     /* add attribute already attached to another document */
8088     doc2 = create_document(&IID_IXMLDOMDocument);
8089 
8090     hr = IXMLDOMDocument_loadXML( doc2, _bstr_(complete4A), &b );
8091     ok( hr == S_OK, "loadXML failed\n");
8092     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8093 
8094     hr = IXMLDOMDocument_get_documentElement(doc2, &elem);
8095     ok( hr == S_OK, "got 0x%08x\n", hr);
8096     hr = IXMLDOMElement_setAttributeNode(elem, attr, NULL);
8097     ok( hr == E_FAIL, "got 0x%08x\n", hr);
8098     IXMLDOMElement_Release(elem);
8099 
8100     IXMLDOMAttribute_Release(attr);
8101 
8102     /* create element, add attribute, see if it's copied or linked */
8103     hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
8104     ok( hr == S_OK, "got 0x%08x\n", hr);
8105 
8106     attr = NULL;
8107     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8108     ok(hr == S_OK, "got 0x%08x\n", hr);
8109     ok(attr != NULL, "got %p\n", attr);
8110 
8111     ref1 = IXMLDOMAttribute_AddRef(attr);
8112     IXMLDOMAttribute_Release(attr);
8113 
8114     V_VT(&v) = VT_BSTR;
8115     V_BSTR(&v) = _bstr_("attrvalue1");
8116     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8117     ok( hr == S_OK, "got 0x%08x\n", hr);
8118 
8119     str = NULL;
8120     hr = IXMLDOMAttribute_get_xml(attr, &str);
8121     ok( hr == S_OK, "got 0x%08x\n", hr);
8122     ok( lstrcmpW(str, _bstr_("attr=\"attrvalue1\"")) == 0,
8123         "got %s\n", wine_dbgstr_w(str));
8124     SysFreeString(str);
8125 
8126     ret_attr = (void*)0xdeadbeef;
8127     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8128     ok(hr == S_OK, "got 0x%08x\n", hr);
8129     ok(ret_attr == NULL, "got %p\n", ret_attr);
8130 
8131     /* attribute reference increased */
8132     ref2 = IXMLDOMAttribute_AddRef(attr);
8133     IXMLDOMAttribute_Release(attr);
8134     ok(ref1 == ref2, "got %d, expected %d\n", ref2, ref1);
8135 
8136     hr = IXMLDOMElement_get_xml(elem, &str);
8137     ok( hr == S_OK, "got 0x%08x\n", hr);
8138     ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue1\"/>")) == 0,
8139         "got %s\n", wine_dbgstr_w(str));
8140     SysFreeString(str);
8141 
8142     V_VT(&v) = VT_BSTR;
8143     V_BSTR(&v) = _bstr_("attrvalue2");
8144     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8145     ok( hr == S_OK, "got 0x%08x\n", hr);
8146 
8147     hr = IXMLDOMElement_get_xml(elem, &str);
8148     ok( hr == S_OK, "got 0x%08x\n", hr);
8149     todo_wine ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue2\"/>")) == 0,
8150         "got %s\n", wine_dbgstr_w(str));
8151     SysFreeString(str);
8152 
8153     IXMLDOMElement_Release(elem);
8154     IXMLDOMAttribute_Release(attr);
8155     IXMLDOMDocument_Release(doc2);
8156     IXMLDOMDocument_Release(doc);
8157     free_bstrs();
8158 }
8159 
8160 static void test_createNode(void)
8161 {
8162     IXMLDOMDocument *doc;
8163     IXMLDOMElement *elem;
8164     IXMLDOMNode *node;
8165     VARIANT v, var;
8166     BSTR prefix, str;
8167     HRESULT hr;
8168     ULONG ref;
8169 
8170     doc = create_document(&IID_IXMLDOMDocument);
8171 
8172     EXPECT_REF(doc, 1);
8173 
8174     /* reference count tests */
8175     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8176     ok( hr == S_OK, "got 0x%08x\n", hr);
8177 
8178     /* initial reference is 2 */
8179 todo_wine {
8180     EXPECT_REF(elem, 2);
8181     ref = IXMLDOMElement_Release(elem);
8182     ok(ref == 1, "got %d\n", ref);
8183     /* it's released already, attempt to release now will crash it */
8184 }
8185 
8186     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8187     ok( hr == S_OK, "got 0x%08x\n", hr);
8188     todo_wine EXPECT_REF(elem, 2);
8189     IXMLDOMDocument_Release(doc);
8190     todo_wine EXPECT_REF(elem, 2);
8191     IXMLDOMElement_Release(elem);
8192 
8193     doc = create_document(&IID_IXMLDOMDocument);
8194 
8195     /* NODE_ELEMENT nodes */
8196     /* 1. specified namespace */
8197     V_VT(&v) = VT_I4;
8198     V_I4(&v) = NODE_ELEMENT;
8199 
8200     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("ns1:test"), _bstr_("http://winehq.org"), &node);
8201     ok( hr == S_OK, "got 0x%08x\n", hr);
8202     prefix = NULL;
8203     hr = IXMLDOMNode_get_prefix(node, &prefix);
8204     ok( hr == S_OK, "got 0x%08x\n", hr);
8205     ok(lstrcmpW(prefix, _bstr_("ns1")) == 0, "wrong prefix\n");
8206     SysFreeString(prefix);
8207     IXMLDOMNode_Release(node);
8208 
8209     /* 2. default namespace */
8210     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("test"), _bstr_("http://winehq.org/default"), &node);
8211     ok( hr == S_OK, "got 0x%08x\n", hr);
8212     prefix = (void*)0xdeadbeef;
8213     hr = IXMLDOMNode_get_prefix(node, &prefix);
8214     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8215     ok(prefix == 0, "expected empty prefix, got %p\n", prefix);
8216     /* check dump */
8217     hr = IXMLDOMNode_get_xml(node, &str);
8218     ok( hr == S_OK, "got 0x%08x\n", hr);
8219     ok( lstrcmpW(str, _bstr_("<test xmlns=\"http://winehq.org/default\"/>")) == 0,
8220         "got %s\n", wine_dbgstr_w(str));
8221     SysFreeString(str);
8222 
8223     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
8224     ok( hr == S_OK, "got 0x%08x\n", hr);
8225 
8226     V_VT(&var) = VT_BSTR;
8227     hr = IXMLDOMElement_getAttribute(elem, _bstr_("xmlns"), &var);
8228     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8229     ok( V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
8230 
8231     str = NULL;
8232     hr = IXMLDOMElement_get_namespaceURI(elem, &str);
8233     ok( hr == S_OK, "got 0x%08x\n", hr);
8234     ok( lstrcmpW(str, _bstr_("http://winehq.org/default")) == 0, "expected default namespace\n");
8235     SysFreeString(str);
8236 
8237     IXMLDOMElement_Release(elem);
8238     IXMLDOMNode_Release(node);
8239 
8240     IXMLDOMDocument_Release(doc);
8241     free_bstrs();
8242 }
8243 
8244 static const char get_prefix_doc[] =
8245     "<?xml version=\"1.0\" ?>"
8246     "<a xmlns:ns1=\"ns1 href\" />";
8247 
8248 static void test_get_prefix(void)
8249 {
8250     IXMLDOMDocumentFragment *fragment;
8251     IXMLDOMCDATASection *cdata;
8252     IXMLDOMElement *element;
8253     IXMLDOMComment *comment;
8254     IXMLDOMDocument *doc;
8255     VARIANT_BOOL b;
8256     HRESULT hr;
8257     BSTR str;
8258 
8259     doc = create_document(&IID_IXMLDOMDocument);
8260 
8261     /* nodes that can't support prefix */
8262     /* 1. document */
8263     str = (void*)0xdeadbeef;
8264     hr = IXMLDOMDocument_get_prefix(doc, &str);
8265     EXPECT_HR(hr, S_FALSE);
8266     ok(str == NULL, "got %p\n", str);
8267 
8268     hr = IXMLDOMDocument_get_prefix(doc, NULL);
8269     EXPECT_HR(hr, E_INVALIDARG);
8270 
8271     /* 2. cdata */
8272     hr = IXMLDOMDocument_createCDATASection(doc, NULL, &cdata);
8273     ok(hr == S_OK, "got %08x\n", hr );
8274 
8275     str = (void*)0xdeadbeef;
8276     hr = IXMLDOMCDATASection_get_prefix(cdata, &str);
8277     ok(hr == S_FALSE, "got %08x\n", hr);
8278     ok( str == 0, "got %p\n", str);
8279 
8280     hr = IXMLDOMCDATASection_get_prefix(cdata, NULL);
8281     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8282     IXMLDOMCDATASection_Release(cdata);
8283 
8284     /* 3. comment */
8285     hr = IXMLDOMDocument_createComment(doc, NULL, &comment);
8286     ok(hr == S_OK, "got %08x\n", hr );
8287 
8288     str = (void*)0xdeadbeef;
8289     hr = IXMLDOMComment_get_prefix(comment, &str);
8290     ok(hr == S_FALSE, "got %08x\n", hr);
8291     ok( str == 0, "got %p\n", str);
8292 
8293     hr = IXMLDOMComment_get_prefix(comment, NULL);
8294     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8295     IXMLDOMComment_Release(comment);
8296 
8297     /* 4. fragment */
8298     hr = IXMLDOMDocument_createDocumentFragment(doc, &fragment);
8299     ok(hr == S_OK, "got %08x\n", hr );
8300 
8301     str = (void*)0xdeadbeef;
8302     hr = IXMLDOMDocumentFragment_get_prefix(fragment, &str);
8303     ok(hr == S_FALSE, "got %08x\n", hr);
8304     ok( str == 0, "got %p\n", str);
8305 
8306     hr = IXMLDOMDocumentFragment_get_prefix(fragment, NULL);
8307     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8308     IXMLDOMDocumentFragment_Release(fragment);
8309 
8310     /* no prefix */
8311     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &element);
8312     ok( hr == S_OK, "got 0x%08x\n", hr);
8313 
8314     hr = IXMLDOMElement_get_prefix(element, NULL);
8315     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8316 
8317     str = (void*)0xdeadbeef;
8318     hr = IXMLDOMElement_get_prefix(element, &str);
8319     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8320     ok( str == 0, "got %p\n", str);
8321 
8322     IXMLDOMElement_Release(element);
8323 
8324     /* with prefix */
8325     hr = IXMLDOMDocument_createElement(doc, _bstr_("a:elem"), &element);
8326     ok( hr == S_OK, "got 0x%08x\n", hr);
8327 
8328     str = (void*)0xdeadbeef;
8329     hr = IXMLDOMElement_get_prefix(element, &str);
8330     ok( hr == S_OK, "got 0x%08x\n", hr);
8331     ok( lstrcmpW(str, _bstr_("a")) == 0, "expected prefix \"a\"\n");
8332     SysFreeString(str);
8333 
8334     str = (void*)0xdeadbeef;
8335     hr = IXMLDOMElement_get_namespaceURI(element, &str);
8336     ok( hr == S_FALSE, "got 0x%08x\n", hr);
8337     ok( str == 0, "got %p\n", str);
8338 
8339     IXMLDOMElement_Release(element);
8340 
8341     hr = IXMLDOMDocument_loadXML(doc, _bstr_(get_prefix_doc), &b);
8342     EXPECT_HR(hr, S_OK);
8343 
8344     hr = IXMLDOMDocument_get_documentElement(doc, &element);
8345     EXPECT_HR(hr, S_OK);
8346 
8347     str = (void*)0xdeadbeef;
8348     hr = IXMLDOMElement_get_prefix(element, &str);
8349     EXPECT_HR(hr, S_FALSE);
8350     ok(str == NULL, "got %p\n", str);
8351 
8352     str = (void*)0xdeadbeef;
8353     hr = IXMLDOMElement_get_namespaceURI(element, &str);
8354     EXPECT_HR(hr, S_FALSE);
8355     ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
8356 
8357     IXMLDOMDocument_Release(doc);
8358     free_bstrs();
8359 }
8360 
8361 static void test_selectSingleNode(void)
8362 {
8363     IXMLDOMDocument *doc;
8364     IXMLDOMNodeList *list;
8365     IXMLDOMNode *node;
8366     VARIANT_BOOL b;
8367     HRESULT hr;
8368     LONG len;
8369 
8370     doc = create_document(&IID_IXMLDOMDocument);
8371 
8372     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8373     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8374 
8375     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8376     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8377 
8378     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8379     ok( hr == S_OK, "loadXML failed\n");
8380     ok( b == VARIANT_TRUE, "failed to load XML string\n");
8381 
8382     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8383     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8384 
8385     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8386     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8387 
8388     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), NULL);
8389     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8390 
8391     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), NULL);
8392     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8393 
8394     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), &node);
8395     ok(hr == S_OK, "got 0x%08x\n", hr);
8396     IXMLDOMNode_Release(node);
8397 
8398     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), &list);
8399     ok(hr == S_OK, "got 0x%08x\n", hr);
8400     IXMLDOMNodeList_Release(list);
8401 
8402     list = (void*)0xdeadbeef;
8403     hr = IXMLDOMDocument_selectNodes(doc, NULL, &list);
8404     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8405     ok(list == (void*)0xdeadbeef, "got %p\n", list);
8406 
8407     node = (void*)0xdeadbeef;
8408     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("nonexistent"), &node);
8409     ok(hr == S_FALSE, "got 0x%08x\n", hr);
8410     ok(node == 0, "got %p\n", node);
8411 
8412     list = (void*)0xdeadbeef;
8413     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("nonexistent"), &list);
8414     ok(hr == S_OK, "got 0x%08x\n", hr);
8415     len = 1;
8416     hr = IXMLDOMNodeList_get_length(list, &len);
8417     ok(hr == S_OK, "got 0x%08x\n", hr);
8418     ok(len == 0, "got %d\n", len);
8419     IXMLDOMNodeList_Release(list);
8420 
8421     IXMLDOMDocument_Release(doc);
8422     free_bstrs();
8423 }
8424 
8425 static void test_events(void)
8426 {
8427     IConnectionPointContainer *conn;
8428     IConnectionPoint *point;
8429     IXMLDOMDocument *doc;
8430     HRESULT hr;
8431     VARIANT v;
8432     IDispatch *event;
8433 
8434     doc = create_document(&IID_IXMLDOMDocument);
8435 
8436     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&conn);
8437     ok(hr == S_OK, "got 0x%08x\n", hr);
8438 
8439     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IDispatch, &point);
8440     ok(hr == S_OK, "got 0x%08x\n", hr);
8441     IConnectionPoint_Release(point);
8442     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IPropertyNotifySink, &point);
8443     ok(hr == S_OK, "got 0x%08x\n", hr);
8444     IConnectionPoint_Release(point);
8445     hr = IConnectionPointContainer_FindConnectionPoint(conn, &DIID_XMLDOMDocumentEvents, &point);
8446     ok(hr == S_OK, "got 0x%08x\n", hr);
8447     IConnectionPoint_Release(point);
8448 
8449     IConnectionPointContainer_Release(conn);
8450 
8451     /* ready state callback */
8452     VariantInit(&v);
8453     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8454     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8455 
8456     event = create_dispevent();
8457     V_VT(&v) = VT_UNKNOWN;
8458     V_UNKNOWN(&v) = (IUnknown*)event;
8459 
8460     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8461     ok(hr == S_OK, "got 0x%08x\n", hr);
8462     EXPECT_REF(event, 2);
8463 
8464     V_VT(&v) = VT_DISPATCH;
8465     V_DISPATCH(&v) = event;
8466 
8467     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8468     ok(hr == S_OK, "got 0x%08x\n", hr);
8469     EXPECT_REF(event, 2);
8470 
8471     /* VT_NULL doesn't reset event handler */
8472     V_VT(&v) = VT_NULL;
8473     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8474     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8475     EXPECT_REF(event, 2);
8476 
8477     V_VT(&v) = VT_DISPATCH;
8478     V_DISPATCH(&v) = NULL;
8479 
8480     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8481     ok(hr == S_OK, "got 0x%08x\n", hr);
8482     EXPECT_REF(event, 1);
8483 
8484     V_VT(&v) = VT_UNKNOWN;
8485     V_DISPATCH(&v) = NULL;
8486     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8487     ok(hr == S_OK, "got 0x%08x\n", hr);
8488 
8489     IDispatch_Release(event);
8490 
8491     IXMLDOMDocument_Release(doc);
8492 }
8493 
8494 static void test_createProcessingInstruction(void)
8495 {
8496     static const WCHAR bodyW[] = {'t','e','s','t',0};
8497     IXMLDOMProcessingInstruction *pi;
8498     IXMLDOMDocument *doc;
8499     WCHAR buff[10];
8500     HRESULT hr;
8501 
8502     doc = create_document(&IID_IXMLDOMDocument);
8503 
8504     /* test for BSTR handling, pass broken BSTR */
8505     memcpy(&buff[2], bodyW, sizeof(bodyW));
8506     /* just a big length */
8507     *(DWORD*)buff = 0xf0f0;
8508     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("test"), &buff[2], &pi);
8509     ok(hr == S_OK, "got 0x%08x\n", hr);
8510 
8511     IXMLDOMProcessingInstruction_Release(pi);
8512     IXMLDOMDocument_Release(doc);
8513 }
8514 
8515 static void test_put_nodeTypedValue(void)
8516 {
8517     static const BYTE binhexdata[16] =
8518         {0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf};
8519     IXMLDOMDocument *doc;
8520     IXMLDOMElement *elem;
8521     VARIANT type, value;
8522     LONG ubound, lbound;
8523     IXMLDOMNode *node;
8524     SAFEARRAY *array;
8525     HRESULT hr;
8526     BYTE *ptr;
8527     BSTR str;
8528 
8529     doc = create_document(&IID_IXMLDOMDocument);
8530 
8531     hr = IXMLDOMDocument_createElement(doc, _bstr_("Element"), &elem);
8532     EXPECT_HR(hr, S_OK);
8533 
8534     V_VT(&type) = VT_EMPTY;
8535     hr = IXMLDOMElement_get_dataType(elem, &type);
8536     EXPECT_HR(hr, S_FALSE);
8537     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8538 
8539     /* set typed value for untyped node */
8540     V_VT(&type) = VT_I1;
8541     V_I1(&type) = 1;
8542     hr = IXMLDOMElement_put_nodeTypedValue(elem, type);
8543     EXPECT_HR(hr, S_OK);
8544 
8545     V_VT(&type) = VT_EMPTY;
8546     hr = IXMLDOMElement_get_dataType(elem, &type);
8547     EXPECT_HR(hr, S_FALSE);
8548     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8549 
8550     /* no type info stored */
8551     V_VT(&type) = VT_EMPTY;
8552     hr = IXMLDOMElement_get_nodeTypedValue(elem, &type);
8553     EXPECT_HR(hr, S_OK);
8554     ok(V_VT(&type) == VT_BSTR, "got %d, expected VT_BSTR\n", V_VT(&type));
8555     ok(memcmp(V_BSTR(&type), _bstr_("1"), 2*sizeof(WCHAR)) == 0,
8556        "got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
8557     VariantClear(&type);
8558 
8559     hr = IXMLDOMElement_get_firstChild(elem, &node);
8560     EXPECT_HR(hr, S_OK);
8561     hr = IXMLDOMElement_removeChild(elem, node, NULL);
8562     EXPECT_HR(hr, S_OK);
8563     IXMLDOMNode_Release(node);
8564 
8565     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)elem, NULL);
8566     EXPECT_HR(hr, S_OK);
8567 
8568     /* bin.base64 */
8569     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.base64"));
8570     EXPECT_HR(hr, S_OK);
8571 
8572     V_VT(&value) = VT_BSTR;
8573     V_BSTR(&value) = _bstr_("ABCD");
8574     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8575     EXPECT_HR(hr, S_OK);
8576 
8577     V_VT(&value) = VT_EMPTY;
8578     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8579     EXPECT_HR(hr, S_OK);
8580     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8581     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8582     ubound = 0;
8583     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8584     EXPECT_HR(hr, S_OK);
8585     ok(ubound == 2, "got %d\n", ubound);
8586     lbound = 0;
8587     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8588     EXPECT_HR(hr, S_OK);
8589     ok(lbound == 0, "got %d\n", lbound);
8590     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8591     EXPECT_HR(hr, S_OK);
8592     ok(ptr[0] == 0, "got %x\n", ptr[0]);
8593     ok(ptr[1] == 0x10, "got %x\n", ptr[1]);
8594     ok(ptr[2] == 0x83, "got %x\n", ptr[2]);
8595     SafeArrayUnaccessData(V_ARRAY(&value));
8596     VariantClear(&value);
8597 
8598     /* when set as VT_BSTR it's stored as is */
8599     hr = IXMLDOMElement_get_firstChild(elem, &node);
8600     EXPECT_HR(hr, S_OK);
8601     hr = IXMLDOMNode_get_text(node, &str);
8602     EXPECT_HR(hr, S_OK);
8603     ok(!lstrcmpW(str, _bstr_("ABCD")), "%s\n", wine_dbgstr_w(str));
8604     IXMLDOMNode_Release(node);
8605     SysFreeString(str);
8606 
8607     array = SafeArrayCreateVector(VT_UI1, 0, 7);
8608     hr = SafeArrayAccessData(array, (void*)&ptr);
8609     EXPECT_HR(hr, S_OK);
8610     memcpy(ptr, "dGVzdA=", strlen("dGVzdA="));
8611     SafeArrayUnaccessData(array);
8612 
8613     V_VT(&value) = VT_UI1|VT_ARRAY;
8614     V_ARRAY(&value) = array;
8615     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8616     EXPECT_HR(hr, S_OK);
8617 
8618     V_VT(&value) = VT_EMPTY;
8619     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8620     EXPECT_HR(hr, S_OK);
8621     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8622     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8623     ubound = 0;
8624     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8625     EXPECT_HR(hr, S_OK);
8626     ok(ubound == 6, "got %d\n", ubound);
8627     lbound = 0;
8628     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8629     EXPECT_HR(hr, S_OK);
8630     ok(lbound == 0, "got %d\n", lbound);
8631     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8632     EXPECT_HR(hr, S_OK);
8633     ok(!memcmp(ptr, "dGVzdA=", strlen("dGVzdA=")), "got wrong data, %s\n", ptr);
8634     SafeArrayUnaccessData(V_ARRAY(&value));
8635     VariantClear(&value);
8636 
8637     /* if set with VT_UI1|VT_ARRAY it's encoded */
8638     hr = IXMLDOMElement_get_firstChild(elem, &node);
8639     EXPECT_HR(hr, S_OK);
8640     hr = IXMLDOMNode_get_text(node, &str);
8641     EXPECT_HR(hr, S_OK);
8642     ok(!lstrcmpW(str, _bstr_("ZEdWemRBPQ==")), "%s\n", wine_dbgstr_w(str));
8643     IXMLDOMNode_Release(node);
8644     SafeArrayDestroyData(array);
8645     SysFreeString(str);
8646 
8647     /* bin.hex */
8648     V_VT(&value) = VT_BSTR;
8649     V_BSTR(&value) = _bstr_("");
8650     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8651     EXPECT_HR(hr, S_OK);
8652 
8653     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.hex"));
8654     EXPECT_HR(hr, S_OK);
8655 
8656     array = SafeArrayCreateVector(VT_UI1, 0, 16);
8657     hr = SafeArrayAccessData(array, (void*)&ptr);
8658     EXPECT_HR(hr, S_OK);
8659     memcpy(ptr, binhexdata, sizeof(binhexdata));
8660     SafeArrayUnaccessData(array);
8661 
8662     V_VT(&value) = VT_UI1|VT_ARRAY;
8663     V_ARRAY(&value) = array;
8664     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8665     EXPECT_HR(hr, S_OK);
8666 
8667     V_VT(&value) = VT_EMPTY;
8668     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8669     EXPECT_HR(hr, S_OK);
8670     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8671     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8672     ubound = 0;
8673     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8674     EXPECT_HR(hr, S_OK);
8675     ok(ubound == 15, "got %d\n", ubound);
8676     lbound = 0;
8677     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8678     EXPECT_HR(hr, S_OK);
8679     ok(lbound == 0, "got %d\n", lbound);
8680     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8681     EXPECT_HR(hr, S_OK);
8682     ok(!memcmp(ptr, binhexdata, sizeof(binhexdata)), "got wrong data\n");
8683     SafeArrayUnaccessData(V_ARRAY(&value));
8684     VariantClear(&value);
8685 
8686     /* if set with VT_UI1|VT_ARRAY it's encoded */
8687     hr = IXMLDOMElement_get_firstChild(elem, &node);
8688     EXPECT_HR(hr, S_OK);
8689     hr = IXMLDOMNode_get_text(node, &str);
8690     EXPECT_HR(hr, S_OK);
8691     ok(!lstrcmpW(str, _bstr_("000102030405060708090a0b0c0d0e0f")), "%s\n", wine_dbgstr_w(str));
8692     IXMLDOMNode_Release(node);
8693     SafeArrayDestroyData(array);
8694     SysFreeString(str);
8695 
8696     IXMLDOMElement_Release(elem);
8697     IXMLDOMDocument_Release(doc);
8698     free_bstrs();
8699 }
8700 
8701 static void test_get_xml(void)
8702 {
8703     static const char xmlA[] = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<a>test</a>\r\n";
8704     static const char attrA[] = "attr=\"&quot;a &amp; b&quot;\"";
8705     static const char attr2A[] = "\"a & b\"";
8706     static const char attr3A[] = "attr=\"&amp;quot;a\"";
8707     static const char attr4A[] = "&quot;a";
8708     static const char fooA[] = "<foo/>";
8709     IXMLDOMProcessingInstruction *pi;
8710     IXMLDOMNode *first;
8711     IXMLDOMElement *elem = NULL;
8712     IXMLDOMAttribute *attr;
8713     IXMLDOMDocument *doc;
8714     VARIANT_BOOL b;
8715     VARIANT v;
8716     BSTR xml;
8717     HRESULT hr;
8718 
8719     doc = create_document(&IID_IXMLDOMDocument);
8720 
8721     b = VARIANT_TRUE;
8722     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8723     ok(hr == S_OK, "got 0x%08x\n", hr);
8724     ok( b == VARIANT_TRUE, "got %d\n", b);
8725 
8726     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"),
8727                              _bstr_("version=\"1.0\" encoding=\"UTF-16\""), &pi);
8728     ok(hr == S_OK, "got 0x%08x\n", hr);
8729 
8730     hr = IXMLDOMDocument_get_firstChild(doc, &first);
8731     ok(hr == S_OK, "got 0x%08x\n", hr);
8732 
8733     V_UNKNOWN(&v) = (IUnknown*)first;
8734     V_VT(&v) = VT_UNKNOWN;
8735 
8736     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)pi, v, NULL);
8737     ok(hr == S_OK, "got 0x%08x\n", hr);
8738 
8739     IXMLDOMProcessingInstruction_Release(pi);
8740     IXMLDOMNode_Release(first);
8741 
8742     hr = IXMLDOMDocument_get_xml(doc, &xml);
8743     ok(hr == S_OK, "got 0x%08x\n", hr);
8744 
8745     ok(memcmp(xml, _bstr_(xmlA), sizeof(xmlA)*sizeof(WCHAR)) == 0,
8746         "got %s, expected %s\n", wine_dbgstr_w(xml), xmlA);
8747     SysFreeString(xml);
8748 
8749     IXMLDOMDocument_Release(doc);
8750 
8751     doc = create_document(&IID_IXMLDOMDocument);
8752 
8753     hr = IXMLDOMDocument_createElement(doc, _bstr_("foo"), &elem);
8754     ok(hr == S_OK, "got 0x%08x\n", hr);
8755 
8756     hr = IXMLDOMDocument_putref_documentElement(doc, elem);
8757     ok(hr == S_OK, "got 0x%08x\n", hr);
8758 
8759     hr = IXMLDOMDocument_get_xml(doc, &xml);
8760     ok(hr == S_OK, "got 0x%08x\n", hr);
8761 
8762     ok(memcmp(xml, _bstr_(fooA), (sizeof(fooA)-1)*sizeof(WCHAR)) == 0,
8763         "got %s, expected %s\n", wine_dbgstr_w(xml), fooA);
8764     SysFreeString(xml);
8765 
8766     IXMLDOMElement_Release(elem);
8767 
8768     /* attribute node */
8769     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8770     ok(hr == S_OK, "got 0x%08x\n", hr);
8771 
8772     V_VT(&v) = VT_BSTR;
8773     V_BSTR(&v) = _bstr_("\"a & b\"");
8774     hr = IXMLDOMAttribute_put_value(attr, v);
8775     ok(hr == S_OK, "got 0x%08x\n", hr);
8776 
8777     xml = NULL;
8778     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8779     ok(hr == S_OK, "got 0x%08x\n", hr);
8780     ok(!memcmp(xml, _bstr_(attrA), (sizeof(attrA)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8781     SysFreeString(xml);
8782 
8783     VariantInit(&v);
8784     hr = IXMLDOMAttribute_get_value(attr, &v);
8785     ok(hr == S_OK, "got 0x%08x\n", hr);
8786     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8787     ok(!memcmp(V_BSTR(&v), _bstr_(attr2A), (sizeof(attr2A)-1)*sizeof(WCHAR)),
8788         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8789     VariantClear(&v);
8790 
8791     V_VT(&v) = VT_BSTR;
8792     V_BSTR(&v) = _bstr_("&quot;a");
8793     hr = IXMLDOMAttribute_put_value(attr, v);
8794     ok(hr == S_OK, "got 0x%08x\n", hr);
8795 
8796     xml = NULL;
8797     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8798     ok(hr == S_OK, "got 0x%08x\n", hr);
8799     ok(!memcmp(xml, _bstr_(attr3A), (sizeof(attr3A)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8800     SysFreeString(xml);
8801 
8802     VariantInit(&v);
8803     hr = IXMLDOMAttribute_get_value(attr, &v);
8804     ok(hr == S_OK, "got 0x%08x\n", hr);
8805     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8806     ok(!memcmp(V_BSTR(&v), _bstr_(attr4A), (sizeof(attr4A)-1)*sizeof(WCHAR)),
8807         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8808     VariantClear(&v);
8809 
8810     IXMLDOMAttribute_Release(attr);
8811 
8812     IXMLDOMDocument_Release(doc);
8813 
8814     free_bstrs();
8815 }
8816 
8817 static void test_xsltemplate(void)
8818 {
8819     IXMLDOMDocument *doc, *doc2, *doc3;
8820     IXSLTemplate *template;
8821     IXSLProcessor *processor;
8822     IStream *stream;
8823     VARIANT_BOOL b;
8824     HRESULT hr;
8825     ULONG ref1, ref2;
8826     VARIANT v;
8827     BSTR str;
8828 
8829     if (!is_clsid_supported(&CLSID_XSLTemplate, &IID_IXSLTemplate)) return;
8830     template = create_xsltemplate(&IID_IXSLTemplate);
8831 
8832     /* works as reset */
8833     hr = IXSLTemplate_putref_stylesheet(template, NULL);
8834     ok(hr == S_OK, "got 0x%08x\n", hr);
8835 
8836     doc = create_document(&IID_IXMLDOMDocument);
8837 
8838     b = VARIANT_TRUE;
8839     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8840     ok(hr == S_OK, "got 0x%08x\n", hr);
8841     ok( b == VARIANT_TRUE, "got %d\n", b);
8842 
8843     /* putref with non-xsl document */
8844     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8845     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8846 
8847     b = VARIANT_TRUE;
8848     hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8849     ok(hr == S_OK, "got 0x%08x\n", hr);
8850     ok( b == VARIANT_TRUE, "got %d\n", b);
8851 
8852     /* not a freethreaded document */
8853     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8854     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8855 
8856     IXMLDOMDocument_Release(doc);
8857 
8858     if (!is_clsid_supported(&CLSID_FreeThreadedDOMDocument, &IID_IXMLDOMDocument))
8859     {
8860         IXSLTemplate_Release(template);
8861         return;
8862     }
8863 
8864     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
8865     ok(hr == S_OK, "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     /* freethreaded document */
8873     ref1 = IXMLDOMDocument_AddRef(doc);
8874     IXMLDOMDocument_Release(doc);
8875     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8876     ok(hr == S_OK, "got 0x%08x\n", hr);
8877     ref2 = IXMLDOMDocument_AddRef(doc);
8878     IXMLDOMDocument_Release(doc);
8879     ok(ref2 > ref1, "got %d\n", ref2);
8880 
8881     /* processor */
8882     hr = IXSLTemplate_createProcessor(template, NULL);
8883     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8884 
8885     EXPECT_REF(template, 1);
8886     hr = IXSLTemplate_createProcessor(template, &processor);
8887     ok(hr == S_OK, "got 0x%08x\n", hr);
8888     EXPECT_REF(template, 2);
8889 
8890     /* input no set yet */
8891     V_VT(&v) = VT_BSTR;
8892     V_BSTR(&v) = NULL;
8893     hr = IXSLProcessor_get_input(processor, &v);
8894 todo_wine {
8895     ok(hr == S_OK, "got 0x%08x\n", hr);
8896     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
8897 }
8898 
8899     hr = IXSLProcessor_get_output(processor, NULL);
8900     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8901 
8902     /* reset before it was set */
8903     V_VT(&v) = VT_EMPTY;
8904     hr = IXSLProcessor_put_output(processor, v);
8905     ok(hr == S_OK, "got 0x%08x\n", hr);
8906 
8907     V_VT(&v) = VT_UNKNOWN;
8908     V_UNKNOWN(&v) = NULL;
8909     hr = IXSLProcessor_put_output(processor, v);
8910     ok(hr == S_OK, "got 0x%08x\n", hr);
8911 
8912     V_VT(&v) = VT_UNKNOWN;
8913     V_DISPATCH(&v) = NULL;
8914     hr = IXSLProcessor_put_output(processor, v);
8915     ok(hr == S_OK, "got 0x%08x\n", hr);
8916 
8917     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
8918     ok(hr == S_OK, "got 0x%08x\n", hr);
8919     EXPECT_REF(stream, 1);
8920 
8921     V_VT(&v) = VT_UNKNOWN;
8922     V_UNKNOWN(&v) = (IUnknown*)stream;
8923     hr = IXSLProcessor_put_output(processor, v);
8924     ok(hr == S_OK, "got 0x%08x\n", hr);
8925 
8926     /* it seems processor grabs 2 references */
8927     todo_wine EXPECT_REF(stream, 3);
8928 
8929     V_VT(&v) = VT_EMPTY;
8930     hr = IXSLProcessor_get_output(processor, &v);
8931     ok(hr == S_OK, "got 0x%08x\n", hr);
8932     ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
8933     ok(V_UNKNOWN(&v) == (IUnknown*)stream, "got %p\n", V_UNKNOWN(&v));
8934 
8935     todo_wine EXPECT_REF(stream, 4);
8936     VariantClear(&v);
8937 
8938     hr = IXSLProcessor_transform(processor, NULL);
8939     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8940 
8941     /* reset and check stream refcount */
8942     V_VT(&v) = VT_EMPTY;
8943     hr = IXSLProcessor_put_output(processor, v);
8944     ok(hr == S_OK, "got 0x%08x\n", hr);
8945 
8946     EXPECT_REF(stream, 1);
8947 
8948     IStream_Release(stream);
8949 
8950     /* no output interface set, check output */
8951     doc2 = create_document(&IID_IXMLDOMDocument);
8952 
8953     b = VARIANT_FALSE;
8954     hr = IXMLDOMDocument_loadXML( doc2, _bstr_("<a>test</a>"), &b );
8955     ok(hr == S_OK, "got 0x%08x\n", hr);
8956     ok( b == VARIANT_TRUE, "got %d\n", b);
8957 
8958     V_VT(&v) = VT_UNKNOWN;
8959     V_UNKNOWN(&v) = (IUnknown*)doc2;
8960     hr = IXSLProcessor_put_input(processor, v);
8961     ok(hr == S_OK, "got 0x%08x\n", hr);
8962 
8963     hr = IXSLProcessor_transform(processor, &b);
8964     ok(hr == S_OK, "got 0x%08x\n", hr);
8965 
8966     V_VT(&v) = VT_EMPTY;
8967     hr = IXSLProcessor_get_output(processor, &v);
8968     ok(hr == S_OK, "got 0x%08x\n", hr);
8969     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8970     ok(*V_BSTR(&v) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8971     VariantClear(&v);
8972 
8973     /* transform to document */
8974     b = VARIANT_FALSE;
8975     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformXML), &b);
8976     ok(hr == S_OK, "got 0x%08x\n", hr);
8977     ok(b == VARIANT_TRUE, "got %d\n", b);
8978 
8979     V_VT(&v) = VT_UNKNOWN;
8980     V_UNKNOWN(&v) = (IUnknown*)doc2;
8981     hr = IXSLProcessor_put_input(processor, v);
8982     ok(hr == S_OK, "got 0x%08x\n", hr);
8983 
8984     doc3 = create_document(&IID_IXMLDOMDocument);
8985     V_VT(&v) = VT_UNKNOWN;
8986     V_UNKNOWN(&v) = (IUnknown *)doc3;
8987     hr = IXSLProcessor_put_output(processor, v);
8988     ok(hr == S_OK, "got 0x%08x\n", hr);
8989 
8990     hr = IXMLDOMDocument_get_xml(doc3, &str);
8991     ok(hr == S_OK, "got 0x%08x\n", hr);
8992     ok(!*str, "Expected empty document\n");
8993     SysFreeString(str);
8994 
8995     hr = IXSLProcessor_transform(processor, &b);
8996     ok(hr == S_OK, "got 0x%08x\n", hr);
8997 
8998     V_VT(&v) = VT_EMPTY;
8999     hr = IXSLProcessor_get_output(processor, &v);
9000     ok(hr == S_OK, "got 0x%08x\n", hr);
9001     ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
9002     VariantClear(&v);
9003 
9004     hr = IXMLDOMDocument_get_xml(doc3, &str);
9005     ok(hr == S_OK, "got 0x%08x\n", hr);
9006     ok(!!*str, "Expected document\n");
9007     SysFreeString(str);
9008 
9009     /* transform to IResponse */
9010     V_VT(&v) = VT_EMPTY;
9011     hr = IXSLProcessor_put_output(processor, v);
9012     ok(hr == S_OK, "got 0x%08x\n", hr);
9013 
9014     V_VT(&v) = VT_UNKNOWN;
9015     V_UNKNOWN(&v) = (IUnknown *)&testresponse;
9016     hr = IXSLProcessor_put_output(processor, v);
9017     ok(hr == S_OK, "got 0x%08x\n", hr);
9018 
9019     b = VARIANT_FALSE;
9020     hr = IXSLProcessor_transform(processor, &b);
9021     ok(hr == S_OK, "got 0x%08x\n", hr);
9022     ok(b == VARIANT_TRUE, "got %x\n", b);
9023 
9024     IXSLProcessor_Release(processor);
9025     IXMLDOMDocument_Release(doc2);
9026     IXMLDOMDocument_Release(doc3);
9027 
9028     /* drop reference */
9029     hr = IXSLTemplate_putref_stylesheet(template, NULL);
9030     ok(hr == S_OK, "got 0x%08x\n", hr);
9031     ref2 = IXMLDOMDocument_AddRef(doc);
9032     IXMLDOMDocument_Release(doc);
9033     ok(ref2 == ref1, "got %d\n", ref2);
9034 
9035     IXMLDOMDocument_Release(doc);
9036     IXSLTemplate_Release(template);
9037     free_bstrs();
9038 }
9039 
9040 static void test_insertBefore(void)
9041 {
9042     IXMLDOMDocument *doc, *doc2, *doc3;
9043     IXMLDOMAttribute *attr;
9044     IXMLDOMElement *elem1, *elem2, *elem3, *elem4, *elem5;
9045     IXMLDOMNode *node, *newnode, *cdata;
9046     HRESULT hr;
9047     VARIANT v;
9048     BSTR p;
9049 
9050     doc = create_document(&IID_IXMLDOMDocument);
9051     doc3 = create_document(&IID_IXMLDOMDocument);
9052 
9053     /* document to document */
9054     V_VT(&v) = VT_NULL;
9055     node = (void*)0xdeadbeef;
9056     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc3, v, &node);
9057     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9058     ok(node == NULL, "got %p\n", node);
9059 
9060     /* document to itself */
9061     V_VT(&v) = VT_NULL;
9062     node = (void*)0xdeadbeef;
9063     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc, v, &node);
9064     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9065     ok(node == NULL, "got %p\n", node);
9066 
9067     /* insertBefore behaviour for attribute node */
9068     V_VT(&v) = VT_I4;
9069     V_I4(&v) = NODE_ATTRIBUTE;
9070 
9071     attr = NULL;
9072     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr"), NULL, (IXMLDOMNode**)&attr);
9073     ok(hr == S_OK, "got 0x%08x\n", hr);
9074     ok(attr != NULL, "got %p\n", attr);
9075 
9076     /* attribute to document */
9077     V_VT(&v) = VT_NULL;
9078     node = (void*)0xdeadbeef;
9079     hr = IXMLDOMDocument_insertBefore(doc3, (IXMLDOMNode*)attr, v, &node);
9080     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9081     ok(node == NULL, "got %p\n", node);
9082 
9083     /* cdata to document */
9084     V_VT(&v) = VT_I4;
9085     V_I4(&v) = NODE_CDATA_SECTION;
9086 
9087     cdata = NULL;
9088     hr = IXMLDOMDocument_createNode(doc3, v, _bstr_("cdata"), NULL, &cdata);
9089     ok(hr == S_OK, "got 0x%08x\n", hr);
9090     ok(cdata != NULL, "got %p\n", cdata);
9091 
9092     EXPECT_NO_CHILDREN(cdata);
9093 
9094     /* attribute to cdata */
9095     V_VT(&v) = VT_NULL;
9096     node = (void*)0xdeadbeef;
9097     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)attr, v, &node);
9098     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9099     ok(node == NULL, "got %p\n", node);
9100 
9101     /* document to cdata */
9102     V_VT(&v) = VT_NULL;
9103     node = (void*)0xdeadbeef;
9104     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)doc, v, &node);
9105     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9106     ok(node == NULL, "got %p\n", node);
9107 
9108     V_VT(&v) = VT_NULL;
9109     node = (void*)0xdeadbeef;
9110     hr = IXMLDOMDocument_insertBefore(doc3, cdata, v, &node);
9111     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9112     ok(node == NULL, "got %p\n", node);
9113 
9114     IXMLDOMNode_Release(cdata);
9115     IXMLDOMDocument_Release(doc3);
9116 
9117     /* attribute to attribute */
9118     V_VT(&v) = VT_I4;
9119     V_I4(&v) = NODE_ATTRIBUTE;
9120     newnode = NULL;
9121     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr2"), NULL, &newnode);
9122     ok(hr == S_OK, "got 0x%08x\n", hr);
9123     ok(newnode != NULL, "got %p\n", newnode);
9124 
9125     V_VT(&v) = VT_NULL;
9126     node = (void*)0xdeadbeef;
9127     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9128     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9129     ok(node == NULL, "got %p\n", node);
9130 
9131     V_VT(&v) = VT_UNKNOWN;
9132     V_UNKNOWN(&v) = (IUnknown*)attr;
9133     node = (void*)0xdeadbeef;
9134     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9135     todo_wine ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9136     ok(node == NULL, "got %p\n", node);
9137     IXMLDOMNode_Release(newnode);
9138 
9139     /* cdata to attribute */
9140     V_VT(&v) = VT_I4;
9141     V_I4(&v) = NODE_CDATA_SECTION;
9142     newnode = NULL;
9143     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9144     ok(hr == S_OK, "got 0x%08x\n", hr);
9145     ok(newnode != NULL, "got %p\n", newnode);
9146 
9147     V_VT(&v) = VT_NULL;
9148     node = (void*)0xdeadbeef;
9149     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9150     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9151     ok(node == NULL, "got %p\n", node);
9152     IXMLDOMNode_Release(newnode);
9153 
9154     /* comment to attribute */
9155     V_VT(&v) = VT_I4;
9156     V_I4(&v) = NODE_COMMENT;
9157     newnode = NULL;
9158     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9159     ok(hr == S_OK, "got 0x%08x\n", hr);
9160     ok(newnode != NULL, "got %p\n", newnode);
9161 
9162     V_VT(&v) = VT_NULL;
9163     node = (void*)0xdeadbeef;
9164     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9165     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9166     ok(node == NULL, "got %p\n", node);
9167     IXMLDOMNode_Release(newnode);
9168 
9169     /* element to attribute */
9170     V_VT(&v) = VT_I4;
9171     V_I4(&v) = NODE_ELEMENT;
9172     newnode = NULL;
9173     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9174     ok(hr == S_OK, "got 0x%08x\n", hr);
9175     ok(newnode != NULL, "got %p\n", newnode);
9176 
9177     V_VT(&v) = VT_NULL;
9178     node = (void*)0xdeadbeef;
9179     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9180     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9181     ok(node == NULL, "got %p\n", node);
9182     IXMLDOMNode_Release(newnode);
9183 
9184     /* pi to attribute */
9185     V_VT(&v) = VT_I4;
9186     V_I4(&v) = NODE_PROCESSING_INSTRUCTION;
9187     newnode = NULL;
9188     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9189     ok(hr == S_OK, "got 0x%08x\n", hr);
9190     ok(newnode != NULL, "got %p\n", newnode);
9191 
9192     V_VT(&v) = VT_NULL;
9193     node = (void*)0xdeadbeef;
9194     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9195     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9196     ok(node == NULL, "got %p\n", node);
9197     IXMLDOMNode_Release(newnode);
9198     IXMLDOMAttribute_Release(attr);
9199 
9200     /* insertBefore for elements */
9201     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem1);
9202     ok(hr == S_OK, "got 0x%08x\n", hr);
9203 
9204     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem2"), &elem2);
9205     ok(hr == S_OK, "got 0x%08x\n", hr);
9206 
9207     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9208     ok(hr == S_OK, "got 0x%08x\n", hr);
9209 
9210     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9211     ok(hr == S_OK, "got 0x%08x\n", hr);
9212 
9213     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem4"), &elem4);
9214     ok(hr == S_OK, "got 0x%08x\n", hr);
9215 
9216     EXPECT_NO_CHILDREN(elem1);
9217     EXPECT_NO_CHILDREN(elem2);
9218     EXPECT_NO_CHILDREN(elem3);
9219 
9220     todo_wine EXPECT_REF(elem2, 2);
9221 
9222     /* document to element */
9223     V_VT(&v) = VT_DISPATCH;
9224     V_DISPATCH(&v) = NULL;
9225     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)doc, v, NULL);
9226     ok(hr == E_FAIL, "got 0x%08x\n", hr);
9227 
9228     V_VT(&v) = VT_DISPATCH;
9229     V_DISPATCH(&v) = NULL;
9230     node = NULL;
9231     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem4, v, &node);
9232     ok(hr == S_OK, "got 0x%08x\n", hr);
9233     ok(node == (void*)elem4, "got %p\n", node);
9234 
9235     EXPECT_CHILDREN(elem1);
9236     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem4, NULL);
9237     EXPECT_HR(hr, S_OK);
9238     IXMLDOMElement_Release(elem4);
9239 
9240     EXPECT_NO_CHILDREN(elem1);
9241 
9242     V_VT(&v) = VT_NULL;
9243     node = NULL;
9244     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9245     ok(hr == S_OK, "got 0x%08x\n", hr);
9246     ok(node == (void*)elem2, "got %p\n", node);
9247 
9248     EXPECT_CHILDREN(elem1);
9249     todo_wine EXPECT_REF(elem2, 3);
9250     IXMLDOMNode_Release(node);
9251 
9252     /* again for already linked node */
9253     V_VT(&v) = VT_NULL;
9254     node = NULL;
9255     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9256     ok(hr == S_OK, "got 0x%08x\n", hr);
9257     ok(node == (void*)elem2, "got %p\n", node);
9258 
9259     EXPECT_CHILDREN(elem1);
9260 
9261     /* increments each time */
9262     todo_wine EXPECT_REF(elem2, 3);
9263     IXMLDOMNode_Release(node);
9264 
9265     /* try to add to another element */
9266     V_VT(&v) = VT_NULL;
9267     node = (void*)0xdeadbeef;
9268     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem2, v, &node);
9269     ok(hr == S_OK, "got 0x%08x\n", hr);
9270     ok(node == (void*)elem2, "got %p\n", node);
9271 
9272     EXPECT_CHILDREN(elem3);
9273     EXPECT_NO_CHILDREN(elem1);
9274 
9275     IXMLDOMNode_Release(node);
9276 
9277     /* cross document case - try to add as child to a node created with other doc */
9278     doc2 = create_document(&IID_IXMLDOMDocument);
9279 
9280     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem4);
9281     ok(hr == S_OK, "got 0x%08x\n", hr);
9282     todo_wine EXPECT_REF(elem4, 2);
9283 
9284     /* same name, another instance */
9285     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem5);
9286     ok(hr == S_OK, "got 0x%08x\n", hr);
9287     todo_wine EXPECT_REF(elem5, 2);
9288 
9289     todo_wine EXPECT_REF(elem3, 2);
9290     V_VT(&v) = VT_NULL;
9291     node = NULL;
9292     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem4, v, &node);
9293     ok(hr == S_OK, "got 0x%08x\n", hr);
9294     ok(node == (void*)elem4, "got %p\n", node);
9295     todo_wine EXPECT_REF(elem4, 3);
9296     todo_wine EXPECT_REF(elem3, 2);
9297     IXMLDOMNode_Release(node);
9298 
9299     V_VT(&v) = VT_NULL;
9300     node = NULL;
9301     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem5, v, &node);
9302     ok(hr == S_OK, "got 0x%08x\n", hr);
9303     ok(node == (void*)elem5, "got %p\n", node);
9304     todo_wine EXPECT_REF(elem4, 2);
9305     todo_wine EXPECT_REF(elem5, 3);
9306     IXMLDOMNode_Release(node);
9307 
9308     IXMLDOMDocument_Release(doc2);
9309 
9310     IXMLDOMElement_Release(elem1);
9311     IXMLDOMElement_Release(elem2);
9312     IXMLDOMElement_Release(elem3);
9313     IXMLDOMElement_Release(elem4);
9314     IXMLDOMElement_Release(elem5);
9315 
9316     /* elements with same default namespace */
9317     V_VT(&v) = VT_I4;
9318     V_I4(&v) = NODE_ELEMENT;
9319     elem1 = NULL;
9320     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9321     ok(hr == S_OK, "got 0x%08x\n", hr);
9322     ok(elem1 != NULL, "got %p\n", elem1);
9323 
9324     V_VT(&v) = VT_I4;
9325     V_I4(&v) = NODE_ELEMENT;
9326     elem2 = NULL;
9327     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem2);
9328     ok(hr == S_OK, "got 0x%08x\n", hr);
9329     ok(elem2 != NULL, "got %p\n", elem2);
9330 
9331     /* check contents so far */
9332     p = NULL;
9333     hr = IXMLDOMElement_get_xml(elem1, &p);
9334     ok(hr == S_OK, "got 0x%08x\n", hr);
9335     ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9336     SysFreeString(p);
9337 
9338     p = NULL;
9339     hr = IXMLDOMElement_get_xml(elem2, &p);
9340     ok(hr == S_OK, "got 0x%08x\n", hr);
9341     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9342     SysFreeString(p);
9343 
9344     V_VT(&v) = VT_NULL;
9345     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9346     ok(hr == S_OK, "got 0x%08x\n", hr);
9347 
9348     /* get_xml depends on context, for top node it omits child namespace attribute,
9349        but at child level it's still returned */
9350     p = NULL;
9351     hr = IXMLDOMElement_get_xml(elem1, &p);
9352     ok(hr == S_OK, "got 0x%08x\n", hr);
9353     todo_wine ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"><elem2/></elem1>")),
9354         "got %s\n", wine_dbgstr_w(p));
9355     SysFreeString(p);
9356 
9357     p = NULL;
9358     hr = IXMLDOMElement_get_xml(elem2, &p);
9359     ok(hr == S_OK, "got 0x%08x\n", hr);
9360     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9361     SysFreeString(p);
9362 
9363     IXMLDOMElement_Release(elem1);
9364     IXMLDOMElement_Release(elem2);
9365 
9366     /* child without default namespace added to node with default namespace */
9367     V_VT(&v) = VT_I4;
9368     V_I4(&v) = NODE_ELEMENT;
9369     elem1 = NULL;
9370     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9371     ok(hr == S_OK, "got 0x%08x\n", hr);
9372     ok(elem1 != NULL, "got %p\n", elem1);
9373 
9374     V_VT(&v) = VT_I4;
9375     V_I4(&v) = NODE_ELEMENT;
9376     elem2 = NULL;
9377     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), NULL, (IXMLDOMNode**)&elem2);
9378     ok(hr == S_OK, "got 0x%08x\n", hr);
9379     ok(elem2 != NULL, "got %p\n", elem2);
9380 
9381     EXPECT_REF(elem2, 1);
9382     V_VT(&v) = VT_NULL;
9383     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9384     ok(hr == S_OK, "got 0x%08x\n", hr);
9385     EXPECT_REF(elem2, 1);
9386 
9387     p = NULL;
9388     hr = IXMLDOMElement_get_xml(elem2, &p);
9389     ok(hr == S_OK, "got 0x%08x\n", hr);
9390     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9391     SysFreeString(p);
9392 
9393     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem2, NULL);
9394     ok(hr == S_OK, "got 0x%08x\n", hr);
9395 
9396     p = NULL;
9397     hr = IXMLDOMElement_get_xml(elem2, &p);
9398     ok(hr == S_OK, "got 0x%08x\n", hr);
9399     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9400     SysFreeString(p);
9401 
9402     IXMLDOMElement_Release(elem1);
9403     IXMLDOMElement_Release(elem2);
9404     IXMLDOMDocument_Release(doc);
9405 }
9406 
9407 static void test_appendChild(void)
9408 {
9409     IXMLDOMDocument *doc, *doc2;
9410     IXMLDOMElement *elem, *elem2;
9411     HRESULT hr;
9412 
9413     doc = create_document(&IID_IXMLDOMDocument);
9414     doc2 = create_document(&IID_IXMLDOMDocument);
9415 
9416     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
9417     ok(hr == S_OK, "got 0x%08x\n", hr);
9418 
9419     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
9420     ok(hr == S_OK, "got 0x%08x\n", hr);
9421 
9422     EXPECT_REF(doc, 1);
9423     todo_wine EXPECT_REF(elem, 2);
9424     EXPECT_REF(doc2, 1);
9425     todo_wine EXPECT_REF(elem2, 2);
9426     EXPECT_NO_CHILDREN(doc);
9427     EXPECT_NO_CHILDREN(doc2);
9428 
9429     hr = IXMLDOMDocument_appendChild(doc2, NULL, NULL);
9430     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9431 
9432     hr = IXMLDOMElement_appendChild(elem, NULL, NULL);
9433     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9434 
9435     /* append from another document */
9436     hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
9437     ok(hr == S_OK, "got 0x%08x\n", hr);
9438 
9439     EXPECT_REF(doc, 1);
9440     todo_wine EXPECT_REF(elem, 2);
9441     EXPECT_REF(doc2, 1);
9442     todo_wine EXPECT_REF(elem2, 2);
9443     EXPECT_NO_CHILDREN(doc);
9444     EXPECT_CHILDREN(doc2);
9445 
9446     IXMLDOMElement_Release(elem);
9447     IXMLDOMElement_Release(elem2);
9448     IXMLDOMDocument_Release(doc);
9449     IXMLDOMDocument_Release(doc2);
9450 }
9451 
9452 static void test_get_doctype(void)
9453 {
9454     static const WCHAR emailW[] = {'e','m','a','i','l',0};
9455     IXMLDOMDocumentType *doctype;
9456     IXMLDOMDocument *doc;
9457     VARIANT_BOOL b;
9458     HRESULT hr;
9459     BSTR s;
9460 
9461     doc = create_document(&IID_IXMLDOMDocument);
9462 
9463     hr = IXMLDOMDocument_get_doctype(doc, NULL);
9464     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9465 
9466     doctype = (void*)0xdeadbeef;
9467     hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9468     ok(hr == S_FALSE, "got 0x%08x\n", hr);
9469     ok(doctype == NULL, "got %p\n", doctype);
9470 
9471     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szEmailXML), &b);
9472     ok(hr == S_OK, "got 0x%08x\n", hr);
9473     ok(b == VARIANT_TRUE, "failed to load XML string\n");
9474 
9475     doctype = NULL;
9476     hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9477     ok(hr == S_OK, "got 0x%08x\n", hr);
9478     ok(doctype != NULL, "got %p\n", doctype);
9479 
9480     hr = IXMLDOMDocumentType_get_name(doctype, NULL);
9481     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9482 
9483     hr = IXMLDOMDocumentType_get_name(doctype, &s);
9484     ok(hr == S_OK, "got 0x%08x\n", hr);
9485     ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9486     SysFreeString(s);
9487 
9488     hr = IXMLDOMDocumentType_get_nodeName(doctype, &s);
9489     ok(hr == S_OK, "got 0x%08x\n", hr);
9490     ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9491     SysFreeString(s);
9492 
9493     IXMLDOMDocumentType_Release(doctype);
9494     IXMLDOMDocument_Release(doc);
9495 }
9496 
9497 static void test_get_tagName(void)
9498 {
9499     IXMLDOMDocument *doc;
9500     IXMLDOMElement *elem, *elem2;
9501     HRESULT hr;
9502     BSTR str;
9503 
9504     doc = create_document(&IID_IXMLDOMDocument);
9505 
9506     hr = IXMLDOMDocument_createElement(doc, _bstr_("element"), &elem);
9507     ok(hr == S_OK, "got 0x%08x\n", hr);
9508 
9509     hr = IXMLDOMElement_get_tagName(elem, NULL);
9510     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9511 
9512     str = NULL;
9513     hr = IXMLDOMElement_get_tagName(elem, &str);
9514     ok(hr == S_OK, "got 0x%08x\n", hr);
9515     ok(!lstrcmpW(str, _bstr_("element")), "got %s\n", wine_dbgstr_w(str));
9516     SysFreeString(str);
9517 
9518     hr = IXMLDOMDocument_createElement(doc, _bstr_("s:element"), &elem2);
9519     ok(hr == S_OK, "got 0x%08x\n", hr);
9520 
9521     str = NULL;
9522     hr = IXMLDOMElement_get_tagName(elem2, &str);
9523     ok(hr == S_OK, "got 0x%08x\n", hr);
9524     ok(!lstrcmpW(str, _bstr_("s:element")), "got %s\n", wine_dbgstr_w(str));
9525     SysFreeString(str);
9526 
9527     IXMLDOMElement_Release(elem);
9528     IXMLDOMElement_Release(elem2);
9529     IXMLDOMDocument_Release(doc);
9530     free_bstrs();
9531 }
9532 
9533 typedef struct {
9534     DOMNodeType type;
9535     const char *name;
9536     VARTYPE vt;
9537     HRESULT hr;
9538 } node_type_t;
9539 
9540 static const node_type_t get_datatype[] = {
9541     { NODE_ELEMENT,                "element",   VT_NULL, S_FALSE },
9542     { NODE_ATTRIBUTE,              "attr",      VT_NULL, S_FALSE },
9543     { NODE_TEXT,                   "text",      VT_NULL, S_FALSE },
9544     { NODE_CDATA_SECTION ,         "cdata",     VT_NULL, S_FALSE },
9545     { NODE_ENTITY_REFERENCE,       "entityref", VT_NULL, S_FALSE },
9546     { NODE_PROCESSING_INSTRUCTION, "pi",        VT_NULL, S_FALSE },
9547     { NODE_COMMENT,                "comment",   VT_NULL, S_FALSE },
9548     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   VT_NULL, S_FALSE },
9549     { 0 }
9550 };
9551 
9552 static void test_get_dataType(void)
9553 {
9554     const node_type_t *entry = get_datatype;
9555     IXMLDOMDocument *doc;
9556 
9557     doc = create_document(&IID_IXMLDOMDocument);
9558 
9559     while (entry->type)
9560     {
9561         IXMLDOMNode *node = NULL;
9562         VARIANT var, type;
9563         HRESULT hr;
9564 
9565         V_VT(&var) = VT_I4;
9566         V_I4(&var) = entry->type;
9567         hr = IXMLDOMDocument_createNode(doc, var, _bstr_(entry->name), NULL, &node);
9568         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9569 
9570         hr = IXMLDOMNode_get_dataType(node, NULL);
9571         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9572 
9573         VariantInit(&type);
9574         hr = IXMLDOMNode_get_dataType(node, &type);
9575         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9576             hr, entry->hr, entry->type);
9577         ok(V_VT(&type) == entry->vt, "got %d, expected %d. node type %d\n",
9578             V_VT(&type), entry->vt, entry->type);
9579         VariantClear(&type);
9580 
9581         IXMLDOMNode_Release(node);
9582 
9583         entry++;
9584     }
9585 
9586     IXMLDOMDocument_Release(doc);
9587     free_bstrs();
9588 }
9589 
9590 typedef struct _get_node_typestring_t {
9591     DOMNodeType type;
9592     const char *string;
9593 } get_node_typestring_t;
9594 
9595 static const get_node_typestring_t get_node_typestring[] = {
9596     { NODE_ELEMENT,                "element"               },
9597     { NODE_ATTRIBUTE,              "attribute"             },
9598     { NODE_TEXT,                   "text"                  },
9599     { NODE_CDATA_SECTION ,         "cdatasection"          },
9600     { NODE_ENTITY_REFERENCE,       "entityreference"       },
9601     { NODE_PROCESSING_INSTRUCTION, "processinginstruction" },
9602     { NODE_COMMENT,                "comment"               },
9603     { NODE_DOCUMENT_FRAGMENT,      "documentfragment"      },
9604     { 0 }
9605 };
9606 
9607 static void test_get_nodeTypeString(void)
9608 {
9609     const get_node_typestring_t *entry = get_node_typestring;
9610     IXMLDOMDocument *doc;
9611     HRESULT hr;
9612     BSTR str;
9613 
9614     doc = create_document(&IID_IXMLDOMDocument);
9615 
9616     hr = IXMLDOMDocument_get_nodeTypeString(doc, &str);
9617     ok(hr == S_OK, "got 0x%08x\n", hr);
9618     ok(!lstrcmpW(str, _bstr_("document")), "got string %s\n", wine_dbgstr_w(str));
9619     SysFreeString(str);
9620 
9621     while (entry->type)
9622     {
9623         IXMLDOMNode *node = NULL;
9624         VARIANT var;
9625 
9626         V_VT(&var) = VT_I4;
9627         V_I4(&var) = entry->type;
9628         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9629         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9630 
9631         hr = IXMLDOMNode_get_nodeTypeString(node, NULL);
9632         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9633 
9634         hr = IXMLDOMNode_get_nodeTypeString(node, &str);
9635         ok(hr == S_OK, "got 0x%08x\n", hr);
9636         ok(!lstrcmpW(str, _bstr_(entry->string)), "got string %s, expected %s. node type %d\n",
9637             wine_dbgstr_w(str), entry->string, entry->type);
9638         SysFreeString(str);
9639         IXMLDOMNode_Release(node);
9640 
9641         entry++;
9642     }
9643 
9644     IXMLDOMDocument_Release(doc);
9645     free_bstrs();
9646 }
9647 
9648 typedef struct _get_attributes_t {
9649     DOMNodeType type;
9650     HRESULT hr;
9651 } get_attributes_t;
9652 
9653 static const get_attributes_t get_attributes[] = {
9654     { NODE_ATTRIBUTE,              S_FALSE },
9655     { NODE_TEXT,                   S_FALSE },
9656     { NODE_CDATA_SECTION ,         S_FALSE },
9657     { NODE_ENTITY_REFERENCE,       S_FALSE },
9658     { NODE_PROCESSING_INSTRUCTION, S_FALSE },
9659     { NODE_COMMENT,                S_FALSE },
9660     { NODE_DOCUMENT_FRAGMENT,      S_FALSE },
9661     { 0 }
9662 };
9663 
9664 static void test_get_attributes(void)
9665 {
9666     const get_attributes_t *entry = get_attributes;
9667     IXMLDOMNamedNodeMap *map;
9668     IXMLDOMDocument *doc, *doc2;
9669     IXMLDOMNode *node, *node2;
9670     IXMLDOMElement *elem;
9671     VARIANT_BOOL b;
9672     HRESULT hr;
9673     VARIANT v;
9674     BSTR str;
9675     LONG length;
9676 
9677     doc = create_document(&IID_IXMLDOMDocument);
9678 
9679     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
9680     ok(hr == S_OK, "got %08x\n", hr);
9681 
9682     hr = IXMLDOMDocument_get_attributes(doc, NULL);
9683     ok(hr == E_INVALIDARG, "got %08x\n", hr);
9684 
9685     map = (void*)0xdeadbeef;
9686     hr = IXMLDOMDocument_get_attributes(doc, &map);
9687     ok(hr == S_FALSE, "got %08x\n", hr);
9688     ok(map == NULL, "got %p\n", map);
9689 
9690     /* first child is <?xml ?> */
9691     hr = IXMLDOMDocument_get_firstChild(doc, &node);
9692     ok(hr == S_OK, "got %08x\n", hr);
9693 
9694     hr = IXMLDOMNode_get_attributes(node, &map);
9695     ok(hr == S_OK, "got %08x\n", hr);
9696 
9697     node2 = (void*)0xdeadbeef;
9698     hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_("attr"), &node2);
9699     ok(hr == S_FALSE, "got %08x\n", hr);
9700     ok(node2 == NULL, "got %p\n", node2);
9701 
9702     length = -1;
9703     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9704     EXPECT_HR(hr, S_OK);
9705     todo_wine ok(length == 1, "got %d\n", length);
9706 
9707     if (hr == S_OK && length == 1)
9708     {
9709         IXMLDOMAttribute *attr;
9710         DOMNodeType type;
9711         VARIANT v;
9712 
9713         node2 = NULL;
9714         hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9715         EXPECT_HR(hr, S_OK);
9716         ok(node != NULL, "got %p\n", node2);
9717 
9718         hr = IXMLDOMNode_get_nodeName(node2, &str);
9719         EXPECT_HR(hr, S_OK);
9720         ok(!lstrcmpW(str, _bstr_("version")), "got %s\n", wine_dbgstr_w(str));
9721         SysFreeString(str);
9722 
9723         length = -1;
9724         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9725         EXPECT_HR(hr, S_OK);
9726         ok(length == 1, "got %d\n", length);
9727 
9728         type = -1;
9729         hr = IXMLDOMNode_get_nodeType(node2, &type);
9730         EXPECT_HR(hr, S_OK);
9731         ok(type == NODE_ATTRIBUTE, "got %d\n", type);
9732 
9733         hr = IXMLDOMNode_get_xml(node, &str);
9734         EXPECT_HR(hr, S_OK);
9735         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9736         SysFreeString(str);
9737 
9738         hr = IXMLDOMNode_get_text(node, &str);
9739         EXPECT_HR(hr, S_OK);
9740         ok(!lstrcmpW(str, _bstr_("version=\"1.0\"")), "got %s\n", wine_dbgstr_w(str));
9741         SysFreeString(str);
9742 
9743         hr = IXMLDOMNamedNodeMap_removeNamedItem(map, _bstr_("version"), NULL);
9744         EXPECT_HR(hr, S_OK);
9745 
9746         length = -1;
9747         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9748         EXPECT_HR(hr, S_OK);
9749         ok(length == 0, "got %d\n", length);
9750 
9751         hr = IXMLDOMNode_get_xml(node, &str);
9752         EXPECT_HR(hr, S_OK);
9753         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9754         SysFreeString(str);
9755 
9756         hr = IXMLDOMNode_get_text(node, &str);
9757         EXPECT_HR(hr, S_OK);
9758         ok(!lstrcmpW(str, _bstr_("")), "got %s\n", wine_dbgstr_w(str));
9759         SysFreeString(str);
9760 
9761         IXMLDOMNamedNodeMap_Release(map);
9762 
9763         hr = IXMLDOMNode_get_attributes(node, &map);
9764         ok(hr == S_OK, "got %08x\n", hr);
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 = IXMLDOMDocument_createAttribute(doc, _bstr_("encoding"), &attr);
9772         EXPECT_HR(hr, S_OK);
9773 
9774         V_VT(&v) = VT_BSTR;
9775         V_BSTR(&v) = _bstr_("UTF-8");
9776         hr = IXMLDOMAttribute_put_nodeValue(attr, v);
9777         EXPECT_HR(hr, S_OK);
9778 
9779         EXPECT_REF(attr, 2);
9780         hr = IXMLDOMNamedNodeMap_setNamedItem(map, (IXMLDOMNode*)attr, NULL);
9781         EXPECT_HR(hr, S_OK);
9782         EXPECT_REF(attr, 2);
9783 
9784         hr = IXMLDOMNode_get_attributes(node, &map);
9785         ok(hr == S_OK, "got %08x\n", hr);
9786 
9787         length = -1;
9788         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9789         EXPECT_HR(hr, S_OK);
9790         ok(length == 1, "got %d\n", length);
9791 
9792         hr = IXMLDOMNode_get_xml(node, &str);
9793         EXPECT_HR(hr, S_OK);
9794         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9795         SysFreeString(str);
9796 
9797         hr = IXMLDOMNode_get_text(node, &str);
9798         EXPECT_HR(hr, S_OK);
9799         ok(!lstrcmpW(str, _bstr_("encoding=\"UTF-8\"")), "got %s\n", wine_dbgstr_w(str));
9800         SysFreeString(str);
9801 
9802         IXMLDOMNamedNodeMap_Release(map);
9803         IXMLDOMNode_Release(node2);
9804     }
9805 
9806     IXMLDOMNode_Release(node);
9807 
9808     /* last child is element */
9809     EXPECT_REF(doc, 1);
9810     hr = IXMLDOMDocument_get_lastChild(doc, &node);
9811     ok(hr == S_OK, "got %08x\n", hr);
9812     EXPECT_REF(doc, 1);
9813 
9814     EXPECT_REF(node, 1);
9815     hr = IXMLDOMNode_get_attributes(node, &map);
9816     ok(hr == S_OK, "got %08x\n", hr);
9817     EXPECT_REF(node, 1);
9818     EXPECT_REF(doc, 1);
9819 
9820     EXPECT_REF(map, 1);
9821     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9822     ok(hr == S_OK, "got %08x\n", hr);
9823     EXPECT_REF(node, 1);
9824     EXPECT_REF(node2, 1);
9825     EXPECT_REF(map, 1);
9826     EXPECT_REF(doc, 1);
9827     IXMLDOMNode_Release(node2);
9828 
9829     /* release node before map release, map still works */
9830     IXMLDOMNode_Release(node);
9831 
9832     length = 0;
9833     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9834     ok(hr == S_OK, "got %08x\n", hr);
9835     ok(length == 1, "got %d\n", length);
9836 
9837     node2 = NULL;
9838     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9839     ok(hr == S_OK, "got %08x\n", hr);
9840     EXPECT_REF(node2, 1);
9841     IXMLDOMNode_Release(node2);
9842 
9843     IXMLDOMNamedNodeMap_Release(map);
9844 
9845     /* append created element a different document, map still works */
9846     hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
9847     ok(hr == S_OK, "createElement failed: %08x\n", hr);
9848 
9849     V_VT(&v) = VT_I4;
9850     V_I4(&v) = 1;
9851     hr = IXMLDOMElement_setAttribute(elem, _bstr_("testattr"), v);
9852     ok(hr == S_OK, "setAttribute failed: %08x\n", hr);
9853 
9854     hr = IXMLDOMElement_get_attributes(elem, &map);
9855     ok(hr == S_OK, "get_attributes failed: %08x\n", hr);
9856 
9857     length = 0;
9858     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9859     ok(hr == S_OK, "got %08x\n", hr);
9860     ok(length == 1, "got %d\n", length);
9861 
9862     doc2 = create_document(&IID_IXMLDOMDocument);
9863 
9864     hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, &node);
9865     ok(hr == S_OK, "appendChild failed: %08x\n", hr);
9866     ok(node == (IXMLDOMNode*)elem, "node != elem\n");
9867     IXMLDOMNode_Release(node);
9868     IXMLDOMElement_Release(elem);
9869     IXMLDOMDocument_Release(doc2);
9870 
9871     length = 0;
9872     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9873     ok(hr == S_OK, "got %08x\n", hr);
9874     ok(length == 1, "got %d\n", length);
9875 
9876     IXMLDOMNamedNodeMap_Release(map);
9877 
9878     while (entry->type)
9879     {
9880         VARIANT var;
9881 
9882         node = NULL;
9883 
9884         V_VT(&var) = VT_I4;
9885         V_I4(&var) = entry->type;
9886         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9887         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9888 
9889         hr = IXMLDOMNode_get_attributes(node, NULL);
9890         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9891 
9892         map = (void*)0xdeadbeef;
9893         hr = IXMLDOMNode_get_attributes(node, &map);
9894         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9895             hr, entry->hr, entry->type);
9896         ok(map == NULL, "got %p\n", map);
9897 
9898         IXMLDOMNode_Release(node);
9899 
9900         entry++;
9901     }
9902 
9903     IXMLDOMDocument_Release(doc);
9904     free_bstrs();
9905 }
9906 
9907 static void test_selection(void)
9908 {
9909     IXMLDOMSelection *selection, *selection2;
9910     IEnumVARIANT *enum1, *enum2, *enum3;
9911     IXMLDOMNodeList *list;
9912     IUnknown *unk1, *unk2;
9913     IXMLDOMDocument *doc;
9914     IDispatchEx *dispex;
9915     IXMLDOMNode *node;
9916     IDispatch *disp;
9917     VARIANT_BOOL b;
9918     HRESULT hr;
9919     DISPID did;
9920     VARIANT v;
9921     BSTR name;
9922     ULONG ret;
9923     LONG len;
9924 
9925     doc = create_document(&IID_IXMLDOMDocument);
9926 
9927     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
9928     EXPECT_HR(hr, S_OK);
9929 
9930     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list);
9931     EXPECT_HR(hr, S_OK);
9932 
9933     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9934     EXPECT_HR(hr, S_OK);
9935     IXMLDOMSelection_Release(selection);
9936 
9937     /* collection disp id */
9938     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IDispatchEx, (void**)&dispex);
9939     EXPECT_HR(hr, S_OK);
9940     did = 0;
9941     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
9942     EXPECT_HR(hr, S_OK);
9943     ok(did == DISPID_DOM_COLLECTION_BASE, "got %d\n", did);
9944     len = 0;
9945     hr = IXMLDOMSelection_get_length(selection, &len);
9946     EXPECT_HR(hr, S_OK);
9947     ok(len == 1, "got %d\n", len);
9948     hr = IDispatchEx_GetDispID(dispex, _bstr_("10"), 0, &did);
9949     EXPECT_HR(hr, S_OK);
9950     ok(did == DISPID_DOM_COLLECTION_BASE+10, "got %d\n", did);
9951     IDispatchEx_Release(dispex);
9952 
9953     /* IEnumVARIANT tests */
9954     enum1 = NULL;
9955     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum1);
9956     EXPECT_HR(hr, S_OK);
9957     ok(enum1 != NULL, "got %p\n", enum1);
9958     EXPECT_REF(enum1, 2);
9959 
9960     EXPECT_REF(selection, 1);
9961     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IUnknown, (void**)&unk1);
9962     EXPECT_HR(hr, S_OK);
9963     EXPECT_REF(selection, 2);
9964     EXPECT_REF(enum1, 2);
9965 
9966     /* enumerator and selection object return same IUnknown* */
9967     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
9968     EXPECT_HR(hr, S_OK);
9969     EXPECT_REF(selection, 3);
9970     EXPECT_REF(enum1, 2);
9971     ok(unk2 == unk1, "got %p, %p\n", unk1, unk2);
9972     IUnknown_Release(unk2);
9973 
9974     EXPECT_REF(selection, 2);
9975     IEnumVARIANT_AddRef(enum1);
9976     EXPECT_REF(selection, 2);
9977     IEnumVARIANT_Release(enum1);
9978 
9979     enum3 = NULL;
9980     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum3);
9981     EXPECT_HR(hr, S_OK);
9982     ok(enum3 != NULL, "got %p\n", enum3);
9983     ok(enum1 == enum3, "got %p and %p\n", enum1, enum3);
9984     EXPECT_REF(enum1, 3);
9985     IEnumVARIANT_Release(enum3);
9986 
9987     EXPECT_REF(selection, 2);
9988     EXPECT_REF(enum1, 2);
9989 
9990     enum2 = NULL;
9991     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
9992     EXPECT_HR(hr, S_OK);
9993     ok(enum2 != NULL, "got %p\n", enum2);
9994 
9995     EXPECT_REF(selection, 3);
9996     EXPECT_REF(enum1, 2);
9997     EXPECT_REF(enum2, 1);
9998 
9999     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10000 
10001     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
10002     EXPECT_HR(hr, S_OK);
10003     EXPECT_REF(selection, 3);
10004     EXPECT_REF(enum2, 2);
10005     ok(unk2 != unk1, "got %p, %p\n", unk1, unk2);
10006     IUnknown_Release(unk2);
10007     IUnknown_Release(unk1);
10008 
10009     selection2 = NULL;
10010     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IXMLDOMSelection, (void**)&selection2);
10011     EXPECT_HR(hr, S_OK);
10012     ok(selection2 == selection, "got %p and %p\n", selection, selection2);
10013     EXPECT_REF(selection, 3);
10014     EXPECT_REF(enum1, 2);
10015 
10016     IXMLDOMSelection_Release(selection2);
10017 
10018     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IDispatch, (void**)&disp);
10019     EXPECT_HR(hr, S_OK);
10020     EXPECT_REF(selection, 3);
10021     IDispatch_Release(disp);
10022 
10023     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enum3);
10024     EXPECT_HR(hr, S_OK);
10025     ok(enum3 == enum1, "got %p and %p\n", enum3, enum1);
10026     EXPECT_REF(selection, 2);
10027     EXPECT_REF(enum1, 3);
10028 
10029     IEnumVARIANT_Release(enum1);
10030     IEnumVARIANT_Release(enum2);
10031     IEnumVARIANT_Release(enum3);
10032 
10033     enum1 = NULL;
10034     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10035     EXPECT_HR(hr, S_OK);
10036     ok(enum1 != NULL, "got %p\n", enum1);
10037     EXPECT_REF(enum1, 1);
10038     EXPECT_REF(selection, 2);
10039 
10040     enum2 = NULL;
10041     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
10042     EXPECT_HR(hr, S_OK);
10043     ok(enum2 != NULL, "got %p\n", enum2);
10044     EXPECT_REF(enum2, 1);
10045     EXPECT_REF(selection, 3);
10046 
10047     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10048 
10049     IEnumVARIANT_AddRef(enum1);
10050     EXPECT_REF(selection, 3);
10051     EXPECT_REF(enum1, 2);
10052     EXPECT_REF(enum2, 1);
10053     IEnumVARIANT_Release(enum1);
10054 
10055     IEnumVARIANT_Release(enum1);
10056     IEnumVARIANT_Release(enum2);
10057 
10058     EXPECT_REF(selection, 1);
10059 
10060     IXMLDOMNodeList_Release(list);
10061 
10062     hr = IXMLDOMDocument_get_childNodes(doc, &list);
10063     EXPECT_HR(hr, S_OK);
10064 
10065     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10066     EXPECT_HR(hr, E_NOINTERFACE);
10067 
10068     IXMLDOMNodeList_Release(list);
10069 
10070     /* test if IEnumVARIANT touches selection context */
10071     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
10072     EXPECT_HR(hr, S_OK);
10073 
10074     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/*"), &list);
10075     EXPECT_HR(hr, S_OK);
10076 
10077     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10078     EXPECT_HR(hr, S_OK);
10079 
10080     len = 0;
10081     hr = IXMLDOMSelection_get_length(selection, &len);
10082     EXPECT_HR(hr, S_OK);
10083     ok(len == 4, "got %d\n", len);
10084 
10085     enum1 = NULL;
10086     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10087     EXPECT_HR(hr, S_OK);
10088 
10089     /* no-op if zero count */
10090     V_VT(&v) = VT_I2;
10091     hr = IEnumVARIANT_Next(enum1, 0, &v, NULL);
10092     EXPECT_HR(hr, S_OK);
10093     ok(V_VT(&v) == VT_I2, "got var type %d\n", V_VT(&v));
10094 
10095     /* positive count, null array pointer */
10096     hr = IEnumVARIANT_Next(enum1, 1, NULL, NULL);
10097     EXPECT_HR(hr, E_INVALIDARG);
10098 
10099     ret = 1;
10100     hr = IEnumVARIANT_Next(enum1, 1, NULL, &ret);
10101     EXPECT_HR(hr, E_INVALIDARG);
10102     ok(ret == 0, "got %d\n", ret);
10103 
10104     V_VT(&v) = VT_I2;
10105     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10106     EXPECT_HR(hr, S_OK);
10107     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10108 
10109     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10110     EXPECT_HR(hr, S_OK);
10111     hr = IXMLDOMNode_get_nodeName(node, &name);
10112     EXPECT_HR(hr, S_OK);
10113     ok(!lstrcmpW(name, _bstr_("a")), "got node name %s\n", wine_dbgstr_w(name));
10114     SysFreeString(name);
10115     IXMLDOMNode_Release(node);
10116     VariantClear(&v);
10117 
10118     /* list cursor is updated */
10119     hr = IXMLDOMSelection_nextNode(selection, &node);
10120     EXPECT_HR(hr, S_OK);
10121     hr = IXMLDOMNode_get_nodeName(node, &name);
10122     EXPECT_HR(hr, S_OK);
10123     ok(!lstrcmpW(name, _bstr_("c")), "got node name %s\n", wine_dbgstr_w(name));
10124     IXMLDOMNode_Release(node);
10125     SysFreeString(name);
10126 
10127     V_VT(&v) = VT_I2;
10128     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10129     EXPECT_HR(hr, S_OK);
10130     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10131     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10132     EXPECT_HR(hr, S_OK);
10133     hr = IXMLDOMNode_get_nodeName(node, &name);
10134     EXPECT_HR(hr, S_OK);
10135     ok(!lstrcmpW(name, _bstr_("b")), "got node name %s\n", wine_dbgstr_w(name));
10136     SysFreeString(name);
10137     IXMLDOMNode_Release(node);
10138     VariantClear(&v);
10139     IEnumVARIANT_Release(enum1);
10140 
10141     hr = IXMLDOMSelection_nextNode(selection, &node);
10142     EXPECT_HR(hr, S_OK);
10143     hr = IXMLDOMNode_get_nodeName(node, &name);
10144     EXPECT_HR(hr, S_OK);
10145     ok(!lstrcmpW(name, _bstr_("d")), "got node name %s\n", wine_dbgstr_w(name));
10146     IXMLDOMNode_Release(node);
10147     SysFreeString(name);
10148 
10149     IXMLDOMSelection_Release(selection);
10150     IXMLDOMNodeList_Release(list);
10151     IXMLDOMDocument_Release(doc);
10152 
10153     free_bstrs();
10154 }
10155 
10156 static void write_to_file(const char *name, const char *data)
10157 {
10158     DWORD written;
10159     HANDLE hfile;
10160     BOOL ret;
10161 
10162     hfile = CreateFileA(name, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
10163     ok(hfile != INVALID_HANDLE_VALUE, "failed to create test file: %s\n", name);
10164 
10165     ret = WriteFile(hfile, data, strlen(data), &written, NULL);
10166     ok(ret, "WriteFile failed: %s, %d\n", name, GetLastError());
10167 
10168     CloseHandle(hfile);
10169 }
10170 
10171 static void test_load(void)
10172 {
10173     IXMLDOMDocument *doc, *doc2;
10174     BSTR pathW, bstr1, bstr2;
10175     IXMLDOMNodeList *list;
10176     IXMLDOMElement *elem;
10177     char path[MAX_PATH];
10178     VARIANT_BOOL b;
10179     VARIANT src;
10180     HRESULT hr;
10181     void* ptr;
10182 
10183     GetTempPathA(MAX_PATH, path);
10184     strcat(path, "winetest.xml");
10185 
10186     /* prepare a file */
10187     write_to_file(path, win1252xml);
10188 
10189     doc = create_document(&IID_IXMLDOMDocument);
10190 
10191     /* null pointer as input */
10192     V_VT(&src) = VT_UNKNOWN;
10193     V_UNKNOWN(&src) = NULL;
10194     hr = IXMLDOMDocument_load(doc, src, &b);
10195     EXPECT_HR(hr, E_INVALIDARG);
10196     ok(b == VARIANT_FALSE, "got %d\n", b);
10197 
10198     pathW = _bstr_(path);
10199 
10200     /* load from path: VT_BSTR */
10201     V_VT(&src) = VT_BSTR;
10202     V_BSTR(&src) = pathW;
10203     hr = IXMLDOMDocument_load(doc, src, &b);
10204     EXPECT_HR(hr, S_OK);
10205     ok(b == VARIANT_TRUE, "got %d\n", b);
10206 
10207     bstr1 = NULL;
10208     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10209     ok(hr == S_OK, "got 0x%08x\n", hr);
10210     SysFreeString(bstr1);
10211 
10212     /* load from a path: VT_BSTR|VT_BYREF */
10213     V_VT(&src) = VT_BSTR | VT_BYREF;
10214     V_BSTRREF(&src) = &pathW;
10215     hr = IXMLDOMDocument_load(doc, src, &b);
10216     EXPECT_HR(hr, S_OK);
10217     ok(b == VARIANT_TRUE, "got %d\n", b);
10218 
10219     bstr1 = NULL;
10220     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10221     ok(hr == S_OK, "got 0x%08x\n", hr);
10222 
10223     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10224     ok(hr == S_OK, "got 0x%08x\n", hr);
10225 
10226     /* create another instance for the same document, check url */
10227     hr = IXMLDOMElement_get_ownerDocument(elem, &doc2);
10228     ok(hr == S_OK, "got 0x%08x\n", hr);
10229 
10230     hr = IXMLDOMDocument_get_url(doc, &bstr2);
10231     ok(hr == S_OK, "got 0x%08x\n", hr);
10232     ok(!lstrcmpW(bstr1, bstr2), "got %s\n", wine_dbgstr_w(bstr2));
10233 
10234     IXMLDOMDocument_Release(doc2);
10235     IXMLDOMElement_Release(elem);
10236 
10237     SysFreeString(bstr1);
10238     SysFreeString(bstr2);
10239 
10240     /* load from a path: VT_BSTR|VT_BYREF, null ptr */
10241     V_VT(&src) = VT_BSTR | VT_BYREF;
10242     V_BSTRREF(&src) = NULL;
10243     hr = IXMLDOMDocument_load(doc, src, &b);
10244     EXPECT_HR(hr, E_INVALIDARG);
10245     ok(b == VARIANT_FALSE, "got %d\n", b);
10246 
10247     bstr1 = NULL;
10248     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10249     ok(hr == S_OK, "got 0x%08x\n", hr);
10250     SysFreeString(bstr1);
10251 
10252     DeleteFileA(path);
10253 
10254     /* load from existing path, no xml content */
10255     write_to_file(path, nocontent);
10256 
10257     V_VT(&src) = VT_BSTR;
10258     V_BSTR(&src) = pathW;
10259     b = VARIANT_TRUE;
10260     hr = IXMLDOMDocument_load(doc, src, &b);
10261     ok(hr == S_FALSE, "got 0x%08x\n", hr);
10262     ok(b == VARIANT_FALSE, "got %d\n", b);
10263 
10264     bstr1 = (void *)0xdeadbeef;
10265     hr = IXMLDOMDocument_get_url(doc, &bstr1);
10266     ok(hr == S_FALSE, "got 0x%08x\n", hr);
10267     ok(bstr1 == NULL, "got %p\n", bstr1);
10268 
10269     DeleteFileA(path);
10270     IXMLDOMDocument_Release(doc);
10271 
10272     doc = create_document(&IID_IXMLDOMDocument);
10273 
10274     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
10275     EXPECT_HR(hr, S_OK);
10276     ok(b == VARIANT_TRUE, "got %d\n", b);
10277 
10278     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10279     EXPECT_HR(hr, S_OK);
10280     bstr1 = _bstr_(list_to_string(list));
10281 
10282     hr = IXMLDOMNodeList_reset(list);
10283     EXPECT_HR(hr, S_OK);
10284 
10285     IXMLDOMDocument_Release(doc);
10286 
10287     doc = create_document(&IID_IXMLDOMDocument);
10288 
10289     VariantInit(&src);
10290     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenA(szExampleXML));
10291     V_VT(&src) = VT_ARRAY|VT_UI1;
10292     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10293     ptr = NULL;
10294     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10295     EXPECT_HR(hr, S_OK);
10296     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10297 
10298     memcpy(ptr, szExampleXML, lstrlenA(szExampleXML));
10299     hr = SafeArrayUnlock(V_ARRAY(&src));
10300     EXPECT_HR(hr, S_OK);
10301 
10302     hr = IXMLDOMDocument_load(doc, src, &b);
10303     EXPECT_HR(hr, S_OK);
10304     ok(b == VARIANT_TRUE, "got %d\n", b);
10305 
10306     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10307     EXPECT_HR(hr, S_OK);
10308     bstr2 = _bstr_(list_to_string(list));
10309 
10310     hr = IXMLDOMNodeList_reset(list);
10311     EXPECT_HR(hr, S_OK);
10312 
10313     ok(lstrcmpW(bstr1, bstr2) == 0, "strings not equal: %s : %s\n",
10314        wine_dbgstr_w(bstr1), wine_dbgstr_w(bstr2));
10315 
10316     IXMLDOMDocument_Release(doc);
10317     IXMLDOMNodeList_Release(list);
10318     VariantClear(&src);
10319 
10320     /* UTF-16 isn't accepted */
10321     doc = create_document(&IID_IXMLDOMDocument);
10322 
10323     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenW(szComplete1) * sizeof(WCHAR));
10324     V_VT(&src) = VT_ARRAY|VT_UI1;
10325     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10326     ptr = NULL;
10327     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10328     EXPECT_HR(hr, S_OK);
10329     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10330 
10331     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10332     hr = SafeArrayUnlock(V_ARRAY(&src));
10333     EXPECT_HR(hr, S_OK);
10334 
10335     hr = IXMLDOMDocument_load(doc, src, &b);
10336     todo_wine EXPECT_HR(hr, S_FALSE);
10337     todo_wine ok(b == VARIANT_FALSE, "got %d\n", b);
10338 
10339     VariantClear(&src);
10340 
10341     /* it doesn't like it as a VT_ARRAY|VT_UI2 either */
10342     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI2, 0, lstrlenW(szComplete1));
10343     V_VT(&src) = VT_ARRAY|VT_UI2;
10344     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10345     ptr = NULL;
10346     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10347     EXPECT_HR(hr, S_OK);
10348     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10349 
10350     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10351     hr = SafeArrayUnlock(V_ARRAY(&src));
10352     EXPECT_HR(hr, S_OK);
10353 
10354     hr = IXMLDOMDocument_load(doc, src, &b);
10355     todo_wine EXPECT_HR(hr, E_INVALIDARG);
10356     ok(b == VARIANT_FALSE, "got %d\n", b);
10357 
10358     VariantClear(&src);
10359     IXMLDOMDocument_Release(doc);
10360 
10361     free_bstrs();
10362 }
10363 
10364 static void test_domobj_dispex(IUnknown *obj)
10365 {
10366     static const WCHAR testW[] = {'t','e','s','t','p','r','o','p',0};
10367     DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
10368     IDispatchEx *dispex;
10369     IUnknown *unk;
10370     DWORD props;
10371     UINT ticnt;
10372     HRESULT hr;
10373     BSTR name;
10374 
10375     hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
10376     EXPECT_HR(hr, S_OK);
10377     if (FAILED(hr)) return;
10378 
10379     ticnt = 0;
10380     hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
10381     EXPECT_HR(hr, S_OK);
10382     ok(ticnt == 1, "ticnt=%u\n", ticnt);
10383 
10384     name = SysAllocString(szstar);
10385     hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
10386     EXPECT_HR(hr, E_NOTIMPL);
10387     SysFreeString(name);
10388 
10389     hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
10390     EXPECT_HR(hr, E_NOTIMPL);
10391 
10392     props = 0;
10393     hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
10394     EXPECT_HR(hr, E_NOTIMPL);
10395     ok(props == 0, "expected 0 got %d\n", props);
10396 
10397     hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
10398     EXPECT_HR(hr, E_NOTIMPL);
10399     if (SUCCEEDED(hr)) SysFreeString(name);
10400 
10401     hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
10402     EXPECT_HR(hr, E_NOTIMPL);
10403 
10404     unk = (IUnknown*)0xdeadbeef;
10405     hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
10406     EXPECT_HR(hr, E_NOTIMPL);
10407     ok(unk == (IUnknown*)0xdeadbeef, "got %p\n", unk);
10408 
10409     name = SysAllocString(testW);
10410     hr = IDispatchEx_GetDispID(dispex, name, fdexNameEnsure, &dispid);
10411     ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
10412     SysFreeString(name);
10413 
10414     IDispatchEx_Release(dispex);
10415 }
10416 
10417 static void test_mxnamespacemanager(void)
10418 {
10419     static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
10420     IMXNamespacePrefixes *prefixes;
10421     IVBMXNamespaceManager *mgr2;
10422     IMXNamespaceManager *nsmgr;
10423     IUnknown *unk1, *unk2;
10424     WCHAR buffW[250];
10425     IDispatch *disp;
10426     IUnknown *unk;
10427     HRESULT hr;
10428     INT len;
10429 
10430     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10431         &IID_IMXNamespaceManager, (void**)&nsmgr);
10432     EXPECT_HR(hr, S_OK);
10433 
10434     /* IMXNamespaceManager inherits from IUnknown */
10435     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IDispatch, (void**)&disp);
10436     EXPECT_HR(hr, S_OK);
10437     IDispatch_Release(disp);
10438 
10439     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IVBMXNamespaceManager, (void**)&mgr2);
10440     EXPECT_HR(hr, S_OK);
10441 
10442     EXPECT_REF(nsmgr, 2);
10443     EXPECT_REF(mgr2, 2);
10444     prefixes = NULL;
10445     hr = IVBMXNamespaceManager_getDeclaredPrefixes(mgr2, &prefixes);
10446 todo_wine
10447     ok(hr == S_OK, "got 0x%08x\n", hr);
10448     if (hr == S_OK)
10449     {
10450         IDispatchEx *dispex;
10451         VARIANT arg, ret;
10452         DISPPARAMS dispparams;
10453 
10454         ok(prefixes != NULL, "got %p\n", prefixes);
10455         EXPECT_REF(nsmgr, 2);
10456         EXPECT_REF(mgr2, 2);
10457         EXPECT_REF(prefixes, 1);
10458 
10459         IVBMXNamespaceManager_QueryInterface(mgr2, &IID_IUnknown, (void**)&unk1);
10460         IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IUnknown, (void**)&unk2);
10461 
10462         EXPECT_REF(mgr2, 3);
10463         EXPECT_REF(prefixes, 2);
10464 
10465         IUnknown_Release(unk1);
10466         IUnknown_Release(unk2);
10467 
10468         hr = IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IDispatchEx, (void**)&dispex);
10469         ok(hr == S_OK, "got 0x%08x\n", hr);
10470 
10471         V_VT(&arg) = VT_I4;
10472         V_I4(&arg) = 0;
10473         dispparams.cArgs = 1;
10474         dispparams.cNamedArgs = 0;
10475         dispparams.rgdispidNamedArgs = NULL;
10476         dispparams.rgvarg = &arg;
10477 
10478         V_VT(&ret) = VT_EMPTY;
10479         V_DISPATCH(&ret) = (void*)0x1;
10480         hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10481         ok(hr == S_OK, "got 0x%08x\n", hr);
10482         ok(V_VT(&ret) == VT_BSTR, "got %d\n", V_VT(&ret));
10483         ok(V_BSTR(&ret) != NULL, "got %p\n", V_BSTR(&ret));
10484         VariantClear(&ret);
10485 
10486         IDispatchEx_Release(dispex);
10487         IMXNamespacePrefixes_Release(prefixes);
10488     }
10489     IVBMXNamespaceManager_Release(mgr2);
10490 
10491     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10492     EXPECT_HR(hr, S_OK);
10493 
10494     /* prefix already added */
10495     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10496     EXPECT_HR(hr, S_FALSE);
10497 
10498     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
10499     EXPECT_HR(hr, E_INVALIDARG);
10500 
10501     /* "xml" and "xmlns" are not allowed here */
10502     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xml"), _bstr_("uri1"));
10503     EXPECT_HR(hr, E_INVALIDARG);
10504 
10505     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
10506     EXPECT_HR(hr, E_INVALIDARG);
10507 todo_wine {
10508     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
10509     EXPECT_HR(hr, E_FAIL);
10510 }
10511     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
10512     EXPECT_HR(hr, E_POINTER);
10513 
10514     len = -1;
10515     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
10516     EXPECT_HR(hr, S_OK);
10517     ok(len == 3, "got %d\n", len);
10518 
10519     len = -1;
10520     buffW[0] = 0x1;
10521     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10522     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10523     ok(len == -1, "got %d\n", len);
10524     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10525 
10526     len = 10;
10527     buffW[0] = 0x1;
10528     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10529     EXPECT_HR(hr, S_OK);
10530     ok(len == 3, "got %d\n", len);
10531     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10532 
10533     /* getURI */
10534     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, NULL);
10535     EXPECT_HR(hr, E_INVALIDARG);
10536 
10537     len = -1;
10538     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, &len);
10539     EXPECT_HR(hr, E_INVALIDARG);
10540     ok(len == -1, "got %d\n", len);
10541 
10542     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, NULL);
10543     EXPECT_HR(hr, E_POINTER);
10544 
10545     len = -1;
10546     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, &len);
10547     EXPECT_HR(hr, S_OK);
10548     /* length of "xml" uri is constant */
10549     ok(len == strlen(xmluriA), "got %d\n", len);
10550 
10551     len = 100;
10552     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10553     EXPECT_HR(hr, S_OK);
10554     ok(len == strlen(xmluriA), "got %d\n", len);
10555     ok(!lstrcmpW(buffW, _bstr_(xmluriA)), "got prefix %s\n", wine_dbgstr_w(buffW));
10556 
10557     len = strlen(xmluriA)-1;
10558     buffW[0] = 0x1;
10559     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10560     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10561     ok(len == strlen(xmluriA)-1, "got %d\n", len);
10562     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10563 
10564     /* prefix xml1 not defined */
10565     len = -1;
10566     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, NULL, &len);
10567     EXPECT_HR(hr, S_FALSE);
10568     ok(len == 0, "got %d\n", len);
10569 
10570     len = 100;
10571     buffW[0] = 0x1;
10572     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, buffW, &len);
10573     EXPECT_HR(hr, S_FALSE);
10574     ok(buffW[0] == 0, "got %x\n", buffW[0]);
10575     ok(len == 0, "got %d\n", len);
10576 
10577     /* IDispatchEx tests */
10578     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IUnknown, (void**)&unk);
10579     EXPECT_HR(hr, S_OK);
10580     test_domobj_dispex(unk);
10581     IUnknown_Release(unk);
10582 
10583     IMXNamespaceManager_Release(nsmgr);
10584 
10585     /* ::getPrefix() */
10586     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10587         &IID_IMXNamespaceManager, (void**)&nsmgr);
10588     EXPECT_HR(hr, S_OK);
10589 
10590     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, NULL);
10591     EXPECT_HR(hr, E_INVALIDARG);
10592 
10593     len = -1;
10594     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, &len);
10595     EXPECT_HR(hr, E_INVALIDARG);
10596     ok(len == -1, "got %d\n", len);
10597 
10598     len = 100;
10599     buffW[0] = 0x1;
10600     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10601     EXPECT_HR(hr, E_FAIL);
10602     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10603     ok(len == 100, "got %d\n", len);
10604 
10605     len = 0;
10606     buffW[0] = 0x1;
10607     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10608     EXPECT_HR(hr, E_FAIL);
10609     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10610     ok(len == 0, "got %d\n", len);
10611 
10612     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10613     EXPECT_HR(hr, S_OK);
10614 
10615     len = 100;
10616     buffW[0] = 0x1;
10617     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10618     EXPECT_HR(hr, S_OK);
10619     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10620     ok(len == 3, "got %d\n", len);
10621 
10622     len = 100;
10623     buffW[0] = 0x1;
10624     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, buffW, &len);
10625     EXPECT_HR(hr, S_OK);
10626     ok(!lstrcmpW(buffW, _bstr_("xml")), "got %s\n", wine_dbgstr_w(buffW));
10627     ok(len == 3, "got %d\n", len);
10628 
10629     /* with null buffer it's possible to get required length */
10630     len = 100;
10631     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10632     EXPECT_HR(hr, S_OK);
10633     ok(len == 3, "got %d\n", len);
10634 
10635     len = 0;
10636     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10637     EXPECT_HR(hr, S_OK);
10638     ok(len == 3, "got %d\n", len);
10639 
10640     len = 100;
10641     buffW[0] = 0x1;
10642     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 1, buffW, &len);
10643     EXPECT_HR(hr, E_FAIL);
10644     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10645     ok(len == 100, "got %d\n", len);
10646 
10647     len = 100;
10648     buffW[0] = 0x1;
10649     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 2, buffW, &len);
10650     EXPECT_HR(hr, E_FAIL);
10651     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10652     ok(len == 100, "got %d\n", len);
10653 
10654     len = 100;
10655     buffW[0] = 0x1;
10656     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 0, buffW, &len);
10657     EXPECT_HR(hr, E_INVALIDARG);
10658     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10659     ok(len == 100, "got %d\n", len);
10660 
10661     len = 100;
10662     buffW[0] = 0x1;
10663     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10664     EXPECT_HR(hr, E_INVALIDARG);
10665     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10666     ok(len == 100, "got %d\n", len);
10667 
10668     len = 100;
10669     buffW[0] = 0x1;
10670     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, buffW, &len);
10671     EXPECT_HR(hr, E_INVALIDARG);
10672     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10673     ok(len == 100, "got %d\n", len);
10674 
10675     len = 100;
10676     buffW[0] = 0x1;
10677     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 1, buffW, &len);
10678     EXPECT_HR(hr, E_FAIL);
10679     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10680     ok(len == 100, "got %d\n", len);
10681 
10682     len = 100;
10683     buffW[0] = 0x1;
10684     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10685     EXPECT_HR(hr, E_INVALIDARG);
10686     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10687     ok(len == 100, "got %d\n", len);
10688 
10689     /* declare another one, indices are shifted */
10690     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10691     EXPECT_HR(hr, S_OK);
10692 
10693     len = 100;
10694     buffW[0] = 0x1;
10695     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10696     EXPECT_HR(hr, S_OK);
10697     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10698     ok(len == 3, "got %d\n", len);
10699 
10700     len = 100;
10701     buffW[0] = 0x1;
10702     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10703     EXPECT_HR(hr, S_OK);
10704     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10705     ok(len == 3, "got %d\n", len);
10706 
10707     len = 100;
10708     buffW[0] = 0x1;
10709     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 1, buffW, &len);
10710     EXPECT_HR(hr, E_FAIL);
10711     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10712     ok(len == 100, "got %d\n", len);
10713 
10714     len = 100;
10715     buffW[0] = 0x1;
10716     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10717     EXPECT_HR(hr, E_INVALIDARG);
10718     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10719     ok(len == 100, "got %d\n", len);
10720 
10721     IMXNamespaceManager_Release(nsmgr);
10722 
10723     /* push/pop tests */
10724     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10725         &IID_IMXNamespaceManager, (void**)&nsmgr);
10726     EXPECT_HR(hr, S_OK);
10727 
10728     /* pop with empty stack */
10729     hr = IMXNamespaceManager_popContext(nsmgr);
10730     EXPECT_HR(hr, E_FAIL);
10731 
10732     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10733     EXPECT_HR(hr, S_OK);
10734 
10735     len = 100;
10736     buffW[0] = 0x1;
10737     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10738     EXPECT_HR(hr, S_OK);
10739     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10740     ok(len == 3, "got %d\n", len);
10741 
10742     hr = IMXNamespaceManager_pushContext(nsmgr);
10743     EXPECT_HR(hr, S_OK);
10744 
10745     len = 100;
10746     buffW[0] = 0x1;
10747     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10748     EXPECT_HR(hr, S_OK);
10749     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10750     ok(len == 3, "got %d\n", len);
10751 
10752     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10753     EXPECT_HR(hr, S_OK);
10754 
10755     len = 100;
10756     buffW[0] = 0x1;
10757     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10758     EXPECT_HR(hr, S_OK);
10759     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10760     ok(len == 3, "got %d\n", len);
10761 
10762     hr = IMXNamespaceManager_pushContext(nsmgr);
10763     EXPECT_HR(hr, S_OK);
10764     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns3"), _bstr_("ns3 uri"));
10765     EXPECT_HR(hr, S_OK);
10766 
10767     len = 100;
10768     buffW[0] = 0x1;
10769     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10770     EXPECT_HR(hr, S_OK);
10771     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10772     ok(len == 3, "got %d\n", len);
10773 
10774     len = 100;
10775     buffW[0] = 0x1;
10776     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10777     EXPECT_HR(hr, S_OK);
10778     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10779     ok(len == 3, "got %d\n", len);
10780 
10781     hr = IMXNamespaceManager_popContext(nsmgr);
10782     EXPECT_HR(hr, S_OK);
10783 
10784     hr = IMXNamespaceManager_popContext(nsmgr);
10785     EXPECT_HR(hr, S_OK);
10786 
10787     len = 100;
10788     buffW[0] = 0x1;
10789     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10790     EXPECT_HR(hr, E_FAIL);
10791     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10792     ok(len == 100, "got %d\n", len);
10793 
10794     len = 100;
10795     buffW[0] = 0x1;
10796     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10797     EXPECT_HR(hr, S_OK);
10798     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10799     ok(len == 3, "got %d\n", len);
10800 
10801     IMXNamespaceManager_Release(nsmgr);
10802 
10803     free_bstrs();
10804 }
10805 
10806 static void test_mxnamespacemanager_override(void)
10807 {
10808     IMXNamespaceManager *nsmgr;
10809     WCHAR buffW[250];
10810     VARIANT_BOOL b;
10811     HRESULT hr;
10812     INT len;
10813 
10814     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10815         &IID_IMXNamespaceManager, (void**)&nsmgr);
10816     EXPECT_HR(hr, S_OK);
10817 
10818     len = sizeof(buffW)/sizeof(WCHAR);
10819     buffW[0] = 0;
10820     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10821     EXPECT_HR(hr, S_OK);
10822     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10823 
10824     len = sizeof(buffW)/sizeof(WCHAR);
10825     buffW[0] = 0;
10826     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10827     EXPECT_HR(hr, E_FAIL);
10828 
10829     hr = IMXNamespaceManager_getAllowOverride(nsmgr, NULL);
10830     EXPECT_HR(hr, E_POINTER);
10831 
10832     b = VARIANT_FALSE;
10833     hr = IMXNamespaceManager_getAllowOverride(nsmgr, &b);
10834     EXPECT_HR(hr, S_OK);
10835     ok(b == VARIANT_TRUE, "got %d\n", b);
10836 
10837     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_FALSE);
10838     EXPECT_HR(hr, S_OK);
10839 
10840     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10841     EXPECT_HR(hr, S_OK);
10842 
10843     len = sizeof(buffW)/sizeof(WCHAR);
10844     buffW[0] = 0;
10845     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10846     EXPECT_HR(hr, S_OK);
10847     ok(!lstrcmpW(buffW, _bstr_("ns0 uri")), "got uri %s\n", wine_dbgstr_w(buffW));
10848 
10849     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), _bstr_("ns0 uri"));
10850     EXPECT_HR(hr, S_OK);
10851 
10852     len = sizeof(buffW)/sizeof(WCHAR);
10853     buffW[0] = 0;
10854     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10855     EXPECT_HR(hr, S_OK);
10856     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10857 
10858     len = sizeof(buffW)/sizeof(WCHAR);
10859     buffW[0] = 0;
10860     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10861     EXPECT_HR(hr, S_OK);
10862     ok(!lstrcmpW(buffW, _bstr_("ns0")), "got prefix %s\n", wine_dbgstr_w(buffW));
10863 
10864     len = sizeof(buffW)/sizeof(WCHAR);
10865     buffW[0] = 0;
10866     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 2, buffW, &len);
10867     EXPECT_HR(hr, S_OK);
10868     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10869 
10870     /* new prefix placed at index 1 always */
10871     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10872     EXPECT_HR(hr, S_OK);
10873 
10874     len = sizeof(buffW)/sizeof(WCHAR);
10875     buffW[0] = 0;
10876     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10877     EXPECT_HR(hr, S_OK);
10878     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got prefix %s\n", wine_dbgstr_w(buffW));
10879 
10880     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_(""), NULL);
10881     todo_wine EXPECT_HR(hr, E_FAIL);
10882 
10883     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10884     EXPECT_HR(hr, E_FAIL);
10885 
10886     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10887     EXPECT_HR(hr, E_FAIL);
10888 
10889     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_TRUE);
10890     EXPECT_HR(hr, S_OK);
10891 
10892     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri override"));
10893     EXPECT_HR(hr, S_FALSE);
10894 
10895     len = sizeof(buffW)/sizeof(WCHAR);
10896     buffW[0] = 0;
10897     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10898     EXPECT_HR(hr, S_OK);
10899     ok(!lstrcmpW(buffW, _bstr_("ns0 uri override")), "got uri %s\n", wine_dbgstr_w(buffW));
10900 
10901     len = sizeof(buffW)/sizeof(WCHAR);
10902     buffW[0] = 0;
10903     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 3, buffW, &len);
10904     EXPECT_HR(hr, S_OK);
10905     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10906 
10907     IMXNamespaceManager_Release(nsmgr);
10908 
10909     free_bstrs();
10910 }
10911 
10912 static const DOMNodeType nodetypes_test[] =
10913 {
10914     NODE_ELEMENT,
10915     NODE_ATTRIBUTE,
10916     NODE_TEXT,
10917     NODE_CDATA_SECTION,
10918     NODE_ENTITY_REFERENCE,
10919     NODE_PROCESSING_INSTRUCTION,
10920     NODE_COMMENT,
10921     NODE_DOCUMENT_FRAGMENT,
10922     NODE_INVALID
10923 };
10924 
10925 static void test_dispex(void)
10926 {
10927     const DOMNodeType *type = nodetypes_test;
10928     IXMLDOMImplementation *impl;
10929     IXMLDOMNodeList *node_list;
10930     IXMLDOMParseError *error;
10931     IXMLDOMNamedNodeMap *map;
10932     IXSLProcessor *processor;
10933     IXSLTemplate *template;
10934     IXMLDOMDocument *doc;
10935     IXMLHTTPRequest *req;
10936     IXMLDOMElement *elem;
10937     IDispatchEx *dispex;
10938     DISPPARAMS dispparams;
10939     IXMLDOMNode *node;
10940     VARIANT arg, ret;
10941     VARIANT_BOOL b;
10942     IUnknown *unk;
10943     HRESULT hr;
10944     DISPID did;
10945 
10946     doc = create_document(&IID_IXMLDOMDocument);
10947 
10948     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
10949     ok(hr == S_OK, "got 0x%08x\n", hr);
10950     test_domobj_dispex(unk);
10951     IUnknown_Release(unk);
10952 
10953     for(; *type != NODE_INVALID; type++)
10954     {
10955         IXMLDOMNode *node;
10956         VARIANT v;
10957 
10958         V_VT(&v) = VT_I2;
10959         V_I2(&v) = *type;
10960 
10961         hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
10962         ok(hr == S_OK, "failed to create node type %d\n", *type);
10963 
10964         IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
10965 
10966         test_domobj_dispex(unk);
10967         IUnknown_Release(unk);
10968         IXMLDOMNode_Release(node);
10969     }
10970 
10971     /* IXMLDOMNodeList */
10972     hr = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), &node_list);
10973     EXPECT_HR(hr, S_OK);
10974     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
10975     ok(hr == S_OK, "got 0x%08x\n", hr);
10976     test_domobj_dispex(unk);
10977     IUnknown_Release(unk);
10978     IXMLDOMNodeList_Release(node_list);
10979 
10980     /* IXMLDOMNodeList for children list */
10981     hr = IXMLDOMDocument_get_childNodes(doc, &node_list);
10982     EXPECT_HR(hr, S_OK);
10983     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
10984     ok(hr == S_OK, "got 0x%08x\n", hr);
10985     test_domobj_dispex(unk);
10986     IUnknown_Release(unk);
10987 
10988     /* collection dispex test, empty collection */
10989     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatchEx, (void**)&dispex);
10990     EXPECT_HR(hr, S_OK);
10991     did = 0;
10992     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
10993     EXPECT_HR(hr, S_OK);
10994     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
10995     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
10996     EXPECT_HR(hr, S_OK);
10997     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
10998     IDispatchEx_Release(dispex);
10999 
11000     did = -1;
11001     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11002     ok(hr == S_OK, "got 0x%08x\n", hr);
11003     ok(did == DISPID_VALUE, "got %d\n", did);
11004 
11005     V_VT(&arg) = VT_I4;
11006     V_I4(&arg) = 0;
11007     dispparams.cArgs = 0;
11008     dispparams.cNamedArgs = 0;
11009     dispparams.rgdispidNamedArgs = NULL;
11010     dispparams.rgvarg = &arg;
11011 
11012     V_VT(&ret) = VT_EMPTY;
11013     V_DISPATCH(&ret) = (void*)0x1;
11014     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11015     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11016     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11017 todo_wine
11018     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11019 
11020     V_VT(&arg) = VT_I4;
11021     V_I4(&arg) = 0;
11022     dispparams.cArgs = 2;
11023     dispparams.cNamedArgs = 0;
11024     dispparams.rgdispidNamedArgs = NULL;
11025     dispparams.rgvarg = &arg;
11026 
11027     V_VT(&ret) = VT_EMPTY;
11028     V_DISPATCH(&ret) = (void*)0x1;
11029     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11030     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11031     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11032 todo_wine
11033     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11034 
11035     V_VT(&arg) = VT_I4;
11036     V_I4(&arg) = 0;
11037     dispparams.cArgs = 1;
11038     dispparams.cNamedArgs = 0;
11039     dispparams.rgdispidNamedArgs = NULL;
11040     dispparams.rgvarg = &arg;
11041 
11042     V_VT(&ret) = VT_EMPTY;
11043     V_DISPATCH(&ret) = (void*)0x1;
11044     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11045     ok(hr == S_OK, "got 0x%08x\n", hr);
11046     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11047     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11048 
11049     V_VT(&ret) = VT_EMPTY;
11050     V_DISPATCH(&ret) = (void*)0x1;
11051     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11052     ok(hr == S_OK, "got 0x%08x\n", hr);
11053     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11054     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11055 
11056     V_VT(&ret) = VT_EMPTY;
11057     V_DISPATCH(&ret) = (void*)0x1;
11058     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11059     ok(hr == S_OK, "got 0x%08x\n", hr);
11060     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11061     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11062 
11063     dispparams.cArgs = 0;
11064     dispparams.cNamedArgs = 0;
11065     dispparams.rgdispidNamedArgs = NULL;
11066     dispparams.rgvarg = NULL;
11067 
11068     V_VT(&ret) = VT_EMPTY;
11069     V_I4(&ret) = 1;
11070     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11071     ok(hr == S_OK, "got 0x%08x\n", hr);
11072     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11073     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11074 
11075     dispparams.cArgs = 0;
11076     dispparams.cNamedArgs = 0;
11077     dispparams.rgdispidNamedArgs = NULL;
11078     dispparams.rgvarg = NULL;
11079 
11080     V_VT(&ret) = VT_EMPTY;
11081     V_I4(&ret) = 1;
11082     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11083     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11084     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11085 todo_wine
11086     ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11087 
11088     IXMLDOMNodeList_Release(node_list);
11089 
11090     /* IXMLDOMParseError */
11091     hr = IXMLDOMDocument_get_parseError(doc, &error);
11092     EXPECT_HR(hr, S_OK);
11093     IXMLDOMParseError_QueryInterface(error, &IID_IUnknown, (void**)&unk);
11094     test_domobj_dispex(unk);
11095 
11096     hr = IXMLDOMParseError_QueryInterface(error, &IID_IDispatchEx, (void**)&dispex);
11097     ok(hr == S_OK, "got 0x%08x\n", hr);
11098 
11099     V_VT(&arg) = VT_I4;
11100     V_I4(&arg) = 0;
11101     dispparams.cArgs = 1;
11102     dispparams.cNamedArgs = 0;
11103     dispparams.rgdispidNamedArgs = NULL;
11104     dispparams.rgvarg = &arg;
11105 
11106     V_VT(&ret) = VT_EMPTY;
11107     V_DISPATCH(&ret) = (void*)0x1;
11108     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11109     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11110     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11111 todo_wine
11112     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11113 
11114     IDispatchEx_Release(dispex);
11115 
11116     IUnknown_Release(unk);
11117     IXMLDOMParseError_Release(error);
11118 
11119     /* IXMLDOMNamedNodeMap */
11120     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
11121     EXPECT_HR(hr, S_OK);
11122 
11123     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/a"), &node_list);
11124     EXPECT_HR(hr, S_OK);
11125     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11126     EXPECT_HR(hr, S_OK);
11127     IXMLDOMNodeList_Release(node_list);
11128 
11129     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11130     EXPECT_HR(hr, S_OK);
11131     IXMLDOMNode_Release(node);
11132     hr = IXMLDOMElement_get_attributes(elem, &map);
11133     EXPECT_HR(hr, S_OK);
11134     IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk);
11135     test_domobj_dispex(unk);
11136     IUnknown_Release(unk);
11137     /* collection dispex test */
11138     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11139     EXPECT_HR(hr, S_OK);
11140     did = 0;
11141     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11142     EXPECT_HR(hr, S_OK);
11143     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11144     IDispatchEx_Release(dispex);
11145     IXMLDOMNamedNodeMap_Release(map);
11146 
11147     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/b"), &node_list);
11148     EXPECT_HR(hr, S_OK);
11149     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11150     EXPECT_HR(hr, S_OK);
11151     IXMLDOMNodeList_Release(node_list);
11152     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11153     EXPECT_HR(hr, S_OK);
11154     IXMLDOMNode_Release(node);
11155     hr = IXMLDOMElement_get_attributes(elem, &map);
11156     EXPECT_HR(hr, S_OK);
11157     /* collection dispex test, empty collection */
11158     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11159     EXPECT_HR(hr, S_OK);
11160     did = 0;
11161     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11162     EXPECT_HR(hr, S_OK);
11163     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11164     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
11165     EXPECT_HR(hr, S_OK);
11166     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
11167     IXMLDOMNamedNodeMap_Release(map);
11168 
11169     did = -1;
11170     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11171     ok(hr == S_OK, "got 0x%08x\n", hr);
11172     ok(did == DISPID_VALUE, "got %d\n", did);
11173 
11174     V_VT(&arg) = VT_I4;
11175     V_I4(&arg) = 0;
11176     dispparams.cArgs = 0;
11177     dispparams.cNamedArgs = 0;
11178     dispparams.rgdispidNamedArgs = NULL;
11179     dispparams.rgvarg = &arg;
11180 
11181     V_VT(&ret) = VT_EMPTY;
11182     V_DISPATCH(&ret) = (void*)0x1;
11183     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11184 todo_wine {
11185     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11186     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11187 }
11188     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11189 
11190     V_VT(&arg) = VT_I4;
11191     V_I4(&arg) = 0;
11192     dispparams.cArgs = 2;
11193     dispparams.cNamedArgs = 0;
11194     dispparams.rgdispidNamedArgs = NULL;
11195     dispparams.rgvarg = &arg;
11196 
11197     V_VT(&ret) = VT_EMPTY;
11198     V_DISPATCH(&ret) = (void*)0x1;
11199     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11200 todo_wine {
11201     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11202     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11203 }
11204     ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11205 
11206     V_VT(&arg) = VT_I4;
11207     V_I4(&arg) = 0;
11208     dispparams.cArgs = 1;
11209     dispparams.cNamedArgs = 0;
11210     dispparams.rgdispidNamedArgs = NULL;
11211     dispparams.rgvarg = &arg;
11212 
11213     V_VT(&ret) = VT_EMPTY;
11214     V_DISPATCH(&ret) = (void*)0x1;
11215     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11216 todo_wine
11217     ok(hr == S_OK, "got 0x%08x\n", hr);
11218     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11219     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11220 
11221     V_VT(&ret) = VT_EMPTY;
11222     V_DISPATCH(&ret) = (void*)0x1;
11223     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11224     ok(hr == S_OK, "got 0x%08x\n", hr);
11225     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11226     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11227 
11228     V_VT(&ret) = VT_EMPTY;
11229     V_DISPATCH(&ret) = (void*)0x1;
11230     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11231     ok(hr == S_OK, "got 0x%08x\n", hr);
11232     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11233     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11234 
11235     dispparams.cArgs = 0;
11236     dispparams.cNamedArgs = 0;
11237     dispparams.rgdispidNamedArgs = NULL;
11238     dispparams.rgvarg = NULL;
11239 
11240     V_VT(&ret) = VT_EMPTY;
11241     V_I4(&ret) = 1;
11242     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11243     ok(hr == S_OK, "got 0x%08x\n", hr);
11244     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11245     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11246 
11247     dispparams.cArgs = 0;
11248     dispparams.cNamedArgs = 0;
11249     dispparams.rgdispidNamedArgs = NULL;
11250     dispparams.rgvarg = NULL;
11251 
11252     V_VT(&ret) = VT_EMPTY;
11253     V_I4(&ret) = 1;
11254     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11255     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11256 todo_wine
11257     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11258     ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11259 
11260     IDispatchEx_Release(dispex);
11261     IXMLDOMElement_Release(elem);
11262 
11263     /* IXMLDOMImplementation */
11264     hr = IXMLDOMDocument_get_implementation(doc, &impl);
11265     EXPECT_HR(hr, S_OK);
11266 
11267     hr = IXMLDOMImplementation_QueryInterface(impl, &IID_IDispatchEx, (void**)&dispex);
11268     EXPECT_HR(hr, S_OK);
11269     IDispatchEx_Release(dispex);
11270     IXMLDOMImplementation_Release(impl);
11271 
11272     IXMLDOMDocument_Release(doc);
11273 
11274     /* IXMLHTTPRequest */
11275     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
11276         &IID_IXMLHttpRequest, (void**)&req);
11277     if (hr == S_OK)
11278     {
11279         hr = IXMLHTTPRequest_QueryInterface(req, &IID_IDispatchEx, (void**)&dispex);
11280         EXPECT_HR(hr, E_NOINTERFACE);
11281         IXMLHTTPRequest_Release(req);
11282     }
11283 
11284     /* IXSLTemplate */
11285     template = create_xsltemplate(&IID_IXSLTemplate);
11286     hr = IXSLTemplate_QueryInterface(template, &IID_IDispatchEx, (void**)&dispex);
11287     EXPECT_HR(hr, S_OK);
11288     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11289     EXPECT_HR(hr, S_OK);
11290     test_domobj_dispex(unk);
11291     IUnknown_Release(unk);
11292     IDispatchEx_Release(dispex);
11293 
11294     /* IXSLProcessor */
11295     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
11296     EXPECT_HR(hr, S_OK);
11297     b = VARIANT_FALSE;
11298     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformSSXML), &b);
11299     EXPECT_HR(hr, S_OK);
11300     ok(b == VARIANT_TRUE, "got %d\n", b);
11301 
11302     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
11303     EXPECT_HR(hr, S_OK);
11304     IXMLDOMDocument_Release(doc);
11305 
11306     hr = IXSLTemplate_createProcessor(template, &processor);
11307     EXPECT_HR(hr, S_OK);
11308     hr = IXSLProcessor_QueryInterface(processor, &IID_IDispatchEx, (void**)&dispex);
11309     EXPECT_HR(hr, S_OK);
11310     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11311     EXPECT_HR(hr, S_OK);
11312     test_domobj_dispex(unk);
11313     IUnknown_Release(unk);
11314     IDispatchEx_Release(dispex);
11315 
11316     IXSLProcessor_Release(processor);
11317     IXSLTemplate_Release(template);
11318 
11319     if (is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument))
11320     {
11321         doc = create_document_version(60, &IID_IXMLDOMDocument);
11322         test_domobj_dispex((IUnknown*)doc);
11323         IXMLDOMDocument_Release(doc);
11324     }
11325 
11326     free_bstrs();
11327 }
11328 
11329 static void test_parseerror(void)
11330 {
11331     IXMLDOMParseError2 *error2;
11332     IXMLDOMParseError *error;
11333     IXMLDOMDocument *doc;
11334     HRESULT hr;
11335 
11336     doc = create_document(&IID_IXMLDOMDocument);
11337 
11338     hr = IXMLDOMDocument_get_parseError(doc, &error);
11339     EXPECT_HR(hr, S_OK);
11340 
11341     hr = IXMLDOMParseError_get_line(error, NULL);
11342     EXPECT_HR(hr, E_INVALIDARG);
11343 
11344     hr = IXMLDOMParseError_get_srcText(error, NULL);
11345     EXPECT_HR(hr, E_INVALIDARG);
11346 
11347     hr = IXMLDOMParseError_get_linepos(error, NULL);
11348     EXPECT_HR(hr, E_INVALIDARG);
11349 
11350     IXMLDOMParseError_Release(error);
11351     IXMLDOMDocument_Release(doc);
11352 
11353     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument)) return;
11354     doc = create_document_version(60, &IID_IXMLDOMDocument);
11355 
11356     hr = IXMLDOMDocument_get_parseError(doc, &error);
11357     EXPECT_HR(hr, S_OK);
11358     hr = IXMLDOMParseError_QueryInterface(error, &IID_IXMLDOMParseError2, (void**)&error2);
11359     EXPECT_HR(hr, S_OK);
11360     IXMLDOMParseError2_Release(error2);
11361     IXMLDOMParseError_Release(error);
11362     IXMLDOMDocument_Release(doc);
11363 }
11364 
11365 static void test_getAttributeNode(void)
11366 {
11367     IXMLDOMAttribute *attr;
11368     IXMLDOMDocument *doc;
11369     IXMLDOMElement *elem;
11370     VARIANT_BOOL v;
11371     HRESULT hr;
11372     BSTR str;
11373 
11374     doc = create_document(&IID_IXMLDOMDocument);
11375 
11376     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11377     EXPECT_HR(hr, S_OK);
11378 
11379     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11380     EXPECT_HR(hr, S_OK);
11381 
11382     str = SysAllocString(nonexistent_fileW);
11383     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11384     EXPECT_HR(hr, E_FAIL);
11385 
11386     attr = (IXMLDOMAttribute*)0xdeadbeef;
11387     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11388     EXPECT_HR(hr, E_FAIL);
11389     ok(attr == NULL, "got %p\n", attr);
11390     SysFreeString(str);
11391 
11392     str = SysAllocString(nonexistent_attrW);
11393     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11394     EXPECT_HR(hr, S_FALSE);
11395 
11396     attr = (IXMLDOMAttribute*)0xdeadbeef;
11397     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11398     EXPECT_HR(hr, S_FALSE);
11399     ok(attr == NULL, "got %p\n", attr);
11400     SysFreeString(str);
11401 
11402     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("foo:b"), &attr);
11403     EXPECT_HR(hr, S_OK);
11404     IXMLDOMAttribute_Release(attr);
11405 
11406     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("b"), &attr);
11407     EXPECT_HR(hr, S_FALSE);
11408 
11409     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("a"), &attr);
11410     EXPECT_HR(hr, S_OK);
11411     IXMLDOMAttribute_Release(attr);
11412 
11413     IXMLDOMElement_Release(elem);
11414     IXMLDOMDocument_Release(doc);
11415     free_bstrs();
11416 }
11417 
11418 static void test_getAttribute(void)
11419 {
11420     IXMLDOMDocument *doc;
11421     IXMLDOMElement *elem;
11422     VARIANT_BOOL v;
11423     VARIANT var;
11424     HRESULT hr;
11425 
11426     doc = create_document(&IID_IXMLDOMDocument);
11427 
11428     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11429     EXPECT_HR(hr, S_OK);
11430 
11431     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11432     EXPECT_HR(hr, S_OK);
11433 
11434     VariantInit(&var);
11435     hr = IXMLDOMElement_getAttribute( elem, _bstr_("xmlns:foo"), &var );
11436     EXPECT_HR(hr, S_OK);
11437     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11438     ok( !lstrcmpW(V_BSTR(&var), _bstr_("urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11439     VariantClear(&var);
11440 
11441     hr = IXMLDOMElement_getAttribute( elem, _bstr_("a"), &var );
11442     EXPECT_HR(hr, S_OK);
11443     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11444     ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr a")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11445     VariantClear(&var);
11446 
11447     hr = IXMLDOMElement_getAttribute( elem, _bstr_("foo:b"), &var );
11448     EXPECT_HR(hr, S_OK);
11449     ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11450     ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr b")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11451     VariantClear(&var);
11452 
11453     hr = IXMLDOMElement_getAttribute( elem, _bstr_("b"), &var );
11454     EXPECT_HR(hr, S_FALSE);
11455     ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11456     VariantClear(&var);
11457 
11458     hr = IXMLDOMElement_getAttribute( elem, _bstr_("non-existent"), &var );
11459     EXPECT_HR(hr, S_FALSE);
11460     ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11461     VariantClear(&var);
11462 
11463     IXMLDOMElement_Release(elem);
11464     IXMLDOMDocument_Release(doc);
11465     free_bstrs();
11466 }
11467 
11468 typedef struct {
11469     DOMNodeType type;
11470     const char *name;
11471     REFIID iids[3];
11472 } supporterror_t;
11473 
11474 static const supporterror_t supporterror_test[] = {
11475     { NODE_ELEMENT,                "element",   { &IID_IXMLDOMNode, &IID_IXMLDOMElement } },
11476     { NODE_ATTRIBUTE,              "attribute", { &IID_IXMLDOMNode, &IID_IXMLDOMAttribute } },
11477     { NODE_CDATA_SECTION,          "cdata",     { &IID_IXMLDOMNode, &IID_IXMLDOMCDATASection } },
11478     { NODE_ENTITY_REFERENCE,       "entityref", { &IID_IXMLDOMNode, &IID_IXMLDOMEntityReference } },
11479     { NODE_PROCESSING_INSTRUCTION, "pi",        { &IID_IXMLDOMNode, &IID_IXMLDOMProcessingInstruction } },
11480     { NODE_COMMENT,                "comment",   { &IID_IXMLDOMNode, &IID_IXMLDOMComment } },
11481     { NODE_DOCUMENT_FRAGMENT,      "fragment",  { &IID_IXMLDOMNode, &IID_IXMLDOMDocumentFragment } },
11482     { NODE_INVALID }
11483 };
11484 
11485 static void test_supporterrorinfo(void)
11486 {
11487     static REFIID iids[5] = { &IID_IXMLDOMNode, &IID_IXMLDOMDocument,
11488                               &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3 };
11489     const supporterror_t *ptr = supporterror_test;
11490     ISupportErrorInfo *errorinfo, *info2;
11491     IXMLDOMSchemaCollection *schemacache;
11492     IXMLDOMNamedNodeMap *map, *map2;
11493     IXMLDOMDocument *doc;
11494     IXMLDOMElement *elem;
11495     VARIANT_BOOL b;
11496     IUnknown *unk;
11497     REFIID *iid;
11498     void *dummy;
11499     HRESULT hr;
11500 
11501     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument3)) return;
11502     doc = create_document_version(60, &IID_IXMLDOMDocument3);
11503 
11504     EXPECT_REF(doc, 1);
11505     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&errorinfo);
11506     EXPECT_HR(hr, S_OK);
11507     EXPECT_REF(doc, 1);
11508     ISupportErrorInfo_AddRef(errorinfo);
11509     EXPECT_REF(errorinfo, 2);
11510     EXPECT_REF(doc, 1);
11511     ISupportErrorInfo_Release(errorinfo);
11512 
11513     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&info2);
11514     EXPECT_HR(hr, S_OK);
11515     ok(errorinfo != info2, "got %p, %p\n", info2, errorinfo);
11516 
11517     /* error interface can't be queried back for DOM interface */
11518     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMDocument, &dummy);
11519     EXPECT_HR(hr, E_NOINTERFACE);
11520     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMNode, &dummy);
11521     EXPECT_HR(hr, E_NOINTERFACE);
11522 
11523     ISupportErrorInfo_Release(info2);
11524 
11525     iid = iids;
11526     while (*iid)
11527     {
11528         hr = IXMLDOMDocument_QueryInterface(doc, *iid, (void**)&unk);
11529         EXPECT_HR(hr, S_OK);
11530         if (hr == S_OK)
11531         {
11532             hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11533             ok(hr == S_OK, "got 0x%08x for %s\n", hr, wine_dbgstr_guid(*iid));
11534             IUnknown_Release(unk);
11535         }
11536 
11537         iid++;
11538     }
11539 
11540     ISupportErrorInfo_Release(errorinfo);
11541 
11542     while (ptr->type != NODE_INVALID)
11543     {
11544         IXMLDOMNode *node;
11545         VARIANT type;
11546 
11547         V_VT(&type) = VT_I1;
11548         V_I1(&type) = ptr->type;
11549 
11550         hr = IXMLDOMDocument_createNode(doc, type, _bstr_(ptr->name), NULL, &node);
11551         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11552 
11553         EXPECT_REF(node, 1);
11554         hr = IXMLDOMNode_QueryInterface(node, &IID_ISupportErrorInfo, (void**)&errorinfo);
11555         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11556         EXPECT_REF(node, 1);
11557 
11558         hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNode, &dummy);
11559         ok(hr == E_NOINTERFACE, "%d: got 0x%08x\n", ptr->type, hr);
11560 
11561         iid = ptr->iids;
11562 
11563         while (*iid)
11564         {
11565             hr = IXMLDOMNode_QueryInterface(node, *iid, (void**)&unk);
11566             if (hr == S_OK)
11567             {
11568                 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11569                 ok(hr == S_OK, "%d: got 0x%08x for %s\n", ptr->type, hr, wine_dbgstr_guid(*iid));
11570                 IUnknown_Release(unk);
11571             }
11572 
11573             iid++;
11574         }
11575 
11576         ISupportErrorInfo_Release(errorinfo);
11577         IXMLDOMNode_Release(node);
11578         ptr++;
11579     }
11580 
11581     /* IXMLDOMNamedNodeMap */
11582     b = VARIANT_FALSE;
11583     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
11584     EXPECT_HR(hr, S_OK);
11585     ok(b == VARIANT_TRUE, "got %d\n", b);
11586 
11587     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11588     EXPECT_HR(hr, S_OK);
11589 
11590     hr = IXMLDOMElement_get_attributes(elem, &map);
11591     EXPECT_HR(hr, S_OK);
11592 
11593     EXPECT_REF(map, 1);
11594     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_ISupportErrorInfo, (void**)&errorinfo);
11595     EXPECT_HR(hr, S_OK);
11596     EXPECT_REF(map, 2);
11597 
11598     hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMNamedNodeMap);
11599     EXPECT_HR(hr, S_OK);
11600 
11601     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNamedNodeMap, (void**)&map2);
11602     EXPECT_HR(hr, S_OK);
11603     ok(map == map2, "got %p\n", map2);
11604     IXMLDOMNamedNodeMap_Release(map2);
11605 
11606     EXPECT_REF(errorinfo, 2);
11607     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IUnknown, (void**)&unk);
11608     EXPECT_HR(hr, S_OK);
11609     EXPECT_REF(errorinfo, 3);
11610     EXPECT_REF(map, 3);
11611     IUnknown_Release(unk);
11612 
11613     ISupportErrorInfo_Release(errorinfo);
11614     IXMLDOMNamedNodeMap_Release(map);
11615     IXMLDOMElement_Release(elem);
11616 
11617     IXMLDOMDocument_Release(doc);
11618 
11619     /* IXMLDOMSchemaCollection */
11620     hr = CoCreateInstance(&CLSID_XMLSchemaCache, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMSchemaCollection, (void**)&schemacache);
11621     ok(hr == S_OK, "failed to create schema collection, 0x%08x\n", hr);
11622 
11623     hr = IXMLDOMSchemaCollection_QueryInterface(schemacache, &IID_ISupportErrorInfo, (void**)&errorinfo);
11624     ok(hr == S_OK, "got 0x%08x\n", hr);
11625 
11626     hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMSchemaCollection);
11627     ok(hr == S_OK, "got 0x%08x\n", hr);
11628 
11629     ISupportErrorInfo_Release(errorinfo);
11630     IXMLDOMSchemaCollection_Release(schemacache);
11631 
11632     free_bstrs();
11633 }
11634 
11635 typedef struct {
11636     DOMNodeType type;
11637     const char *name;
11638     const char *put_content;
11639     HRESULT put_hr;
11640     VARTYPE get_vt;
11641     HRESULT get_hr;
11642 } node_value_t;
11643 
11644 static const node_value_t nodevalue_test[] = {
11645     { NODE_ELEMENT,                "element",   "",             E_FAIL, VT_NULL, S_FALSE },
11646     { NODE_ATTRIBUTE,              "attr",      "value",        S_OK,   VT_BSTR, S_OK },
11647     { NODE_TEXT,                   "text",      "textdata",     S_OK,   VT_BSTR, S_OK },
11648     { NODE_CDATA_SECTION ,         "cdata",     "cdata data",   S_OK,   VT_BSTR, S_OK },
11649     { NODE_ENTITY_REFERENCE,       "entityref", "ref",          E_FAIL, VT_NULL, S_FALSE },
11650     { NODE_PROCESSING_INSTRUCTION, "pi",        "instr",        S_OK,   VT_BSTR, S_OK },
11651     { NODE_COMMENT,                "comment",   "comment data", S_OK,   VT_BSTR, S_OK },
11652     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   "",             E_FAIL, VT_NULL, S_FALSE },
11653     { NODE_INVALID }
11654 };
11655 
11656 static void test_nodeValue(void)
11657 {
11658     const node_value_t *ptr = nodevalue_test;
11659     IXMLDOMDocument *doc;
11660     HRESULT hr;
11661 
11662     doc = create_document(&IID_IXMLDOMDocument);
11663 
11664     while (ptr->type != NODE_INVALID)
11665     {
11666         IXMLDOMNode *node;
11667         VARIANT v;
11668 
11669         V_VT(&v) = VT_I2;
11670         V_I2(&v) = ptr->type;
11671 
11672         hr = IXMLDOMDocument_createNode(doc, v, _bstr_(ptr->name), NULL, &node);
11673         ok(hr == S_OK, "failed to create node type %d\n", ptr->type);
11674 
11675         hr = IXMLDOMNode_get_nodeValue(node, NULL);
11676         ok(hr == E_INVALIDARG, "%d: got 0x%08x\n", ptr->type, hr);
11677 
11678         V_VT(&v) = VT_BSTR;
11679         V_BSTR(&v) = _bstr_(ptr->put_content);
11680         hr = IXMLDOMNode_put_nodeValue(node, v);
11681         ok(hr == ptr->put_hr, "%d: got 0x%08x\n", ptr->type, hr);
11682 
11683         V_VT(&v) = VT_EMPTY;
11684         hr = IXMLDOMNode_get_nodeValue(node, &v);
11685         ok(hr == ptr->get_hr, "%d: got 0x%08x, expected 0x%08x\n", ptr->type, hr, ptr->get_hr);
11686         ok(V_VT(&v) == ptr->get_vt, "%d: got %d, expected %d\n", ptr->type, V_VT(&v), ptr->get_vt);
11687         if (hr == S_OK)
11688             ok(!lstrcmpW(V_BSTR(&v), _bstr_(ptr->put_content)), "%d: got %s\n", ptr->type,
11689                 wine_dbgstr_w(V_BSTR(&v)));
11690         VariantClear(&v);
11691 
11692         IXMLDOMNode_Release(node);
11693 
11694         ptr++;
11695     }
11696 
11697     IXMLDOMDocument_Release(doc);
11698 }
11699 
11700 static void test_xmlns_attribute(void)
11701 {
11702     BSTR str;
11703     IXMLDOMDocument *doc;
11704     IXMLDOMElement *root;
11705     IXMLDOMAttribute *pAttribute;
11706     IXMLDOMElement *elem;
11707     HRESULT hr;
11708     VARIANT v;
11709 
11710     doc = create_document(&IID_IXMLDOMDocument);
11711 
11712     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
11713     EXPECT_HR(hr, S_OK);
11714 
11715     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
11716     EXPECT_HR(hr, S_OK);
11717 
11718     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("xmlns:dt"), &pAttribute);
11719     ok( hr == S_OK, "returns %08x\n", hr );
11720 
11721     V_VT(&v) = VT_BSTR;
11722     V_BSTR(&v) = _bstr_("urn:schemas-microsoft-com:datatypes");
11723     hr = IXMLDOMAttribute_put_nodeValue(pAttribute, v);
11724     ok(hr == S_OK, "ret %08x\n", hr );
11725 
11726     hr = IXMLDOMElement_setAttributeNode(root, pAttribute, NULL);
11727     ok(hr == S_OK, "ret %08x\n", hr );
11728 
11729     hr = IXMLDOMNode_put_dataType((IXMLDOMNode*)root, _bstr_("bin.base64"));
11730     ok(hr == S_OK, "ret %08x\n", hr );
11731 
11732     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11733     EXPECT_HR(hr, S_OK);
11734 
11735     str = NULL;
11736     hr = IXMLDOMElement_get_xml(elem, &str);
11737     ok( hr == S_OK, "got 0x%08x\n", hr);
11738     todo_wine ok( lstrcmpW(str, _bstr_("<Testing xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"bin.base64\"/>")) == 0,
11739     "got %s\n", wine_dbgstr_w(str));
11740     SysFreeString(str);
11741 
11742     IXMLDOMElement_Release(elem);
11743     IXMLDOMAttribute_Release( pAttribute);
11744 
11745     IXMLDOMDocument_Release(doc);
11746 
11747     free_bstrs();
11748 }
11749 
11750 static const char namespacesA[] =
11751 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
11752 "   <ns1:elem1 xmlns:ns1=\"http://blah.org\" b='1' >"
11753 "     <ns2:elem2 xmlns:ns2=\"http://blah.org\"/>"
11754 "     <ns1:elem3/>"
11755 "     <ns1:elem4/>"
11756 "     <elem5 xmlns=\"http://blahblah.org\"/>"
11757 "     <ns1:elem6>true</ns1:elem6>"
11758 "   </ns1:elem1>";
11759 
11760 static const char xsd_schema1_uri[] = "x-schema:test1.xsd";
11761 static const char xsd_schema1_xml[] =
11762 "<?xml version='1.0'?>"
11763 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
11764 "            targetNamespace='x-schema:test1.xsd'>"
11765 "   <element name='root'>"
11766 "       <complexType>"
11767 "           <sequence maxOccurs='unbounded'>"
11768 "               <any/>"
11769 "           </sequence>"
11770 "       </complexType>"
11771 "   </element>"
11772 "</schema>";
11773 
11774 static void test_get_namespaces(void)
11775 {
11776     IXMLDOMSchemaCollection *collection, *collection2;
11777     IXMLDOMDocument2 *doc, *doc2;
11778     IEnumVARIANT *enumv, *enum2;
11779     IUnknown *unk1, *unk2;
11780     IXMLDOMNode *node;
11781     VARIANT_BOOL b;
11782     HRESULT hr;
11783     VARIANT v;
11784     LONG len;
11785     BSTR s;
11786 
11787     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
11788     doc = create_document(&IID_IXMLDOMDocument2);
11789 
11790     /* null pointer */
11791     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11792     EXPECT_HR(hr, E_POINTER);
11793 
11794     /* no document loaded */
11795     collection = (void*)0xdeadbeef;
11796     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11797     EXPECT_HR(hr, S_OK);
11798     if (hr != S_OK)
11799     {
11800         IXMLDOMDocument2_Release(doc);
11801         return;
11802     }
11803     EXPECT_REF(collection, 2);
11804 
11805     collection2 = (void*)0xdeadbeef;
11806     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11807     EXPECT_HR(hr, S_OK);
11808     ok(collection == collection2, "got %p\n", collection2);
11809     EXPECT_REF(collection, 3);
11810     IXMLDOMSchemaCollection_Release(collection);
11811 
11812     len = -1;
11813     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11814     EXPECT_HR(hr, S_OK);
11815     ok(len == 0, "got %d\n", len);
11816     IXMLDOMSchemaCollection_Release(collection);
11817 
11818     /* now with document */
11819     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11820     EXPECT_HR(hr, S_OK);
11821 
11822     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11823     EXPECT_HR(hr, S_OK);
11824 
11825     len = -1;
11826     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11827     EXPECT_HR(hr, S_OK);
11828     ok(len == 2, "got %d\n", len);
11829 
11830     /* try to lookup some uris */
11831     node = (void*)0xdeadbeef;
11832     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
11833     EXPECT_HR(hr, S_OK);
11834     ok(node == NULL, "got %p\n", node);
11835 
11836     node = (void*)0xdeadbeef;
11837     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah1.org"), &node);
11838     EXPECT_HR(hr, S_OK);
11839     ok(node == NULL, "got %p\n", node);
11840 
11841     /* load schema and try to add it */
11842     doc2 = create_document(&IID_IXMLDOMDocument2);
11843     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
11844     EXPECT_HR(hr, S_OK);
11845 
11846     V_VT(&v) = VT_DISPATCH;
11847     V_DISPATCH(&v) = (IDispatch*)doc2;
11848     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
11849     EXPECT_HR(hr, E_FAIL);
11850 
11851     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
11852     EXPECT_HR(hr, S_OK);
11853     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
11854     SysFreeString(s);
11855 
11856     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
11857     EXPECT_HR(hr, S_OK);
11858     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
11859     SysFreeString(s);
11860 
11861     s = (void*)0xdeadbeef;
11862     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
11863     EXPECT_HR(hr, E_FAIL);
11864     ok(s == (void*)0xdeadbeef, "got %p\n", s);
11865 
11866     /* enumerate */
11867     enumv = (void*)0xdeadbeef;
11868     EXPECT_REF(collection, 2);
11869     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
11870     EXPECT_HR(hr, S_OK);
11871     EXPECT_REF(collection, 3);
11872     ok(enumv != NULL, "got %p\n", enumv);
11873 
11874     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IUnknown, (void**)&unk1);
11875     EXPECT_HR(hr, S_OK);
11876     hr = IEnumVARIANT_QueryInterface(enumv, &IID_IUnknown, (void**)&unk2);
11877     EXPECT_HR(hr, S_OK);
11878     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
11879     IUnknown_Release(unk1);
11880     IUnknown_Release(unk2);
11881 
11882     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IEnumVARIANT, (void**)&enum2);
11883     EXPECT_HR(hr, E_NOINTERFACE);
11884 
11885     V_VT(&v) = VT_EMPTY;
11886     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11887     EXPECT_HR(hr, S_OK);
11888     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11889     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11890     VariantClear(&v);
11891 
11892     V_VT(&v) = VT_EMPTY;
11893     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11894     EXPECT_HR(hr, S_OK);
11895     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11896     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11897     VariantClear(&v);
11898 
11899     V_VT(&v) = VT_NULL;
11900     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11901     EXPECT_HR(hr, S_FALSE);
11902     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
11903 
11904     IEnumVARIANT_Release(enumv);
11905     IXMLDOMSchemaCollection_Release(collection);
11906 
11907     IXMLDOMDocument2_Release(doc);
11908 
11909     /* now with CLSID_DOMDocument60 */
11910     if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument2)) return;
11911     doc = create_document_version(60, &IID_IXMLDOMDocument2);
11912 
11913     /* null pointer */
11914     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11915     EXPECT_HR(hr, E_POINTER);
11916 
11917     /* no document loaded */
11918     collection = (void*)0xdeadbeef;
11919     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11920     EXPECT_HR(hr, S_OK);
11921     if (hr != S_OK)
11922     {
11923         IXMLDOMDocument2_Release(doc);
11924         return;
11925     }
11926     EXPECT_REF(collection, 2);
11927 
11928     collection2 = (void*)0xdeadbeef;
11929     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11930     EXPECT_HR(hr, S_OK);
11931     ok(collection == collection2, "got %p\n", collection2);
11932     EXPECT_REF(collection, 3);
11933     IXMLDOMSchemaCollection_Release(collection);
11934 
11935     len = -1;
11936     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11937     EXPECT_HR(hr, S_OK);
11938     ok(len == 0, "got %d\n", len);
11939     IXMLDOMSchemaCollection_Release(collection);
11940 
11941     /* now with document */
11942     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11943     EXPECT_HR(hr, S_OK);
11944 
11945     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11946     EXPECT_HR(hr, S_OK);
11947 
11948     len = -1;
11949     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11950     EXPECT_HR(hr, S_OK);
11951     ok(len == 2, "got %d\n", len);
11952 
11953     /* try to lookup some uris */
11954     node = (void*)0xdeadbeef;
11955     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
11956     EXPECT_HR(hr, E_NOTIMPL);
11957     ok(broken(node == (void*)0xdeadbeef) || (node == NULL), "got %p\n", node);
11958 
11959     /* load schema and try to add it */
11960     doc2 = create_document(&IID_IXMLDOMDocument2);
11961     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
11962     EXPECT_HR(hr, S_OK);
11963 
11964     V_VT(&v) = VT_DISPATCH;
11965     V_DISPATCH(&v) = (IDispatch*)doc2;
11966     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
11967     EXPECT_HR(hr, E_FAIL);
11968     IXMLDOMDocument2_Release(doc2);
11969 
11970     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
11971     EXPECT_HR(hr, S_OK);
11972     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
11973     SysFreeString(s);
11974 
11975     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
11976     EXPECT_HR(hr, S_OK);
11977     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
11978     SysFreeString(s);
11979 
11980     s = (void*)0xdeadbeef;
11981     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
11982     EXPECT_HR(hr, E_FAIL);
11983     ok(broken(s == (void*)0xdeadbeef) || (s == NULL), "got %p\n", s);
11984 
11985     /* enumerate */
11986     enumv = (void*)0xdeadbeef;
11987     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
11988     EXPECT_HR(hr, S_OK);
11989     ok(enumv != NULL, "got %p\n", enumv);
11990 
11991     V_VT(&v) = VT_EMPTY;
11992     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11993     EXPECT_HR(hr, S_OK);
11994     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11995     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11996     VariantClear(&v);
11997 
11998     V_VT(&v) = VT_EMPTY;
11999     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12000     EXPECT_HR(hr, S_OK);
12001     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
12002     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
12003     VariantClear(&v);
12004 
12005     V_VT(&v) = VT_NULL;
12006     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12007     EXPECT_HR(hr, S_FALSE);
12008     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
12009 
12010     IEnumVARIANT_Release(enumv);
12011     IXMLDOMSchemaCollection_Release(collection);
12012     IXMLDOMDocument2_Release(doc);
12013     free_bstrs();
12014 }
12015 
12016 static const DOMNodeType put_data_types[] = {
12017     NODE_TEXT,
12018     NODE_CDATA_SECTION,
12019     NODE_PROCESSING_INSTRUCTION,
12020     NODE_COMMENT,
12021     NODE_INVALID
12022 };
12023 
12024 static void test_put_data(void)
12025 {
12026     static const WCHAR test_data[] = {'t','e','s','t',' ','n','o','d','e',' ','d','a','t','a',0};
12027     WCHAR buff[100], *data;
12028     IXMLDOMDocument *doc;
12029     const DOMNodeType *type;
12030     IXMLDOMText *text;
12031     IXMLDOMNode *node;
12032     VARIANT v;
12033     BSTR get_data;
12034     HRESULT hr;
12035 
12036     doc = create_document(&IID_IXMLDOMDocument);
12037 
12038     memcpy(&buff[2], test_data, sizeof(test_data));
12039     /* just a big length */
12040     *(DWORD*)buff = 0xf0f0;
12041     data = &buff[2];
12042 
12043     type = put_data_types;
12044     while (*type != NODE_INVALID)
12045     {
12046        V_VT(&v) = VT_I2;
12047        V_I2(&v) = *type;
12048 
12049        hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12050        EXPECT_HR(hr, S_OK);
12051 
12052        /* put_data() is interface-specific */
12053        switch (*type)
12054        {
12055            case NODE_TEXT:
12056            {
12057               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12058               EXPECT_HR(hr, S_OK);
12059               hr = IXMLDOMText_put_data(text, data);
12060               EXPECT_HR(hr, S_OK);
12061 
12062               hr = IXMLDOMText_get_data(text, &get_data);
12063               EXPECT_HR(hr, S_OK);
12064 
12065               IXMLDOMText_Release(text);
12066               break;
12067            }
12068            case NODE_CDATA_SECTION:
12069            {
12070               IXMLDOMCDATASection *cdata;
12071 
12072               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
12073               EXPECT_HR(hr, S_OK);
12074               hr = IXMLDOMCDATASection_put_data(cdata, data);
12075               EXPECT_HR(hr, S_OK);
12076 
12077               hr = IXMLDOMCDATASection_get_data(cdata, &get_data);
12078               EXPECT_HR(hr, S_OK);
12079 
12080               IXMLDOMCDATASection_Release(cdata);
12081               break;
12082            }
12083            case NODE_PROCESSING_INSTRUCTION:
12084            {
12085               IXMLDOMProcessingInstruction *pi;
12086 
12087               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)&pi);
12088               EXPECT_HR(hr, S_OK);
12089               hr = IXMLDOMProcessingInstruction_put_data(pi, data);
12090               EXPECT_HR(hr, S_OK);
12091 
12092               hr = IXMLDOMProcessingInstruction_get_data(pi, &get_data);
12093               EXPECT_HR(hr, S_OK);
12094 
12095               IXMLDOMProcessingInstruction_Release(pi);
12096               break;
12097            }
12098            case NODE_COMMENT:
12099            {
12100               IXMLDOMComment *comment;
12101 
12102               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
12103               EXPECT_HR(hr, S_OK);
12104               hr = IXMLDOMComment_put_data(comment, data);
12105               EXPECT_HR(hr, S_OK);
12106 
12107               hr = IXMLDOMComment_get_data(comment, &get_data);
12108               EXPECT_HR(hr, S_OK);
12109 
12110               IXMLDOMComment_Release(comment);
12111               break;
12112            }
12113            default:
12114               get_data = NULL;
12115               break;
12116        }
12117 
12118        /* compare */
12119        ok(!lstrcmpW(data, get_data), "%d: got wrong data %s, expected %s\n", *type, wine_dbgstr_w(get_data),
12120            wine_dbgstr_w(data));
12121        SysFreeString(get_data);
12122 
12123        IXMLDOMNode_Release(node);
12124        type++;
12125     }
12126 
12127     /* \r\n sequence is never escaped */
12128     V_VT(&v) = VT_I2;
12129     V_I2(&v) = NODE_TEXT;
12130 
12131     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12132     ok(hr == S_OK, "got 0x%08x\n", hr);
12133 
12134     IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12135 
12136     hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
12137     ok(hr == S_OK, "got 0x%08x\n", hr);
12138 
12139     hr = IXMLDOMText_get_data(text, &get_data);
12140     ok(hr == S_OK, "got 0x%08x\n", hr);
12141 todo_wine
12142     ok(!lstrcmpW(get_data, _bstr_("\n")), "got %s\n", wine_dbgstr_w(get_data));
12143     SysFreeString(get_data);
12144 
12145     hr = IXMLDOMText_get_xml(text, &get_data);
12146     ok(hr == S_OK, "got 0x%08x\n", hr);
12147     ok(!lstrcmpW(get_data, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(get_data));
12148     SysFreeString(get_data);
12149 
12150     IXMLDOMText_Release(text);
12151     IXMLDOMNode_Release(node);
12152 
12153     IXMLDOMDocument_Release(doc);
12154     free_bstrs();
12155 }
12156 
12157 static void test_putref_schemas(void)
12158 {
12159     IXMLDOMSchemaCollection *cache;
12160     IXMLDOMDocument2 *doc;
12161     VARIANT schema;
12162     HRESULT hr;
12163 
12164     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
12165     if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
12166 
12167     doc = create_document(&IID_IXMLDOMDocument2);
12168     cache = create_cache(&IID_IXMLDOMSchemaCollection);
12169 
12170     /* set to NULL iface when no schema is set */
12171     V_VT(&schema) = VT_DISPATCH;
12172     V_DISPATCH(&schema) = NULL;
12173     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12174     EXPECT_HR(hr, S_OK);
12175 
12176     V_VT(&schema) = VT_UNKNOWN;
12177     V_UNKNOWN(&schema) = NULL;
12178     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12179     EXPECT_HR(hr, S_OK);
12180 
12181     /* set as VT_DISPATCH, reset with it */
12182     V_VT(&schema) = VT_DISPATCH;
12183     V_DISPATCH(&schema) = (IDispatch*)cache;
12184     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12185     EXPECT_HR(hr, S_OK);
12186 
12187     V_DISPATCH(&schema) = NULL;
12188     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12189     EXPECT_HR(hr, S_OK);
12190     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12191 
12192     V_VT(&schema) = VT_DISPATCH;
12193     V_DISPATCH(&schema) = NULL;
12194     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12195     EXPECT_HR(hr, S_OK);
12196 
12197     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12198     V_VT(&schema) = VT_I2;
12199     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12200     EXPECT_HR(hr, S_FALSE);
12201     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12202     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12203 
12204     /* set as VT_UNKNOWN, reset with it */
12205     V_VT(&schema) = VT_UNKNOWN;
12206     V_UNKNOWN(&schema) = (IUnknown*)cache;
12207     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12208     EXPECT_HR(hr, S_OK);
12209 
12210     V_DISPATCH(&schema) = NULL;
12211     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12212     EXPECT_HR(hr, S_OK);
12213     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12214 
12215     V_VT(&schema) = VT_UNKNOWN;
12216     V_UNKNOWN(&schema) = NULL;
12217     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12218     EXPECT_HR(hr, S_OK);
12219 
12220     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12221     V_VT(&schema) = VT_I2;
12222     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12223     EXPECT_HR(hr, S_FALSE);
12224     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12225     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12226 
12227     IXMLDOMSchemaCollection_Release(cache);
12228     IXMLDOMDocument2_Release(doc);
12229 }
12230 
12231 static void test_namedmap_newenum(void)
12232 {
12233     IEnumVARIANT *enum1, *enum2, *enum3;
12234     IXMLDOMNamedNodeMap *map;
12235     IUnknown *unk1, *unk2;
12236     IXMLDOMDocument *doc;
12237     IXMLDOMElement *elem;
12238     IXMLDOMNode *node;
12239     VARIANT_BOOL b;
12240     HRESULT hr;
12241     VARIANT v;
12242     BSTR str;
12243 
12244     doc = create_document(&IID_IXMLDOMDocument);
12245 
12246     hr = IXMLDOMDocument_loadXML(doc, _bstr_(attributes_map), &b);
12247     EXPECT_HR(hr, S_OK);
12248 
12249     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
12250     EXPECT_HR(hr, S_OK);
12251 
12252     hr = IXMLDOMElement_get_attributes(elem, &map);
12253     EXPECT_HR(hr, S_OK);
12254     IXMLDOMElement_Release(elem);
12255 
12256     enum1 = NULL;
12257     EXPECT_REF(map, 1);
12258     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum1);
12259     EXPECT_HR(hr, S_OK);
12260     ok(enum1 != NULL, "got %p\n", enum1);
12261     EXPECT_REF(map, 1);
12262     EXPECT_REF(enum1, 2);
12263 
12264     enum2 = NULL;
12265     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum2);
12266     EXPECT_HR(hr, S_OK);
12267     ok(enum2 == enum1, "got %p\n", enum2);
12268 
12269     IEnumVARIANT_Release(enum2);
12270 
12271     EXPECT_REF(map, 1);
12272     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum2);
12273     EXPECT_HR(hr, S_OK);
12274     EXPECT_REF(map, 2);
12275     EXPECT_REF(enum2, 1);
12276     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
12277 
12278     IEnumVARIANT_Release(enum1);
12279 
12280     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
12281     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk1);
12282     EXPECT_HR(hr, S_OK);
12283     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
12284     EXPECT_HR(hr, S_OK);
12285     EXPECT_REF(map, 3);
12286     EXPECT_REF(enum2, 2);
12287     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
12288     IUnknown_Release(unk1);
12289     IUnknown_Release(unk2);
12290 
12291     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum3);
12292     EXPECT_HR(hr, S_OK);
12293     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
12294     IEnumVARIANT_Release(enum3);
12295 
12296     /* iteration tests */
12297     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node);
12298     EXPECT_HR(hr, S_OK);
12299     hr = IXMLDOMNode_get_nodeName(node, &str);
12300     EXPECT_HR(hr, S_OK);
12301     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12302     SysFreeString(str);
12303     IXMLDOMNode_Release(node);
12304 
12305     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12306     EXPECT_HR(hr, S_OK);
12307     hr = IXMLDOMNode_get_nodeName(node, &str);
12308     EXPECT_HR(hr, S_OK);
12309     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12310     SysFreeString(str);
12311     IXMLDOMNode_Release(node);
12312 
12313     V_VT(&v) = VT_EMPTY;
12314     hr = IEnumVARIANT_Next(enum2, 1, &v, NULL);
12315     EXPECT_HR(hr, S_OK);
12316     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
12317     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
12318     EXPECT_HR(hr, S_OK);
12319     hr = IXMLDOMNode_get_nodeName(node, &str);
12320     EXPECT_HR(hr, S_OK);
12321     ok(!lstrcmpW(str, _bstr_("attr1")), "got node name %s\n", wine_dbgstr_w(str));
12322     SysFreeString(str);
12323     IXMLDOMNode_Release(node);
12324     VariantClear(&v);
12325 
12326     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12327     EXPECT_HR(hr, S_OK);
12328     hr = IXMLDOMNode_get_nodeName(node, &str);
12329     EXPECT_HR(hr, S_OK);
12330     ok(!lstrcmpW(str, _bstr_("attr2")), "got %s\n", wine_dbgstr_w(str));
12331     SysFreeString(str);
12332     IXMLDOMNode_Release(node);
12333 
12334     IEnumVARIANT_Release(enum2);
12335     IXMLDOMNamedNodeMap_Release(map);
12336     IXMLDOMDocument_Release(doc);
12337 }
12338 
12339 static const char xsltext_xsl[] =
12340 "<?xml version=\"1.0\"?>"
12341 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12342 "<xsl:output method=\"html\" encoding=\"us-ascii\"/>"
12343 "<xsl:template match=\"/\">"
12344 "    <xsl:choose>"
12345 "        <xsl:when test=\"testkey\">"
12346 "            <xsl:text>testdata</xsl:text>"
12347 "        </xsl:when>"
12348 "    </xsl:choose>"
12349 "</xsl:template>"
12350 "</xsl:stylesheet>";
12351 
12352 static const char omitxmldecl_xsl[] =
12353 "<?xml version=\"1.0\"?>"
12354 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12355 "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\"/>"
12356 "<xsl:template match=\"/\">"
12357 "    <xsl:for-each select=\"/a/item\">"
12358 "        <xsl:element name=\"node\">"
12359 "            <xsl:value-of select=\"@name\"/>"
12360 "        </xsl:element>"
12361 "    </xsl:for-each>"
12362 "</xsl:template>"
12363 "</xsl:stylesheet>";
12364 
12365 static const char omitxmldecl_doc[] =
12366 "<?xml version=\"1.0\"?>"
12367 "<a>"
12368 "    <item name=\"item1\"/>"
12369 "    <item name=\"item2\"/>"
12370 "</a>";
12371 
12372 static void test_xsltext(void)
12373 {
12374     IXMLDOMDocument *doc, *doc2;
12375     VARIANT_BOOL b;
12376     HRESULT hr;
12377     BSTR ret;
12378 
12379     doc = create_document(&IID_IXMLDOMDocument);
12380     doc2 = create_document(&IID_IXMLDOMDocument);
12381 
12382     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsltext_xsl), &b);
12383     EXPECT_HR(hr, S_OK);
12384 
12385     hr = IXMLDOMDocument_loadXML(doc2, _bstr_("<testkey/>"), &b);
12386     EXPECT_HR(hr, S_OK);
12387 
12388     hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12389     EXPECT_HR(hr, S_OK);
12390     ok(!lstrcmpW(ret, _bstr_("testdata")), "transform result %s\n", wine_dbgstr_w(ret));
12391     SysFreeString(ret);
12392 
12393     /* omit-xml-declaration */
12394     hr = IXMLDOMDocument_loadXML(doc, _bstr_(omitxmldecl_xsl), &b);
12395     ok(hr == S_OK, "got 0x%08x\n", hr);
12396     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(omitxmldecl_doc), &b);
12397     ok(hr == S_OK, "got 0x%08x\n", hr);
12398 
12399     hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12400     ok(hr == S_OK, "got 0x%08x\n", hr);
12401     ok(!lstrcmpW(ret, _bstr_("<node>item1</node><node>item2</node>")), "transform result %s\n", wine_dbgstr_w(ret));
12402     SysFreeString(ret);
12403 
12404     IXMLDOMDocument_Release(doc2);
12405     IXMLDOMDocument_Release(doc);
12406     free_bstrs();
12407 }
12408 
12409 struct attrtest_t {
12410     const char *name;
12411     const char *uri;
12412     const char *prefix;
12413     const char *href;
12414 };
12415 
12416 static struct attrtest_t attrtests[] = {
12417     { "xmlns", "http://www.w3.org/2000/xmlns/", "xmlns", "xmlns" },
12418     { "xmlns", "nondefaulturi", "xmlns", "xmlns" },
12419     { "c", "http://www.w3.org/2000/xmlns/", NULL, "http://www.w3.org/2000/xmlns/" },
12420     { "c", "nsref1", NULL, "nsref1" },
12421     { "ns:c", "nsref1", "ns", "nsref1" },
12422     { "xmlns:c", "http://www.w3.org/2000/xmlns/", "xmlns", "" },
12423     { "xmlns:c", "nondefaulturi", "xmlns", "" },
12424     { 0 }
12425 };
12426 
12427 static void test_create_attribute(void)
12428 {
12429     struct attrtest_t *ptr = attrtests;
12430     IXMLDOMElement *el;
12431     IXMLDOMDocument *doc;
12432     IXMLDOMNode *node, *node2;
12433     VARIANT var;
12434     HRESULT hr;
12435     int i = 0;
12436     BSTR str;
12437 
12438     doc = create_document(&IID_IXMLDOMDocument);
12439 
12440     while (ptr->name)
12441     {
12442         V_VT(&var) = VT_I1;
12443         V_I1(&var) = NODE_ATTRIBUTE;
12444         hr = IXMLDOMDocument_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
12445         ok(hr == S_OK, "got 0x%08x\n", hr);
12446 
12447         str = NULL;
12448         hr = IXMLDOMNode_get_prefix(node, &str);
12449         if (ptr->prefix)
12450         {
12451             ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12452             ok(!lstrcmpW(str, _bstr_(ptr->prefix)), "%d: got prefix %s, expected %s\n", i, wine_dbgstr_w(str), ptr->prefix);
12453         }
12454         else
12455         {
12456             ok(hr == S_FALSE, "%d: got 0x%08x\n", i, hr);
12457             ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str));
12458         }
12459         SysFreeString(str);
12460 
12461         str = NULL;
12462         hr = IXMLDOMNode_get_namespaceURI(node, &str);
12463         ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12464         ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", i, wine_dbgstr_w(str), ptr->href);
12465         SysFreeString(str);
12466 
12467         IXMLDOMNode_Release(node);
12468         free_bstrs();
12469 
12470         i++;
12471         ptr++;
12472     }
12473 
12474     V_VT(&var) = VT_I1;
12475     V_I1(&var) = NODE_ELEMENT;
12476     hr = IXMLDOMDocument_createNode(doc, var, _bstr_("e"), NULL, &node2);
12477     ok(hr == S_OK, "got 0x%08x\n", hr);
12478 
12479     hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&el);
12480     ok(hr == S_OK, "got 0x%08x\n", hr);
12481     IXMLDOMNode_Release(node2);
12482 
12483     V_VT(&var) = VT_I1;
12484     V_I1(&var) = NODE_ATTRIBUTE;
12485     hr = IXMLDOMDocument_createNode(doc, var, _bstr_("xmlns:a"), _bstr_("http://www.w3.org/2000/xmlns/"), &node);
12486     ok(hr == S_OK, "got 0x%08x\n", hr);
12487 
12488     hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL);
12489     ok(hr == S_OK, "got 0x%08x\n", hr);
12490 
12491     /* for some reason default namespace uri is not reported */
12492     hr = IXMLDOMNode_get_namespaceURI(node, &str);
12493     ok(hr == S_OK, "got 0x%08x\n", hr);
12494     ok(!lstrcmpW(str, _bstr_("")), "got uri %s\n", wine_dbgstr_w(str));
12495     SysFreeString(str);
12496 
12497     IXMLDOMNode_Release(node);
12498     IXMLDOMElement_Release(el);
12499     IXMLDOMDocument_Release(doc);
12500     free_bstrs();
12501 }
12502 
12503 static void test_url(void)
12504 {
12505     IXMLDOMDocument *doc;
12506     HRESULT hr;
12507     BSTR s;
12508 
12509     doc = create_document(&IID_IXMLDOMDocument);
12510 
12511     hr = IXMLDOMDocument_get_url(doc, NULL);
12512     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
12513 
12514     s = (void *)0xdeadbeef;
12515     hr = IXMLDOMDocument_get_url(doc, &s);
12516     ok(hr == S_FALSE, "got 0x%08x\n", hr);
12517     ok(s == NULL, "got %s\n", wine_dbgstr_w(s));
12518 
12519     IXMLDOMDocument_Release(doc);
12520 }
12521 
12522 static void test_merging_text(void)
12523 {
12524     IXMLDOMText *nodetext;
12525     IXMLDOMText *newtext;
12526     IXMLDOMElement *root;
12527     IXMLDOMDocument *doc;
12528     IXMLDOMNode *first;
12529     HRESULT hr;
12530     VARIANT v;
12531     BSTR str;
12532     int i;
12533 
12534     doc = create_document(&IID_IXMLDOMDocument);
12535 
12536     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
12537     EXPECT_HR(hr, S_OK);
12538 
12539     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
12540     EXPECT_HR(hr, S_OK);
12541 
12542     /* test xmlAddChild */
12543     for (i = 0; i < 10; i++)
12544     {
12545         str = SysAllocString(szstr1);
12546         hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12547         SysFreeString(str);
12548         EXPECT_HR(hr, S_OK);
12549 
12550         newtext = NULL;
12551         hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)nodetext, (IXMLDOMNode**)&newtext);
12552         EXPECT_HR(hr, S_OK);
12553         ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12554 
12555         IXMLDOMText_Release(newtext);
12556         IXMLDOMText_Release(nodetext);
12557     }
12558 
12559     /* test xmlAddPrevSibling */
12560     hr = IXMLDOMElement_get_firstChild(root, &first);
12561     EXPECT_HR(hr, S_OK);
12562     V_VT(&v) = VT_UNKNOWN;
12563     V_UNKNOWN(&v) = (IUnknown*)first;
12564     for (i = 0; i < 10; i++)
12565     {
12566         str = SysAllocString(szstr2);
12567         hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12568         SysFreeString(str);
12569         EXPECT_HR(hr, S_OK);
12570 
12571         newtext = NULL;
12572         hr = IXMLDOMElement_insertBefore(root, (IXMLDOMNode*)nodetext, v, (IXMLDOMNode**)&newtext);
12573         EXPECT_HR(hr, S_OK);
12574         ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12575 
12576         IXMLDOMText_Release(newtext);
12577         IXMLDOMText_Release(nodetext);
12578     }
12579 
12580     IXMLDOMNode_Release(first);
12581     IXMLDOMElement_Release(root);
12582     IXMLDOMDocument_Release(doc);
12583 
12584     free_bstrs();
12585 }
12586 
12587 static HRESULT WINAPI transformdest_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
12588 {
12589     BOOL known_iid = IsEqualIID(riid, &IID_IHTMLObjectElement) ||
12590         IsEqualIID(riid, &IID_transformdest_unknown) ||
12591         IsEqualIID(riid, &IID_IServiceProvider) ||
12592         IsEqualIID(riid, &IID_IStream) ||
12593         IsEqualIID(riid, &IID_ISequentialStream) ||
12594         IsEqualIID(riid, &IID_IRequestDictionary);
12595 
12596 todo_wine_if(IsEqualIID(riid, &IID_IXMLDOMDocument))
12597     ok(known_iid, "Unexpected riid %s\n", wine_dbgstr_guid(riid));
12598 
12599     return E_NOINTERFACE;
12600 }
12601 
12602 static ULONG WINAPI transformdest_AddRef(IUnknown *iface)
12603 {
12604     return 2;
12605 }
12606 
12607 static ULONG WINAPI transformdest_Release(IUnknown *iface)
12608 {
12609     return 1;
12610 }
12611 
12612 static const IUnknownVtbl transformdestvtbl =
12613 {
12614     transformdest_QueryInterface,
12615     transformdest_AddRef,
12616     transformdest_Release,
12617 };
12618 
12619 static void test_transformNodeToObject(void)
12620 {
12621     IUnknown transformdest = { &transformdestvtbl };
12622     IXMLDOMDocument *doc, *doc2, *doc3;
12623     VARIANT_BOOL b;
12624     HRESULT hr;
12625     VARIANT v;
12626 
12627     doc = create_document(&IID_IXMLDOMDocument);
12628     doc2 = create_document(&IID_IXMLDOMDocument);
12629     doc3 = create_document(&IID_IXMLDOMDocument);
12630 
12631     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &b);
12632     ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12633     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformSSXML), &b);
12634     ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12635 
12636     V_VT(&v) = VT_UNKNOWN;
12637     V_UNKNOWN(&v) = &transformdest;
12638     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12639     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12640 
12641     V_VT(&v) = VT_UNKNOWN;
12642     V_UNKNOWN(&v) = NULL;
12643     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12644     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12645 
12646     V_VT(&v) = VT_DISPATCH;
12647     V_DISPATCH(&v) = NULL;
12648     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12649     ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12650 
12651     V_VT(&v) = VT_DISPATCH;
12652     V_DISPATCH(&v) = (IDispatch *)doc3;
12653     hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12654     ok(hr == S_OK, "Failed to transform node, hr %#x.\n", hr);
12655 
12656     IXMLDOMDocument_Release(doc3);
12657     IXMLDOMDocument_Release(doc2);
12658     IXMLDOMDocument_Release(doc);
12659     free_bstrs();
12660 }
12661 
12662 START_TEST(domdoc)
12663 {
12664     HRESULT hr;
12665 
12666     hr = CoInitialize( NULL );
12667     ok( hr == S_OK, "failed to init com\n");
12668     if (hr != S_OK) return;
12669 
12670     get_class_support_data(domdoc_support_data);
12671     if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument))
12672     {
12673         win_skip("DOMDocument2 is not supported. Skipping all tests.\n");
12674         CoUninitialize();
12675         return;
12676     }
12677 
12678     test_domdoc();
12679     test_persiststream();
12680     test_domnode();
12681     test_refs();
12682     test_create();
12683     test_getElementsByTagName();
12684     test_get_text();
12685     test_get_childNodes();
12686     test_get_firstChild();
12687     test_get_lastChild();
12688     test_removeChild();
12689     test_replaceChild();
12690     test_removeNamedItem();
12691     test_IXMLDOMDocument2();
12692     test_whitespace();
12693     test_XPath();
12694     test_XSLPattern();
12695     test_cloneNode();
12696     test_xmlTypes();
12697     test_save();
12698     test_testTransforms();
12699     test_namespaces_basic();
12700     test_namespaces_change();
12701     test_FormattingXML();
12702     test_nodeTypedValue();
12703     test_TransformWithLoadingLocalFile();
12704     test_put_nodeValue();
12705     test_IObjectSafety();
12706     test_splitText();
12707     test_getQualifiedItem();
12708     test_removeQualifiedItem();
12709     test_get_ownerDocument();
12710     test_setAttributeNode();
12711     test_put_dataType();
12712     test_createNode();
12713     test_create_attribute();
12714     test_get_prefix();
12715     test_default_properties();
12716     test_selectSingleNode();
12717     test_events();
12718     test_createProcessingInstruction();
12719     test_put_nodeTypedValue();
12720     test_get_xml();
12721     test_insertBefore();
12722     test_appendChild();
12723     test_get_doctype();
12724     test_get_tagName();
12725     test_get_dataType();
12726     test_get_nodeTypeString();
12727     test_get_attributes();
12728     test_selection();
12729     test_load();
12730     test_dispex();
12731     test_parseerror();
12732     test_getAttributeNode();
12733     test_getAttribute();
12734     test_supporterrorinfo();
12735     test_nodeValue();
12736     test_get_namespaces();
12737     test_put_data();
12738     test_putref_schemas();
12739     test_namedmap_newenum();
12740     test_xmlns_attribute();
12741     test_url();
12742     test_merging_text();
12743     test_transformNodeToObject();
12744 
12745     test_xsltemplate();
12746     test_xsltext();
12747 
12748     if (is_clsid_supported(&CLSID_MXNamespaceManager40, &IID_IMXNamespaceManager))
12749     {
12750         test_mxnamespacemanager();
12751         test_mxnamespacemanager_override();
12752     }
12753 
12754     CoUninitialize();
12755 }
12756