103d0ed976411f8927d55ee183ea1df72d70b3e5
[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>\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 int i;
1088
1089 if (list == NULL)
1090 {
1091 lstrcpyA(buf, "(null)");
1092 return buf;
1093 }
1094 ole_check(IXMLDOMNodeList_get_length(list, &len));
1095 for (i = 0; i < len; i++)
1096 {
1097 IXMLDOMNode *node;
1098 if (i > 0)
1099 *(pos++) = ' ';
1100 ole_check(IXMLDOMNodeList_nextNode(list, &node));
1101 node_to_string(node, pos);
1102 pos += strlen(pos);
1103 IXMLDOMNode_Release(node);
1104 }
1105 *pos = 0;
1106 return buf;
1107 }
1108
1109 #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); }
1110 #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); }
1111
1112 struct docload_ret_t {
1113 VARIANT_BOOL b;
1114 HRESULT hr;
1115 };
1116
1117 struct leading_spaces_t {
1118 const CLSID *clsid;
1119 const char *name;
1120 struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1121 };
1122
1123 static const struct leading_spaces_t leading_spaces_classdata[] = {
1124 { &CLSID_DOMDocument, "CLSID_DOMDocument", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1125 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1126 { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1127 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1128 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1129 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1130 { NULL }
1131 };
1132
1133 static const char* leading_spaces_xmldata[] = {
1134 "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1135 " <?xml version=\"1.0\"?><root/>",
1136 "\n<?xml version=\"1.0\"?><root/>",
1137 "\t<?xml version=\"1.0\"?><root/>",
1138 "\r\n<?xml version=\"1.0\"?><root/>",
1139 "\r<?xml version=\"1.0\"?><root/>",
1140 "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1141 0
1142 };
1143
1144 static void test_domdoc( void )
1145 {
1146 HRESULT r, hr;
1147 IXMLDOMDocument *doc;
1148 IXMLDOMParseError *error;
1149 IXMLDOMElement *element = NULL;
1150 IXMLDOMNode *node;
1151 IXMLDOMText *nodetext = NULL;
1152 IXMLDOMComment *node_comment = NULL;
1153 IXMLDOMAttribute *node_attr = NULL;
1154 IXMLDOMNode *nodeChild = NULL;
1155 IXMLDOMProcessingInstruction *nodePI = NULL;
1156 const struct leading_spaces_t *class_ptr;
1157 const char **data_ptr;
1158 VARIANT_BOOL b;
1159 VARIANT var;
1160 BSTR str;
1161 LONG code, ref;
1162 LONG nLength = 0;
1163 WCHAR buff[100];
1164 char path[MAX_PATH];
1165 int index;
1166
1167 GetTempPathA(MAX_PATH, path);
1168 strcat(path, "leading_spaces.xml");
1169
1170 /* Load document with leading spaces
1171 *
1172 * Test all CLSIDs with all test data XML strings
1173 */
1174 class_ptr = leading_spaces_classdata;
1175 index = 0;
1176 while (class_ptr->clsid)
1177 {
1178 HRESULT hr;
1179 int i;
1180
1181 if (is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
1182 {
1183 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
1184 }
1185 else
1186 {
1187 class_ptr++;
1188 index++;
1189 continue;
1190 }
1191
1192 data_ptr = leading_spaces_xmldata;
1193 i = 0;
1194 while (*data_ptr) {
1195 BSTR data = _bstr_(*data_ptr);
1196 DWORD written;
1197 HANDLE file;
1198
1199 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1200 ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1201
1202 WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1203 CloseHandle(file);
1204
1205 b = 0xc;
1206 V_VT(&var) = VT_BSTR;
1207 V_BSTR(&var) = _bstr_(path);
1208 hr = IXMLDOMDocument_load(doc, var, &b);
1209 EXPECT_HR(hr, class_ptr->ret[0].hr);
1210 ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1211
1212 DeleteFileA(path);
1213
1214 b = 0xc;
1215 hr = IXMLDOMDocument_loadXML(doc, data, &b);
1216 EXPECT_HR(hr, class_ptr->ret[1].hr);
1217 ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1218
1219 data_ptr++;
1220 i++;
1221 }
1222
1223 class_ptr++;
1224 index++;
1225 free_bstrs();
1226 }
1227
1228 doc = create_document(&IID_IXMLDOMDocument);
1229 if (!doc) return;
1230
1231 if (0)
1232 {
1233 /* crashes on native */
1234 IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1235 }
1236
1237 /* try some stupid things */
1238 hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1239 EXPECT_HR(hr, S_FALSE);
1240
1241 b = VARIANT_TRUE;
1242 hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1243 EXPECT_HR(hr, S_FALSE);
1244 ok( b == VARIANT_FALSE, "failed to load XML string\n");
1245
1246 /* try to load a document from a nonexistent file */
1247 b = VARIANT_TRUE;
1248 str = SysAllocString( nonexistent_fileW );
1249 VariantInit(&var);
1250 V_VT(&var) = VT_BSTR;
1251 V_BSTR(&var) = str;
1252
1253 r = IXMLDOMDocument_load( doc, var, &b);
1254 ok( r == S_FALSE, "loadXML succeeded\n");
1255 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1256 SysFreeString( str );
1257
1258 str = (BSTR)0x1;
1259 hr = IXMLDOMDocument_get_url(doc, &str);
1260 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1261 ok(str == NULL, "got %p\n", str);
1262
1263 /* try load an empty document */
1264 b = VARIANT_TRUE;
1265 str = SysAllocString( szEmpty );
1266 r = IXMLDOMDocument_loadXML( doc, str, &b );
1267 ok( r == S_FALSE, "loadXML succeeded\n");
1268 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1269 SysFreeString( str );
1270
1271 r = IXMLDOMDocument_get_async( doc, &b );
1272 ok( r == S_OK, "get_async failed (%08x)\n", r);
1273 ok( b == VARIANT_TRUE, "Wrong default value\n");
1274
1275 /* check that there's no document element */
1276 element = NULL;
1277 r = IXMLDOMDocument_get_documentElement( doc, &element );
1278 ok( r == S_FALSE, "should be no document element\n");
1279
1280 /* try finding a node */
1281 node = NULL;
1282 str = SysAllocString( szstr1 );
1283 r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1284 ok( r == S_FALSE, "ret %08x\n", r );
1285 SysFreeString( str );
1286
1287 b = VARIANT_TRUE;
1288 str = SysAllocString( szIncomplete );
1289 r = IXMLDOMDocument_loadXML( doc, str, &b );
1290 ok( r == S_FALSE, "loadXML succeeded\n");
1291 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1292 SysFreeString( str );
1293
1294 /* check that there's no document element */
1295 element = (IXMLDOMElement*)1;
1296 r = IXMLDOMDocument_get_documentElement( doc, &element );
1297 ok( r == S_FALSE, "should be no document element\n");
1298 ok( element == NULL, "Element should be NULL\n");
1299
1300 /* test for BSTR handling, pass broken BSTR */
1301 memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1302 /* just a big length */
1303 *(DWORD*)buff = 0xf0f0;
1304 b = VARIANT_FALSE;
1305 r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1306 ok( r == S_OK, "loadXML failed\n");
1307 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1308
1309 /* loadXML ignores the encoding attribute and always expects Unicode */
1310 b = VARIANT_FALSE;
1311 str = SysAllocString( szComplete6 );
1312 r = IXMLDOMDocument_loadXML( doc, str, &b );
1313 ok( r == S_OK, "loadXML failed\n");
1314 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1315 SysFreeString( str );
1316
1317 /* try a BSTR containing a Windows-1252 document */
1318 b = VARIANT_TRUE;
1319 str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1320 r = IXMLDOMDocument_loadXML( doc, str, &b );
1321 ok( r == S_FALSE, "loadXML succeeded\n");
1322 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1323 SysFreeString( str );
1324
1325 /* try to load something valid */
1326 b = VARIANT_FALSE;
1327 str = SysAllocString( szComplete1 );
1328 r = IXMLDOMDocument_loadXML( doc, str, &b );
1329 ok( r == S_OK, "loadXML failed\n");
1330 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1331 SysFreeString( str );
1332
1333 /* check if nodename is correct */
1334 r = IXMLDOMDocument_get_nodeName( doc, NULL );
1335 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1336
1337 str = (BSTR)0xdeadbeef;
1338 r = IXMLDOMDocument_get_baseName( doc, &str );
1339 ok ( r == S_FALSE, "got 0x%08x\n", r);
1340 ok (str == NULL, "got %p\n", str);
1341
1342 /* content doesn't matter here */
1343 str = NULL;
1344 r = IXMLDOMDocument_get_nodeName( doc, &str );
1345 ok ( r == S_OK, "get_nodeName wrong code\n");
1346 ok ( str != NULL, "str is null\n");
1347 ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1348 SysFreeString( str );
1349
1350 /* test put_text */
1351 r = IXMLDOMDocument_put_text( doc, _bstr_("Should fail") );
1352 ok( r == E_FAIL, "ret %08x\n", r );
1353
1354 /* check that there's a document element */
1355 element = NULL;
1356 r = IXMLDOMDocument_get_documentElement( doc, &element );
1357 ok( r == S_OK, "should be a document element\n");
1358 if( element )
1359 {
1360 IObjectIdentity *ident;
1361
1362 r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1363 ok( r == E_NOINTERFACE, "ret %08x\n", r);
1364
1365 IXMLDOMElement_Release( element );
1366 element = NULL;
1367 }
1368
1369 /* as soon as we call loadXML again, the document element will disappear */
1370 b = 2;
1371 r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1372 ok( r == S_FALSE, "loadXML failed\n");
1373 ok( b == 2, "variant modified\n");
1374 r = IXMLDOMDocument_get_documentElement( doc, &element );
1375 ok( r == S_FALSE, "should be no document element\n");
1376
1377 /* try to load something else simple and valid */
1378 b = VARIANT_FALSE;
1379 str = SysAllocString( szComplete3 );
1380 r = IXMLDOMDocument_loadXML( doc, str, &b );
1381 ok( r == S_OK, "loadXML failed\n");
1382 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1383 SysFreeString( str );
1384
1385 /* try something a little more complicated */
1386 b = FALSE;
1387 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1388 ok( r == S_OK, "loadXML failed\n");
1389 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1390
1391 r = IXMLDOMDocument_get_parseError( doc, &error );
1392 ok( r == S_OK, "returns %08x\n", r );
1393
1394 r = IXMLDOMParseError_get_errorCode( error, &code );
1395 ok( r == S_FALSE, "returns %08x\n", r );
1396 ok( code == 0, "code %d\n", code );
1397 IXMLDOMParseError_Release( error );
1398
1399 /* test createTextNode */
1400 r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1401 ok( r == S_OK, "returns %08x\n", r );
1402 IXMLDOMText_Release(nodetext);
1403
1404 str = SysAllocString( szOpen );
1405 r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1406 ok( r == E_INVALIDARG, "returns %08x\n", r );
1407 r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1408 ok( r == S_OK, "returns %08x\n", r );
1409 SysFreeString( str );
1410 if(nodetext)
1411 {
1412 r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1413 ok(r == E_NOINTERFACE, "ret %08x\n", r );
1414
1415 /* Text Last Child Checks */
1416 r = IXMLDOMText_get_lastChild(nodetext, NULL);
1417 ok(r == E_INVALIDARG, "ret %08x\n", r );
1418
1419 nodeChild = (IXMLDOMNode*)0x1;
1420 r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1421 ok(r == S_FALSE, "ret %08x\n", r );
1422 ok(nodeChild == NULL, "nodeChild not NULL\n");
1423
1424 /* test length property */
1425 r = IXMLDOMText_get_length(nodetext, NULL);
1426 ok(r == E_INVALIDARG, "ret %08x\n", r );
1427
1428 r = IXMLDOMText_get_length(nodetext, &nLength);
1429 ok(r == S_OK, "ret %08x\n", r );
1430 ok(nLength == 4, "expected 4 got %d\n", nLength);
1431
1432 /* put data Tests */
1433 r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1434 ok(r == S_OK, "ret %08x\n", r );
1435
1436 /* get data Tests */
1437 r = IXMLDOMText_get_data(nodetext, &str);
1438 ok(r == S_OK, "ret %08x\n", r );
1439 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1440 SysFreeString(str);
1441
1442 /* Confirm XML text is good */
1443 r = IXMLDOMText_get_xml(nodetext, &str);
1444 ok(r == S_OK, "ret %08x\n", r );
1445 ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1446 SysFreeString(str);
1447
1448 /* Confirm we get the put_data Text back */
1449 r = IXMLDOMText_get_text(nodetext, &str);
1450 ok(r == S_OK, "ret %08x\n", r );
1451 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1452 SysFreeString(str);
1453
1454 /* test substringData */
1455 r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1456 ok(r == E_INVALIDARG, "ret %08x\n", r );
1457
1458 /* test substringData - Invalid offset */
1459 str = (BSTR)&szElement;
1460 r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1461 ok(r == E_INVALIDARG, "ret %08x\n", r );
1462 ok( str == NULL, "incorrect string\n");
1463
1464 /* test substringData - Invalid offset */
1465 str = (BSTR)&szElement;
1466 r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1467 ok(r == S_FALSE, "ret %08x\n", r );
1468 ok( str == NULL, "incorrect string\n");
1469
1470 /* test substringData - Invalid size */
1471 str = (BSTR)&szElement;
1472 r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1473 ok(r == E_INVALIDARG, "ret %08x\n", r );
1474 ok( str == NULL, "incorrect string\n");
1475
1476 /* test substringData - Invalid size */
1477 str = (BSTR)&szElement;
1478 r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1479 ok(r == S_FALSE, "ret %08x\n", r );
1480 ok( str == NULL, "incorrect string\n");
1481
1482 /* test substringData - Start of string */
1483 r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1484 ok(r == S_OK, "ret %08x\n", r );
1485 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1486 SysFreeString(str);
1487
1488 /* test substringData - Middle of string */
1489 r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1490 ok(r == S_OK, "ret %08x\n", r );
1491 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1492 SysFreeString(str);
1493
1494 /* test substringData - End of string */
1495 r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1496 ok(r == S_OK, "ret %08x\n", r );
1497 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1498 SysFreeString(str);
1499
1500 /* test appendData */
1501 r = IXMLDOMText_appendData(nodetext, NULL);
1502 ok(r == S_OK, "ret %08x\n", r );
1503
1504 r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1505 ok(r == S_OK, "ret %08x\n", r );
1506
1507 r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1508 ok(r == S_OK, "ret %08x\n", r );
1509
1510 r = IXMLDOMText_get_text(nodetext, &str);
1511 ok(r == S_OK, "ret %08x\n", r );
1512 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1513 SysFreeString(str);
1514
1515 /* test insertData */
1516 str = SysAllocStringLen(NULL, 0);
1517 r = IXMLDOMText_insertData(nodetext, -1, str);
1518 ok(r == S_OK, "ret %08x\n", r );
1519
1520 r = IXMLDOMText_insertData(nodetext, -1, NULL);
1521 ok(r == S_OK, "ret %08x\n", r );
1522
1523 r = IXMLDOMText_insertData(nodetext, 1000, str);
1524 ok(r == S_OK, "ret %08x\n", r );
1525
1526 r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1527 ok(r == S_OK, "ret %08x\n", r );
1528
1529 r = IXMLDOMText_insertData(nodetext, 0, NULL);
1530 ok(r == S_OK, "ret %08x\n", r );
1531
1532 r = IXMLDOMText_insertData(nodetext, 0, str);
1533 ok(r == S_OK, "ret %08x\n", r );
1534 SysFreeString(str);
1535
1536 r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1537 ok(r == E_INVALIDARG, "ret %08x\n", r );
1538
1539 r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1540 ok(r == E_INVALIDARG, "ret %08x\n", r );
1541
1542 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1543 ok(r == S_OK, "ret %08x\n", r );
1544
1545 r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1546 ok(r == S_OK, "ret %08x\n", r );
1547
1548 r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1549 ok(r == S_OK, "ret %08x\n", r );
1550
1551 r = IXMLDOMText_get_text(nodetext, &str);
1552 ok(r == S_OK, "ret %08x\n", r );
1553 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1554 SysFreeString(str);
1555
1556 /* delete data */
1557 /* invalid arguments */
1558 r = IXMLDOMText_deleteData(nodetext, -1, 1);
1559 ok(r == E_INVALIDARG, "ret %08x\n", r );
1560
1561 r = IXMLDOMText_deleteData(nodetext, 0, 0);
1562 ok(r == S_OK, "ret %08x\n", r );
1563
1564 r = IXMLDOMText_deleteData(nodetext, 0, -1);
1565 ok(r == E_INVALIDARG, "ret %08x\n", r );
1566
1567 r = IXMLDOMText_get_length(nodetext, &nLength);
1568 ok(r == S_OK, "ret %08x\n", r );
1569 ok(nLength == 43, "expected 43 got %d\n", nLength);
1570
1571 r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1572 ok(r == S_OK, "ret %08x\n", r );
1573
1574 r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1575 ok(r == E_INVALIDARG, "ret %08x\n", r );
1576
1577 /* delete from start */
1578 r = IXMLDOMText_deleteData(nodetext, 0, 5);
1579 ok(r == S_OK, "ret %08x\n", r );
1580
1581 r = IXMLDOMText_get_length(nodetext, &nLength);
1582 ok(r == S_OK, "ret %08x\n", r );
1583 ok(nLength == 38, "expected 38 got %d\n", nLength);
1584
1585 r = IXMLDOMText_get_text(nodetext, &str);
1586 ok(r == S_OK, "ret %08x\n", r );
1587 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1588 SysFreeString(str);
1589
1590 /* delete from end */
1591 r = IXMLDOMText_deleteData(nodetext, 35, 3);
1592 ok(r == S_OK, "ret %08x\n", r );
1593
1594 r = IXMLDOMText_get_length(nodetext, &nLength);
1595 ok(r == S_OK, "ret %08x\n", r );
1596 ok(nLength == 35, "expected 35 got %d\n", nLength);
1597
1598 r = IXMLDOMText_get_text(nodetext, &str);
1599 ok(r == S_OK, "ret %08x\n", r );
1600 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1601 SysFreeString(str);
1602
1603 /* delete from inside */
1604 r = IXMLDOMText_deleteData(nodetext, 1, 33);
1605 ok(r == S_OK, "ret %08x\n", r );
1606
1607 r = IXMLDOMText_get_length(nodetext, &nLength);
1608 ok(r == S_OK, "ret %08x\n", r );
1609 ok(nLength == 2, "expected 2 got %d\n", nLength);
1610
1611 r = IXMLDOMText_get_text(nodetext, &str);
1612 ok(r == S_OK, "ret %08x\n", r );
1613 ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1614 SysFreeString(str);
1615
1616 /* delete whole data ... */
1617 r = IXMLDOMText_get_length(nodetext, &nLength);
1618 ok(r == S_OK, "ret %08x\n", r );
1619
1620 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1621 ok(r == S_OK, "ret %08x\n", r );
1622 /* ... and try again with empty string */
1623 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1624 ok(r == S_OK, "ret %08x\n", r );
1625
1626 /* test put_data */
1627 V_VT(&var) = VT_BSTR;
1628 V_BSTR(&var) = SysAllocString(szstr1);
1629 r = IXMLDOMText_put_nodeValue(nodetext, var);
1630 ok(r == S_OK, "ret %08x\n", r );
1631 VariantClear(&var);
1632
1633 r = IXMLDOMText_get_text(nodetext, &str);
1634 ok(r == S_OK, "ret %08x\n", r );
1635 ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1636 SysFreeString(str);
1637
1638 /* test put_data */
1639 V_VT(&var) = VT_I4;
1640 V_I4(&var) = 99;
1641 r = IXMLDOMText_put_nodeValue(nodetext, var);
1642 ok(r == S_OK, "ret %08x\n", r );
1643 VariantClear(&var);
1644
1645 r = IXMLDOMText_get_text(nodetext, &str);
1646 ok(r == S_OK, "ret %08x\n", r );
1647 ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1648 SysFreeString(str);
1649
1650 /* ::replaceData() */
1651 V_VT(&var) = VT_BSTR;
1652 V_BSTR(&var) = SysAllocString(szstr1);
1653 r = IXMLDOMText_put_nodeValue(nodetext, var);
1654 ok(r == S_OK, "ret %08x\n", r );
1655 VariantClear(&var);
1656
1657 r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1658 ok(r == E_INVALIDARG, "ret %08x\n", r );
1659 r = IXMLDOMText_get_text(nodetext, &str);
1660 ok(r == S_OK, "ret %08x\n", r );
1661 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1662 SysFreeString(str);
1663
1664 r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1665 ok(r == S_OK, "ret %08x\n", r );
1666 r = IXMLDOMText_get_text(nodetext, &str);
1667 ok(r == S_OK, "ret %08x\n", r );
1668 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1669 SysFreeString(str);
1670
1671 /* NULL pointer means delete */
1672 r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1673 ok(r == S_OK, "ret %08x\n", r );
1674 r = IXMLDOMText_get_text(nodetext, &str);
1675 ok(r == S_OK, "ret %08x\n", r );
1676 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1677 SysFreeString(str);
1678
1679 /* empty string means delete */
1680 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1681 ok(r == S_OK, "ret %08x\n", r );
1682 r = IXMLDOMText_get_text(nodetext, &str);
1683 ok(r == S_OK, "ret %08x\n", r );
1684 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1685 SysFreeString(str);
1686
1687 /* zero count means insert */
1688 r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1689 ok(r == S_OK, "ret %08x\n", r );
1690 r = IXMLDOMText_get_text(nodetext, &str);
1691 ok(r == S_OK, "ret %08x\n", r );
1692 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1693 SysFreeString(str);
1694
1695 r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1696 ok(r == S_OK, "ret %08x\n", r );
1697
1698 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1699 ok(r == S_OK, "ret %08x\n", r );
1700 r = IXMLDOMText_get_text(nodetext, &str);
1701 ok(r == S_OK, "ret %08x\n", r );
1702 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1703 SysFreeString(str);
1704
1705 /* nonempty string, count greater than its length */
1706 r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
1707 ok(r == S_OK, "ret %08x\n", r );
1708 r = IXMLDOMText_get_text(nodetext, &str);
1709 ok(r == S_OK, "ret %08x\n", r );
1710 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1711 SysFreeString(str);
1712
1713 /* nonempty string, count less than its length */
1714 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
1715 ok(r == S_OK, "ret %08x\n", r );
1716 r = IXMLDOMText_get_text(nodetext, &str);
1717 ok(r == S_OK, "ret %08x\n", r );
1718 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1719 SysFreeString(str);
1720
1721 IXMLDOMText_Release( nodetext );
1722 }
1723
1724 /* test Create Comment */
1725 r = IXMLDOMDocument_createComment(doc, NULL, NULL);
1726 ok( r == E_INVALIDARG, "returns %08x\n", r );
1727 node_comment = (IXMLDOMComment*)0x1;
1728
1729 /* empty comment */
1730 r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
1731 ok( r == S_OK, "returns %08x\n", r );
1732 str = (BSTR)0x1;
1733 r = IXMLDOMComment_get_data(node_comment, &str);
1734 ok( r == S_OK, "returns %08x\n", r );
1735 ok( str && SysStringLen(str) == 0, "expected empty string data\n");
1736 IXMLDOMComment_Release(node_comment);
1737 SysFreeString(str);
1738
1739 r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
1740 ok( r == S_OK, "returns %08x\n", r );
1741 str = (BSTR)0x1;
1742 r = IXMLDOMComment_get_data(node_comment, &str);
1743 ok( r == S_OK, "returns %08x\n", r );
1744 ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
1745 IXMLDOMComment_Release(node_comment);
1746 SysFreeString(str);
1747
1748 str = SysAllocString(szComment);
1749 r = IXMLDOMDocument_createComment(doc, str, &node_comment);
1750 SysFreeString(str);
1751 ok( r == S_OK, "returns %08x\n", r );
1752 if(node_comment)
1753 {
1754 /* Last Child Checks */
1755 r = IXMLDOMComment_get_lastChild(node_comment, NULL);
1756 ok(r == E_INVALIDARG, "ret %08x\n", r );
1757
1758 nodeChild = (IXMLDOMNode*)0x1;
1759 r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
1760 ok(r == S_FALSE, "ret %08x\n", r );
1761 ok(nodeChild == NULL, "pLastChild not NULL\n");
1762
1763 /* baseName */
1764 str = (BSTR)0xdeadbeef;
1765 r = IXMLDOMComment_get_baseName(node_comment, &str);
1766 ok(r == S_FALSE, "ret %08x\n", r );
1767 ok(str == NULL, "Expected NULL\n");
1768
1769 IXMLDOMComment_Release( node_comment );
1770 }
1771
1772 /* test Create Attribute */
1773 str = SysAllocString(szAttribute);
1774 r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
1775 ok( r == E_INVALIDARG, "returns %08x\n", r );
1776 r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
1777 ok( r == S_OK, "returns %08x\n", r );
1778 IXMLDOMAttribute_Release( node_attr);
1779 SysFreeString(str);
1780
1781 /* test Processing Instruction */
1782 str = SysAllocStringLen(NULL, 0);
1783 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
1784 ok( r == E_INVALIDARG, "returns %08x\n", r );
1785 r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
1786 ok( r == E_FAIL, "returns %08x\n", r );
1787 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
1788 ok( r == E_FAIL, "returns %08x\n", r );
1789 SysFreeString(str);
1790
1791 r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
1792 ok( r == S_OK, "returns %08x\n", r );
1793 if(nodePI)
1794 {
1795 /* Last Child Checks */
1796 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
1797 ok(r == E_INVALIDARG, "ret %08x\n", r );
1798
1799 nodeChild = (IXMLDOMNode*)0x1;
1800 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
1801 ok(r == S_FALSE, "ret %08x\n", r );
1802 ok(nodeChild == NULL, "nodeChild not NULL\n");
1803
1804 /* test nodeName */
1805 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1806 ok(r == S_OK, "ret %08x\n", r );
1807 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1808 SysFreeString(str);
1809
1810 /* test baseName */
1811 str = (BSTR)0x1;
1812 r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
1813 ok(r == S_OK, "ret %08x\n", r );
1814 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1815 SysFreeString(str);
1816
1817 /* test Target */
1818 r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
1819 ok(r == S_OK, "ret %08x\n", r );
1820 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
1821 SysFreeString(str);
1822
1823 /* test get_data */
1824 r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
1825 ok(r == S_OK, "ret %08x\n", r );
1826 ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
1827 SysFreeString(str);
1828
1829 /* test put_data */
1830 r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
1831 ok(r == E_FAIL, "ret %08x\n", r );
1832
1833 /* test put_data */
1834 V_VT(&var) = VT_BSTR;
1835 V_BSTR(&var) = SysAllocString(szOpen); /* Doesn't matter what the string is, cannot set an xml node. */
1836 r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
1837 ok(r == E_FAIL, "ret %08x\n", r );
1838 VariantClear(&var);
1839
1840 /* test get nodeName */
1841 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
1842 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
1843 ok(r == S_OK, "ret %08x\n", r );
1844 SysFreeString(str);
1845
1846 IXMLDOMProcessingInstruction_Release(nodePI);
1847 }
1848
1849 ref = IXMLDOMDocument_Release( doc );
1850 ok( ref == 0, "got %d\n", ref);
1851
1852 free_bstrs();
1853 }
1854
1855 static void test_persiststreaminit(void)
1856 {
1857 IXMLDOMDocument *doc;
1858 IPersistStreamInit *streaminit;
1859 ULARGE_INTEGER size;
1860 HRESULT hr;
1861
1862 doc = create_document(&IID_IXMLDOMDocument);
1863
1864 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
1865 ok(hr == S_OK, "got 0x%08x\n", hr);
1866
1867 hr = IPersistStreamInit_InitNew(streaminit);
1868 ok(hr == S_OK, "got 0x%08x\n", hr);
1869
1870 hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
1871 ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
1872
1873 IXMLDOMDocument_Release(doc);
1874 }
1875
1876 static void test_domnode( void )
1877 {
1878 HRESULT r;
1879 IXMLDOMDocument *doc, *owner = NULL;
1880 IXMLDOMElement *element = NULL;
1881 IXMLDOMNamedNodeMap *map = NULL;
1882 IXMLDOMNode *node = NULL, *next = NULL;
1883 IXMLDOMNodeList *list = NULL;
1884 IXMLDOMAttribute *attr = NULL;
1885 DOMNodeType type = NODE_INVALID;
1886 VARIANT_BOOL b;
1887 BSTR str;
1888 VARIANT var;
1889 LONG count;
1890
1891 doc = create_document(&IID_IXMLDOMDocument);
1892
1893 b = FALSE;
1894 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1895 ok( r == S_OK, "loadXML failed\n");
1896 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1897
1898 EXPECT_CHILDREN(doc);
1899
1900 r = IXMLDOMDocument_get_documentElement( doc, &element );
1901 ok( r == S_OK, "should be a document element\n");
1902 ok( element != NULL, "should be an element\n");
1903
1904 VariantInit(&var);
1905 ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
1906
1907 r = IXMLDOMDocument_get_nodeValue( doc, NULL );
1908 ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
1909
1910 r = IXMLDOMDocument_get_nodeValue( doc, &var );
1911 ok( r == S_FALSE, "nextNode returned wrong code\n");
1912 ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
1913 ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
1914
1915 if (element)
1916 {
1917 owner = NULL;
1918 r = IXMLDOMElement_get_ownerDocument( element, &owner );
1919 ok( r == S_OK, "get_ownerDocument return code\n");
1920 ok( owner != doc, "get_ownerDocument return\n");
1921 IXMLDOMDocument_Release(owner);
1922
1923 type = NODE_INVALID;
1924 r = IXMLDOMElement_get_nodeType( element, &type);
1925 ok( r == S_OK, "got %08x\n", r);
1926 ok( type == NODE_ELEMENT, "node not an element\n");
1927
1928 str = NULL;
1929 r = IXMLDOMElement_get_baseName( element, &str );
1930 ok( r == S_OK, "get_baseName returned wrong code\n");
1931 ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
1932 SysFreeString(str);
1933
1934 /* check if nodename is correct */
1935 r = IXMLDOMElement_get_nodeName( element, NULL );
1936 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1937
1938 /* content doesn't matter here */
1939 str = NULL;
1940 r = IXMLDOMElement_get_nodeName( element, &str );
1941 ok ( r == S_OK, "get_nodeName wrong code\n");
1942 ok ( str != NULL, "str is null\n");
1943 ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
1944 SysFreeString( str );
1945
1946 str = SysAllocString( nonexistent_fileW );
1947 V_VT(&var) = VT_I4;
1948 V_I4(&var) = 0x1234;
1949 r = IXMLDOMElement_getAttribute( element, str, &var );
1950 ok( r == E_FAIL, "getAttribute ret %08x\n", r );
1951 ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
1952 VariantClear(&var);
1953
1954 str = SysAllocString( szdl );
1955 V_VT(&var) = VT_I4;
1956 V_I4(&var) = 0x1234;
1957 r = IXMLDOMElement_getAttribute( element, str, &var );
1958 ok( r == S_OK, "getAttribute ret %08x\n", r );
1959 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
1960 ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
1961 VariantClear( &var );
1962
1963 r = IXMLDOMElement_getAttribute( element, NULL, &var );
1964 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1965
1966 r = IXMLDOMElement_getAttribute( element, str, NULL );
1967 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
1968
1969 attr = NULL;
1970 r = IXMLDOMElement_getAttributeNode( element, str, &attr);
1971 ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
1972 ok( attr != NULL, "getAttributeNode returned NULL\n" );
1973 if (attr)
1974 {
1975 r = IXMLDOMAttribute_get_parentNode( attr, NULL );
1976 ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
1977
1978 /* attribute doesn't have a parent in msxml interpretation */
1979 node = (IXMLDOMNode*)0xdeadbeef;
1980 r = IXMLDOMAttribute_get_parentNode( attr, &node );
1981 ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
1982 ok( node == NULL, "Expected NULL, got %p\n", node );
1983
1984 IXMLDOMAttribute_Release(attr);
1985 }
1986
1987 SysFreeString( str );
1988
1989 r = IXMLDOMElement_get_attributes( element, &map );
1990 ok( r == S_OK, "get_attributes returned wrong code\n");
1991 ok( map != NULL, "should be attributes\n");
1992
1993 EXPECT_CHILDREN(element);
1994 }
1995 else
1996 ok( FALSE, "no element\n");
1997
1998 if (map)
1999 {
2000 str = SysAllocString( szdl );
2001 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2002 ok( r == S_OK, "getNamedItem returned wrong code\n");
2003 ok( node != NULL, "should be attributes\n");
2004 IXMLDOMNode_Release(node);
2005 SysFreeString( str );
2006
2007 str = SysAllocString( szdl );
2008 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
2009 ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
2010 SysFreeString( str );
2011
2012 /* something that isn't in complete4A */
2013 str = SysAllocString( szOpen );
2014 node = (IXMLDOMNode *) 1;
2015 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2016 ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
2017 ok( node == NULL, "getNamedItem should have returned NULL\n");
2018 SysFreeString( str );
2019
2020 /* test indexed access of attributes */
2021 r = IXMLDOMNamedNodeMap_get_length( map, NULL );
2022 ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
2023
2024 r = IXMLDOMNamedNodeMap_get_length( map, &count );
2025 ok ( r == S_OK, "get_length wrong code\n");
2026 ok ( count == 1, "get_length != 1\n");
2027
2028 node = NULL;
2029 r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
2030 ok ( r == S_FALSE, "get_item (-1) wrong code\n");
2031 ok ( node == NULL, "there is no node\n");
2032
2033 node = NULL;
2034 r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
2035 ok ( r == S_FALSE, "get_item (1) wrong code\n");
2036 ok ( node == NULL, "there is no attribute\n");
2037
2038 node = NULL;
2039 r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
2040 ok ( r == S_OK, "get_item (0) wrong code\n");
2041 ok ( node != NULL, "should be attribute\n");
2042
2043 r = IXMLDOMNode_get_nodeName( node, NULL );
2044 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2045
2046 /* content doesn't matter here */
2047 str = NULL;
2048 r = IXMLDOMNode_get_nodeName( node, &str );
2049 ok ( r == S_OK, "get_nodeName wrong code\n");
2050 ok ( str != NULL, "str is null\n");
2051 ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
2052 SysFreeString( str );
2053 IXMLDOMNode_Release( node );
2054
2055 /* test sequential access of attributes */
2056 node = NULL;
2057 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2058 ok ( r == S_OK, "nextNode (first time) wrong code\n");
2059 ok ( node != NULL, "nextNode, should be attribute\n");
2060 IXMLDOMNode_Release( node );
2061
2062 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2063 ok ( r != S_OK, "nextNode (second time) wrong code\n");
2064 ok ( node == NULL, "nextNode, there is no attribute\n");
2065
2066 r = IXMLDOMNamedNodeMap_reset( map );
2067 ok ( r == S_OK, "reset should return S_OK\n");
2068
2069 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2070 ok ( r == S_OK, "nextNode (third time) wrong code\n");
2071 ok ( node != NULL, "nextNode, should be attribute\n");
2072 }
2073 else
2074 ok( FALSE, "no map\n");
2075
2076 if (node)
2077 {
2078 type = NODE_INVALID;
2079 r = IXMLDOMNode_get_nodeType( node, &type);
2080 ok( r == S_OK, "getNamedItem returned wrong code\n");
2081 ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
2082
2083 str = NULL;
2084 r = IXMLDOMNode_get_baseName( node, NULL );
2085 ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
2086
2087 str = NULL;
2088 r = IXMLDOMNode_get_baseName( node, &str );
2089 ok( r == S_OK, "get_baseName returned wrong code\n");
2090 ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
2091 SysFreeString( str );
2092
2093 r = IXMLDOMNode_get_childNodes( node, NULL );
2094 ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
2095
2096 r = IXMLDOMNode_get_childNodes( node, &list );
2097 ok( r == S_OK, "get_childNodes returned wrong code\n");
2098
2099 if (list)
2100 {
2101 r = IXMLDOMNodeList_nextNode( list, &next );
2102 ok( r == S_OK, "nextNode returned wrong code\n");
2103 }
2104 else
2105 ok( FALSE, "no childlist\n");
2106
2107 if (next)
2108 {
2109 EXPECT_NO_CHILDREN(next);
2110
2111 type = NODE_INVALID;
2112 r = IXMLDOMNode_get_nodeType( next, &type);
2113 ok( r == S_OK, "getNamedItem returned wrong code\n");
2114 ok( type == NODE_TEXT, "node not text\n");
2115
2116 str = (BSTR) 1;
2117 r = IXMLDOMNode_get_baseName( next, &str );
2118 ok( r == S_FALSE, "get_baseName returned wrong code\n");
2119 ok( str == NULL, "basename was wrong\n");
2120 SysFreeString(str);
2121 }
2122 else
2123 ok( FALSE, "no next\n");
2124
2125 if (next)
2126 IXMLDOMNode_Release( next );
2127 next = NULL;
2128 if (list)
2129 IXMLDOMNodeList_Release( list );
2130 list = NULL;
2131 if (node)
2132 IXMLDOMNode_Release( node );
2133 }
2134 else
2135 ok( FALSE, "no node\n");
2136 node = NULL;
2137
2138 if (map)
2139 IXMLDOMNamedNodeMap_Release( map );
2140
2141 /* now traverse the tree from the root element */
2142 if (element)
2143 {
2144 r = IXMLDOMElement_get_childNodes( element, &list );
2145 ok( r == S_OK, "get_childNodes returned wrong code\n");
2146
2147 /* using get_item for child list doesn't advance the position */
2148 ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2149 expect_node(node, "E2.E2.D1");
2150 IXMLDOMNode_Release(node);
2151 ole_check(IXMLDOMNodeList_nextNode(list, &node));
2152 expect_node(node, "E1.E2.D1");
2153 IXMLDOMNode_Release(node);
2154 ole_check(IXMLDOMNodeList_reset(list));
2155
2156 IXMLDOMNodeList_AddRef(list);
2157 expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2158 ole_check(IXMLDOMNodeList_reset(list));
2159
2160 node = (void*)0xdeadbeef;
2161 str = SysAllocString(szdl);
2162 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2163 SysFreeString(str);
2164 ok( r == S_FALSE, "ret %08x\n", r );
2165 ok( node == NULL, "node %p\n", node );
2166
2167 str = SysAllocString(szbs);
2168 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2169 SysFreeString(str);
2170 ok( r == S_OK, "ret %08x\n", r );
2171 r = IXMLDOMNode_Release( node );
2172 ok( r == 0, "ret %08x\n", r );
2173 }
2174 else
2175 ok( FALSE, "no element\n");
2176
2177 if (list)
2178 {
2179 r = IXMLDOMNodeList_get_item(list, 0, NULL);
2180 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2181
2182 r = IXMLDOMNodeList_get_length(list, NULL);
2183 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2184
2185 r = IXMLDOMNodeList_get_length( list, &count );
2186 ok( r == S_OK, "get_length returns %08x\n", r );
2187 ok( count == 4, "get_length got %d\n", count );
2188
2189 r = IXMLDOMNodeList_nextNode(list, NULL);
2190 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2191
2192 r = IXMLDOMNodeList_nextNode( list, &node );
2193 ok( r == S_OK, "nextNode returned wrong code\n");
2194 }
2195 else
2196 ok( FALSE, "no list\n");
2197
2198 if (node)
2199 {
2200 type = NODE_INVALID;
2201 r = IXMLDOMNode_get_nodeType( node, &type);
2202 ok( r == S_OK, "getNamedItem returned wrong code\n");
2203 ok( type == NODE_ELEMENT, "node not text\n");
2204
2205 r = IXMLDOMNode_hasChildNodes( node, NULL );
2206 ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2207
2208 EXPECT_CHILDREN(node);
2209
2210 str = NULL;
2211 r = IXMLDOMNode_get_baseName( node, &str );
2212 ok( r == S_OK, "get_baseName returned wrong code\n");
2213 ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2214 SysFreeString(str);
2215 }
2216 else
2217 ok( FALSE, "no node\n");
2218
2219 if (node)
2220 IXMLDOMNode_Release( node );
2221 if (list)
2222 IXMLDOMNodeList_Release( list );
2223 if (element)
2224 IXMLDOMElement_Release( element );
2225
2226 b = FALSE;
2227 str = SysAllocString( szComplete5 );
2228 r = IXMLDOMDocument_loadXML( doc, str, &b );
2229 ok( r == S_OK, "loadXML failed\n");
2230 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2231 SysFreeString( str );
2232
2233 EXPECT_CHILDREN(doc);
2234
2235 r = IXMLDOMDocument_get_documentElement( doc, &element );
2236 ok( r == S_OK, "should be a document element\n");
2237 ok( element != NULL, "should be an element\n");
2238
2239 if (element)
2240 {
2241 static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2242 BSTR tag = NULL;
2243
2244 /* check if the tag is correct */
2245 r = IXMLDOMElement_get_tagName( element, &tag );
2246 ok( r == S_OK, "couldn't get tag name\n");
2247 ok( tag != NULL, "tag was null\n");
2248 ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2249 SysFreeString( tag );
2250 }
2251
2252 if (element)
2253 IXMLDOMElement_Release( element );
2254 ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2255
2256 free_bstrs();
2257 }
2258
2259 typedef struct {
2260 DOMNodeType type;
2261 REFIID iid;
2262 } refcount_test_t;
2263
2264 static const refcount_test_t refcount_test[] = {
2265 { NODE_ELEMENT, &IID_IXMLDOMElement },
2266 { NODE_ATTRIBUTE, &IID_IXMLDOMAttribute },
2267 { NODE_TEXT, &IID_IXMLDOMText },
2268 { NODE_CDATA_SECTION, &IID_IXMLDOMCDATASection },
2269 { NODE_ENTITY_REFERENCE, &IID_IXMLDOMEntityReference },
2270 { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2271 { NODE_COMMENT, &IID_IXMLDOMComment },
2272 { NODE_DOCUMENT_FRAGMENT, &IID_IXMLDOMDocumentFragment },
2273 { NODE_INVALID, &IID_NULL }
2274 };
2275
2276 static void test_refs(void)
2277 {
2278 IXMLDOMImplementation *impl, *impl2;
2279 IXMLDOMElement *element, *elem2;
2280 IXMLDOMNodeList *node_list = NULL;
2281 IXMLDOMNode *node, *node2, *node3;
2282 const refcount_test_t *ptr;
2283 IXMLDOMDocument *doc;
2284 IUnknown *unk, *unk2;
2285 VARIANT_BOOL b;
2286 HRESULT hr;
2287 LONG ref;
2288
2289 doc = create_document(&IID_IXMLDOMDocument);
2290
2291 ptr = refcount_test;
2292 while (ptr->type != NODE_INVALID)
2293 {
2294 IUnknown *node_typed, *node_typed2;
2295 IDispatchEx *dispex, *dispex2;
2296 IDispatch *disp, *disp2;
2297 VARIANT type;
2298
2299 V_VT(&type) = VT_I1;
2300 V_I1(&type) = ptr->type;
2301
2302 EXPECT_REF(doc, 1);
2303 hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2304 EXPECT_HR(hr, S_OK);
2305 EXPECT_REF(doc, 1);
2306 EXPECT_REF(node, 1);
2307
2308 /* try IDispatch and IUnknown from IXMLDOMNode */
2309 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2310 EXPECT_HR(hr, S_OK);
2311 EXPECT_REF(unk, 2);
2312 todo_wine {
2313 EXPECT_REF(node, 1);
2314 ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2315 }
2316 EXPECT_REF(unk, 2);
2317 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2318 EXPECT_HR(hr, S_OK);
2319 todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2320 EXPECT_REF(unk, 3);
2321 todo_wine EXPECT_REF(disp, 1);
2322
2323 EXPECT_REF(unk, 3);
2324 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2325 EXPECT_HR(hr, S_OK);
2326 todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2327 EXPECT_REF(unk, 4);
2328 todo_wine EXPECT_REF(disp2, 1);
2329
2330 IDispatch_Release(disp);
2331 IDispatch_Release(disp2);
2332
2333 /* get IXMLDOMNode from this IUnknown */
2334 EXPECT_REF(unk, 2);
2335 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2336 EXPECT_HR(hr, S_OK);
2337 todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2338 EXPECT_REF(unk, 3);
2339 todo_wine EXPECT_REF(node2, 1);
2340
2341 EXPECT_REF(unk, 3);
2342 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2343 EXPECT_HR(hr, S_OK);
2344 todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2345 EXPECT_REF(unk, 4);
2346 todo_wine EXPECT_REF(node3, 1);
2347
2348 IXMLDOMNode_Release(node2);
2349 IXMLDOMNode_Release(node3);
2350
2351 /* try IDispatchEx from IUnknown */
2352 EXPECT_REF(unk, 2);
2353 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2354 EXPECT_HR(hr, S_OK);
2355 ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2356 EXPECT_REF(unk, 3);
2357 todo_wine EXPECT_REF(dispex, 1);
2358
2359 EXPECT_REF(unk, 3);
2360 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2361 EXPECT_HR(hr, S_OK);
2362 todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2363 EXPECT_REF(unk, 4);
2364 todo_wine EXPECT_REF(dispex2, 1);
2365
2366 IDispatchEx_Release(dispex);
2367 IDispatchEx_Release(dispex2);
2368
2369 /* try corresponding IXMLDOM* */
2370 EXPECT_REF(unk, 2);
2371 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2372 EXPECT_HR(hr, S_OK);
2373 EXPECT_REF(unk, 3);
2374 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2375 EXPECT_HR(hr, S_OK);
2376 EXPECT_REF(unk, 4);
2377 todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2378 IUnknown_Release(node_typed);
2379 IUnknown_Release(node_typed2);
2380
2381 /* try invalid IXMLDOM* */
2382 hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2383 EXPECT_HR(hr, E_NOINTERFACE);
2384
2385 IUnknown_Release(unk);
2386
2387 EXPECT_REF(node, 1);
2388 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2389 EXPECT_HR(hr, S_OK);
2390 EXPECT_REF(node, 2);
2391 ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2392
2393 EXPECT_REF(node, 2);
2394 hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2395 EXPECT_HR(hr, S_OK);
2396 EXPECT_REF(node, 3);
2397 todo_wine {
2398 EXPECT_REF(node_typed, 2);
2399 ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2400 }
2401 IUnknown_Release(node_typed);
2402
2403 IXMLDOMNode_Release(node2);
2404 IXMLDOMNode_Release(node);
2405
2406 ptr++;
2407 }
2408
2409 EXPECT_REF(doc, 1);
2410 ref = IXMLDOMDocument_Release(doc);
2411 ok( ref == 0, "ref %d\n", ref);
2412
2413 /* check IUnknown after releasing DOM iface */
2414 doc = create_document(&IID_IXMLDOMDocument);
2415 EXPECT_REF(doc, 1);
2416 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2417 EXPECT_HR(hr, S_OK);
2418 todo_wine {
2419 EXPECT_REF(unk, 3);
2420 EXPECT_REF(doc, 1);
2421 }
2422 IXMLDOMDocument_Release(doc);
2423 EXPECT_REF(unk, 1);
2424 IUnknown_Release(unk);
2425
2426 doc = create_document(&IID_IXMLDOMDocument);
2427
2428 EXPECT_REF(doc, 1);
2429 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2430 EXPECT_HR(hr, S_OK);
2431 todo_wine {
2432 EXPECT_REF(unk, 3);
2433 EXPECT_REF(doc, 1);
2434 }
2435 IUnknown_Release(unk);
2436
2437 /* IXMLDOMImplementation */
2438 EXPECT_REF(doc, 1);
2439 hr = IXMLDOMDocument_get_implementation(doc, &impl);
2440 EXPECT_HR(hr, S_OK);
2441 EXPECT_REF(doc, 1);
2442 EXPECT_REF(impl, 1);
2443 hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2444 EXPECT_HR(hr, S_OK);
2445 EXPECT_REF(doc, 1);
2446 EXPECT_REF(impl2, 1);
2447 ok(impl != impl2, "got %p, %p\n", impl, impl2);
2448 IXMLDOMImplementation_Release(impl);
2449 IXMLDOMImplementation_Release(impl2);
2450
2451 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2452 EXPECT_HR(hr, S_OK);
2453 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2454
2455 EXPECT_REF(doc, 1);
2456 IXMLDOMDocument_AddRef( doc );
2457 EXPECT_REF(doc, 2);
2458 IXMLDOMDocument_AddRef( doc );
2459 EXPECT_REF(doc, 3);
2460
2461 IXMLDOMDocument_Release( doc );
2462 IXMLDOMDocument_Release( doc );
2463
2464 EXPECT_REF(doc, 1);
2465 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2466 EXPECT_HR(hr, S_OK);
2467 todo_wine {
2468 EXPECT_REF(unk, 3);
2469 EXPECT_REF(doc, 1);
2470 }
2471 hr = IXMLDOMDocument_get_documentElement(doc, &element);
2472 EXPECT_HR(hr, S_OK);
2473 todo_wine {
2474 EXPECT_REF(doc, 1);
2475 EXPECT_REF(element, 2);
2476 }
2477 hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2478 EXPECT_HR(hr, S_OK);
2479
2480 todo_wine {
2481 EXPECT_REF(doc, 1);
2482 EXPECT_REF(element, 2);
2483 EXPECT_REF(elem2, 2);
2484 }
2485 IXMLDOMElement_AddRef(element);
2486 todo_wine EXPECT_REF(element, 3);
2487 IXMLDOMElement_Release(element);
2488
2489 /* get IUnknown from a node doesn't touch node instance refcount */
2490 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2491 EXPECT_HR(hr, S_OK);
2492 EXPECT_REF(element, 2);
2493 todo_wine {
2494 EXPECT_REF(unk, 4);
2495 EXPECT_REF(elem2, 2);
2496 }
2497 hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2498 EXPECT_HR(hr, S_OK);
2499 todo_wine {
2500 EXPECT_REF(unk, 5);
2501 EXPECT_REF(unk2, 5);
2502 }
2503 EXPECT_REF(element, 2);
2504 EXPECT_REF(elem2, 2);
2505
2506 todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2507 IUnknown_Release(unk);
2508
2509 /* IUnknown refcount is not affected by node refcount */
2510 todo_wine EXPECT_REF(unk2, 4);
2511 IXMLDOMElement_AddRef(elem2);
2512 todo_wine EXPECT_REF(unk2, 4);
2513 IXMLDOMElement_Release(elem2);
2514
2515 IXMLDOMElement_Release(elem2);
2516 todo_wine EXPECT_REF(unk2, 3);
2517
2518 IUnknown_Release(unk2);
2519
2520 hr = IXMLDOMElement_get_childNodes( element, &node_list );
2521 EXPECT_HR(hr, S_OK);
2522
2523 todo_wine EXPECT_REF(element, 2);
2524 EXPECT_REF(node_list, 1);
2525
2526 hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2527 EXPECT_HR(hr, S_OK);
2528 EXPECT_REF(node_list, 1);
2529 EXPECT_REF(node, 1);
2530
2531 hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2532 EXPECT_HR(hr, S_OK);
2533 EXPECT_REF(node_list, 1);
2534 EXPECT_REF(node2, 1);
2535
2536 ref = IXMLDOMNode_Release( node );
2537 ok( ref == 0, "ref %d\n", ref );
2538 ref = IXMLDOMNode_Release( node2 );
2539 ok( ref == 0, "ref %d\n", ref );
2540
2541 ref = IXMLDOMNodeList_Release( node_list );
2542 ok( ref == 0, "ref %d\n", ref );
2543
2544 ok( node != node2, "node %p node2 %p\n", node, node2 );
2545
2546 ref = IXMLDOMDocument_Release( doc );
2547 todo_wine ok( ref == 0, "ref %d\n", ref );
2548
2549 todo_wine EXPECT_REF(element, 2);
2550
2551 /* IUnknown must be unique however we obtain it */
2552 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2553 EXPECT_HR(hr, S_OK);
2554 EXPECT_REF(element, 2);
2555 hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2556 EXPECT_HR(hr, S_OK);
2557 todo_wine EXPECT_REF(element, 2);
2558 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2559 EXPECT_HR(hr, S_OK);
2560 todo_wine EXPECT_REF(element, 2);
2561 ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2562 todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2563
2564 IUnknown_Release( unk2 );
2565 IUnknown_Release( unk );
2566 IXMLDOMNode_Release( node );
2567 todo_wine EXPECT_REF(element, 2);
2568
2569 IXMLDOMElement_Release( element );
2570
2571 free_bstrs();
2572 }
2573
2574 static void test_create(void)
2575 {
2576 static const WCHAR szOne[] = {'1',0};
2577 static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2578 HRESULT r;
2579 VARIANT var;
2580 BSTR str, name;
2581 IXMLDOMDocument *doc;
2582 IXMLDOMElement *element;
2583 IXMLDOMComment *comment;
2584 IXMLDOMText *text;
2585 IXMLDOMCDATASection *cdata;
2586 IXMLDOMNode *root, *node, *child;
2587 IXMLDOMNamedNodeMap *attr_map;
2588 IUnknown *unk;
2589 LONG ref;
2590 LONG num;
2591
2592 doc = create_document(&IID_IXMLDOMDocument);
2593
2594 EXPECT_REF(doc, 1);
2595
2596 /* types not supported for creation */
2597 V_VT(&var) = VT_I1;
2598 V_I1(&var) = NODE_DOCUMENT;
2599 node = (IXMLDOMNode*)0x1;
2600 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2601 ok( r == E_INVALIDARG, "returns %08x\n", r );
2602 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2603
2604 V_VT(&var) = VT_I1;
2605 V_I1(&var) = NODE_DOCUMENT_TYPE;
2606 node = (IXMLDOMNode*)0x1;
2607 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2608 ok( r == E_INVALIDARG, "returns %08x\n", r );
2609 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2610
2611 V_VT(&var) = VT_I1;
2612 V_I1(&var) = NODE_ENTITY;
2613 node = (IXMLDOMNode*)0x1;
2614 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2615 ok( r == E_INVALIDARG, "returns %08x\n", r );
2616 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2617
2618 V_VT(&var) = VT_I1;
2619 V_I1(&var) = NODE_NOTATION;
2620 node = (IXMLDOMNode*)0x1;
2621 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2622 ok( r == E_INVALIDARG, "returns %08x\n", r );
2623 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2624
2625 /* NODE_COMMENT */
2626 V_VT(&var) = VT_I1;
2627 V_I1(&var) = NODE_COMMENT;
2628 node = NULL;
2629 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2630 ok( r == S_OK, "returns %08x\n", r );
2631 ok( node != NULL, "\n");
2632
2633 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2634 ok( r == S_OK, "returns %08x\n", r );
2635 IXMLDOMNode_Release(node);
2636
2637 str = NULL;
2638 r = IXMLDOMComment_get_data(comment, &str);
2639 ok( r == S_OK, "returns %08x\n", r );
2640 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2641 IXMLDOMComment_Release(comment);
2642 SysFreeString(str);
2643
2644 node = (IXMLDOMNode*)0x1;
2645 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2646 ok( r == S_OK, "returns %08x\n", r );
2647
2648 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2649 ok( r == S_OK, "returns %08x\n", r );
2650 IXMLDOMNode_Release(node);
2651
2652 str = NULL;
2653 r = IXMLDOMComment_get_data(comment, &str);
2654 ok( r == S_OK, "returns %08x\n", r );
2655 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2656 IXMLDOMComment_Release(comment);
2657 SysFreeString(str);
2658
2659 node = (IXMLDOMNode*)0x1;
2660 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2661 ok( r == S_OK, "returns %08x\n", r );
2662
2663 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2664 ok( r == S_OK, "returns %08x\n", r );
2665 IXMLDOMNode_Release(node);
2666
2667 str = NULL;
2668 r = IXMLDOMComment_get_data(comment, &str);
2669 ok( r == S_OK, "returns %08x\n", r );
2670 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2671 IXMLDOMComment_Release(comment);
2672 SysFreeString(str);
2673
2674 /* NODE_TEXT */
2675 V_VT(&var) = VT_I1;
2676 V_I1(&var) = NODE_TEXT;
2677 node = NULL;
2678 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2679 ok( r == S_OK, "returns %08x\n", r );
2680 ok( node != NULL, "\n");
2681
2682 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2683 ok( r == S_OK, "returns %08x\n", r );
2684 IXMLDOMNode_Release(node);
2685
2686 str = NULL;
2687 r = IXMLDOMText_get_data(text, &str);
2688 ok( r == S_OK, "returns %08x\n", r );
2689 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2690 IXMLDOMText_Release(text);
2691 SysFreeString(str);
2692
2693 node = (IXMLDOMNode*)0x1;
2694 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2695 ok( r == S_OK, "returns %08x\n", r );
2696
2697 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2698 ok( r == S_OK, "returns %08x\n", r );
2699 IXMLDOMNode_Release(node);
2700
2701 str = NULL;
2702 r = IXMLDOMText_get_data(text, &str);
2703 ok( r == S_OK, "returns %08x\n", r );
2704 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2705 IXMLDOMText_Release(text);
2706 SysFreeString(str);
2707
2708 node = (IXMLDOMNode*)0x1;
2709 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2710 ok( r == S_OK, "returns %08x\n", r );
2711
2712 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
2713 ok( r == S_OK, "returns %08x\n", r );
2714 IXMLDOMNode_Release(node);
2715
2716 str = NULL;
2717 r = IXMLDOMText_get_data(text, &str);
2718 ok( r == S_OK, "returns %08x\n", r );
2719 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2720 IXMLDOMText_Release(text);