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