Release 1.5.29.
[wine] / dlls / msxml3 / tests / domdoc.c
1 /*
2  * XML test
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2007-2008 Alistair Leslie-Hughes
6  * Copyright 2010-2011 Adam Martinson for CodeWeavers
7  * Copyright 2010-2013 Nikolay Sivov for CodeWeavers
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 #include <stdio.h>
29 #include <assert.h>
30
31 #include "windows.h"
32
33 #include "msxml2.h"
34 #include "msxml2did.h"
35 #include "ole2.h"
36 #include "dispex.h"
37 #include "objsafe.h"
38 #include "initguid.h"
39
40 #include "wine/test.h"
41
42 /* undef the #define in msxml2 so that we can access all versions */
43 #undef CLSID_DOMDocument
44
45 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
46
47 static const char *debugstr_guid(REFIID riid)
48 {
49     static char buf[50];
50
51     if(!riid)
52         return "(null)";
53
54     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
55             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
56             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
57             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
58
59     return buf;
60 }
61
62 static int g_unexpectedcall, g_expectedcall;
63
64 typedef struct
65 {
66     IDispatch IDispatch_iface;
67     LONG ref;
68 } dispevent;
69
70 static inline dispevent *impl_from_IDispatch( IDispatch *iface )
71 {
72     return CONTAINING_RECORD(iface, dispevent, IDispatch_iface);
73 }
74
75 static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
76 {
77     *ppvObject = NULL;
78
79     if ( IsEqualGUID( riid, &IID_IDispatch) ||
80          IsEqualGUID( riid, &IID_IUnknown) )
81     {
82         *ppvObject = iface;
83     }
84     else
85         return E_NOINTERFACE;
86
87     IDispatch_AddRef( iface );
88
89     return S_OK;
90 }
91
92 static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
93 {
94     dispevent *This = impl_from_IDispatch( iface );
95     return InterlockedIncrement( &This->ref );
96 }
97
98 static ULONG WINAPI dispevent_Release(IDispatch *iface)
99 {
100     dispevent *This = impl_from_IDispatch( iface );
101     ULONG ref = InterlockedDecrement( &This->ref );
102
103     if (ref == 0)
104         HeapFree(GetProcessHeap(), 0, This);
105
106     return ref;
107 }
108
109 static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
110 {
111     g_unexpectedcall++;
112     *pctinfo = 0;
113     return S_OK;
114 }
115
116 static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
117         LCID lcid, ITypeInfo **ppTInfo)
118 {
119     g_unexpectedcall++;
120     return S_OK;
121 }
122
123 static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
124         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
125 {
126     g_unexpectedcall++;
127     return S_OK;
128 }
129
130 static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
131         LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
132         EXCEPINFO *excepInfo, UINT *argErr)
133 {
134     ok(member == 0, "expected 0 member, got %d\n", member);
135     ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
136     ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
137
138     ok(params->cArgs == 0, "got %d\n", params->cArgs);
139     ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
140     ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
141     ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
142
143     ok(result == NULL, "got %p\n", result);
144     ok(excepInfo == NULL, "got %p\n", excepInfo);
145     ok(argErr == NULL, "got %p\n", argErr);
146
147     g_expectedcall++;
148     return E_FAIL;
149 }
150
151 static const IDispatchVtbl dispeventVtbl =
152 {
153     dispevent_QueryInterface,
154     dispevent_AddRef,
155     dispevent_Release,
156     dispevent_GetTypeInfoCount,
157     dispevent_GetTypeInfo,
158     dispevent_GetIDsOfNames,
159     dispevent_Invoke
160 };
161
162 static IDispatch* create_dispevent(void)
163 {
164     dispevent *event = HeapAlloc(GetProcessHeap(), 0, sizeof(*event));
165
166     event->IDispatch_iface.lpVtbl = &dispeventVtbl;
167     event->ref = 1;
168
169     return (IDispatch*)&event->IDispatch_iface;
170 }
171
172 /* IStream */
173 static HRESULT WINAPI istream_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
174 {
175     *ppvObject = NULL;
176
177     if (IsEqualGUID(riid, &IID_IStream) ||
178         IsEqualGUID(riid, &IID_IUnknown))
179         *ppvObject = iface;
180     else
181         return E_NOINTERFACE;
182
183     return S_OK;
184 }
185
186 static ULONG WINAPI istream_AddRef(IStream *iface)
187 {
188     return 2;
189 }
190
191 static ULONG WINAPI istream_Release(IStream *iface)
192 {
193     return 1;
194 }
195
196 static HRESULT WINAPI istream_Read(IStream *iface, void *ptr, ULONG len, ULONG *pread)
197 {
198     ok(0, "unexpected call\n");
199     return E_NOTIMPL;
200 }
201
202 static HRESULT WINAPI istream_Write(IStream *iface, const void *ptr, ULONG len, ULONG *written)
203 {
204     *written = len/2;
205     return S_OK;
206 }
207
208 static HRESULT WINAPI istream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
209 {
210     ok(0, "unexpected call\n");
211     return E_NOTIMPL;
212 }
213
214 static HRESULT WINAPI istream_SetSize(IStream *iface, ULARGE_INTEGER size)
215 {
216     ok(0, "unexpected call\n");
217     return E_NOTIMPL;
218 }
219
220 static HRESULT WINAPI istream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len,
221         ULARGE_INTEGER *pread, ULARGE_INTEGER *written)
222 {
223     ok(0, "unexpected call\n");
224     return E_NOTIMPL;
225 }
226
227 static HRESULT WINAPI istream_Commit(IStream *iface, DWORD flags)
228 {
229     ok(0, "unexpected call\n");
230     return E_NOTIMPL;
231 }
232
233 static HRESULT WINAPI istream_Revert(IStream *iface)
234 {
235     ok(0, "unexpected call\n");
236     return E_NOTIMPL;
237 }
238
239 static HRESULT WINAPI istream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
240         ULARGE_INTEGER len, DWORD locktype)
241 {
242     ok(0, "unexpected call\n");
243     return E_NOTIMPL;
244 }
245
246 static HRESULT WINAPI istream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
247         ULARGE_INTEGER len, DWORD locktype)
248 {
249     ok(0, "unexpected call\n");
250     return E_NOTIMPL;
251 }
252
253 static HRESULT WINAPI istream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flag)
254 {
255     ok(0, "unexpected call\n");
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI istream_Clone(IStream *iface, IStream **stream)
260 {
261     ok(0, "unexpected call\n");
262     return E_NOTIMPL;
263 }
264
265 static const IStreamVtbl StreamVtbl = {
266     istream_QueryInterface,
267     istream_AddRef,
268     istream_Release,
269     istream_Read,
270     istream_Write,
271     istream_Seek,
272     istream_SetSize,
273     istream_CopyTo,
274     istream_Commit,
275     istream_Revert,
276     istream_LockRegion,
277     istream_UnlockRegion,
278     istream_Stat,
279     istream_Clone
280 };
281
282 static IStream savestream = { &StreamVtbl };
283
284 #define EXPECT_CHILDREN(node) _expect_children((IXMLDOMNode*)node, __LINE__)
285 static void _expect_children(IXMLDOMNode *node, int line)
286 {
287     VARIANT_BOOL b;
288     HRESULT hr;
289
290     b = VARIANT_FALSE;
291     hr = IXMLDOMNode_hasChildNodes(node, &b);
292     ok_(__FILE__,line)(hr == S_OK, "hasChildNodes() failed, 0x%08x\n", hr);
293     ok_(__FILE__,line)(b == VARIANT_TRUE, "no children, %d\n", b);
294 }
295
296 #define EXPECT_NO_CHILDREN(node) _expect_no_children((IXMLDOMNode*)node, __LINE__)
297 static void _expect_no_children(IXMLDOMNode *node, int line)
298 {
299     VARIANT_BOOL b;
300     HRESULT hr;
301
302     b = VARIANT_TRUE;
303     hr = IXMLDOMNode_hasChildNodes(node, &b);
304     ok_(__FILE__,line)(hr == S_FALSE, "hasChildNodes() failed, 0x%08x\n", hr);
305     ok_(__FILE__,line)(b == VARIANT_FALSE, "no children, %d\n", b);
306 }
307
308 #define EXPECT_REF(node,ref) _expect_ref((IUnknown*)node, ref, __LINE__)
309 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
310 {
311     ULONG rc = IUnknown_AddRef(obj);
312     IUnknown_Release(obj);
313     ok_(__FILE__,line)(rc-1 == ref, "expected refcount %d, got %d\n", ref, rc-1);
314 }
315
316 #define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
317 static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
318 {
319     LONG length;
320     HRESULT hr;
321
322     length = 0;
323     hr = IXMLDOMNodeList_get_length(list, &length);
324     ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
325     ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
326 }
327
328 #define EXPECT_HR(hr,hr_exp) \
329     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
330
331 static const WCHAR szEmpty[] = { 0 };
332 static const WCHAR szIncomplete[] = {
333     '<','?','x','m','l',' ',
334     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
335 };
336 static const WCHAR szComplete1[] = {
337     '<','?','x','m','l',' ',
338     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
339     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
340 };
341 static const WCHAR szComplete2[] = {
342     '<','?','x','m','l',' ',
343     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
344     '<','o','>','<','/','o','>','\n',0
345 };
346 static const WCHAR szComplete3[] = {
347     '<','?','x','m','l',' ',
348     'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
349     '<','a','>','<','/','a','>','\n',0
350 };
351 static const char complete4A[] =
352     "<?xml version=\'1.0\'?>\n"
353     "<lc dl=\'str1\'>\n"
354         "<bs vr=\'str2\' sz=\'1234\'>"
355             "fn1.txt\n"
356         "</bs>\n"
357         "<pr id=\'str3\' vr=\'1.2.3\' pn=\'wine 20050804\'>\n"
358             "fn2.txt\n"
359         "</pr>\n"
360         "<empty></empty>\n"
361         "<fo>\n"
362             "<ba>\n"
363                 "f1\n"
364             "</ba>\n"
365         "</fo>\n"
366     "</lc>\n";
367
368 static const WCHAR szComplete5[] = {
369     '<','S',':','s','e','a','r','c','h',' ','x','m','l','n','s',':','D','=','"','D','A','V',':','"',' ',
370     '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','"',
371     ' ','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','"','>',
372         '<','S',':','s','c','o','p','e','>',
373             '<','S',':','d','e','e','p','>','/','<','/','S',':','d','e','e','p','>',
374         '<','/','S',':','s','c','o','p','e','>',
375         '<','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
376             '<','C',':','t','e','x','t','o','r','p','r','o','p','e','r','t','y','/','>',
377             'c','o','m','p','u','t','e','r',
378         '<','/','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
379     '<','/','S',':','s','e','a','r','c','h','>',0
380 };
381
382 static const WCHAR szComplete6[] = {
383     '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'',' ',
384     'e','n','c','o','d','i','n','g','=','\'','W','i','n','d','o','w','s','-','1','2','5','2','\'','?','>','\n',
385     '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
386 };
387
388 #define DECL_WIN_1252 \
389 "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
390
391 static const char win1252xml[] =
392 DECL_WIN_1252
393 "<open></open>";
394
395 static const char win1252decl[] =
396 DECL_WIN_1252
397 ;
398
399 static const char szExampleXML[] =
400 "<?xml version='1.0' encoding='utf-8'?>\n"
401 "<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' a=\"attr a\" foo:b=\"attr b\" >\n"
402 "    <elem>\n"
403 "        <a>A1 field</a>\n"
404 "        <b>B1 field</b>\n"
405 "        <c>C1 field</c>\n"
406 "        <d>D1 field</d>\n"
407 "        <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
408 "            <html xmlns='http://www.w3.org/1999/xhtml'>\n"
409 "                This is <strong>a</strong> <i>description</i>. <bar:x/>\n"
410 "            </html>\n"
411 "            <html xml:space='preserve' xmlns='http://www.w3.org/1999/xhtml'>\n"
412 "                This is <strong>a</strong> <i>description</i> with preserved whitespace. <bar:x/>\n"
413 "            </html>\n"
414 "        </description>\n"
415 "    </elem>\n"
416 "\n"
417 "    <elem>\n"
418 "        <a>A2 field</a>\n"
419 "        <b>B2 field</b>\n"
420 "        <c type=\"old\">C2 field</c>\n"
421 "        <d>D2 field</d>\n"
422 "    </elem>\n"
423 "\n"
424 "    <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
425 "        <a>A3 field</a>\n"
426 "        <b>B3 field</b>\n"
427 "        <c>C3 field</c>\n"
428 "    </elem>\n"
429 "\n"
430 "    <elem>\n"
431 "        <a>A4 field</a>\n"
432 "        <b>B4 field</b>\n"
433 "        <foo:c>C4 field</foo:c>\n"
434 "        <d>D4 field</d>\n"
435 "    </elem>\n"
436 "</root>\n";
437
438 static const CHAR szNodeTypesXML[] =
439 "<?xml version='1.0'?>"
440 "<!-- comment node 0 -->"
441 "<root id='0' depth='0'>"
442 "   <!-- comment node 1 -->"
443 "   text node 0"
444 "   <x id='1' depth='1'>"
445 "       <?foo value='PI for x'?>"
446 "       <!-- comment node 2 -->"
447 "       text node 1"
448 "       <a id='3' depth='2'/>"
449 "       <b id='4' depth='2'/>"
450 "       <c id='5' depth='2'/>"
451 "   </x>"
452 "   <y id='2' depth='1'>"
453 "       <?bar value='PI for y'?>"
454 "       <!-- comment node 3 -->"
455 "       text node 2"
456 "       <a id='6' depth='2'/>"
457 "       <b id='7' depth='2'/>"
458 "       <c id='8' depth='2'/>"
459 "   </y>"
460 "</root>";
461
462 static const CHAR szTransformXML[] =
463 "<?xml version=\"1.0\"?>\n"
464 "<greeting>\n"
465 "Hello World\n"
466 "</greeting>";
467
468 static  const CHAR szTransformSSXML[] =
469 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
470 "   <xsl:output method=\"html\"/>\n"
471 "   <xsl:template match=\"/\">\n"
472 "       <xsl:apply-templates select=\"greeting\"/>\n"
473 "   </xsl:template>\n"
474 "   <xsl:template match=\"greeting\">\n"
475 "       <html>\n"
476 "           <body>\n"
477 "               <h1>\n"
478 "                   <xsl:value-of select=\".\"/>\n"
479 "               </h1>\n"
480 "           </body>\n"
481 "       </html>\n"
482 "   </xsl:template>\n"
483 "</xsl:stylesheet>";
484
485 static  const CHAR szTransformOutput[] =
486 "<html><body><h1>"
487 "Hello World"
488 "</h1></body></html>";
489
490 static const CHAR szTypeValueXML[] =
491 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
492 "<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
493 "   <string>Wine</string>\n"
494 "   <string2 dt:dt=\"string\">String</string2>\n"
495 "   <number dt:dt=\"number\">12.44</number>\n"
496 "   <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
497 "   <int dt:dt=\"int\">-13</int>\n"
498 "   <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
499 "   <bool dt:dt=\"boolean\">1</bool>\n"
500 "   <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
501 "   <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
502 "   <date dt:dt=\"date\">3721-11-01</date>\n"
503 "   <time dt:dt=\"time\">13:57:12.31321</time>\n"
504 "   <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
505 "   <i1 dt:dt=\"i1\">-13</i1>\n"
506 "   <i2 dt:dt=\"i2\">31915</i2>\n"
507 "   <i4 dt:dt=\"i4\">-312232</i4>\n"
508 "   <ui1 dt:dt=\"ui1\">123</ui1>\n"
509 "   <ui2 dt:dt=\"ui2\">48282</ui2>\n"
510 "   <ui4 dt:dt=\"ui4\">949281</ui4>\n"
511 "   <r4 dt:dt=\"r4\">213124.0</r4>\n"
512 "   <r8 dt:dt=\"r8\">0.412</r8>\n"
513 "   <float dt:dt=\"float\">41221.421</float>\n"
514 "   <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
515 "   <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
516 "   <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
517 "   <binbase64_1 dt:dt=\"bin.base64\">\nYmFzZTY0\nIHRlc3Q=\n</binbase64_1>\n"
518 "   <binbase64_2 dt:dt=\"bin.base64\">\nYmF\r\t z  ZTY0\nIHRlc3Q=\n</binbase64_2>\n"
519 "</root>";
520
521 static const CHAR szBasicTransformSSXMLPart1[] =
522 "<?xml version=\"1.0\"?>"
523 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
524 "<xsl:output method=\"html\"/>\n"
525 "<xsl:template match=\"/\">"
526 "<HTML><BODY><TABLE>"
527 "        <xsl:apply-templates select='document(\"";
528
529 static const CHAR szBasicTransformSSXMLPart2[] =
530 "\")/bottle/wine'>"
531 "           <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
532 "        </xsl:apply-templates>"
533 "</TABLE></BODY></HTML>"
534 "</xsl:template>"
535 "<xsl:template match=\"bottle\">"
536 "   <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
537 "</xsl:template>"
538 "<xsl:template match=\"name\">"
539 "   <TD><xsl:apply-templates /></TD>"
540 "</xsl:template>"
541 "<xsl:template match=\"cost\">"
542 "   <TD><xsl:apply-templates /></TD>"
543 "</xsl:template>"
544 "</xsl:stylesheet>";
545
546 static const CHAR szBasicTransformXML[] =
547 "<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
548
549 static const CHAR szBasicTransformOutput[] =
550 "<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
551
552 #define SZ_EMAIL_DTD \
553 "<!DOCTYPE email ["\
554 "   <!ELEMENT email         (recipients,from,reply-to?,subject,body,attachment*)>"\
555 "       <!ATTLIST email attachments IDREFS #REQUIRED>"\
556 "       <!ATTLIST email sent (yes|no) \"no\">"\
557 "   <!ELEMENT recipients    (to+,cc*)>"\
558 "   <!ELEMENT to            (#PCDATA)>"\
559 "       <!ATTLIST to name CDATA #IMPLIED>"\
560 "   <!ELEMENT cc            (#PCDATA)>"\
561 "       <!ATTLIST cc name CDATA #IMPLIED>"\
562 "   <!ELEMENT from          (#PCDATA)>"\
563 "       <!ATTLIST from name CDATA #IMPLIED>"\
564 "   <!ELEMENT reply-to      (#PCDATA)>"\
565 "       <!ATTLIST reply-to name CDATA #IMPLIED>"\
566 "   <!ELEMENT subject       ANY>"\
567 "   <!ELEMENT body          ANY>"\
568 "       <!ATTLIST body enc CDATA #FIXED \"UTF-8\">"\
569 "   <!ELEMENT attachment    (#PCDATA)>"\
570 "       <!ATTLIST attachment id ID #REQUIRED>"\
571 "]>"
572
573 static const CHAR szEmailXML[] =
574 "<?xml version=\"1.0\"?>"
575 SZ_EMAIL_DTD
576 "<email attachments=\"patch1\">"
577 "   <recipients>"
578 "       <to>wine-patches@winehq.org</to>"
579 "   </recipients>"
580 "   <from name=\"Anonymous\">user@localhost</from>"
581 "   <subject>msxml3/tests: DTD validation (try 87)</subject>"
582 "   <body>"
583 "       It no longer causes spontaneous combustion..."
584 "   </body>"
585 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
586 "</email>";
587
588 static const CHAR szEmailXML_0D[] =
589 "<?xml version=\"1.0\"?>"
590 SZ_EMAIL_DTD
591 "<email attachments=\"patch1\">"
592 "   <recipients>"
593 "       <to>wine-patches@winehq.org</to>"
594 "   </recipients>"
595 "   <from name=\"Anonymous\">user@localhost</from>"
596 "   <subject>msxml3/tests: DTD validation (try 88)</subject>"
597 "   <body>"
598 "       <undecl />"
599 "       XML_ELEMENT_UNDECLARED 0xC00CE00D"
600 "   </body>"
601 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
602 "</email>";
603
604 static const CHAR szEmailXML_0E[] =
605 "<?xml version=\"1.0\"?>"
606 SZ_EMAIL_DTD
607 "<email attachments=\"patch1\">"
608 "   <recipients>"
609 "       <to>wine-patches@winehq.org</to>"
610 "   </recipients>"
611 "   <from name=\"Anonymous\">user@localhost</from>"
612 "   <subject>msxml3/tests: DTD validation (try 89)</subject>"
613 "   <body>"
614 "       XML_ELEMENT_ID_NOT_FOUND 0xC00CE00E"
615 "   </body>"
616 "   <attachment id=\"patch\">0001-msxml3-tests-DTD-validation.patch</attachment>"
617 "</email>";
618
619 static const CHAR szEmailXML_11[] =
620 "<?xml version=\"1.0\"?>"
621 SZ_EMAIL_DTD
622 "<email attachments=\"patch1\">"
623 "   <recipients>"
624 "   </recipients>"
625 "   <from name=\"Anonymous\">user@localhost</from>"
626 "   <subject>msxml3/tests: DTD validation (try 90)</subject>"
627 "   <body>"
628 "       XML_EMPTY_NOT_ALLOWED 0xC00CE011"
629 "   </body>"
630 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
631 "</email>";
632
633 static const CHAR szEmailXML_13[] =
634 "<?xml version=\"1.0\"?>"
635 SZ_EMAIL_DTD
636 "<msg attachments=\"patch1\">"
637 "   <recipients>"
638 "       <to>wine-patches@winehq.org</to>"
639 "   </recipients>"
640 "   <from name=\"Anonymous\">user@localhost</from>"
641 "   <subject>msxml3/tests: DTD validation (try 91)</subject>"
642 "   <body>"
643 "       XML_ROOT_NAME_MISMATCH 0xC00CE013"
644 "   </body>"
645 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
646 "</msg>";
647
648 static const CHAR szEmailXML_14[] =
649 "<?xml version=\"1.0\"?>"
650 SZ_EMAIL_DTD
651 "<email attachments=\"patch1\">"
652 "   <to>wine-patches@winehq.org</to>"
653 "   <from name=\"Anonymous\">user@localhost</from>"
654 "   <subject>msxml3/tests: DTD validation (try 92)</subject>"
655 "   <body>"
656 "       XML_INVALID_CONTENT 0xC00CE014"
657 "   </body>"
658 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
659 "</email>";
660
661 static const CHAR szEmailXML_15[] =
662 "<?xml version=\"1.0\"?>"
663 SZ_EMAIL_DTD
664 "<email attachments=\"patch1\" ip=\"127.0.0.1\">"
665 "   <recipients>"
666 "       <to>wine-patches@winehq.org</to>"
667 "   </recipients>"
668 "   <from name=\"Anonymous\">user@localhost</from>"
669 "   <subject>msxml3/tests: DTD validation (try 93)</subject>"
670 "   <body>"
671 "       XML_ATTRIBUTE_NOT_DEFINED 0xC00CE015"
672 "   </body>"
673 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
674 "</email>";
675
676 static const CHAR szEmailXML_16[] =
677 "<?xml version=\"1.0\"?>"
678 SZ_EMAIL_DTD
679 "<email attachments=\"patch1\">"
680 "   <recipients>"
681 "       <to>wine-patches@winehq.org</to>"
682 "   </recipients>"
683 "   <from name=\"Anonymous\">user@localhost</from>"
684 "   <subject>msxml3/tests: DTD validation (try 94)</subject>"
685 "   <body enc=\"ASCII\">"
686 "       XML_ATTRIBUTE_FIXED 0xC00CE016"
687 "   </body>"
688 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
689 "</email>";
690
691 static const CHAR szEmailXML_17[] =
692 "<?xml version=\"1.0\"?>"
693 SZ_EMAIL_DTD
694 "<email attachments=\"patch1\" sent=\"true\">"
695 "   <recipients>"
696 "       <to>wine-patches@winehq.org</to>"
697 "   </recipients>"
698 "   <from name=\"Anonymous\">user@localhost</from>"
699 "   <subject>msxml3/tests: DTD validation (try 95)</subject>"
700 "   <body>"
701 "       XML_ATTRIBUTE_VALUE 0xC00CE017"
702 "   </body>"
703 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
704 "</email>";
705
706 static const CHAR szEmailXML_18[] =
707 "<?xml version=\"1.0\"?>"
708 SZ_EMAIL_DTD
709 "<email attachments=\"patch1\">"
710 "   oops"
711 "   <recipients>"
712 "       <to>wine-patches@winehq.org</to>"
713 "   </recipients>"
714 "   <from name=\"Anonymous\">user@localhost</from>"
715 "   <subject>msxml3/tests: DTD validation (try 96)</subject>"
716 "   <body>"
717 "       XML_ILLEGAL_TEXT 0xC00CE018"
718 "   </body>"
719 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
720 "</email>";
721
722 static const CHAR szEmailXML_20[] =
723 "<?xml version=\"1.0\"?>"
724 SZ_EMAIL_DTD
725 "<email>"
726 "   <recipients>"
727 "       <to>wine-patches@winehq.org</to>"
728 "   </recipients>"
729 "   <from name=\"Anonymous\">user@localhost</from>"
730 "   <subject>msxml3/tests: DTD validation (try 97)</subject>"
731 "   <body>"
732 "       XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020"
733 "   </body>"
734 "   <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
735 "</email>";
736
737 static const char xpath_simple_list[] =
738 "<?xml version=\"1.0\"?>"
739 "<root>"
740 "   <a attr1=\"1\" attr2=\"2\" />"
741 "   <b/>"
742 "   <c/>"
743 "   <d/>"
744 "</root>";
745
746 static const char default_ns_doc[] = {
747     "<?xml version=\"1.0\"?>"
748     "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
749     "    d=\"d attr\" />"
750 };
751
752 static const char attributes_map[] = {
753     "<?xml version=\"1.0\"?>"
754     "<a attr1=\"value1\" attr2=\"value2\" attr3=\"value3\" attr4=\"value4\" />"
755 };
756
757 static const WCHAR nonexistent_fileW[] = {
758     'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
759 };
760 static const WCHAR nonexistent_attrW[] = {
761     'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
762 };
763 static const WCHAR szDocument[] = {
764     '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
765 };
766
767 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
768 static WCHAR szdl[] = { 'd','l',0 };
769 static const WCHAR szvr[] = { 'v','r',0 };
770 static const WCHAR szlc[] = { 'l','c',0 };
771 static WCHAR szbs[] = { 'b','s',0 };
772 static const WCHAR szstr1[] = { 's','t','r','1',0 };
773 static const WCHAR szstr2[] = { 's','t','r','2',0 };
774 static const WCHAR szstar[] = { '*',0 };
775 static const WCHAR szfn1_txt[] = {'f','n','1','.','t','x','t',0};
776
777 static WCHAR szComment[] = {'A',' ','C','o','m','m','e','n','t',0 };
778 static WCHAR szCommentXML[] = {'<','!','-','-','A',' ','C','o','m','m','e','n','t','-','-','>',0 };
779 static WCHAR szCommentNodeText[] = {'#','c','o','m','m','e','n','t',0 };
780
781 static WCHAR szElement[] = {'E','l','e','T','e','s','t', 0 };
782 static WCHAR szElementXML[]  = {'<','E','l','e','T','e','s','t','/','>',0 };
783 static WCHAR szElementXML2[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','/','>',0 };
784 static WCHAR szElementXML3[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
785                                 'T','e','s','t','i','n','g','N','o','d','e','<','/','E','l','e','T','e','s','t','>',0 };
786 static WCHAR szElementXML4[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
787                                 '&','a','m','p',';','x',' ',0x2103,'<','/','E','l','e','T','e','s','t','>',0 };
788
789 static WCHAR szAttribute[] = {'A','t','t','r',0 };
790 static WCHAR szAttributeXML[] = {'A','t','t','r','=','"','"',0 };
791
792 static WCHAR szCData[] = {'[','1',']','*','2','=','3',';',' ','&','g','e','e',' ','t','h','a','t','s',
793                           ' ','n','o','t',' ','r','i','g','h','t','!', 0};
794 static WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*','2','=','3',';',' ','&',
795                              'g','e','e',' ','t','h','a','t','s',' ','n','o','t',' ','r','i','g','h','t',
796                              '!',']',']','>',0};
797 static WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 };
798 static WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 };
799
800 static WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 };
801 static WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 };
802 static WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
803
804 #define expect_bstr_eq_and_free(bstr, expect) { \
805     BSTR bstrExp = alloc_str_from_narrow(expect); \
806     ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \
807     SysFreeString(bstr); \
808     SysFreeString(bstrExp); \
809 }
810
811 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
812
813 #define ole_check(expr) { \
814     HRESULT r = expr; \
815     ok(r == S_OK, #expr " returned %x\n", r); \
816 }
817
818 #define ole_expect(expr, expect) { \
819     HRESULT r = expr; \
820     ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
821 }
822
823 #define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
824
825 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
826 {
827     void *obj = NULL;
828     HRESULT hr;
829
830     hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
831     if (hr != S_OK)
832         win_skip_(__FILE__,line)("failed to create %s instance: 0x%08x\n", name, hr);
833
834     return obj;
835 }
836
837 #define _create(cls) cls, #cls
838
839 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
840 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
841 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
842 #define create_cache_version(v, iid) _create_object(&_create(CLSID_XMLSchemaCache ## v), iid, __LINE__)
843 #define create_xsltemplate(iid) _create_object(&_create(CLSID_XSLTemplate), iid, __LINE__)
844
845 static BSTR alloc_str_from_narrow(const char *str)
846 {
847     int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
848     BSTR ret = SysAllocStringLen(NULL, len - 1);  /* NUL character added automatically */
849     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
850     return ret;
851 }
852
853 static BSTR alloced_bstrs[256];
854 static int alloced_bstrs_count;
855
856 static BSTR _bstr_(const char *str)
857 {
858     assert(alloced_bstrs_count < sizeof(alloced_bstrs)/sizeof(alloced_bstrs[0]));
859     alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
860     return alloced_bstrs[alloced_bstrs_count++];
861 }
862
863 static void free_bstrs(void)
864 {
865     int i;
866     for (i = 0; i < alloced_bstrs_count; i++)
867         SysFreeString(alloced_bstrs[i]);
868     alloced_bstrs_count = 0;
869 }
870
871 static VARIANT _variantbstr_(const char *str)
872 {
873     VARIANT v;
874     V_VT(&v) = VT_BSTR;
875     V_BSTR(&v) = _bstr_(str);
876     return v;
877 }
878
879 static BOOL compareIgnoreReturns(BSTR sLeft, BSTR sRight)
880 {
881     for (;;)
882     {
883         while (*sLeft == '\r' || *sLeft == '\n') sLeft++;
884         while (*sRight == '\r' || *sRight == '\n') sRight++;
885         if (*sLeft != *sRight) return FALSE;
886         if (!*sLeft) return TRUE;
887         sLeft++;
888         sRight++;
889     }
890 }
891
892 static void get_str_for_type(DOMNodeType type, char *buf)
893 {
894     switch (type)
895     {
896         case NODE_ATTRIBUTE:
897             strcpy(buf, "A");
898             break;
899         case NODE_ELEMENT:
900             strcpy(buf, "E");
901             break;
902         case NODE_DOCUMENT:
903             strcpy(buf, "D");
904             break;
905         case NODE_TEXT:
906             strcpy(buf, "T");
907             break;
908         case NODE_COMMENT:
909             strcpy(buf, "C");
910             break;
911         case NODE_PROCESSING_INSTRUCTION:
912             strcpy(buf, "P");
913             break;
914         default:
915             wsprintfA(buf, "[%d]", type);
916     }
917 }
918
919 static int get_node_position(IXMLDOMNode *node)
920 {
921     HRESULT r;
922     int pos = 0;
923
924     IXMLDOMNode_AddRef(node);
925     do
926     {
927         IXMLDOMNode *new_node;
928
929         pos++;
930         r = IXMLDOMNode_get_previousSibling(node, &new_node);
931         ok(SUCCEEDED(r), "get_previousSibling failed\n");
932         IXMLDOMNode_Release(node);
933         node = new_node;
934     } while (r == S_OK);
935     return pos;
936 }
937
938 static void node_to_string(IXMLDOMNode *node, char *buf)
939 {
940     HRESULT r = S_OK;
941     DOMNodeType type;
942
943     if (node == NULL)
944     {
945         lstrcpyA(buf, "(null)");
946         return;
947     }
948
949     IXMLDOMNode_AddRef(node);
950     while (r == S_OK)
951     {
952         IXMLDOMNode *new_node;
953
954         ole_check(IXMLDOMNode_get_nodeType(node, &type));
955         get_str_for_type(type, buf);
956         buf+=strlen(buf);
957
958         if (type == NODE_ATTRIBUTE)
959         {
960             BSTR bstr;
961             ole_check(IXMLDOMNode_get_nodeName(node, &bstr));
962             *(buf++) = '\'';
963             wsprintfA(buf, "%ws", bstr);
964             buf += strlen(buf);
965             *(buf++) = '\'';
966             SysFreeString(bstr);
967
968             r = IXMLDOMNode_selectSingleNode(node, _bstr_(".."), &new_node);
969         }
970         else
971         {
972             r = IXMLDOMNode_get_parentNode(node, &new_node);
973             wsprintf(buf, "%d", get_node_position(node));
974             buf += strlen(buf);
975         }
976
977         ok(SUCCEEDED(r), "get_parentNode failed (%08x)\n", r);
978         IXMLDOMNode_Release(node);
979         node = new_node;
980         if (r == S_OK)
981             *(buf++) = '.';
982     }
983
984     *buf = 0;
985 }
986
987 static char *list_to_string(IXMLDOMNodeList *list)
988 {
989     static char buf[4096];
990     char *pos = buf;
991     LONG len = 0;
992     int i;
993
994     if (list == NULL)
995     {
996         lstrcpyA(buf, "(null)");
997         return buf;
998     }
999     ole_check(IXMLDOMNodeList_get_length(list, &len));
1000     for (i = 0; i < len; i++)
1001     {
1002         IXMLDOMNode *node;
1003         if (i > 0)
1004             *(pos++) = ' ';
1005         ole_check(IXMLDOMNodeList_nextNode(list, &node));
1006         node_to_string(node, pos);
1007         pos += strlen(pos);
1008         IXMLDOMNode_Release(node);
1009     }
1010     *pos = 0;
1011     return buf;
1012 }
1013
1014 #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); }
1015 #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); }
1016
1017 struct docload_ret_t {
1018     VARIANT_BOOL b;
1019     HRESULT hr;
1020 };
1021
1022 struct leading_spaces_t {
1023     const CLSID *clsid;
1024     const char *name;
1025     struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1026 };
1027
1028 static const struct leading_spaces_t leading_spaces_classdata[] = {
1029     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1030     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1031     { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE,  S_OK } }},
1032     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1033     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1034     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1035     { NULL }
1036 };
1037
1038 static const char* leading_spaces_xmldata[] = {
1039     "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1040     " <?xml version=\"1.0\"?><root/>",
1041     "\n<?xml version=\"1.0\"?><root/>",
1042     "\t<?xml version=\"1.0\"?><root/>",
1043     "\r\n<?xml version=\"1.0\"?><root/>",
1044     "\r<?xml version=\"1.0\"?><root/>",
1045     "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1046     0
1047 };
1048
1049 static void test_domdoc( void )
1050 {
1051     HRESULT r, hr;
1052     IXMLDOMDocument *doc;
1053     IXMLDOMParseError *error;
1054     IXMLDOMElement *element = NULL;
1055     IXMLDOMNode *node;
1056     IXMLDOMText *nodetext = NULL;
1057     IXMLDOMComment *node_comment = NULL;
1058     IXMLDOMAttribute *node_attr = NULL;
1059     IXMLDOMNode *nodeChild = NULL;
1060     IXMLDOMProcessingInstruction *nodePI = NULL;
1061     const struct leading_spaces_t *class_ptr;
1062     const char **data_ptr;
1063     VARIANT_BOOL b;
1064     VARIANT var;
1065     BSTR str;
1066     LONG code, ref;
1067     LONG nLength = 0;
1068     WCHAR buff[100];
1069     char path[MAX_PATH];
1070     int index;
1071
1072     GetTempPathA(MAX_PATH, path);
1073     strcat(path, "leading_spaces.xml");
1074
1075     /* Load document with leading spaces
1076      *
1077      * Test all CLSIDs with all test data XML strings
1078      */
1079     class_ptr = leading_spaces_classdata;
1080     index = 0;
1081     while (class_ptr->clsid)
1082     {
1083         HRESULT hr;
1084         int i;
1085
1086         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
1087              &IID_IXMLDOMDocument, (void**)&doc);
1088         if (hr != S_OK) {
1089             win_skip("%d: failed to create class instance for %s\n", index, class_ptr->name);
1090             class_ptr++;
1091             index++;
1092             continue;
1093         }
1094
1095         data_ptr = leading_spaces_xmldata;
1096         i = 0;
1097         while (*data_ptr) {
1098             BSTR data = _bstr_(*data_ptr);
1099             DWORD written;
1100             HANDLE file;
1101
1102             file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1103             ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1104
1105             WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1106             CloseHandle(file);
1107
1108             b = 0xc;
1109             V_VT(&var) = VT_BSTR;
1110             V_BSTR(&var) = _bstr_(path);
1111             hr = IXMLDOMDocument_load(doc, var, &b);
1112         todo_wine {
1113             EXPECT_HR(hr, class_ptr->ret[0].hr);
1114             ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1115         }
1116             DeleteFileA(path);
1117
1118             b = 0xc;
1119             hr = IXMLDOMDocument_loadXML(doc, data, &b);
1120             EXPECT_HR(hr, class_ptr->ret[1].hr);
1121             ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1122
1123             data_ptr++;
1124             i++;
1125         }
1126
1127         class_ptr++;
1128         index++;
1129         free_bstrs();
1130     }
1131
1132     doc = create_document(&IID_IXMLDOMDocument);
1133     if (!doc) return;
1134
1135 if (0)
1136 {
1137     /* crashes on native */
1138     IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1139 }
1140
1141     /* try some stupid things */
1142     hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1143     EXPECT_HR(hr, S_FALSE);
1144
1145     b = VARIANT_TRUE;
1146     hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1147     EXPECT_HR(hr, S_FALSE);
1148     ok( b == VARIANT_FALSE, "failed to load XML string\n");
1149
1150     /* try to load a document from a nonexistent file */
1151     b = VARIANT_TRUE;
1152     str = SysAllocString( nonexistent_fileW );
1153     VariantInit(&var);
1154     V_VT(&var) = VT_BSTR;
1155     V_BSTR(&var) = str;
1156
1157     r = IXMLDOMDocument_load( doc, var, &b);
1158     ok( r == S_FALSE, "loadXML succeeded\n");
1159     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1160     SysFreeString( str );
1161
1162     /* try load an empty document */
1163     b = VARIANT_TRUE;
1164     str = SysAllocString( szEmpty );
1165     r = IXMLDOMDocument_loadXML( doc, str, &b );
1166     ok( r == S_FALSE, "loadXML succeeded\n");
1167     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1168     SysFreeString( str );
1169
1170     r = IXMLDOMDocument_get_async( doc, &b );
1171     ok( r == S_OK, "get_async failed (%08x)\n", r);
1172     ok( b == VARIANT_TRUE, "Wrong default value\n");
1173
1174     /* check that there's no document element */
1175     element = NULL;
1176     r = IXMLDOMDocument_get_documentElement( doc, &element );
1177     ok( r == S_FALSE, "should be no document element\n");
1178
1179     /* try finding a node */
1180     node = NULL;
1181     str = SysAllocString( szstr1 );
1182     r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1183     ok( r == S_FALSE, "ret %08x\n", r );
1184     SysFreeString( str );
1185
1186     b = VARIANT_TRUE;
1187     str = SysAllocString( szIncomplete );
1188     r = IXMLDOMDocument_loadXML( doc, str, &b );
1189     ok( r == S_FALSE, "loadXML succeeded\n");
1190     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1191     SysFreeString( str );
1192
1193     /* check that there's no document element */
1194     element = (IXMLDOMElement*)1;
1195     r = IXMLDOMDocument_get_documentElement( doc, &element );
1196     ok( r == S_FALSE, "should be no document element\n");
1197     ok( element == NULL, "Element should be NULL\n");
1198
1199     /* test for BSTR handling, pass broken BSTR */
1200     memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1201     /* just a big length */
1202     *(DWORD*)buff = 0xf0f0;
1203     b = VARIANT_FALSE;
1204     r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1205     ok( r == S_OK, "loadXML failed\n");
1206     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1207
1208     /* loadXML ignores the encoding attribute and always expects Unicode */
1209     b = VARIANT_FALSE;
1210     str = SysAllocString( szComplete6 );
1211     r = IXMLDOMDocument_loadXML( doc, str, &b );
1212     ok( r == S_OK, "loadXML failed\n");
1213     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1214     SysFreeString( str );
1215
1216     /* try a BSTR containing a Windows-1252 document */
1217     b = VARIANT_TRUE;
1218     str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1219     r = IXMLDOMDocument_loadXML( doc, str, &b );
1220     ok( r == S_FALSE, "loadXML succeeded\n");
1221     ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1222     SysFreeString( str );
1223
1224     /* try to load something valid */
1225     b = VARIANT_FALSE;
1226     str = SysAllocString( szComplete1 );
1227     r = IXMLDOMDocument_loadXML( doc, str, &b );
1228     ok( r == S_OK, "loadXML failed\n");
1229     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1230     SysFreeString( str );
1231
1232     /* check if nodename is correct */
1233     r = IXMLDOMDocument_get_nodeName( doc, NULL );
1234     ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1235
1236     str = (BSTR)0xdeadbeef;
1237     r = IXMLDOMDocument_get_baseName( doc, &str );
1238     ok ( r == S_FALSE, "got 0x%08x\n", r);
1239     ok (str == NULL, "got %p\n", str);
1240
1241     /* content doesn't matter here */
1242     str = NULL;
1243     r = IXMLDOMDocument_get_nodeName( doc, &str );
1244     ok ( r == S_OK, "get_nodeName wrong code\n");
1245     ok ( str != NULL, "str is null\n");
1246     ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1247     SysFreeString( str );
1248
1249     /* test put_text */
1250     r = IXMLDOMDocument_put_text( doc, _bstr_("Should Fail") );
1251     ok( r == E_FAIL, "ret %08x\n", r );
1252
1253     /* check that there's a document element */
1254     element = NULL;
1255     r = IXMLDOMDocument_get_documentElement( doc, &element );
1256     ok( r == S_OK, "should be a document element\n");
1257     if( element )
1258     {
1259         IObjectIdentity *ident;
1260
1261         r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1262         ok( r == E_NOINTERFACE, "ret %08x\n", r);
1263
1264         IXMLDOMElement_Release( element );
1265         element = NULL;
1266     }
1267
1268     /* as soon as we call loadXML again, the document element will disappear */
1269     b = 2;
1270     r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1271     ok( r == S_FALSE, "loadXML failed\n");
1272     ok( b == 2, "variant modified\n");
1273     r = IXMLDOMDocument_get_documentElement( doc, &element );
1274     ok( r == S_FALSE, "should be no document element\n");
1275
1276     /* try to load something else simple and valid */
1277     b = VARIANT_FALSE;
1278     str = SysAllocString( szComplete3 );
1279     r = IXMLDOMDocument_loadXML( doc, str, &b );
1280     ok( r == S_OK, "loadXML failed\n");
1281     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1282     SysFreeString( str );
1283
1284     /* try something a little more complicated */
1285     b = FALSE;
1286     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1287     ok( r == S_OK, "loadXML failed\n");
1288     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1289
1290     r = IXMLDOMDocument_get_parseError( doc, &error );
1291     ok( r == S_OK, "returns %08x\n", r );
1292
1293     r = IXMLDOMParseError_get_errorCode( error, &code );
1294     ok( r == S_FALSE, "returns %08x\n", r );
1295     ok( code == 0, "code %d\n", code );
1296     IXMLDOMParseError_Release( error );
1297
1298     /* test createTextNode */
1299     r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1300     ok( r == S_OK, "returns %08x\n", r );
1301     IXMLDOMText_Release(nodetext);
1302
1303     str = SysAllocString( szOpen );
1304     r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1305     ok( r == E_INVALIDARG, "returns %08x\n", r );
1306     r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1307     ok( r == S_OK, "returns %08x\n", r );
1308     SysFreeString( str );
1309     if(nodetext)
1310     {
1311         r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1312         ok(r == E_NOINTERFACE, "ret %08x\n", r );
1313
1314         /* Text Last Child Checks */
1315         r = IXMLDOMText_get_lastChild(nodetext, NULL);
1316         ok(r == E_INVALIDARG, "ret %08x\n", r );
1317
1318         nodeChild = (IXMLDOMNode*)0x1;
1319         r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1320         ok(r == S_FALSE, "ret %08x\n", r );
1321         ok(nodeChild == NULL, "nodeChild not NULL\n");
1322
1323         /* test length property */
1324         r = IXMLDOMText_get_length(nodetext, NULL);
1325         ok(r == E_INVALIDARG, "ret %08x\n", r );
1326
1327         r = IXMLDOMText_get_length(nodetext, &nLength);
1328         ok(r == S_OK, "ret %08x\n", r );
1329         ok(nLength == 4, "expected 4 got %d\n", nLength);
1330
1331         /* put data Tests */
1332         r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1333         ok(r == S_OK, "ret %08x\n", r );
1334
1335         /* get data Tests */
1336         r = IXMLDOMText_get_data(nodetext, &str);
1337         ok(r == S_OK, "ret %08x\n", r );
1338         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1339         SysFreeString(str);
1340
1341         /* Confirm XML text is good */
1342         r = IXMLDOMText_get_xml(nodetext, &str);
1343         ok(r == S_OK, "ret %08x\n", r );
1344         ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1345         SysFreeString(str);
1346
1347         /* Confirm we get the put_data Text back */
1348         r = IXMLDOMText_get_text(nodetext, &str);
1349         ok(r == S_OK, "ret %08x\n", r );
1350         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1351         SysFreeString(str);
1352
1353         /* test substringData */
1354         r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1355         ok(r == E_INVALIDARG, "ret %08x\n", r );
1356
1357         /* test substringData - Invalid offset */
1358         str = (BSTR)&szElement;
1359         r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1360         ok(r == E_INVALIDARG, "ret %08x\n", r );
1361         ok( str == NULL, "incorrect string\n");
1362
1363         /* test substringData - Invalid offset */
1364         str = (BSTR)&szElement;
1365         r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1366         ok(r == S_FALSE, "ret %08x\n", r );
1367         ok( str == NULL, "incorrect string\n");
1368
1369         /* test substringData - Invalid size */
1370         str = (BSTR)&szElement;
1371         r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1372         ok(r == E_INVALIDARG, "ret %08x\n", r );
1373         ok( str == NULL, "incorrect string\n");
1374
1375         /* test substringData - Invalid size */
1376         str = (BSTR)&szElement;
1377         r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1378         ok(r == S_FALSE, "ret %08x\n", r );
1379         ok( str == NULL, "incorrect string\n");
1380
1381         /* test substringData - Start of string */
1382         r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1383         ok(r == S_OK, "ret %08x\n", r );
1384         ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1385         SysFreeString(str);
1386
1387         /* test substringData - Middle of string */
1388         r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1389         ok(r == S_OK, "ret %08x\n", r );
1390         ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1391         SysFreeString(str);
1392
1393         /* test substringData - End of string */
1394         r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1395         ok(r == S_OK, "ret %08x\n", r );
1396         ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1397         SysFreeString(str);
1398
1399         /* test appendData */
1400         r = IXMLDOMText_appendData(nodetext, NULL);
1401         ok(r == S_OK, "ret %08x\n", r );
1402
1403         r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1404         ok(r == S_OK, "ret %08x\n", r );
1405
1406         r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1407         ok(r == S_OK, "ret %08x\n", r );
1408
1409         r = IXMLDOMText_get_text(nodetext, &str);
1410         ok(r == S_OK, "ret %08x\n", r );
1411         ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1412         SysFreeString(str);
1413
1414         /* test insertData */
1415         str = SysAllocStringLen(NULL, 0);
1416         r = IXMLDOMText_insertData(nodetext, -1, str);
1417         ok(r == S_OK, "ret %08x\n", r );
1418
1419         r = IXMLDOMText_insertData(nodetext, -1, NULL);
1420         ok(r == S_OK, "ret %08x\n", r );
1421
1422         r = IXMLDOMText_insertData(nodetext, 1000, str);
1423         ok(r == S_OK, "ret %08x\n", r );
1424
1425         r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1426         ok(r == S_OK, "ret %08x\n", r );
1427
1428         r = IXMLDOMText_insertData(nodetext, 0, NULL);
1429         ok(r == S_OK, "ret %08x\n", r );
1430
1431         r = IXMLDOMText_insertData(nodetext, 0, str);
1432         ok(r == S_OK, "ret %08x\n", r );
1433         SysFreeString(str);
1434
1435         r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1436         ok(r == E_INVALIDARG, "ret %08x\n", r );
1437
1438         r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1439         ok(r == E_INVALIDARG, "ret %08x\n", r );
1440
1441         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1442         ok(r == S_OK, "ret %08x\n", r );
1443
1444         r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1445         ok(r == S_OK, "ret %08x\n", r );
1446
1447         r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1448         ok(r == S_OK, "ret %08x\n", r );
1449
1450         r = IXMLDOMText_get_text(nodetext, &str);
1451         ok(r == S_OK, "ret %08x\n", r );
1452         ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1453         SysFreeString(str);
1454
1455         /* delete data */
1456         /* invalid arguments */
1457         r = IXMLDOMText_deleteData(nodetext, -1, 1);
1458         ok(r == E_INVALIDARG, "ret %08x\n", r );
1459
1460         r = IXMLDOMText_deleteData(nodetext, 0, 0);
1461         ok(r == S_OK, "ret %08x\n", r );
1462
1463         r = IXMLDOMText_deleteData(nodetext, 0, -1);
1464         ok(r == E_INVALIDARG, "ret %08x\n", r );
1465
1466         r = IXMLDOMText_get_length(nodetext, &nLength);
1467         ok(r == S_OK, "ret %08x\n", r );
1468         ok(nLength == 43, "expected 43 got %d\n", nLength);
1469
1470         r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1471         ok(r == S_OK, "ret %08x\n", r );
1472
1473         r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1474         ok(r == E_INVALIDARG, "ret %08x\n", r );
1475
1476         /* delete from start */
1477         r = IXMLDOMText_deleteData(nodetext, 0, 5);
1478         ok(r == S_OK, "ret %08x\n", r );
1479
1480         r = IXMLDOMText_get_length(nodetext, &nLength);
1481         ok(r == S_OK, "ret %08x\n", r );
1482         ok(nLength == 38, "expected 38 got %d\n", nLength);
1483
1484         r = IXMLDOMText_get_text(nodetext, &str);
1485         ok(r == S_OK, "ret %08x\n", r );
1486         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1487         SysFreeString(str);
1488
1489         /* delete from end */
1490         r = IXMLDOMText_deleteData(nodetext, 35, 3);
1491         ok(r == S_OK, "ret %08x\n", r );
1492
1493         r = IXMLDOMText_get_length(nodetext, &nLength);
1494         ok(r == S_OK, "ret %08x\n", r );
1495         ok(nLength == 35, "expected 35 got %d\n", nLength);
1496
1497         r = IXMLDOMText_get_text(nodetext, &str);
1498         ok(r == S_OK, "ret %08x\n", r );
1499         ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1500         SysFreeString(str);
1501
1502         /* delete from inside */
1503         r = IXMLDOMText_deleteData(nodetext, 1, 33);
1504         ok(r == S_OK, "ret %08x\n", r );
1505
1506         r = IXMLDOMText_get_length(nodetext, &nLength);
1507         ok(r == S_OK, "ret %08x\n", r );
1508         ok(nLength == 2, "expected 2 got %d\n", nLength);
1509
1510         r = IXMLDOMText_get_text(nodetext, &str);
1511         ok(r == S_OK, "ret %08x\n", r );
1512         ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1513         SysFreeString(str);
1514
1515         /* delete whole data ... */
1516         r = IXMLDOMText_get_length(nodetext, &nLength);
1517         ok(r == S_OK, "ret %08x\n", r );
1518
1519         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1520         ok(r == S_OK, "ret %08x\n", r );
1521         /* ... and try again with empty string */
1522         r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1523         ok(r == S_OK, "ret %08x\n", r );
1524
1525         /* test put_data */
1526         V_VT(&var) = VT_BSTR;
1527         V_BSTR(&var) = SysAllocString(szstr1);
1528         r = IXMLDOMText_put_nodeValue(nodetext, var);
1529         ok(r == S_OK, "ret %08x\n", r );
1530         VariantClear(&var);
1531
1532         r = IXMLDOMText_get_text(nodetext, &str);
1533         ok(r == S_OK, "ret %08x\n", r );
1534         ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1535         SysFreeString(str);
1536
1537         /* test put_data */
1538         V_VT(&var) = VT_I4;
1539         V_I4(&var) = 99;
1540         r = IXMLDOMText_put_nodeValue(nodetext, var);
1541         ok(r == S_OK, "ret %08x\n", r );
1542         VariantClear(&var);
1543
1544         r = IXMLDOMText_get_text(nodetext, &str);
1545         ok(r == S_OK, "ret %08x\n", r );
1546         ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1547         SysFreeString(str);
1548
1549         /* ::replaceData() */
1550         V_VT(&var) = VT_BSTR;
1551         V_BSTR(&var) = SysAllocString(szstr1);
1552         r = IXMLDOMText_put_nodeValue(nodetext, var);
1553         ok(r == S_OK, "ret %08x\n", r );
1554         VariantClear(&var);
1555
1556         r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1557         ok(r == E_INVALIDARG, "ret %08x\n", r );
1558         r = IXMLDOMText_get_text(nodetext, &str);
1559         ok(r == S_OK, "ret %08x\n", r );
1560         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1561         SysFreeString(str);
1562
1563         r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1564         ok(r == S_OK, "ret %08x\n", r );
1565         r = IXMLDOMText_get_text(nodetext, &str);
1566         ok(r == S_OK, "ret %08x\n", r );
1567         ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1568         SysFreeString(str);
1569
1570         /* NULL pointer means delete */
1571         r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1572         ok(r == S_OK, "ret %08x\n", r );
1573         r = IXMLDOMText_get_text(nodetext, &str);
1574         ok(r == S_OK, "ret %08x\n", r );
1575         ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1576         SysFreeString(str);
1577
1578         /* empty string means delete */
1579         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1580         ok(r == S_OK, "ret %08x\n", r );
1581         r = IXMLDOMText_get_text(nodetext, &str);
1582         ok(r == S_OK, "ret %08x\n", r );
1583         ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1584         SysFreeString(str);
1585
1586         /* zero count means insert */
1587         r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1588         ok(r == S_OK, "ret %08x\n", r );
1589         r = IXMLDOMText_get_text(nodetext, &str);
1590         ok(r == S_OK, "ret %08x\n", r );
1591         ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1592         SysFreeString(str);
1593
1594         r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1595         ok(r == S_OK, "ret %08x\n", r );
1596
1597         r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1598         ok(r == S_OK, "ret %08x\n", r );
1599         r = IXMLDOMText_get_text(nodetext, &str);
1600         ok(r == S_OK, "ret %08x\n", r );
1601         ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1602         SysFreeString(str);
1603
1604         /* nonempty string, count greater than its length */
1605         r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
1606         ok(r == S_OK, "ret %08x\n", r );
1607         r = IXMLDOMText_get_text(nodetext, &str);
1608         ok(r == S_OK, "ret %08x\n", r );
1609         ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1610         SysFreeString(str);
1611
1612         /* nonempty string, count less than its length */
1613         r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
1614         ok(r == S_OK, "ret %08x\n", r );
1615         r = IXMLDOMText_get_text(nodetext, &str);
1616         ok(r == S_OK, "ret %08x\n", r );
1617         ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1618         SysFreeString(str);
1619
1620         IXMLDOMText_Release( nodetext );
1621     }
1622
1623     /* test Create Comment */
1624     r = IXMLDOMDocument_createComment(doc, NULL, NULL);
1625     ok( r == E_INVALIDARG, "returns %08x\n", r );
1626     node_comment = (IXMLDOMComment*)0x1;
1627
1628     /* empty comment */
1629     r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
1630     ok( r == S_OK, "returns %08x\n", r );
1631     str = (BSTR)0x1;
1632     r = IXMLDOMComment_get_data(node_comment, &str);
1633     ok( r == S_OK, "returns %08x\n", r );
1634     ok( str && SysStringLen(str) == 0, "expected empty string data\n");
1635     IXMLDOMComment_Release(node_comment);
1636     SysFreeString(str);
1637
1638     r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
1639     ok( r == S_OK, "returns %08x\n", r );
1640     str = (BSTR)0x1;
1641     r = IXMLDOMComment_get_data(node_comment, &str);
1642     ok( r == S_OK, "returns %08x\n", r );
1643     ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
1644     IXMLDOMComment_Release(node_comment);
1645     SysFreeString(str);
1646
1647     str = SysAllocString(szComment);
1648     r = IXMLDOMDocument_createComment(doc, str, &node_comment);
1649     SysFreeString(str);
1650     ok( r == S_OK, "returns %08x\n", r );
1651     if(node_comment)
1652     {
1653         /* Last Child Checks */
1654         r = IXMLDOMComment_get_lastChild(node_comment, NULL);
1655         ok(r == E_INVALIDARG, "ret %08x\n", r );
1656
1657         nodeChild = (IXMLDOMNode*)0x1;
1658         r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
1659         ok(r == S_FALSE, "ret %08x\n", r );
1660         ok(nodeChild == NULL, "pLastChild not NULL\n");
1661
1662         /* baseName */
1663         str = (BSTR)0xdeadbeef;
1664         r = IXMLDOMComment_get_baseName(node_comment, &str);
1665         ok(r == S_FALSE, "ret %08x\n", r );
1666         ok(str == NULL, "Expected NULL\n");
1667
1668         IXMLDOMComment_Release( node_comment );
1669     }
1670
1671     /* test Create Attribute */
1672     str = SysAllocString(szAttribute);
1673     r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
1674     ok( r == E_INVALIDARG, "returns %08x\n", r );
1675     r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
1676     ok( r == S_OK, "returns %08x\n", r );
1677     IXMLDOMAttribute_Release( node_attr);
1678     SysFreeString(str);
1679
1680     /* test Processing Instruction */
1681     str = SysAllocStringLen(NULL, 0);
1682     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
1683     ok( r == E_INVALIDARG, "returns %08x\n", r );
1684     r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
1685     ok( r == E_FAIL, "returns %08x\n", r );
1686     r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
1687     ok( r == E_FAIL, "returns %08x\n", r );
1688     SysFreeString(str);
1689
1690     r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
1691     ok( r == S_OK, "returns %08x\n", r );
1692     if(nodePI)
1693     {
1694         /* Last Child Checks */
1695         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
1696         ok(r == E_INVALIDARG, "ret %08x\n", r );
1697
1698         nodeChild = (IXMLDOMNode*)0x1;
1699         r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
1700         ok(r == S_FALSE, "ret %08x\n", r );
1701         ok(nodeChild == NULL, "nodeChild not NULL\n");
1702
1703         /* test nodeName */
1704         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1705         ok(r == S_OK, "ret %08x\n", r );
1706         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1707         SysFreeString(str);
1708
1709         /* test baseName */
1710         str = (BSTR)0x1;
1711         r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
1712         ok(r == S_OK, "ret %08x\n", r );
1713         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1714         SysFreeString(str);
1715
1716         /* test Target */
1717         r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
1718         ok(r == S_OK, "ret %08x\n", r );
1719         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
1720         SysFreeString(str);
1721
1722         /* test get_data */
1723         r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
1724         ok(r == S_OK, "ret %08x\n", r );
1725         ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
1726         SysFreeString(str);
1727
1728         /* test put_data */
1729         r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
1730         ok(r == E_FAIL, "ret %08x\n", r );
1731
1732         /* test put_data */
1733         V_VT(&var) = VT_BSTR;
1734         V_BSTR(&var) = SysAllocString(szOpen);  /* Doesn't matter what the string is, cannot set an xml node. */
1735         r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
1736         ok(r == E_FAIL, "ret %08x\n", r );
1737         VariantClear(&var);
1738
1739         /* test get nodeName */
1740         r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1741         ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1742         ok(r == S_OK, "ret %08x\n", r );
1743         SysFreeString(str);
1744
1745         IXMLDOMProcessingInstruction_Release(nodePI);
1746     }
1747
1748     ref = IXMLDOMDocument_Release( doc );
1749     ok( ref == 0, "got %d\n", ref);
1750
1751     free_bstrs();
1752 }
1753
1754 static void test_persiststreaminit(void)
1755 {
1756     IXMLDOMDocument *doc;
1757     IPersistStreamInit *streaminit;
1758     ULARGE_INTEGER size;
1759     HRESULT hr;
1760
1761     doc = create_document(&IID_IXMLDOMDocument);
1762     if (!doc) return;
1763
1764     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
1765     ok(hr == S_OK, "got 0x%08x\n", hr);
1766
1767     hr = IPersistStreamInit_InitNew(streaminit);
1768     ok(hr == S_OK, "got 0x%08x\n", hr);
1769
1770     hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
1771     ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
1772
1773     IXMLDOMDocument_Release(doc);
1774 }
1775
1776 static void test_domnode( void )
1777 {
1778     HRESULT r;
1779     IXMLDOMDocument *doc, *owner = NULL;
1780     IXMLDOMElement *element = NULL;
1781     IXMLDOMNamedNodeMap *map = NULL;
1782     IXMLDOMNode *node = NULL, *next = NULL;
1783     IXMLDOMNodeList *list = NULL;
1784     IXMLDOMAttribute *attr = NULL;
1785     DOMNodeType type = NODE_INVALID;
1786     VARIANT_BOOL b;
1787     BSTR str;
1788     VARIANT var;
1789     LONG count;
1790
1791     doc = create_document(&IID_IXMLDOMDocument);
1792     if (!doc) return;
1793
1794     b = FALSE;
1795     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1796     ok( r == S_OK, "loadXML failed\n");
1797     ok( b == VARIANT_TRUE, "failed to load XML string\n");
1798
1799     EXPECT_CHILDREN(doc);
1800
1801     r = IXMLDOMDocument_get_documentElement( doc, &element );
1802     ok( r == S_OK, "should be a document element\n");
1803     ok( element != NULL, "should be an element\n");
1804
1805     VariantInit(&var);
1806     ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
1807
1808     r = IXMLDOMDocument_get_nodeValue( doc, NULL );
1809     ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
1810
1811     r = IXMLDOMDocument_get_nodeValue( doc, &var );
1812     ok( r == S_FALSE, "nextNode returned wrong code\n");
1813     ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
1814     ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
1815
1816     if (element)
1817     {
1818         owner = NULL;
1819         r = IXMLDOMElement_get_ownerDocument( element, &owner );
1820         ok( r == S_OK, "get_ownerDocument return code\n");
1821         ok( owner != doc, "get_ownerDocument return\n");
1822         IXMLDOMDocument_Release(owner);
1823
1824         type = NODE_INVALID;
1825         r = IXMLDOMElement_get_nodeType( element, &type);
1826         ok( r == S_OK, "got %08x\n", r);
1827         ok( type == NODE_ELEMENT, "node not an element\n");
1828
1829         str = NULL;
1830         r = IXMLDOMElement_get_baseName( element, &str );
1831         ok( r == S_OK, "get_baseName returned wrong code\n");
1832         ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
1833         SysFreeString(str);
1834
1835         /* check if nodename is correct */
1836         r = IXMLDOMElement_get_nodeName( element, NULL );
1837         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1838
1839         /* content doesn't matter here */
1840         str = NULL;
1841         r = IXMLDOMElement_get_nodeName( element, &str );
1842         ok ( r == S_OK, "get_nodeName wrong code\n");
1843         ok ( str != NULL, "str is null\n");
1844         ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
1845         SysFreeString( str );
1846
1847         str = SysAllocString( nonexistent_fileW );
1848         V_VT(&var) = VT_I4;
1849         V_I4(&var) = 0x1234;
1850         r = IXMLDOMElement_getAttribute( element, str, &var );
1851         ok( r == E_FAIL, "getAttribute ret %08x\n", r );
1852         ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
1853         VariantClear(&var);
1854
1855         str = SysAllocString( szdl );   
1856         V_VT(&var) = VT_I4;
1857         V_I4(&var) = 0x1234;
1858         r = IXMLDOMElement_getAttribute( element, str, &var );
1859         ok( r == S_OK, "getAttribute ret %08x\n", r );
1860         ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
1861         ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
1862         VariantClear( &var );
1863
1864         r = IXMLDOMElement_getAttribute( element, NULL, &var );
1865         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1866
1867         r = IXMLDOMElement_getAttribute( element, str, NULL );
1868         ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1869
1870         attr = NULL;
1871         r = IXMLDOMElement_getAttributeNode( element, str, &attr);
1872         ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
1873         ok( attr != NULL, "getAttributeNode returned NULL\n" );
1874         if (attr)
1875         {
1876             r = IXMLDOMAttribute_get_parentNode( attr, NULL );
1877             ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
1878
1879             /* attribute doesn't have a parent in msxml interpretation */
1880             node = (IXMLDOMNode*)0xdeadbeef;
1881             r = IXMLDOMAttribute_get_parentNode( attr, &node );
1882             ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
1883             ok( node == NULL, "Expected NULL, got %p\n", node );
1884
1885             IXMLDOMAttribute_Release(attr);
1886         }
1887
1888         SysFreeString( str );
1889
1890         r = IXMLDOMElement_get_attributes( element, &map );
1891         ok( r == S_OK, "get_attributes returned wrong code\n");
1892         ok( map != NULL, "should be attributes\n");
1893
1894         EXPECT_CHILDREN(element);
1895     }
1896     else
1897         ok( FALSE, "no element\n");
1898
1899     if (map)
1900     {
1901         str = SysAllocString( szdl );
1902         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
1903         ok( r == S_OK, "getNamedItem returned wrong code\n");
1904         ok( node != NULL, "should be attributes\n");
1905         IXMLDOMNode_Release(node);
1906         SysFreeString( str );
1907
1908         str = SysAllocString( szdl );
1909         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
1910         ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
1911         SysFreeString( str );
1912
1913         /* something that isn't in complete4A */
1914         str = SysAllocString( szOpen );
1915         node = (IXMLDOMNode *) 1;
1916         r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
1917         ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
1918         ok( node == NULL, "getNamedItem should have returned NULL\n");
1919         SysFreeString( str );
1920
1921         /* test indexed access of attributes */
1922         r = IXMLDOMNamedNodeMap_get_length( map, NULL );
1923         ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
1924
1925         r = IXMLDOMNamedNodeMap_get_length( map, &count );
1926         ok ( r == S_OK, "get_length wrong code\n");
1927         ok ( count == 1, "get_length != 1\n");
1928
1929         node = NULL;
1930         r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
1931         ok ( r == S_FALSE, "get_item (-1) wrong code\n");
1932         ok ( node == NULL, "there is no node\n");
1933
1934         node = NULL;
1935         r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
1936         ok ( r == S_FALSE, "get_item (1) wrong code\n");
1937         ok ( node == NULL, "there is no attribute\n");
1938
1939         node = NULL;
1940         r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
1941         ok ( r == S_OK, "get_item (0) wrong code\n");
1942         ok ( node != NULL, "should be attribute\n");
1943
1944         r = IXMLDOMNode_get_nodeName( node, NULL );
1945         ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1946
1947         /* content doesn't matter here */
1948         str = NULL;
1949         r = IXMLDOMNode_get_nodeName( node, &str );
1950         ok ( r == S_OK, "get_nodeName wrong code\n");
1951         ok ( str != NULL, "str is null\n");
1952         ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
1953         SysFreeString( str );
1954         IXMLDOMNode_Release( node );
1955
1956         /* test sequential access of attributes */
1957         node = NULL;
1958         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
1959         ok ( r == S_OK, "nextNode (first time) wrong code\n");
1960         ok ( node != NULL, "nextNode, should be attribute\n");
1961         IXMLDOMNode_Release( node );
1962
1963         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
1964         ok ( r != S_OK, "nextNode (second time) wrong code\n");
1965         ok ( node == NULL, "nextNode, there is no attribute\n");
1966
1967         r = IXMLDOMNamedNodeMap_reset( map );
1968         ok ( r == S_OK, "reset should return S_OK\n");
1969
1970         r = IXMLDOMNamedNodeMap_nextNode( map, &node );
1971         ok ( r == S_OK, "nextNode (third time) wrong code\n");
1972         ok ( node != NULL, "nextNode, should be attribute\n");
1973     }
1974     else
1975         ok( FALSE, "no map\n");
1976
1977     if (node)
1978     {
1979         type = NODE_INVALID;
1980         r = IXMLDOMNode_get_nodeType( node, &type);
1981         ok( r == S_OK, "getNamedItem returned wrong code\n");
1982         ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
1983
1984         str = NULL;
1985         r = IXMLDOMNode_get_baseName( node, NULL );
1986         ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
1987
1988         str = NULL;
1989         r = IXMLDOMNode_get_baseName( node, &str );
1990         ok( r == S_OK, "get_baseName returned wrong code\n");
1991         ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
1992         SysFreeString( str );
1993
1994         r = IXMLDOMNode_get_childNodes( node, NULL );
1995         ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
1996
1997         r = IXMLDOMNode_get_childNodes( node, &list );
1998         ok( r == S_OK, "get_childNodes returned wrong code\n");
1999
2000         if (list)
2001         {
2002             r = IXMLDOMNodeList_nextNode( list, &next );
2003             ok( r == S_OK, "nextNode returned wrong code\n");
2004         }
2005         else
2006             ok( FALSE, "no childlist\n");
2007
2008         if (next)
2009         {
2010             EXPECT_NO_CHILDREN(next);
2011
2012             type = NODE_INVALID;
2013             r = IXMLDOMNode_get_nodeType( next, &type);
2014             ok( r == S_OK, "getNamedItem returned wrong code\n");
2015             ok( type == NODE_TEXT, "node not text\n");
2016
2017             str = (BSTR) 1;
2018             r = IXMLDOMNode_get_baseName( next, &str );
2019             ok( r == S_FALSE, "get_baseName returned wrong code\n");
2020             ok( str == NULL, "basename was wrong\n");
2021             SysFreeString(str);
2022         }
2023         else
2024             ok( FALSE, "no next\n");
2025
2026         if (next)
2027             IXMLDOMNode_Release( next );
2028         next = NULL;
2029         if (list)
2030             IXMLDOMNodeList_Release( list );
2031         list = NULL;
2032         if (node)
2033             IXMLDOMNode_Release( node );
2034     }
2035     else
2036         ok( FALSE, "no node\n");
2037     node = NULL;
2038
2039     if (map)
2040         IXMLDOMNamedNodeMap_Release( map );
2041
2042     /* now traverse the tree from the root element */
2043     if (element)
2044     {
2045         r = IXMLDOMElement_get_childNodes( element, &list );
2046         ok( r == S_OK, "get_childNodes returned wrong code\n");
2047
2048         /* using get_item for child list doesn't advance the position */
2049         ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2050         expect_node(node, "E2.E2.D1");
2051         IXMLDOMNode_Release(node);
2052         ole_check(IXMLDOMNodeList_nextNode(list, &node));
2053         expect_node(node, "E1.E2.D1");
2054         IXMLDOMNode_Release(node);
2055         ole_check(IXMLDOMNodeList_reset(list));
2056
2057         IXMLDOMNodeList_AddRef(list);
2058         expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2059         ole_check(IXMLDOMNodeList_reset(list));
2060
2061         node = (void*)0xdeadbeef;
2062         str = SysAllocString(szdl);
2063         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2064         SysFreeString(str);
2065         ok( r == S_FALSE, "ret %08x\n", r );
2066         ok( node == NULL, "node %p\n", node );
2067
2068         str = SysAllocString(szbs);
2069         r = IXMLDOMElement_selectSingleNode( element, str, &node );
2070         SysFreeString(str);
2071         ok( r == S_OK, "ret %08x\n", r );
2072         r = IXMLDOMNode_Release( node );
2073         ok( r == 0, "ret %08x\n", r );
2074     }
2075     else
2076         ok( FALSE, "no element\n");
2077
2078     if (list)
2079     {
2080         r = IXMLDOMNodeList_get_item(list, 0, NULL);
2081         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2082
2083         r = IXMLDOMNodeList_get_length(list, NULL);
2084         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2085
2086         r = IXMLDOMNodeList_get_length( list, &count );
2087         ok( r == S_OK, "get_length returns %08x\n", r );
2088         ok( count == 4, "get_length got %d\n", count );
2089
2090         r = IXMLDOMNodeList_nextNode(list, NULL);
2091         ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2092
2093         r = IXMLDOMNodeList_nextNode( list, &node );
2094         ok( r == S_OK, "nextNode returned wrong code\n");
2095     }
2096     else
2097         ok( FALSE, "no list\n");
2098
2099     if (node)
2100     {
2101         type = NODE_INVALID;
2102         r = IXMLDOMNode_get_nodeType( node, &type);
2103         ok( r == S_OK, "getNamedItem returned wrong code\n");
2104         ok( type == NODE_ELEMENT, "node not text\n");
2105
2106         r = IXMLDOMNode_hasChildNodes( node, NULL );
2107         ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2108
2109         EXPECT_CHILDREN(node);
2110
2111         str = NULL;
2112         r = IXMLDOMNode_get_baseName( node, &str );
2113         ok( r == S_OK, "get_baseName returned wrong code\n");
2114         ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2115         SysFreeString(str);
2116     }
2117     else
2118         ok( FALSE, "no node\n");
2119
2120     if (node)
2121         IXMLDOMNode_Release( node );
2122     if (list)
2123         IXMLDOMNodeList_Release( list );
2124     if (element)
2125         IXMLDOMElement_Release( element );
2126
2127     b = FALSE;
2128     str = SysAllocString( szComplete5 );
2129     r = IXMLDOMDocument_loadXML( doc, str, &b );
2130     ok( r == S_OK, "loadXML failed\n");
2131     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2132     SysFreeString( str );
2133
2134     EXPECT_CHILDREN(doc);
2135
2136     r = IXMLDOMDocument_get_documentElement( doc, &element );
2137     ok( r == S_OK, "should be a document element\n");
2138     ok( element != NULL, "should be an element\n");
2139
2140     if (element)
2141     {
2142         static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2143         BSTR tag = NULL;
2144
2145         /* check if the tag is correct */
2146         r = IXMLDOMElement_get_tagName( element, &tag );
2147         ok( r == S_OK, "couldn't get tag name\n");
2148         ok( tag != NULL, "tag was null\n");
2149         ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2150         SysFreeString( tag );
2151     }
2152
2153     if (element)
2154         IXMLDOMElement_Release( element );
2155     ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2156
2157     free_bstrs();
2158 }
2159
2160 typedef struct {
2161     DOMNodeType type;
2162     REFIID iid;
2163 } refcount_test_t;
2164
2165 static const refcount_test_t refcount_test[] = {
2166     { NODE_ELEMENT,                &IID_IXMLDOMElement },
2167     { NODE_ATTRIBUTE,              &IID_IXMLDOMAttribute },
2168     { NODE_TEXT,                   &IID_IXMLDOMText },
2169     { NODE_CDATA_SECTION,          &IID_IXMLDOMCDATASection },
2170     { NODE_ENTITY_REFERENCE,       &IID_IXMLDOMEntityReference },
2171     { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2172     { NODE_COMMENT,                &IID_IXMLDOMComment },
2173     { NODE_DOCUMENT_FRAGMENT,      &IID_IXMLDOMDocumentFragment },
2174     { NODE_INVALID,                &IID_NULL }
2175 };
2176
2177 static void test_refs(void)
2178 {
2179     IXMLDOMImplementation *impl, *impl2;
2180     IXMLDOMElement *element, *elem2;
2181     IXMLDOMNodeList *node_list = NULL;
2182     IXMLDOMNode *node, *node2, *node3;
2183     const refcount_test_t *ptr;
2184     IXMLDOMDocument *doc;
2185     IUnknown *unk, *unk2;
2186     VARIANT_BOOL b;
2187     HRESULT hr;
2188     LONG ref;
2189
2190     doc = create_document(&IID_IXMLDOMDocument);
2191     if (!doc) return;
2192
2193     ptr = refcount_test;
2194     while (ptr->type != NODE_INVALID)
2195     {
2196         IUnknown *node_typed, *node_typed2;
2197         IDispatchEx *dispex, *dispex2;
2198         IDispatch *disp, *disp2;
2199         VARIANT type;
2200
2201         V_VT(&type) = VT_I1;
2202         V_I1(&type) = ptr->type;
2203
2204         EXPECT_REF(doc, 1);
2205         hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2206         EXPECT_HR(hr, S_OK);
2207         EXPECT_REF(doc, 1);
2208         EXPECT_REF(node, 1);
2209
2210         /* try IDispatch and IUnknown from IXMLDOMNode */
2211         hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2212         EXPECT_HR(hr, S_OK);
2213         EXPECT_REF(unk, 2);
2214 todo_wine {
2215         EXPECT_REF(node, 1);
2216         ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2217 }
2218         EXPECT_REF(unk, 2);
2219         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2220         EXPECT_HR(hr, S_OK);
2221         todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2222         EXPECT_REF(unk, 3);
2223         todo_wine EXPECT_REF(disp, 1);
2224
2225         EXPECT_REF(unk, 3);
2226         hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2227         EXPECT_HR(hr, S_OK);
2228         todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2229         EXPECT_REF(unk, 4);
2230         todo_wine EXPECT_REF(disp2, 1);
2231
2232         IDispatch_Release(disp);
2233         IDispatch_Release(disp2);
2234
2235         /* get IXMLDOMNode from this IUnknown */
2236         EXPECT_REF(unk, 2);
2237         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2238         EXPECT_HR(hr, S_OK);
2239         todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2240         EXPECT_REF(unk, 3);
2241         todo_wine EXPECT_REF(node2, 1);
2242
2243         EXPECT_REF(unk, 3);
2244         hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2245         EXPECT_HR(hr, S_OK);
2246         todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2247         EXPECT_REF(unk, 4);
2248         todo_wine EXPECT_REF(node3, 1);
2249
2250         IXMLDOMNode_Release(node2);
2251         IXMLDOMNode_Release(node3);
2252
2253         /* try IDispatchEx from IUnknown */
2254         EXPECT_REF(unk, 2);
2255         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2256         EXPECT_HR(hr, S_OK);
2257         ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2258         EXPECT_REF(unk, 3);
2259         todo_wine EXPECT_REF(dispex, 1);
2260
2261         EXPECT_REF(unk, 3);
2262         hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2263         EXPECT_HR(hr, S_OK);
2264         todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2265         EXPECT_REF(unk, 4);
2266         todo_wine EXPECT_REF(dispex2, 1);
2267
2268         IDispatchEx_Release(dispex);
2269         IDispatchEx_Release(dispex2);
2270
2271         /* try corresponding IXMLDOM* */
2272         EXPECT_REF(unk, 2);
2273         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2274         EXPECT_HR(hr, S_OK);
2275         EXPECT_REF(unk, 3);
2276         hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2277         EXPECT_HR(hr, S_OK);
2278         EXPECT_REF(unk, 4);
2279         todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2280         IUnknown_Release(node_typed);
2281         IUnknown_Release(node_typed2);
2282
2283         /* try invalid IXMLDOM* */
2284         hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2285         EXPECT_HR(hr, E_NOINTERFACE);
2286
2287         IUnknown_Release(unk);
2288
2289         EXPECT_REF(node, 1);
2290         hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2291         EXPECT_HR(hr, S_OK);
2292         EXPECT_REF(node, 2);
2293         ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2294
2295         EXPECT_REF(node, 2);
2296         hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2297         EXPECT_HR(hr, S_OK);
2298         EXPECT_REF(node, 3);
2299 todo_wine {
2300         EXPECT_REF(node_typed, 2);
2301         ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2302 }
2303         IUnknown_Release(node_typed);
2304
2305         IXMLDOMNode_Release(node2);
2306         IXMLDOMNode_Release(node);
2307
2308         ptr++;
2309     }
2310
2311     EXPECT_REF(doc, 1);
2312     ref = IXMLDOMDocument_Release(doc);
2313     ok( ref == 0, "ref %d\n", ref);
2314
2315     /* check IUnknown after releasing DOM iface */
2316     doc = create_document(&IID_IXMLDOMDocument);
2317     EXPECT_REF(doc, 1);
2318     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2319     EXPECT_HR(hr, S_OK);
2320 todo_wine {
2321     EXPECT_REF(unk, 3);
2322     EXPECT_REF(doc, 1);
2323 }
2324     IXMLDOMDocument_Release(doc);
2325     EXPECT_REF(unk, 1);
2326     IUnknown_Release(unk);
2327
2328     doc = create_document(&IID_IXMLDOMDocument);
2329     if (!doc) return;
2330
2331     EXPECT_REF(doc, 1);
2332     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2333     EXPECT_HR(hr, S_OK);
2334 todo_wine {
2335     EXPECT_REF(unk, 3);
2336     EXPECT_REF(doc, 1);
2337 }
2338     IUnknown_Release(unk);
2339
2340     /* IXMLDOMImplementation */
2341     EXPECT_REF(doc, 1);
2342     hr = IXMLDOMDocument_get_implementation(doc, &impl);
2343     EXPECT_HR(hr, S_OK);
2344     EXPECT_REF(doc, 1);
2345     EXPECT_REF(impl, 1);
2346     hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2347     EXPECT_HR(hr, S_OK);
2348     EXPECT_REF(doc, 1);
2349     EXPECT_REF(impl2, 1);
2350     ok(impl != impl2, "got %p, %p\n", impl, impl2);
2351     IXMLDOMImplementation_Release(impl);
2352     IXMLDOMImplementation_Release(impl2);
2353
2354     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2355     EXPECT_HR(hr, S_OK);
2356     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2357
2358     EXPECT_REF(doc, 1);
2359     IXMLDOMDocument_AddRef( doc );
2360     EXPECT_REF(doc, 2);
2361     IXMLDOMDocument_AddRef( doc );
2362     EXPECT_REF(doc, 3);
2363
2364     IXMLDOMDocument_Release( doc );
2365     IXMLDOMDocument_Release( doc );
2366
2367     EXPECT_REF(doc, 1);
2368     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2369     EXPECT_HR(hr, S_OK);
2370 todo_wine {
2371     EXPECT_REF(unk, 3);
2372     EXPECT_REF(doc, 1);
2373 }
2374     hr = IXMLDOMDocument_get_documentElement(doc, &element);
2375     EXPECT_HR(hr, S_OK);
2376 todo_wine {
2377     EXPECT_REF(doc, 1);
2378     EXPECT_REF(element, 2);
2379 }
2380     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2381     EXPECT_HR(hr, S_OK);
2382
2383 todo_wine {
2384     EXPECT_REF(doc, 1);
2385     EXPECT_REF(element, 2);
2386     EXPECT_REF(elem2, 2);
2387 }
2388     IXMLDOMElement_AddRef(element);
2389     todo_wine EXPECT_REF(element, 3);
2390     IXMLDOMElement_Release(element);
2391
2392     /* get IUnknown from a node doesn't touch node instance refcount */
2393     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2394     EXPECT_HR(hr, S_OK);
2395     EXPECT_REF(element, 2);
2396 todo_wine {
2397     EXPECT_REF(unk, 4);
2398     EXPECT_REF(elem2, 2);
2399 }
2400     hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2401     EXPECT_HR(hr, S_OK);
2402 todo_wine {
2403     EXPECT_REF(unk, 5);
2404     EXPECT_REF(unk2, 5);
2405 }
2406     EXPECT_REF(element, 2);
2407     EXPECT_REF(elem2, 2);
2408
2409     todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2410
2411     IUnknown_Release(unk);
2412     IUnknown_Release(unk2);
2413
2414     /* IUnknown refcount is not affected by node refcount */
2415     todo_wine EXPECT_REF(unk2, 3);
2416     IXMLDOMElement_AddRef(elem2);
2417     todo_wine EXPECT_REF(unk2, 3);
2418     IXMLDOMElement_Release(elem2);
2419
2420     IXMLDOMElement_Release(elem2);
2421     todo_wine EXPECT_REF(unk2, 2);
2422
2423     hr = IXMLDOMElement_get_childNodes( element, &node_list );
2424     EXPECT_HR(hr, S_OK);
2425
2426     todo_wine EXPECT_REF(element, 2);
2427     EXPECT_REF(node_list, 1);
2428
2429     hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2430     EXPECT_HR(hr, S_OK);
2431     EXPECT_REF(node_list, 1);
2432     EXPECT_REF(node, 1);
2433
2434     hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2435     EXPECT_HR(hr, S_OK);
2436     EXPECT_REF(node_list, 1);
2437     EXPECT_REF(node2, 1);
2438
2439     ref = IXMLDOMNode_Release( node );
2440     ok( ref == 0, "ref %d\n", ref );
2441     ref = IXMLDOMNode_Release( node2 );
2442     ok( ref == 0, "ref %d\n", ref );
2443
2444     ref = IXMLDOMNodeList_Release( node_list );
2445     ok( ref == 0, "ref %d\n", ref );
2446
2447     ok( node != node2, "node %p node2 %p\n", node, node2 );
2448
2449     ref = IXMLDOMDocument_Release( doc );
2450     todo_wine ok( ref == 0, "ref %d\n", ref );
2451
2452     todo_wine EXPECT_REF(element, 2);
2453
2454     /* IUnknown must be unique however we obtain it */
2455     hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2456     EXPECT_HR(hr, S_OK);
2457     EXPECT_REF(element, 2);
2458     hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2459     EXPECT_HR(hr, S_OK);
2460     todo_wine EXPECT_REF(element, 2);
2461     hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2462     EXPECT_HR(hr, S_OK);
2463     todo_wine EXPECT_REF(element, 2);
2464     ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2465     todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2466
2467     IUnknown_Release( unk2 );
2468     IUnknown_Release( unk );
2469     IXMLDOMNode_Release( node );
2470     todo_wine EXPECT_REF(element, 2);
2471
2472     IXMLDOMElement_Release( element );
2473
2474     free_bstrs();
2475 }
2476
2477 static void test_create(void)
2478 {
2479     static const WCHAR szOne[] = {'1',0};
2480     static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2481     HRESULT r;
2482     VARIANT var;
2483     BSTR str, name;
2484     IXMLDOMDocument *doc;
2485     IXMLDOMElement *element;
2486     IXMLDOMComment *comment;
2487     IXMLDOMText *text;
2488     IXMLDOMCDATASection *cdata;
2489     IXMLDOMNode *root, *node, *child;
2490     IXMLDOMNamedNodeMap *attr_map;
2491     IUnknown *unk;
2492     LONG ref;
2493     LONG num;
2494
2495     doc = create_document(&IID_IXMLDOMDocument);
2496     if (!doc) return;
2497
2498     EXPECT_REF(doc, 1);
2499
2500     /* types not supported for creation */
2501     V_VT(&var) = VT_I1;
2502     V_I1(&var) = NODE_DOCUMENT;
2503     node = (IXMLDOMNode*)0x1;
2504     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2505     ok( r == E_INVALIDARG, "returns %08x\n", r );
2506     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2507
2508     V_VT(&var) = VT_I1;
2509     V_I1(&var) = NODE_DOCUMENT_TYPE;
2510     node = (IXMLDOMNode*)0x1;
2511     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2512     ok( r == E_INVALIDARG, "returns %08x\n", r );
2513     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2514
2515     V_VT(&var) = VT_I1;
2516     V_I1(&var) = NODE_ENTITY;
2517     node = (IXMLDOMNode*)0x1;
2518     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2519     ok( r == E_INVALIDARG, "returns %08x\n", r );
2520     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2521
2522     V_VT(&var) = VT_I1;
2523     V_I1(&var) = NODE_NOTATION;
2524     node = (IXMLDOMNode*)0x1;
2525     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2526     ok( r == E_INVALIDARG, "returns %08x\n", r );
2527     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2528
2529     /* NODE_COMMENT */
2530     V_VT(&var) = VT_I1;
2531     V_I1(&var) = NODE_COMMENT;
2532     node = NULL;
2533     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2534     ok( r == S_OK, "returns %08x\n", r );
2535     ok( node != NULL, "\n");
2536
2537     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2538     ok( r == S_OK, "returns %08x\n", r );
2539     IXMLDOMNode_Release(node);
2540
2541     str = NULL;
2542     r = IXMLDOMComment_get_data(comment, &str);
2543     ok( r == S_OK, "returns %08x\n", r );
2544     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2545     IXMLDOMComment_Release(comment);
2546     SysFreeString(str);
2547
2548     node = (IXMLDOMNode*)0x1;
2549     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2550     ok( r == S_OK, "returns %08x\n", r );
2551
2552     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2553     ok( r == S_OK, "returns %08x\n", r );
2554     IXMLDOMNode_Release(node);
2555
2556     str = NULL;
2557     r = IXMLDOMComment_get_data(comment, &str);
2558     ok( r == S_OK, "returns %08x\n", r );
2559     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2560     IXMLDOMComment_Release(comment);
2561     SysFreeString(str);
2562
2563     node = (IXMLDOMNode*)0x1;
2564     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2565     ok( r == S_OK, "returns %08x\n", r );
2566
2567     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2568     ok( r == S_OK, "returns %08x\n", r );
2569     IXMLDOMNode_Release(node);
2570
2571     str = NULL;
2572     r = IXMLDOMComment_get_data(comment, &str);
2573     ok( r == S_OK, "returns %08x\n", r );
2574     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2575     IXMLDOMComment_Release(comment);
2576     SysFreeString(str);
2577
2578     /* NODE_TEXT */
2579     V_VT(&var) = VT_I1;
2580     V_I1(&var) = NODE_TEXT;
2581     node = NULL;
2582     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2583     ok( r == S_OK, "returns %08x\n", r );
2584     ok( node != NULL, "\n");
2585
2586     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2587     ok( r == S_OK, "returns %08x\n", r );
2588     IXMLDOMNode_Release(node);
2589
2590     str = NULL;
2591     r = IXMLDOMText_get_data(text, &str);
2592     ok( r == S_OK, "returns %08x\n", r );
2593     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2594     IXMLDOMText_Release(text);
2595     SysFreeString(str);
2596
2597     node = (IXMLDOMNode*)0x1;
2598     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2599     ok( r == S_OK, "returns %08x\n", r );
2600
2601     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2602     ok( r == S_OK, "returns %08x\n", r );
2603     IXMLDOMNode_Release(node);
2604
2605     str = NULL;
2606     r = IXMLDOMText_get_data(text, &str);
2607     ok( r == S_OK, "returns %08x\n", r );
2608     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2609     IXMLDOMText_Release(text);
2610     SysFreeString(str);
2611
2612     node = (IXMLDOMNode*)0x1;
2613     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2614     ok( r == S_OK, "returns %08x\n", r );
2615
2616     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2617     ok( r == S_OK, "returns %08x\n", r );
2618     IXMLDOMNode_Release(node);
2619
2620     str = NULL;
2621     r = IXMLDOMText_get_data(text, &str);
2622     ok( r == S_OK, "returns %08x\n", r );
2623     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2624     IXMLDOMText_Release(text);
2625     SysFreeString(str);
2626
2627     /* NODE_CDATA_SECTION */
2628     V_VT(&var) = VT_I1;
2629     V_I1(&var) = NODE_CDATA_SECTION;
2630     node = NULL;
2631     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2632     ok( r == S_OK, "returns %08x\n", r );
2633     ok( node != NULL, "\n");
2634
2635     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
2636     ok( r == S_OK, "returns %08x\n", r );
2637     IXMLDOMNode_Release(node);
2638
2639     str = NULL;
2640     r = IXMLDOMCDATASection_get_data(cdata, &str);
2641     ok( r == S_OK, "returns %08x\n", r );
2642     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2643     IXMLDOMCDATASection_Release(cdata);
2644     SysFreeString(str);
2645
2646     node = (IXMLDOMNode*)0x1;
2647     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2648     ok( r == S_OK, "returns %08x\n", r );
2649
2650     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
2651     ok( r == S_OK, "returns %08x\n", r );
2652     IXMLDOMNode_Release(node);
2653
2654     str = NULL;
2655     r = IXMLDOMCDATASection_get_data(cdata, &str);
2656     ok( r == S_OK, "returns %08x\n", r );
2657     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2658     IXMLDOMCDATASection_Release(cdata);
2659     SysFreeString(str);
2660
2661     node = (IXMLDOMNode*)0x1;
2662     r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2663     ok( r == S_OK, "returns %08x\n", r );
2664
2665     r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
2666     ok( r == S_OK, "returns %08x\n", r );
2667     IXMLDOMNode_Release(node);
2668
2669     str = NULL;
2670     r = IXMLDOMCDATASection_get_data(cdata, &str);
2671     ok( r == S_OK, "returns %08x\n", r );
2672     ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2673     IXMLDOMCDATASection_Release(cdata);
2674     SysFreeString(str);
2675
2676     /* NODE_ATTRIBUTE */
2677     V_VT(&var) = VT_I1;
2678     V_I1(&var) = NODE_ATTRIBUTE;
2679     node = (IXMLDOMNode*)0x1;
2680     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2681     ok( r == E_FAIL, "returns %08x\n", r );
2682     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2683
2684     V_VT(&var) = VT_I1;
2685     V_I1(&var) = NODE_ATTRIBUTE;
2686     node = (IXMLDOMNode*)0x1;
2687     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2688     ok( r == E_FAIL, "returns %08x\n", r );
2689     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2690
2691     V_VT(&var) = VT_I1;
2692     V_I1(&var) = NODE_ATTRIBUTE;
2693     str = SysAllocString( szlc );
2694     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2695     ok( r == S_OK, "returns %08x\n", r );
2696     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
2697     SysFreeString(str);
2698
2699     /* a name is required for attribute, try a BSTR with first null wchar */
2700     V_VT(&var) = VT_I1;
2701     V_I1(&var) = NODE_ATTRIBUTE;
2702     str = SysAllocString( szstr1 );
2703     str[0] = 0;
2704     node = (IXMLDOMNode*)0x1;
2705     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2706     ok( r == E_FAIL, "returns %08x\n", r );
2707     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2708     SysFreeString(str);
2709
2710     /* NODE_PROCESSING_INSTRUCTION */
2711     V_VT(&var) = VT_I1;
2712     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
2713     node = (IXMLDOMNode*)0x1;
2714     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2715     ok( r == E_FAIL, "returns %08x\n", r );
2716     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2717
2718     V_VT(&var) = VT_I1;
2719     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
2720     node = (IXMLDOMNode*)0x1;
2721     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2722     ok( r == E_FAIL, "returns %08x\n", r );
2723     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2724
2725     V_VT(&var) = VT_I1;
2726     V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
2727     r = IXMLDOMDocument_createNode( doc, var, _bstr_("pi"), NULL, NULL );
2728     ok( r == E_INVALIDARG, "returns %08x\n", r );
2729
2730     /* NODE_ENTITY_REFERENCE */
2731     V_VT(&var) = VT_I1;
2732     V_I1(&var) = NODE_ENTITY_REFERENCE;
2733     node = (IXMLDOMNode*)0x1;
2734     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2735     ok( r == E_FAIL, "returns %08x\n", r );
2736     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2737
2738     V_VT(&var) = VT_I1;
2739     V_I1(&var) = NODE_ENTITY_REFERENCE;
2740     node = (IXMLDOMNode*)0x1;
2741     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2742     ok( r == E_FAIL, "returns %08x\n", r );
2743     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2744
2745     /* NODE_ELEMENT */
2746     V_VT(&var) = VT_I1;
2747     V_I1(&var) = NODE_ELEMENT;
2748     node = (IXMLDOMNode*)0x1;
2749     r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2750     ok( r == E_FAIL, "returns %08x\n", r );
2751     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2752
2753     V_VT(&var) = VT_I1;
2754     V_I1(&var) = NODE_ELEMENT;
2755     node = (IXMLDOMNode*)0x1;
2756     r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2757     ok( r == E_FAIL, "returns %08x\n", r );
2758     ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2759
2760     V_VT(&var) = VT_I1;
2761     V_I1(&var) = NODE_ELEMENT;
2762     str = SysAllocString( szlc );
2763     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2764     ok( r == S_OK, "returns %08x\n", r );
2765     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
2766
2767     V_VT(&var) = VT_I1;
2768     V_I1(&var) = NODE_ELEMENT;
2769     r = IXMLDOMDocument_createNode( doc, var, str, NULL, NULL );
2770     ok( r == E_INVALIDARG, "returns %08x\n", r );
2771
2772     V_VT(&var) = VT_R4;
2773     V_R4(&var) = NODE_ELEMENT;
2774     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2775     ok( r == S_OK, "returns %08x\n", r );
2776     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
2777
2778     V_VT(&var) = VT_BSTR;
2779     V_BSTR(&var) = SysAllocString( szOne );
2780     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2781     ok( r == S_OK, "returns %08x\n", r );
2782     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
2783     VariantClear(&var);
2784
2785     V_VT(&var) = VT_BSTR;
2786     V_BSTR(&var) = SysAllocString( szOneGarbage );
2787     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2788     ok( r == E_INVALIDARG, "returns %08x\n", r );
2789     if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
2790     VariantClear(&var);
2791
2792     V_VT(&var) = VT_I4;
2793     V_I4(&var) = NODE_ELEMENT;
2794     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2795     ok( r == S_OK, "returns %08x\n", r );
2796
2797     EXPECT_REF(doc, 1);
2798     r = IXMLDOMDocument_appendChild( doc, node, &root );
2799     ok( r == S_OK, "returns %08x\n", r );
2800     ok( node == root, "%p %p\n", node, root );
2801     EXPECT_REF(doc, 1);
2802
2803     EXPECT_REF(node, 2);
2804
2805     ref = IXMLDOMNode_Release( node );
2806     ok(ref == 1, "ref %d\n", ref);
2807     SysFreeString( str );
2808
2809     V_VT(&var) = VT_I4;
2810     V_I4(&var) = NODE_ELEMENT;
2811     str = SysAllocString( szbs );
2812     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2813     ok( r == S_OK, "returns %08x\n", r );
2814     SysFreeString( str );
2815
2816     EXPECT_REF(node, 1);
2817
2818     r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk );
2819     ok( r == S_OK, "returns %08x\n", r );
2820
2821     EXPECT_REF(unk, 2);
2822
2823     V_VT(&var) = VT_EMPTY;
2824     child = NULL;
2825     r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
2826     ok( r == S_OK, "returns %08x\n", r );
2827     ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
2828
2829     todo_wine EXPECT_REF(unk, 4);
2830
2831     IXMLDOMNode_Release( child );
2832     IUnknown_Release( unk );
2833
2834     V_VT(&var) = VT_NULL;
2835     V_DISPATCH(&var) = (IDispatch*)node;
2836     r = IXMLDOMNode_insertBefore( root, node, var, &child );
2837     ok( r == S_OK, "returns %08x\n", r );
2838     ok( node == child, "%p %p\n", node, child );
2839     IXMLDOMNode_Release( child );
2840
2841     V_VT(&var) = VT_NULL;
2842     V_DISPATCH(&var) = (IDispatch*)node;
2843     r = IXMLDOMNode_insertBefore( root, node, var, NULL );
2844     ok( r == S_OK, "returns %08x\n", r );
2845     IXMLDOMNode_Release( node );
2846
2847     r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (void**)&element );
2848     ok( r == S_OK, "returns %08x\n", r );
2849
2850     r = IXMLDOMElement_get_attributes( element, &attr_map );
2851     ok( r == S_OK, "returns %08x\n", r );
2852     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
2853     ok( r == S_OK, "returns %08x\n", r );
2854     ok( num == 0, "num %d\n", num );
2855     IXMLDOMNamedNodeMap_Release( attr_map );
2856
2857     V_VT(&var) = VT_BSTR;
2858     V_BSTR(&var) = SysAllocString( szstr1 );
2859     name = SysAllocString( szdl );
2860     r = IXMLDOMElement_setAttribute( element, name, var );
2861     ok( r == S_OK, "returns %08x\n", r );
2862     r = IXMLDOMElement_get_attributes( element, &attr_map );
2863     ok( r == S_OK, "returns %08x\n", r );
2864     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
2865     ok( r == S_OK, "returns %08x\n", r );
2866     ok( num == 1, "num %d\n", num );
2867     IXMLDOMNamedNodeMap_Release( attr_map );
2868     VariantClear(&var);
2869
2870     V_VT(&var) = VT_BSTR;
2871     V_BSTR(&var) = SysAllocString( szstr2 );
2872     r = IXMLDOMElement_setAttribute( element, name, var );
2873     ok( r == S_OK, "returns %08x\n", r );
2874     r = IXMLDOMElement_get_attributes( element, &attr_map );
2875     ok( r == S_OK, "returns %08x\n", r );
2876     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
2877     ok( r == S_OK, "returns %08x\n", r );
2878     ok( num == 1, "num %d\n", num );
2879     IXMLDOMNamedNodeMap_Release( attr_map );
2880     VariantClear(&var);
2881     r = IXMLDOMElement_getAttribute( element, name, &var );
2882     ok( r == S_OK, "returns %08x\n", r );
2883     ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
2884     VariantClear(&var);
2885     SysFreeString(name);
2886
2887     V_VT(&var) = VT_BSTR;
2888     V_BSTR(&var) = SysAllocString( szstr1 );
2889     name = SysAllocString( szlc );
2890     r = IXMLDOMElement_setAttribute( element, name, var );
2891     ok( r == S_OK, "returns %08x\n", r );
2892     r = IXMLDOMElement_get_attributes( element, &attr_map );
2893     ok( r == S_OK, "returns %08x\n", r );
2894     r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
2895     ok( r == S_OK, "returns %08x\n", r );
2896     ok( num == 2, "num %d\n", num );
2897     IXMLDOMNamedNodeMap_Release( attr_map );
2898     VariantClear(&var);
2899     SysFreeString(name);
2900
2901     V_VT(&var) = VT_I4;
2902     V_I4(&var) = 10;
2903     name = SysAllocString( szbs );
2904     r = IXMLDOMElement_setAttribute( element, name, var );
2905     ok( r == S_OK, "returns %08x\n", r );
2906     VariantClear(&var);
2907     r = IXMLDOMElement_getAttribute( element, name, &var );
2908     ok( r == S_OK, "returns %08x\n", r );
2909     ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
2910     VariantClear(&var);
2911     SysFreeString(name);
2912
2913     /* Create an Attribute */
2914     V_VT(&var) = VT_I4;
2915     V_I4(&var) = NODE_ATTRIBUTE;
2916     str = SysAllocString( szAttribute );
2917     r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
2918     ok( r == S_OK, "returns %08x\n", r );
2919     ok( node != NULL, "node was null\n");
2920     SysFreeString(str);
2921
2922     IXMLDOMElement_Release( element );
2923     IXMLDOMNode_Release( root );
2924     IXMLDOMDocument_Release( doc );
2925 }
2926
2927 static void test_getElementsByTagName(void)
2928 {
2929     IXMLDOMNodeList *node_list;
2930     IXMLDOMDocument *doc;
2931     IXMLDOMElement *elem;
2932     WCHAR buff[100];
2933     VARIANT_BOOL b;
2934     HRESULT r;
2935     LONG len;
2936     BSTR str;
2937
2938     doc = create_document(&IID_IXMLDOMDocument);
2939     if (!doc) return;
2940
2941     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2942     ok( r == S_OK, "loadXML failed\n");
2943     ok( b == VARIANT_TRUE, "failed to load XML string\n");
2944
2945     str = SysAllocString( szstar );
2946
2947     /* null arguments cases */
2948     r = IXMLDOMDocument_getElementsByTagName(doc, NULL, &node_list);
2949     ok( r == E_INVALIDARG, "ret %08x\n", r );
2950     r = IXMLDOMDocument_getElementsByTagName(doc, str, NULL);
2951     ok( r == E_INVALIDARG, "ret %08x\n", r );
2952
2953     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
2954     ok( r == S_OK, "ret %08x\n", r );
2955     r = IXMLDOMNodeList_get_length( node_list, &len );
2956     ok( r == S_OK, "ret %08x\n", r );
2957     ok( len == 6, "len %d\n", len );
2958
2959     IXMLDOMNodeList_Release( node_list );
2960     SysFreeString( str );
2961
2962     /* broken query BSTR */
2963     memcpy(&buff[2], szstar, sizeof(szstar));
2964     /* just a big length */
2965     *(DWORD*)buff = 0xf0f0;
2966     r = IXMLDOMDocument_getElementsByTagName(doc, &buff[2], &node_list);
2967     ok( r == S_OK, "ret %08x\n", r );
2968     r = IXMLDOMNodeList_get_length( node_list, &len );
2969     ok( r == S_OK, "ret %08x\n", r );
2970     ok( len == 6, "len %d\n", len );
2971     IXMLDOMNodeList_Release( node_list );
2972
2973     str = SysAllocString( szbs );
2974     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
2975     ok( r == S_OK, "ret %08x\n", r );
2976     r = IXMLDOMNodeList_get_length( node_list, &len );
2977     ok( r == S_OK, "ret %08x\n", r );
2978     ok( len == 1, "len %d\n", len );
2979     IXMLDOMNodeList_Release( node_list );
2980     SysFreeString( str );
2981
2982     str = SysAllocString( szdl );
2983     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
2984     ok( r == S_OK, "ret %08x\n", r );
2985     r = IXMLDOMNodeList_get_length( node_list, &len );
2986     ok( r == S_OK, "ret %08x\n", r );
2987     ok( len == 0, "len %d\n", len );
2988     IXMLDOMNodeList_Release( node_list );
2989     SysFreeString( str );
2990
2991     str = SysAllocString( szstr1 );
2992     r = IXMLDOMDocument_getElementsByTagName(doc, str, &node_list);
2993     ok( r == S_OK, "ret %08x\n", r );
2994     r = IXMLDOMNodeList_get_length( node_list, &len );
2995     ok( r == S_OK, "ret %08x\n", r );
2996     ok( len == 0, "len %d\n", len );
2997     IXMLDOMNodeList_Release( node_list );
2998     SysFreeString( str );
2999
3000     /* test for element */
3001     r = IXMLDOMDocument_get_documentElement(doc, &elem);
3002     ok( r == S_OK, "ret %08x\n", r );
3003
3004     str = SysAllocString( szstar );
3005
3006     /* null arguments cases */
3007     r = IXMLDOMElement_getElementsByTagName(elem, NULL, &node_list);
3008     ok( r == E_INVALIDARG, "ret %08x\n", r );
3009     r = IXMLDOMElement_getElementsByTagName(elem, str, NULL);
3010     ok( r == E_INVALIDARG, "ret %08x\n", r );
3011
3012     r = IXMLDOMElement_getElementsByTagName(elem, str, &node_list);
3013     ok( r == S_OK, "ret %08x\n", r );
3014     r = IXMLDOMNodeList_get_length( node_list, &len );
3015     ok( r == S_OK, "ret %08x\n", r );
3016     ok( len == 5, "len %d\n", len );
3017     expect_list_and_release(node_list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1");
3018     SysFreeString( str );
3019
3020     /* broken query BSTR */
3021     memcpy(&buff[2], szstar, sizeof(szstar));
3022     /* just a big length */
3023     *(DWORD*)buff = 0xf0f0;
3024     r = IXMLDOMElement_getElementsByTagName(elem, &buff[2], &node_list);
3025     ok( r == S_OK, "ret %08x\n", r );
3026     r = IXMLDOMNodeList_get_length( node_list, &len );
3027     ok( r == S_OK, "ret %08x\n", r );
3028     ok( len == 5, "len %d\n", len );
3029     IXMLDOMNodeList_Release( node_list );
3030
3031     IXMLDOMElement_Release(elem);
3032
3033     IXMLDOMDocument_Release( doc );
3034
3035     free_bstrs();
3036 }
3037
3038 static void test_get_text(void)
3039 {
3040     HRESULT r;
3041     BSTR str;
3042     VARIANT_BOOL b;
3043     IXMLDOMDocument *doc;
3044     IXMLDOMNode *node, *node2, *node3;
3045     IXMLDOMNode *nodeRoot;
3046     IXMLDOMNodeList *node_list;
3047     IXMLDOMNamedNodeMap *node_map;
3048     LONG len;
3049
3050     doc = create_document(&IID_IXMLDOMDocument);
3051     if (!doc) return;
3052
3053     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3054     ok( r == S_OK, "loadXML failed\n");
3055     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3056
3057     str = SysAllocString( szbs );
3058     r = IXMLDOMDocument_getElementsByTagName( doc, str, &node_list );
3059     ok( r == S_OK, "ret %08x\n", r );
3060     SysFreeString(str);
3061
3062     /* Test to get all child node text. */
3063     r = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&nodeRoot);
3064     ok( r == S_OK, "ret %08x\n", r );
3065     if(r == S_OK)
3066     {
3067         r = IXMLDOMNode_get_text( nodeRoot, &str );
3068         ok( r == S_OK, "ret %08x\n", r );
3069         ok( compareIgnoreReturns(str, _bstr_("fn1.txt\n\n fn2.txt \n\nf1\n")), "wrong get_text: %s\n", wine_dbgstr_w(str));
3070         SysFreeString(str);
3071
3072         IXMLDOMNode_Release(nodeRoot);
3073     }
3074
3075     r = IXMLDOMNodeList_get_length( node_list, NULL );
3076     ok( r == E_INVALIDARG, "ret %08x\n", r );
3077
3078     r = IXMLDOMNodeList_get_length( node_list, &len );
3079     ok( r == S_OK, "ret %08x\n", r );
3080     ok( len == 1, "expect 1 got %d\n", len );
3081
3082     r = IXMLDOMNodeList_get_item( node_list, 0, NULL );
3083     ok( r == E_INVALIDARG, "ret %08x\n", r );
3084
3085     r = IXMLDOMNodeList_nextNode( node_list, NULL );
3086     ok( r == E_INVALIDARG, "ret %08x\n", r );
3087
3088     r = IXMLDOMNodeList_get_item( node_list, 0, &node );
3089     ok( r == S_OK, "ret %08x\n", r );
3090     IXMLDOMNodeList_Release( node_list );
3091
3092     /* Invalid output parameter*/
3093     r = IXMLDOMNode_get_text( node, NULL );
3094     ok( r == E_INVALIDARG, "ret %08x\n", r );
3095
3096     r = IXMLDOMNode_get_text( node, &str );
3097     ok( r == S_OK, "ret %08x\n", r );
3098     ok( !memcmp(str, szfn1_txt, lstrlenW(szfn1_txt) ), "wrong string\n" );
3099     SysFreeString(str);
3100
3101     r = IXMLDOMNode_get_attributes( node, &node_map );
3102     ok( r == S_OK, "ret %08x\n", r );
3103
3104     str = SysAllocString( szvr );
3105     r = IXMLDOMNamedNodeMap_getNamedItem( node_map, str, &node2 );
3106     ok( r == S_OK, "ret %08x\n", r );
3107     SysFreeString(str);
3108
3109     r = IXMLDOMNode_get_text( node2, &str );
3110     ok( r == S_OK, "ret %08x\n", r );
3111     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3112     SysFreeString(str);
3113
3114     r = IXMLDOMNode_get_firstChild( node2, &node3 );
3115     ok( r == S_OK, "ret %08x\n", r );
3116
3117     r = IXMLDOMNode_get_text( node3, &str );
3118     ok( r == S_OK, "ret %08x\n", r );
3119     ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3120     SysFreeString(str);
3121
3122
3123     IXMLDOMNode_Release( node3 );
3124     IXMLDOMNode_Release( node2 );
3125     IXMLDOMNamedNodeMap_Release( node_map );
3126     IXMLDOMNode_Release( node );
3127     IXMLDOMDocument_Release( doc );
3128
3129     free_bstrs();
3130 }
3131
3132 static void test_get_childNodes(void)
3133 {
3134     IXMLDOMNodeList *node_list, *node_list2;
3135     IEnumVARIANT *enum1, *enum2, *enum3;
3136     VARIANT_BOOL b;
3137     IXMLDOMDocument *doc;
3138     IXMLDOMNode *node, *node2;
3139     IXMLDOMElement *element;
3140     IUnknown *unk1, *unk2;
3141     HRESULT hr;
3142     VARIANT v;
3143     BSTR str;
3144     LONG len;
3145
3146     doc = create_document(&IID_IXMLDOMDocument);
3147     if (!doc) return;
3148
3149     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3150     EXPECT_HR(hr, S_OK);
3151     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3152
3153     hr = IXMLDOMDocument_get_documentElement( doc, &element );
3154     EXPECT_HR(hr, S_OK);
3155
3156     hr = IXMLDOMElement_get_childNodes( element, &node_list );
3157     EXPECT_HR(hr, S_OK);
3158
3159     hr = IXMLDOMNodeList_get_length( node_list, &len );
3160     EXPECT_HR(hr, S_OK);
3161     ok( len == 4, "len %d\n", len);
3162
3163     /* refcount tests for IEnumVARIANT support */
3164     EXPECT_REF(node_list, 1);
3165     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1);
3166     EXPECT_HR(hr, S_OK);
3167     EXPECT_REF(node_list, 1);
3168     EXPECT_REF(enum1, 2);
3169
3170     EXPECT_REF(node_list, 1);
3171     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum2);
3172     EXPECT_HR(hr, S_OK);
3173     EXPECT_REF(node_list, 1);
3174     ok(enum2 == enum1, "got %p, %p\n", enum2, enum1);
3175     IEnumVARIANT_Release(enum2);
3176
3177     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3178     EXPECT_HR(hr, S_OK);
3179     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
3180     EXPECT_HR(hr, S_OK);
3181     EXPECT_REF(node_list, 3);
3182     EXPECT_REF(enum1, 2);
3183     ok(unk1 == unk2, "got %p, %p\n", unk1, unk2);
3184     IUnknown_Release(unk1);
3185     IUnknown_Release(unk2);
3186
3187     EXPECT_REF(node_list, 1);
3188     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum2);
3189     EXPECT_HR(hr, S_OK);
3190     EXPECT_REF(node_list, 2);
3191     EXPECT_REF(enum2, 1);
3192     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
3193
3194     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
3195     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3196     EXPECT_HR(hr, S_OK);
3197     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
3198     EXPECT_HR(hr, S_OK);
3199     EXPECT_REF(node_list, 3);
3200     EXPECT_REF(enum2, 2);
3201     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
3202     IUnknown_Release(unk1);
3203     IUnknown_Release(unk2);
3204
3205     hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum3);
3206     EXPECT_HR(hr, S_OK);
3207     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
3208     IEnumVARIANT_Release(enum3);
3209     IEnumVARIANT_Release(enum2);
3210
3211     /* iteration tests */
3212     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
3213     EXPECT_HR(hr, S_OK);
3214     hr = IXMLDOMNode_get_nodeName(node, &str);
3215     EXPECT_HR(hr, S_OK);
3216     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3217     SysFreeString(str);
3218     IXMLDOMNode_Release(node);
3219
3220     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3221     EXPECT_HR(hr, S_OK);
3222     hr = IXMLDOMNode_get_nodeName(node, &str);
3223     EXPECT_HR(hr, S_OK);
3224     ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3225     SysFreeString(str);
3226     IXMLDOMNode_Release(node);
3227
3228     V_VT(&v) = VT_EMPTY;
3229     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
3230     EXPECT_HR(hr, S_OK);
3231     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
3232     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
3233     EXPECT_HR(hr, S_OK);
3234     hr = IXMLDOMNode_get_nodeName(node, &str);
3235     EXPECT_HR(hr, S_OK);
3236     ok(!lstrcmpW(str, _bstr_("bs")), "got node name %s\n", wine_dbgstr_w(str));
3237     SysFreeString(str);
3238     IXMLDOMNode_Release(node);
3239     VariantClear(&v);
3240
3241     hr = IXMLDOMNodeList_nextNode(node_list, &node);
3242     EXPECT_HR(hr, S_OK);
3243     hr = IXMLDOMNode_get_nodeName(node, &str);
3244     EXPECT_HR(hr, S_OK);
3245     ok(!lstrcmpW(str, _bstr_("pr")), "got %s\n", wine_dbgstr_w(str));
3246     SysFreeString(str);
3247     IXMLDOMNode_Release(node);
3248
3249     IEnumVARIANT_Release(enum1);
3250
3251     hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
3252     EXPECT_HR(hr, S_OK);
3253
3254     hr = IXMLDOMNode_get_childNodes( node, &node_list2 );
3255     EXPECT_HR(hr, S_OK);
3256
3257     hr = IXMLDOMNodeList_get_length( node_list2, &len );
3258     EXPECT_HR(hr, S_OK);
3259     ok( len == 0, "len %d\n", len);
3260
3261     hr = IXMLDOMNodeList_get_item( node_list2, 0, &node2);
3262     EXPECT_HR(hr, S_FALSE);
3263
3264     IXMLDOMNodeList_Release( node_list2 );
3265     IXMLDOMNode_Release( node );
3266     IXMLDOMNodeList_Release( node_list );
3267     IXMLDOMElement_Release( element );
3268
3269     /* test for children of <?xml ..?> node */
3270     hr = IXMLDOMDocument_get_firstChild(doc, &node);
3271     EXPECT_HR(hr, S_OK);
3272
3273     str = NULL;
3274     hr = IXMLDOMNode_get_nodeName(node, &str);
3275     EXPECT_HR(hr, S_OK);
3276     ok(!lstrcmpW(str, _bstr_("xml")), "got %s\n", wine_dbgstr_w(str));
3277     SysFreeString(str);
3278
3279     /* it returns empty but valid node list */
3280     node_list = (void*)0xdeadbeef;
3281     hr = IXMLDOMNode_get_childNodes(node, &node_list);
3282     EXPECT_HR(hr, S_OK);
3283
3284     len = -1;
3285     hr = IXMLDOMNodeList_get_length(node_list, &len);
3286     EXPECT_HR(hr, S_OK);
3287     ok(len == 0, "got %d\n", len);
3288
3289     IXMLDOMNodeList_Release( node_list );
3290     IXMLDOMNode_Release(node);
3291
3292     IXMLDOMDocument_Release( doc );
3293     free_bstrs();
3294 }
3295
3296 static void test_get_firstChild(void)
3297 {
3298     static WCHAR xmlW[] = {'x','m','l',0};
3299     IXMLDOMDocument *doc;
3300     IXMLDOMNode *node;
3301     VARIANT_BOOL b;
3302     HRESULT r;
3303     BSTR str;
3304
3305     doc = create_document(&IID_IXMLDOMDocument);
3306     if (!doc) return;
3307
3308     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3309     ok( r == S_OK, "loadXML failed\n");
3310     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3311
3312     r = IXMLDOMDocument_get_firstChild( doc, &node );
3313     ok( r == S_OK, "ret %08x\n", r);
3314
3315     r = IXMLDOMNode_get_nodeName( node, &str );
3316     ok( r == S_OK, "ret %08x\n", r);
3317
3318     ok(!lstrcmpW(str, xmlW), "expected \"xml\" node name, got %s\n", wine_dbgstr_w(str));
3319
3320     SysFreeString(str);
3321     IXMLDOMNode_Release( node );
3322     IXMLDOMDocument_Release( doc );
3323
3324     free_bstrs();
3325 }
3326
3327 static void test_get_lastChild(void)
3328 {
3329     static WCHAR lcW[] = {'l','c',0};
3330     static WCHAR foW[] = {'f','o',0};
3331     IXMLDOMDocument *doc;
3332     IXMLDOMNode *node, *child;
3333     VARIANT_BOOL b;
3334     HRESULT r;
3335     BSTR str;
3336
3337     doc = create_document(&IID_IXMLDOMDocument);
3338     if (!doc) return;
3339
3340     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3341     ok( r == S_OK, "loadXML failed\n");
3342     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3343
3344     r = IXMLDOMDocument_get_lastChild( doc, &node );
3345     ok( r == S_OK, "ret %08x\n", r);
3346
3347     r = IXMLDOMNode_get_nodeName( node, &str );
3348     ok( r == S_OK, "ret %08x\n", r);
3349
3350     ok(memcmp(str, lcW, sizeof(lcW)) == 0, "expected \"lc\" node name\n");
3351     SysFreeString(str);
3352
3353     r = IXMLDOMNode_get_lastChild( node, &child );
3354     ok( r == S_OK, "ret %08x\n", r);
3355
3356     r = IXMLDOMNode_get_nodeName( child, &str );
3357     ok( r == S_OK, "ret %08x\n", r);
3358
3359     ok(memcmp(str, foW, sizeof(foW)) == 0, "expected \"fo\" node name\n");
3360     SysFreeString(str);
3361
3362     IXMLDOMNode_Release( child );
3363     IXMLDOMNode_Release( node );
3364     IXMLDOMDocument_Release( doc );
3365
3366     free_bstrs();
3367 }
3368
3369 static void test_removeChild(void)
3370 {
3371     HRESULT r;
3372     VARIANT_BOOL b;
3373     IXMLDOMDocument *doc;
3374     IXMLDOMElement *element, *lc_element;
3375     IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node, *lc_node;
3376     IXMLDOMNodeList *root_list, *fo_list;
3377
3378     doc = create_document(&IID_IXMLDOMDocument);
3379     if (!doc) return;
3380
3381     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3382     ok( r == S_OK, "loadXML failed\n");
3383     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3384
3385     r = IXMLDOMDocument_get_documentElement( doc, &element );
3386     ok( r == S_OK, "ret %08x\n", r);
3387     todo_wine EXPECT_REF(element, 2);
3388
3389     r = IXMLDOMElement_get_childNodes( element, &root_list );
3390     ok( r == S_OK, "ret %08x\n", r);
3391     EXPECT_REF(root_list, 1);
3392
3393     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3394     ok( r == S_OK, "ret %08x\n", r);
3395     EXPECT_REF(fo_node, 1);
3396
3397     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3398     ok( r == S_OK, "ret %08x\n", r);
3399     EXPECT_REF(fo_list, 1);
3400
3401     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3402     ok( r == S_OK, "ret %08x\n", r);
3403     EXPECT_REF(ba_node, 1);
3404
3405     /* invalid parameter: NULL ptr */
3406     removed_node = (void*)0xdeadbeef;
3407     r = IXMLDOMElement_removeChild( element, NULL, &removed_node );
3408     ok( r == E_INVALIDARG, "ret %08x\n", r );
3409     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3410
3411     /* ba_node is a descendant of element, but not a direct child. */
3412     removed_node = (void*)0xdeadbeef;
3413     EXPECT_REF(ba_node, 1);
3414     EXPECT_CHILDREN(fo_node);
3415     r = IXMLDOMElement_removeChild( element, ba_node, &removed_node );
3416     ok( r == E_INVALIDARG, "ret %08x\n", r );
3417     ok( removed_node == NULL, "%p\n", removed_node );
3418     EXPECT_REF(ba_node, 1);
3419     EXPECT_CHILDREN(fo_node);
3420
3421     EXPECT_REF(ba_node, 1);
3422     EXPECT_REF(fo_node, 1);
3423     r = IXMLDOMElement_removeChild( element, fo_node, &removed_node );
3424     ok( r == S_OK, "ret %08x\n", r);
3425     ok( fo_node == removed_node, "node %p node2 %p\n", fo_node, removed_node );
3426     EXPECT_REF(fo_node, 2);
3427     EXPECT_REF(ba_node, 1);
3428
3429     /* try removing already removed child */
3430     temp_node = (void*)0xdeadbeef;
3431     r = IXMLDOMElement_removeChild( element, fo_node, &temp_node );
3432     ok( r == E_INVALIDARG, "ret %08x\n", r);
3433     ok( temp_node == NULL, "%p\n", temp_node );
3434     IXMLDOMNode_Release( fo_node );
3435
3436     /* the removed node has no parent anymore */
3437     r = IXMLDOMNode_get_parentNode( removed_node, &temp_node );
3438     ok( r == S_FALSE, "ret %08x\n", r);
3439     ok( temp_node == NULL, "%p\n", temp_node );
3440
3441     IXMLDOMNode_Release( removed_node );
3442     IXMLDOMNode_Release( ba_node );
3443     IXMLDOMNodeList_Release( fo_list );
3444
3445     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3446     ok( r == S_OK, "ret %08x\n", r);
3447
3448     r = IXMLDOMNode_QueryInterface( lc_node, &IID_IXMLDOMElement, (void**)&lc_element );
3449     ok( r == S_OK, "ret %08x\n", r);
3450
3451     /* MS quirk: passing wrong interface pointer works, too */
3452     r = IXMLDOMElement_removeChild( element, (IXMLDOMNode*)lc_element, NULL );
3453     ok( r == S_OK, "ret %08x\n", r);
3454     IXMLDOMElement_Release( lc_element );
3455
3456     temp_node = (void*)0xdeadbeef;
3457     r = IXMLDOMNode_get_parentNode( lc_node, &temp_node );
3458     ok( r == S_FALSE, "ret %08x\n", r);
3459     ok( temp_node == NULL, "%p\n", temp_node );
3460
3461     IXMLDOMNode_Release( lc_node );
3462     IXMLDOMNodeList_Release( root_list );
3463     IXMLDOMElement_Release( element );
3464     IXMLDOMDocument_Release( doc );
3465
3466     free_bstrs();
3467 }
3468
3469 static void test_replaceChild(void)
3470 {
3471     HRESULT r;
3472     VARIANT_BOOL b;
3473     IXMLDOMDocument *doc;
3474     IXMLDOMElement *element, *ba_element;
3475     IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
3476     IXMLDOMNodeList *root_list, *fo_list;
3477     IUnknown * unk1, *unk2;
3478     LONG len;
3479
3480     doc = create_document(&IID_IXMLDOMDocument);
3481     if (!doc) return;
3482
3483     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3484     ok( r == S_OK, "loadXML failed\n");
3485     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3486
3487     r = IXMLDOMDocument_get_documentElement( doc, &element );
3488     ok( r == S_OK, "ret %08x\n", r);
3489
3490     r = IXMLDOMElement_get_childNodes( element, &root_list );
3491     ok( r == S_OK, "ret %08x\n", r);
3492
3493     r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3494     ok( r == S_OK, "ret %08x\n", r);
3495
3496     r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3497     ok( r == S_OK, "ret %08x\n", r);
3498
3499     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3500     ok( r == S_OK, "ret %08x\n", r);
3501
3502     r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3503     ok( r == S_OK, "ret %08x\n", r);
3504
3505     IXMLDOMNodeList_Release( fo_list );
3506
3507     /* invalid parameter: NULL ptr for element to remove */
3508     removed_node = (void*)0xdeadbeef;
3509     r = IXMLDOMElement_replaceChild( element, ba_node, NULL, &removed_node );
3510     ok( r == E_INVALIDARG, "ret %08x\n", r );
3511     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3512
3513     /* invalid parameter: NULL for replacement element. (Sic!) */
3514     removed_node = (void*)0xdeadbeef;
3515     r = IXMLDOMElement_replaceChild( element, NULL, fo_node, &removed_node );
3516     ok( r == E_INVALIDARG, "ret %08x\n", r );
3517     ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3518
3519     /* invalid parameter: OldNode is not a child */
3520     removed_node = (void*)0xdeadbeef;
3521     r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
3522     ok( r == E_INVALIDARG, "ret %08x\n", r );
3523     ok( removed_node == NULL, "%p\n", removed_node );
3524     IXMLDOMNode_Release( lc_node );
3525
3526     /* invalid parameter: would create loop */
3527     removed_node = (void*)0xdeadbeef;
3528     r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
3529     ok( r == E_FAIL, "ret %08x\n", r );
3530     ok( removed_node == NULL, "%p\n", removed_node );
3531
3532     r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
3533     ok( r == S_OK, "ret %08x\n", r );
3534
3535     r = IXMLDOMNodeList_get_item( root_list, 3, &temp_node );
3536     ok( r == S_OK, "ret %08x\n", r );
3537
3538     /* ba_node and temp_node refer to the same node, yet they
3539        are different interface pointers */
3540     ok( ba_node != temp_node, "ba_node %p temp_node %p\n", ba_node, temp_node);
3541     r = IXMLDOMNode_QueryInterface( temp_node, &IID_IUnknown, (void**)&unk1);
3542     ok( r == S_OK, "ret %08x\n", r );
3543     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IUnknown, (void**)&unk2);
3544     ok( r == S_OK, "ret %08x\n", r );
3545     todo_wine ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
3546
3547     IUnknown_Release( unk1 );
3548     IUnknown_Release( unk2 );
3549
3550     /* ba_node should have been removed from below fo_node */
3551     r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3552     ok( r == S_OK, "ret %08x\n", r );
3553
3554     /* MS quirk: replaceChild also accepts elements instead of nodes */
3555     r = IXMLDOMNode_QueryInterface( ba_node, &IID_IXMLDOMElement, (void**)&ba_element);
3556     ok( r == S_OK, "ret %08x\n", r );
3557     EXPECT_REF(ba_element, 2);
3558
3559     removed_node = NULL;
3560     r = IXMLDOMElement_replaceChild( element, ba_node, (IXMLDOMNode*)ba_element, &removed_node );
3561     ok( r == S_OK, "ret %08x\n", r );
3562     ok( removed_node != NULL, "got %p\n", removed_node);
3563     EXPECT_REF(ba_element, 3);
3564     IXMLDOMElement_Release( ba_element );
3565
3566     r = IXMLDOMNodeList_get_length( fo_list, &len);
3567     ok( r == S_OK, "ret %08x\n", r );
3568     ok( len == 0, "len %d\n", len);
3569
3570     IXMLDOMNodeList_Release( fo_list );
3571
3572     IXMLDOMNode_Release(ba_node);
3573     IXMLDOMNode_Release(fo_node);
3574     IXMLDOMNode_Release(temp_node);
3575     IXMLDOMNodeList_Release( root_list );
3576     IXMLDOMElement_Release( element );
3577     IXMLDOMDocument_Release( doc );
3578
3579     free_bstrs();
3580 }
3581
3582 static void test_removeNamedItem(void)
3583 {
3584     IXMLDOMDocument *doc;
3585     IXMLDOMElement *element;
3586     IXMLDOMNode *pr_node, *removed_node, *removed_node2;
3587     IXMLDOMNodeList *root_list;
3588     IXMLDOMNamedNodeMap * pr_attrs;
3589     VARIANT_BOOL b;
3590     BSTR str;
3591     LONG len;
3592     HRESULT r;
3593
3594     doc = create_document(&IID_IXMLDOMDocument);
3595     if (!doc) return;
3596
3597     r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3598     ok( r == S_OK, "loadXML failed\n");
3599     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3600
3601     r = IXMLDOMDocument_get_documentElement( doc, &element );
3602     ok( r == S_OK, "ret %08x\n", r);
3603
3604     r = IXMLDOMElement_get_childNodes( element, &root_list );
3605     ok( r == S_OK, "ret %08x\n", r);
3606
3607     r = IXMLDOMNodeList_get_item( root_list, 1, &pr_node );
3608     ok( r == S_OK, "ret %08x\n", r);
3609
3610     r = IXMLDOMNode_get_attributes( pr_node, &pr_attrs );
3611     ok( r == S_OK, "ret %08x\n", r);
3612
3613     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
3614     ok( r == S_OK, "ret %08x\n", r);
3615     ok( len == 3, "length %d\n", len);
3616
3617     removed_node = (void*)0xdeadbeef;
3618     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, NULL, &removed_node);
3619     ok ( r == E_INVALIDARG, "ret %08x\n", r);
3620     ok ( removed_node == (void*)0xdeadbeef, "got %p\n", removed_node);
3621
3622     removed_node = (void*)0xdeadbeef;
3623     str = SysAllocString(szvr);
3624     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node);
3625     ok ( r == S_OK, "ret %08x\n", r);
3626
3627     removed_node2 = (void*)0xdeadbeef;
3628     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node2);
3629     ok ( r == S_FALSE, "ret %08x\n", r);
3630     ok ( removed_node2 == NULL, "got %p\n", removed_node2 );
3631
3632     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
3633     ok( r == S_OK, "ret %08x\n", r);
3634     ok( len == 2, "length %d\n", len);
3635
3636     r = IXMLDOMNamedNodeMap_setNamedItem( pr_attrs, removed_node, NULL);
3637     ok ( r == S_OK, "ret %08x\n", r);
3638     IXMLDOMNode_Release(removed_node);
3639
3640     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
3641     ok( r == S_OK, "ret %08x\n", r);
3642     ok( len == 3, "length %d\n", len);
3643
3644     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
3645     ok ( r == S_OK, "ret %08x\n", r);
3646
3647     r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
3648     ok( r == S_OK, "ret %08x\n", r);
3649     ok( len == 2, "length %d\n", len);
3650
3651     r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
3652     ok ( r == S_FALSE, "ret %08x\n", r);
3653
3654     SysFreeString(str);
3655
3656     IXMLDOMNamedNodeMap_Release( pr_attrs );
3657     IXMLDOMNode_Release( pr_node );
3658     IXMLDOMNodeList_Release( root_list );
3659     IXMLDOMElement_Release( element );
3660     IXMLDOMDocument_Release( doc );
3661
3662     free_bstrs();
3663 }
3664
3665 #define test_IObjectSafety_set(p, r, r2, s, m, e, e2) _test_IObjectSafety_set(__LINE__,p, r, r2, s, m, e, e2)
3666 static void _test_IObjectSafety_set(unsigned line, IObjectSafety *safety, HRESULT result,
3667                                     HRESULT result2, DWORD set, DWORD mask, DWORD expected,
3668                                     DWORD expected2)
3669 {
3670     DWORD enabled, supported;
3671     HRESULT hr;
3672
3673     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL, set, mask);
3674     if (result == result2)
3675         ok_(__FILE__,line)(hr == result, "SetInterfaceSafetyOptions: expected %08x, returned %08x\n", result, hr );
3676     else
3677         ok_(__FILE__,line)(broken(hr == result) || hr == result2,
3678            "SetInterfaceSafetyOptions: expected %08x, got %08x\n", result2, hr );
3679
3680     supported = enabled = 0xCAFECAFE;
3681     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
3682     ok(hr == S_OK, "ret %08x\n", hr );
3683     if (expected == expected2)
3684         ok_(__FILE__,line)(enabled == expected, "Expected %08x, got %08x\n", expected, enabled);
3685     else
3686         ok_(__FILE__,line)(broken(enabled == expected) || enabled == expected2,
3687            "Expected %08x, got %08x\n", expected2, enabled);
3688
3689     /* reset the safety options */
3690
3691     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
3692             INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER,
3693             0);
3694     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3695
3696     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
3697     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3698     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
3699 }
3700
3701 #define test_IObjectSafety_common(s) _test_IObjectSafety_common(__LINE__,s)
3702 static void _test_IObjectSafety_common(unsigned line, IObjectSafety *safety)
3703 {
3704     DWORD enabled = 0, supported = 0;
3705     HRESULT hr;
3706
3707     /* get */
3708     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, NULL, &enabled);
3709     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
3710     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, NULL);
3711     ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
3712
3713     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
3714     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3715     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
3716        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
3717         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
3718              "got %08x\n", supported);
3719     ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
3720
3721     /* set -- individual flags */
3722
3723     test_IObjectSafety_set(safety, S_OK, S_OK,
3724         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER,
3725         INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
3726
3727     test_IObjectSafety_set(safety, S_OK, S_OK,
3728         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA,
3729         INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA);
3730
3731     test_IObjectSafety_set(safety, S_OK, S_OK,
3732         INTERFACE_USES_SECURITY_MANAGER, INTERFACE_USES_SECURITY_MANAGER,
3733         0, INTERFACE_USES_SECURITY_MANAGER /* msxml3 SP8+ */);
3734
3735     /* set INTERFACE_USES_DISPEX  */
3736
3737     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
3738         INTERFACE_USES_DISPEX, INTERFACE_USES_DISPEX,
3739         0, 0);
3740
3741     test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
3742         INTERFACE_USES_DISPEX, 0,
3743         0, 0);
3744
3745     test_IObjectSafety_set(safety, S_OK, S_OK /* msxml3 SP8+ */,
3746         0, INTERFACE_USES_DISPEX,
3747         0, 0);
3748
3749     /* set option masking */
3750
3751     test_IObjectSafety_set(safety, S_OK, S_OK,
3752         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
3753         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
3754         INTERFACESAFE_FOR_UNTRUSTED_CALLER,
3755         INTERFACESAFE_FOR_UNTRUSTED_CALLER);
3756
3757     test_IObjectSafety_set(safety, S_OK, S_OK,
3758         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
3759         INTERFACESAFE_FOR_UNTRUSTED_DATA,
3760         INTERFACESAFE_FOR_UNTRUSTED_DATA,
3761         INTERFACESAFE_FOR_UNTRUSTED_DATA);
3762
3763     test_IObjectSafety_set(safety, S_OK, S_OK,
3764         INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
3765         INTERFACE_USES_SECURITY_MANAGER,
3766         0,
3767         0);
3768
3769     /* set -- inheriting previous settings */
3770
3771     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
3772                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER,
3773                                                          INTERFACESAFE_FOR_UNTRUSTED_CALLER);
3774     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3775     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
3776     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3777     ok_(__FILE__,line)(enabled == INTERFACESAFE_FOR_UNTRUSTED_CALLER, "Expected INTERFACESAFE_FOR_UNTRUSTED_CALLER got %08x\n", enabled);
3778     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
3779        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
3780         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
3781              "got %08x\n", supported);
3782
3783     hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
3784                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA,
3785                                                          INTERFACESAFE_FOR_UNTRUSTED_DATA);
3786     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3787     hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
3788     ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
3789     ok_(__FILE__,line)(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_DATA) ||
3790                        enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA),
3791                        "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) got %08x\n", enabled);
3792     ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
3793        supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
3794         "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
3795              "got %08x\n", supported);
3796 }
3797
3798 static void test_IXMLDOMDocument2(void)
3799 {
3800     static const WCHAR emptyW[] = {0};
3801     IXMLDOMDocument2 *doc2, *dtddoc2;
3802     IXMLDOMDocument *doc;
3803     IXMLDOMParseError* err;
3804     IDispatchEx *dispex;
3805     VARIANT_BOOL b;
3806     VARIANT var;
3807     HRESULT r;
3808     LONG res;
3809
3810     doc = create_document(&IID_IXMLDOMDocument);
3811     if (!doc) return;
3812
3813     dtddoc2 = create_document(&IID_IXMLDOMDocument2);
3814     if (!dtddoc2)
3815     {
3816         IXMLDOMDocument_Release(doc);
3817         return;
3818     }
3819
3820     r = IXMLDOMDocument_QueryInterface( doc, &IID_IXMLDOMDocument2, (void**)&doc2 );
3821     ok( r == S_OK, "ret %08x\n", r );
3822     ok( doc == (IXMLDOMDocument*)doc2, "interfaces differ\n");
3823
3824     ole_expect(IXMLDOMDocument2_get_readyState(doc2, NULL), E_INVALIDARG);
3825     ole_check(IXMLDOMDocument2_get_readyState(doc2, &res));
3826     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
3827
3828     err = NULL;
3829     ole_expect(IXMLDOMDocument2_validate(doc2, NULL), S_FALSE);
3830     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
3831     ok(err != NULL, "expected a pointer\n");
3832     if (err)
3833     {
3834         res = 0;
3835         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3836         /* XML_E_NOTWF */
3837         ok(res == E_XML_NOTWF, "got %08x\n", res);
3838         IXMLDOMParseError_Release(err);
3839     }
3840
3841     r = IXMLDOMDocument2_loadXML( doc2, _bstr_(complete4A), &b );
3842     ok( r == S_OK, "loadXML failed\n");
3843     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3844
3845     ole_check(IXMLDOMDocument_get_readyState(doc, &res));
3846     ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
3847
3848     err = NULL;
3849     ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
3850     ok(err != NULL, "expected a pointer\n");
3851     if (err)
3852     {
3853         res = 0;
3854         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3855         /* XML_E_NODTD */
3856         ok(res == E_XML_NODTD, "got %08x\n", res);
3857         IXMLDOMParseError_Release(err);
3858     }
3859
3860     r = IXMLDOMDocument_QueryInterface( doc, &IID_IDispatchEx, (void**)&dispex );
3861     ok( r == S_OK, "ret %08x\n", r );
3862     if(r == S_OK)
3863     {
3864         IDispatchEx_Release(dispex);
3865     }
3866
3867     /* we will check if the variant got cleared */
3868     IXMLDOMDocument2_AddRef(doc2);
3869     EXPECT_REF(doc2, 3); /* doc, doc2, AddRef*/
3870
3871     V_VT(&var) = VT_UNKNOWN;
3872     V_UNKNOWN(&var) = (IUnknown *)doc2;
3873
3874     /* invalid calls */
3875     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("askldhfaklsdf"), &var), E_FAIL);
3876     expect_eq(V_VT(&var), VT_UNKNOWN, int, "%x");
3877     ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), NULL), E_INVALIDARG);
3878
3879     /* valid call */
3880     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
3881     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
3882     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
3883     V_VT(&var) = VT_R4;
3884
3885     /* the variant didn't get cleared*/
3886     expect_eq(IXMLDOMDocument2_Release(doc2), 2, int, "%d");
3887
3888     /* setProperty tests */
3889     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("askldhfaklsdf"), var), E_FAIL);
3890     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), var), E_FAIL);
3891     ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("alskjdh faklsjd hfk")), E_FAIL);
3892     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
3893     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
3894     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
3895
3896     V_VT(&var) = VT_BSTR;
3897     V_BSTR(&var) = SysAllocString(emptyW);
3898     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
3899     ok(r == S_OK, "got 0x%08x\n", r);
3900     VariantClear(&var);
3901
3902     V_VT(&var) = VT_I2;
3903     V_I2(&var) = 0;
3904     r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
3905     ok(r == E_FAIL, "got 0x%08x\n", r);
3906
3907     /* contrary to what MSDN claims you can switch back from XPath to XSLPattern */
3908     ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
3909     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
3910     expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
3911
3912     IXMLDOMDocument2_Release( doc2 );
3913     IXMLDOMDocument_Release( doc );
3914
3915     /* DTD validation */
3916     ole_check(IXMLDOMDocument2_put_validateOnParse(dtddoc2, VARIANT_FALSE));
3917     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML), &b));
3918     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3919     err = NULL;
3920     ole_check(IXMLDOMDocument2_validate(dtddoc2, &err));
3921     ok(err != NULL, "expected pointer\n");
3922     if (err)
3923     {
3924         res = 0;
3925         ole_expect(IXMLDOMParseError_get_errorCode(err, &res), S_FALSE);
3926         ok(res == 0, "got %08x\n", res);
3927         IXMLDOMParseError_Release(err);
3928     }
3929
3930     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0D), &b));
3931     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3932     err = NULL;
3933     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
3934     ok(err != NULL, "expected pointer\n");
3935     if (err)
3936     {
3937         res = 0;
3938         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3939         /* XML_ELEMENT_UNDECLARED */
3940         todo_wine ok(res == 0xC00CE00D, "got %08x\n", res);
3941         IXMLDOMParseError_Release(err);
3942     }
3943
3944     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0E), &b));
3945     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3946     err = NULL;
3947     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
3948     ok(err != NULL, "expected pointer\n");
3949     if (err)
3950     {
3951         res = 0;
3952         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3953         /* XML_ELEMENT_ID_NOT_FOUND */
3954         todo_wine ok(res == 0xC00CE00E, "got %08x\n", res);
3955         IXMLDOMParseError_Release(err);
3956     }
3957
3958     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_11), &b));
3959     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3960     err = NULL;
3961     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
3962     ok(err != NULL, "expected pointer\n");
3963     if (err)
3964     {
3965         res = 0;
3966         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3967         /* XML_EMPTY_NOT_ALLOWED */
3968         todo_wine ok(res == 0xC00CE011, "got %08x\n", res);
3969         IXMLDOMParseError_Release(err);
3970     }
3971
3972     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_13), &b));
3973     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3974     err = NULL;
3975     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
3976     ok(err != NULL, "expected pointer\n");
3977     if (err)
3978     {
3979         res = 0;
3980         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3981         /* XML_ROOT_NAME_MISMATCH */
3982         todo_wine ok(res == 0xC00CE013, "got %08x\n", res);
3983         IXMLDOMParseError_Release(err);
3984     }
3985
3986     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_14), &b));
3987     ok( b == VARIANT_TRUE, "failed to load XML string\n");
3988     err = NULL;
3989     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
3990     ok(err != NULL, "expected pointer\n");
3991     if (err)
3992     {
3993         res = 0;
3994         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
3995         /* XML_INVALID_CONTENT */
3996         todo_wine ok(res == 0xC00CE014, "got %08x\n", res);
3997         IXMLDOMParseError_Release(err);
3998     }
3999
4000     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_15), &b));
4001     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4002     err = NULL;
4003     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4004     ok(err != NULL, "expected pointer\n");
4005     if (err)
4006     {
4007         res = 0;
4008         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4009         /* XML_ATTRIBUTE_NOT_DEFINED */
4010         todo_wine ok(res == 0xC00CE015, "got %08x\n", res);
4011         IXMLDOMParseError_Release(err);
4012     }
4013
4014     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_16), &b));
4015     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4016     err = NULL;
4017     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4018     ok(err != NULL, "expected pointer\n");
4019     if (err)
4020     {
4021         res = 0;
4022         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4023         /* XML_ATTRIBUTE_FIXED */
4024         todo_wine ok(res == 0xC00CE016, "got %08x\n", res);
4025         IXMLDOMParseError_Release(err);
4026     }
4027
4028     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_17), &b));
4029     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4030     err = NULL;
4031     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4032     ok(err != NULL, "expected pointer\n");
4033     if (err)
4034     {
4035         res = 0;
4036         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4037         /* XML_ATTRIBUTE_VALUE */
4038         todo_wine ok(res == 0xC00CE017, "got %08x\n", res);
4039         IXMLDOMParseError_Release(err);
4040     }
4041
4042     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_18), &b));
4043     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4044     err = NULL;
4045     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4046     ok(err != NULL, "expected pointer\n");
4047     if (err)
4048     {
4049         res = 0;
4050         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4051         /* XML_ILLEGAL_TEXT */
4052         todo_wine ok(res == 0xC00CE018, "got %08x\n", res);
4053         IXMLDOMParseError_Release(err);
4054     }
4055
4056     ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_20), &b));
4057     ok( b == VARIANT_TRUE, "failed to load XML string\n");
4058     err = NULL;
4059     ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4060     ok(err != NULL, "expected pointer\n");
4061     if (err)
4062     {
4063         res = 0;
4064         ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4065         /* XML_REQUIRED_ATTRIBUTE_MISSING */
4066         todo_wine ok(res == 0xC00CE020, "got %08x\n", res);
4067         IXMLDOMParseError_Release(err);
4068     }
4069
4070     IXMLDOMDocument2_Release( dtddoc2 );
4071     free_bstrs();
4072 }
4073
4074 #define helper_ole_check(expr) { \
4075     HRESULT r = expr; \
4076     ok_(__FILE__, line)(r == S_OK, "=> %i: " #expr " returned %08x\n", __LINE__, r); \
4077 }
4078
4079 #define helper_expect_list_and_release(list, expstr) { \
4080     char *str = list_to_string(list); \
4081     ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i: Invalid node list: %s, expected %s\n", __LINE__, str, expstr); \
4082     if (list) IXMLDOMNodeList_Release(list); \
4083 }
4084
4085 #define helper_expect_bstr_and_release(bstr, str) { \
4086     ok_(__FILE__, line)(lstrcmpW(bstr, _bstr_(str)) == 0, \
4087        "=> %i: got %s\n", __LINE__, wine_dbgstr_w(bstr)); \
4088     SysFreeString(bstr); \
4089 }
4090
4091 #define check_ws_ignored(doc, str) _check_ws_ignored(__LINE__, doc, str)
4092 static inline void _check_ws_ignored(int line, IXMLDOMDocument2* doc, char const* str)
4093 {
4094     IXMLDOMNode *node1, *node2;
4095     IXMLDOMNodeList *list;
4096     BSTR bstr;
4097
4098     helper_ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4099     helper_ole_check(IXMLDOMNodeList_get_item(list, 0, &node1));
4100     helper_ole_check(IXMLDOMNodeList_get_item(list, 1, &node2));
4101     helper_ole_check(IXMLDOMNodeList_reset(list));
4102     helper_expect_list_and_release(list, "E1.E5.E1.E2.D1 E2.E5.E1.E2.D1");
4103
4104     helper_ole_check(IXMLDOMNode_get_childNodes(node1, &list));
4105     helper_expect_list_and_release(list, "T1.E1.E5.E1.E2.D1 E2.E1.E5.E1.E2.D1 E3.E1.E5.E1.E2.D1 T4.E1.E5.E1.E2.D1 E5.E1.E5.E1.E2.D1");
4106     helper_ole_check(IXMLDOMNode_get_text(node1, &bstr));
4107     if (str)
4108     {
4109         helper_expect_bstr_and_release(bstr, str);
4110     }
4111     else
4112     {
4113         helper_expect_bstr_and_release(bstr, "This is a description.");
4114     }
4115     IXMLDOMNode_Release(node1);
4116
4117     helper_ole_check(IXMLDOMNode_get_childNodes(node2, &list));
4118     helper_expect_list_and_release(list, "T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
4119     helper_ole_check(IXMLDOMNode_get_text(node2, &bstr));
4120     helper_expect_bstr_and_release(bstr, "\n                This is a description with preserved whitespace. \n            ");
4121     IXMLDOMNode_Release(node2);
4122 }
4123
4124 #define check_ws_preserved(doc, str) _check_ws_preserved(__LINE__, doc, str)
4125 static inline void _check_ws_preserved(int line, IXMLDOMDocument2* doc, char const* str)
4126 {
4127     IXMLDOMNode *node1, *node2;
4128     IXMLDOMNodeList *list;
4129     BSTR bstr;
4130
4131     helper_ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4132     helper_ole_check(IXMLDOMNodeList_get_item(list, 0, &node1));
4133     helper_ole_check(IXMLDOMNodeList_get_item(list, 1, &node2));
4134     helper_ole_check(IXMLDOMNodeList_reset(list));
4135     helper_expect_list_and_release(list, "E2.E10.E2.E2.D1 E4.E10.E2.E2.D1");
4136
4137     helper_ole_check(IXMLDOMNode_get_childNodes(node1, &list));
4138     helper_expect_list_and_release(list, "T1.E2.E10.E2.E2.D1 E2.E2.E10.E2.E2.D1 T3.E2.E10.E2.E2.D1 E4.E2.E10.E2.E2.D1 T5.E2.E10.E2.E2.D1 E6.E2.E10.E2.E2.D1 T7.E2.E10.E2.E2.D1");
4139     helper_ole_check(IXMLDOMNode_get_text(node1, &bstr));
4140     if (str)
4141     {
4142         helper_expect_bstr_and_release(bstr, str);
4143     }
4144     else
4145     {
4146         helper_expect_bstr_and_release(bstr, "\n                This is a description. \n            ");
4147     }
4148     IXMLDOMNode_Release(node1);
4149
4150     helper_ole_check(IXMLDOMNode_get_childNodes(node2, &list));
4151     helper_expect_list_and_release(list, "T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
4152     helper_ole_check(IXMLDOMNode_get_text(node2, &bstr));
4153     helper_expect_bstr_and_release(bstr, "\n                This is a description with preserved whitespace. \n            ");
4154     IXMLDOMNode_Release(node2);
4155 }
4156
4157 static void test_whitespace(void)
4158 {
4159     VARIANT_BOOL b;
4160     IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
4161
4162     doc1 = create_document(&IID_IXMLDOMDocument2);
4163     doc2 = create_document(&IID_IXMLDOMDocument2);
4164     if (!doc1 || !doc2) return;
4165
4166     ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
4167     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4168     ok(b == VARIANT_FALSE, "expected false\n");
4169     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4170     ok(b == VARIANT_TRUE, "expected true\n");
4171
4172     ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4173     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4174     ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4175     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4176
4177     /* switch to XPath */
4178     ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4179     ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4180
4181     check_ws_ignored(doc1, NULL);
4182     check_ws_preserved(doc2, NULL);
4183
4184     /* new instances copy the property */
4185     ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
4186     ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
4187
4188     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4189     ok(b == VARIANT_FALSE, "expected false\n");
4190     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4191     ok(b == VARIANT_TRUE, "expected true\n");
4192
4193     check_ws_ignored(doc3, NULL);
4194     check_ws_preserved(doc4, NULL);
4195
4196     /* setting after loading xml affects trimming of leading/trailing ws only */
4197     ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
4198     ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
4199
4200     /* the trailing "\n            " isn't there, because it was ws-only node */
4201     check_ws_ignored(doc1, "\n                This is a description. ");
4202     check_ws_preserved(doc2, "This is a description.");
4203
4204     /* it takes effect on reload */
4205     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4206     ok(b == VARIANT_TRUE, "expected true\n");
4207     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4208     ok(b == VARIANT_FALSE, "expected false\n");
4209
4210     ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4211     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4212     ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4213     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4214
4215     check_ws_preserved(doc1, NULL);
4216     check_ws_ignored(doc2, NULL);
4217
4218     /* other instances follow suit */
4219     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4220     ok(b == VARIANT_TRUE, "expected true\n");
4221     ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4222     ok(b == VARIANT_FALSE, "expected false\n");
4223
4224     check_ws_preserved(doc3, NULL);
4225     check_ws_ignored(doc4, NULL);
4226
4227     IXMLDOMDocument2_Release(doc1);
4228     IXMLDOMDocument2_Release(doc2);
4229     IXMLDOMDocument2_Release(doc3);
4230     IXMLDOMDocument2_Release(doc4);
4231     free_bstrs();
4232 }
4233
4234 typedef struct {
4235     const GUID *clsid;
4236     const char *name;
4237     const char *ns;
4238     HRESULT hr;
4239 } selection_ns_t;
4240
4241 /* supposed to be tested with szExampleXML */
4242 static const selection_ns_t selection_ns_data[] = {
4243     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4244     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4245     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4246     { &CLSID_DOMDocument,   "CLSID_DOMDocument",   "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4247
4248     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4249     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4250     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4251     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2",  "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4252
4253     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4254     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4255     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4256     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4257
4258     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4259     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4260     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4261     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4262
4263     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4264     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4265     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4266     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4267
4268     { NULL }
4269 };
4270
4271 static void test_XPath(void)
4272 {
4273     const selection_ns_t *ptr = selection_ns_data;
4274     VARIANT var;
4275     VARIANT_BOOL b;
4276     IXMLDOMDocument2 *doc;
4277     IXMLDOMDocument *doc2;
4278     IXMLDOMNode *rootNode;
4279     IXMLDOMNode *elem1Node;
4280     IXMLDOMNode *node;
4281     IXMLDOMNodeList *list;
4282     IXMLDOMElement *elem;
4283     IXMLDOMAttribute *attr;
4284     DOMNodeType type;
4285     HRESULT hr;
4286     LONG len;
4287     BSTR str;
4288
4289     doc = create_document(&IID_IXMLDOMDocument2);
4290     if (!doc) return;
4291
4292     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4293     EXPECT_HR(hr, S_OK);
4294     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4295
4296     /* switch to XPath */
4297     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4298
4299     /* some simple queries*/
4300     EXPECT_REF(doc, 1);
4301     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4302     EXPECT_HR(hr, S_OK);
4303     EXPECT_REF(doc, 1);
4304     EXPECT_LIST_LEN(list, 1);
4305
4306     EXPECT_REF(list, 1);
4307     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4308     EXPECT_HR(hr, S_OK);
4309     EXPECT_REF(list, 1);
4310     EXPECT_REF(rootNode, 1);
4311
4312     hr = IXMLDOMNodeList_reset(list);
4313     EXPECT_HR(hr, S_OK);
4314     expect_list_and_release(list, "E2.D1");
4315
4316 if (0)
4317 {
4318     /* namespace:: axis test is disabled until namespace definitions
4319        are supported as attribute nodes, currently it's another node type */
4320     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("/root/namespace::*"), &list);
4321     EXPECT_HR(hr, S_OK);
4322     len = -1;
4323     hr = IXMLDOMNodeList_get_length(list, &len);
4324     EXPECT_HR(hr, S_OK);
4325     ok(len == 2, "got %d\n", len);
4326
4327     hr = IXMLDOMNodeList_nextNode(list, &node);
4328     EXPECT_HR(hr, S_OK);
4329     type = NODE_INVALID;
4330     hr = IXMLDOMNode_get_nodeType(node, &type);
4331     EXPECT_HR(hr, S_OK);
4332     ok(type == NODE_ATTRIBUTE, "got %d\n", type);
4333     IXMLDOMNode_Release(node);
4334
4335     IXMLDOMNodeList_Release(list);
4336 }
4337
4338     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
4339     expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1");
4340
4341     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//c[@type]"), &list));
4342     expect_list_and_release(list, "E3.E2.E2.D1");
4343
4344     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
4345     /* using get_item for query results advances the position */
4346     ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
4347     expect_node(node, "E2.E2.D1");
4348     IXMLDOMNode_Release(node);
4349     ole_check(IXMLDOMNodeList_nextNode(list, &node));
4350     expect_node(node, "E4.E2.D1");
4351     IXMLDOMNode_Release(node);
4352     ole_check(IXMLDOMNodeList_reset(list));
4353     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E4.E2.D1");
4354
4355     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("."), &list));
4356     expect_list_and_release(list, "E2.D1");
4357
4358     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem[3]/preceding-sibling::*"), &list));
4359     ole_check(IXMLDOMNodeList_get_item(list, 0, &elem1Node));
4360     ole_check(IXMLDOMNodeList_reset(list));
4361     expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1");
4362
4363     /* select an attribute */
4364     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//@type"), &list));
4365     expect_list_and_release(list, "A'type'.E3.E2.E2.D1");
4366
4367     /* would evaluate to a number */
4368     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("count(*)"), &list), E_FAIL);
4369     /* would evaluate to a boolean */
4370     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("position()>0"), &list), E_FAIL);
4371     /* would evaluate to a string */
4372     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("name()"), &list), E_FAIL);
4373
4374     /* no results */
4375     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("c"), &list));
4376     expect_list_and_release(list, "");
4377     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("elem//c"), &list));
4378     expect_list_and_release(list, "");
4379     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem[4]"), &list));
4380     expect_list_and_release(list, "");
4381     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[0]"), &list));
4382     expect_list_and_release(list, "");
4383
4384     /* foo undeclared in document node */
4385     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4386     /* undeclared in <root> node */
4387     ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
4388     /* undeclared in <elem> node */
4389     ole_expect(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//foo:c"), &list), E_FAIL);
4390     /* but this trick can be used */
4391     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//*[name()='foo:c']"), &list));
4392     expect_list_and_release(list, "E3.E4.E2.D1");
4393
4394     /* it has to be declared in SelectionNamespaces */
4395     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
4396         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
4397
4398     /* now the namespace can be used */
4399     ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list));
4400     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4401     ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
4402     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4403     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
4404     expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4405     ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
4406     expect_list_and_release(list, "E5.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1");
4407
4408     /* SelectionNamespaces syntax error - the namespaces doesn't work anymore but the value is stored */
4409     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
4410         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL);
4411
4412     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4413
4414     VariantInit(&var);
4415     ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
4416     expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4417     if (V_VT(&var) == VT_BSTR)
4418         expect_bstr_eq_and_free(V_BSTR(&var), "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###");
4419
4420     /* extra attributes - same thing*/
4421     ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
4422         _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' param='test'")), E_FAIL);
4423     ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4424
4425     IXMLDOMNode_Release(rootNode);
4426     IXMLDOMNode_Release(elem1Node);
4427
4428     /* alter document with already built list */
4429     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4430     EXPECT_HR(hr, S_OK);
4431     EXPECT_LIST_LEN(list, 1);
4432
4433     hr = IXMLDOMDocument2_get_lastChild(doc, &rootNode);
4434     EXPECT_HR(hr, S_OK);
4435     EXPECT_REF(rootNode, 1);
4436     EXPECT_REF(doc, 1);
4437
4438     hr = IXMLDOMDocument2_removeChild(doc, rootNode, NULL);
4439     EXPECT_HR(hr, S_OK);
4440     IXMLDOMNode_Release(rootNode);
4441
4442     EXPECT_LIST_LEN(list, 1);
4443
4444     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4445     EXPECT_HR(hr, S_OK);
4446     EXPECT_REF(rootNode, 1);
4447
4448     IXMLDOMNodeList_Release(list);
4449
4450     hr = IXMLDOMNode_get_nodeName(rootNode, &str);
4451     EXPECT_HR(hr, S_OK);
4452     ok(!lstrcmpW(str, _bstr_("root")), "got %s\n", wine_dbgstr_w(str));
4453     SysFreeString(str);
4454     IXMLDOMNode_Release(rootNode);
4455
4456     /* alter node from list and get it another time */
4457     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4458     EXPECT_HR(hr, S_OK);
4459     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4460
4461     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4462     EXPECT_HR(hr, S_OK);
4463     EXPECT_LIST_LEN(list, 1);
4464
4465     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4466     EXPECT_HR(hr, S_OK);
4467
4468     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
4469     EXPECT_HR(hr, S_OK);
4470
4471     V_VT(&var) = VT_I2;
4472     V_I2(&var) = 1;
4473     hr = IXMLDOMElement_setAttribute(elem, _bstr_("attrtest"), var);
4474     EXPECT_HR(hr, S_OK);
4475     IXMLDOMElement_Release(elem);
4476     IXMLDOMNode_Release(rootNode);
4477
4478     /* now check attribute to be present */
4479     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4480     EXPECT_HR(hr, S_OK);
4481
4482     hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
4483     EXPECT_HR(hr, S_OK);
4484
4485     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
4486     EXPECT_HR(hr, S_OK);
4487     IXMLDOMAttribute_Release(attr);
4488
4489     IXMLDOMElement_Release(elem);
4490     IXMLDOMNode_Release(rootNode);
4491
4492     /* and now check for attribute in original document */
4493     hr = IXMLDOMDocument2_get_documentElement(doc, &elem);
4494     EXPECT_HR(hr, S_OK);
4495
4496     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
4497     EXPECT_HR(hr, S_OK);
4498     IXMLDOMAttribute_Release(attr);
4499
4500     IXMLDOMElement_Release(elem);
4501
4502     /* attach node from list to another document */
4503     doc2 = create_document(&IID_IXMLDOMDocument);
4504
4505     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4506     EXPECT_HR(hr, S_OK);
4507     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4508
4509     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4510     EXPECT_HR(hr, S_OK);
4511     EXPECT_LIST_LEN(list, 1);
4512
4513     hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4514     EXPECT_HR(hr, S_OK);
4515     EXPECT_REF(rootNode, 1);
4516
4517     hr = IXMLDOMDocument_appendChild(doc2, rootNode, NULL);
4518     EXPECT_HR(hr, S_OK);
4519     EXPECT_REF(rootNode, 1);
4520     EXPECT_REF(doc2, 1);
4521     EXPECT_REF(list, 1);
4522
4523     EXPECT_LIST_LEN(list, 1);
4524
4525     IXMLDOMNode_Release(rootNode);
4526     IXMLDOMNodeList_Release(list);
4527     IXMLDOMDocument_Release(doc2);
4528     IXMLDOMDocument2_Release(doc);
4529
4530     while (ptr->clsid)
4531     {
4532         hr = CoCreateInstance(ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
4533         if (hr != S_OK)
4534         {
4535             win_skip("can't create instance of %s\n", ptr->name);
4536             ptr++;
4537             continue;
4538         }
4539
4540         hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4541         EXPECT_HR(hr, S_OK);
4542         ok(b == VARIANT_TRUE, "failed to load, %s\n", ptr->name);
4543
4544         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath"));
4545         EXPECT_HR(hr, S_OK);
4546
4547         V_VT(&var) = VT_BSTR;
4548         V_BSTR(&var) = _bstr_(ptr->ns);
4549
4550         hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var);
4551         ok(hr == ptr->hr, "got 0x%08x, for %s, %s\n", hr, ptr->name, ptr->ns);
4552
4553         V_VT(&var) = VT_EMPTY;
4554         hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var);
4555         EXPECT_HR(hr, S_OK);
4556         ok(V_VT(&var) == VT_BSTR, "got wrong property type %d\n", V_VT(&var));
4557         ok(!lstrcmpW(V_BSTR(&var), _bstr_(ptr->ns)), "got wrong value %s\n", wine_dbgstr_w(V_BSTR(&var)));
4558         VariantClear(&var);
4559
4560         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list);
4561         EXPECT_HR(hr, S_OK);
4562         if (hr == S_OK)
4563             expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
4564
4565         IXMLDOMDocument2_Release(doc);
4566         ptr++;
4567         free_bstrs();
4568     }
4569
4570     free_bstrs();
4571 }
4572
4573 static void test_cloneNode(void )
4574 {
4575     IXMLDOMDocument *doc, *doc2;
4576     VARIANT_BOOL b;
4577     IXMLDOMNodeList *pList;
4578     IXMLDOMNamedNodeMap *mapAttr;
4579     LONG length, length1;
4580     LONG attr_cnt, attr_cnt1;
4581     IXMLDOMNode *node, *attr;
4582     IXMLDOMNode *node_clone;
4583     IXMLDOMNode *node_first;
4584     HRESULT hr;
4585
4586     doc = create_document(&IID_IXMLDOMDocument);
4587     if (!doc) return;
4588
4589     ole_check(IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b));
4590     ok(b == VARIANT_TRUE, "failed to load XML string\n");
4591
4592     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc/pr"), &node);
4593     ok( hr == S_OK, "ret %08x\n", hr );
4594     ok( node != NULL, "node %p\n", node );
4595
4596     /* Check invalid parameter */
4597     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, NULL);
4598     ok( hr == E_INVALIDARG, "ret %08x\n", hr );
4599
4600     /* All Children */
4601     hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, &node_clone);
4602     ok( hr == S_OK, "ret %08x\n", hr );
4603     ok( node_clone != NULL, "node %p\n", node );
4604
4605     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
4606     ok( hr == S_OK, "ret %08x\n", hr );
4607     hr = IXMLDOMNode_get_ownerDocument(node_clone, &doc2);
4608     ok( hr == S_OK, "ret %08x\n", hr );
4609     IXMLDOMDocument_Release(doc2);
4610     IXMLDOMNode_Release(node_first);
4611
4612     hr = IXMLDOMNode_get_childNodes(node, &pList);
4613     ok( hr == S_OK, "ret %08x\n", hr );
4614     length = 0;
4615     hr = IXMLDOMNodeList_get_length(pList, &length);
4616     ok( hr == S_OK, "ret %08x\n", hr );
4617     ok(length == 1, "got %d\n", length);
4618     IXMLDOMNodeList_Release(pList);
4619
4620     hr = IXMLDOMNode_get_attributes(node, &mapAttr);
4621     ok( hr == S_OK, "ret %08x\n", hr );
4622     attr_cnt = 0;
4623     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt);
4624     ok( hr == S_OK, "ret %08x\n", hr );
4625     ok(attr_cnt == 3, "got %d\n", attr_cnt);
4626     IXMLDOMNamedNodeMap_Release(mapAttr);
4627
4628     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
4629     ok( hr == S_OK, "ret %08x\n", hr );
4630     length1 = 0;
4631     hr = IXMLDOMNodeList_get_length(pList, &length1);
4632     ok(length1 == 1, "got %d\n", length1);
4633     ok( hr == S_OK, "ret %08x\n", hr );
4634     IXMLDOMNodeList_Release(pList);
4635
4636     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
4637     ok( hr == S_OK, "ret %08x\n", hr );
4638     attr_cnt1 = 0;
4639     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
4640     ok( hr == S_OK, "ret %08x\n", hr );
4641     ok(attr_cnt1 == 3, "got %d\n", attr_cnt1);
4642     /* now really get some attributes from cloned element */
4643     attr = NULL;
4644     hr = IXMLDOMNamedNodeMap_getNamedItem(mapAttr, _bstr_("id"), &attr);
4645     ok(hr == S_OK, "ret %08x\n", hr);
4646     IXMLDOMNode_Release(attr);
4647     IXMLDOMNamedNodeMap_Release(mapAttr);
4648
4649     ok(length == length1, "wrong Child count (%d, %d)\n", length, length1);
4650     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
4651     IXMLDOMNode_Release(node_clone);
4652
4653     /* No Children */
4654     hr = IXMLDOMNode_cloneNode(node, VARIANT_FALSE, &node_clone);
4655     ok( hr == S_OK, "ret %08x\n", hr );
4656     ok( node_clone != NULL, "node %p\n", node );
4657
4658     hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
4659     ok(hr == S_FALSE, "ret %08x\n", hr );
4660
4661     hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
4662     ok(hr == S_OK, "ret %08x\n", hr );
4663     hr = IXMLDOMNodeList_get_length(pList, &length1);
4664     ok(hr == S_OK, "ret %08x\n", hr );
4665     ok( length1 == 0, "Length should be 0 (%d)\n", length1);
4666     IXMLDOMNodeList_Release(pList);
4667
4668     hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
4669     ok(hr == S_OK, "ret %08x\n", hr );
4670     hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
4671     ok(hr == S_OK, "ret %08x\n", hr );
4672     ok(attr_cnt1 == 3, "Attribute count should be 3 (%d)\n", attr_cnt1);
4673     IXMLDOMNamedNodeMap_Release(mapAttr);
4674
4675     ok(length != length1, "wrong Child count (%d, %d)\n", length, length1);
4676     ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
4677     IXMLDOMNode_Release(node_clone);
4678
4679     IXMLDOMNode_Release(node);
4680     IXMLDOMDocument_Release(doc);
4681     free_bstrs();
4682 }
4683
4684 static void test_xmlTypes(void)
4685 {
4686     IXMLDOMDocument *doc;
4687     IXMLDOMElement *pRoot;
4688     HRESULT hr;
4689     IXMLDOMComment *pComment;
4690     IXMLDOMElement *pElement;
4691     IXMLDOMAttribute *pAttribute;
4692     IXMLDOMNamedNodeMap *pAttribs;
4693     IXMLDOMCDATASection *pCDataSec;
4694     IXMLDOMImplementation *pIXMLDOMImplementation = NULL;
4695     IXMLDOMDocumentFragment *pDocFrag = NULL;
4696     IXMLDOMEntityReference *pEntityRef = NULL;
4697     BSTR str;
4698     IXMLDOMNode *pNextChild;
4699     VARIANT v;
4700     LONG len = 0;
4701
4702     doc = create_document(&IID_IXMLDOMDocument);
4703     if (!doc) return;
4704
4705     pNextChild = (void*)0xdeadbeef;
4706     hr = IXMLDOMDocument_get_nextSibling(doc, NULL);
4707     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4708
4709     pNextChild = (void*)0xdeadbeef;
4710     hr = IXMLDOMDocument_get_nextSibling(doc, &pNextChild);
4711     ok(hr == S_FALSE, "ret %08x\n", hr );
4712     ok(pNextChild == NULL, "pDocChild not NULL\n");
4713
4714     /* test previous Sibling */
4715     hr = IXMLDOMDocument_get_previousSibling(doc, NULL);
4716     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4717
4718     pNextChild = (void*)0xdeadbeef;
4719     hr = IXMLDOMDocument_get_previousSibling(doc, &pNextChild);
4720     ok(hr == S_FALSE, "ret %08x\n", hr );
4721     ok(pNextChild == NULL, "pNextChild not NULL\n");
4722
4723     /* test get_dataType */
4724     V_VT(&v) = VT_EMPTY;
4725     hr = IXMLDOMDocument_get_dataType(doc, &v);
4726     ok(hr == S_FALSE, "ret %08x\n", hr );
4727     ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
4728     VariantClear(&v);
4729
4730     /* test implementation */
4731     hr = IXMLDOMDocument_get_implementation(doc, NULL);
4732     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4733
4734     hr = IXMLDOMDocument_get_implementation(doc, &pIXMLDOMImplementation);
4735     ok(hr == S_OK, "ret %08x\n", hr );
4736     if(hr == S_OK)
4737     {
4738         VARIANT_BOOL hasFeature = VARIANT_TRUE;
4739         BSTR sEmpty = SysAllocStringLen(NULL, 0);
4740
4741         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, NULL, sEmpty, &hasFeature);
4742         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4743
4744         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, NULL);
4745         ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4746
4747         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
4748         ok(hr == S_OK, "ret %08x\n", hr );
4749         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
4750
4751         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, &hasFeature);
4752         ok(hr == S_OK, "ret %08x\n", hr );
4753         ok(hasFeature == VARIANT_FALSE, "hasFeature returned true\n");
4754
4755         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), NULL, &hasFeature);
4756         ok(hr == S_OK, "ret %08x\n", hr );
4757         ok(hasFeature == VARIANT_TRUE, "hasFeature returned false\n");
4758
4759         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
4760         ok(hr == S_OK, "ret %08x\n", hr );
4761         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
4762
4763         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), _bstr_("1.0"), &hasFeature);
4764         ok(hr == S_OK, "ret %08x\n", hr );
4765         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
4766
4767         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("XML"), _bstr_("1.0"), &hasFeature);
4768         ok(hr == S_OK, "ret %08x\n", hr );
4769         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
4770
4771         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("MS-DOM"), _bstr_("1.0"), &hasFeature);
4772         ok(hr == S_OK, "ret %08x\n", hr );
4773         ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
4774
4775         hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("SSS"), NULL, &hasFeature);
4776         ok(hr == S_OK, "ret %08x\n", hr );
4777         ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
4778
4779         SysFreeString(sEmpty);
4780         IXMLDOMImplementation_Release(pIXMLDOMImplementation);
4781     }
4782
4783     pRoot = (IXMLDOMElement*)0x1;
4784     hr = IXMLDOMDocument_createElement(doc, NULL, &pRoot);
4785     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4786     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
4787
4788     pRoot = (IXMLDOMElement*)0x1;
4789     hr = IXMLDOMDocument_createElement(doc, _bstr_(""), &pRoot);
4790     ok(hr == E_FAIL, "ret %08x\n", hr );
4791     ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
4792
4793     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
4794     ok(hr == S_OK, "ret %08x\n", hr );
4795     if(hr == S_OK)
4796     {
4797         hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)pRoot, NULL);
4798         ok(hr == S_OK, "ret %08x\n", hr );
4799         if(hr == S_OK)
4800         {
4801             /* Comment */
4802             str = SysAllocString(szComment);
4803             hr = IXMLDOMDocument_createComment(doc, str, &pComment);
4804             SysFreeString(str);
4805             ok(hr == S_OK, "ret %08x\n", hr );
4806             if(hr == S_OK)
4807             {
4808                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pComment, NULL);
4809                 ok(hr == S_OK, "ret %08x\n", hr );
4810
4811                 hr = IXMLDOMComment_get_nodeName(pComment, &str);
4812                 ok(hr == S_OK, "ret %08x\n", hr );
4813                 ok( !lstrcmpW( str, szCommentNodeText ), "incorrect comment node Name\n");
4814                 SysFreeString(str);
4815
4816                 hr = IXMLDOMComment_get_xml(pComment, &str);
4817                 ok(hr == S_OK, "ret %08x\n", hr );
4818                 ok( !lstrcmpW( str, szCommentXML ), "incorrect comment xml\n");
4819                 SysFreeString(str);
4820
4821                 /* put data Tests */
4822                 hr = IXMLDOMComment_put_data(pComment, _bstr_("This &is a ; test <>\\"));
4823                 ok(hr == S_OK, "ret %08x\n", hr );
4824
4825                 /* get data Tests */
4826                 hr = IXMLDOMComment_get_data(pComment, &str);
4827                 ok(hr == S_OK, "ret %08x\n", hr );
4828                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect get_data string\n");
4829                 SysFreeString(str);
4830
4831                 /* Confirm XML text is good */
4832                 hr = IXMLDOMComment_get_xml(pComment, &str);
4833                 ok(hr == S_OK, "ret %08x\n", hr );
4834                 ok( !lstrcmpW( str, _bstr_("<!--This &is a ; test <>\\-->") ), "incorrect xml string\n");
4835                 SysFreeString(str);
4836
4837                 /* Confirm we get the put_data Text back */
4838                 hr = IXMLDOMComment_get_text(pComment, &str);
4839                 ok(hr == S_OK, "ret %08x\n", hr );
4840                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
4841                 SysFreeString(str);
4842
4843                 /* test length property */
4844                 hr = IXMLDOMComment_get_length(pComment, &len);
4845                 ok(hr == S_OK, "ret %08x\n", hr );
4846                 ok(len == 21, "expected 21 got %d\n", len);
4847
4848                 /* test substringData */
4849                 hr = IXMLDOMComment_substringData(pComment, 0, 4, NULL);
4850                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4851
4852                 /* test substringData - Invalid offset */
4853                 str = (BSTR)&szElement;
4854                 hr = IXMLDOMComment_substringData(pComment, -1, 4, &str);
4855                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4856                 ok( str == NULL, "incorrect string\n");
4857
4858                 /* test substringData - Invalid offset */
4859                 str = (BSTR)&szElement;
4860                 hr = IXMLDOMComment_substringData(pComment, 30, 0, &str);
4861                 ok(hr == S_FALSE, "ret %08x\n", hr );
4862                 ok( str == NULL, "incorrect string\n");
4863
4864                 /* test substringData - Invalid size */
4865                 str = (BSTR)&szElement;
4866                 hr = IXMLDOMComment_substringData(pComment, 0, -1, &str);
4867                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4868                 ok( str == NULL, "incorrect string\n");
4869
4870                 /* test substringData - Invalid size */
4871                 str = (BSTR)&szElement;
4872                 hr = IXMLDOMComment_substringData(pComment, 2, 0, &str);
4873                 ok(hr == S_FALSE, "ret %08x\n", hr );
4874                 ok( str == NULL, "incorrect string\n");
4875
4876                 /* test substringData - Start of string */
4877                 hr = IXMLDOMComment_substringData(pComment, 0, 4, &str);
4878                 ok(hr == S_OK, "ret %08x\n", hr );
4879                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
4880                 SysFreeString(str);
4881
4882                 /* test substringData - Middle of string */
4883                 hr = IXMLDOMComment_substringData(pComment, 13, 4, &str);
4884                 ok(hr == S_OK, "ret %08x\n", hr );
4885                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
4886                 SysFreeString(str);
4887
4888                 /* test substringData - End of string */
4889                 hr = IXMLDOMComment_substringData(pComment, 20, 4, &str);
4890                 ok(hr == S_OK, "ret %08x\n", hr );
4891                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
4892                 SysFreeString(str);
4893
4894                 /* test appendData */
4895                 hr = IXMLDOMComment_appendData(pComment, NULL);
4896                 ok(hr == S_OK, "ret %08x\n", hr );
4897
4898                 hr = IXMLDOMComment_appendData(pComment, _bstr_(""));
4899                 ok(hr == S_OK, "ret %08x\n", hr );
4900
4901                 hr = IXMLDOMComment_appendData(pComment, _bstr_("Append"));
4902                 ok(hr == S_OK, "ret %08x\n", hr );
4903
4904                 hr = IXMLDOMComment_get_text(pComment, &str);
4905                 ok(hr == S_OK, "ret %08x\n", hr );
4906                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
4907                 SysFreeString(str);
4908
4909                 /* test insertData */
4910                 str = SysAllocStringLen(NULL, 0);
4911                 hr = IXMLDOMComment_insertData(pComment, -1, str);
4912                 ok(hr == S_OK, "ret %08x\n", hr );
4913
4914                 hr = IXMLDOMComment_insertData(pComment, -1, NULL);
4915                 ok(hr == S_OK, "ret %08x\n", hr );
4916
4917                 hr = IXMLDOMComment_insertData(pComment, 1000, str);
4918                 ok(hr == S_OK, "ret %08x\n", hr );
4919
4920                 hr = IXMLDOMComment_insertData(pComment, 1000, NULL);
4921                 ok(hr == S_OK, "ret %08x\n", hr );
4922
4923                 hr = IXMLDOMComment_insertData(pComment, 0, NULL);
4924                 ok(hr == S_OK, "ret %08x\n", hr );
4925
4926                 hr = IXMLDOMComment_insertData(pComment, 0, str);
4927                 ok(hr == S_OK, "ret %08x\n", hr );
4928                 SysFreeString(str);
4929
4930                 hr = IXMLDOMComment_insertData(pComment, -1, _bstr_("Inserting"));
4931                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4932
4933                 hr = IXMLDOMComment_insertData(pComment, 1000, _bstr_("Inserting"));
4934                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4935
4936                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("Begin "));
4937                 ok(hr == S_OK, "ret %08x\n", hr );
4938
4939                 hr = IXMLDOMComment_insertData(pComment, 17, _bstr_("Middle"));
4940                 ok(hr == S_OK, "ret %08x\n", hr );
4941
4942                 hr = IXMLDOMComment_insertData(pComment, 39, _bstr_(" End"));
4943                 ok(hr == S_OK, "ret %08x\n", hr );
4944
4945                 hr = IXMLDOMComment_get_text(pComment, &str);
4946                 ok(hr == S_OK, "ret %08x\n", hr );
4947                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
4948                 SysFreeString(str);
4949
4950                 /* delete data */
4951                 /* invalid arguments */
4952                 hr = IXMLDOMComment_deleteData(pComment, -1, 1);
4953                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4954
4955                 hr = IXMLDOMComment_deleteData(pComment, 0, 0);
4956                 ok(hr == S_OK, "ret %08x\n", hr );
4957
4958                 hr = IXMLDOMComment_deleteData(pComment, 0, -1);
4959                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4960
4961                 hr = IXMLDOMComment_get_length(pComment, &len);
4962                 ok(hr == S_OK, "ret %08x\n", hr );
4963                 ok(len == 43, "expected 43 got %d\n", len);
4964
4965                 hr = IXMLDOMComment_deleteData(pComment, len, 1);
4966                 ok(hr == S_OK, "ret %08x\n", hr );
4967
4968                 hr = IXMLDOMComment_deleteData(pComment, len+1, 1);
4969                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
4970
4971                 /* delete from start */
4972                 hr = IXMLDOMComment_deleteData(pComment, 0, 5);
4973                 ok(hr == S_OK, "ret %08x\n", hr );
4974
4975                 hr = IXMLDOMComment_get_length(pComment, &len);
4976                 ok(hr == S_OK, "ret %08x\n", hr );
4977                 ok(len == 38, "expected 38 got %d\n", len);
4978
4979                 hr = IXMLDOMComment_get_text(pComment, &str);
4980                 ok(hr == S_OK, "ret %08x\n", hr );
4981                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
4982                 SysFreeString(str);
4983
4984                 /* delete from end */
4985                 hr = IXMLDOMComment_deleteData(pComment, 35, 3);
4986                 ok(hr == S_OK, "ret %08x\n", hr );
4987
4988                 hr = IXMLDOMComment_get_length(pComment, &len);
4989                 ok(hr == S_OK, "ret %08x\n", hr );
4990                 ok(len == 35, "expected 35 got %d\n", len);
4991
4992                 hr = IXMLDOMComment_get_text(pComment, &str);
4993                 ok(hr == S_OK, "ret %08x\n", hr );
4994                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
4995                 SysFreeString(str);
4996
4997                 /* delete from inside */
4998                 hr = IXMLDOMComment_deleteData(pComment, 1, 33);
4999                 ok(hr == S_OK, "ret %08x\n", hr );
5000
5001                 hr = IXMLDOMComment_get_length(pComment, &len);
5002                 ok(hr == S_OK, "ret %08x\n", hr );
5003                 ok(len == 2, "expected 2 got %d\n", len);
5004
5005                 hr = IXMLDOMComment_get_text(pComment, &str);
5006                 ok(hr == S_OK, "ret %08x\n", hr );
5007                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5008                 SysFreeString(str);
5009
5010                 /* delete whole data ... */
5011                 hr = IXMLDOMComment_get_length(pComment, &len);
5012                 ok(hr == S_OK, "ret %08x\n", hr );
5013
5014                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5015                 ok(hr == S_OK, "ret %08x\n", hr );
5016                 /* ... and try again with empty string */
5017                 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5018                 ok(hr == S_OK, "ret %08x\n", hr );
5019
5020                 /* ::replaceData() */
5021                 V_VT(&v) = VT_BSTR;
5022                 V_BSTR(&v) = SysAllocString(szstr1);
5023                 hr = IXMLDOMComment_put_nodeValue(pComment, v);
5024                 ok(hr == S_OK, "ret %08x\n", hr );
5025                 VariantClear(&v);
5026
5027                 hr = IXMLDOMComment_replaceData(pComment, 6, 0, NULL);
5028                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5029                 hr = IXMLDOMComment_get_text(pComment, &str);
5030                 ok(hr == S_OK, "ret %08x\n", hr );
5031                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5032                 SysFreeString(str);
5033
5034                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, NULL);
5035                 ok(hr == S_OK, "ret %08x\n", hr );
5036                 hr = IXMLDOMComment_get_text(pComment, &str);
5037                 ok(hr == S_OK, "ret %08x\n", hr );
5038                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5039                 SysFreeString(str);
5040
5041                 /* NULL pointer means delete */
5042                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, NULL);
5043                 ok(hr == S_OK, "ret %08x\n", hr );
5044                 hr = IXMLDOMComment_get_text(pComment, &str);
5045                 ok(hr == S_OK, "ret %08x\n", hr );
5046                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5047                 SysFreeString(str);
5048
5049                 /* empty string means delete */
5050                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_(""));
5051                 ok(hr == S_OK, "ret %08x\n", hr );
5052                 hr = IXMLDOMComment_get_text(pComment, &str);
5053                 ok(hr == S_OK, "ret %08x\n", hr );
5054                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5055                 SysFreeString(str);
5056
5057                 /* zero count means insert */
5058                 hr = IXMLDOMComment_replaceData(pComment, 0, 0, _bstr_("a"));
5059                 ok(hr == S_OK, "ret %08x\n", hr );
5060                 hr = IXMLDOMComment_get_text(pComment, &str);
5061                 ok(hr == S_OK, "ret %08x\n", hr );
5062                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5063                 SysFreeString(str);
5064
5065                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, NULL);
5066                 ok(hr == S_OK, "ret %08x\n", hr );
5067
5068                 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("m"));
5069                 ok(hr == S_OK, "ret %08x\n", hr );
5070                 hr = IXMLDOMComment_get_text(pComment, &str);
5071                 ok(hr == S_OK, "ret %08x\n", hr );
5072                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5073                 SysFreeString(str);
5074
5075                 /* nonempty string, count greater than its length */
5076                 hr = IXMLDOMComment_replaceData(pComment, 0, 2, _bstr_("a1.2"));
5077                 ok(hr == S_OK, "ret %08x\n", hr );
5078                 hr = IXMLDOMComment_get_text(pComment, &str);
5079                 ok(hr == S_OK, "ret %08x\n", hr );
5080                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5081                 SysFreeString(str);
5082
5083                 /* nonempty string, count less than its length */
5084                 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_("wine"));
5085                 ok(hr == S_OK, "ret %08x\n", hr );
5086                 hr = IXMLDOMComment_get_text(pComment, &str);
5087                 ok(hr == S_OK, "ret %08x\n", hr );
5088                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5089                 SysFreeString(str);
5090
5091                 IXMLDOMComment_Release(pComment);
5092             }
5093
5094             /* Element */
5095             str = SysAllocString(szElement);
5096             hr = IXMLDOMDocument_createElement(doc, str, &pElement);
5097             SysFreeString(str);
5098             ok(hr == S_OK, "ret %08x\n", hr );
5099             if(hr == S_OK)
5100             {
5101                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
5102                 ok(hr == S_OK, "ret %08x\n", hr );
5103
5104                 hr = IXMLDOMElement_get_nodeName(pElement, &str);
5105                 ok(hr == S_OK, "ret %08x\n", hr );
5106                 ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
5107                 SysFreeString(str);
5108
5109                 hr = IXMLDOMElement_get_xml(pElement, &str);
5110                 ok(hr == S_OK, "ret %08x\n", hr );
5111                 ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
5112                 SysFreeString(str);
5113
5114                 /* Attribute */
5115                 pAttribute = (IXMLDOMAttribute*)0x1;
5116                 hr = IXMLDOMDocument_createAttribute(doc, NULL, &pAttribute);
5117                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5118                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5119
5120                 pAttribute = (IXMLDOMAttribute*)0x1;
5121                 hr = IXMLDOMDocument_createAttribute(doc, _bstr_(""), &pAttribute);
5122                 ok(hr == E_FAIL, "ret %08x\n", hr );
5123                 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5124
5125                 str = SysAllocString(szAttribute);
5126                 hr = IXMLDOMDocument_createAttribute(doc, str, &pAttribute);
5127                 SysFreeString(str);
5128                 ok(hr == S_OK, "ret %08x\n", hr );
5129                 if(hr == S_OK)
5130                 {
5131                     IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
5132
5133                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, NULL);
5134                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5135
5136                     pNextChild = (IXMLDOMNode *)0x1;
5137                     hr = IXMLDOMAttribute_get_nextSibling(pAttribute, &pNextChild);
5138                     ok(hr == S_FALSE, "ret %08x\n", hr );
5139                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5140
5141                     /* test Previous Sibling*/
5142                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, NULL);
5143                     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5144
5145                     pNextChild = (IXMLDOMNode *)0x1;
5146                     hr = IXMLDOMAttribute_get_previousSibling(pAttribute, &pNextChild);
5147                     ok(hr == S_FALSE, "ret %08x\n", hr );
5148                     ok(pNextChild == NULL, "pNextChild not NULL\n");
5149
5150                     hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttribute, &pNewChild);
5151                     ok(hr == E_FAIL, "ret %08x\n", hr );
5152                     ok(pNewChild == NULL, "pNewChild not NULL\n");
5153
5154                     hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
5155                     ok(hr == S_OK, "ret %08x\n", hr );
5156                     if ( hr == S_OK )
5157                     {
5158                         hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttribute, NULL );
5159                         ok(hr == S_OK, "ret %08x\n", hr );
5160
5161                         IXMLDOMNamedNodeMap_Release(pAttribs);
5162                     }
5163
5164                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5165                     ok(hr == S_OK, "ret %08x\n", hr );
5166                     ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
5167                     SysFreeString(str);
5168
5169                     /* test nodeName */
5170                     hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5171                     ok(hr == S_OK, "ret %08x\n", hr );
5172                     ok( !lstrcmpW( str, szAttribute ), "incorrect nodeName string\n");
5173                     SysFreeString(str);
5174
5175                     /* test name property */
5176                     hr = IXMLDOMAttribute_get_name(pAttribute, &str);
5177                     ok(hr == S_OK, "ret %08x\n", hr );
5178                     ok( !lstrcmpW( str, szAttribute ), "incorrect name string\n");
5179                     SysFreeString(str);
5180
5181                     hr = IXMLDOMAttribute_get_xml(pAttribute, &str);
5182                     ok(hr == S_OK, "ret %08x\n", hr );
5183                     ok( !lstrcmpW( str, szAttributeXML ), "incorrect attribute xml\n");
5184                     SysFreeString(str);
5185
5186                     IXMLDOMAttribute_Release(pAttribute);
5187
5188                     /* Check Element again with the Add Attribute*/
5189                     hr = IXMLDOMElement_get_xml(pElement, &str);
5190                     ok(hr == S_OK, "ret %08x\n", hr );
5191                     ok( !lstrcmpW( str, szElementXML2 ), "incorrect element xml\n");
5192                     SysFreeString(str);
5193                 }
5194
5195                 hr = IXMLDOMElement_put_text(pElement, _bstr_("TestingNode"));
5196                 ok(hr == S_OK, "ret %08x\n", hr );
5197
5198                 hr = IXMLDOMElement_get_xml(pElement, &str);
5199                 ok(hr == S_OK, "ret %08x\n", hr );
5200                 ok( !lstrcmpW( str, szElementXML3 ), "incorrect element xml\n");
5201                 SysFreeString(str);
5202
5203                 /* Test for reversible escaping */
5204                 str = SysAllocString( szStrangeChars );
5205                 hr = IXMLDOMElement_put_text(pElement, str);
5206                 ok(hr == S_OK, "ret %08x\n", hr );
5207                 SysFreeString( str );
5208
5209                 hr = IXMLDOMElement_get_xml(pElement, &str);
5210                 ok(hr == S_OK, "ret %08x\n", hr );
5211                 ok( !lstrcmpW( str, szElementXML4 ), "incorrect element xml\n");
5212                 SysFreeString(str);
5213
5214                 hr = IXMLDOMElement_get_text(pElement, &str);
5215                 ok(hr == S_OK, "ret %08x\n", hr );
5216                 ok( !lstrcmpW( str, szStrangeChars ), "incorrect element text\n");
5217                 SysFreeString(str);
5218
5219                 IXMLDOMElement_Release(pElement);
5220             }
5221
5222             /* CData Section */
5223             str = SysAllocString(szCData);
5224             hr = IXMLDOMDocument_createCDATASection(doc, str, NULL);
5225             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5226
5227             hr = IXMLDOMDocument_createCDATASection(doc, str, &pCDataSec);
5228             SysFreeString(str);
5229             ok(hr == S_OK, "ret %08x\n", hr );
5230             if(hr == S_OK)
5231             {
5232                 IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
5233                 VARIANT var;
5234
5235                 VariantInit(&var);
5236
5237                 hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (void**)&pElement);
5238                 ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
5239
5240                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pCDataSec, NULL);
5241                 ok(hr == S_OK, "ret %08x\n", hr );
5242
5243                 hr = IXMLDOMCDATASection_get_nodeName(pCDataSec, &str);
5244                 ok(hr == S_OK, "ret %08x\n", hr );
5245                 ok( !lstrcmpW( str, szCDataNodeText ), "incorrect cdata node Name\n");
5246                 SysFreeString(str);
5247
5248                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5249                 ok(hr == S_OK, "ret %08x\n", hr );
5250                 ok( !lstrcmpW( str, szCDataXML ), "incorrect cdata xml\n");
5251                 SysFreeString(str);
5252
5253                 /* test lastChild */
5254                 pNextChild = (IXMLDOMNode*)0x1;
5255                 hr = IXMLDOMCDATASection_get_lastChild(pCDataSec, &pNextChild);
5256                 ok(hr == S_FALSE, "ret %08x\n", hr );
5257                 ok(pNextChild == NULL, "pNextChild not NULL\n");
5258
5259                 /* put data Tests */
5260                 hr = IXMLDOMCDATASection_put_data(pCDataSec, _bstr_("This &is a ; test <>\\"));
5261                 ok(hr == S_OK, "ret %08x\n", hr );
5262
5263                 /* Confirm XML text is good */
5264                 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5265                 ok(hr == S_OK, "ret %08x\n", hr );
5266                 ok( !lstrcmpW( str, _bstr_("<![CDATA[This &is a ; test <>\\]]>") ), "incorrect xml string\n");
5267                 SysFreeString(str);
5268
5269                 /* Confirm we get the put_data Text back */
5270                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5271                 ok(hr == S_OK, "ret %08x\n", hr );
5272                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5273                 SysFreeString(str);
5274
5275                 /* test length property */
5276                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5277                 ok(hr == S_OK, "ret %08x\n", hr );
5278                 ok(len == 21, "expected 21 got %d\n", len);
5279
5280                 /* test get data */
5281                 hr = IXMLDOMCDATASection_get_data(pCDataSec, &str);
5282                 ok(hr == S_OK, "ret %08x\n", hr );
5283                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5284                 SysFreeString(str);
5285
5286                 /* test substringData */
5287                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, NULL);
5288                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5289
5290                 /* test substringData - Invalid offset */
5291                 str = (BSTR)&szElement;
5292                 hr = IXMLDOMCDATASection_substringData(pCDataSec, -1, 4, &str);
5293                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5294                 ok( str == NULL, "incorrect string\n");
5295
5296                 /* test substringData - Invalid offset */
5297                 str = (BSTR)&szElement;
5298                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 30, 0, &str);
5299                 ok(hr == S_FALSE, "ret %08x\n", hr );
5300                 ok( str == NULL, "incorrect string\n");
5301
5302                 /* test substringData - Invalid size */
5303                 str = (BSTR)&szElement;
5304                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, -1, &str);
5305                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5306                 ok( str == NULL, "incorrect string\n");
5307
5308                 /* test substringData - Invalid size */
5309                 str = (BSTR)&szElement;
5310                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 2, 0, &str);
5311                 ok(hr == S_FALSE, "ret %08x\n", hr );
5312                 ok( str == NULL, "incorrect string\n");
5313
5314                 /* test substringData - Start of string */
5315                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, &str);
5316                 ok(hr == S_OK, "ret %08x\n", hr );
5317                 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5318                 SysFreeString(str);
5319
5320                 /* test substringData - Middle of string */
5321                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 13, 4, &str);
5322                 ok(hr == S_OK, "ret %08x\n", hr );
5323                 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5324                 SysFreeString(str);
5325
5326                 /* test substringData - End of string */
5327                 hr = IXMLDOMCDATASection_substringData(pCDataSec, 20, 4, &str);
5328                 ok(hr == S_OK, "ret %08x\n", hr );
5329                 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5330                 SysFreeString(str);
5331
5332                 /* test appendData */
5333                 hr = IXMLDOMCDATASection_appendData(pCDataSec, NULL);
5334                 ok(hr == S_OK, "ret %08x\n", hr );
5335
5336                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_(""));
5337                 ok(hr == S_OK, "ret %08x\n", hr );
5338
5339                 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_("Append"));
5340                 ok(hr == S_OK, "ret %08x\n", hr );
5341
5342                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5343                 ok(hr == S_OK, "ret %08x\n", hr );
5344                 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5345                 SysFreeString(str);
5346
5347                 /* test insertData */
5348                 str = SysAllocStringLen(NULL, 0);
5349                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, str);
5350                 ok(hr == S_OK, "ret %08x\n", hr );
5351
5352                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, NULL);
5353                 ok(hr == S_OK, "ret %08x\n", hr );
5354
5355                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, str);
5356                 ok(hr == S_OK, "ret %08x\n", hr );
5357
5358                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, NULL);
5359                 ok(hr == S_OK, "ret %08x\n", hr );
5360
5361                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, NULL);
5362                 ok(hr == S_OK, "ret %08x\n", hr );
5363
5364                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, str);
5365                 ok(hr == S_OK, "ret %08x\n", hr );
5366                 SysFreeString(str);
5367
5368                 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, _bstr_("Inserting"));
5369                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5370
5371                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, _bstr_("Inserting"));
5372                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5373
5374                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("Begin "));
5375                 ok(hr == S_OK, "ret %08x\n", hr );
5376
5377                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 17, _bstr_("Middle"));
5378                 ok(hr == S_OK, "ret %08x\n", hr );
5379
5380                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 39, _bstr_(" End"));
5381                 ok(hr == S_OK, "ret %08x\n", hr );
5382
5383                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5384                 ok(hr == S_OK, "ret %08x\n", hr );
5385                 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5386                 SysFreeString(str);
5387
5388                 /* delete data */
5389                 /* invalid arguments */
5390                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, -1, 1);
5391                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5392
5393                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 0);
5394                 ok(hr == S_OK, "ret %08x\n", hr );
5395
5396                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, -1);
5397                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5398
5399                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5400                 ok(hr == S_OK, "ret %08x\n", hr );
5401                 ok(len == 43, "expected 43 got %d\n", len);
5402
5403                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len, 1);
5404                 ok(hr == S_OK, "ret %08x\n", hr );
5405
5406                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len+1, 1);
5407                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5408
5409                 /* delete from start */
5410                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 5);
5411                 ok(hr == S_OK, "ret %08x\n", hr );
5412
5413                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5414                 ok(hr == S_OK, "ret %08x\n", hr );
5415                 ok(len == 38, "expected 38 got %d\n", len);
5416
5417                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5418                 ok(hr == S_OK, "ret %08x\n", hr );
5419                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5420                 SysFreeString(str);
5421
5422                 /* delete from end */
5423                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 35, 3);
5424                 ok(hr == S_OK, "ret %08x\n", hr );
5425
5426                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5427                 ok(hr == S_OK, "ret %08x\n", hr );
5428                 ok(len == 35, "expected 35 got %d\n", len);
5429
5430                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5431                 ok(hr == S_OK, "ret %08x\n", hr );
5432                 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5433                 SysFreeString(str);
5434
5435                 /* delete from inside */
5436                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 1, 33);
5437                 ok(hr == S_OK, "ret %08x\n", hr );
5438
5439                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5440                 ok(hr == S_OK, "ret %08x\n", hr );
5441                 ok(len == 2, "expected 2 got %d\n", len);
5442
5443                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5444                 ok(hr == S_OK, "ret %08x\n", hr );
5445                 ok( !lstrcmpW( str, _bstr_("  ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5446                 SysFreeString(str);
5447
5448                 /* delete whole data ... */
5449                 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5450                 ok(hr == S_OK, "ret %08x\n", hr );
5451
5452                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
5453                 ok(hr == S_OK, "ret %08x\n", hr );
5454
5455                 /* ... and try again with empty string */
5456                 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
5457                 ok(hr == S_OK, "ret %08x\n", hr );
5458
5459                 /* ::replaceData() */
5460                 V_VT(&v) = VT_BSTR;
5461                 V_BSTR(&v) = SysAllocString(szstr1);
5462                 hr = IXMLDOMCDATASection_put_nodeValue(pCDataSec, v);
5463                 ok(hr == S_OK, "ret %08x\n", hr );
5464                 VariantClear(&v);
5465
5466                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 6, 0, NULL);
5467                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5468                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5469                 ok(hr == S_OK, "ret %08x\n", hr );
5470                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5471                 SysFreeString(str);
5472
5473                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, NULL);
5474                 ok(hr == S_OK, "ret %08x\n", hr );
5475                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5476                 ok(hr == S_OK, "ret %08x\n", hr );
5477                 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5478                 SysFreeString(str);
5479
5480                 /* NULL pointer means delete */
5481                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, NULL);
5482                 ok(hr == S_OK, "ret %08x\n", hr );
5483                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5484                 ok(hr == S_OK, "ret %08x\n", hr );
5485                 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5486                 SysFreeString(str);
5487
5488                 /* empty string means delete */
5489                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_(""));
5490                 ok(hr == S_OK, "ret %08x\n", hr );
5491                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5492                 ok(hr == S_OK, "ret %08x\n", hr );
5493                 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5494                 SysFreeString(str);
5495
5496                 /* zero count means insert */
5497                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, _bstr_("a"));
5498                 ok(hr == S_OK, "ret %08x\n", hr );
5499                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5500                 ok(hr == S_OK, "ret %08x\n", hr );
5501                 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5502                 SysFreeString(str);
5503
5504                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, NULL);
5505                 ok(hr == S_OK, "ret %08x\n", hr );
5506
5507                 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("m"));
5508                 ok(hr == S_OK, "ret %08x\n", hr );
5509                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5510                 ok(hr == S_OK, "ret %08x\n", hr );
5511                 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5512                 SysFreeString(str);
5513
5514                 /* nonempty string, count greater than its length */
5515                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, _bstr_("a1.2"));
5516                 ok(hr == S_OK, "ret %08x\n", hr );
5517                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5518                 ok(hr == S_OK, "ret %08x\n", hr );
5519                 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5520                 SysFreeString(str);
5521
5522                 /* nonempty string, count less than its length */
5523                 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_("wine"));
5524                 ok(hr == S_OK, "ret %08x\n", hr );
5525                 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5526                 ok(hr == S_OK, "ret %08x\n", hr );
5527                 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5528                 SysFreeString(str);
5529
5530                 IXMLDOMCDATASection_Release(pCDataSec);
5531             }
5532
5533             /* Document Fragments */
5534             hr = IXMLDOMDocument_createDocumentFragment(doc, NULL);
5535             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5536
5537             hr = IXMLDOMDocument_createDocumentFragment(doc, &pDocFrag);
5538             ok(hr == S_OK, "ret %08x\n", hr );
5539             if(hr == S_OK)
5540             {
5541                 IXMLDOMNode *node;
5542
5543                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, NULL);
5544                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5545
5546                 node = (IXMLDOMNode *)0x1;
5547                 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, &node);
5548                 ok(hr == S_FALSE, "ret %08x\n", hr );
5549                 ok(node == NULL, "expected NULL, got %p\n", node);
5550
5551                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pDocFrag, NULL);
5552                 ok(hr == S_OK, "ret %08x\n", hr );
5553
5554                 hr = IXMLDOMDocumentFragment_get_nodeName(pDocFrag, &str);
5555                 ok(hr == S_OK, "ret %08x\n", hr );
5556                 ok( !lstrcmpW( str, szDocFragmentText ), "incorrect docfragment node Name\n");
5557                 SysFreeString(str);
5558
5559                 /* test next Sibling*/
5560                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, NULL);
5561                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5562
5563                 node = (IXMLDOMNode *)0x1;
5564                 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &node);
5565                 ok(hr == S_FALSE, "ret %08x\n", hr );
5566                 ok(node == NULL, "next sibling not NULL\n");
5567
5568                 /* test Previous Sibling*/
5569                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, NULL);
5570                 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5571
5572                 node = (IXMLDOMNode *)0x1;
5573                 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &node);
5574                 ok(hr == S_FALSE, "ret %08x\n", hr );
5575                 ok(node == NULL, "previous sibling not NULL\n");
5576
5577                 IXMLDOMDocumentFragment_Release(pDocFrag);
5578             }
5579
5580             /* Entity References */
5581             hr = IXMLDOMDocument_createEntityReference(doc, NULL, &pEntityRef);
5582             ok(hr == E_FAIL, "ret %08x\n", hr );
5583             hr = IXMLDOMDocument_createEntityReference(doc, _bstr_(""), &pEntityRef);
5584             ok(hr == E_FAIL, "ret %08x\n", hr );
5585
5586             str = SysAllocString(szEntityRef);
5587             hr = IXMLDOMDocument_createEntityReference(doc, str, NULL);
5588             ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5589
5590             hr = IXMLDOMDocument_createEntityReference(doc, str, &pEntityRef);
5591             SysFreeString(str);
5592             ok(hr == S_OK, "ret %08x\n", hr );
5593             if(hr == S_OK)
5594             {
5595                 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pEntityRef, NULL);
5596                 ok(hr == S_OK, "ret %08x\n", hr );
5597
5598                 /* test get_xml*/
5599                 hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str);
5600                 ok(hr == S_OK, "ret %08x\n", hr );
5601                 ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n");
5602                 SysFreeString(str);
5603
5604                 IXMLDOMEntityReference_Release(pEntityRef);
5605             }
5606
5607             IXMLDOMElement_Release( pRoot );
5608         }
5609     }
5610
5611     IXMLDOMDocument_Release(doc);
5612
5613     free_bstrs();
5614 }
5615
5616 typedef struct {
5617     const char *name;
5618     const char *type;
5619     HRESULT hr;
5620 } put_datatype_t;
5621
5622 /* Type test for elements only. Name passed into put_dataType is case-insensitive.
5623    So many of the names have been changed to reflect this. */
5624 static put_datatype_t put_datatype_data[] = {
5625     { "test_inval",      "abcdefg",     E_FAIL },
5626     { "test_bool",       "Boolean",     S_OK },
5627     { "test_string",     "String",      S_OK },
5628     { "test_number",     "number",      S_OK },
5629     { "test_int",        "InT",         S_OK },
5630     { "test_fixed",      "fixed.14.4",  S_OK },
5631     { "test_datetime",   "DateTime",    S_OK },
5632     { "test_datetimetz", "DateTime.tz", S_OK },
5633     { "test_date",       "Date",        S_OK },
5634     { "test_time",       "Time",        S_OK },
5635     { "test_timetz",     "Time.tz",     S_OK },
5636     { "test_I1",         "I1",          S_OK },
5637     { "test_I2",         "I2",          S_OK },
5638     { "test_I4",         "I4",          S_OK },
5639     { "test_UI1",        "UI1",         S_OK },
5640     { "test_UI2",        "UI2",         S_OK },
5641     { "test_UI4",        "UI4",         S_OK },
5642     { "test_r4",         "r4",          S_OK },
5643     { "test_r8",         "r8",          S_OK },
5644     { "test_float",      "float",       S_OK },
5645     { "test_uuid",       "UuId",        S_OK },
5646     { "test_binhex",     "bin.hex",     S_OK },
5647     { "test_binbase64",  "bin.base64",  S_OK },
5648     { NULL }
5649 };
5650
5651 typedef struct {
5652     DOMNodeType type;
5653     HRESULT hr;
5654 } put_datatype_notype_t;
5655
5656 static put_datatype_notype_t put_dt_notype[] = {
5657     { NODE_PROCESSING_INSTRUCTION, E_FAIL },
5658     { NODE_DOCUMENT_FRAGMENT,      E_FAIL },
5659     { NODE_ENTITY_REFERENCE,       E_FAIL },
5660     { NODE_CDATA_SECTION,          E_FAIL },
5661     { NODE_COMMENT,                E_FAIL },
5662     { NODE_INVALID }
5663 };
5664
5665 static void test_put_dataType( void )
5666 {
5667     const put_datatype_notype_t *ptr2 = put_dt_notype;
5668     const put_datatype_t *ptr = put_datatype_data;
5669     IXMLDOMElement *root, *element;
5670     BSTR nameW, type1W, type2W;
5671     IXMLDOMDocument *doc;
5672     HRESULT hr;
5673
5674     doc = create_document(&IID_IXMLDOMDocument);
5675     if (!doc) return;
5676
5677     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), NULL);
5678     EXPECT_HR(hr, E_INVALIDARG);
5679
5680     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
5681     EXPECT_HR(hr, S_OK);
5682
5683     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
5684     EXPECT_HR(hr, S_OK);
5685
5686     hr = IXMLDOMElement_put_dataType(root, NULL);
5687     EXPECT_HR(hr, E_INVALIDARG);
5688
5689     while (ptr->name)
5690     {
5691         hr = IXMLDOMDocument_createElement(doc, _bstr_(ptr->name), &element);
5692         EXPECT_HR(hr, S_OK);
5693         if(hr == S_OK)
5694         {
5695             hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
5696             EXPECT_HR(hr, S_OK);
5697
5698             hr = IXMLDOMElement_put_dataType(element, _bstr_(ptr->type));
5699             ok(hr == ptr->hr, "failed for %s:%s, 0x%08x\n", ptr->name, ptr->type, ptr->hr);
5700
5701             IXMLDOMElement_Release(element);
5702         }
5703         ptr++;
5704     }
5705
5706     /* check changing types */
5707     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Change"), &element);
5708     EXPECT_HR(hr, S_OK);
5709
5710     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
5711     EXPECT_HR(hr, S_OK);
5712
5713     hr = IXMLDOMElement_put_dataType(element, _bstr_("DateTime.tz"));
5714     EXPECT_HR(hr, S_OK);
5715
5716     hr = IXMLDOMElement_put_dataType(element, _bstr_("string"));
5717     EXPECT_HR(hr, S_OK);
5718
5719     IXMLDOMElement_Release(element);
5720
5721     /* try to set type for node without a type */
5722     nameW  = _bstr_("testname");
5723     type1W = _bstr_("string");
5724     type2W = _bstr_("number");
5725     while (ptr2->type != NODE_INVALID)
5726     {
5727         IXMLDOMNode *node;
5728         VARIANT type;
5729
5730         V_VT(&type) = VT_I2;
5731         V_I2(&type) = ptr2->type;
5732
5733         hr = IXMLDOMDocument_createNode(doc, type, nameW, NULL, &node);
5734         EXPECT_HR(hr, S_OK);
5735         if(hr == S_OK)
5736         {
5737             hr = IXMLDOMElement_appendChild(root, node, NULL);
5738             EXPECT_HR(hr, S_OK);
5739
5740             hr = IXMLDOMNode_put_dataType(node, NULL);
5741             EXPECT_HR(hr, E_INVALIDARG);
5742
5743             hr = IXMLDOMNode_put_dataType(node, type1W);
5744             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
5745             hr = IXMLDOMNode_put_dataType(node, type2W);
5746             ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
5747
5748             IXMLDOMNode_Release(node);
5749         }
5750         ptr2++;
5751     }
5752
5753     IXMLDOMElement_Release(root);
5754     IXMLDOMDocument_Release(doc);
5755     free_bstrs();
5756 }
5757
5758 static void test_save(void)
5759 {
5760     IXMLDOMDocument *doc, *doc2;
5761     IXMLDOMElement *root;
5762     BSTR sOrig, sNew, filename;
5763     char buffer[100];
5764     IStream *stream;
5765     HGLOBAL global;
5766     VARIANT_BOOL b;
5767     DWORD read = 0;
5768     VARIANT dest;
5769     HANDLE hfile;
5770     HRESULT hr;
5771     char *ptr;
5772
5773     doc = create_document(&IID_IXMLDOMDocument);
5774     if (!doc) return;
5775
5776     doc2 = create_document(&IID_IXMLDOMDocument);
5777     if (!doc2)
5778     {
5779         IXMLDOMDocument_Release(doc);
5780         return;
5781     }
5782
5783     /* save to IXMLDOMDocument */
5784     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
5785     EXPECT_HR(hr, S_OK);
5786
5787     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
5788     EXPECT_HR(hr, S_OK);
5789
5790     V_VT(&dest) = VT_UNKNOWN;
5791     V_UNKNOWN(&dest) = (IUnknown*)doc2;
5792
5793     hr = IXMLDOMDocument_save(doc, dest);
5794     EXPECT_HR(hr, S_OK);
5795
5796     hr = IXMLDOMDocument_get_xml(doc, &sOrig);
5797     EXPECT_HR(hr, S_OK);
5798
5799     hr = IXMLDOMDocument_get_xml(doc2, &sNew);
5800     EXPECT_HR(hr, S_OK);
5801
5802     ok( !lstrcmpW( sOrig, sNew ), "New document is not the same as original\n");
5803
5804     SysFreeString(sOrig);
5805     SysFreeString(sNew);
5806
5807     IXMLDOMElement_Release(root);
5808     IXMLDOMDocument_Release(doc2);
5809
5810     /* save to path */
5811     V_VT(&dest) = VT_BSTR;
5812     V_BSTR(&dest) = _bstr_("test.xml");
5813
5814     hr = IXMLDOMDocument_save(doc, dest);
5815     EXPECT_HR(hr, S_OK);
5816
5817     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
5818     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
5819     if(hfile == INVALID_HANDLE_VALUE) return;
5820
5821     ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
5822     ok(read != 0, "could not read file\n");
5823     ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
5824
5825     CloseHandle(hfile);
5826     DeleteFile("test.xml");
5827
5828     /* save to path VT_BSTR | VT_BYREF */
5829     filename = _bstr_("test.xml");
5830     V_VT(&dest) = VT_BSTR | VT_BYREF;
5831     V_BSTRREF(&dest) = &filename;
5832
5833     hr = IXMLDOMDocument_save(doc, dest);
5834     EXPECT_HR(hr, S_OK);
5835
5836     hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
5837     ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
5838     if(hfile == INVALID_HANDLE_VALUE) return;
5839
5840     if (hfile != INVALID_HANDLE_VALUE)
5841     {
5842        ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
5843        ok(read != 0, "could not read file\n");
5844        ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
5845
5846        CloseHandle(hfile);
5847        DeleteFile("test.xml");
5848     }
5849
5850     /* save to stream */
5851     V_VT(&dest) = VT_UNKNOWN;
5852     V_UNKNOWN(&dest) = (IUnknown*)&savestream;
5853
5854     hr = IXMLDOMDocument_save(doc, dest);
5855     EXPECT_HR(hr, S_OK);
5856
5857     /* loaded data contains xml declaration */
5858     hr = IXMLDOMDocument_loadXML(doc, _bstr_(win1252xml), &b);
5859     EXPECT_HR(hr, S_OK);
5860
5861     CreateStreamOnHGlobal(NULL, TRUE, &stream);
5862     V_VT(&dest) = VT_UNKNOWN;
5863     V_UNKNOWN(&dest) = (IUnknown*)stream;
5864     hr = IXMLDOMDocument_save(doc, dest);
5865     EXPECT_HR(hr, S_OK);
5866
5867     hr = GetHGlobalFromStream(stream, &global);
5868     EXPECT_HR(hr, S_OK);
5869     ptr = GlobalLock(global);
5870     ok(!memcmp(ptr, win1252decl, strlen(win1252decl)), "got wrong xml declaration\n");
5871     GlobalUnlock(global);
5872     IStream_Release(stream);
5873
5874     /* loaded data without xml declaration */
5875     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<a/>"), &b);
5876     EXPECT_HR(hr, S_OK);
5877
5878     CreateStreamOnHGlobal(NULL, TRUE, &stream);
5879     V_VT(&dest) = VT_UNKNOWN;
5880     V_UNKNOWN(&dest) = (IUnknown*)stream;
5881     hr = IXMLDOMDocument_save(doc, dest);
5882     EXPECT_HR(hr, S_OK);
5883
5884     hr = GetHGlobalFromStream(stream, &global);
5885     EXPECT_HR(hr, S_OK);
5886     ptr = GlobalLock(global);
5887     ok(ptr[0] == '<' && ptr[1] != '?', "got wrong start tag %c%c\n", ptr[0], ptr[1]);
5888     GlobalUnlock(global);
5889     IStream_Release(stream);
5890
5891     IXMLDOMDocument_Release(doc);
5892     free_bstrs();
5893 }
5894
5895 static void test_testTransforms(void)
5896 {
5897     IXMLDOMDocument *doc, *docSS;
5898     IXMLDOMNode *pNode;
5899     VARIANT_BOOL bSucc;
5900
5901     HRESULT hr;
5902
5903     doc = create_document(&IID_IXMLDOMDocument);
5904     if (!doc) return;
5905
5906     docSS = create_document(&IID_IXMLDOMDocument);
5907     if (!docSS)
5908     {
5909         IXMLDOMDocument_Release(doc);
5910         return;
5911     }
5912
5913     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &bSucc);
5914     ok(hr == S_OK, "ret %08x\n", hr );
5915
5916     hr = IXMLDOMDocument_loadXML(docSS, _bstr_(szTransformSSXML), &bSucc);
5917     ok(hr == S_OK, "ret %08x\n", hr );
5918
5919     hr = IXMLDOMDocument_QueryInterface(docSS, &IID_IXMLDOMNode, (void**)&pNode );
5920     ok(hr == S_OK, "ret %08x\n", hr );
5921     if(hr == S_OK)
5922     {
5923         BSTR bOut;
5924
5925         hr = IXMLDOMDocument_transformNode(doc, pNode, &bOut);
5926         ok(hr == S_OK, "ret %08x\n", hr );
5927         if(hr == S_OK)
5928         {
5929             ok( compareIgnoreReturns( bOut, _bstr_(szTransformOutput)), "Stylesheet output not correct\n");
5930             SysFreeString(bOut);
5931         }
5932
5933         IXMLDOMNode_Release(pNode);
5934     }
5935
5936     IXMLDOMDocument_Release(docSS);
5937     IXMLDOMDocument_Release(doc);
5938
5939     free_bstrs();
5940 }
5941
5942 struct namespaces_change_t {
5943     const CLSID *clsid;
5944     const char *name;
5945 };
5946
5947 static const struct namespaces_change_t namespaces_change_test_data[] = {
5948     { &CLSID_DOMDocument,   "CLSID_DOMDocument"   },
5949     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2"  },
5950     { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
5951     { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
5952     { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
5953     { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
5954     { 0 }
5955 };
5956
5957 static void test_namespaces_change(void)
5958 {
5959     const struct namespaces_change_t *class_ptr = namespaces_change_test_data;
5960
5961     while (class_ptr->clsid)
5962     {
5963         IXMLDOMDocument *doc = NULL;
5964         IXMLDOMElement *elem = NULL;
5965         IXMLDOMNode *node = NULL;
5966
5967         VARIANT var;
5968         HRESULT hr;
5969         BSTR str;
5970
5971         hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
5972                               &IID_IXMLDOMDocument, (void**)&doc);
5973         if (hr != S_OK)
5974         {
5975             win_skip("failed to create class instance for %s\n", class_ptr->name);
5976             class_ptr++;
5977             continue;
5978         }
5979
5980         V_VT(&var) = VT_I2;
5981         V_I2(&var) = NODE_ELEMENT;
5982
5983         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("ns:elem"), _bstr_("ns/uri"), &node);
5984         EXPECT_HR(hr, S_OK);
5985
5986         hr = IXMLDOMDocument_appendChild(doc, node, NULL);
5987         EXPECT_HR(hr, S_OK);
5988
5989         hr = IXMLDOMDocument_get_documentElement(doc, &elem);
5990         EXPECT_HR(hr, S_OK);
5991
5992         /* try same prefix, different uri */
5993         V_VT(&var) = VT_BSTR;
5994         V_BSTR(&var) = _bstr_("ns/uri2");
5995
5996         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
5997         EXPECT_HR(hr, E_INVALIDARG);
5998
5999         /* try same prefix and uri */
6000         V_VT(&var) = VT_BSTR;
6001         V_BSTR(&var) = _bstr_("ns/uri");
6002
6003         hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6004         EXPECT_HR(hr, S_OK);
6005
6006         hr = IXMLDOMElement_get_xml(elem, &str);
6007         EXPECT_HR(hr, S_OK);
6008         ok(!lstrcmpW(str, _bstr_("<ns:elem xmlns:ns=\"ns/uri\"/>")), "got element %s for %s\n",
6009            wine_dbgstr_w(str), class_ptr->name);
6010         SysFreeString(str);
6011
6012         IXMLDOMElement_Release(elem);
6013         IXMLDOMDocument_Release(doc);
6014
6015         free_bstrs();
6016
6017         class_ptr++;
6018     }
6019 }
6020
6021 static void test_namespaces_basic(void)
6022 {
6023     static const CHAR namespaces_xmlA[] =
6024         "<?xml version=\"1.0\"?>\n"
6025         "<XMI xmi.version=\"1.1\" xmlns:Model=\"http://omg.org/mof.Model/1.3\">"
6026         "  <XMI.content>"
6027         "    <Model:Package name=\"WinePackage\" Model:name2=\"name2 attr\" />"
6028         "  </XMI.content>"
6029         "</XMI>";
6030
6031     IXMLDOMDocument *doc;
6032     IXMLDOMElement *elem;
6033     IXMLDOMNode *node;
6034
6035     VARIANT_BOOL b;
6036     HRESULT hr;
6037     BSTR str;
6038
6039     doc = create_document(&IID_IXMLDOMDocument);
6040     if (!doc) return;
6041
6042     hr = IXMLDOMDocument_loadXML(doc, _bstr_(namespaces_xmlA), &b);
6043     EXPECT_HR(hr, S_OK);
6044     ok(b == VARIANT_TRUE, "got %d\n", b);
6045
6046     str = (BSTR)0xdeadbeef;
6047     hr = IXMLDOMDocument_get_namespaceURI(doc, &str);
6048     EXPECT_HR(hr, S_FALSE);
6049     ok(str == NULL, "got %p\n", str);
6050
6051     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("//XMI.content"), &node );
6052     EXPECT_HR(hr, S_OK);
6053     if(hr == S_OK)
6054     {
6055         IXMLDOMAttribute *attr;
6056         IXMLDOMNode *node2;
6057
6058         hr = IXMLDOMNode_get_firstChild(node, &node2);
6059         EXPECT_HR(hr, S_OK);
6060         ok(node2 != NULL, "got %p\n", node2);
6061
6062         /* Test get_prefix */
6063         hr = IXMLDOMNode_get_prefix(node2, NULL);
6064         EXPECT_HR(hr, E_INVALIDARG);
6065         /* NOTE: Need to test that arg2 gets cleared on Error. */
6066
6067         hr = IXMLDOMNode_get_prefix(node2, &str);
6068         EXPECT_HR(hr, S_OK);
6069         ok( !lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6070         SysFreeString(str);
6071
6072         hr = IXMLDOMNode_get_nodeName(node2, &str);
6073         EXPECT_HR(hr, S_OK);
6074         ok(!lstrcmpW( str, _bstr_("Model:Package")), "got %s\n", wine_dbgstr_w(str));
6075         SysFreeString(str);
6076
6077         /* Test get_namespaceURI */
6078         hr = IXMLDOMNode_get_namespaceURI(node2, NULL);
6079         EXPECT_HR(hr, E_INVALIDARG);
6080         /* NOTE: Need to test that arg2 gets cleared on Error. */
6081
6082         hr = IXMLDOMNode_get_namespaceURI(node2, &str);
6083         EXPECT_HR(hr, S_OK);
6084         ok(!lstrcmpW( str, _bstr_("http://omg.org/mof.Model/1.3")), "got %s\n", wine_dbgstr_w(str));
6085         SysFreeString(str);
6086
6087         hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&elem);
6088         EXPECT_HR(hr, S_OK);
6089
6090         hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("Model:name2"), &attr);
6091         EXPECT_HR(hr, S_OK);
6092
6093         hr = IXMLDOMAttribute_get_nodeName(attr, &str);
6094         EXPECT_HR(hr, S_OK);
6095         ok(!lstrcmpW( str, _bstr_("Model:name2")), "got %s\n", wine_dbgstr_w(str));
6096         SysFreeString(str);
6097
6098         hr = IXMLDOMAttribute_get_prefix(attr, &str);
6099         EXPECT_HR(hr, S_OK);
6100         ok(!lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6101         SysFreeString(str);
6102
6103         IXMLDOMAttribute_Release(attr);
6104         IXMLDOMElement_Release(elem);
6105
6106         IXMLDOMNode_Release(node2);
6107         IXMLDOMNode_Release(node);
6108     }
6109
6110     IXMLDOMDocument_Release(doc);
6111
6112     free_bstrs();
6113 }
6114
6115 static void test_FormattingXML(void)
6116 {
6117     IXMLDOMDocument *doc;
6118     IXMLDOMElement *pElement;
6119     VARIANT_BOOL bSucc;
6120     HRESULT hr;
6121     BSTR str;
6122     static const CHAR szLinefeedXML[] = "<?xml version=\"1.0\"?>\n<Root>\n\t<Sub val=\"A\" />\n</Root>";
6123     static const CHAR szLinefeedRootXML[] = "<Root>\r\n\t<Sub val=\"A\"/>\r\n</Root>";
6124
6125     doc = create_document(&IID_IXMLDOMDocument);
6126     if (!doc) return;
6127
6128     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szLinefeedXML), &bSucc);
6129     ok(hr == S_OK, "ret %08x\n", hr );
6130     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6131
6132     if(bSucc == VARIANT_TRUE)
6133     {
6134         hr = IXMLDOMDocument_get_documentElement(doc, &pElement);
6135         ok(hr == S_OK, "ret %08x\n", hr );
6136         if(hr == S_OK)
6137         {
6138             hr = IXMLDOMElement_get_xml(pElement, &str);
6139             ok(hr == S_OK, "ret %08x\n", hr );
6140             ok( !lstrcmpW( str, _bstr_(szLinefeedRootXML) ), "incorrect element xml\n");
6141             SysFreeString(str);
6142
6143             IXMLDOMElement_Release(pElement);
6144         }
6145     }
6146
6147     IXMLDOMDocument_Release(doc);
6148
6149     free_bstrs();
6150 }
6151
6152 typedef struct _nodetypedvalue_t {
6153     const char *name;
6154     VARTYPE type;
6155     const char *value; /* value in string format */
6156 } nodetypedvalue_t;
6157
6158 static const nodetypedvalue_t get_nodetypedvalue[] = {
6159     { "root/string",    VT_BSTR, "Wine" },
6160     { "root/string2",   VT_BSTR, "String" },
6161     { "root/number",    VT_BSTR, "12.44" },
6162     { "root/number2",   VT_BSTR, "-3.71e3" },
6163     { "root/int",       VT_I4,   "-13" },
6164     { "root/fixed",     VT_CY,   "7322.9371" },
6165     { "root/bool",      VT_BOOL, "-1" },
6166     { "root/datetime",  VT_DATE, "40135.14" },
6167     { "root/datetimetz",VT_DATE, "37813.59" },
6168     { "root/date",      VT_DATE, "665413" },
6169     { "root/time",      VT_DATE, "0.5813889" },
6170     { "root/timetz",    VT_DATE, "1.112512" },
6171     { "root/i1",        VT_I1,   "-13" },
6172     { "root/i2",        VT_I2,   "31915" },
6173     { "root/i4",        VT_I4,   "-312232" },
6174     { "root/ui1",       VT_UI1,  "123" },
6175     { "root/ui2",       VT_UI2,  "48282" },
6176     { "root/ui4",       VT_UI4,  "949281" },
6177     { "root/r4",        VT_R4,   "213124" },
6178     { "root/r8",        VT_R8,   "0.412" },
6179     { "root/float",     VT_R8,   "41221.421" },
6180     { "root/uuid",      VT_BSTR, "333C7BC4-460F-11D0-BC04-0080C7055a83" },
6181     { "root/binbase64", VT_ARRAY|VT_UI1, "base64 test" },
6182     { "root/binbase64_1", VT_ARRAY|VT_UI1, "base64 test" },
6183     { "root/binbase64_2", VT_ARRAY|VT_UI1, "base64 test" },
6184     { 0 }
6185 };
6186
6187 static void test_nodeTypedValue(void)
6188 {
6189     const nodetypedvalue_t *entry = get_nodetypedvalue;
6190     IXMLDOMDocumentType *doctype, *doctype2;
6191     IXMLDOMProcessingInstruction *pi;
6192     IXMLDOMDocumentFragment *frag;
6193     IXMLDOMDocument *doc, *doc2;
6194     IXMLDOMCDATASection *cdata;
6195     IXMLDOMComment *comment;
6196     IXMLDOMNode *node;
6197     VARIANT_BOOL b;
6198     VARIANT value;
6199     HRESULT hr;
6200
6201     doc = create_document(&IID_IXMLDOMDocument);
6202     if (!doc) return;
6203
6204     b = VARIANT_FALSE;
6205     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &b);
6206     ok(hr == S_OK, "ret %08x\n", hr );
6207     ok(b == VARIANT_TRUE, "got %d\n", b);
6208
6209     hr = IXMLDOMDocument_get_nodeValue(doc, NULL);
6210     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6211
6212     V_VT(&value) = VT_BSTR;
6213     V_BSTR(&value) = NULL;
6214     hr = IXMLDOMDocument_get_nodeValue(doc, &value);
6215     ok(hr == S_FALSE, "ret %08x\n", hr );
6216     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6217
6218     hr = IXMLDOMDocument_get_nodeTypedValue(doc, NULL);
6219     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6220
6221     V_VT(&value) = VT_EMPTY;
6222     hr = IXMLDOMDocument_get_nodeTypedValue(doc, &value);
6223     ok(hr == S_FALSE, "ret %08x\n", hr );
6224     ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6225
6226     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/string"), &node);
6227     ok(hr == S_OK, "ret %08x\n", hr );
6228
6229     V_VT(&value) = VT_BSTR;
6230     V_BSTR(&value) = NULL;
6231     hr = IXMLDOMNode_get_nodeValue(node, &value);
6232     ok(hr == S_FALSE, "ret %08x\n", hr );
6233     ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6234
6235     hr = IXMLDOMNode_get_nodeTypedValue(node, NULL);
6236     ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6237
6238     IXMLDOMNode_Release(node);
6239
6240     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/binhex"), &node);
6241     ok(hr == S_OK, "ret %08x\n", hr );
6242     {
6243         BYTE bytes[] = {0xff,0xfc,0xa0,0x12,0x00,0x3c};
6244
6245         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6246         ok(hr == S_OK, "ret %08x\n", hr );
6247         ok(V_VT(&value) == (VT_ARRAY|VT_UI1), "incorrect type\n");
6248         ok(V_ARRAY(&value)->rgsabound[0].cElements == 6, "incorrect array size\n");
6249         if(V_ARRAY(&value)->rgsabound[0].cElements == 6)
6250             ok(!memcmp(bytes, V_ARRAY(&value)->pvData, sizeof(bytes)), "incorrect value\n");
6251         VariantClear(&value);
6252         IXMLDOMNode_Release(node);
6253     }
6254
6255     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("foo"), _bstr_("value"), &pi);
6256     ok(hr == S_OK, "ret %08x\n", hr );
6257     {
6258         V_VT(&value) = VT_NULL;
6259         V_BSTR(&value) = (void*)0xdeadbeef;
6260         hr = IXMLDOMProcessingInstruction_get_nodeTypedValue(pi, &value);
6261         ok(hr == S_OK, "ret %08x\n", hr );
6262         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6263         ok(!lstrcmpW(V_BSTR(&value), _bstr_("value")), "got wrong value\n");
6264         IXMLDOMProcessingInstruction_Release(pi);
6265         VariantClear(&value);
6266     }
6267
6268     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("[1]*2=3; &gee that's not right!"), &cdata);
6269     ok(hr == S_OK, "ret %08x\n", hr );
6270     {
6271         V_VT(&value) = VT_NULL;
6272         V_BSTR(&value) = (void*)0xdeadbeef;
6273         hr = IXMLDOMCDATASection_get_nodeTypedValue(cdata, &value);
6274         ok(hr == S_OK, "ret %08x\n", hr );
6275         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6276         ok(!lstrcmpW(V_BSTR(&value), _bstr_("[1]*2=3; &gee that's not right!")), "got wrong value\n");
6277         IXMLDOMCDATASection_Release(cdata);
6278         VariantClear(&value);
6279     }
6280
6281     hr = IXMLDOMDocument_createComment(doc, _bstr_("comment"), &comment);
6282     ok(hr == S_OK, "ret %08x\n", hr );
6283     {
6284         V_VT(&value) = VT_NULL;
6285         V_BSTR(&value) = (void*)0xdeadbeef;
6286         hr = IXMLDOMComment_get_nodeTypedValue(comment, &value);
6287         ok(hr == S_OK, "ret %08x\n", hr );
6288         ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6289         ok(!lstrcmpW(V_BSTR(&value), _bstr_("comment")), "got wrong value\n");
6290         IXMLDOMComment_Release(comment);
6291         VariantClear(&value);
6292     }
6293
6294     hr = IXMLDOMDocument_createDocumentFragment(doc, &frag);
6295     ok(hr == S_OK, "ret %08x\n", hr );
6296     {
6297         V_VT(&value) = VT_EMPTY;
6298         hr = IXMLDOMDocumentFragment_get_nodeTypedValue(frag, &value);
6299         ok(hr == S_FALSE, "ret %08x\n", hr );
6300         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6301         IXMLDOMDocumentFragment_Release(frag);
6302     }
6303
6304     doc2 = create_document(&IID_IXMLDOMDocument);
6305
6306     b = VARIANT_FALSE;
6307     hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szEmailXML), &b);
6308     ok(hr == S_OK, "ret %08x\n", hr );
6309     ok(b == VARIANT_TRUE, "got %d\n", b);
6310
6311     EXPECT_REF(doc2, 1);
6312
6313     hr = IXMLDOMDocument_get_doctype(doc2, &doctype);
6314     ok(hr == S_OK, "ret %08x\n", hr );
6315
6316     EXPECT_REF(doc2, 1);
6317     todo_wine EXPECT_REF(doctype, 2);
6318
6319     {
6320         V_VT(&value) = VT_EMPTY;
6321         hr = IXMLDOMDocumentType_get_nodeTypedValue(doctype, &value);
6322         ok(hr == S_FALSE, "ret %08x\n", hr );
6323         ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6324     }
6325
6326     hr = IXMLDOMDocument_get_doctype(doc2, &doctype2);
6327     ok(hr == S_OK, "ret %08x\n", hr );
6328     ok(doctype != doctype2, "got %p, was %p\n", doctype2, doctype);
6329
6330     IXMLDOMDocumentType_Release(doctype2);
6331     IXMLDOMDocumentType_Release(doctype);
6332
6333     IXMLDOMDocument_Release(doc2);
6334
6335     while (entry->name)
6336     {
6337         hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_(entry->name), &node);
6338         ok(hr == S_OK, "ret %08x\n", hr );
6339
6340         hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6341         ok(hr == S_OK, "ret %08x\n", hr );
6342         ok(V_VT(&value) == entry->type, "incorrect type, expected %d, got %d\n", entry->type, V_VT(&value));
6343
6344         if (entry->type == (VT_ARRAY|VT_UI1))
6345         {
6346             ok(V_ARRAY(&value)->rgsabound[0].cElements == strlen(entry->value),
6347                "incorrect array size %d\n", V_ARRAY(&value)->rgsabound[0].cElements);
6348         }
6349
6350         if (entry->type != VT_BSTR)
6351         {
6352            if (entry->type == VT_DATE ||
6353                entry->type == VT_R8 ||
6354                entry->type == VT_CY)
6355            {
6356                if (entry->type == VT_DATE)
6357                {
6358                    hr = VariantChangeType(&value, &value, 0, VT_R4);
6359                    ok(hr == S_OK, "ret %08x\n", hr );
6360                }
6361                hr = VariantChangeTypeEx(&value, &value,
6362                                         MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT),
6363                                         VARIANT_NOUSEROVERRIDE, VT_BSTR);
6364                ok(hr == S_OK, "ret %08x\n", hr );
6365            }
6366            else
6367            {
6368                hr = VariantChangeType(&value, &value, 0, VT_BSTR);
6369                ok(hr == S_OK, "ret %08x\n", hr );
6370            }
6371
6372            /* for byte array from VT_ARRAY|VT_UI1 it's not a WCHAR buffer */
6373            if (entry->type == (VT_ARRAY|VT_UI1))
6374            {
6375                ok(!memcmp( V_BSTR(&value), entry->value, strlen(entry->value)),
6376                   "expected %s\n", entry->value);
6377            }
6378            else
6379                ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
6380                   "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
6381         }
6382         else
6383            ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
6384                "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
6385
6386         VariantClear( &value );
6387         IXMLDOMNode_Release(node);
6388
6389         entry++;
6390     }
6391
6392     IXMLDOMDocument_Release(doc);
6393     free_bstrs();
6394 }
6395
6396 static void test_TransformWithLoadingLocalFile(void)
6397 {
6398     IXMLDOMDocument *doc;
6399     IXMLDOMDocument *xsl;
6400     IXMLDOMNode *pNode;
6401     VARIANT_BOOL bSucc;
6402     HRESULT hr;
6403     HANDLE file;
6404     DWORD dwWritten;
6405     char lpPathBuffer[MAX_PATH];
6406     int i;
6407
6408     /* Create a Temp File. */
6409     GetTempPathA(MAX_PATH, lpPathBuffer);
6410     strcat(lpPathBuffer, "customers.xml" );
6411
6412     file = CreateFileA(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
6413     ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
6414     if(file == INVALID_HANDLE_VALUE)
6415         return;
6416
6417     WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL);
6418     CloseHandle(file);
6419
6420     /* Correct path to not include a escape character. */
6421     for(i=0; i < strlen(lpPathBuffer); i++)
6422     {
6423         if(lpPathBuffer[i] == '\\')
6424             lpPathBuffer[i] = '/';
6425     }
6426
6427     doc = create_document(&IID_IXMLDOMDocument);
6428     if (!doc) return;
6429
6430     xsl = create_document(&IID_IXMLDOMDocument);
6431     if (!xsl)
6432     {
6433         IXMLDOMDocument_Release(doc);
6434         return;
6435     }
6436
6437     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &bSucc);
6438     ok(hr == S_OK, "ret %08x\n", hr );
6439     ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6440     if(bSucc == VARIANT_TRUE)
6441     {
6442         BSTR sXSL;
6443         BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1);
6444         BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2);
6445         BSTR sFileName = _bstr_(lpPathBuffer);
6446         int nLegnth = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1;
6447
6448         sXSL = SysAllocStringLen(NULL, nLegnth);
6449         lstrcpyW(sXSL, sPart1);
6450         lstrcatW(sXSL, sFileName);
6451         lstrcatW(sXSL, sPart2);
6452
6453         hr = IXMLDOMDocument_loadXML(xsl, sXSL, &bSucc);
6454         ok(hr == S_OK, "ret %08x\n", hr );
6455         ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6456         if(bSucc == VARIANT_TRUE)
6457         {
6458             BSTR sResult;
6459
6460             hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (void**)&pNode );
6461             ok(hr == S_OK, "ret %08x\n", hr );
6462             if(hr == S_OK)
6463             {
6464                 /* This will load the temp file via the XSL */
6465                 hr = IXMLDOMDocument_transformNode(doc, pNode, &sResult);
6466                 ok(hr == S_OK, "ret %08x\n", hr );
6467                 if(hr == S_OK)
6468                 {
6469                     ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n");
6470                     SysFreeString(sResult);
6471                 }
6472
6473                 IXMLDOMNode_Release(pNode);
6474             }
6475         }
6476
6477         SysFreeString(sXSL);
6478     }
6479
6480     IXMLDOMDocument_Release(doc);
6481     IXMLDOMDocument_Release(xsl);
6482
6483     DeleteFile(lpPathBuffer);
6484     free_bstrs();
6485 }
6486
6487 static void test_put_nodeValue(void)
6488 {
6489     static const WCHAR jeevesW[] = {'J','e','e','v','e','s',' ','&',' ','W','o','o','s','t','e','r',0};
6490     IXMLDOMDocument *doc;
6491     IXMLDOMText *text;
6492     IXMLDOMEntityReference *entityref;
6493     IXMLDOMAttribute *attr;
6494     IXMLDOMNode *node;
6495     HRESULT hr;
6496     VARIANT data, type;
6497
6498     doc = create_document(&IID_IXMLDOMDocument);
6499     if (!doc) return;
6500
6501     /* test for unsupported types */
6502     /* NODE_DOCUMENT */
6503     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&node);
6504     ok(hr == S_OK, "ret %08x\n", hr );
6505     V_VT(&data) = VT_BSTR;
6506     V_BSTR(&data) = _bstr_("one two three");
6507     hr = IXMLDOMNode_put_nodeValue(node, data);
6508     ok(hr == E_FAIL, "ret %08x\n", hr );
6509     IXMLDOMNode_Release(node);
6510
6511     /* NODE_DOCUMENT_FRAGMENT */
6512     V_VT(&type) = VT_I1;
6513     V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
6514     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
6515     ok(hr == S_OK, "ret %08x\n", hr );
6516     V_VT(&data) = VT_BSTR;
6517     V_BSTR(&data) = _bstr_("one two three");
6518     hr = IXMLDOMNode_put_nodeValue(node, data);
6519     ok(hr == E_FAIL, "ret %08x\n", hr );
6520     IXMLDOMNode_Release(node);
6521
6522     /* NODE_ELEMENT */
6523     V_VT(&type) = VT_I1;
6524     V_I1(&type) = NODE_ELEMENT;
6525     hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
6526     ok(hr == S_OK, "ret %08x\n", hr );
6527     V_VT(&data) = VT_BSTR;
6528     V_BSTR(&data) = _bstr_("one two three");
6529     hr = IXMLDOMNode_put_nodeValue(node, data);
6530     ok(hr == E_FAIL, "ret %08x\n", hr );
6531     IXMLDOMNode_Release(node);
6532
6533     /* NODE_ENTITY_REFERENCE */
6534     hr = IXMLDOMDocument_createEntityReference(doc, _bstr_("ref"), &entityref);
6535     ok(hr == S_OK, "ret %08x\n", hr );
6536
6537     V_VT(&data) = VT_BSTR;
6538     V_BSTR(&data) = _bstr_("one two three");
6539     hr = IXMLDOMEntityReference_put_nodeValue(entityref, data);
6540     ok(hr == E_FAIL, "ret %08x\n", hr );
6541
6542     hr = IXMLDOMEntityReference_QueryInterface(entityref, &IID_IXMLDOMNode, (void**)&node);
6543     ok(hr == S_OK, "ret %08x\n", hr );
6544     V_VT(&data) = VT_BSTR;
6545     V_BSTR(&data) = _bstr_("one two three");
6546     hr = IXMLDOMNode_put_nodeValue(node, data);
6547     ok(hr == E_FAIL, "ret %08x\n", hr );
6548     IXMLDOMNode_Release(node);
6549     IXMLDOMEntityReference_Release(entityref);
6550
6551     /* supported types */
6552     hr = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &text);
6553     ok(hr == S_OK, "ret %08x\n", hr );
6554     V_VT(&data) = VT_BSTR;
6555     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
6556     hr = IXMLDOMText_put_nodeValue(text, data);
6557     ok(hr == S_OK, "ret %08x\n", hr );
6558     IXMLDOMText_Release(text);
6559
6560     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
6561     ok(hr == S_OK, "ret %08x\n", hr );
6562     V_VT(&data) = VT_BSTR;
6563     V_BSTR(&data) = _bstr_("Jeeves & Wooster");
6564     hr = IXMLDOMAttribute_put_nodeValue(attr, data);
6565     ok(hr == S_OK, "ret %08x\n", hr );
6566     hr = IXMLDOMAttribute_get_nodeValue(attr, &data);
6567     ok(hr == S_OK, "ret %08x\n", hr );
6568     ok(memcmp(V_BSTR(&data), jeevesW, sizeof(jeevesW)) == 0, "got %s\n",
6569         wine_dbgstr_w(V_BSTR(&data)));
6570     VariantClear(&data);
6571     IXMLDOMAttribute_Release(attr);
6572
6573     free_bstrs();
6574
6575     IXMLDOMDocument_Release(doc);
6576 }
6577
6578 static void test_IObjectSafety(void)
6579 {
6580     IXMLDOMDocument *doc;
6581     IObjectSafety *safety;
6582     HRESULT hr;
6583
6584     doc = create_document(&IID_IXMLDOMDocument);
6585     if (!doc) return;
6586
6587     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IObjectSafety, (void**)&safety);
6588     ok(hr == S_OK, "ret %08x\n", hr );
6589
6590     test_IObjectSafety_common(safety);
6591
6592     IObjectSafety_Release(safety);
6593     IXMLDOMDocument_Release(doc);
6594
6595     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
6596         &IID_IObjectSafety, (void**)&safety);
6597     ok(hr == S_OK, "Could not create XMLHTTPRequest instance: %08x\n", hr);
6598
6599     test_IObjectSafety_common(safety);
6600
6601     IObjectSafety_Release(safety);
6602
6603 }
6604
6605 typedef struct _property_test_t {
6606     const GUID *guid;
6607     const char *clsid;
6608     const char *property;
6609     const char *value;
6610 } property_test_t;
6611
6612 static const property_test_t properties_test_data[] = {
6613     { &CLSID_DOMDocument,  "CLSID_DOMDocument" , "SelectionLanguage", "XSLPattern" },
6614     { &CLSID_DOMDocument2,  "CLSID_DOMDocument2" , "SelectionLanguage", "XSLPattern" },
6615     { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "SelectionLanguage", "XSLPattern" },
6616     { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "SelectionLanguage", "XPath" },
6617     { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "SelectionLanguage", "XPath" },
6618     { 0 }
6619 };
6620
6621 static void test_default_properties(void)
6622 {
6623     const property_test_t *entry = properties_test_data;
6624
6625     while (entry->guid)
6626     {
6627         IXMLDOMDocument2 *doc;
6628         VARIANT var;
6629         HRESULT hr;
6630
6631         hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
6632         if (hr != S_OK)
6633         {
6634             win_skip("can't create %s instance\n", entry->clsid);
6635             entry++;
6636             continue;
6637         }
6638
6639         hr = IXMLDOMDocument2_getProperty(doc, _bstr_(entry->property), &var);
6640         ok(hr == S_OK, "got 0x%08x\n", hr);
6641         ok(lstrcmpW(V_BSTR(&var), _bstr_(entry->value)) == 0, "expected %s, for %s\n",
6642            entry->value, entry->clsid);
6643         VariantClear(&var);
6644
6645         IXMLDOMDocument2_Release(doc);
6646
6647         entry++;
6648     }
6649 }
6650
6651 typedef struct {
6652     const char *query;
6653     const char *list;
6654 } xslpattern_test_t;
6655
6656 static const xslpattern_test_t xslpattern_test[] = {
6657     { "root//elem[0]", "E1.E2.D1" },
6658     { "root//elem[index()=1]", "E2.E2.D1" },
6659     { "root//elem[index() $eq$ 1]", "E2.E2.D1" },
6660     { "root//elem[end()]", "E4.E2.D1" },
6661     { "root//elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
6662     { "root//elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
6663     { "root//elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
6664     { "root//elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
6665     { "root//elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
6666     { "root//elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
6667     { "root//elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
6668     { "root//elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
6669     { "root//elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
6670     { "root//elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
6671     { "root//elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
6672     { "root//elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
6673     { "root//elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
6674     { "root//elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
6675     { "root//elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
6676     { "root//elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
6677     { "root//elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
6678     { "root//elem[$any$ *='B2 field']", "E2.E2.D1" },
6679     { "root//elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
6680     { "root//elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
6681     { "root//elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
6682     { "root//elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
6683     { "root//elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6684     { "root//elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6685     { "root//elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6686     { "root/elem[0]", "E1.E2.D1" },
6687     { "root/elem[index()=1]", "E2.E2.D1" },
6688     { "root/elem[index() $eq$ 1]", "E2.E2.D1" },
6689     { "root/elem[end()]", "E4.E2.D1" },
6690     { "root/elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
6691     { "root/elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
6692     { "root/elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
6693     { "root/elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
6694     { "root/elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
6695     { "root/elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
6696     { "root/elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
6697     { "root/elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
6698     { "root/elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
6699     { "root/elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
6700     { "root/elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
6701     { "root/elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
6702     { "root/elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
6703     { "root/elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
6704     { "root/elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
6705     { "root/elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
6706     { "root/elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
6707     { "root/elem[$any$ *='B2 field']", "E2.E2.D1" },
6708     { "root/elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
6709     { "root/elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
6710     { "root/elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
6711     { "root/elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
6712     { "root/elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6713     { "root/elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6714     { "root/elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
6715     { "root/elem[d]", "E1.E2.D1 E2.E2.D1 E4.E2.D1" },
6716     { NULL }
6717 };
6718
6719 static const xslpattern_test_t xslpattern_test_no_ns[] = {
6720     /* prefixes don't need to be registered, you may use them as they are in the doc */
6721     { "//bar:x", "E5.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1" },
6722     /* prefixes must be explicitly specified in the name */
6723     { "//foo:elem", "" },
6724     { "//foo:c", "E3.E4.E2.D1" },
6725     { NULL }
6726 };
6727
6728 static const xslpattern_test_t xslpattern_test_func[] = {
6729     { "attribute()", "" },
6730     { "attribute('depth')", "" },
6731     { "root/attribute('depth')", "A'depth'.E3.D1" },
6732     { "//x/attribute()", "A'id'.E3.E3.D1 A'depth'.E3.E3.D1" },
6733     { "//x//attribute(id)", NULL },
6734     { "//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" },
6735     { "comment()", "C2.D1" },
6736     { "//comment()", "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1" },
6737     { "element()", "E3.D1" },
6738     { "root/y/element()", "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1" },
6739     { "//element(a)", NULL },
6740     { "//element('a')", "E4.E3.E3.D1 E4.E4.E3.D1" },
6741     { "node()", "P1.D1 C2.D1 E3.D1" },
6742     { "//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" },
6743     { "//x/node()[nodeType()=1]", "E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
6744     { "//x/node()[nodeType()=3]", "T3.E3.E3.D1" },
6745     { "//x/node()[nodeType()=7]", "P1.E3.E3.D1" },
6746     { "//x/node()[nodeType()=8]", "C2.E3.E3.D1" },
6747     { "pi()", "P1.D1" },
6748     { "//y/pi()", "P1.E4.E3.D1" },
6749     { "root/textnode()", "T2.E3.D1" },
6750     { "root/element()/textnode()", "T3.E3.E3.D1 T3.E4.E3.D1" },
6751     { NULL }
6752 };
6753
6754 static void test_XSLPattern(void)
6755 {
6756     const xslpattern_test_t *ptr = xslpattern_test;
6757     IXMLDOMDocument2 *doc;
6758     IXMLDOMNodeList *list;
6759     VARIANT_BOOL b;
6760     HRESULT hr;
6761     LONG len;
6762
6763     doc = create_document(&IID_IXMLDOMDocument2);
6764     if (!doc) return;
6765
6766     b = VARIANT_FALSE;
6767     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
6768     EXPECT_HR(hr, S_OK);
6769     ok(b == VARIANT_TRUE, "failed to load XML string\n");
6770
6771     /* switch to XSLPattern */
6772     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern"));
6773     EXPECT_HR(hr, S_OK);
6774
6775     /* XPath doesn't select elements with non-null default namespace with unqualified selectors, XSLPattern does */
6776     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem/c"), &list);
6777     EXPECT_HR(hr, S_OK);
6778
6779     len = 0;
6780     hr = IXMLDOMNodeList_get_length(list, &len);
6781     EXPECT_HR(hr, S_OK);
6782     /* should select <elem><c> and <elem xmlns='...'><c> but not <elem><foo:c> */
6783     ok(len == 3, "expected 3 entries in list, got %d\n", len);
6784     IXMLDOMNodeList_Release(list);
6785
6786     while (ptr->query)
6787     {
6788         list = NULL;
6789         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
6790         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
6791         len = 0;
6792         hr = IXMLDOMNodeList_get_length(list, &len);
6793         ok(len != 0, "query=%s, empty list\n", ptr->query);
6794         if (len)
6795             expect_list_and_release(list, ptr->list);
6796
6797         ptr++;
6798     }
6799
6800     /* namespace handling */
6801     /* no registered namespaces */
6802     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_(""));
6803     EXPECT_HR(hr, S_OK);
6804
6805     ptr = xslpattern_test_no_ns;
6806     while (ptr->query)
6807     {
6808         list = NULL;
6809         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
6810         ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
6811
6812         if (*ptr->list)
6813         {
6814             len = 0;
6815             hr = IXMLDOMNodeList_get_length(list, &len);
6816             EXPECT_HR(hr, S_OK);
6817             ok(len != 0, "query=%s, empty list\n", ptr->query);
6818         }
6819         else
6820         {
6821             len = 1;
6822             hr = IXMLDOMNodeList_get_length(list, &len);
6823             EXPECT_HR(hr, S_OK);
6824             ok(len == 0, "query=%s, empty list\n", ptr->query);
6825         }
6826         if (len)
6827             expect_list_and_release(list, ptr->list);
6828
6829         ptr++;
6830     }
6831
6832     /* explicitly register prefix foo */
6833     ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
6834
6835     /* now we get the same behavior as XPath */
6836     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
6837     EXPECT_HR(hr, S_OK);
6838     len = 0;
6839     hr = IXMLDOMNodeList_get_length(list, &len);
6840     EXPECT_HR(hr, S_OK);
6841     ok(len != 0, "expected filled list\n");
6842     if (len)
6843         expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
6844
6845     /* set prefix foo to some nonexistent namespace */
6846     hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:nonexistent-foo'"));
6847     EXPECT_HR(hr, S_OK);
6848
6849     /* the registered prefix takes precedence */
6850     hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
6851     EXPECT_HR(hr, S_OK);
6852     len = 0;
6853     hr = IXMLDOMNodeList_get_length(list, &len);
6854     EXPECT_HR(hr, S_OK);
6855     ok(len == 0, "expected empty list\n");
6856     IXMLDOMNodeList_Release(list);
6857
6858     IXMLDOMDocument2_Release(doc);
6859
6860     doc = create_document(&IID_IXMLDOMDocument2);
6861     if (!doc) return;
6862
6863     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szNodeTypesXML), &b);
6864     EXPECT_HR(hr, S_OK);
6865     ok(b == VARIANT_TRUE, "failed to load XML string\n");
6866
6867     ptr = xslpattern_test_func;
6868     while (ptr->query)
6869     {
6870         list = NULL;
6871         hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
6872         if (ptr->list)
6873         {
6874             ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
6875             len = 0;
6876             hr = IXMLDOMNodeList_get_length(list, &len);
6877             if (*ptr->list)
6878             {
6879                 ok(len != 0, "query=%s, empty list\n", ptr->query);
6880                 if (len)
6881                     expect_list_and_release(list, ptr->list);
6882             }
6883             else
6884                 ok(len == 0, "query=%s, filled list\n", ptr->query);
6885         }
6886         else
6887             ok(hr == E_FAIL, "query=%s, failed with 0x%08x\n", ptr->query, hr);
6888
6889         ptr++;
6890     }
6891
6892     IXMLDOMDocument2_Release(doc);
6893     free_bstrs();
6894 }
6895
6896 static void test_splitText(void)
6897 {
6898     IXMLDOMCDATASection *cdata;
6899     IXMLDOMElement *root;
6900     IXMLDOMDocument *doc;
6901     IXMLDOMText *text, *text2;
6902     IXMLDOMNode *node;
6903     VARIANT var;
6904     VARIANT_BOOL success;
6905     LONG length;
6906     HRESULT hr;
6907
6908     doc = create_document(&IID_IXMLDOMDocument);
6909     if (!doc) return;
6910
6911     hr = IXMLDOMDocument_loadXML(doc, _bstr_("<root></root>"), &success);
6912     ok(hr == S_OK, "got 0x%08x\n", hr);
6913
6914     hr = IXMLDOMDocument_get_documentElement(doc, &root);
6915     ok(hr == S_OK, "got 0x%08x\n", hr);
6916
6917     hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("beautiful plumage"), &cdata);
6918     ok(hr == S_OK, "got 0x%08x\n", hr);
6919
6920     V_VT(&var) = VT_EMPTY;
6921     hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)cdata, NULL);
6922     ok(hr == S_OK, "got 0x%08x\n", hr);
6923
6924     length = 0;
6925     hr = IXMLDOMCDATASection_get_length(cdata, &length);
6926     ok(hr == S_OK, "got 0x%08x\n", hr);
6927     ok(length > 0, "got %d\n", length);
6928
6929     hr = IXMLDOMCDATASection_splitText(cdata, 0, NULL);
6930     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6931
6932     text = (void*)0xdeadbeef;
6933     /* negative offset */
6934     hr = IXMLDOMCDATASection_splitText(cdata, -1, &text);
6935     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6936     ok(text == (void*)0xdeadbeef, "got %p\n", text);
6937
6938     text = (void*)0xdeadbeef;
6939     /* offset outside data */
6940     hr = IXMLDOMCDATASection_splitText(cdata, length + 1, &text);
6941     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6942     ok(text == 0, "got %p\n", text);
6943
6944     text = (void*)0xdeadbeef;
6945     /* offset outside data */
6946     hr = IXMLDOMCDATASection_splitText(cdata, length, &text);
6947     ok(hr == S_FALSE, "got 0x%08x\n", hr);
6948     ok(text == 0, "got %p\n", text);
6949
6950     /* no empty node created */
6951     node = (void*)0xdeadbeef;
6952     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
6953     ok(hr == S_FALSE, "got 0x%08x\n", hr);
6954     ok(node == 0, "got %p\n", text);
6955
6956     hr = IXMLDOMCDATASection_splitText(cdata, 10, &text);
6957     ok(hr == S_OK, "got 0x%08x\n", hr);
6958
6959     length = 0;
6960     hr = IXMLDOMText_get_length(text, &length);
6961     ok(hr == S_OK, "got 0x%08x\n", hr);
6962     ok(length == 7, "got %d\n", length);
6963
6964     hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
6965     ok(hr == S_OK, "got 0x%08x\n", hr);
6966     IXMLDOMNode_Release(node);
6967
6968     /* split new text node */
6969     hr = IXMLDOMText_get_length(text, &length);
6970     ok(hr == S_OK, "got 0x%08x\n", hr);
6971
6972     node = (void*)0xdeadbeef;
6973     hr = IXMLDOMText_get_nextSibling(text, &node);
6974     ok(hr == S_FALSE, "got 0x%08x\n", hr);
6975     ok(node == 0, "got %p\n", text);
6976
6977     hr = IXMLDOMText_splitText(text, 0, NULL);
6978     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6979
6980     text2 = (void*)0xdeadbeef;
6981     /* negative offset */
6982     hr = IXMLDOMText_splitText(text, -1, &text2);
6983     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6984     ok(text2 == (void*)0xdeadbeef, "got %p\n", text2);
6985
6986     text2 = (void*)0xdeadbeef;
6987     /* offset outside data */
6988     hr = IXMLDOMText_splitText(text, length + 1, &text2);
6989     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
6990     ok(text2 == 0, "got %p\n", text2);
6991
6992     text2 = (void*)0xdeadbeef;
6993     /* offset outside data */
6994     hr = IXMLDOMText_splitText(text, length, &text2);
6995     ok(hr == S_FALSE, "got 0x%08x\n", hr);
6996     ok(text2 == 0, "got %p\n", text);
6997
6998     text2 = 0;
6999     hr = IXMLDOMText_splitText(text, 4, &text2);
7000     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7001     if (text2) IXMLDOMText_Release(text2);
7002
7003     node = 0;
7004     hr = IXMLDOMText_get_nextSibling(text, &node);
7005     todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7006     if (node) IXMLDOMNode_Release(node);
7007
7008     IXMLDOMText_Release(text);
7009     IXMLDOMElement_Release(root);
7010     IXMLDOMCDATASection_Release(cdata);
7011     free_bstrs();
7012 }
7013
7014 typedef struct {
7015     const char *name;
7016     const char *uri;
7017     HRESULT hr;
7018 } ns_item_t;
7019
7020 /* default_ns_doc used */
7021 static const ns_item_t qualified_item_tests[] = {
7022     { "xml:lang", NULL, S_FALSE },
7023     { "xml:lang", "http://www.w3.org/XML/1998/namespace", S_FALSE },
7024     { "lang", "http://www.w3.org/XML/1998/namespace", S_OK },
7025     { "ns:b", NULL, S_FALSE },
7026     { "ns:b", "nshref", S_FALSE },
7027     { "b", "nshref", S_OK },
7028     { "d", NULL, S_OK },
7029     { NULL }
7030 };
7031
7032 static const ns_item_t named_item_tests[] = {
7033     { "xml:lang", NULL, S_OK },
7034     { "lang", NULL, S_FALSE },
7035     { "ns:b", NULL, S_OK },
7036     { "b", NULL, S_FALSE },
7037     { "d", NULL, S_OK },
7038     { NULL }
7039 };
7040
7041 static void test_getQualifiedItem(void)
7042 {
7043     IXMLDOMNode *pr_node, *node;
7044     IXMLDOMNodeList *root_list;
7045     IXMLDOMNamedNodeMap *map;
7046     IXMLDOMElement *element;
7047     const ns_item_t* ptr;
7048     IXMLDOMDocument *doc;
7049     VARIANT_BOOL b;
7050     HRESULT hr;
7051     LONG len;
7052
7053     doc = create_document(&IID_IXMLDOMDocument);
7054     if (!doc) return;
7055
7056     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7057     EXPECT_HR(hr, S_OK);
7058     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7059
7060     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7061     EXPECT_HR(hr, S_OK);
7062
7063     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7064     EXPECT_HR(hr, S_OK);
7065
7066     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7067     EXPECT_HR(hr, S_OK);
7068     IXMLDOMNodeList_Release(root_list);
7069
7070     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7071     EXPECT_HR(hr, S_OK);
7072     IXMLDOMNode_Release(pr_node);
7073
7074     len = 0;
7075     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7076     EXPECT_HR(hr, S_OK);
7077     ok( len == 3, "length %d\n", len);
7078
7079     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, NULL);
7080     EXPECT_HR(hr, E_INVALIDARG);
7081
7082     node = (void*)0xdeadbeef;
7083     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, &node);
7084     EXPECT_HR(hr, E_INVALIDARG);
7085     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7086
7087     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, NULL);
7088     EXPECT_HR(hr, E_INVALIDARG);
7089
7090     hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, &node);
7091     EXPECT_HR(hr, S_OK);
7092
7093     IXMLDOMNode_Release(node);
7094     IXMLDOMNamedNodeMap_Release(map);
7095     IXMLDOMElement_Release(element);
7096
7097     hr = IXMLDOMDocument_loadXML(doc, _bstr_(default_ns_doc), &b);
7098     EXPECT_HR(hr, S_OK);
7099
7100     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
7101     EXPECT_HR(hr, S_OK);
7102
7103     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
7104     EXPECT_HR(hr, S_OK);
7105     IXMLDOMNode_Release(node);
7106
7107     hr = IXMLDOMElement_get_attributes(element, &map);
7108     EXPECT_HR(hr, S_OK);
7109
7110     ptr = qualified_item_tests;
7111     while (ptr->name)
7112     {
7113        node = (void*)0xdeadbeef;
7114        hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
7115        ok(hr == ptr->hr, "%s, %s: got 0x%08x, expected 0x%08x\n", ptr->name, ptr->uri, hr, ptr->hr);
7116        if (hr == S_OK)
7117            IXMLDOMNode_Release(node);
7118        else
7119            ok(node == NULL, "%s, %s: got %p\n", ptr->name, ptr->uri, node);
7120        ptr++;
7121     }
7122
7123     ptr = named_item_tests;
7124     while (ptr->name)
7125     {
7126        node = (void*)0xdeadbeef;
7127        hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_(ptr->name), &node);
7128        ok(hr == ptr->hr, "%s: got 0x%08x, expected 0x%08x\n", ptr->name, hr, ptr->hr);
7129        if (hr == S_OK)
7130            IXMLDOMNode_Release(node);
7131        else
7132            ok(node == NULL, "%s: got %p\n", ptr->name, node);
7133        ptr++;
7134     }
7135
7136     IXMLDOMNamedNodeMap_Release(map);
7137
7138     IXMLDOMElement_Release(element);
7139     IXMLDOMDocument_Release(doc);
7140     free_bstrs();
7141 }
7142
7143 static void test_removeQualifiedItem(void)
7144 {
7145     IXMLDOMDocument *doc;
7146     IXMLDOMElement *element;
7147     IXMLDOMNode *pr_node, *node;
7148     IXMLDOMNodeList *root_list;
7149     IXMLDOMNamedNodeMap *map;
7150     VARIANT_BOOL b;
7151     LONG len;
7152     HRESULT hr;
7153
7154     doc = create_document(&IID_IXMLDOMDocument);
7155     if (!doc) return;
7156
7157     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7158     ok( hr == S_OK, "loadXML failed\n");
7159     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7160
7161     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7162     ok( hr == S_OK, "ret %08x\n", hr);
7163
7164     hr = IXMLDOMElement_get_childNodes(element, &root_list);
7165     ok( hr == S_OK, "ret %08x\n", hr);
7166
7167     hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7168     ok( hr == S_OK, "ret %08x\n", hr);
7169     IXMLDOMNodeList_Release(root_list);
7170
7171     hr = IXMLDOMNode_get_attributes(pr_node, &map);
7172     ok( hr == S_OK, "ret %08x\n", hr);
7173     IXMLDOMNode_Release(pr_node);
7174
7175     hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7176     ok( hr == S_OK, "ret %08x\n", hr);
7177     ok( len == 3, "length %d\n", len);
7178
7179     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, NULL);
7180     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7181
7182     node = (void*)0xdeadbeef;
7183     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, &node);
7184     ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7185     ok( node == (void*)0xdeadbeef, "got %p\n", node);
7186
7187     /* out pointer is optional */
7188     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7189     ok( hr == S_OK, "ret %08x\n", hr);
7190
7191     /* already removed */
7192     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7193     ok( hr == S_FALSE, "ret %08x\n", hr);
7194
7195     hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("vr"), NULL, &node);
7196     ok( hr == S_OK, "ret %08x\n", hr);
7197     IXMLDOMNode_Release(node);
7198
7199     IXMLDOMNamedNodeMap_Release( map );
7200     IXMLDOMElement_Release( element );
7201     IXMLDOMDocument_Release( doc );
7202     free_bstrs();
7203 }
7204
7205 #define check_default_props(doc) _check_default_props(__LINE__, doc)
7206 static inline void _check_default_props(int line, IXMLDOMDocument2* doc)
7207 {
7208     VARIANT_BOOL b;
7209     VARIANT var;
7210     HRESULT hr;
7211
7212     VariantInit(&var);
7213     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7214     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XSLPattern")) == 0, "expected XSLPattern\n");
7215     VariantClear(&var);
7216
7217     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7218     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("")) == 0, "expected empty string\n");
7219     VariantClear(&var);
7220
7221     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7222     ok_(__FILE__, line)(b == VARIANT_FALSE, "expected FALSE\n");
7223
7224     hr = IXMLDOMDocument2_get_schemas(doc, &var);
7225     ok_(__FILE__, line)(hr == S_FALSE, "got %08x\n", hr);
7226     VariantClear(&var);
7227 }
7228
7229 #define check_set_props(doc) _check_set_props(__LINE__, doc)
7230 static inline void _check_set_props(int line, IXMLDOMDocument2* doc)
7231 {
7232     VARIANT_BOOL b;
7233     VARIANT var;
7234
7235     VariantInit(&var);
7236     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7237     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XPath")) == 0, "expected XPath\n");
7238     VariantClear(&var);
7239
7240     helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7241     ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
7242     VariantClear(&var);
7243
7244     helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7245     ok_(__FILE__, line)(b == VARIANT_TRUE, "expected TRUE\n");
7246
7247     helper_ole_check(IXMLDOMDocument2_get_schemas(doc, &var));
7248     ok_(__FILE__, line)(V_VT(&var) != VT_NULL, "expected pointer\n");
7249     VariantClear(&var);
7250 }
7251
7252 #define set_props(doc, cache) _set_props(__LINE__, doc, cache)
7253 static inline void _set_props(int line, IXMLDOMDocument2* doc, IXMLDOMSchemaCollection* cache)
7254 {
7255     VARIANT var;
7256
7257     VariantInit(&var);
7258     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
7259     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:wi=\'www.winehq.org\'")));
7260     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_TRUE));
7261     V_VT(&var) = VT_DISPATCH;
7262     V_DISPATCH(&var) = NULL;
7263     helper_ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&var)));
7264     ok_(__FILE__, line)(V_DISPATCH(&var) != NULL, "expected pointer\n");
7265     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7266     VariantClear(&var);
7267 }
7268
7269 #define unset_props(doc) _unset_props(__LINE__, doc)
7270 static inline void _unset_props(int line, IXMLDOMDocument2* doc)
7271 {
7272     VARIANT var;
7273
7274     VariantInit(&var);
7275     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
7276     helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("")));
7277     helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_FALSE));
7278     V_VT(&var) = VT_NULL;
7279     helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7280     VariantClear(&var);
7281 }
7282
7283 static void test_get_ownerDocument(void)
7284 {
7285     IXMLDOMDocument *doc1, *doc2, *doc3;
7286     IXMLDOMDocument2 *doc, *doc_owner;
7287     IXMLDOMNode *node;
7288     IXMLDOMSchemaCollection *cache;
7289     VARIANT_BOOL b;
7290     VARIANT var;
7291
7292     doc = create_document(&IID_IXMLDOMDocument2);
7293     cache = create_cache(&IID_IXMLDOMSchemaCollection);
7294     if (!doc || !cache)
7295     {
7296         if (doc) IXMLDOMDocument2_Release(doc);
7297         if (cache) IXMLDOMSchemaCollection_Release(cache);
7298         return;
7299     }
7300
7301     VariantInit(&var);
7302
7303     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7304     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7305
7306     check_default_props(doc);
7307
7308     /* set properties and check that new instances use them */
7309     set_props(doc, cache);
7310     check_set_props(doc);
7311
7312     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7313     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc1));
7314
7315     /* new interface keeps props */
7316     ole_check(IXMLDOMDocument_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7317     ok( doc_owner != doc, "got %p, doc %p\n", doc_owner, doc);
7318     check_set_props(doc_owner);
7319     IXMLDOMDocument2_Release(doc_owner);
7320
7321     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc2));
7322     IXMLDOMNode_Release(node);
7323
7324     ok(doc1 != doc2, "got %p, expected %p. original %p\n", doc2, doc1, doc);
7325
7326     /* reload */
7327     ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7328     ok(b == VARIANT_TRUE, "failed to load XML string\n");
7329
7330     /* properties retained even after reload */
7331     check_set_props(doc);
7332
7333     ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7334     ole_check(IXMLDOMNode_get_ownerDocument(node, &doc3));
7335     IXMLDOMNode_Release(node);
7336
7337     ole_check(IXMLDOMDocument_QueryInterface(doc3, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7338     ok(doc3 != doc1 && doc3 != doc2 && doc_owner != doc, "got %p, (%p, %p, %p)\n", doc3, doc, doc1, doc2);
7339     check_set_props(doc_owner);
7340
7341     /* changing properties for one instance changes them for all */
7342     unset_props(doc_owner);
7343     check_default_props(doc_owner);
7344     check_default_props(doc);
7345
7346     IXMLDOMSchemaCollection_Release(cache);
7347     IXMLDOMDocument_Release(doc1);
7348     IXMLDOMDocument_Release(doc2);
7349     IXMLDOMDocument_Release(doc3);
7350     IXMLDOMDocument2_Release(doc);
7351     IXMLDOMDocument2_Release(doc_owner);
7352     free_bstrs();
7353 }
7354
7355 static void test_setAttributeNode(void)
7356 {
7357     IXMLDOMDocument *doc, *doc2;
7358     IXMLDOMElement *elem, *elem2;
7359     IXMLDOMAttribute *attr, *attr2, *ret_attr;
7360     VARIANT_BOOL b;
7361     HRESULT hr;
7362     VARIANT v;
7363     BSTR str;
7364     ULONG ref1, ref2;
7365
7366     doc = create_document(&IID_IXMLDOMDocument);
7367     if (!doc) return;
7368
7369     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7370     ok( hr == S_OK, "loadXML failed\n");
7371     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7372
7373     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
7374     ok( hr == S_OK, "got 0x%08x\n", hr);
7375
7376     hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
7377     ok( hr == S_OK, "got 0x%08x\n", hr);
7378     ok( elem2 != elem, "got same instance\n");
7379
7380     ret_attr = (void*)0xdeadbeef;
7381     hr = IXMLDOMElement_setAttributeNode(elem, NULL, &ret_attr);
7382     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
7383     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
7384
7385     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
7386     ok( hr == S_OK, "got 0x%08x\n", hr);
7387
7388     ref1 = IXMLDOMElement_AddRef(elem);
7389     IXMLDOMElement_Release(elem);
7390
7391     ret_attr = (void*)0xdeadbeef;
7392     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
7393     ok( hr == S_OK, "got 0x%08x\n", hr);
7394     ok( ret_attr == NULL, "got %p\n", ret_attr);
7395
7396     /* no reference added */
7397     ref2 = IXMLDOMElement_AddRef(elem);
7398     IXMLDOMElement_Release(elem);
7399     ok(ref2 == ref1, "got %d, expected %d\n", ref2, ref1);
7400
7401     EXPECT_CHILDREN(elem);
7402     EXPECT_CHILDREN(elem2);
7403
7404     IXMLDOMElement_Release(elem2);
7405
7406     attr2 = NULL;
7407     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attr"), &attr2);
7408     ok( hr == S_OK, "got 0x%08x\n", hr);
7409     ok( attr2 != attr, "got same instance %p\n", attr2);
7410     IXMLDOMAttribute_Release(attr2);
7411
7412     /* try to add it another time */
7413     ret_attr = (void*)0xdeadbeef;
7414     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
7415     ok( hr == E_FAIL, "got 0x%08x\n", hr);
7416     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
7417
7418     IXMLDOMElement_Release(elem);
7419
7420     /* initially used element is released, attribute still 'has' a container */
7421     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
7422     ok( hr == S_OK, "got 0x%08x\n", hr);
7423     ret_attr = (void*)0xdeadbeef;
7424     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
7425     ok( hr == E_FAIL, "got 0x%08x\n", hr);
7426     ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
7427     IXMLDOMElement_Release(elem);
7428
7429     /* add attribute already attached to another document */
7430     doc2 = create_document(&IID_IXMLDOMDocument);
7431
7432     hr = IXMLDOMDocument_loadXML( doc2, _bstr_(complete4A), &b );
7433     ok( hr == S_OK, "loadXML failed\n");
7434     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7435
7436     hr = IXMLDOMDocument_get_documentElement(doc2, &elem);
7437     ok( hr == S_OK, "got 0x%08x\n", hr);
7438     hr = IXMLDOMElement_setAttributeNode(elem, attr, NULL);
7439     ok( hr == E_FAIL, "got 0x%08x\n", hr);
7440     IXMLDOMElement_Release(elem);
7441
7442     IXMLDOMAttribute_Release(attr);
7443
7444     /* create element, add attribute, see if it's copied or linked */
7445     hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
7446     ok( hr == S_OK, "got 0x%08x\n", hr);
7447
7448     attr = NULL;
7449     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
7450     ok(hr == S_OK, "got 0x%08x\n", hr);
7451     ok(attr != NULL, "got %p\n", attr);
7452
7453     ref1 = IXMLDOMAttribute_AddRef(attr);
7454     IXMLDOMAttribute_Release(attr);
7455
7456     V_VT(&v) = VT_BSTR;
7457     V_BSTR(&v) = _bstr_("attrvalue1");
7458     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
7459     ok( hr == S_OK, "got 0x%08x\n", hr);
7460
7461     str = NULL;
7462     hr = IXMLDOMAttribute_get_xml(attr, &str);
7463     ok( hr == S_OK, "got 0x%08x\n", hr);
7464     ok( lstrcmpW(str, _bstr_("attr=\"attrvalue1\"")) == 0,
7465         "got %s\n", wine_dbgstr_w(str));
7466     SysFreeString(str);
7467
7468     ret_attr = (void*)0xdeadbeef;
7469     hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
7470     ok(hr == S_OK, "got 0x%08x\n", hr);
7471     ok(ret_attr == NULL, "got %p\n", ret_attr);
7472
7473     /* attribute reference increased */
7474     ref2 = IXMLDOMAttribute_AddRef(attr);
7475     IXMLDOMAttribute_Release(attr);
7476     ok(ref1 == ref2, "got %d, expected %d\n", ref2, ref1);
7477
7478     hr = IXMLDOMElement_get_xml(elem, &str);
7479     ok( hr == S_OK, "got 0x%08x\n", hr);
7480     ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue1\"/>")) == 0,
7481         "got %s\n", wine_dbgstr_w(str));
7482     SysFreeString(str);
7483
7484     V_VT(&v) = VT_BSTR;
7485     V_BSTR(&v) = _bstr_("attrvalue2");
7486     hr = IXMLDOMAttribute_put_nodeValue(attr, v);
7487     ok( hr == S_OK, "got 0x%08x\n", hr);
7488
7489     hr = IXMLDOMElement_get_xml(elem, &str);
7490     ok( hr == S_OK, "got 0x%08x\n", hr);
7491     todo_wine ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue2\"/>")) == 0,
7492         "got %s\n", wine_dbgstr_w(str));
7493     SysFreeString(str);
7494
7495     IXMLDOMElement_Release(elem);
7496     IXMLDOMAttribute_Release(attr);
7497     IXMLDOMDocument_Release(doc2);
7498     IXMLDOMDocument_Release(doc);
7499     free_bstrs();
7500 }
7501
7502 static void test_createNode(void)
7503 {
7504     IXMLDOMDocument *doc;
7505     IXMLDOMElement *elem;
7506     IXMLDOMNode *node;
7507     VARIANT v, var;
7508     BSTR prefix, str;
7509     HRESULT hr;
7510     ULONG ref;
7511
7512     doc = create_document(&IID_IXMLDOMDocument);
7513     if (!doc) return;
7514
7515     EXPECT_REF(doc, 1);
7516
7517     /* reference count tests */
7518     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
7519     ok( hr == S_OK, "got 0x%08x\n", hr);
7520
7521     /* initial reference is 2 */
7522 todo_wine {
7523     EXPECT_REF(elem, 2);
7524     ref = IXMLDOMElement_Release(elem);
7525     ok(ref == 1, "got %d\n", ref);
7526     /* it's released already, attempt to release now will crash it */
7527 }
7528
7529     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
7530     ok( hr == S_OK, "got 0x%08x\n", hr);
7531     todo_wine EXPECT_REF(elem, 2);
7532     IXMLDOMDocument_Release(doc);
7533     todo_wine EXPECT_REF(elem, 2);
7534     IXMLDOMElement_Release(elem);
7535
7536     doc = create_document(&IID_IXMLDOMDocument);
7537
7538     /* NODE_ELEMENT nodes */
7539     /* 1. specified namespace */
7540     V_VT(&v) = VT_I4;
7541     V_I4(&v) = NODE_ELEMENT;
7542
7543     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("ns1:test"), _bstr_("http://winehq.org"), &node);
7544     ok( hr == S_OK, "got 0x%08x\n", hr);
7545     prefix = NULL;
7546     hr = IXMLDOMNode_get_prefix(node, &prefix);
7547     ok( hr == S_OK, "got 0x%08x\n", hr);
7548     ok(lstrcmpW(prefix, _bstr_("ns1")) == 0, "wrong prefix\n");
7549     SysFreeString(prefix);
7550     IXMLDOMNode_Release(node);
7551
7552     /* 2. default namespace */
7553     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("test"), _bstr_("http://winehq.org/default"), &node);
7554     ok( hr == S_OK, "got 0x%08x\n", hr);
7555     prefix = (void*)0xdeadbeef;
7556     hr = IXMLDOMNode_get_prefix(node, &prefix);
7557     ok( hr == S_FALSE, "got 0x%08x\n", hr);
7558     ok(prefix == 0, "expected empty prefix, got %p\n", prefix);
7559     /* check dump */
7560     hr = IXMLDOMNode_get_xml(node, &str);
7561     ok( hr == S_OK, "got 0x%08x\n", hr);
7562     ok( lstrcmpW(str, _bstr_("<test xmlns=\"http://winehq.org/default\"/>")) == 0,
7563         "got %s\n", wine_dbgstr_w(str));
7564     SysFreeString(str);
7565
7566     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
7567     ok( hr == S_OK, "got 0x%08x\n", hr);
7568
7569     V_VT(&var) = VT_BSTR;
7570     hr = IXMLDOMElement_getAttribute(elem, _bstr_("xmlns"), &var);
7571     ok( hr == S_FALSE, "got 0x%08x\n", hr);
7572     ok( V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
7573
7574     str = NULL;
7575     hr = IXMLDOMElement_get_namespaceURI(elem, &str);
7576     ok( hr == S_OK, "got 0x%08x\n", hr);
7577     ok( lstrcmpW(str, _bstr_("http://winehq.org/default")) == 0, "expected default namespace\n");
7578     SysFreeString(str);
7579
7580     IXMLDOMElement_Release(elem);
7581     IXMLDOMNode_Release(node);
7582
7583     IXMLDOMDocument_Release(doc);
7584     free_bstrs();
7585 }
7586
7587 static const char get_prefix_doc[] =
7588     "<?xml version=\"1.0\" ?>"
7589     "<a xmlns:ns1=\"ns1 href\" />";
7590
7591 static void test_get_prefix(void)
7592 {
7593     IXMLDOMDocumentFragment *fragment;
7594     IXMLDOMCDATASection *cdata;
7595     IXMLDOMElement *element;
7596     IXMLDOMComment *comment;
7597     IXMLDOMDocument *doc;
7598     VARIANT_BOOL b;
7599     HRESULT hr;
7600     BSTR str;
7601
7602     doc = create_document(&IID_IXMLDOMDocument);
7603     if (!doc) return;
7604
7605     /* nodes that can't support prefix */
7606     /* 1. document */
7607     str = (void*)0xdeadbeef;
7608     hr = IXMLDOMDocument_get_prefix(doc, &str);
7609     EXPECT_HR(hr, S_FALSE);
7610     ok(str == NULL, "got %p\n", str);
7611
7612     hr = IXMLDOMDocument_get_prefix(doc, NULL);
7613     EXPECT_HR(hr, E_INVALIDARG);
7614
7615     /* 2. cdata */
7616     hr = IXMLDOMDocument_createCDATASection(doc, NULL, &cdata);
7617     ok(hr == S_OK, "got %08x\n", hr );
7618
7619     str = (void*)0xdeadbeef;
7620     hr = IXMLDOMCDATASection_get_prefix(cdata, &str);
7621     ok(hr == S_FALSE, "got %08x\n", hr);
7622     ok( str == 0, "got %p\n", str);
7623
7624     hr = IXMLDOMCDATASection_get_prefix(cdata, NULL);
7625     ok(hr == E_INVALIDARG, "got %08x\n", hr);
7626     IXMLDOMCDATASection_Release(cdata);
7627
7628     /* 3. comment */
7629     hr = IXMLDOMDocument_createComment(doc, NULL, &comment);
7630     ok(hr == S_OK, "got %08x\n", hr );
7631
7632     str = (void*)0xdeadbeef;
7633     hr = IXMLDOMComment_get_prefix(comment, &str);
7634     ok(hr == S_FALSE, "got %08x\n", hr);
7635     ok( str == 0, "got %p\n", str);
7636
7637     hr = IXMLDOMComment_get_prefix(comment, NULL);
7638     ok(hr == E_INVALIDARG, "got %08x\n", hr);
7639     IXMLDOMComment_Release(comment);
7640
7641     /* 4. fragment */
7642     hr = IXMLDOMDocument_createDocumentFragment(doc, &fragment);
7643     ok(hr == S_OK, "got %08x\n", hr );
7644
7645     str = (void*)0xdeadbeef;
7646     hr = IXMLDOMDocumentFragment_get_prefix(fragment, &str);
7647     ok(hr == S_FALSE, "got %08x\n", hr);
7648     ok( str == 0, "got %p\n", str);
7649
7650     hr = IXMLDOMDocumentFragment_get_prefix(fragment, NULL);
7651     ok(hr == E_INVALIDARG, "got %08x\n", hr);
7652     IXMLDOMDocumentFragment_Release(fragment);
7653
7654     /* no prefix */
7655     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &element);
7656     ok( hr == S_OK, "got 0x%08x\n", hr);
7657
7658     hr = IXMLDOMElement_get_prefix(element, NULL);
7659     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
7660
7661     str = (void*)0xdeadbeef;
7662     hr = IXMLDOMElement_get_prefix(element, &str);
7663     ok( hr == S_FALSE, "got 0x%08x\n", hr);
7664     ok( str == 0, "got %p\n", str);
7665
7666     IXMLDOMElement_Release(element);
7667
7668     /* with prefix */
7669     hr = IXMLDOMDocument_createElement(doc, _bstr_("a:elem"), &element);
7670     ok( hr == S_OK, "got 0x%08x\n", hr);
7671
7672     str = (void*)0xdeadbeef;
7673     hr = IXMLDOMElement_get_prefix(element, &str);
7674     ok( hr == S_OK, "got 0x%08x\n", hr);
7675     ok( lstrcmpW(str, _bstr_("a")) == 0, "expected prefix \"a\"\n");
7676     SysFreeString(str);
7677
7678     str = (void*)0xdeadbeef;
7679     hr = IXMLDOMElement_get_namespaceURI(element, &str);
7680     ok( hr == S_FALSE, "got 0x%08x\n", hr);
7681     ok( str == 0, "got %p\n", str);
7682
7683     IXMLDOMElement_Release(element);
7684
7685     hr = IXMLDOMDocument_loadXML(doc, _bstr_(get_prefix_doc), &b);
7686     EXPECT_HR(hr, S_OK);
7687
7688     hr = IXMLDOMDocument_get_documentElement(doc, &element);
7689     EXPECT_HR(hr, S_OK);
7690
7691     str = (void*)0xdeadbeef;
7692     hr = IXMLDOMElement_get_prefix(element, &str);
7693     EXPECT_HR(hr, S_FALSE);
7694     ok(str == NULL, "got %p\n", str);
7695
7696     str = (void*)0xdeadbeef;
7697     hr = IXMLDOMElement_get_namespaceURI(element, &str);
7698     EXPECT_HR(hr, S_FALSE);
7699     ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
7700
7701     IXMLDOMDocument_Release(doc);
7702     free_bstrs();
7703 }
7704
7705 static void test_selectSingleNode(void)
7706 {
7707     IXMLDOMDocument *doc;
7708     IXMLDOMNodeList *list;
7709     IXMLDOMNode *node;
7710     VARIANT_BOOL b;
7711     HRESULT hr;
7712     LONG len;
7713
7714     doc = create_document(&IID_IXMLDOMDocument);
7715     if (!doc) return;
7716
7717     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
7718     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7719
7720     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
7721     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7722
7723     hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7724     ok( hr == S_OK, "loadXML failed\n");
7725     ok( b == VARIANT_TRUE, "failed to load XML string\n");
7726
7727     hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
7728     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7729
7730     hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
7731     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7732
7733     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), NULL);
7734     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7735
7736     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), NULL);
7737     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7738
7739     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), &node);
7740     ok(hr == S_OK, "got 0x%08x\n", hr);
7741     IXMLDOMNode_Release(node);
7742
7743     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), &list);
7744     ok(hr == S_OK, "got 0x%08x\n", hr);
7745     IXMLDOMNodeList_Release(list);
7746
7747     list = (void*)0xdeadbeef;
7748     hr = IXMLDOMDocument_selectNodes(doc, NULL, &list);
7749     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7750     ok(list == (void*)0xdeadbeef, "got %p\n", list);
7751
7752     node = (void*)0xdeadbeef;
7753     hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("nonexistent"), &node);
7754     ok(hr == S_FALSE, "got 0x%08x\n", hr);
7755     ok(node == 0, "got %p\n", node);
7756
7757     list = (void*)0xdeadbeef;
7758     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("nonexistent"), &list);
7759     ok(hr == S_OK, "got 0x%08x\n", hr);
7760     len = 1;
7761     hr = IXMLDOMNodeList_get_length(list, &len);
7762     ok(hr == S_OK, "got 0x%08x\n", hr);
7763     ok(len == 0, "got %d\n", len);
7764     IXMLDOMNodeList_Release(list);
7765
7766     IXMLDOMDocument_Release(doc);
7767     free_bstrs();
7768 }
7769
7770 static void test_events(void)
7771 {
7772     IConnectionPointContainer *conn;
7773     IConnectionPoint *point;
7774     IXMLDOMDocument *doc;
7775     HRESULT hr;
7776     VARIANT v;
7777     IDispatch *event;
7778
7779     doc = create_document(&IID_IXMLDOMDocument);
7780     if (!doc) return;
7781
7782     hr = IXMLDOMDocument_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&conn);
7783     ok(hr == S_OK, "got 0x%08x\n", hr);
7784
7785     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IDispatch, &point);
7786     ok(hr == S_OK, "got 0x%08x\n", hr);
7787     IConnectionPoint_Release(point);
7788     hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IPropertyNotifySink, &point);
7789     ok(hr == S_OK, "got 0x%08x\n", hr);
7790     IConnectionPoint_Release(point);
7791     hr = IConnectionPointContainer_FindConnectionPoint(conn, &DIID_XMLDOMDocumentEvents, &point);
7792     ok(hr == S_OK, "got 0x%08x\n", hr);
7793     IConnectionPoint_Release(point);
7794
7795     IConnectionPointContainer_Release(conn);
7796
7797     /* ready state callback */
7798     VariantInit(&v);
7799     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7800     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
7801
7802     event = create_dispevent();
7803     V_VT(&v) = VT_UNKNOWN;
7804     V_UNKNOWN(&v) = (IUnknown*)event;
7805
7806     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7807     ok(hr == S_OK, "got 0x%08x\n", hr);
7808     EXPECT_REF(event, 2);
7809
7810     V_VT(&v) = VT_DISPATCH;
7811     V_DISPATCH(&v) = event;
7812
7813     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7814     ok(hr == S_OK, "got 0x%08x\n", hr);
7815     EXPECT_REF(event, 2);
7816
7817     /* VT_NULL doesn't reset event handler */
7818     V_VT(&v) = VT_NULL;
7819     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7820     ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
7821     EXPECT_REF(event, 2);
7822
7823     V_VT(&v) = VT_DISPATCH;
7824     V_DISPATCH(&v) = NULL;
7825
7826     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7827     ok(hr == S_OK, "got 0x%08x\n", hr);
7828     EXPECT_REF(event, 1);
7829
7830     V_VT(&v) = VT_UNKNOWN;
7831     V_DISPATCH(&v) = NULL;
7832     hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
7833     ok(hr == S_OK, "got 0x%08x\n", hr);
7834
7835     IDispatch_Release(event);
7836
7837     IXMLDOMDocument_Release(doc);
7838 }
7839
7840 static void test_createProcessingInstruction(void)
7841 {
7842     static const WCHAR bodyW[] = {'t','e','s','t',0};
7843     IXMLDOMProcessingInstruction *pi;
7844     IXMLDOMDocument *doc;
7845     WCHAR buff[10];
7846     HRESULT hr;
7847
7848     doc = create_document(&IID_IXMLDOMDocument);
7849     if (!doc) return;
7850
7851     /* test for BSTR handling, pass broken BSTR */
7852     memcpy(&buff[2], bodyW, sizeof(bodyW));
7853     /* just a big length */
7854     *(DWORD*)buff = 0xf0f0;
7855     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("test"), &buff[2], &pi);
7856     ok(hr == S_OK, "got 0x%08x\n", hr);
7857
7858     IXMLDOMProcessingInstruction_Release(pi);
7859     IXMLDOMDocument_Release(doc);
7860 }
7861
7862 static void test_put_nodeTypedValue(void)
7863 {
7864     static const BYTE binhexdata[16] =
7865         {0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf};
7866     IXMLDOMDocument *doc;
7867     IXMLDOMElement *elem;
7868     VARIANT type, value;
7869     LONG ubound, lbound;
7870     IXMLDOMNode *node;
7871     SAFEARRAY *array;
7872     HRESULT hr;
7873     BYTE *ptr;
7874     BSTR str;
7875
7876     doc = create_document(&IID_IXMLDOMDocument);
7877     if (!doc) return;
7878
7879     hr = IXMLDOMDocument_createElement(doc, _bstr_("Element"), &elem);
7880     EXPECT_HR(hr, S_OK);
7881
7882     V_VT(&type) = VT_EMPTY;
7883     hr = IXMLDOMElement_get_dataType(elem, &type);
7884     EXPECT_HR(hr, S_FALSE);
7885     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
7886
7887     /* set typed value for untyped node */
7888     V_VT(&type) = VT_I1;
7889     V_I1(&type) = 1;
7890     hr = IXMLDOMElement_put_nodeTypedValue(elem, type);
7891     EXPECT_HR(hr, S_OK);
7892
7893     V_VT(&type) = VT_EMPTY;
7894     hr = IXMLDOMElement_get_dataType(elem, &type);
7895     EXPECT_HR(hr, S_FALSE);
7896     ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
7897
7898     /* no type info stored */
7899     V_VT(&type) = VT_EMPTY;
7900     hr = IXMLDOMElement_get_nodeTypedValue(elem, &type);
7901     EXPECT_HR(hr, S_OK);
7902     ok(V_VT(&type) == VT_BSTR, "got %d, expected VT_BSTR\n", V_VT(&type));
7903     ok(memcmp(V_BSTR(&type), _bstr_("1"), 2*sizeof(WCHAR)) == 0,
7904        "got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
7905     VariantClear(&type);
7906
7907     hr = IXMLDOMElement_get_firstChild(elem, &node);
7908     EXPECT_HR(hr, S_OK);
7909     hr = IXMLDOMElement_removeChild(elem, node, NULL);
7910     EXPECT_HR(hr, S_OK);
7911     IXMLDOMNode_Release(node);
7912
7913     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)elem, NULL);
7914     EXPECT_HR(hr, S_OK);
7915
7916     /* bin.base64 */
7917     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.base64"));
7918     EXPECT_HR(hr, S_OK);
7919
7920     V_VT(&value) = VT_BSTR;
7921     V_BSTR(&value) = _bstr_("ABCD");
7922     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
7923     EXPECT_HR(hr, S_OK);
7924
7925     V_VT(&value) = VT_EMPTY;
7926     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
7927     EXPECT_HR(hr, S_OK);
7928     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
7929     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
7930     ubound = 0;
7931     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
7932     EXPECT_HR(hr, S_OK);
7933     ok(ubound == 2, "got %d\n", ubound);
7934     lbound = 0;
7935     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
7936     EXPECT_HR(hr, S_OK);
7937     ok(lbound == 0, "got %d\n", lbound);
7938     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
7939     EXPECT_HR(hr, S_OK);
7940     ok(ptr[0] == 0, "got %x\n", ptr[0]);
7941     ok(ptr[1] == 0x10, "got %x\n", ptr[1]);
7942     ok(ptr[2] == 0x83, "got %x\n", ptr[2]);
7943     SafeArrayUnaccessData(V_ARRAY(&value));
7944     VariantClear(&value);
7945
7946     /* when set as VT_BSTR it's stored as is */
7947     hr = IXMLDOMElement_get_firstChild(elem, &node);
7948     EXPECT_HR(hr, S_OK);
7949     hr = IXMLDOMNode_get_text(node, &str);
7950     EXPECT_HR(hr, S_OK);
7951     ok(!lstrcmpW(str, _bstr_("ABCD")), "%s\n", wine_dbgstr_w(str));
7952     IXMLDOMNode_Release(node);
7953
7954     array = SafeArrayCreateVector(VT_UI1, 0, 7);
7955     hr = SafeArrayAccessData(array, (void*)&ptr);
7956     EXPECT_HR(hr, S_OK);
7957     memcpy(ptr, "dGVzdA=", strlen("dGVzdA="));
7958     SafeArrayUnaccessData(array);
7959
7960     V_VT(&value) = VT_UI1|VT_ARRAY;
7961     V_ARRAY(&value) = array;
7962     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
7963     EXPECT_HR(hr, S_OK);
7964
7965     V_VT(&value) = VT_EMPTY;
7966     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
7967     EXPECT_HR(hr, S_OK);
7968     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
7969     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
7970     ubound = 0;
7971     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
7972     EXPECT_HR(hr, S_OK);
7973     ok(ubound == 6, "got %d\n", ubound);
7974     lbound = 0;
7975     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
7976     EXPECT_HR(hr, S_OK);
7977     ok(lbound == 0, "got %d\n", lbound);
7978     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
7979     EXPECT_HR(hr, S_OK);
7980     ok(!memcmp(ptr, "dGVzdA=", strlen("dGVzdA=")), "got wrong data, %s\n", ptr);
7981     SafeArrayUnaccessData(V_ARRAY(&value));
7982     VariantClear(&value);
7983
7984     /* if set with VT_UI1|VT_ARRAY it's encoded */
7985     hr = IXMLDOMElement_get_firstChild(elem, &node);
7986     EXPECT_HR(hr, S_OK);
7987     hr = IXMLDOMNode_get_text(node, &str);
7988     EXPECT_HR(hr, S_OK);
7989     ok(!lstrcmpW(str, _bstr_("ZEdWemRBPQ==")), "%s\n", wine_dbgstr_w(str));
7990     IXMLDOMNode_Release(node);
7991     SafeArrayDestroyData(array);
7992
7993     /* bin.hex */
7994     V_VT(&value) = VT_BSTR;
7995     V_BSTR(&value) = _bstr_("");
7996     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
7997     EXPECT_HR(hr, S_OK);
7998
7999     hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.hex"));
8000     EXPECT_HR(hr, S_OK);
8001
8002     array = SafeArrayCreateVector(VT_UI1, 0, 16);
8003     hr = SafeArrayAccessData(array, (void*)&ptr);
8004     EXPECT_HR(hr, S_OK);
8005     memcpy(ptr, binhexdata, sizeof(binhexdata));
8006     SafeArrayUnaccessData(array);
8007
8008     V_VT(&value) = VT_UI1|VT_ARRAY;
8009     V_ARRAY(&value) = array;
8010     hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8011     EXPECT_HR(hr, S_OK);
8012
8013     V_VT(&value) = VT_EMPTY;
8014     hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8015     EXPECT_HR(hr, S_OK);
8016     ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8017     ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8018     ubound = 0;
8019     hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8020     EXPECT_HR(hr, S_OK);
8021     ok(ubound == 15, "got %d\n", ubound);
8022     lbound = 0;
8023     hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8024     EXPECT_HR(hr, S_OK);
8025     ok(lbound == 0, "got %d\n", lbound);
8026     hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8027     EXPECT_HR(hr, S_OK);
8028     ok(!memcmp(ptr, binhexdata, sizeof(binhexdata)), "got wrong data\n");
8029     SafeArrayUnaccessData(V_ARRAY(&value));
8030     VariantClear(&value);
8031
8032     /* if set with VT_UI1|VT_ARRAY it's encoded */
8033     hr = IXMLDOMElement_get_firstChild(elem, &node);
8034     EXPECT_HR(hr, S_OK);
8035     hr = IXMLDOMNode_get_text(node, &str);
8036     EXPECT_HR(hr, S_OK);
8037     ok(!lstrcmpW(str, _bstr_("000102030405060708090a0b0c0d0e0f")), "%s\n", wine_dbgstr_w(str));
8038     IXMLDOMNode_Release(node);
8039     SafeArrayDestroyData(array);
8040
8041     IXMLDOMElement_Release(elem);
8042     IXMLDOMDocument_Release(doc);
8043     free_bstrs();
8044 }
8045
8046 static void test_get_xml(void)
8047 {
8048     static const char xmlA[] = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<a>test</a>\r\n";
8049     static const char attrA[] = "attr=\"&quot;a &amp; b&quot;\"";
8050     static const char attr2A[] = "\"a & b\"";
8051     static const char attr3A[] = "attr=\"&amp;quot;a\"";
8052     static const char attr4A[] = "&quot;a";
8053     static const char fooA[] = "<foo/>";
8054     IXMLDOMProcessingInstruction *pi;
8055     IXMLDOMNode *first;
8056     IXMLDOMElement *elem = NULL;
8057     IXMLDOMAttribute *attr;
8058     IXMLDOMDocument *doc;
8059     VARIANT_BOOL b;
8060     VARIANT v;
8061     BSTR xml;
8062     HRESULT hr;
8063
8064     doc = create_document(&IID_IXMLDOMDocument);
8065     if (!doc) return;
8066
8067     b = VARIANT_TRUE;
8068     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8069     ok(hr == S_OK, "got 0x%08x\n", hr);
8070     ok( b == VARIANT_TRUE, "got %d\n", b);
8071
8072     hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"),
8073                              _bstr_("version=\"1.0\" encoding=\"UTF-16\""), &pi);
8074     ok(hr == S_OK, "got 0x%08x\n", hr);
8075
8076     hr = IXMLDOMDocument_get_firstChild(doc, &first);
8077     ok(hr == S_OK, "got 0x%08x\n", hr);
8078
8079     V_UNKNOWN(&v) = (IUnknown*)first;
8080     V_VT(&v) = VT_UNKNOWN;
8081
8082     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)pi, v, NULL);
8083     ok(hr == S_OK, "got 0x%08x\n", hr);
8084
8085     IXMLDOMProcessingInstruction_Release(pi);
8086     IXMLDOMNode_Release(first);
8087
8088     hr = IXMLDOMDocument_get_xml(doc, &xml);
8089     ok(hr == S_OK, "got 0x%08x\n", hr);
8090
8091     ok(memcmp(xml, _bstr_(xmlA), sizeof(xmlA)*sizeof(WCHAR)) == 0,
8092         "got %s, expected %s\n", wine_dbgstr_w(xml), xmlA);
8093     SysFreeString(xml);
8094
8095     IXMLDOMDocument_Release(doc);
8096
8097     doc = create_document(&IID_IXMLDOMDocument);
8098
8099     hr = IXMLDOMDocument_createElement(doc, _bstr_("foo"), &elem);
8100     ok(hr == S_OK, "got 0x%08x\n", hr);
8101
8102     hr = IXMLDOMDocument_putref_documentElement(doc, elem);
8103     ok(hr == S_OK, "got 0x%08x\n", hr);
8104
8105     hr = IXMLDOMDocument_get_xml(doc, &xml);
8106     ok(hr == S_OK, "got 0x%08x\n", hr);
8107
8108     ok(memcmp(xml, _bstr_(fooA), (sizeof(fooA)-1)*sizeof(WCHAR)) == 0,
8109         "got %s, expected %s\n", wine_dbgstr_w(xml), fooA);
8110     SysFreeString(xml);
8111
8112     IXMLDOMElement_Release(elem);
8113
8114     /* attribute node */
8115     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8116     ok(hr == S_OK, "got 0x%08x\n", hr);
8117
8118     V_VT(&v) = VT_BSTR;
8119     V_BSTR(&v) = _bstr_("\"a & b\"");
8120     hr = IXMLDOMAttribute_put_value(attr, v);
8121     ok(hr == S_OK, "got 0x%08x\n", hr);
8122
8123     xml = NULL;
8124     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8125     ok(hr == S_OK, "got 0x%08x\n", hr);
8126     ok(!memcmp(xml, _bstr_(attrA), (sizeof(attrA)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8127     SysFreeString(xml);
8128
8129     VariantInit(&v);
8130     hr = IXMLDOMAttribute_get_value(attr, &v);
8131     ok(hr == S_OK, "got 0x%08x\n", hr);
8132     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8133     ok(!memcmp(V_BSTR(&v), _bstr_(attr2A), (sizeof(attr2A)-1)*sizeof(WCHAR)),
8134         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8135     VariantClear(&v);
8136
8137     V_VT(&v) = VT_BSTR;
8138     V_BSTR(&v) = _bstr_("&quot;a");
8139     hr = IXMLDOMAttribute_put_value(attr, v);
8140     ok(hr == S_OK, "got 0x%08x\n", hr);
8141
8142     xml = NULL;
8143     hr = IXMLDOMAttribute_get_xml(attr, &xml);
8144     ok(hr == S_OK, "got 0x%08x\n", hr);
8145     ok(!memcmp(xml, _bstr_(attr3A), (sizeof(attr3A)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8146     SysFreeString(xml);
8147
8148     VariantInit(&v);
8149     hr = IXMLDOMAttribute_get_value(attr, &v);
8150     ok(hr == S_OK, "got 0x%08x\n", hr);
8151     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8152     ok(!memcmp(V_BSTR(&v), _bstr_(attr4A), (sizeof(attr4A)-1)*sizeof(WCHAR)),
8153         "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8154     VariantClear(&v);
8155
8156     IXMLDOMAttribute_Release(attr);
8157
8158     IXMLDOMDocument_Release(doc);
8159
8160     free_bstrs();
8161 }
8162
8163 static void test_xsltemplate(void)
8164 {
8165     IXSLTemplate *template;
8166     IXSLProcessor *processor;
8167     IXMLDOMDocument *doc, *doc2;
8168     IStream *stream;
8169     VARIANT_BOOL b;
8170     HRESULT hr;
8171     ULONG ref1, ref2;
8172     VARIANT v;
8173
8174     template = create_xsltemplate(&IID_IXSLTemplate);
8175     if (!template) return;
8176
8177     /* works as reset */
8178     hr = IXSLTemplate_putref_stylesheet(template, NULL);
8179     ok(hr == S_OK, "got 0x%08x\n", hr);
8180
8181     doc = create_document(&IID_IXMLDOMDocument);
8182
8183     b = VARIANT_TRUE;
8184     hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8185     ok(hr == S_OK, "got 0x%08x\n", hr);
8186     ok( b == VARIANT_TRUE, "got %d\n", b);
8187
8188     /* putref with non-xsl document */
8189     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8190     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8191
8192     b = VARIANT_TRUE;
8193     hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8194     ok(hr == S_OK, "got 0x%08x\n", hr);
8195     ok( b == VARIANT_TRUE, "got %d\n", b);
8196
8197     /* not a freethreaded document */
8198     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8199     todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8200
8201     IXMLDOMDocument_Release(doc);
8202
8203     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
8204     if (hr != S_OK)
8205     {
8206         win_skip("failed to create free threaded document instance: 0x%08x\n", hr);
8207         IXSLTemplate_Release(template);
8208         return;
8209     }
8210
8211     b = VARIANT_TRUE;
8212     hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8213     ok(hr == S_OK, "got 0x%08x\n", hr);
8214     ok( b == VARIANT_TRUE, "got %d\n", b);
8215
8216     /* freethreaded document */
8217     ref1 = IXMLDOMDocument_AddRef(doc);
8218     IXMLDOMDocument_Release(doc);
8219     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8220     ok(hr == S_OK, "got 0x%08x\n", hr);
8221     ref2 = IXMLDOMDocument_AddRef(doc);
8222     IXMLDOMDocument_Release(doc);
8223     ok(ref2 > ref1, "got %d\n", ref2);
8224
8225     /* processor */
8226     hr = IXSLTemplate_createProcessor(template, NULL);
8227     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8228
8229     EXPECT_REF(template, 1);
8230     hr = IXSLTemplate_createProcessor(template, &processor);
8231     ok(hr == S_OK, "got 0x%08x\n", hr);
8232     EXPECT_REF(template, 2);
8233
8234     /* input no set yet */
8235     V_VT(&v) = VT_BSTR;
8236     V_BSTR(&v) = NULL;
8237     hr = IXSLProcessor_get_input(processor, &v);
8238 todo_wine {
8239     ok(hr == S_OK, "got 0x%08x\n", hr);
8240     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
8241 }
8242
8243     hr = IXSLProcessor_get_output(processor, NULL);
8244     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8245
8246     /* reset before it was set */
8247     V_VT(&v) = VT_EMPTY;
8248     hr = IXSLProcessor_put_output(processor, v);
8249     ok(hr == S_OK, "got 0x%08x\n", hr);
8250
8251     CreateStreamOnHGlobal(NULL, TRUE, &stream);
8252     EXPECT_REF(stream, 1);
8253
8254     V_VT(&v) = VT_UNKNOWN;
8255     V_UNKNOWN(&v) = (IUnknown*)stream;
8256     hr = IXSLProcessor_put_output(processor, v);
8257     ok(hr == S_OK, "got 0x%08x\n", hr);
8258
8259     /* it seems processor grabs 2 references */
8260     todo_wine EXPECT_REF(stream, 3);
8261
8262     V_VT(&v) = VT_EMPTY;
8263     hr = IXSLProcessor_get_output(processor, &v);
8264     ok(hr == S_OK, "got 0x%08x\n", hr);
8265     ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
8266     ok(V_UNKNOWN(&v) == (IUnknown*)stream, "got %p\n", V_UNKNOWN(&v));
8267
8268     todo_wine EXPECT_REF(stream, 4);
8269     VariantClear(&v);
8270
8271     hr = IXSLProcessor_transform(processor, NULL);
8272     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8273
8274     /* reset and check stream refcount */
8275     V_VT(&v) = VT_EMPTY;
8276     hr = IXSLProcessor_put_output(processor, v);
8277     ok(hr == S_OK, "got 0x%08x\n", hr);
8278
8279     EXPECT_REF(stream, 1);
8280
8281     IStream_Release(stream);
8282
8283     /* no output interface set, check output */
8284     doc2 = create_document(&IID_IXMLDOMDocument);
8285
8286     b = VARIANT_TRUE;
8287     hr = IXMLDOMDocument_loadXML( doc2, _bstr_("<a>test</a>"), &b );
8288     ok(hr == S_OK, "got 0x%08x\n", hr);
8289     ok( b == VARIANT_TRUE, "got %d\n", b);
8290
8291     V_VT(&v) = VT_UNKNOWN;
8292     V_UNKNOWN(&v) = (IUnknown*)doc2;
8293     hr = IXSLProcessor_put_input(processor, v);
8294     ok(hr == S_OK, "got 0x%08x\n", hr);
8295
8296     hr = IXSLProcessor_transform(processor, &b);
8297     ok(hr == S_OK, "got 0x%08x\n", hr);
8298
8299     V_VT(&v) = VT_EMPTY;
8300     hr = IXSLProcessor_get_output(processor, &v);
8301     ok(hr == S_OK, "got 0x%08x\n", hr);
8302     ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8303     ok(lstrcmpW(V_BSTR(&v), _bstr_("")) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8304     IXMLDOMDocument_Release(doc2);
8305     VariantClear(&v);
8306
8307     IXSLProcessor_Release(processor);
8308
8309     /* drop reference */
8310     hr = IXSLTemplate_putref_stylesheet(template, NULL);
8311     ok(hr == S_OK, "got 0x%08x\n", hr);
8312     ref2 = IXMLDOMDocument_AddRef(doc);
8313     IXMLDOMDocument_Release(doc);
8314     ok(ref2 == ref1, "got %d\n", ref2);
8315
8316     IXMLDOMDocument_Release(doc);
8317     IXSLTemplate_Release(template);
8318     free_bstrs();
8319 }
8320
8321 static void test_insertBefore(void)
8322 {
8323     IXMLDOMDocument *doc, *doc2, *doc3;
8324     IXMLDOMAttribute *attr;
8325     IXMLDOMElement *elem1, *elem2, *elem3, *elem4, *elem5;
8326     IXMLDOMNode *node, *newnode, *cdata;
8327     HRESULT hr;
8328     VARIANT v;
8329     BSTR p;
8330
8331     doc = create_document(&IID_IXMLDOMDocument);
8332     doc3 = create_document(&IID_IXMLDOMDocument);
8333
8334     /* document to document */
8335     V_VT(&v) = VT_NULL;
8336     node = (void*)0xdeadbeef;
8337     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc3, v, &node);
8338     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8339     ok(node == NULL, "got %p\n", node);
8340
8341     /* document to itself */
8342     V_VT(&v) = VT_NULL;
8343     node = (void*)0xdeadbeef;
8344     hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc, v, &node);
8345     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8346     ok(node == NULL, "got %p\n", node);
8347
8348     /* insertBefore behaviour for attribute node */
8349     V_VT(&v) = VT_I4;
8350     V_I4(&v) = NODE_ATTRIBUTE;
8351
8352     attr = NULL;
8353     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr"), NULL, (IXMLDOMNode**)&attr);
8354     ok(hr == S_OK, "got 0x%08x\n", hr);
8355     ok(attr != NULL, "got %p\n", attr);
8356
8357     /* attribute to document */
8358     V_VT(&v) = VT_NULL;
8359     node = (void*)0xdeadbeef;
8360     hr = IXMLDOMDocument_insertBefore(doc3, (IXMLDOMNode*)attr, v, &node);
8361     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8362     ok(node == NULL, "got %p\n", node);
8363
8364     /* cdata to document */
8365     V_VT(&v) = VT_I4;
8366     V_I4(&v) = NODE_CDATA_SECTION;
8367
8368     cdata = NULL;
8369     hr = IXMLDOMDocument_createNode(doc3, v, _bstr_("cdata"), NULL, &cdata);
8370     ok(hr == S_OK, "got 0x%08x\n", hr);
8371     ok(cdata != NULL, "got %p\n", cdata);
8372
8373     EXPECT_NO_CHILDREN(cdata);
8374
8375     /* attribute to cdata */
8376     V_VT(&v) = VT_NULL;
8377     node = (void*)0xdeadbeef;
8378     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)attr, v, &node);
8379     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8380     ok(node == NULL, "got %p\n", node);
8381
8382     /* document to cdata */
8383     V_VT(&v) = VT_NULL;
8384     node = (void*)0xdeadbeef;
8385     hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)doc, v, &node);
8386     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8387     ok(node == NULL, "got %p\n", node);
8388
8389     V_VT(&v) = VT_NULL;
8390     node = (void*)0xdeadbeef;
8391     hr = IXMLDOMDocument_insertBefore(doc3, cdata, v, &node);
8392     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8393     ok(node == NULL, "got %p\n", node);
8394
8395     IXMLDOMNode_Release(cdata);
8396     IXMLDOMDocument_Release(doc3);
8397
8398     /* attribute to attribute */
8399     V_VT(&v) = VT_I4;
8400     V_I4(&v) = NODE_ATTRIBUTE;
8401     newnode = NULL;
8402     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr2"), NULL, &newnode);
8403     ok(hr == S_OK, "got 0x%08x\n", hr);
8404     ok(newnode != NULL, "got %p\n", newnode);
8405
8406     V_VT(&v) = VT_NULL;
8407     node = (void*)0xdeadbeef;
8408     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8409     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8410     ok(node == NULL, "got %p\n", node);
8411
8412     V_VT(&v) = VT_UNKNOWN;
8413     V_UNKNOWN(&v) = (IUnknown*)attr;
8414     node = (void*)0xdeadbeef;
8415     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8416     todo_wine ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8417     ok(node == NULL, "got %p\n", node);
8418     IXMLDOMNode_Release(newnode);
8419
8420     /* cdata to attribute */
8421     V_VT(&v) = VT_I4;
8422     V_I4(&v) = NODE_CDATA_SECTION;
8423     newnode = NULL;
8424     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
8425     ok(hr == S_OK, "got 0x%08x\n", hr);
8426     ok(newnode != NULL, "got %p\n", newnode);
8427
8428     V_VT(&v) = VT_NULL;
8429     node = (void*)0xdeadbeef;
8430     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8431     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8432     ok(node == NULL, "got %p\n", node);
8433     IXMLDOMNode_Release(newnode);
8434
8435     /* comment to attribute */
8436     V_VT(&v) = VT_I4;
8437     V_I4(&v) = NODE_COMMENT;
8438     newnode = NULL;
8439     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
8440     ok(hr == S_OK, "got 0x%08x\n", hr);
8441     ok(newnode != NULL, "got %p\n", newnode);
8442
8443     V_VT(&v) = VT_NULL;
8444     node = (void*)0xdeadbeef;
8445     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8446     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8447     ok(node == NULL, "got %p\n", node);
8448     IXMLDOMNode_Release(newnode);
8449
8450     /* element to attribute */
8451     V_VT(&v) = VT_I4;
8452     V_I4(&v) = NODE_ELEMENT;
8453     newnode = NULL;
8454     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
8455     ok(hr == S_OK, "got 0x%08x\n", hr);
8456     ok(newnode != NULL, "got %p\n", newnode);
8457
8458     V_VT(&v) = VT_NULL;
8459     node = (void*)0xdeadbeef;
8460     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8461     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8462     ok(node == NULL, "got %p\n", node);
8463     IXMLDOMNode_Release(newnode);
8464
8465     /* pi to attribute */
8466     V_VT(&v) = VT_I4;
8467     V_I4(&v) = NODE_PROCESSING_INSTRUCTION;
8468     newnode = NULL;
8469     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
8470     ok(hr == S_OK, "got 0x%08x\n", hr);
8471     ok(newnode != NULL, "got %p\n", newnode);
8472
8473     V_VT(&v) = VT_NULL;
8474     node = (void*)0xdeadbeef;
8475     hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
8476     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8477     ok(node == NULL, "got %p\n", node);
8478     IXMLDOMNode_Release(newnode);
8479     IXMLDOMAttribute_Release(attr);
8480
8481     /* insertBefore for elements */
8482     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem1);
8483     ok(hr == S_OK, "got 0x%08x\n", hr);
8484
8485     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem2"), &elem2);
8486     ok(hr == S_OK, "got 0x%08x\n", hr);
8487
8488     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
8489     ok(hr == S_OK, "got 0x%08x\n", hr);
8490
8491     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
8492     ok(hr == S_OK, "got 0x%08x\n", hr);
8493
8494     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem4"), &elem4);
8495     ok(hr == S_OK, "got 0x%08x\n", hr);
8496
8497     EXPECT_NO_CHILDREN(elem1);
8498     EXPECT_NO_CHILDREN(elem2);
8499     EXPECT_NO_CHILDREN(elem3);
8500
8501     todo_wine EXPECT_REF(elem2, 2);
8502
8503     /* document to element */
8504     V_VT(&v) = VT_DISPATCH;
8505     V_DISPATCH(&v) = NULL;
8506     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)doc, v, NULL);
8507     ok(hr == E_FAIL, "got 0x%08x\n", hr);
8508
8509     V_VT(&v) = VT_DISPATCH;
8510     V_DISPATCH(&v) = NULL;
8511     node = NULL;
8512     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem4, v, &node);
8513     ok(hr == S_OK, "got 0x%08x\n", hr);
8514     ok(node == (void*)elem4, "got %p\n", node);
8515
8516     EXPECT_CHILDREN(elem1);
8517     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem4, NULL);
8518     EXPECT_HR(hr, S_OK);
8519     IXMLDOMElement_Release(elem4);
8520
8521     EXPECT_NO_CHILDREN(elem1);
8522
8523     V_VT(&v) = VT_NULL;
8524     node = NULL;
8525     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
8526     ok(hr == S_OK, "got 0x%08x\n", hr);
8527     ok(node == (void*)elem2, "got %p\n", node);
8528
8529     EXPECT_CHILDREN(elem1);
8530     todo_wine EXPECT_REF(elem2, 3);
8531     IXMLDOMNode_Release(node);
8532
8533     /* again for already linked node */
8534     V_VT(&v) = VT_NULL;
8535     node = NULL;
8536     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
8537     ok(hr == S_OK, "got 0x%08x\n", hr);
8538     ok(node == (void*)elem2, "got %p\n", node);
8539
8540     EXPECT_CHILDREN(elem1);
8541
8542     /* increments each time */
8543     todo_wine EXPECT_REF(elem2, 3);
8544     IXMLDOMNode_Release(node);
8545
8546     /* try to add to another element */
8547     V_VT(&v) = VT_NULL;
8548     node = (void*)0xdeadbeef;
8549     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem2, v, &node);
8550     ok(hr == S_OK, "got 0x%08x\n", hr);
8551     ok(node == (void*)elem2, "got %p\n", node);
8552
8553     EXPECT_CHILDREN(elem3);
8554     EXPECT_NO_CHILDREN(elem1);
8555
8556     IXMLDOMNode_Release(node);
8557
8558     /* cross document case - try to add as child to a node created with other doc */
8559     doc2 = create_document(&IID_IXMLDOMDocument);
8560
8561     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem4);
8562     ok(hr == S_OK, "got 0x%08x\n", hr);
8563     todo_wine EXPECT_REF(elem4, 2);
8564
8565     /* same name, another instance */
8566     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem5);
8567     ok(hr == S_OK, "got 0x%08x\n", hr);
8568     todo_wine EXPECT_REF(elem5, 2);
8569
8570     todo_wine EXPECT_REF(elem3, 2);
8571     V_VT(&v) = VT_NULL;
8572     node = NULL;
8573     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem4, v, &node);
8574     ok(hr == S_OK, "got 0x%08x\n", hr);
8575     ok(node == (void*)elem4, "got %p\n", node);
8576     todo_wine EXPECT_REF(elem4, 3);
8577     todo_wine EXPECT_REF(elem3, 2);
8578     IXMLDOMNode_Release(node);
8579
8580     V_VT(&v) = VT_NULL;
8581     node = NULL;
8582     hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem5, v, &node);
8583     ok(hr == S_OK, "got 0x%08x\n", hr);
8584     ok(node == (void*)elem5, "got %p\n", node);
8585     todo_wine EXPECT_REF(elem4, 2);
8586     todo_wine EXPECT_REF(elem5, 3);
8587     IXMLDOMNode_Release(node);
8588
8589     IXMLDOMDocument_Release(doc2);
8590
8591     IXMLDOMElement_Release(elem1);
8592     IXMLDOMElement_Release(elem2);
8593     IXMLDOMElement_Release(elem3);
8594     IXMLDOMElement_Release(elem4);
8595     IXMLDOMElement_Release(elem5);
8596
8597     /* elements with same default namespace */
8598     V_VT(&v) = VT_I4;
8599     V_I4(&v) = NODE_ELEMENT;
8600     elem1 = NULL;
8601     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
8602     ok(hr == S_OK, "got 0x%08x\n", hr);
8603     ok(elem1 != NULL, "got %p\n", elem1);
8604
8605     V_VT(&v) = VT_I4;
8606     V_I4(&v) = NODE_ELEMENT;
8607     elem2 = NULL;
8608     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem2);
8609     ok(hr == S_OK, "got 0x%08x\n", hr);
8610     ok(elem2 != NULL, "got %p\n", elem2);
8611
8612     /* check contents so far */
8613     p = NULL;
8614     hr = IXMLDOMElement_get_xml(elem1, &p);
8615     ok(hr == S_OK, "got 0x%08x\n", hr);
8616     ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
8617     SysFreeString(p);
8618
8619     p = NULL;
8620     hr = IXMLDOMElement_get_xml(elem2, &p);
8621     ok(hr == S_OK, "got 0x%08x\n", hr);
8622     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
8623     SysFreeString(p);
8624
8625     V_VT(&v) = VT_NULL;
8626     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
8627     ok(hr == S_OK, "got 0x%08x\n", hr);
8628
8629     /* get_xml depends on context, for top node it omits child namespace attribute,
8630        but at child level it's still returned */
8631     p = NULL;
8632     hr = IXMLDOMElement_get_xml(elem1, &p);
8633     ok(hr == S_OK, "got 0x%08x\n", hr);
8634     todo_wine ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"><elem2/></elem1>")),
8635         "got %s\n", wine_dbgstr_w(p));
8636     SysFreeString(p);
8637
8638     p = NULL;
8639     hr = IXMLDOMElement_get_xml(elem2, &p);
8640     ok(hr == S_OK, "got 0x%08x\n", hr);
8641     ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
8642     SysFreeString(p);
8643
8644     IXMLDOMElement_Release(elem1);
8645     IXMLDOMElement_Release(elem2);
8646
8647     /* child without default namespace added to node with default namespace */
8648     V_VT(&v) = VT_I4;
8649     V_I4(&v) = NODE_ELEMENT;
8650     elem1 = NULL;
8651     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
8652     ok(hr == S_OK, "got 0x%08x\n", hr);
8653     ok(elem1 != NULL, "got %p\n", elem1);
8654
8655     V_VT(&v) = VT_I4;
8656     V_I4(&v) = NODE_ELEMENT;
8657     elem2 = NULL;
8658     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), NULL, (IXMLDOMNode**)&elem2);
8659     ok(hr == S_OK, "got 0x%08x\n", hr);
8660     ok(elem2 != NULL, "got %p\n", elem2);
8661
8662     EXPECT_REF(elem2, 1);
8663     V_VT(&v) = VT_NULL;
8664     hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
8665     ok(hr == S_OK, "got 0x%08x\n", hr);
8666     EXPECT_REF(elem2, 1);
8667
8668     p = NULL;
8669     hr = IXMLDOMElement_get_xml(elem2, &p);
8670     ok(hr == S_OK, "got 0x%08x\n", hr);
8671     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
8672     SysFreeString(p);
8673
8674     hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem2, NULL);
8675     ok(hr == S_OK, "got 0x%08x\n", hr);
8676
8677     p = NULL;
8678     hr = IXMLDOMElement_get_xml(elem2, &p);
8679     ok(hr == S_OK, "got 0x%08x\n", hr);
8680     ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
8681     SysFreeString(p);
8682
8683     IXMLDOMElement_Release(elem1);
8684     IXMLDOMElement_Release(elem2);
8685     IXMLDOMDocument_Release(doc);
8686 }
8687
8688 static void test_appendChild(void)
8689 {
8690     IXMLDOMDocument *doc, *doc2;
8691     IXMLDOMElement *elem, *elem2;
8692     HRESULT hr;
8693
8694     doc = create_document(&IID_IXMLDOMDocument);
8695     doc2 = create_document(&IID_IXMLDOMDocument);
8696
8697     hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8698     ok(hr == S_OK, "got 0x%08x\n", hr);
8699
8700     hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
8701     ok(hr == S_OK, "got 0x%08x\n", hr);
8702
8703     EXPECT_REF(doc, 1);
8704     todo_wine EXPECT_REF(elem, 2);
8705     EXPECT_REF(doc2, 1);
8706     todo_wine EXPECT_REF(elem2, 2);
8707     EXPECT_NO_CHILDREN(doc);
8708     EXPECT_NO_CHILDREN(doc2);
8709
8710     /* append from another document */
8711     hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
8712     ok(hr == S_OK, "got 0x%08x\n", hr);
8713
8714     EXPECT_REF(doc, 1);
8715     todo_wine EXPECT_REF(elem, 2);
8716     EXPECT_REF(doc2, 1);
8717     todo_wine EXPECT_REF(elem2, 2);
8718     EXPECT_NO_CHILDREN(doc);
8719     EXPECT_CHILDREN(doc2);
8720
8721     IXMLDOMElement_Release(elem);
8722     IXMLDOMElement_Release(elem2);
8723     IXMLDOMDocument_Release(doc);
8724     IXMLDOMDocument_Release(doc2);
8725 }
8726
8727 static void test_get_doctype(void)
8728 {
8729     IXMLDOMDocumentType *doctype;
8730     IXMLDOMDocument *doc;
8731     HRESULT hr;
8732
8733     doc = create_document(&IID_IXMLDOMDocument);
8734
8735     hr = IXMLDOMDocument_get_doctype(doc, NULL);
8736     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8737
8738     doctype = (void*)0xdeadbeef;
8739     hr = IXMLDOMDocument_get_doctype(doc, &doctype);
8740     ok(hr == S_FALSE, "got 0x%08x\n", hr);
8741     ok(doctype == NULL, "got %p\n", doctype);
8742
8743     IXMLDOMDocument_Release(doc);
8744 }
8745
8746 static void test_get_tagName(void)
8747 {
8748     IXMLDOMDocument *doc;
8749     IXMLDOMElement *elem, *elem2;
8750     HRESULT hr;
8751     BSTR str;
8752
8753     doc = create_document(&IID_IXMLDOMDocument);
8754
8755     hr = IXMLDOMDocument_createElement(doc, _bstr_("element"), &elem);
8756     ok(hr == S_OK, "got 0x%08x\n", hr);
8757
8758     hr = IXMLDOMElement_get_tagName(elem, NULL);
8759     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8760
8761     str = NULL;
8762     hr = IXMLDOMElement_get_tagName(elem, &str);
8763     ok(hr == S_OK, "got 0x%08x\n", hr);
8764     ok(!lstrcmpW(str, _bstr_("element")), "got %s\n", wine_dbgstr_w(str));
8765     SysFreeString(str);
8766
8767     hr = IXMLDOMDocument_createElement(doc, _bstr_("s:element"), &elem2);
8768     ok(hr == S_OK, "got 0x%08x\n", hr);
8769
8770     str = NULL;
8771     hr = IXMLDOMElement_get_tagName(elem2, &str);
8772     ok(hr == S_OK, "got 0x%08x\n", hr);
8773     ok(!lstrcmpW(str, _bstr_("s:element")), "got %s\n", wine_dbgstr_w(str));
8774     SysFreeString(str);
8775
8776     IXMLDOMElement_Release(elem);
8777     IXMLDOMElement_Release(elem2);
8778     IXMLDOMDocument_Release(doc);
8779     free_bstrs();
8780 }
8781
8782 typedef struct {
8783     DOMNodeType type;
8784     const char *name;
8785     VARTYPE vt;
8786     HRESULT hr;
8787 } node_type_t;
8788
8789 static const node_type_t get_datatype[] = {
8790     { NODE_ELEMENT,                "element",   VT_NULL, S_FALSE },
8791     { NODE_ATTRIBUTE,              "attr",      VT_NULL, S_FALSE },
8792     { NODE_TEXT,                   "text",      VT_NULL, S_FALSE },
8793     { NODE_CDATA_SECTION ,         "cdata",     VT_NULL, S_FALSE },
8794     { NODE_ENTITY_REFERENCE,       "entityref", VT_NULL, S_FALSE },
8795     { NODE_PROCESSING_INSTRUCTION, "pi",        VT_NULL, S_FALSE },
8796     { NODE_COMMENT,                "comment",   VT_NULL, S_FALSE },
8797     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   VT_NULL, S_FALSE },
8798     { 0 }
8799 };
8800
8801 static void test_get_dataType(void)
8802 {
8803     const node_type_t *entry = get_datatype;
8804     IXMLDOMDocument *doc;
8805
8806     doc = create_document(&IID_IXMLDOMDocument);
8807
8808     while (entry->type)
8809     {
8810         IXMLDOMNode *node = NULL;
8811         VARIANT var, type;
8812         HRESULT hr;
8813
8814         V_VT(&var) = VT_I4;
8815         V_I4(&var) = entry->type;
8816         hr = IXMLDOMDocument_createNode(doc, var, _bstr_(entry->name), NULL, &node);
8817         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
8818
8819         hr = IXMLDOMNode_get_dataType(node, NULL);
8820         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8821
8822         VariantInit(&type);
8823         hr = IXMLDOMNode_get_dataType(node, &type);
8824         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
8825             hr, entry->hr, entry->type);
8826         ok(V_VT(&type) == entry->vt, "got %d, expected %d. node type %d\n",
8827             V_VT(&type), entry->vt, entry->type);
8828         VariantClear(&type);
8829
8830         IXMLDOMNode_Release(node);
8831
8832         entry++;
8833     }
8834
8835     IXMLDOMDocument_Release(doc);
8836     free_bstrs();
8837 }
8838
8839 typedef struct _get_node_typestring_t {
8840     DOMNodeType type;
8841     const char *string;
8842 } get_node_typestring_t;
8843
8844 static const get_node_typestring_t get_node_typestring[] = {
8845     { NODE_ELEMENT,                "element"               },
8846     { NODE_ATTRIBUTE,              "attribute"             },
8847     { NODE_TEXT,                   "text"                  },
8848     { NODE_CDATA_SECTION ,         "cdatasection"          },
8849     { NODE_ENTITY_REFERENCE,       "entityreference"       },
8850     { NODE_PROCESSING_INSTRUCTION, "processinginstruction" },
8851     { NODE_COMMENT,                "comment"               },
8852     { NODE_DOCUMENT_FRAGMENT,      "documentfragment"      },
8853     { 0 }
8854 };
8855
8856 static void test_get_nodeTypeString(void)
8857 {
8858     const get_node_typestring_t *entry = get_node_typestring;
8859     IXMLDOMDocument *doc;
8860     HRESULT hr;
8861     BSTR str;
8862
8863     doc = create_document(&IID_IXMLDOMDocument);
8864
8865     hr = IXMLDOMDocument_get_nodeTypeString(doc, &str);
8866     ok(hr == S_OK, "got 0x%08x\n", hr);
8867     ok(!lstrcmpW(str, _bstr_("document")), "got string %s\n", wine_dbgstr_w(str));
8868     SysFreeString(str);
8869
8870     while (entry->type)
8871     {
8872         IXMLDOMNode *node = NULL;
8873         VARIANT var;
8874
8875         V_VT(&var) = VT_I4;
8876         V_I4(&var) = entry->type;
8877         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
8878         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
8879
8880         hr = IXMLDOMNode_get_nodeTypeString(node, NULL);
8881         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8882
8883         hr = IXMLDOMNode_get_nodeTypeString(node, &str);
8884         ok(hr == S_OK, "got 0x%08x\n", hr);
8885         ok(!lstrcmpW(str, _bstr_(entry->string)), "got string %s, expected %s. node type %d\n",
8886             wine_dbgstr_w(str), entry->string, entry->type);
8887         SysFreeString(str);
8888         IXMLDOMNode_Release(node);
8889
8890         entry++;
8891     }
8892
8893     IXMLDOMDocument_Release(doc);
8894     free_bstrs();
8895 }
8896
8897 typedef struct _get_attributes_t {
8898     DOMNodeType type;
8899     HRESULT hr;
8900 } get_attributes_t;
8901
8902 static const get_attributes_t get_attributes[] = {
8903     { NODE_ATTRIBUTE,              S_FALSE },
8904     { NODE_TEXT,                   S_FALSE },
8905     { NODE_CDATA_SECTION ,         S_FALSE },
8906     { NODE_ENTITY_REFERENCE,       S_FALSE },
8907     { NODE_PROCESSING_INSTRUCTION, S_FALSE },
8908     { NODE_COMMENT,                S_FALSE },
8909     { NODE_DOCUMENT_FRAGMENT,      S_FALSE },
8910     { 0 }
8911 };
8912
8913 static void test_get_attributes(void)
8914 {
8915     const get_attributes_t *entry = get_attributes;
8916     IXMLDOMNamedNodeMap *map;
8917     IXMLDOMDocument *doc;
8918     IXMLDOMNode *node, *node2;
8919     VARIANT_BOOL b;
8920     HRESULT hr;
8921     BSTR str;
8922     LONG length;
8923
8924     doc = create_document(&IID_IXMLDOMDocument);
8925
8926     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
8927     ok(hr == S_OK, "got %08x\n", hr);
8928
8929     hr = IXMLDOMDocument_get_attributes(doc, NULL);
8930     ok(hr == E_INVALIDARG, "got %08x\n", hr);
8931
8932     map = (void*)0xdeadbeef;
8933     hr = IXMLDOMDocument_get_attributes(doc, &map);
8934     ok(hr == S_FALSE, "got %08x\n", hr);
8935     ok(map == NULL, "got %p\n", map);
8936
8937     /* first child is <?xml ?> */
8938     hr = IXMLDOMDocument_get_firstChild(doc, &node);
8939     ok(hr == S_OK, "got %08x\n", hr);
8940
8941     hr = IXMLDOMNode_get_attributes(node, &map);
8942     ok(hr == S_OK, "got %08x\n", hr);
8943
8944     length = -1;
8945     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
8946     EXPECT_HR(hr, S_OK);
8947     todo_wine ok(length == 1, "got %d\n", length);
8948
8949     if (hr == S_OK && length == 1)
8950     {
8951         IXMLDOMAttribute *attr;
8952         DOMNodeType type;
8953         VARIANT v;
8954
8955         node2 = NULL;
8956         hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
8957         EXPECT_HR(hr, S_OK);
8958         ok(node != NULL, "got %p\n", node2);
8959
8960         hr = IXMLDOMNode_get_nodeName(node2, &str);
8961         EXPECT_HR(hr, S_OK);
8962         ok(!lstrcmpW(str, _bstr_("version")), "got %s\n", wine_dbgstr_w(str));
8963         SysFreeString(str);
8964
8965         length = -1;
8966         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
8967         EXPECT_HR(hr, S_OK);
8968         ok(length == 1, "got %d\n", length);
8969
8970         type = -1;
8971         hr = IXMLDOMNode_get_nodeType(node2, &type);
8972         EXPECT_HR(hr, S_OK);
8973         ok(type == NODE_ATTRIBUTE, "got %d\n", type);
8974
8975         hr = IXMLDOMNode_get_xml(node, &str);
8976         EXPECT_HR(hr, S_OK);
8977         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
8978         SysFreeString(str);
8979
8980         hr = IXMLDOMNode_get_text(node, &str);
8981         EXPECT_HR(hr, S_OK);
8982         ok(!lstrcmpW(str, _bstr_("version=\"1.0\"")), "got %s\n", wine_dbgstr_w(str));
8983         SysFreeString(str);
8984
8985         hr = IXMLDOMNamedNodeMap_removeNamedItem(map, _bstr_("version"), NULL);
8986         EXPECT_HR(hr, S_OK);
8987
8988         length = -1;
8989         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
8990         EXPECT_HR(hr, S_OK);
8991         ok(length == 0, "got %d\n", length);
8992
8993         hr = IXMLDOMNode_get_xml(node, &str);
8994         EXPECT_HR(hr, S_OK);
8995         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
8996         SysFreeString(str);
8997
8998         hr = IXMLDOMNode_get_text(node, &str);
8999         EXPECT_HR(hr, S_OK);
9000         ok(!lstrcmpW(str, _bstr_("")), "got %s\n", wine_dbgstr_w(str));
9001         SysFreeString(str);
9002
9003         IXMLDOMNamedNodeMap_Release(map);
9004
9005         hr = IXMLDOMNode_get_attributes(node, &map);
9006         ok(hr == S_OK, "got %08x\n", hr);
9007
9008         length = -1;
9009         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9010         EXPECT_HR(hr, S_OK);
9011         ok(length == 0, "got %d\n", length);
9012
9013         hr = IXMLDOMDocument_createAttribute(doc, _bstr_("encoding"), &attr);
9014         EXPECT_HR(hr, S_OK);
9015
9016         V_VT(&v) = VT_BSTR;
9017         V_BSTR(&v) = _bstr_("UTF-8");
9018         hr = IXMLDOMAttribute_put_nodeValue(attr, v);
9019         EXPECT_HR(hr, S_OK);
9020
9021         EXPECT_REF(attr, 2);
9022         hr = IXMLDOMNamedNodeMap_setNamedItem(map, (IXMLDOMNode*)attr, NULL);
9023         EXPECT_HR(hr, S_OK);
9024         EXPECT_REF(attr, 2);
9025
9026         hr = IXMLDOMNode_get_attributes(node, &map);
9027         ok(hr == S_OK, "got %08x\n", hr);
9028
9029         length = -1;
9030         hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9031         EXPECT_HR(hr, S_OK);
9032         ok(length == 1, "got %d\n", length);
9033
9034         hr = IXMLDOMNode_get_xml(node, &str);
9035         EXPECT_HR(hr, S_OK);
9036         ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9037         SysFreeString(str);
9038
9039         hr = IXMLDOMNode_get_text(node, &str);
9040         EXPECT_HR(hr, S_OK);
9041         ok(!lstrcmpW(str, _bstr_("encoding=\"UTF-8\"")), "got %s\n", wine_dbgstr_w(str));
9042         SysFreeString(str);
9043
9044         IXMLDOMNamedNodeMap_Release(map);
9045         IXMLDOMNode_Release(node2);
9046     }
9047
9048     IXMLDOMNode_Release(node);
9049
9050     /* last child is element */
9051     EXPECT_REF(doc, 1);
9052     hr = IXMLDOMDocument_get_lastChild(doc, &node);
9053     ok(hr == S_OK, "got %08x\n", hr);
9054     EXPECT_REF(doc, 1);
9055
9056     EXPECT_REF(node, 1);
9057     hr = IXMLDOMNode_get_attributes(node, &map);
9058     ok(hr == S_OK, "got %08x\n", hr);
9059     EXPECT_REF(node, 1);
9060     EXPECT_REF(doc, 1);
9061
9062     EXPECT_REF(map, 1);
9063     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9064     ok(hr == S_OK, "got %08x\n", hr);
9065     EXPECT_REF(node, 1);
9066     EXPECT_REF(node2, 1);
9067     EXPECT_REF(map, 1);
9068     EXPECT_REF(doc, 1);
9069     IXMLDOMNode_Release(node2);
9070
9071     /* release node before map release, map still works */
9072     IXMLDOMNode_Release(node);
9073
9074     length = 0;
9075     hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9076     ok(hr == S_OK, "got %08x\n", hr);
9077     ok(length == 1, "got %d\n", length);
9078
9079     node2 = NULL;
9080     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9081     ok(hr == S_OK, "got %08x\n", hr);
9082     EXPECT_REF(node2, 1);
9083     IXMLDOMNode_Release(node2);
9084
9085     IXMLDOMNamedNodeMap_Release(map);
9086
9087     while (entry->type)
9088     {
9089         VARIANT var;
9090
9091         node = NULL;
9092
9093         V_VT(&var) = VT_I4;
9094         V_I4(&var) = entry->type;
9095         hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9096         ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9097
9098         hr = IXMLDOMNode_get_attributes(node, NULL);
9099         ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9100
9101         map = (void*)0xdeadbeef;
9102         hr = IXMLDOMNode_get_attributes(node, &map);
9103         ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9104             hr, entry->hr, entry->type);
9105         ok(map == NULL, "got %p\n", map);
9106
9107         IXMLDOMNode_Release(node);
9108
9109         entry++;
9110     }
9111
9112     IXMLDOMDocument_Release(doc);
9113     free_bstrs();
9114 }
9115
9116 static void test_selection(void)
9117 {
9118     IXMLDOMSelection *selection, *selection2;
9119     IEnumVARIANT *enum1, *enum2, *enum3;
9120     IXMLDOMNodeList *list;
9121     IUnknown *unk1, *unk2;
9122     IXMLDOMDocument *doc;
9123     IDispatchEx *dispex;
9124     IXMLDOMNode *node;
9125     IDispatch *disp;
9126     VARIANT_BOOL b;
9127     HRESULT hr;
9128     DISPID did;
9129     VARIANT v;
9130     BSTR name;
9131     ULONG ret;
9132     LONG len;
9133
9134     doc = create_document(&IID_IXMLDOMDocument);
9135
9136     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
9137     EXPECT_HR(hr, S_OK);
9138
9139     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list);
9140     EXPECT_HR(hr, S_OK);
9141
9142     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9143     EXPECT_HR(hr, S_OK);
9144     IXMLDOMSelection_Release(selection);
9145
9146     /* collection disp id */
9147     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IDispatchEx, (void**)&dispex);
9148     EXPECT_HR(hr, S_OK);
9149     did = 0;
9150     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
9151     EXPECT_HR(hr, S_OK);
9152     ok(did == DISPID_DOM_COLLECTION_BASE, "got %d\n", did);
9153     len = 0;
9154     hr = IXMLDOMSelection_get_length(selection, &len);
9155     EXPECT_HR(hr, S_OK);
9156     ok(len == 1, "got %d\n", len);
9157     hr = IDispatchEx_GetDispID(dispex, _bstr_("10"), 0, &did);
9158     EXPECT_HR(hr, S_OK);
9159     ok(did == DISPID_DOM_COLLECTION_BASE+10, "got %d\n", did);
9160     IDispatchEx_Release(dispex);
9161
9162     /* IEnumVARIANT tests */
9163     enum1 = NULL;
9164     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum1);
9165     EXPECT_HR(hr, S_OK);
9166     ok(enum1 != NULL, "got %p\n", enum1);
9167     EXPECT_REF(enum1, 2);
9168
9169     EXPECT_REF(selection, 1);
9170     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IUnknown, (void**)&unk1);
9171     EXPECT_HR(hr, S_OK);
9172     EXPECT_REF(selection, 2);
9173     EXPECT_REF(enum1, 2);
9174
9175     /* enumerator and selection object return same IUnknown* */
9176     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
9177     EXPECT_HR(hr, S_OK);
9178     EXPECT_REF(selection, 3);
9179     EXPECT_REF(enum1, 2);
9180     ok(unk2 == unk1, "got %p, %p\n", unk1, unk2);
9181     IUnknown_Release(unk2);
9182
9183     EXPECT_REF(selection, 2);
9184     IEnumVARIANT_AddRef(enum1);
9185     EXPECT_REF(selection, 2);
9186     IEnumVARIANT_Release(enum1);
9187
9188     enum3 = NULL;
9189     hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum3);
9190     EXPECT_HR(hr, S_OK);
9191     ok(enum3 != NULL, "got %p\n", enum3);
9192     ok(enum1 == enum3, "got %p and %p\n", enum1, enum3);
9193     EXPECT_REF(enum1, 3);
9194     IEnumVARIANT_Release(enum3);
9195
9196     EXPECT_REF(selection, 2);
9197     EXPECT_REF(enum1, 2);
9198
9199     enum2 = NULL;
9200     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
9201     EXPECT_HR(hr, S_OK);
9202     ok(enum2 != NULL, "got %p\n", enum2);
9203
9204     EXPECT_REF(selection, 3);
9205     EXPECT_REF(enum1, 2);
9206     EXPECT_REF(enum2, 1);
9207
9208     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
9209
9210     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
9211     EXPECT_HR(hr, S_OK);
9212     EXPECT_REF(selection, 3);
9213     EXPECT_REF(enum2, 2);
9214     ok(unk2 != unk1, "got %p, %p\n", unk1, unk2);
9215     IUnknown_Release(unk2);
9216     IUnknown_Release(unk1);
9217
9218     selection2 = NULL;
9219     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IXMLDOMSelection, (void**)&selection2);
9220     EXPECT_HR(hr, S_OK);
9221     ok(selection2 == selection, "got %p and %p\n", selection, selection2);
9222     EXPECT_REF(selection, 3);
9223     EXPECT_REF(enum1, 2);
9224
9225     IXMLDOMSelection_Release(selection2);
9226
9227     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IDispatch, (void**)&disp);
9228     EXPECT_HR(hr, S_OK);
9229     EXPECT_REF(selection, 3);
9230     IDispatch_Release(disp);
9231
9232     hr = IEnumVARIANT_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enum3);
9233     EXPECT_HR(hr, S_OK);
9234     ok(enum3 == enum1, "got %p and %p\n", enum3, enum1);
9235     EXPECT_REF(selection, 2);
9236     EXPECT_REF(enum1, 3);
9237
9238     IEnumVARIANT_Release(enum1);
9239     IEnumVARIANT_Release(enum2);
9240
9241     enum1 = NULL;
9242     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
9243     EXPECT_HR(hr, S_OK);
9244     ok(enum1 != NULL, "got %p\n", enum1);
9245     EXPECT_REF(enum1, 1);
9246     EXPECT_REF(selection, 2);
9247
9248     enum2 = NULL;
9249     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
9250     EXPECT_HR(hr, S_OK);
9251     ok(enum2 != NULL, "got %p\n", enum2);
9252     EXPECT_REF(enum2, 1);
9253     EXPECT_REF(selection, 3);
9254
9255     ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
9256
9257     IEnumVARIANT_AddRef(enum1);
9258     EXPECT_REF(selection, 3);
9259     EXPECT_REF(enum1, 2);
9260     EXPECT_REF(enum2, 1);
9261     IEnumVARIANT_Release(enum1);
9262
9263     IEnumVARIANT_Release(enum1);
9264     IEnumVARIANT_Release(enum2);
9265
9266     EXPECT_REF(selection, 1);
9267
9268     IXMLDOMNodeList_Release(list);
9269
9270     hr = IXMLDOMDocument_get_childNodes(doc, &list);
9271     EXPECT_HR(hr, S_OK);
9272
9273     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9274     EXPECT_HR(hr, E_NOINTERFACE);
9275
9276     IXMLDOMNodeList_Release(list);
9277
9278     /* test if IEnumVARIANT touches selection context */
9279     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
9280     EXPECT_HR(hr, S_OK);
9281
9282     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/*"), &list);
9283     EXPECT_HR(hr, S_OK);
9284
9285     hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9286     EXPECT_HR(hr, S_OK);
9287
9288     len = 0;
9289     hr = IXMLDOMSelection_get_length(selection, &len);
9290     EXPECT_HR(hr, S_OK);
9291     ok(len == 4, "got %d\n", len);
9292
9293     enum1 = NULL;
9294     hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
9295     EXPECT_HR(hr, S_OK);
9296
9297     /* no-op if zero count */
9298     V_VT(&v) = VT_I2;
9299     hr = IEnumVARIANT_Next(enum1, 0, &v, NULL);
9300     EXPECT_HR(hr, S_OK);
9301     ok(V_VT(&v) == VT_I2, "got var type %d\n", V_VT(&v));
9302
9303     /* positive count, null array pointer */
9304     hr = IEnumVARIANT_Next(enum1, 1, NULL, NULL);
9305     EXPECT_HR(hr, E_INVALIDARG);
9306
9307     ret = 1;
9308     hr = IEnumVARIANT_Next(enum1, 1, NULL, &ret);
9309     EXPECT_HR(hr, E_INVALIDARG);
9310     ok(ret == 0, "got %d\n", ret);
9311
9312     V_VT(&v) = VT_I2;
9313     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
9314     EXPECT_HR(hr, S_OK);
9315     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
9316
9317     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
9318     EXPECT_HR(hr, S_OK);
9319     hr = IXMLDOMNode_get_nodeName(node, &name);
9320     EXPECT_HR(hr, S_OK);
9321     ok(!lstrcmpW(name, _bstr_("a")), "got node name %s\n", wine_dbgstr_w(name));
9322     SysFreeString(name);
9323     IXMLDOMNode_Release(node);
9324     VariantClear(&v);
9325
9326     /* list cursor is updated */
9327     hr = IXMLDOMSelection_nextNode(selection, &node);
9328     EXPECT_HR(hr, S_OK);
9329     hr = IXMLDOMNode_get_nodeName(node, &name);
9330     EXPECT_HR(hr, S_OK);
9331     ok(!lstrcmpW(name, _bstr_("c")), "got node name %s\n", wine_dbgstr_w(name));
9332     IXMLDOMNode_Release(node);
9333
9334     V_VT(&v) = VT_I2;
9335     hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
9336     EXPECT_HR(hr, S_OK);
9337     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
9338     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
9339     EXPECT_HR(hr, S_OK);
9340     hr = IXMLDOMNode_get_nodeName(node, &name);
9341     EXPECT_HR(hr, S_OK);
9342     ok(!lstrcmpW(name, _bstr_("b")), "got node name %s\n", wine_dbgstr_w(name));
9343     SysFreeString(name);
9344     IXMLDOMNode_Release(node);
9345     VariantClear(&v);
9346     IEnumVARIANT_Release(enum1);
9347
9348     hr = IXMLDOMSelection_nextNode(selection, &node);
9349     EXPECT_HR(hr, S_OK);
9350     hr = IXMLDOMNode_get_nodeName(node, &name);
9351     EXPECT_HR(hr, S_OK);
9352     ok(!lstrcmpW(name, _bstr_("d")), "got node name %s\n", wine_dbgstr_w(name));
9353     IXMLDOMNode_Release(node);
9354
9355     IXMLDOMSelection_Release(selection);
9356     IXMLDOMNodeList_Release(list);
9357     IXMLDOMDocument_Release(doc);
9358
9359     free_bstrs();
9360 }
9361
9362 static void test_load(void)
9363 {
9364     IXMLDOMDocument *doc;
9365     IXMLDOMNodeList *list;
9366     VARIANT_BOOL b;
9367     HANDLE hfile;
9368     VARIANT src;
9369     HRESULT hr;
9370     BOOL ret;
9371     BSTR path, bstr1, bstr2;
9372     DWORD written;
9373     void* ptr;
9374
9375     /* prepare a file */
9376     hfile = CreateFileA("test.xml", GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
9377     ok(hfile != INVALID_HANDLE_VALUE, "failed to create test file\n");
9378     if(hfile == INVALID_HANDLE_VALUE) return;
9379
9380     ret = WriteFile(hfile, win1252xml, strlen(win1252xml), &written, NULL);
9381     ok(ret, "WriteFile failed\n");
9382
9383     CloseHandle(hfile);
9384
9385     doc = create_document(&IID_IXMLDOMDocument);
9386
9387     /* null pointer as input */
9388     V_VT(&src) = VT_UNKNOWN;
9389     V_UNKNOWN(&src) = NULL;
9390     hr = IXMLDOMDocument_load(doc, src, &b);
9391     EXPECT_HR(hr, E_INVALIDARG);
9392     ok(b == VARIANT_FALSE, "got %d\n", b);
9393
9394     path = _bstr_("test.xml");
9395
9396     /* load from path: VT_BSTR */
9397     V_VT(&src) = VT_BSTR;
9398     V_BSTR(&src) = path;
9399     hr = IXMLDOMDocument_load(doc, src, &b);
9400     EXPECT_HR(hr, S_OK);
9401     ok(b == VARIANT_TRUE, "got %d\n", b);
9402
9403     /* load from a path: VT_BSTR|VT_BYREF */
9404     V_VT(&src) = VT_BSTR | VT_BYREF;
9405     V_BSTRREF(&src) = &path;
9406     hr = IXMLDOMDocument_load(doc, src, &b);
9407     EXPECT_HR(hr, S_OK);
9408     ok(b == VARIANT_TRUE, "got %d\n", b);
9409
9410     /* load from a path: VT_BSTR|VT_BYREF, null ptr */
9411     V_VT(&src) = VT_BSTR | VT_BYREF;
9412     V_BSTRREF(&src) = NULL;
9413     hr = IXMLDOMDocument_load(doc, src, &b);
9414     EXPECT_HR(hr, E_INVALIDARG);
9415     ok(b == VARIANT_FALSE, "got %d\n", b);
9416
9417     IXMLDOMDocument_Release(doc);
9418
9419     DeleteFileA("test.xml");
9420
9421     doc = create_document(&IID_IXMLDOMDocument);
9422
9423     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
9424     EXPECT_HR(hr, S_OK);
9425     ok(b == VARIANT_TRUE, "got %d\n", b);
9426
9427     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
9428     EXPECT_HR(hr, S_OK);
9429     bstr1 = _bstr_(list_to_string(list));
9430
9431     hr = IXMLDOMNodeList_reset(list);
9432     EXPECT_HR(hr, S_OK);
9433
9434     IXMLDOMDocument_Release(doc);
9435
9436     doc = create_document(&IID_IXMLDOMDocument);
9437
9438     VariantInit(&src);
9439     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenA(szExampleXML));
9440     V_VT(&src) = VT_ARRAY|VT_UI1;
9441     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
9442     ptr = NULL;
9443     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
9444     EXPECT_HR(hr, S_OK);
9445     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
9446
9447     memcpy(ptr, szExampleXML, lstrlenA(szExampleXML));
9448     hr = SafeArrayUnlock(V_ARRAY(&src));
9449     EXPECT_HR(hr, S_OK);
9450
9451     hr = IXMLDOMDocument_load(doc, src, &b);
9452     EXPECT_HR(hr, S_OK);
9453     ok(b == VARIANT_TRUE, "got %d\n", b);
9454
9455     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
9456     EXPECT_HR(hr, S_OK);
9457     bstr2 = _bstr_(list_to_string(list));
9458
9459     hr = IXMLDOMNodeList_reset(list);
9460     EXPECT_HR(hr, S_OK);
9461
9462     ok(lstrcmpW(bstr1, bstr2) == 0, "strings not equal: %s : %s\n",
9463        wine_dbgstr_w(bstr1), wine_dbgstr_w(bstr2));
9464
9465     IXMLDOMDocument_Release(doc);
9466     IXMLDOMNodeList_Release(list);
9467     VariantClear(&src);
9468
9469     /* UTF-16 isn't accepted */
9470     doc = create_document(&IID_IXMLDOMDocument);
9471
9472     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenW(szComplete1) * sizeof(WCHAR));
9473     V_VT(&src) = VT_ARRAY|VT_UI1;
9474     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
9475     ptr = NULL;
9476     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
9477     EXPECT_HR(hr, S_OK);
9478     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
9479
9480     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
9481     hr = SafeArrayUnlock(V_ARRAY(&src));
9482     EXPECT_HR(hr, S_OK);
9483
9484     hr = IXMLDOMDocument_load(doc, src, &b);
9485     todo_wine EXPECT_HR(hr, S_FALSE);
9486     todo_wine ok(b == VARIANT_FALSE, "got %d\n", b);
9487
9488     VariantClear(&src);
9489
9490     /* it doesn't like it as a VT_ARRAY|VT_UI2 either */
9491     V_ARRAY(&src) = SafeArrayCreateVector(VT_UI2, 0, lstrlenW(szComplete1));
9492     V_VT(&src) = VT_ARRAY|VT_UI2;
9493     ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
9494     ptr = NULL;
9495     hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
9496     EXPECT_HR(hr, S_OK);
9497     ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
9498
9499     memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
9500     hr = SafeArrayUnlock(V_ARRAY(&src));
9501     EXPECT_HR(hr, S_OK);
9502
9503     hr = IXMLDOMDocument_load(doc, src, &b);
9504     todo_wine EXPECT_HR(hr, E_INVALIDARG);
9505     ok(b == VARIANT_FALSE, "got %d\n", b);
9506
9507     VariantClear(&src);
9508     IXMLDOMDocument_Release(doc);
9509
9510     free_bstrs();
9511 }
9512
9513 static void test_domobj_dispex(IUnknown *obj)
9514 {
9515     DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
9516     IDispatchEx *dispex;
9517     IUnknown *unk;
9518     DWORD props;
9519     UINT ticnt;
9520     HRESULT hr;
9521     BSTR name;
9522
9523     hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
9524     EXPECT_HR(hr, S_OK);
9525     if (FAILED(hr)) return;
9526
9527     ticnt = 0;
9528     hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
9529     EXPECT_HR(hr, S_OK);
9530     ok(ticnt == 1, "ticnt=%u\n", ticnt);
9531
9532     name = SysAllocString(szstar);
9533     hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
9534     EXPECT_HR(hr, E_NOTIMPL);
9535     SysFreeString(name);
9536
9537     hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
9538     EXPECT_HR(hr, E_NOTIMPL);
9539
9540     props = 0;
9541     hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
9542     EXPECT_HR(hr, E_NOTIMPL);
9543     ok(props == 0, "expected 0 got %d\n", props);
9544
9545     hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
9546     EXPECT_HR(hr, E_NOTIMPL);
9547     if (SUCCEEDED(hr)) SysFreeString(name);
9548
9549     hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
9550     EXPECT_HR(hr, E_NOTIMPL);
9551
9552     hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
9553     EXPECT_HR(hr, E_NOTIMPL);
9554     if (hr == S_OK && unk) IUnknown_Release(unk);
9555
9556     IDispatchEx_Release(dispex);
9557 }
9558
9559 static void test_mxnamespacemanager(void)
9560 {
9561     static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
9562     IMXNamespacePrefixes *prefixes;
9563     IVBMXNamespaceManager *mgr2;
9564     IMXNamespaceManager *nsmgr;
9565     IUnknown *unk1, *unk2;
9566     WCHAR buffW[250];
9567     IDispatch *disp;
9568     IUnknown *unk;
9569     HRESULT hr;
9570     INT len;
9571
9572     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
9573         &IID_IMXNamespaceManager, (void**)&nsmgr);
9574     EXPECT_HR(hr, S_OK);
9575
9576     /* IMXNamespaceManager inherits from IUnknown */
9577     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IDispatch, (void**)&disp);
9578     EXPECT_HR(hr, S_OK);
9579     IDispatch_Release(disp);
9580
9581     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IVBMXNamespaceManager, (void**)&mgr2);
9582     EXPECT_HR(hr, S_OK);
9583
9584     EXPECT_REF(nsmgr, 2);
9585     EXPECT_REF(mgr2, 2);
9586     prefixes = NULL;
9587     hr = IVBMXNamespaceManager_getDeclaredPrefixes(mgr2, &prefixes);
9588     if (hr == S_OK)
9589     {
9590         IDispatchEx *dispex;
9591         VARIANT arg, ret;
9592         DISPPARAMS dispparams;
9593
9594         ok(prefixes != NULL, "got %p\n", prefixes);
9595         EXPECT_REF(nsmgr, 2);
9596         EXPECT_REF(mgr2, 2);
9597         EXPECT_REF(prefixes, 1);
9598
9599         IVBMXNamespaceManager_QueryInterface(mgr2, &IID_IUnknown, (void**)&unk1);
9600         IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IUnknown, (void**)&unk2);
9601
9602         EXPECT_REF(mgr2, 3);
9603         EXPECT_REF(prefixes, 2);
9604
9605         IUnknown_Release(unk1);
9606         IUnknown_Release(unk2);
9607
9608         hr = IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IDispatchEx, (void**)&dispex);
9609         ok(hr == S_OK, "got 0x%08x\n", hr);
9610
9611         V_VT(&arg) = VT_I4;
9612         V_I4(&arg) = 0;
9613         dispparams.cArgs = 1;
9614         dispparams.cNamedArgs = 0;
9615         dispparams.rgdispidNamedArgs = NULL;
9616         dispparams.rgvarg = &arg;
9617
9618         V_VT(&ret) = VT_EMPTY;
9619         V_DISPATCH(&ret) = (void*)0x1;
9620         hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
9621         ok(hr == S_OK, "got 0x%08x\n", hr);
9622         ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
9623         ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
9624
9625         IDispatchEx_Release(dispex);
9626         IMXNamespacePrefixes_Release(prefixes);
9627     }
9628     IVBMXNamespaceManager_Release(mgr2);
9629
9630     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
9631     EXPECT_HR(hr, S_OK);
9632
9633     /* prefix already added */
9634     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
9635     EXPECT_HR(hr, S_FALSE);
9636
9637     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
9638     EXPECT_HR(hr, E_INVALIDARG);
9639
9640     /* "xml" and "xmlns" are not allowed here */
9641     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xml"), _bstr_("uri1"));
9642     EXPECT_HR(hr, E_INVALIDARG);
9643
9644     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
9645     EXPECT_HR(hr, E_INVALIDARG);
9646 todo_wine {
9647     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
9648     EXPECT_HR(hr, E_FAIL);
9649 }
9650     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
9651     EXPECT_HR(hr, E_POINTER);
9652
9653     len = -1;
9654     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
9655     EXPECT_HR(hr, S_OK);
9656     ok(len == 3, "got %d\n", len);
9657
9658     len = -1;
9659     buffW[0] = 0x1;
9660     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
9661     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
9662     ok(len == -1, "got %d\n", len);
9663     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9664
9665     len = 10;
9666     buffW[0] = 0x1;
9667     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
9668     EXPECT_HR(hr, S_OK);
9669     ok(len == 3, "got %d\n", len);
9670     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
9671
9672     /* getURI */
9673     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, NULL);
9674     EXPECT_HR(hr, E_INVALIDARG);
9675
9676     len = -1;
9677     hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, &len);
9678     EXPECT_HR(hr, E_INVALIDARG);
9679     ok(len == -1, "got %d\n", len);
9680
9681     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, NULL);
9682     EXPECT_HR(hr, E_POINTER);
9683
9684     len = -1;
9685     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, &len);
9686     EXPECT_HR(hr, S_OK);
9687     /* length of "xml" uri is constant */
9688     ok(len == strlen(xmluriA), "got %d\n", len);
9689
9690     len = 100;
9691     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
9692     EXPECT_HR(hr, S_OK);
9693     ok(len == strlen(xmluriA), "got %d\n", len);
9694     ok(!lstrcmpW(buffW, _bstr_(xmluriA)), "got prefix %s\n", wine_dbgstr_w(buffW));
9695
9696     len = strlen(xmluriA)-1;
9697     buffW[0] = 0x1;
9698     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
9699     EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
9700     ok(len == strlen(xmluriA)-1, "got %d\n", len);
9701     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9702
9703     /* prefix xml1 not defined */
9704     len = -1;
9705     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, NULL, &len);
9706     EXPECT_HR(hr, S_FALSE);
9707     ok(len == 0, "got %d\n", len);
9708
9709     len = 100;
9710     buffW[0] = 0x1;
9711     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, buffW, &len);
9712     EXPECT_HR(hr, S_FALSE);
9713     ok(buffW[0] == 0, "got %x\n", buffW[0]);
9714     ok(len == 0, "got %d\n", len);
9715
9716     /* IDispatchEx tests */
9717     hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IUnknown, (void**)&unk);
9718     EXPECT_HR(hr, S_OK);
9719     test_domobj_dispex(unk);
9720     IUnknown_Release(unk);
9721
9722     IMXNamespaceManager_Release(nsmgr);
9723
9724     /* ::getPrefix() */
9725     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
9726         &IID_IMXNamespaceManager, (void**)&nsmgr);
9727     EXPECT_HR(hr, S_OK);
9728
9729     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, NULL);
9730     EXPECT_HR(hr, E_INVALIDARG);
9731
9732     len = -1;
9733     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, &len);
9734     EXPECT_HR(hr, E_INVALIDARG);
9735     ok(len == -1, "got %d\n", len);
9736
9737     len = 100;
9738     buffW[0] = 0x1;
9739     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
9740     EXPECT_HR(hr, E_FAIL);
9741     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9742     ok(len == 100, "got %d\n", len);
9743
9744     len = 0;
9745     buffW[0] = 0x1;
9746     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
9747     EXPECT_HR(hr, E_FAIL);
9748     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9749     ok(len == 0, "got %d\n", len);
9750
9751     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
9752     EXPECT_HR(hr, S_OK);
9753
9754     len = 100;
9755     buffW[0] = 0x1;
9756     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9757     EXPECT_HR(hr, S_OK);
9758     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9759     ok(len == 3, "got %d\n", len);
9760
9761     len = 100;
9762     buffW[0] = 0x1;
9763     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, buffW, &len);
9764     EXPECT_HR(hr, S_OK);
9765     ok(!lstrcmpW(buffW, _bstr_("xml")), "got %s\n", wine_dbgstr_w(buffW));
9766     ok(len == 3, "got %d\n", len);
9767
9768     /* with null buffer it's possible to get required length */
9769     len = 100;
9770     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
9771     EXPECT_HR(hr, S_OK);
9772     ok(len == 3, "got %d\n", len);
9773
9774     len = 0;
9775     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
9776     EXPECT_HR(hr, S_OK);
9777     ok(len == 3, "got %d\n", len);
9778
9779     len = 100;
9780     buffW[0] = 0x1;
9781     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 1, buffW, &len);
9782     EXPECT_HR(hr, E_FAIL);
9783     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9784     ok(len == 100, "got %d\n", len);
9785
9786     len = 100;
9787     buffW[0] = 0x1;
9788     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 2, buffW, &len);
9789     EXPECT_HR(hr, E_FAIL);
9790     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9791     ok(len == 100, "got %d\n", len);
9792
9793     len = 100;
9794     buffW[0] = 0x1;
9795     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 0, buffW, &len);
9796     EXPECT_HR(hr, E_INVALIDARG);
9797     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9798     ok(len == 100, "got %d\n", len);
9799
9800     len = 100;
9801     buffW[0] = 0x1;
9802     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
9803     EXPECT_HR(hr, E_INVALIDARG);
9804     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9805     ok(len == 100, "got %d\n", len);
9806
9807     len = 100;
9808     buffW[0] = 0x1;
9809     hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, buffW, &len);
9810     EXPECT_HR(hr, E_INVALIDARG);
9811     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9812     ok(len == 100, "got %d\n", len);
9813
9814     len = 100;
9815     buffW[0] = 0x1;
9816     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 1, buffW, &len);
9817     EXPECT_HR(hr, E_FAIL);
9818     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9819     ok(len == 100, "got %d\n", len);
9820
9821     len = 100;
9822     buffW[0] = 0x1;
9823     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
9824     EXPECT_HR(hr, E_INVALIDARG);
9825     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9826     ok(len == 100, "got %d\n", len);
9827
9828     /* declare another one, indices are shifted */
9829     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
9830     EXPECT_HR(hr, S_OK);
9831
9832     len = 100;
9833     buffW[0] = 0x1;
9834     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9835     EXPECT_HR(hr, S_OK);
9836     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9837     ok(len == 3, "got %d\n", len);
9838
9839     len = 100;
9840     buffW[0] = 0x1;
9841     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
9842     EXPECT_HR(hr, S_OK);
9843     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
9844     ok(len == 3, "got %d\n", len);
9845
9846     len = 100;
9847     buffW[0] = 0x1;
9848     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 1, buffW, &len);
9849     EXPECT_HR(hr, E_FAIL);
9850     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9851     ok(len == 100, "got %d\n", len);
9852
9853     len = 100;
9854     buffW[0] = 0x1;
9855     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
9856     EXPECT_HR(hr, E_INVALIDARG);
9857     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9858     ok(len == 100, "got %d\n", len);
9859
9860     IMXNamespaceManager_Release(nsmgr);
9861
9862     /* push/pop tests */
9863     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
9864         &IID_IMXNamespaceManager, (void**)&nsmgr);
9865     EXPECT_HR(hr, S_OK);
9866
9867     /* pop with empty stack */
9868     hr = IMXNamespaceManager_popContext(nsmgr);
9869     EXPECT_HR(hr, E_FAIL);
9870
9871     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
9872     EXPECT_HR(hr, S_OK);
9873
9874     len = 100;
9875     buffW[0] = 0x1;
9876     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9877     EXPECT_HR(hr, S_OK);
9878     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9879     ok(len == 3, "got %d\n", len);
9880
9881     hr = IMXNamespaceManager_pushContext(nsmgr);
9882     EXPECT_HR(hr, S_OK);
9883
9884     len = 100;
9885     buffW[0] = 0x1;
9886     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9887     EXPECT_HR(hr, S_OK);
9888     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9889     ok(len == 3, "got %d\n", len);
9890
9891     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
9892     EXPECT_HR(hr, S_OK);
9893
9894     len = 100;
9895     buffW[0] = 0x1;
9896     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
9897     EXPECT_HR(hr, S_OK);
9898     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
9899     ok(len == 3, "got %d\n", len);
9900
9901     hr = IMXNamespaceManager_pushContext(nsmgr);
9902     EXPECT_HR(hr, S_OK);
9903     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns3"), _bstr_("ns3 uri"));
9904     EXPECT_HR(hr, S_OK);
9905
9906     len = 100;
9907     buffW[0] = 0x1;
9908     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
9909     EXPECT_HR(hr, S_OK);
9910     ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
9911     ok(len == 3, "got %d\n", len);
9912
9913     len = 100;
9914     buffW[0] = 0x1;
9915     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9916     EXPECT_HR(hr, S_OK);
9917     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9918     ok(len == 3, "got %d\n", len);
9919
9920     hr = IMXNamespaceManager_popContext(nsmgr);
9921     EXPECT_HR(hr, S_OK);
9922
9923     hr = IMXNamespaceManager_popContext(nsmgr);
9924     EXPECT_HR(hr, S_OK);
9925
9926     len = 100;
9927     buffW[0] = 0x1;
9928     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
9929     EXPECT_HR(hr, E_FAIL);
9930     ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
9931     ok(len == 100, "got %d\n", len);
9932
9933     len = 100;
9934     buffW[0] = 0x1;
9935     hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
9936     EXPECT_HR(hr, S_OK);
9937     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
9938     ok(len == 3, "got %d\n", len);
9939
9940     IMXNamespaceManager_Release(nsmgr);
9941
9942     free_bstrs();
9943 }
9944
9945 static void test_mxnamespacemanager_override(void)
9946 {
9947     IMXNamespaceManager *nsmgr;
9948     WCHAR buffW[250];
9949     VARIANT_BOOL b;
9950     HRESULT hr;
9951     INT len;
9952
9953     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
9954         &IID_IMXNamespaceManager, (void**)&nsmgr);
9955     EXPECT_HR(hr, S_OK);
9956
9957     len = sizeof(buffW)/sizeof(WCHAR);
9958     buffW[0] = 0;
9959     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
9960     EXPECT_HR(hr, S_OK);
9961     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
9962
9963     len = sizeof(buffW)/sizeof(WCHAR);
9964     buffW[0] = 0;
9965     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
9966     EXPECT_HR(hr, E_FAIL);
9967
9968     hr = IMXNamespaceManager_getAllowOverride(nsmgr, NULL);
9969     EXPECT_HR(hr, E_POINTER);
9970
9971     b = VARIANT_FALSE;
9972     hr = IMXNamespaceManager_getAllowOverride(nsmgr, &b);
9973     EXPECT_HR(hr, S_OK);
9974     ok(b == VARIANT_TRUE, "got %d\n", b);
9975
9976     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_FALSE);
9977     EXPECT_HR(hr, S_OK);
9978
9979     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
9980     EXPECT_HR(hr, S_OK);
9981
9982     len = sizeof(buffW)/sizeof(WCHAR);
9983     buffW[0] = 0;
9984     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
9985     EXPECT_HR(hr, S_OK);
9986     ok(!lstrcmpW(buffW, _bstr_("ns0 uri")), "got uri %s\n", wine_dbgstr_w(buffW));
9987
9988     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), _bstr_("ns0 uri"));
9989     EXPECT_HR(hr, S_OK);
9990
9991     len = sizeof(buffW)/sizeof(WCHAR);
9992     buffW[0] = 0;
9993     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
9994     EXPECT_HR(hr, S_OK);
9995     ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
9996
9997     len = sizeof(buffW)/sizeof(WCHAR);
9998     buffW[0] = 0;
9999     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10000     EXPECT_HR(hr, S_OK);
10001     ok(!lstrcmpW(buffW, _bstr_("ns0")), "got prefix %s\n", wine_dbgstr_w(buffW));
10002
10003     len = sizeof(buffW)/sizeof(WCHAR);
10004     buffW[0] = 0;
10005     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 2, buffW, &len);
10006     EXPECT_HR(hr, S_OK);
10007     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10008
10009     /* new prefix placed at index 1 always */
10010     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10011     EXPECT_HR(hr, S_OK);
10012
10013     len = sizeof(buffW)/sizeof(WCHAR);
10014     buffW[0] = 0;
10015     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10016     EXPECT_HR(hr, S_OK);
10017     ok(!lstrcmpW(buffW, _bstr_("ns1")), "got prefix %s\n", wine_dbgstr_w(buffW));
10018
10019     hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_(""), NULL);
10020     todo_wine EXPECT_HR(hr, E_FAIL);
10021
10022     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10023     EXPECT_HR(hr, E_FAIL);
10024
10025     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10026     EXPECT_HR(hr, E_FAIL);
10027
10028     hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_TRUE);
10029     EXPECT_HR(hr, S_OK);
10030
10031     hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri override"));
10032     EXPECT_HR(hr, S_FALSE);
10033
10034     len = sizeof(buffW)/sizeof(WCHAR);
10035     buffW[0] = 0;
10036     hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10037     EXPECT_HR(hr, S_OK);
10038     ok(!lstrcmpW(buffW, _bstr_("ns0 uri override")), "got uri %s\n", wine_dbgstr_w(buffW));
10039
10040     len = sizeof(buffW)/sizeof(WCHAR);
10041     buffW[0] = 0;
10042     hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 3, buffW, &len);
10043     EXPECT_HR(hr, S_OK);
10044     ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10045
10046     IMXNamespaceManager_Release(nsmgr);
10047
10048     free_bstrs();
10049 }
10050
10051 static const DOMNodeType nodetypes_test[] =
10052 {
10053     NODE_ELEMENT,
10054     NODE_ATTRIBUTE,
10055     NODE_TEXT,
10056     NODE_CDATA_SECTION,
10057     NODE_ENTITY_REFERENCE,
10058     NODE_PROCESSING_INSTRUCTION,
10059     NODE_COMMENT,
10060     NODE_DOCUMENT_FRAGMENT,
10061     NODE_INVALID
10062 };
10063
10064 static void test_dispex(void)
10065 {
10066     const DOMNodeType *type = nodetypes_test;
10067     IXMLDOMImplementation *impl;
10068     IXMLDOMNodeList *node_list;
10069     IXMLDOMParseError *error;
10070     IXMLDOMNamedNodeMap *map;
10071     IXSLProcessor *processor;
10072     IXSLTemplate *template;
10073     IXMLDOMDocument *doc;
10074     IXMLHTTPRequest *req;
10075     IXMLDOMElement *elem;
10076     IDispatchEx *dispex;
10077     DISPPARAMS dispparams;
10078     IXMLDOMNode *node;
10079     VARIANT arg, ret;
10080     VARIANT_BOOL b;
10081     IUnknown *unk;
10082     HRESULT hr;
10083     DISPID did;
10084
10085     doc = create_document(&IID_IXMLDOMDocument);
10086
10087     IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
10088     test_domobj_dispex(unk);
10089     IUnknown_Release(unk);
10090
10091     for(; *type != NODE_INVALID; type++)
10092     {
10093         IXMLDOMNode *node;
10094         VARIANT v;
10095
10096         V_VT(&v) = VT_I2;
10097         V_I2(&v) = *type;
10098
10099         hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
10100         ok(hr == S_OK, "failed to create node type %d\n", *type);
10101
10102         IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
10103
10104         test_domobj_dispex(unk);
10105         IUnknown_Release(unk);
10106         IXMLDOMNode_Release(node);
10107     }
10108
10109     /* IXMLDOMNodeList */
10110     hr = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), &node_list);
10111     EXPECT_HR(hr, S_OK);
10112     IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
10113     test_domobj_dispex(unk);
10114     IUnknown_Release(unk);
10115     IXMLDOMNodeList_Release(node_list);
10116
10117     /* IXMLDOMNodeList for children list */
10118     hr = IXMLDOMDocument_get_childNodes(doc, &node_list);
10119     EXPECT_HR(hr, S_OK);
10120     IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
10121     test_domobj_dispex(unk);
10122     IUnknown_Release(unk);
10123
10124     /* collection dispex test, empty collection */
10125     hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatchEx, (void**)&dispex);
10126     EXPECT_HR(hr, S_OK);
10127     did = 0;
10128     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
10129     EXPECT_HR(hr, S_OK);
10130     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
10131     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
10132     EXPECT_HR(hr, S_OK);
10133     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
10134     IDispatchEx_Release(dispex);
10135
10136     did = -1;
10137     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
10138     ok(hr == S_OK, "got 0x%08x\n", hr);
10139     ok(did == DISPID_VALUE, "got %d\n", did);
10140
10141     V_VT(&arg) = VT_I4;
10142     V_I4(&arg) = 0;
10143     dispparams.cArgs = 0;
10144     dispparams.cNamedArgs = 0;
10145     dispparams.rgdispidNamedArgs = NULL;
10146     dispparams.rgvarg = &arg;
10147
10148     V_VT(&ret) = VT_EMPTY;
10149     V_DISPATCH(&ret) = (void*)0x1;
10150     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10151     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
10152     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10153     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
10154
10155     V_VT(&arg) = VT_I4;
10156     V_I4(&arg) = 0;
10157     dispparams.cArgs = 2;
10158     dispparams.cNamedArgs = 0;
10159     dispparams.rgdispidNamedArgs = NULL;
10160     dispparams.rgvarg = &arg;
10161
10162     V_VT(&ret) = VT_EMPTY;
10163     V_DISPATCH(&ret) = (void*)0x1;
10164     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10165     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
10166     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10167     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
10168
10169     V_VT(&arg) = VT_I4;
10170     V_I4(&arg) = 0;
10171     dispparams.cArgs = 1;
10172     dispparams.cNamedArgs = 0;
10173     dispparams.rgdispidNamedArgs = NULL;
10174     dispparams.rgvarg = &arg;
10175
10176     V_VT(&ret) = VT_EMPTY;
10177     V_DISPATCH(&ret) = (void*)0x1;
10178     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10179     ok(hr == S_OK, "got 0x%08x\n", hr);
10180     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10181     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10182
10183     V_VT(&ret) = VT_EMPTY;
10184     V_DISPATCH(&ret) = (void*)0x1;
10185     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
10186     ok(hr == S_OK, "got 0x%08x\n", hr);
10187     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10188     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10189
10190     V_VT(&ret) = VT_EMPTY;
10191     V_DISPATCH(&ret) = (void*)0x1;
10192     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10193     ok(hr == S_OK, "got 0x%08x\n", hr);
10194     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10195     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10196
10197     dispparams.cArgs = 0;
10198     dispparams.cNamedArgs = 0;
10199     dispparams.rgdispidNamedArgs = NULL;
10200     dispparams.rgvarg = NULL;
10201
10202     V_VT(&ret) = VT_EMPTY;
10203     V_I4(&ret) = 1;
10204     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
10205     ok(hr == S_OK, "got 0x%08x\n", hr);
10206     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
10207     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
10208
10209     dispparams.cArgs = 0;
10210     dispparams.cNamedArgs = 0;
10211     dispparams.rgdispidNamedArgs = NULL;
10212     dispparams.rgvarg = NULL;
10213
10214     V_VT(&ret) = VT_EMPTY;
10215     V_I4(&ret) = 1;
10216     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10217     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
10218     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10219     ok(V_I4(&ret) == 1, "got %d\n", V_I4(&ret));
10220
10221     IXMLDOMNodeList_Release(node_list);
10222
10223     /* IXMLDOMParseError */
10224     hr = IXMLDOMDocument_get_parseError(doc, &error);
10225     EXPECT_HR(hr, S_OK);
10226     IXMLDOMParseError_QueryInterface(error, &IID_IUnknown, (void**)&unk);
10227     test_domobj_dispex(unk);
10228
10229     hr = IXMLDOMParseError_QueryInterface(error, &IID_IDispatchEx, (void**)&dispex);
10230     ok(hr == S_OK, "got 0x%08x\n", hr);
10231
10232     V_VT(&arg) = VT_I4;
10233     V_I4(&arg) = 0;
10234     dispparams.cArgs = 1;
10235     dispparams.cNamedArgs = 0;
10236     dispparams.rgdispidNamedArgs = NULL;
10237     dispparams.rgvarg = &arg;
10238
10239     V_VT(&ret) = VT_EMPTY;
10240     V_DISPATCH(&ret) = (void*)0x1;
10241     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10242     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
10243     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10244     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
10245
10246     IDispatchEx_Release(dispex);
10247
10248     IUnknown_Release(unk);
10249     IXMLDOMParseError_Release(error);
10250
10251     /* IXMLDOMNamedNodeMap */
10252     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
10253     EXPECT_HR(hr, S_OK);
10254
10255     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/a"), &node_list);
10256     EXPECT_HR(hr, S_OK);
10257     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
10258     EXPECT_HR(hr, S_OK);
10259     IXMLDOMNodeList_Release(node_list);
10260
10261     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
10262     EXPECT_HR(hr, S_OK);
10263     IXMLDOMNode_Release(node);
10264     hr = IXMLDOMElement_get_attributes(elem, &map);
10265     EXPECT_HR(hr, S_OK);
10266     IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk);
10267     test_domobj_dispex(unk);
10268     IUnknown_Release(unk);
10269     /* collection dispex test */
10270     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
10271     EXPECT_HR(hr, S_OK);
10272     did = 0;
10273     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
10274     EXPECT_HR(hr, S_OK);
10275     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
10276     IDispatchEx_Release(dispex);
10277
10278     hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/b"), &node_list);
10279     EXPECT_HR(hr, S_OK);
10280     hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
10281     EXPECT_HR(hr, S_OK);
10282     IXMLDOMNodeList_Release(node_list);
10283     hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
10284     EXPECT_HR(hr, S_OK);
10285     IXMLDOMNode_Release(node);
10286     hr = IXMLDOMElement_get_attributes(elem, &map);
10287     EXPECT_HR(hr, S_OK);
10288     /* collection dispex test, empty collection */
10289     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
10290     EXPECT_HR(hr, S_OK);
10291     did = 0;
10292     hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
10293     EXPECT_HR(hr, S_OK);
10294     ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
10295     hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
10296     EXPECT_HR(hr, S_OK);
10297     ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
10298     IDispatchEx_Release(dispex);
10299
10300     did = -1;
10301     hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
10302     ok(hr == S_OK, "got 0x%08x\n", hr);
10303     ok(did == DISPID_VALUE, "got %d\n", did);
10304
10305     V_VT(&arg) = VT_I4;
10306     V_I4(&arg) = 0;
10307     dispparams.cArgs = 0;
10308     dispparams.cNamedArgs = 0;
10309     dispparams.rgdispidNamedArgs = NULL;
10310     dispparams.rgvarg = &arg;
10311
10312     V_VT(&ret) = VT_EMPTY;
10313     V_DISPATCH(&ret) = (void*)0x1;
10314     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10315 todo_wine {
10316     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
10317     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10318     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
10319 }
10320     V_VT(&arg) = VT_I4;
10321     V_I4(&arg) = 0;
10322     dispparams.cArgs = 2;
10323     dispparams.cNamedArgs = 0;
10324     dispparams.rgdispidNamedArgs = NULL;
10325     dispparams.rgvarg = &arg;
10326
10327     V_VT(&ret) = VT_EMPTY;
10328     V_DISPATCH(&ret) = (void*)0x1;
10329     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10330 todo_wine {
10331     ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
10332     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10333     ok(V_DISPATCH(&ret) == (void*)0x1, "got %p\n", V_DISPATCH(&ret));
10334 }
10335     V_VT(&arg) = VT_I4;
10336     V_I4(&arg) = 0;
10337     dispparams.cArgs = 1;
10338     dispparams.cNamedArgs = 0;
10339     dispparams.rgdispidNamedArgs = NULL;
10340     dispparams.rgvarg = &arg;
10341
10342     V_VT(&ret) = VT_EMPTY;
10343     V_DISPATCH(&ret) = (void*)0x1;
10344     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10345 todo_wine
10346     ok(hr == S_OK, "got 0x%08x\n", hr);
10347     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10348     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10349
10350     V_VT(&ret) = VT_EMPTY;
10351     V_DISPATCH(&ret) = (void*)0x1;
10352     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
10353     ok(hr == S_OK, "got 0x%08x\n", hr);
10354     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10355     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10356
10357     V_VT(&ret) = VT_EMPTY;
10358     V_DISPATCH(&ret) = (void*)0x1;
10359     hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10360     ok(hr == S_OK, "got 0x%08x\n", hr);
10361     ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
10362     ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
10363
10364     dispparams.cArgs = 0;
10365     dispparams.cNamedArgs = 0;
10366     dispparams.rgdispidNamedArgs = NULL;
10367     dispparams.rgvarg = NULL;
10368
10369     V_VT(&ret) = VT_EMPTY;
10370     V_I4(&ret) = 1;
10371     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
10372     ok(hr == S_OK, "got 0x%08x\n", hr);
10373     ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
10374     ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
10375
10376     dispparams.cArgs = 0;
10377     dispparams.cNamedArgs = 0;
10378     dispparams.rgdispidNamedArgs = NULL;
10379     dispparams.rgvarg = NULL;
10380
10381     V_VT(&ret) = VT_EMPTY;
10382     V_I4(&ret) = 1;
10383     hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10384     ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
10385 todo_wine {
10386     ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
10387     ok(V_I4(&ret) == 1, "got %d\n", V_I4(&ret));
10388 }
10389     IXMLDOMNamedNodeMap_Release(map);
10390     IXMLDOMElement_Release(elem);
10391
10392     /* IXMLDOMImplementation */
10393     hr = IXMLDOMDocument_get_implementation(doc, &impl);
10394     EXPECT_HR(hr, S_OK);
10395
10396     hr = IXMLDOMImplementation_QueryInterface(impl, &IID_IDispatchEx, (void**)&dispex);
10397     EXPECT_HR(hr, S_OK);
10398     IDispatchEx_Release(dispex);
10399     IXMLDOMImplementation_Release(impl);
10400
10401     IXMLDOMDocument_Release(doc);
10402
10403     /* IXMLHTTPRequest */
10404     hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
10405         &IID_IXMLHttpRequest, (void**)&req);
10406     if (hr == S_OK)
10407     {
10408         hr = IXMLHTTPRequest_QueryInterface(req, &IID_IDispatchEx, (void**)&dispex);
10409         EXPECT_HR(hr, E_NOINTERFACE);
10410         IXMLHTTPRequest_Release(req);
10411     }
10412
10413     /* IXSLTemplate */
10414     template = create_xsltemplate(&IID_IXSLTemplate);
10415     hr = IXSLTemplate_QueryInterface(template, &IID_IDispatchEx, (void**)&dispex);
10416     EXPECT_HR(hr, S_OK);
10417     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
10418     EXPECT_HR(hr, S_OK);
10419     test_domobj_dispex(unk);
10420     IUnknown_Release(unk);
10421     IDispatchEx_Release(dispex);
10422
10423     /* IXSLProcessor */
10424     hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
10425     EXPECT_HR(hr, S_OK);
10426     b = VARIANT_FALSE;
10427     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformSSXML), &b);
10428     EXPECT_HR(hr, S_OK);
10429     ok(b == VARIANT_TRUE, "got %d\n", b);
10430
10431     hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
10432     EXPECT_HR(hr, S_OK);
10433     IXMLDOMDocument_Release(doc);
10434
10435     hr = IXSLTemplate_createProcessor(template, &processor);
10436     EXPECT_HR(hr, S_OK);
10437     hr = IXSLProcessor_QueryInterface(processor, &IID_IDispatchEx, (void**)&dispex);
10438     EXPECT_HR(hr, S_OK);
10439     hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
10440     EXPECT_HR(hr, S_OK);
10441     test_domobj_dispex(unk);
10442     IUnknown_Release(unk);
10443     IDispatchEx_Release(dispex);
10444
10445     IXSLProcessor_Release(processor);
10446     IXSLTemplate_Release(template);
10447
10448     free_bstrs();
10449 }
10450
10451 static void test_parseerror(void)
10452 {
10453     IXMLDOMParseError2 *error2;
10454     IXMLDOMParseError *error;
10455     IXMLDOMDocument *doc;
10456     HRESULT hr;
10457
10458     doc = create_document(&IID_IXMLDOMDocument);
10459
10460     hr = IXMLDOMDocument_get_parseError(doc, &error);
10461     EXPECT_HR(hr, S_OK);
10462
10463     hr = IXMLDOMParseError_get_line(error, NULL);
10464     EXPECT_HR(hr, E_INVALIDARG);
10465
10466     hr = IXMLDOMParseError_get_srcText(error, NULL);
10467     EXPECT_HR(hr, E_INVALIDARG);
10468
10469     hr = IXMLDOMParseError_get_linepos(error, NULL);
10470     EXPECT_HR(hr, E_INVALIDARG);
10471
10472     IXMLDOMParseError_Release(error);
10473     IXMLDOMDocument_Release(doc);
10474
10475     doc = create_document_version(60, &IID_IXMLDOMDocument);
10476     if (!doc) return;
10477     hr = IXMLDOMDocument_get_parseError(doc, &error);
10478     EXPECT_HR(hr, S_OK);
10479     hr = IXMLDOMParseError_QueryInterface(error, &IID_IXMLDOMParseError2, (void**)&error2);
10480     EXPECT_HR(hr, S_OK);
10481     IXMLDOMParseError2_Release(error2);
10482     IXMLDOMParseError_Release(error);
10483     IXMLDOMDocument_Release(doc);
10484 }
10485
10486 static void test_getAttributeNode(void)
10487 {
10488     IXMLDOMAttribute *attr;
10489     IXMLDOMDocument *doc;
10490     IXMLDOMElement *elem;
10491     VARIANT_BOOL v;
10492     HRESULT hr;
10493     BSTR str;
10494
10495     doc = create_document(&IID_IXMLDOMDocument);
10496
10497     hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
10498     EXPECT_HR(hr, S_OK);
10499
10500     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10501     EXPECT_HR(hr, S_OK);
10502
10503     str = SysAllocString(nonexistent_fileW);
10504     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
10505     EXPECT_HR(hr, E_FAIL);
10506
10507     attr = (IXMLDOMAttribute*)0xdeadbeef;
10508     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
10509     EXPECT_HR(hr, E_FAIL);
10510     ok(attr == NULL, "got %p\n", attr);
10511     SysFreeString(str);
10512
10513     str = SysAllocString(nonexistent_attrW);
10514     hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
10515     EXPECT_HR(hr, S_FALSE);
10516
10517     attr = (IXMLDOMAttribute*)0xdeadbeef;
10518     hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
10519     EXPECT_HR(hr, S_FALSE);
10520     ok(attr == NULL, "got %p\n", attr);
10521     SysFreeString(str);
10522
10523     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("foo:b"), &attr);
10524     EXPECT_HR(hr, S_OK);
10525     IXMLDOMAttribute_Release(attr);
10526
10527     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("b"), &attr);
10528     EXPECT_HR(hr, S_FALSE);
10529
10530     hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("a"), &attr);
10531     EXPECT_HR(hr, S_OK);
10532     IXMLDOMAttribute_Release(attr);
10533
10534     IXMLDOMElement_Release(elem);
10535     IXMLDOMDocument_Release(doc);
10536     free_bstrs();
10537 }
10538
10539 typedef struct {
10540     DOMNodeType type;
10541     const char *name;
10542     REFIID iids[3];
10543 } supporterror_t;
10544
10545 static const supporterror_t supporterror_test[] = {
10546     { NODE_ELEMENT,                "element",   { &IID_IXMLDOMNode, &IID_IXMLDOMElement } },
10547     { NODE_ATTRIBUTE,              "attribute", { &IID_IXMLDOMNode, &IID_IXMLDOMAttribute } },
10548     { NODE_CDATA_SECTION,          "cdata",     { &IID_IXMLDOMNode, &IID_IXMLDOMCDATASection } },
10549     { NODE_ENTITY_REFERENCE,       "entityref", { &IID_IXMLDOMNode, &IID_IXMLDOMEntityReference } },
10550     { NODE_PROCESSING_INSTRUCTION, "pi",        { &IID_IXMLDOMNode, &IID_IXMLDOMProcessingInstruction } },
10551     { NODE_COMMENT,                "comment",   { &IID_IXMLDOMNode, &IID_IXMLDOMComment } },
10552     { NODE_DOCUMENT_FRAGMENT,      "fragment",  { &IID_IXMLDOMNode, &IID_IXMLDOMDocumentFragment } },
10553     { NODE_INVALID }
10554 };
10555
10556 static void test_supporterrorinfo(void)
10557 {
10558     static REFIID iids[5] = { &IID_IXMLDOMNode, &IID_IXMLDOMDocument,
10559                               &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3 };
10560     const supporterror_t *ptr = supporterror_test;
10561     ISupportErrorInfo *errorinfo, *info2;
10562     IXMLDOMNamedNodeMap *map, *map2;
10563     IXMLDOMDocument *doc;
10564     IXMLDOMElement *elem;
10565     VARIANT_BOOL b;
10566     IUnknown *unk;
10567     REFIID *iid;
10568     void *dummy;
10569     HRESULT hr;
10570
10571     doc = create_document_version(60, &IID_IXMLDOMDocument3);
10572     if (!doc) return;
10573
10574     EXPECT_REF(doc, 1);
10575     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&errorinfo);
10576     EXPECT_HR(hr, S_OK);
10577     EXPECT_REF(doc, 1);
10578     ISupportErrorInfo_AddRef(errorinfo);
10579     EXPECT_REF(errorinfo, 2);
10580     EXPECT_REF(doc, 1);
10581     ISupportErrorInfo_Release(errorinfo);
10582
10583     hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&info2);
10584     EXPECT_HR(hr, S_OK);
10585     ok(errorinfo != info2, "got %p, %p\n", info2, errorinfo);
10586
10587     /* error interface can't be queried back for DOM interface */
10588     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMDocument, &dummy);
10589     EXPECT_HR(hr, E_NOINTERFACE);
10590     hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMNode, &dummy);
10591     EXPECT_HR(hr, E_NOINTERFACE);
10592
10593     ISupportErrorInfo_Release(info2);
10594
10595     iid = iids;
10596     while (*iid)
10597     {
10598         hr = IXMLDOMDocument_QueryInterface(doc, *iid, (void**)&unk);
10599         EXPECT_HR(hr, S_OK);
10600         if (hr == S_OK)
10601         {
10602             hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
10603             ok(hr == S_OK, "got 0x%08x for %s\n", hr, debugstr_guid(*iid));
10604             IUnknown_Release(unk);
10605         }
10606
10607         iid++;
10608     }
10609
10610     ISupportErrorInfo_Release(errorinfo);
10611
10612     while (ptr->type != NODE_INVALID)
10613     {
10614         IXMLDOMNode *node;
10615         VARIANT type;
10616
10617         V_VT(&type) = VT_I1;
10618         V_I1(&type) = ptr->type;
10619
10620         hr = IXMLDOMDocument_createNode(doc, type, _bstr_(ptr->name), NULL, &node);
10621         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
10622
10623         EXPECT_REF(node, 1);
10624         hr = IXMLDOMNode_QueryInterface(node, &IID_ISupportErrorInfo, (void**)&errorinfo);
10625         ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
10626         EXPECT_REF(node, 1);
10627
10628         hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNode, &dummy);
10629         ok(hr == E_NOINTERFACE, "%d: got 0x%08x\n", ptr->type, hr);
10630
10631         iid = ptr->iids;
10632
10633         while (*iid)
10634         {
10635             hr = IXMLDOMNode_QueryInterface(node, *iid, (void**)&unk);
10636             if (hr == S_OK)
10637             {
10638                 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
10639                 ok(hr == S_OK, "%d: got 0x%08x for %s\n", ptr->type, hr, debugstr_guid(*iid));
10640                 IUnknown_Release(unk);
10641             }
10642
10643             iid++;
10644         }
10645
10646         ISupportErrorInfo_Release(errorinfo);
10647         IXMLDOMNode_Release(node);
10648         ptr++;
10649     }
10650
10651     /* IXMLDOMNamedNodeMap */
10652     b = VARIANT_FALSE;
10653     hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
10654     EXPECT_HR(hr, S_OK);
10655     ok(b == VARIANT_TRUE, "got %d\n", b);
10656
10657     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10658     EXPECT_HR(hr, S_OK);
10659
10660     hr = IXMLDOMElement_get_attributes(elem, &map);
10661     EXPECT_HR(hr, S_OK);
10662
10663     EXPECT_REF(map, 1);
10664     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_ISupportErrorInfo, (void**)&errorinfo);
10665     EXPECT_HR(hr, S_OK);
10666     EXPECT_REF(map, 2);
10667
10668     hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMNamedNodeMap);
10669     EXPECT_HR(hr, S_OK);
10670
10671     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNamedNodeMap, (void**)&map2);
10672     EXPECT_HR(hr, S_OK);
10673     ok(map == map2, "got %p\n", map2);
10674     IXMLDOMNamedNodeMap_Release(map2);
10675
10676     EXPECT_REF(errorinfo, 2);
10677     hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IUnknown, (void**)&unk);
10678     EXPECT_HR(hr, S_OK);
10679     EXPECT_REF(errorinfo, 3);
10680     EXPECT_REF(map, 3);
10681     IUnknown_Release(unk);
10682
10683     ISupportErrorInfo_Release(errorinfo);
10684     IXMLDOMNamedNodeMap_Release(map);
10685     IXMLDOMElement_Release(elem);
10686
10687     IXMLDOMDocument_Release(doc);
10688     free_bstrs();
10689 }
10690
10691 typedef struct {
10692     DOMNodeType type;
10693     const char *name;
10694     const char *put_content;
10695     HRESULT put_hr;
10696     VARTYPE get_vt;
10697     HRESULT get_hr;
10698 } node_value_t;
10699
10700 static const node_value_t nodevalue_test[] = {
10701     { NODE_ELEMENT,                "element",   "",             E_FAIL, VT_NULL, S_FALSE },
10702     { NODE_ATTRIBUTE,              "attr",      "value",        S_OK,   VT_BSTR, S_OK },
10703     { NODE_TEXT,                   "text",      "textdata",     S_OK,   VT_BSTR, S_OK },
10704     { NODE_CDATA_SECTION ,         "cdata",     "cdata data",   S_OK,   VT_BSTR, S_OK },
10705     { NODE_ENTITY_REFERENCE,       "entityref", "ref",          E_FAIL, VT_NULL, S_FALSE },
10706     { NODE_PROCESSING_INSTRUCTION, "pi",        "instr",        S_OK,   VT_BSTR, S_OK },
10707     { NODE_COMMENT,                "comment",   "comment data", S_OK,   VT_BSTR, S_OK },
10708     { NODE_DOCUMENT_FRAGMENT,      "docfrag",   "",             E_FAIL, VT_NULL, S_FALSE },
10709     { NODE_INVALID }
10710 };
10711
10712 static void test_nodeValue(void)
10713 {
10714     const node_value_t *ptr = nodevalue_test;
10715     IXMLDOMDocument *doc;
10716     HRESULT hr;
10717
10718     doc = create_document(&IID_IXMLDOMDocument);
10719     if (!doc) return;
10720
10721     while (ptr->type != NODE_INVALID)
10722     {
10723         IXMLDOMNode *node;
10724         VARIANT v;
10725
10726         V_VT(&v) = VT_I2;
10727         V_I2(&v) = ptr->type;
10728
10729         hr = IXMLDOMDocument_createNode(doc, v, _bstr_(ptr->name), NULL, &node);
10730         ok(hr == S_OK, "failed to create node type %d\n", ptr->type);
10731
10732         hr = IXMLDOMNode_get_nodeValue(node, NULL);
10733         ok(hr == E_INVALIDARG, "%d: got 0x%08x\n", ptr->type, hr);
10734
10735         V_VT(&v) = VT_BSTR;
10736         V_BSTR(&v) = _bstr_(ptr->put_content);
10737         hr = IXMLDOMNode_put_nodeValue(node, v);
10738         ok(hr == ptr->put_hr, "%d: got 0x%08x\n", ptr->type, hr);
10739
10740         V_VT(&v) = VT_EMPTY;
10741         hr = IXMLDOMNode_get_nodeValue(node, &v);
10742         ok(hr == ptr->get_hr, "%d: got 0x%08x, expected 0x%08x\n", ptr->type, hr, ptr->get_hr);
10743         ok(V_VT(&v) == ptr->get_vt, "%d: got %d, expected %d\n", ptr->type, V_VT(&v), ptr->get_vt);
10744         if (hr == S_OK)
10745             ok(!lstrcmpW(V_BSTR(&v), _bstr_(ptr->put_content)), "%d: got %s\n", ptr->type,
10746                 wine_dbgstr_w(V_BSTR(&v)));
10747         VariantClear(&v);
10748
10749         IXMLDOMNode_Release(node);
10750
10751         ptr++;
10752     }
10753
10754     IXMLDOMDocument_Release(doc);
10755 }
10756
10757 static void test_xmlns_attribute(void)
10758 {
10759     BSTR str;
10760     IXMLDOMDocument *doc;
10761     IXMLDOMElement *root;
10762     IXMLDOMAttribute *pAttribute;
10763     IXMLDOMElement *elem;
10764     HRESULT hr;
10765
10766     doc = create_document(&IID_IXMLDOMDocument);
10767     if (!doc) return;
10768
10769     hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
10770     EXPECT_HR(hr, S_OK);
10771
10772     hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
10773     EXPECT_HR(hr, S_OK);
10774
10775     str = SysAllocString(szAttribute);
10776     hr = IXMLDOMDocument_createAttribute(doc, _bstr_("xmlns:dt"), &pAttribute);
10777     ok( hr == S_OK, "returns %08x\n", hr );
10778     if(hr == S_OK)
10779     {
10780         VARIANT v;
10781
10782         V_VT(&v) = VT_BSTR;
10783         V_BSTR(&v) = _bstr_("urn:schemas-microsoft-com:datatypes");
10784         hr = IXMLDOMAttribute_put_nodeValue(pAttribute, v);
10785
10786         hr = IXMLDOMElement_setAttributeNode(root, pAttribute, NULL);
10787         ok(hr == S_OK, "ret %08x\n", hr );
10788
10789         hr = IXMLDOMNode_put_dataType((IXMLDOMNode*)root, _bstr_("bin.base64"));
10790         ok(hr == S_OK, "ret %08x\n", hr );
10791
10792         hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10793         EXPECT_HR(hr, S_OK);
10794
10795         hr = IXMLDOMElement_get_xml(elem, &str);
10796         ok( hr == S_OK, "got 0x%08x\n", hr);
10797         todo_wine ok( lstrcmpW(str, _bstr_("<Testing xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"bin.base64\"/>")) == 0,
10798         "got %s\n", wine_dbgstr_w(str));
10799         SysFreeString(str);
10800
10801         IXMLDOMElement_Release(elem);
10802         IXMLDOMAttribute_Release( pAttribute);
10803     }
10804
10805     SysFreeString(str);
10806
10807     IXMLDOMDocument_Release(doc);
10808
10809     free_bstrs();
10810 }
10811
10812 static const char namespacesA[] =
10813 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
10814 "   <ns1:elem1 xmlns:ns1=\"http://blah.org\" b='1' >"
10815 "     <ns2:elem2 xmlns:ns2=\"http://blah.org\"/>"
10816 "     <ns1:elem3/>"
10817 "     <ns1:elem4/>"
10818 "     <elem5 xmlns=\"http://blahblah.org\"/>"
10819 "     <ns1:elem6>true</ns1:elem6>"
10820 "   </ns1:elem1>";
10821
10822 static const char xsd_schema1_uri[] = "x-schema:test1.xsd";
10823 static const char xsd_schema1_xml[] =
10824 "<?xml version='1.0'?>"
10825 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
10826 "            targetNamespace='x-schema:test1.xsd'>"
10827 "   <element name='root'>"
10828 "       <complexType>"
10829 "           <sequence maxOccurs='unbounded'>"
10830 "               <any/>"
10831 "           </sequence>"
10832 "       </complexType>"
10833 "   </element>"
10834 "</schema>";
10835
10836 static void test_get_namespaces(void)
10837 {
10838     IXMLDOMSchemaCollection *collection, *collection2;
10839     IXMLDOMDocument2 *doc, *doc2;
10840     IEnumVARIANT *enumv, *enum2;
10841     IUnknown *unk1, *unk2;
10842     IXMLDOMNode *node;
10843     VARIANT_BOOL b;
10844     HRESULT hr;
10845     VARIANT v;
10846     LONG len;
10847     BSTR s;
10848
10849     doc = create_document(&IID_IXMLDOMDocument2);
10850     if (!doc) return;
10851
10852     /* null pointer */
10853     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
10854     EXPECT_HR(hr, E_POINTER);
10855
10856     /* no document loaded */
10857     collection = (void*)0xdeadbeef;
10858     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
10859     EXPECT_HR(hr, S_OK);
10860     if (hr != S_OK)
10861     {
10862         IXMLDOMDocument2_Release(doc);
10863         return;
10864     }
10865     EXPECT_REF(collection, 2);
10866
10867     collection2 = (void*)0xdeadbeef;
10868     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
10869     EXPECT_HR(hr, S_OK);
10870     ok(collection == collection2, "got %p\n", collection2);
10871     EXPECT_REF(collection, 3);
10872     IXMLDOMSchemaCollection_Release(collection);
10873
10874     len = -1;
10875     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
10876     EXPECT_HR(hr, S_OK);
10877     ok(len == 0, "got %d\n", len);
10878     IXMLDOMSchemaCollection_Release(collection);
10879
10880     /* now with document */
10881     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
10882     EXPECT_HR(hr, S_OK);
10883
10884     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
10885     EXPECT_HR(hr, S_OK);
10886
10887     len = -1;
10888     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
10889     EXPECT_HR(hr, S_OK);
10890     ok(len == 2, "got %d\n", len);
10891
10892     /* try to lookup some uris */
10893     node = (void*)0xdeadbeef;
10894     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
10895     EXPECT_HR(hr, S_OK);
10896     ok(node == NULL, "got %p\n", node);
10897
10898     node = (void*)0xdeadbeef;
10899     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah1.org"), &node);
10900     EXPECT_HR(hr, S_OK);
10901     ok(node == NULL, "got %p\n", node);
10902
10903     /* load schema and try to add it */
10904     doc2 = create_document(&IID_IXMLDOMDocument2);
10905     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
10906     EXPECT_HR(hr, S_OK);
10907
10908     V_VT(&v) = VT_DISPATCH;
10909     V_DISPATCH(&v) = (IDispatch*)doc2;
10910     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
10911     EXPECT_HR(hr, E_FAIL);
10912
10913     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
10914     EXPECT_HR(hr, S_OK);
10915     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
10916     SysFreeString(s);
10917
10918     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
10919     EXPECT_HR(hr, S_OK);
10920     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
10921     SysFreeString(s);
10922
10923     s = (void*)0xdeadbeef;
10924     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
10925     EXPECT_HR(hr, E_FAIL);
10926     ok(s == (void*)0xdeadbeef, "got %p\n", s);
10927
10928     /* enumerate */
10929     enumv = (void*)0xdeadbeef;
10930     EXPECT_REF(collection, 2);
10931     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
10932     EXPECT_HR(hr, S_OK);
10933     EXPECT_REF(collection, 3);
10934     ok(enumv != NULL, "got %p\n", enumv);
10935
10936     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IUnknown, (void**)&unk1);
10937     EXPECT_HR(hr, S_OK);
10938     hr = IEnumVARIANT_QueryInterface(enumv, &IID_IUnknown, (void**)&unk2);
10939     EXPECT_HR(hr, S_OK);
10940     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
10941     IUnknown_Release(unk1);
10942     IUnknown_Release(unk2);
10943
10944     hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IEnumVARIANT, (void**)&enum2);
10945     EXPECT_HR(hr, E_NOINTERFACE);
10946
10947     V_VT(&v) = VT_EMPTY;
10948     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
10949     EXPECT_HR(hr, S_OK);
10950     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
10951     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
10952     VariantClear(&v);
10953
10954     V_VT(&v) = VT_EMPTY;
10955     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
10956     EXPECT_HR(hr, S_OK);
10957     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
10958     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
10959     VariantClear(&v);
10960
10961     V_VT(&v) = VT_NULL;
10962     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
10963     EXPECT_HR(hr, S_FALSE);
10964     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
10965
10966     IEnumVARIANT_Release(enumv);
10967     IXMLDOMSchemaCollection_Release(collection);
10968
10969     IXMLDOMDocument2_Release(doc);
10970
10971     /* now with CLSID_DOMDocument60 */
10972     doc = create_document_version(60, &IID_IXMLDOMDocument2);
10973     if (!doc) return;
10974
10975     /* null pointer */
10976     hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
10977     EXPECT_HR(hr, E_POINTER);
10978
10979     /* no document loaded */
10980     collection = (void*)0xdeadbeef;
10981     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
10982     EXPECT_HR(hr, S_OK);
10983     if (hr != S_OK)
10984     {
10985         IXMLDOMDocument2_Release(doc);
10986         return;
10987     }
10988     EXPECT_REF(collection, 2);
10989
10990     collection2 = (void*)0xdeadbeef;
10991     hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
10992     EXPECT_HR(hr, S_OK);
10993     ok(collection == collection2, "got %p\n", collection2);
10994     EXPECT_REF(collection, 3);
10995     IXMLDOMSchemaCollection_Release(collection);
10996
10997     len = -1;
10998     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
10999     EXPECT_HR(hr, S_OK);
11000     ok(len == 0, "got %d\n", len);
11001     IXMLDOMSchemaCollection_Release(collection);
11002
11003     /* now with document */
11004     hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11005     EXPECT_HR(hr, S_OK);
11006
11007     hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11008     EXPECT_HR(hr, S_OK);
11009
11010     len = -1;
11011     hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11012     EXPECT_HR(hr, S_OK);
11013     ok(len == 2, "got %d\n", len);
11014
11015     /* try to lookup some uris */
11016     node = (void*)0xdeadbeef;
11017     hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
11018     EXPECT_HR(hr, E_NOTIMPL);
11019     ok(node == (void*)0xdeadbeef, "got %p\n", node);
11020
11021     /* load schema and try to add it */
11022     doc2 = create_document(&IID_IXMLDOMDocument2);
11023     hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
11024     EXPECT_HR(hr, S_OK);
11025
11026     V_VT(&v) = VT_DISPATCH;
11027     V_DISPATCH(&v) = (IDispatch*)doc2;
11028     hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
11029     EXPECT_HR(hr, E_FAIL);
11030     IXMLDOMDocument2_Release(doc2);
11031
11032     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
11033     EXPECT_HR(hr, S_OK);
11034     ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
11035     SysFreeString(s);
11036
11037     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
11038     EXPECT_HR(hr, S_OK);
11039     ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
11040     SysFreeString(s);
11041
11042     s = (void*)0xdeadbeef;
11043     hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
11044     EXPECT_HR(hr, E_FAIL);
11045     ok(s == (void*)0xdeadbeef, "got %p\n", s);
11046
11047     /* enumerate */
11048     enumv = (void*)0xdeadbeef;
11049     hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
11050     EXPECT_HR(hr, S_OK);
11051     ok(enumv != NULL, "got %p\n", enumv);
11052
11053     V_VT(&v) = VT_EMPTY;
11054     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11055     EXPECT_HR(hr, S_OK);
11056     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11057     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11058     VariantClear(&v);
11059
11060     V_VT(&v) = VT_EMPTY;
11061     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11062     EXPECT_HR(hr, S_OK);
11063     ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11064     ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11065     VariantClear(&v);
11066
11067     V_VT(&v) = VT_NULL;
11068     hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11069     EXPECT_HR(hr, S_FALSE);
11070     ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
11071
11072     IEnumVARIANT_Release(enumv);
11073     IXMLDOMSchemaCollection_Release(collection);
11074     IXMLDOMDocument2_Release(doc);
11075     free_bstrs();
11076 }
11077
11078 static DOMNodeType put_data_types[] = {
11079     NODE_TEXT,
11080     NODE_CDATA_SECTION,
11081     NODE_PROCESSING_INSTRUCTION,
11082     NODE_COMMENT,
11083     NODE_INVALID
11084 };
11085
11086 static void test_put_data(void)
11087 {
11088     static const WCHAR test_data[] = {'t','e','s','t',' ','n','o','d','e',' ','d','a','t','a',0};
11089     WCHAR buff[100], *data;
11090     IXMLDOMDocument *doc;
11091     DOMNodeType *type;
11092     IXMLDOMText *text;
11093     IXMLDOMNode *node;
11094     VARIANT v;
11095     BSTR get_data;
11096     HRESULT hr;
11097
11098     doc = create_document(&IID_IXMLDOMDocument);
11099     if (!doc) return;
11100
11101     memcpy(&buff[2], test_data, sizeof(test_data));
11102     /* just a big length */
11103     *(DWORD*)buff = 0xf0f0;
11104     data = &buff[2];
11105
11106     type = put_data_types;
11107     while (*type != NODE_INVALID)
11108     {
11109        V_VT(&v) = VT_I2;
11110        V_I2(&v) = *type;
11111
11112        hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
11113        EXPECT_HR(hr, S_OK);
11114
11115        /* put_data() is interface-specific */
11116        switch (*type)
11117        {
11118            case NODE_TEXT:
11119            {
11120               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
11121               EXPECT_HR(hr, S_OK);
11122               hr = IXMLDOMText_put_data(text, data);
11123               EXPECT_HR(hr, S_OK);
11124
11125               hr = IXMLDOMText_get_data(text, &get_data);
11126               EXPECT_HR(hr, S_OK);
11127
11128               IXMLDOMText_Release(text);
11129               break;
11130            }
11131            case NODE_CDATA_SECTION:
11132            {
11133               IXMLDOMCDATASection *cdata;
11134
11135               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
11136               EXPECT_HR(hr, S_OK);
11137               hr = IXMLDOMCDATASection_put_data(cdata, data);
11138               EXPECT_HR(hr, S_OK);
11139
11140               hr = IXMLDOMCDATASection_get_data(cdata, &get_data);
11141               EXPECT_HR(hr, S_OK);
11142
11143               IXMLDOMCDATASection_Release(cdata);
11144               break;
11145            }
11146            case NODE_PROCESSING_INSTRUCTION:
11147            {
11148               IXMLDOMProcessingInstruction *pi;
11149
11150               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)&pi);
11151               EXPECT_HR(hr, S_OK);
11152               hr = IXMLDOMProcessingInstruction_put_data(pi, data);
11153               EXPECT_HR(hr, S_OK);
11154
11155               hr = IXMLDOMProcessingInstruction_get_data(pi, &get_data);
11156               EXPECT_HR(hr, S_OK);
11157
11158               IXMLDOMProcessingInstruction_Release(pi);
11159               break;
11160            }
11161            case NODE_COMMENT:
11162            {
11163               IXMLDOMComment *comment;
11164
11165               hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
11166               EXPECT_HR(hr, S_OK);
11167               hr = IXMLDOMComment_put_data(comment, data);
11168               EXPECT_HR(hr, S_OK);
11169
11170               hr = IXMLDOMComment_get_data(comment, &get_data);
11171               EXPECT_HR(hr, S_OK);
11172
11173               IXMLDOMComment_Release(comment);
11174               break;
11175            }
11176            default:
11177               break;
11178        }
11179
11180        /* compare */
11181        ok(!lstrcmpW(data, get_data), "%d: got wrong data %s, expected %s\n", *type, wine_dbgstr_w(get_data),
11182            wine_dbgstr_w(data));
11183        SysFreeString(get_data);
11184
11185        IXMLDOMNode_Release(node);
11186        type++;
11187     }
11188
11189     /* \r\n sequence is never escaped */
11190     V_VT(&v) = VT_I2;
11191     V_I2(&v) = NODE_TEXT;
11192
11193     hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
11194     ok(hr == S_OK, "got 0x%08x\n", hr);
11195
11196     IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
11197
11198     hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
11199     ok(hr == S_OK, "got 0x%08x\n", hr);
11200
11201     hr = IXMLDOMText_get_data(text, &get_data);
11202     ok(hr == S_OK, "got 0x%08x\n", hr);
11203 todo_wine
11204     ok(!lstrcmpW(get_data, _bstr_("\n")), "got %s\n", wine_dbgstr_w(get_data));
11205     SysFreeString(get_data);
11206
11207     hr = IXMLDOMText_get_xml(text, &get_data);
11208     ok(hr == S_OK, "got 0x%08x\n", hr);
11209     ok(!lstrcmpW(get_data, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(get_data));
11210     SysFreeString(get_data);
11211
11212     IXMLDOMText_Release(text);
11213     IXMLDOMNode_Release(node);
11214
11215     IXMLDOMDocument_Release(doc);
11216     free_bstrs();
11217 }
11218
11219 static void test_putref_schemas(void)
11220 {
11221     IXMLDOMSchemaCollection *cache;
11222     IXMLDOMDocument2 *doc;
11223     VARIANT schema;
11224     HRESULT hr;
11225
11226     doc = create_document(&IID_IXMLDOMDocument2);
11227     if (!doc) return;
11228     cache = create_cache(&IID_IXMLDOMSchemaCollection);
11229
11230     /* set to NULL iface when no schema is set */
11231     V_VT(&schema) = VT_DISPATCH;
11232     V_DISPATCH(&schema) = NULL;
11233     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11234     EXPECT_HR(hr, S_OK);
11235
11236     V_VT(&schema) = VT_UNKNOWN;
11237     V_UNKNOWN(&schema) = NULL;
11238     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11239     EXPECT_HR(hr, S_OK);
11240
11241     /* set as VT_DISPATCH, reset with it */
11242     V_VT(&schema) = VT_DISPATCH;
11243     V_DISPATCH(&schema) = (IDispatch*)cache;
11244     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11245     EXPECT_HR(hr, S_OK);
11246
11247     V_DISPATCH(&schema) = NULL;
11248     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
11249     EXPECT_HR(hr, S_OK);
11250     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
11251
11252     V_VT(&schema) = VT_DISPATCH;
11253     V_DISPATCH(&schema) = NULL;
11254     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11255     EXPECT_HR(hr, S_OK);
11256
11257     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
11258     V_VT(&schema) = VT_I2;
11259     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
11260     EXPECT_HR(hr, S_FALSE);
11261     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
11262     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
11263
11264     /* set as VT_UNKNOWN, reset with it */
11265     V_VT(&schema) = VT_UNKNOWN;
11266     V_UNKNOWN(&schema) = (IUnknown*)cache;
11267     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11268     EXPECT_HR(hr, S_OK);
11269
11270     V_DISPATCH(&schema) = NULL;
11271     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
11272     EXPECT_HR(hr, S_OK);
11273     ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
11274
11275     V_VT(&schema) = VT_UNKNOWN;
11276     V_UNKNOWN(&schema) = NULL;
11277     hr = IXMLDOMDocument2_putref_schemas(doc, schema);
11278     EXPECT_HR(hr, S_OK);
11279
11280     V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
11281     V_VT(&schema) = VT_I2;
11282     hr = IXMLDOMDocument2_get_schemas(doc, &schema);
11283     EXPECT_HR(hr, S_FALSE);
11284     ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
11285     ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
11286
11287     IXMLDOMSchemaCollection_Release(cache);
11288     IXMLDOMDocument2_Release(doc);
11289 }
11290
11291 static void test_namedmap_newenum(void)
11292 {
11293     IEnumVARIANT *enum1, *enum2, *enum3;
11294     IXMLDOMNamedNodeMap *map;
11295     IUnknown *unk1, *unk2;
11296     IXMLDOMDocument *doc;
11297     IXMLDOMElement *elem;
11298     IXMLDOMNode *node;
11299     VARIANT_BOOL b;
11300     HRESULT hr;
11301     VARIANT v;
11302     BSTR str;
11303
11304     doc = create_document(&IID_IXMLDOMDocument);
11305
11306     hr = IXMLDOMDocument_loadXML(doc, _bstr_(attributes_map), &b);
11307     EXPECT_HR(hr, S_OK);
11308
11309     hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11310     EXPECT_HR(hr, S_OK);
11311
11312     hr = IXMLDOMElement_get_attributes(elem, &map);
11313     EXPECT_HR(hr, S_OK);
11314     IXMLDOMElement_Release(elem);
11315
11316     enum1 = NULL;
11317     EXPECT_REF(map, 1);
11318     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum1);
11319     EXPECT_HR(hr, S_OK);
11320     ok(enum1 != NULL, "got %p\n", enum1);
11321     EXPECT_REF(map, 1);
11322     EXPECT_REF(enum1, 2);
11323
11324     enum2 = NULL;
11325     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum2);
11326     EXPECT_HR(hr, S_OK);
11327     ok(enum2 == enum1, "got %p\n", enum2);
11328
11329     IEnumVARIANT_Release(enum2);
11330
11331     EXPECT_REF(map, 1);
11332     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum2);
11333     EXPECT_HR(hr, S_OK);
11334     EXPECT_REF(map, 2);
11335     EXPECT_REF(enum2, 1);
11336     ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
11337
11338     IEnumVARIANT_Release(enum1);
11339
11340     /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
11341     hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk1);
11342     EXPECT_HR(hr, S_OK);
11343     hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
11344     EXPECT_HR(hr, S_OK);
11345     EXPECT_REF(map, 3);
11346     EXPECT_REF(enum2, 2);
11347     ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
11348     IUnknown_Release(unk1);
11349     IUnknown_Release(unk2);
11350
11351     hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum3);
11352     EXPECT_HR(hr, S_OK);
11353     ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
11354     IEnumVARIANT_Release(enum3);
11355
11356     /* iteration tests */
11357     hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node);
11358     EXPECT_HR(hr, S_OK);
11359     hr = IXMLDOMNode_get_nodeName(node, &str);
11360     EXPECT_HR(hr, S_OK);
11361     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
11362     SysFreeString(str);
11363     IXMLDOMNode_Release(node);
11364
11365     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
11366     EXPECT_HR(hr, S_OK);
11367     hr = IXMLDOMNode_get_nodeName(node, &str);
11368     EXPECT_HR(hr, S_OK);
11369     ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
11370     SysFreeString(str);
11371     IXMLDOMNode_Release(node);
11372
11373     V_VT(&v) = VT_EMPTY;
11374     hr = IEnumVARIANT_Next(enum2, 1, &v, NULL);
11375     EXPECT_HR(hr, S_OK);
11376     ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
11377     hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
11378     EXPECT_HR(hr, S_OK);
11379     hr = IXMLDOMNode_get_nodeName(node, &str);
11380     EXPECT_HR(hr, S_OK);
11381     ok(!lstrcmpW(str, _bstr_("attr1")), "got node name %s\n", wine_dbgstr_w(str));
11382     SysFreeString(str);
11383     IXMLDOMNode_Release(node);
11384     VariantClear(&v);
11385
11386     hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
11387     EXPECT_HR(hr, S_OK);
11388     hr = IXMLDOMNode_get_nodeName(node, &str);
11389     EXPECT_HR(hr, S_OK);
11390     ok(!lstrcmpW(str, _bstr_("attr2")), "got %s\n", wine_dbgstr_w(str));
11391     SysFreeString(str);
11392     IXMLDOMNode_Release(node);
11393
11394     IEnumVARIANT_Release(enum2);
11395     IXMLDOMNamedNodeMap_Release(map);
11396     IXMLDOMDocument_Release(doc);
11397 }
11398
11399 static const char xsltext_xsl[] =
11400 "<?xml version=\"1.0\"?>"
11401 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
11402 "<xsl:output method=\"html\" encoding=\"us-ascii\"/>"
11403 "<xsl:template match=\"/\">"
11404 "    <xsl:choose>"
11405 "        <xsl:when test=\"testkey\">"
11406 "            <xsl:text>testdata</xsl:text>"
11407 "        </xsl:when>"
11408 "    </xsl:choose>"
11409 "</xsl:template>"
11410 "</xsl:stylesheet>";
11411
11412 static void test_xsltext(void)
11413 {
11414     IXMLDOMDocument *doc, *doc2;
11415     VARIANT_BOOL b;
11416     HRESULT hr;
11417     BSTR ret;
11418
11419     doc = create_document(&IID_IXMLDOMDocument);
11420     if (!doc) return;
11421
11422     doc2 = create_document(&IID_IXMLDOMDocument);
11423
11424     hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsltext_xsl), &b);
11425     EXPECT_HR(hr, S_OK);
11426
11427     hr = IXMLDOMDocument_loadXML(doc2, _bstr_("<testkey/>"), &b);
11428     EXPECT_HR(hr, S_OK);
11429
11430     hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
11431     EXPECT_HR(hr, S_OK);
11432     ok(!lstrcmpW(ret, _bstr_("testdata")), "transform result %s\n", wine_dbgstr_w(ret));
11433     SysFreeString(ret);
11434
11435     IXMLDOMDocument_Release(doc2);
11436     IXMLDOMDocument_Release(doc);
11437     free_bstrs();
11438 }
11439
11440 START_TEST(domdoc)
11441 {
11442     IXMLDOMDocument *doc;
11443     IUnknown *unk;
11444     HRESULT hr;
11445
11446     hr = CoInitialize( NULL );
11447     ok( hr == S_OK, "failed to init com\n");
11448     if (hr != S_OK) return;
11449
11450     hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc );
11451     if (hr != S_OK)
11452     {
11453         win_skip("IXMLDOMDocument is not available (0x%08x)\n", hr);
11454         return;
11455     }
11456
11457     IXMLDOMDocument_Release(doc);
11458
11459     test_domdoc();
11460     test_persiststreaminit();
11461     test_domnode();
11462     test_refs();
11463     test_create();
11464     test_getElementsByTagName();
11465     test_get_text();
11466     test_get_childNodes();
11467     test_get_firstChild();
11468     test_get_lastChild();
11469     test_removeChild();
11470     test_replaceChild();
11471     test_removeNamedItem();
11472     test_IXMLDOMDocument2();
11473     test_whitespace();
11474     test_XPath();
11475     test_XSLPattern();
11476     test_cloneNode();
11477     test_xmlTypes();
11478     test_save();
11479     test_testTransforms();
11480     test_namespaces_basic();
11481     test_namespaces_change();
11482     test_FormattingXML();
11483     test_nodeTypedValue();
11484     test_TransformWithLoadingLocalFile();
11485     test_put_nodeValue();
11486     test_IObjectSafety();
11487     test_splitText();
11488     test_getQualifiedItem();
11489     test_removeQualifiedItem();
11490     test_get_ownerDocument();
11491     test_setAttributeNode();
11492     test_put_dataType();
11493     test_createNode();
11494     test_get_prefix();
11495     test_default_properties();
11496     test_selectSingleNode();
11497     test_events();
11498     test_createProcessingInstruction();
11499     test_put_nodeTypedValue();
11500     test_get_xml();
11501     test_insertBefore();
11502     test_appendChild();
11503     test_get_doctype();
11504     test_get_tagName();
11505     test_get_dataType();
11506     test_get_nodeTypeString();
11507     test_get_attributes();
11508     test_selection();
11509     test_load();
11510     test_dispex();
11511     test_parseerror();
11512     test_getAttributeNode();
11513     test_supporterrorinfo();
11514     test_nodeValue();
11515     test_get_namespaces();
11516     test_put_data();
11517     test_putref_schemas();
11518     test_namedmap_newenum();
11519     test_xmlns_attribute();
11520
11521     test_xsltemplate();
11522     test_xsltext();
11523
11524     hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
11525         &IID_IMXNamespaceManager, (void**)&unk);
11526     if (hr == S_OK)
11527     {
11528         test_mxnamespacemanager();
11529         test_mxnamespacemanager_override();
11530
11531         IUnknown_Release(unk);
11532     }
11533     else
11534         win_skip("MXNamespaceManager is not available\n");
11535
11536     CoUninitialize();
11537 }