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 \"/>", "attr1", "val ", S_OK }, 1871 { "<a attr1=\"val \"/>", "attr1", "val ", S_OK }, 1872 { "<a attr1=\"<>&'"\"/>", "attr1", "<>&\'\"", S_OK }, 1873 { "<a attr1=\"&entname;\"/>", NULL, NULL, WC_E_UNDECLAREDENTITY }, 1874 { "<a attr1=\"val\"/>", NULL, NULL, WC_E_XMLCHARACTER }, 1875 { "<a attr1=\"val &#a;\"/>", NULL, NULL, WC_E_DIGIT, WC_E_SEMICOLON }, 1876 { "<a attr1=\"val a;\"/>", NULL, NULL, WC_E_SEMICOLON }, 1877 { "<a attr1=\"val g;\"/>", 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\">dză></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