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