eb8c62a522591fa4bad8bff3fa0383e3f1b20925
[reactos.git] / rostests / winetests / msxml3 / 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 WIN32_NO_STATUS
26 #define _INC_WINDOWS
27 #define COM_NO_WINDOWS_H
28
29 #define COBJMACROS
30 #define CONST_VTABLE
31
32 #include <stdio.h>
33 #include <assert.h>
34
35 //#include "windows.h"
36
37 #include <wine/test.h>
38
39 #include <winnls.h>
40 #include <ole2.h>
41 #include <msxml.h>
42 #include <msxml2.h>
43 #include <msxml2did.h>
44 #include <dispex.h>
45 #include <objsafe.h>
46 //#include "initguid.h"
47
48 /* undef the #define in msxml2 so that we can access all versions */
49 #undef CLSID_DOMDocument
50
51 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
52
53 static int g_unexpectedcall, g_expectedcall;
54
55 struct msxmlsupported_data_t
56 {
57 const GUID *clsid;
58 const char *name;
59 const IID *ifaces[3];
60 BOOL supported[3];
61 };
62
63 static struct msxmlsupported_data_t domdoc_support_data[] =
64 {
65 { &CLSID_DOMDocument, "DOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
66 { &CLSID_DOMDocument2, "DOMDocument2", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
67 { &CLSID_DOMDocument30, "DOMDocument30", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
68 { &CLSID_DOMDocument40, "DOMDocument40", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
69 { &CLSID_DOMDocument60, "DOMDocument60", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3} },
70 { &CLSID_FreeThreadedDOMDocument, "FreeThreadedDOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
71 { &CLSID_XMLSchemaCache, "XMLSchemaCache", {&IID_IXMLDOMSchemaCollection} },
72 { &CLSID_XSLTemplate, "XSLTemplate", {&IID_IXSLTemplate} },
73 { &CLSID_MXNamespaceManager40, "MXNamespaceManager40", {&IID_IMXNamespaceManager} },
74 { NULL }
75 };
76
77 static const char *debugstr_msxml_guid(REFIID riid)
78 {
79 if(!riid)
80 return "(null)";
81
82 if (IsEqualIID(&IID_IXMLDOMDocument, riid))
83 return "IXMLDOMDocument";
84 else if (IsEqualIID(&IID_IXMLDOMDocument2, riid))
85 return "IXMLDOMDocument2";
86 else if (IsEqualIID(&IID_IXMLDOMDocument3, riid))
87 return "IXMLDOMDocument3";
88 else if (IsEqualIID(&IID_IXMLDOMSchemaCollection, riid))
89 return "IXMLDOMSchemaCollection";
90 else if (IsEqualIID(&IID_IXSLTemplate, riid))
91 return "IXSLTemplate";
92 else if (IsEqualIID(&IID_IMXNamespaceManager, riid))
93 return "IMXNamespaceManager";
94 else
95 return wine_dbgstr_guid(riid);
96 }
97
98 static void get_class_support_data(struct msxmlsupported_data_t *table)
99 {
100 while (table->clsid)
101 {
102 IUnknown *unk;
103 HRESULT hr;
104 int i;
105
106 for (i = 0; i < sizeof(table->ifaces)/sizeof(table->ifaces[0]) && table->ifaces[i] != NULL; i++)
107 {
108 hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, table->ifaces[i], (void**)&unk);
109 if (hr == S_OK) IUnknown_Release(unk);
110
111 table->supported[i] = hr == S_OK;
112 if (hr != S_OK) win_skip("class %s, iface %s not supported\n", table->name, debugstr_msxml_guid(table->ifaces[i]));
113 }
114
115 table++;
116 }
117 }
118
119 static BOOL is_clsid_supported(const GUID *clsid, REFIID riid)
120 {
121 const struct msxmlsupported_data_t *table = domdoc_support_data;
122 while (table->clsid)
123 {
124 if (table->clsid == clsid)
125 {
126 int i;
127
128 for (i = 0; i < sizeof(table->ifaces)/sizeof(table->ifaces[0]) && table->ifaces[i] != NULL; i++)
129 if (table->ifaces[i] == riid) return table->supported[i];
130 }
131
132 table++;
133 }
134 return FALSE;
135 }
136
137 typedef struct
138 {
139 IDispatch IDispatch_iface;
140 LONG ref;
141 } dispevent;
142
143 static inline dispevent *impl_from_IDispatch( IDispatch *iface )
144 {
145 return CONTAINING_RECORD(iface, dispevent, IDispatch_iface);
146 }
147
148 static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
149 {
150 *ppvObject = NULL;
151
152 if ( IsEqualGUID( riid, &IID_IDispatch) ||
153 IsEqualGUID( riid, &IID_IUnknown) )
154 {
155 *ppvObject = iface;
156 }
157 else
158 return E_NOINTERFACE;
159
160 IDispatch_AddRef( iface );
161
162 return S_OK;
163 }
164
165 static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
166 {
167 dispevent *This = impl_from_IDispatch( iface );
168 return InterlockedIncrement( &This->ref );
169 }
170
171 static ULONG WINAPI dispevent_Release(IDispatch *iface)
172 {
173 dispevent *This = impl_from_IDispatch( iface );
174 ULONG ref = InterlockedDecrement( &This->ref );
175
176 if (ref == 0)
177 HeapFree(GetProcessHeap(), 0, This);
178
179 return ref;
180 }
181
182 static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
183 {
184 g_unexpectedcall++;
185 *pctinfo = 0;
186 return S_OK;
187 }
188
189 static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
190 LCID lcid, ITypeInfo **ppTInfo)
191 {
192 g_unexpectedcall++;
193 return S_OK;
194 }
195
196 static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
197 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
198 {
199 g_unexpectedcall++;
200 return S_OK;
201 }
202
203 static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
204 LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
205 EXCEPINFO *excepInfo, UINT *argErr)
206 {
207 ok(member == 0, "expected 0 member, got %d\n", member);
208 ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
209 ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
210
211 ok(params->cArgs == 0, "got %d\n", params->cArgs);
212 ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
213 ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
214 ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
215
216 ok(result == NULL, "got %p\n", result);
217 ok(excepInfo == NULL, "got %p\n", excepInfo);
218 ok(argErr == NULL, "got %p\n", argErr);
219
220 g_expectedcall++;
221 return E_FAIL;
222 }
223
224 static const IDispatchVtbl dispeventVtbl =
225 {
226 dispevent_QueryInterface,
227 dispevent_AddRef,
228 dispevent_Release,
229 dispevent_GetTypeInfoCount,
230 dispevent_GetTypeInfo,
231 dispevent_GetIDsOfNames,
232 dispevent_Invoke
233 };
234
235 static IDispatch* create_dispevent(void)
236 {
237 dispevent *event = HeapAlloc(GetProcessHeap(), 0, sizeof(*event));
238
239 event->IDispatch_iface.lpVtbl = &dispeventVtbl;
240 event->ref = 1;
241
242 return (IDispatch*)&event->IDispatch_iface;
243 }
244
245 /* IStream */
246 static HRESULT WINAPI istream_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
247 {
248 *ppvObject = NULL;
249
250 if (IsEqualGUID(riid, &IID_IStream) ||
251 IsEqualGUID(riid, &IID_IUnknown))
252 *ppvObject = iface;
253 else
254 return E_NOINTERFACE;
255
256 return S_OK;
257 }
258
259 static ULONG WINAPI istream_AddRef(IStream *iface)
260 {
261 return 2;
262 }
263
264 static ULONG WINAPI istream_Release(IStream *iface)
265 {
266 return 1;
267 }
268
269 static HRESULT WINAPI istream_Read(IStream *iface, void *ptr, ULONG len, ULONG *pread)
270 {
271 ok(0, "unexpected call\n");
272 return E_NOTIMPL;
273 }
274
275 static HRESULT WINAPI istream_Write(IStream *iface, const void *ptr, ULONG len, ULONG *written)
276 {
277 *written = len/2;
278 return S_OK;
279 }
280
281 static HRESULT WINAPI istream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
282 {
283 ok(0, "unexpected call\n");
284 return E_NOTIMPL;
285 }
286
287 static HRESULT WINAPI istream_SetSize(IStream *iface, ULARGE_INTEGER size)
288 {
289 ok(0, "unexpected call\n");
290 return E_NOTIMPL;
291 }
292
293 static HRESULT WINAPI istream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len,
294 ULARGE_INTEGER *pread, ULARGE_INTEGER *written)
295 {
296 ok(0, "unexpected call\n");
297 return E_NOTIMPL;
298 }
299
300 static HRESULT WINAPI istream_Commit(IStream *iface, DWORD flags)
301 {
302 ok(0, "unexpected call\n");
303 return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI istream_Revert(IStream *iface)
307 {
308 ok(0, "unexpected call\n");
309 return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI istream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
313 ULARGE_INTEGER len, DWORD locktype)
314 {
315 ok(0, "unexpected call\n");
316 return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI istream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
320 ULARGE_INTEGER len, DWORD locktype)
321 {
322 ok(0, "unexpected call\n");
323 return E_NOTIMPL;
324 }
325
326 static HRESULT WINAPI istream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flag)
327 {
328 ok(0, "unexpected call\n");
329 return E_NOTIMPL;
330 }
331
332 static HRESULT WINAPI istream_Clone(IStream *iface, IStream **stream)
333 {
334 ok(0, "unexpected call\n");
335 return E_NOTIMPL;
336 }
337
338 static const IStreamVtbl StreamVtbl = {
339 istream_QueryInterface,
340 istream_AddRef,
341 istream_Release,
342 istream_Read,
343 istream_Write,
344 istream_Seek,
345 istream_SetSize,
346 istream_CopyTo,
347 istream_Commit,
348 istream_Revert,
349 istream_LockRegion,
350 istream_UnlockRegion,
351 istream_Stat,
352 istream_Clone
353 };
354
355 #if CORE_6738_IS_FIXED
356 static IStream savestream = { &StreamVtbl };
357 #endif
358
359 #define EXPECT_CHILDREN(node) _expect_children((IXMLDOMNode*)node, __LINE__)
360 static void _expect_children(IXMLDOMNode *node, int line)
361 {
362 VARIANT_BOOL b;
363 HRESULT hr;
364
365 b = VARIANT_FALSE;
366 hr = IXMLDOMNode_hasChildNodes(node, &b);
367 ok_(__FILE__,line)(hr == S_OK, "hasChildNodes() failed, 0x%08x\n", hr);
368 ok_(__FILE__,line)(b == VARIANT_TRUE, "no children, %d\n", b);
369 }
370
371 #define EXPECT_NO_CHILDREN(node) _expect_no_children((IXMLDOMNode*)node, __LINE__)
372 static void _expect_no_children(IXMLDOMNode *node, int line)
373 {
374 VARIANT_BOOL b;
375 HRESULT hr;
376
377 b = VARIANT_TRUE;
378 hr = IXMLDOMNode_hasChildNodes(node, &b);
379 ok_(__FILE__,line)(hr == S_FALSE, "hasChildNodes() failed, 0x%08x\n", hr);
380 ok_(__FILE__,line)(b == VARIANT_FALSE, "no children, %d\n", b);
381 }
382
383 #define EXPECT_REF(node,ref) _expect_ref((IUnknown*)node, ref, __LINE__)
384 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
385 {
386 ULONG rc;
387 IUnknown_AddRef(obj);
388 rc = IUnknown_Release(obj);
389 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
390 }
391
392 #define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
393 static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
394 {
395 LONG length;
396 HRESULT hr;
397
398 length = 0;
399 hr = IXMLDOMNodeList_get_length(list, &length);
400 ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
401 ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
402 }
403
404 #define EXPECT_HR(hr,hr_exp) \
405 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
406
407 #define EXPECT_NOT_HR(hr,hr_exp) \
408 ok(hr != hr_exp, "got 0x%08x, expected not 0x%08x\n", hr, hr_exp)
409
410 static const WCHAR szEmpty[] = { 0 };
411 static const WCHAR szIncomplete[] = {
412 '<','?','x','m','l',' ',
413 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
414 };
415 static const WCHAR szComplete1[] = {
416 '<','?','x','m','l',' ',
417 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
418 '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
419 };
420 static const WCHAR szComplete2[] = {
421 '<','?','x','m','l',' ',
422 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
423 '<','o','>','<','/','o','>','\n',0
424 };
425 static const WCHAR szComplete3[] = {
426 '<','?','x','m','l',' ',
427 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
428 '<','a','>','<','/','a','>','\n',0
429 };
430 static const char complete4A[] =
431 "<?xml version=\'1.0\'?>\n"
432 "<lc dl=\'str1\'>\n"
433 "<bs vr=\'str2\' sz=\'1234\'>"
434 "fn1.txt\n"
435 "</bs>\n"
436 "<pr id=\'str3\' vr=\'1.2.3\' pn=\'wine 20050804\'>\n"
437 "fn2.txt\n"
438 "</pr>\n"
439 "<empty></empty>\n"
440 "<fo>\n"
441 "<ba>\n"
442 "f1\n"
443 "</ba>\n"
444 "</fo>\n"
445 "</lc>\n";
446
447 static const WCHAR szComplete5[] = {
448 '<','S',':','s','e','a','r','c','h',' ','x','m','l','n','s',':','D','=','"','D','A','V',':','"',' ',
449 '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','"',
450 ' ','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','"','>',
451 '<','S',':','s','c','o','p','e','>',
452 '<','S',':','d','e','e','p','>','/','<','/','S',':','d','e','e','p','>',
453 '<','/','S',':','s','c','o','p','e','>',
454 '<','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
455 '<','C',':','t','e','x','t','o','r','p','r','o','p','e','r','t','y','/','>',
456 'c','o','m','p','u','t','e','r',
457 '<','/','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
458 '<','/','S',':','s','e','a','r','c','h','>',0
459 };
460
461 static const WCHAR szComplete6[] = {
462 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'',' ',
463 'e','n','c','o','d','i','n','g','=','\'','W','i','n','d','o','w','s','-','1','2','5','2','\'','?','>','\n',
464 '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
465 };
466
467 static const char complete7[] = {
468 "<?xml version=\"1.0\"?>\n\t"
469 "<root>\n"
470 "\t<a/>\n"
471 "\t<b/>\n"
472 "\t<c/>\n"
473 "</root>"
474 };
475
476 #define DECL_WIN_1252 \
477 "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
478
479 static const char win1252xml[] =
480 DECL_WIN_1252
481 "<open></open>";
482
483 static const char win1252decl[] =
484 DECL_WIN_1252
485 ;
486
487 static const char nocontent[] = "no xml content here";
488
489 static const char szExampleXML[] =
490 "<?xml version='1.0' encoding='utf-8'?>\n"
491 "<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' a=\"attr a\" foo:b=\"attr b\" >\n"
492 " <elem>\n"
493 " <a>A1 field</a>\n"
494 " <b>B1 field</b>\n"
495 " <c>C1 field</c>\n"
496 " <d>D1 field</d>\n"
497 " <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
498 " <html xmlns='http://www.w3.org/1999/xhtml'>\n"
499 " This is <strong>a</strong> <i>description</i>. <bar:x/>\n"
500 " </html>\n"
501 " <html xml:space='preserve' xmlns='http://www.w3.org/1999/xhtml'>\n"
502 " This is <strong>a</strong> <i>description</i> with preserved whitespace. <bar:x/>\n"
503 " </html>\n"
504 " </description>\n"
505 " </elem>\n"
506 "\n"
507 " <elem a='a'>\n"
508 " <a>A2 field</a>\n"
509 " <b>B2 field</b>\n"
510 " <c type=\"old\">C2 field</c>\n"
511 " <d>D2 field</d>\n"
512 " </elem>\n"
513 "\n"
514 " <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
515 " <a>A3 field</a>\n"
516 " <b>B3 field</b>\n"
517 " <c>C3 field</c>\n"
518 " </elem>\n"
519 "\n"
520 " <elem>\n"
521 " <a>A4 field</a>\n"
522 " <b>B4 field</b>\n"
523 " <foo:c>C4 field</foo:c>\n"
524 " <d>D4 field</d>\n"
525 " </elem>\n"
526 "</root>\n";
527
528 static const char charrefsxml[] =
529 "<?xml version='1.0'?>"
530 "<a>"
531 "<b1> Text &#65; end </b1>"
532 "<b2>&#65;&#66; &#67; </b2>"
533 "</a>";
534
535 static const CHAR szNodeTypesXML[] =
536 "<?xml version='1.0'?>"
537 "<!-- comment node 0 -->"
538 "<root id='0' depth='0'>"
539 " <!-- comment node 1 -->"
540 " text node 0"
541 " <x id='1' depth='1'>"
542 " <?foo value='PI for x'?>"
543 " <!-- comment node 2 -->"
544 " text node 1"
545 " <a id='3' depth='2'/>"
546 " <b id='4' depth='2'/>"
547 " <c id='5' depth='2'/>"
548 " </x>"
549 " <y id='2' depth='1'>"
550 " <?bar value='PI for y'?>"
551 " <!-- comment node 3 -->"
552 " text node 2"
553 " <a id='6' depth='2'/>"
554 " <b id='7' depth='2'/>"
555 " <c id='8' depth='2'/>"
556 " </y>"
557 "</root>";
558
559 static const CHAR szTransformXML[] =
560 "<?xml version=\"1.0\"?>\n"
561 "<greeting>\n"
562 "Hello World\n"
563 "</greeting>";
564
565 static const CHAR szTransformSSXML[] =
566 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
567 " <xsl:output method=\"html\"/>\n"
568 " <xsl:template match=\"/\">\n"
569 " <xsl:apply-templates select=\"greeting\"/>\n"
570 " </xsl:template>\n"
571 " <xsl:template match=\"greeting\">\n"
572 " <html>\n"
573 " <body>\n"
574 " <h1>\n"
575 " <xsl:value-of select=\".\"/>\n"
576 " </h1>\n"
577 " </body>\n"
578 " </html>\n"
579 " </xsl:template>\n"
580 "</xsl:stylesheet>";
581
582 static const CHAR szTransformOutput[] =
583 "<html><body><h1>"
584 "Hello World"
585 "</h1></body></html>";
586
587 static const CHAR szTypeValueXML[] =
588 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
589 "<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
590 " <string>Wine</string>\n"
591 " <string2 dt:dt=\"string\">String</string2>\n"
592 " <number dt:dt=\"number\">12.44</number>\n"
593 " <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
594 " <int dt:dt=\"int\">-13</int>\n"
595 " <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
596 " <bool dt:dt=\"boolean\">1</bool>\n"
597 " <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
598 " <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
599 " <date dt:dt=\"date\">3721-11-01</date>\n"
600 " <time dt:dt=\"time\">13:57:12.31321</time>\n"
601 " <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
602 " <i1 dt:dt=\"i1\">-13</i1>\n"
603 " <i2 dt:dt=\"i2\">31915</i2>\n"
604 " <i4 dt:dt=\"i4\">-312232</i4>\n"
605 " <ui1 dt:dt=\"ui1\">123</ui1>\n"
606 " <ui2 dt:dt=\"ui2\">48282</ui2>\n"
607 " <ui4 dt:dt=\"ui4\">949281</ui4>\n"
608 " <r4 dt:dt=\"r4\">213124.0</r4>\n"
609 " <r8 dt:dt=\"r8\">0.412</r8>\n"
610 " <float dt:dt=\"float\">41221.421</float>\n"
611 " <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
612 " <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
613 " <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
614 " <binbase64_1 dt:dt=\"bin.base64\">\nYmFzZTY0\nIHRlc3Q=\n</binbase64_1>\n"
615 " <binbase64_2 dt:dt=\"bin.base64\">\nYmF\r\t z ZTY0\nIHRlc3Q=\n</binbase64_2>\n"
616 "</root>";
617
618 static const CHAR szBasicTransformSSXMLPart1[] =
619 "<?xml version=\"1.0\"?>"
620 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
621 "<xsl:output method=\"html\"/>\n"
622 "<xsl:template match=\"/\">"
623 "<HTML><BODY><TABLE>"
624 " <xsl:apply-templates select='document(\"";
625
626 static const CHAR szBasicTransformSSXMLPart2[] =
627 "\")/bottle/wine'>"
628 " <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
629 " </xsl:apply-templates>"
630 "</TABLE></BODY></HTML>"
631 "</xsl:template>"
632 "<xsl:template match=\"bottle\">"
633 " <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
634 "</xsl:template>"
635 "<xsl:template match=\"name\">"
636 " <TD><xsl:apply-templates /></TD>"
637 "</xsl:template>"
638 "<xsl:template match=\"cost\">"
639 " <TD><xsl:apply-templates /></TD>"
640 "</xsl:template>"
641 "</xsl:stylesheet>";
642
643 static const CHAR szBasicTransformXML[] =
644 "<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
645
646 static const CHAR szBasicTransformOutput[] =
647 "<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
648
649 #define SZ_EMAIL_DTD \
650 "<!DOCTYPE email ["\
651 " <!ELEMENT email (recipients,from,reply-to?,subject,body,attachment*)>"\
652 " <!ATTLIST email attachments IDREFS #REQUIRED>"\
653 " <!ATTLIST email sent (yes|no) \"no\">"\
654 " <!ELEMENT recipients (to+,cc*)>"\
655 " <!ELEMENT to (#PCDATA)>"\
656 " <!ATTLIST to name CDATA #IMPLIED>"\
657 " <!ELEMENT cc (#PCDATA)>"\
658 " <!ATTLIST cc name CDATA #IMPLIED>"\
659 " <!ELEMENT from (#PCDATA)>"\
660 " <!ATTLIST from name CDATA #IMPLIED>"\
661 " <!ELEMENT reply-to (#PCDATA)>"\
662 " <!ATTLIST reply-to name CDATA #IMPLIED>"\
663 " <!ELEMENT subject ANY>"\
664 " <!ELEMENT body ANY>"\
665 " <!ATTLIST body enc CDATA #FIXED \"UTF-8\">"\
666 " <!ELEMENT attachment (#PCDATA)>"\
667 " <!ATTLIST attachment id ID #REQUIRED>"\
668 "]>"
669
670 static const CHAR szEmailXML[] =
671 "<?xml version=\"1.0\"?>"
672 SZ_EMAIL_DTD
673 "<email attachments=\"patch1\">"
674 " <recipients>"
675 " <to>wine-patches@winehq.org</to>"
676 " </recipients>"
677 " <from name=\"Anonymous\">user@localhost</from>"
678 " <subject>msxml3/tests: DTD validation (try 87)</subject>"
679 " <body>"
680 " It no longer causes spontaneous combustion..."
681 " </body>"
682 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
683 "</email>";
684
685 static const CHAR szEmailXML_0D[] =
686 "<?xml version=\"1.0\"?>"
687 SZ_EMAIL_DTD
688 "<email attachments=\"patch1\">"
689 " <recipients>"
690 " <to>wine-patches@winehq.org</to>"
691 " </recipients>"
692 " <from name=\"Anonymous\">user@localhost</from>"
693 " <subject>msxml3/tests: DTD validation (try 88)</subject>"
694 " <body>"
695 " <undecl />"
696 " XML_ELEMENT_UNDECLARED 0xC00CE00D"
697 " </body>"
698 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
699 "</email>";
700
701 static const CHAR szEmailXML_0E[] =
702 "<?xml version=\"1.0\"?>"
703 SZ_EMAIL_DTD
704 "<email attachments=\"patch1\">"
705 " <recipients>"
706 " <to>wine-patches@winehq.org</to>"
707 " </recipients>"
708 " <from name=\"Anonymous\">user@localhost</from>"
709 " <subject>msxml3/tests: DTD validation (try 89)</subject>"
710 " <body>"
711 " XML_ELEMENT_ID_NOT_FOUND 0xC00CE00E"
712 " </body>"
713 " <attachment id=\"patch\">0001-msxml3-tests-DTD-validation.patch</attachment>"
714 "</email>";
715
716 static const CHAR szEmailXML_11[] =
717 "<?xml version=\"1.0\"?>"
718 SZ_EMAIL_DTD
719 "<email attachments=\"patch1\">"
720 " <recipients>"
721 " </recipients>"
722 " <from name=\"Anonymous\">user@localhost</from>"
723 " <subject>msxml3/tests: DTD validation (try 90)</subject>"
724 " <body>"
725 " XML_EMPTY_NOT_ALLOWED 0xC00CE011"
726 " </body>"
727 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
728 "</email>";
729
730 static const CHAR szEmailXML_13[] =
731 "<?xml version=\"1.0\"?>"
732 SZ_EMAIL_DTD
733 "<msg attachments=\"patch1\">"
734 " <recipients>"
735 " <to>wine-patches@winehq.org</to>"
736 " </recipients>"
737 " <from name=\"Anonymous\">user@localhost</from>"
738 " <subject>msxml3/tests: DTD validation (try 91)</subject>"
739 " <body>"
740 " XML_ROOT_NAME_MISMATCH 0xC00CE013"
741 " </body>"
742 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
743 "</msg>";
744
745 static const CHAR szEmailXML_14[] =
746 "<?xml version=\"1.0\"?>"
747 SZ_EMAIL_DTD
748 "<email attachments=\"patch1\">"
749 " <to>wine-patches@winehq.org</to>"
750 " <from name=\"Anonymous\">user@localhost</from>"
751 " <subject>msxml3/tests: DTD validation (try 92)</subject>"
752 " <body>"
753 " XML_INVALID_CONTENT 0xC00CE014"
754 " </body>"
755 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
756 "</email>";
757
758 static const CHAR szEmailXML_15[] =
759 "<?xml version=\"1.0\"?>"
760 SZ_EMAIL_DTD
761 "<email attachments=\"patch1\" ip=\"127.0.0.1\">"
762 " <recipients>"
763 " <to>wine-patches@winehq.org</to>"
764 " </recipients>"
765 " <from name=\"Anonymous\">user@localhost</from>"
766 " <subject>msxml3/tests: DTD validation (try 93)</subject>"
767 " <body>"
768 " XML_ATTRIBUTE_NOT_DEFINED 0xC00CE015"
769 " </body>"
770 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
771 "</email>";
772
773 static const CHAR szEmailXML_16[] =
774 "<?xml version=\"1.0\"?>"
775 SZ_EMAIL_DTD
776 "<email attachments=\"patch1\">"
777 " <recipients>"
778 " <to>wine-patches@winehq.org</to>"
779 " </recipients>"
780 " <from name=\"Anonymous\">user@localhost</from>"
781 " <subject>msxml3/tests: DTD validation (try 94)</subject>"
782 " <body enc=\"ASCII\">"
783 " XML_ATTRIBUTE_FIXED 0xC00CE016"
784 " </body>"
785 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
786 "</email>";
787
788 static const CHAR szEmailXML_17[] =
789 "<?xml version=\"1.0\"?>"
790 SZ_EMAIL_DTD
791 "<email attachments=\"patch1\" sent=\"true\">"
792 " <recipients>"
793 " <to>wine-patches@winehq.org</to>"
794 " </recipients>"
795 " <from name=\"Anonymous\">user@localhost</from>"
796 " <subject>msxml3/tests: DTD validation (try 95)</subject>"
797 " <body>"
798 " XML_ATTRIBUTE_VALUE 0xC00CE017"
799 " </body>"
800 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
801 "</email>";
802
803 static const CHAR szEmailXML_18[] =
804 "<?xml version=\"1.0\"?>"
805 SZ_EMAIL_DTD
806 "<email attachments=\"patch1\">"
807 " oops"
808 " <recipients>"
809 " <to>wine-patches@winehq.org</to>"
810 " </recipients>"
811 " <from name=\"Anonymous\">user@localhost</from>"
812 " <subject>msxml3/tests: DTD validation (try 96)</subject>"
813 " <body>"
814 " XML_ILLEGAL_TEXT 0xC00CE018"
815 " </body>"
816 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
817 "</email>";
818
819 static const CHAR szEmailXML_20[] =
820 "<?xml version=\"1.0\"?>"
821 SZ_EMAIL_DTD
822 "<email>"
823 " <recipients>"
824 " <to>wine-patches@winehq.org</to>"
825 " </recipients>"
826 " <from name=\"Anonymous\">user@localhost</from>"
827 " <subject>msxml3/tests: DTD validation (try 97)</subject>"
828 " <body>"
829 " XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020"
830 " </body>"
831 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
832 "</email>";
833
834 static const char xpath_simple_list[] =
835 "<?xml version=\"1.0\"?>"
836 "<root>"
837 " <a attr1=\"1\" attr2=\"2\" />"
838 " <b/>"
839 " <c/>"
840 " <d/>"
841 "</root>";
842
843 static const char default_ns_doc[] = {
844 "<?xml version=\"1.0\"?>"
845 "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
846 " d=\"d attr\" />"
847 };
848
849 static const char attributes_map[] = {
850 "<?xml version=\"1.0\"?>"
851 "<a attr1=\"value1\" attr2=\"value2\" attr3=\"value3\" attr4=\"value4\" />"
852 };
853
854 static const WCHAR nonexistent_fileW[] = {
855 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
856 };
857 static const WCHAR nonexistent_attrW[] = {
858 'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
859 };
860 static const WCHAR szDocument[] = {
861 '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
862 };
863
864 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
865 static const WCHAR szdl[] = { 'd','l',0 };
866 static const WCHAR szvr[] = { 'v','r',0 };
867 static const WCHAR szlc[] = { 'l','c',0 };
868 static const WCHAR szbs[] = { 'b','s',0 };
869 static const WCHAR szstr1[] = { 's','t','r','1',0 };
870 static const WCHAR szstr2[] = { 's','t','r','2',0 };
871 static const WCHAR szstar[] = { '*',0 };
872 static const WCHAR szfn1_txt[] = {'f','n','1','.','t','x','t',0};
873
874 static const WCHAR szComment[] = {'A',' ','C','o','m','m','e','n','t',0 };
875 static const WCHAR szCommentXML[] = {'<','!','-','-','A',' ','C','o','m','m','e','n','t','-','-','>',0 };
876 static const WCHAR szCommentNodeText[] = {'#','c','o','m','m','e','n','t',0 };
877
878 static WCHAR szElement[] = {'E','l','e','T','e','s','t', 0 };
879 static const WCHAR szElementXML[] = {'<','E','l','e','T','e','s','t','/','>',0 };
880 static const WCHAR szElementXML2[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','/','>',0 };
881 static const WCHAR szElementXML3[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
882 'T','e','s','t','i','n','g','N','o','d','e','<','/','E','l','e','T','e','s','t','>',0 };
883 static const WCHAR szElementXML4[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
884 '&','a','m','p',';','x',' ',0x2103,'<','/','E','l','e','T','e','s','t','>',0 };
885
886 static const WCHAR szAttribute[] = {'A','t','t','r',0 };
887 static const WCHAR szAttributeXML[] = {'A','t','t','r','=','"','"',0 };
888
889 static const WCHAR szCData[] = {'[','1',']','*','2','=','3',';',' ','&','g','e','e',' ','t','h','a','t','s',
890 ' ','n','o','t',' ','r','i','g','h','t','!', 0};
891 static const WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*','2','=','3',';',' ','&',
892 'g','e','e',' ','t','h','a','t','s',' ','n','o','t',' ','r','i','g','h','t',
893 '!',']',']','>',0};
894 static const WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 };
895 static const WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 };
896
897 static const WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 };
898 static const WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 };
899 static const WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
900
901 #define expect_bstr_eq_and_free(bstr, expect) { \
902 BSTR bstrExp = alloc_str_from_narrow(expect); \
903 ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \
904 SysFreeString(bstr); \
905 SysFreeString(bstrExp); \
906 }
907
908 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
909
910 #define ole_check(expr) { \
911 HRESULT r = expr; \
912 ok(r == S_OK, #expr " returned %x\n", r); \
913 }
914
915 #define ole_expect(expr, expect) { \
916 HRESULT r = expr; \
917 ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
918 }
919
920 #define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
921
922 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
923 {
924 void *obj = NULL;
925 HRESULT hr;
926
927 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
928 ok(hr == S_OK, "failed to create %s instance: 0x%08x\n", name, hr);
929
930 return obj;
931 }
932
933 #define _create(cls) cls, #cls
934
935 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
936 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
937 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
938 #define create_xsltemplate(iid) _create_object(&_create(CLSID_XSLTemplate), iid, __LINE__)
939
940 static BSTR alloc_str_from_narrow(const char *str)
941 {
942 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
943 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
944 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
945 return ret;
946 }
947
948 static BSTR alloced_bstrs[256];
949 static int alloced_bstrs_count;
950
951 static BSTR _bstr_(const char *str)
952 {
953 assert(alloced_bstrs_count < sizeof(alloced_bstrs)/sizeof(alloced_bstrs[0]));
954 alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
955 return alloced_bstrs[alloced_bstrs_count++];
956 }
957
958 static void free_bstrs(void)
959 {
960 int i;
961 for (i = 0; i < alloced_bstrs_count; i++)
962 SysFreeString(alloced_bstrs[i]);
963 alloced_bstrs_count = 0;
964 }
965
966 static VARIANT _variantbstr_(const char *str)
967 {
968 VARIANT v;
969 V_VT(&v) = VT_BSTR;
970 V_BSTR(&v) = _bstr_(str);
971 return v;
972 }
973
974 static BOOL compareIgnoreReturns(BSTR sLeft, BSTR sRight)
975 {
976 for (;;)
977 {
978 while (*sLeft == '\r' || *sLeft == '\n') sLeft++;
979 while (*sRight == '\r' || *sRight == '\n') sRight++;
980 if (*sLeft != *sRight) return FALSE;
981 if (!*sLeft) return TRUE;
982 sLeft++;
983 sRight++;
984 }
985 }
986
987 static void get_str_for_type(DOMNodeType type, char *buf)
988 {
989 switch (type)
990 {
991 case NODE_ATTRIBUTE:
992 strcpy(buf, "A");
993 break;
994 case NODE_ELEMENT:
995 strcpy(buf, "E");
996 break;
997 case NODE_DOCUMENT:
998 strcpy(buf, "D");
999 break;
1000 case NODE_TEXT:
1001 strcpy(buf, "T");
1002 break;
1003 case NODE_COMMENT:
1004 strcpy(buf, "C");
1005 break;
1006 case NODE_PROCESSING_INSTRUCTION:
1007 strcpy(buf, "P");
1008 break;
1009 default:
1010 wsprintfA(buf, "[%d]", type);
1011 }
1012 }
1013
1014 static int get_node_position(IXMLDOMNode *node)
1015 {
1016 HRESULT r;
1017 int pos = 0;
1018
1019 IXMLDOMNode_AddRef(node);
1020 do
1021 {
1022 IXMLDOMNode *new_node;
1023
1024 pos++;
1025 r = IXMLDOMNode_get_previousSibling(node, &new_node);
1026 ok(SUCCEEDED(r), "get_previousSibling failed\n");
1027 IXMLDOMNode_Release(node);
1028 node = new_node;
1029 } while (r == S_OK);
1030 return pos;
1031 }
1032
1033 static void node_to_string(IXMLDOMNode *node, char *buf)
1034 {
1035 HRESULT r = S_OK;
1036 DOMNodeType type;
1037
1038 if (node == NULL)
1039 {
1040 lstrcpyA(buf, "(null)");
1041 return;
1042 }
1043
1044 IXMLDOMNode_AddRef(node);
1045 while (r == S_OK)
1046 {
1047 IXMLDOMNode *new_node;
1048
1049 ole_check(IXMLDOMNode_get_nodeType(node, &type));
1050 get_str_for_type(type, buf);
1051 buf+=strlen(buf);
1052
1053 if (type == NODE_ATTRIBUTE)
1054 {
1055 BSTR bstr;
1056 ole_check(IXMLDOMNode_get_nodeName(node, &bstr));
1057 *(buf++) = '\'';
1058 wsprintfA(buf, "%ws", bstr);
1059 buf += strlen(buf);
1060 *(buf++) = '\'';
1061 SysFreeString(bstr);
1062
1063 r = IXMLDOMNode_selectSingleNode(node, _bstr_(".."), &new_node);
1064 }
1065 else
1066 {
1067 r = IXMLDOMNode_get_parentNode(node, &new_node);
1068 sprintf(buf, "%d", get_node_position(node));
1069 buf += strlen(buf);
1070 }
1071
1072 ok(SUCCEEDED(r), "get_parentNode failed (%08x)\n", r);
1073 IXMLDOMNode_Release(node);
1074 node = new_node;
1075 if (r == S_OK)
1076 *(buf++) = '.';
1077 }
1078
1079 *buf = 0;
1080 }
1081
1082 static char *list_to_string(IXMLDOMNodeList *list)
1083 {
1084 static char buf[4096];
1085 char *pos = buf;
1086 LONG len = 0;
1087 HRESULT hr;
1088 int i;
1089
1090 if (list == NULL)
1091 {
1092 strcpy(buf, "(null)");
1093 return buf;
1094 }
1095 hr = IXMLDOMNodeList_get_length(list, &len);
1096 ok(hr == S_OK, "got 0x%08x\n", hr);
1097 for (i = 0; i < len; i++)
1098 {
1099 IXMLDOMNode *node;
1100 if (i > 0)
1101 *(pos++) = ' ';
1102 ole_check(IXMLDOMNodeList_nextNode(list, &node));
1103 node_to_string(node, pos);
1104 pos += strlen(pos);
1105 IXMLDOMNode_Release(node);
1106 }
1107 *pos = 0;
1108 return buf;
1109 }
1110
1111 #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); }
1112 #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); }
1113
1114 struct docload_ret_t {
1115 VARIANT_BOOL b;
1116 HRESULT hr;
1117 };
1118
1119 struct leading_spaces_t {
1120 const CLSID *clsid;
1121 const char *name;
1122 struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1123 };
1124
1125 static const struct leading_spaces_t leading_spaces_classdata[] = {
1126 { &CLSID_DOMDocument, "CLSID_DOMDocument", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1127 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1128 { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1129 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1130 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1131 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1132 { NULL }
1133 };
1134
1135 static const char* leading_spaces_xmldata[] = {
1136 "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1137 " <?xml version=\"1.0\"?><root/>",
1138 "\n<?xml version=\"1.0\"?><root/>",
1139 "\t<?xml version=\"1.0\"?><root/>",
1140 "\r\n<?xml version=\"1.0\"?><root/>",
1141 "\r<?xml version=\"1.0\"?><root/>",
1142 "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1143 0
1144 };
1145
1146 static void test_domdoc( void )
1147 {
1148 HRESULT r, hr;
1149 IXMLDOMDocument *doc;
1150 IXMLDOMParseError *error;
1151 IXMLDOMElement *element = NULL;
1152 IXMLDOMNode *node;
1153 IXMLDOMText *nodetext = NULL;
1154 IXMLDOMComment *node_comment = NULL;
1155 IXMLDOMAttribute *node_attr = NULL;
1156 IXMLDOMNode *nodeChild = NULL;
1157 IXMLDOMProcessingInstruction *nodePI = NULL;
1158 const struct leading_spaces_t *class_ptr;
1159 const char **data_ptr;
1160 VARIANT_BOOL b;
1161 VARIANT var;
1162 BSTR str;
1163 LONG code, ref;
1164 LONG nLength = 0;
1165 WCHAR buff[100];
1166 char path[MAX_PATH];
1167 int index;
1168
1169 GetTempPathA(MAX_PATH, path);
1170 strcat(path, "leading_spaces.xml");
1171
1172 /* Load document with leading spaces
1173 *
1174 * Test all CLSIDs with all test data XML strings
1175 */
1176 class_ptr = leading_spaces_classdata;
1177 index = 0;
1178 while (class_ptr->clsid)
1179 {
1180 HRESULT hr;
1181 int i;
1182
1183 if (is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
1184 {
1185 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
1186 }
1187 else
1188 {
1189 class_ptr++;
1190 index++;
1191 continue;
1192 }
1193
1194 data_ptr = leading_spaces_xmldata;
1195 i = 0;
1196 while (*data_ptr) {
1197 BSTR data = _bstr_(*data_ptr);
1198 DWORD written;
1199 HANDLE file;
1200
1201 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1202 ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1203
1204 WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1205 CloseHandle(file);
1206
1207 b = 0xc;
1208 V_VT(&var) = VT_BSTR;
1209 V_BSTR(&var) = _bstr_(path);
1210 hr = IXMLDOMDocument_load(doc, var, &b);
1211 EXPECT_HR(hr, class_ptr->ret[0].hr);
1212 ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1213
1214 DeleteFileA(path);
1215
1216 b = 0xc;
1217 hr = IXMLDOMDocument_loadXML(doc, data, &b);
1218 EXPECT_HR(hr, class_ptr->ret[1].hr);
1219 ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1220
1221 data_ptr++;
1222 i++;
1223 }
1224
1225 class_ptr++;
1226 index++;
1227 free_bstrs();
1228 }
1229
1230 doc = create_document(&IID_IXMLDOMDocument);
1231 if (!doc) return;
1232
1233 if (0)
1234 {
1235 /* crashes on native */
1236 IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1237 }
1238
1239 /* try some stupid things */
1240 hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1241 EXPECT_HR(hr, S_FALSE);
1242
1243 b = VARIANT_TRUE;
1244 hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1245 EXPECT_HR(hr, S_FALSE);
1246 ok( b == VARIANT_FALSE, "failed to load XML string\n");
1247
1248 /* try to load a document from a nonexistent file */
1249 b = VARIANT_TRUE;
1250 str = SysAllocString( nonexistent_fileW );
1251 VariantInit(&var);
1252 V_VT(&var) = VT_BSTR;
1253 V_BSTR(&var) = str;
1254
1255 r = IXMLDOMDocument_load( doc, var, &b);
1256 ok( r == S_FALSE, "loadXML succeeded\n");
1257 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1258 SysFreeString( str );
1259
1260 str = (BSTR)0x1;
1261 hr = IXMLDOMDocument_get_url(doc, &str);
1262 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1263 ok(str == NULL, "got %p\n", str);
1264
1265 /* try load an empty document */
1266 b = VARIANT_TRUE;
1267 str = SysAllocString( szEmpty );
1268 r = IXMLDOMDocument_loadXML( doc, str, &b );
1269 ok( r == S_FALSE, "loadXML succeeded\n");
1270 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1271 SysFreeString( str );
1272
1273 r = IXMLDOMDocument_get_async( doc, &b );
1274 ok( r == S_OK, "get_async failed (%08x)\n", r);
1275 ok( b == VARIANT_TRUE, "Wrong default value\n");
1276
1277 /* check that there's no document element */
1278 element = NULL;
1279 r = IXMLDOMDocument_get_documentElement( doc, &element );
1280 ok( r == S_FALSE, "should be no document element\n");
1281
1282 /* try finding a node */
1283 node = NULL;
1284 str = SysAllocString( szstr1 );
1285 r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1286 ok( r == S_FALSE, "ret %08x\n", r );
1287 SysFreeString( str );
1288
1289 b = VARIANT_TRUE;
1290 str = SysAllocString( szIncomplete );
1291 r = IXMLDOMDocument_loadXML( doc, str, &b );
1292 ok( r == S_FALSE, "loadXML succeeded\n");
1293 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1294 SysFreeString( str );
1295
1296 /* check that there's no document element */
1297 element = (IXMLDOMElement*)1;
1298 r = IXMLDOMDocument_get_documentElement( doc, &element );
1299 ok( r == S_FALSE, "should be no document element\n");
1300 ok( element == NULL, "Element should be NULL\n");
1301
1302 /* test for BSTR handling, pass broken BSTR */
1303 memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1304 /* just a big length */
1305 *(DWORD*)buff = 0xf0f0;
1306 b = VARIANT_FALSE;
1307 r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1308 ok( r == S_OK, "loadXML failed\n");
1309 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1310
1311 /* loadXML ignores the encoding attribute and always expects Unicode */
1312 b = VARIANT_FALSE;
1313 str = SysAllocString( szComplete6 );
1314 r = IXMLDOMDocument_loadXML( doc, str, &b );
1315 ok( r == S_OK, "loadXML failed\n");
1316 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1317 SysFreeString( str );
1318
1319 /* try a BSTR containing a Windows-1252 document */
1320 b = VARIANT_TRUE;
1321 str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1322 r = IXMLDOMDocument_loadXML( doc, str, &b );
1323 ok( r == S_FALSE, "loadXML succeeded\n");
1324 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1325 SysFreeString( str );
1326
1327 /* try to load something valid */
1328 b = VARIANT_FALSE;
1329 str = SysAllocString( szComplete1 );
1330 r = IXMLDOMDocument_loadXML( doc, str, &b );
1331 ok( r == S_OK, "loadXML failed\n");
1332 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1333 SysFreeString( str );
1334
1335 /* check if nodename is correct */
1336 r = IXMLDOMDocument_get_nodeName( doc, NULL );
1337 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1338
1339 str = (BSTR)0xdeadbeef;
1340 r = IXMLDOMDocument_get_baseName( doc, &str );
1341 ok ( r == S_FALSE, "got 0x%08x\n", r);
1342 ok (str == NULL, "got %p\n", str);
1343
1344 /* content doesn't matter here */
1345 str = NULL;
1346 r = IXMLDOMDocument_get_nodeName( doc, &str );
1347 ok ( r == S_OK, "get_nodeName wrong code\n");
1348 ok ( str != NULL, "str is null\n");
1349 ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1350 SysFreeString( str );
1351
1352 /* test put_text */
1353 r = IXMLDOMDocument_put_text( doc, _bstr_("Should fail") );
1354 ok( r == E_FAIL, "ret %08x\n", r );
1355
1356 /* check that there's a document element */
1357 element = NULL;
1358 r = IXMLDOMDocument_get_documentElement( doc, &element );
1359 ok( r == S_OK, "should be a document element\n");
1360 if( element )
1361 {
1362 IObjectIdentity *ident;
1363
1364 r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1365 ok( r == E_NOINTERFACE, "ret %08x\n", r);
1366
1367 IXMLDOMElement_Release( element );
1368 element = NULL;
1369 }
1370
1371 /* as soon as we call loadXML again, the document element will disappear */
1372 b = 2;
1373 r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1374 ok( r == S_FALSE, "loadXML failed\n");
1375 ok( b == 2, "variant modified\n");
1376 r = IXMLDOMDocument_get_documentElement( doc, &element );
1377 ok( r == S_FALSE, "should be no document element\n");
1378
1379 /* try to load something else simple and valid */
1380 b = VARIANT_FALSE;
1381 str = SysAllocString( szComplete3 );
1382 r = IXMLDOMDocument_loadXML( doc, str, &b );
1383 ok( r == S_OK, "loadXML failed\n");
1384 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1385 SysFreeString( str );
1386
1387 /* try something a little more complicated */
1388 b = FALSE;
1389 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1390 ok( r == S_OK, "loadXML failed\n");
1391 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1392
1393 r = IXMLDOMDocument_get_parseError( doc, &error );
1394 ok( r == S_OK, "returns %08x\n", r );
1395
1396 r = IXMLDOMParseError_get_errorCode( error, &code );
1397 ok( r == S_FALSE, "returns %08x\n", r );
1398 ok( code == 0, "code %d\n", code );
1399 IXMLDOMParseError_Release( error );
1400
1401 /* test createTextNode */
1402 r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1403 ok( r == S_OK, "returns %08x\n", r );
1404 IXMLDOMText_Release(nodetext);
1405
1406 str = SysAllocString( szOpen );
1407 r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1408 ok( r == E_INVALIDARG, "returns %08x\n", r );
1409 r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1410 ok( r == S_OK, "returns %08x\n", r );
1411 SysFreeString( str );
1412 if(nodetext)
1413 {
1414 r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1415 ok(r == E_NOINTERFACE, "ret %08x\n", r );
1416
1417 /* Text Last Child Checks */
1418 r = IXMLDOMText_get_lastChild(nodetext, NULL);
1419 ok(r == E_INVALIDARG, "ret %08x\n", r );
1420
1421 nodeChild = (IXMLDOMNode*)0x1;
1422 r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1423 ok(r == S_FALSE, "ret %08x\n", r );
1424 ok(nodeChild == NULL, "nodeChild not NULL\n");
1425
1426 /* test length property */
1427 r = IXMLDOMText_get_length(nodetext, NULL);
1428 ok(r == E_INVALIDARG, "ret %08x\n", r );
1429
1430 r = IXMLDOMText_get_length(nodetext, &nLength);
1431 ok(r == S_OK, "ret %08x\n", r );
1432 ok(nLength == 4, "expected 4 got %d\n", nLength);
1433
1434 /* put data Tests */
1435 r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1436 ok(r == S_OK, "ret %08x\n", r );
1437
1438 /* get data Tests */
1439 r = IXMLDOMText_get_data(nodetext, &str);
1440 ok(r == S_OK, "ret %08x\n", r );
1441 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1442 SysFreeString(str);
1443
1444 /* Confirm XML text is good */
1445 r = IXMLDOMText_get_xml(nodetext, &str);
1446 ok(r == S_OK, "ret %08x\n", r );
1447 ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1448 SysFreeString(str);
1449
1450 /* Confirm we get the put_data Text back */
1451 r = IXMLDOMText_get_text(nodetext, &str);
1452 ok(r == S_OK, "ret %08x\n", r );
1453 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1454 SysFreeString(str);
1455
1456 /* test substringData */
1457 r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1458 ok(r == E_INVALIDARG, "ret %08x\n", r );
1459
1460 /* test substringData - Invalid offset */
1461 str = (BSTR)&szElement;
1462 r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1463 ok(r == E_INVALIDARG, "ret %08x\n", r );
1464 ok( str == NULL, "incorrect string\n");
1465
1466 /* test substringData - Invalid offset */
1467 str = (BSTR)&szElement;
1468 r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1469 ok(r == S_FALSE, "ret %08x\n", r );
1470 ok( str == NULL, "incorrect string\n");
1471
1472 /* test substringData - Invalid size */
1473 str = (BSTR)&szElement;
1474 r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1475 ok(r == E_INVALIDARG, "ret %08x\n", r );
1476 ok( str == NULL, "incorrect string\n");
1477
1478 /* test substringData - Invalid size */
1479 str = (BSTR)&szElement;
1480 r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1481 ok(r == S_FALSE, "ret %08x\n", r );
1482 ok( str == NULL, "incorrect string\n");
1483
1484 /* test substringData - Start of string */
1485 r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1486 ok(r == S_OK, "ret %08x\n", r );
1487 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1488 SysFreeString(str);
1489
1490 /* test substringData - Middle of string */
1491 r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1492 ok(r == S_OK, "ret %08x\n", r );
1493 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1494 SysFreeString(str);
1495
1496 /* test substringData - End of string */
1497 r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1498 ok(r == S_OK, "ret %08x\n", r );
1499 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1500 SysFreeString(str);
1501
1502 /* test appendData */
1503 r = IXMLDOMText_appendData(nodetext, NULL);
1504 ok(r == S_OK, "ret %08x\n", r );
1505
1506 r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1507 ok(r == S_OK, "ret %08x\n", r );
1508
1509 r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1510 ok(r == S_OK, "ret %08x\n", r );
1511
1512 r = IXMLDOMText_get_text(nodetext, &str);
1513 ok(r == S_OK, "ret %08x\n", r );
1514 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1515 SysFreeString(str);
1516
1517 /* test insertData */
1518 str = SysAllocStringLen(NULL, 0);
1519 r = IXMLDOMText_insertData(nodetext, -1, str);
1520 ok(r == S_OK, "ret %08x\n", r );
1521
1522 r = IXMLDOMText_insertData(nodetext, -1, NULL);
1523 ok(r == S_OK, "ret %08x\n", r );
1524
1525 r = IXMLDOMText_insertData(nodetext, 1000, str);
1526 ok(r == S_OK, "ret %08x\n", r );
1527
1528 r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1529 ok(r == S_OK, "ret %08x\n", r );
1530
1531 r = IXMLDOMText_insertData(nodetext, 0, NULL);
1532 ok(r == S_OK, "ret %08x\n", r );
1533
1534 r = IXMLDOMText_insertData(nodetext, 0, str);
1535 ok(r == S_OK, "ret %08x\n", r );
1536 SysFreeString(str);
1537
1538 r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1539 ok(r == E_INVALIDARG, "ret %08x\n", r );
1540
1541 r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1542 ok(r == E_INVALIDARG, "ret %08x\n", r );
1543
1544 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1545 ok(r == S_OK, "ret %08x\n", r );
1546
1547 r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1548 ok(r == S_OK, "ret %08x\n", r );
1549
1550 r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1551 ok(r == S_OK, "ret %08x\n", r );
1552
1553 r = IXMLDOMText_get_text(nodetext, &str);
1554 ok(r == S_OK, "ret %08x\n", r );
1555 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1556 SysFreeString(str);
1557
1558 /* delete data */
1559 /* invalid arguments */
1560 r = IXMLDOMText_deleteData(nodetext, -1, 1);
1561 ok(r == E_INVALIDARG, "ret %08x\n", r );
1562
1563 r = IXMLDOMText_deleteData(nodetext, 0, 0);
1564 ok(r == S_OK, "ret %08x\n", r );
1565
1566 r = IXMLDOMText_deleteData(nodetext, 0, -1);
1567 ok(r == E_INVALIDARG, "ret %08x\n", r );
1568
1569 r = IXMLDOMText_get_length(nodetext, &nLength);
1570 ok(r == S_OK, "ret %08x\n", r );
1571 ok(nLength == 43, "expected 43 got %d\n", nLength);
1572
1573 r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1574 ok(r == S_OK, "ret %08x\n", r );
1575
1576 r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1577 ok(r == E_INVALIDARG, "ret %08x\n", r );
1578
1579 /* delete from start */
1580 r = IXMLDOMText_deleteData(nodetext, 0, 5);
1581 ok(r == S_OK, "ret %08x\n", r );
1582
1583 r = IXMLDOMText_get_length(nodetext, &nLength);
1584 ok(r == S_OK, "ret %08x\n", r );
1585 ok(nLength == 38, "expected 38 got %d\n", nLength);
1586
1587 r = IXMLDOMText_get_text(nodetext, &str);
1588 ok(r == S_OK, "ret %08x\n", r );
1589 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1590 SysFreeString(str);
1591
1592 /* delete from end */
1593 r = IXMLDOMText_deleteData(nodetext, 35, 3);
1594 ok(r == S_OK, "ret %08x\n", r );
1595
1596 r = IXMLDOMText_get_length(nodetext, &nLength);
1597 ok(r == S_OK, "ret %08x\n", r );
1598 ok(nLength == 35, "expected 35 got %d\n", nLength);
1599
1600 r = IXMLDOMText_get_text(nodetext, &str);
1601 ok(r == S_OK, "ret %08x\n", r );
1602 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1603 SysFreeString(str);
1604
1605 /* delete from inside */
1606 r = IXMLDOMText_deleteData(nodetext, 1, 33);
1607 ok(r == S_OK, "ret %08x\n", r );
1608
1609 r = IXMLDOMText_get_length(nodetext, &nLength);
1610 ok(r == S_OK, "ret %08x\n", r );
1611 ok(nLength == 2, "expected 2 got %d\n", nLength);
1612
1613 r = IXMLDOMText_get_text(nodetext, &str);
1614 ok(r == S_OK, "ret %08x\n", r );
1615 ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1616 SysFreeString(str);
1617
1618 /* delete whole data ... */
1619 r = IXMLDOMText_get_length(nodetext, &nLength);
1620 ok(r == S_OK, "ret %08x\n", r );
1621
1622 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1623 ok(r == S_OK, "ret %08x\n", r );
1624 /* ... and try again with empty string */
1625 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1626 ok(r == S_OK, "ret %08x\n", r );
1627
1628 /* test put_data */
1629 V_VT(&var) = VT_BSTR;
1630 V_BSTR(&var) = SysAllocString(szstr1);
1631 r = IXMLDOMText_put_nodeValue(nodetext, var);
1632 ok(r == S_OK, "ret %08x\n", r );
1633 VariantClear(&var);
1634
1635 r = IXMLDOMText_get_text(nodetext, &str);
1636 ok(r == S_OK, "ret %08x\n", r );
1637 ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1638 SysFreeString(str);
1639
1640 /* test put_data */
1641 V_VT(&var) = VT_I4;
1642 V_I4(&var) = 99;
1643 r = IXMLDOMText_put_nodeValue(nodetext, var);
1644 ok(r == S_OK, "ret %08x\n", r );
1645 VariantClear(&var);
1646
1647 r = IXMLDOMText_get_text(nodetext, &str);
1648 ok(r == S_OK, "ret %08x\n", r );
1649 ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1650 SysFreeString(str);
1651
1652 /* ::replaceData() */
1653 V_VT(&var) = VT_BSTR;
1654 V_BSTR(&var) = SysAllocString(szstr1);
1655 r = IXMLDOMText_put_nodeValue(nodetext, var);
1656 ok(r == S_OK, "ret %08x\n", r );
1657 VariantClear(&var);
1658
1659 r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1660 ok(r == E_INVALIDARG, "ret %08x\n", r );
1661 r = IXMLDOMText_get_text(nodetext, &str);
1662 ok(r == S_OK, "ret %08x\n", r );
1663 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1664 SysFreeString(str);
1665
1666 r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1667 ok(r == S_OK, "ret %08x\n", r );
1668 r = IXMLDOMText_get_text(nodetext, &str);
1669 ok(r == S_OK, "ret %08x\n", r );
1670 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1671 SysFreeString(str);
1672
1673 /* NULL pointer means delete */
1674 r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1675 ok(r == S_OK, "ret %08x\n", r );
1676 r = IXMLDOMText_get_text(nodetext, &str);
1677 ok(r == S_OK, "ret %08x\n", r );
1678 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1679 SysFreeString(str);
1680
1681 /* empty string means delete */
1682 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1683 ok(r == S_OK, "ret %08x\n", r );
1684 r = IXMLDOMText_get_text(nodetext, &str);
1685 ok(r == S_OK, "ret %08x\n", r );
1686 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1687 SysFreeString(str);
1688
1689 /* zero count means insert */
1690 r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1691 ok(r == S_OK, "ret %08x\n", r );
1692 r = IXMLDOMText_get_text(nodetext, &str);
1693 ok(r == S_OK, "ret %08x\n", r );
1694 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1695 SysFreeString(str);
1696
1697 r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1698 ok(r == S_OK, "ret %08x\n", r );
1699
1700 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1701 ok(r == S_OK, "ret %08x\n", r );
1702 r = IXMLDOMText_get_text(nodetext, &str);
1703 ok(r == S_OK, "ret %08x\n", r );
1704 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1705 SysFreeString(str);
1706
1707 /* nonempty string, count greater than its length */
1708 r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
1709 ok(r == S_OK, "ret %08x\n", r );
1710 r = IXMLDOMText_get_text(nodetext, &str);
1711 ok(r == S_OK, "ret %08x\n", r );
1712 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1713 SysFreeString(str);
1714
1715 /* nonempty string, count less than its length */
1716 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
1717 ok(r == S_OK, "ret %08x\n", r );
1718 r = IXMLDOMText_get_text(nodetext, &str);
1719 ok(r == S_OK, "ret %08x\n", r );
1720 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1721 SysFreeString(str);
1722
1723 IXMLDOMText_Release( nodetext );
1724 }
1725
1726 /* test Create Comment */
1727 r = IXMLDOMDocument_createComment(doc, NULL, NULL);
1728 ok( r == E_INVALIDARG, "returns %08x\n", r );
1729 node_comment = (IXMLDOMComment*)0x1;
1730
1731 /* empty comment */
1732 r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
1733 ok( r == S_OK, "returns %08x\n", r );
1734 str = (BSTR)0x1;
1735 r = IXMLDOMComment_get_data(node_comment, &str);
1736 ok( r == S_OK, "returns %08x\n", r );
1737 ok( str && SysStringLen(str) == 0, "expected empty string data\n");
1738 IXMLDOMComment_Release(node_comment);
1739 SysFreeString(str);
1740
1741 r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
1742 ok( r == S_OK, "returns %08x\n", r );
1743 str = (BSTR)0x1;
1744 r = IXMLDOMComment_get_data(node_comment, &str);
1745 ok( r == S_OK, "returns %08x\n", r );
1746 ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
1747 IXMLDOMComment_Release(node_comment);
1748 SysFreeString(str);
1749
1750 str = SysAllocString(szComment);
1751 r = IXMLDOMDocument_createComment(doc, str, &node_comment);
1752 SysFreeString(str);
1753 ok( r == S_OK, "returns %08x\n", r );
1754 if(node_comment)
1755 {
1756 /* Last Child Checks */
1757 r = IXMLDOMComment_get_lastChild(node_comment, NULL);
1758 ok(r == E_INVALIDARG, "ret %08x\n", r );
1759
1760 nodeChild = (IXMLDOMNode*)0x1;
1761 r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
1762 ok(r == S_FALSE, "ret %08x\n", r );
1763 ok(nodeChild == NULL, "pLastChild not NULL\n");
1764
1765 /* baseName */
1766 str = (BSTR)0xdeadbeef;
1767 r = IXMLDOMComment_get_baseName(node_comment, &str);
1768 ok(r == S_FALSE, "ret %08x\n", r );
1769 ok(str == NULL, "Expected NULL\n");
1770
1771 IXMLDOMComment_Release( node_comment );
1772 }
1773
1774 /* test Create Attribute */
1775 str = SysAllocString(szAttribute);
1776 r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
1777 ok( r == E_INVALIDARG, "returns %08x\n", r );
1778 r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
1779 ok( r == S_OK, "returns %08x\n", r );
1780 IXMLDOMAttribute_Release( node_attr);
1781 SysFreeString(str);
1782
1783 /* test Processing Instruction */
1784 str = SysAllocStringLen(NULL, 0);
1785 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
1786 ok( r == E_INVALIDARG, "returns %08x\n", r );
1787 r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
1788 ok( r == E_FAIL, "returns %08x\n", r );
1789 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
1790 ok( r == E_FAIL, "returns %08x\n", r );
1791 SysFreeString(str);
1792
1793 r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
1794 ok( r == S_OK, "returns %08x\n", r );
1795 if(nodePI)
1796 {
1797 /* Last Child Checks */
1798 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
1799 ok(r == E_INVALIDARG, "ret %08x\n", r );
1800
1801 nodeChild = (IXMLDOMNode*)0x1;
1802 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
1803 ok(r == S_FALSE, "ret %08x\n", r );
1804 ok(nodeChild == NULL, "nodeChild not NULL\n");
1805
1806 /* test nodeName */
1807 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1808 ok(r == S_OK, "ret %08x\n", r );
1809 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1810 SysFreeString(str);
1811
1812 /* test baseName */
1813 str = (BSTR)0x1;
1814 r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
1815 ok(r == S_OK, "ret %08x\n", r );
1816 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1817 SysFreeString(str);
1818
1819 /* test Target */
1820 r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
1821 ok(r == S_OK, "ret %08x\n", r );
1822 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
1823 SysFreeString(str);
1824
1825 /* test get_data */
1826 r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
1827 ok(r == S_OK, "ret %08x\n", r );
1828 ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
1829 SysFreeString(str);
1830
1831 /* test put_data */
1832 r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
1833 ok(r == E_FAIL, "ret %08x\n", r );
1834
1835 /* test put_data */
1836 V_VT(&var) = VT_BSTR;
1837 V_BSTR(&var) = SysAllocString(szOpen); /* Doesn't matter what the string is, cannot set an xml node. */
1838 r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
1839 ok(r == E_FAIL, "ret %08x\n", r );
1840 VariantClear(&var);
1841
1842 /* test get nodeName */
1843 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1844 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1845 ok(r == S_OK, "ret %08x\n", r );
1846 SysFreeString(str);
1847
1848 IXMLDOMProcessingInstruction_Release(nodePI);
1849 }
1850
1851 ref = IXMLDOMDocument_Release( doc );
1852 ok( ref == 0, "got %d\n", ref);
1853
1854 free_bstrs();
1855 }
1856
1857 static void test_persiststreaminit(void)
1858 {
1859 IXMLDOMDocument *doc;
1860 IPersistStreamInit *streaminit;
1861 ULARGE_INTEGER size;
1862 HRESULT hr;
1863
1864 doc = create_document(&IID_IXMLDOMDocument);
1865
1866 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
1867 ok(hr == S_OK, "got 0x%08x\n", hr);
1868
1869 hr = IPersistStreamInit_InitNew(streaminit);
1870 ok(hr == S_OK, "got 0x%08x\n", hr);
1871
1872 hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
1873 ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
1874
1875 IXMLDOMDocument_Release(doc);
1876 }
1877
1878 static void test_domnode( void )
1879 {
1880 HRESULT r;
1881 IXMLDOMDocument *doc, *owner = NULL;
1882 IXMLDOMElement *element = NULL;
1883 IXMLDOMNamedNodeMap *map = NULL;
1884 IXMLDOMNode *node = NULL, *next = NULL;
1885 IXMLDOMNodeList *list = NULL;
1886 IXMLDOMAttribute *attr = NULL;
1887 DOMNodeType type = NODE_INVALID;
1888 VARIANT_BOOL b;
1889 BSTR str;
1890 VARIANT var;
1891 LONG count;
1892
1893 doc = create_document(&IID_IXMLDOMDocument);
1894
1895 b = FALSE;
1896 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1897 ok( r == S_OK, "loadXML failed\n");
1898 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1899
1900 EXPECT_CHILDREN(doc);
1901
1902 r = IXMLDOMDocument_get_documentElement( doc, &element );
1903 ok( r == S_OK, "should be a document element\n");
1904 ok( element != NULL, "should be an element\n");
1905
1906 VariantInit(&var);
1907 ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
1908
1909 r = IXMLDOMDocument_get_nodeValue( doc, NULL );
1910 ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
1911
1912 r = IXMLDOMDocument_get_nodeValue( doc, &var );
1913 ok( r == S_FALSE, "nextNode returned wrong code\n");
1914 ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
1915 ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
1916
1917 if (element)
1918 {
1919 owner = NULL;
1920 r = IXMLDOMElement_get_ownerDocument( element, &owner );
1921 ok( r == S_OK, "get_ownerDocument return code\n");
1922 ok( owner != doc, "get_ownerDocument return\n");
1923 IXMLDOMDocument_Release(owner);
1924
1925 type = NODE_INVALID;
1926 r = IXMLDOMElement_get_nodeType( element, &type);
1927 ok( r == S_OK, "got %08x\n", r);
1928 ok( type == NODE_ELEMENT, "node not an element\n");
1929
1930 str = NULL;
1931 r = IXMLDOMElement_get_baseName( element, &str );
1932 ok( r == S_OK, "get_baseName returned wrong code\n");
1933 ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
1934 SysFreeString(str);
1935
1936 /* check if nodename is correct */
1937 r = IXMLDOMElement_get_nodeName( element, NULL );
1938 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1939
1940 /* content doesn't matter here */
1941 str = NULL;
1942 r = IXMLDOMElement_get_nodeName( element, &str );
1943 ok ( r == S_OK, "get_nodeName wrong code\n");
1944 ok ( str != NULL, "str is null\n");
1945 ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
1946 SysFreeString( str );
1947
1948 str = SysAllocString( nonexistent_fileW );
1949 V_VT(&var) = VT_I4;
1950 V_I4(&var) = 0x1234;
1951 r = IXMLDOMElement_getAttribute( element, str, &var );
1952 ok( r == E_FAIL, "getAttribute ret %08x\n", r );
1953 ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
1954 VariantClear(&var);
1955 SysFreeString(str);
1956
1957 str = SysAllocString( szdl );
1958 V_VT(&var) = VT_I4;
1959 V_I4(&var) = 0x1234;
1960 r = IXMLDOMElement_getAttribute( element, str, &var );
1961 ok( r == S_OK, "getAttribute ret %08x\n", r );
1962 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
1963 ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
1964 VariantClear( &var );
1965
1966 r = IXMLDOMElement_getAttribute( element, NULL, &var );
1967 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1968
1969 r = IXMLDOMElement_getAttribute( element, str, NULL );
1970 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1971
1972 attr = NULL;
1973 r = IXMLDOMElement_getAttributeNode( element, str, &attr);
1974 ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
1975 ok( attr != NULL, "getAttributeNode returned NULL\n" );
1976 if (attr)
1977 {
1978 r = IXMLDOMAttribute_get_parentNode( attr, NULL );
1979 ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
1980
1981 /* attribute doesn't have a parent in msxml interpretation */
1982 node = (IXMLDOMNode*)0xdeadbeef;
1983 r = IXMLDOMAttribute_get_parentNode( attr, &node );
1984 ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
1985 ok( node == NULL, "Expected NULL, got %p\n", node );
1986
1987 IXMLDOMAttribute_Release(attr);
1988 }
1989
1990 SysFreeString( str );
1991
1992 r = IXMLDOMElement_get_attributes( element, &map );
1993 ok( r == S_OK, "get_attributes returned wrong code\n");
1994 ok( map != NULL, "should be attributes\n");
1995
1996 EXPECT_CHILDREN(element);
1997 }
1998 else
1999 ok( FALSE, "no element\n");
2000
2001 if (map)
2002 {
2003 str = SysAllocString( szdl );
2004 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2005 ok( r == S_OK, "getNamedItem returned wrong code\n");
2006 ok( node != NULL, "should be attributes\n");
2007 IXMLDOMNode_Release(node);
2008 SysFreeString( str );
2009
2010 str = SysAllocString( szdl );
2011 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
2012 ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
2013 SysFreeString( str );
2014
2015 /* something that isn't in complete4A */
2016 str = SysAllocString( szOpen );
2017 node = (IXMLDOMNode *) 1;
2018 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2019 ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
2020 ok( node == NULL, "getNamedItem should have returned NULL\n");
2021 SysFreeString( str );
2022
2023 /* test indexed access of attributes */
2024 r = IXMLDOMNamedNodeMap_get_length( map, NULL );
2025 ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
2026
2027 r = IXMLDOMNamedNodeMap_get_length( map, &count );
2028 ok ( r == S_OK, "get_length wrong code\n");
2029 ok ( count == 1, "get_length != 1\n");
2030
2031 node = NULL;
2032 r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
2033 ok ( r == S_FALSE, "get_item (-1) wrong code\n");
2034 ok ( node == NULL, "there is no node\n");
2035
2036 node = NULL;
2037 r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
2038 ok ( r == S_FALSE, "get_item (1) wrong code\n");
2039 ok ( node == NULL, "there is no attribute\n");
2040
2041 node = NULL;
2042 r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
2043 ok ( r == S_OK, "get_item (0) wrong code\n");
2044 ok ( node != NULL, "should be attribute\n");
2045
2046 r = IXMLDOMNode_get_nodeName( node, NULL );
2047 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2048
2049 /* content doesn't matter here */
2050 str = NULL;
2051 r = IXMLDOMNode_get_nodeName( node, &str );
2052 ok ( r == S_OK, "get_nodeName wrong code\n");
2053 ok ( str != NULL, "str is null\n");
2054 ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
2055 SysFreeString( str );
2056 IXMLDOMNode_Release( node );
2057
2058 /* test sequential access of attributes */
2059 node = NULL;
2060 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2061 ok ( r == S_OK, "nextNode (first time) wrong code\n");
2062 ok ( node != NULL, "nextNode, should be attribute\n");
2063 IXMLDOMNode_Release( node );
2064
2065 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2066 ok ( r != S_OK, "nextNode (second time) wrong code\n");
2067 ok ( node == NULL, "nextNode, there is no attribute\n");
2068
2069 r = IXMLDOMNamedNodeMap_reset( map );
2070 ok ( r == S_OK, "reset should return S_OK\n");
2071
2072 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2073 ok ( r == S_OK, "nextNode (third time) wrong code\n");
2074 ok ( node != NULL, "nextNode, should be attribute\n");
2075 }
2076 else
2077 ok( FALSE, "no map\n");
2078
2079 if (node)
2080 {
2081 type = NODE_INVALID;
2082 r = IXMLDOMNode_get_nodeType( node, &type);
2083 ok( r == S_OK, "getNamedItem returned wrong code\n");
2084 ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
2085
2086 str = NULL;
2087 r = IXMLDOMNode_get_baseName( node, NULL );
2088 ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
2089
2090 str = NULL;
2091 r = IXMLDOMNode_get_baseName( node, &str );
2092 ok( r == S_OK, "get_baseName returned wrong code\n");
2093 ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
2094 SysFreeString( str );
2095
2096 r = IXMLDOMNode_get_childNodes( node, NULL );
2097 ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
2098
2099 r = IXMLDOMNode_get_childNodes( node, &list );
2100 ok( r == S_OK, "get_childNodes returned wrong code\n");
2101
2102 if (list)
2103 {
2104 r = IXMLDOMNodeList_nextNode( list, &next );
2105 ok( r == S_OK, "nextNode returned wrong code\n");
2106 }
2107 else
2108 ok( FALSE, "no childlist\n");
2109
2110 if (next)
2111 {
2112 EXPECT_NO_CHILDREN(next);
2113
2114 type = NODE_INVALID;
2115 r = IXMLDOMNode_get_nodeType( next, &type);
2116 ok( r == S_OK, "getNamedItem returned wrong code\n");
2117 ok( type == NODE_TEXT, "node not text\n");
2118
2119 str = (BSTR) 1;
2120 r = IXMLDOMNode_get_baseName( next, &str );
2121 ok( r == S_FALSE, "get_baseName returned wrong code\n");
2122 ok( str == NULL, "basename was wrong\n");
2123 SysFreeString(str);
2124 }
2125 else
2126 ok( FALSE, "no next\n");
2127
2128 if (next)
2129 IXMLDOMNode_Release( next );
2130 next = NULL;
2131 if (list)
2132 IXMLDOMNodeList_Release( list );
2133 list = NULL;
2134 if (node)
2135 IXMLDOMNode_Release( node );
2136 }
2137 else
2138 ok( FALSE, "no node\n");
2139 node = NULL;
2140
2141 if (map)
2142 IXMLDOMNamedNodeMap_Release( map );
2143
2144 /* now traverse the tree from the root element */
2145 if (element)
2146 {
2147 r = IXMLDOMElement_get_childNodes( element, &list );
2148 ok( r == S_OK, "get_childNodes returned wrong code\n");
2149
2150 /* using get_item for child list doesn't advance the position */
2151 ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2152 expect_node(node, "E2.E2.D1");
2153 IXMLDOMNode_Release(node);
2154 ole_check(IXMLDOMNodeList_nextNode(list, &node));
2155 expect_node(node, "E1.E2.D1");
2156 IXMLDOMNode_Release(node);
2157 ole_check(IXMLDOMNodeList_reset(list));
2158
2159 IXMLDOMNodeList_AddRef(list);
2160 expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2161 ole_check(IXMLDOMNodeList_reset(list));
2162
2163 node = (void*)0xdeadbeef;
2164 str = SysAllocString(szdl);
2165 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2166 SysFreeString(str);
2167 ok( r == S_FALSE, "ret %08x\n", r );
2168 ok( node == NULL, "node %p\n", node );
2169
2170 str = SysAllocString(szbs);
2171 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2172 SysFreeString(str);
2173 ok( r == S_OK, "ret %08x\n", r );
2174 r = IXMLDOMNode_Release( node );
2175 ok( r == 0, "ret %08x\n", r );
2176 }
2177 else
2178 ok( FALSE, "no element\n");
2179
2180 if (list)
2181 {
2182 r = IXMLDOMNodeList_get_item(list, 0, NULL);
2183 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2184
2185 r = IXMLDOMNodeList_get_length(list, NULL);
2186 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2187
2188 r = IXMLDOMNodeList_get_length( list, &count );
2189 ok( r == S_OK, "get_length returns %08x\n", r );
2190 ok( count == 4, "get_length got %d\n", count );
2191
2192 r = IXMLDOMNodeList_nextNode(list, NULL);
2193 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2194
2195 r = IXMLDOMNodeList_nextNode( list, &node );
2196 ok( r == S_OK, "nextNode returned wrong code\n");
2197 }
2198 else
2199 ok( FALSE, "no list\n");
2200
2201 if (node)
2202 {
2203 type = NODE_INVALID;
2204 r = IXMLDOMNode_get_nodeType( node, &type);
2205 ok( r == S_OK, "getNamedItem returned wrong code\n");
2206 ok( type == NODE_ELEMENT, "node not text\n");
2207
2208 r = IXMLDOMNode_hasChildNodes( node, NULL );
2209 ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2210
2211 EXPECT_CHILDREN(node);
2212
2213 str = NULL;
2214 r = IXMLDOMNode_get_baseName( node, &str );
2215 ok( r == S_OK, "get_baseName returned wrong code\n");
2216 ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2217 SysFreeString(str);
2218 }
2219 else
2220 ok( FALSE, "no node\n");
2221
2222 if (node)
2223 IXMLDOMNode_Release( node );
2224 if (list)
2225 IXMLDOMNodeList_Release( list );
2226 if (element)
2227 IXMLDOMElement_Release( element );
2228
2229 b = FALSE;
2230 str = SysAllocString( szComplete5 );
2231 r = IXMLDOMDocument_loadXML( doc, str, &b );
2232 ok( r == S_OK, "loadXML failed\n");
2233 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2234 SysFreeString( str );
2235
2236 EXPECT_CHILDREN(doc);
2237
2238 r = IXMLDOMDocument_get_documentElement( doc, &element );
2239 ok( r == S_OK, "should be a document element\n");
2240 ok( element != NULL, "should be an element\n");
2241
2242 if (element)
2243 {
2244 static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2245 BSTR tag = NULL;
2246
2247 /* check if the tag is correct */
2248 r = IXMLDOMElement_get_tagName( element, &tag );
2249 ok( r == S_OK, "couldn't get tag name\n");
2250 ok( tag != NULL, "tag was null\n");
2251 ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2252 SysFreeString( tag );
2253 }
2254
2255 if (element)
2256 IXMLDOMElement_Release( element );
2257 ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2258
2259 free_bstrs();
2260 }
2261
2262 typedef struct {
2263 DOMNodeType type;
2264 REFIID iid;
2265 } refcount_test_t;
2266
2267 static const refcount_test_t refcount_test[] = {
2268 { NODE_ELEMENT, &IID_IXMLDOMElement },
2269 { NODE_ATTRIBUTE, &IID_IXMLDOMAttribute },
2270 { NODE_TEXT, &IID_IXMLDOMText },
2271 { NODE_CDATA_SECTION, &IID_IXMLDOMCDATASection },
2272 { NODE_ENTITY_REFERENCE, &IID_IXMLDOMEntityReference },
2273 { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2274 { NODE_COMMENT, &IID_IXMLDOMComment },
2275 { NODE_DOCUMENT_FRAGMENT, &IID_IXMLDOMDocumentFragment },
2276 { NODE_INVALID, &IID_NULL }
2277 };
2278
2279 static void test_refs(void)
2280 {
2281 IXMLDOMImplementation *impl, *impl2;
2282 IXMLDOMElement *element, *elem2;
2283 IXMLDOMNodeList *node_list = NULL;
2284 IXMLDOMNode *node, *node2, *node3;
2285 const refcount_test_t *ptr;
2286 IXMLDOMDocument *doc;
2287 IUnknown *unk, *unk2;
2288 VARIANT_BOOL b;
2289 HRESULT hr;
2290 LONG ref;
2291
2292 doc = create_document(&IID_IXMLDOMDocument);
2293
2294 ptr = refcount_test;
2295 while (ptr->type != NODE_INVALID)
2296 {
2297 IUnknown *node_typed, *node_typed2;
2298 IDispatchEx *dispex, *dispex2;
2299 IDispatch *disp, *disp2;
2300 VARIANT type;
2301
2302 V_VT(&type) = VT_I1;
2303 V_I1(&type) = ptr->type;
2304
2305 EXPECT_REF(doc, 1);
2306 hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2307 EXPECT_HR(hr, S_OK);
2308 EXPECT_REF(doc, 1);
2309 EXPECT_REF(node, 1);
2310
2311 /* try IDispatch and IUnknown from IXMLDOMNode */
2312 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2313 EXPECT_HR(hr, S_OK);
2314 EXPECT_REF(unk, 2);
2315 todo_wine {
2316 EXPECT_REF(node, 1);
2317 ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2318 }
2319 EXPECT_REF(unk, 2);
2320 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2321 EXPECT_HR(hr, S_OK);
2322 todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2323 EXPECT_REF(unk, 3);
2324 todo_wine EXPECT_REF(disp, 1);
2325
2326 EXPECT_REF(unk, 3);
2327 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2328 EXPECT_HR(hr, S_OK);
2329 todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2330 EXPECT_REF(unk, 4);
2331 todo_wine EXPECT_REF(disp2, 1);
2332
2333 IDispatch_Release(disp);
2334 IDispatch_Release(disp2);
2335
2336 /* get IXMLDOMNode from this IUnknown */
2337 EXPECT_REF(unk, 2);
2338 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2339 EXPECT_HR(hr, S_OK);
2340 todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2341 EXPECT_REF(unk, 3);
2342 todo_wine EXPECT_REF(node2, 1);
2343
2344 EXPECT_REF(unk, 3);
2345 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2346 EXPECT_HR(hr, S_OK);
2347 todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2348 EXPECT_REF(unk, 4);
2349 todo_wine EXPECT_REF(node3, 1);
2350
2351 IXMLDOMNode_Release(node2);
2352 IXMLDOMNode_Release(node3);
2353
2354 /* try IDispatchEx from IUnknown */
2355 EXPECT_REF(unk, 2);
2356 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2357 EXPECT_HR(hr, S_OK);
2358 ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2359 EXPECT_REF(unk, 3);
2360 todo_wine EXPECT_REF(dispex, 1);
2361
2362 EXPECT_REF(unk, 3);
2363 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2364 EXPECT_HR(hr, S_OK);
2365 todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2366 EXPECT_REF(unk, 4);
2367 todo_wine EXPECT_REF(dispex2, 1);
2368
2369 IDispatchEx_Release(dispex);
2370 IDispatchEx_Release(dispex2);
2371
2372 /* try corresponding IXMLDOM* */
2373 EXPECT_REF(unk, 2);
2374 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2375 EXPECT_HR(hr, S_OK);
2376 EXPECT_REF(unk, 3);
2377 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2378 EXPECT_HR(hr, S_OK);
2379 EXPECT_REF(unk, 4);
2380 todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2381 IUnknown_Release(node_typed);
2382 IUnknown_Release(node_typed2);
2383
2384 /* try invalid IXMLDOM* */
2385 hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2386 EXPECT_HR(hr, E_NOINTERFACE);
2387
2388 IUnknown_Release(unk);
2389
2390 EXPECT_REF(node, 1);
2391 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2392 EXPECT_HR(hr, S_OK);
2393 EXPECT_REF(node, 2);
2394 ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2395
2396 EXPECT_REF(node, 2);
2397 hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2398 EXPECT_HR(hr, S_OK);
2399 EXPECT_REF(node, 3);
2400 todo_wine {
2401 EXPECT_REF(node_typed, 2);
2402 ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2403 }
2404 IUnknown_Release(node_typed);
2405
2406 IXMLDOMNode_Release(node2);
2407 IXMLDOMNode_Release(node);
2408
2409 ptr++;
2410 }
2411
2412 EXPECT_REF(doc, 1);
2413 ref = IXMLDOMDocument_Release(doc);
2414 ok( ref == 0, "ref %d\n", ref);
2415
2416 /* check IUnknown after releasing DOM iface */
2417 doc = create_document(&IID_IXMLDOMDocument);
2418 EXPECT_REF(doc, 1);
2419 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2420 EXPECT_HR(hr, S_OK);
2421 todo_wine {
2422 EXPECT_REF(unk, 3);
2423 EXPECT_REF(doc, 1);
2424 }
2425 IXMLDOMDocument_Release(doc);
2426 EXPECT_REF(unk, 1);
2427 IUnknown_Release(unk);
2428
2429 doc = create_document(&IID_IXMLDOMDocument);
2430
2431 EXPECT_REF(doc, 1);
2432 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2433 EXPECT_HR(hr, S_OK);
2434 todo_wine {
2435 EXPECT_REF(unk, 3);
2436 EXPECT_REF(doc, 1);
2437 }
2438 IUnknown_Release(unk);
2439
2440 /* IXMLDOMImplementation */
2441 EXPECT_REF(doc, 1);
2442 hr = IXMLDOMDocument_get_implementation(doc, &impl);
2443 EXPECT_HR(hr, S_OK);
2444 EXPECT_REF(doc, 1);
2445 EXPECT_REF(impl, 1);
2446 hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2447 EXPECT_HR(hr, S_OK);
2448 EXPECT_REF(doc, 1);
2449 EXPECT_REF(impl2, 1);
2450 ok(impl != impl2, "got %p, %p\n", impl, impl2);
2451 IXMLDOMImplementation_Release(impl);
2452 IXMLDOMImplementation_Release(impl2);
2453
2454 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2455 EXPECT_HR(hr, S_OK);
2456 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2457
2458 EXPECT_REF(doc, 1);
2459 IXMLDOMDocument_AddRef( doc );
2460 EXPECT_REF(doc, 2);
2461 IXMLDOMDocument_AddRef( doc );
2462 EXPECT_REF(doc, 3);
2463
2464 IXMLDOMDocument_Release( doc );
2465 IXMLDOMDocument_Release( doc );
2466
2467 EXPECT_REF(doc, 1);
2468 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2469 EXPECT_HR(hr, S_OK);
2470 todo_wine {
2471 EXPECT_REF(unk, 3);
2472 EXPECT_REF(doc, 1);
2473 }
2474 hr = IXMLDOMDocument_get_documentElement(doc, &element);
2475 EXPECT_HR(hr, S_OK);
2476 todo_wine {
2477 EXPECT_REF(doc, 1);
2478 EXPECT_REF(element, 2);
2479 }
2480 hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2481 EXPECT_HR(hr, S_OK);
2482
2483 todo_wine {
2484 EXPECT_REF(doc, 1);
2485 EXPECT_REF(element, 2);
2486 EXPECT_REF(elem2, 2);
2487 }
2488 IXMLDOMElement_AddRef(element);
2489 todo_wine EXPECT_REF(element, 3);
2490 IXMLDOMElement_Release(element);
2491
2492 /* get IUnknown from a node doesn't touch node instance refcount */
2493 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2494 EXPECT_HR(hr, S_OK);
2495 EXPECT_REF(element, 2);
2496 todo_wine {
2497 EXPECT_REF(unk, 4);
2498 EXPECT_REF(elem2, 2);
2499 }
2500 hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2501 EXPECT_HR(hr, S_OK);
2502 todo_wine {
2503 EXPECT_REF(unk, 5);
2504 EXPECT_REF(unk2, 5);
2505 }
2506 EXPECT_REF(element, 2);
2507 EXPECT_REF(elem2, 2);
2508
2509 todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2510 IUnknown_Release(unk);
2511
2512 /* IUnknown refcount is not affected by node refcount */
2513 todo_wine EXPECT_REF(unk2, 4);
2514 IXMLDOMElement_AddRef(elem2);
2515 todo_wine EXPECT_REF(unk2, 4);
2516 IXMLDOMElement_Release(elem2);
2517
2518 IXMLDOMElement_Release(elem2);
2519 todo_wine EXPECT_REF(unk2, 3);
2520
2521 IUnknown_Release(unk2);
2522
2523 hr = IXMLDOMElement_get_childNodes( element, &node_list );
2524 EXPECT_HR(hr, S_OK);
2525
2526 todo_wine EXPECT_REF(element, 2);
2527 EXPECT_REF(node_list, 1);
2528
2529 hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2530 EXPECT_HR(hr, S_OK);
2531 EXPECT_REF(node_list, 1);
2532 EXPECT_REF(node, 1);
2533
2534 hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2535 EXPECT_HR(hr, S_OK);
2536 EXPECT_REF(node_list, 1);
2537 EXPECT_REF(node2, 1);
2538
2539 ref = IXMLDOMNode_Release( node );
2540 ok( ref == 0, "ref %d\n", ref );
2541 ref = IXMLDOMNode_Release( node2 );
2542 ok( ref == 0, "ref %d\n", ref );
2543
2544 ref = IXMLDOMNodeList_Release( node_list );
2545 ok( ref == 0, "ref %d\n", ref );
2546
2547 ok( node != node2, "node %p node2 %p\n", node, node2 );
2548
2549 ref = IXMLDOMDocument_Release( doc );
2550 todo_wine ok( ref == 0, "ref %d\n", ref );
2551
2552 todo_wine EXPECT_REF(element, 2);
2553
2554 /* IUnknown must be unique however we obtain it */
2555 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2556 EXPECT_HR(hr, S_OK);
2557 EXPECT_REF(element, 2);
2558 hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2559 EXPECT_HR(hr, S_OK);
2560 todo_wine EXPECT_REF(element, 2);
2561 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2562 EXPECT_HR(hr, S_OK);
2563 todo_wine EXPECT_REF(element, 2);
2564 ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2565 todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2566
2567 IUnknown_Release( unk2 );
2568 IUnknown_Release( unk );
2569 IXMLDOMNode_Release( node );
2570 todo_wine EXPECT_REF(element, 2);
2571
2572 IXMLDOMElement_Release( element );
2573
2574 free_bstrs();
2575 }
2576
2577 static void test_create(void)
2578 {
2579 static const WCHAR szOne[] = {'1',0};
2580 static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2581 HRESULT r;
2582 VARIANT var;
2583 BSTR str, name;
2584 IXMLDOMDocument *doc;
2585 IXMLDOMElement *element;
2586 IXMLDOMComment *comment;
2587 IXMLDOMText *text;
2588 IXMLDOMCDATASection *cdata;
2589 IXMLDOMNode *root, *node, *child;
2590 IXMLDOMNamedNodeMap *attr_map;
2591 IUnknown *unk;
2592 LONG ref;
2593 LONG num;
2594
2595 doc = create_document(&IID_IXMLDOMDocument);
2596
2597 EXPECT_REF(doc, 1);
2598
2599 /* types not supported for creation */
2600 V_VT(&var) = VT_I1;
2601 V_I1(&var) = NODE_DOCUMENT;
2602 node = (IXMLDOMNode*)0x1;
2603 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2604 ok( r == E_INVALIDARG, "returns %08x\n", r );
2605 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2606
2607 V_VT(&var) = VT_I1;
2608 V_I1(&var) = NODE_DOCUMENT_TYPE;
2609 node = (IXMLDOMNode*)0x1;
2610 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2611 ok( r == E_INVALIDARG, "returns %08x\n", r );
2612 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2613
2614 V_VT(&var) = VT_I1;
2615 V_I1(&var) = NODE_ENTITY;
2616 node = (IXMLDOMNode*)0x1;
2617 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2618 ok( r == E_INVALIDARG, "returns %08x\n", r );
2619 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2620
2621 V_VT(&var) = VT_I1;
2622 V_I1(&var) = NODE_NOTATION;
2623 node = (IXMLDOMNode*)0x1;
2624 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2625 ok( r == E_INVALIDARG, "returns %08x\n", r );
2626 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2627
2628 /* NODE_COMMENT */
2629 V_VT(&var) = VT_I1;
2630 V_I1(&var) = NODE_COMMENT;
2631 node = NULL;
2632 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2633 ok( r == S_OK, "returns %08x\n", r );
2634 ok( node != NULL, "\n");
2635
2636 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2637 ok( r == S_OK, "returns %08x\n", r );
2638 IXMLDOMNode_Release(node);
2639
2640 str = NULL;
2641 r = IXMLDOMComment_get_data(comment, &str);
2642 ok( r == S_OK, "returns %08x\n", r );
2643 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2644 IXMLDOMComment_Release(comment);
2645 SysFreeString(str);
2646
2647 node = (IXMLDOMNode*)0x1;
2648 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2649 ok( r == S_OK, "returns %08x\n", r );
2650
2651 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2652 ok( r == S_OK, "returns %08x\n", r );
2653 IXMLDOMNode_Release(node);
2654
2655 str = NULL;
2656 r = IXMLDOMComment_get_data(comment, &str);
2657 ok( r == S_OK, "returns %08x\n", r );
2658 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2659 IXMLDOMComment_Release(comment);
2660 SysFreeString(str);
2661
2662 node = (IXMLDOMNode*)0x1;
2663 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2664 ok( r == S_OK, "returns %08x\n", r );
2665
2666 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2667 ok( r == S_OK, "returns %08x\n", r );
2668 IXMLDOMNode_Release(node);
2669
2670 str = NULL;
2671 r = IXMLDOMComment_get_data(comment, &str);
2672 ok( r == S_OK, "returns %08x\n", r );
2673 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2674 IXMLDOMComment_Release(comment);
2675 SysFreeString(str);
2676
2677 /* NODE_TEXT */
2678 V_VT(&var) = VT_I1;
2679 V_I1(&var) = NODE_TEXT;
2680 node = NULL;
2681 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2682 ok( r == S_OK, "returns %08x\n", r );
2683 ok( node != NULL, "\n");
2684
2685 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2686 ok( r == S_OK, "returns %08x\n", r );
2687 IXMLDOMNode_Release(node);
2688
2689 str = NULL;
2690 r = IXMLDOMText_get_data(text, &str);
2691 ok( r == S_OK, "returns %08x\n", r );
2692 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2693 IXMLDOMText_Release(text);
2694 SysFreeString(str);
2695
2696 node = (IXMLDOMNode*)0x1;
2697 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2698 ok( r == S_OK, "returns %08x\n", r );
2699
2700 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2701 ok( r == S_OK, "returns %08x\n", r );
2702 IXMLDOMNode_Release(node);
2703
2704 str = NULL;
2705 r = IXMLDOMText_get_data(text, &str);
2706 ok( r == S_OK, "returns %08x\n", r );
2707 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2708 IXMLDOMText_Release(text);
2709 SysFreeString(str);
2710
2711 node = (IXMLDOMNode*)0x1;
2712 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2713 ok( r == S_OK, "returns %08x\n", r );
2714
2715 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2716 ok( r == S_OK, "returns %08x\n", r );
2717 IXMLDOMNode_Release(node);
2718
2719 str = NULL;
2720 r = IXMLDOMText_get_data(text, &str);
2721 ok( r == S_OK, "returns %08x\n", r );