Release 1.5.29.
[wine] / dlls / msxml3 / tests / xmldoc.c
1 /*
2  * IXMLDocument tests
3  *
4  * Copyright 2007 James Hawkins
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24 #include "windows.h"
25 #include "ole2.h"
26 #include "msxml2.h"
27 #include "msxml2did.h"
28 #include "ocidl.h"
29
30 #include "wine/test.h"
31
32 #define EXPECT_HR(hr,hr_exp) \
33     ok(hr == hr_exp, "got 0x%08x, expected 0x%08x\n", hr, hr_exp)
34
35 /* Deprecated Error Code */
36 #define XML_E_INVALIDATROOTLEVEL    0xc00ce556
37
38 static void create_xml_file(LPCSTR filename)
39 {
40     DWORD dwNumberOfBytesWritten;
41     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
42                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
43
44     static const char data[] =
45         "<?xml version=\"1.0\" ?>\n"
46         "<!DOCTYPE BankAccount>\n"
47         "<BankAccount>\n"
48         "  <Number>1234</Number>\n"
49         "  <Name>Captain Ahab</Name>\n"
50         "</BankAccount>";
51
52     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
53     CloseHandle(hf);
54 }
55
56 static void create_stream_on_file(IStream **stream, LPCSTR path)
57 {
58     HANDLE hfile;
59     HGLOBAL hglobal;
60     LPVOID ptr;
61     HRESULT hr;
62     DWORD file_size, read;
63
64     hfile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL,
65                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
66     ok(hfile != INVALID_HANDLE_VALUE, "Expected a valid file handle\n");
67     file_size = GetFileSize(hfile, NULL);
68
69     hglobal = GlobalAlloc(GHND, file_size);
70     ptr = GlobalLock(hglobal);
71
72     ReadFile(hfile, ptr, file_size, &read, NULL);
73     ok(file_size == read, "Expected to read the whole file, read %d\n", read);
74
75     hr = CreateStreamOnHGlobal(hglobal, TRUE, stream);
76     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
77     ok(*stream != NULL, "Expected non-NULL stream\n");
78
79     CloseHandle(hfile);
80     GlobalUnlock(hglobal);
81 }
82
83 static void test_xmldoc(void)
84 {
85     IXMLElement *element = NULL, *child = NULL, *value = NULL;
86     IXMLElementCollection *collection = NULL, *inner = NULL;
87     IPersistStreamInit *psi = NULL;
88     IXMLDocument *doc = NULL;
89     IStream *stream = NULL;
90     VARIANT vIndex, vName;
91     LONG type, num_child;
92     CHAR path[MAX_PATH];
93     IDispatch *disp;
94     ITypeInfo *ti;
95     HRESULT hr;
96     BSTR name;
97
98     static const WCHAR szBankAccount[] = {'B','A','N','K','A','C','C','O','U','N','T',0};
99     static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
100     static const WCHAR szNumVal[] = {'1','2','3','4',0};
101     static const WCHAR szName[] = {'N','A','M','E',0};
102     static const WCHAR szNameVal[] = {'C','a','p','t','a','i','n',' ','A','h','a','b',0};
103     static const WCHAR szVersion[] = {'1','.','0',0};
104     static const WCHAR rootW[] = {'r','o','o','t',0};
105
106     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
107                           &IID_IXMLDocument, (void**)&doc);
108     EXPECT_HR(hr, S_OK);
109
110     /* IDispatch */
111     hr = IXMLDocument_QueryInterface(doc, &IID_IDispatch, (void**)&disp);
112     EXPECT_HR(hr, S_OK);
113
114     /* just to make sure we're on right type data */
115     hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti);
116     EXPECT_HR(hr, S_OK);
117     name = NULL;
118     hr = ITypeInfo_GetDocumentation(ti, DISPID_XMLDOCUMENT_ROOT, &name, NULL, NULL, NULL);
119     EXPECT_HR(hr, S_OK);
120     ok(!lstrcmpW(name, rootW), "got name %s\n", wine_dbgstr_w(name));
121     SysFreeString(name);
122
123     ITypeInfo_Release(ti);
124     IDispatch_Release(disp);
125
126     hr = IXMLDocument_QueryInterface(doc, &IID_IXMLDOMDocument, (void**)&disp);
127     EXPECT_HR(hr, E_NOINTERFACE);
128
129     create_xml_file("bank.xml");
130     GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
131     create_stream_on_file(&stream, path);
132
133     hr = IXMLDocument_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&psi);
134     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
135     ok(psi != NULL, "Expected non-NULL psi\n");
136
137     hr = IXMLDocument_get_root(doc, &element);
138     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
139     ok(element == NULL, "Expected NULL element\n");
140
141     hr = IPersistStreamInit_Load(psi, stream);
142     ok(hr == S_OK || hr == XML_E_INVALIDATROOTLEVEL, "Expected S_OK, got %08x\n", hr);
143     if(hr == XML_E_INVALIDATROOTLEVEL)
144         goto cleanup;
145
146     ok(stream != NULL, "Expected non-NULL stream\n");
147
148     /* version field */
149     hr = IXMLDocument_get_version(doc, NULL);
150     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
151
152     name = NULL;
153     hr = IXMLDocument_get_version(doc, &name);
154     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
155     ok(!lstrcmpW(name, szVersion), "Expected 1.0, got %s\n", wine_dbgstr_w(name));
156     SysFreeString(name);
157
158     /* doctype */
159     hr = IXMLDocument_get_doctype(doc, NULL);
160     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
161
162     hr = IXMLDocument_get_doctype(doc, &name);
163     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
164     ok(!lstrcmpW(name, szBankAccount), "Expected BANKACCOUNT, got %s\n", wine_dbgstr_w(name));
165     SysFreeString(name);
166
167     hr = IXMLDocument_get_root(doc, &element);
168     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
169     ok(element != NULL, "Expected non-NULL element\n");
170
171     /* ::root() returns new instance each time */
172     hr = IXMLDocument_get_root(doc, &child);
173     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
174     ok(child != NULL, "Expected non-NULL element\n");
175     ok(child != element, "Expected new element instance\n");
176     IXMLElement_Release(child);
177
178     hr = IXMLElement_get_type(element, &type);
179     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
180     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
181
182     hr = IXMLElement_get_tagName(element, &name);
183     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
184     ok(!lstrcmpW(name, szBankAccount), "Expected BANKACCOUNT\n");
185     SysFreeString(name);
186
187     hr = IXMLElement_get_children(element, &collection);
188     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
189     ok(collection != NULL, "Expected non-NULL collection\n");
190
191     hr = IXMLElementCollection_get_length(collection, &num_child);
192     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
193     ok(num_child == 2, "Expected 2, got %d\n", num_child);
194
195     V_VT(&vIndex) = VT_I4;
196     V_I4(&vIndex) = 0;
197     V_VT(&vName) = VT_ERROR;
198     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
199     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
200     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
201     ok(child != NULL, "Expected non-NULL child\n");
202
203     hr = IXMLElement_get_type(child, &type);
204     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
205     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
206
207     hr = IXMLElement_get_tagName(child, &name);
208     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
209     ok(!lstrcmpW(name, szNumber), "Expected NUMBER\n");
210     SysFreeString(name);
211
212     hr = IXMLElement_get_children(child, &inner);
213     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
214     ok(inner != NULL, "Expected non-NULL inner\n");
215
216     hr = IXMLElementCollection_get_length(inner, &num_child);
217     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
218     ok(num_child == 1, "Expected 1, got %d\n", num_child);
219
220     hr = IXMLElementCollection_item(inner, vIndex, vName, (IDispatch **)&value);
221     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
222     ok(value != NULL, "Expected non-NULL value\n");
223
224     hr = IXMLElement_get_type(value, &type);
225     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
226     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
227
228     hr = IXMLElement_get_text(value, &name);
229     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
230     ok(!lstrcmpW(name, szNumVal), "Expected '1234'\n");
231     SysFreeString(name);
232
233     IXMLElementCollection_Release(inner);
234
235     inner = (IXMLElementCollection *)0xdeadbeef;
236     hr = IXMLElement_get_children(value, &inner);
237     ok(hr == 1, "Expected 1, got %08x\n", hr);
238     ok(inner == NULL, "Expected NULL inner, got %p\n", inner);
239
240     IXMLElement_Release(value);
241     IXMLElement_Release(child);
242     value = NULL;
243     child = NULL;
244
245     V_I4(&vIndex) = 1;
246     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
247     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
248     ok(child != NULL, "Expected non-NULL child\n");
249
250     hr = IXMLElement_get_type(child, &type);
251     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
252     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
253
254     hr = IXMLElement_get_tagName(child, &name);
255     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
256     ok(!lstrcmpW(name, szName), "Expected NAME\n");
257     SysFreeString(name);
258
259     hr = IXMLElement_get_children(child, &inner);
260     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
261     ok(inner != NULL, "Expected non-NULL inner\n");
262
263     hr = IXMLElementCollection_get_length(inner, &num_child);
264     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
265     ok(num_child == 1, "Expected 1, got %d\n", num_child);
266
267     V_I4(&vIndex) = 0;
268     hr = IXMLElementCollection_item(inner, vIndex, vName, (IDispatch **)&value);
269     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
270     ok(value != NULL, "Expected non-NULL value\n");
271
272     hr = IXMLElement_get_type(value, &type);
273     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
274     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
275
276     hr = IXMLElement_get_text(value, &name);
277     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
278     ok(!lstrcmpW(name, szNameVal), "Expected 'Captain Ahab'\n");
279     SysFreeString(name);
280
281     IXMLElementCollection_Release(inner);
282
283     inner = (IXMLElementCollection *)0xdeadbeef;
284     hr = IXMLElement_get_children(value, &inner);
285     ok(hr == 1, "Expected 1, got %08x\n", hr);
286     ok(inner == NULL, "Expected NULL inner, got %p\n", inner);
287
288     IXMLElement_Release(value);
289     IXMLElement_Release(child);
290     IXMLElementCollection_Release(collection);
291     IXMLElement_Release(element);
292 cleanup:
293     IStream_Release(stream);
294     IPersistStreamInit_Release(psi);
295     IXMLDocument_Release(doc);
296
297     DeleteFileA("bank.xml");
298 }
299
300 static void test_createElement(void)
301 {
302     HRESULT hr;
303     IXMLDocument *doc = NULL;
304     IXMLElement *element = NULL, *root = NULL;
305     VARIANT vType, vName;
306     LONG type;
307
308     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
309                           &IID_IXMLDocument, (LPVOID*)&doc);
310     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
311
312     /* invalid vType type */
313     V_VT(&vType) = VT_NULL;
314     V_VT(&vName) = VT_NULL;
315     element = (IXMLElement *)0xdeadbeef;
316     hr = IXMLDocument_createElement(doc, vType, vName, &element);
317     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
318     ok(element == NULL, "Expected NULL element\n");
319
320     /* invalid vType value */
321     V_VT(&vType) = VT_I4;
322     V_I4(&vType) = -1;
323     V_VT(&vName) = VT_NULL;
324     hr = IXMLDocument_createElement(doc, vType, vName, &element);
325     /* Up to and including SP7, createElement returns an element. */
326     if(hr == S_OK)
327     {
328         ok(element != NULL, "Expected element\n");
329         if (element != NULL)
330         {
331             hr = IXMLElement_get_type(element, &type);
332             ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
333             /* SP7 returns an XMLELEMTYPE_ELEMENT */
334             ok(type == XMLELEMTYPE_OTHER || type == XMLELEMTYPE_ELEMENT,
335                          "Expected XMLELEMTYPE_OTHER || XMLELEMTYPE_ELEMENT, got %d\n", type);
336
337             IXMLElement_Release(element);
338         }
339     }
340     else
341     {
342         ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
343         ok(element == NULL, "Expected NULL element\n");
344     }
345
346     /* invalid vName type */
347     V_VT(&vType) = VT_I4;
348     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
349     V_VT(&vName) = VT_I4;
350     hr = IXMLDocument_createElement(doc, vType, vName, &element);
351     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
352     ok(element != NULL, "Expected non-NULL element\n");
353
354     hr = IXMLElement_get_type(element, &type);
355     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
356     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
357
358     IXMLElement_Release(element);
359
360     /* NULL element */
361     V_VT(&vType) = VT_I4;
362     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
363     V_VT(&vName) = VT_I4;
364     hr = IXMLDocument_createElement(doc, vType, vName, NULL);
365     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
366
367     root = (IXMLElement *)0xdeadbeef;
368     hr = IXMLDocument_get_root(doc, &root);
369     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
370     ok(root == NULL, "Expected NULL root\n");
371
372     V_VT(&vType) = VT_I4;
373     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
374     V_VT(&vName) = VT_NULL;
375     hr = IXMLDocument_createElement(doc, vType, vName, &element);
376     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
377     ok(element != NULL, "Expected non-NULL element\n");
378
379     /* createElement does not set the new element as root */
380     root = (IXMLElement *)0xdeadbeef;
381     hr = IXMLDocument_get_root(doc, &root);
382     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
383     ok(root == NULL, "Expected NULL root\n");
384
385     IXMLElement_Release(element);
386     IXMLDocument_Release(doc);
387 }
388
389 static void test_persiststreaminit(void)
390 {
391     IXMLDocument *doc = NULL;
392     IXMLElement *element = NULL;
393     IPersistStreamInit *psi = NULL;
394     IStream *stream = NULL;
395     STATSTG stat;
396     HRESULT hr;
397     ULARGE_INTEGER size;
398     CHAR path[MAX_PATH];
399     CLSID id;
400     BSTR str;
401     static const WCHAR testW[] = {'t','e','s','t',0};
402
403     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
404                           &IID_IXMLDocument, (LPVOID*)&doc);
405     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
406
407     hr = IXMLDocument_QueryInterface(doc, &IID_IPersistStreamInit, (LPVOID *)&psi);
408     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
409     ok(psi != NULL, "Expected non-NULL psi\n");
410
411     /* null arguments */
412     hr = IPersistStreamInit_GetSizeMax(psi, NULL);
413     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
414
415     hr = IPersistStreamInit_Load(psi, NULL);
416     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
417
418     hr = IPersistStreamInit_Save(psi, NULL, FALSE);
419     todo_wine ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
420
421     hr = IPersistStreamInit_GetClassID(psi, NULL);
422     ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);
423
424     hr = IPersistStreamInit_IsDirty(psi);
425     todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
426
427     create_xml_file("bank.xml");
428     GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
429     create_stream_on_file(&stream, path);
430
431     /* GetSizeMax not implemented */
432     size.QuadPart = 0;
433     hr = IPersistStreamInit_GetSizeMax(psi, &size);
434     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
435     ok(size.QuadPart == 0, "Expected 0\n");
436
437     hr = IPersistStreamInit_Load(psi, stream);
438     IStream_Release(stream);
439     ok(hr == S_OK || hr == XML_E_INVALIDATROOTLEVEL, "Expected S_OK, got %08x\n", hr);
440     if(hr == XML_E_INVALIDATROOTLEVEL)
441         goto cleanup;
442
443     hr = IPersistStreamInit_IsDirty(psi);
444     todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
445
446     /* try to save document */
447     stream = NULL;
448     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
449     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
450     hr = IPersistStreamInit_Save(psi, stream, FALSE);
451     todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
452
453     stat.cbSize.QuadPart = 0;
454     hr = IStream_Stat(stream, &stat, 0);
455     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
456     todo_wine ok(stat.cbSize.QuadPart > 0, "Expected >0\n");
457     IStream_Release(stream);
458
459     str = SysAllocString(testW);
460     hr = IXMLDocument_get_root(doc, &element);
461     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
462     hr = IXMLElement_put_text(element, str);
463     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
464     IXMLElement_Release(element);
465     SysFreeString(str);
466
467     hr = IPersistStreamInit_IsDirty(psi);
468     todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
469
470     create_stream_on_file(&stream, path);
471     hr = IPersistStreamInit_Load(psi, stream);
472     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
473     IStream_Release(stream);
474
475     hr = IPersistStreamInit_IsDirty(psi);
476     todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
477
478     /* reset internal stream */
479     hr = IPersistStreamInit_InitNew(psi);
480     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
481
482     hr = IPersistStreamInit_IsDirty(psi);
483     todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
484
485     stream = NULL;
486     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
487     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
488
489     hr = IPersistStreamInit_Save(psi, stream, FALSE);
490     todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
491
492     stat.cbSize.QuadPart = 0;
493     hr = IStream_Stat(stream, &stat, 0);
494     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
495     todo_wine ok(stat.cbSize.QuadPart > 0, "Expected >0\n");
496     IStream_Release(stream);
497
498     memset(&id, 0, sizeof(id));
499     hr = IPersistStreamInit_GetClassID(psi, &id);
500     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
501     ok(IsEqualCLSID(&id, &CLSID_XMLDocument), "Expected CLSID_XMLDocument\n");
502
503 cleanup:
504     IPersistStreamInit_Release(psi);
505     IXMLDocument_Release(doc);
506     DeleteFileA("bank.xml");
507 }
508
509 static BOOL test_try_xmldoc(void)
510 {
511     IXMLDocument *doc = NULL;
512     HRESULT hr;
513
514     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
515                           &IID_IXMLDocument, (LPVOID*)&doc);
516     if (FAILED(hr))
517     {
518         skip("Failed to create XMLDocument instance\n");
519         return FALSE;
520     }
521
522     IXMLDocument_Release(doc);
523     return TRUE;
524 }
525
526 static void test_xmlelem_children(void)
527 {
528     IXMLDocument *doc = NULL;
529     IXMLElement *element = NULL, *child = NULL, *child2 = NULL;
530     IXMLElementCollection *collection = NULL;
531     VARIANT vType, vName, vIndex;
532     LONG length;
533     HRESULT hr;
534
535     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
536                           &IID_IXMLDocument, (LPVOID*)&doc);
537     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
538
539     V_VT(&vType) = VT_I4;
540     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
541     V_VT(&vName) = VT_NULL;
542     hr = IXMLDocument_createElement(doc, vType, vName, &element);
543     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
544     ok(element != NULL, "Expected non-NULL element\n");
545
546     V_VT(&vType) = VT_I4;
547     V_I4(&vType) = XMLELEMTYPE_TEXT;
548     V_VT(&vName) = VT_NULL;
549     hr = IXMLDocument_createElement(doc, vType, vName, &child);
550     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
551     ok(child != NULL, "Expected non-NULL child\n");
552
553     V_VT(&vType) = VT_I4;
554     V_I4(&vType) = XMLELEMTYPE_TEXT;
555     V_VT(&vName) = VT_NULL;
556     hr = IXMLDocument_createElement(doc, vType, vName, &child2);
557     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
558     ok(child2 != NULL, "Expected non-NULL child\n");
559
560     hr = IXMLElement_addChild(element, child, 0, -1);
561     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
562
563     hr = IXMLElement_get_children(element, &collection);
564     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
565     ok(collection != NULL, "Expected non-NULL collection\n");
566
567     length = 0;
568     hr = IXMLElementCollection_get_length(collection, &length);
569     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
570     ok(length == 1, "Expected 1, got %08x\n", length);
571
572     /* remove/add child and check what happens with collection */
573     hr = IXMLElement_removeChild(element, child);
574     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
575
576     length = -1;
577     hr = IXMLElementCollection_get_length(collection, &length);
578     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
579     ok(length == 0, "Expected 0, got %08x\n", length);
580     IXMLElementCollection_Release(collection);
581
582     hr = IXMLElement_AddRef(child);
583     ok(hr == 2, "Expected 2, got %08x\n", hr);
584     IXMLElement_Release(child);
585     hr = IXMLElement_addChild(element, child, 0, -1);
586     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
587     hr = IXMLElement_AddRef(child);
588     ok(hr == 2, "Expected 2, got %08x\n", hr);
589     IXMLElement_Release(child);
590     hr = IXMLElement_addChild(element, child2, 0, -1);
591     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
592
593     hr = IXMLElement_get_children(element, &collection);
594     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
595     ok(collection != NULL, "Expected non-NULL collection\n");
596
597     hr = IXMLElement_AddRef(child);
598     ok(hr == 2, "Expected 2, got %08x\n", hr);
599     IXMLElement_Release(child);
600
601     length = 0;
602     hr = IXMLElementCollection_get_length(collection, &length);
603     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
604     ok(length == 2, "Expected 2, got %08x\n", length);
605
606     IXMLElement_Release(child2);
607
608     length = 0;
609     hr = IXMLElementCollection_get_length(collection, &length);
610     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
611     ok(length == 2, "Expected 2, got %08x\n", length);
612
613     V_VT(&vIndex) = VT_I4;
614     V_I4(&vIndex) = 1;
615     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child2);
616     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
617     ok(child2 != NULL, "Expected not NULL child\n");
618     IXMLElementCollection_Release(collection);
619     IXMLElement_Release(child2);
620
621     /* add element->child->child2 structure, then remove child2 from node */
622     V_VT(&vType) = VT_I4;
623     V_I4(&vType) = XMLELEMTYPE_TEXT;
624     V_VT(&vName) = VT_NULL;
625     hr = IXMLDocument_createElement(doc, vType, vName, &child2);
626     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
627     ok(child2 != NULL, "Expected non-NULL child\n");
628
629     hr = IXMLElement_addChild(child, child2, 0, -1);
630     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
631
632     hr = IXMLElement_removeChild(element, child2);
633     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
634
635     hr = IXMLElement_removeChild(child, child2);
636     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
637
638     hr = IXMLElement_removeChild(child, NULL);
639     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
640
641     IXMLElement_Release(element);
642     IXMLElement_Release(child);
643     IXMLElement_Release(child2);
644     IXMLDocument_Release(doc);
645 }
646
647 static void test_xmlelem_collection(void)
648 {
649     HRESULT hr;
650     IUnknown *unk = NULL;
651     IXMLDocument *doc = NULL;
652     IXMLElement *element = NULL, *child;
653     IXMLElementCollection *collection = NULL;
654     IEnumVARIANT *enumVar = NULL;
655     CHAR pathA[MAX_PATH];
656     WCHAR path[MAX_PATH];
657     LONG length, type;
658     ULONG num_vars;
659     VARIANT var, vIndex, vName;
660     BSTR url, str;
661     static const CHAR szBankXML[] = "bank.xml";
662     static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
663     static const WCHAR szName[] = {'N','A','M','E',0};
664
665     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
666                           &IID_IXMLDocument, (LPVOID*)&doc);
667     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
668
669     create_xml_file(szBankXML);
670     GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL);
671     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
672
673     url = SysAllocString(path);
674     hr = IXMLDocument_put_URL(doc, url);
675     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
676     SysFreeString(url);
677
678     if(hr != S_OK)
679         goto cleanup;
680
681     hr = IXMLDocument_get_root(doc, &element);
682     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
683     ok(element != NULL, "Expected non-NULL element\n");
684
685     hr = IXMLElement_get_children(element, &collection);
686     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
687     ok(collection != NULL, "Expected non-NULL collection\n");
688
689     hr = IXMLElementCollection_get_length(collection, NULL);
690     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
691
692     hr = IXMLElementCollection_get_length(collection, &length);
693     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
694     ok(length == 2, "Expected 2, got %d\n", length);
695
696     /* IXMLElementCollection:put_length does nothing */
697     hr = IXMLElementCollection_put_length(collection, -1);
698     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
699
700     hr = IXMLElementCollection_put_length(collection, 0);
701     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
702
703     hr = IXMLElementCollection_put_length(collection, 1);
704     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
705
706     hr = IXMLElementCollection_put_length(collection, 2);
707     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
708
709     hr = IXMLElementCollection_put_length(collection, 3);
710     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
711
712     hr = IXMLElementCollection_put_length(collection, 50);
713     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
714
715     /* make sure the length hasn't changed */
716     hr = IXMLElementCollection_get_length(collection, &length);
717     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
718     ok(length == 2, "Expected 2, got %d\n", length);
719
720     /* IXMLElementCollection implements IEnumVARIANT */
721     hr = IXMLElementCollection_QueryInterface(collection, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
722     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
723     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
724     IEnumVARIANT_Release(enumVar);
725
726     hr = IXMLElementCollection_get__newEnum(collection, &unk);
727     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
728     ok(unk != NULL, "Expected non-NULL unk\n");
729
730     hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
731     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
732     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
733     IUnknown_Release(unk);
734
735     /* <Number>1234</Number> */
736     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
737     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
738     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
739     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
740
741     hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
742     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
743     ok(child != NULL, "Expected non-NULL child\n");
744
745     VariantClear(&var);
746
747     hr = IXMLElement_get_type(child, &type);
748     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
749     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
750
751     hr = IXMLElement_get_tagName(child, &str);
752     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
753     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
754     SysFreeString(str);
755     IXMLElement_Release(child);
756
757     /* <Name>Captain Ahab</Name> */
758     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
759     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
760     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
761     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
762
763     /* try advance further, no children left */
764     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
765     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
766     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
767     ok(num_vars == 0, "Expected 0, got %d\n", num_vars);
768
769     hr = IEnumVARIANT_Next(enumVar, 1, &var, NULL);
770     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
771     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
772
773     hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
774     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
775     ok(child != NULL, "Expected non-NULL child\n");
776
777     VariantClear(&var);
778
779     hr = IXMLElement_get_type(child, &type);
780     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
781     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
782
783     hr = IXMLElement_get_tagName(child, &str);
784     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
785     ok(!lstrcmpW(str, szName), "Expected NAME\n");
786     SysFreeString(str);
787     IXMLElement_Release(child);
788
789     /* <Number>1234</Number> */
790     V_VT(&vIndex) = VT_I4;
791     V_I4(&vIndex) = 0;
792     V_VT(&vName) = VT_ERROR;
793     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
794     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
795     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
796     ok(child != NULL, "Expected non-NULL child\n");
797
798     hr = IXMLElement_get_type(child, &type);
799     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
800     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
801
802     hr = IXMLElement_get_tagName(child, &str);
803     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
804     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
805     SysFreeString(str);
806     IXMLElement_Release(child);
807
808     /* <Name>Captain Ahab</Name> */
809     V_VT(&vIndex) = VT_I4;
810     V_I4(&vIndex) = 1;
811     V_VT(&vName) = VT_ERROR;
812     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
813     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
814     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
815     ok(child != NULL, "Expected non-NULL child\n");
816
817     hr = IXMLElement_get_type(child, &type);
818     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
819     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
820
821     hr = IXMLElement_get_tagName(child, &str);
822     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
823     ok(!lstrcmpW(str, szName), "Expected NAME\n");
824     SysFreeString(str);
825     IXMLElement_Release(child);
826
827     V_I4(&vIndex) = 100;
828     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
829     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
830     ok(child == NULL, "Expected NULL child\n");
831
832     V_I4(&vIndex) = -1;
833     child = (IXMLElement *)0xdeadbeef;
834     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
835     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
836     ok(child == NULL, "Expected NULL child\n");
837
838     IEnumVARIANT_Release(enumVar);
839     IXMLElement_Release(element);
840     IXMLElementCollection_Release(collection);
841 cleanup:
842     IXMLDocument_Release(doc);
843     DeleteFileA("bank.xml");
844 }
845
846 static void test_xmlelem(void)
847 {
848     HRESULT hr;
849     IXMLDocument *doc = NULL;
850     IXMLElement *element = NULL, *parent;
851     IXMLElement *child, *child2;
852     IXMLElementCollection *children;
853     VARIANT vType, vName;
854     VARIANT vIndex, vValue;
855     BSTR str, val, name;
856     LONG type, num_child;
857     IDispatch *disp;
858     ITypeInfo *ti;
859
860     static const WCHAR propName[] = {'p','r','o','p',0};
861     static const WCHAR propVal[] = {'v','a','l',0};
862     static const WCHAR nextVal[] = {'n','e','x','t',0};
863     static const WCHAR noexist[] = {'n','o','e','x','i','s','t',0};
864     static const WCHAR crazyCase1[] = {'C','R','a','z','Y','c','A','S','E',0};
865     static const WCHAR crazyCase2[] = {'C','R','A','Z','Y','C','A','S','E',0};
866
867     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
868                           &IID_IXMLDocument, (LPVOID*)&doc);
869     EXPECT_HR(hr, S_OK);
870
871     V_VT(&vType) = VT_I4;
872     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
873     V_VT(&vName) = VT_NULL;
874     hr = IXMLDocument_createElement(doc, vType, vName, &element);
875     EXPECT_HR(hr, S_OK);
876     ok(element != NULL, "Expected non-NULL element\n");
877
878     /* test for IDispatch */
879     disp = NULL;
880     hr = IXMLElement_QueryInterface(element, &IID_IDispatch, (void**)&disp);
881     EXPECT_HR(hr, S_OK);
882
883     hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti);
884     EXPECT_HR(hr, S_OK);
885
886     name = NULL;
887     hr = ITypeInfo_GetDocumentation(ti, DISPID_XMLELEMENT_TAGNAME, &name, NULL, NULL, NULL);
888     EXPECT_HR(hr, S_OK);
889     SysFreeString(name);
890
891     ITypeInfo_Release(ti);
892     IDispatch_Release(disp);
893
894     hr = IXMLElement_get_tagName(element, &str);
895     EXPECT_HR(hr, S_OK);
896     ok(lstrlenW(str) == 0, "Expected empty tag name\n");
897     SysFreeString(str);
898
899     parent = (IXMLElement *)0xdeadbeef;
900     hr = IXMLElement_get_parent(element, &parent);
901     ok(hr == 1, "Expected 1, got %08x\n", hr);
902     ok(parent == NULL, "Expected NULL parent\n");
903
904     str = SysAllocString(noexist);
905     hr = IXMLElement_getAttribute(element, str, &vValue);
906     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
907     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
908     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
909     VariantClear(&vValue);
910     SysFreeString(str);
911
912     str = SysAllocString(crazyCase1);
913     val = SysAllocString(propVal);
914     V_VT(&vValue) = VT_BSTR;
915     V_BSTR(&vValue) = val;
916     hr = IXMLElement_setAttribute(element, str, vValue);
917     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
918     SysFreeString(str);
919     SysFreeString(val);
920
921     str = SysAllocString(crazyCase2);
922     hr = IXMLElement_getAttribute(element, str, &vValue);
923     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
924     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
925     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
926     VariantClear(&vValue);
927     SysFreeString(str);
928
929     str = SysAllocString(propName);
930     val = SysAllocString(propVal);
931     V_VT(&vValue) = VT_BSTR;
932     V_BSTR(&vValue) = val;
933     hr = IXMLElement_setAttribute(element, str, vValue);
934     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
935     SysFreeString(val);
936
937     hr = IXMLElement_getAttribute(element, str, &vValue);
938     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
939     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
940     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
941     VariantClear(&vValue);
942
943     hr = IXMLElement_removeAttribute(element, str);
944     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
945
946     /* remove now nonexistent attribute */
947     hr = IXMLElement_removeAttribute(element, str);
948     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
949
950     hr = IXMLElement_getAttribute(element, str, &vValue);
951     ok(hr == 1, "Expected 1, got %08x\n", hr);
952     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
953     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
954     SysFreeString(str);
955     VariantClear(&vValue);
956
957     children = (IXMLElementCollection *)0xdeadbeef;
958     hr = IXMLElement_get_children(element, &children);
959     ok(hr == 1, "Expected 1, got %08x\n", hr);
960     ok(children == NULL, "Expected NULL collection\n");
961
962     hr = IXMLElement_get_type(element, &type);
963     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
964     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
965
966     hr = IXMLElement_get_text(element, &str);
967     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
968     ok(lstrlenW(str) == 0, "Expected empty text\n");
969     SysFreeString(str);
970
971     /* put_text with an ELEMENT */
972     str = SysAllocString(propVal);
973     hr = IXMLElement_put_text(element, str);
974     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
975     SysFreeString(str);
976
977     V_VT(&vType) = VT_I4;
978     V_I4(&vType) = XMLELEMTYPE_TEXT;
979     V_VT(&vName) = VT_NULL;
980     hr = IXMLDocument_createElement(doc, vType, vName, &child);
981     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
982     ok(child != NULL, "Expected non-NULL child\n");
983
984     hr = IXMLElement_addChild(element, child, 0, -1);
985     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
986
987     str = SysAllocString(propVal);
988     hr = IXMLElement_put_text(child, str);
989     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
990     SysFreeString(str);
991
992     parent = (IXMLElement *)0xdeadbeef;
993     hr = IXMLElement_get_parent(child, &parent);
994     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
995     ok(parent != element, "Expected parent != element\n");
996
997     hr = IXMLElement_get_type(parent, &type);
998     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
999     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
1000
1001     children = (IXMLElementCollection *)0xdeadbeef;
1002     hr = IXMLElement_get_children(element, &children);
1003     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1004     ok(children != NULL, "Expected non-NULL collection\n");
1005
1006     hr = IXMLElementCollection_get_length(children, &num_child);
1007     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1008     ok(num_child == 1, "Expected 1, got %d\n", num_child);
1009
1010     V_VT(&vIndex) = VT_I4;
1011     V_I4(&vIndex) = 0;
1012     V_VT(&vName) = VT_ERROR;
1013     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
1014     hr = IXMLElementCollection_item(children, vIndex, vName, (IDispatch **)&child2);
1015     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1016     ok(child2 != NULL, "Expected non-NULL child\n");
1017
1018     hr = IXMLElement_get_type(child2, &type);
1019     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1020     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
1021
1022     hr = IXMLElement_get_text(element, &str);
1023     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1024     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
1025     SysFreeString(str);
1026
1027     hr = IXMLElement_get_text(child2, &str);
1028     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1029     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
1030     SysFreeString(str);
1031
1032     /* try put_text on ELEMENT again, now that it has a text child */
1033     str = SysAllocString(nextVal);
1034     hr = IXMLElement_put_text(element, str);
1035     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
1036     SysFreeString(str);
1037
1038     str = SysAllocString(nextVal);
1039     hr = IXMLElement_put_text(child2, str);
1040     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1041     SysFreeString(str);
1042
1043     hr = IXMLElement_get_text(element, &str);
1044     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1045     ok(!lstrcmpW(str, nextVal), "Expected 'val'\n");
1046     SysFreeString(str);
1047
1048     IXMLElement_Release(child2);
1049     IXMLElementCollection_Release(children);
1050     IXMLElement_Release(parent);
1051     IXMLElement_Release(child);
1052     IXMLElement_Release(element);
1053     IXMLDocument_Release(doc);
1054 }
1055
1056 START_TEST(xmldoc)
1057 {
1058     HRESULT hr;
1059
1060     hr = CoInitialize(NULL);
1061     ok(hr == S_OK, "failed to init com\n");
1062
1063     if (!test_try_xmldoc())
1064     {
1065         CoUninitialize();
1066         return;
1067     }
1068
1069     test_xmldoc();
1070     test_createElement();
1071     test_persiststreaminit();
1072     test_xmlelem();
1073     test_xmlelem_collection();
1074     test_xmlelem_children();
1075
1076     CoUninitialize();
1077 }