4 * Copyright 2007 James Hawkins
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.
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.
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
29 #include "wine/test.h"
31 /* Deprecated Error Code */
32 #define XML_E_INVALIDATROOTLEVEL 0xc00ce556
34 static void create_xml_file(LPCSTR filename)
36 DWORD dwNumberOfBytesWritten;
37 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
38 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
40 static const char data[] =
41 "<?xml version=\"1.0\" ?>\n"
42 "<!DOCTYPE BankAccount>\n"
44 " <Number>1234</Number>\n"
45 " <Name>Captain Ahab</Name>\n"
48 WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
53 static void create_xml_file(LPCSTR filename)
55 DWORD dwNumberOfBytesWritten;
56 HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
57 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
59 static const char data[] =
60 "<?xml version=\"1.0\" ?>\n"
62 " <Number>1234</Number>\n"
63 " <Name>Captain Ahab</Name>\n"
66 WriteFile(hf, data, sizeof(data) - 1, &dwNumberOfBytesWritten, NULL);
71 static void create_stream_on_file(IStream **stream, LPCSTR path)
77 DWORD file_size, read;
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);
84 hglobal = GlobalAlloc(GHND, file_size);
85 ptr = GlobalLock(hglobal);
87 ReadFile(hfile, ptr, file_size, &read, NULL);
88 ok(file_size == read, "Expected to read the whole file, read %d\n", read);
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");
95 GlobalUnlock(hglobal);
98 static void test_xmldoc(void)
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;
107 LONG type, num_child;
108 VARIANT vIndex, vName;
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};
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);
122 create_xml_file("bank.xml");
123 GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
124 create_stream_on_file(&stream, path);
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");
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");
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)
139 ok(stream != NULL, "Expected non-NULL stream\n");
142 hr = IXMLDocument_get_version(doc, NULL);
143 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
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));
151 hr = IXMLDocument_get_doctype(doc, NULL);
152 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
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));
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");
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);
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);
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");
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");
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);
187 V_VT(&vIndex) = VT_I4;
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");
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);
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");
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");
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);
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");
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);
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");
225 IXMLElementCollection_Release(inner);
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);
232 IXMLElement_Release(value);
233 IXMLElement_Release(child);
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");
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);
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");
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");
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);
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");
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);
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");
273 IXMLElementCollection_Release(inner);
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);
280 IXMLElement_Release(value);
281 IXMLElement_Release(child);
282 IXMLElementCollection_Release(collection);
283 IXMLElement_Release(element);
285 IStream_Release(stream);
286 IPersistStreamInit_Release(psi);
287 IXMLDocument_Release(doc);
289 DeleteFileA("bank.xml");
292 static void test_createElement(void)
295 IXMLDocument *doc = NULL;
296 IXMLElement *element = NULL, *root = NULL;
297 VARIANT vType, vName;
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);
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");
312 /* invalid vType value */
313 V_VT(&vType) = VT_I4;
315 V_VT(&vName) = VT_NULL;
316 hr = IXMLDocument_createElement(doc, vType, vName, &element);
317 /* Up to and including SP7, createElement returns an element. */
320 ok(element != NULL, "Expected element\n");
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);
329 IXMLElement_Release(element);
334 ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
335 ok(element == NULL, "Expected NULL element\n");
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");
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);
350 IXMLElement_Release(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);
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");
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");
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");
377 IXMLElement_Release(element);
378 IXMLDocument_Release(doc);
381 static void test_persiststreaminit(void)
383 IXMLDocument *doc = NULL;
384 IXMLElement *element = NULL;
385 IPersistStreamInit *psi = NULL;
386 IStream *stream = NULL;
393 static const WCHAR testW[] = {'t','e','s','t',0};
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);
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");
404 hr = IPersistStreamInit_GetSizeMax(psi, NULL);
405 ok(hr == E_NOTIMPL, "Expected E_NOTIMPL, got %08x\n", hr);
407 hr = IPersistStreamInit_Load(psi, NULL);
408 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
410 hr = IPersistStreamInit_Save(psi, NULL, FALSE);
411 todo_wine ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
413 hr = IPersistStreamInit_GetClassID(psi, NULL);
414 ok(hr == E_POINTER, "Expected E_POINTER, got %08x\n", hr);
416 hr = IPersistStreamInit_IsDirty(psi);
417 todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
419 create_xml_file("bank.xml");
420 GetFullPathNameA("bank.xml", MAX_PATH, path, NULL);
421 create_stream_on_file(&stream, path);
423 /* GetSizeMax not implemented */
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");
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)
435 hr = IPersistStreamInit_IsDirty(psi);
436 todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
438 /* try to save document */
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);
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);
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);
459 hr = IPersistStreamInit_IsDirty(psi);
460 todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
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);
467 hr = IPersistStreamInit_IsDirty(psi);
468 todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
470 /* reset internal stream */
471 hr = IPersistStreamInit_InitNew(psi);
472 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
474 hr = IPersistStreamInit_IsDirty(psi);
475 todo_wine ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
478 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
479 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
481 hr = IPersistStreamInit_Save(psi, stream, FALSE);
482 todo_wine ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
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);
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");
496 IPersistStreamInit_Release(psi);
497 IXMLDocument_Release(doc);
498 DeleteFileA("bank.xml");
501 static BOOL test_try_xmldoc(void)
503 IXMLDocument *doc = NULL;
506 hr = CoCreateInstance(&CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER,
507 &IID_IXMLDocument, (LPVOID*)&doc);
510 skip("Failed to create XMLDocument instance\n");
514 IXMLDocument_Release(doc);
518 static void test_xmlelem_children(void)
520 IXMLDocument *doc = NULL;
521 IXMLElement *element = NULL, *child = NULL, *child2 = NULL;
522 IXMLElementCollection *collection = NULL;
523 VARIANT vType, vName, vIndex;
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);
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");
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");
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");
552 hr = IXMLElement_addChild(element, child, 0, -1);
553 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
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");
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);
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);
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);
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);
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");
589 hr = IXMLElement_AddRef(child);
590 ok(hr == 2, "Expected 2, got %08x\n", hr);
591 IXMLElement_Release(child);
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);
598 IXMLElement_Release(child2);
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);
605 V_VT(&vIndex) = VT_I4;
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);
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");
621 hr = IXMLElement_addChild(child, child2, 0, -1);
622 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
624 hr = IXMLElement_removeChild(element, child2);
625 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
627 hr = IXMLElement_removeChild(child, child2);
628 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
630 hr = IXMLElement_removeChild(child, NULL);
631 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
633 IXMLElement_Release(element);
634 IXMLElement_Release(child);
635 IXMLElement_Release(child2);
636 IXMLDocument_Release(doc);
639 static void test_xmlelem_collection(void)
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];
651 VARIANT var, vIndex, vName;
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};
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);
661 create_xml_file(szBankXML);
662 GetFullPathNameA(szBankXML, MAX_PATH, pathA, NULL);
663 MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
665 url = SysAllocString(path);
666 hr = IXMLDocument_put_URL(doc, url);
667 ok(hr == S_OK, "Expected S_OK, got 0x%08x\n", hr);
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");
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");
681 hr = IXMLElementCollection_get_length(collection, NULL);
682 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
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);
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);
692 hr = IXMLElementCollection_put_length(collection, 0);
693 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
695 hr = IXMLElementCollection_put_length(collection, 1);
696 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
698 hr = IXMLElementCollection_put_length(collection, 2);
699 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
701 hr = IXMLElementCollection_put_length(collection, 3);
702 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
704 hr = IXMLElementCollection_put_length(collection, 50);
705 ok(hr == E_FAIL, "Expected E_FAIL, got %08x\n", hr);
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);
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);
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");
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);
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);
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");
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);
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");
747 IXMLElement_Release(child);
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);
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);
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));
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");
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);
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");
779 IXMLElement_Release(child);
781 /* <Number>1234</Number> */
782 V_VT(&vIndex) = VT_I4;
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");
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);
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");
798 IXMLElement_Release(child);
800 /* <Name>Captain Ahab</Name> */
801 V_VT(&vIndex) = VT_I4;
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");
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);
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");
817 IXMLElement_Release(child);
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");
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");
830 IEnumVARIANT_Release(enumVar);
831 IXMLElement_Release(element);
832 IXMLElementCollection_Release(collection);
834 IXMLDocument_Release(doc);
835 DeleteFileA("bank.xml");
838 static void test_xmlelem(void)
841 IXMLDocument *doc = NULL;
842 IXMLElement *element = NULL, *parent;
843 IXMLElement *child, *child2;
844 IXMLElementCollection *children;
845 VARIANT vType, vName;
846 VARIANT vIndex, vValue;
848 LONG type, num_child;
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};
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);
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");
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");
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");
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);
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);
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);
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);
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);
917 hr = IXMLElement_removeAttribute(element, str);
918 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
920 /* remove now nonexistent attribute */
921 hr = IXMLElement_removeAttribute(element, str);
922 ok(hr == S_FALSE, "Expected S_FALSE, got %08x\n", hr);
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");
929 VariantClear(&vValue);
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");
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);
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");
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);
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");
958 hr = IXMLElement_addChild(element, child, 0, -1);
959 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
961 str = SysAllocString(propVal);
962 hr = IXMLElement_put_text(child, str);
963 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
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");
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);
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");
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);
984 V_VT(&vIndex) = VT_I4;
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");
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);
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");
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");
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);
1012 str = SysAllocString(nextVal);
1013 hr = IXMLElement_put_text(child2, str);
1014 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
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");
1022 IXMLElement_Release(child2);
1023 IXMLElementCollection_Release(children);
1024 IXMLElement_Release(parent);
1025 IXMLElement_Release(child);
1026 IXMLElement_Release(element);
1027 IXMLDocument_Release(doc);
1034 hr = CoInitialize(NULL);
1035 ok(hr == S_OK, "failed to init com\n");
1037 if (!test_try_xmldoc())
1044 test_createElement();
1045 test_persiststreaminit();
1047 test_xmlelem_collection();
1048 test_xmlelem_children();