[ROSTESTS] Skip some flaky test / do not count successes
[reactos.git] / modules / 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 COBJMACROS
26 #define CONST_VTABLE
27
28 #include <stdio.h>
29 #include <assert.h>
30
31 #include "windows.h"
32
33 #include "msxml.h"
34 #include "msxml2.h"
35 #include "msxml2did.h"
36 #include "ole2.h"
37 #include "dispex.h"
38 #include "objsafe.h"
39 #include "mshtml.h"
40 #include "initguid.h"
41 #include "asptlb.h"
42
43 #include "wine/heap.h"
44 #include "wine/test.h"
45
46 /* undef the #define in msxml2 so that we can access all versions */
47 #undef CLSID_DOMDocument
48
49 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
50 DEFINE_GUID(IID_transformdest_unknown,0xf5078f3a,0xc551,0x11d3,0x89,0xb9,0x00,0x00,0xf8,0x1f,0xe2,0x21);
51
52 static int g_unexpectedcall, g_expectedcall;
53
54 struct msxmlsupported_data_t
55 {
56 const GUID *clsid;
57 const char *name;
58 const IID *ifaces[3];
59 BOOL supported[3];
60 };
61
62 static struct msxmlsupported_data_t domdoc_support_data[] =
63 {
64 { &CLSID_DOMDocument, "DOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
65 { &CLSID_DOMDocument2, "DOMDocument2", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
66 { &CLSID_DOMDocument30, "DOMDocument30", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
67 { &CLSID_DOMDocument40, "DOMDocument40", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
68 { &CLSID_DOMDocument60, "DOMDocument60", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3} },
69 { &CLSID_FreeThreadedDOMDocument, "FreeThreadedDOMDocument", {&IID_IXMLDOMDocument, &IID_IXMLDOMDocument2} },
70 { &CLSID_XMLSchemaCache, "XMLSchemaCache", {&IID_IXMLDOMSchemaCollection} },
71 { &CLSID_XSLTemplate, "XSLTemplate", {&IID_IXSLTemplate} },
72 { &CLSID_MXNamespaceManager40, "MXNamespaceManager40", {&IID_IMXNamespaceManager} },
73 { NULL }
74 };
75
76 static const char *debugstr_msxml_guid(REFIID riid)
77 {
78 if(!riid)
79 return "(null)";
80
81 if (IsEqualIID(&IID_IXMLDOMDocument, riid))
82 return "IXMLDOMDocument";
83 else if (IsEqualIID(&IID_IXMLDOMDocument2, riid))
84 return "IXMLDOMDocument2";
85 else if (IsEqualIID(&IID_IXMLDOMDocument3, riid))
86 return "IXMLDOMDocument3";
87 else if (IsEqualIID(&IID_IXMLDOMSchemaCollection, riid))
88 return "IXMLDOMSchemaCollection";
89 else if (IsEqualIID(&IID_IXSLTemplate, riid))
90 return "IXSLTemplate";
91 else if (IsEqualIID(&IID_IMXNamespaceManager, riid))
92 return "IMXNamespaceManager";
93 else
94 return wine_dbgstr_guid(riid);
95 }
96
97 static void get_class_support_data(struct msxmlsupported_data_t *table)
98 {
99 while (table->clsid)
100 {
101 IUnknown *unk;
102 HRESULT hr;
103 int i;
104
105 for (i = 0; i < ARRAY_SIZE(table->ifaces) && table->ifaces[i] != NULL; i++)
106 {
107 hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, table->ifaces[i], (void**)&unk);
108 if (hr == S_OK) IUnknown_Release(unk);
109
110 table->supported[i] = hr == S_OK;
111 if (hr != S_OK) win_skip("class %s, iface %s not supported\n", table->name, debugstr_msxml_guid(table->ifaces[i]));
112 }
113
114 table++;
115 }
116 }
117
118 static BOOL is_clsid_supported(const GUID *clsid, REFIID riid)
119 {
120 const struct msxmlsupported_data_t *table = domdoc_support_data;
121 while (table->clsid)
122 {
123 if (table->clsid == clsid)
124 {
125 int i;
126
127 for (i = 0; i < ARRAY_SIZE(table->ifaces) && table->ifaces[i] != NULL; i++)
128 if (table->ifaces[i] == riid) return table->supported[i];
129 }
130
131 table++;
132 }
133 return FALSE;
134 }
135
136 typedef struct
137 {
138 IDispatch IDispatch_iface;
139 LONG ref;
140 } dispevent;
141
142 static inline dispevent *impl_from_IDispatch( IDispatch *iface )
143 {
144 return CONTAINING_RECORD(iface, dispevent, IDispatch_iface);
145 }
146
147 static HRESULT WINAPI dispevent_QueryInterface(IDispatch *iface, REFIID riid, void **ppvObject)
148 {
149 *ppvObject = NULL;
150
151 if ( IsEqualGUID( riid, &IID_IDispatch) ||
152 IsEqualGUID( riid, &IID_IUnknown) )
153 {
154 *ppvObject = iface;
155 }
156 else
157 return E_NOINTERFACE;
158
159 IDispatch_AddRef( iface );
160
161 return S_OK;
162 }
163
164 static ULONG WINAPI dispevent_AddRef(IDispatch *iface)
165 {
166 dispevent *This = impl_from_IDispatch( iface );
167 return InterlockedIncrement( &This->ref );
168 }
169
170 static ULONG WINAPI dispevent_Release(IDispatch *iface)
171 {
172 dispevent *This = impl_from_IDispatch( iface );
173 ULONG ref = InterlockedDecrement( &This->ref );
174
175 if (ref == 0)
176 heap_free(This);
177
178 return ref;
179 }
180
181 static HRESULT WINAPI dispevent_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
182 {
183 g_unexpectedcall++;
184 *pctinfo = 0;
185 return S_OK;
186 }
187
188 static HRESULT WINAPI dispevent_GetTypeInfo(IDispatch *iface, UINT iTInfo,
189 LCID lcid, ITypeInfo **ppTInfo)
190 {
191 g_unexpectedcall++;
192 return S_OK;
193 }
194
195 static HRESULT WINAPI dispevent_GetIDsOfNames(IDispatch *iface, REFIID riid,
196 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
197 {
198 g_unexpectedcall++;
199 return S_OK;
200 }
201
202 static HRESULT WINAPI dispevent_Invoke(IDispatch *iface, DISPID member, REFIID riid,
203 LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result,
204 EXCEPINFO *excepInfo, UINT *argErr)
205 {
206 ok(member == 0, "expected 0 member, got %d\n", member);
207 ok(lcid == LOCALE_SYSTEM_DEFAULT, "expected LOCALE_SYSTEM_DEFAULT, got lcid %x\n", lcid);
208 ok(flags == DISPATCH_METHOD, "expected DISPATCH_METHOD, got %d\n", flags);
209
210 ok(params->cArgs == 0, "got %d\n", params->cArgs);
211 ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
212 ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
213 ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
214
215 ok(result == NULL, "got %p\n", result);
216 ok(excepInfo == NULL, "got %p\n", excepInfo);
217 ok(argErr == NULL, "got %p\n", argErr);
218
219 g_expectedcall++;
220 return E_FAIL;
221 }
222
223 static const IDispatchVtbl dispeventVtbl =
224 {
225 dispevent_QueryInterface,
226 dispevent_AddRef,
227 dispevent_Release,
228 dispevent_GetTypeInfoCount,
229 dispevent_GetTypeInfo,
230 dispevent_GetIDsOfNames,
231 dispevent_Invoke
232 };
233
234 static IDispatch* create_dispevent(void)
235 {
236 dispevent *event = heap_alloc(sizeof(*event));
237
238 event->IDispatch_iface.lpVtbl = &dispeventVtbl;
239 event->ref = 1;
240
241 return (IDispatch*)&event->IDispatch_iface;
242 }
243
244 /* IStream */
245 static HRESULT WINAPI istream_QueryInterface(IStream *iface, REFIID riid, void **ppvObject)
246 {
247 *ppvObject = NULL;
248
249 if (IsEqualGUID(riid, &IID_IStream) ||
250 IsEqualGUID(riid, &IID_IUnknown))
251 *ppvObject = iface;
252 else
253 return E_NOINTERFACE;
254
255 return S_OK;
256 }
257
258 static ULONG WINAPI istream_AddRef(IStream *iface)
259 {
260 return 2;
261 }
262
263 static ULONG WINAPI istream_Release(IStream *iface)
264 {
265 return 1;
266 }
267
268 static HRESULT WINAPI istream_Read(IStream *iface, void *ptr, ULONG len, ULONG *pread)
269 {
270 ok(0, "unexpected call\n");
271 return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI istream_Write(IStream *iface, const void *ptr, ULONG len, ULONG *written)
275 {
276 *written = len/2;
277 return S_OK;
278 }
279
280 static HRESULT WINAPI istream_Seek(IStream *iface, LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
281 {
282 ok(0, "unexpected call\n");
283 return E_NOTIMPL;
284 }
285
286 static HRESULT WINAPI istream_SetSize(IStream *iface, ULARGE_INTEGER size)
287 {
288 ok(0, "unexpected call\n");
289 return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI istream_CopyTo(IStream *iface, IStream *stream, ULARGE_INTEGER len,
293 ULARGE_INTEGER *pread, ULARGE_INTEGER *written)
294 {
295 ok(0, "unexpected call\n");
296 return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI istream_Commit(IStream *iface, DWORD flags)
300 {
301 ok(0, "unexpected call\n");
302 return E_NOTIMPL;
303 }
304
305 static HRESULT WINAPI istream_Revert(IStream *iface)
306 {
307 ok(0, "unexpected call\n");
308 return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI istream_LockRegion(IStream *iface, ULARGE_INTEGER offset,
312 ULARGE_INTEGER len, DWORD locktype)
313 {
314 ok(0, "unexpected call\n");
315 return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI istream_UnlockRegion(IStream *iface, ULARGE_INTEGER offset,
319 ULARGE_INTEGER len, DWORD locktype)
320 {
321 ok(0, "unexpected call\n");
322 return E_NOTIMPL;
323 }
324
325 static HRESULT WINAPI istream_Stat(IStream *iface, STATSTG *pstatstg, DWORD flag)
326 {
327 ok(0, "unexpected call\n");
328 return E_NOTIMPL;
329 }
330
331 static HRESULT WINAPI istream_Clone(IStream *iface, IStream **stream)
332 {
333 ok(0, "unexpected call\n");
334 return E_NOTIMPL;
335 }
336
337 static const IStreamVtbl StreamVtbl = {
338 istream_QueryInterface,
339 istream_AddRef,
340 istream_Release,
341 istream_Read,
342 istream_Write,
343 istream_Seek,
344 istream_SetSize,
345 istream_CopyTo,
346 istream_Commit,
347 istream_Revert,
348 istream_LockRegion,
349 istream_UnlockRegion,
350 istream_Stat,
351 istream_Clone
352 };
353
354 static IStream savestream = { &StreamVtbl };
355
356 static HRESULT WINAPI response_QI(IResponse *iface, REFIID riid, void **obj)
357 {
358 if (IsEqualIID(&IID_IResponse, riid) ||
359 IsEqualIID(&IID_IDispatch, riid) ||
360 IsEqualIID(&IID_IUnknown, riid))
361 {
362 *obj = iface;
363 return S_OK;
364 }
365
366 if (!IsEqualIID(&IID_IStream, riid) && !IsEqualIID(&IID_ISequentialStream, riid))
367 ok(0, "unexpected call\n");
368 return E_NOINTERFACE;
369 }
370
371 static ULONG WINAPI response_AddRef(IResponse *iface)
372 {
373 return 2;
374 }
375
376 static ULONG WINAPI response_Release(IResponse *iface)
377 {
378 return 1;
379 }
380
381 static HRESULT WINAPI response_GetTypeInfoCount(IResponse *iface, UINT *count)
382 {
383 ok(0, "unexpected call\n");
384 return E_NOTIMPL;
385 }
386
387 static HRESULT WINAPI response_GetTypeInfo(IResponse *iface, UINT ti, LCID lcid, ITypeInfo **tinfo)
388 {
389 ok(0, "unexpected call\n");
390 return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI response_GetIDsOfNames(IResponse *iface, REFIID riid, LPOLESTR *names,
394 UINT cnames, LCID lcid, DISPID *rgDispId)
395 {
396 ok(0, "unexpected call\n");
397 return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI response_Invoke(IResponse *iface, DISPID dispid, REFIID riid, LCID lcid,
401 WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *ei, UINT *argerr)
402 {
403 ok(0, "unexpected call\n");
404 return E_NOTIMPL;
405 }
406
407 static HRESULT WINAPI response_get_Buffer(IResponse *iface, VARIANT_BOOL *fIsBuffering)
408 {
409 ok(0, "unexpected call\n");
410 return E_NOTIMPL;
411 }
412
413 static HRESULT WINAPI response_put_Buffer(IResponse *iface, VARIANT_BOOL fIsBuffering)
414 {
415 ok(0, "unexpected call\n");
416 return E_NOTIMPL;
417 }
418
419 static HRESULT WINAPI response_get_ContentType(IResponse *iface, BSTR *pbstrContentTypeRet)
420 {
421 ok(0, "unexpected call\n");
422 return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI response_put_ContentType(IResponse *iface, BSTR bstrContentType)
426 {
427 ok(0, "unexpected call\n");
428 return E_NOTIMPL;
429 }
430
431 static HRESULT WINAPI response_get_Expires(IResponse *iface, VARIANT *pvarExpiresMinutesRet)
432 {
433 ok(0, "unexpected call\n");
434 return E_NOTIMPL;
435 }
436
437 static HRESULT WINAPI response_put_Expires(IResponse *iface, LONG lExpiresMinutes)
438 {
439 ok(0, "unexpected call\n");
440 return E_NOTIMPL;
441 }
442
443 static HRESULT WINAPI response_get_ExpiresAbsolute(IResponse *iface, VARIANT *pvarExpiresRet)
444 {
445 ok(0, "unexpected call\n");
446 return E_NOTIMPL;
447 }
448
449 static HRESULT WINAPI response_put_ExpiresAbsolute(IResponse *iface, DATE dtExpires)
450 {
451 ok(0, "unexpected call\n");
452 return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI response_get_Cookies(IResponse *iface, IRequestDictionary **ppCookies)
456 {
457 ok(0, "unexpected call\n");
458 return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI response_get_Status(IResponse *iface, BSTR *pbstrStatusRet)
462 {
463 ok(0, "unexpected call\n");
464 return E_NOTIMPL;
465 }
466
467 static HRESULT WINAPI response_put_Status(IResponse *iface, BSTR bstrStatus)
468 {
469 ok(0, "unexpected call\n");
470 return E_NOTIMPL;
471 }
472
473 static HRESULT WINAPI response_Add(IResponse *iface, BSTR bstrHeaderValue, BSTR bstrHeaderName)
474 {
475 ok(0, "unexpected call\n");
476 return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI response_AddHeader(IResponse *iface, BSTR bstrHeaderName, BSTR bstrHeaderValue)
480 {
481 ok(0, "unexpected call\n");
482 return E_NOTIMPL;
483 }
484
485 static HRESULT WINAPI response_AppendToLog(IResponse *iface, BSTR bstrLogEntry)
486 {
487 ok(0, "unexpected call\n");
488 return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI response_BinaryWrite(IResponse *iface, VARIANT input)
492 {
493 HRESULT hr;
494 LONG bound;
495 UINT dim;
496
497 ok(V_VT(&input) == (VT_ARRAY | VT_UI1), "got wrong input type %x\n", V_VT(&input));
498
499 dim = SafeArrayGetDim(V_ARRAY(&input));
500 ok(dim == 1, "got wrong array dimensions %u\n", dim);
501
502 bound = 1;
503 hr = SafeArrayGetLBound(V_ARRAY(&input), 1, &bound);
504 ok(hr == S_OK, "got %#x\n", hr);
505 ok(bound == 0, "wrong array low bound %d\n", bound);
506
507 bound = 0;
508 hr = SafeArrayGetUBound(V_ARRAY(&input), 1, &bound);
509 ok(hr == S_OK, "got %#x\n", hr);
510 ok(bound > 0, "wrong array high bound %d\n", bound);
511
512 return E_NOTIMPL;
513 }
514
515 static HRESULT WINAPI response_Clear(IResponse *iface)
516 {
517 ok(0, "unexpected call\n");
518 return E_NOTIMPL;
519 }
520
521 static HRESULT WINAPI response_End(IResponse *iface)
522 {
523 ok(0, "unexpected call\n");
524 return E_NOTIMPL;
525 }
526
527 static HRESULT WINAPI response_Flush(IResponse *iface)
528 {
529 ok(0, "unexpected call\n");
530 return E_NOTIMPL;
531 }
532
533 static HRESULT WINAPI response_Redirect(IResponse *iface, BSTR bstrURL)
534 {
535 ok(0, "unexpected call\n");
536 return E_NOTIMPL;
537 }
538
539 static HRESULT WINAPI response_Write(IResponse *iface, VARIANT varText)
540 {
541 ok(0, "unexpected call\n");
542 return E_NOTIMPL;
543 }
544
545 static HRESULT WINAPI response_WriteBlock(IResponse *iface, short iBlockNumber)
546 {
547 ok(0, "unexpected call\n");
548 return E_NOTIMPL;
549 }
550
551 static HRESULT WINAPI response_IsClientConnected(IResponse *iface, VARIANT_BOOL *pfIsClientConnected)
552 {
553 ok(0, "unexpected call\n");
554 return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI response_get_CharSet(IResponse *iface, BSTR *pbstrCharSetRet)
558 {
559 ok(0, "unexpected call\n");
560 return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI response_put_CharSet(IResponse *iface, BSTR bstrCharSet)
564 {
565 ok(0, "unexpected call\n");
566 return E_NOTIMPL;
567 }
568
569 static HRESULT WINAPI response_Pics(IResponse *iface, BSTR bstrHeaderValue)
570 {
571 ok(0, "unexpected call\n");
572 return E_NOTIMPL;
573 }
574
575 static HRESULT WINAPI response_get_CacheControl(IResponse *iface, BSTR *pbstrCacheControl)
576 {
577 ok(0, "unexpected call\n");
578 return E_NOTIMPL;
579 }
580
581 static HRESULT WINAPI response_put_CacheControl(IResponse *iface, BSTR bstrCacheControl)
582 {
583 ok(0, "unexpected call\n");
584 return E_NOTIMPL;
585 }
586
587 static HRESULT WINAPI response_get_CodePage(IResponse *iface, LONG *plvar)
588 {
589 ok(0, "unexpected call\n");
590 return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI response_put_CodePage(IResponse *iface, LONG codepage)
594 {
595 ok(0, "unexpected call\n");
596 return E_NOTIMPL;
597 }
598
599 static HRESULT WINAPI response_get_LCID(IResponse *iface, LONG *lcid)
600 {
601 ok(0, "unexpected call\n");
602 return E_NOTIMPL;
603 }
604
605 static HRESULT WINAPI response_put_LCID(IResponse *iface, LONG lcid)
606 {
607 ok(0, "unexpected call\n");
608 return E_NOTIMPL;
609 }
610
611 static const IResponseVtbl testresponsevtbl =
612 {
613 response_QI,
614 response_AddRef,
615 response_Release,
616 response_GetTypeInfoCount,
617 response_GetTypeInfo,
618 response_GetIDsOfNames,
619 response_Invoke,
620 response_get_Buffer,
621 response_put_Buffer,
622 response_get_ContentType,
623 response_put_ContentType,
624 response_get_Expires,
625 response_put_Expires,
626 response_get_ExpiresAbsolute,
627 response_put_ExpiresAbsolute,
628 response_get_Cookies,
629 response_get_Status,
630 response_put_Status,
631 response_Add,
632 response_AddHeader,
633 response_AppendToLog,
634 response_BinaryWrite,
635 response_Clear,
636 response_End,
637 response_Flush,
638 response_Redirect,
639 response_Write,
640 response_WriteBlock,
641 response_IsClientConnected,
642 response_get_CharSet,
643 response_put_CharSet,
644 response_Pics,
645 response_get_CacheControl,
646 response_put_CacheControl,
647 response_get_CodePage,
648 response_put_CodePage,
649 response_get_LCID,
650 response_put_LCID,
651 };
652
653 static IResponse testresponse = { &testresponsevtbl };
654
655 #define EXPECT_CHILDREN(node) _expect_children((IXMLDOMNode*)node, __LINE__)
656 static void _expect_children(IXMLDOMNode *node, int line)
657 {
658 VARIANT_BOOL b;
659 HRESULT hr;
660
661 b = VARIANT_FALSE;
662 hr = IXMLDOMNode_hasChildNodes(node, &b);
663 ok_(__FILE__,line)(hr == S_OK, "hasChildNodes() failed, 0x%08x\n", hr);
664 ok_(__FILE__,line)(b == VARIANT_TRUE, "no children, %d\n", b);
665 }
666
667 #define EXPECT_NO_CHILDREN(node) _expect_no_children((IXMLDOMNode*)node, __LINE__)
668 static void _expect_no_children(IXMLDOMNode *node, int line)
669 {
670 VARIANT_BOOL b;
671 HRESULT hr;
672
673 b = VARIANT_TRUE;
674 hr = IXMLDOMNode_hasChildNodes(node, &b);
675 ok_(__FILE__,line)(hr == S_FALSE, "hasChildNodes() failed, 0x%08x\n", hr);
676 ok_(__FILE__,line)(b == VARIANT_FALSE, "no children, %d\n", b);
677 }
678
679 #define EXPECT_REF(node,ref) _expect_ref((IUnknown*)node, ref, __LINE__)
680 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
681 {
682 ULONG rc;
683 IUnknown_AddRef(obj);
684 rc = IUnknown_Release(obj);
685 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
686 }
687
688 #define EXPECT_LIST_LEN(list,len) _expect_list_len(list, len, __LINE__)
689 static void _expect_list_len(IXMLDOMNodeList *list, LONG len, int line)
690 {
691 LONG length;
692 HRESULT hr;
693
694 length = 0;
695 hr = IXMLDOMNodeList_get_length(list, &length);
696 ok_(__FILE__,line)(hr == S_OK, "got 0x%08x\n", hr);
697 ok_(__FILE__,line)(length == len, "got %d, expected %d\n", length, len);
698 }
699
700 #define EXPECT_HR(hr,hr_exp) \
701 ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
702
703 #ifdef __REACTOS__
704 #define EXPECT_NOT_HR(hr,hr_exp) \
705 ok(hr != hr_exp, "got 0x%08x, expected not 0x%08x\n", hr, hr_exp)
706 #endif
707
708 static const WCHAR szEmpty[] = { 0 };
709 static const WCHAR szIncomplete[] = {
710 '<','?','x','m','l',' ',
711 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',0
712 };
713 static const WCHAR szComplete1[] = {
714 '<','?','x','m','l',' ',
715 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
716 '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
717 };
718 static const WCHAR szComplete2[] = {
719 '<','?','x','m','l',' ',
720 'v','e','r','s','i','o','n','=','\'','1','.','0','\'','?','>','\n',
721 '<','a','>','<','/','a','>','\n',0
722 };
723 static const char complete4A[] =
724 "<?xml version=\'1.0\'?>\n"
725 "<lc dl=\'str1\'>\n"
726 "<bs vr=\'str2\' sz=\'1234\'>"
727 "fn1.txt\n"
728 "</bs>\n"
729 "<pr id=\'str3\' vr=\'1.2.3\' pn=\'wine 20050804\'>\n"
730 "fn2.txt\n"
731 "</pr>\n"
732 "<empty></empty>\n"
733 "<fo>\n"
734 "<ba>\n"
735 "f1\n"
736 "</ba>\n"
737 "</fo>\n"
738 "</lc>\n";
739
740 static const WCHAR szComplete5[] = {
741 '<','S',':','s','e','a','r','c','h',' ','x','m','l','n','s',':','D','=','"','D','A','V',':','"',' ',
742 'x','m','l','n','s',':','C','=','"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','o','f','f','i','c','e',':','c','l','i','p','g','a','l','l','e','r','y','"',
743 ' ','x','m','l','n','s',':','S','=','"','u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','o','f','f','i','c','e',':','c','l','i','p','g','a','l','l','e','r','y',':','s','e','a','r','c','h','"','>',
744 '<','S',':','s','c','o','p','e','>',
745 '<','S',':','d','e','e','p','>','/','<','/','S',':','d','e','e','p','>',
746 '<','/','S',':','s','c','o','p','e','>',
747 '<','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
748 '<','C',':','t','e','x','t','o','r','p','r','o','p','e','r','t','y','/','>',
749 'c','o','m','p','u','t','e','r',
750 '<','/','S',':','c','o','n','t','e','n','t','f','r','e','e','t','e','x','t','>',
751 '<','/','S',':','s','e','a','r','c','h','>',0
752 };
753
754 static const WCHAR szComplete6[] = {
755 '<','?','x','m','l',' ','v','e','r','s','i','o','n','=','\'','1','.','0','\'',' ',
756 'e','n','c','o','d','i','n','g','=','\'','W','i','n','d','o','w','s','-','1','2','5','2','\'','?','>','\n',
757 '<','o','p','e','n','>','<','/','o','p','e','n','>','\n',0
758 };
759
760 static const char complete7[] = {
761 "<?xml version=\"1.0\"?>\n\t"
762 "<root>\n"
763 "\t<a/>\n"
764 "\t<b/>\n"
765 "\t<c/>\n"
766 "</root>"
767 };
768
769 #define DECL_WIN_1252 \
770 "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
771
772 static const char win1252xml[] =
773 DECL_WIN_1252
774 "<open></open>";
775
776 static const char win1252decl[] =
777 DECL_WIN_1252
778 ;
779
780 static const char nocontent[] = "no xml content here";
781
782 static const char szExampleXML[] =
783 "<?xml version='1.0' encoding='utf-8'?>\n"
784 "<root xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' a=\"attr a\" foo:b=\"attr b\" >\n"
785 " <elem>\n"
786 " <a>A1 field</a>\n"
787 " <b>B1 field</b>\n"
788 " <c>C1 field</c>\n"
789 " <d>D1 field</d>\n"
790 " <description xmlns:foo='http://www.winehq.org' xmlns:bar='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
791 " <html xmlns='http://www.w3.org/1999/xhtml'>\n"
792 " <![CDATA[]]> This is<strong> a</strong> <i>description</i><dot>. </dot><bar:x/>\n"
793 " </html>\n"
794 " <html xml:space='preserve' xmlns='http://www.w3.org/1999/xhtml'>\n"
795 " This is <strong>a</strong> <i>description</i> with preserved whitespace. <bar:x/>\n"
796 " </html>\n"
797 " </description>\n"
798 " </elem>\n"
799 "\n"
800 " <elem a='a'>\n"
801 " <a>A2 field</a>\n"
802 " <b>B2 field</b>\n"
803 " <c type=\"old\">C2 field</c>\n"
804 " <d>D2 field</d>\n"
805 " </elem>\n"
806 "\n"
807 " <elem xmlns='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'>\n"
808 " <a>A3 field</a>\n"
809 " <b>B3 field</b>\n"
810 " <c>C3 field</c>\n"
811 " </elem>\n"
812 "\n"
813 " <elem>\n"
814 " <a>A4 field</a>\n"
815 " <b>B4 field</b>\n"
816 " <foo:c>C4 field</foo:c>\n"
817 " <d>D4 field</d>\n"
818 " </elem>\n"
819 "</root>\n";
820
821 static const char charrefsxml[] =
822 "<?xml version='1.0'?>"
823 "<a>"
824 "<b1> Text &#65; end </b1>"
825 "<b2>&#65;&#66; &#67; </b2>"
826 "</a>";
827
828 static const CHAR szNodeTypesXML[] =
829 "<?xml version='1.0'?>"
830 "<!-- comment node 0 -->"
831 "<root id='0' depth='0'>"
832 " <!-- comment node 1 -->"
833 " text node 0"
834 " <x id='1' depth='1'>"
835 " <?foo value='PI for x'?>"
836 " <!-- comment node 2 -->"
837 " text node 1"
838 " <a id='3' depth='2'/>"
839 " <b id='4' depth='2'/>"
840 " <c id='5' depth='2'/>"
841 " </x>"
842 " <y id='2' depth='1'>"
843 " <?bar value='PI for y'?>"
844 " <!-- comment node 3 -->"
845 " text node 2"
846 " <a id='6' depth='2'/>"
847 " <b id='7' depth='2'/>"
848 " <c id='8' depth='2'/>"
849 " </y>"
850 "</root>";
851
852 static const CHAR szTransformXML[] =
853 "<?xml version=\"1.0\"?>\n"
854 "<greeting>\n"
855 "Hello World\n"
856 "</greeting>";
857
858 static const CHAR szTransformSSXML[] =
859 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
860 " <xsl:output method=\"html\"/>\n"
861 " <xsl:template match=\"/\">\n"
862 " <xsl:apply-templates select=\"greeting\"/>\n"
863 " </xsl:template>\n"
864 " <xsl:template match=\"greeting\">\n"
865 " <html>\n"
866 " <body>\n"
867 " <h1>\n"
868 " <xsl:value-of select=\".\"/>\n"
869 " </h1>\n"
870 " </body>\n"
871 " </html>\n"
872 " </xsl:template>\n"
873 "</xsl:stylesheet>";
874
875 static const CHAR szTransformOutput[] =
876 "<html><body><h1>"
877 "Hello World"
878 "</h1></body></html>";
879
880 static const CHAR szTypeValueXML[] =
881 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
882 "<root xmlns:dt=\"urn:schemas-microsoft-com:datatypes\">\n"
883 " <string>Wine</string>\n"
884 " <string2 dt:dt=\"string\">String</string2>\n"
885 " <number dt:dt=\"number\">12.44</number>\n"
886 " <number2 dt:dt=\"NUMbEr\">-3.71e3</number2>\n"
887 " <int dt:dt=\"int\">-13</int>\n"
888 " <fixed dt:dt=\"fixed.14.4\">7322.9371</fixed>\n"
889 " <bool dt:dt=\"boolean\">1</bool>\n"
890 " <datetime dt:dt=\"datetime\">2009-11-18T03:21:33.12</datetime>\n"
891 " <datetimetz dt:dt=\"datetime.tz\">2003-07-11T11:13:57+03:00</datetimetz>\n"
892 " <date dt:dt=\"date\">3721-11-01</date>\n"
893 " <time dt:dt=\"time\">13:57:12.31321</time>\n"
894 " <timetz dt:dt=\"time.tz\">23:21:01.13+03:21</timetz>\n"
895 " <i1 dt:dt=\"i1\">-13</i1>\n"
896 " <i2 dt:dt=\"i2\">31915</i2>\n"
897 " <i4 dt:dt=\"i4\">-312232</i4>\n"
898 " <ui1 dt:dt=\"ui1\">123</ui1>\n"
899 " <ui2 dt:dt=\"ui2\">48282</ui2>\n"
900 " <ui4 dt:dt=\"ui4\">949281</ui4>\n"
901 " <r4 dt:dt=\"r4\">213124.0</r4>\n"
902 " <r8 dt:dt=\"r8\">0.412</r8>\n"
903 " <float dt:dt=\"float\">41221.421</float>\n"
904 " <uuid dt:dt=\"uuid\">333C7BC4-460F-11D0-BC04-0080C7055a83</uuid>\n"
905 " <binhex dt:dt=\"bin.hex\">fffca012003c</binhex>\n"
906 " <binbase64 dt:dt=\"bin.base64\">YmFzZTY0IHRlc3Q=</binbase64>\n"
907 " <binbase64_1 dt:dt=\"bin.base64\">\nYmFzZTY0\nIHRlc3Q=\n</binbase64_1>\n"
908 " <binbase64_2 dt:dt=\"bin.base64\">\nYmF\r\t z ZTY0\nIHRlc3Q=\n</binbase64_2>\n"
909 "</root>";
910
911 static const CHAR szBasicTransformSSXMLPart1[] =
912 "<?xml version=\"1.0\"?>"
913 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
914 "<xsl:output method=\"html\"/>\n"
915 "<xsl:template match=\"/\">"
916 "<HTML><BODY><TABLE>"
917 " <xsl:apply-templates select='document(\"";
918
919 static const CHAR szBasicTransformSSXMLPart2[] =
920 "\")/bottle/wine'>"
921 " <xsl:sort select=\"cost\"/><xsl:sort select=\"name\"/>"
922 " </xsl:apply-templates>"
923 "</TABLE></BODY></HTML>"
924 "</xsl:template>"
925 "<xsl:template match=\"bottle\">"
926 " <TR><xsl:apply-templates select=\"name\" /><xsl:apply-templates select=\"cost\" /></TR>"
927 "</xsl:template>"
928 "<xsl:template match=\"name\">"
929 " <TD><xsl:apply-templates /></TD>"
930 "</xsl:template>"
931 "<xsl:template match=\"cost\">"
932 " <TD><xsl:apply-templates /></TD>"
933 "</xsl:template>"
934 "</xsl:stylesheet>";
935
936 static const CHAR szBasicTransformXML[] =
937 "<?xml version=\"1.0\"?><bottle><wine><name>Wine</name><cost>$25.00</cost></wine></bottle>";
938
939 static const CHAR szBasicTransformOutput[] =
940 "<HTML><BODY><TABLE><TD>Wine</TD><TD>$25.00</TD></TABLE></BODY></HTML>";
941
942 #define SZ_EMAIL_DTD \
943 "<!DOCTYPE email ["\
944 " <!ELEMENT email (recipients,from,reply-to?,subject,body,attachment*)>"\
945 " <!ATTLIST email attachments IDREFS #REQUIRED>"\
946 " <!ATTLIST email sent (yes|no) \"no\">"\
947 " <!ELEMENT recipients (to+,cc*)>"\
948 " <!ELEMENT to (#PCDATA)>"\
949 " <!ATTLIST to name CDATA #IMPLIED>"\
950 " <!ELEMENT cc (#PCDATA)>"\
951 " <!ATTLIST cc name CDATA #IMPLIED>"\
952 " <!ELEMENT from (#PCDATA)>"\
953 " <!ATTLIST from name CDATA #IMPLIED>"\
954 " <!ELEMENT reply-to (#PCDATA)>"\
955 " <!ATTLIST reply-to name CDATA #IMPLIED>"\
956 " <!ELEMENT subject ANY>"\
957 " <!ELEMENT body ANY>"\
958 " <!ATTLIST body enc CDATA #FIXED \"UTF-8\">"\
959 " <!ELEMENT attachment (#PCDATA)>"\
960 " <!ATTLIST attachment id ID #REQUIRED>"\
961 "]>"
962
963 static const CHAR szEmailXML[] =
964 "<?xml version=\"1.0\"?>"
965 SZ_EMAIL_DTD
966 "<email attachments=\"patch1\">"
967 " <recipients>"
968 " <to>wine-patches@winehq.org</to>"
969 " </recipients>"
970 " <from name=\"Anonymous\">user@localhost</from>"
971 " <subject>msxml3/tests: DTD validation (try 87)</subject>"
972 " <body>"
973 " It no longer causes spontaneous combustion..."
974 " </body>"
975 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
976 "</email>";
977
978 static const CHAR szEmailXML_0D[] =
979 "<?xml version=\"1.0\"?>"
980 SZ_EMAIL_DTD
981 "<email attachments=\"patch1\">"
982 " <recipients>"
983 " <to>wine-patches@winehq.org</to>"
984 " </recipients>"
985 " <from name=\"Anonymous\">user@localhost</from>"
986 " <subject>msxml3/tests: DTD validation (try 88)</subject>"
987 " <body>"
988 " <undecl />"
989 " XML_ELEMENT_UNDECLARED 0xC00CE00D"
990 " </body>"
991 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
992 "</email>";
993
994 static const CHAR szEmailXML_0E[] =
995 "<?xml version=\"1.0\"?>"
996 SZ_EMAIL_DTD
997 "<email attachments=\"patch1\">"
998 " <recipients>"
999 " <to>wine-patches@winehq.org</to>"
1000 " </recipients>"
1001 " <from name=\"Anonymous\">user@localhost</from>"
1002 " <subject>msxml3/tests: DTD validation (try 89)</subject>"
1003 " <body>"
1004 " XML_ELEMENT_ID_NOT_FOUND 0xC00CE00E"
1005 " </body>"
1006 " <attachment id=\"patch\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1007 "</email>";
1008
1009 static const CHAR szEmailXML_11[] =
1010 "<?xml version=\"1.0\"?>"
1011 SZ_EMAIL_DTD
1012 "<email attachments=\"patch1\">"
1013 " <recipients>"
1014 " </recipients>"
1015 " <from name=\"Anonymous\">user@localhost</from>"
1016 " <subject>msxml3/tests: DTD validation (try 90)</subject>"
1017 " <body>"
1018 " XML_EMPTY_NOT_ALLOWED 0xC00CE011"
1019 " </body>"
1020 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1021 "</email>";
1022
1023 static const CHAR szEmailXML_13[] =
1024 "<?xml version=\"1.0\"?>"
1025 SZ_EMAIL_DTD
1026 "<msg attachments=\"patch1\">"
1027 " <recipients>"
1028 " <to>wine-patches@winehq.org</to>"
1029 " </recipients>"
1030 " <from name=\"Anonymous\">user@localhost</from>"
1031 " <subject>msxml3/tests: DTD validation (try 91)</subject>"
1032 " <body>"
1033 " XML_ROOT_NAME_MISMATCH 0xC00CE013"
1034 " </body>"
1035 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1036 "</msg>";
1037
1038 static const CHAR szEmailXML_14[] =
1039 "<?xml version=\"1.0\"?>"
1040 SZ_EMAIL_DTD
1041 "<email attachments=\"patch1\">"
1042 " <to>wine-patches@winehq.org</to>"
1043 " <from name=\"Anonymous\">user@localhost</from>"
1044 " <subject>msxml3/tests: DTD validation (try 92)</subject>"
1045 " <body>"
1046 " XML_INVALID_CONTENT 0xC00CE014"
1047 " </body>"
1048 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1049 "</email>";
1050
1051 static const CHAR szEmailXML_15[] =
1052 "<?xml version=\"1.0\"?>"
1053 SZ_EMAIL_DTD
1054 "<email attachments=\"patch1\" ip=\"127.0.0.1\">"
1055 " <recipients>"
1056 " <to>wine-patches@winehq.org</to>"
1057 " </recipients>"
1058 " <from name=\"Anonymous\">user@localhost</from>"
1059 " <subject>msxml3/tests: DTD validation (try 93)</subject>"
1060 " <body>"
1061 " XML_ATTRIBUTE_NOT_DEFINED 0xC00CE015"
1062 " </body>"
1063 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1064 "</email>";
1065
1066 static const CHAR szEmailXML_16[] =
1067 "<?xml version=\"1.0\"?>"
1068 SZ_EMAIL_DTD
1069 "<email attachments=\"patch1\">"
1070 " <recipients>"
1071 " <to>wine-patches@winehq.org</to>"
1072 " </recipients>"
1073 " <from name=\"Anonymous\">user@localhost</from>"
1074 " <subject>msxml3/tests: DTD validation (try 94)</subject>"
1075 " <body enc=\"ASCII\">"
1076 " XML_ATTRIBUTE_FIXED 0xC00CE016"
1077 " </body>"
1078 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1079 "</email>";
1080
1081 static const CHAR szEmailXML_17[] =
1082 "<?xml version=\"1.0\"?>"
1083 SZ_EMAIL_DTD
1084 "<email attachments=\"patch1\" sent=\"true\">"
1085 " <recipients>"
1086 " <to>wine-patches@winehq.org</to>"
1087 " </recipients>"
1088 " <from name=\"Anonymous\">user@localhost</from>"
1089 " <subject>msxml3/tests: DTD validation (try 95)</subject>"
1090 " <body>"
1091 " XML_ATTRIBUTE_VALUE 0xC00CE017"
1092 " </body>"
1093 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1094 "</email>";
1095
1096 static const CHAR szEmailXML_18[] =
1097 "<?xml version=\"1.0\"?>"
1098 SZ_EMAIL_DTD
1099 "<email attachments=\"patch1\">"
1100 " oops"
1101 " <recipients>"
1102 " <to>wine-patches@winehq.org</to>"
1103 " </recipients>"
1104 " <from name=\"Anonymous\">user@localhost</from>"
1105 " <subject>msxml3/tests: DTD validation (try 96)</subject>"
1106 " <body>"
1107 " XML_ILLEGAL_TEXT 0xC00CE018"
1108 " </body>"
1109 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1110 "</email>";
1111
1112 static const CHAR szEmailXML_20[] =
1113 "<?xml version=\"1.0\"?>"
1114 SZ_EMAIL_DTD
1115 "<email>"
1116 " <recipients>"
1117 " <to>wine-patches@winehq.org</to>"
1118 " </recipients>"
1119 " <from name=\"Anonymous\">user@localhost</from>"
1120 " <subject>msxml3/tests: DTD validation (try 97)</subject>"
1121 " <body>"
1122 " XML_REQUIRED_ATTRIBUTE_MISSING 0xC00CE020"
1123 " </body>"
1124 " <attachment id=\"patch1\">0001-msxml3-tests-DTD-validation.patch</attachment>"
1125 "</email>";
1126
1127 static const char xpath_simple_list[] =
1128 "<?xml version=\"1.0\"?>"
1129 "<root>"
1130 " <a attr1=\"1\" attr2=\"2\" />"
1131 " <b/>"
1132 " <c/>"
1133 " <d/>"
1134 "</root>";
1135
1136 static const char default_ns_doc[] = {
1137 "<?xml version=\"1.0\"?>"
1138 "<a xmlns:ns=\"nshref\" xml:lang=\"ru\" ns:b=\"b attr\" xml:c=\"c attr\" "
1139 " d=\"d attr\" />"
1140 };
1141
1142 static const char attributes_map[] = {
1143 "<?xml version=\"1.0\"?>"
1144 "<a attr1=\"value1\" attr2=\"value2\" attr3=\"value3\" attr4=\"value4\" />"
1145 };
1146
1147 static const WCHAR nonexistent_fileW[] = {
1148 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0
1149 };
1150 static const WCHAR nonexistent_attrW[] = {
1151 'n','o','n','E','x','i','s','i','t','i','n','g','A','t','t','r','i','b','u','t','e',0
1152 };
1153 static const WCHAR szDocument[] = {
1154 '#', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't', 0
1155 };
1156
1157 static const WCHAR szOpen[] = { 'o','p','e','n',0 };
1158 static const WCHAR szdl[] = { 'd','l',0 };
1159 static const WCHAR szvr[] = { 'v','r',0 };
1160 static const WCHAR szlc[] = { 'l','c',0 };
1161 static const WCHAR szbs[] = { 'b','s',0 };
1162 static const WCHAR szstr1[] = { 's','t','r','1',0 };
1163 static const WCHAR szstr2[] = { 's','t','r','2',0 };
1164 static const WCHAR szstar[] = { '*',0 };
1165 static const WCHAR szfn1_txt[] = {'f','n','1','.','t','x','t',0};
1166
1167 static const WCHAR szComment[] = {'A',' ','C','o','m','m','e','n','t',0 };
1168 static const WCHAR szCommentXML[] = {'<','!','-','-','A',' ','C','o','m','m','e','n','t','-','-','>',0 };
1169 static const WCHAR szCommentNodeText[] = {'#','c','o','m','m','e','n','t',0 };
1170
1171 static WCHAR szElement[] = {'E','l','e','T','e','s','t', 0 };
1172 static const WCHAR szElementXML[] = {'<','E','l','e','T','e','s','t','/','>',0 };
1173 static const WCHAR szElementXML2[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','/','>',0 };
1174 static const WCHAR szElementXML3[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1175 'T','e','s','t','i','n','g','N','o','d','e','<','/','E','l','e','T','e','s','t','>',0 };
1176 static const WCHAR szElementXML4[] = {'<','E','l','e','T','e','s','t',' ','A','t','t','r','=','"','"','>',
1177 '&','a','m','p',';','x',' ',0x2103,'<','/','E','l','e','T','e','s','t','>',0 };
1178
1179 static const WCHAR szAttribute[] = {'A','t','t','r',0 };
1180 static const WCHAR szAttributeXML[] = {'A','t','t','r','=','"','"',0 };
1181
1182 static const WCHAR szCData[] = {'[','1',']','*','2','=','3',';',' ','&','g','e','e',' ','t','h','a','t','s',
1183 ' ','n','o','t',' ','r','i','g','h','t','!', 0};
1184 static const WCHAR szCDataXML[] = {'<','!','[','C','D','A','T','A','[','[','1',']','*','2','=','3',';',' ','&',
1185 'g','e','e',' ','t','h','a','t','s',' ','n','o','t',' ','r','i','g','h','t',
1186 '!',']',']','>',0};
1187 static const WCHAR szCDataNodeText[] = {'#','c','d','a','t','a','-','s','e','c','t','i','o','n',0 };
1188 static const WCHAR szDocFragmentText[] = {'#','d','o','c','u','m','e','n','t','-','f','r','a','g','m','e','n','t',0 };
1189
1190 static const WCHAR szEntityRef[] = {'e','n','t','i','t','y','r','e','f',0 };
1191 static const WCHAR szEntityRefXML[] = {'&','e','n','t','i','t','y','r','e','f',';',0 };
1192 static const WCHAR szStrangeChars[] = {'&','x',' ',0x2103, 0};
1193
1194 #define expect_bstr_eq_and_free(bstr, expect) { \
1195 BSTR bstrExp = alloc_str_from_narrow(expect); \
1196 ok(lstrcmpW(bstr, bstrExp) == 0, "String differs\n"); \
1197 SysFreeString(bstr); \
1198 SysFreeString(bstrExp); \
1199 }
1200
1201 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
1202
1203 #define ole_check(expr) { \
1204 HRESULT r = expr; \
1205 ok(r == S_OK, #expr " returned %x\n", r); \
1206 }
1207
1208 #define ole_expect(expr, expect) { \
1209 HRESULT r = expr; \
1210 ok(r == (expect), #expr " returned %x, expected %x\n", r, expect); \
1211 }
1212
1213 #define double_eq(x, y) ok((x)-(y)<=1e-14*(x) && (x)-(y)>=-1e-14*(x), "expected %.16g, got %.16g\n", x, y)
1214
1215 static void* _create_object(const GUID *clsid, const char *name, const IID *iid, int line)
1216 {
1217 void *obj = NULL;
1218 HRESULT hr;
1219
1220 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, &obj);
1221 ok(hr == S_OK, "failed to create %s instance: 0x%08x\n", name, hr);
1222
1223 return obj;
1224 }
1225
1226 #define _create(cls) cls, #cls
1227
1228 #define create_document(iid) _create_object(&_create(CLSID_DOMDocument2), iid, __LINE__)
1229 #define create_document_version(v, iid) _create_object(&_create(CLSID_DOMDocument ## v), iid, __LINE__)
1230 #define create_cache(iid) _create_object(&_create(CLSID_XMLSchemaCache), iid, __LINE__)
1231 #define create_xsltemplate(iid) _create_object(&_create(CLSID_XSLTemplate), iid, __LINE__)
1232
1233 static BSTR alloc_str_from_narrow(const char *str)
1234 {
1235 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1236 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */
1237 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
1238 return ret;
1239 }
1240
1241 static BSTR alloced_bstrs[256];
1242 static int alloced_bstrs_count;
1243
1244 static BSTR _bstr_(const char *str)
1245 {
1246 assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs));
1247 alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str);
1248 return alloced_bstrs[alloced_bstrs_count++];
1249 }
1250
1251 static void free_bstrs(void)
1252 {
1253 int i;
1254 for (i = 0; i < alloced_bstrs_count; i++)
1255 SysFreeString(alloced_bstrs[i]);
1256 alloced_bstrs_count = 0;
1257 }
1258
1259 static VARIANT _variantbstr_(const char *str)
1260 {
1261 VARIANT v;
1262 V_VT(&v) = VT_BSTR;
1263 V_BSTR(&v) = _bstr_(str);
1264 return v;
1265 }
1266
1267 static BOOL compareIgnoreReturns(BSTR sLeft, BSTR sRight)
1268 {
1269 for (;;)
1270 {
1271 while (*sLeft == '\r' || *sLeft == '\n') sLeft++;
1272 while (*sRight == '\r' || *sRight == '\n') sRight++;
1273 if (*sLeft != *sRight) return FALSE;
1274 if (!*sLeft) return TRUE;
1275 sLeft++;
1276 sRight++;
1277 }
1278 }
1279
1280 static void get_str_for_type(DOMNodeType type, char *buf)
1281 {
1282 switch (type)
1283 {
1284 case NODE_ATTRIBUTE:
1285 strcpy(buf, "A");
1286 break;
1287 case NODE_ELEMENT:
1288 strcpy(buf, "E");
1289 break;
1290 case NODE_DOCUMENT:
1291 strcpy(buf, "D");
1292 break;
1293 case NODE_TEXT:
1294 strcpy(buf, "T");
1295 break;
1296 case NODE_COMMENT:
1297 strcpy(buf, "C");
1298 break;
1299 case NODE_PROCESSING_INSTRUCTION:
1300 strcpy(buf, "P");
1301 break;
1302 default:
1303 wsprintfA(buf, "[%d]", type);
1304 }
1305 }
1306
1307 static int get_node_position(IXMLDOMNode *node)
1308 {
1309 HRESULT r;
1310 int pos = 0;
1311
1312 IXMLDOMNode_AddRef(node);
1313 do
1314 {
1315 IXMLDOMNode *new_node;
1316
1317 pos++;
1318 r = IXMLDOMNode_get_previousSibling(node, &new_node);
1319 ok(SUCCEEDED(r), "get_previousSibling failed\n");
1320 IXMLDOMNode_Release(node);
1321 node = new_node;
1322 } while (r == S_OK);
1323 return pos;
1324 }
1325
1326 static void node_to_string(IXMLDOMNode *node, char *buf)
1327 {
1328 HRESULT r = S_OK;
1329 DOMNodeType type;
1330
1331 if (node == NULL)
1332 {
1333 lstrcpyA(buf, "(null)");
1334 return;
1335 }
1336
1337 IXMLDOMNode_AddRef(node);
1338 while (r == S_OK)
1339 {
1340 IXMLDOMNode *new_node;
1341
1342 ole_check(IXMLDOMNode_get_nodeType(node, &type));
1343 get_str_for_type(type, buf);
1344 buf+=strlen(buf);
1345
1346 if (type == NODE_ATTRIBUTE)
1347 {
1348 BSTR bstr;
1349 ole_check(IXMLDOMNode_get_nodeName(node, &bstr));
1350 *(buf++) = '\'';
1351 wsprintfA(buf, "%ws", bstr);
1352 buf += strlen(buf);
1353 *(buf++) = '\'';
1354 SysFreeString(bstr);
1355
1356 r = IXMLDOMNode_selectSingleNode(node, _bstr_(".."), &new_node);
1357 }
1358 else
1359 {
1360 r = IXMLDOMNode_get_parentNode(node, &new_node);
1361 sprintf(buf, "%d", get_node_position(node));
1362 buf += strlen(buf);
1363 }
1364
1365 ok(SUCCEEDED(r), "get_parentNode failed (%08x)\n", r);
1366 IXMLDOMNode_Release(node);
1367 node = new_node;
1368 if (r == S_OK)
1369 *(buf++) = '.';
1370 }
1371
1372 *buf = 0;
1373 }
1374
1375 static char *list_to_string(IXMLDOMNodeList *list)
1376 {
1377 static char buf[4096];
1378 char *pos = buf;
1379 LONG len = 0;
1380 HRESULT hr;
1381 int i;
1382
1383 if (list == NULL)
1384 {
1385 strcpy(buf, "(null)");
1386 return buf;
1387 }
1388 hr = IXMLDOMNodeList_get_length(list, &len);
1389 ok(hr == S_OK, "got 0x%08x\n", hr);
1390 for (i = 0; i < len; i++)
1391 {
1392 IXMLDOMNode *node;
1393 if (i > 0)
1394 *(pos++) = ' ';
1395 ole_check(IXMLDOMNodeList_nextNode(list, &node));
1396 node_to_string(node, pos);
1397 pos += strlen(pos);
1398 IXMLDOMNode_Release(node);
1399 }
1400 *pos = 0;
1401 return buf;
1402 }
1403
1404 #define expect_node(node, expstr) { char str[4096]; node_to_string(node, str); ok(strcmp(str, expstr)==0, "Invalid node: %s, expected %s\n", str, expstr); }
1405 #define expect_list_and_release(list, expstr) { char *str = list_to_string(list); ok(strcmp(str, expstr)==0, "Invalid node list: %s, expected %s\n", str, expstr); if (list) IXMLDOMNodeList_Release(list); }
1406
1407 struct docload_ret_t {
1408 VARIANT_BOOL b;
1409 HRESULT hr;
1410 };
1411
1412 struct leading_spaces_t {
1413 const CLSID *clsid;
1414 const char *name;
1415 struct docload_ret_t ret[2]; /* 0 - ::load(), 1 - ::loadXML() */
1416 };
1417
1418 static const struct leading_spaces_t leading_spaces_classdata[] = {
1419 { &CLSID_DOMDocument, "CLSID_DOMDocument", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1420 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1421 { &CLSID_DOMDocument26, "CLSID_DOMDocument26", {{VARIANT_FALSE, S_FALSE }, {VARIANT_TRUE, S_OK } }},
1422 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1423 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1424 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", {{VARIANT_FALSE, S_FALSE }, {VARIANT_FALSE, S_FALSE } }},
1425 { NULL }
1426 };
1427
1428 static const char* leading_spaces_xmldata[] = {
1429 "\n<?xml version=\"1.0\" encoding=\"UTF-16\" ?><root/>",
1430 " <?xml version=\"1.0\"?><root/>",
1431 "\n<?xml version=\"1.0\"?><root/>",
1432 "\t<?xml version=\"1.0\"?><root/>",
1433 "\r\n<?xml version=\"1.0\"?><root/>",
1434 "\r<?xml version=\"1.0\"?><root/>",
1435 "\r\r\r\r\t\t \n\n <?xml version=\"1.0\"?><root/>",
1436 0
1437 };
1438
1439 static void test_domdoc( void )
1440 {
1441 HRESULT r, hr;
1442 IXMLDOMDocument *doc;
1443 IXMLDOMParseError *error;
1444 IXMLDOMElement *element = NULL;
1445 IXMLDOMNode *node;
1446 IXMLDOMText *nodetext = NULL;
1447 IXMLDOMComment *node_comment = NULL;
1448 IXMLDOMAttribute *node_attr = NULL;
1449 IXMLDOMNode *nodeChild = NULL;
1450 IXMLDOMProcessingInstruction *nodePI = NULL;
1451 const struct leading_spaces_t *class_ptr;
1452 const char **data_ptr;
1453 VARIANT_BOOL b;
1454 VARIANT var;
1455 BSTR str;
1456 LONG code, ref;
1457 LONG nLength = 0;
1458 WCHAR buff[100];
1459 char path[MAX_PATH];
1460 int index;
1461
1462 GetTempPathA(MAX_PATH, path);
1463 strcat(path, "leading_spaces.xml");
1464
1465 /* Load document with leading spaces
1466 *
1467 * Test all CLSIDs with all test data XML strings
1468 */
1469 class_ptr = leading_spaces_classdata;
1470 index = 0;
1471 while (class_ptr->clsid)
1472 {
1473 HRESULT hr;
1474 int i;
1475
1476 if (is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
1477 {
1478 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
1479 }
1480 else
1481 {
1482 class_ptr++;
1483 index++;
1484 continue;
1485 }
1486
1487 data_ptr = leading_spaces_xmldata;
1488 i = 0;
1489 while (*data_ptr) {
1490 BSTR data = _bstr_(*data_ptr);
1491 DWORD written;
1492 HANDLE file;
1493
1494 file = CreateFileA(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1495 ok(file != INVALID_HANDLE_VALUE, "can't create file %s: %u\n", path, GetLastError());
1496
1497 WriteFile(file, data, lstrlenW(data)*sizeof(WCHAR), &written, NULL);
1498 CloseHandle(file);
1499
1500 b = 0xc;
1501 V_VT(&var) = VT_BSTR;
1502 V_BSTR(&var) = _bstr_(path);
1503 hr = IXMLDOMDocument_load(doc, var, &b);
1504 EXPECT_HR(hr, class_ptr->ret[0].hr);
1505 ok(b == class_ptr->ret[0].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[0].b);
1506
1507 DeleteFileA(path);
1508
1509 b = 0xc;
1510 hr = IXMLDOMDocument_loadXML(doc, data, &b);
1511 EXPECT_HR(hr, class_ptr->ret[1].hr);
1512 ok(b == class_ptr->ret[1].b, "%d:%d, got %d, expected %d\n", index, i, b, class_ptr->ret[1].b);
1513
1514 data_ptr++;
1515 i++;
1516 }
1517
1518 class_ptr++;
1519 index++;
1520 free_bstrs();
1521 }
1522
1523 doc = create_document(&IID_IXMLDOMDocument);
1524 if (!doc) return;
1525
1526 if (0)
1527 {
1528 /* crashes on native */
1529 IXMLDOMDocument_loadXML( doc, (BSTR)0x1, NULL );
1530 }
1531
1532 /* try some stupid things */
1533 hr = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1534 EXPECT_HR(hr, S_FALSE);
1535
1536 b = VARIANT_TRUE;
1537 hr = IXMLDOMDocument_loadXML( doc, NULL, &b );
1538 EXPECT_HR(hr, S_FALSE);
1539 ok( b == VARIANT_FALSE, "failed to load XML string\n");
1540
1541 /* try to load a document from a nonexistent file */
1542 b = VARIANT_TRUE;
1543 str = SysAllocString( nonexistent_fileW );
1544 VariantInit(&var);
1545 V_VT(&var) = VT_BSTR;
1546 V_BSTR(&var) = str;
1547
1548 r = IXMLDOMDocument_load( doc, var, &b);
1549 ok( r == S_FALSE, "loadXML succeeded\n");
1550 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1551 SysFreeString( str );
1552
1553 str = (void *)0xdeadbeef;
1554 hr = IXMLDOMDocument_get_url(doc, &str);
1555 ok(hr == S_FALSE, "got 0x%08x\n", hr);
1556 ok(str == NULL, "got %p\n", str);
1557
1558 /* try load an empty document */
1559 b = VARIANT_TRUE;
1560 str = SysAllocString( szEmpty );
1561 r = IXMLDOMDocument_loadXML( doc, str, &b );
1562 ok( r == S_FALSE, "loadXML succeeded\n");
1563 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1564 SysFreeString( str );
1565
1566 r = IXMLDOMDocument_get_async( doc, &b );
1567 ok( r == S_OK, "get_async failed (%08x)\n", r);
1568 ok( b == VARIANT_TRUE, "Wrong default value\n");
1569
1570 /* check that there's no document element */
1571 element = NULL;
1572 r = IXMLDOMDocument_get_documentElement( doc, &element );
1573 ok( r == S_FALSE, "should be no document element\n");
1574
1575 /* try finding a node */
1576 node = NULL;
1577 str = SysAllocString( szstr1 );
1578 r = IXMLDOMDocument_selectSingleNode( doc, str, &node );
1579 ok( r == S_FALSE, "ret %08x\n", r );
1580 SysFreeString( str );
1581
1582 b = VARIANT_TRUE;
1583 str = SysAllocString( szIncomplete );
1584 r = IXMLDOMDocument_loadXML( doc, str, &b );
1585 ok( r == S_FALSE, "loadXML succeeded\n");
1586 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1587 SysFreeString( str );
1588
1589 /* check that there's no document element */
1590 element = (IXMLDOMElement*)1;
1591 r = IXMLDOMDocument_get_documentElement( doc, &element );
1592 ok( r == S_FALSE, "should be no document element\n");
1593 ok( element == NULL, "Element should be NULL\n");
1594
1595 /* test for BSTR handling, pass broken BSTR */
1596 memcpy(&buff[2], szComplete1, sizeof(szComplete1));
1597 /* just a big length */
1598 *(DWORD*)buff = 0xf0f0;
1599 b = VARIANT_FALSE;
1600 r = IXMLDOMDocument_loadXML( doc, &buff[2], &b );
1601 ok( r == S_OK, "loadXML failed\n");
1602 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1603
1604 /* loadXML ignores the encoding attribute and always expects Unicode */
1605 b = VARIANT_FALSE;
1606 str = SysAllocString( szComplete6 );
1607 r = IXMLDOMDocument_loadXML( doc, str, &b );
1608 ok( r == S_OK, "loadXML failed\n");
1609 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1610 SysFreeString( str );
1611
1612 /* try a BSTR containing a Windows-1252 document */
1613 b = VARIANT_TRUE;
1614 str = SysAllocStringByteLen( win1252xml, strlen(win1252xml) );
1615 r = IXMLDOMDocument_loadXML( doc, str, &b );
1616 ok( r == S_FALSE, "loadXML succeeded\n");
1617 ok( b == VARIANT_FALSE, "succeeded in loading XML string\n");
1618 SysFreeString( str );
1619
1620 /* try to load something valid */
1621 b = VARIANT_FALSE;
1622 str = SysAllocString( szComplete1 );
1623 r = IXMLDOMDocument_loadXML( doc, str, &b );
1624 ok( r == S_OK, "loadXML failed\n");
1625 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1626 SysFreeString( str );
1627
1628 /* check if nodename is correct */
1629 r = IXMLDOMDocument_get_nodeName( doc, NULL );
1630 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
1631
1632 str = (void *)0xdeadbeef;
1633 r = IXMLDOMDocument_get_baseName( doc, &str );
1634 ok ( r == S_FALSE, "got 0x%08x\n", r);
1635 ok (str == NULL, "got %p\n", str);
1636
1637 /* content doesn't matter here */
1638 str = NULL;
1639 r = IXMLDOMDocument_get_nodeName( doc, &str );
1640 ok ( r == S_OK, "get_nodeName wrong code\n");
1641 ok ( str != NULL, "str is null\n");
1642 ok( !lstrcmpW( str, szDocument ), "incorrect nodeName\n");
1643 SysFreeString( str );
1644
1645 /* test put_text */
1646 r = IXMLDOMDocument_put_text( doc, _bstr_("Should fail") );
1647 ok( r == E_FAIL, "ret %08x\n", r );
1648
1649 /* check that there's a document element */
1650 element = NULL;
1651 r = IXMLDOMDocument_get_documentElement( doc, &element );
1652 ok( r == S_OK, "should be a document element\n");
1653 if( element )
1654 {
1655 IObjectIdentity *ident;
1656
1657 r = IXMLDOMElement_QueryInterface( element, &IID_IObjectIdentity, (void**)&ident );
1658 ok( r == E_NOINTERFACE, "ret %08x\n", r);
1659
1660 IXMLDOMElement_Release( element );
1661 element = NULL;
1662 }
1663
1664 /* as soon as we call loadXML again, the document element will disappear */
1665 b = 2;
1666 r = IXMLDOMDocument_loadXML( doc, NULL, NULL );
1667 ok( r == S_FALSE, "loadXML failed\n");
1668 ok( b == 2, "variant modified\n");
1669 r = IXMLDOMDocument_get_documentElement( doc, &element );
1670 ok( r == S_FALSE, "should be no document element\n");
1671
1672 /* try to load something else simple and valid */
1673 b = VARIANT_FALSE;
1674 str = SysAllocString( szComplete2 );
1675 r = IXMLDOMDocument_loadXML( doc, str, &b );
1676 ok( r == S_OK, "loadXML failed\n");
1677 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1678 SysFreeString( str );
1679
1680 /* try something a little more complicated */
1681 b = FALSE;
1682 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
1683 ok( r == S_OK, "loadXML failed\n");
1684 ok( b == VARIANT_TRUE, "failed to load XML string\n");
1685
1686 r = IXMLDOMDocument_get_parseError( doc, &error );
1687 ok( r == S_OK, "returns %08x\n", r );
1688
1689 r = IXMLDOMParseError_get_errorCode( error, &code );
1690 ok( r == S_FALSE, "returns %08x\n", r );
1691 ok( code == 0, "code %d\n", code );
1692 IXMLDOMParseError_Release( error );
1693
1694 /* test createTextNode */
1695 r = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &nodetext);
1696 ok( r == S_OK, "returns %08x\n", r );
1697 IXMLDOMText_Release(nodetext);
1698
1699 str = SysAllocString( szOpen );
1700 r = IXMLDOMDocument_createTextNode(doc, str, NULL);
1701 ok( r == E_INVALIDARG, "returns %08x\n", r );
1702 r = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
1703 ok( r == S_OK, "returns %08x\n", r );
1704 SysFreeString( str );
1705 if(nodetext)
1706 {
1707 r = IXMLDOMText_QueryInterface(nodetext, &IID_IXMLDOMElement, (void**)&element);
1708 ok(r == E_NOINTERFACE, "ret %08x\n", r );
1709
1710 /* Text Last Child Checks */
1711 r = IXMLDOMText_get_lastChild(nodetext, NULL);
1712 ok(r == E_INVALIDARG, "ret %08x\n", r );
1713
1714 nodeChild = (IXMLDOMNode*)0x1;
1715 r = IXMLDOMText_get_lastChild(nodetext, &nodeChild);
1716 ok(r == S_FALSE, "ret %08x\n", r );
1717 ok(nodeChild == NULL, "nodeChild not NULL\n");
1718
1719 /* test length property */
1720 r = IXMLDOMText_get_length(nodetext, NULL);
1721 ok(r == E_INVALIDARG, "ret %08x\n", r );
1722
1723 r = IXMLDOMText_get_length(nodetext, &nLength);
1724 ok(r == S_OK, "ret %08x\n", r );
1725 ok(nLength == 4, "expected 4 got %d\n", nLength);
1726
1727 /* put data Tests */
1728 r = IXMLDOMText_put_data(nodetext, _bstr_("This &is a ; test <>\\"));
1729 ok(r == S_OK, "ret %08x\n", r );
1730
1731 /* get data Tests */
1732 r = IXMLDOMText_get_data(nodetext, &str);
1733 ok(r == S_OK, "ret %08x\n", r );
1734 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect put_data string\n");
1735 SysFreeString(str);
1736
1737 /* Confirm XML text is good */
1738 r = IXMLDOMText_get_xml(nodetext, &str);
1739 ok(r == S_OK, "ret %08x\n", r );
1740 ok( !lstrcmpW( str, _bstr_("This &amp;is a ; test &lt;&gt;\\") ), "incorrect xml string\n");
1741 SysFreeString(str);
1742
1743 /* Confirm we get the put_data Text back */
1744 r = IXMLDOMText_get_text(nodetext, &str);
1745 ok(r == S_OK, "ret %08x\n", r );
1746 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
1747 SysFreeString(str);
1748
1749 /* test substringData */
1750 r = IXMLDOMText_substringData(nodetext, 0, 4, NULL);
1751 ok(r == E_INVALIDARG, "ret %08x\n", r );
1752
1753 /* test substringData - Invalid offset */
1754 str = (void *)0xdeadbeef;
1755 r = IXMLDOMText_substringData(nodetext, -1, 4, &str);
1756 ok(r == E_INVALIDARG, "ret %08x\n", r );
1757 ok( str == NULL, "incorrect string\n");
1758
1759 /* test substringData - Invalid offset */
1760 str = (void *)0xdeadbeef;
1761 r = IXMLDOMText_substringData(nodetext, 30, 0, &str);
1762 ok(r == S_FALSE, "ret %08x\n", r );
1763 ok( str == NULL, "incorrect string\n");
1764
1765 /* test substringData - Invalid size */
1766 str = (void *)0xdeadbeef;
1767 r = IXMLDOMText_substringData(nodetext, 0, -1, &str);
1768 ok(r == E_INVALIDARG, "ret %08x\n", r );
1769 ok( str == NULL, "incorrect string\n");
1770
1771 /* test substringData - Invalid size */
1772 str = (void *)0xdeadbeef;
1773 r = IXMLDOMText_substringData(nodetext, 2, 0, &str);
1774 ok(r == S_FALSE, "ret %08x\n", r );
1775 ok( str == NULL, "incorrect string\n");
1776
1777 /* test substringData - Start of string */
1778 r = IXMLDOMText_substringData(nodetext, 0, 4, &str);
1779 ok(r == S_OK, "ret %08x\n", r );
1780 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
1781 SysFreeString(str);
1782
1783 /* test substringData - Middle of string */
1784 r = IXMLDOMText_substringData(nodetext, 13, 4, &str);
1785 ok(r == S_OK, "ret %08x\n", r );
1786 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
1787 SysFreeString(str);
1788
1789 /* test substringData - End of string */
1790 r = IXMLDOMText_substringData(nodetext, 20, 4, &str);
1791 ok(r == S_OK, "ret %08x\n", r );
1792 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
1793 SysFreeString(str);
1794
1795 /* test appendData */
1796 r = IXMLDOMText_appendData(nodetext, NULL);
1797 ok(r == S_OK, "ret %08x\n", r );
1798
1799 r = IXMLDOMText_appendData(nodetext, _bstr_(""));
1800 ok(r == S_OK, "ret %08x\n", r );
1801
1802 r = IXMLDOMText_appendData(nodetext, _bstr_("Append"));
1803 ok(r == S_OK, "ret %08x\n", r );
1804
1805 r = IXMLDOMText_get_text(nodetext, &str);
1806 ok(r == S_OK, "ret %08x\n", r );
1807 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1808 SysFreeString(str);
1809
1810 /* test insertData */
1811 str = SysAllocStringLen(NULL, 0);
1812 r = IXMLDOMText_insertData(nodetext, -1, str);
1813 ok(r == S_OK, "ret %08x\n", r );
1814
1815 r = IXMLDOMText_insertData(nodetext, -1, NULL);
1816 ok(r == S_OK, "ret %08x\n", r );
1817
1818 r = IXMLDOMText_insertData(nodetext, 1000, str);
1819 ok(r == S_OK, "ret %08x\n", r );
1820
1821 r = IXMLDOMText_insertData(nodetext, 1000, NULL);
1822 ok(r == S_OK, "ret %08x\n", r );
1823
1824 r = IXMLDOMText_insertData(nodetext, 0, NULL);
1825 ok(r == S_OK, "ret %08x\n", r );
1826
1827 r = IXMLDOMText_insertData(nodetext, 0, str);
1828 ok(r == S_OK, "ret %08x\n", r );
1829 SysFreeString(str);
1830
1831 r = IXMLDOMText_insertData(nodetext, -1, _bstr_("Inserting"));
1832 ok(r == E_INVALIDARG, "ret %08x\n", r );
1833
1834 r = IXMLDOMText_insertData(nodetext, 1000, _bstr_("Inserting"));
1835 ok(r == E_INVALIDARG, "ret %08x\n", r );
1836
1837 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("Begin "));
1838 ok(r == S_OK, "ret %08x\n", r );
1839
1840 r = IXMLDOMText_insertData(nodetext, 17, _bstr_("Middle"));
1841 ok(r == S_OK, "ret %08x\n", r );
1842
1843 r = IXMLDOMText_insertData(nodetext, 39, _bstr_(" End"));
1844 ok(r == S_OK, "ret %08x\n", r );
1845
1846 r = IXMLDOMText_get_text(nodetext, &str);
1847 ok(r == S_OK, "ret %08x\n", r );
1848 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1849 SysFreeString(str);
1850
1851 /* delete data */
1852 /* invalid arguments */
1853 r = IXMLDOMText_deleteData(nodetext, -1, 1);
1854 ok(r == E_INVALIDARG, "ret %08x\n", r );
1855
1856 r = IXMLDOMText_deleteData(nodetext, 0, 0);
1857 ok(r == S_OK, "ret %08x\n", r );
1858
1859 r = IXMLDOMText_deleteData(nodetext, 0, -1);
1860 ok(r == E_INVALIDARG, "ret %08x\n", r );
1861
1862 r = IXMLDOMText_get_length(nodetext, &nLength);
1863 ok(r == S_OK, "ret %08x\n", r );
1864 ok(nLength == 43, "expected 43 got %d\n", nLength);
1865
1866 r = IXMLDOMText_deleteData(nodetext, nLength, 1);
1867 ok(r == S_OK, "ret %08x\n", r );
1868
1869 r = IXMLDOMText_deleteData(nodetext, nLength+1, 1);
1870 ok(r == E_INVALIDARG, "ret %08x\n", r );
1871
1872 /* delete from start */
1873 r = IXMLDOMText_deleteData(nodetext, 0, 5);
1874 ok(r == S_OK, "ret %08x\n", r );
1875
1876 r = IXMLDOMText_get_length(nodetext, &nLength);
1877 ok(r == S_OK, "ret %08x\n", r );
1878 ok(nLength == 38, "expected 38 got %d\n", nLength);
1879
1880 r = IXMLDOMText_get_text(nodetext, &str);
1881 ok(r == S_OK, "ret %08x\n", r );
1882 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1883 SysFreeString(str);
1884
1885 /* delete from end */
1886 r = IXMLDOMText_deleteData(nodetext, 35, 3);
1887 ok(r == S_OK, "ret %08x\n", r );
1888
1889 r = IXMLDOMText_get_length(nodetext, &nLength);
1890 ok(r == S_OK, "ret %08x\n", r );
1891 ok(nLength == 35, "expected 35 got %d\n", nLength);
1892
1893 r = IXMLDOMText_get_text(nodetext, &str);
1894 ok(r == S_OK, "ret %08x\n", r );
1895 ok( !lstrcmpW( str, _bstr_("This &is a Middle; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1896 SysFreeString(str);
1897
1898 /* delete from inside */
1899 r = IXMLDOMText_deleteData(nodetext, 1, 33);
1900 ok(r == S_OK, "ret %08x\n", r );
1901
1902 r = IXMLDOMText_get_length(nodetext, &nLength);
1903 ok(r == S_OK, "ret %08x\n", r );
1904 ok(nLength == 2, "expected 2 got %d\n", nLength);
1905
1906 r = IXMLDOMText_get_text(nodetext, &str);
1907 ok(r == S_OK, "ret %08x\n", r );
1908 ok( !lstrcmpW( str, _bstr_("") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1909 SysFreeString(str);
1910
1911 /* delete whole data ... */
1912 r = IXMLDOMText_get_length(nodetext, &nLength);
1913 ok(r == S_OK, "ret %08x\n", r );
1914
1915 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1916 ok(r == S_OK, "ret %08x\n", r );
1917 /* ... and try again with empty string */
1918 r = IXMLDOMText_deleteData(nodetext, 0, nLength);
1919 ok(r == S_OK, "ret %08x\n", r );
1920
1921 /* test put_data */
1922 V_VT(&var) = VT_BSTR;
1923 V_BSTR(&var) = SysAllocString(szstr1);
1924 r = IXMLDOMText_put_nodeValue(nodetext, var);
1925 ok(r == S_OK, "ret %08x\n", r );
1926 VariantClear(&var);
1927
1928 r = IXMLDOMText_get_text(nodetext, &str);
1929 ok(r == S_OK, "ret %08x\n", r );
1930 ok( !lstrcmpW( str, szstr1 ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1931 SysFreeString(str);
1932
1933 /* test put_data */
1934 V_VT(&var) = VT_I4;
1935 V_I4(&var) = 99;
1936 r = IXMLDOMText_put_nodeValue(nodetext, var);
1937 ok(r == S_OK, "ret %08x\n", r );
1938 VariantClear(&var);
1939
1940 r = IXMLDOMText_get_text(nodetext, &str);
1941 ok(r == S_OK, "ret %08x\n", r );
1942 ok( !lstrcmpW( str, _bstr_("99") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1943 SysFreeString(str);
1944
1945 /* ::replaceData() */
1946 V_VT(&var) = VT_BSTR;
1947 V_BSTR(&var) = SysAllocString(szstr1);
1948 r = IXMLDOMText_put_nodeValue(nodetext, var);
1949 ok(r == S_OK, "ret %08x\n", r );
1950 VariantClear(&var);
1951
1952 r = IXMLDOMText_replaceData(nodetext, 6, 0, NULL);
1953 ok(r == E_INVALIDARG, "ret %08x\n", r );
1954 r = IXMLDOMText_get_text(nodetext, &str);
1955 ok(r == S_OK, "ret %08x\n", r );
1956 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1957 SysFreeString(str);
1958
1959 r = IXMLDOMText_replaceData(nodetext, 0, 0, NULL);
1960 ok(r == S_OK, "ret %08x\n", r );
1961 r = IXMLDOMText_get_text(nodetext, &str);
1962 ok(r == S_OK, "ret %08x\n", r );
1963 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1964 SysFreeString(str);
1965
1966 /* NULL pointer means delete */
1967 r = IXMLDOMText_replaceData(nodetext, 0, 1, NULL);
1968 ok(r == S_OK, "ret %08x\n", r );
1969 r = IXMLDOMText_get_text(nodetext, &str);
1970 ok(r == S_OK, "ret %08x\n", r );
1971 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1972 SysFreeString(str);
1973
1974 /* empty string means delete */
1975 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_(""));
1976 ok(r == S_OK, "ret %08x\n", r );
1977 r = IXMLDOMText_get_text(nodetext, &str);
1978 ok(r == S_OK, "ret %08x\n", r );
1979 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1980 SysFreeString(str);
1981
1982 /* zero count means insert */
1983 r = IXMLDOMText_replaceData(nodetext, 0, 0, _bstr_("a"));
1984 ok(r == S_OK, "ret %08x\n", r );
1985 r = IXMLDOMText_get_text(nodetext, &str);
1986 ok(r == S_OK, "ret %08x\n", r );
1987 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1988 SysFreeString(str);
1989
1990 r = IXMLDOMText_replaceData(nodetext, 0, 2, NULL);
1991 ok(r == S_OK, "ret %08x\n", r );
1992
1993 r = IXMLDOMText_insertData(nodetext, 0, _bstr_("m"));
1994 ok(r == S_OK, "ret %08x\n", r );
1995 r = IXMLDOMText_get_text(nodetext, &str);
1996 ok(r == S_OK, "ret %08x\n", r );
1997 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
1998 SysFreeString(str);
1999
2000 /* nonempty string, count greater than its length */
2001 r = IXMLDOMText_replaceData(nodetext, 0, 2, _bstr_("a1.2"));
2002 ok(r == S_OK, "ret %08x\n", r );
2003 r = IXMLDOMText_get_text(nodetext, &str);
2004 ok(r == S_OK, "ret %08x\n", r );
2005 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
2006 SysFreeString(str);
2007
2008 /* nonempty string, count less than its length */
2009 r = IXMLDOMText_replaceData(nodetext, 0, 1, _bstr_("wine"));
2010 ok(r == S_OK, "ret %08x\n", r );
2011 r = IXMLDOMText_get_text(nodetext, &str);
2012 ok(r == S_OK, "ret %08x\n", r );
2013 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
2014 SysFreeString(str);
2015
2016 IXMLDOMText_Release( nodetext );
2017 }
2018
2019 /* test Create Comment */
2020 r = IXMLDOMDocument_createComment(doc, NULL, NULL);
2021 ok( r == E_INVALIDARG, "returns %08x\n", r );
2022 node_comment = (IXMLDOMComment*)0x1;
2023
2024 /* empty comment */
2025 r = IXMLDOMDocument_createComment(doc, _bstr_(""), &node_comment);
2026 ok( r == S_OK, "returns %08x\n", r );
2027 str = NULL;
2028 r = IXMLDOMComment_get_data(node_comment, &str);
2029 ok( r == S_OK, "returns %08x\n", r );
2030 ok( str && SysStringLen(str) == 0, "expected empty string data\n");
2031 IXMLDOMComment_Release(node_comment);
2032 SysFreeString(str);
2033
2034 r = IXMLDOMDocument_createComment(doc, NULL, &node_comment);
2035 ok( r == S_OK, "returns %08x\n", r );
2036 str = NULL;
2037 r = IXMLDOMComment_get_data(node_comment, &str);
2038 ok( r == S_OK, "returns %08x\n", r );
2039 ok( str && (SysStringLen(str) == 0), "expected empty string data\n");
2040 IXMLDOMComment_Release(node_comment);
2041 SysFreeString(str);
2042
2043 str = SysAllocString(szComment);
2044 r = IXMLDOMDocument_createComment(doc, str, &node_comment);
2045 SysFreeString(str);
2046 ok( r == S_OK, "returns %08x\n", r );
2047 if(node_comment)
2048 {
2049 /* Last Child Checks */
2050 r = IXMLDOMComment_get_lastChild(node_comment, NULL);
2051 ok(r == E_INVALIDARG, "ret %08x\n", r );
2052
2053 nodeChild = (IXMLDOMNode*)0x1;
2054 r = IXMLDOMComment_get_lastChild(node_comment, &nodeChild);
2055 ok(r == S_FALSE, "ret %08x\n", r );
2056 ok(nodeChild == NULL, "pLastChild not NULL\n");
2057
2058 /* baseName */
2059 str = (void *)0xdeadbeef;
2060 r = IXMLDOMComment_get_baseName(node_comment, &str);
2061 ok(r == S_FALSE, "ret %08x\n", r );
2062 ok(str == NULL, "Expected NULL\n");
2063
2064 IXMLDOMComment_Release( node_comment );
2065 }
2066
2067 /* test Create Attribute */
2068 str = SysAllocString(szAttribute);
2069 r = IXMLDOMDocument_createAttribute(doc, NULL, NULL);
2070 ok( r == E_INVALIDARG, "returns %08x\n", r );
2071 r = IXMLDOMDocument_createAttribute(doc, str, &node_attr);
2072 ok( r == S_OK, "returns %08x\n", r );
2073 IXMLDOMAttribute_Release( node_attr);
2074 SysFreeString(str);
2075
2076 /* test Processing Instruction */
2077 str = SysAllocStringLen(NULL, 0);
2078 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, NULL);
2079 ok( r == E_INVALIDARG, "returns %08x\n", r );
2080 r = IXMLDOMDocument_createProcessingInstruction(doc, NULL, str, &nodePI);
2081 ok( r == E_FAIL, "returns %08x\n", r );
2082 r = IXMLDOMDocument_createProcessingInstruction(doc, str, str, &nodePI);
2083 ok( r == E_FAIL, "returns %08x\n", r );
2084 SysFreeString(str);
2085
2086 r = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"), _bstr_("version=\"1.0\""), &nodePI);
2087 ok( r == S_OK, "returns %08x\n", r );
2088 if(nodePI)
2089 {
2090 /* Last Child Checks */
2091 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, NULL);
2092 ok(r == E_INVALIDARG, "ret %08x\n", r );
2093
2094 nodeChild = (IXMLDOMNode*)0x1;
2095 r = IXMLDOMProcessingInstruction_get_lastChild(nodePI, &nodeChild);
2096 ok(r == S_FALSE, "ret %08x\n", r );
2097 ok(nodeChild == NULL, "nodeChild not NULL\n");
2098
2099 /* test nodeName */
2100 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2101 ok(r == S_OK, "ret %08x\n", r );
2102 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2103 SysFreeString(str);
2104
2105 /* test baseName */
2106 str = NULL;
2107 r = IXMLDOMProcessingInstruction_get_baseName(nodePI, &str);
2108 ok(r == S_OK, "ret %08x\n", r );
2109 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2110 SysFreeString(str);
2111
2112 /* test Target */
2113 r = IXMLDOMProcessingInstruction_get_target(nodePI, &str);
2114 ok(r == S_OK, "ret %08x\n", r );
2115 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect target string\n");
2116 SysFreeString(str);
2117
2118 /* test get_data */
2119 r = IXMLDOMProcessingInstruction_get_data(nodePI, &str);
2120 ok(r == S_OK, "ret %08x\n", r );
2121 ok( !lstrcmpW( str, _bstr_("version=\"1.0\"") ), "incorrect data string\n");
2122 SysFreeString(str);
2123
2124 /* test put_data */
2125 r = IXMLDOMProcessingInstruction_put_data(nodePI, _bstr_("version=\"1.0\" encoding=\"UTF-8\""));
2126 ok(r == E_FAIL, "ret %08x\n", r );
2127
2128 /* test put_data */
2129 V_VT(&var) = VT_BSTR;
2130 V_BSTR(&var) = SysAllocString(szOpen); /* Doesn't matter what the string is, cannot set an xml node. */
2131 r = IXMLDOMProcessingInstruction_put_nodeValue(nodePI, var);
2132 ok(r == E_FAIL, "ret %08x\n", r );
2133 VariantClear(&var);
2134
2135 /* test get nodeName */
2136 r = IXMLDOMProcessingInstruction_get_nodeName(nodePI, &str);
2137 ok( !lstrcmpW( str, _bstr_("xml") ), "incorrect nodeName string\n");
2138 ok(r == S_OK, "ret %08x\n", r );
2139 SysFreeString(str);
2140
2141 IXMLDOMProcessingInstruction_Release(nodePI);
2142 }
2143
2144 ref = IXMLDOMDocument_Release( doc );
2145 ok( ref == 0, "got %d\n", ref);
2146
2147 free_bstrs();
2148 }
2149
2150 static void test_persiststream(void)
2151 {
2152 IPersistStreamInit *streaminit;
2153 IPersistStream *stream;
2154 IXMLDOMDocument *doc;
2155 ULARGE_INTEGER size;
2156 IPersist *persist;
2157 HRESULT hr;
2158 CLSID clsid;
2159
2160 doc = create_document(&IID_IXMLDOMDocument);
2161
2162 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&streaminit);
2163 ok(hr == S_OK, "got 0x%08x\n", hr);
2164
2165 hr = IPersistStreamInit_InitNew(streaminit);
2166 ok(hr == S_OK, "got 0x%08x\n", hr);
2167
2168 hr = IPersistStreamInit_GetSizeMax(streaminit, &size);
2169 ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
2170
2171 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersistStream, (void **)&stream);
2172 ok(hr == S_OK, "got 0x%08x\n", hr);
2173 ok((IUnknown *)stream == (IUnknown *)streaminit, "got %p, %p\n", stream, streaminit);
2174
2175 hr = IPersistStream_QueryInterface(stream, &IID_IPersist, (void **)&persist);
2176 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2177
2178 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IPersist, (void **)&persist);
2179 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
2180
2181 hr = IPersistStreamInit_GetClassID(streaminit, NULL);
2182 ok(hr == E_POINTER, "got 0x%08x\n", hr);
2183
2184 memset(&clsid, 0, sizeof(clsid));
2185 hr = IPersistStreamInit_GetClassID(streaminit, &clsid);
2186 ok(hr == S_OK, "got 0x%08x\n", hr);
2187 ok(IsEqualGUID(&clsid, &CLSID_DOMDocument2), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
2188
2189 IPersistStream_Release(stream);
2190 IPersistStreamInit_Release(streaminit);
2191 IXMLDOMDocument_Release(doc);
2192 }
2193
2194 static void test_domnode( void )
2195 {
2196 HRESULT r;
2197 IXMLDOMDocument *doc, *owner = NULL;
2198 IXMLDOMElement *element = NULL;
2199 IXMLDOMNamedNodeMap *map = NULL;
2200 IXMLDOMNode *node = NULL, *next = NULL;
2201 IXMLDOMNodeList *list = NULL;
2202 IXMLDOMAttribute *attr = NULL;
2203 DOMNodeType type = NODE_INVALID;
2204 VARIANT_BOOL b;
2205 BSTR str;
2206 VARIANT var;
2207 LONG count;
2208
2209 doc = create_document(&IID_IXMLDOMDocument);
2210
2211 b = FALSE;
2212 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2213 ok( r == S_OK, "loadXML failed\n");
2214 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2215
2216 EXPECT_CHILDREN(doc);
2217
2218 r = IXMLDOMDocument_get_documentElement( doc, &element );
2219 ok( r == S_OK, "should be a document element\n");
2220 ok( element != NULL, "should be an element\n");
2221
2222 VariantInit(&var);
2223 ok( V_VT(&var) == VT_EMPTY, "variant init failed\n");
2224
2225 r = IXMLDOMDocument_get_nodeValue( doc, NULL );
2226 ok(r == E_INVALIDARG, "get_nodeValue ret %08x\n", r );
2227
2228 r = IXMLDOMDocument_get_nodeValue( doc, &var );
2229 ok( r == S_FALSE, "nextNode returned wrong code\n");
2230 ok( V_VT(&var) == VT_NULL, "variant wasn't empty\n");
2231 ok( V_BSTR(&var) == NULL, "variant value wasn't null\n");
2232
2233 if (element)
2234 {
2235 owner = NULL;
2236 r = IXMLDOMElement_get_ownerDocument( element, &owner );
2237 ok( r == S_OK, "get_ownerDocument return code\n");
2238 ok( owner != doc, "get_ownerDocument return\n");
2239 IXMLDOMDocument_Release(owner);
2240
2241 type = NODE_INVALID;
2242 r = IXMLDOMElement_get_nodeType( element, &type);
2243 ok( r == S_OK, "got %08x\n", r);
2244 ok( type == NODE_ELEMENT, "node not an element\n");
2245
2246 str = NULL;
2247 r = IXMLDOMElement_get_baseName( element, &str );
2248 ok( r == S_OK, "get_baseName returned wrong code\n");
2249 ok( lstrcmpW(str,szlc) == 0, "basename was wrong\n");
2250 SysFreeString(str);
2251
2252 /* check if nodename is correct */
2253 r = IXMLDOMElement_get_nodeName( element, NULL );
2254 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2255
2256 /* content doesn't matter here */
2257 str = NULL;
2258 r = IXMLDOMElement_get_nodeName( element, &str );
2259 ok ( r == S_OK, "get_nodeName wrong code\n");
2260 ok ( str != NULL, "str is null\n");
2261 ok( !lstrcmpW( str, szlc ), "incorrect nodeName\n");
2262 SysFreeString( str );
2263
2264 str = SysAllocString( nonexistent_fileW );
2265 V_VT(&var) = VT_I4;
2266 V_I4(&var) = 0x1234;
2267 r = IXMLDOMElement_getAttribute( element, str, &var );
2268 ok( r == E_FAIL, "getAttribute ret %08x\n", r );
2269 ok( V_VT(&var) == VT_NULL || V_VT(&var) == VT_EMPTY, "vt = %x\n", V_VT(&var));
2270 VariantClear(&var);
2271 SysFreeString(str);
2272
2273 str = SysAllocString( szdl );
2274 V_VT(&var) = VT_I4;
2275 V_I4(&var) = 0x1234;
2276 r = IXMLDOMElement_getAttribute( element, str, &var );
2277 ok( r == S_OK, "getAttribute ret %08x\n", r );
2278 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
2279 ok( !lstrcmpW(V_BSTR(&var), szstr1), "wrong attr value\n");
2280 VariantClear( &var );
2281
2282 r = IXMLDOMElement_getAttribute( element, NULL, &var );
2283 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2284
2285 r = IXMLDOMElement_getAttribute( element, str, NULL );
2286 ok( r == E_INVALIDARG, "getAttribute ret %08x\n", r );
2287
2288 attr = NULL;
2289 r = IXMLDOMElement_getAttributeNode( element, str, &attr);
2290 ok( r == S_OK, "GetAttributeNode ret %08x\n", r );
2291 ok( attr != NULL, "getAttributeNode returned NULL\n" );
2292 if (attr)
2293 {
2294 r = IXMLDOMAttribute_get_parentNode( attr, NULL );
2295 ok( r == E_INVALIDARG, "Expected E_INVALIDARG, ret %08x\n", r );
2296
2297 /* attribute doesn't have a parent in msxml interpretation */
2298 node = (IXMLDOMNode*)0xdeadbeef;
2299 r = IXMLDOMAttribute_get_parentNode( attr, &node );
2300 ok( r == S_FALSE, "Expected S_FALSE, ret %08x\n", r );
2301 ok( node == NULL, "Expected NULL, got %p\n", node );
2302
2303 IXMLDOMAttribute_Release(attr);
2304 }
2305
2306 SysFreeString( str );
2307
2308 r = IXMLDOMElement_get_attributes( element, &map );
2309 ok( r == S_OK, "get_attributes returned wrong code\n");
2310 ok( map != NULL, "should be attributes\n");
2311
2312 EXPECT_CHILDREN(element);
2313 }
2314 else
2315 ok( FALSE, "no element\n");
2316
2317 if (map)
2318 {
2319 str = SysAllocString( szdl );
2320 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2321 ok( r == S_OK, "getNamedItem returned wrong code\n");
2322 ok( node != NULL, "should be attributes\n");
2323 IXMLDOMNode_Release(node);
2324 SysFreeString( str );
2325
2326 str = SysAllocString( szdl );
2327 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, NULL );
2328 ok( r == E_INVALIDARG, "getNamedItem should return E_INVALIDARG\n");
2329 SysFreeString( str );
2330
2331 /* something that isn't in complete4A */
2332 str = SysAllocString( szOpen );
2333 node = (IXMLDOMNode *) 1;
2334 r = IXMLDOMNamedNodeMap_getNamedItem( map, str, &node );
2335 ok( r == S_FALSE, "getNamedItem found a node that wasn't there\n");
2336 ok( node == NULL, "getNamedItem should have returned NULL\n");
2337 SysFreeString( str );
2338
2339 /* test indexed access of attributes */
2340 r = IXMLDOMNamedNodeMap_get_length( map, NULL );
2341 ok ( r == E_INVALIDARG, "get_length should return E_INVALIDARG\n");
2342
2343 r = IXMLDOMNamedNodeMap_get_length( map, &count );
2344 ok ( r == S_OK, "get_length wrong code\n");
2345 ok ( count == 1, "get_length != 1\n");
2346
2347 node = NULL;
2348 r = IXMLDOMNamedNodeMap_get_item( map, -1, &node);
2349 ok ( r == S_FALSE, "get_item (-1) wrong code\n");
2350 ok ( node == NULL, "there is no node\n");
2351
2352 node = NULL;
2353 r = IXMLDOMNamedNodeMap_get_item( map, 1, &node);
2354 ok ( r == S_FALSE, "get_item (1) wrong code\n");
2355 ok ( node == NULL, "there is no attribute\n");
2356
2357 node = NULL;
2358 r = IXMLDOMNamedNodeMap_get_item( map, 0, &node);
2359 ok ( r == S_OK, "get_item (0) wrong code\n");
2360 ok ( node != NULL, "should be attribute\n");
2361
2362 r = IXMLDOMNode_get_nodeName( node, NULL );
2363 ok ( r == E_INVALIDARG, "get_nodeName (NULL) wrong code\n");
2364
2365 /* content doesn't matter here */
2366 str = NULL;
2367 r = IXMLDOMNode_get_nodeName( node, &str );
2368 ok ( r == S_OK, "get_nodeName wrong code\n");
2369 ok ( str != NULL, "str is null\n");
2370 ok( !lstrcmpW( str, szdl ), "incorrect node name\n");
2371 SysFreeString( str );
2372 IXMLDOMNode_Release( node );
2373
2374 /* test sequential access of attributes */
2375 node = NULL;
2376 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2377 ok ( r == S_OK, "nextNode (first time) wrong code\n");
2378 ok ( node != NULL, "nextNode, should be attribute\n");
2379 IXMLDOMNode_Release( node );
2380
2381 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2382 ok ( r != S_OK, "nextNode (second time) wrong code\n");
2383 ok ( node == NULL, "nextNode, there is no attribute\n");
2384
2385 r = IXMLDOMNamedNodeMap_reset( map );
2386 ok ( r == S_OK, "reset should return S_OK\n");
2387
2388 r = IXMLDOMNamedNodeMap_nextNode( map, &node );
2389 ok ( r == S_OK, "nextNode (third time) wrong code\n");
2390 ok ( node != NULL, "nextNode, should be attribute\n");
2391 }
2392 else
2393 ok( FALSE, "no map\n");
2394
2395 if (node)
2396 {
2397 type = NODE_INVALID;
2398 r = IXMLDOMNode_get_nodeType( node, &type);
2399 ok( r == S_OK, "getNamedItem returned wrong code\n");
2400 ok( type == NODE_ATTRIBUTE, "node not an attribute\n");
2401
2402 str = NULL;
2403 r = IXMLDOMNode_get_baseName( node, NULL );
2404 ok( r == E_INVALIDARG, "get_baseName returned wrong code\n");
2405
2406 str = NULL;
2407 r = IXMLDOMNode_get_baseName( node, &str );
2408 ok( r == S_OK, "get_baseName returned wrong code\n");
2409 ok( lstrcmpW(str,szdl) == 0, "basename was wrong\n");
2410 SysFreeString( str );
2411
2412 r = IXMLDOMNode_get_childNodes( node, NULL );
2413 ok( r == E_INVALIDARG, "get_childNodes returned wrong code\n");
2414
2415 r = IXMLDOMNode_get_childNodes( node, &list );
2416 ok( r == S_OK, "get_childNodes returned wrong code\n");
2417
2418 if (list)
2419 {
2420 r = IXMLDOMNodeList_nextNode( list, &next );
2421 ok( r == S_OK, "nextNode returned wrong code\n");
2422 }
2423 else
2424 ok( FALSE, "no childlist\n");
2425
2426 if (next)
2427 {
2428 EXPECT_NO_CHILDREN(next);
2429
2430 type = NODE_INVALID;
2431 r = IXMLDOMNode_get_nodeType( next, &type);
2432 ok( r == S_OK, "getNamedItem returned wrong code\n");
2433 ok( type == NODE_TEXT, "node not text\n");
2434
2435 str = (void *)0xdeadbeef;
2436 r = IXMLDOMNode_get_baseName( next, &str );
2437 ok( r == S_FALSE, "get_baseName returned wrong code\n");
2438 ok( str == NULL, "basename was wrong\n");
2439 SysFreeString(str);
2440 }
2441 else
2442 ok( FALSE, "no next\n");
2443
2444 if (next)
2445 IXMLDOMNode_Release( next );
2446 next = NULL;
2447 if (list)
2448 IXMLDOMNodeList_Release( list );
2449 list = NULL;
2450 if (node)
2451 IXMLDOMNode_Release( node );
2452 }
2453 else
2454 ok( FALSE, "no node\n");
2455 node = NULL;
2456
2457 if (map)
2458 IXMLDOMNamedNodeMap_Release( map );
2459
2460 /* now traverse the tree from the root element */
2461 if (element)
2462 {
2463 r = IXMLDOMElement_get_childNodes( element, &list );
2464 ok( r == S_OK, "get_childNodes returned wrong code\n");
2465
2466 /* using get_item for child list doesn't advance the position */
2467 ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
2468 expect_node(node, "E2.E2.D1");
2469 IXMLDOMNode_Release(node);
2470 ole_check(IXMLDOMNodeList_nextNode(list, &node));
2471 expect_node(node, "E1.E2.D1");
2472 IXMLDOMNode_Release(node);
2473 ole_check(IXMLDOMNodeList_reset(list));
2474
2475 IXMLDOMNodeList_AddRef(list);
2476 expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1");
2477 ole_check(IXMLDOMNodeList_reset(list));
2478
2479 node = (void*)0xdeadbeef;
2480 str = SysAllocString(szdl);
2481 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2482 SysFreeString(str);
2483 ok( r == S_FALSE, "ret %08x\n", r );
2484 ok( node == NULL, "node %p\n", node );
2485
2486 str = SysAllocString(szbs);
2487 r = IXMLDOMElement_selectSingleNode( element, str, &node );
2488 SysFreeString(str);
2489 ok( r == S_OK, "ret %08x\n", r );
2490 r = IXMLDOMNode_Release( node );
2491 ok( r == 0, "ret %08x\n", r );
2492 }
2493 else
2494 ok( FALSE, "no element\n");
2495
2496 if (list)
2497 {
2498 r = IXMLDOMNodeList_get_item(list, 0, NULL);
2499 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2500
2501 r = IXMLDOMNodeList_get_length(list, NULL);
2502 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2503
2504 r = IXMLDOMNodeList_get_length( list, &count );
2505 ok( r == S_OK, "get_length returns %08x\n", r );
2506 ok( count == 4, "get_length got %d\n", count );
2507
2508 r = IXMLDOMNodeList_nextNode(list, NULL);
2509 ok(r == E_INVALIDARG, "Expected E_INVALIDARG got %08x\n", r);
2510
2511 r = IXMLDOMNodeList_nextNode( list, &node );
2512 ok( r == S_OK, "nextNode returned wrong code\n");
2513 }
2514 else
2515 ok( FALSE, "no list\n");
2516
2517 if (node)
2518 {
2519 type = NODE_INVALID;
2520 r = IXMLDOMNode_get_nodeType( node, &type);
2521 ok( r == S_OK, "getNamedItem returned wrong code\n");
2522 ok( type == NODE_ELEMENT, "node not text\n");
2523
2524 r = IXMLDOMNode_hasChildNodes( node, NULL );
2525 ok( r == E_INVALIDARG, "hasChildNodes bad return\n");
2526
2527 EXPECT_CHILDREN(node);
2528
2529 str = NULL;
2530 r = IXMLDOMNode_get_baseName( node, &str );
2531 ok( r == S_OK, "get_baseName returned wrong code\n");
2532 ok( lstrcmpW(str,szbs) == 0, "basename was wrong\n");
2533 SysFreeString(str);
2534 }
2535 else
2536 ok( FALSE, "no node\n");
2537
2538 if (node)
2539 IXMLDOMNode_Release( node );
2540 if (list)
2541 IXMLDOMNodeList_Release( list );
2542 if (element)
2543 IXMLDOMElement_Release( element );
2544
2545 b = FALSE;
2546 str = SysAllocString( szComplete5 );
2547 r = IXMLDOMDocument_loadXML( doc, str, &b );
2548 ok( r == S_OK, "loadXML failed\n");
2549 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2550 SysFreeString( str );
2551
2552 EXPECT_CHILDREN(doc);
2553
2554 r = IXMLDOMDocument_get_documentElement( doc, &element );
2555 ok( r == S_OK, "should be a document element\n");
2556 ok( element != NULL, "should be an element\n");
2557
2558 if (element)
2559 {
2560 static const WCHAR szSSearch[] = {'S',':','s','e','a','r','c','h',0};
2561 BSTR tag = NULL;
2562
2563 /* check if the tag is correct */
2564 r = IXMLDOMElement_get_tagName( element, &tag );
2565 ok( r == S_OK, "couldn't get tag name\n");
2566 ok( tag != NULL, "tag was null\n");
2567 ok( !lstrcmpW( tag, szSSearch ), "incorrect tag name\n");
2568 SysFreeString( tag );
2569
2570 IXMLDOMElement_Release( element );
2571 }
2572 ok(IXMLDOMDocument_Release( doc ) == 0, "document is not destroyed\n");
2573
2574 free_bstrs();
2575 }
2576
2577 typedef struct {
2578 DOMNodeType type;
2579 REFIID iid;
2580 } refcount_test_t;
2581
2582 static const refcount_test_t refcount_test[] = {
2583 { NODE_ELEMENT, &IID_IXMLDOMElement },
2584 { NODE_ATTRIBUTE, &IID_IXMLDOMAttribute },
2585 { NODE_TEXT, &IID_IXMLDOMText },
2586 { NODE_CDATA_SECTION, &IID_IXMLDOMCDATASection },
2587 { NODE_ENTITY_REFERENCE, &IID_IXMLDOMEntityReference },
2588 { NODE_PROCESSING_INSTRUCTION, &IID_IXMLDOMProcessingInstruction },
2589 { NODE_COMMENT, &IID_IXMLDOMComment },
2590 { NODE_DOCUMENT_FRAGMENT, &IID_IXMLDOMDocumentFragment },
2591 { NODE_INVALID, &IID_NULL }
2592 };
2593
2594 static void test_refs(void)
2595 {
2596 IXMLDOMImplementation *impl, *impl2;
2597 IXMLDOMElement *element, *elem2;
2598 IXMLDOMNodeList *node_list = NULL;
2599 IXMLDOMNode *node, *node2, *node3;
2600 const refcount_test_t *ptr;
2601 IXMLDOMDocument *doc;
2602 IUnknown *unk, *unk2;
2603 VARIANT_BOOL b;
2604 HRESULT hr;
2605 LONG ref;
2606
2607 doc = create_document(&IID_IXMLDOMDocument);
2608
2609 ptr = refcount_test;
2610 while (ptr->type != NODE_INVALID)
2611 {
2612 IUnknown *node_typed, *node_typed2;
2613 IDispatchEx *dispex, *dispex2;
2614 IDispatch *disp, *disp2;
2615 VARIANT type;
2616
2617 V_VT(&type) = VT_I1;
2618 V_I1(&type) = ptr->type;
2619
2620 EXPECT_REF(doc, 1);
2621 hr = IXMLDOMDocument_createNode(doc, type, _bstr_("name"), NULL, &node);
2622 EXPECT_HR(hr, S_OK);
2623 EXPECT_REF(doc, 1);
2624 EXPECT_REF(node, 1);
2625
2626 /* try IDispatch and IUnknown from IXMLDOMNode */
2627 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
2628 EXPECT_HR(hr, S_OK);
2629 EXPECT_REF(unk, 2);
2630 todo_wine {
2631 EXPECT_REF(node, 1);
2632 ok(unk != (IUnknown*)node, "%d: got %p and %p\n", ptr->type, unk, node);
2633 }
2634 EXPECT_REF(unk, 2);
2635 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp);
2636 EXPECT_HR(hr, S_OK);
2637 todo_wine ok(unk != (IUnknown*)disp, "%d: got %p and %p\n", ptr->type, unk, disp);
2638 EXPECT_REF(unk, 3);
2639 todo_wine EXPECT_REF(disp, 1);
2640
2641 EXPECT_REF(unk, 3);
2642 hr = IUnknown_QueryInterface(unk, &IID_IDispatch, (void**)&disp2);
2643 EXPECT_HR(hr, S_OK);
2644 todo_wine ok(disp != disp2, "%d: got %p and %p\n", ptr->type, disp, disp2);
2645 EXPECT_REF(unk, 4);
2646 todo_wine EXPECT_REF(disp2, 1);
2647
2648 IDispatch_Release(disp);
2649 IDispatch_Release(disp2);
2650
2651 /* get IXMLDOMNode from this IUnknown */
2652 EXPECT_REF(unk, 2);
2653 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node2);
2654 EXPECT_HR(hr, S_OK);
2655 todo_wine ok(unk != (IUnknown*)node2, "%d: got %p and %p\n", ptr->type, unk, node2);
2656 EXPECT_REF(unk, 3);
2657 todo_wine EXPECT_REF(node2, 1);
2658
2659 EXPECT_REF(unk, 3);
2660 hr = IUnknown_QueryInterface(unk, &IID_IXMLDOMNode, (void**)&node3);
2661 EXPECT_HR(hr, S_OK);
2662 todo_wine ok(node2 != node3, "%d: got %p and %p\n", ptr->type, node2, node3);
2663 EXPECT_REF(unk, 4);
2664 todo_wine EXPECT_REF(node3, 1);
2665
2666 IXMLDOMNode_Release(node2);
2667 IXMLDOMNode_Release(node3);
2668
2669 /* try IDispatchEx from IUnknown */
2670 EXPECT_REF(unk, 2);
2671 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
2672 EXPECT_HR(hr, S_OK);
2673 ok(unk != (IUnknown*)dispex, "%d: got %p and %p\n", ptr->type, unk, dispex);
2674 EXPECT_REF(unk, 3);
2675 todo_wine EXPECT_REF(dispex, 1);
2676
2677 EXPECT_REF(unk, 3);
2678 hr = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex2);
2679 EXPECT_HR(hr, S_OK);
2680 todo_wine ok(dispex != dispex2, "%d: got %p and %p\n", ptr->type, dispex, dispex2);
2681 EXPECT_REF(unk, 4);
2682 todo_wine EXPECT_REF(dispex2, 1);
2683
2684 IDispatchEx_Release(dispex);
2685 IDispatchEx_Release(dispex2);
2686
2687 /* try corresponding IXMLDOM* */
2688 EXPECT_REF(unk, 2);
2689 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed);
2690 EXPECT_HR(hr, S_OK);
2691 EXPECT_REF(unk, 3);
2692 hr = IUnknown_QueryInterface(unk, ptr->iid, (void**)&node_typed2);
2693 EXPECT_HR(hr, S_OK);
2694 EXPECT_REF(unk, 4);
2695 todo_wine ok(node_typed != node_typed2, "%d: got %p and %p\n", ptr->type, node_typed, node_typed2);
2696 IUnknown_Release(node_typed);
2697 IUnknown_Release(node_typed2);
2698
2699 /* try invalid IXMLDOM* */
2700 hr = IUnknown_QueryInterface(unk, (ptr+1)->iid, (void**)&node_typed);
2701 EXPECT_HR(hr, E_NOINTERFACE);
2702
2703 IUnknown_Release(unk);
2704
2705 EXPECT_REF(node, 1);
2706 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMNode, (void**)&node2);
2707 EXPECT_HR(hr, S_OK);
2708 EXPECT_REF(node, 2);
2709 ok(node == node2, "%d: got %p and %p\n", ptr->type, node, node2);
2710
2711 EXPECT_REF(node, 2);
2712 hr = IXMLDOMNode_QueryInterface(node, ptr->iid, (void**)&node_typed);
2713 EXPECT_HR(hr, S_OK);
2714 EXPECT_REF(node, 3);
2715 todo_wine {
2716 EXPECT_REF(node_typed, 2);
2717 ok((IUnknown*)node != node_typed, "%d: got %p and %p\n", ptr->type, node, node_typed);
2718 }
2719 IUnknown_Release(node_typed);
2720
2721 IXMLDOMNode_Release(node2);
2722 IXMLDOMNode_Release(node);
2723
2724 ptr++;
2725 }
2726
2727 EXPECT_REF(doc, 1);
2728 ref = IXMLDOMDocument_Release(doc);
2729 ok( ref == 0, "ref %d\n", ref);
2730
2731 /* check IUnknown after releasing DOM iface */
2732 doc = create_document(&IID_IXMLDOMDocument);
2733 EXPECT_REF(doc, 1);
2734 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2735 EXPECT_HR(hr, S_OK);
2736 todo_wine {
2737 EXPECT_REF(unk, 3);
2738 EXPECT_REF(doc, 1);
2739 }
2740 IXMLDOMDocument_Release(doc);
2741 EXPECT_REF(unk, 1);
2742 IUnknown_Release(unk);
2743
2744 doc = create_document(&IID_IXMLDOMDocument);
2745
2746 EXPECT_REF(doc, 1);
2747 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2748 EXPECT_HR(hr, S_OK);
2749 todo_wine {
2750 EXPECT_REF(unk, 3);
2751 EXPECT_REF(doc, 1);
2752 }
2753 IUnknown_Release(unk);
2754
2755 /* IXMLDOMImplementation */
2756 EXPECT_REF(doc, 1);
2757 hr = IXMLDOMDocument_get_implementation(doc, &impl);
2758 EXPECT_HR(hr, S_OK);
2759 EXPECT_REF(doc, 1);
2760 EXPECT_REF(impl, 1);
2761 hr = IXMLDOMDocument_get_implementation(doc, &impl2);
2762 EXPECT_HR(hr, S_OK);
2763 EXPECT_REF(doc, 1);
2764 EXPECT_REF(impl2, 1);
2765 ok(impl != impl2, "got %p, %p\n", impl, impl2);
2766 IXMLDOMImplementation_Release(impl);
2767 IXMLDOMImplementation_Release(impl2);
2768
2769 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
2770 EXPECT_HR(hr, S_OK);
2771 ok( b == VARIANT_TRUE, "failed to load XML string\n");
2772
2773 EXPECT_REF(doc, 1);
2774 IXMLDOMDocument_AddRef( doc );
2775 EXPECT_REF(doc, 2);
2776 IXMLDOMDocument_AddRef( doc );
2777 EXPECT_REF(doc, 3);
2778
2779 IXMLDOMDocument_Release( doc );
2780 IXMLDOMDocument_Release( doc );
2781
2782 EXPECT_REF(doc, 1);
2783 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
2784 EXPECT_HR(hr, S_OK);
2785 todo_wine {
2786 EXPECT_REF(unk, 3);
2787 EXPECT_REF(doc, 1);
2788 }
2789 hr = IXMLDOMDocument_get_documentElement(doc, &element);
2790 EXPECT_HR(hr, S_OK);
2791 todo_wine {
2792 EXPECT_REF(doc, 1);
2793 EXPECT_REF(element, 2);
2794 }
2795 hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
2796 EXPECT_HR(hr, S_OK);
2797
2798 todo_wine {
2799 EXPECT_REF(doc, 1);
2800 EXPECT_REF(element, 2);
2801 EXPECT_REF(elem2, 2);
2802 }
2803 IXMLDOMElement_AddRef(element);
2804 todo_wine EXPECT_REF(element, 3);
2805 IXMLDOMElement_Release(element);
2806
2807 /* get IUnknown from a node doesn't touch node instance refcount */
2808 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2809 EXPECT_HR(hr, S_OK);
2810 EXPECT_REF(element, 2);
2811 todo_wine {
2812 EXPECT_REF(unk, 4);
2813 EXPECT_REF(elem2, 2);
2814 }
2815 hr = IXMLDOMElement_QueryInterface(elem2, &IID_IUnknown, (void**)&unk2);
2816 EXPECT_HR(hr, S_OK);
2817 todo_wine {
2818 EXPECT_REF(unk, 5);
2819 EXPECT_REF(unk2, 5);
2820 }
2821 EXPECT_REF(element, 2);
2822 EXPECT_REF(elem2, 2);
2823
2824 todo_wine ok(unk == unk2, "got %p and %p\n", unk, unk2);
2825 IUnknown_Release(unk);
2826
2827 /* IUnknown refcount is not affected by node refcount */
2828 todo_wine EXPECT_REF(unk2, 4);
2829 IXMLDOMElement_AddRef(elem2);
2830 todo_wine EXPECT_REF(unk2, 4);
2831 IXMLDOMElement_Release(elem2);
2832
2833 IXMLDOMElement_Release(elem2);
2834 todo_wine EXPECT_REF(unk2, 3);
2835
2836 IUnknown_Release(unk2);
2837
2838 hr = IXMLDOMElement_get_childNodes( element, &node_list );
2839 EXPECT_HR(hr, S_OK);
2840
2841 todo_wine EXPECT_REF(element, 2);
2842 EXPECT_REF(node_list, 1);
2843
2844 hr = IXMLDOMNodeList_get_item( node_list, 0, &node );
2845 EXPECT_HR(hr, S_OK);
2846 EXPECT_REF(node_list, 1);
2847 EXPECT_REF(node, 1);
2848
2849 hr = IXMLDOMNodeList_get_item( node_list, 0, &node2 );
2850 EXPECT_HR(hr, S_OK);
2851 EXPECT_REF(node_list, 1);
2852 EXPECT_REF(node2, 1);
2853
2854 ref = IXMLDOMNode_Release( node );
2855 ok( ref == 0, "ref %d\n", ref );
2856 ref = IXMLDOMNode_Release( node2 );
2857 ok( ref == 0, "ref %d\n", ref );
2858
2859 ref = IXMLDOMNodeList_Release( node_list );
2860 ok( ref == 0, "ref %d\n", ref );
2861
2862 ok( node != node2, "node %p node2 %p\n", node, node2 );
2863
2864 ref = IXMLDOMDocument_Release( doc );
2865 todo_wine ok( ref == 0, "ref %d\n", ref );
2866
2867 todo_wine EXPECT_REF(element, 2);
2868
2869 /* IUnknown must be unique however we obtain it */
2870 hr = IXMLDOMElement_QueryInterface(element, &IID_IUnknown, (void**)&unk);
2871 EXPECT_HR(hr, S_OK);
2872 EXPECT_REF(element, 2);
2873 hr = IXMLDOMElement_QueryInterface(element, &IID_IXMLDOMNode, (void**)&node);
2874 EXPECT_HR(hr, S_OK);
2875 todo_wine EXPECT_REF(element, 2);
2876 hr = IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk2);
2877 EXPECT_HR(hr, S_OK);
2878 todo_wine EXPECT_REF(element, 2);
2879 ok(unk == unk2, "unk %p unk2 %p\n", unk, unk2);
2880 todo_wine ok(element != (void*)node, "node %p element %p\n", node, element);
2881
2882 IUnknown_Release( unk2 );
2883 IUnknown_Release( unk );
2884 IXMLDOMNode_Release( node );
2885 todo_wine EXPECT_REF(element, 2);
2886
2887 IXMLDOMElement_Release( element );
2888
2889 free_bstrs();
2890 }
2891
2892 static void test_create(void)
2893 {
2894 static const WCHAR szOne[] = {'1',0};
2895 static const WCHAR szOneGarbage[] = {'1','G','a','r','b','a','g','e',0};
2896 HRESULT r;
2897 VARIANT var;
2898 BSTR str, name;
2899 IXMLDOMDocument *doc;
2900 IXMLDOMElement *element;
2901 IXMLDOMComment *comment;
2902 IXMLDOMText *text;
2903 IXMLDOMCDATASection *cdata;
2904 IXMLDOMNode *root, *node, *child;
2905 IXMLDOMNamedNodeMap *attr_map;
2906 IUnknown *unk;
2907 LONG ref;
2908 LONG num;
2909
2910 doc = create_document(&IID_IXMLDOMDocument);
2911
2912 EXPECT_REF(doc, 1);
2913
2914 /* types not supported for creation */
2915 V_VT(&var) = VT_I1;
2916 V_I1(&var) = NODE_DOCUMENT;
2917 node = (IXMLDOMNode*)0x1;
2918 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2919 ok( r == E_INVALIDARG, "returns %08x\n", r );
2920 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2921
2922 V_VT(&var) = VT_I1;
2923 V_I1(&var) = NODE_DOCUMENT_TYPE;
2924 node = (IXMLDOMNode*)0x1;
2925 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2926 ok( r == E_INVALIDARG, "returns %08x\n", r );
2927 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2928
2929 V_VT(&var) = VT_I1;
2930 V_I1(&var) = NODE_ENTITY;
2931 node = (IXMLDOMNode*)0x1;
2932 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2933 ok( r == E_INVALIDARG, "returns %08x\n", r );
2934 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2935
2936 V_VT(&var) = VT_I1;
2937 V_I1(&var) = NODE_NOTATION;
2938 node = (IXMLDOMNode*)0x1;
2939 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2940 ok( r == E_INVALIDARG, "returns %08x\n", r );
2941 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
2942
2943 /* NODE_COMMENT */
2944 V_VT(&var) = VT_I1;
2945 V_I1(&var) = NODE_COMMENT;
2946 node = NULL;
2947 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2948 ok( r == S_OK, "returns %08x\n", r );
2949 ok( node != NULL, "\n");
2950
2951 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2952 ok( r == S_OK, "returns %08x\n", r );
2953 IXMLDOMNode_Release(node);
2954
2955 str = NULL;
2956 r = IXMLDOMComment_get_data(comment, &str);
2957 ok( r == S_OK, "returns %08x\n", r );
2958 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2959 IXMLDOMComment_Release(comment);
2960 SysFreeString(str);
2961
2962 node = (IXMLDOMNode*)0x1;
2963 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
2964 ok( r == S_OK, "returns %08x\n", r );
2965
2966 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2967 ok( r == S_OK, "returns %08x\n", r );
2968 IXMLDOMNode_Release(node);
2969
2970 str = NULL;
2971 r = IXMLDOMComment_get_data(comment, &str);
2972 ok( r == S_OK, "returns %08x\n", r );
2973 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2974 IXMLDOMComment_Release(comment);
2975 SysFreeString(str);
2976
2977 node = (IXMLDOMNode*)0x1;
2978 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
2979 ok( r == S_OK, "returns %08x\n", r );
2980
2981 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
2982 ok( r == S_OK, "returns %08x\n", r );
2983 IXMLDOMNode_Release(node);
2984
2985 str = NULL;
2986 r = IXMLDOMComment_get_data(comment, &str);
2987 ok( r == S_OK, "returns %08x\n", r );
2988 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
2989 IXMLDOMComment_Release(comment);
2990 SysFreeString(str);
2991
2992 /* NODE_TEXT */
2993 V_VT(&var) = VT_I1;
2994 V_I1(&var) = NODE_TEXT;
2995 node = NULL;
2996 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
2997 ok( r == S_OK, "returns %08x\n", r );
2998 ok( node != NULL, "\n");
2999
3000 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3001 ok( r == S_OK, "returns %08x\n", r );
3002 IXMLDOMNode_Release(node);
3003
3004 str = NULL;
3005 r = IXMLDOMText_get_data(text, &str);
3006 ok( r == S_OK, "returns %08x\n", r );
3007 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3008 IXMLDOMText_Release(text);
3009 SysFreeString(str);
3010
3011 node = (IXMLDOMNode*)0x1;
3012 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3013 ok( r == S_OK, "returns %08x\n", r );
3014
3015 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3016 ok( r == S_OK, "returns %08x\n", r );
3017 IXMLDOMNode_Release(node);
3018
3019 str = NULL;
3020 r = IXMLDOMText_get_data(text, &str);
3021 ok( r == S_OK, "returns %08x\n", r );
3022 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3023 IXMLDOMText_Release(text);
3024 SysFreeString(str);
3025
3026 node = (IXMLDOMNode*)0x1;
3027 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3028 ok( r == S_OK, "returns %08x\n", r );
3029
3030 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
3031 ok( r == S_OK, "returns %08x\n", r );
3032 IXMLDOMNode_Release(node);
3033
3034 str = NULL;
3035 r = IXMLDOMText_get_data(text, &str);
3036 ok( r == S_OK, "returns %08x\n", r );
3037 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3038 IXMLDOMText_Release(text);
3039 SysFreeString(str);
3040
3041 /* NODE_CDATA_SECTION */
3042 V_VT(&var) = VT_I1;
3043 V_I1(&var) = NODE_CDATA_SECTION;
3044 node = NULL;
3045 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3046 ok( r == S_OK, "returns %08x\n", r );
3047 ok( node != NULL, "\n");
3048
3049 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3050 ok( r == S_OK, "returns %08x\n", r );
3051 IXMLDOMNode_Release(node);
3052
3053 str = NULL;
3054 r = IXMLDOMCDATASection_get_data(cdata, &str);
3055 ok( r == S_OK, "returns %08x\n", r );
3056 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3057 IXMLDOMCDATASection_Release(cdata);
3058 SysFreeString(str);
3059
3060 node = (IXMLDOMNode*)0x1;
3061 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3062 ok( r == S_OK, "returns %08x\n", r );
3063
3064 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3065 ok( r == S_OK, "returns %08x\n", r );
3066 IXMLDOMNode_Release(node);
3067
3068 str = NULL;
3069 r = IXMLDOMCDATASection_get_data(cdata, &str);
3070 ok( r == S_OK, "returns %08x\n", r );
3071 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3072 IXMLDOMCDATASection_Release(cdata);
3073 SysFreeString(str);
3074
3075 node = (IXMLDOMNode*)0x1;
3076 r = IXMLDOMDocument_createNode( doc, var, _bstr_("blah"), NULL, &node );
3077 ok( r == S_OK, "returns %08x\n", r );
3078
3079 r = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
3080 ok( r == S_OK, "returns %08x\n", r );
3081 IXMLDOMNode_Release(node);
3082
3083 str = NULL;
3084 r = IXMLDOMCDATASection_get_data(cdata, &str);
3085 ok( r == S_OK, "returns %08x\n", r );
3086 ok( str && SysStringLen(str) == 0, "expected empty comment, %p\n", str);
3087 IXMLDOMCDATASection_Release(cdata);
3088 SysFreeString(str);
3089
3090 /* NODE_ATTRIBUTE */
3091 V_VT(&var) = VT_I1;
3092 V_I1(&var) = NODE_ATTRIBUTE;
3093 node = (IXMLDOMNode*)0x1;
3094 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3095 ok( r == E_FAIL, "returns %08x\n", r );
3096 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3097
3098 V_VT(&var) = VT_I1;
3099 V_I1(&var) = NODE_ATTRIBUTE;
3100 node = (IXMLDOMNode*)0x1;
3101 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3102 ok( r == E_FAIL, "returns %08x\n", r );
3103 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3104
3105 V_VT(&var) = VT_I1;
3106 V_I1(&var) = NODE_ATTRIBUTE;
3107 str = SysAllocString( szlc );
3108 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3109 ok( r == S_OK, "returns %08x\n", r );
3110 if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3111 SysFreeString(str);
3112
3113 /* a name is required for attribute, try a BSTR with first null wchar */
3114 V_VT(&var) = VT_I1;
3115 V_I1(&var) = NODE_ATTRIBUTE;
3116 str = SysAllocString( szstr1 );
3117 str[0] = 0;
3118 node = (IXMLDOMNode*)0x1;
3119 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3120 ok( r == E_FAIL, "returns %08x\n", r );
3121 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3122 SysFreeString(str);
3123
3124 /* NODE_PROCESSING_INSTRUCTION */
3125 V_VT(&var) = VT_I1;
3126 V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3127 node = (IXMLDOMNode*)0x1;
3128 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3129 ok( r == E_FAIL, "returns %08x\n", r );
3130 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3131
3132 V_VT(&var) = VT_I1;
3133 V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3134 node = (IXMLDOMNode*)0x1;
3135 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3136 ok( r == E_FAIL, "returns %08x\n", r );
3137 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3138
3139 V_VT(&var) = VT_I1;
3140 V_I1(&var) = NODE_PROCESSING_INSTRUCTION;
3141 r = IXMLDOMDocument_createNode( doc, var, _bstr_("pi"), NULL, NULL );
3142 ok( r == E_INVALIDARG, "returns %08x\n", r );
3143
3144 /* NODE_ENTITY_REFERENCE */
3145 V_VT(&var) = VT_I1;
3146 V_I1(&var) = NODE_ENTITY_REFERENCE;
3147 node = (IXMLDOMNode*)0x1;
3148 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3149 ok( r == E_FAIL, "returns %08x\n", r );
3150 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3151
3152 V_VT(&var) = VT_I1;
3153 V_I1(&var) = NODE_ENTITY_REFERENCE;
3154 node = (IXMLDOMNode*)0x1;
3155 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3156 ok( r == E_FAIL, "returns %08x\n", r );
3157 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3158
3159 /* NODE_ELEMENT */
3160 V_VT(&var) = VT_I1;
3161 V_I1(&var) = NODE_ELEMENT;
3162 node = (IXMLDOMNode*)0x1;
3163 r = IXMLDOMDocument_createNode( doc, var, NULL, NULL, &node );
3164 ok( r == E_FAIL, "returns %08x\n", r );
3165 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3166
3167 V_VT(&var) = VT_I1;
3168 V_I1(&var) = NODE_ELEMENT;
3169 node = (IXMLDOMNode*)0x1;
3170 r = IXMLDOMDocument_createNode( doc, var, _bstr_(""), NULL, &node );
3171 ok( r == E_FAIL, "returns %08x\n", r );
3172 ok( node == (void*)0x1, "expected same ptr, got %p\n", node);
3173
3174 V_VT(&var) = VT_I1;
3175 V_I1(&var) = NODE_ELEMENT;
3176 str = SysAllocString( szlc );
3177 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3178 ok( r == S_OK, "returns %08x\n", r );
3179 if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3180
3181 V_VT(&var) = VT_I1;
3182 V_I1(&var) = NODE_ELEMENT;
3183 r = IXMLDOMDocument_createNode( doc, var, str, NULL, NULL );
3184 ok( r == E_INVALIDARG, "returns %08x\n", r );
3185
3186 V_VT(&var) = VT_R4;
3187 V_R4(&var) = NODE_ELEMENT;
3188 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3189 ok( r == S_OK, "returns %08x\n", r );
3190 if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3191
3192 V_VT(&var) = VT_BSTR;
3193 V_BSTR(&var) = SysAllocString( szOne );
3194 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3195 ok( r == S_OK, "returns %08x\n", r );
3196 if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3197 VariantClear(&var);
3198
3199 V_VT(&var) = VT_BSTR;
3200 V_BSTR(&var) = SysAllocString( szOneGarbage );
3201 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3202 ok( r == E_INVALIDARG, "returns %08x\n", r );
3203 if( SUCCEEDED(r) ) IXMLDOMNode_Release( node );
3204 VariantClear(&var);
3205
3206 V_VT(&var) = VT_I4;
3207 V_I4(&var) = NODE_ELEMENT;
3208 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3209 ok( r == S_OK, "returns %08x\n", r );
3210
3211 EXPECT_REF(doc, 1);
3212 r = IXMLDOMDocument_appendChild( doc, node, &root );
3213 ok( r == S_OK, "returns %08x\n", r );
3214 ok( node == root, "%p %p\n", node, root );
3215 EXPECT_REF(doc, 1);
3216
3217 EXPECT_REF(node, 2);
3218
3219 ref = IXMLDOMNode_Release( node );
3220 ok(ref == 1, "ref %d\n", ref);
3221 SysFreeString( str );
3222
3223 V_VT(&var) = VT_I4;
3224 V_I4(&var) = NODE_ELEMENT;
3225 str = SysAllocString( szbs );
3226 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3227 ok( r == S_OK, "returns %08x\n", r );
3228 SysFreeString( str );
3229
3230 EXPECT_REF(node, 1);
3231
3232 r = IXMLDOMNode_QueryInterface( node, &IID_IUnknown, (void**)&unk );
3233 ok( r == S_OK, "returns %08x\n", r );
3234
3235 EXPECT_REF(unk, 2);
3236
3237 V_VT(&var) = VT_EMPTY;
3238 child = NULL;
3239 r = IXMLDOMNode_insertBefore( root, (IXMLDOMNode*)unk, var, &child );
3240 ok( r == S_OK, "returns %08x\n", r );
3241 ok( unk == (IUnknown*)child, "%p %p\n", unk, child );
3242
3243 todo_wine EXPECT_REF(unk, 4);
3244
3245 IXMLDOMNode_Release( child );
3246 IUnknown_Release( unk );
3247
3248 V_VT(&var) = VT_NULL;
3249 V_DISPATCH(&var) = (IDispatch*)node;
3250 r = IXMLDOMNode_insertBefore( root, node, var, &child );
3251 ok( r == S_OK, "returns %08x\n", r );
3252 ok( node == child, "%p %p\n", node, child );
3253 IXMLDOMNode_Release( child );
3254
3255 V_VT(&var) = VT_NULL;
3256 V_DISPATCH(&var) = (IDispatch*)node;
3257 r = IXMLDOMNode_insertBefore( root, node, var, NULL );
3258 ok( r == S_OK, "returns %08x\n", r );
3259 IXMLDOMNode_Release( node );
3260
3261 r = IXMLDOMNode_QueryInterface( root, &IID_IXMLDOMElement, (void**)&element );
3262 ok( r == S_OK, "returns %08x\n", r );
3263
3264 r = IXMLDOMElement_get_attributes( element, &attr_map );
3265 ok( r == S_OK, "returns %08x\n", r );
3266 r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3267 ok( r == S_OK, "returns %08x\n", r );
3268 ok( num == 0, "num %d\n", num );
3269 IXMLDOMNamedNodeMap_Release( attr_map );
3270
3271 V_VT(&var) = VT_BSTR;
3272 V_BSTR(&var) = SysAllocString( szstr1 );
3273 name = SysAllocString( szdl );
3274 r = IXMLDOMElement_setAttribute( element, name, var );
3275 ok( r == S_OK, "returns %08x\n", r );
3276 r = IXMLDOMElement_get_attributes( element, &attr_map );
3277 ok( r == S_OK, "returns %08x\n", r );
3278 r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3279 ok( r == S_OK, "returns %08x\n", r );
3280 ok( num == 1, "num %d\n", num );
3281 IXMLDOMNamedNodeMap_Release( attr_map );
3282 VariantClear(&var);
3283
3284 V_VT(&var) = VT_BSTR;
3285 V_BSTR(&var) = SysAllocString( szstr2 );
3286 r = IXMLDOMElement_setAttribute( element, name, var );
3287 ok( r == S_OK, "returns %08x\n", r );
3288 r = IXMLDOMElement_get_attributes( element, &attr_map );
3289 ok( r == S_OK, "returns %08x\n", r );
3290 r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3291 ok( r == S_OK, "returns %08x\n", r );
3292 ok( num == 1, "num %d\n", num );
3293 IXMLDOMNamedNodeMap_Release( attr_map );
3294 VariantClear(&var);
3295 r = IXMLDOMElement_getAttribute( element, name, &var );
3296 ok( r == S_OK, "returns %08x\n", r );
3297 ok( !lstrcmpW(V_BSTR(&var), szstr2), "wrong attr value\n");
3298 VariantClear(&var);
3299 SysFreeString(name);
3300
3301 V_VT(&var) = VT_BSTR;
3302 V_BSTR(&var) = SysAllocString( szstr1 );
3303 name = SysAllocString( szlc );
3304 r = IXMLDOMElement_setAttribute( element, name, var );
3305 ok( r == S_OK, "returns %08x\n", r );
3306 r = IXMLDOMElement_get_attributes( element, &attr_map );
3307 ok( r == S_OK, "returns %08x\n", r );
3308 r = IXMLDOMNamedNodeMap_get_length( attr_map, &num );
3309 ok( r == S_OK, "returns %08x\n", r );
3310 ok( num == 2, "num %d\n", num );
3311 IXMLDOMNamedNodeMap_Release( attr_map );
3312 VariantClear(&var);
3313 SysFreeString(name);
3314
3315 V_VT(&var) = VT_I4;
3316 V_I4(&var) = 10;
3317 name = SysAllocString( szbs );
3318 r = IXMLDOMElement_setAttribute( element, name, var );
3319 ok( r == S_OK, "returns %08x\n", r );
3320 VariantClear(&var);
3321 r = IXMLDOMElement_getAttribute( element, name, &var );
3322 ok( r == S_OK, "returns %08x\n", r );
3323 ok( V_VT(&var) == VT_BSTR, "variant type %x\n", V_VT(&var));
3324 VariantClear(&var);
3325 SysFreeString(name);
3326
3327 /* Create an Attribute */
3328 V_VT(&var) = VT_I4;
3329 V_I4(&var) = NODE_ATTRIBUTE;
3330 str = SysAllocString( szAttribute );
3331 r = IXMLDOMDocument_createNode( doc, var, str, NULL, &node );
3332 ok( r == S_OK, "returns %08x\n", r );
3333 ok( node != NULL, "node was null\n");
3334 SysFreeString(str);
3335
3336 IXMLDOMElement_Release( element );
3337 IXMLDOMNode_Release( root );
3338 IXMLDOMDocument_Release( doc );
3339 }
3340
3341 struct queryresult_t {
3342 const char *query;
3343 const char *result;
3344 int len;
3345 };
3346
3347 static const struct queryresult_t elementsbytagname[] = {
3348 { "", "P1.D1 E2.D1 E1.E2.D1 T1.E1.E2.D1 E2.E2.D1 T1.E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1 T1.E1.E4.E2.D1", 10 },
3349 { "*", "E2.D1 E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1", 6 },
3350 { "bs", "E1.E2.D1", 1 },
3351 { "dl", "", 0 },
3352 { "str1","", 0 },
3353 { NULL }
3354 };
3355
3356 static void test_getElementsByTagName(void)
3357 {
3358 const struct queryresult_t *ptr = elementsbytagname;
3359 IXMLDOMNodeList *node_list;
3360 IXMLDOMDocument *doc;
3361 IXMLDOMElement *elem;
3362 WCHAR buff[100];
3363 VARIANT_BOOL b;
3364 HRESULT r;
3365 LONG len;
3366 BSTR str;
3367
3368 doc = create_document(&IID_IXMLDOMDocument);
3369
3370 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3371 ok( r == S_OK, "loadXML failed\n");
3372 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3373
3374 /* null arguments cases */
3375 r = IXMLDOMDocument_getElementsByTagName(doc, NULL, &node_list);
3376 ok( r == E_INVALIDARG, "ret %08x\n", r );
3377 r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), NULL);
3378 ok( r == E_INVALIDARG, "ret %08x\n", r );
3379
3380 while (ptr->query)
3381 {
3382 r = IXMLDOMDocument_getElementsByTagName(doc, _bstr_(ptr->query), &node_list);
3383 ok(r == S_OK, "ret %08x\n", r);
3384 r = IXMLDOMNodeList_get_length(node_list, &len);
3385 ok(r == S_OK, "ret %08x\n", r);
3386 ok(len == ptr->len, "%s: got len %d, expected %d\n", ptr->query, len, ptr->len);
3387 expect_list_and_release(node_list, ptr->result);
3388
3389 free_bstrs();
3390 ptr++;
3391 }
3392
3393 /* broken query BSTR */
3394 memcpy(&buff[2], szstar, sizeof(szstar));
3395 /* just a big length */
3396 *(DWORD*)buff = 0xf0f0;
3397 r = IXMLDOMDocument_getElementsByTagName(doc, &buff[2], &node_list);
3398 ok( r == S_OK, "ret %08x\n", r );
3399 r = IXMLDOMNodeList_get_length( node_list, &len );
3400 ok( r == S_OK, "ret %08x\n", r );
3401 ok( len == 6, "len %d\n", len );
3402 IXMLDOMNodeList_Release( node_list );
3403
3404 /* test for element */
3405 r = IXMLDOMDocument_get_documentElement(doc, &elem);
3406 ok( r == S_OK, "ret %08x\n", r );
3407
3408 str = SysAllocString( szstar );
3409
3410 /* null arguments cases */
3411 r = IXMLDOMElement_getElementsByTagName(elem, NULL, &node_list);
3412 ok( r == E_INVALIDARG, "ret %08x\n", r );
3413 r = IXMLDOMElement_getElementsByTagName(elem, str, NULL);
3414 ok( r == E_INVALIDARG, "ret %08x\n", r );
3415
3416 r = IXMLDOMElement_getElementsByTagName(elem, str, &node_list);
3417 ok( r == S_OK, "ret %08x\n", r );
3418 r = IXMLDOMNodeList_get_length( node_list, &len );
3419 ok( r == S_OK, "ret %08x\n", r );
3420 ok( len == 5, "len %d\n", len );
3421 expect_list_and_release(node_list, "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1 E1.E4.E2.D1");
3422 SysFreeString( str );
3423
3424 /* broken query BSTR */
3425 memcpy(&buff[2], szstar, sizeof(szstar));
3426 /* just a big length */
3427 *(DWORD*)buff = 0xf0f0;
3428 r = IXMLDOMElement_getElementsByTagName(elem, &buff[2], &node_list);
3429 ok( r == S_OK, "ret %08x\n", r );
3430 r = IXMLDOMNodeList_get_length( node_list, &len );
3431 ok( r == S_OK, "ret %08x\n", r );
3432 ok( len == 5, "len %d\n", len );
3433 IXMLDOMNodeList_Release( node_list );
3434
3435 IXMLDOMElement_Release(elem);
3436
3437 IXMLDOMDocument_Release( doc );
3438
3439 free_bstrs();
3440 }
3441
3442 static void test_get_text(void)
3443 {
3444 HRESULT r;
3445 BSTR str;
3446 VARIANT_BOOL b;
3447 IXMLDOMDocument *doc;
3448 IXMLDOMNode *node, *node2, *node3;
3449 IXMLDOMNode *nodeRoot;
3450 IXMLDOMNodeList *node_list;
3451 IXMLDOMNamedNodeMap *node_map;
3452 LONG len;
3453
3454 doc = create_document(&IID_IXMLDOMDocument);
3455
3456 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3457 ok( r == S_OK, "loadXML failed\n");
3458 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3459
3460 str = SysAllocString( szbs );
3461 r = IXMLDOMDocument_getElementsByTagName( doc, str, &node_list );
3462 ok( r == S_OK, "ret %08x\n", r );
3463 SysFreeString(str);
3464
3465 /* Test to get all child node text. */
3466 r = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&nodeRoot);
3467 ok( r == S_OK, "ret %08x\n", r );
3468 if(r == S_OK)
3469 {
3470 r = IXMLDOMNode_get_text( nodeRoot, &str );
3471 ok( r == S_OK, "ret %08x\n", r );
3472 expect_bstr_eq_and_free(str, "fn1.txt\n \nfn2.txt\n \nf1");
3473
3474 IXMLDOMNode_Release(nodeRoot);
3475 }
3476
3477 r = IXMLDOMNodeList_get_length( node_list, NULL );
3478 ok( r == E_INVALIDARG, "ret %08x\n", r );
3479
3480 r = IXMLDOMNodeList_get_length( node_list, &len );
3481 ok( r == S_OK, "ret %08x\n", r );
3482 ok( len == 1, "expect 1 got %d\n", len );
3483
3484 r = IXMLDOMNodeList_get_item( node_list, 0, NULL );
3485 ok( r == E_INVALIDARG, "ret %08x\n", r );
3486
3487 r = IXMLDOMNodeList_nextNode( node_list, NULL );
3488 ok( r == E_INVALIDARG, "ret %08x\n", r );
3489
3490 r = IXMLDOMNodeList_get_item( node_list, 0, &node );
3491 ok( r == S_OK, "ret %08x\n", r );
3492 IXMLDOMNodeList_Release( node_list );
3493
3494 /* Invalid output parameter*/
3495 r = IXMLDOMNode_get_text( node, NULL );
3496 ok( r == E_INVALIDARG, "ret %08x\n", r );
3497
3498 r = IXMLDOMNode_get_text( node, &str );
3499 ok( r == S_OK, "ret %08x\n", r );
3500 ok( !memcmp(str, szfn1_txt, lstrlenW(szfn1_txt) ), "wrong string\n" );
3501 SysFreeString(str);
3502
3503 r = IXMLDOMNode_get_attributes( node, &node_map );
3504 ok( r == S_OK, "ret %08x\n", r );
3505
3506 str = SysAllocString( szvr );
3507 r = IXMLDOMNamedNodeMap_getNamedItem( node_map, str, &node2 );
3508 ok( r == S_OK, "ret %08x\n", r );
3509 SysFreeString(str);
3510
3511 r = IXMLDOMNode_get_text( node2, &str );
3512 ok( r == S_OK, "ret %08x\n", r );
3513 ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3514 SysFreeString(str);
3515
3516 r = IXMLDOMNode_get_firstChild( node2, &node3 );
3517 ok( r == S_OK, "ret %08x\n", r );
3518
3519 r = IXMLDOMNode_get_text( node3, &str );
3520 ok( r == S_OK, "ret %08x\n", r );
3521 ok( !memcmp(str, szstr2, sizeof(szstr2)), "wrong string\n" );
3522 SysFreeString(str);
3523
3524
3525 IXMLDOMNode_Release( node3 );
3526 IXMLDOMNode_Release( node2 );
3527 IXMLDOMNamedNodeMap_Release( node_map );
3528 IXMLDOMNode_Release( node );
3529 IXMLDOMDocument_Release( doc );
3530
3531 free_bstrs();
3532 }
3533
3534 #ifdef __REACTOS__
3535 /*
3536 * This function is to display that xmlnodelist_QueryInterface
3537 * generates SEGV for these conditions, and once fixed make sure
3538 * it never does it again.
3539 */
3540 static void verify_nodelist_query_interface(IXMLDOMNodeList *node_list)
3541 {
3542 HRESULT hr;
3543 /*
3544 * NOTE: The following calls are supposed to test wine's
3545 * xmlnodelist_QueryInterface behaving properly.
3546 * While we should be able to expect E_POINTER (due to the NULL pointer),
3547 * it seems MS' own implementation(s) violate the spec and return
3548 * E_INVALIDARG. To not get cought be a potentially correct implementation
3549 * in the future, we check for NOT S_OK.
3550 */
3551 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, NULL);
3552 EXPECT_NOT_HR(hr, S_OK);
3553 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatch, NULL);
3554 EXPECT_NOT_HR(hr, S_OK);
3555 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IXMLDOMNodeList, NULL);
3556 EXPECT_NOT_HR(hr, S_OK);
3557 }
3558 #endif
3559
3560 static void test_get_childNodes(void)
3561 {
3562 IXMLDOMNodeList *node_list, *node_list2;
3563 IEnumVARIANT *enum1, *enum2, *enum3;
3564 VARIANT_BOOL b;
3565 IXMLDOMDocument *doc;
3566 IXMLDOMNode *node, *node2;
3567 IXMLDOMElement *element;
3568 IUnknown *unk1, *unk2;
3569 HRESULT hr;
3570 VARIANT v;
3571 BSTR str;
3572 LONG len;
3573
3574 doc = create_document(&IID_IXMLDOMDocument);
3575
3576 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3577 EXPECT_HR(hr, S_OK);
3578 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3579
3580 hr = IXMLDOMDocument_get_documentElement( doc, &element );
3581 EXPECT_HR(hr, S_OK);
3582
3583 hr = IXMLDOMElement_get_childNodes( element, &node_list );
3584 EXPECT_HR(hr, S_OK);
3585
3586 #ifdef __REACTOS__
3587 verify_nodelist_query_interface(node_list);
3588 #endif
3589
3590 hr = IXMLDOMNodeList_get_length( node_list, &len );
3591 EXPECT_HR(hr, S_OK);
3592 ok( len == 4, "len %d\n", len);
3593
3594 /* refcount tests for IEnumVARIANT support */
3595 EXPECT_REF(node_list, 1);
3596 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum1);
3597 EXPECT_HR(hr, S_OK);
3598 EXPECT_REF(node_list, 1);
3599 EXPECT_REF(enum1, 2);
3600
3601 EXPECT_REF(node_list, 1);
3602 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IEnumVARIANT, (void**)&enum2);
3603 EXPECT_HR(hr, S_OK);
3604 EXPECT_REF(node_list, 1);
3605 ok(enum2 == enum1, "got %p, %p\n", enum2, enum1);
3606 IEnumVARIANT_Release(enum2);
3607
3608 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3609 EXPECT_HR(hr, S_OK);
3610 hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
3611 EXPECT_HR(hr, S_OK);
3612 EXPECT_REF(node_list, 3);
3613 EXPECT_REF(enum1, 2);
3614 ok(unk1 == unk2, "got %p, %p\n", unk1, unk2);
3615 IUnknown_Release(unk1);
3616 IUnknown_Release(unk2);
3617
3618 EXPECT_REF(node_list, 1);
3619 hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum2);
3620 EXPECT_HR(hr, S_OK);
3621 EXPECT_REF(node_list, 2);
3622 EXPECT_REF(enum2, 1);
3623 ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
3624
3625 /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
3626 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk1);
3627 EXPECT_HR(hr, S_OK);
3628 hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
3629 EXPECT_HR(hr, S_OK);
3630 EXPECT_REF(node_list, 3);
3631 EXPECT_REF(enum2, 2);
3632 ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
3633 IUnknown_Release(unk1);
3634 IUnknown_Release(unk2);
3635
3636 hr = IXMLDOMNodeList__newEnum(node_list, (IUnknown**)&enum3);
3637 EXPECT_HR(hr, S_OK);
3638 ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
3639 IEnumVARIANT_Release(enum3);
3640 IEnumVARIANT_Release(enum2);
3641
3642 /* iteration tests */
3643 hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
3644 EXPECT_HR(hr, S_OK);
3645 hr = IXMLDOMNode_get_nodeName(node, &str);
3646 EXPECT_HR(hr, S_OK);
3647 ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3648 SysFreeString(str);
3649 IXMLDOMNode_Release(node);
3650
3651 hr = IXMLDOMNodeList_nextNode(node_list, &node);
3652 EXPECT_HR(hr, S_OK);
3653 hr = IXMLDOMNode_get_nodeName(node, &str);
3654 EXPECT_HR(hr, S_OK);
3655 ok(!lstrcmpW(str, _bstr_("bs")), "got %s\n", wine_dbgstr_w(str));
3656 SysFreeString(str);
3657 IXMLDOMNode_Release(node);
3658
3659 V_VT(&v) = VT_EMPTY;
3660 hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
3661 EXPECT_HR(hr, S_OK);
3662 ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
3663 hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
3664 EXPECT_HR(hr, S_OK);
3665 hr = IXMLDOMNode_get_nodeName(node, &str);
3666 EXPECT_HR(hr, S_OK);
3667 ok(!lstrcmpW(str, _bstr_("bs")), "got node name %s\n", wine_dbgstr_w(str));
3668 SysFreeString(str);
3669 IXMLDOMNode_Release(node);
3670 VariantClear(&v);
3671
3672 hr = IXMLDOMNodeList_nextNode(node_list, &node);
3673 EXPECT_HR(hr, S_OK);
3674 hr = IXMLDOMNode_get_nodeName(node, &str);
3675 EXPECT_HR(hr, S_OK);
3676 ok(!lstrcmpW(str, _bstr_("pr")), "got %s\n", wine_dbgstr_w(str));
3677 SysFreeString(str);
3678 IXMLDOMNode_Release(node);
3679
3680 IEnumVARIANT_Release(enum1);
3681
3682 hr = IXMLDOMNodeList_get_item( node_list, 2, &node );
3683 EXPECT_HR(hr, S_OK);
3684
3685 hr = IXMLDOMNode_get_childNodes( node, &node_list2 );
3686 EXPECT_HR(hr, S_OK);
3687
3688 hr = IXMLDOMNodeList_get_length( node_list2, &len );
3689 EXPECT_HR(hr, S_OK);
3690 ok( len == 0, "len %d\n", len);
3691
3692 hr = IXMLDOMNodeList_get_item( node_list2, 0, &node2);
3693 EXPECT_HR(hr, S_FALSE);
3694
3695 IXMLDOMNodeList_Release( node_list2 );
3696 IXMLDOMNode_Release( node );
3697 IXMLDOMNodeList_Release( node_list );
3698 IXMLDOMElement_Release( element );
3699
3700 /* test for children of <?xml ..?> node */
3701 hr = IXMLDOMDocument_get_firstChild(doc, &node);
3702 EXPECT_HR(hr, S_OK);
3703
3704 str = NULL;
3705 hr = IXMLDOMNode_get_nodeName(node, &str);
3706 EXPECT_HR(hr, S_OK);
3707 ok(!lstrcmpW(str, _bstr_("xml")), "got %s\n", wine_dbgstr_w(str));
3708 SysFreeString(str);
3709
3710 /* it returns empty but valid node list */
3711 node_list = (void*)0xdeadbeef;
3712 hr = IXMLDOMNode_get_childNodes(node, &node_list);
3713 EXPECT_HR(hr, S_OK);
3714
3715 len = -1;
3716 hr = IXMLDOMNodeList_get_length(node_list, &len);
3717 EXPECT_HR(hr, S_OK);
3718 ok(len == 0, "got %d\n", len);
3719
3720 IXMLDOMNodeList_Release( node_list );
3721 IXMLDOMNode_Release(node);
3722
3723 IXMLDOMDocument_Release( doc );
3724 free_bstrs();
3725 }
3726
3727 static void test_get_firstChild(void)
3728 {
3729 static const WCHAR xmlW[] = {'x','m','l',0};
3730 IXMLDOMDocument *doc;
3731 IXMLDOMNode *node;
3732 VARIANT_BOOL b;
3733 HRESULT r;
3734 BSTR str;
3735
3736 doc = create_document(&IID_IXMLDOMDocument);
3737
3738 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3739 ok( r == S_OK, "loadXML failed\n");
3740 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3741
3742 r = IXMLDOMDocument_get_firstChild( doc, &node );
3743 ok( r == S_OK, "ret %08x\n", r);
3744
3745 r = IXMLDOMNode_get_nodeName( node, &str );
3746 ok( r == S_OK, "ret %08x\n", r);
3747
3748 ok(!lstrcmpW(str, xmlW), "expected \"xml\" node name, got %s\n", wine_dbgstr_w(str));
3749
3750 SysFreeString(str);
3751 IXMLDOMNode_Release( node );
3752 IXMLDOMDocument_Release( doc );
3753
3754 free_bstrs();
3755 }
3756
3757 static void test_get_lastChild(void)
3758 {
3759 static const WCHAR lcW[] = {'l','c',0};
3760 static const WCHAR foW[] = {'f','o',0};
3761 IXMLDOMDocument *doc;
3762 IXMLDOMNode *node, *child;
3763 VARIANT_BOOL b;
3764 HRESULT r;
3765 BSTR str;
3766
3767 doc = create_document(&IID_IXMLDOMDocument);
3768
3769 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3770 ok( r == S_OK, "loadXML failed\n");
3771 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3772
3773 r = IXMLDOMDocument_get_lastChild( doc, &node );
3774 ok( r == S_OK, "ret %08x\n", r);
3775
3776 r = IXMLDOMNode_get_nodeName( node, &str );
3777 ok( r == S_OK, "ret %08x\n", r);
3778
3779 ok(memcmp(str, lcW, sizeof(lcW)) == 0, "expected \"lc\" node name\n");
3780 SysFreeString(str);
3781
3782 r = IXMLDOMNode_get_lastChild( node, &child );
3783 ok( r == S_OK, "ret %08x\n", r);
3784
3785 r = IXMLDOMNode_get_nodeName( child, &str );
3786 ok( r == S_OK, "ret %08x\n", r);
3787
3788 ok(memcmp(str, foW, sizeof(foW)) == 0, "expected \"fo\" node name\n");
3789 SysFreeString(str);
3790
3791 IXMLDOMNode_Release( child );
3792 IXMLDOMNode_Release( node );
3793 IXMLDOMDocument_Release( doc );
3794
3795 free_bstrs();
3796 }
3797
3798 static void test_removeChild(void)
3799 {
3800 HRESULT r;
3801 VARIANT_BOOL b;
3802 IXMLDOMDocument *doc;
3803 IXMLDOMElement *element, *lc_element;
3804 IXMLDOMNode *fo_node, *ba_node, *removed_node, *temp_node, *lc_node;
3805 IXMLDOMNodeList *root_list, *fo_list;
3806
3807 doc = create_document(&IID_IXMLDOMDocument);
3808
3809 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3810 ok( r == S_OK, "loadXML failed\n");
3811 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3812
3813 r = IXMLDOMDocument_get_documentElement( doc, &element );
3814 ok( r == S_OK, "ret %08x\n", r);
3815 todo_wine EXPECT_REF(element, 2);
3816
3817 r = IXMLDOMElement_get_childNodes( element, &root_list );
3818 ok( r == S_OK, "ret %08x\n", r);
3819 EXPECT_REF(root_list, 1);
3820
3821 r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3822 ok( r == S_OK, "ret %08x\n", r);
3823 EXPECT_REF(fo_node, 1);
3824
3825 r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3826 ok( r == S_OK, "ret %08x\n", r);
3827 EXPECT_REF(fo_list, 1);
3828
3829 r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3830 ok( r == S_OK, "ret %08x\n", r);
3831 EXPECT_REF(ba_node, 1);
3832
3833 /* invalid parameter: NULL ptr */
3834 removed_node = (void*)0xdeadbeef;
3835 r = IXMLDOMElement_removeChild( element, NULL, &removed_node );
3836 ok( r == E_INVALIDARG, "ret %08x\n", r );
3837 ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3838
3839 /* ba_node is a descendant of element, but not a direct child. */
3840 removed_node = (void*)0xdeadbeef;
3841 EXPECT_REF(ba_node, 1);
3842 EXPECT_CHILDREN(fo_node);
3843 r = IXMLDOMElement_removeChild( element, ba_node, &removed_node );
3844 ok( r == E_INVALIDARG, "ret %08x\n", r );
3845 ok( removed_node == NULL, "%p\n", removed_node );
3846 EXPECT_REF(ba_node, 1);
3847 EXPECT_CHILDREN(fo_node);
3848
3849 EXPECT_REF(ba_node, 1);
3850 EXPECT_REF(fo_node, 1);
3851 r = IXMLDOMElement_removeChild( element, fo_node, &removed_node );
3852 ok( r == S_OK, "ret %08x\n", r);
3853 ok( fo_node == removed_node, "node %p node2 %p\n", fo_node, removed_node );
3854 EXPECT_REF(fo_node, 2);
3855 EXPECT_REF(ba_node, 1);
3856
3857 /* try removing already removed child */
3858 temp_node = (void*)0xdeadbeef;
3859 r = IXMLDOMElement_removeChild( element, fo_node, &temp_node );
3860 ok( r == E_INVALIDARG, "ret %08x\n", r);
3861 ok( temp_node == NULL, "%p\n", temp_node );
3862 IXMLDOMNode_Release( fo_node );
3863
3864 /* the removed node has no parent anymore */
3865 r = IXMLDOMNode_get_parentNode( removed_node, &temp_node );
3866 ok( r == S_FALSE, "ret %08x\n", r);
3867 ok( temp_node == NULL, "%p\n", temp_node );
3868
3869 IXMLDOMNode_Release( removed_node );
3870 IXMLDOMNode_Release( ba_node );
3871 IXMLDOMNodeList_Release( fo_list );
3872
3873 r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3874 ok( r == S_OK, "ret %08x\n", r);
3875
3876 r = IXMLDOMNode_QueryInterface( lc_node, &IID_IXMLDOMElement, (void**)&lc_element );
3877 ok( r == S_OK, "ret %08x\n", r);
3878
3879 /* MS quirk: passing wrong interface pointer works, too */
3880 r = IXMLDOMElement_removeChild( element, (IXMLDOMNode*)lc_element, NULL );
3881 ok( r == S_OK, "ret %08x\n", r);
3882 IXMLDOMElement_Release( lc_element );
3883
3884 temp_node = (void*)0xdeadbeef;
3885 r = IXMLDOMNode_get_parentNode( lc_node, &temp_node );
3886 ok( r == S_FALSE, "ret %08x\n", r);
3887 ok( temp_node == NULL, "%p\n", temp_node );
3888
3889 IXMLDOMNode_Release( lc_node );
3890 IXMLDOMNodeList_Release( root_list );
3891 IXMLDOMElement_Release( element );
3892 IXMLDOMDocument_Release( doc );
3893
3894 free_bstrs();
3895 }
3896
3897 static void test_replaceChild(void)
3898 {
3899 HRESULT r;
3900 VARIANT_BOOL b;
3901 IXMLDOMDocument *doc;
3902 IXMLDOMElement *element, *ba_element;
3903 IXMLDOMNode *fo_node, *ba_node, *lc_node, *removed_node, *temp_node;
3904 IXMLDOMNodeList *root_list, *fo_list;
3905 IUnknown * unk1, *unk2;
3906 LONG len;
3907
3908 doc = create_document(&IID_IXMLDOMDocument);
3909
3910 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
3911 ok( r == S_OK, "loadXML failed\n");
3912 ok( b == VARIANT_TRUE, "failed to load XML string\n");
3913
3914 r = IXMLDOMDocument_get_documentElement( doc, &element );
3915 ok( r == S_OK, "ret %08x\n", r);
3916
3917 r = IXMLDOMElement_get_childNodes( element, &root_list );
3918 ok( r == S_OK, "ret %08x\n", r);
3919
3920 r = IXMLDOMNodeList_get_item( root_list, 0, &lc_node );
3921 ok( r == S_OK, "ret %08x\n", r);
3922
3923 r = IXMLDOMNodeList_get_item( root_list, 3, &fo_node );
3924 ok( r == S_OK, "ret %08x\n", r);
3925
3926 r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3927 ok( r == S_OK, "ret %08x\n", r);
3928
3929 r = IXMLDOMNodeList_get_item( fo_list, 0, &ba_node );
3930 ok( r == S_OK, "ret %08x\n", r);
3931
3932 IXMLDOMNodeList_Release( fo_list );
3933
3934 /* invalid parameter: NULL ptr for element to remove */
3935 removed_node = (void*)0xdeadbeef;
3936 r = IXMLDOMElement_replaceChild( element, ba_node, NULL, &removed_node );
3937 ok( r == E_INVALIDARG, "ret %08x\n", r );
3938 ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3939
3940 /* invalid parameter: NULL for replacement element. (Sic!) */
3941 removed_node = (void*)0xdeadbeef;
3942 r = IXMLDOMElement_replaceChild( element, NULL, fo_node, &removed_node );
3943 ok( r == E_INVALIDARG, "ret %08x\n", r );
3944 ok( removed_node == (void*)0xdeadbeef, "%p\n", removed_node );
3945
3946 /* invalid parameter: OldNode is not a child */
3947 removed_node = (void*)0xdeadbeef;
3948 r = IXMLDOMElement_replaceChild( element, lc_node, ba_node, &removed_node );
3949 ok( r == E_INVALIDARG, "ret %08x\n", r );
3950 ok( removed_node == NULL, "%p\n", removed_node );
3951 IXMLDOMNode_Release( lc_node );
3952
3953 /* invalid parameter: would create loop */
3954 removed_node = (void*)0xdeadbeef;
3955 r = IXMLDOMNode_replaceChild( fo_node, fo_node, ba_node, &removed_node );
3956 ok( r == E_FAIL, "ret %08x\n", r );
3957 ok( removed_node == NULL, "%p\n", removed_node );
3958
3959 r = IXMLDOMElement_replaceChild( element, ba_node, fo_node, NULL );
3960 ok( r == S_OK, "ret %08x\n", r );
3961
3962 r = IXMLDOMNodeList_get_item( root_list, 3, &temp_node );
3963 ok( r == S_OK, "ret %08x\n", r );
3964
3965 /* ba_node and temp_node refer to the same node, yet they
3966 are different interface pointers */
3967 ok( ba_node != temp_node, "ba_node %p temp_node %p\n", ba_node, temp_node);
3968 r = IXMLDOMNode_QueryInterface( temp_node, &IID_IUnknown, (void**)&unk1);
3969 ok( r == S_OK, "ret %08x\n", r );
3970 r = IXMLDOMNode_QueryInterface( ba_node, &IID_IUnknown, (void**)&unk2);
3971 ok( r == S_OK, "ret %08x\n", r );
3972 todo_wine ok( unk1 == unk2, "unk1 %p unk2 %p\n", unk1, unk2);
3973
3974 IUnknown_Release( unk1 );
3975 IUnknown_Release( unk2 );
3976
3977 /* ba_node should have been removed from below fo_node */
3978 r = IXMLDOMNode_get_childNodes( fo_node, &fo_list );
3979 ok( r == S_OK, "ret %08x\n", r );
3980
3981 /* MS quirk: replaceChild also accepts elements instead of nodes */
3982 r = IXMLDOMNode_QueryInterface( ba_node, &IID_IXMLDOMElement, (void**)&ba_element);
3983 ok( r == S_OK, "ret %08x\n", r );
3984 EXPECT_REF(ba_element, 2);
3985
3986 removed_node = NULL;
3987 r = IXMLDOMElement_replaceChild( element, ba_node, (IXMLDOMNode*)ba_element, &removed_node );
3988 ok( r == S_OK, "ret %08x\n", r );
3989 ok( removed_node != NULL, "got %p\n", removed_node);
3990 EXPECT_REF(ba_element, 3);
3991 IXMLDOMElement_Release( ba_element );
3992
3993 r = IXMLDOMNodeList_get_length( fo_list, &len);
3994 ok( r == S_OK, "ret %08x\n", r );
3995 ok( len == 0, "len %d\n", len);
3996
3997 IXMLDOMNodeList_Release( fo_list );
3998
3999 IXMLDOMNode_Release(ba_node);
4000 IXMLDOMNode_Release(fo_node);
4001 IXMLDOMNode_Release(temp_node);
4002 IXMLDOMNodeList_Release( root_list );
4003 IXMLDOMElement_Release( element );
4004 IXMLDOMDocument_Release( doc );
4005
4006 free_bstrs();
4007 }
4008
4009 static void test_removeNamedItem(void)
4010 {
4011 IXMLDOMDocument *doc;
4012 IXMLDOMElement *element;
4013 IXMLDOMNode *pr_node, *removed_node, *removed_node2;
4014 IXMLDOMNodeList *root_list;
4015 IXMLDOMNamedNodeMap * pr_attrs;
4016 VARIANT_BOOL b;
4017 BSTR str;
4018 LONG len;
4019 HRESULT r;
4020
4021 doc = create_document(&IID_IXMLDOMDocument);
4022
4023 r = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
4024 ok( r == S_OK, "loadXML failed\n");
4025 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4026
4027 r = IXMLDOMDocument_get_documentElement( doc, &element );
4028 ok( r == S_OK, "ret %08x\n", r);
4029
4030 r = IXMLDOMElement_get_childNodes( element, &root_list );
4031 ok( r == S_OK, "ret %08x\n", r);
4032
4033 r = IXMLDOMNodeList_get_item( root_list, 1, &pr_node );
4034 ok( r == S_OK, "ret %08x\n", r);
4035
4036 r = IXMLDOMNode_get_attributes( pr_node, &pr_attrs );
4037 ok( r == S_OK, "ret %08x\n", r);
4038
4039 r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4040 ok( r == S_OK, "ret %08x\n", r);
4041 ok( len == 3, "length %d\n", len);
4042
4043 removed_node = (void*)0xdeadbeef;
4044 r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, NULL, &removed_node);
4045 ok ( r == E_INVALIDARG, "ret %08x\n", r);
4046 ok ( removed_node == (void*)0xdeadbeef, "got %p\n", removed_node);
4047
4048 removed_node = (void*)0xdeadbeef;
4049 str = SysAllocString(szvr);
4050 r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node);
4051 ok ( r == S_OK, "ret %08x\n", r);
4052
4053 removed_node2 = (void*)0xdeadbeef;
4054 r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, &removed_node2);
4055 ok ( r == S_FALSE, "ret %08x\n", r);
4056 ok ( removed_node2 == NULL, "got %p\n", removed_node2 );
4057
4058 r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4059 ok( r == S_OK, "ret %08x\n", r);
4060 ok( len == 2, "length %d\n", len);
4061
4062 r = IXMLDOMNamedNodeMap_setNamedItem( pr_attrs, removed_node, NULL);
4063 ok ( r == S_OK, "ret %08x\n", r);
4064 IXMLDOMNode_Release(removed_node);
4065
4066 r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4067 ok( r == S_OK, "ret %08x\n", r);
4068 ok( len == 3, "length %d\n", len);
4069
4070 r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4071 ok ( r == S_OK, "ret %08x\n", r);
4072
4073 r = IXMLDOMNamedNodeMap_get_length( pr_attrs, &len );
4074 ok( r == S_OK, "ret %08x\n", r);
4075 ok( len == 2, "length %d\n", len);
4076
4077 r = IXMLDOMNamedNodeMap_removeNamedItem( pr_attrs, str, NULL);
4078 ok ( r == S_FALSE, "ret %08x\n", r);
4079
4080 SysFreeString(str);
4081
4082 IXMLDOMNamedNodeMap_Release( pr_attrs );
4083 IXMLDOMNode_Release( pr_node );
4084 IXMLDOMNodeList_Release( root_list );
4085 IXMLDOMElement_Release( element );
4086 IXMLDOMDocument_Release( doc );
4087
4088 free_bstrs();
4089 }
4090
4091 #define test_IObjectSafety_set(p, r, r2, s, m, e, e2) _test_IObjectSafety_set(__LINE__,p, r, r2, s, m, e, e2)
4092 static void _test_IObjectSafety_set(unsigned line, IObjectSafety *safety, HRESULT result,
4093 HRESULT result2, DWORD set, DWORD mask, DWORD expected,
4094 DWORD expected2)
4095 {
4096 DWORD enabled, supported;
4097 HRESULT hr;
4098
4099 hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL, set, mask);
4100 if (result == result2)
4101 ok_(__FILE__,line)(hr == result, "SetInterfaceSafetyOptions: expected %08x, returned %08x\n", result, hr );
4102 else
4103 ok_(__FILE__,line)(broken(hr == result) || hr == result2,
4104 "SetInterfaceSafetyOptions: expected %08x, got %08x\n", result2, hr );
4105
4106 supported = enabled = 0xCAFECAFE;
4107 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4108 ok(hr == S_OK, "ret %08x\n", hr );
4109 if (expected == expected2)
4110 ok_(__FILE__,line)(enabled == expected, "Expected %08x, got %08x\n", expected, enabled);
4111 else
4112 ok_(__FILE__,line)(broken(enabled == expected) || enabled == expected2,
4113 "Expected %08x, got %08x\n", expected2, enabled);
4114
4115 /* reset the safety options */
4116
4117 hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4118 INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA|INTERFACE_USES_SECURITY_MANAGER,
4119 0);
4120 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4121
4122 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4123 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4124 ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4125 }
4126
4127 #define test_IObjectSafety_common(s) _test_IObjectSafety_common(__LINE__,s)
4128 static void _test_IObjectSafety_common(unsigned line, IObjectSafety *safety)
4129 {
4130 DWORD enabled = 0, supported = 0;
4131 HRESULT hr;
4132
4133 /* get */
4134 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, NULL, &enabled);
4135 ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4136 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, NULL);
4137 ok_(__FILE__,line)(hr == E_POINTER, "ret %08x\n", hr );
4138
4139 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4140 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4141 ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4142 supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4143 "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4144 "got %08x\n", supported);
4145 ok_(__FILE__,line)(enabled == 0, "Expected 0, got %08x\n", enabled);
4146
4147 /* set -- individual flags */
4148
4149 test_IObjectSafety_set(safety, S_OK, S_OK,
4150 INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4151 INTERFACESAFE_FOR_UNTRUSTED_CALLER, INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4152
4153 test_IObjectSafety_set(safety, S_OK, S_OK,
4154 INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA,
4155 INTERFACESAFE_FOR_UNTRUSTED_DATA, INTERFACESAFE_FOR_UNTRUSTED_DATA);
4156
4157 test_IObjectSafety_set(safety, S_OK, S_OK,
4158 INTERFACE_USES_SECURITY_MANAGER, INTERFACE_USES_SECURITY_MANAGER,
4159 0, INTERFACE_USES_SECURITY_MANAGER /* msxml3 SP8+ */);
4160
4161 /* set INTERFACE_USES_DISPEX */
4162
4163 test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4164 INTERFACE_USES_DISPEX, INTERFACE_USES_DISPEX,
4165 0, 0);
4166
4167 test_IObjectSafety_set(safety, S_OK, E_FAIL /* msxml3 SP8+ */,
4168 INTERFACE_USES_DISPEX, 0,
4169 0, 0);
4170
4171 test_IObjectSafety_set(safety, S_OK, S_OK /* msxml3 SP8+ */,
4172 0, INTERFACE_USES_DISPEX,
4173 0, 0);
4174
4175 /* set option masking */
4176
4177 test_IObjectSafety_set(safety, S_OK, S_OK,
4178 INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4179 INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4180 INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4181 INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4182
4183 test_IObjectSafety_set(safety, S_OK, S_OK,
4184 INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4185 INTERFACESAFE_FOR_UNTRUSTED_DATA,
4186 INTERFACESAFE_FOR_UNTRUSTED_DATA,
4187 INTERFACESAFE_FOR_UNTRUSTED_DATA);
4188
4189 test_IObjectSafety_set(safety, S_OK, S_OK,
4190 INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA,
4191 INTERFACE_USES_SECURITY_MANAGER,
4192 0,
4193 0);
4194
4195 /* set -- inheriting previous settings */
4196
4197 hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4198 INTERFACESAFE_FOR_UNTRUSTED_CALLER,
4199 INTERFACESAFE_FOR_UNTRUSTED_CALLER);
4200 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4201 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4202 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4203 ok_(__FILE__,line)(enabled == INTERFACESAFE_FOR_UNTRUSTED_CALLER, "Expected INTERFACESAFE_FOR_UNTRUSTED_CALLER got %08x\n", enabled);
4204 ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4205 supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4206 "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4207 "got %08x\n", supported);
4208
4209 hr = IObjectSafety_SetInterfaceSafetyOptions(safety, NULL,
4210 INTERFACESAFE_FOR_UNTRUSTED_DATA,
4211 INTERFACESAFE_FOR_UNTRUSTED_DATA);
4212 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4213 hr = IObjectSafety_GetInterfaceSafetyOptions(safety, NULL, &supported, &enabled);
4214 ok_(__FILE__,line)(hr == S_OK, "ret %08x\n", hr );
4215 ok_(__FILE__,line)(broken(enabled == INTERFACESAFE_FOR_UNTRUSTED_DATA) ||
4216 enabled == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA),
4217 "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA) got %08x\n", enabled);
4218 ok_(__FILE__,line)(broken(supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA)) ||
4219 supported == (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER) /* msxml3 SP8+ */,
4220 "Expected (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACE_USES_SECURITY_MANAGER), "
4221 "got %08x\n", supported);
4222 }
4223
4224 static void test_IXMLDOMDocument2(void)
4225 {
4226 static const WCHAR emptyW[] = {0};
4227 IXMLDOMDocument2 *doc2, *dtddoc2;
4228 IXMLDOMDocument *doc;
4229 IXMLDOMParseError* err;
4230 IDispatchEx *dispex;
4231 VARIANT_BOOL b;
4232 VARIANT var;
4233 HRESULT r;
4234 LONG res;
4235
4236 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4237
4238 doc = create_document(&IID_IXMLDOMDocument);
4239 dtddoc2 = create_document(&IID_IXMLDOMDocument2);
4240
4241 r = IXMLDOMDocument_QueryInterface( doc, &IID_IXMLDOMDocument2, (void**)&doc2 );
4242 ok( r == S_OK, "ret %08x\n", r );
4243 ok( doc == (IXMLDOMDocument*)doc2, "interfaces differ\n");
4244
4245 ole_expect(IXMLDOMDocument2_get_readyState(doc2, NULL), E_INVALIDARG);
4246 ole_check(IXMLDOMDocument2_get_readyState(doc2, &res));
4247 ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4248
4249 err = NULL;
4250 ole_expect(IXMLDOMDocument2_validate(doc2, NULL), S_FALSE);
4251 ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4252 ok(err != NULL, "expected a pointer\n");
4253 if (err)
4254 {
4255 res = 0;
4256 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4257 /* XML_E_NOTWF */
4258 ok(res == E_XML_NOTWF, "got %08x\n", res);
4259 IXMLDOMParseError_Release(err);
4260 }
4261
4262 r = IXMLDOMDocument2_loadXML( doc2, _bstr_(complete4A), &b );
4263 ok( r == S_OK, "loadXML failed\n");
4264 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4265
4266 ole_check(IXMLDOMDocument_get_readyState(doc, &res));
4267 ok(res == READYSTATE_COMPLETE, "expected READYSTATE_COMPLETE (4), got %i\n", res);
4268
4269 err = NULL;
4270 ole_expect(IXMLDOMDocument2_validate(doc2, &err), S_FALSE);
4271 ok(err != NULL, "expected a pointer\n");
4272 if (err)
4273 {
4274 res = 0;
4275 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4276 /* XML_E_NODTD */
4277 ok(res == E_XML_NODTD, "got %08x\n", res);
4278 IXMLDOMParseError_Release(err);
4279 }
4280
4281 r = IXMLDOMDocument_QueryInterface( doc, &IID_IDispatchEx, (void**)&dispex );
4282 ok( r == S_OK, "ret %08x\n", r );
4283 if(r == S_OK)
4284 {
4285 IDispatchEx_Release(dispex);
4286 }
4287
4288 /* we will check if the variant got cleared */
4289 IXMLDOMDocument2_AddRef(doc2);
4290 EXPECT_REF(doc2, 3); /* doc, doc2, AddRef*/
4291
4292 V_VT(&var) = VT_UNKNOWN;
4293 V_UNKNOWN(&var) = (IUnknown *)doc2;
4294
4295 /* invalid calls */
4296 ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("askldhfaklsdf"), &var), E_FAIL);
4297 expect_eq(V_VT(&var), VT_UNKNOWN, int, "%x");
4298 ole_expect(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), NULL), E_INVALIDARG);
4299
4300 /* valid call */
4301 ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4302 expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4303 expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4304 V_VT(&var) = VT_R4;
4305
4306 /* the variant didn't get cleared*/
4307 expect_eq(IXMLDOMDocument2_Release(doc2), 2, int, "%d");
4308
4309 /* setProperty tests */
4310 ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("askldhfaklsdf"), var), E_FAIL);
4311 ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), var), E_FAIL);
4312 ole_expect(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("alskjdh faklsjd hfk")), E_FAIL);
4313 ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4314 ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4315 ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
4316
4317 V_VT(&var) = VT_BSTR;
4318 V_BSTR(&var) = SysAllocString(emptyW);
4319 r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4320 ok(r == S_OK, "got 0x%08x\n", r);
4321 VariantClear(&var);
4322
4323 V_VT(&var) = VT_I2;
4324 V_I2(&var) = 0;
4325 r = IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionNamespaces"), var);
4326 ok(r == E_FAIL, "got 0x%08x\n", r);
4327
4328 /* contrary to what MSDN claims you can switch back from XPath to XSLPattern */
4329 ole_check(IXMLDOMDocument2_getProperty(doc2, _bstr_("SelectionLanguage"), &var));
4330 expect_eq(V_VT(&var), VT_BSTR, int, "%x");
4331 expect_bstr_eq_and_free(V_BSTR(&var), "XSLPattern");
4332
4333 IXMLDOMDocument2_Release( doc2 );
4334 IXMLDOMDocument_Release( doc );
4335
4336 /* DTD validation */
4337 ole_check(IXMLDOMDocument2_put_validateOnParse(dtddoc2, VARIANT_FALSE));
4338 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML), &b));
4339 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4340 err = NULL;
4341 ole_check(IXMLDOMDocument2_validate(dtddoc2, &err));
4342 ok(err != NULL, "expected pointer\n");
4343 if (err)
4344 {
4345 res = 0;
4346 ole_expect(IXMLDOMParseError_get_errorCode(err, &res), S_FALSE);
4347 ok(res == 0, "got %08x\n", res);
4348 IXMLDOMParseError_Release(err);
4349 }
4350
4351 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0D), &b));
4352 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4353 err = NULL;
4354 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4355 ok(err != NULL, "expected pointer\n");
4356 if (err)
4357 {
4358 res = 0;
4359 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4360 /* XML_ELEMENT_UNDECLARED */
4361 todo_wine ok(res == 0xC00CE00D, "got %08x\n", res);
4362 IXMLDOMParseError_Release(err);
4363 }
4364
4365 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_0E), &b));
4366 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4367 err = NULL;
4368 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4369 ok(err != NULL, "expected pointer\n");
4370 if (err)
4371 {
4372 res = 0;
4373 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4374 /* XML_ELEMENT_ID_NOT_FOUND */
4375 todo_wine ok(res == 0xC00CE00E, "got %08x\n", res);
4376 IXMLDOMParseError_Release(err);
4377 }
4378
4379 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_11), &b));
4380 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4381 err = NULL;
4382 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4383 ok(err != NULL, "expected pointer\n");
4384 if (err)
4385 {
4386 res = 0;
4387 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4388 /* XML_EMPTY_NOT_ALLOWED */
4389 todo_wine ok(res == 0xC00CE011, "got %08x\n", res);
4390 IXMLDOMParseError_Release(err);
4391 }
4392
4393 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_13), &b));
4394 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4395 err = NULL;
4396 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4397 ok(err != NULL, "expected pointer\n");
4398 if (err)
4399 {
4400 res = 0;
4401 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4402 /* XML_ROOT_NAME_MISMATCH */
4403 todo_wine ok(res == 0xC00CE013, "got %08x\n", res);
4404 IXMLDOMParseError_Release(err);
4405 }
4406
4407 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_14), &b));
4408 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4409 err = NULL;
4410 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4411 ok(err != NULL, "expected pointer\n");
4412 if (err)
4413 {
4414 res = 0;
4415 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4416 /* XML_INVALID_CONTENT */
4417 todo_wine ok(res == 0xC00CE014, "got %08x\n", res);
4418 IXMLDOMParseError_Release(err);
4419 }
4420
4421 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_15), &b));
4422 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4423 err = NULL;
4424 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4425 ok(err != NULL, "expected pointer\n");
4426 if (err)
4427 {
4428 res = 0;
4429 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4430 /* XML_ATTRIBUTE_NOT_DEFINED */
4431 todo_wine ok(res == 0xC00CE015, "got %08x\n", res);
4432 IXMLDOMParseError_Release(err);
4433 }
4434
4435 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_16), &b));
4436 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4437 err = NULL;
4438 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4439 ok(err != NULL, "expected pointer\n");
4440 if (err)
4441 {
4442 res = 0;
4443 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4444 /* XML_ATTRIBUTE_FIXED */
4445 todo_wine ok(res == 0xC00CE016, "got %08x\n", res);
4446 IXMLDOMParseError_Release(err);
4447 }
4448
4449 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_17), &b));
4450 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4451 err = NULL;
4452 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4453 ok(err != NULL, "expected pointer\n");
4454 if (err)
4455 {
4456 res = 0;
4457 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4458 /* XML_ATTRIBUTE_VALUE */
4459 todo_wine ok(res == 0xC00CE017, "got %08x\n", res);
4460 IXMLDOMParseError_Release(err);
4461 }
4462
4463 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_18), &b));
4464 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4465 err = NULL;
4466 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4467 ok(err != NULL, "expected pointer\n");
4468 if (err)
4469 {
4470 res = 0;
4471 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4472 /* XML_ILLEGAL_TEXT */
4473 todo_wine ok(res == 0xC00CE018, "got %08x\n", res);
4474 IXMLDOMParseError_Release(err);
4475 }
4476
4477 ole_check(IXMLDOMDocument2_loadXML(dtddoc2, _bstr_(szEmailXML_20), &b));
4478 ok( b == VARIANT_TRUE, "failed to load XML string\n");
4479 err = NULL;
4480 ole_expect(IXMLDOMDocument2_validate(dtddoc2, &err), S_FALSE);
4481 ok(err != NULL, "expected pointer\n");
4482 if (err)
4483 {
4484 res = 0;
4485 ole_check(IXMLDOMParseError_get_errorCode(err, &res));
4486 /* XML_REQUIRED_ATTRIBUTE_MISSING */
4487 todo_wine ok(res == 0xC00CE020, "got %08x\n", res);
4488 IXMLDOMParseError_Release(err);
4489 }
4490
4491 IXMLDOMDocument2_Release( dtddoc2 );
4492 free_bstrs();
4493 }
4494
4495 #define helper_ole_check(expr) { \
4496 HRESULT r = expr; \
4497 ok_(__FILE__, line)(r == S_OK, "=> %i: " #expr " returned %08x\n", __LINE__, r); \
4498 }
4499
4500 #define helper_ole_check_ver(expr) { \
4501 HRESULT r = expr; \
4502 ok_(__FILE__, line)(r == S_OK, "-> %i (%s): " #expr " returned %08x\n", __LINE__, ver, r); \
4503 }
4504
4505 #define helper_expect_list_and_release(list, expstr) { \
4506 char *str = list_to_string(list); \
4507 ok_(__FILE__, line)(strcmp(str, expstr)==0, "=> %i (%s): Invalid node list: %s, expected %s\n", __LINE__, ver, str, expstr); \
4508 if (list) IXMLDOMNodeList_Release(list); \
4509 }
4510
4511 #define helper_expect_bstr_and_release(bstr, str) { \
4512 ok_(__FILE__, line)(lstrcmpW(bstr, _bstr_(str)) == 0, \
4513 "=> %i (%s): got %s\n", __LINE__, ver, wine_dbgstr_w(bstr)); \
4514 SysFreeString(bstr); \
4515 }
4516
4517 #define check_ws_ignored(ver, doc, str) _check_ws_ignored(__LINE__, ver, doc, str)
4518 static inline void _check_ws_ignored(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4519 {
4520 IXMLDOMNode *node1, *node2;
4521 IXMLDOMNodeList *list;
4522 BSTR bstr;
4523
4524 helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4525 helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4526 helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4527 helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4528 helper_expect_list_and_release(list, "E1.E5.E1.E2.D1 E2.E5.E1.E2.D1");
4529
4530 helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4531 helper_expect_list_and_release(list,
4532 "[4]1.E1.E5.E1.E2.D1 T2.E1.E5.E1.E2.D1 E3.E1.E5.E1.E2.D1 "
4533 "E4.E1.E5.E1.E2.D1 E5.E1.E5.E1.E2.D1 E6.E1.E5.E1.E2.D1");
4534 helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4535 if (str)
4536 {
4537 helper_expect_bstr_and_release(bstr, str);
4538 }
4539 else
4540 {
4541 helper_expect_bstr_and_release(bstr, " This is a description.");
4542 }
4543 IXMLDOMNode_Release(node1);
4544
4545 helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4546 helper_expect_list_and_release(list,
4547 "T1.E2.E5.E1.E2.D1 E2.E2.E5.E1.E2.D1 T3.E2.E5.E1.E2.D1 "
4548 "E4.E2.E5.E1.E2.D1 T5.E2.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1 T7.E2.E5.E1.E2.D1");
4549 helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4550 helper_expect_bstr_and_release(bstr,
4551 "\n This is a description with preserved whitespace. \n ");
4552 IXMLDOMNode_Release(node2);
4553 }
4554
4555 #define check_ws_preserved(ver, doc, str) _check_ws_preserved(__LINE__, ver, doc, str)
4556 static inline void _check_ws_preserved(int line, const char *ver, IXMLDOMDocument2* doc, char const* str)
4557 {
4558 IXMLDOMNode *node1, *node2;
4559 IXMLDOMNodeList *list;
4560 BSTR bstr;
4561
4562 helper_ole_check_ver(IXMLDOMDocument2_selectNodes(doc, _bstr_("//*[local-name()='html']"), &list));
4563 helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 0, &node1));
4564 helper_ole_check_ver(IXMLDOMNodeList_get_item(list, 1, &node2));
4565 helper_ole_check_ver(IXMLDOMNodeList_reset(list));
4566 helper_expect_list_and_release(list, "E2.E10.E2.E2.D1 E4.E10.E2.E2.D1");
4567
4568 helper_ole_check_ver(IXMLDOMNode_get_childNodes(node1, &list));
4569 helper_expect_list_and_release(list,
4570 "T1.E2.E10.E2.E2.D1 [4]2.E2.E10.E2.E2.D1 T3.E2.E10.E2.E2.D1 "
4571 "E4.E2.E10.E2.E2.D1 T5.E2.E10.E2.E2.D1 E6.E2.E10.E2.E2.D1 "
4572 "E7.E2.E10.E2.E2.D1 E8.E2.E10.E2.E2.D1 T9.E2.E10.E2.E2.D1");
4573 helper_ole_check_ver(IXMLDOMNode_get_text(node1, &bstr));
4574 if (str)
4575 {
4576 helper_expect_bstr_and_release(bstr, str);
4577 }
4578 else
4579 {
4580 helper_expect_bstr_and_release(bstr, "\n This is a description. \n ");
4581 }
4582 IXMLDOMNode_Release(node1);
4583
4584 helper_ole_check_ver(IXMLDOMNode_get_childNodes(node2, &list));
4585 helper_expect_list_and_release(list,
4586 "T1.E4.E10.E2.E2.D1 E2.E4.E10.E2.E2.D1 T3.E4.E10.E2.E2.D1 "
4587 "E4.E4.E10.E2.E2.D1 T5.E4.E10.E2.E2.D1 E6.E4.E10.E2.E2.D1 T7.E4.E10.E2.E2.D1");
4588 helper_ole_check_ver(IXMLDOMNode_get_text(node2, &bstr));
4589 helper_expect_bstr_and_release(bstr,
4590 "\n This is a description with preserved whitespace. \n ");
4591 IXMLDOMNode_Release(node2);
4592 }
4593
4594 static void test_preserve_charref(IXMLDOMDocument2 *doc, VARIANT_BOOL preserve)
4595 {
4596 static const WCHAR b1_p[] = {' ','T','e','x','t',' ','A',' ','e','n','d',' ',0};
4597 static const WCHAR b1_i[] = {'T','e','x','t',' ','A',' ','e','n','d',0};
4598 static const WCHAR b2_p[] = {'A','B',' ','C',' ',0};
4599 static const WCHAR b2_i[] = {'A','B',' ','C',0};
4600 IXMLDOMNodeList *list;
4601 IXMLDOMElement *root;
4602 IXMLDOMNode *node;
4603 const WCHAR *text;
4604 VARIANT_BOOL b;
4605 HRESULT hr;
4606 BSTR s;
4607
4608 hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc, preserve);
4609 ok(hr == S_OK, "got 0x%08x\n", hr);
4610
4611 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(charrefsxml), &b);
4612 ok(hr == S_OK, "got 0x%08x\n", hr);
4613
4614 hr = IXMLDOMDocument2_get_documentElement(doc, &root);
4615 ok(hr == S_OK, "got 0x%08x\n", hr);
4616
4617 hr = IXMLDOMElement_get_childNodes(root, &list);
4618 ok(hr == S_OK, "got 0x%08x\n", hr);
4619 IXMLDOMElement_Release(root);
4620
4621 text = preserve == VARIANT_TRUE ? b1_p : b1_i;
4622 hr = IXMLDOMNodeList_get_item(list, 0, &node);
4623 ok(hr == S_OK, "got 0x%08x\n", hr);
4624 hr = IXMLDOMNode_get_text(node, &s);
4625 ok(hr == S_OK, "got 0x%08x\n", hr);
4626 ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4627 SysFreeString(s);
4628 IXMLDOMNode_Release(node);
4629
4630 text = preserve == VARIANT_TRUE ? b2_p : b2_i;
4631 hr = IXMLDOMNodeList_get_item(list, 1, &node);
4632 ok(hr == S_OK, "got 0x%08x\n", hr);
4633 hr = IXMLDOMNode_get_text(node, &s);
4634 ok(hr == S_OK, "got 0x%08x\n", hr);
4635 ok(!lstrcmpW(s, text), "0x%x, got %s\n", preserve, wine_dbgstr_w(s));
4636 SysFreeString(s);
4637 IXMLDOMNode_Release(node);
4638
4639 IXMLDOMNodeList_Release(list);
4640 }
4641
4642 struct whitespace_t {
4643 const CLSID *clsid;
4644 const char *name;
4645 };
4646
4647 static const struct whitespace_t whitespace_test_data[] = {
4648 { &CLSID_DOMDocument, "CLSID_DOMDocument" },
4649 { &CLSID_DOMDocument2, "CLSID_DOMDocument2" },
4650 { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
4651 { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
4652 { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
4653 { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
4654 { 0 }
4655 };
4656
4657 static void test_whitespace(void)
4658 {
4659 const struct whitespace_t *class_ptr = whitespace_test_data;
4660
4661 while (class_ptr->clsid)
4662 {
4663 IXMLDOMDocument2 *doc1, *doc2, *doc3, *doc4;
4664 IXMLDOMNodeList *list;
4665 IXMLDOMElement *root;
4666 VARIANT_BOOL b;
4667 HRESULT hr;
4668 LONG len;
4669
4670 if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument2))
4671 {
4672 class_ptr++;
4673 continue;
4674 }
4675
4676 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4677 &IID_IXMLDOMDocument2, (void**)&doc1);
4678 ok(hr == S_OK, "got 0x%08x\n", hr);
4679
4680 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
4681 &IID_IXMLDOMDocument2, (void**)&doc2);
4682 ok(hr == S_OK, "got 0x%08x\n", hr);
4683
4684 ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_TRUE));
4685 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4686 ok(b == VARIANT_FALSE, "expected false\n");
4687 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4688 ok(b == VARIANT_TRUE, "expected true\n");
4689
4690 ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4691 ok(b == VARIANT_TRUE, "failed to load XML string\n");
4692 ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4693 ok(b == VARIANT_TRUE, "failed to load XML string\n");
4694
4695 /* switch to XPath */
4696 ole_check(IXMLDOMDocument2_setProperty(doc1, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4697 ole_check(IXMLDOMDocument2_setProperty(doc2, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4698
4699 check_ws_ignored(class_ptr->name, doc1, NULL);
4700 check_ws_preserved(class_ptr->name, doc2, NULL);
4701
4702 /* new instances copy the property */
4703 ole_check(IXMLDOMDocument2_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**) &doc3));
4704 ole_check(IXMLDOMDocument2_QueryInterface(doc2, &IID_IXMLDOMDocument2, (void**) &doc4));
4705
4706 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4707 ok(b == VARIANT_FALSE, "expected false\n");
4708 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4709 ok(b == VARIANT_TRUE, "expected true\n");
4710
4711 check_ws_ignored(class_ptr->name, doc3, NULL);
4712 check_ws_preserved(class_ptr->name, doc4, NULL);
4713
4714 /* setting after loading xml affects trimming of leading/trailing ws only */
4715 ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_TRUE));
4716 ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc2, VARIANT_FALSE));
4717
4718 /* the trailing "\n " isn't there, because it was ws-only node */
4719 check_ws_ignored(class_ptr->name, doc1, " This is a description. ");
4720 check_ws_preserved(class_ptr->name, doc2, " This is a description.");
4721
4722 /* it takes effect on reload */
4723 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc1, &b));
4724 ok(b == VARIANT_TRUE, "expected true\n");
4725 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc2, &b));
4726 ok(b == VARIANT_FALSE, "expected false\n");
4727
4728 ole_check(IXMLDOMDocument2_loadXML(doc1, _bstr_(szExampleXML), &b));
4729 ok(b == VARIANT_TRUE, "failed to load XML string\n");
4730 ole_check(IXMLDOMDocument2_loadXML(doc2, _bstr_(szExampleXML), &b));
4731 ok(b == VARIANT_TRUE, "failed to load XML string\n");
4732
4733 check_ws_preserved(class_ptr->name, doc1, NULL);
4734 check_ws_ignored(class_ptr->name, doc2, NULL);
4735
4736 /* other instances follow suit */
4737 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc3, &b));
4738 ok(b == VARIANT_TRUE, "expected true\n");
4739 ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc4, &b));
4740 ok(b == VARIANT_FALSE, "expected false\n");
4741
4742 check_ws_preserved(class_ptr->name, doc3, NULL);
4743 check_ws_ignored(class_ptr->name, doc4, NULL);
4744
4745 IXMLDOMDocument2_Release(doc2);
4746 IXMLDOMDocument2_Release(doc3);
4747 IXMLDOMDocument2_Release(doc4);
4748
4749 /* text with char references */
4750 test_preserve_charref(doc1, VARIANT_TRUE);
4751 test_preserve_charref(doc1, VARIANT_FALSE);
4752
4753 /* formatting whitespaces */
4754 hr = IXMLDOMDocument2_put_preserveWhiteSpace(doc1, VARIANT_FALSE);
4755 ok(hr == S_OK, "got 0x%08x\n", hr);
4756
4757 hr = IXMLDOMDocument2_loadXML(doc1, _bstr_(complete7), &b);
4758 ok(hr == S_OK, "got 0x%08x\n", hr);
4759 ok(b == VARIANT_TRUE, "for %x\n", b);
4760
4761 hr = IXMLDOMDocument2_get_documentElement(doc1, &root);
4762 ok(hr == S_OK, "got 0x%08x\n", hr);
4763 hr = IXMLDOMElement_get_childNodes(root, &list);
4764 ok(hr == S_OK, "got 0x%08x\n", hr);
4765 len = 0;
4766 hr = IXMLDOMNodeList_get_length(list, &len);
4767 ok(hr == S_OK, "got 0x%08x\n", hr);
4768 ok(len == 3, "got %d\n", len);
4769 IXMLDOMNodeList_Release(list);
4770 IXMLDOMElement_Release(root);
4771
4772 IXMLDOMDocument2_Release(doc1);
4773
4774 free_bstrs();
4775
4776 class_ptr++;
4777 }
4778 }
4779
4780 typedef struct {
4781 const GUID *clsid;
4782 const char *name;
4783 const char *ns;
4784 HRESULT hr;
4785 } selection_ns_t;
4786
4787 /* supposed to be tested with szExampleXML */
4788 static const selection_ns_t selection_ns_data[] = {
4789 { &CLSID_DOMDocument, "CLSID_DOMDocument", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4790 { &CLSID_DOMDocument, "CLSID_DOMDocument", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4791 { &CLSID_DOMDocument, "CLSID_DOMDocument", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4792 { &CLSID_DOMDocument, "CLSID_DOMDocument", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4793
4794 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4795 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4796 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4797 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4798
4799 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4800 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4801 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4802 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4803
4804 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4805 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4806 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4807 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4808
4809 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\txmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4810 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "\n\rxmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4811 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", " xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'", S_OK },
4812 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' ", S_OK },
4813
4814 { NULL }
4815 };
4816
4817 typedef struct {
4818 const char *query;
4819 const char *list;
4820 } xpath_test_t;
4821
4822 static const xpath_test_t xpath_test[] = {
4823 { "*/a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4824 { "*/b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4825 { "*/c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4826 { "*/d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4827 { "//a", "E1.E1.E2.D1 E1.E2.E2.D1 E1.E4.E2.D1" },
4828 { "//b", "E2.E1.E2.D1 E2.E2.E2.D1 E2.E4.E2.D1" },
4829 { "//c", "E3.E1.E2.D1 E3.E2.E2.D1" },
4830 { "//d", "E4.E1.E2.D1 E4.E2.E2.D1 E4.E4.E2.D1" },
4831 { "//c[@type]", "E3.E2.E2.D1" },
4832 { "//c[@type]/ancestor::node()[1]", "E2.E2.D1" },
4833 { "//c[@type]/ancestor-or-self::node()[1]", "E3.E2.E2.D1" },
4834 { "//c[@type]/attribute::node()[1]", "A'type'.E3.E2.E2.D1" },
4835 { "//c[@type]/child::node()[1]", "T1.E3.E2.E2.D1" },
4836 { "//c[@type]/descendant::node()[1]", "T1.E3.E2.E2.D1" },
4837 { "//c[@type]/descendant-or-self::node()[1]", "E3.E2.E2.D1" },
4838 { "//c[@type]/following::node()[1]", "E4.E2.E2.D1" },
4839 { "//c[@type]/following-sibling::node()[1]", "E4.E2.E2.D1" },
4840 { "//c[@type]/parent::node()[1]", "E2.E2.D1" },
4841 { "//c[@type]/preceding::node()[1]", "T1.E2.E2.E2.D1" },
4842 { "//c[@type]/self::node()[1]", "E3.E2.E2.D1" },
4843 { "child::*", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4844 { "child::node()", "E1.E2.D1 E2.E2.D1 E3.E2.D1 E4.E2.D1" },
4845 { "child::text()", "" },
4846 { "child::*/..", "E2.D1" },
4847 { "child::*//@*/..", "E2.E5.E1.E2.D1 E2.E2.D1 E3.E2.E2.D1" },
4848 { "self::node()", "E2.D1" },
4849 { "ancestor::node()", "D1" },
4850 { "elem[c][last()]/a", "E1.E2.E2.D1"},
4851 { "ancestor-or-self::node()[1]", "E2.D1" },
4852 { "((//a)[1])[last()]", "E1.E1.E2.D1" },
4853 { "//elem[@*]", "E2.E2.D1" },
4854 { NULL }
4855 };
4856
4857 static void test_XPath(void)
4858 {
4859 const selection_ns_t *ptr = selection_ns_data;
4860 const xpath_test_t *xptest = xpath_test;
4861 VARIANT var;
4862 VARIANT_BOOL b;
4863 IXMLDOMDocument2 *doc;
4864 IXMLDOMDocument *doc2;
4865 IXMLDOMNode *rootNode;
4866 IXMLDOMNode *elem1Node;
4867 IXMLDOMNode *node;
4868 IXMLDOMNodeList *list;
4869 IXMLDOMElement *elem;
4870 IXMLDOMAttribute *attr;
4871 DOMNodeType type;
4872 HRESULT hr;
4873 LONG len;
4874 BSTR str;
4875
4876 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
4877 doc = create_document(&IID_IXMLDOMDocument2);
4878
4879 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
4880 EXPECT_HR(hr, S_OK);
4881 ok(b == VARIANT_TRUE, "failed to load XML string\n");
4882
4883 /* switch to XPath */
4884 ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
4885
4886 /* some simple queries*/
4887 EXPECT_REF(doc, 1);
4888 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
4889 EXPECT_HR(hr, S_OK);
4890 EXPECT_REF(doc, 1);
4891 EXPECT_LIST_LEN(list, 1);
4892
4893 EXPECT_REF(list, 1);
4894 hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
4895 EXPECT_HR(hr, S_OK);
4896 EXPECT_REF(list, 1);
4897 EXPECT_REF(rootNode, 1);
4898
4899 hr = IXMLDOMNodeList_reset(list);
4900 EXPECT_HR(hr, S_OK);
4901 expect_list_and_release(list, "E2.D1");
4902
4903 /* peform xpath tests */
4904 for ( ; xptest->query ; xptest++ )
4905 {
4906 char *str;
4907
4908 hr = IXMLDOMNode_selectNodes(rootNode, _bstr_(xptest->query), &list);
4909 ok(hr == S_OK, "query evaluation failed for query=%s\n", xptest->query);
4910
4911 if (hr != S_OK)
4912 continue;
4913
4914 str = list_to_string(list);
4915
4916 ok(!strcmp(str, xptest->list), "query=%s, invalid node list: \"%s\", expected \"%s\"\n",
4917 xptest->query, str, xptest->list);
4918
4919 if (list)
4920 IXMLDOMNodeList_Release(list);
4921 }
4922
4923 if (0)
4924 {
4925 /* namespace:: axis test is disabled until namespace definitions
4926 are supported as attribute nodes, currently it's another node type */
4927 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("/root/namespace::*"), &list);
4928 EXPECT_HR(hr, S_OK);
4929 len = -1;
4930 hr = IXMLDOMNodeList_get_length(list, &len);
4931 EXPECT_HR(hr, S_OK);
4932 ok(len == 2, "got %d\n", len);
4933
4934 hr = IXMLDOMNodeList_nextNode(list, &node);
4935 EXPECT_HR(hr, S_OK);
4936 type = NODE_INVALID;
4937 hr = IXMLDOMNode_get_nodeType(node, &type);
4938 EXPECT_HR(hr, S_OK);
4939 ok(type == NODE_ATTRIBUTE, "got %d\n", type);
4940 IXMLDOMNode_Release(node);
4941
4942 IXMLDOMNodeList_Release(list);
4943 }
4944
4945 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//c"), &list));
4946 expect_list_and_release(list, "E3.E1.E2.D1 E3.E2.E2.D1");
4947
4948 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//c[@type]"), &list));
4949 expect_list_and_release(list, "E3.E2.E2.D1");
4950
4951 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem"), &list));
4952 /* using get_item for query results advances the position */
4953 ole_check(IXMLDOMNodeList_get_item(list, 1, &node));
4954 expect_node(node, "E2.E2.D1");
4955 IXMLDOMNode_Release(node);
4956 ole_check(IXMLDOMNodeList_nextNode(list, &node));
4957 expect_node(node, "E4.E2.D1");
4958 IXMLDOMNode_Release(node);
4959 ole_check(IXMLDOMNodeList_reset(list));
4960 expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E4.E2.D1");
4961
4962 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("."), &list));
4963 expect_list_and_release(list, "E2.D1");
4964
4965 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("elem[3]/preceding-sibling::*"), &list));
4966 ole_check(IXMLDOMNodeList_get_item(list, 0, &elem1Node));
4967 ole_check(IXMLDOMNodeList_reset(list));
4968 expect_list_and_release(list, "E1.E2.D1 E2.E2.D1 E3.E2.D1");
4969
4970 /* select an attribute */
4971 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//@type"), &list));
4972 expect_list_and_release(list, "A'type'.E3.E2.E2.D1");
4973
4974 /* would evaluate to a number */
4975 ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("count(*)"), &list), E_FAIL);
4976 /* would evaluate to a boolean */
4977 ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("position()>0"), &list), E_FAIL);
4978 /* would evaluate to a string */
4979 ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_("name()"), &list), E_FAIL);
4980
4981 /* no results */
4982 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_("c"), &list));
4983 expect_list_and_release(list, "");
4984 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("elem//c"), &list));
4985 expect_list_and_release(list, "");
4986 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem[4]"), &list));
4987 expect_list_and_release(list, "");
4988 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//elem[0]"), &list));
4989 expect_list_and_release(list, "");
4990
4991 /* foo undeclared in document node */
4992 ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
4993 /* undeclared in <root> node */
4994 ole_expect(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//foo:c"), &list), E_FAIL);
4995 /* undeclared in <elem> node */
4996 ole_expect(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//foo:c"), &list), E_FAIL);
4997 /* but this trick can be used */
4998 ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//*[name()='foo:c']"), &list));
4999 expect_list_and_release(list, "E3.E4.E2.D1");
5000
5001 /* it has to be declared in SelectionNamespaces */
5002 ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5003 _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
5004
5005 /* now the namespace can be used */
5006 ole_check(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list));
5007 expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5008 ole_check(IXMLDOMNode_selectNodes(rootNode, _bstr_(".//test:c"), &list));
5009 expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5010 ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_("//test:c"), &list));
5011 expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5012 ole_check(IXMLDOMNode_selectNodes(elem1Node, _bstr_(".//test:x"), &list));
5013 expect_list_and_release(list, "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1");
5014
5015 /* SelectionNamespaces syntax error - the namespaces doesn't work anymore but the value is stored */
5016 ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5017 _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###")), E_FAIL);
5018
5019 ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5020
5021 VariantInit(&var);
5022 ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
5023 expect_eq(V_VT(&var), VT_BSTR, int, "%x");
5024 if (V_VT(&var) == VT_BSTR)
5025 expect_bstr_eq_and_free(V_BSTR(&var), "xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' xmlns:foo=###");
5026
5027 /* extra attributes - same thing*/
5028 ole_expect(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"),
5029 _variantbstr_("xmlns:test='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29' param='test'")), E_FAIL);
5030 ole_expect(IXMLDOMDocument2_selectNodes(doc, _bstr_("root//foo:c"), &list), E_FAIL);
5031
5032 IXMLDOMNode_Release(rootNode);
5033 IXMLDOMNode_Release(elem1Node);
5034
5035 /* alter document with already built list */
5036 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5037 EXPECT_HR(hr, S_OK);
5038 EXPECT_LIST_LEN(list, 1);
5039
5040 hr = IXMLDOMDocument2_get_lastChild(doc, &rootNode);
5041 EXPECT_HR(hr, S_OK);
5042 EXPECT_REF(rootNode, 1);
5043 EXPECT_REF(doc, 1);
5044
5045 hr = IXMLDOMDocument2_removeChild(doc, rootNode, NULL);
5046 EXPECT_HR(hr, S_OK);
5047 IXMLDOMNode_Release(rootNode);
5048
5049 EXPECT_LIST_LEN(list, 1);
5050
5051 hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5052 EXPECT_HR(hr, S_OK);
5053 EXPECT_REF(rootNode, 1);
5054
5055 IXMLDOMNodeList_Release(list);
5056
5057 hr = IXMLDOMNode_get_nodeName(rootNode, &str);
5058 EXPECT_HR(hr, S_OK);
5059 ok(!lstrcmpW(str, _bstr_("root")), "got %s\n", wine_dbgstr_w(str));
5060 SysFreeString(str);
5061 IXMLDOMNode_Release(rootNode);
5062
5063 /* alter node from list and get it another time */
5064 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5065 EXPECT_HR(hr, S_OK);
5066 ok(b == VARIANT_TRUE, "failed to load XML string\n");
5067
5068 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5069 EXPECT_HR(hr, S_OK);
5070 EXPECT_LIST_LEN(list, 1);
5071
5072 hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5073 EXPECT_HR(hr, S_OK);
5074
5075 hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5076 EXPECT_HR(hr, S_OK);
5077
5078 V_VT(&var) = VT_I2;
5079 V_I2(&var) = 1;
5080 hr = IXMLDOMElement_setAttribute(elem, _bstr_("attrtest"), var);
5081 EXPECT_HR(hr, S_OK);
5082 IXMLDOMElement_Release(elem);
5083 IXMLDOMNode_Release(rootNode);
5084
5085 /* now check attribute to be present */
5086 hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5087 EXPECT_HR(hr, S_OK);
5088
5089 hr = IXMLDOMNode_QueryInterface(rootNode, &IID_IXMLDOMElement, (void**)&elem);
5090 EXPECT_HR(hr, S_OK);
5091
5092 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5093 EXPECT_HR(hr, S_OK);
5094 IXMLDOMAttribute_Release(attr);
5095
5096 IXMLDOMElement_Release(elem);
5097 IXMLDOMNode_Release(rootNode);
5098
5099 /* and now check for attribute in original document */
5100 hr = IXMLDOMDocument2_get_documentElement(doc, &elem);
5101 EXPECT_HR(hr, S_OK);
5102
5103 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attrtest"), &attr);
5104 EXPECT_HR(hr, S_OK);
5105 IXMLDOMAttribute_Release(attr);
5106
5107 IXMLDOMElement_Release(elem);
5108
5109 /* attach node from list to another document */
5110 doc2 = create_document(&IID_IXMLDOMDocument);
5111
5112 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5113 EXPECT_HR(hr, S_OK);
5114 ok(b == VARIANT_TRUE, "failed to load XML string\n");
5115
5116 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root"), &list);
5117 EXPECT_HR(hr, S_OK);
5118 EXPECT_LIST_LEN(list, 1);
5119
5120 hr = IXMLDOMNodeList_get_item(list, 0, &rootNode);
5121 EXPECT_HR(hr, S_OK);
5122 EXPECT_REF(rootNode, 1);
5123
5124 hr = IXMLDOMDocument_appendChild(doc2, rootNode, NULL);
5125 EXPECT_HR(hr, S_OK);
5126 EXPECT_REF(rootNode, 1);
5127 EXPECT_REF(doc2, 1);
5128 EXPECT_REF(list, 1);
5129
5130 EXPECT_LIST_LEN(list, 1);
5131
5132 IXMLDOMNode_Release(rootNode);
5133 IXMLDOMNodeList_Release(list);
5134 IXMLDOMDocument_Release(doc2);
5135 IXMLDOMDocument2_Release(doc);
5136
5137 while (ptr->clsid)
5138 {
5139 if (is_clsid_supported(ptr->clsid, &IID_IXMLDOMDocument2))
5140 {
5141 hr = CoCreateInstance(ptr->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
5142 ok(hr == S_OK, "got 0x%08x\n", hr);
5143 }
5144 else
5145 {
5146 ptr++;
5147 continue;
5148 }
5149
5150 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
5151 EXPECT_HR(hr, S_OK);
5152 ok(b == VARIANT_TRUE, "failed to load, %s\n", ptr->name);
5153
5154 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath"));
5155 EXPECT_HR(hr, S_OK);
5156
5157 V_VT(&var) = VT_BSTR;
5158 V_BSTR(&var) = _bstr_(ptr->ns);
5159
5160 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), var);
5161 ok(hr == ptr->hr, "got 0x%08x, for %s, %s\n", hr, ptr->name, ptr->ns);
5162
5163 V_VT(&var) = VT_EMPTY;
5164 hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var);
5165 EXPECT_HR(hr, S_OK);
5166 ok(V_VT(&var) == VT_BSTR, "got wrong property type %d\n", V_VT(&var));
5167 ok(!lstrcmpW(V_BSTR(&var), _bstr_(ptr->ns)), "got wrong value %s\n", wine_dbgstr_w(V_BSTR(&var)));
5168 VariantClear(&var);
5169
5170 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("root//test:c"), &list);
5171 EXPECT_HR(hr, S_OK);
5172 if (hr == S_OK)
5173 expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
5174
5175 IXMLDOMDocument2_Release(doc);
5176 ptr++;
5177 free_bstrs();
5178 }
5179
5180 free_bstrs();
5181 }
5182
5183 static void test_cloneNode(void )
5184 {
5185 IXMLDOMDocument2 *doc, *doc_clone;
5186 IXMLDOMDocument *doc2;
5187 VARIANT_BOOL b;
5188 IXMLDOMNodeList *pList;
5189 IXMLDOMNamedNodeMap *mapAttr;
5190 LONG length, length1;
5191 LONG attr_cnt, attr_cnt1;
5192 IXMLDOMNode *node, *attr;
5193 IXMLDOMNode *node_clone;
5194 IXMLDOMNode *node_first;
5195 VARIANT v;
5196 HRESULT hr;
5197
5198 doc = create_document(&IID_IXMLDOMDocument2);
5199
5200 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b);
5201 ok(hr == S_OK, "got 0x%08x\n", hr);
5202 ok(b == VARIANT_TRUE, "failed to load XML string\n");
5203
5204 hr = IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &v);
5205 ok(hr == S_OK, "got 0x%08x\n", hr);
5206 ok(!lstrcmpW(V_BSTR(&v), _bstr_("XSLPattern")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5207 VariantClear(&v);
5208
5209 V_BSTR(&v) = _bstr_("XPath");
5210 V_VT(&v) = VT_BSTR;
5211 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), v);
5212 ok(hr == S_OK, "got 0x%08x\n", hr);
5213 VariantClear(&v);
5214
5215 /* clone document node */
5216 hr = IXMLDOMDocument2_cloneNode(doc, VARIANT_TRUE, &node);
5217 ok( hr == S_OK, "ret %08x\n", hr );
5218 ok( node != NULL, "node %p\n", node );
5219
5220 hr = IXMLDOMNode_get_childNodes(node, &pList);
5221 ok( hr == S_OK, "ret %08x\n", hr );
5222 length = 0;
5223 hr = IXMLDOMNodeList_get_length(pList, &length);
5224 ok( hr == S_OK, "ret %08x\n", hr );
5225 ok(length == 2, "got %d\n", length);
5226 IXMLDOMNodeList_Release(pList);
5227
5228 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMDocument2, (void**)&doc_clone);
5229 ok(hr == S_OK, "got 0x%08x\n", hr);
5230
5231 /* cloned document inherits properties */
5232 hr = IXMLDOMDocument2_getProperty(doc_clone, _bstr_("SelectionLanguage"), &v);
5233 ok(hr == S_OK, "got 0x%08x\n", hr);
5234 ok(!lstrcmpW(V_BSTR(&v), _bstr_("XPath")), "got prop value %s\n", wine_dbgstr_w(V_BSTR(&v)));
5235 VariantClear(&v);
5236
5237 IXMLDOMDocument2_Release(doc_clone);
5238 IXMLDOMNode_Release(node);
5239
5240 hr = IXMLDOMDocument2_selectSingleNode(doc, _bstr_("lc/pr"), &node);
5241 ok( hr == S_OK, "ret %08x\n", hr );
5242 ok( node != NULL, "node %p\n", node );
5243
5244 /* Check invalid parameter */
5245 hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, NULL);
5246 ok( hr == E_INVALIDARG, "ret %08x\n", hr );
5247
5248 /* All Children */
5249 hr = IXMLDOMNode_cloneNode(node, VARIANT_TRUE, &node_clone);
5250 ok( hr == S_OK, "ret %08x\n", hr );
5251 ok( node_clone != NULL, "node %p\n", node );
5252
5253 hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5254 ok( hr == S_OK, "ret %08x\n", hr );
5255 hr = IXMLDOMNode_get_ownerDocument(node_clone, &doc2);
5256 ok( hr == S_OK, "ret %08x\n", hr );
5257 IXMLDOMDocument_Release(doc2);
5258 IXMLDOMNode_Release(node_first);
5259
5260 hr = IXMLDOMNode_get_childNodes(node, &pList);
5261 ok( hr == S_OK, "ret %08x\n", hr );
5262 length = 0;
5263 hr = IXMLDOMNodeList_get_length(pList, &length);
5264 ok( hr == S_OK, "ret %08x\n", hr );
5265 ok(length == 1, "got %d\n", length);
5266 IXMLDOMNodeList_Release(pList);
5267
5268 hr = IXMLDOMNode_get_attributes(node, &mapAttr);
5269 ok( hr == S_OK, "ret %08x\n", hr );
5270 attr_cnt = 0;
5271 hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt);
5272 ok( hr == S_OK, "ret %08x\n", hr );
5273 ok(attr_cnt == 3, "got %d\n", attr_cnt);
5274 IXMLDOMNamedNodeMap_Release(mapAttr);
5275
5276 hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5277 ok( hr == S_OK, "ret %08x\n", hr );
5278 length1 = 0;
5279 hr = IXMLDOMNodeList_get_length(pList, &length1);
5280 ok(length1 == 1, "got %d\n", length1);
5281 ok( hr == S_OK, "ret %08x\n", hr );
5282 IXMLDOMNodeList_Release(pList);
5283
5284 hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5285 ok( hr == S_OK, "ret %08x\n", hr );
5286 attr_cnt1 = 0;
5287 hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5288 ok( hr == S_OK, "ret %08x\n", hr );
5289 ok(attr_cnt1 == 3, "got %d\n", attr_cnt1);
5290 /* now really get some attributes from cloned element */
5291 attr = NULL;
5292 hr = IXMLDOMNamedNodeMap_getNamedItem(mapAttr, _bstr_("id"), &attr);
5293 ok(hr == S_OK, "ret %08x\n", hr);
5294 IXMLDOMNode_Release(attr);
5295 IXMLDOMNamedNodeMap_Release(mapAttr);
5296
5297 ok(length == length1, "wrong Child count (%d, %d)\n", length, length1);
5298 ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5299 IXMLDOMNode_Release(node_clone);
5300
5301 /* No Children */
5302 hr = IXMLDOMNode_cloneNode(node, VARIANT_FALSE, &node_clone);
5303 ok( hr == S_OK, "ret %08x\n", hr );
5304 ok( node_clone != NULL, "node %p\n", node );
5305
5306 hr = IXMLDOMNode_get_firstChild(node_clone, &node_first);
5307 ok(hr == S_FALSE, "ret %08x\n", hr );
5308
5309 hr = IXMLDOMNode_get_childNodes(node_clone, &pList);
5310 ok(hr == S_OK, "ret %08x\n", hr );
5311 hr = IXMLDOMNodeList_get_length(pList, &length1);
5312 ok(hr == S_OK, "ret %08x\n", hr );
5313 ok( length1 == 0, "Length should be 0 (%d)\n", length1);
5314 IXMLDOMNodeList_Release(pList);
5315
5316 hr = IXMLDOMNode_get_attributes(node_clone, &mapAttr);
5317 ok(hr == S_OK, "ret %08x\n", hr );
5318 hr = IXMLDOMNamedNodeMap_get_length(mapAttr, &attr_cnt1);
5319 ok(hr == S_OK, "ret %08x\n", hr );
5320 ok(attr_cnt1 == 3, "Attribute count should be 3 (%d)\n", attr_cnt1);
5321 IXMLDOMNamedNodeMap_Release(mapAttr);
5322
5323 ok(length != length1, "wrong Child count (%d, %d)\n", length, length1);
5324 ok(attr_cnt == attr_cnt1, "wrong Attribute count (%d, %d)\n", attr_cnt, attr_cnt1);
5325 IXMLDOMNode_Release(node_clone);
5326
5327 IXMLDOMNode_Release(node);
5328 IXMLDOMDocument2_Release(doc);
5329 free_bstrs();
5330 }
5331
5332 static void test_xmlTypes(void)
5333 {
5334 IXMLDOMDocument *doc;
5335 IXMLDOMElement *pRoot;
5336 HRESULT hr;
5337 IXMLDOMComment *pComment;
5338 IXMLDOMElement *pElement;
5339 IXMLDOMAttribute *pAttribute;
5340 IXMLDOMNamedNodeMap *pAttribs;
5341 IXMLDOMCDATASection *pCDataSec;
5342 IXMLDOMImplementation *pIXMLDOMImplementation = NULL;
5343 IXMLDOMDocumentFragment *pDocFrag = NULL;
5344 IXMLDOMEntityReference *pEntityRef = NULL;
5345 BSTR str;
5346 IXMLDOMNode *pNextChild;
5347 VARIANT v;
5348 LONG len = 0;
5349
5350 doc = create_document(&IID_IXMLDOMDocument);
5351
5352 hr = IXMLDOMDocument_get_nextSibling(doc, NULL);
5353 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5354
5355 pNextChild = (void*)0xdeadbeef;
5356 hr = IXMLDOMDocument_get_nextSibling(doc, &pNextChild);
5357 ok(hr == S_FALSE, "ret %08x\n", hr );
5358 ok(pNextChild == NULL, "pDocChild not NULL\n");
5359
5360 /* test previous Sibling */
5361 hr = IXMLDOMDocument_get_previousSibling(doc, NULL);
5362 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5363
5364 pNextChild = (void*)0xdeadbeef;
5365 hr = IXMLDOMDocument_get_previousSibling(doc, &pNextChild);
5366 ok(hr == S_FALSE, "ret %08x\n", hr );
5367 ok(pNextChild == NULL, "pNextChild not NULL\n");
5368
5369 /* test get_dataType */
5370 V_VT(&v) = VT_EMPTY;
5371 hr = IXMLDOMDocument_get_dataType(doc, &v);
5372 ok(hr == S_FALSE, "ret %08x\n", hr );
5373 ok( V_VT(&v) == VT_NULL, "incorrect dataType type\n");
5374 VariantClear(&v);
5375
5376 /* test implementation */
5377 hr = IXMLDOMDocument_get_implementation(doc, NULL);
5378 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5379
5380 hr = IXMLDOMDocument_get_implementation(doc, &pIXMLDOMImplementation);
5381 ok(hr == S_OK, "ret %08x\n", hr );
5382 if(hr == S_OK)
5383 {
5384 VARIANT_BOOL hasFeature = VARIANT_TRUE;
5385 BSTR sEmpty = SysAllocStringLen(NULL, 0);
5386
5387 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, NULL, sEmpty, &hasFeature);
5388 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5389
5390 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, NULL);
5391 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5392
5393 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5394 ok(hr == S_OK, "ret %08x\n", hr );
5395 ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5396
5397 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, sEmpty, sEmpty, &hasFeature);
5398 ok(hr == S_OK, "ret %08x\n", hr );
5399 ok(hasFeature == VARIANT_FALSE, "hasFeature returned true\n");
5400
5401 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), NULL, &hasFeature);
5402 ok(hr == S_OK, "ret %08x\n", hr );
5403 ok(hasFeature == VARIANT_TRUE, "hasFeature returned false\n");
5404
5405 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), sEmpty, &hasFeature);
5406 ok(hr == S_OK, "ret %08x\n", hr );
5407 ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5408
5409 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("DOM"), _bstr_("1.0"), &hasFeature);
5410 ok(hr == S_OK, "ret %08x\n", hr );
5411 ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5412
5413 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("XML"), _bstr_("1.0"), &hasFeature);
5414 ok(hr == S_OK, "ret %08x\n", hr );
5415 ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5416
5417 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("MS-DOM"), _bstr_("1.0"), &hasFeature);
5418 ok(hr == S_OK, "ret %08x\n", hr );
5419 ok(hasFeature == VARIANT_TRUE, "hasFeature returned true\n");
5420
5421 hr = IXMLDOMImplementation_hasFeature(pIXMLDOMImplementation, _bstr_("SSS"), NULL, &hasFeature);
5422 ok(hr == S_OK, "ret %08x\n", hr );
5423 ok(hasFeature == VARIANT_FALSE, "hasFeature returned false\n");
5424
5425 SysFreeString(sEmpty);
5426 IXMLDOMImplementation_Release(pIXMLDOMImplementation);
5427 }
5428
5429 pRoot = (IXMLDOMElement*)0x1;
5430 hr = IXMLDOMDocument_createElement(doc, NULL, &pRoot);
5431 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5432 ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5433
5434 pRoot = (IXMLDOMElement*)0x1;
5435 hr = IXMLDOMDocument_createElement(doc, _bstr_(""), &pRoot);
5436 ok(hr == E_FAIL, "ret %08x\n", hr );
5437 ok(pRoot == (void*)0x1, "Expect same ptr, got %p\n", pRoot);
5438
5439 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &pRoot);
5440 ok(hr == S_OK, "ret %08x\n", hr );
5441 if(hr == S_OK)
5442 {
5443 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)pRoot, NULL);
5444 ok(hr == S_OK, "ret %08x\n", hr );
5445 if(hr == S_OK)
5446 {
5447 /* Comment */
5448 str = SysAllocString(szComment);
5449 hr = IXMLDOMDocument_createComment(doc, str, &pComment);
5450 SysFreeString(str);
5451 ok(hr == S_OK, "ret %08x\n", hr );
5452 if(hr == S_OK)
5453 {
5454 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pComment, NULL);
5455 ok(hr == S_OK, "ret %08x\n", hr );
5456
5457 hr = IXMLDOMComment_get_nodeName(pComment, &str);
5458 ok(hr == S_OK, "ret %08x\n", hr );
5459 ok( !lstrcmpW( str, szCommentNodeText ), "incorrect comment node Name\n");
5460 SysFreeString(str);
5461
5462 hr = IXMLDOMComment_get_xml(pComment, &str);
5463 ok(hr == S_OK, "ret %08x\n", hr );
5464 ok( !lstrcmpW( str, szCommentXML ), "incorrect comment xml\n");
5465 SysFreeString(str);
5466
5467 /* put data Tests */
5468 hr = IXMLDOMComment_put_data(pComment, _bstr_("This &is a ; test <>\\"));
5469 ok(hr == S_OK, "ret %08x\n", hr );
5470
5471 /* get data Tests */
5472 hr = IXMLDOMComment_get_data(pComment, &str);
5473 ok(hr == S_OK, "ret %08x\n", hr );
5474 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect get_data string\n");
5475 SysFreeString(str);
5476
5477 /* Confirm XML text is good */
5478 hr = IXMLDOMComment_get_xml(pComment, &str);
5479 ok(hr == S_OK, "ret %08x\n", hr );
5480 ok( !lstrcmpW( str, _bstr_("<!--This &is a ; test <>\\-->") ), "incorrect xml string\n");
5481 SysFreeString(str);
5482
5483 /* Confirm we get the put_data Text back */
5484 hr = IXMLDOMComment_get_text(pComment, &str);
5485 ok(hr == S_OK, "ret %08x\n", hr );
5486 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect xml string\n");
5487 SysFreeString(str);
5488
5489 /* test length property */
5490 hr = IXMLDOMComment_get_length(pComment, &len);
5491 ok(hr == S_OK, "ret %08x\n", hr );
5492 ok(len == 21, "expected 21 got %d\n", len);
5493
5494 /* test substringData */
5495 hr = IXMLDOMComment_substringData(pComment, 0, 4, NULL);
5496 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5497
5498 /* test substringData - Invalid offset */
5499 str = (void *)0xdeadbeef;
5500 hr = IXMLDOMComment_substringData(pComment, -1, 4, &str);
5501 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5502 ok( str == NULL, "incorrect string\n");
5503
5504 /* test substringData - Invalid offset */
5505 str = (void *)0xdeadbeef;
5506 hr = IXMLDOMComment_substringData(pComment, 30, 0, &str);
5507 ok(hr == S_FALSE, "ret %08x\n", hr );
5508 ok( str == NULL, "incorrect string\n");
5509
5510 /* test substringData - Invalid size */
5511 str = (void *)0xdeadbeef;
5512 hr = IXMLDOMComment_substringData(pComment, 0, -1, &str);
5513 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5514 ok( str == NULL, "incorrect string\n");
5515
5516 /* test substringData - Invalid size */
5517 str = (void *)0xdeadbeef;
5518 hr = IXMLDOMComment_substringData(pComment, 2, 0, &str);
5519 ok(hr == S_FALSE, "ret %08x\n", hr );
5520 ok( str == NULL, "incorrect string\n");
5521
5522 /* test substringData - Start of string */
5523 hr = IXMLDOMComment_substringData(pComment, 0, 4, &str);
5524 ok(hr == S_OK, "ret %08x\n", hr );
5525 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5526 SysFreeString(str);
5527
5528 /* test substringData - Middle of string */
5529 hr = IXMLDOMComment_substringData(pComment, 13, 4, &str);
5530 ok(hr == S_OK, "ret %08x\n", hr );
5531 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5532 SysFreeString(str);
5533
5534 /* test substringData - End of string */
5535 hr = IXMLDOMComment_substringData(pComment, 20, 4, &str);
5536 ok(hr == S_OK, "ret %08x\n", hr );
5537 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5538 SysFreeString(str);
5539
5540 /* test appendData */
5541 hr = IXMLDOMComment_appendData(pComment, NULL);
5542 ok(hr == S_OK, "ret %08x\n", hr );
5543
5544 hr = IXMLDOMComment_appendData(pComment, _bstr_(""));
5545 ok(hr == S_OK, "ret %08x\n", hr );
5546
5547 hr = IXMLDOMComment_appendData(pComment, _bstr_("Append"));
5548 ok(hr == S_OK, "ret %08x\n", hr );
5549
5550 hr = IXMLDOMComment_get_text(pComment, &str);
5551 ok(hr == S_OK, "ret %08x\n", hr );
5552 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5553 SysFreeString(str);
5554
5555 /* test insertData */
5556 str = SysAllocStringLen(NULL, 0);
5557 hr = IXMLDOMComment_insertData(pComment, -1, str);
5558 ok(hr == S_OK, "ret %08x\n", hr );
5559
5560 hr = IXMLDOMComment_insertData(pComment, -1, NULL);
5561 ok(hr == S_OK, "ret %08x\n", hr );
5562
5563 hr = IXMLDOMComment_insertData(pComment, 1000, str);
5564 ok(hr == S_OK, "ret %08x\n", hr );
5565
5566 hr = IXMLDOMComment_insertData(pComment, 1000, NULL);
5567 ok(hr == S_OK, "ret %08x\n", hr );
5568
5569 hr = IXMLDOMComment_insertData(pComment, 0, NULL);
5570 ok(hr == S_OK, "ret %08x\n", hr );
5571
5572 hr = IXMLDOMComment_insertData(pComment, 0, str);
5573 ok(hr == S_OK, "ret %08x\n", hr );
5574 SysFreeString(str);
5575
5576 hr = IXMLDOMComment_insertData(pComment, -1, _bstr_("Inserting"));
5577 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5578
5579 hr = IXMLDOMComment_insertData(pComment, 1000, _bstr_("Inserting"));
5580 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5581
5582 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("Begin "));
5583 ok(hr == S_OK, "ret %08x\n", hr );
5584
5585 hr = IXMLDOMComment_insertData(pComment, 17, _bstr_("Middle"));
5586 ok(hr == S_OK, "ret %08x\n", hr );
5587
5588 hr = IXMLDOMComment_insertData(pComment, 39, _bstr_(" End"));
5589 ok(hr == S_OK, "ret %08x\n", hr );
5590
5591 hr = IXMLDOMComment_get_text(pComment, &str);
5592 ok(hr == S_OK, "ret %08x\n", hr );
5593 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5594 SysFreeString(str);
5595
5596 /* delete data */
5597 /* invalid arguments */
5598 hr = IXMLDOMComment_deleteData(pComment, -1, 1);
5599 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5600
5601 hr = IXMLDOMComment_deleteData(pComment, 0, 0);
5602 ok(hr == S_OK, "ret %08x\n", hr );
5603
5604 hr = IXMLDOMComment_deleteData(pComment, 0, -1);
5605 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5606
5607 hr = IXMLDOMComment_get_length(pComment, &len);
5608 ok(hr == S_OK, "ret %08x\n", hr );
5609 ok(len == 43, "expected 43 got %d\n", len);
5610
5611 hr = IXMLDOMComment_deleteData(pComment, len, 1);
5612 ok(hr == S_OK, "ret %08x\n", hr );
5613
5614 hr = IXMLDOMComment_deleteData(pComment, len+1, 1);
5615 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5616
5617 /* delete from start */
5618 hr = IXMLDOMComment_deleteData(pComment, 0, 5);
5619 ok(hr == S_OK, "ret %08x\n", hr );
5620
5621 hr = IXMLDOMComment_get_length(pComment, &len);
5622 ok(hr == S_OK, "ret %08x\n", hr );
5623 ok(len == 38, "expected 38 got %d\n", len);
5624
5625 hr = IXMLDOMComment_get_text(pComment, &str);
5626 ok(hr == S_OK, "ret %08x\n", hr );
5627 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5628 SysFreeString(str);
5629
5630 /* delete from end */
5631 hr = IXMLDOMComment_deleteData(pComment, 35, 3);
5632 ok(hr == S_OK, "ret %08x\n", hr );
5633
5634 hr = IXMLDOMComment_get_length(pComment, &len);
5635 ok(hr == S_OK, "ret %08x\n", hr );
5636 ok(len == 35, "expected 35 got %d\n", len);
5637
5638 hr = IXMLDOMComment_get_text(pComment, &str);
5639 ok(hr == S_OK, "ret %08x\n", hr );
5640 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5641 SysFreeString(str);
5642
5643 /* delete from inside */
5644 hr = IXMLDOMComment_deleteData(pComment, 1, 33);
5645 ok(hr == S_OK, "ret %08x\n", hr );
5646
5647 hr = IXMLDOMComment_get_length(pComment, &len);
5648 ok(hr == S_OK, "ret %08x\n", hr );
5649 ok(len == 2, "expected 2 got %d\n", len);
5650
5651 hr = IXMLDOMComment_get_text(pComment, &str);
5652 ok(hr == S_OK, "ret %08x\n", hr );
5653 ok( !lstrcmpW( str, _bstr_(" ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5654 SysFreeString(str);
5655
5656 /* delete whole data ... */
5657 hr = IXMLDOMComment_get_length(pComment, &len);
5658 ok(hr == S_OK, "ret %08x\n", hr );
5659
5660 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5661 ok(hr == S_OK, "ret %08x\n", hr );
5662 /* ... and try again with empty string */
5663 hr = IXMLDOMComment_deleteData(pComment, 0, len);
5664 ok(hr == S_OK, "ret %08x\n", hr );
5665
5666 /* ::replaceData() */
5667 V_VT(&v) = VT_BSTR;
5668 V_BSTR(&v) = SysAllocString(szstr1);
5669 hr = IXMLDOMComment_put_nodeValue(pComment, v);
5670 ok(hr == S_OK, "ret %08x\n", hr );
5671 VariantClear(&v);
5672
5673 hr = IXMLDOMComment_replaceData(pComment, 6, 0, NULL);
5674 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5675 hr = IXMLDOMComment_get_text(pComment, &str);
5676 ok(hr == S_OK, "ret %08x\n", hr );
5677 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5678 SysFreeString(str);
5679
5680 hr = IXMLDOMComment_replaceData(pComment, 0, 0, NULL);
5681 ok(hr == S_OK, "ret %08x\n", hr );
5682 hr = IXMLDOMComment_get_text(pComment, &str);
5683 ok(hr == S_OK, "ret %08x\n", hr );
5684 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5685 SysFreeString(str);
5686
5687 /* NULL pointer means delete */
5688 hr = IXMLDOMComment_replaceData(pComment, 0, 1, NULL);
5689 ok(hr == S_OK, "ret %08x\n", hr );
5690 hr = IXMLDOMComment_get_text(pComment, &str);
5691 ok(hr == S_OK, "ret %08x\n", hr );
5692 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5693 SysFreeString(str);
5694
5695 /* empty string means delete */
5696 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_(""));
5697 ok(hr == S_OK, "ret %08x\n", hr );
5698 hr = IXMLDOMComment_get_text(pComment, &str);
5699 ok(hr == S_OK, "ret %08x\n", hr );
5700 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5701 SysFreeString(str);
5702
5703 /* zero count means insert */
5704 hr = IXMLDOMComment_replaceData(pComment, 0, 0, _bstr_("a"));
5705 ok(hr == S_OK, "ret %08x\n", hr );
5706 hr = IXMLDOMComment_get_text(pComment, &str);
5707 ok(hr == S_OK, "ret %08x\n", hr );
5708 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5709 SysFreeString(str);
5710
5711 hr = IXMLDOMComment_replaceData(pComment, 0, 2, NULL);
5712 ok(hr == S_OK, "ret %08x\n", hr );
5713
5714 hr = IXMLDOMComment_insertData(pComment, 0, _bstr_("m"));
5715 ok(hr == S_OK, "ret %08x\n", hr );
5716 hr = IXMLDOMComment_get_text(pComment, &str);
5717 ok(hr == S_OK, "ret %08x\n", hr );
5718 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5719 SysFreeString(str);
5720
5721 /* nonempty string, count greater than its length */
5722 hr = IXMLDOMComment_replaceData(pComment, 0, 2, _bstr_("a1.2"));
5723 ok(hr == S_OK, "ret %08x\n", hr );
5724 hr = IXMLDOMComment_get_text(pComment, &str);
5725 ok(hr == S_OK, "ret %08x\n", hr );
5726 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5727 SysFreeString(str);
5728
5729 /* nonempty string, count less than its length */
5730 hr = IXMLDOMComment_replaceData(pComment, 0, 1, _bstr_("wine"));
5731 ok(hr == S_OK, "ret %08x\n", hr );
5732 hr = IXMLDOMComment_get_text(pComment, &str);
5733 ok(hr == S_OK, "ret %08x\n", hr );
5734 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5735 SysFreeString(str);
5736
5737 IXMLDOMComment_Release(pComment);
5738 }
5739
5740 /* Element */
5741 str = SysAllocString(szElement);
5742 hr = IXMLDOMDocument_createElement(doc, str, &pElement);
5743 SysFreeString(str);
5744 ok(hr == S_OK, "ret %08x\n", hr );
5745 if(hr == S_OK)
5746 {
5747 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pElement, NULL);
5748 ok(hr == S_OK, "ret %08x\n", hr );
5749
5750 hr = IXMLDOMElement_get_nodeName(pElement, &str);
5751 ok(hr == S_OK, "ret %08x\n", hr );
5752 ok( !lstrcmpW( str, szElement ), "incorrect element node Name\n");
5753 SysFreeString(str);
5754
5755 hr = IXMLDOMElement_get_xml(pElement, &str);
5756 ok(hr == S_OK, "ret %08x\n", hr );
5757 ok( !lstrcmpW( str, szElementXML ), "incorrect element xml\n");
5758 SysFreeString(str);
5759
5760 /* Attribute */
5761 pAttribute = (IXMLDOMAttribute*)0x1;
5762 hr = IXMLDOMDocument_createAttribute(doc, NULL, &pAttribute);
5763 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5764 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5765
5766 pAttribute = (IXMLDOMAttribute*)0x1;
5767 hr = IXMLDOMDocument_createAttribute(doc, _bstr_(""), &pAttribute);
5768 ok(hr == E_FAIL, "ret %08x\n", hr );
5769 ok(pAttribute == (void*)0x1, "Expect same ptr, got %p\n", pAttribute);
5770
5771 str = SysAllocString(szAttribute);
5772 hr = IXMLDOMDocument_createAttribute(doc, str, &pAttribute);
5773 SysFreeString(str);
5774 ok(hr == S_OK, "ret %08x\n", hr );
5775 if(hr == S_OK)
5776 {
5777 IXMLDOMNode *pNewChild = (IXMLDOMNode *)0x1;
5778
5779 hr = IXMLDOMAttribute_get_nextSibling(pAttribute, NULL);
5780 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5781
5782 pNextChild = (IXMLDOMNode *)0x1;
5783 hr = IXMLDOMAttribute_get_nextSibling(pAttribute, &pNextChild);
5784 ok(hr == S_FALSE, "ret %08x\n", hr );
5785 ok(pNextChild == NULL, "pNextChild not NULL\n");
5786
5787 /* test Previous Sibling*/
5788 hr = IXMLDOMAttribute_get_previousSibling(pAttribute, NULL);
5789 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5790
5791 pNextChild = (IXMLDOMNode *)0x1;
5792 hr = IXMLDOMAttribute_get_previousSibling(pAttribute, &pNextChild);
5793 ok(hr == S_FALSE, "ret %08x\n", hr );
5794 ok(pNextChild == NULL, "pNextChild not NULL\n");
5795
5796 hr = IXMLDOMElement_appendChild(pElement, (IXMLDOMNode*)pAttribute, &pNewChild);
5797 ok(hr == E_FAIL, "ret %08x\n", hr );
5798 ok(pNewChild == NULL, "pNewChild not NULL\n");
5799
5800 hr = IXMLDOMElement_get_attributes(pElement, &pAttribs);
5801 ok(hr == S_OK, "ret %08x\n", hr );
5802 if ( hr == S_OK )
5803 {
5804 hr = IXMLDOMNamedNodeMap_setNamedItem(pAttribs, (IXMLDOMNode*)pAttribute, NULL );
5805 ok(hr == S_OK, "ret %08x\n", hr );
5806
5807 IXMLDOMNamedNodeMap_Release(pAttribs);
5808 }
5809
5810 hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5811 ok(hr == S_OK, "ret %08x\n", hr );
5812 ok( !lstrcmpW( str, szAttribute ), "incorrect attribute node Name\n");
5813 SysFreeString(str);
5814
5815 /* test nodeName */
5816 hr = IXMLDOMAttribute_get_nodeName(pAttribute, &str);
5817 ok(hr == S_OK, "ret %08x\n", hr );
5818 ok( !lstrcmpW( str, szAttribute ), "incorrect nodeName string\n");
5819 SysFreeString(str);
5820
5821 /* test name property */
5822 hr = IXMLDOMAttribute_get_name(pAttribute, &str);
5823 ok(hr == S_OK, "ret %08x\n", hr );
5824 ok( !lstrcmpW( str, szAttribute ), "incorrect name string\n");
5825 SysFreeString(str);
5826
5827 hr = IXMLDOMAttribute_get_xml(pAttribute, &str);
5828 ok(hr == S_OK, "ret %08x\n", hr );
5829 ok( !lstrcmpW( str, szAttributeXML ), "incorrect attribute xml\n");
5830 SysFreeString(str);
5831
5832 IXMLDOMAttribute_Release(pAttribute);
5833
5834 /* Check Element again with the Add Attribute*/
5835 hr = IXMLDOMElement_get_xml(pElement, &str);
5836 ok(hr == S_OK, "ret %08x\n", hr );
5837 ok( !lstrcmpW( str, szElementXML2 ), "incorrect element xml\n");
5838 SysFreeString(str);
5839 }
5840
5841 hr = IXMLDOMElement_put_text(pElement, _bstr_("TestingNode"));
5842 ok(hr == S_OK, "ret %08x\n", hr );
5843
5844 hr = IXMLDOMElement_get_xml(pElement, &str);
5845 ok(hr == S_OK, "ret %08x\n", hr );
5846 ok( !lstrcmpW( str, szElementXML3 ), "incorrect element xml\n");
5847 SysFreeString(str);
5848
5849 /* Test for reversible escaping */
5850 str = SysAllocString( szStrangeChars );
5851 hr = IXMLDOMElement_put_text(pElement, str);
5852 ok(hr == S_OK, "ret %08x\n", hr );
5853 SysFreeString( str );
5854
5855 hr = IXMLDOMElement_get_xml(pElement, &str);
5856 ok(hr == S_OK, "ret %08x\n", hr );
5857 ok( !lstrcmpW( str, szElementXML4 ), "incorrect element xml\n");
5858 SysFreeString(str);
5859
5860 hr = IXMLDOMElement_get_text(pElement, &str);
5861 ok(hr == S_OK, "ret %08x\n", hr );
5862 ok( !lstrcmpW( str, szStrangeChars ), "incorrect element text\n");
5863 SysFreeString(str);
5864
5865 IXMLDOMElement_Release(pElement);
5866 }
5867
5868 /* CData Section */
5869 str = SysAllocString(szCData);
5870 hr = IXMLDOMDocument_createCDATASection(doc, str, NULL);
5871 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5872
5873 hr = IXMLDOMDocument_createCDATASection(doc, str, &pCDataSec);
5874 SysFreeString(str);
5875 ok(hr == S_OK, "ret %08x\n", hr );
5876 if(hr == S_OK)
5877 {
5878 IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
5879 VARIANT var;
5880
5881 VariantInit(&var);
5882
5883 hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (void**)&pElement);
5884 ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
5885
5886 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pCDataSec, NULL);
5887 ok(hr == S_OK, "ret %08x\n", hr );
5888
5889 hr = IXMLDOMCDATASection_get_nodeName(pCDataSec, &str);
5890 ok(hr == S_OK, "ret %08x\n", hr );
5891 ok( !lstrcmpW( str, szCDataNodeText ), "incorrect cdata node Name\n");
5892 SysFreeString(str);
5893
5894 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5895 ok(hr == S_OK, "ret %08x\n", hr );
5896 ok( !lstrcmpW( str, szCDataXML ), "incorrect cdata xml\n");
5897 SysFreeString(str);
5898
5899 /* test lastChild */
5900 pNextChild = (IXMLDOMNode*)0x1;
5901 hr = IXMLDOMCDATASection_get_lastChild(pCDataSec, &pNextChild);
5902 ok(hr == S_FALSE, "ret %08x\n", hr );
5903 ok(pNextChild == NULL, "pNextChild not NULL\n");
5904
5905 /* put data Tests */
5906 hr = IXMLDOMCDATASection_put_data(pCDataSec, _bstr_("This &is a ; test <>\\"));
5907 ok(hr == S_OK, "ret %08x\n", hr );
5908
5909 /* Confirm XML text is good */
5910 hr = IXMLDOMCDATASection_get_xml(pCDataSec, &str);
5911 ok(hr == S_OK, "ret %08x\n", hr );
5912 ok( !lstrcmpW( str, _bstr_("<![CDATA[This &is a ; test <>\\]]>") ), "incorrect xml string\n");
5913 SysFreeString(str);
5914
5915 /* Confirm we get the put_data Text back */
5916 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5917 ok(hr == S_OK, "ret %08x\n", hr );
5918 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5919 SysFreeString(str);
5920
5921 /* test length property */
5922 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
5923 ok(hr == S_OK, "ret %08x\n", hr );
5924 ok(len == 21, "expected 21 got %d\n", len);
5925
5926 /* test get data */
5927 hr = IXMLDOMCDATASection_get_data(pCDataSec, &str);
5928 ok(hr == S_OK, "ret %08x\n", hr );
5929 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
5930 SysFreeString(str);
5931
5932 /* test substringData */
5933 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, NULL);
5934 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5935
5936 /* test substringData - Invalid offset */
5937 str = (void *)0xdeadbeef;
5938 hr = IXMLDOMCDATASection_substringData(pCDataSec, -1, 4, &str);
5939 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5940 ok( str == NULL, "incorrect string\n");
5941
5942 /* test substringData - Invalid offset */
5943 str = (void *)0xdeadbeef;
5944 hr = IXMLDOMCDATASection_substringData(pCDataSec, 30, 0, &str);
5945 ok(hr == S_FALSE, "ret %08x\n", hr );
5946 ok( str == NULL, "incorrect string\n");
5947
5948 /* test substringData - Invalid size */
5949 str = (void *)0xdeadbeef;
5950 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, -1, &str);
5951 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
5952 ok( str == NULL, "incorrect string\n");
5953
5954 /* test substringData - Invalid size */
5955 str = (void *)0xdeadbeef;
5956 hr = IXMLDOMCDATASection_substringData(pCDataSec, 2, 0, &str);
5957 ok(hr == S_FALSE, "ret %08x\n", hr );
5958 ok( str == NULL, "incorrect string\n");
5959
5960 /* test substringData - Start of string */
5961 hr = IXMLDOMCDATASection_substringData(pCDataSec, 0, 4, &str);
5962 ok(hr == S_OK, "ret %08x\n", hr );
5963 ok( !lstrcmpW( str, _bstr_("This") ), "incorrect substringData string\n");
5964 SysFreeString(str);
5965
5966 /* test substringData - Middle of string */
5967 hr = IXMLDOMCDATASection_substringData(pCDataSec, 13, 4, &str);
5968 ok(hr == S_OK, "ret %08x\n", hr );
5969 ok( !lstrcmpW( str, _bstr_("test") ), "incorrect substringData string\n");
5970 SysFreeString(str);
5971
5972 /* test substringData - End of string */
5973 hr = IXMLDOMCDATASection_substringData(pCDataSec, 20, 4, &str);
5974 ok(hr == S_OK, "ret %08x\n", hr );
5975 ok( !lstrcmpW( str, _bstr_("\\") ), "incorrect substringData string\n");
5976 SysFreeString(str);
5977
5978 /* test appendData */
5979 hr = IXMLDOMCDATASection_appendData(pCDataSec, NULL);
5980 ok(hr == S_OK, "ret %08x\n", hr );
5981
5982 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_(""));
5983 ok(hr == S_OK, "ret %08x\n", hr );
5984
5985 hr = IXMLDOMCDATASection_appendData(pCDataSec, _bstr_("Append"));
5986 ok(hr == S_OK, "ret %08x\n", hr );
5987
5988 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
5989 ok(hr == S_OK, "ret %08x\n", hr );
5990 ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\Append") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
5991 SysFreeString(str);
5992
5993 /* test insertData */
5994 str = SysAllocStringLen(NULL, 0);
5995 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, str);
5996 ok(hr == S_OK, "ret %08x\n", hr );
5997
5998 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, NULL);
5999 ok(hr == S_OK, "ret %08x\n", hr );
6000
6001 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, str);
6002 ok(hr == S_OK, "ret %08x\n", hr );
6003
6004 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, NULL);
6005 ok(hr == S_OK, "ret %08x\n", hr );
6006
6007 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, NULL);
6008 ok(hr == S_OK, "ret %08x\n", hr );
6009
6010 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, str);
6011 ok(hr == S_OK, "ret %08x\n", hr );
6012 SysFreeString(str);
6013
6014 hr = IXMLDOMCDATASection_insertData(pCDataSec, -1, _bstr_("Inserting"));
6015 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6016
6017 hr = IXMLDOMCDATASection_insertData(pCDataSec, 1000, _bstr_("Inserting"));
6018 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6019
6020 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("Begin "));
6021 ok(hr == S_OK, "ret %08x\n", hr );
6022
6023 hr = IXMLDOMCDATASection_insertData(pCDataSec, 17, _bstr_("Middle"));
6024 ok(hr == S_OK, "ret %08x\n", hr );
6025
6026 hr = IXMLDOMCDATASection_insertData(pCDataSec, 39, _bstr_(" End"));
6027 ok(hr == S_OK, "ret %08x\n", hr );
6028
6029 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6030 ok(hr == S_OK, "ret %08x\n", hr );
6031 ok( !lstrcmpW( str, _bstr_("Begin This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6032 SysFreeString(str);
6033
6034 /* delete data */
6035 /* invalid arguments */
6036 hr = IXMLDOMCDATASection_deleteData(pCDataSec, -1, 1);
6037 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6038
6039 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 0);
6040 ok(hr == S_OK, "ret %08x\n", hr );
6041
6042 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, -1);
6043 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6044
6045 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6046 ok(hr == S_OK, "ret %08x\n", hr );
6047 ok(len == 43, "expected 43 got %d\n", len);
6048
6049 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len, 1);
6050 ok(hr == S_OK, "ret %08x\n", hr );
6051
6052 hr = IXMLDOMCDATASection_deleteData(pCDataSec, len+1, 1);
6053 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6054
6055 /* delete from start */
6056 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, 5);
6057 ok(hr == S_OK, "ret %08x\n", hr );
6058
6059 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6060 ok(hr == S_OK, "ret %08x\n", hr );
6061 ok(len == 38, "expected 38 got %d\n", len);
6062
6063 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6064 ok(hr == S_OK, "ret %08x\n", hr );
6065 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append End") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6066 SysFreeString(str);
6067
6068 /* delete from end */
6069 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 35, 3);
6070 ok(hr == S_OK, "ret %08x\n", hr );
6071
6072 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6073 ok(hr == S_OK, "ret %08x\n", hr );
6074 ok(len == 35, "expected 35 got %d\n", len);
6075
6076 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6077 ok(hr == S_OK, "ret %08x\n", hr );
6078 ok( !lstrcmpW( str, _bstr_(" This &is a Middle; test <>\\Append ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6079 SysFreeString(str);
6080
6081 /* delete from inside */
6082 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 1, 33);
6083 ok(hr == S_OK, "ret %08x\n", hr );
6084
6085 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6086 ok(hr == S_OK, "ret %08x\n", hr );
6087 ok(len == 2, "expected 2 got %d\n", len);
6088
6089 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6090 ok(hr == S_OK, "ret %08x\n", hr );
6091 ok( !lstrcmpW( str, _bstr_(" ") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6092 SysFreeString(str);
6093
6094 /* delete whole data ... */
6095 hr = IXMLDOMCDATASection_get_length(pCDataSec, &len);
6096 ok(hr == S_OK, "ret %08x\n", hr );
6097
6098 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6099 ok(hr == S_OK, "ret %08x\n", hr );
6100
6101 /* ... and try again with empty string */
6102 hr = IXMLDOMCDATASection_deleteData(pCDataSec, 0, len);
6103 ok(hr == S_OK, "ret %08x\n", hr );
6104
6105 /* ::replaceData() */
6106 V_VT(&v) = VT_BSTR;
6107 V_BSTR(&v) = SysAllocString(szstr1);
6108 hr = IXMLDOMCDATASection_put_nodeValue(pCDataSec, v);
6109 ok(hr == S_OK, "ret %08x\n", hr );
6110 VariantClear(&v);
6111
6112 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 6, 0, NULL);
6113 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6114 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6115 ok(hr == S_OK, "ret %08x\n", hr );
6116 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6117 SysFreeString(str);
6118
6119 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, NULL);
6120 ok(hr == S_OK, "ret %08x\n", hr );
6121 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6122 ok(hr == S_OK, "ret %08x\n", hr );
6123 ok( !lstrcmpW( str, _bstr_("str1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6124 SysFreeString(str);
6125
6126 /* NULL pointer means delete */
6127 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, NULL);
6128 ok(hr == S_OK, "ret %08x\n", hr );
6129 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6130 ok(hr == S_OK, "ret %08x\n", hr );
6131 ok( !lstrcmpW( str, _bstr_("tr1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6132 SysFreeString(str);
6133
6134 /* empty string means delete */
6135 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_(""));
6136 ok(hr == S_OK, "ret %08x\n", hr );
6137 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6138 ok(hr == S_OK, "ret %08x\n", hr );
6139 ok( !lstrcmpW( str, _bstr_("r1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6140 SysFreeString(str);
6141
6142 /* zero count means insert */
6143 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 0, _bstr_("a"));
6144 ok(hr == S_OK, "ret %08x\n", hr );
6145 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6146 ok(hr == S_OK, "ret %08x\n", hr );
6147 ok( !lstrcmpW( str, _bstr_("ar1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6148 SysFreeString(str);
6149
6150 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, NULL);
6151 ok(hr == S_OK, "ret %08x\n", hr );
6152
6153 hr = IXMLDOMCDATASection_insertData(pCDataSec, 0, _bstr_("m"));
6154 ok(hr == S_OK, "ret %08x\n", hr );
6155 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6156 ok(hr == S_OK, "ret %08x\n", hr );
6157 ok( !lstrcmpW( str, _bstr_("m1") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6158 SysFreeString(str);
6159
6160 /* nonempty string, count greater than its length */
6161 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 2, _bstr_("a1.2"));
6162 ok(hr == S_OK, "ret %08x\n", hr );
6163 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6164 ok(hr == S_OK, "ret %08x\n", hr );
6165 ok( !lstrcmpW( str, _bstr_("a1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6166 SysFreeString(str);
6167
6168 /* nonempty string, count less than its length */
6169 hr = IXMLDOMCDATASection_replaceData(pCDataSec, 0, 1, _bstr_("wine"));
6170 ok(hr == S_OK, "ret %08x\n", hr );
6171 hr = IXMLDOMCDATASection_get_text(pCDataSec, &str);
6172 ok(hr == S_OK, "ret %08x\n", hr );
6173 ok( !lstrcmpW( str, _bstr_("wine1.2") ), "incorrect get_text string, got '%s'\n", wine_dbgstr_w(str) );
6174 SysFreeString(str);
6175
6176 IXMLDOMCDATASection_Release(pCDataSec);
6177 }
6178
6179 /* Document Fragments */
6180 hr = IXMLDOMDocument_createDocumentFragment(doc, NULL);
6181 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6182
6183 hr = IXMLDOMDocument_createDocumentFragment(doc, &pDocFrag);
6184 ok(hr == S_OK, "ret %08x\n", hr );
6185 if(hr == S_OK)
6186 {
6187 IXMLDOMNode *node;
6188
6189 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, NULL);
6190 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6191
6192 node = (IXMLDOMNode *)0x1;
6193 hr = IXMLDOMDocumentFragment_get_parentNode(pDocFrag, &node);
6194 ok(hr == S_FALSE, "ret %08x\n", hr );
6195 ok(node == NULL, "expected NULL, got %p\n", node);
6196
6197 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pDocFrag, NULL);
6198 ok(hr == S_OK, "ret %08x\n", hr );
6199
6200 hr = IXMLDOMDocumentFragment_get_nodeName(pDocFrag, &str);
6201 ok(hr == S_OK, "ret %08x\n", hr );
6202 ok( !lstrcmpW( str, szDocFragmentText ), "incorrect docfragment node Name\n");
6203 SysFreeString(str);
6204
6205 /* test next Sibling*/
6206 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, NULL);
6207 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6208
6209 node = (IXMLDOMNode *)0x1;
6210 hr = IXMLDOMDocumentFragment_get_nextSibling(pDocFrag, &node);
6211 ok(hr == S_FALSE, "ret %08x\n", hr );
6212 ok(node == NULL, "next sibling not NULL\n");
6213
6214 /* test Previous Sibling*/
6215 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, NULL);
6216 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6217
6218 node = (IXMLDOMNode *)0x1;
6219 hr = IXMLDOMDocumentFragment_get_previousSibling(pDocFrag, &node);
6220 ok(hr == S_FALSE, "ret %08x\n", hr );
6221 ok(node == NULL, "previous sibling not NULL\n");
6222
6223 IXMLDOMDocumentFragment_Release(pDocFrag);
6224 }
6225
6226 /* Entity References */
6227 hr = IXMLDOMDocument_createEntityReference(doc, NULL, &pEntityRef);
6228 ok(hr == E_FAIL, "ret %08x\n", hr );
6229 hr = IXMLDOMDocument_createEntityReference(doc, _bstr_(""), &pEntityRef);
6230 ok(hr == E_FAIL, "ret %08x\n", hr );
6231
6232 str = SysAllocString(szEntityRef);
6233 hr = IXMLDOMDocument_createEntityReference(doc, str, NULL);
6234 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6235
6236 hr = IXMLDOMDocument_createEntityReference(doc, str, &pEntityRef);
6237 SysFreeString(str);
6238 ok(hr == S_OK, "ret %08x\n", hr );
6239 if(hr == S_OK)
6240 {
6241 hr = IXMLDOMElement_appendChild(pRoot, (IXMLDOMNode*)pEntityRef, NULL);
6242 ok(hr == S_OK, "ret %08x\n", hr );
6243
6244 /* test get_xml*/
6245 hr = IXMLDOMEntityReference_get_xml(pEntityRef, &str);
6246 ok(hr == S_OK, "ret %08x\n", hr );
6247 ok( !lstrcmpW( str, szEntityRefXML ), "incorrect xml string\n");
6248 SysFreeString(str);
6249
6250 IXMLDOMEntityReference_Release(pEntityRef);
6251 }
6252
6253 IXMLDOMElement_Release( pRoot );
6254 }
6255 }
6256
6257 IXMLDOMDocument_Release(doc);
6258
6259 free_bstrs();
6260 }
6261
6262 typedef struct {
6263 const char *name;
6264 const char *type;
6265 HRESULT hr;
6266 } put_datatype_t;
6267
6268 /* Type test for elements only. Name passed into put_dataType is case-insensitive.
6269 So many of the names have been changed to reflect this. */
6270 static put_datatype_t put_datatype_data[] = {
6271 { "test_inval", "abcdefg", E_FAIL },
6272 { "test_bool", "Boolean", S_OK },
6273 { "test_string", "String", S_OK },
6274 { "test_number", "number", S_OK },
6275 { "test_int", "InT", S_OK },
6276 { "test_fixed", "fixed.14.4", S_OK },
6277 { "test_datetime", "DateTime", S_OK },
6278 { "test_datetimetz", "DateTime.tz", S_OK },
6279 { "test_date", "Date", S_OK },
6280 { "test_time", "Time", S_OK },
6281 { "test_timetz", "Time.tz", S_OK },
6282 { "test_I1", "I1", S_OK },
6283 { "test_I2", "I2", S_OK },
6284 { "test_I4", "I4", S_OK },
6285 { "test_UI1", "UI1", S_OK },
6286 { "test_UI2", "UI2", S_OK },
6287 { "test_UI4", "UI4", S_OK },
6288 { "test_r4", "r4", S_OK },
6289 { "test_r8", "r8", S_OK },
6290 { "test_float", "float", S_OK },
6291 { "test_uuid", "UuId", S_OK },
6292 { "test_binhex", "bin.hex", S_OK },
6293 { "test_binbase64", "bin.base64", S_OK },
6294 { NULL }
6295 };
6296
6297 typedef struct {
6298 DOMNodeType type;
6299 HRESULT hr;
6300 } put_datatype_notype_t;
6301
6302 static put_datatype_notype_t put_dt_notype[] = {
6303 { NODE_PROCESSING_INSTRUCTION, E_FAIL },
6304 { NODE_DOCUMENT_FRAGMENT, E_FAIL },
6305 { NODE_ENTITY_REFERENCE, E_FAIL },
6306 { NODE_CDATA_SECTION, E_FAIL },
6307 { NODE_COMMENT, E_FAIL },
6308 { NODE_INVALID }
6309 };
6310
6311 static void test_put_dataType( void )
6312 {
6313 const put_datatype_notype_t *ptr2 = put_dt_notype;
6314 const put_datatype_t *ptr = put_datatype_data;
6315 IXMLDOMElement *root, *element;
6316 BSTR nameW, type1W, type2W;
6317 IXMLDOMDocument *doc;
6318 HRESULT hr;
6319
6320 doc = create_document(&IID_IXMLDOMDocument);
6321
6322 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), NULL);
6323 EXPECT_HR(hr, E_INVALIDARG);
6324
6325 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6326 EXPECT_HR(hr, S_OK);
6327
6328 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6329 EXPECT_HR(hr, S_OK);
6330
6331 hr = IXMLDOMElement_put_dataType(root, NULL);
6332 EXPECT_HR(hr, E_INVALIDARG);
6333
6334 while (ptr->name)
6335 {
6336 hr = IXMLDOMDocument_createElement(doc, _bstr_(ptr->name), &element);
6337 EXPECT_HR(hr, S_OK);
6338 if(hr == S_OK)
6339 {
6340 hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6341 EXPECT_HR(hr, S_OK);
6342
6343 hr = IXMLDOMElement_put_dataType(element, _bstr_(ptr->type));
6344 ok(hr == ptr->hr, "failed for %s:%s, 0x%08x\n", ptr->name, ptr->type, ptr->hr);
6345
6346 IXMLDOMElement_Release(element);
6347 }
6348 ptr++;
6349 }
6350
6351 /* check changing types */
6352 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing_Change"), &element);
6353 EXPECT_HR(hr, S_OK);
6354
6355 hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)element, NULL);
6356 EXPECT_HR(hr, S_OK);
6357
6358 hr = IXMLDOMElement_put_dataType(element, _bstr_("DateTime.tz"));
6359 EXPECT_HR(hr, S_OK);
6360
6361 hr = IXMLDOMElement_put_dataType(element, _bstr_("string"));
6362 EXPECT_HR(hr, S_OK);
6363
6364 IXMLDOMElement_Release(element);
6365
6366 /* try to set type for node without a type */
6367 nameW = _bstr_("testname");
6368 type1W = _bstr_("string");
6369 type2W = _bstr_("number");
6370 while (ptr2->type != NODE_INVALID)
6371 {
6372 IXMLDOMNode *node;
6373 VARIANT type;
6374
6375 V_VT(&type) = VT_I2;
6376 V_I2(&type) = ptr2->type;
6377
6378 hr = IXMLDOMDocument_createNode(doc, type, nameW, NULL, &node);
6379 EXPECT_HR(hr, S_OK);
6380 if(hr == S_OK)
6381 {
6382 hr = IXMLDOMElement_appendChild(root, node, NULL);
6383 EXPECT_HR(hr, S_OK);
6384
6385 hr = IXMLDOMNode_put_dataType(node, NULL);
6386 EXPECT_HR(hr, E_INVALIDARG);
6387
6388 hr = IXMLDOMNode_put_dataType(node, type1W);
6389 ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6390 hr = IXMLDOMNode_put_dataType(node, type2W);
6391 ok(hr == ptr2->hr, "failed for type %d, 0x%08x\n", ptr2->type, ptr->hr);
6392
6393 IXMLDOMNode_Release(node);
6394 }
6395 ptr2++;
6396 }
6397
6398 IXMLDOMElement_Release(root);
6399 IXMLDOMDocument_Release(doc);
6400 free_bstrs();
6401 }
6402
6403 static void test_save(void)
6404 {
6405 IXMLDOMDocument *doc, *doc2;
6406 IXMLDOMElement *root;
6407 BSTR sOrig, sNew, filename;
6408 char buffer[100];
6409 IStream *stream;
6410 HGLOBAL global;
6411 VARIANT_BOOL b;
6412 DWORD read = 0;
6413 VARIANT dest;
6414 HANDLE hfile;
6415 HRESULT hr;
6416 char *ptr;
6417
6418 doc = create_document(&IID_IXMLDOMDocument);
6419 doc2 = create_document(&IID_IXMLDOMDocument);
6420
6421 /* save to IXMLDOMDocument */
6422 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
6423 EXPECT_HR(hr, S_OK);
6424
6425 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
6426 EXPECT_HR(hr, S_OK);
6427
6428 V_VT(&dest) = VT_UNKNOWN;
6429 V_UNKNOWN(&dest) = (IUnknown*)doc2;
6430
6431 hr = IXMLDOMDocument_save(doc, dest);
6432 EXPECT_HR(hr, S_OK);
6433
6434 hr = IXMLDOMDocument_get_xml(doc, &sOrig);
6435 EXPECT_HR(hr, S_OK);
6436
6437 hr = IXMLDOMDocument_get_xml(doc2, &sNew);
6438 EXPECT_HR(hr, S_OK);
6439
6440 ok( !lstrcmpW( sOrig, sNew ), "New document is not the same as original\n");
6441
6442 SysFreeString(sOrig);
6443 SysFreeString(sNew);
6444
6445 IXMLDOMElement_Release(root);
6446 IXMLDOMDocument_Release(doc2);
6447
6448 /* save to path */
6449 V_VT(&dest) = VT_BSTR;
6450 V_BSTR(&dest) = _bstr_("test.xml");
6451
6452 hr = IXMLDOMDocument_save(doc, dest);
6453 EXPECT_HR(hr, S_OK);
6454
6455 hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6456 ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6457 if(hfile == INVALID_HANDLE_VALUE) return;
6458
6459 ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6460 ok(read != 0, "could not read file\n");
6461 ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6462
6463 CloseHandle(hfile);
6464 DeleteFileA("test.xml");
6465
6466 /* save to path VT_BSTR | VT_BYREF */
6467 filename = _bstr_("test.xml");
6468 V_VT(&dest) = VT_BSTR | VT_BYREF;
6469 V_BSTRREF(&dest) = &filename;
6470
6471 hr = IXMLDOMDocument_save(doc, dest);
6472 EXPECT_HR(hr, S_OK);
6473
6474 hfile = CreateFileA("test.xml", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
6475 ok(hfile != INVALID_HANDLE_VALUE, "Could not open file: %u\n", GetLastError());
6476 if(hfile == INVALID_HANDLE_VALUE) return;
6477
6478 if (hfile != INVALID_HANDLE_VALUE)
6479 {
6480 ReadFile(hfile, buffer, sizeof(buffer), &read, NULL);
6481 ok(read != 0, "could not read file\n");
6482 ok(buffer[0] != '<' || buffer[1] != '?', "File contains processing instruction\n");
6483
6484 CloseHandle(hfile);
6485 DeleteFileA("test.xml");
6486 }
6487
6488 /* save to stream */
6489 V_VT(&dest) = VT_UNKNOWN;
6490 V_UNKNOWN(&dest) = (IUnknown*)&savestream;
6491
6492 hr = IXMLDOMDocument_save(doc, dest);
6493 EXPECT_HR(hr, S_OK);
6494
6495 /* loaded data contains xml declaration */
6496 hr = IXMLDOMDocument_loadXML(doc, _bstr_(win1252xml), &b);
6497 EXPECT_HR(hr, S_OK);
6498
6499 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6500 ok(hr == S_OK, "got 0x%08x\n", hr);
6501 V_VT(&dest) = VT_UNKNOWN;
6502 V_UNKNOWN(&dest) = (IUnknown*)stream;
6503 hr = IXMLDOMDocument_save(doc, dest);
6504 EXPECT_HR(hr, S_OK);
6505
6506 hr = GetHGlobalFromStream(stream, &global);
6507 EXPECT_HR(hr, S_OK);
6508 ptr = GlobalLock(global);
6509 ok(!memcmp(ptr, win1252decl, strlen(win1252decl)), "got wrong xml declaration\n");
6510 GlobalUnlock(global);
6511 IStream_Release(stream);
6512
6513 /* loaded data without xml declaration */
6514 hr = IXMLDOMDocument_loadXML(doc, _bstr_("<a/>"), &b);
6515 EXPECT_HR(hr, S_OK);
6516
6517 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
6518 ok(hr == S_OK, "got 0x%08x\n", hr);
6519 V_VT(&dest) = VT_UNKNOWN;
6520 V_UNKNOWN(&dest) = (IUnknown*)stream;
6521 hr = IXMLDOMDocument_save(doc, dest);
6522 EXPECT_HR(hr, S_OK);
6523
6524 hr = GetHGlobalFromStream(stream, &global);
6525 EXPECT_HR(hr, S_OK);
6526 ptr = GlobalLock(global);
6527 ok(ptr[0] == '<' && ptr[1] != '?', "got wrong start tag %c%c\n", ptr[0], ptr[1]);
6528 GlobalUnlock(global);
6529 IStream_Release(stream);
6530
6531 IXMLDOMDocument_Release(doc);
6532 free_bstrs();
6533 }
6534
6535 static void test_testTransforms(void)
6536 {
6537 IXMLDOMDocument *doc, *docSS;
6538 IXMLDOMNode *pNode;
6539 VARIANT_BOOL bSucc;
6540 HRESULT hr;
6541
6542 doc = create_document(&IID_IXMLDOMDocument);
6543 docSS = create_document(&IID_IXMLDOMDocument);
6544
6545 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &bSucc);
6546 ok(hr == S_OK, "ret %08x\n", hr );
6547
6548 hr = IXMLDOMDocument_loadXML(docSS, _bstr_(szTransformSSXML), &bSucc);
6549 ok(hr == S_OK, "ret %08x\n", hr );
6550
6551 hr = IXMLDOMDocument_QueryInterface(docSS, &IID_IXMLDOMNode, (void**)&pNode );
6552 ok(hr == S_OK, "ret %08x\n", hr );
6553 if(hr == S_OK)
6554 {
6555 BSTR bOut;
6556
6557 hr = IXMLDOMDocument_transformNode(doc, pNode, &bOut);
6558 ok(hr == S_OK, "ret %08x\n", hr );
6559 if(hr == S_OK)
6560 {
6561 ok( compareIgnoreReturns( bOut, _bstr_(szTransformOutput)), "got output %s\n", wine_dbgstr_w(bOut));
6562 SysFreeString(bOut);
6563 }
6564
6565 IXMLDOMNode_Release(pNode);
6566 }
6567
6568 IXMLDOMDocument_Release(docSS);
6569 IXMLDOMDocument_Release(doc);
6570
6571 free_bstrs();
6572 }
6573
6574 struct namespaces_change_t {
6575 const CLSID *clsid;
6576 const char *name;
6577 };
6578
6579 static const struct namespaces_change_t namespaces_change_test_data[] = {
6580 { &CLSID_DOMDocument, "CLSID_DOMDocument" },
6581 { &CLSID_DOMDocument2, "CLSID_DOMDocument2" },
6582 { &CLSID_DOMDocument26, "CLSID_DOMDocument26" },
6583 { &CLSID_DOMDocument30, "CLSID_DOMDocument30" },
6584 { &CLSID_DOMDocument40, "CLSID_DOMDocument40" },
6585 { &CLSID_DOMDocument60, "CLSID_DOMDocument60" },
6586 { 0 }
6587 };
6588
6589 static void test_namespaces_change(void)
6590 {
6591 const struct namespaces_change_t *class_ptr = namespaces_change_test_data;
6592
6593 while (class_ptr->clsid)
6594 {
6595 IXMLDOMDocument *doc = NULL;
6596 IXMLDOMElement *elem = NULL;
6597 IXMLDOMNode *node = NULL;
6598
6599 VARIANT var;
6600 HRESULT hr;
6601 BSTR str;
6602
6603 if (!is_clsid_supported(class_ptr->clsid, &IID_IXMLDOMDocument))
6604 {
6605 class_ptr++;
6606 continue;
6607 }
6608
6609 hr = CoCreateInstance(class_ptr->clsid, NULL, CLSCTX_INPROC_SERVER,
6610 &IID_IXMLDOMDocument, (void**)&doc);
6611 ok(hr == S_OK, "got 0x%08x\n", hr);
6612
6613 V_VT(&var) = VT_I2;
6614 V_I2(&var) = NODE_ELEMENT;
6615
6616 hr = IXMLDOMDocument_createNode(doc, var, _bstr_("ns:elem"), _bstr_("ns/uri"), &node);
6617 EXPECT_HR(hr, S_OK);
6618
6619 hr = IXMLDOMDocument_appendChild(doc, node, NULL);
6620 EXPECT_HR(hr, S_OK);
6621
6622 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
6623 EXPECT_HR(hr, S_OK);
6624
6625 /* try same prefix, different uri */
6626 V_VT(&var) = VT_BSTR;
6627 V_BSTR(&var) = _bstr_("ns/uri2");
6628
6629 hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6630 EXPECT_HR(hr, E_INVALIDARG);
6631
6632 /* try same prefix and uri */
6633 V_VT(&var) = VT_BSTR;
6634 V_BSTR(&var) = _bstr_("ns/uri");
6635
6636 hr = IXMLDOMElement_setAttribute(elem, _bstr_("xmlns:ns"), var);
6637 EXPECT_HR(hr, S_OK);
6638
6639 hr = IXMLDOMElement_get_xml(elem, &str);
6640 EXPECT_HR(hr, S_OK);
6641 ok(!lstrcmpW(str, _bstr_("<ns:elem xmlns:ns=\"ns/uri\"/>")), "got element %s for %s\n",
6642 wine_dbgstr_w(str), class_ptr->name);
6643 SysFreeString(str);
6644
6645 IXMLDOMElement_Release(elem);
6646 IXMLDOMDocument_Release(doc);
6647
6648 free_bstrs();
6649
6650 class_ptr++;
6651 }
6652 }
6653
6654 static void test_namespaces_basic(void)
6655 {
6656 static const CHAR namespaces_xmlA[] =
6657 "<?xml version=\"1.0\"?>\n"
6658 "<XMI xmi.version=\"1.1\" xmlns:Model=\"http://omg.org/mof.Model/1.3\">"
6659 " <XMI.content>"
6660 " <Model:Package name=\"WinePackage\" Model:name2=\"name2 attr\" />"
6661 " </XMI.content>"
6662 "</XMI>";
6663
6664 IXMLDOMDocument *doc;
6665 IXMLDOMElement *elem;
6666 IXMLDOMNode *node;
6667
6668 VARIANT_BOOL b;
6669 HRESULT hr;
6670 BSTR str;
6671
6672 doc = create_document(&IID_IXMLDOMDocument);
6673
6674 hr = IXMLDOMDocument_loadXML(doc, _bstr_(namespaces_xmlA), &b);
6675 EXPECT_HR(hr, S_OK);
6676 ok(b == VARIANT_TRUE, "got %d\n", b);
6677
6678 str = (void *)0xdeadbeef;
6679 hr = IXMLDOMDocument_get_namespaceURI(doc, &str);
6680 EXPECT_HR(hr, S_FALSE);
6681 ok(str == NULL, "got %p\n", str);
6682
6683 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("//XMI.content"), &node );
6684 EXPECT_HR(hr, S_OK);
6685 if(hr == S_OK)
6686 {
6687 IXMLDOMAttribute *attr;
6688 IXMLDOMNode *node2;
6689
6690 hr = IXMLDOMNode_get_firstChild(node, &node2);
6691 EXPECT_HR(hr, S_OK);
6692 ok(node2 != NULL, "got %p\n", node2);
6693
6694 /* Test get_prefix */
6695 hr = IXMLDOMNode_get_prefix(node2, NULL);
6696 EXPECT_HR(hr, E_INVALIDARG);
6697 /* NOTE: Need to test that arg2 gets cleared on Error. */
6698
6699 hr = IXMLDOMNode_get_prefix(node2, &str);
6700 EXPECT_HR(hr, S_OK);
6701 ok( !lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6702 SysFreeString(str);
6703
6704 hr = IXMLDOMNode_get_nodeName(node2, &str);
6705 EXPECT_HR(hr, S_OK);
6706 ok(!lstrcmpW( str, _bstr_("Model:Package")), "got %s\n", wine_dbgstr_w(str));
6707 SysFreeString(str);
6708
6709 /* Test get_namespaceURI */
6710 hr = IXMLDOMNode_get_namespaceURI(node2, NULL);
6711 EXPECT_HR(hr, E_INVALIDARG);
6712 /* NOTE: Need to test that arg2 gets cleared on Error. */
6713
6714 hr = IXMLDOMNode_get_namespaceURI(node2, &str);
6715 EXPECT_HR(hr, S_OK);
6716 ok(!lstrcmpW( str, _bstr_("http://omg.org/mof.Model/1.3")), "got %s\n", wine_dbgstr_w(str));
6717 SysFreeString(str);
6718
6719 hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&elem);
6720 EXPECT_HR(hr, S_OK);
6721
6722 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("Model:name2"), &attr);
6723 EXPECT_HR(hr, S_OK);
6724
6725 hr = IXMLDOMAttribute_get_nodeName(attr, &str);
6726 EXPECT_HR(hr, S_OK);
6727 ok(!lstrcmpW( str, _bstr_("Model:name2")), "got %s\n", wine_dbgstr_w(str));
6728 SysFreeString(str);
6729
6730 hr = IXMLDOMAttribute_get_prefix(attr, &str);
6731 EXPECT_HR(hr, S_OK);
6732 ok(!lstrcmpW( str, _bstr_("Model")), "got %s\n", wine_dbgstr_w(str));
6733 SysFreeString(str);
6734
6735 IXMLDOMAttribute_Release(attr);
6736 IXMLDOMElement_Release(elem);
6737
6738 IXMLDOMNode_Release(node2);
6739 IXMLDOMNode_Release(node);
6740 }
6741
6742 IXMLDOMDocument_Release(doc);
6743
6744 free_bstrs();
6745 }
6746
6747 static void test_FormattingXML(void)
6748 {
6749 IXMLDOMDocument *doc;
6750 IXMLDOMElement *pElement;
6751 VARIANT_BOOL bSucc;
6752 HRESULT hr;
6753 BSTR str;
6754 static const CHAR szLinefeedXML[] = "<?xml version=\"1.0\"?>\n<Root>\n\t<Sub val=\"A\" />\n</Root>";
6755 static const CHAR szLinefeedRootXML[] = "<Root>\r\n\t<Sub val=\"A\"/>\r\n</Root>";
6756
6757 doc = create_document(&IID_IXMLDOMDocument);
6758
6759 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szLinefeedXML), &bSucc);
6760 ok(hr == S_OK, "ret %08x\n", hr );
6761 ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
6762
6763 if(bSucc == VARIANT_TRUE)
6764 {
6765 hr = IXMLDOMDocument_get_documentElement(doc, &pElement);
6766 ok(hr == S_OK, "ret %08x\n", hr );
6767 if(hr == S_OK)
6768 {
6769 hr = IXMLDOMElement_get_xml(pElement, &str);
6770 ok(hr == S_OK, "ret %08x\n", hr );
6771 ok( !lstrcmpW( str, _bstr_(szLinefeedRootXML) ), "incorrect element xml\n");
6772 SysFreeString(str);
6773
6774 IXMLDOMElement_Release(pElement);
6775 }
6776 }
6777
6778 IXMLDOMDocument_Release(doc);
6779
6780 free_bstrs();
6781 }
6782
6783 typedef struct _nodetypedvalue_t {
6784 const char *name;
6785 VARTYPE type;
6786 const char *value; /* value in string format */
6787 } nodetypedvalue_t;
6788
6789 static const nodetypedvalue_t get_nodetypedvalue[] = {
6790 { "root/string", VT_BSTR, "Wine" },
6791 { "root/string2", VT_BSTR, "String" },
6792 { "root/number", VT_BSTR, "12.44" },
6793 { "root/number2", VT_BSTR, "-3.71e3" },
6794 { "root/int", VT_I4, "-13" },
6795 { "root/fixed", VT_CY, "7322.9371" },
6796 { "root/bool", VT_BOOL, "-1" },
6797 { "root/datetime", VT_DATE, "40135.14" },
6798 { "root/datetimetz",VT_DATE, "37813.59" },
6799 { "root/date", VT_DATE, "665413" },
6800 { "root/time", VT_DATE, "0.5813889" },
6801 { "root/timetz", VT_DATE, "1.112512" },
6802 { "root/i1", VT_I1, "-13" },
6803 { "root/i2", VT_I2, "31915" },
6804 { "root/i4", VT_I4, "-312232" },
6805 { "root/ui1", VT_UI1, "123" },
6806 { "root/ui2", VT_UI2, "48282" },
6807 { "root/ui4", VT_UI4, "949281" },
6808 { "root/r4", VT_R4, "213124" },
6809 { "root/r8", VT_R8, "0.412" },
6810 { "root/float", VT_R8, "41221.421" },
6811 { "root/uuid", VT_BSTR, "333C7BC4-460F-11D0-BC04-0080C7055a83" },
6812 { "root/binbase64", VT_ARRAY|VT_UI1, "base64 test" },
6813 { "root/binbase64_1", VT_ARRAY|VT_UI1, "base64 test" },
6814 { "root/binbase64_2", VT_ARRAY|VT_UI1, "base64 test" },
6815 { 0 }
6816 };
6817
6818 static void test_nodeTypedValue(void)
6819 {
6820 const nodetypedvalue_t *entry = get_nodetypedvalue;
6821 IXMLDOMDocumentType *doctype, *doctype2;
6822 IXMLDOMProcessingInstruction *pi;
6823 IXMLDOMDocumentFragment *frag;
6824 IXMLDOMDocument *doc, *doc2;
6825 IXMLDOMCDATASection *cdata;
6826 IXMLDOMComment *comment;
6827 IXMLDOMNode *node;
6828 VARIANT_BOOL b;
6829 VARIANT value;
6830 HRESULT hr;
6831
6832 doc = create_document(&IID_IXMLDOMDocument);
6833
6834 b = VARIANT_FALSE;
6835 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &b);
6836 ok(hr == S_OK, "ret %08x\n", hr );
6837 ok(b == VARIANT_TRUE, "got %d\n", b);
6838
6839 hr = IXMLDOMDocument_get_nodeValue(doc, NULL);
6840 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6841
6842 V_VT(&value) = VT_BSTR;
6843 V_BSTR(&value) = NULL;
6844 hr = IXMLDOMDocument_get_nodeValue(doc, &value);
6845 ok(hr == S_FALSE, "ret %08x\n", hr );
6846 ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6847
6848 hr = IXMLDOMDocument_get_nodeTypedValue(doc, NULL);
6849 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6850
6851 V_VT(&value) = VT_EMPTY;
6852 hr = IXMLDOMDocument_get_nodeTypedValue(doc, &value);
6853 ok(hr == S_FALSE, "ret %08x\n", hr );
6854 ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6855
6856 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/string"), &node);
6857 ok(hr == S_OK, "ret %08x\n", hr );
6858
6859 V_VT(&value) = VT_BSTR;
6860 V_BSTR(&value) = NULL;
6861 hr = IXMLDOMNode_get_nodeValue(node, &value);
6862 ok(hr == S_FALSE, "ret %08x\n", hr );
6863 ok(V_VT(&value) == VT_NULL, "expect VT_NULL got %d\n", V_VT(&value));
6864
6865 hr = IXMLDOMNode_get_nodeTypedValue(node, NULL);
6866 ok(hr == E_INVALIDARG, "ret %08x\n", hr );
6867
6868 IXMLDOMNode_Release(node);
6869
6870 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("root/binhex"), &node);
6871 ok(hr == S_OK, "ret %08x\n", hr );
6872 {
6873 BYTE bytes[] = {0xff,0xfc,0xa0,0x12,0x00,0x3c};
6874
6875 hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6876 ok(hr == S_OK, "ret %08x\n", hr );
6877 ok(V_VT(&value) == (VT_ARRAY|VT_UI1), "incorrect type\n");
6878 ok(V_ARRAY(&value)->rgsabound[0].cElements == 6, "incorrect array size\n");
6879 if(V_ARRAY(&value)->rgsabound[0].cElements == 6)
6880 ok(!memcmp(bytes, V_ARRAY(&value)->pvData, sizeof(bytes)), "incorrect value\n");
6881 VariantClear(&value);
6882 IXMLDOMNode_Release(node);
6883 }
6884
6885 hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("foo"), _bstr_("value"), &pi);
6886 ok(hr == S_OK, "ret %08x\n", hr );
6887 {
6888 V_VT(&value) = VT_NULL;
6889 V_BSTR(&value) = (void*)0xdeadbeef;
6890 hr = IXMLDOMProcessingInstruction_get_nodeTypedValue(pi, &value);
6891 ok(hr == S_OK, "ret %08x\n", hr );
6892 ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6893 ok(!lstrcmpW(V_BSTR(&value), _bstr_("value")), "got wrong value\n");
6894 IXMLDOMProcessingInstruction_Release(pi);
6895 VariantClear(&value);
6896 }
6897
6898 hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("[1]*2=3; &gee that's not right!"), &cdata);
6899 ok(hr == S_OK, "ret %08x\n", hr );
6900 {
6901 V_VT(&value) = VT_NULL;
6902 V_BSTR(&value) = (void*)0xdeadbeef;
6903 hr = IXMLDOMCDATASection_get_nodeTypedValue(cdata, &value);
6904 ok(hr == S_OK, "ret %08x\n", hr );
6905 ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6906 ok(!lstrcmpW(V_BSTR(&value), _bstr_("[1]*2=3; &gee that's not right!")), "got wrong value\n");
6907 IXMLDOMCDATASection_Release(cdata);
6908 VariantClear(&value);
6909 }
6910
6911 hr = IXMLDOMDocument_createComment(doc, _bstr_("comment"), &comment);
6912 ok(hr == S_OK, "ret %08x\n", hr );
6913 {
6914 V_VT(&value) = VT_NULL;
6915 V_BSTR(&value) = (void*)0xdeadbeef;
6916 hr = IXMLDOMComment_get_nodeTypedValue(comment, &value);
6917 ok(hr == S_OK, "ret %08x\n", hr );
6918 ok(V_VT(&value) == VT_BSTR, "got %d\n", V_VT(&value));
6919 ok(!lstrcmpW(V_BSTR(&value), _bstr_("comment")), "got wrong value\n");
6920 IXMLDOMComment_Release(comment);
6921 VariantClear(&value);
6922 }
6923
6924 hr = IXMLDOMDocument_createDocumentFragment(doc, &frag);
6925 ok(hr == S_OK, "ret %08x\n", hr );
6926 {
6927 V_VT(&value) = VT_EMPTY;
6928 hr = IXMLDOMDocumentFragment_get_nodeTypedValue(frag, &value);
6929 ok(hr == S_FALSE, "ret %08x\n", hr );
6930 ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6931 IXMLDOMDocumentFragment_Release(frag);
6932 }
6933
6934 doc2 = create_document(&IID_IXMLDOMDocument);
6935
6936 b = VARIANT_FALSE;
6937 hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szEmailXML), &b);
6938 ok(hr == S_OK, "ret %08x\n", hr );
6939 ok(b == VARIANT_TRUE, "got %d\n", b);
6940
6941 EXPECT_REF(doc2, 1);
6942
6943 hr = IXMLDOMDocument_get_doctype(doc2, &doctype);
6944 ok(hr == S_OK, "ret %08x\n", hr );
6945
6946 EXPECT_REF(doc2, 1);
6947 todo_wine EXPECT_REF(doctype, 2);
6948
6949 {
6950 V_VT(&value) = VT_EMPTY;
6951 hr = IXMLDOMDocumentType_get_nodeTypedValue(doctype, &value);
6952 ok(hr == S_FALSE, "ret %08x\n", hr );
6953 ok(V_VT(&value) == VT_NULL, "got %d\n", V_VT(&value));
6954 }
6955
6956 hr = IXMLDOMDocument_get_doctype(doc2, &doctype2);
6957 ok(hr == S_OK, "ret %08x\n", hr );
6958 ok(doctype != doctype2, "got %p, was %p\n", doctype2, doctype);
6959
6960 IXMLDOMDocumentType_Release(doctype2);
6961 IXMLDOMDocumentType_Release(doctype);
6962
6963 IXMLDOMDocument_Release(doc2);
6964
6965 while (entry->name)
6966 {
6967 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_(entry->name), &node);
6968 ok(hr == S_OK, "ret %08x\n", hr );
6969
6970 hr = IXMLDOMNode_get_nodeTypedValue(node, &value);
6971 ok(hr == S_OK, "ret %08x\n", hr );
6972 ok(V_VT(&value) == entry->type, "incorrect type, expected %d, got %d\n", entry->type, V_VT(&value));
6973
6974 if (entry->type == (VT_ARRAY|VT_UI1))
6975 {
6976 ok(V_ARRAY(&value)->rgsabound[0].cElements == strlen(entry->value),
6977 "incorrect array size %d\n", V_ARRAY(&value)->rgsabound[0].cElements);
6978 }
6979
6980 if (entry->type != VT_BSTR)
6981 {
6982 if (entry->type == VT_DATE ||
6983 entry->type == VT_R8 ||
6984 entry->type == VT_CY)
6985 {
6986 if (entry->type == VT_DATE)
6987 {
6988 hr = VariantChangeType(&value, &value, 0, VT_R4);
6989 ok(hr == S_OK, "ret %08x\n", hr );
6990 }
6991 hr = VariantChangeTypeEx(&value, &value,
6992 MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), SORT_DEFAULT),
6993 VARIANT_NOUSEROVERRIDE, VT_BSTR);
6994 ok(hr == S_OK, "ret %08x\n", hr );
6995 }
6996 else
6997 {
6998 hr = VariantChangeType(&value, &value, 0, VT_BSTR);
6999 ok(hr == S_OK, "ret %08x\n", hr );
7000 }
7001
7002 /* for byte array from VT_ARRAY|VT_UI1 it's not a WCHAR buffer */
7003 if (entry->type == (VT_ARRAY|VT_UI1))
7004 {
7005 ok(!memcmp( V_BSTR(&value), entry->value, strlen(entry->value)),
7006 "expected %s\n", entry->value);
7007 }
7008 else
7009 ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
7010 "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
7011 }
7012 else
7013 ok(lstrcmpW( V_BSTR(&value), _bstr_(entry->value)) == 0,
7014 "expected %s, got %s\n", entry->value, wine_dbgstr_w(V_BSTR(&value)));
7015
7016 VariantClear( &value );
7017 IXMLDOMNode_Release(node);
7018
7019 entry++;
7020 }
7021
7022 IXMLDOMDocument_Release(doc);
7023 free_bstrs();
7024 }
7025
7026 static void test_TransformWithLoadingLocalFile(void)
7027 {
7028 IXMLDOMDocument *doc;
7029 IXMLDOMDocument *xsl;
7030 IXMLDOMNode *pNode;
7031 VARIANT_BOOL bSucc;
7032 HRESULT hr;
7033 HANDLE file;
7034 DWORD dwWritten;
7035 char lpPathBuffer[MAX_PATH];
7036 int i;
7037
7038 /* Create a Temp File. */
7039 GetTempPathA(MAX_PATH, lpPathBuffer);
7040 strcat(lpPathBuffer, "customers.xml" );
7041
7042 file = CreateFileA(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
7043 ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError());
7044 if(file == INVALID_HANDLE_VALUE)
7045 return;
7046
7047 WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL);
7048 CloseHandle(file);
7049
7050 /* Correct path to not include an escape character. */
7051 for(i=0; i < strlen(lpPathBuffer); i++)
7052 {
7053 if(lpPathBuffer[i] == '\\')
7054 lpPathBuffer[i] = '/';
7055 }
7056
7057 doc = create_document(&IID_IXMLDOMDocument);
7058 xsl = create_document(&IID_IXMLDOMDocument);
7059
7060 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTypeValueXML), &bSucc);
7061 ok(hr == S_OK, "ret %08x\n", hr );
7062 ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7063 if(bSucc == VARIANT_TRUE)
7064 {
7065 BSTR sXSL;
7066 BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1);
7067 BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2);
7068 BSTR sFileName = _bstr_(lpPathBuffer);
7069 int nLength = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1;
7070
7071 sXSL = SysAllocStringLen(NULL, nLength);
7072 lstrcpyW(sXSL, sPart1);
7073 lstrcatW(sXSL, sFileName);
7074 lstrcatW(sXSL, sPart2);
7075
7076 hr = IXMLDOMDocument_loadXML(xsl, sXSL, &bSucc);
7077 ok(hr == S_OK, "ret %08x\n", hr );
7078 ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n");
7079 if(bSucc == VARIANT_TRUE)
7080 {
7081 BSTR sResult;
7082
7083 hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (void**)&pNode );
7084 ok(hr == S_OK, "ret %08x\n", hr );
7085 if(hr == S_OK)
7086 {
7087 /* This will load the temp file via the XSL */
7088 hr = IXMLDOMDocument_transformNode(doc, pNode, &sResult);
7089 ok(hr == S_OK, "ret %08x\n", hr );
7090 if(hr == S_OK)
7091 {
7092 ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n");
7093 SysFreeString(sResult);
7094 }
7095
7096 IXMLDOMNode_Release(pNode);
7097 }
7098 }
7099
7100 SysFreeString(sXSL);
7101 }
7102
7103 IXMLDOMDocument_Release(doc);
7104 IXMLDOMDocument_Release(xsl);
7105
7106 DeleteFileA(lpPathBuffer);
7107 free_bstrs();
7108 }
7109
7110 static void test_put_nodeValue(void)
7111 {
7112 static const WCHAR jeevesW[] = {'J','e','e','v','e','s',' ','&',' ','W','o','o','s','t','e','r',0};
7113 IXMLDOMDocument *doc;
7114 IXMLDOMText *text;
7115 IXMLDOMEntityReference *entityref;
7116 IXMLDOMAttribute *attr;
7117 IXMLDOMNode *node;
7118 HRESULT hr;
7119 VARIANT data, type;
7120
7121 doc = create_document(&IID_IXMLDOMDocument);
7122
7123 /* test for unsupported types */
7124 /* NODE_DOCUMENT */
7125 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IXMLDOMNode, (void**)&node);
7126 ok(hr == S_OK, "ret %08x\n", hr );
7127 V_VT(&data) = VT_BSTR;
7128 V_BSTR(&data) = _bstr_("one two three");
7129 hr = IXMLDOMNode_put_nodeValue(node, data);
7130 ok(hr == E_FAIL, "ret %08x\n", hr );
7131 IXMLDOMNode_Release(node);
7132
7133 /* NODE_DOCUMENT_FRAGMENT */
7134 V_VT(&type) = VT_I1;
7135 V_I1(&type) = NODE_DOCUMENT_FRAGMENT;
7136 hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7137 ok(hr == S_OK, "ret %08x\n", hr );
7138 V_VT(&data) = VT_BSTR;
7139 V_BSTR(&data) = _bstr_("one two three");
7140 hr = IXMLDOMNode_put_nodeValue(node, data);
7141 ok(hr == E_FAIL, "ret %08x\n", hr );
7142 IXMLDOMNode_Release(node);
7143
7144 /* NODE_ELEMENT */
7145 V_VT(&type) = VT_I1;
7146 V_I1(&type) = NODE_ELEMENT;
7147 hr = IXMLDOMDocument_createNode(doc, type, _bstr_("test"), NULL, &node);
7148 ok(hr == S_OK, "ret %08x\n", hr );
7149 V_VT(&data) = VT_BSTR;
7150 V_BSTR(&data) = _bstr_("one two three");
7151 hr = IXMLDOMNode_put_nodeValue(node, data);
7152 ok(hr == E_FAIL, "ret %08x\n", hr );
7153 IXMLDOMNode_Release(node);
7154
7155 /* NODE_ENTITY_REFERENCE */
7156 hr = IXMLDOMDocument_createEntityReference(doc, _bstr_("ref"), &entityref);
7157 ok(hr == S_OK, "ret %08x\n", hr );
7158
7159 V_VT(&data) = VT_BSTR;
7160 V_BSTR(&data) = _bstr_("one two three");
7161 hr = IXMLDOMEntityReference_put_nodeValue(entityref, data);
7162 ok(hr == E_FAIL, "ret %08x\n", hr );
7163
7164 hr = IXMLDOMEntityReference_QueryInterface(entityref, &IID_IXMLDOMNode, (void**)&node);
7165 ok(hr == S_OK, "ret %08x\n", hr );
7166 V_VT(&data) = VT_BSTR;
7167 V_BSTR(&data) = _bstr_("one two three");
7168 hr = IXMLDOMNode_put_nodeValue(node, data);
7169 ok(hr == E_FAIL, "ret %08x\n", hr );
7170 IXMLDOMNode_Release(node);
7171 IXMLDOMEntityReference_Release(entityref);
7172
7173 /* supported types */
7174 hr = IXMLDOMDocument_createTextNode(doc, _bstr_(""), &text);
7175 ok(hr == S_OK, "ret %08x\n", hr );
7176 V_VT(&data) = VT_BSTR;
7177 V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7178 hr = IXMLDOMText_put_nodeValue(text, data);
7179 ok(hr == S_OK, "ret %08x\n", hr );
7180 IXMLDOMText_Release(text);
7181
7182 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
7183 ok(hr == S_OK, "ret %08x\n", hr );
7184 V_VT(&data) = VT_BSTR;
7185 V_BSTR(&data) = _bstr_("Jeeves & Wooster");
7186 hr = IXMLDOMAttribute_put_nodeValue(attr, data);
7187 ok(hr == S_OK, "ret %08x\n", hr );
7188 hr = IXMLDOMAttribute_get_nodeValue(attr, &data);
7189 ok(hr == S_OK, "ret %08x\n", hr );
7190 ok(memcmp(V_BSTR(&data), jeevesW, sizeof(jeevesW)) == 0, "got %s\n",
7191 wine_dbgstr_w(V_BSTR(&data)));
7192 VariantClear(&data);
7193 IXMLDOMAttribute_Release(attr);
7194
7195 free_bstrs();
7196
7197 IXMLDOMDocument_Release(doc);
7198 }
7199
7200 static void test_IObjectSafety(void)
7201 {
7202 IXMLDOMDocument *doc;
7203 IObjectSafety *safety;
7204 HRESULT hr;
7205
7206 doc = create_document(&IID_IXMLDOMDocument);
7207
7208 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IObjectSafety, (void**)&safety);
7209 ok(hr == S_OK, "ret %08x\n", hr );
7210
7211 test_IObjectSafety_common(safety);
7212
7213 IObjectSafety_Release(safety);
7214 IXMLDOMDocument_Release(doc);
7215
7216 hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
7217 &IID_IObjectSafety, (void**)&safety);
7218 ok(hr == S_OK, "Could not create XMLHTTPRequest instance: %08x\n", hr);
7219
7220 test_IObjectSafety_common(safety);
7221
7222 IObjectSafety_Release(safety);
7223
7224 }
7225
7226 typedef struct _property_test_t {
7227 const GUID *guid;
7228 const char *clsid;
7229 const char *property;
7230 const char *value;
7231 } property_test_t;
7232
7233 static const property_test_t properties_test_data[] = {
7234 { &CLSID_DOMDocument, "CLSID_DOMDocument" , "SelectionLanguage", "XSLPattern" },
7235 { &CLSID_DOMDocument2, "CLSID_DOMDocument2" , "SelectionLanguage", "XSLPattern" },
7236 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "SelectionLanguage", "XSLPattern" },
7237 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "SelectionLanguage", "XPath" },
7238 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "SelectionLanguage", "XPath" },
7239 { 0 }
7240 };
7241
7242 static void test_default_properties(void)
7243 {
7244 const property_test_t *entry = properties_test_data;
7245
7246 while (entry->guid)
7247 {
7248 IXMLDOMDocument2 *doc;
7249 VARIANT var;
7250 HRESULT hr;
7251
7252 if (!is_clsid_supported(entry->guid, &IID_IXMLDOMDocument2))
7253 {
7254 entry++;
7255 continue;
7256 }
7257
7258 hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void**)&doc);
7259 ok(hr == S_OK, "got 0x%08x\n", hr);
7260
7261 hr = IXMLDOMDocument2_getProperty(doc, _bstr_(entry->property), &var);
7262 ok(hr == S_OK, "got 0x%08x\n", hr);
7263 ok(lstrcmpW(V_BSTR(&var), _bstr_(entry->value)) == 0, "expected %s, for %s\n",
7264 entry->value, entry->clsid);
7265 VariantClear(&var);
7266
7267 IXMLDOMDocument2_Release(doc);
7268
7269 entry++;
7270 }
7271 }
7272
7273 typedef struct {
7274 const char *query;
7275 const char *list;
7276 BOOL todo;
7277 } xslpattern_test_t;
7278
7279 static const xslpattern_test_t xslpattern_test[] = {
7280 { "root//elem[0]", "E1.E2.D1" },
7281 { "root//elem[index()=1]", "E2.E2.D1" },
7282 { "root//elem[index() $eq$ 1]", "E2.E2.D1" },
7283 { "root//elem[end()]", "E4.E2.D1" },
7284 { "root//elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7285 { "root//elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7286 { "root//elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7287 { "root//elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7288 { "root//elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7289 { "root//elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7290 { "root//elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7291 { "root//elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7292 { "root//elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7293 { "root//elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7294 { "root//elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7295 { "root//elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7296 { "root//elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7297 { "root//elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7298 { "root//elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7299 { "root//elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7300 { "root//elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7301 { "root//elem[$any$ *='B2 field']", "E2.E2.D1" },
7302 { "root//elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7303 { "root//elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7304 { "root//elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7305 { "root//elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7306 { "root//elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7307 { "root//elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7308 { "root//elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7309 { "root/elem[0]", "E1.E2.D1" },
7310 { "root/elem[index()=1]", "E2.E2.D1" },
7311 { "root/elem[index() $eq$ 1]", "E2.E2.D1" },
7312 { "root/elem[end()]", "E4.E2.D1" },
7313 { "root/elem[$not$ end()]", "E1.E2.D1 E2.E2.D1 E3.E2.D1" },
7314 { "root/elem[index() != 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7315 { "root/elem[index() $ne$ 0]", "E2.E2.D1 E3.E2.D1 E4.E2.D1" },
7316 { "root/elem[index() < 2]", "E1.E2.D1 E2.E2.D1" },
7317 { "root/elem[index() $lt$ 2]", "E1.E2.D1 E2.E2.D1" },
7318 { "root/elem[index() <= 1]", "E1.E2.D1 E2.E2.D1" },
7319 { "root/elem[index() $le$ 1]", "E1.E2.D1 E2.E2.D1" },
7320 { "root/elem[index() > 1]", "E3.E2.D1 E4.E2.D1" },
7321 { "root/elem[index() $gt$ 1]", "E3.E2.D1 E4.E2.D1" },
7322 { "root/elem[index() >= 2]", "E3.E2.D1 E4.E2.D1" },
7323 { "root/elem[index() $ge$ 2]", "E3.E2.D1 E4.E2.D1" },
7324 { "root/elem[a $ieq$ 'a2 field']", "E2.E2.D1" },
7325 { "root/elem[a $ine$ 'a2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7326 { "root/elem[a $ilt$ 'a3 field']", "E1.E2.D1 E2.E2.D1" },
7327 { "root/elem[a $ile$ 'a2 field']", "E1.E2.D1 E2.E2.D1" },
7328 { "root/elem[a $igt$ 'a2 field']", "E3.E2.D1 E4.E2.D1" },
7329 { "root/elem[a $ige$ 'a3 field']", "E3.E2.D1 E4.E2.D1" },
7330 { "root/elem[$any$ *='B2 field']", "E2.E2.D1" },
7331 { "root/elem[$all$ *!='B2 field']", "E1.E2.D1 E3.E2.D1 E4.E2.D1" },
7332 { "root/elem[index()=0 or end()]", "E1.E2.D1 E4.E2.D1" },
7333 { "root/elem[index()=0 $or$ end()]", "E1.E2.D1 E4.E2.D1" },
7334 { "root/elem[index()=0 || end()]", "E1.E2.D1 E4.E2.D1" },
7335 { "root/elem[index()>0 and $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7336 { "root/elem[index()>0 $and$ $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7337 { "root/elem[index()>0 && $not$ end()]", "E2.E2.D1 E3.E2.D1" },
7338 { "root/elem[d]", "E1.E2.D1 E2.E2.D1 E4.E2.D1" },
7339 { "root/elem[@*]", "E2.E2.D1 E3.E2.D1", TRUE },
7340 { NULL }
7341 };
7342
7343 static const xslpattern_test_t xslpattern_test_no_ns[] = {
7344 /* prefixes don't need to be registered, you may use them as they are in the doc */
7345 { "//bar:x", "E6.E1.E5.E1.E2.D1 E6.E2.E5.E1.E2.D1" },
7346 /* prefixes must be explicitly specified in the name */
7347 { "//foo:elem", "" },
7348 { "//foo:c", "E3.E4.E2.D1" },
7349 { NULL }
7350 };
7351
7352 static const xslpattern_test_t xslpattern_test_func[] = {
7353 { "attribute()", "" },
7354 { "attribute('depth')", "" },
7355 { "root/attribute('depth')", "A'depth'.E3.D1" },
7356 { "//x/attribute()", "A'id'.E3.E3.D1 A'depth'.E3.E3.D1" },
7357 { "//x//attribute(id)", NULL },
7358 { "//x//attribute('id')", "A'id'.E3.E3.D1 A'id'.E4.E3.E3.D1 A'id'.E5.E3.E3.D1 A'id'.E6.E3.E3.D1" },
7359 { "comment()", "C2.D1" },
7360 { "//comment()", "C2.D1 C1.E3.D1 C2.E3.E3.D1 C2.E4.E3.D1" },
7361 { "element()", "E3.D1" },
7362 { "root/y/element()", "E4.E4.E3.D1 E5.E4.E3.D1 E6.E4.E3.D1" },
7363 { "//element(a)", NULL },
7364 { "//element('a')", "E4.E3.E3.D1 E4.E4.E3.D1" },
7365 { "node()", "P1.D1 C2.D1 E3.D1" },
7366 { "//x/node()", "P1.E3.E3.D1 C2.E3.E3.D1 T3.E3.E3.D1 E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
7367 { "//x/node()[nodeType()=1]", "E4.E3.E3.D1 E5.E3.E3.D1 E6.E3.E3.D1" },
7368 { "//x/node()[nodeType()=3]", "T3.E3.E3.D1" },
7369 { "//x/node()[nodeType()=7]", "P1.E3.E3.D1" },
7370 { "//x/node()[nodeType()=8]", "C2.E3.E3.D1" },
7371 { "pi()", "P1.D1" },
7372 { "//y/pi()", "P1.E4.E3.D1" },
7373 { "root/textnode()", "T2.E3.D1" },
7374 { "root/element()/textnode()", "T3.E3.E3.D1 T3.E4.E3.D1" },
7375 { NULL }
7376 };
7377
7378 static void test_XSLPattern(void)
7379 {
7380 const xslpattern_test_t *ptr = xslpattern_test;
7381 IXMLDOMDocument2 *doc;
7382 IXMLDOMNodeList *list;
7383 VARIANT_BOOL b;
7384 HRESULT hr;
7385 LONG len;
7386
7387 doc = create_document(&IID_IXMLDOMDocument2);
7388
7389 b = VARIANT_FALSE;
7390 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szExampleXML), &b);
7391 EXPECT_HR(hr, S_OK);
7392 ok(b == VARIANT_TRUE, "failed to load XML string\n");
7393
7394 /* switch to XSLPattern */
7395 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern"));
7396 EXPECT_HR(hr, S_OK);
7397
7398 /* XPath doesn't select elements with non-null default namespace with unqualified selectors, XSLPattern does */
7399 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//elem/c"), &list);
7400 EXPECT_HR(hr, S_OK);
7401
7402 len = 0;
7403 hr = IXMLDOMNodeList_get_length(list, &len);
7404 EXPECT_HR(hr, S_OK);
7405 /* should select <elem><c> and <elem xmlns='...'><c> but not <elem><foo:c> */
7406 ok(len == 3, "expected 3 entries in list, got %d\n", len);
7407 IXMLDOMNodeList_Release(list);
7408
7409 while (ptr->query)
7410 {
7411 list = NULL;
7412 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7413 ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7414 len = 0;
7415 hr = IXMLDOMNodeList_get_length(list, &len);
7416 ok(len != 0, "query=%s, empty list\n", ptr->query);
7417 if (len) {
7418 if (ptr->todo) {
7419 char *str = list_to_string(list);
7420 todo_wine
7421 ok(!strcmp(str, ptr->list), "Invalid node list: %s, expected %s\n", str, ptr->list);
7422 IXMLDOMNodeList_Release(list);
7423 }
7424 else
7425 expect_list_and_release(list, ptr->list);
7426 }
7427
7428 ptr++;
7429 }
7430
7431 /* namespace handling */
7432 /* no registered namespaces */
7433 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_(""));
7434 EXPECT_HR(hr, S_OK);
7435
7436 ptr = xslpattern_test_no_ns;
7437 while (ptr->query)
7438 {
7439 list = NULL;
7440 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7441 ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7442
7443 if (*ptr->list)
7444 {
7445 len = 0;
7446 hr = IXMLDOMNodeList_get_length(list, &len);
7447 EXPECT_HR(hr, S_OK);
7448 ok(len != 0, "query=%s, empty list\n", ptr->query);
7449 }
7450 else
7451 {
7452 len = 1;
7453 hr = IXMLDOMNodeList_get_length(list, &len);
7454 EXPECT_HR(hr, S_OK);
7455 ok(len == 0, "query=%s, empty list\n", ptr->query);
7456 }
7457 if (len)
7458 expect_list_and_release(list, ptr->list);
7459
7460 ptr++;
7461 }
7462
7463 /* explicitly register prefix foo */
7464 ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29'")));
7465
7466 /* now we get the same behavior as XPath */
7467 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7468 EXPECT_HR(hr, S_OK);
7469 len = 0;
7470 hr = IXMLDOMNodeList_get_length(list, &len);
7471 EXPECT_HR(hr, S_OK);
7472 ok(len != 0, "expected filled list\n");
7473 if (len)
7474 expect_list_and_release(list, "E3.E3.E2.D1 E3.E4.E2.D1");
7475
7476 /* set prefix foo to some nonexistent namespace */
7477 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:foo='urn:nonexistent-foo'"));
7478 EXPECT_HR(hr, S_OK);
7479
7480 /* the registered prefix takes precedence */
7481 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_("//foo:c"), &list);
7482 EXPECT_HR(hr, S_OK);
7483 len = 0;
7484 hr = IXMLDOMNodeList_get_length(list, &len);
7485 EXPECT_HR(hr, S_OK);
7486 ok(len == 0, "expected empty list\n");
7487 IXMLDOMNodeList_Release(list);
7488
7489 IXMLDOMDocument2_Release(doc);
7490
7491 doc = create_document(&IID_IXMLDOMDocument2);
7492
7493 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szNodeTypesXML), &b);
7494 EXPECT_HR(hr, S_OK);
7495 ok(b == VARIANT_TRUE, "failed to load XML string\n");
7496
7497 ptr = xslpattern_test_func;
7498 while (ptr->query)
7499 {
7500 list = NULL;
7501 hr = IXMLDOMDocument2_selectNodes(doc, _bstr_(ptr->query), &list);
7502 if (ptr->list)
7503 {
7504 ok(hr == S_OK, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7505 len = 0;
7506 hr = IXMLDOMNodeList_get_length(list, &len);
7507 ok(hr == S_OK, "Failed to get list length, hr %#x.\n", hr);
7508 if (*ptr->list)
7509 {
7510 ok(len != 0, "query=%s, empty list\n", ptr->query);
7511 if (len)
7512 expect_list_and_release(list, ptr->list);
7513 }
7514 else
7515 ok(len == 0, "query=%s, filled list\n", ptr->query);
7516 }
7517 else
7518 ok(hr == E_FAIL, "query=%s, failed with 0x%08x\n", ptr->query, hr);
7519
7520 ptr++;
7521 }
7522
7523 IXMLDOMDocument2_Release(doc);
7524 free_bstrs();
7525 }
7526
7527 static void test_splitText(void)
7528 {
7529 IXMLDOMCDATASection *cdata;
7530 IXMLDOMElement *root;
7531 IXMLDOMDocument *doc;
7532 IXMLDOMText *text, *text2;
7533 IXMLDOMNode *node;
7534 VARIANT var;
7535 VARIANT_BOOL success;
7536 LONG length;
7537 HRESULT hr;
7538
7539 doc = create_document(&IID_IXMLDOMDocument);
7540
7541 hr = IXMLDOMDocument_loadXML(doc, _bstr_("<root></root>"), &success);
7542 ok(hr == S_OK, "got 0x%08x\n", hr);
7543
7544 hr = IXMLDOMDocument_get_documentElement(doc, &root);
7545 ok(hr == S_OK, "got 0x%08x\n", hr);
7546
7547 hr = IXMLDOMDocument_createCDATASection(doc, _bstr_("beautiful plumage"), &cdata);
7548 ok(hr == S_OK, "got 0x%08x\n", hr);
7549
7550 V_VT(&var) = VT_EMPTY;
7551 hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)cdata, NULL);
7552 ok(hr == S_OK, "got 0x%08x\n", hr);
7553
7554 length = 0;
7555 hr = IXMLDOMCDATASection_get_length(cdata, &length);
7556 ok(hr == S_OK, "got 0x%08x\n", hr);
7557 ok(length > 0, "got %d\n", length);
7558
7559 hr = IXMLDOMCDATASection_splitText(cdata, 0, NULL);
7560 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7561
7562 text = (void*)0xdeadbeef;
7563 /* negative offset */
7564 hr = IXMLDOMCDATASection_splitText(cdata, -1, &text);
7565 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7566 ok(text == (void*)0xdeadbeef, "got %p\n", text);
7567
7568 text = (void*)0xdeadbeef;
7569 /* offset outside data */
7570 hr = IXMLDOMCDATASection_splitText(cdata, length + 1, &text);
7571 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7572 ok(text == 0, "got %p\n", text);
7573
7574 text = (void*)0xdeadbeef;
7575 /* offset outside data */
7576 hr = IXMLDOMCDATASection_splitText(cdata, length, &text);
7577 ok(hr == S_FALSE, "got 0x%08x\n", hr);
7578 ok(text == 0, "got %p\n", text);
7579
7580 /* no empty node created */
7581 node = (void*)0xdeadbeef;
7582 hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7583 ok(hr == S_FALSE, "got 0x%08x\n", hr);
7584 ok(node == 0, "got %p\n", text);
7585
7586 hr = IXMLDOMCDATASection_splitText(cdata, 10, &text);
7587 ok(hr == S_OK, "got 0x%08x\n", hr);
7588
7589 length = 0;
7590 hr = IXMLDOMText_get_length(text, &length);
7591 ok(hr == S_OK, "got 0x%08x\n", hr);
7592 ok(length == 7, "got %d\n", length);
7593
7594 hr = IXMLDOMCDATASection_get_nextSibling(cdata, &node);
7595 ok(hr == S_OK, "got 0x%08x\n", hr);
7596 IXMLDOMNode_Release(node);
7597
7598 /* split new text node */
7599 hr = IXMLDOMText_get_length(text, &length);
7600 ok(hr == S_OK, "got 0x%08x\n", hr);
7601
7602 node = (void*)0xdeadbeef;
7603 hr = IXMLDOMText_get_nextSibling(text, &node);
7604 ok(hr == S_FALSE, "got 0x%08x\n", hr);
7605 ok(node == 0, "got %p\n", text);
7606
7607 hr = IXMLDOMText_splitText(text, 0, NULL);
7608 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7609
7610 text2 = (void*)0xdeadbeef;
7611 /* negative offset */
7612 hr = IXMLDOMText_splitText(text, -1, &text2);
7613 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7614 ok(text2 == (void*)0xdeadbeef, "got %p\n", text2);
7615
7616 text2 = (void*)0xdeadbeef;
7617 /* offset outside data */
7618 hr = IXMLDOMText_splitText(text, length + 1, &text2);
7619 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
7620 ok(text2 == 0, "got %p\n", text2);
7621
7622 text2 = (void*)0xdeadbeef;
7623 /* offset outside data */
7624 hr = IXMLDOMText_splitText(text, length, &text2);
7625 ok(hr == S_FALSE, "got 0x%08x\n", hr);
7626 ok(text2 == 0, "got %p\n", text);
7627
7628 text2 = 0;
7629 hr = IXMLDOMText_splitText(text, 4, &text2);
7630 todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7631 if (text2) IXMLDOMText_Release(text2);
7632
7633 node = 0;
7634 hr = IXMLDOMText_get_nextSibling(text, &node);
7635 todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
7636 if (node) IXMLDOMNode_Release(node);
7637
7638 IXMLDOMText_Release(text);
7639 IXMLDOMElement_Release(root);
7640 IXMLDOMCDATASection_Release(cdata);
7641 free_bstrs();
7642 }
7643
7644 typedef struct {
7645 const char *name;
7646 const char *uri;
7647 HRESULT hr;
7648 } ns_item_t;
7649
7650 /* default_ns_doc used */
7651 static const ns_item_t qualified_item_tests[] = {
7652 { "xml:lang", NULL, S_FALSE },
7653 { "xml:lang", "http://www.w3.org/XML/1998/namespace", S_FALSE },
7654 { "lang", "http://www.w3.org/XML/1998/namespace", S_OK },
7655 { "ns:b", NULL, S_FALSE },
7656 { "ns:b", "nshref", S_FALSE },
7657 { "b", "nshref", S_OK },
7658 { "d", NULL, S_OK },
7659 { NULL }
7660 };
7661
7662 static const ns_item_t named_item_tests[] = {
7663 { "xml:lang", NULL, S_OK },
7664 { "lang", NULL, S_FALSE },
7665 { "ns:b", NULL, S_OK },
7666 { "b", NULL, S_FALSE },
7667 { "d", NULL, S_OK },
7668 { NULL }
7669 };
7670
7671 static void test_getQualifiedItem(void)
7672 {
7673 IXMLDOMNode *pr_node, *node;
7674 IXMLDOMNodeList *root_list;
7675 IXMLDOMNamedNodeMap *map;
7676 IXMLDOMElement *element;
7677 const ns_item_t* ptr;
7678 IXMLDOMDocument *doc;
7679 VARIANT_BOOL b;
7680 HRESULT hr;
7681 LONG len;
7682
7683 doc = create_document(&IID_IXMLDOMDocument);
7684
7685 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7686 EXPECT_HR(hr, S_OK);
7687 ok( b == VARIANT_TRUE, "failed to load XML string\n");
7688
7689 hr = IXMLDOMDocument_get_documentElement(doc, &element);
7690 EXPECT_HR(hr, S_OK);
7691
7692 hr = IXMLDOMElement_get_childNodes(element, &root_list);
7693 EXPECT_HR(hr, S_OK);
7694
7695 hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7696 EXPECT_HR(hr, S_OK);
7697 IXMLDOMNodeList_Release(root_list);
7698
7699 hr = IXMLDOMNode_get_attributes(pr_node, &map);
7700 EXPECT_HR(hr, S_OK);
7701 IXMLDOMNode_Release(pr_node);
7702
7703 len = 0;
7704 hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7705 EXPECT_HR(hr, S_OK);
7706 ok( len == 3, "length %d\n", len);
7707
7708 hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, NULL);
7709 EXPECT_HR(hr, E_INVALIDARG);
7710
7711 node = (void*)0xdeadbeef;
7712 hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, NULL, NULL, &node);
7713 EXPECT_HR(hr, E_INVALIDARG);
7714 ok( node == (void*)0xdeadbeef, "got %p\n", node);
7715
7716 hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, NULL);
7717 EXPECT_HR(hr, E_INVALIDARG);
7718
7719 hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_("id"), NULL, &node);
7720 EXPECT_HR(hr, S_OK);
7721
7722 IXMLDOMNode_Release(node);
7723 IXMLDOMNamedNodeMap_Release(map);
7724 IXMLDOMElement_Release(element);
7725
7726 hr = IXMLDOMDocument_loadXML(doc, _bstr_(default_ns_doc), &b);
7727 EXPECT_HR(hr, S_OK);
7728
7729 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
7730 EXPECT_HR(hr, S_OK);
7731
7732 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
7733 EXPECT_HR(hr, S_OK);
7734 IXMLDOMNode_Release(node);
7735
7736 hr = IXMLDOMElement_get_attributes(element, &map);
7737 EXPECT_HR(hr, S_OK);
7738
7739 ptr = qualified_item_tests;
7740 while (ptr->name)
7741 {
7742 node = (void*)0xdeadbeef;
7743 hr = IXMLDOMNamedNodeMap_getQualifiedItem(map, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
7744 ok(hr == ptr->hr, "%s, %s: got 0x%08x, expected 0x%08x\n", ptr->name, ptr->uri, hr, ptr->hr);
7745 if (hr == S_OK)
7746 IXMLDOMNode_Release(node);
7747 else
7748 ok(node == NULL, "%s, %s: got %p\n", ptr->name, ptr->uri, node);
7749 ptr++;
7750 }
7751
7752 ptr = named_item_tests;
7753 while (ptr->name)
7754 {
7755 node = (void*)0xdeadbeef;
7756 hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_(ptr->name), &node);
7757 ok(hr == ptr->hr, "%s: got 0x%08x, expected 0x%08x\n", ptr->name, hr, ptr->hr);
7758 if (hr == S_OK)
7759 IXMLDOMNode_Release(node);
7760 else
7761 ok(node == NULL, "%s: got %p\n", ptr->name, node);
7762 ptr++;
7763 }
7764
7765 IXMLDOMNamedNodeMap_Release(map);
7766
7767 IXMLDOMElement_Release(element);
7768 IXMLDOMDocument_Release(doc);
7769 free_bstrs();
7770 }
7771
7772 static void test_removeQualifiedItem(void)
7773 {
7774 IXMLDOMDocument *doc;
7775 IXMLDOMElement *element;
7776 IXMLDOMNode *pr_node, *node;
7777 IXMLDOMNodeList *root_list;
7778 IXMLDOMNamedNodeMap *map;
7779 VARIANT_BOOL b;
7780 LONG len;
7781 HRESULT hr;
7782
7783 doc = create_document(&IID_IXMLDOMDocument);
7784
7785 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
7786 ok( hr == S_OK, "loadXML failed\n");
7787 ok( b == VARIANT_TRUE, "failed to load XML string\n");
7788
7789 hr = IXMLDOMDocument_get_documentElement(doc, &element);
7790 ok( hr == S_OK, "ret %08x\n", hr);
7791
7792 hr = IXMLDOMElement_get_childNodes(element, &root_list);
7793 ok( hr == S_OK, "ret %08x\n", hr);
7794
7795 hr = IXMLDOMNodeList_get_item(root_list, 1, &pr_node);
7796 ok( hr == S_OK, "ret %08x\n", hr);
7797 IXMLDOMNodeList_Release(root_list);
7798
7799 hr = IXMLDOMNode_get_attributes(pr_node, &map);
7800 ok( hr == S_OK, "ret %08x\n", hr);
7801 IXMLDOMNode_Release(pr_node);
7802
7803 hr = IXMLDOMNamedNodeMap_get_length(map, &len);
7804 ok( hr == S_OK, "ret %08x\n", hr);
7805 ok( len == 3, "length %d\n", len);
7806
7807 hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, NULL);
7808 ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7809
7810 node = (void*)0xdeadbeef;
7811 hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, NULL, NULL, &node);
7812 ok( hr == E_INVALIDARG, "ret %08x\n", hr);
7813 ok( node == (void*)0xdeadbeef, "got %p\n", node);
7814
7815 /* out pointer is optional */
7816 hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7817 ok( hr == S_OK, "ret %08x\n", hr);
7818
7819 /* already removed */
7820 hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("id"), NULL, NULL);
7821 ok( hr == S_FALSE, "ret %08x\n", hr);
7822
7823 hr = IXMLDOMNamedNodeMap_removeQualifiedItem(map, _bstr_("vr"), NULL, &node);
7824 ok( hr == S_OK, "ret %08x\n", hr);
7825 IXMLDOMNode_Release(node);
7826
7827 IXMLDOMNamedNodeMap_Release( map );
7828 IXMLDOMElement_Release( element );
7829 IXMLDOMDocument_Release( doc );
7830 free_bstrs();
7831 }
7832
7833 #define check_default_props(doc) _check_default_props(__LINE__, doc)
7834 static inline void _check_default_props(int line, IXMLDOMDocument2* doc)
7835 {
7836 VARIANT_BOOL b;
7837 VARIANT var;
7838 HRESULT hr;
7839
7840 VariantInit(&var);
7841 helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7842 ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XSLPattern")) == 0, "expected XSLPattern\n");
7843 VariantClear(&var);
7844
7845 helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7846 ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("")) == 0, "expected empty string\n");
7847 VariantClear(&var);
7848
7849 helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7850 ok_(__FILE__, line)(b == VARIANT_FALSE, "expected FALSE\n");
7851
7852 hr = IXMLDOMDocument2_get_schemas(doc, &var);
7853 ok_(__FILE__, line)(hr == S_FALSE, "got %08x\n", hr);
7854 VariantClear(&var);
7855 }
7856
7857 #define check_set_props(doc) _check_set_props(__LINE__, doc)
7858 static inline void _check_set_props(int line, IXMLDOMDocument2* doc)
7859 {
7860 VARIANT_BOOL b;
7861 VARIANT var;
7862
7863 VariantInit(&var);
7864 helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionLanguage"), &var));
7865 ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("XPath")) == 0, "expected XPath\n");
7866 VariantClear(&var);
7867
7868 helper_ole_check(IXMLDOMDocument2_getProperty(doc, _bstr_("SelectionNamespaces"), &var));
7869 ok_(__FILE__, line)(lstrcmpW(V_BSTR(&var), _bstr_("xmlns:wi=\'www.winehq.org\'")) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
7870 VariantClear(&var);
7871
7872 helper_ole_check(IXMLDOMDocument2_get_preserveWhiteSpace(doc, &b));
7873 ok_(__FILE__, line)(b == VARIANT_TRUE, "expected TRUE\n");
7874
7875 helper_ole_check(IXMLDOMDocument2_get_schemas(doc, &var));
7876 ok_(__FILE__, line)(V_VT(&var) != VT_NULL, "expected pointer\n");
7877 VariantClear(&var);
7878 }
7879
7880 #define set_props(doc, cache) _set_props(__LINE__, doc, cache)
7881 static inline void _set_props(int line, IXMLDOMDocument2* doc, IXMLDOMSchemaCollection* cache)
7882 {
7883 VARIANT var;
7884
7885 VariantInit(&var);
7886 helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XPath")));
7887 helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("xmlns:wi=\'www.winehq.org\'")));
7888 helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_TRUE));
7889 V_VT(&var) = VT_DISPATCH;
7890 V_DISPATCH(&var) = NULL;
7891 helper_ole_check(IXMLDOMSchemaCollection_QueryInterface(cache, &IID_IDispatch, (void**)&V_DISPATCH(&var)));
7892 ok_(__FILE__, line)(V_DISPATCH(&var) != NULL, "expected pointer\n");
7893 helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7894 VariantClear(&var);
7895 }
7896
7897 #define unset_props(doc) _unset_props(__LINE__, doc)
7898 static inline void _unset_props(int line, IXMLDOMDocument2* doc)
7899 {
7900 VARIANT var;
7901
7902 VariantInit(&var);
7903 helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionLanguage"), _variantbstr_("XSLPattern")));
7904 helper_ole_check(IXMLDOMDocument2_setProperty(doc, _bstr_("SelectionNamespaces"), _variantbstr_("")));
7905 helper_ole_check(IXMLDOMDocument2_put_preserveWhiteSpace(doc, VARIANT_FALSE));
7906 V_VT(&var) = VT_NULL;
7907 helper_ole_check(IXMLDOMDocument2_putref_schemas(doc, var));
7908 VariantClear(&var);
7909 }
7910
7911 static void test_get_ownerDocument(void)
7912 {
7913 IXMLDOMDocument *doc1, *doc2, *doc3;
7914 IXMLDOMDocument2 *doc, *doc_owner;
7915 IXMLDOMNode *node;
7916 IXMLDOMSchemaCollection *cache;
7917 VARIANT_BOOL b;
7918 VARIANT var;
7919 IXMLDOMElement *element;
7920 IXMLDOMNodeList *node_list;
7921 IXMLDOMAttribute *attr;
7922 LONG i, len;
7923 HRESULT hr;
7924 const CHAR nodeXML[] =
7925 "<root id='0'>"
7926 " <!-- comment node 0 -->"
7927 " text node 0"
7928 " <x attr='val'></x>"
7929 " <?foo value='PI for x'?>"
7930 " <![CDATA[ cdata ]]>"
7931 "</root>";
7932
7933 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
7934 if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
7935
7936 doc = create_document(&IID_IXMLDOMDocument2);
7937 cache = create_cache(&IID_IXMLDOMSchemaCollection);
7938
7939 VariantInit(&var);
7940
7941 ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7942 ok(b == VARIANT_TRUE, "failed to load XML string\n");
7943
7944 check_default_props(doc);
7945
7946 /* set properties and check that new instances use them */
7947 set_props(doc, cache);
7948 check_set_props(doc);
7949
7950 ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7951 ole_check(IXMLDOMNode_get_ownerDocument(node, &doc1));
7952
7953 /* new interface keeps props */
7954 ole_check(IXMLDOMDocument_QueryInterface(doc1, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7955 ok( doc_owner != doc, "got %p, doc %p\n", doc_owner, doc);
7956 check_set_props(doc_owner);
7957 IXMLDOMDocument2_Release(doc_owner);
7958
7959 ole_check(IXMLDOMNode_get_ownerDocument(node, &doc2));
7960 IXMLDOMNode_Release(node);
7961
7962 ok(doc1 != doc2, "got %p, expected %p. original %p\n", doc2, doc1, doc);
7963
7964 /* reload */
7965 ole_check(IXMLDOMDocument2_loadXML(doc, _bstr_(complete4A), &b));
7966 ok(b == VARIANT_TRUE, "failed to load XML string\n");
7967
7968 /* properties retained even after reload */
7969 check_set_props(doc);
7970
7971 ole_check(IXMLDOMDocument2_get_firstChild(doc, &node));
7972 ole_check(IXMLDOMNode_get_ownerDocument(node, &doc3));
7973 IXMLDOMNode_Release(node);
7974
7975 ole_check(IXMLDOMDocument_QueryInterface(doc3, &IID_IXMLDOMDocument2, (void**)&doc_owner));
7976 ok(doc3 != doc1 && doc3 != doc2 && doc_owner != doc, "got %p, (%p, %p, %p)\n", doc3, doc, doc1, doc2);
7977 check_set_props(doc_owner);
7978
7979 /* changing properties for one instance changes them for all */
7980 unset_props(doc_owner);
7981 check_default_props(doc_owner);
7982 check_default_props(doc);
7983
7984 /* NULL check */
7985 hr = IXMLDOMDocument_loadXML(doc1, _bstr_(nodeXML), &b);
7986 EXPECT_HR(hr, S_OK);
7987 ok(b == VARIANT_TRUE, "failed to load XML string\n");
7988
7989 hr = IXMLDOMDocument_get_documentElement(doc1, &element);
7990 EXPECT_HR(hr, S_OK);
7991
7992 hr = IXMLDOMElement_get_childNodes(element, &node_list);
7993 EXPECT_HR(hr, S_OK);
7994
7995 hr = IXMLDOMNodeList_get_length(node_list, &len);
7996 EXPECT_HR(hr, S_OK);
7997
7998 for(i = 0; i < len; i++) {
7999 hr = IXMLDOMNodeList_get_item(node_list, i, &node);
8000 EXPECT_HR(hr, S_OK);
8001
8002 hr = IXMLDOMNode_get_ownerDocument(node, NULL);
8003 EXPECT_HR(hr, E_INVALIDARG);
8004
8005 IXMLDOMNode_Release(node);
8006 }
8007 IXMLDOMElement_Release(element);
8008
8009 /* Test Attribute Node */
8010 hr = IXMLDOMNodeList_get_item(node_list, 2, &node);
8011 EXPECT_HR(hr, S_OK);
8012 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&element);
8013 EXPECT_HR(hr, S_OK);
8014 IXMLDOMNode_Release(node);
8015
8016 hr = IXMLDOMElement_getAttributeNode(element, _bstr_("attr"), &attr);
8017 EXPECT_HR(hr, S_OK);
8018 ok(attr != NULL, "attr == NULL\n");
8019 IXMLDOMElement_Release(element);
8020 hr = IXMLDOMAttribute_get_ownerDocument(attr, NULL);
8021 EXPECT_HR(hr, E_INVALIDARG);
8022 IXMLDOMAttribute_Release(attr);
8023 IXMLDOMNodeList_Release(node_list);
8024
8025 IXMLDOMSchemaCollection_Release(cache);
8026 IXMLDOMDocument_Release(doc1);
8027 IXMLDOMDocument_Release(doc2);
8028 IXMLDOMDocument_Release(doc3);
8029 IXMLDOMDocument2_Release(doc);
8030 //IXMLDOMDocument2_Release(doc_owner); FIXME: double-free!
8031 free_bstrs();
8032 }
8033
8034 static void test_setAttributeNode(void)
8035 {
8036 IXMLDOMDocument *doc, *doc2;
8037 IXMLDOMElement *elem, *elem2;
8038 IXMLDOMAttribute *attr, *attr2, *ret_attr;
8039 VARIANT_BOOL b;
8040 HRESULT hr;
8041 VARIANT v;
8042 BSTR str;
8043 ULONG ref1, ref2;
8044
8045 doc = create_document(&IID_IXMLDOMDocument);
8046
8047 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8048 ok( hr == S_OK, "loadXML failed\n");
8049 ok( b == VARIANT_TRUE, "failed to load XML string\n");
8050
8051 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8052 ok( hr == S_OK, "got 0x%08x\n", hr);
8053
8054 hr = IXMLDOMDocument_get_documentElement(doc, &elem2);
8055 ok( hr == S_OK, "got 0x%08x\n", hr);
8056 ok( elem2 != elem, "got same instance\n");
8057
8058 ret_attr = (void*)0xdeadbeef;
8059 hr = IXMLDOMElement_setAttributeNode(elem, NULL, &ret_attr);
8060 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8061 ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8062
8063 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8064 ok( hr == S_OK, "got 0x%08x\n", hr);
8065
8066 ref1 = IXMLDOMElement_AddRef(elem);
8067 IXMLDOMElement_Release(elem);
8068
8069 ret_attr = (void*)0xdeadbeef;
8070 hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8071 ok( hr == S_OK, "got 0x%08x\n", hr);
8072 ok( ret_attr == NULL, "got %p\n", ret_attr);
8073
8074 /* no reference added */
8075 ref2 = IXMLDOMElement_AddRef(elem);
8076 IXMLDOMElement_Release(elem);
8077 ok(ref2 == ref1, "got %d, expected %d\n", ref2, ref1);
8078
8079 EXPECT_CHILDREN(elem);
8080 EXPECT_CHILDREN(elem2);
8081
8082 IXMLDOMElement_Release(elem2);
8083
8084 attr2 = NULL;
8085 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("attr"), &attr2);
8086 ok( hr == S_OK, "got 0x%08x\n", hr);
8087 ok( attr2 != attr, "got same instance %p\n", attr2);
8088 IXMLDOMAttribute_Release(attr2);
8089
8090 /* try to add it another time */
8091 ret_attr = (void*)0xdeadbeef;
8092 hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8093 ok( hr == E_FAIL, "got 0x%08x\n", hr);
8094 ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8095
8096 IXMLDOMElement_Release(elem);
8097
8098 /* initially used element is released, attribute still 'has' a container */
8099 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
8100 ok( hr == S_OK, "got 0x%08x\n", hr);
8101 ret_attr = (void*)0xdeadbeef;
8102 hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8103 ok( hr == E_FAIL, "got 0x%08x\n", hr);
8104 ok( ret_attr == (void*)0xdeadbeef, "got %p\n", ret_attr);
8105 IXMLDOMElement_Release(elem);
8106
8107 /* add attribute already attached to another document */
8108 doc2 = create_document(&IID_IXMLDOMDocument);
8109
8110 hr = IXMLDOMDocument_loadXML( doc2, _bstr_(complete4A), &b );
8111 ok( hr == S_OK, "loadXML failed\n");
8112 ok( b == VARIANT_TRUE, "failed to load XML string\n");
8113
8114 hr = IXMLDOMDocument_get_documentElement(doc2, &elem);
8115 ok( hr == S_OK, "got 0x%08x\n", hr);
8116 hr = IXMLDOMElement_setAttributeNode(elem, attr, NULL);
8117 ok( hr == E_FAIL, "got 0x%08x\n", hr);
8118 IXMLDOMElement_Release(elem);
8119
8120 IXMLDOMAttribute_Release(attr);
8121
8122 /* create element, add attribute, see if it's copied or linked */
8123 hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
8124 ok( hr == S_OK, "got 0x%08x\n", hr);
8125
8126 attr = NULL;
8127 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8128 ok(hr == S_OK, "got 0x%08x\n", hr);
8129 ok(attr != NULL, "got %p\n", attr);
8130
8131 ref1 = IXMLDOMAttribute_AddRef(attr);
8132 IXMLDOMAttribute_Release(attr);
8133
8134 V_VT(&v) = VT_BSTR;
8135 V_BSTR(&v) = _bstr_("attrvalue1");
8136 hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8137 ok( hr == S_OK, "got 0x%08x\n", hr);
8138
8139 str = NULL;
8140 hr = IXMLDOMAttribute_get_xml(attr, &str);
8141 ok( hr == S_OK, "got 0x%08x\n", hr);
8142 ok( lstrcmpW(str, _bstr_("attr=\"attrvalue1\"")) == 0,
8143 "got %s\n", wine_dbgstr_w(str));
8144 SysFreeString(str);
8145
8146 ret_attr = (void*)0xdeadbeef;
8147 hr = IXMLDOMElement_setAttributeNode(elem, attr, &ret_attr);
8148 ok(hr == S_OK, "got 0x%08x\n", hr);
8149 ok(ret_attr == NULL, "got %p\n", ret_attr);
8150
8151 /* attribute reference increased */
8152 ref2 = IXMLDOMAttribute_AddRef(attr);
8153 IXMLDOMAttribute_Release(attr);
8154 ok(ref1 == ref2, "got %d, expected %d\n", ref2, ref1);
8155
8156 hr = IXMLDOMElement_get_xml(elem, &str);
8157 ok( hr == S_OK, "got 0x%08x\n", hr);
8158 ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue1\"/>")) == 0,
8159 "got %s\n", wine_dbgstr_w(str));
8160 SysFreeString(str);
8161
8162 V_VT(&v) = VT_BSTR;
8163 V_BSTR(&v) = _bstr_("attrvalue2");
8164 hr = IXMLDOMAttribute_put_nodeValue(attr, v);
8165 ok( hr == S_OK, "got 0x%08x\n", hr);
8166
8167 hr = IXMLDOMElement_get_xml(elem, &str);
8168 ok( hr == S_OK, "got 0x%08x\n", hr);
8169 todo_wine ok( lstrcmpW(str, _bstr_("<test attr=\"attrvalue2\"/>")) == 0,
8170 "got %s\n", wine_dbgstr_w(str));
8171 SysFreeString(str);
8172
8173 IXMLDOMElement_Release(elem);
8174 IXMLDOMAttribute_Release(attr);
8175 IXMLDOMDocument_Release(doc2);
8176 IXMLDOMDocument_Release(doc);
8177 free_bstrs();
8178 }
8179
8180 static void test_createNode(void)
8181 {
8182 IXMLDOMDocument *doc;
8183 IXMLDOMElement *elem;
8184 IXMLDOMNode *node;
8185 VARIANT v, var;
8186 BSTR prefix, str;
8187 HRESULT hr;
8188 ULONG ref;
8189
8190 doc = create_document(&IID_IXMLDOMDocument);
8191
8192 EXPECT_REF(doc, 1);
8193
8194 /* reference count tests */
8195 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8196 ok( hr == S_OK, "got 0x%08x\n", hr);
8197
8198 /* initial reference is 2 */
8199 todo_wine {
8200 EXPECT_REF(elem, 2);
8201 ref = IXMLDOMElement_Release(elem);
8202 ok(ref == 1, "got %d\n", ref);
8203 /* it's released already, attempt to release now will crash it */
8204 }
8205
8206 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
8207 ok( hr == S_OK, "got 0x%08x\n", hr);
8208 todo_wine EXPECT_REF(elem, 2);
8209 IXMLDOMDocument_Release(doc);
8210 todo_wine EXPECT_REF(elem, 2);
8211 IXMLDOMElement_Release(elem);
8212
8213 doc = create_document(&IID_IXMLDOMDocument);
8214
8215 /* NODE_ELEMENT nodes */
8216 /* 1. specified namespace */
8217 V_VT(&v) = VT_I4;
8218 V_I4(&v) = NODE_ELEMENT;
8219
8220 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("ns1:test"), _bstr_("http://winehq.org"), &node);
8221 ok( hr == S_OK, "got 0x%08x\n", hr);
8222 prefix = NULL;
8223 hr = IXMLDOMNode_get_prefix(node, &prefix);
8224 ok( hr == S_OK, "got 0x%08x\n", hr);
8225 ok(lstrcmpW(prefix, _bstr_("ns1")) == 0, "wrong prefix\n");
8226 SysFreeString(prefix);
8227 IXMLDOMNode_Release(node);
8228
8229 /* 2. default namespace */
8230 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("test"), _bstr_("http://winehq.org/default"), &node);
8231 ok( hr == S_OK, "got 0x%08x\n", hr);
8232 prefix = (void*)0xdeadbeef;
8233 hr = IXMLDOMNode_get_prefix(node, &prefix);
8234 ok( hr == S_FALSE, "got 0x%08x\n", hr);
8235 ok(prefix == 0, "expected empty prefix, got %p\n", prefix);
8236 /* check dump */
8237 hr = IXMLDOMNode_get_xml(node, &str);
8238 ok( hr == S_OK, "got 0x%08x\n", hr);
8239 ok( lstrcmpW(str, _bstr_("<test xmlns=\"http://winehq.org/default\"/>")) == 0,
8240 "got %s\n", wine_dbgstr_w(str));
8241 SysFreeString(str);
8242
8243 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
8244 ok( hr == S_OK, "got 0x%08x\n", hr);
8245
8246 V_VT(&var) = VT_BSTR;
8247 hr = IXMLDOMElement_getAttribute(elem, _bstr_("xmlns"), &var);
8248 ok( hr == S_FALSE, "got 0x%08x\n", hr);
8249 ok( V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
8250
8251 str = NULL;
8252 hr = IXMLDOMElement_get_namespaceURI(elem, &str);
8253 ok( hr == S_OK, "got 0x%08x\n", hr);
8254 ok( lstrcmpW(str, _bstr_("http://winehq.org/default")) == 0, "expected default namespace\n");
8255 SysFreeString(str);
8256
8257 IXMLDOMElement_Release(elem);
8258 IXMLDOMNode_Release(node);
8259
8260 IXMLDOMDocument_Release(doc);
8261 free_bstrs();
8262 }
8263
8264 static const char get_prefix_doc[] =
8265 "<?xml version=\"1.0\" ?>"
8266 "<a xmlns:ns1=\"ns1 href\" />";
8267
8268 static void test_get_prefix(void)
8269 {
8270 IXMLDOMDocumentFragment *fragment;
8271 IXMLDOMCDATASection *cdata;
8272 IXMLDOMElement *element;
8273 IXMLDOMComment *comment;
8274 IXMLDOMDocument *doc;
8275 VARIANT_BOOL b;
8276 HRESULT hr;
8277 BSTR str;
8278
8279 doc = create_document(&IID_IXMLDOMDocument);
8280
8281 /* nodes that can't support prefix */
8282 /* 1. document */
8283 str = (void*)0xdeadbeef;
8284 hr = IXMLDOMDocument_get_prefix(doc, &str);
8285 EXPECT_HR(hr, S_FALSE);
8286 ok(str == NULL, "got %p\n", str);
8287
8288 hr = IXMLDOMDocument_get_prefix(doc, NULL);
8289 EXPECT_HR(hr, E_INVALIDARG);
8290
8291 /* 2. cdata */
8292 hr = IXMLDOMDocument_createCDATASection(doc, NULL, &cdata);
8293 ok(hr == S_OK, "got %08x\n", hr );
8294
8295 str = (void*)0xdeadbeef;
8296 hr = IXMLDOMCDATASection_get_prefix(cdata, &str);
8297 ok(hr == S_FALSE, "got %08x\n", hr);
8298 ok( str == 0, "got %p\n", str);
8299
8300 hr = IXMLDOMCDATASection_get_prefix(cdata, NULL);
8301 ok(hr == E_INVALIDARG, "got %08x\n", hr);
8302 IXMLDOMCDATASection_Release(cdata);
8303
8304 /* 3. comment */
8305 hr = IXMLDOMDocument_createComment(doc, NULL, &comment);
8306 ok(hr == S_OK, "got %08x\n", hr );
8307
8308 str = (void*)0xdeadbeef;
8309 hr = IXMLDOMComment_get_prefix(comment, &str);
8310 ok(hr == S_FALSE, "got %08x\n", hr);
8311 ok( str == 0, "got %p\n", str);
8312
8313 hr = IXMLDOMComment_get_prefix(comment, NULL);
8314 ok(hr == E_INVALIDARG, "got %08x\n", hr);
8315 IXMLDOMComment_Release(comment);
8316
8317 /* 4. fragment */
8318 hr = IXMLDOMDocument_createDocumentFragment(doc, &fragment);
8319 ok(hr == S_OK, "got %08x\n", hr );
8320
8321 str = (void*)0xdeadbeef;
8322 hr = IXMLDOMDocumentFragment_get_prefix(fragment, &str);
8323 ok(hr == S_FALSE, "got %08x\n", hr);
8324 ok( str == 0, "got %p\n", str);
8325
8326 hr = IXMLDOMDocumentFragment_get_prefix(fragment, NULL);
8327 ok(hr == E_INVALIDARG, "got %08x\n", hr);
8328 IXMLDOMDocumentFragment_Release(fragment);
8329
8330 /* no prefix */
8331 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &element);
8332 ok( hr == S_OK, "got 0x%08x\n", hr);
8333
8334 hr = IXMLDOMElement_get_prefix(element, NULL);
8335 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
8336
8337 str = (void*)0xdeadbeef;
8338 hr = IXMLDOMElement_get_prefix(element, &str);
8339 ok( hr == S_FALSE, "got 0x%08x\n", hr);
8340 ok( str == 0, "got %p\n", str);
8341
8342 IXMLDOMElement_Release(element);
8343
8344 /* with prefix */
8345 hr = IXMLDOMDocument_createElement(doc, _bstr_("a:elem"), &element);
8346 ok( hr == S_OK, "got 0x%08x\n", hr);
8347
8348 str = (void*)0xdeadbeef;
8349 hr = IXMLDOMElement_get_prefix(element, &str);
8350 ok( hr == S_OK, "got 0x%08x\n", hr);
8351 ok( lstrcmpW(str, _bstr_("a")) == 0, "expected prefix \"a\"\n");
8352 SysFreeString(str);
8353
8354 str = (void*)0xdeadbeef;
8355 hr = IXMLDOMElement_get_namespaceURI(element, &str);
8356 ok( hr == S_FALSE, "got 0x%08x\n", hr);
8357 ok( str == 0, "got %p\n", str);
8358
8359 IXMLDOMElement_Release(element);
8360
8361 hr = IXMLDOMDocument_loadXML(doc, _bstr_(get_prefix_doc), &b);
8362 EXPECT_HR(hr, S_OK);
8363
8364 hr = IXMLDOMDocument_get_documentElement(doc, &element);
8365 EXPECT_HR(hr, S_OK);
8366
8367 str = (void*)0xdeadbeef;
8368 hr = IXMLDOMElement_get_prefix(element, &str);
8369 EXPECT_HR(hr, S_FALSE);
8370 ok(str == NULL, "got %p\n", str);
8371
8372 str = (void*)0xdeadbeef;
8373 hr = IXMLDOMElement_get_namespaceURI(element, &str);
8374 EXPECT_HR(hr, S_FALSE);
8375 ok(str == NULL, "got %s\n", wine_dbgstr_w(str));
8376
8377 IXMLDOMDocument_Release(doc);
8378 free_bstrs();
8379 }
8380
8381 static void test_selectSingleNode(void)
8382 {
8383 IXMLDOMDocument *doc;
8384 IXMLDOMNodeList *list;
8385 IXMLDOMNode *node;
8386 VARIANT_BOOL b;
8387 HRESULT hr;
8388 LONG len;
8389
8390 doc = create_document(&IID_IXMLDOMDocument);
8391
8392 hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8393 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8394
8395 hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8396 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8397
8398 hr = IXMLDOMDocument_loadXML( doc, _bstr_(complete4A), &b );
8399 ok( hr == S_OK, "loadXML failed\n");
8400 ok( b == VARIANT_TRUE, "failed to load XML string\n");
8401
8402 hr = IXMLDOMDocument_selectSingleNode(doc, NULL, NULL);
8403 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8404
8405 hr = IXMLDOMDocument_selectNodes(doc, NULL, NULL);
8406 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8407
8408 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), NULL);
8409 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8410
8411 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), NULL);
8412 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8413
8414 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("lc"), &node);
8415 ok(hr == S_OK, "got 0x%08x\n", hr);
8416 IXMLDOMNode_Release(node);
8417
8418 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("lc"), &list);
8419 ok(hr == S_OK, "got 0x%08x\n", hr);
8420 IXMLDOMNodeList_Release(list);
8421
8422 list = (void*)0xdeadbeef;
8423 hr = IXMLDOMDocument_selectNodes(doc, NULL, &list);
8424 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8425 ok(list == (void*)0xdeadbeef, "got %p\n", list);
8426
8427 node = (void*)0xdeadbeef;
8428 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("nonexistent"), &node);
8429 ok(hr == S_FALSE, "got 0x%08x\n", hr);
8430 ok(node == 0, "got %p\n", node);
8431
8432 list = (void*)0xdeadbeef;
8433 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("nonexistent"), &list);
8434 ok(hr == S_OK, "got 0x%08x\n", hr);
8435 len = 1;
8436 hr = IXMLDOMNodeList_get_length(list, &len);
8437 ok(hr == S_OK, "got 0x%08x\n", hr);
8438 ok(len == 0, "got %d\n", len);
8439 IXMLDOMNodeList_Release(list);
8440
8441 IXMLDOMDocument_Release(doc);
8442 free_bstrs();
8443 }
8444
8445 static void test_events(void)
8446 {
8447 IConnectionPointContainer *conn;
8448 IConnectionPoint *point;
8449 IXMLDOMDocument *doc;
8450 HRESULT hr;
8451 VARIANT v;
8452 IDispatch *event;
8453
8454 doc = create_document(&IID_IXMLDOMDocument);
8455
8456 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IConnectionPointContainer, (void**)&conn);
8457 ok(hr == S_OK, "got 0x%08x\n", hr);
8458
8459 hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IDispatch, &point);
8460 ok(hr == S_OK, "got 0x%08x\n", hr);
8461 IConnectionPoint_Release(point);
8462 hr = IConnectionPointContainer_FindConnectionPoint(conn, &IID_IPropertyNotifySink, &point);
8463 ok(hr == S_OK, "got 0x%08x\n", hr);
8464 IConnectionPoint_Release(point);
8465 hr = IConnectionPointContainer_FindConnectionPoint(conn, &DIID_XMLDOMDocumentEvents, &point);
8466 ok(hr == S_OK, "got 0x%08x\n", hr);
8467 IConnectionPoint_Release(point);
8468
8469 IConnectionPointContainer_Release(conn);
8470
8471 /* ready state callback */
8472 VariantInit(&v);
8473 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8474 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8475
8476 event = create_dispevent();
8477 V_VT(&v) = VT_UNKNOWN;
8478 V_UNKNOWN(&v) = (IUnknown*)event;
8479
8480 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8481 ok(hr == S_OK, "got 0x%08x\n", hr);
8482 EXPECT_REF(event, 2);
8483
8484 V_VT(&v) = VT_DISPATCH;
8485 V_DISPATCH(&v) = event;
8486
8487 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8488 ok(hr == S_OK, "got 0x%08x\n", hr);
8489 EXPECT_REF(event, 2);
8490
8491 /* VT_NULL doesn't reset event handler */
8492 V_VT(&v) = VT_NULL;
8493 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8494 ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
8495 EXPECT_REF(event, 2);
8496
8497 V_VT(&v) = VT_DISPATCH;
8498 V_DISPATCH(&v) = NULL;
8499
8500 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8501 ok(hr == S_OK, "got 0x%08x\n", hr);
8502 EXPECT_REF(event, 1);
8503
8504 V_VT(&v) = VT_UNKNOWN;
8505 V_DISPATCH(&v) = NULL;
8506 hr = IXMLDOMDocument_put_onreadystatechange(doc, v);
8507 ok(hr == S_OK, "got 0x%08x\n", hr);
8508
8509 IDispatch_Release(event);
8510
8511 IXMLDOMDocument_Release(doc);
8512 }
8513
8514 static void test_createProcessingInstruction(void)
8515 {
8516 static const WCHAR bodyW[] = {'t','e','s','t',0};
8517 IXMLDOMProcessingInstruction *pi;
8518 IXMLDOMDocument *doc;
8519 WCHAR buff[10];
8520 HRESULT hr;
8521
8522 doc = create_document(&IID_IXMLDOMDocument);
8523
8524 /* test for BSTR handling, pass broken BSTR */
8525 memcpy(&buff[2], bodyW, sizeof(bodyW));
8526 /* just a big length */
8527 *(DWORD*)buff = 0xf0f0;
8528 hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("test"), &buff[2], &pi);
8529 ok(hr == S_OK, "got 0x%08x\n", hr);
8530
8531 IXMLDOMProcessingInstruction_Release(pi);
8532 IXMLDOMDocument_Release(doc);
8533 }
8534
8535 static void test_put_nodeTypedValue(void)
8536 {
8537 static const BYTE binhexdata[16] =
8538 {0,1,2,3,4,5,6,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf};
8539 IXMLDOMDocument *doc;
8540 IXMLDOMElement *elem;
8541 VARIANT type, value;
8542 LONG ubound, lbound;
8543 IXMLDOMNode *node;
8544 SAFEARRAY *array;
8545 HRESULT hr;
8546 BYTE *ptr;
8547 BSTR str;
8548
8549 doc = create_document(&IID_IXMLDOMDocument);
8550
8551 hr = IXMLDOMDocument_createElement(doc, _bstr_("Element"), &elem);
8552 EXPECT_HR(hr, S_OK);
8553
8554 V_VT(&type) = VT_EMPTY;
8555 hr = IXMLDOMElement_get_dataType(elem, &type);
8556 EXPECT_HR(hr, S_FALSE);
8557 ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8558
8559 /* set typed value for untyped node */
8560 V_VT(&type) = VT_I1;
8561 V_I1(&type) = 1;
8562 hr = IXMLDOMElement_put_nodeTypedValue(elem, type);
8563 EXPECT_HR(hr, S_OK);
8564
8565 V_VT(&type) = VT_EMPTY;
8566 hr = IXMLDOMElement_get_dataType(elem, &type);
8567 EXPECT_HR(hr, S_FALSE);
8568 ok(V_VT(&type) == VT_NULL, "got %d, expected VT_NULL\n", V_VT(&type));
8569
8570 /* no type info stored */
8571 V_VT(&type) = VT_EMPTY;
8572 hr = IXMLDOMElement_get_nodeTypedValue(elem, &type);
8573 EXPECT_HR(hr, S_OK);
8574 ok(V_VT(&type) == VT_BSTR, "got %d, expected VT_BSTR\n", V_VT(&type));
8575 ok(memcmp(V_BSTR(&type), _bstr_("1"), 2*sizeof(WCHAR)) == 0,
8576 "got %s, expected \"1\"\n", wine_dbgstr_w(V_BSTR(&type)));
8577 VariantClear(&type);
8578
8579 hr = IXMLDOMElement_get_firstChild(elem, &node);
8580 EXPECT_HR(hr, S_OK);
8581 hr = IXMLDOMElement_removeChild(elem, node, NULL);
8582 EXPECT_HR(hr, S_OK);
8583 IXMLDOMNode_Release(node);
8584
8585 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)elem, NULL);
8586 EXPECT_HR(hr, S_OK);
8587
8588 /* bin.base64 */
8589 hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.base64"));
8590 EXPECT_HR(hr, S_OK);
8591
8592 V_VT(&value) = VT_BSTR;
8593 V_BSTR(&value) = _bstr_("ABCD");
8594 hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8595 EXPECT_HR(hr, S_OK);
8596
8597 V_VT(&value) = VT_EMPTY;
8598 hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8599 EXPECT_HR(hr, S_OK);
8600 ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8601 ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8602 ubound = 0;
8603 hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8604 EXPECT_HR(hr, S_OK);
8605 ok(ubound == 2, "got %d\n", ubound);
8606 lbound = 0;
8607 hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8608 EXPECT_HR(hr, S_OK);
8609 ok(lbound == 0, "got %d\n", lbound);
8610 hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8611 EXPECT_HR(hr, S_OK);
8612 ok(ptr[0] == 0, "got %x\n", ptr[0]);
8613 ok(ptr[1] == 0x10, "got %x\n", ptr[1]);
8614 ok(ptr[2] == 0x83, "got %x\n", ptr[2]);
8615 SafeArrayUnaccessData(V_ARRAY(&value));
8616 VariantClear(&value);
8617
8618 /* when set as VT_BSTR it's stored as is */
8619 hr = IXMLDOMElement_get_firstChild(elem, &node);
8620 EXPECT_HR(hr, S_OK);
8621 hr = IXMLDOMNode_get_text(node, &str);
8622 EXPECT_HR(hr, S_OK);
8623 ok(!lstrcmpW(str, _bstr_("ABCD")), "%s\n", wine_dbgstr_w(str));
8624 IXMLDOMNode_Release(node);
8625 SysFreeString(str);
8626
8627 array = SafeArrayCreateVector(VT_UI1, 0, 7);
8628 hr = SafeArrayAccessData(array, (void*)&ptr);
8629 EXPECT_HR(hr, S_OK);
8630 memcpy(ptr, "dGVzdA=", strlen("dGVzdA="));
8631 SafeArrayUnaccessData(array);
8632
8633 V_VT(&value) = VT_UI1|VT_ARRAY;
8634 V_ARRAY(&value) = array;
8635 hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8636 EXPECT_HR(hr, S_OK);
8637
8638 V_VT(&value) = VT_EMPTY;
8639 hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8640 EXPECT_HR(hr, S_OK);
8641 ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8642 ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8643 ubound = 0;
8644 hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8645 EXPECT_HR(hr, S_OK);
8646 ok(ubound == 6, "got %d\n", ubound);
8647 lbound = 0;
8648 hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8649 EXPECT_HR(hr, S_OK);
8650 ok(lbound == 0, "got %d\n", lbound);
8651 hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8652 EXPECT_HR(hr, S_OK);
8653 ok(!memcmp(ptr, "dGVzdA=", strlen("dGVzdA=")), "got wrong data, %s\n", ptr);
8654 SafeArrayUnaccessData(V_ARRAY(&value));
8655 VariantClear(&value);
8656
8657 /* if set with VT_UI1|VT_ARRAY it's encoded */
8658 hr = IXMLDOMElement_get_firstChild(elem, &node);
8659 EXPECT_HR(hr, S_OK);
8660 hr = IXMLDOMNode_get_text(node, &str);
8661 EXPECT_HR(hr, S_OK);
8662 ok(!lstrcmpW(str, _bstr_("ZEdWemRBPQ==")), "%s\n", wine_dbgstr_w(str));
8663 IXMLDOMNode_Release(node);
8664 SafeArrayDestroyData(array);
8665 SysFreeString(str);
8666
8667 /* bin.hex */
8668 V_VT(&value) = VT_BSTR;
8669 V_BSTR(&value) = _bstr_("");
8670 hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8671 EXPECT_HR(hr, S_OK);
8672
8673 hr = IXMLDOMElement_put_dataType(elem, _bstr_("bin.hex"));
8674 EXPECT_HR(hr, S_OK);
8675
8676 array = SafeArrayCreateVector(VT_UI1, 0, 16);
8677 hr = SafeArrayAccessData(array, (void*)&ptr);
8678 EXPECT_HR(hr, S_OK);
8679 memcpy(ptr, binhexdata, sizeof(binhexdata));
8680 SafeArrayUnaccessData(array);
8681
8682 V_VT(&value) = VT_UI1|VT_ARRAY;
8683 V_ARRAY(&value) = array;
8684 hr = IXMLDOMElement_put_nodeTypedValue(elem, value);
8685 EXPECT_HR(hr, S_OK);
8686
8687 V_VT(&value) = VT_EMPTY;
8688 hr = IXMLDOMElement_get_nodeTypedValue(elem, &value);
8689 EXPECT_HR(hr, S_OK);
8690 ok(V_VT(&value) == (VT_UI1|VT_ARRAY), "got %d\n", V_VT(&value));
8691 ok(SafeArrayGetDim(V_ARRAY(&value)) == 1, "got wrong dimension\n");
8692 ubound = 0;
8693 hr = SafeArrayGetUBound(V_ARRAY(&value), 1, &ubound);
8694 EXPECT_HR(hr, S_OK);
8695 ok(ubound == 15, "got %d\n", ubound);
8696 lbound = 0;
8697 hr = SafeArrayGetLBound(V_ARRAY(&value), 1, &lbound);
8698 EXPECT_HR(hr, S_OK);
8699 ok(lbound == 0, "got %d\n", lbound);
8700 hr = SafeArrayAccessData(V_ARRAY(&value), (void*)&ptr);
8701 EXPECT_HR(hr, S_OK);
8702 ok(!memcmp(ptr, binhexdata, sizeof(binhexdata)), "got wrong data\n");
8703 SafeArrayUnaccessData(V_ARRAY(&value));
8704 VariantClear(&value);
8705
8706 /* if set with VT_UI1|VT_ARRAY it's encoded */
8707 hr = IXMLDOMElement_get_firstChild(elem, &node);
8708 EXPECT_HR(hr, S_OK);
8709 hr = IXMLDOMNode_get_text(node, &str);
8710 EXPECT_HR(hr, S_OK);
8711 ok(!lstrcmpW(str, _bstr_("000102030405060708090a0b0c0d0e0f")), "%s\n", wine_dbgstr_w(str));
8712 IXMLDOMNode_Release(node);
8713 SafeArrayDestroyData(array);
8714 SysFreeString(str);
8715
8716 IXMLDOMElement_Release(elem);
8717 IXMLDOMDocument_Release(doc);
8718 free_bstrs();
8719 }
8720
8721 static void test_get_xml(void)
8722 {
8723 static const char xmlA[] = "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<a>test</a>\r\n";
8724 static const char attrA[] = "attr=\"&quot;a &amp; b&quot;\"";
8725 static const char attr2A[] = "\"a & b\"";
8726 static const char attr3A[] = "attr=\"&amp;quot;a\"";
8727 static const char attr4A[] = "&quot;a";
8728 static const char fooA[] = "<foo/>";
8729 IXMLDOMProcessingInstruction *pi;
8730 IXMLDOMNode *first;
8731 IXMLDOMElement *elem = NULL;
8732 IXMLDOMAttribute *attr;
8733 IXMLDOMDocument *doc;
8734 VARIANT_BOOL b;
8735 VARIANT v;
8736 BSTR xml;
8737 HRESULT hr;
8738
8739 doc = create_document(&IID_IXMLDOMDocument);
8740
8741 b = VARIANT_TRUE;
8742 hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8743 ok(hr == S_OK, "got 0x%08x\n", hr);
8744 ok( b == VARIANT_TRUE, "got %d\n", b);
8745
8746 hr = IXMLDOMDocument_createProcessingInstruction(doc, _bstr_("xml"),
8747 _bstr_("version=\"1.0\" encoding=\"UTF-16\""), &pi);
8748 ok(hr == S_OK, "got 0x%08x\n", hr);
8749
8750 hr = IXMLDOMDocument_get_firstChild(doc, &first);
8751 ok(hr == S_OK, "got 0x%08x\n", hr);
8752
8753 V_UNKNOWN(&v) = (IUnknown*)first;
8754 V_VT(&v) = VT_UNKNOWN;
8755
8756 hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)pi, v, NULL);
8757 ok(hr == S_OK, "got 0x%08x\n", hr);
8758
8759 IXMLDOMProcessingInstruction_Release(pi);
8760 IXMLDOMNode_Release(first);
8761
8762 hr = IXMLDOMDocument_get_xml(doc, &xml);
8763 ok(hr == S_OK, "got 0x%08x\n", hr);
8764
8765 ok(memcmp(xml, _bstr_(xmlA), sizeof(xmlA)*sizeof(WCHAR)) == 0,
8766 "got %s, expected %s\n", wine_dbgstr_w(xml), xmlA);
8767 SysFreeString(xml);
8768
8769 IXMLDOMDocument_Release(doc);
8770
8771 doc = create_document(&IID_IXMLDOMDocument);
8772
8773 hr = IXMLDOMDocument_createElement(doc, _bstr_("foo"), &elem);
8774 ok(hr == S_OK, "got 0x%08x\n", hr);
8775
8776 hr = IXMLDOMDocument_putref_documentElement(doc, elem);
8777 ok(hr == S_OK, "got 0x%08x\n", hr);
8778
8779 hr = IXMLDOMDocument_get_xml(doc, &xml);
8780 ok(hr == S_OK, "got 0x%08x\n", hr);
8781
8782 ok(memcmp(xml, _bstr_(fooA), (sizeof(fooA)-1)*sizeof(WCHAR)) == 0,
8783 "got %s, expected %s\n", wine_dbgstr_w(xml), fooA);
8784 SysFreeString(xml);
8785
8786 IXMLDOMElement_Release(elem);
8787
8788 /* attribute node */
8789 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("attr"), &attr);
8790 ok(hr == S_OK, "got 0x%08x\n", hr);
8791
8792 V_VT(&v) = VT_BSTR;
8793 V_BSTR(&v) = _bstr_("\"a & b\"");
8794 hr = IXMLDOMAttribute_put_value(attr, v);
8795 ok(hr == S_OK, "got 0x%08x\n", hr);
8796
8797 xml = NULL;
8798 hr = IXMLDOMAttribute_get_xml(attr, &xml);
8799 ok(hr == S_OK, "got 0x%08x\n", hr);
8800 ok(!memcmp(xml, _bstr_(attrA), (sizeof(attrA)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8801 SysFreeString(xml);
8802
8803 VariantInit(&v);
8804 hr = IXMLDOMAttribute_get_value(attr, &v);
8805 ok(hr == S_OK, "got 0x%08x\n", hr);
8806 ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8807 ok(!memcmp(V_BSTR(&v), _bstr_(attr2A), (sizeof(attr2A)-1)*sizeof(WCHAR)),
8808 "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8809 VariantClear(&v);
8810
8811 V_VT(&v) = VT_BSTR;
8812 V_BSTR(&v) = _bstr_("&quot;a");
8813 hr = IXMLDOMAttribute_put_value(attr, v);
8814 ok(hr == S_OK, "got 0x%08x\n", hr);
8815
8816 xml = NULL;
8817 hr = IXMLDOMAttribute_get_xml(attr, &xml);
8818 ok(hr == S_OK, "got 0x%08x\n", hr);
8819 ok(!memcmp(xml, _bstr_(attr3A), (sizeof(attr3A)-1)*sizeof(WCHAR)), "got %s\n", wine_dbgstr_w(xml));
8820 SysFreeString(xml);
8821
8822 VariantInit(&v);
8823 hr = IXMLDOMAttribute_get_value(attr, &v);
8824 ok(hr == S_OK, "got 0x%08x\n", hr);
8825 ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8826 ok(!memcmp(V_BSTR(&v), _bstr_(attr4A), (sizeof(attr4A)-1)*sizeof(WCHAR)),
8827 "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8828 VariantClear(&v);
8829
8830 IXMLDOMAttribute_Release(attr);
8831
8832 IXMLDOMDocument_Release(doc);
8833
8834 free_bstrs();
8835 }
8836
8837 static void test_xsltemplate(void)
8838 {
8839 IXMLDOMDocument *doc, *doc2, *doc3;
8840 IXSLTemplate *template;
8841 IXSLProcessor *processor;
8842 IStream *stream;
8843 VARIANT_BOOL b;
8844 HRESULT hr;
8845 ULONG ref1, ref2;
8846 VARIANT v;
8847 BSTR str;
8848
8849 if (!is_clsid_supported(&CLSID_XSLTemplate, &IID_IXSLTemplate)) return;
8850 template = create_xsltemplate(&IID_IXSLTemplate);
8851
8852 /* works as reset */
8853 hr = IXSLTemplate_putref_stylesheet(template, NULL);
8854 ok(hr == S_OK, "got 0x%08x\n", hr);
8855
8856 doc = create_document(&IID_IXMLDOMDocument);
8857
8858 b = VARIANT_TRUE;
8859 hr = IXMLDOMDocument_loadXML( doc, _bstr_("<a>test</a>"), &b );
8860 ok(hr == S_OK, "got 0x%08x\n", hr);
8861 ok( b == VARIANT_TRUE, "got %d\n", b);
8862
8863 /* putref with non-xsl document */
8864 hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8865 todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8866
8867 b = VARIANT_TRUE;
8868 hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8869 ok(hr == S_OK, "got 0x%08x\n", hr);
8870 ok( b == VARIANT_TRUE, "got %d\n", b);
8871
8872 /* not a freethreaded document */
8873 hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8874 todo_wine ok(hr == E_FAIL, "got 0x%08x\n", hr);
8875
8876 IXMLDOMDocument_Release(doc);
8877
8878 if (!is_clsid_supported(&CLSID_FreeThreadedDOMDocument, &IID_IXMLDOMDocument))
8879 {
8880 IXSLTemplate_Release(template);
8881 return;
8882 }
8883
8884 hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
8885 ok(hr == S_OK, "got 0x%08x\n", hr);
8886
8887 b = VARIANT_TRUE;
8888 hr = IXMLDOMDocument_loadXML( doc, _bstr_(szTransformSSXML), &b );
8889 ok(hr == S_OK, "got 0x%08x\n", hr);
8890 ok( b == VARIANT_TRUE, "got %d\n", b);
8891
8892 /* freethreaded document */
8893 ref1 = IXMLDOMDocument_AddRef(doc);
8894 IXMLDOMDocument_Release(doc);
8895 hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
8896 ok(hr == S_OK, "got 0x%08x\n", hr);
8897 ref2 = IXMLDOMDocument_AddRef(doc);
8898 IXMLDOMDocument_Release(doc);
8899 ok(ref2 > ref1, "got %d\n", ref2);
8900
8901 /* processor */
8902 hr = IXSLTemplate_createProcessor(template, NULL);
8903 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8904
8905 EXPECT_REF(template, 1);
8906 hr = IXSLTemplate_createProcessor(template, &processor);
8907 ok(hr == S_OK, "got 0x%08x\n", hr);
8908 EXPECT_REF(template, 2);
8909
8910 /* input no set yet */
8911 V_VT(&v) = VT_BSTR;
8912 V_BSTR(&v) = NULL;
8913 hr = IXSLProcessor_get_input(processor, &v);
8914 todo_wine {
8915 ok(hr == S_OK, "got 0x%08x\n", hr);
8916 ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
8917 }
8918
8919 hr = IXSLProcessor_get_output(processor, NULL);
8920 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8921
8922 /* reset before it was set */
8923 V_VT(&v) = VT_EMPTY;
8924 hr = IXSLProcessor_put_output(processor, v);
8925 ok(hr == S_OK, "got 0x%08x\n", hr);
8926
8927 V_VT(&v) = VT_UNKNOWN;
8928 V_UNKNOWN(&v) = NULL;
8929 hr = IXSLProcessor_put_output(processor, v);
8930 ok(hr == S_OK, "got 0x%08x\n", hr);
8931
8932 V_VT(&v) = VT_UNKNOWN;
8933 V_DISPATCH(&v) = NULL;
8934 hr = IXSLProcessor_put_output(processor, v);
8935 ok(hr == S_OK, "got 0x%08x\n", hr);
8936
8937 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
8938 ok(hr == S_OK, "got 0x%08x\n", hr);
8939 EXPECT_REF(stream, 1);
8940
8941 V_VT(&v) = VT_UNKNOWN;
8942 V_UNKNOWN(&v) = (IUnknown*)stream;
8943 hr = IXSLProcessor_put_output(processor, v);
8944 ok(hr == S_OK, "got 0x%08x\n", hr);
8945
8946 /* it seems processor grabs 2 references */
8947 todo_wine EXPECT_REF(stream, 3);
8948
8949 V_VT(&v) = VT_EMPTY;
8950 hr = IXSLProcessor_get_output(processor, &v);
8951 ok(hr == S_OK, "got 0x%08x\n", hr);
8952 ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
8953 ok(V_UNKNOWN(&v) == (IUnknown*)stream, "got %p\n", V_UNKNOWN(&v));
8954
8955 todo_wine EXPECT_REF(stream, 4);
8956 VariantClear(&v);
8957
8958 hr = IXSLProcessor_transform(processor, NULL);
8959 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
8960
8961 /* reset and check stream refcount */
8962 V_VT(&v) = VT_EMPTY;
8963 hr = IXSLProcessor_put_output(processor, v);
8964 ok(hr == S_OK, "got 0x%08x\n", hr);
8965
8966 EXPECT_REF(stream, 1);
8967
8968 IStream_Release(stream);
8969
8970 /* no output interface set, check output */
8971 doc2 = create_document(&IID_IXMLDOMDocument);
8972
8973 b = VARIANT_FALSE;
8974 hr = IXMLDOMDocument_loadXML( doc2, _bstr_("<a>test</a>"), &b );
8975 ok(hr == S_OK, "got 0x%08x\n", hr);
8976 ok( b == VARIANT_TRUE, "got %d\n", b);
8977
8978 V_VT(&v) = VT_UNKNOWN;
8979 V_UNKNOWN(&v) = (IUnknown*)doc2;
8980 hr = IXSLProcessor_put_input(processor, v);
8981 ok(hr == S_OK, "got 0x%08x\n", hr);
8982
8983 hr = IXSLProcessor_transform(processor, &b);
8984 ok(hr == S_OK, "got 0x%08x\n", hr);
8985
8986 V_VT(&v) = VT_EMPTY;
8987 hr = IXSLProcessor_get_output(processor, &v);
8988 ok(hr == S_OK, "got 0x%08x\n", hr);
8989 ok(V_VT(&v) == VT_BSTR, "got type %d\n", V_VT(&v));
8990 ok(*V_BSTR(&v) == 0, "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
8991 VariantClear(&v);
8992
8993 /* transform to document */
8994 b = VARIANT_FALSE;
8995 hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformXML), &b);
8996 ok(hr == S_OK, "got 0x%08x\n", hr);
8997 ok(b == VARIANT_TRUE, "got %d\n", b);
8998
8999 V_VT(&v) = VT_UNKNOWN;
9000 V_UNKNOWN(&v) = (IUnknown*)doc2;
9001 hr = IXSLProcessor_put_input(processor, v);
9002 ok(hr == S_OK, "got 0x%08x\n", hr);
9003
9004 doc3 = create_document(&IID_IXMLDOMDocument);
9005 V_VT(&v) = VT_UNKNOWN;
9006 V_UNKNOWN(&v) = (IUnknown *)doc3;
9007 hr = IXSLProcessor_put_output(processor, v);
9008 ok(hr == S_OK, "got 0x%08x\n", hr);
9009
9010 hr = IXMLDOMDocument_get_xml(doc3, &str);
9011 ok(hr == S_OK, "got 0x%08x\n", hr);
9012 ok(!*str, "Expected empty document\n");
9013 SysFreeString(str);
9014
9015 hr = IXSLProcessor_transform(processor, &b);
9016 ok(hr == S_OK, "got 0x%08x\n", hr);
9017
9018 V_VT(&v) = VT_EMPTY;
9019 hr = IXSLProcessor_get_output(processor, &v);
9020 ok(hr == S_OK, "got 0x%08x\n", hr);
9021 ok(V_VT(&v) == VT_UNKNOWN, "got type %d\n", V_VT(&v));
9022 VariantClear(&v);
9023
9024 hr = IXMLDOMDocument_get_xml(doc3, &str);
9025 ok(hr == S_OK, "got 0x%08x\n", hr);
9026 ok(!!*str, "Expected document\n");
9027 SysFreeString(str);
9028
9029 /* transform to IResponse */
9030 V_VT(&v) = VT_EMPTY;
9031 hr = IXSLProcessor_put_output(processor, v);
9032 ok(hr == S_OK, "got 0x%08x\n", hr);
9033
9034 V_VT(&v) = VT_UNKNOWN;
9035 V_UNKNOWN(&v) = (IUnknown *)&testresponse;
9036 hr = IXSLProcessor_put_output(processor, v);
9037 ok(hr == S_OK, "got 0x%08x\n", hr);
9038
9039 b = VARIANT_FALSE;
9040 hr = IXSLProcessor_transform(processor, &b);
9041 ok(hr == S_OK, "got 0x%08x\n", hr);
9042 ok(b == VARIANT_TRUE, "got %x\n", b);
9043
9044 IXSLProcessor_Release(processor);
9045 IXMLDOMDocument_Release(doc2);
9046 IXMLDOMDocument_Release(doc3);
9047
9048 /* drop reference */
9049 hr = IXSLTemplate_putref_stylesheet(template, NULL);
9050 ok(hr == S_OK, "got 0x%08x\n", hr);
9051 ref2 = IXMLDOMDocument_AddRef(doc);
9052 IXMLDOMDocument_Release(doc);
9053 ok(ref2 == ref1, "got %d\n", ref2);
9054
9055 IXMLDOMDocument_Release(doc);
9056 IXSLTemplate_Release(template);
9057 free_bstrs();
9058 }
9059
9060 static void test_insertBefore(void)
9061 {
9062 IXMLDOMDocument *doc, *doc2, *doc3;
9063 IXMLDOMAttribute *attr;
9064 IXMLDOMElement *elem1, *elem2, *elem3, *elem4, *elem5;
9065 IXMLDOMNode *node, *newnode, *cdata;
9066 HRESULT hr;
9067 VARIANT v;
9068 BSTR p;
9069
9070 doc = create_document(&IID_IXMLDOMDocument);
9071 doc3 = create_document(&IID_IXMLDOMDocument);
9072
9073 /* document to document */
9074 V_VT(&v) = VT_NULL;
9075 node = (void*)0xdeadbeef;
9076 hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc3, v, &node);
9077 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9078 ok(node == NULL, "got %p\n", node);
9079
9080 /* document to itself */
9081 V_VT(&v) = VT_NULL;
9082 node = (void*)0xdeadbeef;
9083 hr = IXMLDOMDocument_insertBefore(doc, (IXMLDOMNode*)doc, v, &node);
9084 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9085 ok(node == NULL, "got %p\n", node);
9086
9087 /* insertBefore behaviour for attribute node */
9088 V_VT(&v) = VT_I4;
9089 V_I4(&v) = NODE_ATTRIBUTE;
9090
9091 attr = NULL;
9092 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr"), NULL, (IXMLDOMNode**)&attr);
9093 ok(hr == S_OK, "got 0x%08x\n", hr);
9094 ok(attr != NULL, "got %p\n", attr);
9095
9096 /* attribute to document */
9097 V_VT(&v) = VT_NULL;
9098 node = (void*)0xdeadbeef;
9099 hr = IXMLDOMDocument_insertBefore(doc3, (IXMLDOMNode*)attr, v, &node);
9100 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9101 ok(node == NULL, "got %p\n", node);
9102
9103 /* cdata to document */
9104 V_VT(&v) = VT_I4;
9105 V_I4(&v) = NODE_CDATA_SECTION;
9106
9107 cdata = NULL;
9108 hr = IXMLDOMDocument_createNode(doc3, v, _bstr_("cdata"), NULL, &cdata);
9109 ok(hr == S_OK, "got 0x%08x\n", hr);
9110 ok(cdata != NULL, "got %p\n", cdata);
9111
9112 EXPECT_NO_CHILDREN(cdata);
9113
9114 /* attribute to cdata */
9115 V_VT(&v) = VT_NULL;
9116 node = (void*)0xdeadbeef;
9117 hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)attr, v, &node);
9118 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9119 ok(node == NULL, "got %p\n", node);
9120
9121 /* document to cdata */
9122 V_VT(&v) = VT_NULL;
9123 node = (void*)0xdeadbeef;
9124 hr = IXMLDOMNode_insertBefore(cdata, (IXMLDOMNode*)doc, v, &node);
9125 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9126 ok(node == NULL, "got %p\n", node);
9127
9128 V_VT(&v) = VT_NULL;
9129 node = (void*)0xdeadbeef;
9130 hr = IXMLDOMDocument_insertBefore(doc3, cdata, v, &node);
9131 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9132 ok(node == NULL, "got %p\n", node);
9133
9134 IXMLDOMNode_Release(cdata);
9135 IXMLDOMDocument_Release(doc3);
9136
9137 /* attribute to attribute */
9138 V_VT(&v) = VT_I4;
9139 V_I4(&v) = NODE_ATTRIBUTE;
9140 newnode = NULL;
9141 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("attr2"), NULL, &newnode);
9142 ok(hr == S_OK, "got 0x%08x\n", hr);
9143 ok(newnode != NULL, "got %p\n", newnode);
9144
9145 V_VT(&v) = VT_NULL;
9146 node = (void*)0xdeadbeef;
9147 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9148 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9149 ok(node == NULL, "got %p\n", node);
9150
9151 V_VT(&v) = VT_UNKNOWN;
9152 V_UNKNOWN(&v) = (IUnknown*)attr;
9153 node = (void*)0xdeadbeef;
9154 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9155 todo_wine ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9156 ok(node == NULL, "got %p\n", node);
9157 IXMLDOMNode_Release(newnode);
9158
9159 /* cdata to attribute */
9160 V_VT(&v) = VT_I4;
9161 V_I4(&v) = NODE_CDATA_SECTION;
9162 newnode = NULL;
9163 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9164 ok(hr == S_OK, "got 0x%08x\n", hr);
9165 ok(newnode != NULL, "got %p\n", newnode);
9166
9167 V_VT(&v) = VT_NULL;
9168 node = (void*)0xdeadbeef;
9169 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9170 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9171 ok(node == NULL, "got %p\n", node);
9172 IXMLDOMNode_Release(newnode);
9173
9174 /* comment to attribute */
9175 V_VT(&v) = VT_I4;
9176 V_I4(&v) = NODE_COMMENT;
9177 newnode = NULL;
9178 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9179 ok(hr == S_OK, "got 0x%08x\n", hr);
9180 ok(newnode != NULL, "got %p\n", newnode);
9181
9182 V_VT(&v) = VT_NULL;
9183 node = (void*)0xdeadbeef;
9184 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9185 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9186 ok(node == NULL, "got %p\n", node);
9187 IXMLDOMNode_Release(newnode);
9188
9189 /* element to attribute */
9190 V_VT(&v) = VT_I4;
9191 V_I4(&v) = NODE_ELEMENT;
9192 newnode = NULL;
9193 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9194 ok(hr == S_OK, "got 0x%08x\n", hr);
9195 ok(newnode != NULL, "got %p\n", newnode);
9196
9197 V_VT(&v) = VT_NULL;
9198 node = (void*)0xdeadbeef;
9199 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9200 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9201 ok(node == NULL, "got %p\n", node);
9202 IXMLDOMNode_Release(newnode);
9203
9204 /* pi to attribute */
9205 V_VT(&v) = VT_I4;
9206 V_I4(&v) = NODE_PROCESSING_INSTRUCTION;
9207 newnode = NULL;
9208 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("cdata"), NULL, &newnode);
9209 ok(hr == S_OK, "got 0x%08x\n", hr);
9210 ok(newnode != NULL, "got %p\n", newnode);
9211
9212 V_VT(&v) = VT_NULL;
9213 node = (void*)0xdeadbeef;
9214 hr = IXMLDOMAttribute_insertBefore(attr, newnode, v, &node);
9215 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9216 ok(node == NULL, "got %p\n", node);
9217 IXMLDOMNode_Release(newnode);
9218 IXMLDOMAttribute_Release(attr);
9219
9220 /* insertBefore for elements */
9221 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem1);
9222 ok(hr == S_OK, "got 0x%08x\n", hr);
9223
9224 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem2"), &elem2);
9225 ok(hr == S_OK, "got 0x%08x\n", hr);
9226
9227 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9228 ok(hr == S_OK, "got 0x%08x\n", hr);
9229
9230 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem3"), &elem3);
9231 ok(hr == S_OK, "got 0x%08x\n", hr);
9232
9233 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem4"), &elem4);
9234 ok(hr == S_OK, "got 0x%08x\n", hr);
9235
9236 EXPECT_NO_CHILDREN(elem1);
9237 EXPECT_NO_CHILDREN(elem2);
9238 EXPECT_NO_CHILDREN(elem3);
9239
9240 todo_wine EXPECT_REF(elem2, 2);
9241
9242 /* document to element */
9243 V_VT(&v) = VT_DISPATCH;
9244 V_DISPATCH(&v) = NULL;
9245 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)doc, v, NULL);
9246 ok(hr == E_FAIL, "got 0x%08x\n", hr);
9247
9248 V_VT(&v) = VT_DISPATCH;
9249 V_DISPATCH(&v) = NULL;
9250 node = NULL;
9251 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem4, v, &node);
9252 ok(hr == S_OK, "got 0x%08x\n", hr);
9253 ok(node == (void*)elem4, "got %p\n", node);
9254
9255 EXPECT_CHILDREN(elem1);
9256 hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem4, NULL);
9257 EXPECT_HR(hr, S_OK);
9258 IXMLDOMElement_Release(elem4);
9259
9260 EXPECT_NO_CHILDREN(elem1);
9261
9262 V_VT(&v) = VT_NULL;
9263 node = NULL;
9264 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9265 ok(hr == S_OK, "got 0x%08x\n", hr);
9266 ok(node == (void*)elem2, "got %p\n", node);
9267
9268 EXPECT_CHILDREN(elem1);
9269 todo_wine EXPECT_REF(elem2, 3);
9270 IXMLDOMNode_Release(node);
9271
9272 /* again for already linked node */
9273 V_VT(&v) = VT_NULL;
9274 node = NULL;
9275 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, &node);
9276 ok(hr == S_OK, "got 0x%08x\n", hr);
9277 ok(node == (void*)elem2, "got %p\n", node);
9278
9279 EXPECT_CHILDREN(elem1);
9280
9281 /* increments each time */
9282 todo_wine EXPECT_REF(elem2, 3);
9283 IXMLDOMNode_Release(node);
9284
9285 /* try to add to another element */
9286 V_VT(&v) = VT_NULL;
9287 node = (void*)0xdeadbeef;
9288 hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem2, v, &node);
9289 ok(hr == S_OK, "got 0x%08x\n", hr);
9290 ok(node == (void*)elem2, "got %p\n", node);
9291
9292 EXPECT_CHILDREN(elem3);
9293 EXPECT_NO_CHILDREN(elem1);
9294
9295 IXMLDOMNode_Release(node);
9296
9297 /* cross document case - try to add as child to a node created with other doc */
9298 doc2 = create_document(&IID_IXMLDOMDocument);
9299
9300 hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem4);
9301 ok(hr == S_OK, "got 0x%08x\n", hr);
9302 todo_wine EXPECT_REF(elem4, 2);
9303
9304 /* same name, another instance */
9305 hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem4"), &elem5);
9306 ok(hr == S_OK, "got 0x%08x\n", hr);
9307 todo_wine EXPECT_REF(elem5, 2);
9308
9309 todo_wine EXPECT_REF(elem3, 2);
9310 V_VT(&v) = VT_NULL;
9311 node = NULL;
9312 hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem4, v, &node);
9313 ok(hr == S_OK, "got 0x%08x\n", hr);
9314 ok(node == (void*)elem4, "got %p\n", node);
9315 todo_wine EXPECT_REF(elem4, 3);
9316 todo_wine EXPECT_REF(elem3, 2);
9317 IXMLDOMNode_Release(node);
9318
9319 V_VT(&v) = VT_NULL;
9320 node = NULL;
9321 hr = IXMLDOMElement_insertBefore(elem3, (IXMLDOMNode*)elem5, v, &node);
9322 ok(hr == S_OK, "got 0x%08x\n", hr);
9323 ok(node == (void*)elem5, "got %p\n", node);
9324 todo_wine EXPECT_REF(elem4, 2);
9325 todo_wine EXPECT_REF(elem5, 3);
9326 IXMLDOMNode_Release(node);
9327
9328 IXMLDOMDocument_Release(doc2);
9329
9330 IXMLDOMElement_Release(elem1);
9331 IXMLDOMElement_Release(elem2);
9332 IXMLDOMElement_Release(elem3);
9333 IXMLDOMElement_Release(elem4);
9334 IXMLDOMElement_Release(elem5);
9335
9336 /* elements with same default namespace */
9337 V_VT(&v) = VT_I4;
9338 V_I4(&v) = NODE_ELEMENT;
9339 elem1 = NULL;
9340 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9341 ok(hr == S_OK, "got 0x%08x\n", hr);
9342 ok(elem1 != NULL, "got %p\n", elem1);
9343
9344 V_VT(&v) = VT_I4;
9345 V_I4(&v) = NODE_ELEMENT;
9346 elem2 = NULL;
9347 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem2);
9348 ok(hr == S_OK, "got 0x%08x\n", hr);
9349 ok(elem2 != NULL, "got %p\n", elem2);
9350
9351 /* check contents so far */
9352 p = NULL;
9353 hr = IXMLDOMElement_get_xml(elem1, &p);
9354 ok(hr == S_OK, "got 0x%08x\n", hr);
9355 ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9356 SysFreeString(p);
9357
9358 p = NULL;
9359 hr = IXMLDOMElement_get_xml(elem2, &p);
9360 ok(hr == S_OK, "got 0x%08x\n", hr);
9361 ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9362 SysFreeString(p);
9363
9364 V_VT(&v) = VT_NULL;
9365 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9366 ok(hr == S_OK, "got 0x%08x\n", hr);
9367
9368 /* get_xml depends on context, for top node it omits child namespace attribute,
9369 but at child level it's still returned */
9370 p = NULL;
9371 hr = IXMLDOMElement_get_xml(elem1, &p);
9372 ok(hr == S_OK, "got 0x%08x\n", hr);
9373 todo_wine ok(!lstrcmpW(p, _bstr_("<elem1 xmlns=\"http://winehq.org/default\"><elem2/></elem1>")),
9374 "got %s\n", wine_dbgstr_w(p));
9375 SysFreeString(p);
9376
9377 p = NULL;
9378 hr = IXMLDOMElement_get_xml(elem2, &p);
9379 ok(hr == S_OK, "got 0x%08x\n", hr);
9380 ok(!lstrcmpW(p, _bstr_("<elem2 xmlns=\"http://winehq.org/default\"/>")), "got %s\n", wine_dbgstr_w(p));
9381 SysFreeString(p);
9382
9383 IXMLDOMElement_Release(elem1);
9384 IXMLDOMElement_Release(elem2);
9385
9386 /* child without default namespace added to node with default namespace */
9387 V_VT(&v) = VT_I4;
9388 V_I4(&v) = NODE_ELEMENT;
9389 elem1 = NULL;
9390 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem1"), _bstr_("http://winehq.org/default"), (IXMLDOMNode**)&elem1);
9391 ok(hr == S_OK, "got 0x%08x\n", hr);
9392 ok(elem1 != NULL, "got %p\n", elem1);
9393
9394 V_VT(&v) = VT_I4;
9395 V_I4(&v) = NODE_ELEMENT;
9396 elem2 = NULL;
9397 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("elem2"), NULL, (IXMLDOMNode**)&elem2);
9398 ok(hr == S_OK, "got 0x%08x\n", hr);
9399 ok(elem2 != NULL, "got %p\n", elem2);
9400
9401 EXPECT_REF(elem2, 1);
9402 V_VT(&v) = VT_NULL;
9403 hr = IXMLDOMElement_insertBefore(elem1, (IXMLDOMNode*)elem2, v, NULL);
9404 ok(hr == S_OK, "got 0x%08x\n", hr);
9405 EXPECT_REF(elem2, 1);
9406
9407 p = NULL;
9408 hr = IXMLDOMElement_get_xml(elem2, &p);
9409 ok(hr == S_OK, "got 0x%08x\n", hr);
9410 ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9411 SysFreeString(p);
9412
9413 hr = IXMLDOMElement_removeChild(elem1, (IXMLDOMNode*)elem2, NULL);
9414 ok(hr == S_OK, "got 0x%08x\n", hr);
9415
9416 p = NULL;
9417 hr = IXMLDOMElement_get_xml(elem2, &p);
9418 ok(hr == S_OK, "got 0x%08x\n", hr);
9419 ok(!lstrcmpW(p, _bstr_("<elem2/>")), "got %s\n", wine_dbgstr_w(p));
9420 SysFreeString(p);
9421
9422 IXMLDOMElement_Release(elem1);
9423 IXMLDOMElement_Release(elem2);
9424 IXMLDOMDocument_Release(doc);
9425 }
9426
9427 static void test_appendChild(void)
9428 {
9429 IXMLDOMDocument *doc, *doc2;
9430 IXMLDOMElement *elem, *elem2;
9431 HRESULT hr;
9432
9433 doc = create_document(&IID_IXMLDOMDocument);
9434 doc2 = create_document(&IID_IXMLDOMDocument);
9435
9436 hr = IXMLDOMDocument_createElement(doc, _bstr_("elem"), &elem);
9437 ok(hr == S_OK, "got 0x%08x\n", hr);
9438
9439 hr = IXMLDOMDocument_createElement(doc2, _bstr_("elem2"), &elem2);
9440 ok(hr == S_OK, "got 0x%08x\n", hr);
9441
9442 EXPECT_REF(doc, 1);
9443 todo_wine EXPECT_REF(elem, 2);
9444 EXPECT_REF(doc2, 1);
9445 todo_wine EXPECT_REF(elem2, 2);
9446 EXPECT_NO_CHILDREN(doc);
9447 EXPECT_NO_CHILDREN(doc2);
9448
9449 hr = IXMLDOMDocument_appendChild(doc2, NULL, NULL);
9450 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9451
9452 hr = IXMLDOMElement_appendChild(elem, NULL, NULL);
9453 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9454
9455 /* append from another document */
9456 hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, NULL);
9457 ok(hr == S_OK, "got 0x%08x\n", hr);
9458
9459 EXPECT_REF(doc, 1);
9460 todo_wine EXPECT_REF(elem, 2);
9461 EXPECT_REF(doc2, 1);
9462 todo_wine EXPECT_REF(elem2, 2);
9463 EXPECT_NO_CHILDREN(doc);
9464 EXPECT_CHILDREN(doc2);
9465
9466 IXMLDOMElement_Release(elem);
9467 IXMLDOMElement_Release(elem2);
9468 IXMLDOMDocument_Release(doc);
9469 IXMLDOMDocument_Release(doc2);
9470 }
9471
9472 static void test_get_doctype(void)
9473 {
9474 static const WCHAR emailW[] = {'e','m','a','i','l',0};
9475 IXMLDOMDocumentType *doctype;
9476 IXMLDOMDocument *doc;
9477 VARIANT_BOOL b;
9478 HRESULT hr;
9479 BSTR s;
9480
9481 doc = create_document(&IID_IXMLDOMDocument);
9482
9483 hr = IXMLDOMDocument_get_doctype(doc, NULL);
9484 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9485
9486 doctype = (void*)0xdeadbeef;
9487 hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9488 ok(hr == S_FALSE, "got 0x%08x\n", hr);
9489 ok(doctype == NULL, "got %p\n", doctype);
9490
9491 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szEmailXML), &b);
9492 ok(hr == S_OK, "got 0x%08x\n", hr);
9493 ok(b == VARIANT_TRUE, "failed to load XML string\n");
9494
9495 doctype = NULL;
9496 hr = IXMLDOMDocument_get_doctype(doc, &doctype);
9497 ok(hr == S_OK, "got 0x%08x\n", hr);
9498 ok(doctype != NULL, "got %p\n", doctype);
9499
9500 hr = IXMLDOMDocumentType_get_name(doctype, NULL);
9501 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9502
9503 hr = IXMLDOMDocumentType_get_name(doctype, &s);
9504 ok(hr == S_OK, "got 0x%08x\n", hr);
9505 ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9506 SysFreeString(s);
9507
9508 hr = IXMLDOMDocumentType_get_nodeName(doctype, &s);
9509 ok(hr == S_OK, "got 0x%08x\n", hr);
9510 ok(!lstrcmpW(emailW, s), "got name %s\n", wine_dbgstr_w(s));
9511 SysFreeString(s);
9512
9513 IXMLDOMDocumentType_Release(doctype);
9514 IXMLDOMDocument_Release(doc);
9515 }
9516
9517 static void test_get_tagName(void)
9518 {
9519 IXMLDOMDocument *doc;
9520 IXMLDOMElement *elem, *elem2;
9521 HRESULT hr;
9522 BSTR str;
9523
9524 doc = create_document(&IID_IXMLDOMDocument);
9525
9526 hr = IXMLDOMDocument_createElement(doc, _bstr_("element"), &elem);
9527 ok(hr == S_OK, "got 0x%08x\n", hr);
9528
9529 hr = IXMLDOMElement_get_tagName(elem, NULL);
9530 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9531
9532 str = NULL;
9533 hr = IXMLDOMElement_get_tagName(elem, &str);
9534 ok(hr == S_OK, "got 0x%08x\n", hr);
9535 ok(!lstrcmpW(str, _bstr_("element")), "got %s\n", wine_dbgstr_w(str));
9536 SysFreeString(str);
9537
9538 hr = IXMLDOMDocument_createElement(doc, _bstr_("s:element"), &elem2);
9539 ok(hr == S_OK, "got 0x%08x\n", hr);
9540
9541 str = NULL;
9542 hr = IXMLDOMElement_get_tagName(elem2, &str);
9543 ok(hr == S_OK, "got 0x%08x\n", hr);
9544 ok(!lstrcmpW(str, _bstr_("s:element")), "got %s\n", wine_dbgstr_w(str));
9545 SysFreeString(str);
9546
9547 IXMLDOMElement_Release(elem);
9548 IXMLDOMElement_Release(elem2);
9549 IXMLDOMDocument_Release(doc);
9550 free_bstrs();
9551 }
9552
9553 typedef struct {
9554 DOMNodeType type;
9555 const char *name;
9556 VARTYPE vt;
9557 HRESULT hr;
9558 } node_type_t;
9559
9560 static const node_type_t get_datatype[] = {
9561 { NODE_ELEMENT, "element", VT_NULL, S_FALSE },
9562 { NODE_ATTRIBUTE, "attr", VT_NULL, S_FALSE },
9563 { NODE_TEXT, "text", VT_NULL, S_FALSE },
9564 { NODE_CDATA_SECTION , "cdata", VT_NULL, S_FALSE },
9565 { NODE_ENTITY_REFERENCE, "entityref", VT_NULL, S_FALSE },
9566 { NODE_PROCESSING_INSTRUCTION, "pi", VT_NULL, S_FALSE },
9567 { NODE_COMMENT, "comment", VT_NULL, S_FALSE },
9568 { NODE_DOCUMENT_FRAGMENT, "docfrag", VT_NULL, S_FALSE },
9569 { 0 }
9570 };
9571
9572 static void test_get_dataType(void)
9573 {
9574 const node_type_t *entry = get_datatype;
9575 IXMLDOMDocument *doc;
9576
9577 doc = create_document(&IID_IXMLDOMDocument);
9578
9579 while (entry->type)
9580 {
9581 IXMLDOMNode *node = NULL;
9582 VARIANT var, type;
9583 HRESULT hr;
9584
9585 V_VT(&var) = VT_I4;
9586 V_I4(&var) = entry->type;
9587 hr = IXMLDOMDocument_createNode(doc, var, _bstr_(entry->name), NULL, &node);
9588 ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9589
9590 hr = IXMLDOMNode_get_dataType(node, NULL);
9591 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9592
9593 VariantInit(&type);
9594 hr = IXMLDOMNode_get_dataType(node, &type);
9595 ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9596 hr, entry->hr, entry->type);
9597 ok(V_VT(&type) == entry->vt, "got %d, expected %d. node type %d\n",
9598 V_VT(&type), entry->vt, entry->type);
9599 VariantClear(&type);
9600
9601 IXMLDOMNode_Release(node);
9602
9603 entry++;
9604 }
9605
9606 IXMLDOMDocument_Release(doc);
9607 free_bstrs();
9608 }
9609
9610 typedef struct _get_node_typestring_t {
9611 DOMNodeType type;
9612 const char *string;
9613 } get_node_typestring_t;
9614
9615 static const get_node_typestring_t get_node_typestring[] = {
9616 { NODE_ELEMENT, "element" },
9617 { NODE_ATTRIBUTE, "attribute" },
9618 { NODE_TEXT, "text" },
9619 { NODE_CDATA_SECTION , "cdatasection" },
9620 { NODE_ENTITY_REFERENCE, "entityreference" },
9621 { NODE_PROCESSING_INSTRUCTION, "processinginstruction" },
9622 { NODE_COMMENT, "comment" },
9623 { NODE_DOCUMENT_FRAGMENT, "documentfragment" },
9624 { 0 }
9625 };
9626
9627 static void test_get_nodeTypeString(void)
9628 {
9629 const get_node_typestring_t *entry = get_node_typestring;
9630 IXMLDOMDocument *doc;
9631 HRESULT hr;
9632 BSTR str;
9633
9634 doc = create_document(&IID_IXMLDOMDocument);
9635
9636 hr = IXMLDOMDocument_get_nodeTypeString(doc, &str);
9637 ok(hr == S_OK, "got 0x%08x\n", hr);
9638 ok(!lstrcmpW(str, _bstr_("document")), "got string %s\n", wine_dbgstr_w(str));
9639 SysFreeString(str);
9640
9641 while (entry->type)
9642 {
9643 IXMLDOMNode *node = NULL;
9644 VARIANT var;
9645
9646 V_VT(&var) = VT_I4;
9647 V_I4(&var) = entry->type;
9648 hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9649 ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9650
9651 hr = IXMLDOMNode_get_nodeTypeString(node, NULL);
9652 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9653
9654 hr = IXMLDOMNode_get_nodeTypeString(node, &str);
9655 ok(hr == S_OK, "got 0x%08x\n", hr);
9656 ok(!lstrcmpW(str, _bstr_(entry->string)), "got string %s, expected %s. node type %d\n",
9657 wine_dbgstr_w(str), entry->string, entry->type);
9658 SysFreeString(str);
9659 IXMLDOMNode_Release(node);
9660
9661 entry++;
9662 }
9663
9664 IXMLDOMDocument_Release(doc);
9665 free_bstrs();
9666 }
9667
9668 typedef struct _get_attributes_t {
9669 DOMNodeType type;
9670 HRESULT hr;
9671 } get_attributes_t;
9672
9673 static const get_attributes_t get_attributes[] = {
9674 { NODE_ATTRIBUTE, S_FALSE },
9675 { NODE_TEXT, S_FALSE },
9676 { NODE_CDATA_SECTION , S_FALSE },
9677 { NODE_ENTITY_REFERENCE, S_FALSE },
9678 { NODE_PROCESSING_INSTRUCTION, S_FALSE },
9679 { NODE_COMMENT, S_FALSE },
9680 { NODE_DOCUMENT_FRAGMENT, S_FALSE },
9681 { 0 }
9682 };
9683
9684 static void test_get_attributes(void)
9685 {
9686 const get_attributes_t *entry = get_attributes;
9687 IXMLDOMNamedNodeMap *map;
9688 IXMLDOMDocument *doc, *doc2;
9689 IXMLDOMNode *node, *node2;
9690 IXMLDOMElement *elem;
9691 VARIANT_BOOL b;
9692 HRESULT hr;
9693 VARIANT v;
9694 BSTR str;
9695 LONG length;
9696
9697 doc = create_document(&IID_IXMLDOMDocument);
9698
9699 hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
9700 ok(hr == S_OK, "got %08x\n", hr);
9701
9702 hr = IXMLDOMDocument_get_attributes(doc, NULL);
9703 ok(hr == E_INVALIDARG, "got %08x\n", hr);
9704
9705 map = (void*)0xdeadbeef;
9706 hr = IXMLDOMDocument_get_attributes(doc, &map);
9707 ok(hr == S_FALSE, "got %08x\n", hr);
9708 ok(map == NULL, "got %p\n", map);
9709
9710 /* first child is <?xml ?> */
9711 hr = IXMLDOMDocument_get_firstChild(doc, &node);
9712 ok(hr == S_OK, "got %08x\n", hr);
9713
9714 hr = IXMLDOMNode_get_attributes(node, &map);
9715 ok(hr == S_OK, "got %08x\n", hr);
9716
9717 node2 = (void*)0xdeadbeef;
9718 hr = IXMLDOMNamedNodeMap_getNamedItem(map, _bstr_("attr"), &node2);
9719 ok(hr == S_FALSE, "got %08x\n", hr);
9720 ok(node2 == NULL, "got %p\n", node2);
9721
9722 length = -1;
9723 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9724 EXPECT_HR(hr, S_OK);
9725 todo_wine ok(length == 1, "got %d\n", length);
9726
9727 if (hr == S_OK && length == 1)
9728 {
9729 IXMLDOMAttribute *attr;
9730 DOMNodeType type;
9731 VARIANT v;
9732
9733 node2 = NULL;
9734 hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9735 EXPECT_HR(hr, S_OK);
9736 ok(node != NULL, "got %p\n", node2);
9737
9738 hr = IXMLDOMNode_get_nodeName(node2, &str);
9739 EXPECT_HR(hr, S_OK);
9740 ok(!lstrcmpW(str, _bstr_("version")), "got %s\n", wine_dbgstr_w(str));
9741 SysFreeString(str);
9742
9743 length = -1;
9744 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9745 EXPECT_HR(hr, S_OK);
9746 ok(length == 1, "got %d\n", length);
9747
9748 type = -1;
9749 hr = IXMLDOMNode_get_nodeType(node2, &type);
9750 EXPECT_HR(hr, S_OK);
9751 ok(type == NODE_ATTRIBUTE, "got %d\n", type);
9752
9753 hr = IXMLDOMNode_get_xml(node, &str);
9754 EXPECT_HR(hr, S_OK);
9755 ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9756 SysFreeString(str);
9757
9758 hr = IXMLDOMNode_get_text(node, &str);
9759 EXPECT_HR(hr, S_OK);
9760 ok(!lstrcmpW(str, _bstr_("version=\"1.0\"")), "got %s\n", wine_dbgstr_w(str));
9761 SysFreeString(str);
9762
9763 hr = IXMLDOMNamedNodeMap_removeNamedItem(map, _bstr_("version"), NULL);
9764 EXPECT_HR(hr, S_OK);
9765
9766 length = -1;
9767 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9768 EXPECT_HR(hr, S_OK);
9769 ok(length == 0, "got %d\n", length);
9770
9771 hr = IXMLDOMNode_get_xml(node, &str);
9772 EXPECT_HR(hr, S_OK);
9773 ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9774 SysFreeString(str);
9775
9776 hr = IXMLDOMNode_get_text(node, &str);
9777 EXPECT_HR(hr, S_OK);
9778 ok(!lstrcmpW(str, _bstr_("")), "got %s\n", wine_dbgstr_w(str));
9779 SysFreeString(str);
9780
9781 IXMLDOMNamedNodeMap_Release(map);
9782
9783 hr = IXMLDOMNode_get_attributes(node, &map);
9784 ok(hr == S_OK, "got %08x\n", hr);
9785
9786 length = -1;
9787 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9788 EXPECT_HR(hr, S_OK);
9789 ok(length == 0, "got %d\n", length);
9790
9791 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("encoding"), &attr);
9792 EXPECT_HR(hr, S_OK);
9793
9794 V_VT(&v) = VT_BSTR;
9795 V_BSTR(&v) = _bstr_("UTF-8");
9796 hr = IXMLDOMAttribute_put_nodeValue(attr, v);
9797 EXPECT_HR(hr, S_OK);
9798
9799 EXPECT_REF(attr, 2);
9800 hr = IXMLDOMNamedNodeMap_setNamedItem(map, (IXMLDOMNode*)attr, NULL);
9801 EXPECT_HR(hr, S_OK);
9802 EXPECT_REF(attr, 2);
9803
9804 hr = IXMLDOMNode_get_attributes(node, &map);
9805 ok(hr == S_OK, "got %08x\n", hr);
9806
9807 length = -1;
9808 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9809 EXPECT_HR(hr, S_OK);
9810 ok(length == 1, "got %d\n", length);
9811
9812 hr = IXMLDOMNode_get_xml(node, &str);
9813 EXPECT_HR(hr, S_OK);
9814 ok(!lstrcmpW(str, _bstr_("<?xml version=\"1.0\"?>")), "got %s\n", wine_dbgstr_w(str));
9815 SysFreeString(str);
9816
9817 hr = IXMLDOMNode_get_text(node, &str);
9818 EXPECT_HR(hr, S_OK);
9819 ok(!lstrcmpW(str, _bstr_("encoding=\"UTF-8\"")), "got %s\n", wine_dbgstr_w(str));
9820 SysFreeString(str);
9821
9822 IXMLDOMNamedNodeMap_Release(map);
9823 IXMLDOMNode_Release(node2);
9824 }
9825
9826 IXMLDOMNode_Release(node);
9827
9828 /* last child is element */
9829 EXPECT_REF(doc, 1);
9830 hr = IXMLDOMDocument_get_lastChild(doc, &node);
9831 ok(hr == S_OK, "got %08x\n", hr);
9832 EXPECT_REF(doc, 1);
9833
9834 EXPECT_REF(node, 1);
9835 hr = IXMLDOMNode_get_attributes(node, &map);
9836 ok(hr == S_OK, "got %08x\n", hr);
9837 EXPECT_REF(node, 1);
9838 EXPECT_REF(doc, 1);
9839
9840 EXPECT_REF(map, 1);
9841 hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9842 ok(hr == S_OK, "got %08x\n", hr);
9843 EXPECT_REF(node, 1);
9844 EXPECT_REF(node2, 1);
9845 EXPECT_REF(map, 1);
9846 EXPECT_REF(doc, 1);
9847 IXMLDOMNode_Release(node2);
9848
9849 /* release node before map release, map still works */
9850 IXMLDOMNode_Release(node);
9851
9852 length = 0;
9853 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9854 ok(hr == S_OK, "got %08x\n", hr);
9855 ok(length == 1, "got %d\n", length);
9856
9857 node2 = NULL;
9858 hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node2);
9859 ok(hr == S_OK, "got %08x\n", hr);
9860 EXPECT_REF(node2, 1);
9861 IXMLDOMNode_Release(node2);
9862
9863 IXMLDOMNamedNodeMap_Release(map);
9864
9865 /* append created element a different document, map still works */
9866 hr = IXMLDOMDocument_createElement(doc, _bstr_("test"), &elem);
9867 ok(hr == S_OK, "createElement failed: %08x\n", hr);
9868
9869 V_VT(&v) = VT_I4;
9870 V_I4(&v) = 1;
9871 hr = IXMLDOMElement_setAttribute(elem, _bstr_("testattr"), v);
9872 ok(hr == S_OK, "setAttribute failed: %08x\n", hr);
9873
9874 hr = IXMLDOMElement_get_attributes(elem, &map);
9875 ok(hr == S_OK, "get_attributes failed: %08x\n", hr);
9876
9877 length = 0;
9878 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9879 ok(hr == S_OK, "got %08x\n", hr);
9880 ok(length == 1, "got %d\n", length);
9881
9882 doc2 = create_document(&IID_IXMLDOMDocument);
9883
9884 hr = IXMLDOMDocument_appendChild(doc2, (IXMLDOMNode*)elem, &node);
9885 ok(hr == S_OK, "appendChild failed: %08x\n", hr);
9886 ok(node == (IXMLDOMNode*)elem, "node != elem\n");
9887 IXMLDOMNode_Release(node);
9888 IXMLDOMElement_Release(elem);
9889 IXMLDOMDocument_Release(doc2);
9890
9891 length = 0;
9892 hr = IXMLDOMNamedNodeMap_get_length(map, &length);
9893 ok(hr == S_OK, "got %08x\n", hr);
9894 ok(length == 1, "got %d\n", length);
9895
9896 IXMLDOMNamedNodeMap_Release(map);
9897
9898 while (entry->type)
9899 {
9900 VARIANT var;
9901
9902 node = NULL;
9903
9904 V_VT(&var) = VT_I4;
9905 V_I4(&var) = entry->type;
9906 hr = IXMLDOMDocument_createNode(doc, var, _bstr_("node"), NULL, &node);
9907 ok(hr == S_OK, "failed to create node, type %d\n", entry->type);
9908
9909 hr = IXMLDOMNode_get_attributes(node, NULL);
9910 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
9911
9912 map = (void*)0xdeadbeef;
9913 hr = IXMLDOMNode_get_attributes(node, &map);
9914 ok(hr == entry->hr, "got 0x%08x, expected 0x%08x. node type %d\n",
9915 hr, entry->hr, entry->type);
9916 ok(map == NULL, "got %p\n", map);
9917
9918 IXMLDOMNode_Release(node);
9919
9920 entry++;
9921 }
9922
9923 IXMLDOMDocument_Release(doc);
9924 free_bstrs();
9925 }
9926
9927 static void test_selection(void)
9928 {
9929 IXMLDOMSelection *selection, *selection2;
9930 IEnumVARIANT *enum1, *enum2, *enum3;
9931 IXMLDOMNodeList *list;
9932 IUnknown *unk1, *unk2;
9933 IXMLDOMDocument *doc;
9934 IDispatchEx *dispex;
9935 IXMLDOMNode *node;
9936 IDispatch *disp;
9937 VARIANT_BOOL b;
9938 HRESULT hr;
9939 DISPID did;
9940 VARIANT v;
9941 BSTR name;
9942 ULONG ret;
9943 LONG len;
9944
9945 doc = create_document(&IID_IXMLDOMDocument);
9946
9947 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
9948 EXPECT_HR(hr, S_OK);
9949
9950 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root"), &list);
9951 EXPECT_HR(hr, S_OK);
9952
9953 hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
9954 EXPECT_HR(hr, S_OK);
9955 IXMLDOMSelection_Release(selection);
9956
9957 /* collection disp id */
9958 hr = IXMLDOMSelection_QueryInterface(selection, &IID_IDispatchEx, (void**)&dispex);
9959 EXPECT_HR(hr, S_OK);
9960 did = 0;
9961 hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
9962 EXPECT_HR(hr, S_OK);
9963 ok(did == DISPID_DOM_COLLECTION_BASE, "got %d\n", did);
9964 len = 0;
9965 hr = IXMLDOMSelection_get_length(selection, &len);
9966 EXPECT_HR(hr, S_OK);
9967 ok(len == 1, "got %d\n", len);
9968 hr = IDispatchEx_GetDispID(dispex, _bstr_("10"), 0, &did);
9969 EXPECT_HR(hr, S_OK);
9970 ok(did == DISPID_DOM_COLLECTION_BASE+10, "got %d\n", did);
9971 IDispatchEx_Release(dispex);
9972
9973 /* IEnumVARIANT tests */
9974 enum1 = NULL;
9975 hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum1);
9976 EXPECT_HR(hr, S_OK);
9977 ok(enum1 != NULL, "got %p\n", enum1);
9978 EXPECT_REF(enum1, 2);
9979
9980 EXPECT_REF(selection, 1);
9981 hr = IXMLDOMSelection_QueryInterface(selection, &IID_IUnknown, (void**)&unk1);
9982 EXPECT_HR(hr, S_OK);
9983 EXPECT_REF(selection, 2);
9984 EXPECT_REF(enum1, 2);
9985
9986 /* enumerator and selection object return same IUnknown* */
9987 hr = IEnumVARIANT_QueryInterface(enum1, &IID_IUnknown, (void**)&unk2);
9988 EXPECT_HR(hr, S_OK);
9989 EXPECT_REF(selection, 3);
9990 EXPECT_REF(enum1, 2);
9991 ok(unk2 == unk1, "got %p, %p\n", unk1, unk2);
9992 IUnknown_Release(unk2);
9993
9994 EXPECT_REF(selection, 2);
9995 IEnumVARIANT_AddRef(enum1);
9996 EXPECT_REF(selection, 2);
9997 IEnumVARIANT_Release(enum1);
9998
9999 enum3 = NULL;
10000 hr = IXMLDOMSelection_QueryInterface(selection, &IID_IEnumVARIANT, (void**)&enum3);
10001 EXPECT_HR(hr, S_OK);
10002 ok(enum3 != NULL, "got %p\n", enum3);
10003 ok(enum1 == enum3, "got %p and %p\n", enum1, enum3);
10004 EXPECT_REF(enum1, 3);
10005 IEnumVARIANT_Release(enum3);
10006
10007 EXPECT_REF(selection, 2);
10008 EXPECT_REF(enum1, 2);
10009
10010 enum2 = NULL;
10011 hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
10012 EXPECT_HR(hr, S_OK);
10013 ok(enum2 != NULL, "got %p\n", enum2);
10014
10015 EXPECT_REF(selection, 3);
10016 EXPECT_REF(enum1, 2);
10017 EXPECT_REF(enum2, 1);
10018
10019 ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10020
10021 hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
10022 EXPECT_HR(hr, S_OK);
10023 EXPECT_REF(selection, 3);
10024 EXPECT_REF(enum2, 2);
10025 ok(unk2 != unk1, "got %p, %p\n", unk1, unk2);
10026 IUnknown_Release(unk2);
10027 IUnknown_Release(unk1);
10028
10029 selection2 = NULL;
10030 hr = IEnumVARIANT_QueryInterface(enum1, &IID_IXMLDOMSelection, (void**)&selection2);
10031 EXPECT_HR(hr, S_OK);
10032 ok(selection2 == selection, "got %p and %p\n", selection, selection2);
10033 EXPECT_REF(selection, 3);
10034 EXPECT_REF(enum1, 2);
10035
10036 IXMLDOMSelection_Release(selection2);
10037
10038 hr = IEnumVARIANT_QueryInterface(enum1, &IID_IDispatch, (void**)&disp);
10039 EXPECT_HR(hr, S_OK);
10040 EXPECT_REF(selection, 3);
10041 IDispatch_Release(disp);
10042
10043 hr = IEnumVARIANT_QueryInterface(enum1, &IID_IEnumVARIANT, (void**)&enum3);
10044 EXPECT_HR(hr, S_OK);
10045 ok(enum3 == enum1, "got %p and %p\n", enum3, enum1);
10046 EXPECT_REF(selection, 2);
10047 EXPECT_REF(enum1, 3);
10048
10049 IEnumVARIANT_Release(enum1);
10050 IEnumVARIANT_Release(enum2);
10051 IEnumVARIANT_Release(enum3);
10052
10053 enum1 = NULL;
10054 hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10055 EXPECT_HR(hr, S_OK);
10056 ok(enum1 != NULL, "got %p\n", enum1);
10057 EXPECT_REF(enum1, 1);
10058 EXPECT_REF(selection, 2);
10059
10060 enum2 = NULL;
10061 hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum2);
10062 EXPECT_HR(hr, S_OK);
10063 ok(enum2 != NULL, "got %p\n", enum2);
10064 EXPECT_REF(enum2, 1);
10065 EXPECT_REF(selection, 3);
10066
10067 ok(enum1 != enum2, "got %p, %p\n", enum1, enum2);
10068
10069 IEnumVARIANT_AddRef(enum1);
10070 EXPECT_REF(selection, 3);
10071 EXPECT_REF(enum1, 2);
10072 EXPECT_REF(enum2, 1);
10073 IEnumVARIANT_Release(enum1);
10074
10075 IEnumVARIANT_Release(enum1);
10076 IEnumVARIANT_Release(enum2);
10077
10078 EXPECT_REF(selection, 1);
10079
10080 IXMLDOMNodeList_Release(list);
10081
10082 hr = IXMLDOMDocument_get_childNodes(doc, &list);
10083 EXPECT_HR(hr, S_OK);
10084
10085 hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10086 EXPECT_HR(hr, E_NOINTERFACE);
10087
10088 IXMLDOMNodeList_Release(list);
10089
10090 /* test if IEnumVARIANT touches selection context */
10091 hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
10092 EXPECT_HR(hr, S_OK);
10093
10094 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/*"), &list);
10095 EXPECT_HR(hr, S_OK);
10096
10097 hr = IXMLDOMNodeList_QueryInterface(list, &IID_IXMLDOMSelection, (void**)&selection);
10098 EXPECT_HR(hr, S_OK);
10099
10100 len = 0;
10101 hr = IXMLDOMSelection_get_length(selection, &len);
10102 EXPECT_HR(hr, S_OK);
10103 ok(len == 4, "got %d\n", len);
10104
10105 enum1 = NULL;
10106 hr = IXMLDOMSelection_get__newEnum(selection, (IUnknown**)&enum1);
10107 EXPECT_HR(hr, S_OK);
10108
10109 /* no-op if zero count */
10110 V_VT(&v) = VT_I2;
10111 hr = IEnumVARIANT_Next(enum1, 0, &v, NULL);
10112 EXPECT_HR(hr, S_OK);
10113 ok(V_VT(&v) == VT_I2, "got var type %d\n", V_VT(&v));
10114
10115 /* positive count, null array pointer */
10116 hr = IEnumVARIANT_Next(enum1, 1, NULL, NULL);
10117 EXPECT_HR(hr, E_INVALIDARG);
10118
10119 ret = 1;
10120 hr = IEnumVARIANT_Next(enum1, 1, NULL, &ret);
10121 EXPECT_HR(hr, E_INVALIDARG);
10122 ok(ret == 0, "got %d\n", ret);
10123
10124 V_VT(&v) = VT_I2;
10125 hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10126 EXPECT_HR(hr, S_OK);
10127 ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10128
10129 hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10130 EXPECT_HR(hr, S_OK);
10131 hr = IXMLDOMNode_get_nodeName(node, &name);
10132 EXPECT_HR(hr, S_OK);
10133 ok(!lstrcmpW(name, _bstr_("a")), "got node name %s\n", wine_dbgstr_w(name));
10134 SysFreeString(name);
10135 IXMLDOMNode_Release(node);
10136 VariantClear(&v);
10137
10138 /* list cursor is updated */
10139 hr = IXMLDOMSelection_nextNode(selection, &node);
10140 EXPECT_HR(hr, S_OK);
10141 hr = IXMLDOMNode_get_nodeName(node, &name);
10142 EXPECT_HR(hr, S_OK);
10143 ok(!lstrcmpW(name, _bstr_("c")), "got node name %s\n", wine_dbgstr_w(name));
10144 IXMLDOMNode_Release(node);
10145 SysFreeString(name);
10146
10147 V_VT(&v) = VT_I2;
10148 hr = IEnumVARIANT_Next(enum1, 1, &v, NULL);
10149 EXPECT_HR(hr, S_OK);
10150 ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
10151 hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
10152 EXPECT_HR(hr, S_OK);
10153 hr = IXMLDOMNode_get_nodeName(node, &name);
10154 EXPECT_HR(hr, S_OK);
10155 ok(!lstrcmpW(name, _bstr_("b")), "got node name %s\n", wine_dbgstr_w(name));
10156 SysFreeString(name);
10157 IXMLDOMNode_Release(node);
10158 VariantClear(&v);
10159 IEnumVARIANT_Release(enum1);
10160
10161 hr = IXMLDOMSelection_nextNode(selection, &node);
10162 EXPECT_HR(hr, S_OK);
10163 hr = IXMLDOMNode_get_nodeName(node, &name);
10164 EXPECT_HR(hr, S_OK);
10165 ok(!lstrcmpW(name, _bstr_("d")), "got node name %s\n", wine_dbgstr_w(name));
10166 IXMLDOMNode_Release(node);
10167 SysFreeString(name);
10168
10169 IXMLDOMSelection_Release(selection);
10170 IXMLDOMNodeList_Release(list);
10171 IXMLDOMDocument_Release(doc);
10172
10173 free_bstrs();
10174 }
10175
10176 static void write_to_file(const char *name, const char *data)
10177 {
10178 DWORD written;
10179 HANDLE hfile;
10180 BOOL ret;
10181
10182 hfile = CreateFileA(name, GENERIC_WRITE|GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
10183 ok(hfile != INVALID_HANDLE_VALUE, "failed to create test file: %s\n", name);
10184
10185 ret = WriteFile(hfile, data, strlen(data), &written, NULL);
10186 ok(ret, "WriteFile failed: %s, %d\n", name, GetLastError());
10187
10188 CloseHandle(hfile);
10189 }
10190
10191 static void test_doc_load_from_path(IXMLDOMDocument *doc, const char *path)
10192 {
10193 IXMLDOMDocument *doc2;
10194 IXMLDOMElement *elem;
10195 BSTR url, url2;
10196 VARIANT_BOOL b;
10197 VARIANT src;
10198 HRESULT hr;
10199
10200 url = _bstr_(path);
10201
10202 V_VT(&src) = VT_BSTR;
10203 V_BSTR(&src) = url;
10204 hr = IXMLDOMDocument_load(doc, src, &b);
10205 ok(hr == S_OK, "Failed to load document, %#x.\n", hr);
10206 ok(b == VARIANT_TRUE, "got %d\n", b);
10207
10208 V_VT(&src) = VT_BSTR | VT_BYREF;
10209 V_BSTRREF(&src) = &url;
10210 hr = IXMLDOMDocument_load(doc, src, &b);
10211 ok(hr == S_OK, "Failed to load document, %#x.\n", hr);
10212 ok(b == VARIANT_TRUE, "got %d\n", b);
10213
10214 url = NULL;
10215 hr = IXMLDOMDocument_get_url(doc, &url);
10216 ok(hr == S_OK, "Failed to get document url, hr %#x.\n", hr);
10217
10218 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
10219 ok(hr == S_OK, "got 0x%08x\n", hr);
10220
10221 /* Create another instance for the same document, check url */
10222 hr = IXMLDOMElement_get_ownerDocument(elem, &doc2);
10223 ok(hr == S_OK, "Failed to get owner document, hr %#x.\n", hr);
10224
10225 hr = IXMLDOMDocument_get_url(doc2, &url2);
10226 ok(hr == S_OK, "Failed to get document url, hr %#x.\n", hr);
10227 ok(!lstrcmpW(url, url2), "Unexpected url %s.\n", wine_dbgstr_w(url2));
10228
10229 IXMLDOMDocument_Release(doc2);
10230 IXMLDOMElement_Release(elem);
10231 SysFreeString(url2);
10232 SysFreeString(url);
10233 }
10234
10235 static void url_forward_slash(char *url)
10236 {
10237 char *p = url;
10238
10239 while (*p)
10240 {
10241 if (*p == '\\')
10242 *p = '/';
10243 p++;
10244 }
10245 }
10246
10247 static void test_load(void)
10248 {
10249 char path[MAX_PATH], path2[MAX_PATH];
10250 IXMLDOMNodeList *list;
10251 IXMLDOMDocument *doc;
10252 BSTR bstr1, bstr2;
10253 VARIANT_BOOL b;
10254 VARIANT src;
10255 HRESULT hr;
10256 void* ptr;
10257
10258 GetTempPathA(MAX_PATH, path);
10259 strcat(path, "winetest.xml");
10260
10261 /* prepare a file */
10262 write_to_file(path, win1252xml);
10263
10264 doc = create_document(&IID_IXMLDOMDocument);
10265
10266 /* null pointer as input */
10267 V_VT(&src) = VT_UNKNOWN;
10268 V_UNKNOWN(&src) = NULL;
10269 hr = IXMLDOMDocument_load(doc, src, &b);
10270 EXPECT_HR(hr, E_INVALIDARG);
10271 ok(b == VARIANT_FALSE, "got %d\n", b);
10272
10273 /* "file://" url */
10274 strcpy(path2, "file://");
10275 strcat(path2, path);
10276 test_doc_load_from_path(doc, path2);
10277
10278 /* file:// url, forward slashes */
10279 url_forward_slash(path2);
10280 test_doc_load_from_path(doc, path2);
10281
10282 /* "file:/" url */
10283 strcpy(path2, "file:/");
10284 strcat(path2, path);
10285 test_doc_load_from_path(doc, path);
10286
10287 /* file:/ with forward slashes. */
10288 url_forward_slash(path2);
10289 test_doc_load_from_path(doc, path2);
10290
10291 /* Regular local path. */
10292 test_doc_load_from_path(doc, path);
10293
10294 /* load from a path: VT_BSTR|VT_BYREF, null ptr */
10295 V_VT(&src) = VT_BSTR | VT_BYREF;
10296 V_BSTRREF(&src) = NULL;
10297 hr = IXMLDOMDocument_load(doc, src, &b);
10298 EXPECT_HR(hr, E_INVALIDARG);
10299 ok(b == VARIANT_FALSE, "got %d\n", b);
10300
10301 bstr1 = NULL;
10302 hr = IXMLDOMDocument_get_url(doc, &bstr1);
10303 ok(hr == S_OK, "got 0x%08x\n", hr);
10304 SysFreeString(bstr1);
10305
10306 DeleteFileA(path);
10307
10308 /* load from existing path, no xml content */
10309 write_to_file(path, nocontent);
10310
10311 V_VT(&src) = VT_BSTR;
10312 V_BSTR(&src) = _bstr_(path);
10313 b = VARIANT_TRUE;
10314 hr = IXMLDOMDocument_load(doc, src, &b);
10315 ok(hr == S_FALSE, "got 0x%08x\n", hr);
10316 ok(b == VARIANT_FALSE, "got %d\n", b);
10317
10318 bstr1 = (void *)0xdeadbeef;
10319 hr = IXMLDOMDocument_get_url(doc, &bstr1);
10320 ok(hr == S_FALSE, "got 0x%08x\n", hr);
10321 ok(bstr1 == NULL, "got %p\n", bstr1);
10322
10323 DeleteFileA(path);
10324 IXMLDOMDocument_Release(doc);
10325
10326 doc = create_document(&IID_IXMLDOMDocument);
10327
10328 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &b);
10329 EXPECT_HR(hr, S_OK);
10330 ok(b == VARIANT_TRUE, "got %d\n", b);
10331
10332 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10333 EXPECT_HR(hr, S_OK);
10334 bstr1 = _bstr_(list_to_string(list));
10335
10336 hr = IXMLDOMNodeList_reset(list);
10337 EXPECT_HR(hr, S_OK);
10338
10339 IXMLDOMDocument_Release(doc);
10340
10341 doc = create_document(&IID_IXMLDOMDocument);
10342
10343 VariantInit(&src);
10344 V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenA(szExampleXML));
10345 V_VT(&src) = VT_ARRAY|VT_UI1;
10346 ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10347 ptr = NULL;
10348 hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10349 EXPECT_HR(hr, S_OK);
10350 ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10351
10352 memcpy(ptr, szExampleXML, lstrlenA(szExampleXML));
10353 hr = SafeArrayUnlock(V_ARRAY(&src));
10354 EXPECT_HR(hr, S_OK);
10355
10356 hr = IXMLDOMDocument_load(doc, src, &b);
10357 EXPECT_HR(hr, S_OK);
10358 ok(b == VARIANT_TRUE, "got %d\n", b);
10359
10360 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("//*"), &list);
10361 EXPECT_HR(hr, S_OK);
10362 bstr2 = _bstr_(list_to_string(list));
10363
10364 hr = IXMLDOMNodeList_reset(list);
10365 EXPECT_HR(hr, S_OK);
10366
10367 ok(lstrcmpW(bstr1, bstr2) == 0, "strings not equal: %s : %s\n",
10368 wine_dbgstr_w(bstr1), wine_dbgstr_w(bstr2));
10369
10370 IXMLDOMDocument_Release(doc);
10371 IXMLDOMNodeList_Release(list);
10372 VariantClear(&src);
10373
10374 /* UTF-16 isn't accepted */
10375 doc = create_document(&IID_IXMLDOMDocument);
10376
10377 V_ARRAY(&src) = SafeArrayCreateVector(VT_UI1, 0, lstrlenW(szComplete1) * sizeof(WCHAR));
10378 V_VT(&src) = VT_ARRAY|VT_UI1;
10379 ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10380 ptr = NULL;
10381 hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10382 EXPECT_HR(hr, S_OK);
10383 ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10384
10385 memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10386 hr = SafeArrayUnlock(V_ARRAY(&src));
10387 EXPECT_HR(hr, S_OK);
10388
10389 hr = IXMLDOMDocument_load(doc, src, &b);
10390 todo_wine EXPECT_HR(hr, S_FALSE);
10391 todo_wine ok(b == VARIANT_FALSE, "got %d\n", b);
10392
10393 VariantClear(&src);
10394
10395 /* it doesn't like it as a VT_ARRAY|VT_UI2 either */
10396 V_ARRAY(&src) = SafeArrayCreateVector(VT_UI2, 0, lstrlenW(szComplete1));
10397 V_VT(&src) = VT_ARRAY|VT_UI2;
10398 ok(V_ARRAY(&src) != NULL, "SafeArrayCreateVector() returned NULL\n");
10399 ptr = NULL;
10400 hr = SafeArrayAccessData(V_ARRAY(&src), &ptr);
10401 EXPECT_HR(hr, S_OK);
10402 ok(ptr != NULL, "SafeArrayAccessData() returned NULL\n");
10403
10404 memcpy(ptr, szComplete1, lstrlenW(szComplete1) * sizeof(WCHAR));
10405 hr = SafeArrayUnlock(V_ARRAY(&src));
10406 EXPECT_HR(hr, S_OK);
10407
10408 hr = IXMLDOMDocument_load(doc, src, &b);
10409 todo_wine EXPECT_HR(hr, E_INVALIDARG);
10410 ok(b == VARIANT_FALSE, "got %d\n", b);
10411
10412 VariantClear(&src);
10413 IXMLDOMDocument_Release(doc);
10414
10415 free_bstrs();
10416 }
10417
10418 static void test_domobj_dispex(IUnknown *obj)
10419 {
10420 static const WCHAR testW[] = {'t','e','s','t','p','r','o','p',0};
10421 DISPID dispid = DISPID_XMLDOM_NODELIST_RESET;
10422 IDispatchEx *dispex;
10423 IUnknown *unk;
10424 DWORD props;
10425 UINT ticnt;
10426 HRESULT hr;
10427 BSTR name;
10428
10429 hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex);
10430 EXPECT_HR(hr, S_OK);
10431 if (FAILED(hr)) return;
10432
10433 ticnt = 0;
10434 hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
10435 EXPECT_HR(hr, S_OK);
10436 ok(ticnt == 1, "ticnt=%u\n", ticnt);
10437
10438 name = SysAllocString(szstar);
10439 hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive);
10440 EXPECT_HR(hr, E_NOTIMPL);
10441 SysFreeString(name);
10442
10443 hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid);
10444 EXPECT_HR(hr, E_NOTIMPL);
10445
10446 props = 0;
10447 hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props);
10448 EXPECT_HR(hr, E_NOTIMPL);
10449 ok(props == 0, "expected 0 got %d\n", props);
10450
10451 hr = IDispatchEx_GetMemberName(dispex, dispid, &name);
10452 EXPECT_HR(hr, E_NOTIMPL);
10453 if (SUCCEEDED(hr)) SysFreeString(name);
10454
10455 hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_XMLDOM_NODELIST_RESET, &dispid);
10456 EXPECT_HR(hr, E_NOTIMPL);
10457
10458 unk = (IUnknown*)0xdeadbeef;
10459 hr = IDispatchEx_GetNameSpaceParent(dispex, &unk);
10460 EXPECT_HR(hr, E_NOTIMPL);
10461 ok(unk == (IUnknown*)0xdeadbeef, "got %p\n", unk);
10462
10463 name = SysAllocString(testW);
10464 hr = IDispatchEx_GetDispID(dispex, name, fdexNameEnsure, &dispid);
10465 ok(hr == DISP_E_UNKNOWNNAME, "got 0x%08x\n", hr);
10466 SysFreeString(name);
10467
10468 IDispatchEx_Release(dispex);
10469 }
10470
10471 static void test_mxnamespacemanager(void)
10472 {
10473 static const char xmluriA[] = "http://www.w3.org/XML/1998/namespace";
10474 IMXNamespacePrefixes *prefixes;
10475 IVBMXNamespaceManager *mgr2;
10476 IMXNamespaceManager *nsmgr;
10477 IUnknown *unk1, *unk2;
10478 WCHAR buffW[250];
10479 IDispatch *disp;
10480 IUnknown *unk;
10481 HRESULT hr;
10482 INT len;
10483
10484 hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10485 &IID_IMXNamespaceManager, (void**)&nsmgr);
10486 EXPECT_HR(hr, S_OK);
10487
10488 /* IMXNamespaceManager inherits from IUnknown */
10489 hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IDispatch, (void**)&disp);
10490 EXPECT_HR(hr, S_OK);
10491 IDispatch_Release(disp);
10492
10493 hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IVBMXNamespaceManager, (void**)&mgr2);
10494 EXPECT_HR(hr, S_OK);
10495
10496 EXPECT_REF(nsmgr, 2);
10497 EXPECT_REF(mgr2, 2);
10498 prefixes = NULL;
10499 hr = IVBMXNamespaceManager_getDeclaredPrefixes(mgr2, &prefixes);
10500 todo_wine
10501 ok(hr == S_OK, "got 0x%08x\n", hr);
10502 if (hr == S_OK)
10503 {
10504 IDispatchEx *dispex;
10505 VARIANT arg, ret;
10506 DISPPARAMS dispparams;
10507
10508 ok(prefixes != NULL, "got %p\n", prefixes);
10509 EXPECT_REF(nsmgr, 2);
10510 EXPECT_REF(mgr2, 2);
10511 EXPECT_REF(prefixes, 1);
10512
10513 IVBMXNamespaceManager_QueryInterface(mgr2, &IID_IUnknown, (void**)&unk1);
10514 IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IUnknown, (void**)&unk2);
10515
10516 EXPECT_REF(mgr2, 3);
10517 EXPECT_REF(prefixes, 2);
10518
10519 IUnknown_Release(unk1);
10520 IUnknown_Release(unk2);
10521
10522 hr = IMXNamespacePrefixes_QueryInterface(prefixes, &IID_IDispatchEx, (void**)&dispex);
10523 ok(hr == S_OK, "got 0x%08x\n", hr);
10524
10525 V_VT(&arg) = VT_I4;
10526 V_I4(&arg) = 0;
10527 dispparams.cArgs = 1;
10528 dispparams.cNamedArgs = 0;
10529 dispparams.rgdispidNamedArgs = NULL;
10530 dispparams.rgvarg = &arg;
10531
10532 V_VT(&ret) = VT_EMPTY;
10533 V_DISPATCH(&ret) = (void*)0x1;
10534 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
10535 ok(hr == S_OK, "got 0x%08x\n", hr);
10536 ok(V_VT(&ret) == VT_BSTR, "got %d\n", V_VT(&ret));
10537 ok(V_BSTR(&ret) != NULL, "got %p\n", V_BSTR(&ret));
10538 VariantClear(&ret);
10539
10540 IDispatchEx_Release(dispex);
10541 IMXNamespacePrefixes_Release(prefixes);
10542 }
10543 IVBMXNamespaceManager_Release(mgr2);
10544
10545 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10546 EXPECT_HR(hr, S_OK);
10547
10548 /* prefix already added */
10549 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10550 EXPECT_HR(hr, S_FALSE);
10551
10552 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), NULL);
10553 EXPECT_HR(hr, E_INVALIDARG);
10554
10555 /* "xml" and "xmlns" are not allowed here */
10556 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xml"), _bstr_("uri1"));
10557 EXPECT_HR(hr, E_INVALIDARG);
10558
10559 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("xmlns"), _bstr_("uri1"));
10560 EXPECT_HR(hr, E_INVALIDARG);
10561 todo_wine {
10562 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, -1, NULL, NULL);
10563 EXPECT_HR(hr, E_FAIL);
10564 }
10565 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, NULL);
10566 EXPECT_HR(hr, E_POINTER);
10567
10568 len = -1;
10569 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, NULL, &len);
10570 EXPECT_HR(hr, S_OK);
10571 ok(len == 3, "got %d\n", len);
10572
10573 len = -1;
10574 buffW[0] = 0x1;
10575 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10576 EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10577 ok(len == -1, "got %d\n", len);
10578 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10579
10580 len = 10;
10581 buffW[0] = 0x1;
10582 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10583 EXPECT_HR(hr, S_OK);
10584 ok(len == 3, "got %d\n", len);
10585 ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10586
10587 /* getURI */
10588 hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, NULL);
10589 EXPECT_HR(hr, E_INVALIDARG);
10590
10591 len = -1;
10592 hr = IMXNamespaceManager_getURI(nsmgr, NULL, NULL, NULL, &len);
10593 EXPECT_HR(hr, E_INVALIDARG);
10594 ok(len == -1, "got %d\n", len);
10595
10596 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, NULL);
10597 EXPECT_HR(hr, E_POINTER);
10598
10599 len = -1;
10600 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, NULL, &len);
10601 EXPECT_HR(hr, S_OK);
10602 /* length of "xml" uri is constant */
10603 ok(len == strlen(xmluriA), "got %d\n", len);
10604
10605 len = 100;
10606 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10607 EXPECT_HR(hr, S_OK);
10608 ok(len == strlen(xmluriA), "got %d\n", len);
10609 ok(!lstrcmpW(buffW, _bstr_(xmluriA)), "got prefix %s\n", wine_dbgstr_w(buffW));
10610
10611 len = strlen(xmluriA)-1;
10612 buffW[0] = 0x1;
10613 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml"), NULL, buffW, &len);
10614 EXPECT_HR(hr, E_XML_BUFFERTOOSMALL);
10615 ok(len == strlen(xmluriA)-1, "got %d\n", len);
10616 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10617
10618 /* prefix xml1 not defined */
10619 len = -1;
10620 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, NULL, &len);
10621 EXPECT_HR(hr, S_FALSE);
10622 ok(len == 0, "got %d\n", len);
10623
10624 len = 100;
10625 buffW[0] = 0x1;
10626 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_("xml1"), NULL, buffW, &len);
10627 EXPECT_HR(hr, S_FALSE);
10628 ok(buffW[0] == 0, "got %x\n", buffW[0]);
10629 ok(len == 0, "got %d\n", len);
10630
10631 /* IDispatchEx tests */
10632 hr = IMXNamespaceManager_QueryInterface(nsmgr, &IID_IUnknown, (void**)&unk);
10633 EXPECT_HR(hr, S_OK);
10634 test_domobj_dispex(unk);
10635 IUnknown_Release(unk);
10636
10637 IMXNamespaceManager_Release(nsmgr);
10638
10639 /* ::getPrefix() */
10640 hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10641 &IID_IMXNamespaceManager, (void**)&nsmgr);
10642 EXPECT_HR(hr, S_OK);
10643
10644 hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, NULL);
10645 EXPECT_HR(hr, E_INVALIDARG);
10646
10647 len = -1;
10648 hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, NULL, &len);
10649 EXPECT_HR(hr, E_INVALIDARG);
10650 ok(len == -1, "got %d\n", len);
10651
10652 len = 100;
10653 buffW[0] = 0x1;
10654 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10655 EXPECT_HR(hr, E_FAIL);
10656 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10657 ok(len == 100, "got %d\n", len);
10658
10659 len = 0;
10660 buffW[0] = 0x1;
10661 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 0, buffW, &len);
10662 EXPECT_HR(hr, E_FAIL);
10663 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10664 ok(len == 0, "got %d\n", len);
10665
10666 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10667 EXPECT_HR(hr, S_OK);
10668
10669 len = 100;
10670 buffW[0] = 0x1;
10671 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10672 EXPECT_HR(hr, S_OK);
10673 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10674 ok(len == 3, "got %d\n", len);
10675
10676 len = 100;
10677 buffW[0] = 0x1;
10678 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, buffW, &len);
10679 EXPECT_HR(hr, S_OK);
10680 ok(!lstrcmpW(buffW, _bstr_("xml")), "got %s\n", wine_dbgstr_w(buffW));
10681 ok(len == 3, "got %d\n", len);
10682
10683 /* with null buffer it's possible to get required length */
10684 len = 100;
10685 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10686 EXPECT_HR(hr, S_OK);
10687 ok(len == 3, "got %d\n", len);
10688
10689 len = 0;
10690 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("http://www.w3.org/XML/1998/namespace"), 0, NULL, &len);
10691 EXPECT_HR(hr, S_OK);
10692 ok(len == 3, "got %d\n", len);
10693
10694 len = 100;
10695 buffW[0] = 0x1;
10696 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 1, buffW, &len);
10697 EXPECT_HR(hr, E_FAIL);
10698 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10699 ok(len == 100, "got %d\n", len);
10700
10701 len = 100;
10702 buffW[0] = 0x1;
10703 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 2, buffW, &len);
10704 EXPECT_HR(hr, E_FAIL);
10705 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10706 ok(len == 100, "got %d\n", len);
10707
10708 len = 100;
10709 buffW[0] = 0x1;
10710 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 0, buffW, &len);
10711 EXPECT_HR(hr, E_INVALIDARG);
10712 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10713 ok(len == 100, "got %d\n", len);
10714
10715 len = 100;
10716 buffW[0] = 0x1;
10717 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10718 EXPECT_HR(hr, E_INVALIDARG);
10719 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10720 ok(len == 100, "got %d\n", len);
10721
10722 len = 100;
10723 buffW[0] = 0x1;
10724 hr = IMXNamespaceManager_getPrefix(nsmgr, NULL, 0, buffW, &len);
10725 EXPECT_HR(hr, E_INVALIDARG);
10726 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10727 ok(len == 100, "got %d\n", len);
10728
10729 len = 100;
10730 buffW[0] = 0x1;
10731 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns0 uri"), 1, buffW, &len);
10732 EXPECT_HR(hr, E_FAIL);
10733 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10734 ok(len == 100, "got %d\n", len);
10735
10736 len = 100;
10737 buffW[0] = 0x1;
10738 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10739 EXPECT_HR(hr, E_INVALIDARG);
10740 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10741 ok(len == 100, "got %d\n", len);
10742
10743 /* declare another one, indices are shifted */
10744 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10745 EXPECT_HR(hr, S_OK);
10746
10747 len = 100;
10748 buffW[0] = 0x1;
10749 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10750 EXPECT_HR(hr, S_OK);
10751 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10752 ok(len == 3, "got %d\n", len);
10753
10754 len = 100;
10755 buffW[0] = 0x1;
10756 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10757 EXPECT_HR(hr, S_OK);
10758 ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10759 ok(len == 3, "got %d\n", len);
10760
10761 len = 100;
10762 buffW[0] = 0x1;
10763 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 1, buffW, &len);
10764 EXPECT_HR(hr, E_FAIL);
10765 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10766 ok(len == 100, "got %d\n", len);
10767
10768 len = 100;
10769 buffW[0] = 0x1;
10770 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_(""), 1, buffW, &len);
10771 EXPECT_HR(hr, E_INVALIDARG);
10772 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10773 ok(len == 100, "got %d\n", len);
10774
10775 IMXNamespaceManager_Release(nsmgr);
10776
10777 /* push/pop tests */
10778 hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10779 &IID_IMXNamespaceManager, (void**)&nsmgr);
10780 EXPECT_HR(hr, S_OK);
10781
10782 /* pop with empty stack */
10783 hr = IMXNamespaceManager_popContext(nsmgr);
10784 EXPECT_HR(hr, E_FAIL);
10785
10786 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10787 EXPECT_HR(hr, S_OK);
10788
10789 len = 100;
10790 buffW[0] = 0x1;
10791 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10792 EXPECT_HR(hr, S_OK);
10793 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10794 ok(len == 3, "got %d\n", len);
10795
10796 hr = IMXNamespaceManager_pushContext(nsmgr);
10797 EXPECT_HR(hr, S_OK);
10798
10799 len = 100;
10800 buffW[0] = 0x1;
10801 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10802 EXPECT_HR(hr, S_OK);
10803 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10804 ok(len == 3, "got %d\n", len);
10805
10806 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns2"), _bstr_("ns2 uri"));
10807 EXPECT_HR(hr, S_OK);
10808
10809 len = 100;
10810 buffW[0] = 0x1;
10811 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10812 EXPECT_HR(hr, S_OK);
10813 ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10814 ok(len == 3, "got %d\n", len);
10815
10816 hr = IMXNamespaceManager_pushContext(nsmgr);
10817 EXPECT_HR(hr, S_OK);
10818 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns3"), _bstr_("ns3 uri"));
10819 EXPECT_HR(hr, S_OK);
10820
10821 len = 100;
10822 buffW[0] = 0x1;
10823 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10824 EXPECT_HR(hr, S_OK);
10825 ok(!lstrcmpW(buffW, _bstr_("ns2")), "got %s\n", wine_dbgstr_w(buffW));
10826 ok(len == 3, "got %d\n", len);
10827
10828 len = 100;
10829 buffW[0] = 0x1;
10830 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10831 EXPECT_HR(hr, S_OK);
10832 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10833 ok(len == 3, "got %d\n", len);
10834
10835 hr = IMXNamespaceManager_popContext(nsmgr);
10836 EXPECT_HR(hr, S_OK);
10837
10838 hr = IMXNamespaceManager_popContext(nsmgr);
10839 EXPECT_HR(hr, S_OK);
10840
10841 len = 100;
10842 buffW[0] = 0x1;
10843 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns2 uri"), 0, buffW, &len);
10844 EXPECT_HR(hr, E_FAIL);
10845 ok(buffW[0] == 0x1, "got %x\n", buffW[0]);
10846 ok(len == 100, "got %d\n", len);
10847
10848 len = 100;
10849 buffW[0] = 0x1;
10850 hr = IMXNamespaceManager_getPrefix(nsmgr, _bstr_("ns1 uri"), 0, buffW, &len);
10851 EXPECT_HR(hr, S_OK);
10852 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got %s\n", wine_dbgstr_w(buffW));
10853 ok(len == 3, "got %d\n", len);
10854
10855 IMXNamespaceManager_Release(nsmgr);
10856
10857 free_bstrs();
10858 }
10859
10860 static void test_mxnamespacemanager_override(void)
10861 {
10862 IMXNamespaceManager *nsmgr;
10863 WCHAR buffW[250];
10864 VARIANT_BOOL b;
10865 HRESULT hr;
10866 INT len;
10867
10868 hr = CoCreateInstance(&CLSID_MXNamespaceManager40, NULL, CLSCTX_INPROC_SERVER,
10869 &IID_IMXNamespaceManager, (void**)&nsmgr);
10870 EXPECT_HR(hr, S_OK);
10871
10872 len = ARRAY_SIZE(buffW);
10873 buffW[0] = 0;
10874 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10875 EXPECT_HR(hr, S_OK);
10876 ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10877
10878 len = ARRAY_SIZE(buffW);
10879 buffW[0] = 0;
10880 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10881 EXPECT_HR(hr, E_FAIL);
10882
10883 hr = IMXNamespaceManager_getAllowOverride(nsmgr, NULL);
10884 EXPECT_HR(hr, E_POINTER);
10885
10886 b = VARIANT_FALSE;
10887 hr = IMXNamespaceManager_getAllowOverride(nsmgr, &b);
10888 EXPECT_HR(hr, S_OK);
10889 ok(b == VARIANT_TRUE, "got %d\n", b);
10890
10891 hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_FALSE);
10892 EXPECT_HR(hr, S_OK);
10893
10894 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10895 EXPECT_HR(hr, S_OK);
10896
10897 len = ARRAY_SIZE(buffW);
10898 buffW[0] = 0;
10899 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10900 EXPECT_HR(hr, S_OK);
10901 ok(!lstrcmpW(buffW, _bstr_("ns0 uri")), "got uri %s\n", wine_dbgstr_w(buffW));
10902
10903 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns0"), _bstr_("ns0 uri"));
10904 EXPECT_HR(hr, S_OK);
10905
10906 len = ARRAY_SIZE(buffW);
10907 buffW[0] = 0;
10908 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 0, buffW, &len);
10909 EXPECT_HR(hr, S_OK);
10910 ok(!lstrcmpW(buffW, _bstr_("xml")), "got prefix %s\n", wine_dbgstr_w(buffW));
10911
10912 len = ARRAY_SIZE(buffW);
10913 buffW[0] = 0;
10914 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10915 EXPECT_HR(hr, S_OK);
10916 ok(!lstrcmpW(buffW, _bstr_("ns0")), "got prefix %s\n", wine_dbgstr_w(buffW));
10917
10918 len = ARRAY_SIZE(buffW);
10919 buffW[0] = 0;
10920 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 2, buffW, &len);
10921 EXPECT_HR(hr, S_OK);
10922 ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10923
10924 /* new prefix placed at index 1 always */
10925 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_("ns1"), _bstr_("ns1 uri"));
10926 EXPECT_HR(hr, S_OK);
10927
10928 len = ARRAY_SIZE(buffW);
10929 buffW[0] = 0;
10930 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 1, buffW, &len);
10931 EXPECT_HR(hr, S_OK);
10932 ok(!lstrcmpW(buffW, _bstr_("ns1")), "got prefix %s\n", wine_dbgstr_w(buffW));
10933
10934 hr = IMXNamespaceManager_declarePrefix(nsmgr, _bstr_(""), NULL);
10935 todo_wine EXPECT_HR(hr, E_FAIL);
10936
10937 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, NULL);
10938 EXPECT_HR(hr, E_FAIL);
10939
10940 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri"));
10941 EXPECT_HR(hr, E_FAIL);
10942
10943 hr = IMXNamespaceManager_putAllowOverride(nsmgr, VARIANT_TRUE);
10944 EXPECT_HR(hr, S_OK);
10945
10946 hr = IMXNamespaceManager_declarePrefix(nsmgr, NULL, _bstr_("ns0 uri override"));
10947 EXPECT_HR(hr, S_FALSE);
10948
10949 len = ARRAY_SIZE(buffW);
10950 buffW[0] = 0;
10951 hr = IMXNamespaceManager_getURI(nsmgr, _bstr_(""), NULL, buffW, &len);
10952 EXPECT_HR(hr, S_OK);
10953 ok(!lstrcmpW(buffW, _bstr_("ns0 uri override")), "got uri %s\n", wine_dbgstr_w(buffW));
10954
10955 len = ARRAY_SIZE(buffW);
10956 buffW[0] = 0;
10957 hr = IMXNamespaceManager_getDeclaredPrefix(nsmgr, 3, buffW, &len);
10958 EXPECT_HR(hr, S_OK);
10959 ok(!lstrcmpW(buffW, _bstr_("")), "got prefix %s\n", wine_dbgstr_w(buffW));
10960
10961 IMXNamespaceManager_Release(nsmgr);
10962
10963 free_bstrs();
10964 }
10965
10966 static const DOMNodeType nodetypes_test[] =
10967 {
10968 NODE_ELEMENT,
10969 NODE_ATTRIBUTE,
10970 NODE_TEXT,
10971 NODE_CDATA_SECTION,
10972 NODE_ENTITY_REFERENCE,
10973 NODE_PROCESSING_INSTRUCTION,
10974 NODE_COMMENT,
10975 NODE_DOCUMENT_FRAGMENT,
10976 NODE_INVALID
10977 };
10978
10979 static void test_dispex(void)
10980 {
10981 const DOMNodeType *type = nodetypes_test;
10982 IXMLDOMImplementation *impl;
10983 IXMLDOMNodeList *node_list;
10984 IXMLDOMParseError *error;
10985 IXMLDOMNamedNodeMap *map;
10986 IXSLProcessor *processor;
10987 IXSLTemplate *template;
10988 IXMLDOMDocument *doc;
10989 IXMLHTTPRequest *req;
10990 IXMLDOMElement *elem;
10991 IDispatchEx *dispex;
10992 DISPPARAMS dispparams;
10993 IXMLDOMNode *node;
10994 VARIANT arg, ret;
10995 VARIANT_BOOL b;
10996 IUnknown *unk;
10997 HRESULT hr;
10998 DISPID did;
10999
11000 doc = create_document(&IID_IXMLDOMDocument);
11001
11002 hr = IXMLDOMDocument_QueryInterface(doc, &IID_IUnknown, (void**)&unk);
11003 ok(hr == S_OK, "got 0x%08x\n", hr);
11004 test_domobj_dispex(unk);
11005 IUnknown_Release(unk);
11006
11007 for(; *type != NODE_INVALID; type++)
11008 {
11009 IXMLDOMNode *node;
11010 VARIANT v;
11011
11012 V_VT(&v) = VT_I2;
11013 V_I2(&v) = *type;
11014
11015 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
11016 ok(hr == S_OK, "failed to create node type %d\n", *type);
11017
11018 IXMLDOMNode_QueryInterface(node, &IID_IUnknown, (void**)&unk);
11019
11020 test_domobj_dispex(unk);
11021 IUnknown_Release(unk);
11022 IXMLDOMNode_Release(node);
11023 }
11024
11025 /* IXMLDOMNodeList */
11026 hr = IXMLDOMDocument_getElementsByTagName(doc, _bstr_("*"), &node_list);
11027 EXPECT_HR(hr, S_OK);
11028 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
11029 ok(hr == S_OK, "got 0x%08x\n", hr);
11030 test_domobj_dispex(unk);
11031 IUnknown_Release(unk);
11032 IXMLDOMNodeList_Release(node_list);
11033
11034 /* IXMLDOMNodeList for children list */
11035 hr = IXMLDOMDocument_get_childNodes(doc, &node_list);
11036 EXPECT_HR(hr, S_OK);
11037 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IUnknown, (void**)&unk);
11038 ok(hr == S_OK, "got 0x%08x\n", hr);
11039 test_domobj_dispex(unk);
11040 IUnknown_Release(unk);
11041
11042 /* collection dispex test, empty collection */
11043 hr = IXMLDOMNodeList_QueryInterface(node_list, &IID_IDispatchEx, (void**)&dispex);
11044 EXPECT_HR(hr, S_OK);
11045 did = 0;
11046 hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11047 EXPECT_HR(hr, S_OK);
11048 ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11049 hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
11050 EXPECT_HR(hr, S_OK);
11051 ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
11052 IDispatchEx_Release(dispex);
11053
11054 did = -1;
11055 hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11056 ok(hr == S_OK, "got 0x%08x\n", hr);
11057 ok(did == DISPID_VALUE, "got %d\n", did);
11058
11059 V_VT(&arg) = VT_I4;
11060 V_I4(&arg) = 0;
11061 dispparams.cArgs = 0;
11062 dispparams.cNamedArgs = 0;
11063 dispparams.rgdispidNamedArgs = NULL;
11064 dispparams.rgvarg = &arg;
11065
11066 V_VT(&ret) = VT_EMPTY;
11067 V_DISPATCH(&ret) = (void*)0x1;
11068 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11069 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11070 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11071 todo_wine
11072 ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11073
11074 V_VT(&arg) = VT_I4;
11075 V_I4(&arg) = 0;
11076 dispparams.cArgs = 2;
11077 dispparams.cNamedArgs = 0;
11078 dispparams.rgdispidNamedArgs = NULL;
11079 dispparams.rgvarg = &arg;
11080
11081 V_VT(&ret) = VT_EMPTY;
11082 V_DISPATCH(&ret) = (void*)0x1;
11083 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11084 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11085 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11086 todo_wine
11087 ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11088
11089 V_VT(&arg) = VT_I4;
11090 V_I4(&arg) = 0;
11091 dispparams.cArgs = 1;
11092 dispparams.cNamedArgs = 0;
11093 dispparams.rgdispidNamedArgs = NULL;
11094 dispparams.rgvarg = &arg;
11095
11096 V_VT(&ret) = VT_EMPTY;
11097 V_DISPATCH(&ret) = (void*)0x1;
11098 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11099 ok(hr == S_OK, "got 0x%08x\n", hr);
11100 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11101 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11102
11103 V_VT(&ret) = VT_EMPTY;
11104 V_DISPATCH(&ret) = (void*)0x1;
11105 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11106 ok(hr == S_OK, "got 0x%08x\n", hr);
11107 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11108 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11109
11110 V_VT(&ret) = VT_EMPTY;
11111 V_DISPATCH(&ret) = (void*)0x1;
11112 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11113 ok(hr == S_OK, "got 0x%08x\n", hr);
11114 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11115 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11116
11117 dispparams.cArgs = 0;
11118 dispparams.cNamedArgs = 0;
11119 dispparams.rgdispidNamedArgs = NULL;
11120 dispparams.rgvarg = NULL;
11121
11122 V_VT(&ret) = VT_EMPTY;
11123 V_I4(&ret) = 1;
11124 hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11125 ok(hr == S_OK, "got 0x%08x\n", hr);
11126 ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11127 ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11128
11129 dispparams.cArgs = 0;
11130 dispparams.cNamedArgs = 0;
11131 dispparams.rgdispidNamedArgs = NULL;
11132 dispparams.rgvarg = NULL;
11133
11134 V_VT(&ret) = VT_EMPTY;
11135 V_I4(&ret) = 1;
11136 hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11137 ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11138 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11139 todo_wine
11140 ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11141
11142 IXMLDOMNodeList_Release(node_list);
11143
11144 /* IXMLDOMParseError */
11145 hr = IXMLDOMDocument_get_parseError(doc, &error);
11146 EXPECT_HR(hr, S_OK);
11147 IXMLDOMParseError_QueryInterface(error, &IID_IUnknown, (void**)&unk);
11148 test_domobj_dispex(unk);
11149
11150 hr = IXMLDOMParseError_QueryInterface(error, &IID_IDispatchEx, (void**)&dispex);
11151 ok(hr == S_OK, "got 0x%08x\n", hr);
11152
11153 V_VT(&arg) = VT_I4;
11154 V_I4(&arg) = 0;
11155 dispparams.cArgs = 1;
11156 dispparams.cNamedArgs = 0;
11157 dispparams.rgdispidNamedArgs = NULL;
11158 dispparams.rgvarg = &arg;
11159
11160 V_VT(&ret) = VT_EMPTY;
11161 V_DISPATCH(&ret) = (void*)0x1;
11162 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11163 ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11164 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11165 todo_wine
11166 ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11167
11168 IDispatchEx_Release(dispex);
11169
11170 IUnknown_Release(unk);
11171 IXMLDOMParseError_Release(error);
11172
11173 /* IXMLDOMNamedNodeMap */
11174 hr = IXMLDOMDocument_loadXML(doc, _bstr_(xpath_simple_list), &b);
11175 EXPECT_HR(hr, S_OK);
11176
11177 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/a"), &node_list);
11178 EXPECT_HR(hr, S_OK);
11179 hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11180 EXPECT_HR(hr, S_OK);
11181 IXMLDOMNodeList_Release(node_list);
11182
11183 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11184 EXPECT_HR(hr, S_OK);
11185 IXMLDOMNode_Release(node);
11186 hr = IXMLDOMElement_get_attributes(elem, &map);
11187 EXPECT_HR(hr, S_OK);
11188 IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk);
11189 test_domobj_dispex(unk);
11190 IUnknown_Release(unk);
11191 /* collection dispex test */
11192 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11193 EXPECT_HR(hr, S_OK);
11194 did = 0;
11195 hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11196 EXPECT_HR(hr, S_OK);
11197 ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11198 IDispatchEx_Release(dispex);
11199 IXMLDOMNamedNodeMap_Release(map);
11200
11201 hr = IXMLDOMDocument_selectNodes(doc, _bstr_("root/b"), &node_list);
11202 EXPECT_HR(hr, S_OK);
11203 hr = IXMLDOMNodeList_get_item(node_list, 0, &node);
11204 EXPECT_HR(hr, S_OK);
11205 IXMLDOMNodeList_Release(node_list);
11206 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMElement, (void**)&elem);
11207 EXPECT_HR(hr, S_OK);
11208 IXMLDOMNode_Release(node);
11209 hr = IXMLDOMElement_get_attributes(elem, &map);
11210 EXPECT_HR(hr, S_OK);
11211 /* collection dispex test, empty collection */
11212 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IDispatchEx, (void**)&dispex);
11213 EXPECT_HR(hr, S_OK);
11214 did = 0;
11215 hr = IDispatchEx_GetDispID(dispex, _bstr_("0"), 0, &did);
11216 EXPECT_HR(hr, S_OK);
11217 ok(did == DISPID_DOM_COLLECTION_BASE, "got 0x%08x\n", did);
11218 hr = IDispatchEx_GetDispID(dispex, _bstr_("1"), 0, &did);
11219 EXPECT_HR(hr, S_OK);
11220 ok(did == DISPID_DOM_COLLECTION_BASE+1, "got 0x%08x\n", did);
11221 IXMLDOMNamedNodeMap_Release(map);
11222
11223 did = -1;
11224 hr = IDispatchEx_GetDispID(dispex, _bstr_("item"), 0, &did);
11225 ok(hr == S_OK, "got 0x%08x\n", hr);
11226 ok(did == DISPID_VALUE, "got %d\n", did);
11227
11228 V_VT(&arg) = VT_I4;
11229 V_I4(&arg) = 0;
11230 dispparams.cArgs = 0;
11231 dispparams.cNamedArgs = 0;
11232 dispparams.rgdispidNamedArgs = NULL;
11233 dispparams.rgvarg = &arg;
11234
11235 V_VT(&ret) = VT_EMPTY;
11236 V_DISPATCH(&ret) = (void*)0x1;
11237 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11238 todo_wine {
11239 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11240 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11241 }
11242 ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11243
11244 V_VT(&arg) = VT_I4;
11245 V_I4(&arg) = 0;
11246 dispparams.cArgs = 2;
11247 dispparams.cNamedArgs = 0;
11248 dispparams.rgdispidNamedArgs = NULL;
11249 dispparams.rgvarg = &arg;
11250
11251 V_VT(&ret) = VT_EMPTY;
11252 V_DISPATCH(&ret) = (void*)0x1;
11253 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11254 todo_wine {
11255 ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
11256 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11257 }
11258 ok(broken(V_DISPATCH(&ret) == (void*)0x1) || (V_DISPATCH(&ret) == NULL), "got %p\n", V_DISPATCH(&ret));
11259
11260 V_VT(&arg) = VT_I4;
11261 V_I4(&arg) = 0;
11262 dispparams.cArgs = 1;
11263 dispparams.cNamedArgs = 0;
11264 dispparams.rgdispidNamedArgs = NULL;
11265 dispparams.rgvarg = &arg;
11266
11267 V_VT(&ret) = VT_EMPTY;
11268 V_DISPATCH(&ret) = (void*)0x1;
11269 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11270 todo_wine
11271 ok(hr == S_OK, "got 0x%08x\n", hr);
11272 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11273 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11274
11275 V_VT(&ret) = VT_EMPTY;
11276 V_DISPATCH(&ret) = (void*)0x1;
11277 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11278 ok(hr == S_OK, "got 0x%08x\n", hr);
11279 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11280 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11281
11282 V_VT(&ret) = VT_EMPTY;
11283 V_DISPATCH(&ret) = (void*)0x1;
11284 hr = IDispatchEx_Invoke(dispex, DISPID_VALUE, &IID_NULL, 0, DISPATCH_PROPERTYGET|DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11285 ok(hr == S_OK, "got 0x%08x\n", hr);
11286 ok(V_VT(&ret) == VT_DISPATCH, "got %d\n", V_VT(&ret));
11287 ok(V_DISPATCH(&ret) == NULL, "got %p\n", V_DISPATCH(&ret));
11288
11289 dispparams.cArgs = 0;
11290 dispparams.cNamedArgs = 0;
11291 dispparams.rgdispidNamedArgs = NULL;
11292 dispparams.rgvarg = NULL;
11293
11294 V_VT(&ret) = VT_EMPTY;
11295 V_I4(&ret) = 1;
11296 hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &ret, NULL, NULL);
11297 ok(hr == S_OK, "got 0x%08x\n", hr);
11298 ok(V_VT(&ret) == VT_I4, "got %d\n", V_VT(&ret));
11299 ok(V_I4(&ret) == 0, "got %d\n", V_I4(&ret));
11300
11301 dispparams.cArgs = 0;
11302 dispparams.cNamedArgs = 0;
11303 dispparams.rgdispidNamedArgs = NULL;
11304 dispparams.rgvarg = NULL;
11305
11306 V_VT(&ret) = VT_EMPTY;
11307 V_I4(&ret) = 1;
11308 hr = IDispatchEx_Invoke(dispex, DISPID_DOM_NODELIST_LENGTH, &IID_NULL, 0, DISPATCH_METHOD, &dispparams, &ret, NULL, NULL);
11309 ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x\n", hr);
11310 todo_wine
11311 ok(V_VT(&ret) == VT_EMPTY, "got %d\n", V_VT(&ret));
11312 ok(broken(V_I4(&ret) == 1) || (V_I4(&ret) == 0), "got %d\n", V_I4(&ret));
11313
11314 IDispatchEx_Release(dispex);
11315 IXMLDOMElement_Release(elem);
11316
11317 /* IXMLDOMImplementation */
11318 hr = IXMLDOMDocument_get_implementation(doc, &impl);
11319 EXPECT_HR(hr, S_OK);
11320
11321 hr = IXMLDOMImplementation_QueryInterface(impl, &IID_IDispatchEx, (void**)&dispex);
11322 EXPECT_HR(hr, S_OK);
11323 IDispatchEx_Release(dispex);
11324 IXMLDOMImplementation_Release(impl);
11325
11326 IXMLDOMDocument_Release(doc);
11327
11328 /* IXMLHTTPRequest */
11329 hr = CoCreateInstance(&CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER,
11330 &IID_IXMLHttpRequest, (void**)&req);
11331 if (hr == S_OK)
11332 {
11333 hr = IXMLHTTPRequest_QueryInterface(req, &IID_IDispatchEx, (void**)&dispex);
11334 EXPECT_HR(hr, E_NOINTERFACE);
11335 IXMLHTTPRequest_Release(req);
11336 }
11337
11338 /* IXSLTemplate */
11339 template = create_xsltemplate(&IID_IXSLTemplate);
11340 hr = IXSLTemplate_QueryInterface(template, &IID_IDispatchEx, (void**)&dispex);
11341 EXPECT_HR(hr, S_OK);
11342 hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11343 EXPECT_HR(hr, S_OK);
11344 test_domobj_dispex(unk);
11345 IUnknown_Release(unk);
11346 IDispatchEx_Release(dispex);
11347
11348 /* IXSLProcessor */
11349 hr = CoCreateInstance(&CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
11350 EXPECT_HR(hr, S_OK);
11351 b = VARIANT_FALSE;
11352 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformSSXML), &b);
11353 EXPECT_HR(hr, S_OK);
11354 ok(b == VARIANT_TRUE, "got %d\n", b);
11355
11356 hr = IXSLTemplate_putref_stylesheet(template, (IXMLDOMNode*)doc);
11357 EXPECT_HR(hr, S_OK);
11358 IXMLDOMDocument_Release(doc);
11359
11360 hr = IXSLTemplate_createProcessor(template, &processor);
11361 EXPECT_HR(hr, S_OK);
11362 hr = IXSLProcessor_QueryInterface(processor, &IID_IDispatchEx, (void**)&dispex);
11363 EXPECT_HR(hr, S_OK);
11364 hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk);
11365 EXPECT_HR(hr, S_OK);
11366 test_domobj_dispex(unk);
11367 IUnknown_Release(unk);
11368 IDispatchEx_Release(dispex);
11369
11370 IXSLProcessor_Release(processor);
11371 IXSLTemplate_Release(template);
11372
11373 if (is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument))
11374 {
11375 doc = create_document_version(60, &IID_IXMLDOMDocument);
11376 test_domobj_dispex((IUnknown*)doc);
11377 IXMLDOMDocument_Release(doc);
11378 }
11379
11380 free_bstrs();
11381 }
11382
11383 static void test_parseerror(void)
11384 {
11385 IXMLDOMParseError2 *error2;
11386 IXMLDOMParseError *error;
11387 IXMLDOMDocument *doc;
11388 HRESULT hr;
11389
11390 doc = create_document(&IID_IXMLDOMDocument);
11391
11392 hr = IXMLDOMDocument_get_parseError(doc, &error);
11393 EXPECT_HR(hr, S_OK);
11394
11395 hr = IXMLDOMParseError_get_line(error, NULL);
11396 EXPECT_HR(hr, E_INVALIDARG);
11397
11398 hr = IXMLDOMParseError_get_srcText(error, NULL);
11399 EXPECT_HR(hr, E_INVALIDARG);
11400
11401 hr = IXMLDOMParseError_get_linepos(error, NULL);
11402 EXPECT_HR(hr, E_INVALIDARG);
11403
11404 IXMLDOMParseError_Release(error);
11405 IXMLDOMDocument_Release(doc);
11406
11407 if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument)) return;
11408 doc = create_document_version(60, &IID_IXMLDOMDocument);
11409
11410 hr = IXMLDOMDocument_get_parseError(doc, &error);
11411 EXPECT_HR(hr, S_OK);
11412 hr = IXMLDOMParseError_QueryInterface(error, &IID_IXMLDOMParseError2, (void**)&error2);
11413 EXPECT_HR(hr, S_OK);
11414 IXMLDOMParseError2_Release(error2);
11415 IXMLDOMParseError_Release(error);
11416 IXMLDOMDocument_Release(doc);
11417 }
11418
11419 static void test_getAttributeNode(void)
11420 {
11421 IXMLDOMAttribute *attr;
11422 IXMLDOMDocument *doc;
11423 IXMLDOMElement *elem;
11424 VARIANT_BOOL v;
11425 HRESULT hr;
11426 BSTR str;
11427
11428 doc = create_document(&IID_IXMLDOMDocument);
11429
11430 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11431 EXPECT_HR(hr, S_OK);
11432
11433 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11434 EXPECT_HR(hr, S_OK);
11435
11436 str = SysAllocString(nonexistent_fileW);
11437 hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11438 EXPECT_HR(hr, E_FAIL);
11439
11440 attr = (IXMLDOMAttribute*)0xdeadbeef;
11441 hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11442 EXPECT_HR(hr, E_FAIL);
11443 ok(attr == NULL, "got %p\n", attr);
11444 SysFreeString(str);
11445
11446 str = SysAllocString(nonexistent_attrW);
11447 hr = IXMLDOMElement_getAttributeNode(elem, str, NULL);
11448 EXPECT_HR(hr, S_FALSE);
11449
11450 attr = (IXMLDOMAttribute*)0xdeadbeef;
11451 hr = IXMLDOMElement_getAttributeNode(elem, str, &attr);
11452 EXPECT_HR(hr, S_FALSE);
11453 ok(attr == NULL, "got %p\n", attr);
11454 SysFreeString(str);
11455
11456 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("foo:b"), &attr);
11457 EXPECT_HR(hr, S_OK);
11458 IXMLDOMAttribute_Release(attr);
11459
11460 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("b"), &attr);
11461 EXPECT_HR(hr, S_FALSE);
11462
11463 hr = IXMLDOMElement_getAttributeNode(elem, _bstr_("a"), &attr);
11464 EXPECT_HR(hr, S_OK);
11465 IXMLDOMAttribute_Release(attr);
11466
11467 IXMLDOMElement_Release(elem);
11468 IXMLDOMDocument_Release(doc);
11469 free_bstrs();
11470 }
11471
11472 static void test_getAttribute(void)
11473 {
11474 IXMLDOMDocument *doc;
11475 IXMLDOMElement *elem;
11476 VARIANT_BOOL v;
11477 VARIANT var;
11478 HRESULT hr;
11479
11480 doc = create_document(&IID_IXMLDOMDocument);
11481
11482 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szExampleXML), &v);
11483 EXPECT_HR(hr, S_OK);
11484
11485 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11486 EXPECT_HR(hr, S_OK);
11487
11488 VariantInit(&var);
11489 hr = IXMLDOMElement_getAttribute( elem, _bstr_("xmlns:foo"), &var );
11490 EXPECT_HR(hr, S_OK);
11491 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11492 ok( !lstrcmpW(V_BSTR(&var), _bstr_("urn:uuid:86B2F87F-ACB6-45cd-8B77-9BDB92A01A29")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11493 VariantClear(&var);
11494
11495 hr = IXMLDOMElement_getAttribute( elem, _bstr_("a"), &var );
11496 EXPECT_HR(hr, S_OK);
11497 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11498 ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr a")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11499 VariantClear(&var);
11500
11501 hr = IXMLDOMElement_getAttribute( elem, _bstr_("foo:b"), &var );
11502 EXPECT_HR(hr, S_OK);
11503 ok( V_VT(&var) == VT_BSTR, "vt = %x\n", V_VT(&var));
11504 ok( !lstrcmpW(V_BSTR(&var), _bstr_("attr b")), "wrong attr value: %s\n", wine_dbgstr_w(V_BSTR(&var)));
11505 VariantClear(&var);
11506
11507 hr = IXMLDOMElement_getAttribute( elem, _bstr_("b"), &var );
11508 EXPECT_HR(hr, S_FALSE);
11509 ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11510 VariantClear(&var);
11511
11512 hr = IXMLDOMElement_getAttribute( elem, _bstr_("non-existent"), &var );
11513 EXPECT_HR(hr, S_FALSE);
11514 ok( V_VT(&var) == VT_NULL, "vt = %x\n", V_VT(&var));
11515 VariantClear(&var);
11516
11517 IXMLDOMElement_Release(elem);
11518 IXMLDOMDocument_Release(doc);
11519 free_bstrs();
11520 }
11521
11522 typedef struct {
11523 DOMNodeType type;
11524 const char *name;
11525 REFIID iids[3];
11526 } supporterror_t;
11527
11528 static const supporterror_t supporterror_test[] = {
11529 { NODE_ELEMENT, "element", { &IID_IXMLDOMNode, &IID_IXMLDOMElement } },
11530 { NODE_ATTRIBUTE, "attribute", { &IID_IXMLDOMNode, &IID_IXMLDOMAttribute } },
11531 { NODE_CDATA_SECTION, "cdata", { &IID_IXMLDOMNode, &IID_IXMLDOMCDATASection } },
11532 { NODE_ENTITY_REFERENCE, "entityref", { &IID_IXMLDOMNode, &IID_IXMLDOMEntityReference } },
11533 { NODE_PROCESSING_INSTRUCTION, "pi", { &IID_IXMLDOMNode, &IID_IXMLDOMProcessingInstruction } },
11534 { NODE_COMMENT, "comment", { &IID_IXMLDOMNode, &IID_IXMLDOMComment } },
11535 { NODE_DOCUMENT_FRAGMENT, "fragment", { &IID_IXMLDOMNode, &IID_IXMLDOMDocumentFragment } },
11536 { NODE_INVALID }
11537 };
11538
11539 static void test_supporterrorinfo(void)
11540 {
11541 static REFIID iids[5] = { &IID_IXMLDOMNode, &IID_IXMLDOMDocument,
11542 &IID_IXMLDOMDocument2, &IID_IXMLDOMDocument3 };
11543 const supporterror_t *ptr = supporterror_test;
11544 ISupportErrorInfo *errorinfo, *info2;
11545 IXMLDOMSchemaCollection *schemacache;
11546 IXMLDOMNamedNodeMap *map, *map2;
11547 IXMLDOMDocument *doc;
11548 IXMLDOMElement *elem;
11549 VARIANT_BOOL b;
11550 IUnknown *unk;
11551 REFIID *iid;
11552 void *dummy;
11553 HRESULT hr;
11554
11555 if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument3)) return;
11556 doc = create_document_version(60, &IID_IXMLDOMDocument3);
11557
11558 EXPECT_REF(doc, 1);
11559 hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&errorinfo);
11560 EXPECT_HR(hr, S_OK);
11561 EXPECT_REF(doc, 1);
11562 ISupportErrorInfo_AddRef(errorinfo);
11563 EXPECT_REF(errorinfo, 2);
11564 EXPECT_REF(doc, 1);
11565 ISupportErrorInfo_Release(errorinfo);
11566
11567 hr = IXMLDOMDocument_QueryInterface(doc, &IID_ISupportErrorInfo, (void**)&info2);
11568 EXPECT_HR(hr, S_OK);
11569 ok(errorinfo != info2, "got %p, %p\n", info2, errorinfo);
11570
11571 /* error interface can't be queried back for DOM interface */
11572 hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMDocument, &dummy);
11573 EXPECT_HR(hr, E_NOINTERFACE);
11574 hr = ISupportErrorInfo_QueryInterface(info2, &IID_IXMLDOMNode, &dummy);
11575 EXPECT_HR(hr, E_NOINTERFACE);
11576
11577 ISupportErrorInfo_Release(info2);
11578
11579 iid = iids;
11580 while (*iid)
11581 {
11582 hr = IXMLDOMDocument_QueryInterface(doc, *iid, (void**)&unk);
11583 EXPECT_HR(hr, S_OK);
11584 if (hr == S_OK)
11585 {
11586 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11587 ok(hr == S_OK, "got 0x%08x for %s\n", hr, wine_dbgstr_guid(*iid));
11588 IUnknown_Release(unk);
11589 }
11590
11591 iid++;
11592 }
11593
11594 ISupportErrorInfo_Release(errorinfo);
11595
11596 while (ptr->type != NODE_INVALID)
11597 {
11598 IXMLDOMNode *node;
11599 VARIANT type;
11600
11601 V_VT(&type) = VT_I1;
11602 V_I1(&type) = ptr->type;
11603
11604 hr = IXMLDOMDocument_createNode(doc, type, _bstr_(ptr->name), NULL, &node);
11605 ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11606
11607 EXPECT_REF(node, 1);
11608 hr = IXMLDOMNode_QueryInterface(node, &IID_ISupportErrorInfo, (void**)&errorinfo);
11609 ok(hr == S_OK, "%d: got 0x%08x\n", ptr->type, hr);
11610 EXPECT_REF(node, 1);
11611
11612 hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNode, &dummy);
11613 ok(hr == E_NOINTERFACE, "%d: got 0x%08x\n", ptr->type, hr);
11614
11615 iid = ptr->iids;
11616
11617 while (*iid)
11618 {
11619 hr = IXMLDOMNode_QueryInterface(node, *iid, (void**)&unk);
11620 if (hr == S_OK)
11621 {
11622 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, *iid);
11623 ok(hr == S_OK, "%d: got 0x%08x for %s\n", ptr->type, hr, wine_dbgstr_guid(*iid));
11624 IUnknown_Release(unk);
11625 }
11626
11627 iid++;
11628 }
11629
11630 ISupportErrorInfo_Release(errorinfo);
11631 IXMLDOMNode_Release(node);
11632 ptr++;
11633 }
11634
11635 /* IXMLDOMNamedNodeMap */
11636 b = VARIANT_FALSE;
11637 hr = IXMLDOMDocument_loadXML(doc, _bstr_(complete4A), &b);
11638 EXPECT_HR(hr, S_OK);
11639 ok(b == VARIANT_TRUE, "got %d\n", b);
11640
11641 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11642 EXPECT_HR(hr, S_OK);
11643
11644 hr = IXMLDOMElement_get_attributes(elem, &map);
11645 EXPECT_HR(hr, S_OK);
11646
11647 EXPECT_REF(map, 1);
11648 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_ISupportErrorInfo, (void**)&errorinfo);
11649 EXPECT_HR(hr, S_OK);
11650 EXPECT_REF(map, 2);
11651
11652 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMNamedNodeMap);
11653 EXPECT_HR(hr, S_OK);
11654
11655 hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IXMLDOMNamedNodeMap, (void**)&map2);
11656 EXPECT_HR(hr, S_OK);
11657 ok(map == map2, "got %p\n", map2);
11658 IXMLDOMNamedNodeMap_Release(map2);
11659
11660 EXPECT_REF(errorinfo, 2);
11661 hr = ISupportErrorInfo_QueryInterface(errorinfo, &IID_IUnknown, (void**)&unk);
11662 EXPECT_HR(hr, S_OK);
11663 EXPECT_REF(errorinfo, 3);
11664 EXPECT_REF(map, 3);
11665 IUnknown_Release(unk);
11666
11667 ISupportErrorInfo_Release(errorinfo);
11668 IXMLDOMNamedNodeMap_Release(map);
11669 IXMLDOMElement_Release(elem);
11670
11671 IXMLDOMDocument_Release(doc);
11672
11673 /* IXMLDOMSchemaCollection */
11674 hr = CoCreateInstance(&CLSID_XMLSchemaCache, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMSchemaCollection, (void**)&schemacache);
11675 ok(hr == S_OK, "failed to create schema collection, 0x%08x\n", hr);
11676
11677 hr = IXMLDOMSchemaCollection_QueryInterface(schemacache, &IID_ISupportErrorInfo, (void**)&errorinfo);
11678 ok(hr == S_OK, "got 0x%08x\n", hr);
11679
11680 hr = ISupportErrorInfo_InterfaceSupportsErrorInfo(errorinfo, &IID_IXMLDOMSchemaCollection);
11681 ok(hr == S_OK, "got 0x%08x\n", hr);
11682
11683 ISupportErrorInfo_Release(errorinfo);
11684 IXMLDOMSchemaCollection_Release(schemacache);
11685
11686 free_bstrs();
11687 }
11688
11689 typedef struct {
11690 DOMNodeType type;
11691 const char *name;
11692 const char *put_content;
11693 HRESULT put_hr;
11694 VARTYPE get_vt;
11695 HRESULT get_hr;
11696 } node_value_t;
11697
11698 static const node_value_t nodevalue_test[] = {
11699 { NODE_ELEMENT, "element", "", E_FAIL, VT_NULL, S_FALSE },
11700 { NODE_ATTRIBUTE, "attr", "value", S_OK, VT_BSTR, S_OK },
11701 { NODE_TEXT, "text", "textdata", S_OK, VT_BSTR, S_OK },
11702 { NODE_CDATA_SECTION , "cdata", "cdata data", S_OK, VT_BSTR, S_OK },
11703 { NODE_ENTITY_REFERENCE, "entityref", "ref", E_FAIL, VT_NULL, S_FALSE },
11704 { NODE_PROCESSING_INSTRUCTION, "pi", "instr", S_OK, VT_BSTR, S_OK },
11705 { NODE_COMMENT, "comment", "comment data", S_OK, VT_BSTR, S_OK },
11706 { NODE_DOCUMENT_FRAGMENT, "docfrag", "", E_FAIL, VT_NULL, S_FALSE },
11707 { NODE_INVALID }
11708 };
11709
11710 static void test_nodeValue(void)
11711 {
11712 const node_value_t *ptr = nodevalue_test;
11713 IXMLDOMDocument *doc;
11714 HRESULT hr;
11715
11716 doc = create_document(&IID_IXMLDOMDocument);
11717
11718 while (ptr->type != NODE_INVALID)
11719 {
11720 IXMLDOMNode *node;
11721 VARIANT v;
11722
11723 V_VT(&v) = VT_I2;
11724 V_I2(&v) = ptr->type;
11725
11726 hr = IXMLDOMDocument_createNode(doc, v, _bstr_(ptr->name), NULL, &node);
11727 ok(hr == S_OK, "failed to create node type %d\n", ptr->type);
11728
11729 hr = IXMLDOMNode_get_nodeValue(node, NULL);
11730 ok(hr == E_INVALIDARG, "%d: got 0x%08x\n", ptr->type, hr);
11731
11732 V_VT(&v) = VT_BSTR;
11733 V_BSTR(&v) = _bstr_(ptr->put_content);
11734 hr = IXMLDOMNode_put_nodeValue(node, v);
11735 ok(hr == ptr->put_hr, "%d: got 0x%08x\n", ptr->type, hr);
11736
11737 V_VT(&v) = VT_EMPTY;
11738 hr = IXMLDOMNode_get_nodeValue(node, &v);
11739 ok(hr == ptr->get_hr, "%d: got 0x%08x, expected 0x%08x\n", ptr->type, hr, ptr->get_hr);
11740 ok(V_VT(&v) == ptr->get_vt, "%d: got %d, expected %d\n", ptr->type, V_VT(&v), ptr->get_vt);
11741 if (hr == S_OK)
11742 ok(!lstrcmpW(V_BSTR(&v), _bstr_(ptr->put_content)), "%d: got %s\n", ptr->type,
11743 wine_dbgstr_w(V_BSTR(&v)));
11744 VariantClear(&v);
11745
11746 IXMLDOMNode_Release(node);
11747
11748 ptr++;
11749 }
11750
11751 IXMLDOMDocument_Release(doc);
11752 }
11753
11754 static void test_xmlns_attribute(void)
11755 {
11756 BSTR str;
11757 IXMLDOMDocument *doc;
11758 IXMLDOMElement *root;
11759 IXMLDOMAttribute *pAttribute;
11760 IXMLDOMElement *elem;
11761 HRESULT hr;
11762 VARIANT v;
11763
11764 doc = create_document(&IID_IXMLDOMDocument);
11765
11766 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
11767 EXPECT_HR(hr, S_OK);
11768
11769 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
11770 EXPECT_HR(hr, S_OK);
11771
11772 hr = IXMLDOMDocument_createAttribute(doc, _bstr_("xmlns:dt"), &pAttribute);
11773 ok( hr == S_OK, "returns %08x\n", hr );
11774
11775 V_VT(&v) = VT_BSTR;
11776 V_BSTR(&v) = _bstr_("urn:schemas-microsoft-com:datatypes");
11777 hr = IXMLDOMAttribute_put_nodeValue(pAttribute, v);
11778 ok(hr == S_OK, "ret %08x\n", hr );
11779
11780 hr = IXMLDOMElement_setAttributeNode(root, pAttribute, NULL);
11781 ok(hr == S_OK, "ret %08x\n", hr );
11782
11783 hr = IXMLDOMNode_put_dataType((IXMLDOMNode*)root, _bstr_("bin.base64"));
11784 ok(hr == S_OK, "ret %08x\n", hr );
11785
11786 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
11787 EXPECT_HR(hr, S_OK);
11788
11789 str = NULL;
11790 hr = IXMLDOMElement_get_xml(elem, &str);
11791 ok( hr == S_OK, "got 0x%08x\n", hr);
11792 todo_wine ok( lstrcmpW(str, _bstr_("<Testing xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"bin.base64\"/>")) == 0,
11793 "got %s\n", wine_dbgstr_w(str));
11794 SysFreeString(str);
11795
11796 IXMLDOMElement_Release(elem);
11797 IXMLDOMAttribute_Release( pAttribute);
11798
11799 IXMLDOMDocument_Release(doc);
11800
11801 free_bstrs();
11802 }
11803
11804 static const char namespacesA[] =
11805 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
11806 " <ns1:elem1 xmlns:ns1=\"http://blah.org\" b='1' >"
11807 " <ns2:elem2 xmlns:ns2=\"http://blah.org\"/>"
11808 " <ns1:elem3/>"
11809 " <ns1:elem4/>"
11810 " <elem5 xmlns=\"http://blahblah.org\"/>"
11811 " <ns1:elem6>true</ns1:elem6>"
11812 " </ns1:elem1>";
11813
11814 static const char xsd_schema1_uri[] = "x-schema:test1.xsd";
11815 static const char xsd_schema1_xml[] =
11816 "<?xml version='1.0'?>"
11817 "<schema xmlns='http://www.w3.org/2001/XMLSchema'"
11818 " targetNamespace='x-schema:test1.xsd'>"
11819 " <element name='root'>"
11820 " <complexType>"
11821 " <sequence maxOccurs='unbounded'>"
11822 " <any/>"
11823 " </sequence>"
11824 " </complexType>"
11825 " </element>"
11826 "</schema>";
11827
11828 static void test_get_namespaces(void)
11829 {
11830 IXMLDOMSchemaCollection *collection, *collection2;
11831 IXMLDOMDocument2 *doc, *doc2;
11832 IEnumVARIANT *enumv, *enum2;
11833 IUnknown *unk1, *unk2;
11834 IXMLDOMNode *node;
11835 VARIANT_BOOL b;
11836 HRESULT hr;
11837 VARIANT v;
11838 LONG len;
11839 BSTR s;
11840
11841 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
11842 doc = create_document(&IID_IXMLDOMDocument2);
11843
11844 /* null pointer */
11845 hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11846 EXPECT_HR(hr, E_POINTER);
11847
11848 /* no document loaded */
11849 collection = (void*)0xdeadbeef;
11850 hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11851 EXPECT_HR(hr, S_OK);
11852 if (hr != S_OK)
11853 {
11854 IXMLDOMDocument2_Release(doc);
11855 return;
11856 }
11857 EXPECT_REF(collection, 2);
11858
11859 collection2 = (void*)0xdeadbeef;
11860 hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11861 EXPECT_HR(hr, S_OK);
11862 ok(collection == collection2, "got %p\n", collection2);
11863 EXPECT_REF(collection, 3);
11864 IXMLDOMSchemaCollection_Release(collection);
11865
11866 len = -1;
11867 hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11868 EXPECT_HR(hr, S_OK);
11869 ok(len == 0, "got %d\n", len);
11870 IXMLDOMSchemaCollection_Release(collection);
11871
11872 /* now with document */
11873 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11874 EXPECT_HR(hr, S_OK);
11875
11876 hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11877 EXPECT_HR(hr, S_OK);
11878
11879 len = -1;
11880 hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11881 EXPECT_HR(hr, S_OK);
11882 ok(len == 2, "got %d\n", len);
11883
11884 /* try to lookup some uris */
11885 node = (void*)0xdeadbeef;
11886 hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
11887 EXPECT_HR(hr, S_OK);
11888 ok(node == NULL, "got %p\n", node);
11889
11890 node = (void*)0xdeadbeef;
11891 hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah1.org"), &node);
11892 EXPECT_HR(hr, S_OK);
11893 ok(node == NULL, "got %p\n", node);
11894
11895 /* load schema and try to add it */
11896 doc2 = create_document(&IID_IXMLDOMDocument2);
11897 hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
11898 EXPECT_HR(hr, S_OK);
11899
11900 V_VT(&v) = VT_DISPATCH;
11901 V_DISPATCH(&v) = (IDispatch*)doc2;
11902 hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
11903 EXPECT_HR(hr, E_FAIL);
11904
11905 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
11906 EXPECT_HR(hr, S_OK);
11907 ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
11908 SysFreeString(s);
11909
11910 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
11911 EXPECT_HR(hr, S_OK);
11912 ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
11913 SysFreeString(s);
11914
11915 s = (void*)0xdeadbeef;
11916 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
11917 EXPECT_HR(hr, E_FAIL);
11918 ok(s == (void*)0xdeadbeef, "got %p\n", s);
11919
11920 /* enumerate */
11921 enumv = (void*)0xdeadbeef;
11922 EXPECT_REF(collection, 2);
11923 hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
11924 EXPECT_HR(hr, S_OK);
11925 EXPECT_REF(collection, 3);
11926 ok(enumv != NULL, "got %p\n", enumv);
11927
11928 hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IUnknown, (void**)&unk1);
11929 EXPECT_HR(hr, S_OK);
11930 hr = IEnumVARIANT_QueryInterface(enumv, &IID_IUnknown, (void**)&unk2);
11931 EXPECT_HR(hr, S_OK);
11932 ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
11933 IUnknown_Release(unk1);
11934 IUnknown_Release(unk2);
11935
11936 hr = IXMLDOMSchemaCollection_QueryInterface(collection, &IID_IEnumVARIANT, (void**)&enum2);
11937 EXPECT_HR(hr, E_NOINTERFACE);
11938
11939 V_VT(&v) = VT_EMPTY;
11940 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11941 EXPECT_HR(hr, S_OK);
11942 ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11943 ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11944 VariantClear(&v);
11945
11946 V_VT(&v) = VT_EMPTY;
11947 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11948 EXPECT_HR(hr, S_OK);
11949 ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
11950 ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
11951 VariantClear(&v);
11952
11953 V_VT(&v) = VT_NULL;
11954 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
11955 EXPECT_HR(hr, S_FALSE);
11956 ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
11957
11958 IEnumVARIANT_Release(enumv);
11959 IXMLDOMSchemaCollection_Release(collection);
11960
11961 IXMLDOMDocument2_Release(doc);
11962
11963 /* now with CLSID_DOMDocument60 */
11964 if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument2)) return;
11965 doc = create_document_version(60, &IID_IXMLDOMDocument2);
11966
11967 /* null pointer */
11968 hr = IXMLDOMDocument2_get_namespaces(doc, NULL);
11969 EXPECT_HR(hr, E_POINTER);
11970
11971 /* no document loaded */
11972 collection = (void*)0xdeadbeef;
11973 hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
11974 EXPECT_HR(hr, S_OK);
11975 if (hr != S_OK)
11976 {
11977 IXMLDOMDocument2_Release(doc);
11978 return;
11979 }
11980 EXPECT_REF(collection, 2);
11981
11982 collection2 = (void*)0xdeadbeef;
11983 hr = IXMLDOMDocument2_get_namespaces(doc, &collection2);
11984 EXPECT_HR(hr, S_OK);
11985 ok(collection == collection2, "got %p\n", collection2);
11986 EXPECT_REF(collection, 3);
11987 IXMLDOMSchemaCollection_Release(collection);
11988
11989 len = -1;
11990 hr = IXMLDOMSchemaCollection_get_length(collection, &len);
11991 EXPECT_HR(hr, S_OK);
11992 ok(len == 0, "got %d\n", len);
11993 IXMLDOMSchemaCollection_Release(collection);
11994
11995 /* now with document */
11996 hr = IXMLDOMDocument2_loadXML(doc, _bstr_(namespacesA), &b);
11997 EXPECT_HR(hr, S_OK);
11998
11999 hr = IXMLDOMDocument2_get_namespaces(doc, &collection);
12000 EXPECT_HR(hr, S_OK);
12001
12002 len = -1;
12003 hr = IXMLDOMSchemaCollection_get_length(collection, &len);
12004 EXPECT_HR(hr, S_OK);
12005 ok(len == 2, "got %d\n", len);
12006
12007 /* try to lookup some uris */
12008 node = (void*)0xdeadbeef;
12009 hr = IXMLDOMSchemaCollection_get(collection, _bstr_("http://blah.org"), &node);
12010 EXPECT_HR(hr, E_NOTIMPL);
12011 ok(broken(node == (void*)0xdeadbeef) || (node == NULL), "got %p\n", node);
12012
12013 /* load schema and try to add it */
12014 doc2 = create_document(&IID_IXMLDOMDocument2);
12015 hr = IXMLDOMDocument2_loadXML(doc2, _bstr_(xsd_schema1_xml), &b);
12016 EXPECT_HR(hr, S_OK);
12017
12018 V_VT(&v) = VT_DISPATCH;
12019 V_DISPATCH(&v) = (IDispatch*)doc2;
12020 hr = IXMLDOMSchemaCollection_add(collection, _bstr_(xsd_schema1_uri), v);
12021 EXPECT_HR(hr, E_FAIL);
12022 IXMLDOMDocument2_Release(doc2);
12023
12024 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 0, &s);
12025 EXPECT_HR(hr, S_OK);
12026 ok(!lstrcmpW(s, _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(s));
12027 SysFreeString(s);
12028
12029 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 1, &s);
12030 EXPECT_HR(hr, S_OK);
12031 ok(!lstrcmpW(s, _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(s));
12032 SysFreeString(s);
12033
12034 s = (void*)0xdeadbeef;
12035 hr = IXMLDOMSchemaCollection_get_namespaceURI(collection, 2, &s);
12036 EXPECT_HR(hr, E_FAIL);
12037 ok(broken(s == (void*)0xdeadbeef) || (s == NULL), "got %p\n", s);
12038
12039 /* enumerate */
12040 enumv = (void*)0xdeadbeef;
12041 hr = IXMLDOMSchemaCollection_get__newEnum(collection, (IUnknown**)&enumv);
12042 EXPECT_HR(hr, S_OK);
12043 ok(enumv != NULL, "got %p\n", enumv);
12044
12045 V_VT(&v) = VT_EMPTY;
12046 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12047 EXPECT_HR(hr, S_OK);
12048 ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
12049 ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
12050 VariantClear(&v);
12051
12052 V_VT(&v) = VT_EMPTY;
12053 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12054 EXPECT_HR(hr, S_OK);
12055 ok(V_VT(&v) == VT_BSTR, "got %d\n", V_VT(&v));
12056 ok(!lstrcmpW(V_BSTR(&v), _bstr_("http://blahblah.org")), "got %s\n", wine_dbgstr_w(V_BSTR(&v)));
12057 VariantClear(&v);
12058
12059 V_VT(&v) = VT_NULL;
12060 hr = IEnumVARIANT_Next(enumv, 1, &v, NULL);
12061 EXPECT_HR(hr, S_FALSE);
12062 ok(V_VT(&v) == VT_EMPTY, "got %d\n", V_VT(&v));
12063
12064 IEnumVARIANT_Release(enumv);
12065 IXMLDOMSchemaCollection_Release(collection);
12066 IXMLDOMDocument2_Release(doc);
12067 free_bstrs();
12068 }
12069
12070 static const DOMNodeType put_data_types[] = {
12071 NODE_TEXT,
12072 NODE_CDATA_SECTION,
12073 NODE_PROCESSING_INSTRUCTION,
12074 NODE_COMMENT,
12075 NODE_INVALID
12076 };
12077
12078 static void test_put_data(void)
12079 {
12080 static const WCHAR test_data[] = {'t','e','s','t',' ','n','o','d','e',' ','d','a','t','a',0};
12081 WCHAR buff[100], *data;
12082 IXMLDOMDocument *doc;
12083 const DOMNodeType *type;
12084 IXMLDOMText *text;
12085 IXMLDOMNode *node;
12086 VARIANT v;
12087 BSTR get_data;
12088 HRESULT hr;
12089
12090 doc = create_document(&IID_IXMLDOMDocument);
12091
12092 memcpy(&buff[2], test_data, sizeof(test_data));
12093 /* just a big length */
12094 *(DWORD*)buff = 0xf0f0;
12095 data = &buff[2];
12096
12097 type = put_data_types;
12098 while (*type != NODE_INVALID)
12099 {
12100 V_VT(&v) = VT_I2;
12101 V_I2(&v) = *type;
12102
12103 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12104 EXPECT_HR(hr, S_OK);
12105
12106 /* put_data() is interface-specific */
12107 switch (*type)
12108 {
12109 case NODE_TEXT:
12110 {
12111 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12112 EXPECT_HR(hr, S_OK);
12113 hr = IXMLDOMText_put_data(text, data);
12114 EXPECT_HR(hr, S_OK);
12115
12116 hr = IXMLDOMText_get_data(text, &get_data);
12117 EXPECT_HR(hr, S_OK);
12118
12119 IXMLDOMText_Release(text);
12120 break;
12121 }
12122 case NODE_CDATA_SECTION:
12123 {
12124 IXMLDOMCDATASection *cdata;
12125
12126 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMCDATASection, (void**)&cdata);
12127 EXPECT_HR(hr, S_OK);
12128 hr = IXMLDOMCDATASection_put_data(cdata, data);
12129 EXPECT_HR(hr, S_OK);
12130
12131 hr = IXMLDOMCDATASection_get_data(cdata, &get_data);
12132 EXPECT_HR(hr, S_OK);
12133
12134 IXMLDOMCDATASection_Release(cdata);
12135 break;
12136 }
12137 case NODE_PROCESSING_INSTRUCTION:
12138 {
12139 IXMLDOMProcessingInstruction *pi;
12140
12141 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMProcessingInstruction, (void**)&pi);
12142 EXPECT_HR(hr, S_OK);
12143 hr = IXMLDOMProcessingInstruction_put_data(pi, data);
12144 EXPECT_HR(hr, S_OK);
12145
12146 hr = IXMLDOMProcessingInstruction_get_data(pi, &get_data);
12147 EXPECT_HR(hr, S_OK);
12148
12149 IXMLDOMProcessingInstruction_Release(pi);
12150 break;
12151 }
12152 case NODE_COMMENT:
12153 {
12154 IXMLDOMComment *comment;
12155
12156 hr = IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMComment, (void**)&comment);
12157 EXPECT_HR(hr, S_OK);
12158 hr = IXMLDOMComment_put_data(comment, data);
12159 EXPECT_HR(hr, S_OK);
12160
12161 hr = IXMLDOMComment_get_data(comment, &get_data);
12162 EXPECT_HR(hr, S_OK);
12163
12164 IXMLDOMComment_Release(comment);
12165 break;
12166 }
12167 default:
12168 get_data = NULL;
12169 break;
12170 }
12171
12172 /* compare */
12173 ok(!lstrcmpW(data, get_data), "%d: got wrong data %s, expected %s\n", *type, wine_dbgstr_w(get_data),
12174 wine_dbgstr_w(data));
12175 SysFreeString(get_data);
12176
12177 IXMLDOMNode_Release(node);
12178 type++;
12179 }
12180
12181 IXMLDOMDocument_Release(doc);
12182 free_bstrs();
12183 }
12184
12185 static void test_newline_normalization(void)
12186 {
12187 const struct msxmlsupported_data_t *table = domdoc_support_data;
12188 IXMLDOMDocument *doc;
12189 IXMLDOMText *text;
12190 IXMLDOMNode *node;
12191 VARIANT v;
12192 VARIANT_BOOL b;
12193 BSTR s;
12194 HRESULT hr;
12195 LONG length;
12196
12197 V_VT(&v) = VT_I2;
12198 V_I2(&v) = NODE_TEXT;
12199
12200 while (table->clsid)
12201 {
12202 if (!is_clsid_supported(table->clsid, &IID_IXMLDOMDocument))
12203 {
12204 table++;
12205 continue;
12206 }
12207
12208 hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void**)&doc);
12209 ok(hr == S_OK, "got 0x%08x\n", hr);
12210
12211 hr = IXMLDOMDocument_createNode(doc, v, _bstr_("name"), NULL, &node);
12212 ok(hr == S_OK, "got 0x%08x\n", hr);
12213
12214 IXMLDOMNode_QueryInterface(node, &IID_IXMLDOMText, (void**)&text);
12215
12216 /* \r\n is normalized to \n and back to \r\n */
12217
12218 hr = IXMLDOMText_put_data(text, _bstr_("\r\n"));
12219 ok(hr == S_OK, "got 0x%08x\n", hr);
12220
12221 hr = IXMLDOMText_get_data(text, &s);
12222 ok(hr == S_OK, "got 0x%08x\n", hr);
12223 ok(!lstrcmpW(s, _bstr_("\n")), "got %s\n", wine_dbgstr_w(s));
12224 SysFreeString(s);
12225
12226 hr = IXMLDOMText_get_length(text, &length);
12227 ok(hr == S_OK, "got 0x%08x\n", hr);
12228 ok(length == 1, "got %d, expected 1\n", length);
12229
12230 hr = IXMLDOMText_get_xml(text, &s);
12231 ok(hr == S_OK, "got 0x%08x\n", hr);
12232 ok(!lstrcmpW(s, _bstr_("\r\n")), "got %s\n", wine_dbgstr_w(s));
12233 SysFreeString(s);
12234
12235 /* \r\r\n is normalized to \n\n and back to \r\n\r\n */
12236
12237 hr = IXMLDOMText_put_data(text, _bstr_("\r\r\n"));
12238 ok(hr == S_OK, "got 0x%08x\n", hr);
12239
12240 hr = IXMLDOMText_get_data(text, &s);
12241 ok(hr == S_OK, "got 0x%08x\n", hr);
12242 ok(!lstrcmpW(s, _bstr_("\n\n")), "got %s\n", wine_dbgstr_w(s));
12243 SysFreeString(s);
12244
12245 hr = IXMLDOMText_get_length(text, &length);
12246 ok(hr == S_OK, "got 0x%08x\n", hr);
12247 ok(length == 2, "got %d, expected 2\n", length);
12248
12249 hr = IXMLDOMText_get_xml(text, &s);
12250 ok(hr == S_OK, "got 0x%08x\n", hr);
12251 ok(!lstrcmpW(s, _bstr_("\r\n\r\n")), "got %s\n", wine_dbgstr_w(s));
12252 SysFreeString(s);
12253
12254 /* the same normalizations are applied when loading a document as a whole */
12255
12256 hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?><root>foo\n\r\n\r\r\nbar</root>"), &b);
12257 ok(hr == S_OK, "got 0x%08x\n", hr);
12258
12259 hr = IXMLDOMDocument_get_text(doc, &s);
12260 ok(hr == S_OK, "got 0x%08x\n", hr);
12261 ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12262 SysFreeString(s);
12263
12264 hr = IXMLDOMDocument_get_xml(doc, &s);
12265 ok(hr == S_OK, "got 0x%08x\n", hr);
12266 ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n<root>foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12267 "got %s\n", wine_dbgstr_w(s));
12268 SysFreeString(s);
12269
12270 /* even if xml:space="preserve" */
12271
12272 hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?>"
12273 "<root xml:space=\"preserve\">foo\n\r\n\r\r\nbar</root>"), &b);
12274 ok(hr == S_OK, "got 0x%08x\n", hr);
12275
12276 hr = IXMLDOMDocument_get_text(doc, &s);
12277 ok(hr == S_OK, "got 0x%08x\n", hr);
12278 ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12279 SysFreeString(s);
12280
12281 hr = IXMLDOMDocument_get_xml(doc, &s);
12282 ok(hr == S_OK, "got 0x%08x\n", hr);
12283 ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n"
12284 "<root xml:space=\"preserve\">foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12285 "got %s\n", wine_dbgstr_w(s));
12286 SysFreeString(s);
12287
12288 /* or preserveWhiteSpace is set */
12289
12290 hr = IXMLDOMDocument_put_preserveWhiteSpace(doc, VARIANT_TRUE);
12291 ok(hr == S_OK, "got 0x%08x\n", hr);
12292
12293 hr = IXMLDOMDocument_loadXML(doc, _bstr_("<?xml version=\"1.0\"?><root>foo\n\r\n\r\r\nbar</root>"), &b);
12294 ok(hr == S_OK, "got 0x%08x\n", hr);
12295
12296 hr = IXMLDOMDocument_get_text(doc, &s);
12297 ok(hr == S_OK, "got 0x%08x\n", hr);
12298 ok(!lstrcmpW(s, _bstr_("foo\n\n\n\nbar")), "got %s\n", wine_dbgstr_w(s));
12299 SysFreeString(s);
12300
12301 hr = IXMLDOMDocument_get_xml(doc, &s);
12302 ok(hr == S_OK, "got 0x%08x\n", hr);
12303 if (IsEqualGUID(table->clsid, &CLSID_DOMDocument60))
12304 {
12305 /* DOMDocument60 does the newline normalization but does not insert line breaks around the root node */
12306 todo_wine
12307 ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?><root>foo\r\n\r\n\r\n\r\nbar</root>")),
12308 "got %s\n", wine_dbgstr_w(s));
12309 }
12310 else
12311 {
12312 ok(!lstrcmpW(s, _bstr_("<?xml version=\"1.0\"?>\r\n<root>foo\r\n\r\n\r\n\r\nbar</root>\r\n")),
12313 "got %s\n", wine_dbgstr_w(s));
12314 }
12315 SysFreeString(s);
12316
12317 IXMLDOMText_Release(text);
12318 IXMLDOMNode_Release(node);
12319 IXMLDOMDocument_Release(doc);
12320 free_bstrs();
12321 table++;
12322 }
12323 }
12324
12325 static void test_putref_schemas(void)
12326 {
12327 IXMLDOMSchemaCollection *cache;
12328 IXMLDOMDocument2 *doc;
12329 VARIANT schema;
12330 HRESULT hr;
12331
12332 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument2)) return;
12333 if (!is_clsid_supported(&CLSID_XMLSchemaCache, &IID_IXMLDOMSchemaCollection)) return;
12334
12335 doc = create_document(&IID_IXMLDOMDocument2);
12336 cache = create_cache(&IID_IXMLDOMSchemaCollection);
12337
12338 /* set to NULL iface when no schema is set */
12339 V_VT(&schema) = VT_DISPATCH;
12340 V_DISPATCH(&schema) = NULL;
12341 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12342 EXPECT_HR(hr, S_OK);
12343
12344 V_VT(&schema) = VT_UNKNOWN;
12345 V_UNKNOWN(&schema) = NULL;
12346 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12347 EXPECT_HR(hr, S_OK);
12348
12349 /* set as VT_DISPATCH, reset with it */
12350 V_VT(&schema) = VT_DISPATCH;
12351 V_DISPATCH(&schema) = (IDispatch*)cache;
12352 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12353 EXPECT_HR(hr, S_OK);
12354
12355 V_DISPATCH(&schema) = NULL;
12356 hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12357 EXPECT_HR(hr, S_OK);
12358 ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12359
12360 V_VT(&schema) = VT_DISPATCH;
12361 V_DISPATCH(&schema) = NULL;
12362 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12363 EXPECT_HR(hr, S_OK);
12364
12365 V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12366 V_VT(&schema) = VT_I2;
12367 hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12368 EXPECT_HR(hr, S_FALSE);
12369 ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12370 ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12371
12372 /* set as VT_UNKNOWN, reset with it */
12373 V_VT(&schema) = VT_UNKNOWN;
12374 V_UNKNOWN(&schema) = (IUnknown*)cache;
12375 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12376 EXPECT_HR(hr, S_OK);
12377
12378 V_DISPATCH(&schema) = NULL;
12379 hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12380 EXPECT_HR(hr, S_OK);
12381 ok(V_DISPATCH(&schema) == (IDispatch*)cache, "got %p\n", V_DISPATCH(&schema));
12382
12383 V_VT(&schema) = VT_UNKNOWN;
12384 V_UNKNOWN(&schema) = NULL;
12385 hr = IXMLDOMDocument2_putref_schemas(doc, schema);
12386 EXPECT_HR(hr, S_OK);
12387
12388 V_DISPATCH(&schema) = (IDispatch*)0xdeadbeef;
12389 V_VT(&schema) = VT_I2;
12390 hr = IXMLDOMDocument2_get_schemas(doc, &schema);
12391 EXPECT_HR(hr, S_FALSE);
12392 ok(V_DISPATCH(&schema) == NULL, "got %p\n", V_DISPATCH(&schema));
12393 ok(V_VT(&schema) == VT_NULL, "got %d\n", V_VT(&schema));
12394
12395 IXMLDOMSchemaCollection_Release(cache);
12396 IXMLDOMDocument2_Release(doc);
12397 }
12398
12399 static void test_namedmap_newenum(void)
12400 {
12401 IEnumVARIANT *enum1, *enum2, *enum3;
12402 IXMLDOMNamedNodeMap *map;
12403 IUnknown *unk1, *unk2;
12404 IXMLDOMDocument *doc;
12405 IXMLDOMElement *elem;
12406 IXMLDOMNode *node;
12407 VARIANT_BOOL b;
12408 HRESULT hr;
12409 VARIANT v;
12410 BSTR str;
12411
12412 doc = create_document(&IID_IXMLDOMDocument);
12413
12414 hr = IXMLDOMDocument_loadXML(doc, _bstr_(attributes_map), &b);
12415 EXPECT_HR(hr, S_OK);
12416
12417 hr = IXMLDOMDocument_get_documentElement(doc, &elem);
12418 EXPECT_HR(hr, S_OK);
12419
12420 hr = IXMLDOMElement_get_attributes(elem, &map);
12421 EXPECT_HR(hr, S_OK);
12422 IXMLDOMElement_Release(elem);
12423
12424 enum1 = NULL;
12425 EXPECT_REF(map, 1);
12426 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum1);
12427 EXPECT_HR(hr, S_OK);
12428 ok(enum1 != NULL, "got %p\n", enum1);
12429 EXPECT_REF(map, 1);
12430 EXPECT_REF(enum1, 2);
12431
12432 enum2 = NULL;
12433 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IEnumVARIANT, (void**)&enum2);
12434 EXPECT_HR(hr, S_OK);
12435 ok(enum2 == enum1, "got %p\n", enum2);
12436
12437 IEnumVARIANT_Release(enum2);
12438
12439 EXPECT_REF(map, 1);
12440 hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum2);
12441 EXPECT_HR(hr, S_OK);
12442 EXPECT_REF(map, 2);
12443 EXPECT_REF(enum2, 1);
12444 ok(enum2 != enum1, "got %p, %p\n", enum2, enum1);
12445
12446 IEnumVARIANT_Release(enum1);
12447
12448 /* enumerator created with _newEnum() doesn't share IUnknown* with main object */
12449 hr = IXMLDOMNamedNodeMap_QueryInterface(map, &IID_IUnknown, (void**)&unk1);
12450 EXPECT_HR(hr, S_OK);
12451 hr = IEnumVARIANT_QueryInterface(enum2, &IID_IUnknown, (void**)&unk2);
12452 EXPECT_HR(hr, S_OK);
12453 EXPECT_REF(map, 3);
12454 EXPECT_REF(enum2, 2);
12455 ok(unk1 != unk2, "got %p, %p\n", unk1, unk2);
12456 IUnknown_Release(unk1);
12457 IUnknown_Release(unk2);
12458
12459 hr = IXMLDOMNamedNodeMap__newEnum(map, (IUnknown**)&enum3);
12460 EXPECT_HR(hr, S_OK);
12461 ok(enum2 != enum3, "got %p, %p\n", enum2, enum3);
12462 IEnumVARIANT_Release(enum3);
12463
12464 /* iteration tests */
12465 hr = IXMLDOMNamedNodeMap_get_item(map, 0, &node);
12466 EXPECT_HR(hr, S_OK);
12467 hr = IXMLDOMNode_get_nodeName(node, &str);
12468 EXPECT_HR(hr, S_OK);
12469 ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12470 SysFreeString(str);
12471 IXMLDOMNode_Release(node);
12472
12473 hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12474 EXPECT_HR(hr, S_OK);
12475 hr = IXMLDOMNode_get_nodeName(node, &str);
12476 EXPECT_HR(hr, S_OK);
12477 ok(!lstrcmpW(str, _bstr_("attr1")), "got %s\n", wine_dbgstr_w(str));
12478 SysFreeString(str);
12479 IXMLDOMNode_Release(node);
12480
12481 V_VT(&v) = VT_EMPTY;
12482 hr = IEnumVARIANT_Next(enum2, 1, &v, NULL);
12483 EXPECT_HR(hr, S_OK);
12484 ok(V_VT(&v) == VT_DISPATCH, "got var type %d\n", V_VT(&v));
12485 hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IXMLDOMNode, (void**)&node);
12486 EXPECT_HR(hr, S_OK);
12487 hr = IXMLDOMNode_get_nodeName(node, &str);
12488 EXPECT_HR(hr, S_OK);
12489 ok(!lstrcmpW(str, _bstr_("attr1")), "got node name %s\n", wine_dbgstr_w(str));
12490 SysFreeString(str);
12491 IXMLDOMNode_Release(node);
12492 VariantClear(&v);
12493
12494 hr = IXMLDOMNamedNodeMap_nextNode(map, &node);
12495 EXPECT_HR(hr, S_OK);
12496 hr = IXMLDOMNode_get_nodeName(node, &str);
12497 EXPECT_HR(hr, S_OK);
12498 ok(!lstrcmpW(str, _bstr_("attr2")), "got %s\n", wine_dbgstr_w(str));
12499 SysFreeString(str);
12500 IXMLDOMNode_Release(node);
12501
12502 IEnumVARIANT_Release(enum2);
12503 IXMLDOMNamedNodeMap_Release(map);
12504 IXMLDOMDocument_Release(doc);
12505 }
12506
12507 static const char xsltext_xsl[] =
12508 "<?xml version=\"1.0\"?>"
12509 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12510 "<xsl:output method=\"html\" encoding=\"us-ascii\"/>"
12511 "<xsl:template match=\"/\">"
12512 " <xsl:choose>"
12513 " <xsl:when test=\"testkey\">"
12514 " <xsl:text>testdata</xsl:text>"
12515 " </xsl:when>"
12516 " </xsl:choose>"
12517 "</xsl:template>"
12518 "</xsl:stylesheet>";
12519
12520 static const char omitxmldecl_xsl[] =
12521 "<?xml version=\"1.0\"?>"
12522 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" >"
12523 "<xsl:output method=\"xml\" omit-xml-declaration=\"yes\"/>"
12524 "<xsl:template match=\"/\">"
12525 " <xsl:for-each select=\"/a/item\">"
12526 " <xsl:element name=\"node\">"
12527 " <xsl:value-of select=\"@name\"/>"
12528 " </xsl:element>"
12529 " </xsl:for-each>"
12530 "</xsl:template>"
12531 "</xsl:stylesheet>";
12532
12533 static const char omitxmldecl_doc[] =
12534 "<?xml version=\"1.0\"?>"
12535 "<a>"
12536 " <item name=\"item1\"/>"
12537 " <item name=\"item2\"/>"
12538 "</a>";
12539
12540 static void test_xsltext(void)
12541 {
12542 IXMLDOMDocument *doc, *doc2;
12543 VARIANT_BOOL b;
12544 HRESULT hr;
12545 BSTR ret;
12546
12547 doc = create_document(&IID_IXMLDOMDocument);
12548 doc2 = create_document(&IID_IXMLDOMDocument);
12549
12550 hr = IXMLDOMDocument_loadXML(doc, _bstr_(xsltext_xsl), &b);
12551 EXPECT_HR(hr, S_OK);
12552
12553 hr = IXMLDOMDocument_loadXML(doc2, _bstr_("<testkey/>"), &b);
12554 EXPECT_HR(hr, S_OK);
12555
12556 hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12557 EXPECT_HR(hr, S_OK);
12558 ok(!lstrcmpW(ret, _bstr_("testdata")), "transform result %s\n", wine_dbgstr_w(ret));
12559 SysFreeString(ret);
12560
12561 /* omit-xml-declaration */
12562 hr = IXMLDOMDocument_loadXML(doc, _bstr_(omitxmldecl_xsl), &b);
12563 ok(hr == S_OK, "got 0x%08x\n", hr);
12564 hr = IXMLDOMDocument_loadXML(doc2, _bstr_(omitxmldecl_doc), &b);
12565 ok(hr == S_OK, "got 0x%08x\n", hr);
12566
12567 hr = IXMLDOMDocument_transformNode(doc2, (IXMLDOMNode*)doc, &ret);
12568 ok(hr == S_OK, "got 0x%08x\n", hr);
12569 ok(!lstrcmpW(ret, _bstr_("<node>item1</node><node>item2</node>")), "transform result %s\n", wine_dbgstr_w(ret));
12570 SysFreeString(ret);
12571
12572 IXMLDOMDocument_Release(doc2);
12573 IXMLDOMDocument_Release(doc);
12574 free_bstrs();
12575 }
12576
12577 struct attrtest_t {
12578 const char *name;
12579 const char *uri;
12580 const char *prefix;
12581 const char *href;
12582 };
12583
12584 static struct attrtest_t attrtests[] = {
12585 { "xmlns", "http://www.w3.org/2000/xmlns/", "xmlns", "xmlns" },
12586 { "xmlns", "nondefaulturi", "xmlns", "xmlns" },
12587 { "c", "http://www.w3.org/2000/xmlns/", NULL, "http://www.w3.org/2000/xmlns/" },
12588 { "c", "nsref1", NULL, "nsref1" },
12589 { "ns:c", "nsref1", "ns", "nsref1" },
12590 { "xmlns:c", "http://www.w3.org/2000/xmlns/", "xmlns", "" },
12591 { "xmlns:c", "nondefaulturi", "xmlns", "" },
12592 { 0 }
12593 };
12594
12595 static void test_create_attribute(void)
12596 {
12597 struct attrtest_t *ptr = attrtests;
12598 IXMLDOMElement *el;
12599 IXMLDOMDocument *doc;
12600 IXMLDOMNode *node, *node2;
12601 VARIANT var;
12602 HRESULT hr;
12603 int i = 0;
12604 BSTR str;
12605
12606 doc = create_document(&IID_IXMLDOMDocument);
12607
12608 while (ptr->name)
12609 {
12610 V_VT(&var) = VT_I1;
12611 V_I1(&var) = NODE_ATTRIBUTE;
12612 hr = IXMLDOMDocument_createNode(doc, var, _bstr_(ptr->name), _bstr_(ptr->uri), &node);
12613 ok(hr == S_OK, "got 0x%08x\n", hr);
12614
12615 str = NULL;
12616 hr = IXMLDOMNode_get_prefix(node, &str);
12617 if (ptr->prefix)
12618 {
12619 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12620 ok(!lstrcmpW(str, _bstr_(ptr->prefix)), "%d: got prefix %s, expected %s\n", i, wine_dbgstr_w(str), ptr->prefix);
12621 }
12622 else
12623 {
12624 ok(hr == S_FALSE, "%d: got 0x%08x\n", i, hr);
12625 ok(str == NULL, "%d: got prefix %s\n", i, wine_dbgstr_w(str));
12626 }
12627 SysFreeString(str);
12628
12629 str = NULL;
12630 hr = IXMLDOMNode_get_namespaceURI(node, &str);
12631 ok(hr == S_OK, "%d: got 0x%08x\n", i, hr);
12632 ok(!lstrcmpW(str, _bstr_(ptr->href)), "%d: got uri %s, expected %s\n", i, wine_dbgstr_w(str), ptr->href);
12633 SysFreeString(str);
12634
12635 IXMLDOMNode_Release(node);
12636 free_bstrs();
12637
12638 i++;
12639 ptr++;
12640 }
12641
12642 V_VT(&var) = VT_I1;
12643 V_I1(&var) = NODE_ELEMENT;
12644 hr = IXMLDOMDocument_createNode(doc, var, _bstr_("e"), NULL, &node2);
12645 ok(hr == S_OK, "got 0x%08x\n", hr);
12646
12647 hr = IXMLDOMNode_QueryInterface(node2, &IID_IXMLDOMElement, (void**)&el);
12648 ok(hr == S_OK, "got 0x%08x\n", hr);
12649 IXMLDOMNode_Release(node2);
12650
12651 V_VT(&var) = VT_I1;
12652 V_I1(&var) = NODE_ATTRIBUTE;
12653 hr = IXMLDOMDocument_createNode(doc, var, _bstr_("xmlns:a"), _bstr_("http://www.w3.org/2000/xmlns/"), &node);
12654 ok(hr == S_OK, "got 0x%08x\n", hr);
12655
12656 hr = IXMLDOMElement_setAttributeNode(el, (IXMLDOMAttribute*)node, NULL);
12657 ok(hr == S_OK, "got 0x%08x\n", hr);
12658
12659 /* for some reason default namespace uri is not reported */
12660 hr = IXMLDOMNode_get_namespaceURI(node, &str);
12661 ok(hr == S_OK, "got 0x%08x\n", hr);
12662 ok(!lstrcmpW(str, _bstr_("")), "got uri %s\n", wine_dbgstr_w(str));
12663 SysFreeString(str);
12664
12665 IXMLDOMNode_Release(node);
12666 IXMLDOMElement_Release(el);
12667 IXMLDOMDocument_Release(doc);
12668 free_bstrs();
12669 }
12670
12671 static void test_url(void)
12672 {
12673 IXMLDOMDocument *doc;
12674 HRESULT hr;
12675 BSTR s;
12676
12677 doc = create_document(&IID_IXMLDOMDocument);
12678
12679 hr = IXMLDOMDocument_get_url(doc, NULL);
12680 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
12681
12682 s = (void *)0xdeadbeef;
12683 hr = IXMLDOMDocument_get_url(doc, &s);
12684 ok(hr == S_FALSE, "got 0x%08x\n", hr);
12685 ok(s == NULL, "got %s\n", wine_dbgstr_w(s));
12686
12687 IXMLDOMDocument_Release(doc);
12688 }
12689
12690 static void test_merging_text(void)
12691 {
12692 IXMLDOMText *nodetext;
12693 IXMLDOMText *newtext;
12694 IXMLDOMElement *root;
12695 IXMLDOMDocument *doc;
12696 IXMLDOMNode *first;
12697 HRESULT hr;
12698 VARIANT v;
12699 BSTR str;
12700 int i;
12701
12702 doc = create_document(&IID_IXMLDOMDocument);
12703
12704 hr = IXMLDOMDocument_createElement(doc, _bstr_("Testing"), &root);
12705 EXPECT_HR(hr, S_OK);
12706
12707 hr = IXMLDOMDocument_appendChild(doc, (IXMLDOMNode*)root, NULL);
12708 EXPECT_HR(hr, S_OK);
12709
12710 /* test xmlAddChild */
12711 for (i = 0; i < 10; i++)
12712 {
12713 str = SysAllocString(szstr1);
12714 hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12715 SysFreeString(str);
12716 EXPECT_HR(hr, S_OK);
12717
12718 newtext = NULL;
12719 hr = IXMLDOMElement_appendChild(root, (IXMLDOMNode*)nodetext, (IXMLDOMNode**)&newtext);
12720 EXPECT_HR(hr, S_OK);
12721 ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12722
12723 IXMLDOMText_Release(newtext);
12724 IXMLDOMText_Release(nodetext);
12725 }
12726
12727 /* test xmlAddPrevSibling */
12728 hr = IXMLDOMElement_get_firstChild(root, &first);
12729 EXPECT_HR(hr, S_OK);
12730 V_VT(&v) = VT_UNKNOWN;
12731 V_UNKNOWN(&v) = (IUnknown*)first;
12732 for (i = 0; i < 10; i++)
12733 {
12734 str = SysAllocString(szstr2);
12735 hr = IXMLDOMDocument_createTextNode(doc, str, &nodetext);
12736 SysFreeString(str);
12737 EXPECT_HR(hr, S_OK);
12738
12739 newtext = NULL;
12740 hr = IXMLDOMElement_insertBefore(root, (IXMLDOMNode*)nodetext, v, (IXMLDOMNode**)&newtext);
12741 EXPECT_HR(hr, S_OK);
12742 ok(nodetext == newtext, "expected %p, got %p\n", nodetext, newtext);
12743
12744 IXMLDOMText_Release(newtext);
12745 IXMLDOMText_Release(nodetext);
12746 }
12747
12748 IXMLDOMNode_Release(first);
12749 IXMLDOMElement_Release(root);
12750 IXMLDOMDocument_Release(doc);
12751
12752 free_bstrs();
12753 }
12754
12755 static HRESULT WINAPI transformdest_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
12756 {
12757 BOOL known_iid = IsEqualIID(riid, &IID_IHTMLObjectElement) ||
12758 IsEqualIID(riid, &IID_transformdest_unknown) ||
12759 IsEqualIID(riid, &IID_IServiceProvider) ||
12760 IsEqualIID(riid, &IID_IStream) ||
12761 IsEqualIID(riid, &IID_ISequentialStream) ||
12762 IsEqualIID(riid, &IID_IRequestDictionary);
12763
12764 todo_wine_if(IsEqualIID(riid, &IID_IXMLDOMDocument))
12765 ok(known_iid, "Unexpected riid %s\n", wine_dbgstr_guid(riid));
12766
12767 return E_NOINTERFACE;
12768 }
12769
12770 static ULONG WINAPI transformdest_AddRef(IUnknown *iface)
12771 {
12772 return 2;
12773 }
12774
12775 static ULONG WINAPI transformdest_Release(IUnknown *iface)
12776 {
12777 return 1;
12778 }
12779
12780 static const IUnknownVtbl transformdestvtbl =
12781 {
12782 transformdest_QueryInterface,
12783 transformdest_AddRef,
12784 transformdest_Release,
12785 };
12786
12787 static void test_transformNodeToObject(void)
12788 {
12789 IUnknown transformdest = { &transformdestvtbl };
12790 IXMLDOMDocument *doc, *doc2, *doc3;
12791 VARIANT_BOOL b;
12792 HRESULT hr;
12793 VARIANT v;
12794
12795 doc = create_document(&IID_IXMLDOMDocument);
12796 doc2 = create_document(&IID_IXMLDOMDocument);
12797 doc3 = create_document(&IID_IXMLDOMDocument);
12798
12799 hr = IXMLDOMDocument_loadXML(doc, _bstr_(szTransformXML), &b);
12800 ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12801 hr = IXMLDOMDocument_loadXML(doc2, _bstr_(szTransformSSXML), &b);
12802 ok(hr == S_OK, "Failed to load document, hr %#x.\n", hr);
12803
12804 V_VT(&v) = VT_UNKNOWN;
12805 V_UNKNOWN(&v) = &transformdest;
12806 hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12807 ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12808
12809 V_VT(&v) = VT_UNKNOWN;
12810 V_UNKNOWN(&v) = NULL;
12811 hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12812 ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12813
12814 V_VT(&v) = VT_DISPATCH;
12815 V_DISPATCH(&v) = NULL;
12816 hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12817 ok(hr == E_INVALIDARG, "Failed to transform node, hr %#x.\n", hr);
12818
12819 V_VT(&v) = VT_DISPATCH;
12820 V_DISPATCH(&v) = (IDispatch *)doc3;
12821 hr = IXMLDOMDocument_transformNodeToObject(doc, (IXMLDOMNode *)doc2, v);
12822 ok(hr == S_OK, "Failed to transform node, hr %#x.\n", hr);
12823
12824 IXMLDOMDocument_Release(doc3);
12825 IXMLDOMDocument_Release(doc2);
12826 IXMLDOMDocument_Release(doc);
12827 free_bstrs();
12828 }
12829
12830 static void test_normalize_attribute_values(void)
12831 {
12832 IXMLDOMDocument2 *doc;
12833 VARIANT var;
12834 HRESULT hr;
12835
12836 if (!is_clsid_supported(&CLSID_DOMDocument60, &IID_IXMLDOMDocument2))
12837 {
12838 win_skip("NormalizeAttributeValues is not supported.\n");
12839 return;
12840 }
12841
12842 doc = create_document_version(60, &IID_IXMLDOMDocument2);
12843
12844 V_VT(&var) = VT_I2;
12845 V_I2(&var) = 10;
12846 hr = IXMLDOMDocument2_getProperty(doc, _bstr_("NormalizeAttributeValues"), &var);
12847 todo_wine {
12848 ok(hr == S_OK, "Failed to get property value, hr %#x.\n", hr);
12849 ok(V_VT(&var) == VT_BOOL, "Unexpected property value type, vt %d.\n", V_VT(&var));
12850 ok(V_BOOL(&var) == VARIANT_FALSE, "Unexpected property value.\n");
12851 }
12852 V_VT(&var) = VT_BOOL;
12853 V_BOOL(&var) = VARIANT_TRUE;
12854 hr = IXMLDOMDocument2_setProperty(doc, _bstr_("NormalizeAttributeValues"), var);
12855 ok(hr == S_OK, "Failed to set property, hr %#x.\n", hr);
12856
12857 V_VT(&var) = VT_I2;
12858 V_I2(&var) = 10;
12859 hr = IXMLDOMDocument2_getProperty(doc, _bstr_("NormalizeAttributeValues"), &var);
12860 todo_wine {
12861 ok(hr == S_OK, "Failed to get property value, hr %#x.\n", hr);
12862 ok(V_VT(&var) == VT_BOOL, "Unexpected property value type, vt %d.\n", V_VT(&var));
12863 ok(V_BOOL(&var) == VARIANT_TRUE, "Unexpected property value.\n");
12864 }
12865 IXMLDOMDocument2_Release(doc);
12866 }
12867
12868 typedef struct _namespace_as_attribute_t {
12869 const GUID *guid;
12870 const char *clsid;
12871 const char *xmlns_uri;
12872 } namespace_as_attribute_t;
12873
12874 static const namespace_as_attribute_t namespace_as_attribute_test_data[] = {
12875 { &CLSID_DOMDocument, "CLSID_DOMDocument", "" },
12876 { &CLSID_DOMDocument2, "CLSID_DOMDocument2", "" },
12877 { &CLSID_DOMDocument26, "CLSID_DOMDocument26", "" },
12878 { &CLSID_DOMDocument30, "CLSID_DOMDocument30", "" },
12879 { &CLSID_DOMDocument40, "CLSID_DOMDocument40", "" },
12880 { &CLSID_DOMDocument60, "CLSID_DOMDocument60", "http://www.w3.org/2000/xmlns/" },
12881 { 0 }
12882 };
12883
12884 static void test_namespaces_as_attributes(void)
12885 {
12886 const namespace_as_attribute_t *entry = namespace_as_attribute_test_data;
12887 struct test {
12888 const char *xml;
12889 int explen;
12890 const char *names[3];
12891 const char *prefixes[3];
12892 const char *basenames[3];
12893 const char *uris[3];
12894 const char *texts[3];
12895 };
12896 static const struct test tests[] = {
12897 {
12898 "<a ns:b=\"b attr\" d=\"d attr\" xmlns:ns=\"nshref\" />", 3,
12899 { "ns:b", "d", "xmlns:ns" }, /* nodeName */
12900 { "ns", NULL, "xmlns" }, /* prefix */
12901 { "b", "d", "ns" }, /* baseName */
12902 { "nshref", NULL, "" }, /* namespaceURI */
12903 { "b attr", "d attr", "nshref" }, /* text */
12904 },
12905 /* property only */
12906 {
12907 "<a d=\"d attr\" />", 1,
12908 { "d" }, /* nodeName */
12909 { NULL }, /* prefix */
12910 { "d" }, /* baseName */
12911 { NULL }, /* namespaceURI */
12912 { "d attr" }, /* text */
12913 },
12914 /* namespace only */
12915 {
12916 "<a xmlns:ns=\"nshref\" />", 1,
12917 { "xmlns:ns" }, /* nodeName */
12918 { "xmlns" }, /* prefix */
12919 { "ns" }, /* baseName */
12920 { "" }, /* namespaceURI */
12921 { "nshref" }, /* text */
12922 },
12923 /* no properties or namespaces */
12924 {
12925 "<a />", 0,
12926 },
12927
12928 { NULL }
12929 };
12930 const struct test *test;
12931 IXMLDOMNamedNodeMap *map;
12932 IXMLDOMNode *node, *item;
12933 IXMLDOMDocument *doc;
12934 VARIANT_BOOL b;
12935 LONG len, i;
12936 HRESULT hr;
12937 BSTR str;
12938
12939 while (entry->guid)
12940 {
12941 if (!is_clsid_supported(entry->guid, &IID_IXMLDOMDocument2))
12942 {
12943 entry++;
12944 continue;
12945 }
12946
12947 test = tests;
12948 while (test->xml) {
12949 hr = CoCreateInstance(entry->guid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&doc);
12950 ok(SUCCEEDED(hr), "Failed to create document %s, hr %#x.\n", wine_dbgstr_guid(entry->guid), hr);
12951
12952 hr = IXMLDOMDocument_loadXML(doc, _bstr_(test->xml), &b);
12953 ok(hr == S_OK, "Failed to load xml, hr %#x.\n", hr);
12954
12955 node = NULL;
12956 hr = IXMLDOMDocument_selectSingleNode(doc, _bstr_("a"), &node);
12957 ok(SUCCEEDED(hr), "Failed to select a node, hr %#x.\n", hr);
12958
12959 hr = IXMLDOMNode_get_attributes(node, &map);
12960 ok(SUCCEEDED(hr), "Failed to get attributes, hr %#x.\n", hr);
12961
12962 len = -1;
12963 hr = IXMLDOMNamedNodeMap_get_length(map, &len);
12964 ok(SUCCEEDED(hr), "Failed to get map length, hr %#x.\n", hr);
12965 ok(len == test->explen, "got %d\n", len);
12966
12967 item = NULL;
12968 hr = IXMLDOMNamedNodeMap_get_item(map, test->explen+1, &item);
12969 ok(hr == S_FALSE, "Failed to get item, hr %#x.\n", hr);
12970 ok(!item, "Item should be NULL\n");
12971
12972 for (i = 0; i < len; i++)
12973 {
12974 item = NULL;
12975 hr = IXMLDOMNamedNodeMap_get_item(map, i, &item);
12976 ok(SUCCEEDED(hr), "Failed to get item, hr %#x.\n", hr);
12977
12978 str = NULL;
12979 hr = IXMLDOMNode_get_nodeName(item, &str);
12980 ok(SUCCEEDED(hr), "Failed to get node name, hr %#x.\n", hr);
12981 ok(!lstrcmpW(str, _bstr_(test->names[i])), "got %s\n", wine_dbgstr_w(str));
12982 SysFreeString(str);
12983
12984 str = NULL;
12985 hr = IXMLDOMNode_get_prefix(item, &str);
12986 if (test->prefixes[i])
12987 {
12988 ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr);
12989 ok(!lstrcmpW(str, _bstr_(test->prefixes[i])), "got %s\n", wine_dbgstr_w(str));
12990 SysFreeString(str);
12991 }
12992 else
12993 ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
12994
12995 str = NULL;
12996 hr = IXMLDOMNode_get_baseName(item, &str);
12997 ok(SUCCEEDED(hr), "Failed to get base name, hr %#x.\n", hr);
12998 ok(!lstrcmpW(str, _bstr_(test->basenames[i])), "got %s\n", wine_dbgstr_w(str));
12999 SysFreeString(str);
13000
13001 str = NULL;
13002 hr = IXMLDOMNode_get_namespaceURI(item, &str);
13003 if (test->uris[i])
13004 {
13005 ok(hr == S_OK, "Failed to get node name, hr %#x.\n", hr);
13006 if (test->prefixes[i] && !strcmp(test->prefixes[i], "xmlns"))
13007 ok(!lstrcmpW(str, _bstr_(entry->xmlns_uri)), "got %s\n", wine_dbgstr_w(str));
13008 else
13009 ok(!lstrcmpW(str, _bstr_(test->uris[i])), "got %s\n", wine_dbgstr_w(str));
13010 SysFreeString(str);
13011 }
13012 else
13013 ok(hr == S_FALSE, "Failed to get node name, hr %#x.\n", hr);
13014
13015 str = NULL;
13016 hr = IXMLDOMNode_get_text(item, &str);
13017 ok(SUCCEEDED(hr), "Failed to get node text, hr %#x.\n", hr);
13018 ok(!lstrcmpW(str, _bstr_(test->texts[i])), "got %s\n", wine_dbgstr_w(str));
13019 SysFreeString(str);
13020
13021 IXMLDOMNode_Release(item);
13022 }
13023
13024 IXMLDOMNamedNodeMap_Release(map);
13025 IXMLDOMNode_Release(node);
13026 IXMLDOMDocument_Release(doc);
13027
13028 test++;
13029 }
13030
13031 entry++;
13032 }
13033 free_bstrs();
13034 }
13035
13036 START_TEST(domdoc)
13037 {
13038 HRESULT hr;
13039
13040 hr = CoInitialize( NULL );
13041 ok( hr == S_OK, "failed to init com\n");
13042 if (hr != S_OK) return;
13043
13044 get_class_support_data(domdoc_support_data);
13045 if (!is_clsid_supported(&CLSID_DOMDocument2, &IID_IXMLDOMDocument))
13046 {
13047 win_skip("DOMDocument2 is not supported. Skipping all tests.\n");
13048 CoUninitialize();
13049 return;
13050 }
13051
13052 test_domdoc();
13053 test_persiststream();
13054 test_domnode();
13055 test_refs();
13056 test_create();
13057 test_getElementsByTagName();
13058 test_get_text();
13059 test_get_childNodes();
13060 test_get_firstChild();
13061 test_get_lastChild();
13062 test_removeChild();
13063 test_replaceChild();
13064 test_removeNamedItem();
13065 test_IXMLDOMDocument2();
13066 test_whitespace();
13067 test_XPath();
13068 test_XSLPattern();
13069 test_cloneNode();
13070 test_xmlTypes();
13071 test_save();
13072 test_testTransforms();
13073 test_namespaces_basic();
13074 test_namespaces_change();
13075 test_FormattingXML();
13076 test_nodeTypedValue();
13077 test_TransformWithLoadingLocalFile();
13078 test_put_nodeValue();
13079 test_IObjectSafety();
13080 test_splitText();
13081 test_getQualifiedItem();
13082 test_removeQualifiedItem();
13083 test_get_ownerDocument();
13084 test_setAttributeNode();
13085 test_put_dataType();
13086 test_createNode();
13087 test_create_attribute();
13088 test_get_prefix();
13089 test_default_properties();
13090 test_selectSingleNode();
13091 test_events();
13092 test_createProcessingInstruction();
13093 test_put_nodeTypedValue();
13094 test_get_xml();
13095 test_insertBefore();
13096 test_appendChild();
13097 test_get_doctype();
13098 test_get_tagName();
13099 test_get_dataType();
13100 test_get_nodeTypeString();
13101 test_get_attributes();
13102 test_selection();
13103 test_load();
13104 test_dispex();
13105 test_parseerror();
13106 test_getAttributeNode();
13107 test_getAttribute();
13108 test_supporterrorinfo();
13109 test_nodeValue();
13110 test_get_namespaces();
13111 test_put_data();
13112 test_newline_normalization();
13113 test_putref_schemas();
13114 test_namedmap_newenum();
13115 test_xmlns_attribute();
13116 test_url();
13117 test_merging_text();
13118 test_transformNodeToObject();
13119 test_normalize_attribute_values();
13120 test_namespaces_as_attributes();
13121
13122 test_xsltemplate();
13123 test_xsltext();
13124
13125 if (is_clsid_supported(&CLSID_MXNamespaceManager40, &IID_IMXNamespaceManager))
13126 {
13127 test_mxnamespacemanager();
13128 test_mxnamespacemanager_override();
13129 }
13130
13131 CoUninitialize();
13132 }