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