Reactos
at master 2871 lines 102 kB view raw
1/* 2 * Copyright 2008 Piotr Caban 3 * Copyright 2011 Thomas Mullaly 4 * Copyright 2012 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 <stdio.h> 25#include <assert.h> 26 27#include "windows.h" 28#include "ole2.h" 29#include "msxml6.h" 30#include "msxml6did.h" 31#include "ocidl.h" 32#include "initguid.h" 33#include "dispex.h" 34 35#include "wine/test.h" 36 37struct class_support 38{ 39 const GUID *clsid; 40 const char *name; 41 const IID *iid; 42 BOOL supported; 43}; 44 45static struct class_support class_support[] = 46{ 47 { &CLSID_MXXMLWriter60, "MXXMLWriter60", &IID_IMXWriter }, 48 { &CLSID_SAXAttributes60, "SAXAttributes60", &IID_IMXAttributes }, 49 { NULL } 50}; 51 52static void get_class_support_data(void) 53{ 54 struct class_support *table = class_support; 55 56 while (table->clsid) 57 { 58 IUnknown *unk; 59 HRESULT hr; 60 61 hr = CoCreateInstance(table->clsid, NULL, CLSCTX_INPROC_SERVER, table->iid, (void **)&unk); 62 if (hr == S_OK) IUnknown_Release(unk); 63 64 table->supported = hr == S_OK; 65 if (hr != S_OK) win_skip("class %s not supported\n", table->name); 66 67 table++; 68 } 69} 70 71static BOOL is_class_supported(const CLSID *clsid) 72{ 73 struct class_support *table = class_support; 74 75 while (table->clsid) 76 { 77 if (table->clsid == clsid) return table->supported; 78 table++; 79 } 80 return FALSE; 81} 82 83#define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__) 84static void _expect_ref(IUnknown* obj, ULONG ref, int line) 85{ 86 ULONG rc; 87 IUnknown_AddRef(obj); 88 rc = IUnknown_Release(obj); 89 ok_(__FILE__, line)(rc == ref, "expected refcount %ld, got %ld.\n", ref, rc); 90} 91 92#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c) 93static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported) 94{ 95 IUnknown *iface = iface_ptr; 96 HRESULT hr, expected_hr; 97 IUnknown *unk; 98 99 expected_hr = supported ? S_OK : E_NOINTERFACE; 100 101 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); 102 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr); 103 if (SUCCEEDED(hr)) 104 IUnknown_Release(unk); 105} 106 107static LONG get_refcount(void *iface) 108{ 109 IUnknown *unk = iface; 110 LONG ref; 111 112 ref = IUnknown_AddRef(unk); 113 IUnknown_Release(unk); 114 return ref-1; 115} 116 117static BSTR alloc_str_from_narrow(const char *str) 118{ 119 int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); 120 BSTR ret = SysAllocStringLen(NULL, len - 1); /* NUL character added automatically */ 121 MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); 122 return ret; 123} 124 125static BSTR alloced_bstrs[512]; 126static int alloced_bstrs_count; 127 128static BSTR _bstr_(const char *str) 129{ 130 assert(alloced_bstrs_count < ARRAY_SIZE(alloced_bstrs)); 131 alloced_bstrs[alloced_bstrs_count] = alloc_str_from_narrow(str); 132 return alloced_bstrs[alloced_bstrs_count++]; 133} 134 135static void free_bstrs(void) 136{ 137 int i; 138 for (i = 0; i < alloced_bstrs_count; i++) 139 SysFreeString(alloced_bstrs[i]); 140 alloced_bstrs_count = 0; 141} 142 143static HRESULT WINAPI isaxattributes_QueryInterface( 144 ISAXAttributes* iface, 145 REFIID riid, 146 void **ppvObject) 147{ 148 *ppvObject = NULL; 149 150 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISAXAttributes)) 151 { 152 *ppvObject = iface; 153 } 154 else 155 { 156 return E_NOINTERFACE; 157 } 158 159 return S_OK; 160} 161 162static ULONG WINAPI isaxattributes_AddRef(ISAXAttributes* iface) 163{ 164 return 2; 165} 166 167static ULONG WINAPI isaxattributes_Release(ISAXAttributes* iface) 168{ 169 return 1; 170} 171 172static HRESULT WINAPI isaxattributes_getLength(ISAXAttributes* iface, int *length) 173{ 174 *length = 3; 175 return S_OK; 176} 177 178static HRESULT WINAPI isaxattributes_getURI( 179 ISAXAttributes* iface, 180 int nIndex, 181 const WCHAR **pUrl, 182 int *pUriSize) 183{ 184 ok(0, "unexpected call\n"); 185 return E_NOTIMPL; 186} 187 188static HRESULT WINAPI isaxattributes_getLocalName( 189 ISAXAttributes* iface, 190 int nIndex, 191 const WCHAR **pLocalName, 192 int *pLocalNameLength) 193{ 194 ok(0, "unexpected call\n"); 195 return E_NOTIMPL; 196} 197 198static HRESULT WINAPI isaxattributes_getQName( 199 ISAXAttributes* iface, 200 int index, 201 const WCHAR **QName, 202 int *QNameLength) 203{ 204 static const WCHAR attrqnamesW[][15] = {L"a:attr1junk", 205 L"attr2junk", 206 L"attr3"}; 207 static const int attrqnamelen[] = {7, 5, 5}; 208 209 ok(index >= 0 && index <= 2, "invalid index received %d\n", index); 210 211 if (index >= 0 && index <= 2) { 212 *QName = attrqnamesW[index]; 213 *QNameLength = attrqnamelen[index]; 214 } else { 215 *QName = NULL; 216 *QNameLength = 0; 217 } 218 219 return S_OK; 220} 221 222static HRESULT WINAPI isaxattributes_getName( 223 ISAXAttributes* iface, 224 int nIndex, 225 const WCHAR **pUri, 226 int * pUriLength, 227 const WCHAR ** pLocalName, 228 int * pLocalNameSize, 229 const WCHAR ** pQName, 230 int * pQNameLength) 231{ 232 ok(0, "unexpected call\n"); 233 return E_NOTIMPL; 234} 235 236static HRESULT WINAPI isaxattributes_getIndexFromName( 237 ISAXAttributes* iface, 238 const WCHAR * pUri, 239 int cUriLength, 240 const WCHAR * pLocalName, 241 int cocalNameLength, 242 int * index) 243{ 244 ok(0, "unexpected call\n"); 245 return E_NOTIMPL; 246} 247 248static HRESULT WINAPI isaxattributes_getIndexFromQName( 249 ISAXAttributes* iface, 250 const WCHAR * pQName, 251 int nQNameLength, 252 int * index) 253{ 254 ok(0, "unexpected call\n"); 255 return E_NOTIMPL; 256} 257 258static HRESULT WINAPI isaxattributes_getType( 259 ISAXAttributes* iface, 260 int nIndex, 261 const WCHAR ** pType, 262 int * pTypeLength) 263{ 264 ok(0, "unexpected call\n"); 265 return E_NOTIMPL; 266} 267 268static HRESULT WINAPI isaxattributes_getTypeFromName( 269 ISAXAttributes* iface, 270 const WCHAR * pUri, 271 int nUri, 272 const WCHAR * pLocalName, 273 int nLocalName, 274 const WCHAR ** pType, 275 int * nType) 276{ 277 ok(0, "unexpected call\n"); 278 return E_NOTIMPL; 279} 280 281static HRESULT WINAPI isaxattributes_getTypeFromQName( 282 ISAXAttributes* iface, 283 const WCHAR * pQName, 284 int nQName, 285 const WCHAR ** pType, 286 int * nType) 287{ 288 ok(0, "unexpected call\n"); 289 return E_NOTIMPL; 290} 291 292static HRESULT WINAPI isaxattributes_getValue(ISAXAttributes* iface, int index, 293 const WCHAR **value, int *nValue) 294{ 295 static const WCHAR attrvaluesW[][10] = {L"a1junk", 296 L"a2junk", 297 L"<&\">'"}; 298 static const int attrvalueslen[] = {2, 2, 5}; 299 300 ok(index >= 0 && index <= 2, "invalid index received %d\n", index); 301 302 if (index >= 0 && index <= 2) { 303 *value = attrvaluesW[index]; 304 *nValue = attrvalueslen[index]; 305 } else { 306 *value = NULL; 307 *nValue = 0; 308 } 309 310 return S_OK; 311} 312 313static HRESULT WINAPI isaxattributes_getValueFromName( 314 ISAXAttributes* iface, 315 const WCHAR * pUri, 316 int nUri, 317 const WCHAR * pLocalName, 318 int nLocalName, 319 const WCHAR ** pValue, 320 int * nValue) 321{ 322 ok(0, "unexpected call\n"); 323 return E_NOTIMPL; 324} 325 326static HRESULT WINAPI isaxattributes_getValueFromQName( 327 ISAXAttributes* iface, 328 const WCHAR * pQName, 329 int nQName, 330 const WCHAR ** pValue, 331 int * nValue) 332{ 333 ok(0, "unexpected call\n"); 334 return E_NOTIMPL; 335} 336 337static const ISAXAttributesVtbl SAXAttributesVtbl = 338{ 339 isaxattributes_QueryInterface, 340 isaxattributes_AddRef, 341 isaxattributes_Release, 342 isaxattributes_getLength, 343 isaxattributes_getURI, 344 isaxattributes_getLocalName, 345 isaxattributes_getQName, 346 isaxattributes_getName, 347 isaxattributes_getIndexFromName, 348 isaxattributes_getIndexFromQName, 349 isaxattributes_getType, 350 isaxattributes_getTypeFromName, 351 isaxattributes_getTypeFromQName, 352 isaxattributes_getValue, 353 isaxattributes_getValueFromName, 354 isaxattributes_getValueFromQName 355}; 356 357static ISAXAttributes saxattributes = { &SAXAttributesVtbl }; 358 359static void test_mxwriter_handlers(void) 360{ 361 IMXWriter *writer; 362 HRESULT hr; 363 int i; 364 365 static const IID *riids[] = 366 { 367 &IID_ISAXContentHandler, 368 &IID_ISAXLexicalHandler, 369 &IID_ISAXDeclHandler, 370 &IID_ISAXDTDHandler, 371 &IID_ISAXErrorHandler, 372 &IID_IVBSAXDeclHandler, 373 &IID_IVBSAXLexicalHandler, 374 &IID_IVBSAXContentHandler, 375 &IID_IVBSAXDTDHandler, 376 &IID_IVBSAXErrorHandler 377 }; 378 379 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 380 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 381 382 EXPECT_REF(writer, 1); 383 384 for (i = 0; i < ARRAY_SIZE(riids); i++) 385 { 386 IUnknown *handler; 387 IMXWriter *writer2; 388 389 /* handler from IMXWriter */ 390 hr = IMXWriter_QueryInterface(writer, riids[i], (void**)&handler); 391 ok(hr == S_OK, "%s, unexpected hr %#lx.\n", wine_dbgstr_guid(riids[i]), hr); 392 EXPECT_REF(writer, 2); 393 394 /* IMXWriter from a handler */ 395 hr = IUnknown_QueryInterface(handler, &IID_IMXWriter, (void**)&writer2); 396 ok(hr == S_OK, "%s, unexpected hr %#lx.\n", wine_dbgstr_guid(riids[i]), hr); 397 ok(writer2 == writer, "got %p, expected %p\n", writer2, writer); 398 EXPECT_REF(writer, 3); 399 IMXWriter_Release(writer2); 400 IUnknown_Release(handler); 401 } 402 403 IMXWriter_Release(writer); 404} 405 406static void test_mxwriter_default_properties(void) 407{ 408 IMXWriter *writer; 409 VARIANT_BOOL b; 410 BSTR encoding; 411 HRESULT hr; 412 413 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 415 416 b = VARIANT_FALSE; 417 hr = IMXWriter_get_byteOrderMark(writer, &b); 418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 419 ok(b == VARIANT_TRUE, "Unexpected value %d.\n", b); 420 421 b = VARIANT_TRUE; 422 hr = IMXWriter_get_disableOutputEscaping(writer, &b); 423 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 424 ok(b == VARIANT_FALSE, "Unexpected value %d.\n", b); 425 426 b = VARIANT_TRUE; 427 hr = IMXWriter_get_indent(writer, &b); 428 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 429 ok(b == VARIANT_FALSE, "Unexpected value %d.\n", b); 430 431 b = VARIANT_TRUE; 432 hr = IMXWriter_get_omitXMLDeclaration(writer, &b); 433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 434 ok(b == VARIANT_FALSE, "Unexpected value %d.\n", b); 435 436 b = VARIANT_TRUE; 437 hr = IMXWriter_get_standalone(writer, &b); 438 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 439 ok(b == VARIANT_FALSE, "Unexpected value %d.\n", b); 440 441 hr = IMXWriter_get_encoding(writer, &encoding); 442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 443 ok(!lstrcmpW(encoding, L"UTF-16"), "Unexpected value %s.\n", wine_dbgstr_w(encoding)); 444 SysFreeString(encoding); 445 446 IMXWriter_Release(writer); 447} 448 449static void test_mxwriter_properties(void) 450{ 451 ISAXContentHandler *content; 452 IMXWriter *writer; 453 VARIANT_BOOL b; 454 HRESULT hr; 455 BSTR str, str2; 456 VARIANT dest; 457 458 test_mxwriter_default_properties(); 459 460 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 462 463 hr = IMXWriter_get_disableOutputEscaping(writer, NULL); 464 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 465 466 hr = IMXWriter_get_byteOrderMark(writer, NULL); 467 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 468 469 hr = IMXWriter_get_indent(writer, NULL); 470 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 471 472 hr = IMXWriter_get_omitXMLDeclaration(writer, NULL); 473 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 474 475 hr = IMXWriter_get_standalone(writer, NULL); 476 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 477 478 /* set and check */ 479 hr = IMXWriter_put_standalone(writer, VARIANT_TRUE); 480 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 481 482 b = VARIANT_FALSE; 483 hr = IMXWriter_get_standalone(writer, &b); 484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 485 ok(b == VARIANT_TRUE, "got %d\n", b); 486 487 hr = IMXWriter_get_encoding(writer, NULL); 488 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 489 490 str = (void*)0xdeadbeef; 491 hr = IMXWriter_get_encoding(writer, &str); 492 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 493 ok(!lstrcmpW(str, L"UTF-16"), "Unexpected string %s.\n", wine_dbgstr_w(str)); 494 495 str2 = (void*)0xdeadbeef; 496 hr = IMXWriter_get_encoding(writer, &str2); 497 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 498 ok(str != str2, "expected newly allocated, got same %p\n", str); 499 500 SysFreeString(str2); 501 SysFreeString(str); 502 503 /* put empty string */ 504 str = SysAllocString(L""); 505 hr = IMXWriter_put_encoding(writer, str); 506 todo_wine 507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 508 SysFreeString(str); 509 510 str = (void*)0xdeadbeef; 511 hr = IMXWriter_get_encoding(writer, &str); 512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 513 ok(!lstrcmpW(str, L"UTF-16"), "got %s\n", wine_dbgstr_w(str)); 514 SysFreeString(str); 515 516 /* invalid encoding name */ 517 str = SysAllocString(L"test"); 518 hr = IMXWriter_put_encoding(writer, str); 519 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 520 SysFreeString(str); 521 522 /* test case sensitivity */ 523 hr = IMXWriter_put_encoding(writer, _bstr_("utf-8")); 524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 525 str = (void*)0xdeadbeef; 526 hr = IMXWriter_get_encoding(writer, &str); 527 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 528 ok(!lstrcmpW(str, L"utf-8"), "got %s\n", wine_dbgstr_w(str)); 529 SysFreeString(str); 530 531 hr = IMXWriter_put_encoding(writer, _bstr_("uTf-16")); 532 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 533 str = (void*)0xdeadbeef; 534 hr = IMXWriter_get_encoding(writer, &str); 535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 536 ok(!lstrcmpW(str, L"uTf-16"), "got %s\n", wine_dbgstr_w(str)); 537 SysFreeString(str); 538 539 /* how it affects document creation */ 540 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 541 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 542 543 hr = ISAXContentHandler_startDocument(content); 544 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 545 hr = ISAXContentHandler_endDocument(content); 546 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 547 548 V_VT(&dest) = VT_EMPTY; 549 hr = IMXWriter_get_output(writer, &dest); 550 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 551 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 552 todo_wine 553 ok(!lstrcmpW(L"<?xml version=\"1.0\" standalone=\"yes\"?>\r\n", 554 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 555 VariantClear(&dest); 556 ISAXContentHandler_Release(content); 557 558 hr = IMXWriter_get_version(writer, NULL); 559 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 560 /* default version is 'surprisingly' 1.0 */ 561 hr = IMXWriter_get_version(writer, &str); 562 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 563 ok(!lstrcmpW(str, L"1.0"), "got %s\n", wine_dbgstr_w(str)); 564 SysFreeString(str); 565 566 /* store version string as is */ 567 hr = IMXWriter_put_version(writer, NULL); 568 todo_wine 569 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 570 571 hr = IMXWriter_put_version(writer, _bstr_("1.0")); 572 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 573 574 hr = IMXWriter_put_version(writer, _bstr_("")); 575 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 576 hr = IMXWriter_get_version(writer, &str); 577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 578 todo_wine 579 ok(!lstrcmpW(str, L"1.0"), "got %s\n", wine_dbgstr_w(str)); 580 SysFreeString(str); 581 582 hr = IMXWriter_put_version(writer, _bstr_("a.b")); 583 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 584 hr = IMXWriter_get_version(writer, &str); 585 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 586 ok(!lstrcmpW(str, L"a.b"), "got %s\n", wine_dbgstr_w(str)); 587 SysFreeString(str); 588 589 hr = IMXWriter_put_version(writer, _bstr_("2.0")); 590 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 591 hr = IMXWriter_get_version(writer, &str); 592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 593 ok(!lstrcmpW(str, L"2.0"), "got %s\n", wine_dbgstr_w(str)); 594 SysFreeString(str); 595 596 IMXWriter_Release(writer); 597 free_bstrs(); 598} 599 600static void test_mxwriter_flush(void) 601{ 602 ISAXContentHandler *content; 603 IMXWriter *writer; 604 LARGE_INTEGER pos; 605 ULARGE_INTEGER pos2; 606 IStream *stream; 607 VARIANT dest; 608 HRESULT hr; 609 char *buff; 610 LONG ref; 611 int len; 612 613 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 614 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 615 616 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 617 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 618 EXPECT_REF(stream, 1); 619 620 /* detach when nothing was attached */ 621 V_VT(&dest) = VT_EMPTY; 622 hr = IMXWriter_put_output(writer, dest); 623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 624 625 /* attach stream */ 626 V_VT(&dest) = VT_UNKNOWN; 627 V_UNKNOWN(&dest) = (IUnknown*)stream; 628 hr = IMXWriter_put_output(writer, dest); 629 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 630 todo_wine EXPECT_REF(stream, 3); 631 632 /* detach setting VT_EMPTY destination */ 633 V_VT(&dest) = VT_EMPTY; 634 hr = IMXWriter_put_output(writer, dest); 635 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 636 EXPECT_REF(stream, 1); 637 638 V_VT(&dest) = VT_UNKNOWN; 639 V_UNKNOWN(&dest) = (IUnknown*)stream; 640 hr = IMXWriter_put_output(writer, dest); 641 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 642 643 /* flush() doesn't detach a stream */ 644 hr = IMXWriter_flush(writer); 645 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 646 todo_wine EXPECT_REF(stream, 3); 647 648 pos.QuadPart = 0; 649 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 650 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 651 ok(pos2.QuadPart == 0, "expected stream beginning\n"); 652 653 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 655 656 hr = ISAXContentHandler_startDocument(content); 657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 658 659 pos.QuadPart = 0; 660 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 662 ok(pos2.QuadPart != 0, "expected stream beginning\n"); 663 664 /* already started */ 665 hr = ISAXContentHandler_startDocument(content); 666 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 667 668 hr = ISAXContentHandler_endDocument(content); 669 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 670 671 /* flushed on endDocument() */ 672 pos.QuadPart = 0; 673 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 674 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 675 ok(pos2.QuadPart != 0, "expected stream position moved\n"); 676 677 IStream_Release(stream); 678 679 /* auto-flush feature */ 680 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 682 EXPECT_REF(stream, 1); 683 684 V_VT(&dest) = VT_UNKNOWN; 685 V_UNKNOWN(&dest) = (IUnknown*)stream; 686 hr = IMXWriter_put_output(writer, dest); 687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 688 689 hr = IMXWriter_put_byteOrderMark(writer, VARIANT_FALSE); 690 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 691 692 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 694 695 hr = ISAXContentHandler_startDocument(content); 696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 697 698 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("a"), 1, NULL); 699 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 700 701 /* internal buffer is flushed automatically on certain threshold */ 702 pos.QuadPart = 0; 703 pos2.QuadPart = 1; 704 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 705 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 706 ok(pos2.QuadPart == 0, "expected stream beginning\n"); 707 708 len = 2048; 709 buff = malloc(len + 1); 710 memset(buff, 'A', len); 711 buff[len] = 0; 712 hr = ISAXContentHandler_characters(content, _bstr_(buff), len); 713 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 714 715 pos.QuadPart = 0; 716 pos2.QuadPart = 0; 717 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 719 ok(pos2.QuadPart != 0, "unexpected stream beginning\n"); 720 721 hr = IMXWriter_get_output(writer, NULL); 722 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 723 724 ref = get_refcount(stream); 725 V_VT(&dest) = VT_EMPTY; 726 hr = IMXWriter_get_output(writer, &dest); 727 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 728 ok(V_VT(&dest) == VT_UNKNOWN, "got vt type %d\n", V_VT(&dest)); 729 ok(V_UNKNOWN(&dest) == (IUnknown*)stream, "got pointer %p\n", V_UNKNOWN(&dest)); 730 ok(ref+1 == get_refcount(stream), "expected increased refcount\n"); 731 VariantClear(&dest); 732 733 hr = ISAXContentHandler_endDocument(content); 734 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 735 736 IStream_Release(stream); 737 738 /* test char count lower than threshold */ 739 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 741 EXPECT_REF(stream, 1); 742 743 hr = ISAXContentHandler_startDocument(content); 744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 745 746 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("a"), 1, NULL); 747 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 748 749 pos.QuadPart = 0; 750 pos2.QuadPart = 1; 751 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 752 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 753 ok(pos2.QuadPart == 0, "expected stream beginning\n"); 754 755 memset(buff, 'A', len); 756 buff[len] = 0; 757 hr = ISAXContentHandler_characters(content, _bstr_(buff), len - 8); 758 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 759 760 pos.QuadPart = 0; 761 pos2.QuadPart = 1; 762 hr = IStream_Seek(stream, pos, STREAM_SEEK_CUR, &pos2); 763 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 764 ok(pos2.QuadPart == 0, "expected stream beginning\n"); 765 766 hr = ISAXContentHandler_endDocument(content); 767 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 768 769 /* test auto-flush function when stream is not set */ 770 V_VT(&dest) = VT_EMPTY; 771 hr = IMXWriter_put_output(writer, dest); 772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 773 774 hr = ISAXContentHandler_startDocument(content); 775 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 776 777 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("a"), 1, NULL); 778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 779 780 memset(buff, 'A', len); 781 buff[len] = 0; 782 hr = ISAXContentHandler_characters(content, _bstr_(buff), len); 783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 784 785 V_VT(&dest) = VT_EMPTY; 786 hr = IMXWriter_get_output(writer, &dest); 787 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 788 len += strlen("<a>"); 789 ok(SysStringLen(V_BSTR(&dest)) == len, "got len=%d, expected %d\n", SysStringLen(V_BSTR(&dest)), len); 790 VariantClear(&dest); 791 792 free(buff); 793 ISAXContentHandler_Release(content); 794 IStream_Release(stream); 795 IMXWriter_Release(writer); 796 free_bstrs(); 797} 798 799static void test_mxwriter_startenddocument(void) 800{ 801 ISAXContentHandler *content; 802 IMXWriter *writer; 803 VARIANT dest; 804 HRESULT hr; 805 806 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 807 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 808 809 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 811 812 hr = ISAXContentHandler_startDocument(content); 813 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 814 815 hr = ISAXContentHandler_endDocument(content); 816 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 817 818 V_VT(&dest) = VT_EMPTY; 819 hr = IMXWriter_get_output(writer, &dest); 820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 821 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 822 ok(!lstrcmpW(L"<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n", V_BSTR(&dest)), 823 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 824 VariantClear(&dest); 825 826 /* now try another startDocument */ 827 hr = ISAXContentHandler_startDocument(content); 828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 829 /* and get duplicated prolog */ 830 V_VT(&dest) = VT_EMPTY; 831 hr = IMXWriter_get_output(writer, &dest); 832 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 833 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 834 ok(!lstrcmpW(_bstr_("<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n" 835 "<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n"), V_BSTR(&dest)), 836 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 837 VariantClear(&dest); 838 839 ISAXContentHandler_Release(content); 840 IMXWriter_Release(writer); 841 842 /* now with omitted declaration */ 843 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 845 846 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 847 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 848 849 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 851 852 hr = ISAXContentHandler_startDocument(content); 853 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 854 855 hr = ISAXContentHandler_endDocument(content); 856 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 857 858 V_VT(&dest) = VT_EMPTY; 859 hr = IMXWriter_get_output(writer, &dest); 860 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 861 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 862 ok(!lstrcmpW(L"", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 863 VariantClear(&dest); 864 865 ISAXContentHandler_Release(content); 866 IMXWriter_Release(writer); 867 868 free_bstrs(); 869} 870 871enum startendtype 872{ 873 StartElement = 0x001, 874 EndElement = 0x010, 875 StartEndElement = 0x011, 876 DisableEscaping = 0x100 877}; 878 879struct writer_startendelement_t 880{ 881 enum startendtype type; 882 const char *uri; 883 const char *local_name; 884 const char *qname; 885 const char *output; 886 HRESULT hr; 887 ISAXAttributes *attr; 888}; 889 890static const char startelement_xml[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"&lt;&amp;&quot;&gt;\'\">"; 891static const char startendelement_xml[] = "<uri:local a:attr1=\"a1\" attr2=\"a2\" attr3=\"&lt;&amp;&quot;&gt;\'\"/>"; 892 893static const struct writer_startendelement_t writer_startendelement[] = 894{ 895 { StartElement, NULL, NULL, NULL, "<>", S_OK }, 896 { StartElement, "uri", NULL, NULL, "<>", S_OK }, 897 { StartElement, NULL, "local", NULL, "<>", S_OK }, 898 { StartElement, NULL, NULL, "qname", "<qname>", S_OK }, 899 { StartElement, "uri", "local", "qname", "<qname>", S_OK }, 900 { StartElement, "uri", "local", NULL, "<>", S_OK }, 901 { StartElement, "uri", "local", "uri:local", "<uri:local>", S_OK }, 902 { StartElement, "uri", "local", "uri:local2", "<uri:local2>", S_OK }, 903 { EndElement, NULL, NULL, NULL, "</>", S_OK }, 904 { EndElement, "uri", NULL, NULL, "</>", S_OK }, 905 { EndElement, NULL, "local", NULL, "</>", S_OK }, 906 { EndElement, NULL, NULL, "qname", "</qname>", S_OK }, 907 { EndElement, "uri", "local", "qname", "</qname>", S_OK }, 908 { EndElement, "uri", "local", NULL, "</>", S_OK }, 909 { EndElement, "uri", "local", "uri:local", "</uri:local>", S_OK }, 910 { EndElement, "uri", "local", "uri:local2", "</uri:local2>", S_OK }, 911 { StartElement, "uri", "local", "uri:local", startelement_xml, S_OK, &saxattributes }, 912 { StartEndElement, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes }, 913 { StartEndElement, "", "", "", "</>", S_OK }, 914 { StartEndElement | DisableEscaping, "uri", "local", "uri:local", startendelement_xml, S_OK, &saxattributes }, 915}; 916 917static void test_mxwriter_startendelement_batch(void) 918{ 919 unsigned int i; 920 921 for (i = 0; i < ARRAY_SIZE(writer_startendelement); ++i) 922 { 923 const struct writer_startendelement_t *table = &writer_startendelement[i]; 924 ISAXContentHandler *content; 925 IMXWriter *writer; 926 HRESULT hr; 927 928 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 930 931 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 932 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 933 934 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 936 937 hr = ISAXContentHandler_startDocument(content); 938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 939 940 if (table->type & DisableEscaping) 941 { 942 hr = IMXWriter_put_disableOutputEscaping(writer, VARIANT_TRUE); 943 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 944 } 945 946 if (table->type & StartElement) 947 { 948 hr = ISAXContentHandler_startElement(content, _bstr_(table->uri), table->uri ? strlen(table->uri) : 0, 949 _bstr_(table->local_name), table->local_name ? strlen(table->local_name) : 0, _bstr_(table->qname), 950 table->qname ? strlen(table->qname) : 0, table->attr); 951 ok(hr == table->hr, "test %d: got %#lx, expected %#lx\n", i, hr, table->hr); 952 } 953 954 if (table->type & EndElement) 955 { 956 hr = ISAXContentHandler_endElement(content, _bstr_(table->uri), table->uri ? strlen(table->uri) : 0, 957 _bstr_(table->local_name), table->local_name ? strlen(table->local_name) : 0, _bstr_(table->qname), 958 table->qname ? strlen(table->qname) : 0); 959 ok(hr == table->hr, "test %d: got %#lx, expected %#lx\n", i, hr, table->hr); 960 } 961 962 /* test output */ 963 if (hr == S_OK) 964 { 965 VARIANT dest; 966 967 V_VT(&dest) = VT_EMPTY; 968 hr = IMXWriter_get_output(writer, &dest); 969 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 970 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 971 ok(!lstrcmpW(_bstr_(table->output), V_BSTR(&dest)), 972 "test %d: got wrong content %s, expected %s\n", i, wine_dbgstr_w(V_BSTR(&dest)), table->output); 973 VariantClear(&dest); 974 } 975 976 ISAXContentHandler_Release(content); 977 IMXWriter_Release(writer); 978 } 979 980 free_bstrs(); 981} 982 983/* point of these test is to start/end element with different names and name lengths */ 984struct writer_startendelement2_t 985{ 986 const char *qnamestart; 987 int qnamestart_len; 988 const char *qnameend; 989 int qnameend_len; 990 const char *output; 991 HRESULT hr; 992}; 993 994static const struct writer_startendelement2_t writer_startendelement2[] = 995{ 996 { "a", -1, "b", -1, "<a/>", E_INVALIDARG }, 997 { "a", 1, "b", 1, "<a/>", S_OK }, 998}; 999 1000static void test_mxwriter_startendelement_batch2(void) 1001{ 1002 unsigned int i; 1003 1004 for (i = 0; i < ARRAY_SIZE(writer_startendelement2); ++i) 1005 { 1006 const struct writer_startendelement2_t *table = &writer_startendelement2[i]; 1007 ISAXContentHandler *content; 1008 IMXWriter *writer; 1009 HRESULT hr; 1010 1011 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1012 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1013 1014 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1015 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1016 1017 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1018 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1019 1020 hr = ISAXContentHandler_startDocument(content); 1021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1022 1023 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, 1024 _bstr_(table->qnamestart), table->qnamestart_len, NULL); 1025 ok(hr == table->hr, "test %d: got %#lx, expected %#lx\n", i, hr, table->hr); 1026 1027 hr = ISAXContentHandler_endElement(content, _bstr_(""), 0, _bstr_(""), 0, 1028 _bstr_(table->qnameend), table->qnameend_len); 1029 ok(hr == table->hr, "test %d: got %#lx, expected %#lx\n", i, hr, table->hr); 1030 1031 /* test output */ 1032 if (hr == S_OK) 1033 { 1034 VARIANT dest; 1035 1036 V_VT(&dest) = VT_EMPTY; 1037 hr = IMXWriter_get_output(writer, &dest); 1038 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1039 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1040 ok(!lstrcmpW(_bstr_(table->output), V_BSTR(&dest)), 1041 "test %d: got wrong content %s, expected %s\n", i, wine_dbgstr_w(V_BSTR(&dest)), table->output); 1042 VariantClear(&dest); 1043 } 1044 1045 ISAXContentHandler_Release(content); 1046 IMXWriter_Release(writer); 1047 1048 free_bstrs(); 1049 } 1050} 1051 1052static void test_mxwriter_startendelement(void) 1053{ 1054 ISAXContentHandler *content; 1055 IVBSAXContentHandler *vb_content; 1056 IMXWriter *writer; 1057 VARIANT dest; 1058 BSTR bstr_null = NULL, bstr_empty, bstr_a, bstr_b, bstr_ab; 1059 HRESULT hr; 1060 1061 test_mxwriter_startendelement_batch(); 1062 test_mxwriter_startendelement_batch2(); 1063 1064 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1065 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1066 1067 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1069 1070 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXContentHandler, (void**)&vb_content); 1071 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1072 1073 hr = IVBSAXContentHandler_startDocument(vb_content); 1074 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1075 1076 bstr_empty = SysAllocString(L""); 1077 bstr_a = SysAllocString(L"a"); 1078 bstr_b = SysAllocString(L"b"); 1079 bstr_ab = SysAllocString(L"a:b"); 1080 1081 hr = IVBSAXContentHandler_startElement(vb_content, &bstr_null, &bstr_empty, &bstr_b, NULL); 1082 todo_wine 1083 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1084 1085 hr = IVBSAXContentHandler_startElement(vb_content, &bstr_empty, &bstr_b, &bstr_empty, NULL); 1086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1087 1088 V_VT(&dest) = VT_EMPTY; 1089 hr = IMXWriter_get_output(writer, &dest); 1090 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1091 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1092 todo_wine 1093 ok(!lstrcmpW(L"<b><>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1094 VariantClear(&dest); 1095 1096 hr = IVBSAXContentHandler_startElement(vb_content, &bstr_empty, &bstr_empty, &bstr_b, NULL); 1097 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1098 1099 V_VT(&dest) = VT_EMPTY; 1100 hr = IMXWriter_get_output(writer, &dest); 1101 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1102 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1103 todo_wine 1104 ok(!lstrcmpW(L"<b><><b>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1105 VariantClear(&dest); 1106 1107 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_null, &bstr_null, &bstr_b); 1108 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1109 1110 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_null, &bstr_a, &bstr_b); 1111 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1112 1113 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_a, &bstr_b, &bstr_null); 1114 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1115 1116 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_empty, &bstr_null, &bstr_b); 1117 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1118 1119 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_empty, &bstr_b, &bstr_null); 1120 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1121 1122 hr = IVBSAXContentHandler_endElement(vb_content, &bstr_empty, &bstr_empty, &bstr_b); 1123 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1124 1125 V_VT(&dest) = VT_EMPTY; 1126 hr = IMXWriter_get_output(writer, &dest); 1127 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1128 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1129 todo_wine 1130 ok(!lstrcmpW(L"<b><><b></b></b></></b></></b>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1131 VariantClear(&dest); 1132 1133 SysFreeString(bstr_empty); 1134 SysFreeString(bstr_a); 1135 SysFreeString(bstr_b); 1136 SysFreeString(bstr_ab); 1137 1138 hr = IVBSAXContentHandler_endDocument(vb_content); 1139 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1140 1141 IVBSAXContentHandler_Release(vb_content); 1142 IMXWriter_Release(writer); 1143 1144 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1146 1147 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1149 1150 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1151 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1152 1153 hr = ISAXContentHandler_startDocument(content); 1154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1155 1156 /* all string pointers should be not null */ 1157 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_("b"), 1, _bstr_(""), 0, NULL); 1158 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1159 1160 V_VT(&dest) = VT_EMPTY; 1161 hr = IMXWriter_get_output(writer, &dest); 1162 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1163 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1164 ok(!lstrcmpW(L"<>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1165 VariantClear(&dest); 1166 1167 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1, NULL); 1168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1169 1170 V_VT(&dest) = VT_EMPTY; 1171 hr = IMXWriter_get_output(writer, &dest); 1172 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1173 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1174 ok(!lstrcmpW(L"<><b>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1175 VariantClear(&dest); 1176 1177 hr = ISAXContentHandler_endElement(content, NULL, 0, NULL, 0, _bstr_("a:b"), 3); 1178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1179 1180 hr = ISAXContentHandler_endElement(content, NULL, 0, _bstr_("b"), 1, _bstr_("a:b"), 3); 1181 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1182 1183 /* only local name is an error too */ 1184 hr = ISAXContentHandler_endElement(content, NULL, 0, _bstr_("b"), 1, NULL, 0); 1185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1186 1187 hr = ISAXContentHandler_endElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("b"), 1); 1188 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1189 1190 V_VT(&dest) = VT_EMPTY; 1191 hr = IMXWriter_get_output(writer, &dest); 1192 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1193 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1194 ok(!lstrcmpW(L"<><b></a:b></a:b></></b>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1195 VariantClear(&dest); 1196 1197 hr = ISAXContentHandler_endDocument(content); 1198 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1199 1200 V_VT(&dest) = VT_EMPTY; 1201 hr = IMXWriter_put_output(writer, dest); 1202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1203 1204 V_VT(&dest) = VT_EMPTY; 1205 hr = IMXWriter_get_output(writer, &dest); 1206 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1207 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1208 ok(!lstrcmpW(L"", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1209 VariantClear(&dest); 1210 1211 hr = ISAXContentHandler_startDocument(content); 1212 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1213 1214 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abcdef"), 3, NULL); 1215 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1216 1217 V_VT(&dest) = VT_EMPTY; 1218 hr = IMXWriter_get_output(writer, &dest); 1219 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1220 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1221 ok(!lstrcmpW(L"<abc>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1222 VariantClear(&dest); 1223 1224 hr = ISAXContentHandler_endDocument(content); 1225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1226 IMXWriter_flush(writer); 1227 1228 hr = ISAXContentHandler_endElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("abdcdef"), 3); 1229 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1230 V_VT(&dest) = VT_EMPTY; 1231 hr = IMXWriter_get_output(writer, &dest); 1232 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1233 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1234 ok(!lstrcmpW(L"<abc></abd>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1235 VariantClear(&dest); 1236 1237 V_VT(&dest) = VT_EMPTY; 1238 hr = IMXWriter_put_output(writer, dest); 1239 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1240 1241 /* length -1 */ 1242 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), -1, NULL); 1243 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 1244 1245 ISAXContentHandler_Release(content); 1246 IMXWriter_Release(writer); 1247 free_bstrs(); 1248} 1249 1250struct writer_characters_t 1251{ 1252 const char *data; 1253 const char *output; 1254}; 1255 1256static const struct writer_characters_t writer_characters[] = 1257{ 1258 { "< > & \" \'", "&lt; &gt; &amp; \" \'" }, 1259}; 1260 1261static void test_mxwriter_characters(void) 1262{ 1263 static const WCHAR embedded_nullbytes[] = L"a\0b\0\0\0c"; 1264 IVBSAXContentHandler *vb_content; 1265 ISAXContentHandler *content; 1266 IMXWriter *writer; 1267 VARIANT dest; 1268 BSTR str; 1269 HRESULT hr; 1270 int i = 0; 1271 1272 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1274 1275 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1276 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1277 1278 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXContentHandler, (void**)&vb_content); 1279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1280 1281 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1283 1284 hr = ISAXContentHandler_startDocument(content); 1285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1286 1287 hr = ISAXContentHandler_characters(content, NULL, 0); 1288 todo_wine 1289 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1290 1291 hr = ISAXContentHandler_characters(content, L"TESTCHARDATA .", 0); 1292 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1293 1294 str = _bstr_("VbChars"); 1295 hr = IVBSAXContentHandler_characters(vb_content, &str); 1296 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1297 1298 hr = ISAXContentHandler_characters(content, L"TESTCHARDATA .", 14); 1299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1300 1301 V_VT(&dest) = VT_EMPTY; 1302 hr = IMXWriter_get_output(writer, &dest); 1303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1304 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1305 ok(!lstrcmpW(L"VbCharsTESTCHARDATA .", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1306 VariantClear(&dest); 1307 1308 hr = ISAXContentHandler_endDocument(content); 1309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1310 1311 ISAXContentHandler_Release(content); 1312 IVBSAXContentHandler_Release(vb_content); 1313 IMXWriter_Release(writer); 1314 1315 /* try empty characters data to see if element is closed */ 1316 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1317 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1318 1319 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1320 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1321 1322 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1323 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1324 1325 hr = ISAXContentHandler_startDocument(content); 1326 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1327 1328 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL); 1329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1330 1331 hr = ISAXContentHandler_characters(content, L"TESTCHARDATA .", 0); 1332 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1333 1334 hr = ISAXContentHandler_endElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1); 1335 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1336 1337 V_VT(&dest) = VT_EMPTY; 1338 hr = IMXWriter_get_output(writer, &dest); 1339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1340 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1341 ok(!lstrcmpW(L"<a></a>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1342 VariantClear(&dest); 1343 1344 ISAXContentHandler_Release(content); 1345 IMXWriter_Release(writer); 1346 1347 /* test embedded null bytes */ 1348 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1350 1351 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1352 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1353 1354 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1356 1357 hr = ISAXContentHandler_startDocument(content); 1358 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1359 1360 hr = ISAXContentHandler_characters(content, embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)); 1361 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1362 1363 V_VT(&dest) = VT_EMPTY; 1364 hr = IMXWriter_get_output(writer, &dest); 1365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1366 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1367 ok(SysStringLen(V_BSTR(&dest)) == ARRAY_SIZE(embedded_nullbytes), "unexpected len %d\n", SysStringLen(V_BSTR(&dest))); 1368 ok(!memcmp(V_BSTR(&dest), embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)), 1369 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1370 VariantClear(&dest); 1371 1372 ISAXContentHandler_Release(content); 1373 IMXWriter_Release(writer); 1374 1375 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1376 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1377 1378 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXContentHandler, (void**)&vb_content); 1379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1380 1381 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1382 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1383 1384 hr = IVBSAXContentHandler_startDocument(vb_content); 1385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1386 1387 str = SysAllocStringLen(embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)); 1388 hr = IVBSAXContentHandler_characters(vb_content, &str); 1389 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1390 SysFreeString(str); 1391 1392 V_VT(&dest) = VT_EMPTY; 1393 hr = IMXWriter_get_output(writer, &dest); 1394 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1395 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1396 todo_wine 1397 ok(SysStringLen(V_BSTR(&dest)) == 1, "Unexpected length %d.\n", SysStringLen(V_BSTR(&dest))); 1398 ok(!memcmp(V_BSTR(&dest), embedded_nullbytes, ARRAY_SIZE(embedded_nullbytes)), 1399 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1400 VariantClear(&dest); 1401 1402 IVBSAXContentHandler_Release(vb_content); 1403 IMXWriter_Release(writer); 1404 1405 /* batch tests */ 1406 for (i = 0; i < ARRAY_SIZE(writer_characters); ++i) 1407 { 1408 const struct writer_characters_t *table = &writer_characters[i]; 1409 ISAXContentHandler *content; 1410 IMXWriter *writer; 1411 VARIANT dest; 1412 HRESULT hr; 1413 1414 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1416 1417 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1419 1420 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1422 1423 hr = ISAXContentHandler_startDocument(content); 1424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1425 1426 hr = ISAXContentHandler_characters(content, _bstr_(table->data), strlen(table->data)); 1427 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1428 1429 /* test output */ 1430 if (hr == S_OK) 1431 { 1432 V_VT(&dest) = VT_EMPTY; 1433 hr = IMXWriter_get_output(writer, &dest); 1434 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1435 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1436 ok(!lstrcmpW(_bstr_(table->output), V_BSTR(&dest)), 1437 "test %d: got wrong content %s, expected \"%s\"\n", i, wine_dbgstr_w(V_BSTR(&dest)), table->output); 1438 VariantClear(&dest); 1439 } 1440 1441 /* with disabled escaping */ 1442 V_VT(&dest) = VT_EMPTY; 1443 hr = IMXWriter_put_output(writer, dest); 1444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1445 1446 hr = IMXWriter_put_disableOutputEscaping(writer, VARIANT_TRUE); 1447 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1448 1449 hr = ISAXContentHandler_characters(content, _bstr_(table->data), strlen(table->data)); 1450 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1451 1452 /* test output */ 1453 if (hr == S_OK) 1454 { 1455 V_VT(&dest) = VT_EMPTY; 1456 hr = IMXWriter_get_output(writer, &dest); 1457 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1458 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1459 ok(!lstrcmpW(_bstr_(table->data), V_BSTR(&dest)), 1460 "test %d: got wrong content %s, expected \"%s\"\n", i, wine_dbgstr_w(V_BSTR(&dest)), table->data); 1461 VariantClear(&dest); 1462 } 1463 1464 ISAXContentHandler_Release(content); 1465 IMXWriter_Release(writer); 1466 } 1467 1468 free_bstrs(); 1469} 1470 1471static void test_mxwriter_domdoc(void) 1472{ 1473 ISAXContentHandler *content; 1474 IXMLDOMDocument *domdoc; 1475 IMXWriter *writer; 1476 HRESULT hr; 1477 VARIANT dest; 1478 IXMLDOMElement *root = NULL; 1479 IXMLDOMNodeList *node_list = NULL; 1480 IXMLDOMNode *node = NULL; 1481 LONG list_length = 0; 1482 BSTR str; 1483 1484 /* Create writer and attach DOMDocument output */ 1485 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void**)&writer); 1486 ok(hr == S_OK, "Failed to create a writer, hr %#lx.\n", hr); 1487 1488 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1490 1491 hr = CoCreateInstance(&CLSID_DOMDocument60, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&domdoc); 1492 ok(hr == S_OK, "Failed to create a document, hr %#lx.\n", hr); 1493 1494 V_VT(&dest) = VT_DISPATCH; 1495 V_DISPATCH(&dest) = (IDispatch *)domdoc; 1496 1497 hr = IMXWriter_put_output(writer, dest); 1498 todo_wine 1499 ok(hr == S_OK, "Failed to set writer output, hr %#lx.\n", hr); 1500 if (FAILED(hr)) 1501 { 1502 IXMLDOMDocument_Release(domdoc); 1503 IMXWriter_Release(writer); 1504 return; 1505 } 1506 1507 /* Add root element to document. */ 1508 hr = IXMLDOMDocument_createElement(domdoc, _bstr_("TestElement"), &root); 1509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1510 hr = IXMLDOMDocument_appendChild(domdoc, (IXMLDOMNode *)root, NULL); 1511 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1512 IXMLDOMElement_Release(root); 1513 1514 hr = IXMLDOMDocument_get_documentElement(domdoc, &root); 1515 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1516 ok(root != NULL, "Unexpected document root.\n"); 1517 IXMLDOMElement_Release(root); 1518 1519 /* startDocument clears root element and disables methods. */ 1520 hr = ISAXContentHandler_startDocument(content); 1521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1522 1523 hr = IXMLDOMDocument_get_documentElement(domdoc, &root); 1524 todo_wine 1525 ok(hr == S_FALSE, "Unexpected hr %#lx.\n", hr); 1526 1527 hr = IXMLDOMDocument_createElement(domdoc, _bstr_("TestElement"), &root); 1528 todo_wine 1529 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr); 1530 1531 /* startElement allows document root node to be accessed. */ 1532 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"BankAccount", 11, NULL); 1533 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1534 1535 hr = IXMLDOMDocument_get_documentElement(domdoc, &root); 1536 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1537 ok(root != NULL, "Unexpected document root.\n"); 1538 1539 hr = IXMLDOMElement_get_nodeName(root, &str); 1540 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1541 todo_wine 1542 ok(!lstrcmpW(L"BankAccount", str), "Unexpected name %s.\n", wine_dbgstr_w(str)); 1543 SysFreeString(str); 1544 1545 /* startElement immediately updates previous node. */ 1546 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"Number", 6, NULL); 1547 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1548 1549 hr = IXMLDOMElement_get_childNodes(root, &node_list); 1550 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1551 1552 hr = IXMLDOMNodeList_get_length(node_list, &list_length); 1553 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1554 todo_wine 1555 ok(list_length == 1, "list length %ld, expected 1\n", list_length); 1556 1557 hr = IXMLDOMNodeList_get_item(node_list, 0, &node); 1558 todo_wine 1559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1560 1561 hr = IXMLDOMNode_get_nodeName(node, &str); 1562todo_wine { 1563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1564 ok(!lstrcmpW(L"Number", str), "got %s\n", wine_dbgstr_w(str)); 1565} 1566 SysFreeString(str); 1567 1568 /* characters not immediately visible. */ 1569 hr = ISAXContentHandler_characters(content, L"12345", 5); 1570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1571 1572 hr = IXMLDOMNode_get_text(node, &str); 1573todo_wine { 1574 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1575 ok(!lstrcmpW(L"", str), "got %s\n", wine_dbgstr_w(str)); 1576} 1577 SysFreeString(str); 1578 1579 /* characters visible after endElement. */ 1580 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"Number", 6); 1581 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1582 1583 hr = IXMLDOMNode_get_text(node, &str); 1584todo_wine { 1585 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1586 ok(!lstrcmpW(L"12345", str), "got %s\n", wine_dbgstr_w(str)); 1587} 1588 SysFreeString(str); 1589 1590 IXMLDOMNode_Release(node); 1591 1592 /* second startElement updates the existing node list. */ 1593 1594 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, L"Name", 4, NULL); 1595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1596 1597 hr = ISAXContentHandler_characters(content, L"Captain Ahab", 12); 1598 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1599 1600 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"Name", 4); 1601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1602 1603 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, L"BankAccount", 11); 1604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1605 1606 hr = IXMLDOMNodeList_get_length(node_list, &list_length); 1607todo_wine { 1608 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1609 ok(2 == list_length, "list length %ld, expected 2\n", list_length); 1610} 1611 hr = IXMLDOMNodeList_get_item(node_list, 1, &node); 1612 todo_wine 1613 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1614 1615 hr = IXMLDOMNode_get_nodeName(node, &str); 1616todo_wine { 1617 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1618 ok(!lstrcmpW(L"Name", str), "got %s\n", wine_dbgstr_w(str)); 1619} 1620 SysFreeString(str); 1621 1622 hr = IXMLDOMNode_get_text(node, &str); 1623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1624todo_wine { 1625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1626 ok(!lstrcmpW(L"Captain Ahab", str), "got %s\n", wine_dbgstr_w(str)); 1627} 1628 SysFreeString(str); 1629 1630 IXMLDOMNode_Release(node); 1631 IXMLDOMNodeList_Release(node_list); 1632 IXMLDOMElement_Release(root); 1633 1634 /* endDocument makes document modifiable again. */ 1635 1636 hr = ISAXContentHandler_endDocument(content); 1637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1638 1639 hr = IXMLDOMDocument_createElement(domdoc, _bstr_("TestElement"), &root); 1640 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1641 IXMLDOMElement_Release(root); 1642 1643 /* finally check doc output */ 1644 hr = IXMLDOMDocument_get_xml(domdoc, &str); 1645todo_wine { 1646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1647 ok(!lstrcmpW( 1648 L"<BankAccount>" 1649 "<Number>12345</Number>" 1650 "<Name>Captain Ahab</Name>" 1651 "</BankAccount>\r\n", 1652 str), 1653 "got %s\n", wine_dbgstr_w(str)); 1654} 1655 SysFreeString(str); 1656 1657 IXMLDOMDocument_Release(domdoc); 1658 ISAXContentHandler_Release(content); 1659 IMXWriter_Release(writer); 1660 1661 free_bstrs(); 1662} 1663 1664static const char *encoding_names[] = { 1665 "iso-8859-1", 1666 "iso-8859-2", 1667 "iso-8859-3", 1668 "iso-8859-4", 1669 "iso-8859-5", 1670 "iso-8859-7", 1671 "iso-8859-9", 1672 "iso-8859-13", 1673 "iso-8859-15", 1674 NULL 1675}; 1676 1677static void test_mxwriter_encoding(void) 1678{ 1679 ISAXContentHandler *content; 1680 IMXWriter *writer; 1681 IStream *stream; 1682 const char *enc; 1683 VARIANT dest; 1684 HRESULT hr; 1685 HGLOBAL g; 1686 char *ptr; 1687 BSTR s; 1688 int i; 1689 1690 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1691 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1692 1693 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1694 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1695 1696 hr = IMXWriter_put_encoding(writer, _bstr_("UTF-8")); 1697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1698 1699 hr = ISAXContentHandler_startDocument(content); 1700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1701 1702 hr = ISAXContentHandler_endDocument(content); 1703 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1704 1705 /* The content is always re-encoded to UTF-16 when the output is 1706 * retrieved as a BSTR. 1707 */ 1708 V_VT(&dest) = VT_EMPTY; 1709 hr = IMXWriter_get_output(writer, &dest); 1710 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1711 ok(V_VT(&dest) == VT_BSTR, "Expected VT_BSTR, got %d\n", V_VT(&dest)); 1712 todo_wine 1713 ok(!lstrcmpW(L"<?xml version=\"1.0\" standalone=\"no\"?>\r\n", V_BSTR(&dest)), 1714 "got wrong content: %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1715 VariantClear(&dest); 1716 1717 /* switch encoding when something is written already */ 1718 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1719 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1720 1721 V_VT(&dest) = VT_UNKNOWN; 1722 V_UNKNOWN(&dest) = (IUnknown*)stream; 1723 hr = IMXWriter_put_output(writer, dest); 1724 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1725 1726 hr = IMXWriter_put_encoding(writer, _bstr_("UTF-8")); 1727 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1728 1729 /* write empty element */ 1730 hr = ISAXContentHandler_startElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1, NULL); 1731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1732 1733 hr = ISAXContentHandler_endElement(content, _bstr_(""), 0, _bstr_(""), 0, _bstr_("a"), 1); 1734 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1735 1736 /* switch */ 1737 hr = IMXWriter_put_encoding(writer, _bstr_("UTF-16")); 1738 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1739 1740 hr = IMXWriter_flush(writer); 1741 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1742 1743 hr = GetHGlobalFromStream(stream, &g); 1744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1745 1746 ptr = GlobalLock(g); 1747 ok(!strncmp(ptr, "<a/>", 4), "got %c%c%c%c\n", ptr[0],ptr[1],ptr[2],ptr[3]); 1748 GlobalUnlock(g); 1749 1750 /* so output is unaffected, encoding name is stored however */ 1751 hr = IMXWriter_get_encoding(writer, &s); 1752 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1753 ok(!lstrcmpW(s, L"UTF-16"), "got %s\n", wine_dbgstr_w(s)); 1754 SysFreeString(s); 1755 1756 IStream_Release(stream); 1757 1758 i = 0; 1759 enc = encoding_names[i]; 1760 while (enc) 1761 { 1762 char expectedA[200]; 1763 1764 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1766 1767 V_VT(&dest) = VT_UNKNOWN; 1768 V_UNKNOWN(&dest) = (IUnknown*)stream; 1769 hr = IMXWriter_put_output(writer, dest); 1770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1771 1772 hr = IMXWriter_put_encoding(writer, _bstr_(enc)); 1773 ok(hr == S_OK || broken(hr != S_OK) /* old win versions do not support certain encodings */, 1774 "%s: encoding not accepted\n", enc); 1775 if (hr != S_OK) 1776 { 1777 enc = encoding_names[++i]; 1778 IStream_Release(stream); 1779 continue; 1780 } 1781 1782 hr = ISAXContentHandler_startDocument(content); 1783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1784 1785 hr = ISAXContentHandler_endDocument(content); 1786 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1787 1788 hr = IMXWriter_flush(writer); 1789 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1790 1791 /* prepare expected string */ 1792 *expectedA = 0; 1793 strcat(expectedA, "<?xml version=\"1.0\" encoding=\""); 1794 strcat(expectedA, enc); 1795 strcat(expectedA, "\" standalone=\"no\"?>\r\n"); 1796 1797 hr = GetHGlobalFromStream(stream, &g); 1798 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1799 1800 ptr = GlobalLock(g); 1801 ok(!strncmp(ptr, expectedA, strlen(expectedA)), "%s: got %s, expected %.50s\n", enc, ptr, expectedA); 1802 GlobalUnlock(g); 1803 1804 V_VT(&dest) = VT_EMPTY; 1805 hr = IMXWriter_put_output(writer, dest); 1806 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1807 1808 IStream_Release(stream); 1809 1810 enc = encoding_names[++i]; 1811 } 1812 1813 ISAXContentHandler_Release(content); 1814 IMXWriter_Release(writer); 1815 1816 free_bstrs(); 1817} 1818 1819static void test_obj_dispex(IUnknown *obj) 1820{ 1821 DISPID dispid = DISPID_SAX_XMLREADER_GETFEATURE; 1822 IDispatchEx *dispex; 1823 IUnknown *unk; 1824 DWORD props; 1825 UINT ticnt; 1826 HRESULT hr; 1827 BSTR name; 1828 DISPID did; 1829 1830 hr = IUnknown_QueryInterface(obj, &IID_IDispatchEx, (void**)&dispex); 1831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1832 if (FAILED(hr)) return; 1833 1834 ticnt = 0; 1835 hr = IDispatchEx_GetTypeInfoCount(dispex, &ticnt); 1836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1837 ok(ticnt == 1, "ticnt=%u\n", ticnt); 1838 1839 name = SysAllocString(L"*"); 1840 hr = IDispatchEx_DeleteMemberByName(dispex, name, fdexNameCaseSensitive); 1841 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1842 SysFreeString(name); 1843 1844 hr = IDispatchEx_DeleteMemberByDispID(dispex, dispid); 1845 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1846 1847 props = 0; 1848 hr = IDispatchEx_GetMemberProperties(dispex, dispid, grfdexPropCanAll, &props); 1849 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1850 ok(props == 0, "Unexpected value %ld.\n", props); 1851 1852 hr = IDispatchEx_GetMemberName(dispex, dispid, &name); 1853 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1854 if (SUCCEEDED(hr)) SysFreeString(name); 1855 1856 hr = IDispatchEx_GetNextDispID(dispex, fdexEnumDefault, DISPID_SAX_XMLREADER_GETFEATURE, &dispid); 1857 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1858 1859 unk = (IUnknown*)0xdeadbeef; 1860 hr = IDispatchEx_GetNameSpaceParent(dispex, &unk); 1861 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr); 1862 ok(unk == (IUnknown*)0xdeadbeef, "got %p\n", unk); 1863 1864 name = SysAllocString(L"testprop"); 1865 hr = IDispatchEx_GetDispID(dispex, name, fdexNameEnsure, &did); 1866 ok(hr == DISP_E_UNKNOWNNAME, "Unexpected hr %#lx.\n", hr); 1867 SysFreeString(name); 1868 1869 IDispatchEx_Release(dispex); 1870} 1871 1872static void test_mxwriter_dispex(void) 1873{ 1874 IDispatchEx *dispex; 1875 IMXWriter *writer; 1876 IUnknown *unk; 1877 HRESULT hr; 1878 1879 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1880 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1881 1882 hr = IMXWriter_QueryInterface(writer, &IID_IDispatchEx, (void**)&dispex); 1883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1884 hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk); 1885 test_obj_dispex(unk); 1886 IUnknown_Release(unk); 1887 IDispatchEx_Release(dispex); 1888 IMXWriter_Release(writer); 1889 1890 if (is_class_supported(&CLSID_MXXMLWriter60)) 1891 { 1892 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&unk); 1893 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1894 test_obj_dispex(unk); 1895 IUnknown_Release(unk); 1896 } 1897} 1898 1899static void test_mxwriter_comment(void) 1900{ 1901 IVBSAXLexicalHandler *vblexical; 1902 ISAXContentHandler *content; 1903 ISAXLexicalHandler *lexical; 1904 IMXWriter *writer; 1905 VARIANT dest; 1906 HRESULT hr; 1907 1908 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1910 1911 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1912 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1913 1914 hr = IMXWriter_QueryInterface(writer, &IID_ISAXLexicalHandler, (void**)&lexical); 1915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1916 1917 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXLexicalHandler, (void**)&vblexical); 1918 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1919 1920 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1921 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1922 1923 hr = ISAXContentHandler_startDocument(content); 1924 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1925 1926 hr = ISAXLexicalHandler_comment(lexical, NULL, 0); 1927 todo_wine 1928 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1929 1930 hr = IVBSAXLexicalHandler_comment(vblexical, NULL); 1931 todo_wine 1932 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 1933 1934 hr = ISAXLexicalHandler_comment(lexical, L"comment", 0); 1935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1936 1937 V_VT(&dest) = VT_EMPTY; 1938 hr = IMXWriter_get_output(writer, &dest); 1939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1940 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1941 todo_wine 1942 ok(!lstrcmpW(L"<!---->\r\n<!---->\r\n", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1943 VariantClear(&dest); 1944 1945 hr = ISAXLexicalHandler_comment(lexical, L"comment", 7); 1946 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1947 1948 V_VT(&dest) = VT_EMPTY; 1949 hr = IMXWriter_get_output(writer, &dest); 1950 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1951 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1952 todo_wine 1953 ok(!lstrcmpW(L"<!---->\r\n<!---->\r\n<!--comment-->\r\n", V_BSTR(&dest)), "Unexpected content %s.\n", 1954 wine_dbgstr_w(V_BSTR(&dest))); 1955 VariantClear(&dest); 1956 1957 ISAXContentHandler_Release(content); 1958 ISAXLexicalHandler_Release(lexical); 1959 IVBSAXLexicalHandler_Release(vblexical); 1960 IMXWriter_Release(writer); 1961 free_bstrs(); 1962} 1963 1964static void test_mxwriter_cdata(void) 1965{ 1966 IVBSAXLexicalHandler *vblexical; 1967 ISAXContentHandler *content; 1968 ISAXLexicalHandler *lexical; 1969 IMXWriter *writer; 1970 VARIANT dest; 1971 HRESULT hr; 1972 1973 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 1974 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1975 1976 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 1977 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1978 1979 hr = IMXWriter_QueryInterface(writer, &IID_ISAXLexicalHandler, (void**)&lexical); 1980 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1981 1982 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXLexicalHandler, (void**)&vblexical); 1983 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1984 1985 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 1986 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1987 1988 hr = ISAXContentHandler_startDocument(content); 1989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1990 1991 hr = ISAXLexicalHandler_startCDATA(lexical); 1992 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1993 1994 V_VT(&dest) = VT_EMPTY; 1995 hr = IMXWriter_get_output(writer, &dest); 1996 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 1997 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 1998 ok(!lstrcmpW(L"<![CDATA[", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 1999 VariantClear(&dest); 2000 2001 hr = IVBSAXLexicalHandler_startCDATA(vblexical); 2002 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2003 2004 /* all these are escaped for text nodes */ 2005 hr = ISAXContentHandler_characters(content, _bstr_("< > & \""), 7); 2006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2007 2008 hr = ISAXLexicalHandler_endCDATA(lexical); 2009 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2010 2011 V_VT(&dest) = VT_EMPTY; 2012 hr = IMXWriter_get_output(writer, &dest); 2013 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2014 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2015 ok(!lstrcmpW(L"<![CDATA[<![CDATA[< > & \"]]>", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2016 VariantClear(&dest); 2017 2018 ISAXContentHandler_Release(content); 2019 ISAXLexicalHandler_Release(lexical); 2020 IVBSAXLexicalHandler_Release(vblexical); 2021 IMXWriter_Release(writer); 2022 free_bstrs(); 2023} 2024 2025static void test_mxwriter_pi(void) 2026{ 2027 ISAXContentHandler *content; 2028 IMXWriter *writer; 2029 VARIANT dest; 2030 HRESULT hr; 2031 2032 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 2033 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2034 2035 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 2036 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2037 2038 hr = ISAXContentHandler_processingInstruction(content, NULL, 0, NULL, 0); 2039 todo_wine 2040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2041 2042 hr = ISAXContentHandler_processingInstruction(content, L"target", 0, NULL, 0); 2043 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2044 2045 hr = ISAXContentHandler_processingInstruction(content, L"target", 6, NULL, 0); 2046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2047 2048 V_VT(&dest) = VT_EMPTY; 2049 hr = IMXWriter_get_output(writer, &dest); 2050 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2051 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2052 todo_wine 2053 ok(!lstrcmpW(L"<?\?>\r\n<?\?>\r\n<?target?>\r\n", V_BSTR(&dest)), "Unexpected content %s.\n", wine_dbgstr_w(V_BSTR(&dest))); 2054 VariantClear(&dest); 2055 2056 hr = ISAXContentHandler_processingInstruction(content, L"target", 4, L"data", 4); 2057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2058 2059 V_VT(&dest) = VT_EMPTY; 2060 hr = IMXWriter_get_output(writer, &dest); 2061 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2062 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2063 todo_wine 2064 ok(!lstrcmpW(L"<?\?>\r\n<?\?>\r\n<?target?>\r\n<?targ data?>\r\n", V_BSTR(&dest)), "Unexpected content %s.\n", wine_dbgstr_w(V_BSTR(&dest))); 2065 VariantClear(&dest); 2066 2067 V_VT(&dest) = VT_EMPTY; 2068 hr = IMXWriter_put_output(writer, dest); 2069 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2070 2071 hr = ISAXContentHandler_processingInstruction(content, L"target", 6, L"data", 0); 2072 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2073 2074 V_VT(&dest) = VT_EMPTY; 2075 hr = IMXWriter_get_output(writer, &dest); 2076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2077 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2078 ok(!lstrcmpW(L"<?target?>\r\n", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2079 VariantClear(&dest); 2080 2081 2082 ISAXContentHandler_Release(content); 2083 IMXWriter_Release(writer); 2084} 2085 2086static void test_mxwriter_ignorablespaces(void) 2087{ 2088 ISAXContentHandler *content; 2089 IMXWriter *writer; 2090 VARIANT dest; 2091 HRESULT hr; 2092 2093 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 2094 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2095 2096 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 2097 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2098 2099 hr = ISAXContentHandler_ignorableWhitespace(content, NULL, 0); 2100 todo_wine 2101 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2102 2103 hr = ISAXContentHandler_ignorableWhitespace(content, L"data", 0); 2104 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2105 2106 hr = ISAXContentHandler_ignorableWhitespace(content, L"data", 4); 2107 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2108 2109 hr = ISAXContentHandler_ignorableWhitespace(content, L"data", 1); 2110 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2111 2112 V_VT(&dest) = VT_EMPTY; 2113 hr = IMXWriter_get_output(writer, &dest); 2114 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2115 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2116 ok(!lstrcmpW(L"datad", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2117 VariantClear(&dest); 2118 2119 ISAXContentHandler_Release(content); 2120 IMXWriter_Release(writer); 2121} 2122 2123static void test_mxwriter_dtd(void) 2124{ 2125 IVBSAXLexicalHandler *vblexical; 2126 ISAXContentHandler *content; 2127 ISAXLexicalHandler *lexical; 2128 IVBSAXDeclHandler *vbdecl; 2129 ISAXDeclHandler *decl; 2130 ISAXDTDHandler *dtd; 2131 IMXWriter *writer; 2132 VARIANT dest; 2133 HRESULT hr; 2134 2135 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 2136 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2137 2138 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 2139 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2140 2141 hr = IMXWriter_QueryInterface(writer, &IID_ISAXLexicalHandler, (void**)&lexical); 2142 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2143 2144 hr = IMXWriter_QueryInterface(writer, &IID_ISAXDeclHandler, (void**)&decl); 2145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2146 2147 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXDeclHandler, (void**)&vbdecl); 2148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2149 2150 hr = IMXWriter_QueryInterface(writer, &IID_IVBSAXLexicalHandler, (void**)&vblexical); 2151 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2152 2153 hr = IMXWriter_put_omitXMLDeclaration(writer, VARIANT_TRUE); 2154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2155 2156 hr = ISAXContentHandler_startDocument(content); 2157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2158 2159 hr = ISAXLexicalHandler_startDTD(lexical, NULL, 0, NULL, 0, NULL, 0); 2160 todo_wine 2161 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2162 2163 hr = IVBSAXLexicalHandler_startDTD(vblexical, NULL, NULL, NULL); 2164 todo_wine 2165 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2166 2167 hr = ISAXLexicalHandler_startDTD(lexical, NULL, 0, L"pub", 3, NULL, 0); 2168 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2169 2170 hr = ISAXLexicalHandler_startDTD(lexical, NULL, 0, NULL, 0, L"sys", 3); 2171 todo_wine 2172 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2173 2174 hr = ISAXLexicalHandler_startDTD(lexical, NULL, 0, L"pub", 3, L"sys", 3); 2175 todo_wine 2176 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2177 2178 hr = ISAXLexicalHandler_startDTD(lexical, L"name", 4, NULL, 0, NULL, 0); 2179 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2180 2181 V_VT(&dest) = VT_EMPTY; 2182 hr = IMXWriter_get_output(writer, &dest); 2183 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2184 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2185 todo_wine 2186 ok(!lstrcmpW(L"<!DOCTYPE [\r\n<!DOCTYPE PUBLIC \"pub\"<!DOCTYPE SYSTEM \"sys\" [\r\n" 2187 "<!DOCTYPE PUBLIC \"pub\" \"sys\" [\r\n<!DOCTYPE name [\r\n", V_BSTR(&dest)), "Unexpected content %s.\n", wine_dbgstr_w(V_BSTR(&dest))); 2188 VariantClear(&dest); 2189 2190 /* system id is required if public is present */ 2191 hr = ISAXLexicalHandler_startDTD(lexical, L"name", 4, L"pub", 3, NULL, 0); 2192 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2193 2194 hr = ISAXLexicalHandler_startDTD(lexical, L"name", 4, L"pub", 3, L"sys", 3); 2195 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2196 2197 V_VT(&dest) = VT_EMPTY; 2198 hr = IMXWriter_get_output(writer, &dest); 2199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2200 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2201 todo_wine 2202 ok(!lstrcmpW(L"<!DOCTYPE [\r\n<!DOCTYPE PUBLIC \"pub\"<!DOCTYPE SYSTEM \"sys\" [\r\n" 2203 "<!DOCTYPE PUBLIC \"pub\" \"sys\" [\r\n<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\"<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n", 2204 V_BSTR(&dest)), "Unexpected content %s.\n", debugstr_w(V_BSTR(&dest))); 2205 VariantClear(&dest); 2206 2207 hr = ISAXLexicalHandler_endDTD(lexical); 2208 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2209 2210 hr = IVBSAXLexicalHandler_endDTD(vblexical); 2211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2212 2213 V_VT(&dest) = VT_EMPTY; 2214 hr = IMXWriter_get_output(writer, &dest); 2215 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2216 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2217 todo_wine 2218 ok(!lstrcmpW(L"<!DOCTYPE [\r\n<!DOCTYPE PUBLIC \"pub\"<!DOCTYPE SYSTEM \"sys\" [\r\n" 2219 "<!DOCTYPE PUBLIC \"pub\" \"sys\" [\r\n<!DOCTYPE name [\r\n<!DOCTYPE name PUBLIC \"pub\"<!DOCTYPE name PUBLIC \"pub\" \"sys\" [\r\n]>\r\n]>\r\n", 2220 V_BSTR(&dest)), "Unexpected content %s.\n", debugstr_w(V_BSTR(&dest))); 2221 VariantClear(&dest); 2222 2223 /* element declaration */ 2224 V_VT(&dest) = VT_EMPTY; 2225 hr = IMXWriter_put_output(writer, dest); 2226 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2227 2228 hr = ISAXDeclHandler_elementDecl(decl, NULL, 0, NULL, 0); 2229 todo_wine 2230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2231 2232 hr = IVBSAXDeclHandler_elementDecl(vbdecl, NULL, NULL); 2233 todo_wine 2234 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2235 2236 hr = ISAXDeclHandler_elementDecl(decl, L"name", 4, NULL, 0); 2237 todo_wine 2238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2239 2240 hr = ISAXDeclHandler_elementDecl(decl, L"name", 4, L"content", 7); 2241 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2242 2243 V_VT(&dest) = VT_EMPTY; 2244 hr = IMXWriter_get_output(writer, &dest); 2245 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2246 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2247 todo_wine 2248 ok(!lstrcmpW(L"<!ELEMENT >\r\n<!ELEMENT name >\r\n<!ELEMENT name content>\r\n", 2249 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2250 VariantClear(&dest); 2251 2252 V_VT(&dest) = VT_EMPTY; 2253 hr = IMXWriter_put_output(writer, dest); 2254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2255 2256 hr = ISAXDeclHandler_elementDecl(decl, L"name", 4, L"content", 0); 2257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2258 2259 V_VT(&dest) = VT_EMPTY; 2260 hr = IMXWriter_get_output(writer, &dest); 2261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2262 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2263 ok(!lstrcmpW(L"<!ELEMENT name >\r\n", 2264 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2265 VariantClear(&dest); 2266 2267 /* attribute declaration */ 2268 V_VT(&dest) = VT_EMPTY; 2269 hr = IMXWriter_put_output(writer, dest); 2270 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2271 2272 hr = ISAXDeclHandler_attributeDecl(decl, _bstr_("element"), strlen("element"), 2273 _bstr_("attribute"), strlen("attribute"), _bstr_("CDATA"), strlen("CDATA"), 2274 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value"), strlen("value")); 2275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2276 2277 V_VT(&dest) = VT_EMPTY; 2278 hr = IMXWriter_get_output(writer, &dest); 2279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2280 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2281 todo_wine 2282 ok(!lstrcmpW(L"<!ATTLIST element attribute CDATA #REQUIRED>\r\n", 2283 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2284 VariantClear(&dest); 2285 2286 hr = ISAXDeclHandler_attributeDecl(decl, _bstr_("element"), strlen("element"), 2287 _bstr_("attribute2"), strlen("attribute2"), _bstr_("CDATA"), strlen("CDATA"), 2288 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value2"), strlen("value2")); 2289 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2290 2291 hr = ISAXDeclHandler_attributeDecl(decl, _bstr_("element2"), strlen("element2"), 2292 _bstr_("attribute3"), strlen("attribute3"), _bstr_("CDATA"), strlen("CDATA"), 2293 _bstr_("#REQUIRED"), strlen("#REQUIRED"), _bstr_("value3"), strlen("value3")); 2294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2295 2296 V_VT(&dest) = VT_EMPTY; 2297 hr = IMXWriter_get_output(writer, &dest); 2298 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2299 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2300 todo_wine 2301 ok(!lstrcmpW(L"<!ATTLIST element attribute CDATA #REQUIRED>\r\n" 2302 "<!ATTLIST element attribute2 CDATA #REQUIRED>\r\n<!ATTLIST element2 attribute3 CDATA #REQUIRED>\r\n", 2303 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2304 VariantClear(&dest); 2305 2306 /* internal entities */ 2307 V_VT(&dest) = VT_EMPTY; 2308 hr = IMXWriter_put_output(writer, dest); 2309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2310 2311 hr = ISAXDeclHandler_internalEntityDecl(decl, NULL, 0, NULL, 0); 2312 todo_wine 2313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2314 2315 hr = IVBSAXDeclHandler_internalEntityDecl(vbdecl, NULL, NULL); 2316 todo_wine 2317 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2318 2319 hr = ISAXDeclHandler_internalEntityDecl(decl, _bstr_("name"), -1, NULL, 0); 2320 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2321 2322 hr = ISAXDeclHandler_internalEntityDecl(decl, _bstr_("name"), strlen("name"), _bstr_("value"), strlen("value")); 2323 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2324 2325 V_VT(&dest) = VT_EMPTY; 2326 hr = IMXWriter_get_output(writer, &dest); 2327 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2328 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2329 todo_wine 2330 ok(!lstrcmpW(L"<!ENTITY \"\">\r\n<!ENTITY name \"value\">\r\n", V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2331 VariantClear(&dest); 2332 2333 /* external entities */ 2334 V_VT(&dest) = VT_EMPTY; 2335 hr = IMXWriter_put_output(writer, dest); 2336 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2337 2338 hr = ISAXDeclHandler_externalEntityDecl(decl, NULL, 0, NULL, 0, NULL, 0); 2339 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2340 2341 hr = IVBSAXDeclHandler_externalEntityDecl(vbdecl, NULL, NULL, NULL); 2342 todo_wine 2343 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2344 2345 hr = ISAXDeclHandler_externalEntityDecl(decl, _bstr_("name"), 0, NULL, 0, NULL, 0); 2346 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2347 2348 hr = ISAXDeclHandler_externalEntityDecl(decl, _bstr_("name"), -1, NULL, 0, NULL, 0); 2349 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2350 2351 hr = ISAXDeclHandler_externalEntityDecl(decl, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), 2352 _bstr_("sysid"), strlen("sysid")); 2353 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2354 2355 hr = ISAXDeclHandler_externalEntityDecl(decl, _bstr_("name"), strlen("name"), NULL, 0, _bstr_("sysid"), strlen("sysid")); 2356 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2357 2358 hr = ISAXDeclHandler_externalEntityDecl(decl, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), 2359 NULL, 0); 2360 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2361 2362 V_VT(&dest) = VT_EMPTY; 2363 hr = IMXWriter_get_output(writer, &dest); 2364 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2365 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2366 todo_wine 2367 ok(!lstrcmpW(L"<!ENTITY <!ENTITY <!ENTITY name PUBLIC \"pubid\" \"sysid\">\r\n" 2368 "<!ENTITY name SYSTEM \"sysid\">\r\n<!ENTITY name PUBLIC \"pubid\"", 2369 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2370 2371 VariantClear(&dest); 2372 2373 /* notation declaration */ 2374 hr = IMXWriter_QueryInterface(writer, &IID_ISAXDTDHandler, (void**)&dtd); 2375 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2376 2377 V_VT(&dest) = VT_EMPTY; 2378 hr = IMXWriter_put_output(writer, dest); 2379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2380 2381 hr = ISAXDTDHandler_notationDecl(dtd, NULL, 0, NULL, 0, NULL, 0); 2382 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2383 2384 hr = ISAXDTDHandler_notationDecl(dtd, _bstr_("name"), strlen("name"), NULL, 0, NULL, 0); 2385 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2386 2387 hr = ISAXDTDHandler_notationDecl(dtd, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), NULL, 0); 2388 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2389 2390 hr = ISAXDTDHandler_notationDecl(dtd, _bstr_("name"), strlen("name"), _bstr_("pubid"), strlen("pubid"), _bstr_("sysid"), strlen("sysid")); 2391 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2392 2393 hr = ISAXDTDHandler_notationDecl(dtd, _bstr_("name"), strlen("name"), NULL, 0, _bstr_("sysid"), strlen("sysid")); 2394 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2395 2396 hr = IMXWriter_get_output(writer, &dest); 2397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2398 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2399 todo_wine 2400 ok(!lstrcmpW(L"<!NOTATION <!NOTATION name<!NOTATION name PUBLIC \"pubid\">\r\n" 2401 "<!NOTATION name PUBLIC \"pubid\" \"sysid\">\r\n" 2402 "<!NOTATION name SYSTEM \"sysid\">\r\n", 2403 V_BSTR(&dest)), "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2404 2405 VariantClear(&dest); 2406 2407 ISAXDTDHandler_Release(dtd); 2408 2409 ISAXContentHandler_Release(content); 2410 ISAXLexicalHandler_Release(lexical); 2411 IVBSAXLexicalHandler_Release(vblexical); 2412 IVBSAXDeclHandler_Release(vbdecl); 2413 ISAXDeclHandler_Release(decl); 2414 IMXWriter_Release(writer); 2415 free_bstrs(); 2416} 2417 2418typedef struct 2419{ 2420 const char *uri; 2421 const char *local; 2422 const char *qname; 2423 const char *type; 2424 const char *value; 2425 HRESULT hr; 2426} addattribute_test_t; 2427 2428static const addattribute_test_t addattribute_data[] = 2429{ 2430 { NULL, NULL, "ns:qname", NULL, "value", S_OK }, 2431 { NULL, "qname", "ns:qname", NULL, "value", S_OK }, 2432 { "uri", "qname", "ns:qname", NULL, "value", S_OK }, 2433 { "uri", "qname", "ns:qname", "type", "value", S_OK }, 2434}; 2435 2436static void test_mxattr_addAttribute(void) 2437{ 2438 int i = 0; 2439 2440 for (i = 0; i < ARRAY_SIZE(addattribute_data); ++i) 2441 { 2442 const addattribute_test_t *table = &addattribute_data[i]; 2443 ISAXAttributes *saxattr; 2444 IMXAttributes *mxattr; 2445 const WCHAR *value; 2446 int len, index; 2447 HRESULT hr; 2448 2449 hr = CoCreateInstance(&CLSID_SAXAttributes60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXAttributes, (void **)&mxattr); 2450 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2451 2452 hr = IMXAttributes_QueryInterface(mxattr, &IID_ISAXAttributes, (void**)&saxattr); 2453 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2454 2455 len = -1; 2456 hr = ISAXAttributes_getLength(saxattr, &len); 2457 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2458 ok(len == 0, "got %d\n", len); 2459 2460 hr = ISAXAttributes_getValue(saxattr, 0, &value, &len); 2461 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2462 2463 hr = ISAXAttributes_getValue(saxattr, 0, NULL, &len); 2464 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2465 2466 hr = ISAXAttributes_getValue(saxattr, 0, &value, NULL); 2467 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2468 2469 hr = ISAXAttributes_getValue(saxattr, 0, NULL, NULL); 2470 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2471 2472 hr = ISAXAttributes_getType(saxattr, 0, &value, &len); 2473 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2474 2475 hr = ISAXAttributes_getType(saxattr, 0, NULL, &len); 2476 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2477 2478 hr = ISAXAttributes_getType(saxattr, 0, &value, NULL); 2479 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2480 2481 hr = ISAXAttributes_getType(saxattr, 0, NULL, NULL); 2482 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2483 2484 hr = IMXAttributes_addAttribute(mxattr, _bstr_(table->uri), _bstr_(table->local), 2485 _bstr_(table->qname), _bstr_(table->type), _bstr_(table->value)); 2486 ok(hr == table->hr, "%d: got %#lx, expected %#lx.\n", i, hr, table->hr); 2487 2488 if (hr == S_OK) 2489 { 2490 /* Crashes. */ 2491 if (0) 2492 { 2493 hr = ISAXAttributes_getValue(saxattr, 0, NULL, &len); 2494 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2495 2496 hr = ISAXAttributes_getValue(saxattr, 0, &value, NULL); 2497 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2498 2499 hr = ISAXAttributes_getValue(saxattr, 0, NULL, NULL); 2500 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2501 2502 hr = ISAXAttributes_getType(saxattr, 0, NULL, &len); 2503 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2504 2505 hr = ISAXAttributes_getType(saxattr, 0, &value, NULL); 2506 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2507 2508 hr = ISAXAttributes_getType(saxattr, 0, NULL, NULL); 2509 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2510 } 2511 2512 len = -1; 2513 hr = ISAXAttributes_getValue(saxattr, 0, &value, &len); 2514 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2515 ok(!lstrcmpW(_bstr_(table->value), value), "%d: got %s, expected %s\n", i, wine_dbgstr_w(value), 2516 table->value); 2517 ok(lstrlenW(value) == len, "%d: got wrong value length %d\n", i, len); 2518 2519 len = -1; 2520 value = (void*)0xdeadbeef; 2521 hr = ISAXAttributes_getType(saxattr, 0, &value, &len); 2522 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2523 2524 if (table->type) 2525 { 2526 ok(!lstrcmpW(_bstr_(table->type), value), "%d: got %s, expected %s\n", i, wine_dbgstr_w(value), 2527 table->type); 2528 ok(lstrlenW(value) == len, "%d: got wrong type value length %d\n", i, len); 2529 } 2530 else 2531 { 2532 ok(*value == 0, "%d: got type value %s\n", i, wine_dbgstr_w(value)); 2533 ok(len == 0, "%d: got wrong type value length %d\n", i, len); 2534 } 2535 2536 hr = ISAXAttributes_getIndexFromQName(saxattr, NULL, 0, NULL); 2537 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2538 2539 hr = ISAXAttributes_getIndexFromQName(saxattr, NULL, 0, &index); 2540 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2541 2542 index = -1; 2543 hr = ISAXAttributes_getIndexFromQName(saxattr, _bstr_("nonexistent"), 11, &index); 2544 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2545 ok(index == -1, "%d: got wrong index %d\n", i, index); 2546 2547 index = -1; 2548 hr = ISAXAttributes_getIndexFromQName(saxattr, _bstr_(table->qname), 0, &index); 2549 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2550 ok(index == -1, "%d: got wrong index %d\n", i, index); 2551 2552 index = -1; 2553 hr = ISAXAttributes_getIndexFromQName(saxattr, _bstr_(table->qname), strlen(table->qname), &index); 2554 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2555 ok(index == 0, "%d: got wrong index %d\n", i, index); 2556 2557 index = -1; 2558 hr = ISAXAttributes_getIndexFromQName(saxattr, _bstr_(table->qname), strlen(table->qname)-1, &index); 2559 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2560 ok(index == -1, "%d: got wrong index %d\n", i, index); 2561 2562 hr = ISAXAttributes_getValueFromQName(saxattr, NULL, 0, NULL, NULL); 2563 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2564 2565 hr = ISAXAttributes_getValueFromQName(saxattr, _bstr_(table->qname), 0, NULL, NULL); 2566 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2567 2568 hr = ISAXAttributes_getValueFromQName(saxattr, _bstr_(table->qname), 0, &value, NULL); 2569 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2570 2571 hr = ISAXAttributes_getValueFromName(saxattr, NULL, 0, NULL, 0, NULL, NULL); 2572 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2573 2574 hr = ISAXAttributes_getValueFromName(saxattr, _bstr_(table->uri), 0, NULL, 0, NULL, NULL); 2575 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2576 2577 hr = ISAXAttributes_getValueFromName(saxattr, _bstr_(table->uri), 0, NULL, 0, &value, NULL); 2578 ok(hr == E_POINTER /* win8 */ || hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2579 2580 hr = ISAXAttributes_getValueFromQName(saxattr, _bstr_(table->qname), strlen(table->qname), &value, &len); 2581 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2582 ok(!lstrcmpW(_bstr_(table->value), value), "%d: got %s, expected %s\n", i, wine_dbgstr_w(value), 2583 table->value); 2584 ok(lstrlenW(value) == len, "%d: got wrong value length %d\n", i, len); 2585 2586 if (table->uri) { 2587 hr = ISAXAttributes_getValueFromName(saxattr, _bstr_(table->uri), strlen(table->uri), 2588 _bstr_(table->local), strlen(table->local), &value, &len); 2589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2590 ok(!lstrcmpW(_bstr_(table->value), value), "%d: got %s, expected %s\n", i, wine_dbgstr_w(value), 2591 table->value); 2592 ok(lstrlenW(value) == len, "%d: got wrong value length %d\n", i, len); 2593 } 2594 } 2595 2596 len = -1; 2597 hr = ISAXAttributes_getLength(saxattr, &len); 2598 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2599 if (table->hr == S_OK) 2600 ok(len == 1, "%d: got %d length, expected 1\n", i, len); 2601 else 2602 ok(len == 0, "%d: got %d length, expected 0\n", i, len); 2603 2604 ISAXAttributes_Release(saxattr); 2605 IMXAttributes_Release(mxattr); 2606 } 2607 2608 free_bstrs(); 2609} 2610 2611static void test_mxattr_clear(void) 2612{ 2613 ISAXAttributes *saxattr; 2614 IMXAttributes *mxattr; 2615 const WCHAR *ptr; 2616 HRESULT hr; 2617 int len; 2618 2619 hr = CoCreateInstance(&CLSID_SAXAttributes60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXAttributes, (void **)&mxattr); 2620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2621 2622 hr = IMXAttributes_QueryInterface(mxattr, &IID_ISAXAttributes, (void**)&saxattr); 2623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2624 2625 hr = ISAXAttributes_getQName(saxattr, 0, NULL, NULL); 2626 todo_wine 2627 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2628 2629 hr = ISAXAttributes_getQName(saxattr, 0, &ptr, &len); 2630 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2631 2632 hr = IMXAttributes_clear(mxattr); 2633 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2634 2635 hr = IMXAttributes_addAttribute(mxattr, _bstr_("uri"), _bstr_("local"), 2636 _bstr_("qname"), _bstr_("type"), _bstr_("value")); 2637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2638 2639 len = -1; 2640 hr = ISAXAttributes_getLength(saxattr, &len); 2641 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2642 ok(len == 1, "got %d\n", len); 2643 2644 len = -1; 2645 hr = ISAXAttributes_getQName(saxattr, 0, NULL, &len); 2646 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2647 ok(len == -1, "got %d\n", len); 2648 2649 ptr = (void*)0xdeadbeef; 2650 hr = ISAXAttributes_getQName(saxattr, 0, &ptr, NULL); 2651 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); 2652 todo_wine 2653 ok(!ptr, "Unexpected pointer %p.\n", ptr); 2654 2655 len = 0; 2656 hr = ISAXAttributes_getQName(saxattr, 0, &ptr, &len); 2657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2658 ok(len == 5, "got %d\n", len); 2659 ok(!lstrcmpW(ptr, L"qname"), "got %s\n", wine_dbgstr_w(ptr)); 2660 2661 hr = IMXAttributes_clear(mxattr); 2662 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2663 2664 len = -1; 2665 hr = ISAXAttributes_getLength(saxattr, &len); 2666 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2667 ok(len == 0, "got %d\n", len); 2668 2669 len = -1; 2670 ptr = (void*)0xdeadbeef; 2671 hr = ISAXAttributes_getQName(saxattr, 0, &ptr, &len); 2672 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2673 todo_wine 2674 ok(!len, "Unexpected length %d.\n", len); 2675 todo_wine 2676 ok(!ptr, "Unexpected pointer %p.\n", ptr); 2677 2678 IMXAttributes_Release(mxattr); 2679 ISAXAttributes_Release(saxattr); 2680 free_bstrs(); 2681} 2682 2683static void test_mxattr_dispex(void) 2684{ 2685 IMXAttributes *mxattr; 2686 IDispatchEx *dispex; 2687 IUnknown *unk; 2688 HRESULT hr; 2689 2690 hr = CoCreateInstance(&CLSID_SAXAttributes60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXAttributes, (void **)&mxattr); 2691 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2692 2693 hr = IMXAttributes_QueryInterface(mxattr, &IID_IDispatchEx, (void**)&dispex); 2694 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2695 hr = IDispatchEx_QueryInterface(dispex, &IID_IUnknown, (void**)&unk); 2696 test_obj_dispex(unk); 2697 IUnknown_Release(unk); 2698 IDispatchEx_Release(dispex); 2699 2700 IMXAttributes_Release(mxattr); 2701} 2702 2703static void test_mxattr_qi(void) 2704{ 2705 IMXAttributes *mxattr; 2706 HRESULT hr; 2707 2708 hr = CoCreateInstance(&CLSID_SAXAttributes60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXAttributes, (void **)&mxattr); 2709 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2710 2711 check_interface(mxattr, &IID_IMXAttributes, TRUE); 2712 check_interface(mxattr, &IID_ISAXAttributes, TRUE); 2713 check_interface(mxattr, &IID_IVBSAXAttributes, TRUE); 2714 check_interface(mxattr, &IID_IDispatch, TRUE); 2715 check_interface(mxattr, &IID_IDispatchEx, TRUE); 2716 2717 IMXAttributes_Release(mxattr); 2718} 2719 2720static void test_mxattr_localname(void) 2721{ 2722 ISAXAttributes *saxattr; 2723 IMXAttributes *mxattr; 2724 HRESULT hr; 2725 int index; 2726 2727 hr = CoCreateInstance(&CLSID_SAXAttributes60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXAttributes, (void **)&mxattr); 2728 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2729 2730 hr = IMXAttributes_QueryInterface(mxattr, &IID_ISAXAttributes, (void**)&saxattr); 2731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2732 2733 hr = ISAXAttributes_getIndexFromName(saxattr, NULL, 0, NULL, 0, &index); 2734 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2735 2736 /* add some ambiguous attribute names */ 2737 hr = IMXAttributes_addAttribute(mxattr, _bstr_("uri"), _bstr_("localname"), 2738 _bstr_("a:localname"), _bstr_(""), _bstr_("value")); 2739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2740 hr = IMXAttributes_addAttribute(mxattr, _bstr_("uri"), _bstr_("localname"), 2741 _bstr_("b:localname"), _bstr_(""), _bstr_("value")); 2742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2743 2744 index = -1; 2745 hr = ISAXAttributes_getIndexFromName(saxattr, L"uri", 3, L"localname", 9, &index); 2746 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2747 ok(!index, "Got index %d.\n", index); 2748 2749 index = -1; 2750 hr = ISAXAttributes_getIndexFromName(saxattr, L"uri1", 4, L"localname", 9, &index); 2751 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2752 ok(index == -1, "Got index %d.\n", index); 2753 2754 index = -1; 2755 hr = ISAXAttributes_getIndexFromName(saxattr, L"uri", 3, L"localname1", 10, &index); 2756 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2757 ok(index == -1, "Got index %d.\n", index); 2758 2759 hr = ISAXAttributes_getIndexFromName(saxattr, NULL, 0, NULL, 0, NULL); 2760 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2761 2762 hr = ISAXAttributes_getIndexFromName(saxattr, L"uri", 3, L"localname1", 10, NULL); 2763 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2764 2765 hr = ISAXAttributes_getIndexFromName(saxattr, L"uri", 3, NULL, 0, &index); 2766 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2767 2768 hr = ISAXAttributes_getIndexFromName(saxattr, NULL, 0, L"localname1", 10, &index); 2769 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); 2770 2771 ISAXAttributes_Release(saxattr); 2772 IMXAttributes_Release(mxattr); 2773 free_bstrs(); 2774} 2775 2776static void test_mxwriter_indent(void) 2777{ 2778 ISAXContentHandler *content; 2779 IMXWriter *writer; 2780 VARIANT dest; 2781 HRESULT hr; 2782 2783 hr = CoCreateInstance(&CLSID_MXXMLWriter60, NULL, CLSCTX_INPROC_SERVER, &IID_IMXWriter, (void **)&writer); 2784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2785 2786 hr = IMXWriter_put_indent(writer, VARIANT_TRUE); 2787 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2788 2789 hr = IMXWriter_QueryInterface(writer, &IID_ISAXContentHandler, (void**)&content); 2790 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2791 2792 hr = ISAXContentHandler_startDocument(content); 2793 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2794 2795 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("a"), 1, NULL); 2796 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2797 2798 hr = ISAXContentHandler_characters(content, _bstr_(""), 0); 2799 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2800 2801 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("b"), 1, NULL); 2802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2803 2804 hr = ISAXContentHandler_startElement(content, L"", 0, L"", 0, _bstr_("c"), 1, NULL); 2805 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2806 2807 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, _bstr_("c"), 1); 2808 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2809 2810 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, _bstr_("b"), 1); 2811 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2812 2813 hr = ISAXContentHandler_endElement(content, L"", 0, L"", 0, _bstr_("a"), 1); 2814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2815 2816 hr = ISAXContentHandler_endDocument(content); 2817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2818 2819 V_VT(&dest) = VT_EMPTY; 2820 hr = IMXWriter_get_output(writer, &dest); 2821 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); 2822 ok(V_VT(&dest) == VT_BSTR, "got %d\n", V_VT(&dest)); 2823 ok(!lstrcmpW(L"<?xml version=\"1.0\" encoding=\"UTF-16\" standalone=\"no\"?>\r\n<a><b>\r\n\t\t<c/>\r\n\t</b>\r\n</a>", V_BSTR(&dest)), 2824 "got wrong content %s\n", wine_dbgstr_w(V_BSTR(&dest))); 2825 VariantClear(&dest); 2826 2827 ISAXContentHandler_Release(content); 2828 IMXWriter_Release(writer); 2829 2830 free_bstrs(); 2831} 2832 2833START_TEST(saxreader) 2834{ 2835 HRESULT hr; 2836 2837 hr = CoInitialize(NULL); 2838 ok(hr == S_OK, "Failed to initialize COM, hr %#lx.\n", hr); 2839 2840 get_class_support_data(); 2841 2842 if (is_class_supported(&CLSID_MXXMLWriter60)) 2843 { 2844 test_mxwriter_handlers(); 2845 test_mxwriter_startenddocument(); 2846 test_mxwriter_startendelement(); 2847 test_mxwriter_characters(); 2848 test_mxwriter_comment(); 2849 test_mxwriter_cdata(); 2850 test_mxwriter_pi(); 2851 test_mxwriter_ignorablespaces(); 2852 test_mxwriter_dtd(); 2853 test_mxwriter_properties(); 2854 test_mxwriter_flush(); 2855 test_mxwriter_domdoc(); 2856 test_mxwriter_encoding(); 2857 test_mxwriter_dispex(); 2858 test_mxwriter_indent(); 2859 } 2860 2861 if (is_class_supported(&CLSID_SAXAttributes60)) 2862 { 2863 test_mxattr_qi(); 2864 test_mxattr_addAttribute(); 2865 test_mxattr_clear(); 2866 test_mxattr_localname(); 2867 test_mxattr_dispex(); 2868 } 2869 2870 CoUninitialize(); 2871}