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
);
52 static void create_stream_on_file(IStream
**stream
, LPCSTR path
)
58 DWORD file_size
, read
;
60 hfile
= CreateFile(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
61 OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
62 ok(hfile
!= INVALID_HANDLE_VALUE
, "Expected a valid file handle\n");
63 file_size
= GetFileSize(hfile
, NULL
);
65 hglobal
= GlobalAlloc(GHND
, file_size
);
66 ptr
= GlobalLock(hglobal
);
68 ReadFile(hfile
, ptr
, file_size
, &read
, NULL
);
69 ok(file_size
== read
, "Expected to read the whole file, read %d\n", read
);
71 hr
= CreateStreamOnHGlobal(hglobal
, TRUE
, stream
);
72 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
73 ok(*stream
!= NULL
, "Expected non-NULL stream\n");
76 GlobalUnlock(hglobal
);
79 static void test_xmldoc(void)
82 IXMLDocument
*doc
= NULL
;
83 IXMLElement
*element
= NULL
, *child
= NULL
, *value
= NULL
;
84 IXMLElementCollection
*collection
= NULL
, *inner
= NULL
;
85 IPersistStreamInit
*psi
= NULL
;
86 IStream
*stream
= NULL
;
89 VARIANT vIndex
, vName
;
92 static const WCHAR szBankAccount
[] = {'B','A','N','K','A','C','C','O','U','N','T',0};
93 static const WCHAR szNumber
[] = {'N','U','M','B','E','R',0};
94 static const WCHAR szNumVal
[] = {'1','2','3','4',0};
95 static const WCHAR szName
[] = {'N','A','M','E',0};
96 static const WCHAR szNameVal
[] = {'C','a','p','t','a','i','n',' ','A','h','a','b',0};
97 static const WCHAR szVersion
[] = {'1','.','0',0};
99 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
100 &IID_IXMLDocument
, (LPVOID
*)&doc
);
101 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
103 create_xml_file("bank.xml");
104 GetFullPathNameA("bank.xml", MAX_PATH
, path
, NULL
);
105 create_stream_on_file(&stream
, path
);
107 hr
= IXMLDocument_QueryInterface(doc
, &IID_IPersistStreamInit
, (LPVOID
*)&psi
);
108 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
109 ok(psi
!= NULL
, "Expected non-NULL psi\n");
111 hr
= IXMLDocument_get_root(doc
, &element
);
112 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
113 ok(element
== NULL
, "Expected NULL element\n");
115 hr
= IPersistStreamInit_Load(psi
, stream
);
116 ok(hr
== S_OK
|| hr
== XML_E_INVALIDATROOTLEVEL
, "Expected S_OK, got %08x\n", hr
);
117 if(hr
== XML_E_INVALIDATROOTLEVEL
)
120 ok(stream
!= NULL
, "Expected non-NULL stream\n");
123 hr
= IXMLDocument_get_version(doc
, NULL
);
124 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
126 hr
= IXMLDocument_get_version(doc
, &name
);
127 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
128 ok(!lstrcmpW(name
, szVersion
), "Expected 1.0, got %s\n", wine_dbgstr_w(name
));
132 hr
= IXMLDocument_get_doctype(doc
, NULL
);
133 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
135 hr
= IXMLDocument_get_doctype(doc
, &name
);
136 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
137 ok(!lstrcmpW(name
, szBankAccount
), "Expected BANKACCOUNT, got %s\n", wine_dbgstr_w(name
));
140 hr
= IXMLDocument_get_root(doc
, &element
);
141 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
142 ok(element
!= NULL
, "Expected non-NULL element\n");
144 /* ::root() returns new instance each time */
145 hr
= IXMLDocument_get_root(doc
, &child
);
146 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
147 ok(child
!= NULL
, "Expected non-NULL element\n");
148 ok(child
!= element
, "Expected new element instance\n");
149 IXMLElement_Release(child
);
151 hr
= IXMLElement_get_type(element
, &type
);
152 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
153 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type
);
155 hr
= IXMLElement_get_tagName(element
, &name
);
156 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
157 ok(!lstrcmpW(name
, szBankAccount
), "Expected BANKACCOUNT\n");
160 hr
= IXMLElement_get_children(element
, &collection
);
161 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
162 ok(collection
!= NULL
, "Expected non-NULL collection\n");
164 hr
= IXMLElementCollection_get_length(collection
, &num_child
);
165 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
166 ok(num_child
== 2, "Expected 2, got %d\n", num_child
);
168 V_VT(&vIndex
) = VT_I4
;
170 V_VT(&vName
) = VT_ERROR
;
171 V_ERROR(&vName
) = DISP_E_PARAMNOTFOUND
;
172 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
173 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
174 ok(child
!= NULL
, "Expected non-NULL child\n");
176 hr
= IXMLElement_get_type(child
, &type
);
177 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
178 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type
);
180 hr
= IXMLElement_get_tagName(child
, &name
);
181 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
182 ok(!lstrcmpW(name
, szNumber
), "Expected NUMBER\n");
185 hr
= IXMLElement_get_children(child
, &inner
);
186 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
187 ok(inner
!= NULL
, "Expected non-NULL inner\n");
189 hr
= IXMLElementCollection_get_length(inner
, &num_child
);
190 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
191 ok(num_child
== 1, "Expected 1, got %d\n", num_child
);
193 hr
= IXMLElementCollection_item(inner
, vIndex
, vName
, (IDispatch
**)&value
);
194 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
195 ok(value
!= NULL
, "Expected non-NULL value\n");
197 hr
= IXMLElement_get_type(value
, &type
);
198 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
199 ok(type
== XMLELEMTYPE_TEXT
, "Expected XMLELEMTYPE_TEXT, got %d\n", type
);
201 hr
= IXMLElement_get_text(value
, &name
);
202 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
203 ok(!lstrcmpW(name
, szNumVal
), "Expected '1234'\n");
206 IXMLElementCollection_Release(inner
);
208 inner
= (IXMLElementCollection
*)0xdeadbeef;
209 hr
= IXMLElement_get_children(value
, &inner
);
210 ok(hr
== 1, "Expected 1, got %08x\n", hr
);
211 ok(inner
== NULL
, "Expected NULL inner, got %p\n", inner
);
213 IXMLElement_Release(value
);
214 IXMLElement_Release(child
);
219 hr
= IXMLElementCollection_item(collection
, vIndex
, vName
, (IDispatch
**)&child
);
220 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
221 ok(child
!= NULL
, "Expected non-NULL child\n");
223 hr
= IXMLElement_get_type(child
, &type
);
224 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
225 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type
);
227 hr
= IXMLElement_get_tagName(child
, &name
);
228 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
229 ok(!lstrcmpW(name
, szName
), "Expected NAME\n");
232 hr
= IXMLElement_get_children(child
, &inner
);
233 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
234 ok(inner
!= NULL
, "Expected non-NULL inner\n");
236 hr
= IXMLElementCollection_get_length(inner
, &num_child
);
237 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
238 ok(num_child
== 1, "Expected 1, got %d\n", num_child
);
241 hr
= IXMLElementCollection_item(inner
, vIndex
, vName
, (IDispatch
**)&value
);
242 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
243 ok(value
!= NULL
, "Expected non-NULL value\n");
245 hr
= IXMLElement_get_type(value
, &type
);
246 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
247 ok(type
== XMLELEMTYPE_TEXT
, "Expected XMLELEMTYPE_TEXT, got %d\n", type
);
249 hr
= IXMLElement_get_text(value
, &name
);
250 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
251 ok(!lstrcmpW(name
, szNameVal
), "Expected 'Captain Ahab'\n");
254 IXMLElementCollection_Release(inner
);
256 inner
= (IXMLElementCollection
*)0xdeadbeef;
257 hr
= IXMLElement_get_children(value
, &inner
);
258 ok(hr
== 1, "Expected 1, got %08x\n", hr
);
259 ok(inner
== NULL
, "Expected NULL inner, got %p\n", inner
);
261 IXMLElement_Release(value
);
262 IXMLElement_Release(child
);
263 IXMLElementCollection_Release(collection
);
264 IXMLElement_Release(element
);
266 IStream_Release(stream
);
267 IPersistStreamInit_Release(psi
);
268 IXMLDocument_Release(doc
);
270 DeleteFileA("bank.xml");
273 static void test_createElement(void)
276 IXMLDocument
*doc
= NULL
;
277 IXMLElement
*element
= NULL
, *root
= NULL
;
278 VARIANT vType
, vName
;
281 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
282 &IID_IXMLDocument
, (LPVOID
*)&doc
);
283 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
285 /* invalid vType type */
286 V_VT(&vType
) = VT_NULL
;
287 V_VT(&vName
) = VT_NULL
;
288 element
= (IXMLElement
*)0xdeadbeef;
289 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &element
);
290 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
291 ok(element
== NULL
, "Expected NULL element\n");
293 /* invalid vType value */
294 V_VT(&vType
) = VT_I4
;
296 V_VT(&vName
) = VT_NULL
;
297 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &element
);
298 /* Up to and including SP7, createElement returns an element. */
301 ok(element
!= NULL
, "Expected element\n");
304 hr
= IXMLElement_get_type(element
, &type
);
305 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
306 /* SP7 returns an XMLELEMTYPE_ELEMENT */
307 ok(type
== XMLELEMTYPE_OTHER
|| type
== XMLELEMTYPE_ELEMENT
,
308 "Expected XMLELEMTYPE_OTHER || XMLELEMTYPE_ELEMENT, got %d\n", type
);
310 IXMLElement_Release(element
);
315 ok(hr
== E_NOTIMPL
, "Expected E_NOTIMPL, got %08x\n", hr
);
316 ok(element
== NULL
, "Expected NULL element\n");
319 /* invalid vName type */
320 V_VT(&vType
) = VT_I4
;
321 V_I4(&vType
) = XMLELEMTYPE_ELEMENT
;
322 V_VT(&vName
) = VT_I4
;
323 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &element
);
324 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
325 ok(element
!= NULL
, "Expected non-NULL element\n");
327 hr
= IXMLElement_get_type(element
, &type
);
328 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
329 ok(type
== XMLELEMTYPE_ELEMENT
, "Expected XMLELEMTYPE_ELEMENT, got %d\n", type
);
331 IXMLElement_Release(element
);
334 V_VT(&vType
) = VT_I4
;
335 V_I4(&vType
) = XMLELEMTYPE_ELEMENT
;
336 V_VT(&vName
) = VT_I4
;
337 hr
= IXMLDocument_createElement(doc
, vType
, vName
, NULL
);
338 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
340 root
= (IXMLElement
*)0xdeadbeef;
341 hr
= IXMLDocument_get_root(doc
, &root
);
342 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
343 ok(root
== NULL
, "Expected NULL root\n");
345 V_VT(&vType
) = VT_I4
;
346 V_I4(&vType
) = XMLELEMTYPE_ELEMENT
;
347 V_VT(&vName
) = VT_NULL
;
348 hr
= IXMLDocument_createElement(doc
, vType
, vName
, &element
);
349 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
350 ok(element
!= NULL
, "Expected non-NULL element\n");
352 /* createElement does not set the new element as root */
353 root
= (IXMLElement
*)0xdeadbeef;
354 hr
= IXMLDocument_get_root(doc
, &root
);
355 ok(hr
== E_FAIL
, "Expected E_FAIL, got %08x\n", hr
);
356 ok(root
== NULL
, "Expected NULL root\n");
358 IXMLElement_Release(element
);
359 IXMLDocument_Release(doc
);
362 static void test_persiststreaminit(void)
364 IXMLDocument
*doc
= NULL
;
365 IXMLElement
*element
= NULL
;
366 IPersistStreamInit
*psi
= NULL
;
367 IStream
*stream
= NULL
;
374 static const WCHAR testW
[] = {'t','e','s','t',0};
376 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
377 &IID_IXMLDocument
, (LPVOID
*)&doc
);
378 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
380 hr
= IXMLDocument_QueryInterface(doc
, &IID_IPersistStreamInit
, (LPVOID
*)&psi
);
381 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
382 ok(psi
!= NULL
, "Expected non-NULL psi\n");
385 hr
= IPersistStreamInit_GetSizeMax(psi
, NULL
);
386 ok(hr
== E_NOTIMPL
, "Expected E_NOTIMPL, got %08x\n", hr
);
388 hr
= IPersistStreamInit_Load(psi
, NULL
);
389 ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
391 hr
= IPersistStreamInit_Save(psi
, NULL
, FALSE
);
392 todo_wine
ok(hr
== E_INVALIDARG
, "Expected E_INVALIDARG, got %08x\n", hr
);
394 hr
= IPersistStreamInit_GetClassID(psi
, NULL
);
395 ok(hr
== E_POINTER
, "Expected E_POINTER, got %08x\n", hr
);
397 hr
= IPersistStreamInit_IsDirty(psi
);
398 todo_wine
ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
400 create_xml_file("bank.xml");
401 GetFullPathNameA("bank.xml", MAX_PATH
, path
, NULL
);
402 create_stream_on_file(&stream
, path
);
404 /* GetSizeMax not implemented */
406 hr
= IPersistStreamInit_GetSizeMax(psi
, &size
);
407 ok(hr
== E_NOTIMPL
, "Expected E_NOTIMPL, got %08x\n", hr
);
408 ok(size
.QuadPart
== 0, "Expected 0\n");
410 hr
= IPersistStreamInit_Load(psi
, stream
);
411 IStream_Release(stream
);
412 ok(hr
== S_OK
|| hr
== XML_E_INVALIDATROOTLEVEL
, "Expected S_OK, got %08x\n", hr
);
413 if(hr
== XML_E_INVALIDATROOTLEVEL
)
416 hr
= IPersistStreamInit_IsDirty(psi
);
417 todo_wine
ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
419 /* try to save document */
421 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
422 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
423 hr
= IPersistStreamInit_Save(psi
, stream
, FALSE
);
424 todo_wine
ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
426 stat
.cbSize
.QuadPart
= 0;
427 hr
= IStream_Stat(stream
, &stat
, 0);
428 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
429 todo_wine
ok(stat
.cbSize
.QuadPart
> 0, "Expected >0\n");
430 IStream_Release(stream
);
432 str
= SysAllocString(testW
);
433 hr
= IXMLDocument_get_root(doc
, &element
);
434 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
435 hr
= IXMLElement_put_text(element
, str
);
436 IXMLElement_Release(element
);
439 hr
= IPersistStreamInit_IsDirty(psi
);
440 todo_wine
ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
442 create_stream_on_file(&stream
, path
);
443 hr
= IPersistStreamInit_Load(psi
, stream
);
444 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
445 IStream_Release(stream
);
447 hr
= IPersistStreamInit_IsDirty(psi
);
448 todo_wine
ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
450 /* reset internal stream */
451 hr
= IPersistStreamInit_InitNew(psi
);
452 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
454 hr
= IPersistStreamInit_IsDirty(psi
);
455 todo_wine
ok(hr
== S_FALSE
, "Expected S_FALSE, got %08x\n", hr
);
458 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
459 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
461 hr
= IPersistStreamInit_Save(psi
, stream
, FALSE
);
462 todo_wine
ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
464 stat
.cbSize
.QuadPart
= 0;
465 hr
= IStream_Stat(stream
, &stat
, 0);
466 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
467 todo_wine
ok(stat
.cbSize
.QuadPart
> 0, "Expected >0\n");
468 IStream_Release(stream
);
470 memset(&id
, 0, sizeof(id
));
471 hr
= IPersistStreamInit_GetClassID(psi
, &id
);
472 ok(hr
== S_OK
, "Expected S_OK, got %08x\n", hr
);
473 ok(IsEqualCLSID(&id
, &CLSID_XMLDocument
), "Expected CLSID_XMLDocument\n");
476 IPersistStreamInit_Release(psi
);
477 IXMLDocument_Release(doc
);
478 DeleteFileA("bank.xml");
481 static BOOL
test_try_xmldoc(void)
483 IXMLDocument
*doc
= NULL
;
486 hr
= CoCreateInstance(&CLSID_XMLDocument
, NULL
, CLSCTX_INPROC_SERVER
,
487 &IID_IXMLDocument
, (LPVOID
*)&doc
);
490 skip("Failed to create XMLDocument instance\n");
494 IXMLDocument_Release(doc
);
502 hr
= CoInitialize(NULL
);
503 ok(hr
== S_OK
, "failed to init com\n");
505 if (!test_try_xmldoc())
512 test_createElement();
513 test_persiststreaminit();