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 = CreateFileA(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 = CreateFileA(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         win_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, dummy, 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     enumVar = (void *)0xdeadbeef;
731     hr = IUnknown_QueryInterface(unk, &IID_IXMLElementCollection, (LPVOID *)&enumVar);
732     ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
733     ok(enumVar == NULL || broken(enumVar == (void *)0xdeadbeef) /* XP */, "Expected NULL, got %p\n", enumVar);
734 
735     hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
736     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
737     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
738     IUnknown_Release(unk);
739 
740     /* <Number>1234</Number> */
741     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
742     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
743     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
744     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
745 
746     hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
747     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
748     ok(child != NULL, "Expected non-NULL child\n");
749 
750     VariantClear(&var);
751 
752     hr = IXMLElement_get_type(child, &type);
753     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
754     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
755 
756     hr = IXMLElement_get_tagName(child, &str);
757     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
758     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
759     SysFreeString(str);
760     IXMLElement_Release(child);
761 
762     /* <Name>Captain Ahab</Name> */
763     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
764     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
765     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
766     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
767 
768     /* try advance further, no children left */
769     V_VT(&dummy) = VT_I4;
770     hr = IEnumVARIANT_Next(enumVar, 1, &dummy, &num_vars);
771     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
772     ok(V_VT(&dummy) == VT_EMPTY, "Expected 0, got %d\n", V_VT(&dummy));
773     ok(num_vars == 0, "Expected 0, got %d\n", num_vars);
774 
775     V_VT(&dummy) = VT_I4;
776     hr = IEnumVARIANT_Next(enumVar, 1, &dummy, NULL);
777     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
778     ok(V_VT(&dummy) == VT_EMPTY, "Expected 0, got %d\n", V_VT(&dummy));
779 
780     hr = IDispatch_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
781     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
782     ok(child != NULL, "Expected non-NULL child\n");
783 
784     VariantClear(&var);
785 
786     hr = IXMLElement_get_type(child, &type);
787     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
788     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
789 
790     hr = IXMLElement_get_tagName(child, &str);
791     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
792     ok(!lstrcmpW(str, szName), "Expected NAME\n");
793     SysFreeString(str);
794     IXMLElement_Release(child);
795 
796     /* <Number>1234</Number> */
797     V_VT(&vIndex) = VT_I4;
798     V_I4(&vIndex) = 0;
799     V_VT(&vName) = VT_ERROR;
800     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
801     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
802     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
803     ok(child != NULL, "Expected non-NULL child\n");
804 
805     hr = IXMLElement_get_type(child, &type);
806     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
807     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
808 
809     hr = IXMLElement_get_tagName(child, &str);
810     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
811     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
812     SysFreeString(str);
813     IXMLElement_Release(child);
814 
815     /* <Name>Captain Ahab</Name> */
816     V_VT(&vIndex) = VT_I4;
817     V_I4(&vIndex) = 1;
818     V_VT(&vName) = VT_ERROR;
819     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
820     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
821     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
822     ok(child != NULL, "Expected non-NULL child\n");
823 
824     hr = IXMLElement_get_type(child, &type);
825     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
826     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
827 
828     hr = IXMLElement_get_tagName(child, &str);
829     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
830     ok(!lstrcmpW(str, szName), "Expected NAME\n");
831     SysFreeString(str);
832     IXMLElement_Release(child);
833 
834     V_I4(&vIndex) = 100;
835     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
836     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
837     ok(child == NULL, "Expected NULL child\n");
838 
839     V_I4(&vIndex) = -1;
840     child = (IXMLElement *)0xdeadbeef;
841     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
842     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
843     ok(child == NULL, "Expected NULL child\n");
844 
845     IEnumVARIANT_Release(enumVar);
846     IXMLElement_Release(element);
847     IXMLElementCollection_Release(collection);
848 cleanup:
849     IXMLDocument_Release(doc);
850     DeleteFileA("bank.xml");
851 }
852 
853 static void test_xmlelem(void)
854 {
855     HRESULT hr;
856     IXMLDocument *doc = NULL;
857     IXMLElement *element = NULL, *parent;
858     IXMLElement *child, *child2;
859     IXMLElementCollection *children;
860     VARIANT vType, vName;
861     VARIANT vIndex, vValue;
862     BSTR str, val, name;
863     LONG type, num_child;
864     IDispatch *disp;
865     ITypeInfo *ti;
866 
867     static const WCHAR propName[] = {'p','r','o','p',0};
868     static const WCHAR propVal[] = {'v','a','l',0};
869     static const WCHAR nextVal[] = {'n','e','x','t',0};
870     static const WCHAR noexist[] = {'n','o','e','x','i','s','t',0};
871     static const WCHAR crazyCase1[] = {'C','R','a','z','Y','c','A','S','E',0};
872     static const WCHAR crazyCase2[] = {'C','R','A','Z','Y','C','A','S','E',0};
873 
874     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
875                           &IID_IXMLDocument, (LPVOID*)&doc);
876     EXPECT_HR(hr, S_OK);
877 
878     V_VT(&vType) = VT_I4;
879     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
880     V_VT(&vName) = VT_NULL;
881     hr = IXMLDocument_createElement(doc, vType, vName, &element);
882     EXPECT_HR(hr, S_OK);
883     ok(element != NULL, "Expected non-NULL element\n");
884 
885     /* test for IDispatch */
886     disp = NULL;
887     hr = IXMLElement_QueryInterface(element, &IID_IDispatch, (void**)&disp);
888     EXPECT_HR(hr, S_OK);
889 
890     hr = IDispatch_GetTypeInfo(disp, 0, 0, &ti);
891     EXPECT_HR(hr, S_OK);
892 
893     name = NULL;
894     hr = ITypeInfo_GetDocumentation(ti, DISPID_XMLELEMENT_TAGNAME, &name, NULL, NULL, NULL);
895     EXPECT_HR(hr, S_OK);
896     SysFreeString(name);
897 
898     ITypeInfo_Release(ti);
899     IDispatch_Release(disp);
900 
901     hr = IXMLElement_get_tagName(element, &str);
902     EXPECT_HR(hr, S_OK);
903     ok(!str, "Expected empty tag name, got %s\n", wine_dbgstr_w(str));
904     SysFreeString(str);
905 
906     parent = (IXMLElement *)0xdeadbeef;
907     hr = IXMLElement_get_parent(element, &parent);
908     ok(hr == 1, "Expected 1, got %08x\n", hr);
909     ok(parent == NULL, "Expected NULL parent\n");
910 
911     str = SysAllocString(noexist);
912     hr = IXMLElement_getAttribute(element, str, &vValue);
913     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
914     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
915     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
916     VariantClear(&vValue);
917     SysFreeString(str);
918 
919     str = SysAllocString(crazyCase1);
920     val = SysAllocString(propVal);
921     V_VT(&vValue) = VT_BSTR;
922     V_BSTR(&vValue) = val;
923     hr = IXMLElement_setAttribute(element, str, vValue);
924     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
925     SysFreeString(str);
926     SysFreeString(val);
927 
928     str = SysAllocString(crazyCase2);
929     hr = IXMLElement_getAttribute(element, str, &vValue);
930     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
931     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
932     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
933     VariantClear(&vValue);
934     SysFreeString(str);
935 
936     str = SysAllocString(propName);
937     val = SysAllocString(propVal);
938     V_VT(&vValue) = VT_BSTR;
939     V_BSTR(&vValue) = val;
940     hr = IXMLElement_setAttribute(element, str, vValue);
941     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
942     SysFreeString(val);
943 
944     hr = IXMLElement_getAttribute(element, str, &vValue);
945     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
946     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
947     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
948     VariantClear(&vValue);
949 
950     hr = IXMLElement_removeAttribute(element, str);
951     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
952 
953     /* remove now nonexistent attribute */
954     hr = IXMLElement_removeAttribute(element, str);
955     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
956 
957     hr = IXMLElement_getAttribute(element, str, &vValue);
958     ok(hr == 1, "Expected 1, got %08x\n", hr);
959     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
960     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
961     SysFreeString(str);
962     VariantClear(&vValue);
963 
964     children = (IXMLElementCollection *)0xdeadbeef;
965     hr = IXMLElement_get_children(element, &children);
966     ok(hr == 1, "Expected 1, got %08x\n", hr);
967     ok(children == NULL, "Expected NULL collection\n");
968 
969     hr = IXMLElement_get_type(element, &type);
970     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
971     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
972 
973     hr = IXMLElement_get_text(element, &str);
974     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
975     ok(lstrlenW(str) == 0, "Expected empty text\n");
976     SysFreeString(str);
977 
978     /* put_text with an ELEMENT */
979     str = SysAllocString(propVal);
980     hr = IXMLElement_put_text(element, str);
981     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
982     SysFreeString(str);
983 
984     V_VT(&vType) = VT_I4;
985     V_I4(&vType) = XMLELEMTYPE_TEXT;
986     V_VT(&vName) = VT_NULL;
987     hr = IXMLDocument_createElement(doc, vType, vName, &child);
988     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
989     ok(child != NULL, "Expected non-NULL child\n");
990 
991     hr = IXMLElement_addChild(element, child, 0, -1);
992     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
993 
994     str = SysAllocString(propVal);
995     hr = IXMLElement_put_text(child, str);
996     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
997     SysFreeString(str);
998 
999     parent = (IXMLElement *)0xdeadbeef;
1000     hr = IXMLElement_get_parent(child, &parent);
1001     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1002     ok(parent != element, "Expected parent != element\n");
1003 
1004     hr = IXMLElement_get_type(parent, &type);
1005     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1006     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
1007 
1008     children = (IXMLElementCollection *)0xdeadbeef;
1009     hr = IXMLElement_get_children(element, &children);
1010     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1011     ok(children != NULL, "Expected non-NULL collection\n");
1012 
1013     hr = IXMLElementCollection_get_length(children, &num_child);
1014     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1015     ok(num_child == 1, "Expected 1, got %d\n", num_child);
1016 
1017     V_VT(&vIndex) = VT_I4;
1018     V_I4(&vIndex) = 0;
1019     V_VT(&vName) = VT_ERROR;
1020     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
1021     hr = IXMLElementCollection_item(children, vIndex, vName, (IDispatch **)&child2);
1022     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1023     ok(child2 != NULL, "Expected non-NULL child\n");
1024 
1025     hr = IXMLElement_get_type(child2, &type);
1026     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1027     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
1028 
1029     hr = IXMLElement_get_text(element, &str);
1030     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1031     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
1032     SysFreeString(str);
1033 
1034     hr = IXMLElement_get_text(child2, &str);
1035     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1036     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
1037     SysFreeString(str);
1038 
1039     /* try put_text on ELEMENT again, now that it has a text child */
1040     str = SysAllocString(nextVal);
1041     hr = IXMLElement_put_text(element, str);
1042     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
1043     SysFreeString(str);
1044 
1045     str = SysAllocString(nextVal);
1046     hr = IXMLElement_put_text(child2, str);
1047     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1048     SysFreeString(str);
1049 
1050     hr = IXMLElement_get_text(element, &str);
1051     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
1052     ok(!lstrcmpW(str, nextVal), "Expected 'val'\n");
1053     SysFreeString(str);
1054 
1055     IXMLElement_Release(child2);
1056     IXMLElementCollection_Release(children);
1057     IXMLElement_Release(parent);
1058     IXMLElement_Release(child);
1059     IXMLElement_Release(element);
1060     IXMLDocument_Release(doc);
1061 }
1062 
1063 START_TEST(xmldoc)
1064 {
1065     HRESULT hr;
1066 
1067     hr = CoInitialize(NULL);
1068     ok(hr == S_OK, "failed to init com\n");
1069 
1070     if (!test_try_xmldoc())
1071     {
1072         CoUninitialize();
1073         return;
1074     }
1075 
1076     test_xmldoc();
1077     test_createElement();
1078     test_persiststreaminit();
1079     test_xmlelem();
1080     test_xmlelem_collection();
1081     test_xmlelem_children();
1082 
1083     CoUninitialize();
1084 }
1085