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