shell32: Fix interface leak while adding tree items.
[wine] / dlls / msxml3 / tests / xmlelem.c
1 /*
2  * IXMLElement 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
25 #include "windows.h"
26 #include "ole2.h"
27 #include "msxml2.h"
28 #include "ocidl.h"
29
30 #include "wine/test.h"
31
32 #define ERROR_URL_NOT_FOUND 0x800c0006
33
34 static void test_xmlelem(void)
35 {
36     HRESULT hr;
37     IXMLDocument *doc = NULL;
38     IXMLElement *element = NULL, *parent;
39     IXMLElement *child, *child2;
40     IXMLElementCollection *children;
41     VARIANT vType, vName;
42     VARIANT vIndex, vValue;
43     BSTR str, val;
44     LONG type, num_child;
45
46     static const WCHAR propName[] = {'p','r','o','p',0};
47     static const WCHAR propVal[] = {'v','a','l',0};
48     static const WCHAR nextVal[] = {'n','e','x','t',0};
49     static const WCHAR noexist[] = {'n','o','e','x','i','s','t',0};
50     static const WCHAR crazyCase1[] = {'C','R','a','z','Y','c','A','S','E',0};
51     static const WCHAR crazyCase2[] = {'C','R','A','Z','Y','C','A','S','E',0};
52
53     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
54                           &IID_IXMLDocument, (LPVOID*)&doc);
55     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
56
57     V_VT(&vType) = VT_I4;
58     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
59     V_VT(&vName) = VT_NULL;
60     hr = IXMLDocument_createElement(doc, vType, vName, &element);
61     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
62     ok(element != NULL, "Expected non-NULL element\n");
63
64     hr = IXMLElement_get_tagName(element, &str);
65     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
66     ok(lstrlenW(str) == 0, "Expected empty tag name\n");
67     SysFreeString(str);
68
69     parent = (IXMLElement *)0xdeadbeef;
70     hr = IXMLElement_get_parent(element, &parent);
71     ok(hr == 1, "Expected 1, got %08x\n", hr);
72     ok(parent == NULL, "Expected NULL parent\n");
73
74     str = SysAllocString(noexist);
75     hr = IXMLElement_getAttribute(element, str, &vValue);
76     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
77     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
78     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
79     VariantClear(&vValue);
80     SysFreeString(str);
81
82     str = SysAllocString(crazyCase1);
83     val = SysAllocString(propVal);
84     V_VT(&vValue) = VT_BSTR;
85     V_BSTR(&vValue) = val;
86     hr = IXMLElement_setAttribute(element, str, vValue);
87     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
88     SysFreeString(str);
89     SysFreeString(val);
90
91     str = SysAllocString(crazyCase2);
92     hr = IXMLElement_getAttribute(element, str, &vValue);
93     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
94     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
95     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
96     VariantClear(&vValue);
97     SysFreeString(str);
98
99     str = SysAllocString(propName);
100     val = SysAllocString(propVal);
101     V_VT(&vValue) = VT_BSTR;
102     V_BSTR(&vValue) = val;
103     hr = IXMLElement_setAttribute(element, str, vValue);
104     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
105     SysFreeString(val);
106
107     hr = IXMLElement_getAttribute(element, str, &vValue);
108     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
109     ok(V_VT(&vValue) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&vValue));
110     ok(!lstrcmpW(V_BSTR(&vValue), propVal), "Expected 'val'\n");
111     VariantClear(&vValue);
112
113     hr = IXMLElement_removeAttribute(element, str);
114     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
115
116     /* remove now nonexistent attribute */
117     hr = IXMLElement_removeAttribute(element, str);
118     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
119
120     hr = IXMLElement_getAttribute(element, str, &vValue);
121     ok(hr == 1, "Expected 1, got %08x\n", hr);
122     ok(V_VT(&vValue) == VT_EMPTY, "Expected VT_EMPTY, got %d\n", V_VT(&vValue));
123     ok(V_BSTR(&vValue) == NULL, "Expected null value\n");
124     SysFreeString(str);
125     VariantClear(&vValue);
126
127     children = (IXMLElementCollection *)0xdeadbeef;
128     hr = IXMLElement_get_children(element, &children);
129     ok(hr == 1, "Expected 1, got %08x\n", hr);
130     ok(children == NULL, "Expected NULL collection\n");
131
132     hr = IXMLElement_get_type(element, &type);
133     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
134     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
135
136     hr = IXMLElement_get_text(element, &str);
137     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
138     ok(lstrlenW(str) == 0, "Expected empty text\n");
139     SysFreeString(str);
140
141     /* put_text with an ELEMENT */
142     str = SysAllocString(propVal);
143     hr = IXMLElement_put_text(element, str);
144     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
145     SysFreeString(str);
146
147     V_VT(&vType) = VT_I4;
148     V_I4(&vType) = XMLELEMTYPE_TEXT;
149     V_VT(&vName) = VT_NULL;
150     hr = IXMLDocument_createElement(doc, vType, vName, &child);
151     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
152     ok(child != NULL, "Expected non-NULL child\n");
153
154     hr = IXMLElement_addChild(element, child, 0, -1);
155     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
156
157     str = SysAllocString(propVal);
158     hr = IXMLElement_put_text(child, str);
159     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
160     SysFreeString(str);
161
162     parent = (IXMLElement *)0xdeadbeef;
163     hr = IXMLElement_get_parent(child, &parent);
164     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
165     ok(parent != element, "Expected parent != element\n");
166
167     hr = IXMLElement_get_type(parent, &type);
168     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
169     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
170
171     children = (IXMLElementCollection *)0xdeadbeef;
172     hr = IXMLElement_get_children(element, &children);
173     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
174     ok(children != NULL, "Expected non-NULL collection\n");
175
176     hr = IXMLElementCollection_get_length(children, &num_child);
177     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
178     ok(num_child == 1, "Expected 1, got %d\n", num_child);
179
180     V_VT(&vIndex) = VT_I4;
181     V_I4(&vIndex) = 0;
182     V_VT(&vName) = VT_ERROR;
183     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
184     hr = IXMLElementCollection_item(children, vIndex, vName, (IDispatch **)&child2);
185     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
186     ok(child2 != NULL, "Expected non-NULL child\n");
187
188     hr = IXMLElement_get_type(child2, &type);
189     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
190     ok(type == XMLELEMTYPE_TEXT, "Expected XMLELEMTYPE_TEXT, got %d\n", type);
191
192     hr = IXMLElement_get_text(element, &str);
193     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
194     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
195     SysFreeString(str);
196
197     hr = IXMLElement_get_text(child2, &str);
198     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
199     ok(!lstrcmpW(str, propVal), "Expected 'val'\n");
200     SysFreeString(str);
201
202     /* try put_text on ELEMENT again, now that it has a text child */
203     str = SysAllocString(nextVal);
204     hr = IXMLElement_put_text(element, str);
205     ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
206     SysFreeString(str);
207
208     str = SysAllocString(nextVal);
209     hr = IXMLElement_put_text(child2, str);
210     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
211     SysFreeString(str);
212
213     hr = IXMLElement_get_text(element, &str);
214     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
215     ok(!lstrcmpW(str, nextVal), "Expected 'val'\n");
216     SysFreeString(str);
217
218     IXMLElement_Release(child2);
219     IXMLElementCollection_Release(children);
220     IXMLElement_Release(parent);
221     IXMLElement_Release(child);
222     IXMLElement_Release(element);
223     IXMLDocument_Release(doc);
224 }
225
226 static void create_xml_file(LPCSTR filename)
227 {
228     DWORD dwNumberOfBytesWritten;
229     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
230                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
231
232     static const char data[] =
233         "<?xml version=\"1.0\" ?>\n"
234         "<BankAccount>\n"
235         "  <Number>1234</Number>\n"
236         "  <Name>Captain Ahab</Name>\n"
237         "</BankAccount>\n";
238
239     WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
240     CloseHandle(hf);
241 }
242
243 static void test_xmlelem_collection(void)
244 {
245     HRESULT hr;
246     IUnknown *unk = NULL;
247     IXMLDocument *doc = NULL;
248     IXMLElement *element = NULL, *child;
249     IXMLElementCollection *collection = NULL;
250     IEnumVARIANT *enumVar = NULL;
251     CHAR pathA[MAX_PATH];
252     WCHAR path[MAX_PATH];
253     LONG length, type;
254     ULONG num_vars;
255     VARIANT var, vIndex, vName;
256     BSTR url, str;
257     static const CHAR szBankXML[] = "bank.xml";
258     static const WCHAR szNumber[] = {'N','U','M','B','E','R',0};
259     static const WCHAR szName[] = {'N','A','M','E',0};
260
261     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
262                           &IID_IXMLDocument, (LPVOID*)&doc);
263     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
264
265     create_xml_file(szBankXML);
266     GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL);
267     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
268
269     url = SysAllocString(path);
270     hr = IXMLDocument_put_URL(doc, url);
271     ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
272     SysFreeString(url);
273
274     if(hr != S_OK)
275         goto cleanup;
276
277     hr = IXMLDocument_get_root(doc, &element);
278     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
279     ok(element != NULL, "Expected non-NULL element\n");
280
281     hr = IXMLElement_get_children(element, &collection);
282     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
283     ok(collection != NULL, "Expected non-NULL collection\n");
284
285     hr = IXMLElementCollection_get_length(collection, NULL);
286     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
287
288     hr = IXMLElementCollection_get_length(collection, &length);
289     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
290     ok(length == 2, "Expected 2, got %d\n", length);
291
292     /* IXMLElementCollection:put_length does nothing */
293     hr = IXMLElementCollection_put_length(collection, -1);
294     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
295
296     hr = IXMLElementCollection_put_length(collection, 0);
297     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
298
299     hr = IXMLElementCollection_put_length(collection, 1);
300     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
301
302     hr = IXMLElementCollection_put_length(collection, 2);
303     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
304
305     hr = IXMLElementCollection_put_length(collection, 3);
306     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
307
308     hr = IXMLElementCollection_put_length(collection, 50);
309     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
310
311     /* make sure the length hasn't changed */
312     hr = IXMLElementCollection_get_length(collection, &length);
313     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
314     ok(length == 2, "Expected 2, got %d\n", length);
315
316     /* IXMLElementCollection implements IEnumVARIANT */
317     hr = IXMLElementCollection_QueryInterface(collection, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
318     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
319     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
320     IEnumVARIANT_Release(enumVar);
321
322     hr = IXMLElementCollection_get__newEnum(collection, &unk);
323     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
324     ok(unk != NULL, "Expected non-NULL unk\n");
325
326     hr = IUnknown_QueryInterface(unk, &IID_IEnumVARIANT, (LPVOID *)&enumVar);
327     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
328     ok(enumVar != NULL, "Expected non-NULL enumVar\n");
329     IUnknown_Release(unk);
330
331     /* <Number>1234</Number> */
332     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
333     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
334     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
335     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
336
337     hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
338     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
339     ok(child != NULL, "Expected non-NULL child\n");
340
341     VariantClear(&var);
342
343     hr = IXMLElement_get_type(child, &type);
344     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
345     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
346
347     hr = IXMLElement_get_tagName(child, &str);
348     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
349     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
350     SysFreeString(str);
351     IXMLElement_Release(child);
352
353     /* <Name>Captain Ahab</Name> */
354     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
355     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
356     ok(V_VT(&var) == VT_DISPATCH, "Expected VT_DISPATCH, got %d\n", V_VT(&var));
357     ok(num_vars == 1, "Expected 1, got %d\n", num_vars);
358
359     /* try advance further, no children left */
360     hr = IEnumVARIANT_Next(enumVar, 1, &var, &num_vars);
361     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
362     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
363     ok(num_vars == 0, "Expected 0, got %d\n", num_vars);
364
365     hr = IEnumVARIANT_Next(enumVar, 1, &var, NULL);
366     ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
367     ok(V_VT(&var) == 0, "Expected 0, got %d\n", V_VT(&var));
368
369     hr = IUnknown_QueryInterface(V_DISPATCH(&var), &IID_IXMLElement, (LPVOID *)&child);
370     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
371     ok(child != NULL, "Expected non-NULL child\n");
372
373     VariantClear(&var);
374
375     hr = IXMLElement_get_type(child, &type);
376     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
377     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
378
379     hr = IXMLElement_get_tagName(child, &str);
380     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
381     ok(!lstrcmpW(str, szName), "Expected NAME\n");
382     SysFreeString(str);
383     IXMLElement_Release(child);
384
385     /* <Number>1234</Number> */
386     V_VT(&vIndex) = VT_I4;
387     V_I4(&vIndex) = 0;
388     V_VT(&vName) = VT_ERROR;
389     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
390     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
391     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
392     ok(child != NULL, "Expected non-NULL child\n");
393
394     hr = IXMLElement_get_type(child, &type);
395     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
396     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
397
398     hr = IXMLElement_get_tagName(child, &str);
399     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
400     ok(!lstrcmpW(str, szNumber), "Expected NUMBER\n");
401     SysFreeString(str);
402     IXMLElement_Release(child);
403
404     /* <Name>Captain Ahab</Name> */
405     V_VT(&vIndex) = VT_I4;
406     V_I4(&vIndex) = 1;
407     V_VT(&vName) = VT_ERROR;
408     V_ERROR(&vName) = DISP_E_PARAMNOTFOUND;
409     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
410     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
411     ok(child != NULL, "Expected non-NULL child\n");
412
413     hr = IXMLElement_get_type(child, &type);
414     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
415     ok(type == XMLELEMTYPE_ELEMENT, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type);
416
417     hr = IXMLElement_get_tagName(child, &str);
418     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
419     ok(!lstrcmpW(str, szName), "Expected NAME\n");
420     SysFreeString(str);
421     IXMLElement_Release(child);
422
423     V_I4(&vIndex) = 100;
424     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
425     ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
426     ok(child == NULL, "Expected NULL child\n");
427
428     V_I4(&vIndex) = -1;
429     child = (IXMLElement *)0xdeadbeef;
430     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child);
431     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
432     ok(child == NULL, "Expected NULL child\n");
433
434     IEnumVARIANT_Release(enumVar);
435     IXMLElement_Release(element);
436     IXMLElementCollection_Release(collection);
437 cleanup:
438     IXMLDocument_Release(doc);
439     DeleteFileA("bank.xml");
440 }
441
442 static void test_xmlelem_children(void)
443 {
444     IXMLDocument *doc = NULL;
445     IXMLElement *element = NULL, *child = NULL, *child2 = NULL;
446     IXMLElementCollection *collection = NULL;
447     VARIANT vType, vName, vIndex;
448     LONG length;
449     HRESULT hr;
450
451     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
452                           &IID_IXMLDocument, (LPVOID*)&doc);
453     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
454
455     V_VT(&vType) = VT_I4;
456     V_I4(&vType) = XMLELEMTYPE_ELEMENT;
457     V_VT(&vName) = VT_NULL;
458     hr = IXMLDocument_createElement(doc, vType, vName, &element);
459     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
460     ok(element != NULL, "Expected non-NULL element\n");
461
462     V_VT(&vType) = VT_I4;
463     V_I4(&vType) = XMLELEMTYPE_TEXT;
464     V_VT(&vName) = VT_NULL;
465     hr = IXMLDocument_createElement(doc, vType, vName, &child);
466     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
467     ok(child != NULL, "Expected non-NULL child\n");
468
469     V_VT(&vType) = VT_I4;
470     V_I4(&vType) = XMLELEMTYPE_TEXT;
471     V_VT(&vName) = VT_NULL;
472     hr = IXMLDocument_createElement(doc, vType, vName, &child2);
473     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
474     ok(child2 != NULL, "Expected non-NULL child\n");
475
476     hr = IXMLElement_addChild(element, child, 0, -1);
477     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
478
479     hr = IXMLElement_get_children(element, &collection);
480     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
481     ok(collection != NULL, "Expected non-NULL collection\n");
482
483     length = 0;
484     hr = IXMLElementCollection_get_length(collection, &length);
485     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
486     ok(length == 1, "Expected 1, got %08x\n", length);
487
488     /* remove/add child and check what happens with collection */
489     hr = IXMLElement_removeChild(element, child);
490     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
491
492     length = -1;
493     hr = IXMLElementCollection_get_length(collection, &length);
494     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
495     ok(length == 0, "Expected 0, got %08x\n", length);
496     IXMLElementCollection_Release(collection);
497
498     hr = IXMLElement_AddRef(child);
499     ok(hr == 2, "Expected 2, got %08x\n", hr);
500     IXMLElement_Release(child);
501     hr = IXMLElement_addChild(element, child, 0, -1);
502     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
503     hr = IXMLElement_AddRef(child);
504     ok(hr == 2, "Expected 2, got %08x\n", hr);
505     IXMLElement_Release(child);
506     hr = IXMLElement_addChild(element, child2, 0, -1);
507     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
508
509     hr = IXMLElement_get_children(element, &collection);
510     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
511     ok(collection != NULL, "Expected non-NULL collection\n");
512
513     hr = IXMLElement_AddRef(child);
514     ok(hr == 2, "Expected 2, got %08x\n", hr);
515     IXMLElement_Release(child);
516
517     length = 0;
518     hr = IXMLElementCollection_get_length(collection, &length);
519     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
520     ok(length == 2, "Expected 2, got %08x\n", length);
521
522     IXMLElement_Release(child2);
523
524     length = 0;
525     hr = IXMLElementCollection_get_length(collection, &length);
526     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
527     ok(length == 2, "Expected 2, got %08x\n", length);
528
529     V_VT(&vIndex) = VT_I4;
530     V_I4(&vIndex) = 1;
531     hr = IXMLElementCollection_item(collection, vIndex, vName, (IDispatch **)&child2);
532     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
533     ok(child2 != NULL, "Expected not NULL child\n");
534     IXMLElementCollection_Release(collection);
535     IXMLElement_Release(child2);
536
537     /* add element->child->child2 structure, then remove child2 from node */
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, &child2);
542     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
543     ok(child2 != NULL, "Expected non-NULL child\n");
544
545     hr = IXMLElement_addChild(child, child2, 0, -1);
546     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
547
548     hr = IXMLElement_removeChild(element, child2);
549     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
550
551     hr = IXMLElement_removeChild(child, child2);
552     ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
553
554     hr = IXMLElement_removeChild(child, NULL);
555     ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
556
557     IXMLElement_Release(element);
558     IXMLElement_Release(child);
559     IXMLElement_Release(child2);
560     IXMLDocument_Release(doc);
561 }
562
563 static BOOL test_try_xmldoc(void)
564 {
565     IXMLDocument *doc = NULL;
566     HRESULT hr;
567
568     hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
569                           &IID_IXMLDocument, (LPVOID*)&doc);
570     if (FAILED(hr))
571     {
572         skip("Failed to create XMLDocument instance\n");
573         return FALSE;
574     }
575
576     IXMLDocument_Release(doc);
577     return TRUE;
578 }
579
580 START_TEST(xmlelem)
581 {
582     HRESULT hr;
583
584     hr = CoInitialize(NULL);
585     ok(hr == S_OK, "failed to init com\n");
586
587     if (!test_try_xmldoc())
588     {
589         CoUninitialize();
590         return;
591     }
592
593     test_xmlelem();
594     test_xmlelem_collection();
595     test_xmlelem_children();
596
597     CoUninitialize();
598 }