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