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