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