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