[XMLLITE] Sync with Wine Staging 2.2. CORE-12823
[reactos.git] / rostests / winetests / xmllite / reader.c
1 /*
2 * IXmlReader tests
3 *
4 * Copyright 2010, 2012-2013 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 WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26 #define CONST_VTABLE
27
28 //#include <stdarg.h>
29 #include <stdio.h>
30
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <initguid.h>
35 #include <ole2.h>
36 #include <xmllite.h>
37 #include <wine/test.h>
38
39 DEFINE_GUID(IID_IXmlReaderInput, 0x0b3ccc9b, 0x9214, 0x428b, 0xa2, 0xae, 0xef, 0x3a, 0xa8, 0x71, 0xaf, 0xda);
40
41 static WCHAR *a2w(const char *str)
42 {
43 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
44 WCHAR *ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
45 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
46 return ret;
47 }
48
49 static void free_str(WCHAR *str)
50 {
51 HeapFree(GetProcessHeap(), 0, str);
52 }
53
54 static const char xmldecl_full[] = "\xef\xbb\xbf<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n";
55 static const char xmldecl_short[] = "<?xml version=\"1.0\"?><RegistrationInfo/>";
56
57 static IStream *create_stream_on_data(const char *data, int size)
58 {
59 IStream *stream = NULL;
60 HGLOBAL hglobal;
61 void *ptr;
62 HRESULT hr;
63
64 hglobal = GlobalAlloc(GHND, size);
65 ptr = GlobalLock(hglobal);
66
67 memcpy(ptr, data, size);
68
69 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
70 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
71 ok(stream != NULL, "Expected non-NULL stream\n");
72
73 GlobalUnlock(hglobal);
74
75 return stream;
76 }
77
78 static void ok_pos_(IXmlReader *reader, int line, int pos, int line_broken,
79 int pos_broken, BOOL todo, int _line_)
80 {
81 UINT l, p;
82 HRESULT hr;
83 BOOL broken_state;
84
85 hr = IXmlReader_GetLineNumber(reader, &l);
86 ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
87 hr = IXmlReader_GetLinePosition(reader, &p);
88 ok_(__FILE__, _line_)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
89
90 if (line_broken == -1 && pos_broken == -1)
91 broken_state = FALSE;
92 else
93 broken_state = broken((line_broken == -1 ? line : line_broken) == l &&
94 (pos_broken == -1 ? pos : pos_broken) == p);
95
96 todo_wine_if (todo)
97 ok_(__FILE__, _line_)((l == line && pos == p) || broken_state,
98 "Expected (%d,%d), got (%d,%d)\n", line, pos, l, p);
99 }
100 #define ok_pos(reader, l, p, l_brk, p_brk, todo) ok_pos_(reader, l, p, l_brk, p_brk, todo, __LINE__)
101
102 typedef struct input_iids_t {
103 IID iids[10];
104 int count;
105 } input_iids_t;
106
107 static const IID *setinput_full[] = {
108 &IID_IXmlReaderInput,
109 &IID_IStream,
110 &IID_ISequentialStream,
111 NULL
112 };
113
114 /* this applies to early xmllite versions */
115 static const IID *setinput_full_old[] = {
116 &IID_IXmlReaderInput,
117 &IID_ISequentialStream,
118 &IID_IStream,
119 NULL
120 };
121
122 /* after ::SetInput(IXmlReaderInput*) */
123 static const IID *setinput_readerinput[] = {
124 &IID_IStream,
125 &IID_ISequentialStream,
126 NULL
127 };
128
129 static const IID *empty_seq[] = {
130 NULL
131 };
132
133 static input_iids_t input_iids;
134
135 static void ok_iids_(const input_iids_t *iids, const IID **expected, const IID **exp_broken, BOOL todo, int line)
136 {
137 int i = 0, size = 0;
138
139 while (expected[i++]) size++;
140
141 todo_wine_if (todo)
142 ok_(__FILE__, line)(iids->count == size, "Sequence size mismatch (%d), got (%d)\n", size, iids->count);
143
144 if (iids->count != size) return;
145
146 for (i = 0; i < size; i++) {
147 ok_(__FILE__, line)(IsEqualGUID(&iids->iids[i], expected[i]) ||
148 (exp_broken ? broken(IsEqualGUID(&iids->iids[i], exp_broken[i])) : FALSE),
149 "Wrong IID(%d), got %s\n", i, wine_dbgstr_guid(&iids->iids[i]));
150 }
151 }
152 #define ok_iids(got, exp, brk, todo) ok_iids_(got, exp, brk, todo, __LINE__)
153
154 static const char *state_to_str(XmlReadState state)
155 {
156 static const char* state_names[] = {
157 "XmlReadState_Initial",
158 "XmlReadState_Interactive",
159 "XmlReadState_Error",
160 "XmlReadState_EndOfFile",
161 "XmlReadState_Closed"
162 };
163
164 static const char unknown[] = "unknown";
165
166 switch (state)
167 {
168 case XmlReadState_Initial:
169 case XmlReadState_Interactive:
170 case XmlReadState_Error:
171 case XmlReadState_EndOfFile:
172 case XmlReadState_Closed:
173 return state_names[state];
174 default:
175 return unknown;
176 }
177 }
178
179 static const char *type_to_str(XmlNodeType type)
180 {
181 static const char* type_names[] = {
182 "XmlNodeType_None",
183 "XmlNodeType_Element",
184 "XmlNodeType_Attribute",
185 "XmlNodeType_Text",
186 "XmlNodeType_CDATA",
187 "", "",
188 "XmlNodeType_ProcessingInstruction",
189 "XmlNodeType_Comment",
190 "",
191 "XmlNodeType_DocumentType",
192 "", "",
193 "XmlNodeType_Whitespace",
194 "",
195 "XmlNodeType_EndElement",
196 "",
197 "XmlNodeType_XmlDeclaration"
198 };
199
200 static const char unknown[] = "unknown";
201
202 switch (type)
203 {
204 case XmlNodeType_None:
205 case XmlNodeType_Element:
206 case XmlNodeType_Attribute:
207 case XmlNodeType_Text:
208 case XmlNodeType_CDATA:
209 case XmlNodeType_ProcessingInstruction:
210 case XmlNodeType_Comment:
211 case XmlNodeType_DocumentType:
212 case XmlNodeType_Whitespace:
213 case XmlNodeType_EndElement:
214 case XmlNodeType_XmlDeclaration:
215 return type_names[type];
216 default:
217 return unknown;
218 }
219 }
220
221 static void test_read_state_(IXmlReader *reader, XmlReadState expected,
222 XmlReadState exp_broken, BOOL todo, int line)
223 {
224 LONG_PTR state;
225 HRESULT hr;
226 BOOL broken_state;
227
228 state = -1; /* invalid value */
229 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, &state);
230 ok_(__FILE__, line)(hr == S_OK, "Expected S_OK, got %08x\n", hr);
231
232 if (exp_broken == -1)
233 broken_state = FALSE;
234 else
235 broken_state = broken(exp_broken == state);
236
237 todo_wine_if (todo)
238 ok_(__FILE__, line)(state == expected || broken_state, "Expected (%s), got (%s)\n",
239 state_to_str(expected), state_to_str(state));
240 }
241
242 #define test_read_state(reader, exp, brk, todo) test_read_state_(reader, exp, brk, todo, __LINE__)
243
244 typedef struct _testinput
245 {
246 IUnknown IUnknown_iface;
247 LONG ref;
248 } testinput;
249
250 static inline testinput *impl_from_IUnknown(IUnknown *iface)
251 {
252 return CONTAINING_RECORD(iface, testinput, IUnknown_iface);
253 }
254
255 static HRESULT WINAPI testinput_QueryInterface(IUnknown *iface, REFIID riid, void** ppvObj)
256 {
257 if (IsEqualGUID( riid, &IID_IUnknown ))
258 {
259 *ppvObj = iface;
260 IUnknown_AddRef(iface);
261 return S_OK;
262 }
263
264 input_iids.iids[input_iids.count++] = *riid;
265
266 *ppvObj = NULL;
267
268 return E_NOINTERFACE;
269 }
270
271 static ULONG WINAPI testinput_AddRef(IUnknown *iface)
272 {
273 testinput *This = impl_from_IUnknown(iface);
274 return InterlockedIncrement(&This->ref);
275 }
276
277 static ULONG WINAPI testinput_Release(IUnknown *iface)
278 {
279 testinput *This = impl_from_IUnknown(iface);
280 LONG ref;
281
282 ref = InterlockedDecrement(&This->ref);
283 if (ref == 0)
284 {
285 HeapFree(GetProcessHeap(), 0, This);
286 }
287
288 return ref;
289 }
290
291 static const struct IUnknownVtbl testinput_vtbl =
292 {
293 testinput_QueryInterface,
294 testinput_AddRef,
295 testinput_Release
296 };
297
298 static HRESULT testinput_createinstance(void **ppObj)
299 {
300 testinput *input;
301
302 input = HeapAlloc(GetProcessHeap(), 0, sizeof (*input));
303 if(!input) return E_OUTOFMEMORY;
304
305 input->IUnknown_iface.lpVtbl = &testinput_vtbl;
306 input->ref = 1;
307
308 *ppObj = &input->IUnknown_iface;
309
310 return S_OK;
311 }
312
313 static HRESULT WINAPI teststream_QueryInterface(ISequentialStream *iface, REFIID riid, void **obj)
314 {
315 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_ISequentialStream))
316 {
317 *obj = iface;
318 return S_OK;
319 }
320
321 *obj = NULL;
322 return E_NOINTERFACE;
323 }
324
325 static ULONG WINAPI teststream_AddRef(ISequentialStream *iface)
326 {
327 return 2;
328 }
329
330 static ULONG WINAPI teststream_Release(ISequentialStream *iface)
331 {
332 return 1;
333 }
334
335 static int stream_readcall;
336
337 static HRESULT WINAPI teststream_Read(ISequentialStream *iface, void *pv, ULONG cb, ULONG *pread)
338 {
339 static const char xml[] = "<!-- comment -->";
340
341 if (stream_readcall++)
342 {
343 *pread = 0;
344 return E_PENDING;
345 }
346
347 *pread = sizeof(xml) / 2;
348 memcpy(pv, xml, *pread);
349 return S_OK;
350 }
351
352 static HRESULT WINAPI teststream_Write(ISequentialStream *iface, const void *pv, ULONG cb, ULONG *written)
353 {
354 ok(0, "unexpected call\n");
355 return E_NOTIMPL;
356 }
357
358 static const ISequentialStreamVtbl teststreamvtbl =
359 {
360 teststream_QueryInterface,
361 teststream_AddRef,
362 teststream_Release,
363 teststream_Read,
364 teststream_Write
365 };
366
367 static HRESULT WINAPI resolver_QI(IXmlResolver *iface, REFIID riid, void **obj)
368 {
369 ok(0, "unexpected call, riid %s\n", wine_dbgstr_guid(riid));
370
371 if (IsEqualIID(riid, &IID_IXmlResolver) || IsEqualIID(riid, &IID_IUnknown))
372 {
373 *obj = iface;
374 IXmlResolver_AddRef(iface);
375 return S_OK;
376 }
377
378 *obj = NULL;
379 return E_NOINTERFACE;
380 }
381
382 static ULONG WINAPI resolver_AddRef(IXmlResolver *iface)
383 {
384 return 2;
385 }
386
387 static ULONG WINAPI resolver_Release(IXmlResolver *iface)
388 {
389 return 1;
390 }
391
392 static HRESULT WINAPI resolver_ResolveUri(IXmlResolver *iface, const WCHAR *base_uri,
393 const WCHAR *public_id, const WCHAR *system_id, IUnknown **input)
394 {
395 ok(0, "unexpected call\n");
396 return E_NOTIMPL;
397 }
398
399 static const IXmlResolverVtbl resolvervtbl =
400 {
401 resolver_QI,
402 resolver_AddRef,
403 resolver_Release,
404 resolver_ResolveUri
405 };
406
407 static IXmlResolver testresolver = { &resolvervtbl };
408
409 static void test_reader_create(void)
410 {
411 IXmlResolver *resolver;
412 HRESULT hr;
413 IXmlReader *reader;
414 IUnknown *input;
415 DtdProcessing dtd;
416 XmlNodeType nodetype;
417
418 /* crashes native */
419 if (0)
420 {
421 CreateXmlReader(&IID_IXmlReader, NULL, NULL);
422 CreateXmlReader(NULL, (void**)&reader, NULL);
423 }
424
425 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
426 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
427
428 test_read_state(reader, XmlReadState_Closed, -1, FALSE);
429
430 nodetype = XmlNodeType_Element;
431 hr = IXmlReader_GetNodeType(reader, &nodetype);
432 ok(hr == S_FALSE, "got %08x\n", hr);
433 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
434
435 /* crashes on XP, 2k3, works on newer versions */
436 if (0)
437 {
438 hr = IXmlReader_GetNodeType(reader, NULL);
439 ok(hr == E_INVALIDARG, "got %08x\n", hr);
440 }
441
442 resolver = (void*)0xdeadbeef;
443 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
444 ok(hr == S_OK, "got 0x%08x\n", hr);
445 ok(resolver == NULL, "got %p\n", resolver);
446
447 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
448 ok(hr == S_OK, "got 0x%08x\n", hr);
449
450 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR)&testresolver);
451 ok(hr == S_OK, "got 0x%08x\n", hr);
452
453 resolver = NULL;
454 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_XmlResolver, (LONG_PTR*)&resolver);
455 ok(hr == S_OK, "got 0x%08x\n", hr);
456 ok(resolver == &testresolver, "got %p\n", resolver);
457 IXmlResolver_Release(resolver);
458
459 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_XmlResolver, 0);
460 ok(hr == S_OK, "got 0x%08x\n", hr);
461
462 dtd = 2;
463 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_DtdProcessing, (LONG_PTR*)&dtd);
464 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
465 ok(dtd == DtdProcessing_Prohibit, "got %d\n", dtd);
466
467 dtd = 2;
468 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, dtd);
469 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
470
471 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, -1);
472 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
473
474 /* Null input pointer, releases previous input */
475 hr = IXmlReader_SetInput(reader, NULL);
476 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
477
478 test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE);
479
480 /* test input interface selection sequence */
481 hr = testinput_createinstance((void**)&input);
482 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
483
484 if (hr == S_OK)
485 {
486 input_iids.count = 0;
487 hr = IXmlReader_SetInput(reader, input);
488 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
489 ok_iids(&input_iids, setinput_full, setinput_full_old, FALSE);
490 IUnknown_Release(input);
491 }
492 IXmlReader_Release(reader);
493 }
494
495 static void test_readerinput(void)
496 {
497 IXmlReaderInput *reader_input;
498 IXmlReader *reader, *reader2;
499 IUnknown *obj, *input;
500 IStream *stream, *stream2;
501 XmlNodeType nodetype;
502 HRESULT hr;
503 LONG ref;
504
505 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, NULL);
506 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
507 hr = CreateXmlReaderInputWithEncodingName(NULL, NULL, NULL, FALSE, NULL, &reader_input);
508 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
509
510 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
511 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
512
513 ref = IStream_AddRef(stream);
514 ok(ref == 2, "Expected 2, got %d\n", ref);
515 IStream_Release(stream);
516 hr = CreateXmlReaderInputWithEncodingName((IUnknown*)stream, NULL, NULL, FALSE, NULL, &reader_input);
517 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
518
519 hr = IUnknown_QueryInterface(reader_input, &IID_IStream, (void**)&stream2);
520 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
521
522 hr = IUnknown_QueryInterface(reader_input, &IID_ISequentialStream, (void**)&stream2);
523 ok(hr == E_NOINTERFACE, "Expected S_OK, got %08x\n", hr);
524
525 /* IXmlReaderInput grabs a stream reference */
526 ref = IStream_AddRef(stream);
527 ok(ref == 3, "Expected 3, got %d\n", ref);
528 IStream_Release(stream);
529
530 /* try ::SetInput() with valid IXmlReaderInput */
531 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
532 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
533
534 ref = IUnknown_AddRef(reader_input);
535 ok(ref == 2, "Expected 2, got %d\n", ref);
536 IUnknown_Release(reader_input);
537
538 hr = IXmlReader_SetInput(reader, reader_input);
539 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
540
541 test_read_state(reader, XmlReadState_Initial, -1, FALSE);
542
543 nodetype = XmlNodeType_Element;
544 hr = IXmlReader_GetNodeType(reader, &nodetype);
545 ok(hr == S_OK, "got %08x\n", hr);
546 ok(nodetype == XmlNodeType_None, "got %d\n", nodetype);
547
548 /* IXmlReader grabs a IXmlReaderInput reference */
549 ref = IUnknown_AddRef(reader_input);
550 ok(ref == 3, "Expected 3, got %d\n", ref);
551 IUnknown_Release(reader_input);
552
553 ref = IStream_AddRef(stream);
554 ok(ref == 4, "Expected 4, got %d\n", ref);
555 IStream_Release(stream);
556
557 /* reset input and check state */
558 hr = IXmlReader_SetInput(reader, NULL);
559 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
560
561 test_read_state(reader, XmlReadState_Initial, XmlReadState_Closed, FALSE);
562
563 IXmlReader_Release(reader);
564
565 ref = IStream_AddRef(stream);
566 ok(ref == 3, "Expected 3, got %d\n", ref);
567 IStream_Release(stream);
568
569 ref = IUnknown_AddRef(reader_input);
570 ok(ref == 2, "Expected 2, got %d\n", ref);
571 IUnknown_Release(reader_input);
572
573 /* IID_IXmlReaderInput */
574 /* it returns a kind of private undocumented vtable incompatible with IUnknown,
575 so it's not a COM interface actually.
576 Such query will be used only to check if input is really IXmlReaderInput */
577 obj = (IUnknown*)0xdeadbeef;
578 hr = IUnknown_QueryInterface(reader_input, &IID_IXmlReaderInput, (void**)&obj);
579 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
580 ref = IUnknown_AddRef(reader_input);
581 ok(ref == 3, "Expected 3, got %d\n", ref);
582 IUnknown_Release(reader_input);
583
584 IUnknown_Release(reader_input);
585 IUnknown_Release(reader_input);
586 IStream_Release(stream);
587
588 /* test input interface selection sequence */
589 input = NULL;
590 hr = testinput_createinstance((void**)&input);
591 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
592
593 input_iids.count = 0;
594 ref = IUnknown_AddRef(input);
595 ok(ref == 2, "Expected 2, got %d\n", ref);
596 IUnknown_Release(input);
597 hr = CreateXmlReaderInputWithEncodingName(input, NULL, NULL, FALSE, NULL, &reader_input);
598 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
599 ok_iids(&input_iids, empty_seq, NULL, FALSE);
600 /* IXmlReaderInput stores stream interface as IUnknown */
601 ref = IUnknown_AddRef(input);
602 ok(ref == 3, "Expected 3, got %d\n", ref);
603 IUnknown_Release(input);
604
605 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
606 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
607
608 input_iids.count = 0;
609 ref = IUnknown_AddRef(reader_input);
610 ok(ref == 2, "Expected 2, got %d\n", ref);
611 IUnknown_Release(reader_input);
612 ref = IUnknown_AddRef(input);
613 ok(ref == 3, "Expected 3, got %d\n", ref);
614 IUnknown_Release(input);
615 hr = IXmlReader_SetInput(reader, reader_input);
616 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
617 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
618
619 test_read_state(reader, XmlReadState_Closed, -1, FALSE);
620
621 ref = IUnknown_AddRef(input);
622 ok(ref == 3, "Expected 3, got %d\n", ref);
623 IUnknown_Release(input);
624
625 ref = IUnknown_AddRef(reader_input);
626 ok(ref == 3 || broken(ref == 2) /* versions 1.0.x and 1.1.x - XP, Vista */,
627 "Expected 3, got %d\n", ref);
628 IUnknown_Release(reader_input);
629 /* repeat another time, no check or caching here */
630 input_iids.count = 0;
631 hr = IXmlReader_SetInput(reader, reader_input);
632 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
633 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
634
635 /* another reader */
636 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader2, NULL);
637 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
638
639 /* resolving from IXmlReaderInput to IStream/ISequentialStream is done at
640 ::SetInput() level, each time it's called */
641 input_iids.count = 0;
642 hr = IXmlReader_SetInput(reader2, reader_input);
643 ok(hr == E_NOINTERFACE, "Expected E_NOINTERFACE, got %08x\n", hr);
644 ok_iids(&input_iids, setinput_readerinput, NULL, FALSE);
645
646 IXmlReader_Release(reader2);
647 IXmlReader_Release(reader);
648
649 IUnknown_Release(reader_input);
650 IUnknown_Release(input);
651 }
652
653 static void test_reader_state(void)
654 {
655 IXmlReader *reader;
656 XmlNodeType nodetype;
657 HRESULT hr;
658
659 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
660 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
661
662 /* invalid arguments */
663 hr = IXmlReader_GetProperty(reader, XmlReaderProperty_ReadState, NULL);
664 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
665
666 /* attempt to read on closed reader */
667 test_read_state(reader, XmlReadState_Closed, -1, FALSE);
668 if (0)
669 {
670 /* newer versions crash here, probably cause no input was set */
671 hr = IXmlReader_Read(reader, &nodetype);
672 ok(hr == S_FALSE, "got %08x\n", hr);
673 }
674 IXmlReader_Release(reader);
675 }
676
677 static void test_read_xmldeclaration(void)
678 {
679 static const WCHAR xmlW[] = {'x','m','l',0};
680 static const WCHAR RegistrationInfoW[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0};
681 static const struct
682 {
683 WCHAR name[12];
684 WCHAR val[12];
685 } name_val[] =
686 {
687 { {'v','e','r','s','i','o','n',0}, {'1','.','0',0} },
688 { {'e','n','c','o','d','i','n','g',0}, {'U','T','F','-','8',0} },
689 { {'s','t','a','n','d','a','l','o','n','e',0}, {'y','e','s',0} }
690 };
691 IXmlReader *reader;
692 IStream *stream;
693 HRESULT hr;
694 XmlNodeType type;
695 UINT count = 0, len, i;
696 BOOL ret;
697 const WCHAR *val;
698
699 hr = CreateXmlReader(&IID_IXmlReader, (LPVOID*)&reader, NULL);
700 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
701
702 /* position methods with Null args */
703 hr = IXmlReader_GetLineNumber(reader, NULL);
704 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
705
706 hr = IXmlReader_GetLinePosition(reader, NULL);
707 ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
708
709 stream = create_stream_on_data(xmldecl_full, sizeof(xmldecl_full));
710
711 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
712 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
713
714 hr = IXmlReader_GetAttributeCount(reader, &count);
715 ok(hr == S_OK, "got %08x\n", hr);
716 ok(count == 0, "got %d\n", count);
717
718 /* try to move without attributes */
719 hr = IXmlReader_MoveToElement(reader);
720 ok(hr == S_FALSE, "got %08x\n", hr);
721
722 hr = IXmlReader_MoveToNextAttribute(reader);
723 ok(hr == S_FALSE, "got %08x\n", hr);
724
725 hr = IXmlReader_MoveToFirstAttribute(reader);
726 ok(hr == S_FALSE, "got %08x\n", hr);
727
728 ok_pos(reader, 0, 0, -1, -1, FALSE);
729
730 type = -1;
731 hr = IXmlReader_Read(reader, &type);
732 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
733 ok(type == XmlNodeType_XmlDeclaration,
734 "Expected XmlNodeType_XmlDeclaration, got %s\n", type_to_str(type));
735 /* new version 1.2.x and 1.3.x properly update position for <?xml ?> */
736 ok_pos(reader, 1, 3, -1, 55, TRUE);
737 test_read_state(reader, XmlReadState_Interactive, -1, FALSE);
738
739 hr = IXmlReader_GetValue(reader, &val, NULL);
740 ok(hr == S_OK, "got %08x\n", hr);
741 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
742
743 /* check attributes */
744 hr = IXmlReader_MoveToNextAttribute(reader);
745 ok(hr == S_OK, "got %08x\n", hr);
746
747 type = XmlNodeType_None;
748 hr = IXmlReader_GetNodeType(reader, &type);
749 ok(hr == S_OK, "got %08x\n", hr);
750 ok(type == XmlNodeType_Attribute, "got %d\n", type);
751
752 ok_pos(reader, 1, 7, -1, 55, TRUE);
753
754 /* try to move from last attribute */
755 hr = IXmlReader_MoveToNextAttribute(reader);
756 ok(hr == S_OK, "got %08x\n", hr);
757 hr = IXmlReader_MoveToNextAttribute(reader);
758 ok(hr == S_OK, "got %08x\n", hr);
759 hr = IXmlReader_MoveToNextAttribute(reader);
760 ok(hr == S_FALSE, "got %08x\n", hr);
761
762 type = XmlNodeType_None;
763 hr = IXmlReader_GetNodeType(reader, &type);
764 ok(hr == S_OK, "got %08x\n", hr);
765 ok(type == XmlNodeType_Attribute, "got %d\n", type);
766
767 hr = IXmlReader_MoveToFirstAttribute(reader);
768 ok(hr == S_OK, "got %08x\n", hr);
769 ok_pos(reader, 1, 7, -1, 55, TRUE);
770
771 hr = IXmlReader_GetAttributeCount(reader, NULL);
772 ok(hr == E_INVALIDARG, "got %08x\n", hr);
773
774 hr = IXmlReader_GetAttributeCount(reader, &count);
775 ok(hr == S_OK, "got %08x\n", hr);
776 ok(count == 3, "Expected 3, got %d\n", count);
777
778 for (i = 0; i < count; i++)
779 {
780 len = 0;
781 hr = IXmlReader_GetLocalName(reader, &val, &len);
782 ok(hr == S_OK, "got %08x\n", hr);
783 ok(len == lstrlenW(name_val[i].name), "expected %u, got %u\n", lstrlenW(name_val[i].name), len);
784 ok(!lstrcmpW(name_val[i].name, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].name), wine_dbgstr_w(val));
785
786 len = 0;
787 hr = IXmlReader_GetValue(reader, &val, &len);
788 ok(hr == S_OK, "got %08x\n", hr);
789 ok(len == lstrlenW(name_val[i].val), "expected %u, got %u\n", lstrlenW(name_val[i].val), len);
790 ok(!lstrcmpW(name_val[i].val, val), "expected %s, got %s\n", wine_dbgstr_w(name_val[i].val), wine_dbgstr_w(val));
791
792 hr = IXmlReader_MoveToNextAttribute(reader);
793 ok(hr == ((i < count - 1) ? S_OK : S_FALSE), "got %08x\n", hr);
794 }
795
796 hr = IXmlReader_GetDepth(reader, &count);
797 ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
798 ok(count == 1, "Expected 1, got %d\n", count);
799
800 hr = IXmlReader_MoveToElement(reader);
801 ok(hr == S_OK, "got %08x\n", hr);
802
803 type = XmlNodeType_None;
804 hr = IXmlReader_GetNodeType(reader, &type);
805 ok(hr == S_OK, "got %08x\n", hr);
806 ok(type == XmlNodeType_XmlDeclaration, "got %d\n", type);
807
808 type = XmlNodeType_XmlDeclaration;
809 hr = IXmlReader_Read(reader, &type);
810 /* newer versions return syntax error here cause document is incomplete,
811 it makes more sense than invalid char error */
812 todo_wine {
813 ok(hr == WC_E_SYNTAX || broken(hr == WC_E_XMLCHARACTER), "got 0x%08x\n", hr);
814 ok(type == XmlNodeType_None, "got %d\n", type);
815 }
816 IStream_Release(stream);
817
818 /* test short variant */
819 stream = create_stream_on_data(xmldecl_short, sizeof(xmldecl_short));
820
821 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
822 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
823
824 type = -1;
825 hr = IXmlReader_Read(reader, &type);
826 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
827 ok(type == XmlNodeType_XmlDeclaration, "expected XmlDeclaration, got %s\n", type_to_str(type));
828 ok_pos(reader, 1, 3, 1, 21, TRUE);
829 test_read_state(reader, XmlReadState_Interactive, -1, TRUE);
830
831 hr = IXmlReader_GetAttributeCount(reader, &count);
832 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
833 ok(count == 1, "expected 1, got %d\n", count);
834
835 ret = IXmlReader_IsEmptyElement(reader);
836 ok(!ret, "element should not be empty\n");
837
838 hr = IXmlReader_GetValue(reader, &val, NULL);
839 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
840 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
841
842 hr = IXmlReader_GetLocalName(reader, &val, NULL);
843 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
844 todo_wine
845 ok(!lstrcmpW(val, xmlW), "got %s\n", wine_dbgstr_w(val));
846
847 /* check attributes */
848 hr = IXmlReader_MoveToNextAttribute(reader);
849 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
850
851 type = -1;
852 hr = IXmlReader_GetNodeType(reader, &type);
853 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
854 ok(type == XmlNodeType_Attribute, "got %d\n", type);
855 ok_pos(reader, 1, 7, 1, 21, TRUE);
856
857 /* try to move from last attribute */
858 hr = IXmlReader_MoveToNextAttribute(reader);
859 ok(hr == S_FALSE, "expected S_FALSE, got %08x\n", hr);
860
861 type = -1;
862 hr = IXmlReader_Read(reader, &type);
863 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
864 ok(type == XmlNodeType_Element, "expected Element, got %s\n", type_to_str(type));
865 ok_pos(reader, 1, 23, 1, 40, TRUE);
866 test_read_state(reader, XmlReadState_Interactive, -1, TRUE);
867
868 hr = IXmlReader_GetAttributeCount(reader, &count);
869 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
870 ok(count == 0, "expected 0, got %d\n", count);
871
872 ret = IXmlReader_IsEmptyElement(reader);
873 ok(ret, "element should be empty\n");
874
875 hr = IXmlReader_GetValue(reader, &val, NULL);
876 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
877 todo_wine
878 ok(*val == 0, "got %s\n", wine_dbgstr_w(val));
879
880 hr = IXmlReader_GetLocalName(reader, &val, NULL);
881 ok(hr == S_OK, "expected S_OK, got %08x\n", hr);
882 ok(!lstrcmpW(val, RegistrationInfoW), "got %s\n", wine_dbgstr_w(val));
883
884 type = -1;
885 hr = IXmlReader_Read(reader, &type);
886 todo_wine
887 ok(hr == WC_E_SYNTAX || hr == WC_E_XMLCHARACTER /* XP */, "expected WC_E_SYNTAX, got %08x\n", hr);
888 todo_wine
889 ok(type == XmlNodeType_None, "expected None, got %s\n", type_to_str(type));
890 ok_pos(reader, 1, 41, -1, -1, TRUE);
891 test_read_state(reader, XmlReadState_Error, -1, TRUE);
892
893 IStream_Release(stream);
894 IXmlReader_Release(reader);
895 }
896
897 struct test_entry {
898 const char *xml;
899 const char *name;
900 const char *value;
901 HRESULT hr;
902 HRESULT hr_broken; /* this is set to older version results */
903 BOOL todo;
904 };
905
906 static struct test_entry comment_tests[] = {
907 { "<!-- comment -->", "", " comment ", S_OK },
908 { "<!-- - comment-->", "", " - comment", S_OK },
909 { "<!-- -- comment-->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
910 { "<!-- -- comment--->", NULL, NULL, WC_E_COMMENT, WC_E_GREATERTHAN },
911 { NULL }
912 };
913
914 static void test_read_comment(void)
915 {
916 struct test_entry *test = comment_tests;
917 IXmlReader *reader;
918 HRESULT hr;
919
920 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
921 ok(hr == S_OK, "S_OK, got %08x\n", hr);
922
923 while (test->xml)
924 {
925 XmlNodeType type;
926 IStream *stream;
927
928 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
929 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
930 ok(hr == S_OK, "got %08x\n", hr);
931
932 type = XmlNodeType_None;
933 hr = IXmlReader_Read(reader, &type);
934 if (test->hr_broken)
935 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
936 else
937 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
938 if (hr == S_OK)
939 {
940 const WCHAR *str;
941 WCHAR *str_exp;
942 UINT len;
943
944 ok(type == XmlNodeType_Comment, "got %d for %s\n", type, test->xml);
945
946 len = 1;
947 str = NULL;
948 hr = IXmlReader_GetLocalName(reader, &str, &len);
949 ok(hr == S_OK, "got 0x%08x\n", hr);
950 ok(len == strlen(test->name), "got %u\n", len);
951 str_exp = a2w(test->name);
952 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
953 free_str(str_exp);
954
955 len = 1;
956 str = NULL;
957 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
958 ok(hr == S_OK, "got 0x%08x\n", hr);
959 ok(len == strlen(test->name), "got %u\n", len);
960 str_exp = a2w(test->name);
961 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
962 free_str(str_exp);
963
964 /* value */
965 len = 1;
966 str = NULL;
967 hr = IXmlReader_GetValue(reader, &str, &len);
968 ok(hr == S_OK, "got 0x%08x\n", hr);
969 ok(len == strlen(test->value), "got %u\n", len);
970 str_exp = a2w(test->value);
971 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
972 free_str(str_exp);
973 }
974
975 IStream_Release(stream);
976 test++;
977 }
978
979 IXmlReader_Release(reader);
980 }
981
982 static struct test_entry pi_tests[] = {
983 { "<?pi?>", "pi", "", S_OK },
984 { "<?pi ?>", "pi", "", S_OK },
985 { "<?pi ?>", "pi", "", S_OK },
986 { "<?pi pi data?>", "pi", "pi data", S_OK },
987 { "<?pi pi data ?>", "pi", "pi data ", S_OK },
988 { "<?pi data ?>", "pi", "data ", S_OK },
989 { "<?pi:pi?>", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER },
990 { "<?:pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
991 { "<?-pi ?>", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER },
992 { "<?xml-stylesheet ?>", "xml-stylesheet", "", S_OK },
993 { NULL }
994 };
995
996 static void test_read_pi(void)
997 {
998 struct test_entry *test = pi_tests;
999 IXmlReader *reader;
1000 HRESULT hr;
1001
1002 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1003 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1004
1005 while (test->xml)
1006 {
1007 XmlNodeType type;
1008 IStream *stream;
1009
1010 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1011 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1012 ok(hr == S_OK, "got %08x\n", hr);
1013
1014 type = XmlNodeType_None;
1015 hr = IXmlReader_Read(reader, &type);
1016 if (test->hr_broken)
1017 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1018 else
1019 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1020 if (hr == S_OK)
1021 {
1022 const WCHAR *str;
1023 WCHAR *str_exp;
1024 UINT len;
1025
1026 ok(type == XmlNodeType_ProcessingInstruction, "got %d for %s\n", type, test->xml);
1027
1028 len = 0;
1029 str = NULL;
1030 hr = IXmlReader_GetLocalName(reader, &str, &len);
1031 ok(hr == S_OK, "got 0x%08x\n", hr);
1032 ok(len == strlen(test->name), "got %u\n", len);
1033 str_exp = a2w(test->name);
1034 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1035 free_str(str_exp);
1036
1037 len = 0;
1038 str = NULL;
1039 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1040 ok(hr == S_OK, "got 0x%08x\n", hr);
1041 ok(len == strlen(test->name), "got %u\n", len);
1042 str_exp = a2w(test->name);
1043 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1044 free_str(str_exp);
1045
1046 /* value */
1047 len = !strlen(test->value);
1048 str = NULL;
1049 hr = IXmlReader_GetValue(reader, &str, &len);
1050 ok(hr == S_OK, "got 0x%08x\n", hr);
1051 ok(len == strlen(test->value), "got %u\n", len);
1052 str_exp = a2w(test->value);
1053 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1054 free_str(str_exp);
1055 }
1056
1057 IStream_Release(stream);
1058 test++;
1059 }
1060
1061 IXmlReader_Release(reader);
1062 }
1063
1064 struct nodes_test {
1065 const char *xml;
1066 XmlNodeType types[20];
1067 };
1068
1069 static const char misc_test_xml[] =
1070 "<!-- comment1 -->"
1071 "<!-- comment2 -->"
1072 "<?pi1 pi1body ?>"
1073 "<!-- comment3 -->"
1074 " \t \r \n"
1075 "<!-- comment4 -->"
1076 "<a>"
1077 "\r\n\t"
1078 "<b/>"
1079 "text"
1080 "<!-- comment -->"
1081 "text2"
1082 "<?pi pibody ?>"
1083 "\r\n"
1084 "</a>"
1085 ;
1086
1087 static struct nodes_test misc_test = {
1088 misc_test_xml,
1089 {
1090 XmlNodeType_Comment,
1091 XmlNodeType_Comment,
1092 XmlNodeType_ProcessingInstruction,
1093 XmlNodeType_Comment,
1094 XmlNodeType_Whitespace,
1095 XmlNodeType_Comment,
1096 XmlNodeType_Element,
1097 XmlNodeType_Whitespace,
1098 XmlNodeType_Element,
1099 XmlNodeType_Text,
1100 XmlNodeType_Comment,
1101 XmlNodeType_Text,
1102 XmlNodeType_ProcessingInstruction,
1103 XmlNodeType_Whitespace,
1104 XmlNodeType_EndElement,
1105 XmlNodeType_None
1106 }
1107 };
1108
1109 static void test_read_full(void)
1110 {
1111 struct nodes_test *test = &misc_test;
1112 IXmlReader *reader;
1113 XmlNodeType type;
1114 IStream *stream;
1115 HRESULT hr;
1116 int i;
1117
1118 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1119 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1120
1121 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1122 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1123 ok(hr == S_OK, "got %08x\n", hr);
1124
1125 i = 0;
1126 type = XmlNodeType_None;
1127 hr = IXmlReader_Read(reader, &type);
1128 while (hr == S_OK)
1129 {
1130 ok(test->types[i] != XmlNodeType_None, "%d: unexpected end of test data\n", i);
1131 if (test->types[i] == XmlNodeType_None) break;
1132 ok(type == test->types[i], "%d: got wrong type %d, expected %d\n", i, type, test->types[i]);
1133 if (type == XmlNodeType_Whitespace)
1134 {
1135 const WCHAR *ptr;
1136 UINT len = 0;
1137
1138 hr = IXmlReader_GetValue(reader, &ptr, &len);
1139 ok(hr == S_OK, "%d: GetValue failed 0x%08x\n", i, hr);
1140 ok(len > 0, "%d: wrong value length %d\n", i, len);
1141 }
1142 hr = IXmlReader_Read(reader, &type);
1143 i++;
1144 }
1145 ok(test->types[i] == XmlNodeType_None, "incomplete sequence, got %d\n", test->types[i]);
1146
1147 IStream_Release(stream);
1148 IXmlReader_Release(reader);
1149 }
1150
1151 static const char test_public_dtd[] =
1152 "<!DOCTYPE testdtd PUBLIC \"pubid\" \"externalid uri\" >";
1153
1154 static void test_read_public_dtd(void)
1155 {
1156 static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0};
1157 static const WCHAR pubvalW[] = {'p','u','b','i','d',0};
1158 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1159 static const WCHAR sysW[] = {'S','Y','S','T','E','M',0};
1160 static const WCHAR pubW[] = {'P','U','B','L','I','C',0};
1161 IXmlReader *reader;
1162 const WCHAR *str;
1163 XmlNodeType type;
1164 IStream *stream;
1165 UINT len, count;
1166 HRESULT hr;
1167
1168 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1169 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1170
1171 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1172 ok(hr == S_OK, "got 0x%8x\n", hr);
1173
1174 stream = create_stream_on_data(test_public_dtd, sizeof(test_public_dtd));
1175 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1176 ok(hr == S_OK, "got %08x\n", hr);
1177
1178 type = XmlNodeType_None;
1179 hr = IXmlReader_Read(reader, &type);
1180 ok(hr == S_OK, "got 0x%8x\n", hr);
1181 ok(type == XmlNodeType_DocumentType, "got type %d\n", type);
1182
1183 count = 0;
1184 hr = IXmlReader_GetAttributeCount(reader, &count);
1185 ok(hr == S_OK, "got %08x\n", hr);
1186 ok(count == 2, "got %d\n", count);
1187
1188 hr = IXmlReader_MoveToFirstAttribute(reader);
1189 ok(hr == S_OK, "got %08x\n", hr);
1190
1191 type = XmlNodeType_None;
1192 hr = IXmlReader_GetNodeType(reader, &type);
1193 ok(hr == S_OK, "got %08x\n", hr);
1194 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1195
1196 len = 0;
1197 str = NULL;
1198 hr = IXmlReader_GetLocalName(reader, &str, &len);
1199 ok(hr == S_OK, "got 0x%08x\n", hr);
1200 ok(len == lstrlenW(pubW), "got %u\n", len);
1201 ok(!lstrcmpW(str, pubW), "got %s\n", wine_dbgstr_w(str));
1202
1203 len = 0;
1204 str = NULL;
1205 hr = IXmlReader_GetValue(reader, &str, &len);
1206 ok(hr == S_OK, "got 0x%08x\n", hr);
1207 ok(len == lstrlenW(pubvalW), "got %u\n", len);
1208 ok(!lstrcmpW(str, pubvalW), "got %s\n", wine_dbgstr_w(str));
1209
1210 hr = IXmlReader_MoveToNextAttribute(reader);
1211 ok(hr == S_OK, "got %08x\n", hr);
1212
1213 type = XmlNodeType_None;
1214 hr = IXmlReader_GetNodeType(reader, &type);
1215 ok(hr == S_OK, "got %08x\n", hr);
1216 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1217
1218 len = 0;
1219 str = NULL;
1220 hr = IXmlReader_GetLocalName(reader, &str, &len);
1221 ok(hr == S_OK, "got 0x%08x\n", hr);
1222 ok(len == lstrlenW(sysW), "got %u\n", len);
1223 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
1224
1225 len = 0;
1226 str = NULL;
1227 hr = IXmlReader_GetValue(reader, &str, &len);
1228 ok(hr == S_OK, "got 0x%08x\n", hr);
1229 ok(len == lstrlenW(sysvalW), "got %u\n", len);
1230 ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str));
1231
1232 hr = IXmlReader_MoveToElement(reader);
1233 ok(hr == S_OK, "got 0x%08x\n", hr);
1234
1235 len = 0;
1236 str = NULL;
1237 hr = IXmlReader_GetLocalName(reader, &str, &len);
1238 ok(hr == S_OK, "got 0x%08x\n", hr);
1239 todo_wine {
1240 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1241 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1242 }
1243 len = 0;
1244 str = NULL;
1245 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1246 ok(hr == S_OK, "got 0x%08x\n", hr);
1247 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1248 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1249
1250 IStream_Release(stream);
1251 IXmlReader_Release(reader);
1252 }
1253
1254 static const char test_system_dtd[] =
1255 "<!DOCTYPE testdtd SYSTEM \"externalid uri\" >"
1256 "<!-- comment -->";
1257
1258 static void test_read_system_dtd(void)
1259 {
1260 static const WCHAR sysvalW[] = {'e','x','t','e','r','n','a','l','i','d',' ','u','r','i',0};
1261 static const WCHAR dtdnameW[] = {'t','e','s','t','d','t','d',0};
1262 static const WCHAR sysW[] = {'S','Y','S','T','E','M',0};
1263 IXmlReader *reader;
1264 const WCHAR *str;
1265 XmlNodeType type;
1266 IStream *stream;
1267 UINT len, count;
1268 HRESULT hr;
1269
1270 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1271 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1272
1273 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_DtdProcessing, DtdProcessing_Parse);
1274 ok(hr == S_OK, "got 0x%8x\n", hr);
1275
1276 stream = create_stream_on_data(test_system_dtd, sizeof(test_system_dtd));
1277 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1278 ok(hr == S_OK, "got %08x\n", hr);
1279
1280 type = XmlNodeType_None;
1281 hr = IXmlReader_Read(reader, &type);
1282 ok(hr == S_OK, "got 0x%8x\n", hr);
1283 ok(type == XmlNodeType_DocumentType, "got type %d\n", type);
1284
1285 count = 0;
1286 hr = IXmlReader_GetAttributeCount(reader, &count);
1287 ok(hr == S_OK, "got %08x\n", hr);
1288 ok(count == 1, "got %d\n", count);
1289
1290 hr = IXmlReader_MoveToFirstAttribute(reader);
1291 ok(hr == S_OK, "got %08x\n", hr);
1292
1293 type = XmlNodeType_None;
1294 hr = IXmlReader_GetNodeType(reader, &type);
1295 ok(hr == S_OK, "got %08x\n", hr);
1296 ok(type == XmlNodeType_Attribute, "got %d\n", type);
1297
1298 len = 0;
1299 str = NULL;
1300 hr = IXmlReader_GetLocalName(reader, &str, &len);
1301 ok(hr == S_OK, "got 0x%08x\n", hr);
1302 ok(len == lstrlenW(sysW), "got %u\n", len);
1303 ok(!lstrcmpW(str, sysW), "got %s\n", wine_dbgstr_w(str));
1304
1305 len = 0;
1306 str = NULL;
1307 hr = IXmlReader_GetValue(reader, &str, &len);
1308 ok(hr == S_OK, "got 0x%08x\n", hr);
1309 ok(len == lstrlenW(sysvalW), "got %u\n", len);
1310 ok(!lstrcmpW(str, sysvalW), "got %s\n", wine_dbgstr_w(str));
1311
1312 hr = IXmlReader_MoveToElement(reader);
1313 ok(hr == S_OK, "got 0x%08x\n", hr);
1314
1315 len = 0;
1316 str = NULL;
1317 hr = IXmlReader_GetLocalName(reader, &str, &len);
1318 ok(hr == S_OK, "got 0x%08x\n", hr);
1319 todo_wine {
1320 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1321 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1322 }
1323 len = 0;
1324 str = NULL;
1325 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1326 ok(hr == S_OK, "got 0x%08x\n", hr);
1327 ok(len == lstrlenW(dtdnameW), "got %u\n", len);
1328 ok(!lstrcmpW(str, dtdnameW), "got %s\n", wine_dbgstr_w(str));
1329
1330 type = XmlNodeType_None;
1331 hr = IXmlReader_Read(reader, &type);
1332 ok(hr == S_OK, "got 0x%8x\n", hr);
1333 ok(type == XmlNodeType_Comment, "got type %d\n", type);
1334
1335 IStream_Release(stream);
1336 IXmlReader_Release(reader);
1337 }
1338
1339 static struct test_entry element_tests[] = {
1340 { "<a/>", "a", "", S_OK },
1341 { "<a />", "a", "", S_OK },
1342 { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX },
1343 { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1344 { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER },
1345 { "<a>", "a", "", S_OK },
1346 { "<a >", "a", "", S_OK },
1347 { "<a \r \t\n>", "a", "", S_OK },
1348 { "</a>", NULL, NULL, NC_E_QNAMECHARACTER },
1349 { NULL }
1350 };
1351
1352 static void test_read_element(void)
1353 {
1354 struct test_entry *test = element_tests;
1355 static const char stag[] = "<a><b></b></a>";
1356 static const char mismatch[] = "<a></b>";
1357 IXmlReader *reader;
1358 XmlNodeType type;
1359 IStream *stream;
1360 UINT depth;
1361 HRESULT hr;
1362
1363 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1364 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1365
1366 while (test->xml)
1367 {
1368 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1369 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1370 ok(hr == S_OK, "got %08x\n", hr);
1371
1372 type = XmlNodeType_None;
1373 hr = IXmlReader_Read(reader, &type);
1374 if (test->hr_broken)
1375 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1376 else
1377 todo_wine_if(test->hr == NC_E_UNDECLAREDPREFIX)
1378 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1379 if (hr == S_OK)
1380 {
1381 const WCHAR *str;
1382 WCHAR *str_exp;
1383 UINT len;
1384
1385 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1386
1387 len = 0;
1388 str = NULL;
1389 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1390 ok(hr == S_OK, "got 0x%08x\n", hr);
1391 ok(len == strlen(test->name), "got %u\n", len);
1392 str_exp = a2w(test->name);
1393 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1394 free_str(str_exp);
1395
1396 /* value */
1397 len = 1;
1398 str = NULL;
1399 hr = IXmlReader_GetValue(reader, &str, &len);
1400 ok(hr == S_OK, "got 0x%08x\n", hr);
1401 ok(len == 0, "got %u\n", len);
1402 ok(*str == 0, "got %s\n", wine_dbgstr_w(str));
1403 }
1404
1405 IStream_Release(stream);
1406 test++;
1407 }
1408
1409 /* test reader depth increment */
1410 stream = create_stream_on_data(stag, sizeof(stag));
1411 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1412 ok(hr == S_OK, "got %08x\n", hr);
1413
1414 depth = 1;
1415 hr = IXmlReader_GetDepth(reader, &depth);
1416 ok(hr == S_OK, "got %08x\n", hr);
1417 ok(depth == 0, "got %d\n", depth);
1418
1419 type = XmlNodeType_None;
1420 hr = IXmlReader_Read(reader, &type);
1421 ok(hr == S_OK, "got %08x\n", hr);
1422 ok(type == XmlNodeType_Element, "got %d\n", type);
1423
1424 depth = 1;
1425 hr = IXmlReader_GetDepth(reader, &depth);
1426 ok(hr == S_OK, "got %08x\n", hr);
1427 ok(depth == 0, "got %d\n", depth);
1428
1429 type = XmlNodeType_None;
1430 hr = IXmlReader_Read(reader, &type);
1431 ok(hr == S_OK, "got %08x\n", hr);
1432 ok(type == XmlNodeType_Element, "got %d\n", type);
1433
1434 depth = 0;
1435 hr = IXmlReader_GetDepth(reader, &depth);
1436 ok(hr == S_OK, "got %08x\n", hr);
1437 ok(depth == 1, "got %d\n", depth);
1438
1439 /* read end tag for inner element */
1440 type = XmlNodeType_None;
1441 hr = IXmlReader_Read(reader, &type);
1442 ok(hr == S_OK, "got %08x\n", hr);
1443 ok(type == XmlNodeType_EndElement, "got %d\n", type);
1444
1445 depth = 0;
1446 hr = IXmlReader_GetDepth(reader, &depth);
1447 ok(hr == S_OK, "got %08x\n", hr);
1448 todo_wine
1449 ok(depth == 2, "got %d\n", depth);
1450
1451 /* read end tag for container element */
1452 type = XmlNodeType_None;
1453 hr = IXmlReader_Read(reader, &type);
1454 ok(hr == S_OK, "got %08x\n", hr);
1455 ok(type == XmlNodeType_EndElement, "got %d\n", type);
1456
1457 depth = 0;
1458 hr = IXmlReader_GetDepth(reader, &depth);
1459 ok(hr == S_OK, "got %08x\n", hr);
1460 ok(depth == 1, "got %d\n", depth);
1461
1462 IStream_Release(stream);
1463
1464 /* start/end tag mismatch */
1465 stream = create_stream_on_data(mismatch, sizeof(mismatch));
1466 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1467 ok(hr == S_OK, "got %08x\n", hr);
1468
1469 type = XmlNodeType_None;
1470 hr = IXmlReader_Read(reader, &type);
1471 ok(hr == S_OK, "got %08x\n", hr);
1472 ok(type == XmlNodeType_Element, "got %d\n", type);
1473
1474 type = XmlNodeType_Element;
1475 hr = IXmlReader_Read(reader, &type);
1476 ok(hr == WC_E_ELEMENTMATCH, "got %08x\n", hr);
1477 todo_wine
1478 ok(type == XmlNodeType_None, "got %d\n", type);
1479
1480 IStream_Release(stream);
1481
1482 IXmlReader_Release(reader);
1483 }
1484
1485 static ISequentialStream teststream = { &teststreamvtbl };
1486
1487 static void test_read_pending(void)
1488 {
1489 IXmlReader *reader;
1490 const WCHAR *value;
1491 XmlNodeType type;
1492 HRESULT hr;
1493 int c;
1494
1495 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1496 ok(hr == S_OK, "S_OK, got 0x%08x\n", hr);
1497
1498 hr = IXmlReader_SetInput(reader, (IUnknown*)&teststream);
1499 ok(hr == S_OK, "got 0x%08x\n", hr);
1500
1501 /* first read call returns incomplete node, second attempt fails with E_PENDING */
1502 stream_readcall = 0;
1503 type = XmlNodeType_Element;
1504 hr = IXmlReader_Read(reader, &type);
1505 ok(hr == S_OK || broken(hr == E_PENDING), "got 0x%08x\n", hr);
1506 /* newer versions are happy when it's enough data to detect node type,
1507 older versions keep reading until it fails to read more */
1508 ok(stream_readcall == 1 || broken(stream_readcall > 1), "got %d\n", stream_readcall);
1509 ok(type == XmlNodeType_Comment || broken(type == XmlNodeType_None), "got %d\n", type);
1510
1511 /* newer versions' GetValue() makes an attempt to read more */
1512 c = stream_readcall;
1513 value = (void*)0xdeadbeef;
1514 hr = IXmlReader_GetValue(reader, &value, NULL);
1515 ok(hr == E_PENDING, "got 0x%08x\n", hr);
1516 ok(value == NULL || broken(value == (void*)0xdeadbeef) /* Win8 sets it to NULL */, "got %p\n", value);
1517 ok(c < stream_readcall || broken(c == stream_readcall), "got %d, expected %d\n", stream_readcall, c+1);
1518
1519 IXmlReader_Release(reader);
1520 }
1521
1522 static void test_readvaluechunk(void)
1523 {
1524 static const char testA[] = "<!-- comment1 -->";
1525 IXmlReader *reader;
1526 XmlNodeType type;
1527 IStream *stream;
1528 const WCHAR *value;
1529 WCHAR b;
1530 HRESULT hr;
1531 UINT c;
1532
1533 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1534 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1535
1536 stream = create_stream_on_data(testA, sizeof(testA));
1537 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1538 ok(hr == S_OK, "got %08x\n", hr);
1539
1540 hr = IXmlReader_Read(reader, &type);
1541 ok(hr == S_OK, "got %08x\n", hr);
1542
1543 c = 0;
1544 b = 0;
1545 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1546 ok(hr == S_OK, "got %08x\n", hr);
1547 ok(c == 1, "got %u\n", c);
1548 ok(b == ' ', "got %x\n", b);
1549
1550 /* portion read as chunk is skipped from resulting node value */
1551 value = NULL;
1552 hr = IXmlReader_GetValue(reader, &value, NULL);
1553 ok(hr == S_OK, "got %08x\n", hr);
1554 ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value));
1555
1556 /* once value is returned/allocated it's not possible to read by chunk */
1557 c = 0;
1558 b = 0;
1559 hr = IXmlReader_ReadValueChunk(reader, &b, 1, &c);
1560 ok(hr == S_FALSE, "got %08x\n", hr);
1561 ok(c == 0, "got %u\n", c);
1562 ok(b == 0, "got %x\n", b);
1563
1564 value = NULL;
1565 hr = IXmlReader_GetValue(reader, &value, NULL);
1566 ok(hr == S_OK, "got %08x\n", hr);
1567 ok(value[0] == 'c', "got %s\n", wine_dbgstr_w(value));
1568
1569 IXmlReader_Release(reader);
1570 IStream_Release(stream);
1571 }
1572
1573 static struct test_entry cdata_tests[] = {
1574 { "<a><![CDATA[ ]]data ]]></a>", "", " ]]data ", S_OK },
1575 { "<a><![CDATA[<![CDATA[ data ]]]]></a>", "", "<![CDATA[ data ]]", S_OK },
1576 { "<a><![CDATA[\n \r\n \n\n ]]></a>", "", "\n \n \n\n ", S_OK, S_OK, TRUE },
1577 { "<a><![CDATA[\r \r\r\n \n\n ]]></a>", "", "\n \n\n \n\n ", S_OK, S_OK, TRUE },
1578 { "<a><![CDATA[\r\r \n\r \r \n\n ]]></a>", "", "\n\n \n\n \n \n\n ", S_OK },
1579 { NULL }
1580 };
1581
1582 static void test_read_cdata(void)
1583 {
1584 struct test_entry *test = cdata_tests;
1585 IXmlReader *reader;
1586 HRESULT hr;
1587
1588 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1589 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1590
1591 while (test->xml)
1592 {
1593 XmlNodeType type;
1594 IStream *stream;
1595
1596 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1597 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1598 ok(hr == S_OK, "got %08x\n", hr);
1599
1600 type = XmlNodeType_None;
1601 hr = IXmlReader_Read(reader, &type);
1602
1603 /* read one more to get to CDATA */
1604 if (type == XmlNodeType_Element)
1605 {
1606 type = XmlNodeType_None;
1607 hr = IXmlReader_Read(reader, &type);
1608 }
1609
1610 if (test->hr_broken)
1611 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1612 else
1613 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1614 if (hr == S_OK)
1615 {
1616 const WCHAR *str;
1617 WCHAR *str_exp;
1618 UINT len;
1619
1620 ok(type == XmlNodeType_CDATA, "got %d for %s\n", type, test->xml);
1621
1622 str_exp = a2w(test->name);
1623
1624 len = 1;
1625 str = NULL;
1626 hr = IXmlReader_GetLocalName(reader, &str, &len);
1627 ok(hr == S_OK, "got 0x%08x\n", hr);
1628 ok(len == strlen(test->name), "got %u\n", len);
1629 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1630
1631 str = NULL;
1632 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1633 ok(hr == S_OK, "got 0x%08x\n", hr);
1634 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1635
1636 free_str(str_exp);
1637
1638 len = 1;
1639 str = NULL;
1640 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1641 ok(hr == S_OK, "got 0x%08x\n", hr);
1642 ok(len == strlen(test->name), "got %u\n", len);
1643 str_exp = a2w(test->name);
1644 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1645 free_str(str_exp);
1646
1647 /* value */
1648 len = 1;
1649 str = NULL;
1650 hr = IXmlReader_GetValue(reader, &str, &len);
1651 ok(hr == S_OK, "got 0x%08x\n", hr);
1652
1653 str_exp = a2w(test->value);
1654 todo_wine_if (test->todo)
1655 {
1656 ok(len == strlen(test->value), "got %u\n", len);
1657 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1658 }
1659 free_str(str_exp);
1660 }
1661
1662 IStream_Release(stream);
1663 test++;
1664 }
1665
1666 IXmlReader_Release(reader);
1667 }
1668
1669 static struct test_entry text_tests[] = {
1670 { "<a>simple text</a>", "", "simple text", S_OK },
1671 { "<a>text ]]> text</a>", "", "", WC_E_CDSECTEND },
1672 { NULL }
1673 };
1674
1675 static void test_read_text(void)
1676 {
1677 struct test_entry *test = text_tests;
1678 IXmlReader *reader;
1679 HRESULT hr;
1680
1681 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1682 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1683
1684 while (test->xml)
1685 {
1686 XmlNodeType type;
1687 IStream *stream;
1688
1689 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1690 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1691 ok(hr == S_OK, "got %08x\n", hr);
1692
1693 type = XmlNodeType_None;
1694 hr = IXmlReader_Read(reader, &type);
1695
1696 /* read one more to get to CDATA */
1697 if (type == XmlNodeType_Element)
1698 {
1699 type = XmlNodeType_None;
1700 hr = IXmlReader_Read(reader, &type);
1701 }
1702
1703 if (test->hr_broken)
1704 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1705 else
1706 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1707 if (hr == S_OK)
1708 {
1709 const WCHAR *str;
1710 WCHAR *str_exp;
1711 UINT len;
1712
1713 ok(type == XmlNodeType_Text, "got %d for %s\n", type, test->xml);
1714
1715 str_exp = a2w(test->name);
1716
1717 len = 1;
1718 str = NULL;
1719 hr = IXmlReader_GetLocalName(reader, &str, &len);
1720 ok(hr == S_OK, "got 0x%08x\n", hr);
1721 ok(len == strlen(test->name), "got %u\n", len);
1722 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1723
1724 str = NULL;
1725 hr = IXmlReader_GetLocalName(reader, &str, NULL);
1726 ok(hr == S_OK, "got 0x%08x\n", hr);
1727 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1728
1729 free_str(str_exp);
1730
1731 len = 1;
1732 str = NULL;
1733 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1734 ok(hr == S_OK, "got 0x%08x\n", hr);
1735 ok(len == strlen(test->name), "got %u\n", len);
1736 str_exp = a2w(test->name);
1737 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1738 free_str(str_exp);
1739
1740 /* value */
1741 len = 1;
1742 str = NULL;
1743 hr = IXmlReader_GetValue(reader, &str, &len);
1744 ok(hr == S_OK, "got 0x%08x\n", hr);
1745
1746 str_exp = a2w(test->value);
1747 todo_wine_if (test->todo)
1748 {
1749 ok(len == strlen(test->value), "got %u\n", len);
1750 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1751 }
1752 free_str(str_exp);
1753 }
1754
1755 IStream_Release(stream);
1756 test++;
1757 }
1758
1759 IXmlReader_Release(reader);
1760 }
1761
1762 struct test_entry_empty {
1763 const char *xml;
1764 BOOL empty;
1765 };
1766
1767 static struct test_entry_empty empty_element_tests[] = {
1768 { "<a></a>", FALSE },
1769 { "<a/>", TRUE },
1770 { NULL }
1771 };
1772
1773 static void test_isemptyelement(void)
1774 {
1775 struct test_entry_empty *test = empty_element_tests;
1776 IXmlReader *reader;
1777 HRESULT hr;
1778
1779 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1780 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1781
1782 while (test->xml)
1783 {
1784 XmlNodeType type;
1785 IStream *stream;
1786 BOOL ret;
1787
1788 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1789 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1790 ok(hr == S_OK, "got %08x\n", hr);
1791
1792 type = XmlNodeType_None;
1793 hr = IXmlReader_Read(reader, &type);
1794 ok(hr == S_OK, "got 0x%08x\n", hr);
1795 ok(type == XmlNodeType_Element, "got %d\n", type);
1796
1797 ret = IXmlReader_IsEmptyElement(reader);
1798 ok(ret == test->empty, "got %d, expected %d. xml=%s\n", ret, test->empty, test->xml);
1799
1800 IStream_Release(stream);
1801 test++;
1802 }
1803
1804 IXmlReader_Release(reader);
1805 }
1806
1807 static struct test_entry attributes_tests[] = {
1808 { "<a attr1=\"attrvalue\"/>", "attr1", "attrvalue", S_OK },
1809 { "<a attr1=\"a\'\'ttrvalue\"/>", "attr1", "a\'\'ttrvalue", S_OK },
1810 { "<a attr1=\'a\"ttrvalue\'/>", "attr1", "a\"ttrvalue", S_OK },
1811 { "<a attr1=\' \'/>", "attr1", " ", S_OK },
1812 { "<a attr1=\" \"/>", "attr1", " ", S_OK },
1813 { "<a attr1=\"\r\n \r \n \t\n\r\"/>", "attr1", " ", S_OK },
1814 { "<a attr1=\" val \"/>", "attr1", " val ", S_OK },
1815 { "<a attr1=\"\r\n\tval\n\"/>", "attr1", " val ", S_OK },
1816 { "<a attr1=\"val&#32;\"/>", "attr1", "val ", S_OK },
1817 { "<a attr1=\"val&#x20;\"/>", "attr1", "val ", S_OK },
1818 { "<a attr1=\"&lt;&gt;&amp;&apos;&quot;\"/>", "attr1", "<>&\'\"", S_OK },
1819 { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY },
1820 { "<a attr1=\"val&#xfffe;\"/>", NULL, NULL, WC_E_XMLCHARACTER },
1821 { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON },
1822 { "<a attr1=\"val &#12a;\"/>", NULL, NULL, WC_E_SEMICOLON },
1823 { "<a attr1=\"val &#x12g;\"/>", NULL, NULL, WC_E_SEMICOLON },
1824 { "<a attr1=\"val &#xg;\"/>", NULL, NULL, WC_E_HEXDIGIT, WC_E_SEMICOLON },
1825 { "<a attr1=attrvalue/>", NULL, NULL, WC_E_QUOTE },
1826 { "<a attr1=\"attr<value\"/>", NULL, NULL, WC_E_LESSTHAN },
1827 { "<a attr1=\"&entname\"/>", NULL, NULL, WC_E_SEMICOLON },
1828 { NULL }
1829 };
1830
1831 static void test_read_attribute(void)
1832 {
1833 struct test_entry *test = attributes_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 IStream *stream;
1844
1845 stream = create_stream_on_data(test->xml, strlen(test->xml)+1);
1846 hr = IXmlReader_SetInput(reader, (IUnknown*)stream);
1847 ok(hr == S_OK, "got %08x\n", hr);
1848
1849 hr = IXmlReader_Read(reader, NULL);
1850
1851 if (test->hr_broken)
1852 ok(hr == test->hr || broken(hr == test->hr_broken), "got %08x for %s\n", hr, test->xml);
1853 else
1854 ok(hr == test->hr, "got %08x for %s\n", hr, test->xml);
1855 if (hr == S_OK)
1856 {
1857 const WCHAR *str;
1858 WCHAR *str_exp;
1859 UINT len;
1860
1861 type = XmlNodeType_None;
1862 hr = IXmlReader_GetNodeType(reader, &type);
1863 ok(hr == S_OK, "Failed to get node type, %#x\n", hr);
1864
1865 ok(type == XmlNodeType_Element, "got %d for %s\n", type, test->xml);
1866
1867 hr = IXmlReader_MoveToFirstAttribute(reader);
1868 ok(hr == S_OK, "got 0x%08x\n", hr);
1869
1870 len = 1;
1871 str = NULL;
1872 hr = IXmlReader_GetLocalName(reader, &str, &len);
1873 ok(hr == S_OK, "got 0x%08x\n", hr);
1874 ok(len == strlen(test->name), "got %u\n", len);
1875 str_exp = a2w(test->name);
1876 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1877 free_str(str_exp);
1878
1879 len = 1;
1880 str = NULL;
1881 hr = IXmlReader_GetQualifiedName(reader, &str, &len);
1882 ok(hr == S_OK, "got 0x%08x\n", hr);
1883 todo_wine {
1884 ok(len == strlen(test->name), "got %u\n", len);
1885 str_exp = a2w(test->name);
1886 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1887 free_str(str_exp);
1888 }
1889 /* value */
1890 len = 1;
1891 str = NULL;
1892 hr = IXmlReader_GetValue(reader, &str, &len);
1893 ok(hr == S_OK, "got 0x%08x\n", hr);
1894 ok(len == strlen(test->value), "got %u\n", len);
1895 str_exp = a2w(test->value);
1896 ok(!lstrcmpW(str, str_exp), "got %s\n", wine_dbgstr_w(str));
1897 free_str(str_exp);
1898 }
1899
1900 IStream_Release(stream);
1901 test++;
1902 }
1903
1904 IXmlReader_Release(reader);
1905 }
1906
1907 static void test_reader_properties(void)
1908 {
1909 IXmlReader *reader;
1910 HRESULT hr;
1911
1912 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1913 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1914
1915 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MultiLanguage, 0);
1916 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1917
1918 hr = IXmlReader_SetProperty(reader, XmlReaderProperty_MaxElementDepth, 0);
1919 ok(hr == S_OK, "SetProperty failed: %08x\n", hr);
1920
1921 IXmlReader_Release(reader);
1922 }
1923
1924 static void test_prefix(void)
1925 {
1926 static const struct
1927 {
1928 const char *xml;
1929 const char *prefix1;
1930 const char *prefix2;
1931 const char *prefix3;
1932 } prefix_tests[] =
1933 {
1934 { "<b xmlns=\"defns\" xml:a=\"a ns\"/>", "", "", "xml" },
1935 };
1936 IXmlReader *reader;
1937 unsigned int i;
1938 HRESULT hr;
1939
1940 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
1941 ok(hr == S_OK, "S_OK, got %08x\n", hr);
1942
1943 for (i = 0; i < sizeof(prefix_tests)/sizeof(prefix_tests[0]); i++) {
1944 const WCHAR *prefix;
1945 XmlNodeType type;
1946 WCHAR *expected;
1947 IStream *stream;
1948
1949 stream = create_stream_on_data(prefix_tests[i].xml, strlen(prefix_tests[i].xml) + 1);
1950 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
1951 ok(hr == S_OK, "got %08x\n", hr);
1952
1953 hr = IXmlReader_Read(reader, &type);
1954 ok(hr == S_OK, "Read() failed, %#x\n", hr);
1955 ok(type == XmlNodeType_Element, "Unexpected node type %d.\n", type);
1956
1957 expected = a2w(prefix_tests[i].prefix1);
1958 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
1959 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
1960 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
1961 wine_dbgstr_w(expected));
1962 free_str(expected);
1963
1964 hr = IXmlReader_MoveToFirstAttribute(reader);
1965 ok(hr == S_OK, "MoveToFirstAttribute() failed, %#x.\n", hr);
1966
1967 hr = IXmlReader_GetNodeType(reader, &type);
1968 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
1969 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
1970
1971 expected = a2w(prefix_tests[i].prefix2);
1972 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
1973 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
1974 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
1975 wine_dbgstr_w(expected));
1976 free_str(expected);
1977
1978 hr = IXmlReader_MoveToNextAttribute(reader);
1979 ok(hr == S_OK, "MoveToNextAttribute() failed, %#x.\n", hr);
1980
1981 hr = IXmlReader_GetNodeType(reader, &type);
1982 ok(hr == S_OK, "GetNodeType() failed, %#x.\n", hr);
1983 ok(type == XmlNodeType_Attribute, "Unexpected node type %d.\n", type);
1984
1985 expected = a2w(prefix_tests[i].prefix3);
1986 hr = IXmlReader_GetPrefix(reader, &prefix, NULL);
1987 ok(hr == S_OK, "GetPrefix() failed, %#x.\n", hr);
1988 ok(!lstrcmpW(prefix, expected), "Unexpected prefix %s, expected %s.\n", wine_dbgstr_w(prefix),
1989 wine_dbgstr_w(expected));
1990 free_str(expected);
1991
1992 IStream_Release(stream);
1993 }
1994
1995 IXmlReader_Release(reader);
1996 }
1997
1998 static void test_namespaceuri(void)
1999 {
2000 struct uri_test
2001 {
2002 const char *xml;
2003 const char *uri[5];
2004 } uri_tests[] =
2005 {
2006 { "<a xmlns=\"defns a\"><b xmlns=\"defns b\"><c xmlns=\"defns c\"/></b></a>",
2007 { "defns a", "defns b", "defns c", "defns b", "defns a" }},
2008 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"/>",
2009 { "ns r" }},
2010 { "<r:a xmlns=\"defns a\" xmlns:r=\"ns r\"><b/></r:a>",
2011 { "ns r", "defns a", "ns r" }},
2012 { "<a xmlns=\"defns a\" xmlns:r=\"ns r\"><r:b/></a>",
2013 { "defns a", "ns r", "defns a" }},
2014 { "<a><b><c/></b></a>",
2015 { "", "", "", "", "" }},
2016 };
2017 IXmlReader *reader;
2018 XmlNodeType type;
2019 unsigned int i;
2020 HRESULT hr;
2021
2022 hr = CreateXmlReader(&IID_IXmlReader, (void**)&reader, NULL);
2023 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2024
2025 for (i = 0; i < sizeof(uri_tests)/sizeof(uri_tests[0]); i++) {
2026 IStream *stream = create_stream_on_data(uri_tests[i].xml, strlen(uri_tests[i].xml) + 1);
2027 unsigned int j = 0;
2028
2029 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2030 ok(hr == S_OK, "got %08x\n", hr);
2031
2032 while (IXmlReader_Read(reader, &type) == S_OK) {
2033 const WCHAR *uri, *local;
2034 WCHAR *uriW;
2035
2036 ok(type == XmlNodeType_Element || type == XmlNodeType_EndElement, "Unexpected node type %d.\n", type);
2037
2038 hr = IXmlReader_GetLocalName(reader, &local, NULL);
2039 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2040
2041 hr = IXmlReader_GetNamespaceUri(reader, &uri, NULL);
2042 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2043
2044 uriW = a2w(uri_tests[i].uri[j]);
2045 ok(!lstrcmpW(uriW, uri), "%s: uri %s\n", wine_dbgstr_w(local), wine_dbgstr_w(uri));
2046 free_str(uriW);
2047
2048 j++;
2049 }
2050
2051 IStream_Release(stream);
2052 }
2053
2054 IXmlReader_Release(reader);
2055 }
2056
2057 static void test_read_charref(void)
2058 {
2059 static const char testA[] = "<a b=\"c\">&#x1f3;&#x103;</a>";
2060 static const WCHAR chardataW[] = {0x01f3,0x0103,0};
2061 const WCHAR *value;
2062 IXmlReader *reader;
2063 XmlNodeType type;
2064 IStream *stream;
2065 HRESULT hr;
2066
2067 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2068 ok(hr == S_OK, "S_OK, got %08x\n", hr);
2069
2070 stream = create_stream_on_data(testA, sizeof(testA));
2071 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2072 ok(hr == S_OK, "got %08x\n", hr);
2073
2074 hr = IXmlReader_Read(reader, &type);
2075 ok(hr == S_OK, "got %08x\n", hr);
2076 ok(type == XmlNodeType_Element, "Unexpected node type %d\n", type);
2077
2078 hr = IXmlReader_Read(reader, &type);
2079 ok(hr == S_OK, "got %08x\n", hr);
2080 ok(type == XmlNodeType_Text, "Unexpected node type %d\n", type);
2081
2082 hr = IXmlReader_GetValue(reader, &value, NULL);
2083 ok(hr == S_OK, "got %08x\n", hr);
2084 ok(!lstrcmpW(value, chardataW), "Text value : %s\n", wine_dbgstr_w(value));
2085
2086 hr = IXmlReader_Read(reader, &type);
2087 ok(hr == S_OK, "got %08x\n", hr);
2088 ok(type == XmlNodeType_EndElement, "Unexpected node type %d\n", type);
2089
2090 IXmlReader_Release(reader);
2091 IStream_Release(stream);
2092 }
2093
2094 START_TEST(reader)
2095 {
2096 test_reader_create();
2097 test_readerinput();
2098 test_reader_state();
2099 test_read_attribute();
2100 test_read_cdata();
2101 test_read_comment();
2102 test_read_pi();
2103 test_read_system_dtd();
2104 test_read_public_dtd();
2105 test_read_element();
2106 test_isemptyelement();
2107 test_read_text();
2108 test_read_full();
2109 test_read_pending();
2110 test_readvaluechunk();
2111 test_read_xmldeclaration();
2112 test_reader_properties();
2113 test_prefix();
2114 test_namespaceuri();
2115 test_read_charref();
2116 }