[XMLLITE_WINETEST] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / modules / rostests / winetests / xmllite / reader.c
1 /*
2 * IXmlReader tests
3 *
4 * Copyright 2010, 2012-2013, 2016-2017 Nikolay Sivov
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 #define CONST_VTABLE
23
24 #include <stdarg.h>
25 #include <stdio.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "initguid.h"
30 #include "ole2.h"
31 #include "xmllite.h"
32 #include "wine/test.h"
33 #include "wine/heap.h"
34
35 #define ARRAY_SIZE(array) (sizeof(array)/sizeof((array)[0]))
36
37 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
38
39 static WCHAR *a2w(const char *str)
40 {
41 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
42 WCHAR *ret = heap_alloc(len * sizeof(WCHAR));
43 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
44 return ret;
45 }
46
47 static void free_str(WCHAR *str)
48 {
49 heap_free(str);
50 }
51
52 static int strcmp_wa(const WCHAR *str1, const char *stra)
53 {
54 WCHAR *str2 = a2w(stra);
55 int r = lstrcmpW(str1, str2);
56 free_str(str2);
57 return r;
58 }
59
60 static const char xmldecl_full[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
61 static const char xmldecl_short[] = "<?xml version=\"1.0\"?><RegistrationInfo/>";
62
63 static IStream *create_stream_on_data(const void *data, unsigned int size)
64 {
65 IStream *stream = NULL;
66 HGLOBAL hglobal;
67 void *ptr;
68 HRESULT hr;
69
70 hglobal = GlobalAlloc(GHND, size);
71 ptr = GlobalLock(hglobal);
72
73 memcpy(ptr, data, size);
74
75 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
76 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
77 ok(stream != NULL, "Expected non-NULL stream\n");
78
79 GlobalUnlock(hglobal);
80
81 return stream;
82 }
83
84 static void test_reader_pos(IXmlReader *reader, UINT line, UINT pos, UINT line_broken,
85 UINT pos_broken, int _line_)
86 {
87 UINT l = ~0u, p = ~0u;
88 BOOL broken_state;
89
90 IXmlReader_GetLineNumber(reader, &l);
91 IXmlReader_GetLinePosition(reader, &p);
92
93 if (line_broken == ~0u && pos_broken == ~0u)
94 broken_state = FALSE;
95 else
96 broken_state = broken((line_broken == ~0u ? line : line_broken) == l &&
97 (pos_broken == ~0u ? pos : pos_broken) == p);
98
99 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
100 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
101 }
102 #define TEST_READER_POSITION(reader, line, pos) \
103 test_reader_pos(reader, line, pos, ~0u, ~0u, __LINE__)
104 #define TEST_READER_POSITION2(reader, line, pos, line_broken, pos_broken) \
105 test_reader_pos(reader, line, pos, line_broken, pos_broken, __LINE__)
106
107 typedef struct input_iids_t {
108 IID iids[10];
109 int count;
110 } input_iids_t;
111
112 static const IID *setinput_full[] = {
113 &IID_IXmlReaderInput,
114 &IID_IStream,
115 &IID_ISequentialStream,
116 NULL
117 };
118
119 /* this applies to early xmllite versions */
120 static const IID *setinput_full_old[] = {
121 &IID_IXmlReaderInput,
122 &IID_ISequentialStream,
123 &IID_IStream,
124 NULL
125 };
126
127 /* after ::SetInput(IXmlReaderInput*) */
128 static const IID *setinput_readerinput[] = {
129 &IID_IStream,
130 &IID_ISequentialStream,
131 NULL
132 };
133
134 static const IID *empty_seq[] = {
135 NULL
136 };
137
138 static input_iids_t input_iids;
139
140 static void ok_iids_(const input_iids_t *iids, const IID **expected, const IID **exp_broken, BOOL todo, int line)
141 {
142 int i = 0, size = 0;
143
144 while (expected[i++]) size++;
145
146 todo_wine_if (todo)
147 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
148
149 if (iids->count != size) return;
150
151 for (i = 0; i < size; i++) {
152 ok_(__FILE__, line)(IsEqualGUID(&iids->iids[i], expected[i]) ||
153 (exp_broken ? broken(IsEqualGUID(&iids->iids[i], exp_broken[i])) : FALSE),
154 "Wrong IID(%d), got %s\n", i, wine_dbgstr_guid(&iids->iids[i]));
155 }
156 }
157 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
158
159 static const char *state_to_str(XmlReadState state)
160 {
161 static const char* state_names[] = {
162 "XmlReadState_Initial",
163 "XmlReadState_Interactive",
164 "XmlReadState_Error",
165 "XmlReadState_EndOfFile",
166 "XmlReadState_Closed"
167 };
168
169 static const char unknown[] = "unknown";
170
171 switch (state)
172 {
173 case XmlReadState_Initial:
174 case XmlReadState_Interactive:
175 case XmlReadState_Error:
176 case XmlReadState_EndOfFile:
177 case XmlReadState_Closed:
178 return state_names[state];
179 default:
180 return unknown;
181 }
182 }
183
184 static const char *type_to_str(XmlNodeType type)
185 {
186 static const char* type_names[] = {
187 "XmlNodeType_None",
188 "XmlNodeType_Element",
189 "XmlNodeType_Attribute",
190 "XmlNodeType_Text",
191 "XmlNodeType_CDATA",
192 "", "",
193 "XmlNodeType_ProcessingInstruction",
194 "XmlNodeType_Comment",
195 "",
196 "XmlNodeType_DocumentType",
197 "", "",
198 "XmlNodeType_Whitespace",
199 "",
200 "XmlNodeType_EndElement",
201 "",
202 "XmlNodeType_XmlDeclaration"
203 };
204
205 static const char unknown[] = "unknown";
206
207 switch (type)
208 {
209 case XmlNodeType_None:
210 case XmlNodeType_Element:
211 case XmlNodeType_Attribute:
212 case XmlNodeType_Text:
213 case XmlNodeType_CDATA:
214 case XmlNodeType_ProcessingInstruction:
215 case XmlNodeType_Comment:
216 case XmlNodeType_DocumentType:
217 case XmlNodeType_Whitespace:
218 case XmlNodeType_EndElement:
219 case XmlNodeType_XmlDeclaration:
220 return type_names[type];
221 default:
222 return unknown;
223 }
224 }
225
226 #define set_input_string(a,b) _set_input_string(__LINE__,a,b);
227 static void _set_input_string(unsigned line, IXmlReader *reader, const char *xml)
228 {
229 IStream *stream;
230 HRESULT hr;
231
232 stream = create_stream_on_data(xml, strlen(xml));
233
234 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
235 ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr);
236
237 IStream_Release(stream);
238 }
239
240 #define read_node(a,b) _read_node(__LINE__,a,b)
241 static void _read_node(unsigned line, IXmlReader *reader, XmlNodeType expected_type)
242 {
243 XmlNodeType type;
244 HRESULT hr;
245
246 hr = IXmlReader_Read(reader, &type);
247 if (expected_type == XmlNodeType_None)
248 ok_(__FILE__,line)(hr == S_FALSE, "Read returned %08x, expected S_FALSE\n", hr);
249 else
250 ok_(__FILE__,line)(hr == S_OK, "Read returned %08x\n", hr);
251 ok_(__FILE__,line)(type == expected_type, "read type %d, expected %d\n", type, expected_type);
252 }
253
254 #define next_attribute(a) _next_attribute(__LINE__,a)
255 static void _next_attribute(unsigned line, IXmlReader *reader)
256 {
257 HRESULT hr;
258 hr = IXmlReader_MoveToNextAttribute(reader);
259 ok_(__FILE__,line)(hr == S_OK, "MoveToNextAttribute returned %08x\n", hr);
260 }
261
262 #define move_to_element(a) _move_to_element(__LINE__,a)
263 static void _move_to_element(unsigned line, IXmlReader *reader)
264 {
265 HRESULT hr;
266 hr = IXmlReader_MoveToElement(reader);
267 ok_(__FILE__,line)(hr == S_OK, "MoveToElement failed: %08x\n", hr);
268 }
269
270 static void test_read_state(IXmlReader *reader, XmlReadState expected,
271 XmlReadState exp_broken, int line)
272 {
273 BOOL broken_state;
274 LONG_PTR state;
275
276 state = -1; /* invalid state value */
277 IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
278
279 if (exp_broken == expected)
280 broken_state = FALSE;
281 else
282 broken_state = broken(exp_broken == state);
283
284 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
285 state_to_str(expected), state_to_str(state));
286 }
287
288 #define TEST_READER_STATE(reader, state) test_read_state(reader, state, state, __LINE__)
289 #define TEST_READER_STATE2(reader, state, brk) test_read_state(reader, state, brk, __LINE__)
290
291 #define reader_value(a,b) _reader_value(__LINE__,a,b)
292 static const WCHAR *_reader_value(unsigned line, IXmlReader *reader, const char *expect)
293 {
294 const WCHAR *str = (void*)0xdeadbeef;
295 ULONG len = 0xdeadbeef;
296 HRESULT hr;
297
298 hr = IXmlReader_GetValue(reader, &str, &len);
299 ok_(__FILE__,line)(hr == S_OK, "GetValue returned %08x\n", hr);
300 ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len);
301 ok_(__FILE__,line)(!strcmp_wa(str, expect), "value = %s\n", wine_dbgstr_w(str));
302 return str;
303 }
304
305 #define reader_name(a,b) _reader_name(__LINE__,a,b)
306 static const WCHAR *_reader_name(unsigned line, IXmlReader *reader, const char *expect)
307 {
308 const WCHAR *str = (void*)0xdeadbeef;
309 ULONG len = 0xdeadbeef;
310 HRESULT hr;
311
312 hr = IXmlReader_GetLocalName(reader, &str, &len);
313 ok_(__FILE__,line)(hr == S_OK, "GetLocalName returned %08x\n", hr);
314 ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len);
315 ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str));
316 return str;
317 }
318
319 #define reader_prefix(a,b) _reader_prefix(__LINE__,a,b)
320 static const WCHAR *_reader_prefix(unsigned line, IXmlReader *reader, const char *expect)
321 {
322 const WCHAR *str = (void*)0xdeadbeef;
323 ULONG len = 0xdeadbeef;
324 HRESULT hr;
325
326 hr = IXmlReader_GetPrefix(reader, &str, &len);
327 ok_(__FILE__,line)(hr == S_OK, "GetPrefix returned %08x\n", hr);
328 ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len);
329 ok_(__FILE__,line)(!strcmp_wa(str, expect), "prefix = %s\n", wine_dbgstr_w(str));
330 return str;
331 }
332
333 #define reader_namespace(a,b) _reader_namespace(__LINE__,a,b)
334 static const WCHAR *_reader_namespace(unsigned line, IXmlReader *reader, const char *expect)
335 {
336 const WCHAR *str = (void*)0xdeadbeef;
337 ULONG len = 0xdeadbeef;
338 HRESULT hr;
339
340 hr = IXmlReader_GetNamespaceUri(reader, &str, &len);
341 ok_(__FILE__,line)(hr == S_OK, "GetNamespaceUri returned %08x\n", hr);
342 ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len);
343 ok_(__FILE__,line)(!strcmp_wa(str, expect), "namespace = %s\n", wine_dbgstr_w(str));
344 return str;
345 }
346
347 #define reader_qname(a,b) _reader_qname(a,b,__LINE__)
348 static const WCHAR *_reader_qname(IXmlReader *reader, const char *expect, unsigned line)
349 {
350 const WCHAR *str = (void*)0xdeadbeef;
351 ULONG len = 0xdeadbeef;
352 HRESULT hr;
353
354 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
355 ok_(__FILE__,line)(hr == S_OK, "GetQualifiedName returned %08x\n", hr);
356 ok_(__FILE__,line)(len == lstrlenW(str), "len = %u\n", len);
357 ok_(__FILE__,line)(!strcmp_wa(str, expect), "name = %s\n", wine_dbgstr_w(str));
358 return str;
359 }
360
361 #define read_value_char(a,b) _read_value_char(a,b,__LINE__)
362 static void _read_value_char(IXmlReader *reader, WCHAR expected_char, unsigned line)
363 {
364 WCHAR c = 0xffff;
365 UINT count = 0;
366 HRESULT hr;
367
368 hr = IXmlReader_ReadValueChunk(reader, &c, 1, &count);
369 ok_(__FILE__,line)(hr == S_OK, "got %08x\n", hr);
370 ok_(__FILE__,line)(count == 1, "got %u\n", c);
371 ok_(__FILE__,line)(c == expected_char, "got %x\n", c);
372 }
373
374 typedef struct _testinput
375 {
376 IUnknown IUnknown_iface;
377 LONG ref;
378 } testinput;
379
380 static inline testinput *impl_from_IUnknown(IUnknown *iface)
381 {
382 return CONTAINING_RECORD(iface, testinput, IUnknown_iface);
383 }
384
385 static HRESULT WINAPI testinput_QueryInterface(IUnknown *iface, REFIID riid, void** ppvObj)
386 {
387 if (IsEqualGUID( riid, &IID_IUnknown ))
388 {
389 *ppvObj = iface;
390 IUnknown_AddRef(iface);
391 return S_OK;
392 }
393
394 input_iids.iids[input_iids.count++] = *riid;
395
396 *ppvObj = NULL;
397
398 return E_NOINTERFACE;
399 }
400
401 static ULONG WINAPI testinput_AddRef(IUnknown *iface)
402 {
403 testinput *This = impl_from_IUnknown(iface);
404 return InterlockedIncrement(&This->ref);
405 }
406
407 static ULONG WINAPI testinput_Release(IUnknown *iface)
408 {
409 testinput *This = impl_from_IUnknown(iface);
410 LONG ref;
411
412 ref = InterlockedDecrement(&This->ref);
413 if (ref == 0)
414 heap_free(This);
415
416 return ref;
417 }
418
419 static const struct IUnknownVtbl testinput_vtbl =
420 {
421 testinput_QueryInterface,
422 testinput_AddRef,
423 testinput_Release
424 };
425
426 static HRESULT testinput_createinstance(void **ppObj)
427 {
428 testinput *input;
429
430 input = heap_alloc(sizeof(*input));
431 if(!input) return E_OUTOFMEMORY;
432
433 input->IUnknown_iface.lpVtbl = &testinput_vtbl;
434 input->ref = 1;
435
436 *ppObj = &input->IUnknown_iface;
437
438 return S_OK;
439 }
440
441 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
442 {
443 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
444 {
445 *obj = iface;
446 return S_OK;
447 }
448
449 *obj = NULL;
450 return E_NOINTERFACE;
451 }
452
453 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
454 {
455 return 2;
456 }
457
458 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
459 {
460 return 1;
461 }
462
463 static int stream_readcall;
464
465 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
466 {
467 static const char xml[] = "<!-- comment -->";
468
469 if (stream_readcall++)
470 {
471 *pread = 0;
472 return E_PENDING;
473 }
474
475 *pread = sizeof(xml) / 2;
476 memcpy(pv, xml, *pread);
477 return S_OK;
478 }
479
480 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
481 {
482 ok(0, "unexpected call\n");
483 return E_NOTIMPL;
484 }
485
486 static const ISequentialStreamVtbl teststreamvtbl =
487 {
488 teststream_QueryInterface,
489 teststream_AddRef,
490 teststream_Release,
491 teststream_Read,
492 teststream_Write
493 };
494
495 static HRESULT WINAPI resolver_QI(IXmlResolver *iface, REFIID riid, void **obj)
496 {
497 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
498
499 if (IsEqualIID(riid, &IID_IXmlResolver) || IsEqualIID(riid, &IID_IUnknown))
500 {
501 *obj = iface;
502 IXmlResolver_AddRef(iface);
503 return S_OK;
504 }
505
506 *obj = NULL;
507 return E_NOINTERFACE;
508 }
509
510 static ULONG WINAPI resolver_AddRef(IXmlResolver *iface)
511 {
512 return 2;
513 }
514
515 static ULONG WINAPI resolver_Release(IXmlResolver *iface)
516 {
517 return 1;
518 }
519
520 static HRESULT WINAPI resolver_ResolveUri(IXmlResolver *iface, const WCHAR *base_uri,
521 const WCHAR *public_id, const WCHAR *system_id, IUnknown **input)
522 {
523 ok(0, "unexpected call\n");
524 return E_NOTIMPL;
525 }
526
527 static const IXmlResolverVtbl resolvervtbl =
528 {
529 resolver_QI,
530 resolver_AddRef,
531 resolver_Release,
532 resolver_ResolveUri
533 };
534
535 static IXmlResolver testresolver = { &resolvervtbl };
536
537 static void test_reader_create(void)
538 {
539 IXmlResolver *resolver;
540 IUnknown *input, *unk;
541 IXmlReader *reader;
542 DtdProcessing dtd;
543 XmlNodeType nodetype;
544 HRESULT hr;
545
546 /* crashes native */
547 if (0)
548 {
549 CreateXmlReader(&IID_IXmlReader, NULL, NULL);
550 CreateXmlReader(NULL, (void**)&reader, NULL);
551 }
552
553 hr = CreateXmlReader(&IID_IStream, (void **)&unk, NULL);
554 ok(hr == E_NOINTERFACE, "got %08x\n", hr);
555
556 hr = CreateXmlReader(&IID_IUnknown, (void **)&unk, NULL);
557 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
558 hr = IUnknown_QueryInterface(unk, &IID_IXmlReader, (void **)&reader);
559 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
560 ok(unk == (IUnknown *)reader, "unexpected interface\n");
561 IXmlReader_Release(reader);
562 IUnknown_Release(unk);
563
564 hr = CreateXmlReader(&IID_IUnknown, (void **)&reader, NULL);
565 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
566 IXmlReader_Release(reader);
567
568 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
569 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
570
571 TEST_READER_STATE(reader, XmlReadState_Closed);
572
573 nodetype = XmlNodeType_Element;
574 hr = IXmlReader_GetNodeType(reader, &nodetype);
575 ok(hr == S_FALSE, "got %08x\n", hr);
576 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
577
578 /* crashes on XP, 2k3, works on newer versions */
579 if (0)
580 {
581 hr = IXmlReader_GetNodeType(reader, NULL);
582 ok(hr == E_INVALIDARG, "got %08x\n", hr);
583 }
584
585 resolver = (void*)0xdeadbeef;
586 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
587 ok(hr == S_OK, "got 0x%08x\n", hr);
588 ok(resolver == NULL, "got %p\n", resolver);
589
590 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
591 ok(hr == S_OK, "got 0x%08x\n", hr);
592
593 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR)&testresolver);
594 ok(hr == S_OK, "got 0x%08x\n", hr);
595
596 resolver = NULL;
597 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
598 ok(hr == S_OK, "got 0x%08x\n", hr);
599 ok(resolver == &testresolver, "got %p\n", resolver);
600 IXmlResolver_Release(resolver);
601
602 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
603 ok(hr == S_OK, "got 0x%08x\n", hr);
604
605 dtd = 2;
606 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_DtdProcessing, (LONG_PTR*)&dtd);
607 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
608 ok(dtd == DtdProcessing_Prohibit, "got %d\n", dtd);
609
610 dtd = 2;
611 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, dtd);
612 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
613
614 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, -1);
615 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
616
617 /* Null input pointer, releases previous input */
618 hr = IXmlReader_SetInput(reader, NULL);
619 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
620
621 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
622
623 /* test input interface selection sequence */
624 hr = testinput_createinstance((void**)&input);
625 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
626
627 if (hr == S_OK)
628 {
629 input_iids.count = 0;
630 hr = IXmlReader_SetInput(reader, input);
631 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
632 ok_iids(&input_iids, setinput_full, setinput_full_old, FALSE);
633 IUnknown_Release(input);
634 }
635 IXmlReader_Release(reader);
636 }
637
638 static void test_readerinput(void)
639 {
640 IXmlReaderInput *reader_input;
641 IXmlReader *reader, *reader2;
642 IUnknown *obj, *input;
643 IStream *stream, *stream2;
644 XmlNodeType nodetype;
645 HRESULT hr;
646 LONG ref;
647
648 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, NULL);
649 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
650 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, &reader_input);
651 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
652
653 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
654 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
655
656 ref = IStream_AddRef(stream);
657 ok(ref == 2, "Expected 2, got %d\n", ref);
658 IStream_Release(stream);
659 hr = CreateXmlReaderInputWithEncodingName((IUnknown*)stream, NULL, NULL, FALSE, NULL, &reader_input);
660 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
661
662 hr = IUnknown_QueryInterface(reader_input, &IID_IStream, (void**)&stream2);
663 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
664
665 hr = IUnknown_QueryInterface(reader_input, &IID_ISequentialStream, (void**)&stream2);
666 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
667
668 /* IXmlReaderInput grabs a stream reference */
669 ref = IStream_AddRef(stream);
670 ok(ref == 3, "Expected 3, got %d\n", ref);
671 IStream_Release(stream);
672
673 /* try ::SetInput() with valid IXmlReaderInput */
674 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
675 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
676
677 ref = IUnknown_AddRef(reader_input);
678 ok(ref == 2, "Expected 2, got %d\n", ref);
679 IUnknown_Release(reader_input);
680
681 hr = IXmlReader_SetInput(reader, reader_input);
682 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
683
684 TEST_READER_STATE(reader, XmlReadState_Initial);
685
686 nodetype = XmlNodeType_Element;
687 hr = IXmlReader_GetNodeType(reader, &nodetype);
688 ok(hr == S_OK, "got %08x\n", hr);
689 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
690
691 /* IXmlReader grabs a IXmlReaderInput reference */
692 ref = IUnknown_AddRef(reader_input);
693 ok(ref == 3, "Expected 3, got %d\n", ref);
694 IUnknown_Release(reader_input);
695
696 ref = IStream_AddRef(stream);
697 ok(ref == 4, "Expected 4, got %d\n", ref);
698 IStream_Release(stream);
699
700 /* reset input and check state */
701 hr = IXmlReader_SetInput(reader, NULL);
702 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
703
704 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
705
706 IXmlReader_Release(reader);
707
708 ref = IStream_AddRef(stream);
709 ok(ref == 3, "Expected 3, got %d\n", ref);
710 IStream_Release(stream);
711
712 ref = IUnknown_AddRef(reader_input);
713 ok(ref == 2, "Expected 2, got %d\n", ref);
714 IUnknown_Release(reader_input);
715
716 /* IID_IXmlReaderInput */
717 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
718 so it's not a COM interface actually.
719 Such query will be used only to check if input is really IXmlReaderInput */
720 obj = (IUnknown*)0xdeadbeef;
721 hr = IUnknown_QueryInterface(reader_input, &IID_IXmlReaderInput, (void**)&obj);
722 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
723 ref = IUnknown_AddRef(reader_input);
724 ok(ref == 3, "Expected 3, got %d\n", ref);
725 IUnknown_Release(reader_input);
726
727 IUnknown_Release(reader_input);
728 IUnknown_Release(reader_input);
729 IStream_Release(stream);
730
731 /* test input interface selection sequence */
732 input = NULL;
733 hr = testinput_createinstance((void**)&input);
734 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
735
736 input_iids.count = 0;
737 ref = IUnknown_AddRef(input);
738 ok(ref == 2, "Expected 2, got %d\n", ref);
739 IUnknown_Release(input);
740 hr = CreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &reader_input);
741 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
742 ok_iids(&input_iids, empty_seq, NULL, FALSE);
743 /* IXmlReaderInput stores stream interface as IUnknown */
744 ref = IUnknown_AddRef(input);
745 ok(ref == 3, "Expected 3, got %d\n", ref);
746 IUnknown_Release(input);
747
748 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
749 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
750
751 input_iids.count = 0;
752 ref = IUnknown_AddRef(reader_input);
753 ok(ref == 2, "Expected 2, got %d\n", ref);
754 IUnknown_Release(reader_input);
755 ref = IUnknown_AddRef(input);
756 ok(ref == 3, "Expected 3, got %d\n", ref);
757 IUnknown_Release(input);
758 hr = IXmlReader_SetInput(reader, reader_input);
759 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
760 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
761
762 TEST_READER_STATE(reader, XmlReadState_Closed);
763
764 ref = IUnknown_AddRef(input);
765 ok(ref == 3, "Expected 3, got %d\n", ref);
766 IUnknown_Release(input);
767
768 ref = IUnknown_AddRef(reader_input);
769 ok(ref == 3 || broken(ref == 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
770 "Expected 3, got %d\n", ref);
771 IUnknown_Release(reader_input);
772 /* repeat another time, no check or caching here */
773 input_iids.count = 0;
774 hr = IXmlReader_SetInput(reader, reader_input);
775 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
776 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
777
778 /* another reader */
779 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader2, NULL);
780 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
781
782 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
783 ::SetInput() level, each time it's called */
784 input_iids.count = 0;
785 hr = IXmlReader_SetInput(reader2, reader_input);
786 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
787 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
788
789 IXmlReader_Release(reader2);
790 IXmlReader_Release(reader);
791
792 IUnknown_Release(reader_input);
793 IUnknown_Release(input);
794 }
795
796 static void test_reader_state(void)
797 {
798 XmlNodeType nodetype;
799 IXmlReader *reader;
800 HRESULT hr;
801
802 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
803 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
804
805 /* invalid arguments */
806 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, NULL);
807 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
808
809 /* attempt to read on closed reader */
810 TEST_READER_STATE(reader, XmlReadState_Closed);
811
812 if (0)
813 {
814 /* newer versions crash here, probably because no input was set */
815 hr = IXmlReader_Read(reader, &nodetype);
816 ok(hr == S_FALSE, "got %08x\n", hr);
817 }
818 set_input_string(reader, "xml");
819 TEST_READER_STATE(reader, XmlReadState_Initial);
820
821 nodetype = XmlNodeType_Element;
822 hr = IXmlReader_Read(reader, &nodetype);
823 todo_wine
824 ok(FAILED(hr), "got %08x\n", hr);
825 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
826
827 todo_wine
828 TEST_READER_STATE(reader, XmlReadState_Error);
829
830 nodetype = XmlNodeType_Element;
831 hr = IXmlReader_Read(reader, &nodetype);
832 todo_wine
833 ok(FAILED(hr), "got %08x\n", hr);
834 ok(nodetype == XmlNodeType_None, "Unexpected node type %d\n", nodetype);
835
836 IXmlReader_Release(reader);
837 }
838
839 static void test_reader_depth(IXmlReader *reader, UINT depth, UINT brk, int line)
840 {
841 BOOL condition;
842 UINT d = ~0u;
843
844 IXmlReader_GetDepth(reader, &d);
845
846 condition = d == depth;
847 if (brk != ~0u)
848 condition |= broken(d == brk);
849 ok_(__FILE__, line)(condition, "Unexpected nesting depth %u, expected %u\n", d, depth);
850 }
851
852 #define TEST_DEPTH(reader, depth) test_reader_depth(reader, depth, ~0u, __LINE__)
853 #define TEST_DEPTH2(reader, depth, brk) test_reader_depth(reader, depth, brk, __LINE__)
854
855 static void test_read_xmldeclaration(void)
856 {
857 static const struct
858 {
859 WCHAR name[12];
860 WCHAR val[12];
861 } name_val[] =
862 {
863 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
864 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
865 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
866 };
867 IXmlReader *reader;
868 IStream *stream;
869 HRESULT hr;
870 XmlNodeType type;
871 UINT count = 0, len, i;
872 BOOL ret;
873 const WCHAR *val;
874
875 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
876 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
877
878 stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
879
880 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
881 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
882
883 hr = IXmlReader_GetAttributeCount(reader, &count);
884 ok(hr == S_OK, "got %08x\n", hr);
885 ok(count == 0, "got %d\n", count);
886
887 /* try to move without attributes */
888 hr = IXmlReader_MoveToElement(reader);
889 ok(hr == S_FALSE, "got %08x\n", hr);
890
891 hr = IXmlReader_MoveToNextAttribute(reader);
892 ok(hr == S_FALSE, "got %08x\n", hr);
893
894 hr = IXmlReader_MoveToFirstAttribute(reader);
895 ok(hr == S_FALSE, "got %08x\n", hr);
896
897 TEST_READER_POSITION(reader, 0, 0);
898
899 read_node(reader, XmlNodeType_XmlDeclaration);
900
901 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
902 TEST_READER_POSITION2(reader, 1, 3, ~0u, 55);
903
904 TEST_DEPTH(reader, 0);
905 TEST_READER_STATE(reader, XmlReadState_Interactive);
906
907 reader_value(reader, "");
908
909 /* check attributes */
910 next_attribute(reader);
911
912 TEST_DEPTH(reader, 1);
913
914 type = XmlNodeType_None;
915 hr = IXmlReader_GetNodeType(reader, &type);
916 ok(hr == S_OK, "got %08x\n", hr);
917 ok(type == XmlNodeType_Attribute, "got %d\n", type);
918
919 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
920
921 /* try to move from last attribute */
922 next_attribute(reader);
923 next_attribute(reader);
924 hr = IXmlReader_MoveToNextAttribute(reader);
925 ok(hr == S_FALSE, "got %08x\n", hr);
926
927 type = XmlNodeType_None;
928 hr = IXmlReader_GetNodeType(reader, &type);
929 ok(hr == S_OK, "got %08x\n", hr);
930 ok(type == XmlNodeType_Attribute, "got %d\n", type);
931
932 hr = IXmlReader_MoveToFirstAttribute(reader);
933 ok(hr == S_OK, "got %08x\n", hr);
934 TEST_READER_POSITION2(reader, 1, 7, ~0u, 55);
935
936 hr = IXmlReader_GetAttributeCount(reader, NULL);
937 ok(hr == E_INVALIDARG, "got %08x\n", hr);
938
939 hr = IXmlReader_GetAttributeCount(reader, &count);
940 ok(hr == S_OK, "got %08x\n", hr);
941 ok(count == 3, "Expected 3, got %d\n", count);
942
943 for (i = 0; i < count; i++)
944 {
945 len = 0;
946 hr = IXmlReader_GetLocalName(reader, &val, &len);
947 ok(hr == S_OK, "got %08x\n", hr);
948 ok(len == lstrlenW(name_val[i].name), "expected %u, got %u\n", lstrlenW(name_val[i].name), len);
949 ok(!lstrcmpW(name_val[i].name, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].name), wine_dbgstr_w(val));
950
951 len = 0;
952 hr = IXmlReader_GetValue(reader, &val, &len);
953 ok(hr == S_OK, "got %08x\n", hr);
954 ok(len == lstrlenW(name_val[i].val), "expected %u, got %u\n", lstrlenW(name_val[i].val), len);
955 ok(!lstrcmpW(name_val[i].val, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].val), wine_dbgstr_w(val));
956
957 hr = IXmlReader_MoveToNextAttribute(reader);
958 ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
959 }
960
961 TEST_DEPTH(reader, 1);
962
963 move_to_element(reader);
964 TEST_READER_POSITION2(reader, 1, 3, ~0u, 55);
965
966 type = XmlNodeType_None;
967 hr = IXmlReader_GetNodeType(reader, &type);
968 ok(hr == S_OK, "got %08x\n", hr);
969 ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type);
970
971 type = XmlNodeType_XmlDeclaration;
972 hr = IXmlReader_Read(reader, &type);
973 /* newer versions return syntax error here cause document is incomplete,
974 it makes more sense than invalid char error */
975 todo_wine {
976 ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
977 ok(type == XmlNodeType_None, "got %d\n", type);
978 }
979 IStream_Release(stream);
980
981 /* test short variant */
982 stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
983
984 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
985 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
986
987 read_node(reader, XmlNodeType_XmlDeclaration);
988 TEST_READER_POSITION2(reader, 1, 3, ~0u, 21);
989 TEST_READER_STATE(reader, XmlReadState_Interactive);
990
991 hr = IXmlReader_GetAttributeCount(reader, &count);
992 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
993 ok(count == 1, "expected 1, got %d\n", count);
994
995 ret = IXmlReader_IsEmptyElement(reader);
996 ok(!ret, "element should not be empty\n");
997
998 reader_value(reader, "");
999 reader_name(reader, "xml");
1000
1001 reader_qname(reader, "xml");
1002
1003 /* check attributes */
1004 next_attribute(reader);
1005
1006 type = -1;
1007 hr = IXmlReader_GetNodeType(reader, &type);
1008 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
1009 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1010 TEST_READER_POSITION2(reader, 1, 7, ~0u, 21);
1011
1012 /* try to move from last attribute */
1013 hr = IXmlReader_MoveToNextAttribute(reader);
1014 ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
1015
1016 read_node(reader, XmlNodeType_Element);
1017 TEST_READER_POSITION2(reader, 1, 23, ~0u, 40);
1018 TEST_READER_STATE(reader, XmlReadState_Interactive);
1019
1020 hr = IXmlReader_GetAttributeCount(reader, &count);
1021 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
1022 ok(count == 0, "expected 0, got %d\n", count);
1023
1024 ret = IXmlReader_IsEmptyElement(reader);
1025 ok(ret, "element should be empty\n");
1026
1027 reader_value(reader, "");
1028 reader_name(reader, "RegistrationInfo");
1029
1030 type = -1;
1031 hr = IXmlReader_Read(reader, &type);
1032 todo_wine
1033 ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
1034 ok(type == XmlNodeType_None, "expected XmlNodeType_None, got %s\n", type_to_str(type));
1035 TEST_READER_POSITION(reader, 1, 41);
1036 todo_wine
1037 TEST_READER_STATE(reader, XmlReadState_Error);
1038
1039 IStream_Release(stream);
1040 IXmlReader_Release(reader);
1041 }
1042
1043 struct test_entry {
1044 const char *xml;
1045 const char *name;
1046 const char *value;
1047 HRESULT hr;
1048 HRESULT hr_broken; /* this is set to older version results */
1049 BOOL todo;
1050 };
1051
1052 static struct test_entry comment_tests[] = {
1053 { "<!-- comment -->", "", " comment ", S_OK },
1054 { "<!-- - comment-->", "", " - comment", S_OK },
1055 { "<!-- -- comment-->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
1056 { "<!-- -- comment--->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
1057 { NULL }
1058 };
1059
1060 static void test_read_comment(void)
1061 {
1062 static const char *teststr = "<a>text<!-- comment --></a>";
1063 struct test_entry *test = comment_tests;
1064 static const XmlNodeType types[] =
1065 {
1066 XmlNodeType_Element,
1067 XmlNodeType_Text,
1068 XmlNodeType_Comment,
1069 XmlNodeType_EndElement,
1070 };
1071 unsigned int i = 0;
1072 IXmlReader *reader;
1073 XmlNodeType type;
1074 HRESULT hr;
1075
1076 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1077 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1078
1079 set_input_string(reader, teststr);
1080
1081 while (IXmlReader_Read(reader, &type) == S_OK)
1082 {
1083 const WCHAR *value;
1084
1085 ok(type == types[i], "%d: unexpected node type %d\n", i, type);
1086
1087 if (type == XmlNodeType_Text || type == XmlNodeType_Comment)
1088 {
1089 hr = IXmlReader_GetValue(reader, &value, NULL);
1090 ok(hr == S_OK, "got %08x\n", hr);
1091 ok(*value != 0, "Expected node value\n");
1092 }
1093 i++;
1094 }
1095
1096 while (test->xml)
1097 {
1098 set_input_string(reader, test->xml);
1099
1100 type = XmlNodeType_None;
1101 hr = IXmlReader_Read(reader, &type);
1102 if (test->hr_broken)
1103 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1104 else
1105 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1106 if (hr == S_OK)
1107 {
1108 const WCHAR *str;
1109
1110 ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml);
1111
1112 reader_name(reader, "");
1113
1114 str = NULL;
1115 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1116 ok(hr == S_OK, "got 0x%08x\n", hr);
1117 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1118
1119 reader_qname(reader, "");
1120
1121 str = NULL;
1122 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1123 ok(hr == S_OK, "got 0x%08x\n", hr);
1124 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1125
1126 /* value */
1127 reader_value(reader, test->value);
1128 }
1129
1130 test++;
1131 }
1132
1133 IXmlReader_Release(reader);
1134 }
1135
1136 static struct test_entry pi_tests[] = {
1137 { "<?pi?>", "pi", "", S_OK },
1138 { "<?pi ?>", "pi", "", S_OK },
1139 { "<?pi ?>", "pi", "", S_OK },
1140 { "<?pi pi data?>", "pi", "pi data", S_OK },
1141 { "<?pi pi data ?>", "pi", "pi data ", S_OK },
1142 { "<?pi data ?>", "pi", "data ", S_OK },
1143 { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
1144 { "<?:pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1145 { "<?-pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
1146 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK },
1147 { NULL }
1148 };
1149
1150 static void test_read_pi(void)
1151 {
1152 struct test_entry *test = pi_tests;
1153 IXmlReader *reader;
1154 HRESULT hr;
1155
1156 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1157 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1158
1159 while (test->xml)
1160 {
1161 XmlNodeType type;
1162
1163 set_input_string(reader, test->xml);
1164
1165 type = XmlNodeType_None;
1166 hr = IXmlReader_Read(reader, &type);
1167 if (test->hr_broken)
1168 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1169 else
1170 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1171 if (hr == S_OK)
1172 {
1173 const WCHAR *str;
1174 WCHAR *str_exp;
1175 UINT len;
1176
1177 ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml);
1178
1179 reader_name(reader, test->name);
1180
1181 len = 0;
1182 str = NULL;
1183 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1184 ok(hr == S_OK, "got 0x%08x\n", hr);
1185 ok(len == strlen(test->name), "got %u\n", len);
1186 str_exp = a2w(test->name);
1187 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1188 free_str(str_exp);
1189
1190 /* value */
1191 reader_value(reader, test->value);
1192 }
1193
1194 test++;
1195 }
1196
1197 IXmlReader_Release(reader);
1198 }
1199
1200 struct nodes_test {
1201 const char *xml;
1202 struct {
1203 XmlNodeType type;
1204 const char *value;
1205 } nodes[20];
1206 };
1207
1208 static const char misc_test_xml[] =
1209 "<!-- comment1 -->"
1210 "<!-- comment2 -->"
1211 "<?pi1 pi1body ?>"
1212 "<!-- comment3 -->"
1213 " \t \r \n"
1214 "<!-- comment4 -->"
1215 "<a>"
1216 "\r\n\t"
1217 "<b/>"
1218 "text"
1219 "<!-- comment -->"
1220 "text2"
1221 "<?pi pibody ?>"
1222 "\r\n"
1223 "</a>"
1224 ;
1225
1226 static struct nodes_test misc_test = {
1227 misc_test_xml,
1228 {
1229 {XmlNodeType_Comment, " comment1 "},
1230 {XmlNodeType_Comment, " comment2 "},
1231 {XmlNodeType_ProcessingInstruction, "pi1body "},
1232 {XmlNodeType_Comment, " comment3 "},
1233 {XmlNodeType_Whitespace, " \t \n \n"},
1234 {XmlNodeType_Comment, " comment4 "},
1235 {XmlNodeType_Element, ""},
1236 {XmlNodeType_Whitespace, "\n\t"},
1237 {XmlNodeType_Element, ""},
1238 {XmlNodeType_Text, "text"},
1239 {XmlNodeType_Comment, " comment "},
1240 {XmlNodeType_Text, "text2"},
1241 {XmlNodeType_ProcessingInstruction, "pibody "},
1242 {XmlNodeType_Whitespace, "\n"},
1243 {XmlNodeType_EndElement, ""},
1244 {XmlNodeType_None, ""}
1245 }
1246 };
1247
1248 static void test_read_full(void)
1249 {
1250 struct nodes_test *test = &misc_test;
1251 IXmlReader *reader;
1252 HRESULT hr;
1253 int i;
1254
1255 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1256 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1257
1258 set_input_string(reader, test->xml);
1259
1260 i = 0;
1261 do
1262 {
1263 read_node(reader, test->nodes[i].type);
1264 reader_value(reader, test->nodes[i].value);
1265 } while(test->nodes[i++].type != XmlNodeType_None);
1266
1267 IXmlReader_Release(reader);
1268 }
1269
1270 static const char test_public_dtd[] =
1271 "<!DOCTYPE testdtd PUBLIC \"pubid\" \"externalid uri\" >";
1272
1273 static void test_read_public_dtd(void)
1274 {
1275 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1276 IXmlReader *reader;
1277 const WCHAR *str;
1278 XmlNodeType type;
1279 UINT len, count;
1280 HRESULT hr;
1281
1282 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1283 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1284
1285 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1286 ok(hr == S_OK, "got 0x%8x\n", hr);
1287
1288 set_input_string(reader, test_public_dtd);
1289
1290 read_node(reader, XmlNodeType_DocumentType);
1291
1292 count = 0;
1293 hr = IXmlReader_GetAttributeCount(reader, &count);
1294 ok(hr == S_OK, "got %08x\n", hr);
1295 ok(count == 2, "got %d\n", count);
1296
1297 hr = IXmlReader_MoveToFirstAttribute(reader);
1298 ok(hr == S_OK, "got %08x\n", hr);
1299
1300 type = XmlNodeType_None;
1301 hr = IXmlReader_GetNodeType(reader, &type);
1302 ok(hr == S_OK, "got %08x\n", hr);
1303 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1304
1305 reader_name(reader, "PUBLIC");
1306 reader_value(reader, "pubid");
1307
1308 next_attribute(reader);
1309
1310 type = XmlNodeType_None;
1311 hr = IXmlReader_GetNodeType(reader, &type);
1312 ok(hr == S_OK, "got %08x\n", hr);
1313 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1314
1315 reader_name(reader, "SYSTEM");
1316 reader_value(reader, "externalid uri");
1317
1318 move_to_element(reader);
1319 reader_name(reader, "testdtd");
1320
1321 len = 0;
1322 str = NULL;
1323 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1324 ok(hr == S_OK, "got 0x%08x\n", hr);
1325 todo_wine {
1326 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1327 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1328 }
1329 IXmlReader_Release(reader);
1330 }
1331
1332 static const char test_system_dtd[] =
1333 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1334 "<!-- comment -->";
1335
1336 static void test_read_system_dtd(void)
1337 {
1338 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1339 IXmlReader *reader;
1340 const WCHAR *str;
1341 XmlNodeType type;
1342 UINT len, count;
1343 HRESULT hr;
1344
1345 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1346 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1347
1348 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1349 ok(hr == S_OK, "got 0x%8x\n", hr);
1350
1351 set_input_string(reader, test_system_dtd);
1352
1353 read_node(reader, XmlNodeType_DocumentType);
1354
1355 count = 0;
1356 hr = IXmlReader_GetAttributeCount(reader, &count);
1357 ok(hr == S_OK, "got %08x\n", hr);
1358 ok(count == 1, "got %d\n", count);
1359
1360 hr = IXmlReader_MoveToFirstAttribute(reader);
1361 ok(hr == S_OK, "got %08x\n", hr);
1362
1363 type = XmlNodeType_None;
1364 hr = IXmlReader_GetNodeType(reader, &type);
1365 ok(hr == S_OK, "got %08x\n", hr);
1366 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1367
1368 reader_name(reader, "SYSTEM");
1369 reader_value(reader, "externalid uri");
1370
1371 move_to_element(reader);
1372 reader_name(reader, "testdtd");
1373
1374 len = 0;
1375 str = NULL;
1376 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1377 ok(hr == S_OK, "got 0x%08x\n", hr);
1378 todo_wine {
1379 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1380 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1381 }
1382
1383 read_node(reader, XmlNodeType_Comment);
1384
1385 IXmlReader_Release(reader);
1386 }
1387
1388 static struct test_entry element_tests[] = {
1389 { "<a/>", "a", "", S_OK },
1390 { "<a />", "a", "", S_OK },
1391 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX },
1392 { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1393 { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1394 { "<a>", "a", "", S_OK },
1395 { "<a >", "a", "", S_OK },
1396 { "<a \r \t\n>", "a", "", S_OK },
1397 { "</a>", NULL, NULL, NC_E_QNAMECHARACTER },
1398 { "<a:b:c />", NULL, NULL, NC_E_QNAMECOLON },
1399 { "<:b:c />", NULL, NULL, NC_E_QNAMECHARACTER },
1400 { NULL }
1401 };
1402
1403 static void test_read_element(void)
1404 {
1405 struct test_entry *test = element_tests;
1406 static const char stag[] =
1407 "<a attr1=\"_a\">"
1408 "<b attr2=\"_b\">"
1409 "text"
1410 "<c attr3=\"_c\"/>"
1411 "<d attr4=\"_d\"></d>"
1412 "</b>"
1413 "</a>";
1414 static const UINT depths[] = { 0, 1, 2, 2, 2, 3, 2, 1 };
1415 IXmlReader *reader;
1416 XmlNodeType type;
1417 unsigned int i;
1418 UINT depth;
1419 HRESULT hr;
1420
1421 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1422 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1423
1424 while (test->xml)
1425 {
1426 set_input_string(reader, test->xml);
1427
1428 type = XmlNodeType_None;
1429 hr = IXmlReader_Read(reader, &type);
1430 if (test->hr_broken)
1431 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1432 else
1433 todo_wine_if(test->hr == NC_E_UNDECLAREDPREFIX)
1434 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1435 if (hr == S_OK)
1436 {
1437 const WCHAR *str;
1438 WCHAR *str_exp;
1439 UINT len;
1440
1441 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1442
1443 len = 0;
1444 str = NULL;
1445 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1446 ok(hr == S_OK, "got 0x%08x\n", hr);
1447 ok(len == strlen(test->name), "got %u\n", len);
1448 str_exp = a2w(test->name);
1449 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1450 free_str(str_exp);
1451
1452 /* value */
1453 reader_value(reader, "");
1454 }
1455
1456 test++;
1457 }
1458
1459 /* test reader depth increment */
1460 set_input_string(reader, stag);
1461
1462 i = 0;
1463 while (IXmlReader_Read(reader, &type) == S_OK)
1464 {
1465 UINT count;
1466
1467 ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement ||
1468 type == XmlNodeType_Text, "Unexpected node type %d\n", type);
1469
1470 depth = 123;
1471 hr = IXmlReader_GetDepth(reader, &depth);
1472 ok(hr == S_OK, "got %08x\n", hr);
1473 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1474
1475 if (type == XmlNodeType_Element || type == XmlNodeType_EndElement)
1476 {
1477 const WCHAR *prefix;
1478
1479 prefix = NULL;
1480 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
1481 ok(hr == S_OK, "got %08x\n", hr);
1482 ok(prefix != NULL, "got %p\n", prefix);
1483
1484 if (!*prefix)
1485 {
1486 const WCHAR *local, *qname;
1487
1488 local = NULL;
1489 hr = IXmlReader_GetLocalName(reader, &local, NULL);
1490 ok(hr == S_OK, "got %08x\n", hr);
1491 ok(local != NULL, "got %p\n", local);
1492
1493 qname = NULL;
1494 hr = IXmlReader_GetQualifiedName(reader, &qname, NULL);
1495 ok(hr == S_OK, "got %08x\n", hr);
1496 ok(qname != NULL, "got %p\n", qname);
1497
1498 ok(local == qname, "expected same pointer\n");
1499 }
1500 }
1501
1502 if (type == XmlNodeType_EndElement)
1503 {
1504 count = 1;
1505 hr = IXmlReader_GetAttributeCount(reader, &count);
1506 ok(hr == S_OK, "got %08x\n", hr);
1507 ok(count == 0, "got %u\n", count);
1508 }
1509
1510 if (type == XmlNodeType_Element)
1511 {
1512 count = 0;
1513 hr = IXmlReader_GetAttributeCount(reader, &count);
1514 ok(hr == S_OK, "got %08x\n", hr);
1515
1516 /* moving to attributes increases depth */
1517 if (count)
1518 {
1519 const WCHAR *value;
1520
1521 reader_value(reader, "");
1522
1523 hr = IXmlReader_MoveToFirstAttribute(reader);
1524 ok(hr == S_OK, "got %08x\n", hr);
1525
1526 hr = IXmlReader_GetValue(reader, &value, NULL);
1527 ok(*value != 0, "Unexpected value %s\n", wine_dbgstr_w(value));
1528
1529 depth = 123;
1530 hr = IXmlReader_GetDepth(reader, &depth);
1531 ok(hr == S_OK, "got %08x\n", hr);
1532 ok(depth == depths[i] + 1, "%u: got depth %u, expected %u\n", i, depth, depths[i] + 1);
1533
1534 move_to_element(reader);
1535 reader_value(reader, "");
1536
1537 depth = 123;
1538 hr = IXmlReader_GetDepth(reader, &depth);
1539 ok(hr == S_OK, "got %08x\n", hr);
1540 ok(depth == depths[i], "%u: got depth %u, expected %u\n", i, depth, depths[i]);
1541 }
1542 }
1543
1544 i++;
1545 }
1546
1547 /* start/end tag mismatch */
1548 set_input_string(reader, "<a></b>");
1549
1550 read_node(reader, XmlNodeType_Element);
1551
1552 type = XmlNodeType_Element;
1553 hr = IXmlReader_Read(reader, &type);
1554 ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr);
1555 ok(type == XmlNodeType_None, "got %d\n", type);
1556 TEST_READER_STATE(reader, XmlReadState_Error);
1557
1558 IXmlReader_Release(reader);
1559 }
1560
1561 static ISequentialStream teststream = { &teststreamvtbl };
1562
1563 static void test_read_pending(void)
1564 {
1565 IXmlReader *reader;
1566 const WCHAR *value;
1567 XmlNodeType type;
1568 HRESULT hr;
1569 int c;
1570
1571 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1572 ok(hr == S_OK, "S_OK, got 0x%08x\n", hr);
1573
1574 hr = IXmlReader_SetInput(reader, (IUnknown*)&teststream);
1575 ok(hr == S_OK, "got 0x%08x\n", hr);
1576
1577 /* first read call returns incomplete node, second attempt fails with E_PENDING */
1578 stream_readcall = 0;
1579 type = XmlNodeType_Element;
1580 hr = IXmlReader_Read(reader, &type);
1581 ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr);
1582 /* newer versions are happy when it's enough data to detect node type,
1583 older versions keep reading until it fails to read more */
1584 todo_wine
1585 ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall);
1586 ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type);
1587
1588 /* newer versions' GetValue() makes an attempt to read more */
1589 c = stream_readcall;
1590 value = (void*)0xdeadbeef;
1591 hr = IXmlReader_GetValue(reader, &value, NULL);
1592 ok(hr == E_PENDING, "got 0x%08x\n", hr);
1593 ok(value == NULL || broken(value == (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value);
1594 ok(c < stream_readcall || broken(c == stream_readcall), "got %d, expected %d\n", stream_readcall, c+1);
1595
1596 IXmlReader_Release(reader);
1597 }
1598
1599 static void test_readvaluechunk(void)
1600 {
1601 IXmlReader *reader;
1602 XmlNodeType type;
1603 WCHAR buf[64];
1604 WCHAR b;
1605 HRESULT hr;
1606 UINT c;
1607
1608 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1609 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1610
1611 set_input_string(reader, "<!-- comment1 --><!-- comment2 -->");
1612
1613 hr = IXmlReader_Read(reader, &type);
1614 ok(hr == S_OK, "got %08x\n", hr);
1615 ok(type == XmlNodeType_Comment, "type = %u\n", type);
1616
1617 read_value_char(reader, ' ');
1618 read_value_char(reader, 'c');
1619
1620 /* portion read as chunk is skipped from resulting node value */
1621 reader_value(reader, "omment1 ");
1622
1623 /* once value is returned/allocated it's not possible to read by chunk */
1624 c = 0;
1625 b = 0;
1626 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1627 ok(hr == S_FALSE, "got %08x\n", hr);
1628 ok(c == 0, "got %u\n", c);
1629 ok(b == 0, "got %x\n", b);
1630
1631 c = 0xdeadbeef;
1632 hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c);
1633 ok(hr == S_OK, "got %08x\n", hr);
1634 ok(!c, "c = %u\n", c);
1635
1636 reader_value(reader, "omment1 ");
1637
1638 /* read comment2 */
1639 read_node(reader, XmlNodeType_Comment);
1640
1641 c = 0xdeadbeef;
1642 hr = IXmlReader_ReadValueChunk(reader, buf, 0, &c);
1643 ok(hr == S_OK, "got %08x\n", hr);
1644 ok(!c, "c = %u\n", c);
1645
1646 c = 0xdeadbeef;
1647 memset(buf, 0xcc, sizeof(buf));
1648 hr = IXmlReader_ReadValueChunk(reader, buf, ARRAY_SIZE(buf), &c);
1649 ok(hr == S_OK, "got %08x\n", hr);
1650 ok(c == 10, "got %u\n", c);
1651 ok(buf[c] == 0xcccc, "buffer overflow\n");
1652 buf[c] = 0;
1653 ok(!strcmp_wa(buf, " comment2 "), "buf = %s\n", wine_dbgstr_w(buf));
1654
1655 c = 0xdeadbeef;
1656 memset(buf, 0xcc, sizeof(buf));
1657 hr = IXmlReader_ReadValueChunk(reader, buf, ARRAY_SIZE(buf), &c);
1658 ok(hr == S_FALSE, "got %08x\n", hr);
1659 ok(!c, "got %u\n", c);
1660
1661 /* portion read as chunk is skipped from resulting node value */
1662 reader_value(reader, "");
1663
1664 /* once value is returned/allocated it's not possible to read by chunk */
1665 c = 0xdeadbeef;
1666 b = 0xffff;
1667 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1668 ok(hr == S_FALSE, "got %08x\n", hr);
1669 ok(c == 0, "got %u\n", c);
1670 ok(b == 0xffff, "got %x\n", b);
1671
1672 reader_value(reader, "");
1673
1674 IXmlReader_Release(reader);
1675 }
1676
1677 static struct test_entry cdata_tests[] = {
1678 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK },
1679 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK },
1680 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK },
1681 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK },
1682 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK },
1683 { NULL }
1684 };
1685
1686 static void test_read_cdata(void)
1687 {
1688 struct test_entry *test = cdata_tests;
1689 IXmlReader *reader;
1690 HRESULT hr;
1691
1692 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1693 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1694
1695 while (test->xml)
1696 {
1697 XmlNodeType type;
1698
1699 set_input_string(reader, test->xml);
1700
1701 type = XmlNodeType_None;
1702 hr = IXmlReader_Read(reader, &type);
1703
1704 /* read one more to get to CDATA */
1705 if (type == XmlNodeType_Element)
1706 {
1707 type = XmlNodeType_None;
1708 hr = IXmlReader_Read(reader, &type);
1709 }
1710
1711 if (test->hr_broken)
1712 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1713 else
1714 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1715 if (hr == S_OK)
1716 {
1717 const WCHAR *str;
1718 UINT len;
1719
1720 ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml);
1721
1722 reader_name(reader, "");
1723
1724 str = NULL;
1725 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1726 ok(hr == S_OK, "got 0x%08x\n", hr);
1727 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1728
1729 len = 1;
1730 str = NULL;
1731 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1732 ok(hr == S_OK, "got 0x%08x\n", hr);
1733 ok(len == 0, "got %u\n", len);
1734 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1735
1736 str = NULL;
1737 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1738 ok(hr == S_OK, "got 0x%08x\n", hr);
1739 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1740
1741 /* value */
1742 reader_value(reader, test->value);
1743 }
1744
1745 test++;
1746 }
1747
1748 IXmlReader_Release(reader);
1749 }
1750
1751 static struct test_entry text_tests[] = {
1752 { "<a>simple text</a>", "", "simple text", S_OK },
1753 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND },
1754 { "<a>\n \r\n \n\n text</a>", "", "\n \n \n\n text", S_OK, S_OK },
1755 { "<a>\r \r\r\n \n\n text</a>", "", "\n \n\n \n\n text", S_OK, S_OK },
1756 { NULL }
1757 };
1758
1759 static void test_read_text(void)
1760 {
1761 struct test_entry *test = text_tests;
1762 IXmlReader *reader;
1763 HRESULT hr;
1764
1765 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1766 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1767
1768 while (test->xml)
1769 {
1770 XmlNodeType type;
1771
1772 set_input_string(reader, test->xml);
1773
1774 type = XmlNodeType_None;
1775 hr = IXmlReader_Read(reader, &type);
1776
1777 /* read one more to get to text node */
1778 if (type == XmlNodeType_Element)
1779 {
1780 type = XmlNodeType_None;
1781 hr = IXmlReader_Read(reader, &type);
1782 }
1783 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1784 if (hr == S_OK)
1785 {
1786 const WCHAR *str;
1787 UINT len;
1788
1789 ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml);
1790
1791 reader_name(reader, "");
1792
1793 str = NULL;
1794 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1795 ok(hr == S_OK, "got 0x%08x\n", hr);
1796 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1797
1798 len = 1;
1799 str = NULL;
1800 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1801 ok(hr == S_OK, "got 0x%08x\n", hr);
1802 ok(len == 0, "got %u\n", len);
1803 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1804
1805 str = NULL;
1806 hr = IXmlReader_GetQualifiedName(reader, &str, NULL);
1807 ok(hr == S_OK, "got 0x%08x\n", hr);
1808 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1809
1810 /* value */
1811 reader_value(reader, test->value);
1812 }
1813
1814 test++;
1815 }
1816
1817 IXmlReader_Release(reader);
1818 }
1819
1820 struct test_entry_empty {
1821 const char *xml;
1822 BOOL empty;
1823 };
1824
1825 static struct test_entry_empty empty_element_tests[] = {
1826 { "<a></a>", FALSE },
1827 { "<a/>", TRUE },
1828 { NULL }
1829 };
1830
1831 static void test_isemptyelement(void)
1832 {
1833 struct test_entry_empty *test = empty_element_tests;
1834 IXmlReader *reader;
1835 HRESULT hr;
1836
1837 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1838 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1839
1840 while (test->xml)
1841 {
1842 XmlNodeType type;
1843 BOOL ret;
1844
1845 set_input_string(reader, test->xml);
1846
1847 type = XmlNodeType_None;
1848 hr = IXmlReader_Read(reader, &type);
1849 ok(hr == S_OK, "got 0x%08x\n", hr);
1850 ok(type == XmlNodeType_Element, "got %d\n", type);
1851
1852 ret = IXmlReader_IsEmptyElement(reader);
1853 ok(ret == test->empty, "got %d, expected %d. xml=%s\n", ret, test->empty, test->xml);
1854
1855 test++;
1856 }
1857
1858 IXmlReader_Release(reader);
1859 }
1860
1861 static struct test_entry attributes_tests[] = {
1862 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK },
1863 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK },
1864 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK },
1865 { "<a attr1=\' \'/>", "attr1", " ", S_OK },
1866 { "<a attr1=\" \"/>", "attr1", " ", S_OK },
1867 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK },
1868 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK },
1869 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK },
1870 { "<a attr1=\"val&#32;\"/>", "attr1", "val ", S_OK },
1871 { "<a attr1=\"val&#x20;\"/>", "attr1", "val ", S_OK },
1872 { "<a attr1=\"&lt;&gt;&amp;&apos;&quot;\"/>", "attr1", "<>&\'\"", S_OK },
1873 { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY },
1874 { "<a attr1=\"val&#xfffe;\"/>", NULL, NULL, WC_E_XMLCHARACTER },
1875 { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON },
1876 { "<a attr1=\"val &#12a;\"/>", NULL, NULL, WC_E_SEMICOLON },
1877 { "<a attr1=\"val &#x12g;\"/>", NULL, NULL, WC_E_SEMICOLON },
1878 { "<a attr1=\"val &#xg;\"/>", NULL, NULL, WC_E_HEXDIGIT, WC_E_SEMICOLON },
1879 { "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
1880 { "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
1881 { "<a attr1=\"&entname\"/>", NULL, NULL, WC_E_SEMICOLON },
1882 { NULL }
1883 };
1884
1885 static void test_read_attribute(void)
1886 {
1887 struct test_entry *test = attributes_tests;
1888 IXmlReader *reader;
1889 HRESULT hr;
1890
1891 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1892 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1893
1894 while (test->xml)
1895 {
1896 XmlNodeType type;
1897
1898 set_input_string(reader, test->xml);
1899
1900 hr = IXmlReader_Read(reader, NULL);
1901
1902 if (test->hr_broken)
1903 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1904 else
1905 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1906 if (hr == S_OK)
1907 {
1908 const WCHAR *str;
1909 WCHAR *str_exp;
1910 UINT len;
1911
1912 type = XmlNodeType_None;
1913 hr = IXmlReader_GetNodeType(reader, &type);
1914 ok(hr == S_OK, "Failed to get node type, %#x\n", hr);
1915
1916 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1917
1918 hr = IXmlReader_MoveToFirstAttribute(reader);
1919 ok(hr == S_OK, "got 0x%08x\n", hr);
1920
1921 reader_name(reader, test->name);
1922
1923 len = 1;
1924 str = NULL;
1925 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1926 ok(hr == S_OK, "got 0x%08x\n", hr);
1927 ok(len == strlen(test->name), "got %u\n", len);
1928 str_exp = a2w(test->name);
1929 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1930 free_str(str_exp);
1931
1932 /* value */
1933 reader_value(reader, test->value);
1934 }
1935
1936 test++;
1937 }
1938
1939 IXmlReader_Release(reader);
1940 }
1941
1942 static void test_reader_properties(void)
1943 {
1944 IXmlReader *reader;
1945 LONG_PTR value;
1946 HRESULT hr;
1947
1948 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1949 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1950
1951 value = 0;
1952 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
1953 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
1954 ok(value == 256, "Unexpected default max depth value %ld\n", value);
1955
1956 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0);
1957 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1958
1959 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
1960 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1961
1962 value = 256;
1963 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_MaxElementDepth, &value);
1964 ok(hr == S_OK, "GetProperty failed: %08x\n", hr);
1965 ok(value == 0, "Unexpected max depth value %ld\n", value);
1966
1967 IXmlReader_Release(reader);
1968 }
1969
1970 static void test_prefix(void)
1971 {
1972 static const struct
1973 {
1974 const char *xml;
1975 const char *prefix1;
1976 const char *prefix2;
1977 const char *prefix3;
1978 } prefix_tests[] =
1979 {
1980 { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" },
1981 { "<c:b xmlns:c=\"c ns\" xml:a=\"a ns\"/>", "c", "xmlns", "xml" },
1982 };
1983 IXmlReader *reader;
1984 unsigned int i;
1985 HRESULT hr;
1986
1987 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1988 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1989
1990 for (i = 0; i < ARRAY_SIZE(prefix_tests); i++) {
1991 XmlNodeType type;
1992
1993 set_input_string(reader, prefix_tests[i].xml);
1994
1995 hr = IXmlReader_Read(reader, &type);
1996 ok(hr == S_OK, "Read() failed, %#x\n", hr);
1997 ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type);
1998
1999 reader_prefix(reader, prefix_tests[i].prefix1);
2000
2001 hr = IXmlReader_MoveToFirstAttribute(reader);
2002 ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr);
2003
2004 hr = IXmlReader_GetNodeType(reader, &type);
2005 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
2006 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
2007
2008 reader_prefix(reader, prefix_tests[i].prefix2);
2009
2010 next_attribute(reader);
2011
2012 hr = IXmlReader_GetNodeType(reader, &type);
2013 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
2014 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
2015
2016 reader_prefix(reader, prefix_tests[i].prefix3);
2017
2018 /* back to the element, check prefix */
2019 move_to_element(reader);
2020 reader_prefix(reader, prefix_tests[i].prefix1);
2021 }
2022
2023 IXmlReader_Release(reader);
2024 }
2025
2026 static void test_namespaceuri(void)
2027 {
2028 struct uri_test
2029 {
2030 const char *xml;
2031 const char *uri[5];
2032 } uri_tests[] =
2033 {
2034 { "<a xmlns=\"defns a\"><b xmlns=\"defns b\"><c xmlns=\"defns c\"/></b></a>",
2035 { "defns a", "defns b", "defns c", "defns b", "defns a" }},
2036 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"/>",
2037 { "ns r" }},
2038 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"><b/></r:a>",
2039 { "ns r", "defns a", "ns r" }},
2040 { "<a xmlns=\"defns a\" xmlns:r=\"ns r\"><r:b/></a>",
2041 { "defns a", "ns r", "defns a" }},
2042 { "<a><b><c/></b></a>",
2043 { "", "", "", "", "" }},
2044 { "<a>text</a>",
2045 { "", "", "" }},
2046 { "<a>\r\n</a>",
2047 { "", "", "" }},
2048 { "<a><![CDATA[data]]></a>",
2049 { "", "", "" }},
2050 { "<?xml version=\"1.0\" ?><a/>",
2051 { "", "" }},
2052 { "<a><?pi ?></a>",
2053 { "", "", "" }},
2054 { "<a><!-- comment --></a>",
2055 { "", "", "" }},
2056 };
2057 IXmlReader *reader;
2058 XmlNodeType type;
2059 unsigned int i;
2060 HRESULT hr;
2061
2062 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
2063 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2064
2065 for (i = 0; i < ARRAY_SIZE(uri_tests); i++) {
2066 unsigned int j = 0;
2067
2068 set_input_string(reader, uri_tests[i].xml);
2069
2070 type = ~0u;
2071 while (IXmlReader_Read(reader, &type) == S_OK) {
2072 const WCHAR *local, *qname;
2073 UINT length, length2;
2074
2075 ok(type == XmlNodeType_Element ||
2076 type == XmlNodeType_Text ||
2077 type == XmlNodeType_CDATA ||
2078 type == XmlNodeType_ProcessingInstruction ||
2079 type == XmlNodeType_Comment ||
2080 type == XmlNodeType_Whitespace ||
2081 type == XmlNodeType_EndElement ||
2082 type == XmlNodeType_XmlDeclaration, "Unexpected node type %d.\n", type);
2083
2084 local = NULL;
2085 length = 0;
2086 hr = IXmlReader_GetLocalName(reader, &local, &length);
2087 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2088 ok(local != NULL, "Unexpected NULL local name pointer\n");
2089
2090 qname = NULL;
2091 length2 = 0;
2092 hr = IXmlReader_GetQualifiedName(reader, &qname, &length2);
2093 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2094 ok(qname != NULL, "Unexpected NULL qualified name pointer\n");
2095
2096 if (type == XmlNodeType_Element ||
2097 type == XmlNodeType_EndElement ||
2098 type == XmlNodeType_ProcessingInstruction ||
2099 type == XmlNodeType_XmlDeclaration)
2100 {
2101 ok(*local != 0, "Unexpected empty local name\n");
2102 ok(length > 0, "Unexpected local name length\n");
2103
2104 ok(*qname != 0, "Unexpected empty qualified name\n");
2105 ok(length2 > 0, "Unexpected qualified name length\n");
2106 }
2107
2108 reader_namespace(reader, uri_tests[i].uri[j]);
2109
2110 j++;
2111 }
2112 ok(type == XmlNodeType_None, "Unexpected node type %d\n", type);
2113 }
2114
2115 IXmlReader_Release(reader);
2116 }
2117
2118 static void test_read_charref(void)
2119 {
2120 static const char testA[] = "<a b=\"c\">&#x1f3;&#x103;&gt;</a>";
2121 static const WCHAR chardataW[] = {0x01f3,0x0103,'>',0};
2122 const WCHAR *value;
2123 IXmlReader *reader;
2124 XmlNodeType type;
2125 HRESULT hr;
2126
2127 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2128 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2129
2130 set_input_string(reader, testA);
2131
2132 hr = IXmlReader_Read(reader, &type);
2133 ok(hr == S_OK, "got %08x\n", hr);
2134 ok(type == XmlNodeType_Element, "Unexpected node type %d\n", type);
2135
2136 hr = IXmlReader_Read(reader, &type);
2137 ok(hr == S_OK, "got %08x\n", hr);
2138 ok(type == XmlNodeType_Text, "Unexpected node type %d\n", type);
2139
2140 hr = IXmlReader_GetValue(reader, &value, NULL);
2141 ok(hr == S_OK, "got %08x\n", hr);
2142 ok(!lstrcmpW(value, chardataW), "Text value : %s\n", wine_dbgstr_w(value));
2143
2144 hr = IXmlReader_Read(reader, &type);
2145 ok(hr == S_OK, "got %08x\n", hr);
2146 ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type);
2147
2148 hr = IXmlReader_Read(reader, &type);
2149 ok(hr == S_FALSE, "got %08x\n", hr);
2150 ok(type == XmlNodeType_None, "Unexpected node type %d\n", type);
2151
2152 IXmlReader_Release(reader);
2153 }
2154
2155 static void test_encoding_detection(void)
2156 {
2157 static const struct encoding_testW
2158 {
2159 WCHAR text[16];
2160 }
2161 encoding_testsW[] =
2162 {
2163 { { '<','?','p','i',' ','?','>',0 } },
2164 { { '<','!','-','-',' ','c','-','-','>',0 } },
2165 { { 0xfeff,'<','a','/','>',0 } },
2166 { { '<','a','/','>',0 } },
2167 };
2168 static const char *encoding_testsA[] =
2169 {
2170 "<?pi ?>",
2171 "<!-- comment -->",
2172 "\xef\xbb\xbf<a/>", /* UTF-8 BOM */
2173 "<a/>",
2174 };
2175 IXmlReader *reader;
2176 XmlNodeType type;
2177 IStream *stream;
2178 unsigned int i;
2179 HRESULT hr;
2180
2181 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2182 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2183
2184 /* there's no way to query detected encoding back, so just verify that document is browsable */
2185
2186 for (i = 0; i < ARRAY_SIZE(encoding_testsA); i++)
2187 {
2188 set_input_string(reader, encoding_testsA[i]);
2189
2190 type = XmlNodeType_None;
2191 hr = IXmlReader_Read(reader, &type);
2192 ok(hr == S_OK, "got %08x\n", hr);
2193 ok(type != XmlNodeType_None, "Unexpected node type %d\n", type);
2194 }
2195
2196 for (i = 0; i < ARRAY_SIZE(encoding_testsW); i++)
2197 {
2198 stream = create_stream_on_data(encoding_testsW[i].text, lstrlenW(encoding_testsW[i].text) * sizeof(WCHAR));
2199
2200 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2201 ok(hr == S_OK, "got %08x\n", hr);
2202
2203 type = XmlNodeType_None;
2204 hr = IXmlReader_Read(reader, &type);
2205 ok(hr == S_OK, "%u: got %08x\n", i, hr);
2206 ok(type != XmlNodeType_None, "%u: unexpected node type %d\n", i, type);
2207
2208 IStream_Release(stream);
2209 }
2210
2211 IXmlReader_Release(reader);
2212 }
2213
2214 static void test_eof_state(IXmlReader *reader, BOOL eof)
2215 {
2216 LONG_PTR state;
2217 HRESULT hr;
2218
2219 ok(IXmlReader_IsEOF(reader) == eof, "Unexpected IsEOF() result\n");
2220 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
2221 ok(hr == S_OK, "GetProperty() failed, %#x\n", hr);
2222 ok((state == XmlReadState_EndOfFile) == eof, "Unexpected EndOfFile state %ld\n", state);
2223 }
2224
2225 static void test_endoffile(void)
2226 {
2227 IXmlReader *reader;
2228 XmlNodeType type;
2229 HRESULT hr;
2230
2231 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2232 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2233
2234 test_eof_state(reader, FALSE);
2235
2236 set_input_string(reader, "<a/>");
2237
2238 test_eof_state(reader, FALSE);
2239
2240 type = XmlNodeType_None;
2241 hr = IXmlReader_Read(reader, &type);
2242 ok(hr == S_OK, "got %#x\n", hr);
2243 ok(type == XmlNodeType_Element, "Unexpected type %d\n", type);
2244
2245 test_eof_state(reader, FALSE);
2246
2247 type = XmlNodeType_Element;
2248 hr = IXmlReader_Read(reader, &type);
2249 ok(hr == S_FALSE, "got %#x\n", hr);
2250 ok(type == XmlNodeType_None, "Unexpected type %d\n", type);
2251
2252 test_eof_state(reader, TRUE);
2253
2254 hr = IXmlReader_SetInput(reader, NULL);
2255 ok(hr == S_OK, "got %08x\n", hr);
2256
2257 test_eof_state(reader, FALSE);
2258
2259 IXmlReader_Release(reader);
2260
2261 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2262 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2263
2264 set_input_string(reader, "<a/>text");
2265
2266 type = XmlNodeType_None;
2267 hr = IXmlReader_Read(reader, &type);
2268 ok(hr == S_OK, "got %#x\n", hr);
2269 ok(type == XmlNodeType_Element, "Unexpected type %d\n", type);
2270
2271 test_eof_state(reader, FALSE);
2272
2273 type = XmlNodeType_Element;
2274 hr = IXmlReader_Read(reader, &type);
2275 ok(hr == WC_E_SYNTAX, "got %#x\n", hr);
2276 ok(type == XmlNodeType_None, "Unexpected type %d\n", type);
2277
2278 test_eof_state(reader, FALSE);
2279
2280 hr = IXmlReader_SetInput(reader, NULL);
2281 ok(hr == S_OK, "got %08x\n", hr);
2282
2283 IXmlReader_Release(reader);
2284 }
2285
2286 static void test_max_element_depth(void)
2287 {
2288 static const char *xml =
2289 "<a>"
2290 "<b attrb=\"_b\">"
2291 "<c>"
2292 "<d></d>"
2293 "</c>"
2294 "</b>"
2295 "</a>";
2296 XmlNodeType nodetype;
2297 unsigned int count;
2298 IXmlReader *reader;
2299 HRESULT hr;
2300
2301 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2302 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2303
2304 set_input_string(reader, xml);
2305
2306 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2307 ok(hr == S_OK, "got %08x\n", hr);
2308
2309 TEST_DEPTH(reader, 0);
2310
2311 hr = IXmlReader_Read(reader, NULL);
2312 ok(hr == S_OK, "got %08x\n", hr);
2313
2314 TEST_DEPTH(reader, 0);
2315
2316 hr = IXmlReader_Read(reader, NULL);
2317 ok(hr == S_OK, "got %08x\n", hr);
2318
2319 TEST_DEPTH(reader, 1);
2320 TEST_READER_STATE(reader, XmlReadState_Interactive);
2321
2322 hr = IXmlReader_Read(reader, NULL);
2323 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2324
2325 TEST_DEPTH2(reader, 0, 2);
2326 TEST_READER_STATE(reader, XmlReadState_Error);
2327
2328 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 10);
2329 ok(hr == S_OK, "got %08x\n", hr);
2330
2331 hr = IXmlReader_Read(reader, NULL);
2332 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2333
2334 TEST_DEPTH2(reader, 0, 2);
2335 TEST_READER_STATE(reader, XmlReadState_Error);
2336
2337 /* test if stepping into attributes enforces depth limit too */
2338 set_input_string(reader, xml);
2339
2340 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 2);
2341 ok(hr == S_OK, "got %08x\n", hr);
2342
2343 TEST_DEPTH(reader, 0);
2344
2345 hr = IXmlReader_Read(reader, NULL);
2346 ok(hr == S_OK, "got %08x\n", hr);
2347
2348 TEST_DEPTH(reader, 0);
2349
2350 hr = IXmlReader_Read(reader, NULL);
2351 ok(hr == S_OK, "got %08x\n", hr);
2352
2353 TEST_DEPTH(reader, 1);
2354
2355 hr = IXmlReader_MoveToFirstAttribute(reader);
2356 ok(hr == S_OK, "got %08x\n", hr);
2357
2358 TEST_DEPTH(reader, 2);
2359 TEST_READER_STATE(reader, XmlReadState_Interactive);
2360
2361 nodetype = 123;
2362 hr = IXmlReader_Read(reader, &nodetype);
2363 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2364 ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype);
2365
2366 nodetype = 123;
2367 hr = IXmlReader_Read(reader, &nodetype);
2368 ok(hr == SC_E_MAXELEMENTDEPTH, "got %08x\n", hr);
2369 ok(nodetype == XmlNodeType_None, "got node type %d\n", nodetype);
2370
2371 TEST_DEPTH2(reader, 0, 2);
2372 TEST_READER_STATE(reader, XmlReadState_Error);
2373
2374 /* set max depth to 0, this disables depth limit */
2375 set_input_string(reader, xml);
2376
2377 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
2378 ok(hr == S_OK, "got %08x\n", hr);
2379
2380 count = 0;
2381 while (IXmlReader_Read(reader, NULL) == S_OK)
2382 count++;
2383 ok(count == 8, "Unexpected node number %u\n", count);
2384 TEST_READER_STATE(reader, XmlReadState_EndOfFile);
2385
2386 IXmlReader_Release(reader);
2387 }
2388
2389 static void test_reader_position(void)
2390 {
2391 static const char *xml = "<c:a xmlns:c=\"nsdef c\" b=\"attr b\">\n</c:a>";
2392 IXmlReader *reader;
2393 XmlNodeType type;
2394 UINT position;
2395 HRESULT hr;
2396
2397 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2398 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2399
2400 TEST_READER_STATE(reader, XmlReadState_Closed);
2401
2402 /* position methods with Null args */
2403 hr = IXmlReader_GetLineNumber(reader, NULL);
2404 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2405
2406 hr = IXmlReader_GetLinePosition(reader, NULL);
2407 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
2408
2409 position = 123;
2410 hr = IXmlReader_GetLinePosition(reader, &position);
2411 ok(hr == S_FALSE, "got %#x\n", hr);
2412 ok(position == 0, "got %u\n", position);
2413
2414 position = 123;
2415 hr = IXmlReader_GetLineNumber(reader, &position);
2416 ok(hr == S_FALSE, "got %#x\n", hr);
2417 ok(position == 0, "got %u\n", position);
2418
2419 set_input_string(reader, xml);
2420
2421 TEST_READER_STATE(reader, XmlReadState_Initial);
2422 TEST_READER_POSITION(reader, 0, 0);
2423 hr = IXmlReader_Read(reader, &type);
2424 ok(hr == S_OK, "got %08x\n", hr);
2425 ok(type == XmlNodeType_Element, "got type %d\n", type);
2426 TEST_READER_POSITION2(reader, 1, 2, ~0u, 34);
2427
2428 next_attribute(reader);
2429 TEST_READER_POSITION2(reader, 1, 6, ~0u, 34);
2430
2431 next_attribute(reader);
2432 TEST_READER_POSITION2(reader, 1, 24, ~0u, 34);
2433
2434 move_to_element(reader);
2435 TEST_READER_POSITION2(reader, 1, 2, ~0u, 34);
2436
2437 hr = IXmlReader_Read(reader, &type);
2438 ok(hr == S_OK, "got %08x\n", hr);
2439 ok(type == XmlNodeType_Whitespace, "got type %d\n", type);
2440 TEST_READER_POSITION2(reader, 1, 35, 2, 6);
2441
2442 hr = IXmlReader_Read(reader, &type);
2443 ok(hr == S_OK, "got %08x\n", hr);
2444 ok(type == XmlNodeType_EndElement, "got type %d\n", type);
2445 TEST_READER_POSITION2(reader, 2, 3, 2, 6);
2446
2447 hr = IXmlReader_SetInput(reader, NULL);
2448 ok(hr == S_OK, "got %08x\n", hr);
2449 TEST_READER_STATE2(reader, XmlReadState_Initial, XmlReadState_Closed);
2450 TEST_READER_POSITION(reader, 0, 0);
2451
2452 IXmlReader_Release(reader);
2453 }
2454
2455 static void test_string_pointers(void)
2456 {
2457 const WCHAR *ns, *nsq, *empty, *xmlns_ns, *xmlns_name, *name, *p, *q, *xml, *ptr, *value;
2458 IXmlReader *reader;
2459 HRESULT hr;
2460
2461 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2462 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2463
2464 set_input_string(reader, "<elem xmlns=\"myns\">myns<elem2 /></elem>");
2465
2466 read_node(reader, XmlNodeType_Element);
2467 empty = reader_value(reader, "");
2468 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2469 name = reader_name(reader, "elem");
2470 ok(name == reader_qname(reader, "elem"), "name != qname\n");
2471 ns = reader_namespace(reader, "myns");
2472
2473 next_attribute(reader);
2474 ptr = reader_value(reader, "myns");
2475 if (ns != ptr)
2476 {
2477 win_skip("attr value is different than namespace pointer, assuming old xmllite\n");
2478 IXmlReader_Release(reader);
2479 return;
2480 }
2481 ok(ns == ptr, "ns != value\n");
2482 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2483 xmlns_ns = reader_namespace(reader, "http://www.w3.org/2000/xmlns/");
2484 xmlns_name = reader_name(reader, "xmlns");
2485 ok(xmlns_name == reader_qname(reader, "xmlns"), "xmlns_name != qname\n");
2486
2487 read_node(reader, XmlNodeType_Text);
2488 ok(ns != reader_value(reader, "myns"), "ns == value\n");
2489 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2490 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2491 ok(empty == reader_name(reader, ""), "empty != name\n");
2492 ok(empty == reader_qname(reader, ""), "empty != qname\n");
2493
2494 read_node(reader, XmlNodeType_Element);
2495 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2496 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2497
2498 read_node(reader, XmlNodeType_EndElement);
2499 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2500 ok(name == reader_name(reader, "elem"), "empty != name\n");
2501 ok(name == reader_qname(reader, "elem"), "empty != qname\n");
2502 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2503
2504 set_input_string(reader, "<elem xmlns:p=\"myns\" xmlns:q=\"mynsq\"><p:elem2 q:attr=\"\"></p:elem2></elem>");
2505
2506 read_node(reader, XmlNodeType_Element);
2507 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2508 name = reader_name(reader, "elem");
2509 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2510
2511 next_attribute(reader);
2512 ns = reader_value(reader, "myns");
2513 ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n");
2514 p = reader_name(reader, "p");
2515 ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2516
2517 next_attribute(reader);
2518 nsq = reader_value(reader, "mynsq");
2519 ok(xmlns_name == reader_prefix(reader, "xmlns"), "xmlns_name != prefix\n");
2520 q = reader_name(reader, "q");
2521 ok(xmlns_ns == reader_namespace(reader, "http://www.w3.org/2000/xmlns/"), "xmlns_ns != namespace\n");
2522
2523 read_node(reader, XmlNodeType_Element);
2524 ok(p == reader_prefix(reader, "p"), "p != prefix\n");
2525 ok(ns == reader_namespace(reader, "myns"), "empty != namespace\n");
2526 name = reader_qname(reader, "p:elem2");
2527
2528 next_attribute(reader);
2529 ok(empty != reader_value(reader, ""), "empty == value\n");
2530 ok(q == reader_prefix(reader, "q"), "q != prefix\n");
2531 ok(nsq == reader_namespace(reader, "mynsq"), "nsq != namespace\n");
2532
2533 read_node(reader, XmlNodeType_EndElement);
2534 ptr = reader_qname(reader, "p:elem2"); todo_wine ok(name != ptr, "q == qname\n");
2535
2536 set_input_string(reader, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
2537
2538 read_node(reader, XmlNodeType_XmlDeclaration);
2539 ok(empty == reader_value(reader, ""), "empty != value\n");
2540 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2541 xml = reader_name(reader, "xml");
2542 ptr = reader_qname(reader, "xml"); todo_wine ok(xml == ptr, "xml != qname\n");
2543 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2544
2545 next_attribute(reader);
2546 ok(empty == reader_prefix(reader, ""), "empty != prefix\n");
2547 ok(empty == reader_namespace(reader, ""), "empty != namespace\n");
2548
2549 set_input_string(reader, "<elem xmlns:p=\"myns\"><p:elem2 attr=\"\" /></elem>");
2550
2551 read_node(reader, XmlNodeType_Element);
2552 next_attribute(reader);
2553 read_value_char(reader, 'm');
2554 p = reader_value(reader, "yns");
2555
2556 read_node(reader, XmlNodeType_Element);
2557 ns = reader_namespace(reader, "myns");
2558 ok(ns+1 == p, "ns+1 != p\n");
2559
2560 set_input_string(reader, "<elem attr=\"value\"></elem>");
2561
2562 read_node(reader, XmlNodeType_Element);
2563 next_attribute(reader);
2564 name = reader_name(reader, "attr");
2565 value = reader_value(reader, "value");
2566
2567 move_to_element(reader);
2568 next_attribute(reader);
2569 ok(name == reader_name(reader, "attr"), "attr pointer changed\n");
2570 ok(value == reader_value(reader, "value"), "value pointer changed\n");
2571
2572 IXmlReader_Release(reader);
2573 }
2574
2575 static void test_attribute_by_name(void)
2576 {
2577 static const char *xml = "<a><elem xmlns=\"myns\" a=\"value a\" b=\"value b\" xmlns:ns=\"ns uri\" "
2578 "ns:c=\"value c\" c=\"value c2\"/></a>";
2579 static const WCHAR xmlns_uriW[] = {'h','t','t','p',':','/','/','w','w','w','.','w','3','.','o','r','g','/',
2580 '2','0','0','0','/','x','m','l','n','s','/',0};
2581 static const WCHAR nsuriW[] = {'n','s',' ','u','r','i',0};
2582 static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
2583 static const WCHAR mynsW[] = {'m','y','n','s',0};
2584 static const WCHAR nsW[] = {'n','s',0};
2585 static const WCHAR emptyW[] = {0};
2586 static const WCHAR aW[] = {'a',0};
2587 static const WCHAR bW[] = {'b',0};
2588 static const WCHAR cW[] = {'c',0};
2589 IXmlReader *reader;
2590 HRESULT hr;
2591
2592 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2593 ok(hr == S_OK, "Failed to create reader, hr %#x.\n", hr);
2594
2595 set_input_string(reader, xml);
2596
2597 hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
2598 ok(hr == E_INVALIDARG || broken(hr == S_FALSE) /* WinXP */, "Unexpected hr %#x.\n", hr);
2599
2600 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
2601 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2602
2603 read_node(reader, XmlNodeType_Element);
2604
2605 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, NULL);
2606 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2607
2608 read_node(reader, XmlNodeType_Element);
2609
2610 hr = IXmlReader_MoveToAttributeByName(reader, NULL, NULL);
2611 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2612
2613 hr = IXmlReader_MoveToAttributeByName(reader, NULL, xmlns_uriW);
2614 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2615
2616 hr = IXmlReader_MoveToAttributeByName(reader, emptyW, xmlns_uriW);
2617 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2618
2619 hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, NULL);
2620 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2621
2622 hr = IXmlReader_MoveToAttributeByName(reader, xmlnsW, xmlns_uriW);
2623 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2624 reader_value(reader, "myns");
2625
2626 hr = IXmlReader_MoveToAttributeByName(reader, aW, NULL);
2627 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2628 reader_value(reader, "value a");
2629
2630 hr = IXmlReader_MoveToAttributeByName(reader, bW, NULL);
2631 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2632 reader_value(reader, "value b");
2633
2634 hr = IXmlReader_MoveToAttributeByName(reader, aW, mynsW);
2635 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2636
2637 hr = IXmlReader_MoveToAttributeByName(reader, nsW, NULL);
2638 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2639
2640 hr = IXmlReader_MoveToAttributeByName(reader, nsW, xmlns_uriW);
2641 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2642 reader_value(reader, "ns uri");
2643
2644 hr = IXmlReader_MoveToAttributeByName(reader, bW, emptyW);
2645 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2646 reader_value(reader, "value b");
2647
2648 hr = IXmlReader_MoveToAttributeByName(reader, cW, NULL);
2649 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2650 reader_value(reader, "value c2");
2651
2652 hr = IXmlReader_MoveToAttributeByName(reader, cW, nsuriW);
2653 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2654 reader_value(reader, "value c");
2655
2656 IXmlReader_Release(reader);
2657 }
2658
2659 START_TEST(reader)
2660 {
2661 test_reader_create();
2662 test_readerinput();
2663 test_reader_state();
2664 test_read_attribute();
2665 test_read_cdata();
2666 test_read_comment();
2667 test_read_pi();
2668 test_read_system_dtd();
2669 test_read_public_dtd();
2670 test_read_element();
2671 test_isemptyelement();
2672 test_read_text();
2673 test_read_full();
2674 test_read_pending();
2675 test_readvaluechunk();
2676 test_read_xmldeclaration();
2677 test_reader_properties();
2678 test_prefix();
2679 test_namespaceuri();
2680 test_read_charref();
2681 test_encoding_detection();
2682 test_endoffile();
2683 test_max_element_depth();
2684 test_reader_position();
2685 test_string_pointers();
2686 test_attribute_by_name();
2687 }