1 /* 2 * MXWriter implementation 3 * 4 * Copyright 2011-2014, 2016 Nikolay Sivov for CodeWeavers 5 * Copyright 2011 Thomas Mullaly 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define COBJMACROS 23 #include "config.h" 24 25 #include <stdarg.h> 26 #ifdef HAVE_LIBXML2 27 # include <libxml/parser.h> 28 #endif 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "ole2.h" 33 34 #include "msxml6.h" 35 36 #include "wine/debug.h" 37 #include "wine/list.h" 38 39 #include "msxml_private.h" 40 41 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 42 43 static const WCHAR emptyW[] = {0}; 44 static const WCHAR spaceW[] = {' '}; 45 static const WCHAR quotW[] = {'\"'}; 46 static const WCHAR closetagW[] = {'>','\r','\n'}; 47 static const WCHAR crlfW[] = {'\r','\n'}; 48 static const WCHAR entityW[] = {'<','!','E','N','T','I','T','Y',' '}; 49 static const WCHAR publicW[] = {'P','U','B','L','I','C',' '}; 50 static const WCHAR systemW[] = {'S','Y','S','T','E','M',' '}; 51 52 /* should be ordered as encoding names are sorted */ 53 typedef enum 54 { 55 XmlEncoding_ISO_8859_1 = 0, 56 XmlEncoding_ISO_8859_13, 57 XmlEncoding_ISO_8859_15, 58 XmlEncoding_ISO_8859_2, 59 XmlEncoding_ISO_8859_3, 60 XmlEncoding_ISO_8859_4, 61 XmlEncoding_ISO_8859_5, 62 XmlEncoding_ISO_8859_7, 63 XmlEncoding_ISO_8859_9, 64 XmlEncoding_UTF16, 65 XmlEncoding_UTF8, 66 XmlEncoding_Unknown 67 } xml_encoding; 68 69 struct xml_encoding_data 70 { 71 const WCHAR *encoding; 72 xml_encoding enc; 73 UINT cp; 74 }; 75 76 static const WCHAR iso_8859_1W[] = {'i','s','o','-','8','8','5','9','-','1',0}; 77 static const WCHAR iso_8859_2W[] = {'i','s','o','-','8','8','5','9','-','2',0}; 78 static const WCHAR iso_8859_3W[] = {'i','s','o','-','8','8','5','9','-','3',0}; 79 static const WCHAR iso_8859_4W[] = {'i','s','o','-','8','8','5','9','-','4',0}; 80 static const WCHAR iso_8859_5W[] = {'i','s','o','-','8','8','5','9','-','5',0}; 81 static const WCHAR iso_8859_7W[] = {'i','s','o','-','8','8','5','9','-','7',0}; 82 static const WCHAR iso_8859_9W[] = {'i','s','o','-','8','8','5','9','-','9',0}; 83 static const WCHAR iso_8859_13W[] = {'i','s','o','-','8','8','5','9','-','1','3',0}; 84 static const WCHAR iso_8859_15W[] = {'i','s','o','-','8','8','5','9','-','1','5',0}; 85 static const WCHAR utf16W[] = {'U','T','F','-','1','6',0}; 86 static const WCHAR utf8W[] = {'U','T','F','-','8',0}; 87 88 static const struct xml_encoding_data xml_encoding_map[] = { 89 { iso_8859_1W, XmlEncoding_ISO_8859_1, 28591 }, 90 { iso_8859_13W, XmlEncoding_ISO_8859_13, 28603 }, 91 { iso_8859_15W, XmlEncoding_ISO_8859_15, 28605 }, 92 { iso_8859_2W, XmlEncoding_ISO_8859_2, 28592 }, 93 { iso_8859_3W, XmlEncoding_ISO_8859_3, 28593 }, 94 { iso_8859_4W, XmlEncoding_ISO_8859_4, 28594 }, 95 { iso_8859_5W, XmlEncoding_ISO_8859_5, 28595 }, 96 { iso_8859_7W, XmlEncoding_ISO_8859_7, 28597 }, 97 { iso_8859_9W, XmlEncoding_ISO_8859_9, 28599 }, 98 { utf16W, XmlEncoding_UTF16, ~0 }, 99 { utf8W, XmlEncoding_UTF8, CP_UTF8 } 100 }; 101 102 typedef enum 103 { 104 MXWriter_BOM = 0, 105 MXWriter_DisableEscaping, 106 MXWriter_Indent, 107 MXWriter_OmitXmlDecl, 108 MXWriter_Standalone, 109 MXWriter_LastProp 110 } mxwriter_prop; 111 112 typedef enum 113 { 114 EscapeValue, 115 EscapeText 116 } escape_mode; 117 118 typedef struct 119 { 120 struct list entry; 121 char *data; 122 unsigned int allocated; 123 unsigned int written; 124 } encoded_buffer; 125 126 typedef struct 127 { 128 encoded_buffer encoded; 129 UINT code_page; 130 UINT utf16_total; /* total number of bytes written since last buffer reinitialization */ 131 struct list blocks; /* only used when output was not set, for BSTR case */ 132 } output_buffer; 133 134 typedef struct 135 { 136 DispatchEx dispex; 137 IMXWriter IMXWriter_iface; 138 ISAXContentHandler ISAXContentHandler_iface; 139 ISAXLexicalHandler ISAXLexicalHandler_iface; 140 ISAXDeclHandler ISAXDeclHandler_iface; 141 ISAXDTDHandler ISAXDTDHandler_iface; 142 ISAXErrorHandler ISAXErrorHandler_iface; 143 IVBSAXDeclHandler IVBSAXDeclHandler_iface; 144 IVBSAXLexicalHandler IVBSAXLexicalHandler_iface; 145 IVBSAXContentHandler IVBSAXContentHandler_iface; 146 IVBSAXDTDHandler IVBSAXDTDHandler_iface; 147 IVBSAXErrorHandler IVBSAXErrorHandler_iface; 148 149 LONG ref; 150 MSXML_VERSION class_version; 151 152 VARIANT_BOOL props[MXWriter_LastProp]; 153 BOOL prop_changed; 154 BOOL cdata; 155 156 BOOL text; /* last node was text node, so we shouldn't indent next node */ 157 BOOL newline; /* newline was already added as a part of previous call */ 158 UINT indent; /* indentation level for next node */ 159 160 BSTR version; 161 162 BSTR encoding; /* exact property value */ 163 xml_encoding xml_enc; 164 165 /* contains a pending (or not closed yet) element name or NULL if 166 we don't have to close */ 167 BSTR element; 168 169 IStream *dest; 170 171 output_buffer buffer; 172 } mxwriter; 173 174 typedef struct 175 { 176 BSTR qname; 177 BSTR local; 178 BSTR uri; 179 BSTR type; 180 BSTR value; 181 } mxattribute; 182 183 typedef struct 184 { 185 DispatchEx dispex; 186 IMXAttributes IMXAttributes_iface; 187 ISAXAttributes ISAXAttributes_iface; 188 IVBSAXAttributes IVBSAXAttributes_iface; 189 LONG ref; 190 191 MSXML_VERSION class_version; 192 193 mxattribute *attr; 194 int length; 195 int allocated; 196 } mxattributes; 197 198 static inline mxattributes *impl_from_IMXAttributes( IMXAttributes *iface ) 199 { 200 return CONTAINING_RECORD(iface, mxattributes, IMXAttributes_iface); 201 } 202 203 static inline mxattributes *impl_from_ISAXAttributes( ISAXAttributes *iface ) 204 { 205 return CONTAINING_RECORD(iface, mxattributes, ISAXAttributes_iface); 206 } 207 208 static inline mxattributes *impl_from_IVBSAXAttributes( IVBSAXAttributes *iface ) 209 { 210 return CONTAINING_RECORD(iface, mxattributes, IVBSAXAttributes_iface); 211 } 212 213 static HRESULT mxattributes_grow(mxattributes *This) 214 { 215 if (This->length < This->allocated) return S_OK; 216 217 This->allocated *= 2; 218 This->attr = heap_realloc(This->attr, This->allocated*sizeof(mxattribute)); 219 220 return This->attr ? S_OK : E_OUTOFMEMORY; 221 } 222 223 static xml_encoding parse_encoding_name(const WCHAR *encoding) 224 { 225 int min, max, n, c; 226 227 min = 0; 228 max = ARRAY_SIZE(xml_encoding_map) - 1; 229 230 while (min <= max) 231 { 232 n = (min+max)/2; 233 234 c = strcmpiW(xml_encoding_map[n].encoding, encoding); 235 if (!c) 236 return xml_encoding_map[n].enc; 237 238 if (c > 0) 239 max = n-1; 240 else 241 min = n+1; 242 } 243 244 return XmlEncoding_Unknown; 245 } 246 247 static HRESULT init_encoded_buffer(encoded_buffer *buffer) 248 { 249 const int initial_len = 0x1000; 250 buffer->data = heap_alloc(initial_len); 251 if (!buffer->data) return E_OUTOFMEMORY; 252 253 memset(buffer->data, 0, 4); 254 buffer->allocated = initial_len; 255 buffer->written = 0; 256 257 return S_OK; 258 } 259 260 static void free_encoded_buffer(encoded_buffer *buffer) 261 { 262 heap_free(buffer->data); 263 } 264 265 static HRESULT get_code_page(xml_encoding encoding, UINT *cp) 266 { 267 const struct xml_encoding_data *data; 268 269 if (encoding == XmlEncoding_Unknown) 270 { 271 FIXME("unsupported encoding %d\n", encoding); 272 return E_NOTIMPL; 273 } 274 275 data = &xml_encoding_map[encoding]; 276 *cp = data->cp; 277 278 return S_OK; 279 } 280 281 static HRESULT init_output_buffer(xml_encoding encoding, output_buffer *buffer) 282 { 283 HRESULT hr; 284 285 hr = get_code_page(encoding, &buffer->code_page); 286 if (hr != S_OK) 287 return hr; 288 289 hr = init_encoded_buffer(&buffer->encoded); 290 if (hr != S_OK) 291 return hr; 292 293 list_init(&buffer->blocks); 294 buffer->utf16_total = 0; 295 296 return S_OK; 297 } 298 299 static void free_output_buffer(output_buffer *buffer) 300 { 301 encoded_buffer *cur, *cur2; 302 303 free_encoded_buffer(&buffer->encoded); 304 305 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &buffer->blocks, encoded_buffer, entry) 306 { 307 list_remove(&cur->entry); 308 free_encoded_buffer(cur); 309 heap_free(cur); 310 } 311 } 312 313 static HRESULT write_output_buffer(mxwriter *writer, const WCHAR *data, int len) 314 { 315 output_buffer *buffer = &writer->buffer; 316 encoded_buffer *buff; 317 unsigned int written; 318 int src_len; 319 320 if (!len || !*data) 321 return S_OK; 322 323 src_len = len == -1 ? strlenW(data) : len; 324 if (writer->dest) 325 { 326 buff = &buffer->encoded; 327 328 if (buffer->code_page == ~0) 329 { 330 unsigned int avail = buff->allocated - buff->written; 331 332 src_len *= sizeof(WCHAR); 333 written = min(avail, src_len); 334 335 /* fill internal buffer first */ 336 if (avail) 337 { 338 memcpy(buff->data + buff->written, data, written); 339 data += written / sizeof(WCHAR); 340 buff->written += written; 341 avail -= written; 342 src_len -= written; 343 } 344 345 if (!avail) 346 { 347 IStream_Write(writer->dest, buff->data, buff->written, &written); 348 buff->written = 0; 349 if (src_len >= buff->allocated) 350 IStream_Write(writer->dest, data, src_len, &written); 351 else if (src_len) 352 { 353 memcpy(buff->data, data, src_len); 354 buff->written += src_len; 355 } 356 } 357 } 358 else 359 { 360 unsigned int avail = buff->allocated - buff->written; 361 int length; 362 363 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, NULL, 0, NULL, NULL); 364 if (avail >= length) 365 { 366 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL); 367 buff->written += length; 368 } 369 else 370 { 371 /* drain what we go so far */ 372 if (buff->written) 373 { 374 IStream_Write(writer->dest, buff->data, buff->written, &written); 375 buff->written = 0; 376 avail = buff->allocated; 377 } 378 379 if (avail >= length) 380 { 381 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, buff->data + buff->written, length, NULL, NULL); 382 buff->written += length; 383 } 384 else 385 { 386 char *mb; 387 388 /* if current chunk is larger than total buffer size, convert it at once using temporary allocated buffer */ 389 mb = heap_alloc(length); 390 if (!mb) 391 return E_OUTOFMEMORY; 392 393 length = WideCharToMultiByte(buffer->code_page, 0, data, src_len, mb, length, NULL, NULL); 394 IStream_Write(writer->dest, mb, length, &written); 395 heap_free(mb); 396 } 397 } 398 } 399 } 400 /* When writer has no output set we have to accumulate everything to return it later in a form of BSTR. 401 To achieve that: 402 403 - fill a buffer already allocated as part of output buffer; 404 - when current buffer is full, allocate another one and switch to it; buffers themselves never grow, 405 but are linked together, with head pointing to first allocated buffer after initial one got filled; 406 - later during get_output() contents are concatenated by copying one after another to destination BSTR buffer, 407 that's returned to the client. */ 408 else 409 { 410 /* select last used block */ 411 if (list_empty(&buffer->blocks)) 412 buff = &buffer->encoded; 413 else 414 buff = LIST_ENTRY(list_tail(&buffer->blocks), encoded_buffer, entry); 415 416 src_len *= sizeof(WCHAR); 417 while (src_len) 418 { 419 unsigned int avail = buff->allocated - buff->written; 420 unsigned int written = min(avail, src_len); 421 422 if (avail) 423 { 424 memcpy(buff->data + buff->written, data, written); 425 buff->written += written; 426 buffer->utf16_total += written; 427 src_len -= written; 428 } 429 430 /* alloc new block if needed and retry */ 431 if (src_len) 432 { 433 encoded_buffer *next = heap_alloc(sizeof(*next)); 434 HRESULT hr; 435 436 if (FAILED(hr = init_encoded_buffer(next))) { 437 heap_free(next); 438 return hr; 439 } 440 441 list_add_tail(&buffer->blocks, &next->entry); 442 buff = next; 443 } 444 } 445 } 446 447 return S_OK; 448 } 449 450 static HRESULT write_output_buffer_quoted(mxwriter *writer, const WCHAR *data, int len) 451 { 452 write_output_buffer(writer, quotW, 1); 453 write_output_buffer(writer, data, len); 454 write_output_buffer(writer, quotW, 1); 455 456 return S_OK; 457 } 458 459 /* frees buffer data, reallocates with a default lengths */ 460 static void close_output_buffer(mxwriter *writer) 461 { 462 encoded_buffer *cur, *cur2; 463 464 heap_free(writer->buffer.encoded.data); 465 466 LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &writer->buffer.blocks, encoded_buffer, entry) 467 { 468 list_remove(&cur->entry); 469 free_encoded_buffer(cur); 470 heap_free(cur); 471 } 472 473 init_encoded_buffer(&writer->buffer.encoded); 474 get_code_page(writer->xml_enc, &writer->buffer.code_page); 475 writer->buffer.utf16_total = 0; 476 list_init(&writer->buffer.blocks); 477 } 478 479 /* Escapes special characters like: 480 '<' -> "<" 481 '&' -> "&" 482 '"' -> """ 483 '>' -> ">" 484 485 On call 'len' contains a length of 'str' in chars or -1 if it's null terminated. 486 After a call it's updated with actual new length if it wasn't -1 initially. 487 */ 488 static WCHAR *get_escaped_string(const WCHAR *str, escape_mode mode, int *len) 489 { 490 static const WCHAR ltW[] = {'&','l','t',';'}; 491 static const WCHAR ampW[] = {'&','a','m','p',';'}; 492 static const WCHAR equotW[] = {'&','q','u','o','t',';'}; 493 static const WCHAR gtW[] = {'&','g','t',';'}; 494 495 const int default_alloc = 100; 496 const int grow_thresh = 10; 497 int p = *len, conv_len; 498 WCHAR *ptr, *ret; 499 500 /* default buffer size to something if length is unknown */ 501 conv_len = max(2**len, default_alloc); 502 ptr = ret = heap_alloc(conv_len*sizeof(WCHAR)); 503 504 while (p) 505 { 506 if (ptr - ret > conv_len - grow_thresh) 507 { 508 int written = ptr - ret; 509 conv_len *= 2; 510 ptr = ret = heap_realloc(ret, conv_len*sizeof(WCHAR)); 511 ptr += written; 512 } 513 514 switch (*str) 515 { 516 case '<': 517 memcpy(ptr, ltW, sizeof(ltW)); 518 ptr += ARRAY_SIZE(ltW); 519 break; 520 case '&': 521 memcpy(ptr, ampW, sizeof(ampW)); 522 ptr += ARRAY_SIZE(ampW); 523 break; 524 case '>': 525 memcpy(ptr, gtW, sizeof(gtW)); 526 ptr += ARRAY_SIZE(gtW); 527 break; 528 case '"': 529 if (mode == EscapeValue) 530 { 531 memcpy(ptr, equotW, sizeof(equotW)); 532 ptr += ARRAY_SIZE(equotW); 533 break; 534 } 535 /* fallthrough for text mode */ 536 default: 537 *ptr++ = *str; 538 break; 539 } 540 541 str++; 542 p--; 543 } 544 545 *len = ptr-ret; 546 *++ptr = 0; 547 548 return ret; 549 } 550 551 static void write_prolog_buffer(mxwriter *writer) 552 { 553 static const WCHAR versionW[] = {'<','?','x','m','l',' ','v','e','r','s','i','o','n','='}; 554 static const WCHAR encodingW[] = {' ','e','n','c','o','d','i','n','g','=','\"'}; 555 static const WCHAR standaloneW[] = {' ','s','t','a','n','d','a','l','o','n','e','=','\"'}; 556 static const WCHAR yesW[] = {'y','e','s','\"','?','>'}; 557 static const WCHAR noW[] = {'n','o','\"','?','>'}; 558 559 /* version */ 560 write_output_buffer(writer, versionW, ARRAY_SIZE(versionW)); 561 write_output_buffer_quoted(writer, writer->version, -1); 562 563 /* encoding */ 564 write_output_buffer(writer, encodingW, ARRAY_SIZE(encodingW)); 565 566 if (writer->dest) 567 write_output_buffer(writer, writer->encoding, -1); 568 else 569 write_output_buffer(writer, utf16W, ARRAY_SIZE(utf16W) - 1); 570 write_output_buffer(writer, quotW, 1); 571 572 /* standalone */ 573 write_output_buffer(writer, standaloneW, ARRAY_SIZE(standaloneW)); 574 if (writer->props[MXWriter_Standalone] == VARIANT_TRUE) 575 write_output_buffer(writer, yesW, ARRAY_SIZE(yesW)); 576 else 577 write_output_buffer(writer, noW, ARRAY_SIZE(noW)); 578 579 write_output_buffer(writer, crlfW, ARRAY_SIZE(crlfW)); 580 writer->newline = TRUE; 581 } 582 583 /* Attempts to the write data from the mxwriter's buffer to 584 * the destination stream (if there is one). 585 */ 586 static HRESULT write_data_to_stream(mxwriter *writer) 587 { 588 encoded_buffer *buffer = &writer->buffer.encoded; 589 ULONG written = 0; 590 591 if (!writer->dest) 592 return S_OK; 593 594 if (buffer->written == 0) 595 { 596 if (writer->xml_enc == XmlEncoding_UTF8) 597 IStream_Write(writer->dest, buffer->data, 0, &written); 598 } 599 else 600 { 601 IStream_Write(writer->dest, buffer->data, buffer->written, &written); 602 buffer->written = 0; 603 } 604 605 return S_OK; 606 } 607 608 /* Newly added element start tag left unclosed cause for empty elements 609 we have to close it differently. */ 610 static void close_element_starttag(mxwriter *writer) 611 { 612 static const WCHAR gtW[] = {'>'}; 613 if (!writer->element) return; 614 write_output_buffer(writer, gtW, 1); 615 } 616 617 static void write_node_indent(mxwriter *writer) 618 { 619 static const WCHAR tabW[] = {'\t'}; 620 int indent = writer->indent; 621 622 if (!writer->props[MXWriter_Indent] || writer->text) 623 { 624 writer->text = FALSE; 625 return; 626 } 627 628 /* This is to workaround PI output logic that always puts newline chars, 629 document prolog PI does that too. */ 630 if (!writer->newline) 631 write_output_buffer(writer, crlfW, ARRAY_SIZE(crlfW)); 632 while (indent--) 633 write_output_buffer(writer, tabW, 1); 634 635 writer->newline = FALSE; 636 writer->text = FALSE; 637 } 638 639 static inline void writer_inc_indent(mxwriter *This) 640 { 641 This->indent++; 642 } 643 644 static inline void writer_dec_indent(mxwriter *This) 645 { 646 if (This->indent) This->indent--; 647 /* depth is decreased only when element is closed, meaning it's not a text node 648 at this point */ 649 This->text = FALSE; 650 } 651 652 static void set_element_name(mxwriter *This, const WCHAR *name, int len) 653 { 654 SysFreeString(This->element); 655 if (name) 656 This->element = len != -1 ? SysAllocStringLen(name, len) : SysAllocString(name); 657 else 658 This->element = NULL; 659 } 660 661 static inline HRESULT flush_output_buffer(mxwriter *This) 662 { 663 close_element_starttag(This); 664 set_element_name(This, NULL, 0); 665 This->cdata = FALSE; 666 return write_data_to_stream(This); 667 } 668 669 /* Resets the mxwriter's output buffer by closing it, then creating a new 670 * output buffer using the given encoding. 671 */ 672 static inline void reset_output_buffer(mxwriter *This) 673 { 674 close_output_buffer(This); 675 } 676 677 static HRESULT writer_set_property(mxwriter *writer, mxwriter_prop property, VARIANT_BOOL value) 678 { 679 writer->props[property] = value; 680 writer->prop_changed = TRUE; 681 return S_OK; 682 } 683 684 static HRESULT writer_get_property(const mxwriter *writer, mxwriter_prop property, VARIANT_BOOL *value) 685 { 686 if (!value) return E_POINTER; 687 *value = writer->props[property]; 688 return S_OK; 689 } 690 691 static inline mxwriter *impl_from_IMXWriter(IMXWriter *iface) 692 { 693 return CONTAINING_RECORD(iface, mxwriter, IMXWriter_iface); 694 } 695 696 static inline mxwriter *impl_from_ISAXContentHandler(ISAXContentHandler *iface) 697 { 698 return CONTAINING_RECORD(iface, mxwriter, ISAXContentHandler_iface); 699 } 700 701 static inline mxwriter *impl_from_IVBSAXContentHandler(IVBSAXContentHandler *iface) 702 { 703 return CONTAINING_RECORD(iface, mxwriter, IVBSAXContentHandler_iface); 704 } 705 706 static inline mxwriter *impl_from_ISAXLexicalHandler(ISAXLexicalHandler *iface) 707 { 708 return CONTAINING_RECORD(iface, mxwriter, ISAXLexicalHandler_iface); 709 } 710 711 static inline mxwriter *impl_from_IVBSAXLexicalHandler(IVBSAXLexicalHandler *iface) 712 { 713 return CONTAINING_RECORD(iface, mxwriter, IVBSAXLexicalHandler_iface); 714 } 715 716 static inline mxwriter *impl_from_ISAXDeclHandler(ISAXDeclHandler *iface) 717 { 718 return CONTAINING_RECORD(iface, mxwriter, ISAXDeclHandler_iface); 719 } 720 721 static inline mxwriter *impl_from_IVBSAXDeclHandler(IVBSAXDeclHandler *iface) 722 { 723 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDeclHandler_iface); 724 } 725 726 static inline mxwriter *impl_from_ISAXDTDHandler(ISAXDTDHandler *iface) 727 { 728 return CONTAINING_RECORD(iface, mxwriter, ISAXDTDHandler_iface); 729 } 730 731 static inline mxwriter *impl_from_IVBSAXDTDHandler(IVBSAXDTDHandler *iface) 732 { 733 return CONTAINING_RECORD(iface, mxwriter, IVBSAXDTDHandler_iface); 734 } 735 736 static inline mxwriter *impl_from_ISAXErrorHandler(ISAXErrorHandler *iface) 737 { 738 return CONTAINING_RECORD(iface, mxwriter, ISAXErrorHandler_iface); 739 } 740 741 static inline mxwriter *impl_from_IVBSAXErrorHandler(IVBSAXErrorHandler *iface) 742 { 743 return CONTAINING_RECORD(iface, mxwriter, IVBSAXErrorHandler_iface); 744 } 745 746 static HRESULT WINAPI mxwriter_QueryInterface(IMXWriter *iface, REFIID riid, void **obj) 747 { 748 mxwriter *This = impl_from_IMXWriter( iface ); 749 750 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 751 752 *obj = NULL; 753 754 if ( IsEqualGUID( riid, &IID_IMXWriter ) || 755 IsEqualGUID( riid, &IID_IDispatch ) || 756 IsEqualGUID( riid, &IID_IUnknown ) ) 757 { 758 *obj = &This->IMXWriter_iface; 759 } 760 else if ( IsEqualGUID( riid, &IID_ISAXContentHandler ) ) 761 { 762 *obj = &This->ISAXContentHandler_iface; 763 } 764 else if ( IsEqualGUID( riid, &IID_ISAXLexicalHandler ) ) 765 { 766 *obj = &This->ISAXLexicalHandler_iface; 767 } 768 else if ( IsEqualGUID( riid, &IID_ISAXDeclHandler ) ) 769 { 770 *obj = &This->ISAXDeclHandler_iface; 771 } 772 else if ( IsEqualGUID( riid, &IID_ISAXDTDHandler ) ) 773 { 774 *obj = &This->ISAXDTDHandler_iface; 775 } 776 else if ( IsEqualGUID( riid, &IID_ISAXErrorHandler ) ) 777 { 778 *obj = &This->ISAXErrorHandler_iface; 779 } 780 else if ( IsEqualGUID( riid, &IID_IVBSAXDeclHandler ) ) 781 { 782 *obj = &This->IVBSAXDeclHandler_iface; 783 } 784 else if ( IsEqualGUID( riid, &IID_IVBSAXLexicalHandler ) ) 785 { 786 *obj = &This->IVBSAXLexicalHandler_iface; 787 } 788 else if ( IsEqualGUID( riid, &IID_IVBSAXContentHandler ) ) 789 { 790 *obj = &This->IVBSAXContentHandler_iface; 791 } 792 else if ( IsEqualGUID( riid, &IID_IVBSAXDTDHandler ) ) 793 { 794 *obj = &This->IVBSAXDTDHandler_iface; 795 } 796 else if ( IsEqualGUID( riid, &IID_IVBSAXErrorHandler ) ) 797 { 798 *obj = &This->IVBSAXErrorHandler_iface; 799 } 800 else if (dispex_query_interface(&This->dispex, riid, obj)) 801 { 802 return *obj ? S_OK : E_NOINTERFACE; 803 } 804 else 805 { 806 ERR("interface %s not implemented\n", debugstr_guid(riid)); 807 *obj = NULL; 808 return E_NOINTERFACE; 809 } 810 811 IMXWriter_AddRef(iface); 812 return S_OK; 813 } 814 815 static ULONG WINAPI mxwriter_AddRef(IMXWriter *iface) 816 { 817 mxwriter *This = impl_from_IMXWriter( iface ); 818 LONG ref = InterlockedIncrement(&This->ref); 819 820 TRACE("(%p)->(%d)\n", This, ref); 821 822 return ref; 823 } 824 825 static ULONG WINAPI mxwriter_Release(IMXWriter *iface) 826 { 827 mxwriter *This = impl_from_IMXWriter( iface ); 828 ULONG ref = InterlockedDecrement(&This->ref); 829 830 TRACE("(%p)->(%d)\n", This, ref); 831 832 if(!ref) 833 { 834 /* Windows flushes the buffer when the interface is destroyed. */ 835 flush_output_buffer(This); 836 free_output_buffer(&This->buffer); 837 838 if (This->dest) IStream_Release(This->dest); 839 SysFreeString(This->version); 840 SysFreeString(This->encoding); 841 842 SysFreeString(This->element); 843 heap_free(This); 844 } 845 846 return ref; 847 } 848 849 static HRESULT WINAPI mxwriter_GetTypeInfoCount(IMXWriter *iface, UINT* pctinfo) 850 { 851 mxwriter *This = impl_from_IMXWriter( iface ); 852 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 853 } 854 855 static HRESULT WINAPI mxwriter_GetTypeInfo( 856 IMXWriter *iface, 857 UINT iTInfo, LCID lcid, 858 ITypeInfo** ppTInfo ) 859 { 860 mxwriter *This = impl_from_IMXWriter( iface ); 861 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, 862 iTInfo, lcid, ppTInfo); 863 } 864 865 static HRESULT WINAPI mxwriter_GetIDsOfNames( 866 IMXWriter *iface, 867 REFIID riid, LPOLESTR* rgszNames, 868 UINT cNames, LCID lcid, DISPID* rgDispId ) 869 { 870 mxwriter *This = impl_from_IMXWriter( iface ); 871 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, 872 riid, rgszNames, cNames, lcid, rgDispId); 873 } 874 875 static HRESULT WINAPI mxwriter_Invoke( 876 IMXWriter *iface, 877 DISPID dispIdMember, REFIID riid, LCID lcid, 878 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, 879 EXCEPINFO* pExcepInfo, UINT* puArgErr ) 880 { 881 mxwriter *This = impl_from_IMXWriter( iface ); 882 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, 883 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 884 } 885 886 static HRESULT WINAPI mxwriter_put_output(IMXWriter *iface, VARIANT dest) 887 { 888 mxwriter *This = impl_from_IMXWriter( iface ); 889 HRESULT hr; 890 891 TRACE("(%p)->(%s)\n", This, debugstr_variant(&dest)); 892 893 hr = flush_output_buffer(This); 894 if (FAILED(hr)) 895 return hr; 896 897 switch (V_VT(&dest)) 898 { 899 case VT_EMPTY: 900 { 901 if (This->dest) IStream_Release(This->dest); 902 This->dest = NULL; 903 reset_output_buffer(This); 904 break; 905 } 906 case VT_UNKNOWN: 907 { 908 IStream *stream; 909 910 hr = IUnknown_QueryInterface(V_UNKNOWN(&dest), &IID_IStream, (void**)&stream); 911 if (hr == S_OK) 912 { 913 /* Recreate the output buffer to make sure it's using the correct encoding. */ 914 reset_output_buffer(This); 915 916 if (This->dest) IStream_Release(This->dest); 917 This->dest = stream; 918 break; 919 } 920 921 FIXME("unhandled interface type for VT_UNKNOWN destination\n"); 922 return E_NOTIMPL; 923 } 924 default: 925 FIXME("unhandled destination type %s\n", debugstr_variant(&dest)); 926 return E_NOTIMPL; 927 } 928 929 return S_OK; 930 } 931 932 static HRESULT WINAPI mxwriter_get_output(IMXWriter *iface, VARIANT *dest) 933 { 934 mxwriter *This = impl_from_IMXWriter( iface ); 935 936 TRACE("(%p)->(%p)\n", This, dest); 937 938 if (!dest) return E_POINTER; 939 940 if (This->dest) 941 { 942 /* we only support IStream output so far */ 943 V_VT(dest) = VT_UNKNOWN; 944 V_UNKNOWN(dest) = (IUnknown*)This->dest; 945 IStream_AddRef(This->dest); 946 } 947 else 948 { 949 encoded_buffer *buff; 950 char *dest_ptr; 951 HRESULT hr; 952 953 hr = flush_output_buffer(This); 954 if (FAILED(hr)) 955 return hr; 956 957 V_VT(dest) = VT_BSTR; 958 V_BSTR(dest) = SysAllocStringLen(NULL, This->buffer.utf16_total / sizeof(WCHAR)); 959 if (!V_BSTR(dest)) 960 return E_OUTOFMEMORY; 961 962 dest_ptr = (char*)V_BSTR(dest); 963 buff = &This->buffer.encoded; 964 965 if (buff->written) 966 { 967 memcpy(dest_ptr, buff->data, buff->written); 968 dest_ptr += buff->written; 969 } 970 971 LIST_FOR_EACH_ENTRY(buff, &This->buffer.blocks, encoded_buffer, entry) 972 { 973 memcpy(dest_ptr, buff->data, buff->written); 974 dest_ptr += buff->written; 975 } 976 } 977 978 return S_OK; 979 } 980 981 static HRESULT WINAPI mxwriter_put_encoding(IMXWriter *iface, BSTR encoding) 982 { 983 mxwriter *This = impl_from_IMXWriter( iface ); 984 xml_encoding enc; 985 HRESULT hr; 986 987 TRACE("(%p)->(%s)\n", This, debugstr_w(encoding)); 988 989 enc = parse_encoding_name(encoding); 990 if (enc == XmlEncoding_Unknown) 991 { 992 FIXME("unsupported encoding %s\n", debugstr_w(encoding)); 993 return E_INVALIDARG; 994 } 995 996 hr = flush_output_buffer(This); 997 if (FAILED(hr)) 998 return hr; 999 1000 SysReAllocString(&This->encoding, encoding); 1001 This->xml_enc = enc; 1002 1003 TRACE("got encoding %d\n", This->xml_enc); 1004 reset_output_buffer(This); 1005 return S_OK; 1006 } 1007 1008 static HRESULT WINAPI mxwriter_get_encoding(IMXWriter *iface, BSTR *encoding) 1009 { 1010 mxwriter *This = impl_from_IMXWriter( iface ); 1011 1012 TRACE("(%p)->(%p)\n", This, encoding); 1013 1014 if (!encoding) return E_POINTER; 1015 1016 *encoding = SysAllocString(This->encoding); 1017 if (!*encoding) return E_OUTOFMEMORY; 1018 1019 return S_OK; 1020 } 1021 1022 static HRESULT WINAPI mxwriter_put_byteOrderMark(IMXWriter *iface, VARIANT_BOOL value) 1023 { 1024 mxwriter *This = impl_from_IMXWriter( iface ); 1025 1026 TRACE("(%p)->(%d)\n", This, value); 1027 return writer_set_property(This, MXWriter_BOM, value); 1028 } 1029 1030 static HRESULT WINAPI mxwriter_get_byteOrderMark(IMXWriter *iface, VARIANT_BOOL *value) 1031 { 1032 mxwriter *This = impl_from_IMXWriter( iface ); 1033 1034 TRACE("(%p)->(%p)\n", This, value); 1035 return writer_get_property(This, MXWriter_BOM, value); 1036 } 1037 1038 static HRESULT WINAPI mxwriter_put_indent(IMXWriter *iface, VARIANT_BOOL value) 1039 { 1040 mxwriter *This = impl_from_IMXWriter( iface ); 1041 1042 TRACE("(%p)->(%d)\n", This, value); 1043 return writer_set_property(This, MXWriter_Indent, value); 1044 } 1045 1046 static HRESULT WINAPI mxwriter_get_indent(IMXWriter *iface, VARIANT_BOOL *value) 1047 { 1048 mxwriter *This = impl_from_IMXWriter( iface ); 1049 1050 TRACE("(%p)->(%p)\n", This, value); 1051 return writer_get_property(This, MXWriter_Indent, value); 1052 } 1053 1054 static HRESULT WINAPI mxwriter_put_standalone(IMXWriter *iface, VARIANT_BOOL value) 1055 { 1056 mxwriter *This = impl_from_IMXWriter( iface ); 1057 1058 TRACE("(%p)->(%d)\n", This, value); 1059 return writer_set_property(This, MXWriter_Standalone, value); 1060 } 1061 1062 static HRESULT WINAPI mxwriter_get_standalone(IMXWriter *iface, VARIANT_BOOL *value) 1063 { 1064 mxwriter *This = impl_from_IMXWriter( iface ); 1065 1066 TRACE("(%p)->(%p)\n", This, value); 1067 return writer_get_property(This, MXWriter_Standalone, value); 1068 } 1069 1070 static HRESULT WINAPI mxwriter_put_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL value) 1071 { 1072 mxwriter *This = impl_from_IMXWriter( iface ); 1073 1074 TRACE("(%p)->(%d)\n", This, value); 1075 return writer_set_property(This, MXWriter_OmitXmlDecl, value); 1076 } 1077 1078 static HRESULT WINAPI mxwriter_get_omitXMLDeclaration(IMXWriter *iface, VARIANT_BOOL *value) 1079 { 1080 mxwriter *This = impl_from_IMXWriter( iface ); 1081 1082 TRACE("(%p)->(%p)\n", This, value); 1083 return writer_get_property(This, MXWriter_OmitXmlDecl, value); 1084 } 1085 1086 static HRESULT WINAPI mxwriter_put_version(IMXWriter *iface, BSTR version) 1087 { 1088 mxwriter *This = impl_from_IMXWriter( iface ); 1089 1090 TRACE("(%p)->(%s)\n", This, debugstr_w(version)); 1091 1092 if (!version) return E_INVALIDARG; 1093 1094 SysFreeString(This->version); 1095 This->version = SysAllocString(version); 1096 1097 return S_OK; 1098 } 1099 1100 static HRESULT WINAPI mxwriter_get_version(IMXWriter *iface, BSTR *version) 1101 { 1102 mxwriter *This = impl_from_IMXWriter( iface ); 1103 1104 TRACE("(%p)->(%p)\n", This, version); 1105 1106 if (!version) return E_POINTER; 1107 1108 return return_bstr(This->version, version); 1109 } 1110 1111 static HRESULT WINAPI mxwriter_put_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL value) 1112 { 1113 mxwriter *This = impl_from_IMXWriter( iface ); 1114 1115 TRACE("(%p)->(%d)\n", This, value); 1116 return writer_set_property(This, MXWriter_DisableEscaping, value); 1117 } 1118 1119 static HRESULT WINAPI mxwriter_get_disableOutputEscaping(IMXWriter *iface, VARIANT_BOOL *value) 1120 { 1121 mxwriter *This = impl_from_IMXWriter( iface ); 1122 1123 TRACE("(%p)->(%p)\n", This, value); 1124 return writer_get_property(This, MXWriter_DisableEscaping, value); 1125 } 1126 1127 static HRESULT WINAPI mxwriter_flush(IMXWriter *iface) 1128 { 1129 mxwriter *This = impl_from_IMXWriter( iface ); 1130 TRACE("(%p)\n", This); 1131 return flush_output_buffer(This); 1132 } 1133 1134 static const struct IMXWriterVtbl MXWriterVtbl = 1135 { 1136 mxwriter_QueryInterface, 1137 mxwriter_AddRef, 1138 mxwriter_Release, 1139 mxwriter_GetTypeInfoCount, 1140 mxwriter_GetTypeInfo, 1141 mxwriter_GetIDsOfNames, 1142 mxwriter_Invoke, 1143 mxwriter_put_output, 1144 mxwriter_get_output, 1145 mxwriter_put_encoding, 1146 mxwriter_get_encoding, 1147 mxwriter_put_byteOrderMark, 1148 mxwriter_get_byteOrderMark, 1149 mxwriter_put_indent, 1150 mxwriter_get_indent, 1151 mxwriter_put_standalone, 1152 mxwriter_get_standalone, 1153 mxwriter_put_omitXMLDeclaration, 1154 mxwriter_get_omitXMLDeclaration, 1155 mxwriter_put_version, 1156 mxwriter_get_version, 1157 mxwriter_put_disableOutputEscaping, 1158 mxwriter_get_disableOutputEscaping, 1159 mxwriter_flush 1160 }; 1161 1162 /*** ISAXContentHandler ***/ 1163 static HRESULT WINAPI SAXContentHandler_QueryInterface( 1164 ISAXContentHandler *iface, 1165 REFIID riid, 1166 void **obj) 1167 { 1168 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1169 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 1170 } 1171 1172 static ULONG WINAPI SAXContentHandler_AddRef(ISAXContentHandler *iface) 1173 { 1174 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1175 return IMXWriter_AddRef(&This->IMXWriter_iface); 1176 } 1177 1178 static ULONG WINAPI SAXContentHandler_Release(ISAXContentHandler *iface) 1179 { 1180 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1181 return IMXWriter_Release(&This->IMXWriter_iface); 1182 } 1183 1184 static HRESULT WINAPI SAXContentHandler_putDocumentLocator( 1185 ISAXContentHandler *iface, 1186 ISAXLocator *locator) 1187 { 1188 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1189 FIXME("(%p)->(%p)\n", This, locator); 1190 return E_NOTIMPL; 1191 } 1192 1193 static HRESULT WINAPI SAXContentHandler_startDocument(ISAXContentHandler *iface) 1194 { 1195 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1196 1197 TRACE("(%p)\n", This); 1198 1199 /* If properties have been changed since the last "endDocument" call 1200 * we need to reset the output buffer. If we don't the output buffer 1201 * could end up with multiple XML documents in it, plus this seems to 1202 * be how Windows works. 1203 */ 1204 if (This->prop_changed) { 1205 reset_output_buffer(This); 1206 This->prop_changed = FALSE; 1207 } 1208 1209 if (This->props[MXWriter_OmitXmlDecl] == VARIANT_TRUE) return S_OK; 1210 1211 write_prolog_buffer(This); 1212 1213 if (This->dest && This->xml_enc == XmlEncoding_UTF16) { 1214 static const char utf16BOM[] = {0xff,0xfe}; 1215 1216 if (This->props[MXWriter_BOM] == VARIANT_TRUE) 1217 /* Windows passes a NULL pointer as the pcbWritten parameter and 1218 * ignores any error codes returned from this Write call. 1219 */ 1220 IStream_Write(This->dest, utf16BOM, sizeof(utf16BOM), NULL); 1221 } 1222 1223 return S_OK; 1224 } 1225 1226 static HRESULT WINAPI SAXContentHandler_endDocument(ISAXContentHandler *iface) 1227 { 1228 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1229 TRACE("(%p)\n", This); 1230 This->prop_changed = FALSE; 1231 return flush_output_buffer(This); 1232 } 1233 1234 static HRESULT WINAPI SAXContentHandler_startPrefixMapping( 1235 ISAXContentHandler *iface, 1236 const WCHAR *prefix, 1237 int nprefix, 1238 const WCHAR *uri, 1239 int nuri) 1240 { 1241 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1242 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(prefix, nprefix), debugstr_wn(uri, nuri)); 1243 return S_OK; 1244 } 1245 1246 static HRESULT WINAPI SAXContentHandler_endPrefixMapping( 1247 ISAXContentHandler *iface, 1248 const WCHAR *prefix, 1249 int nprefix) 1250 { 1251 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1252 TRACE("(%p)->(%s)\n", This, debugstr_wn(prefix, nprefix)); 1253 return S_OK; 1254 } 1255 1256 static void mxwriter_write_attribute(mxwriter *writer, const WCHAR *qname, int qname_len, 1257 const WCHAR *value, int value_len, BOOL escape) 1258 { 1259 static const WCHAR eqW[] = {'='}; 1260 1261 /* space separator in front of every attribute */ 1262 write_output_buffer(writer, spaceW, 1); 1263 write_output_buffer(writer, qname, qname_len); 1264 write_output_buffer(writer, eqW, 1); 1265 1266 if (escape) 1267 { 1268 WCHAR *escaped = get_escaped_string(value, EscapeValue, &value_len); 1269 write_output_buffer_quoted(writer, escaped, value_len); 1270 heap_free(escaped); 1271 } 1272 else 1273 write_output_buffer_quoted(writer, value, value_len); 1274 } 1275 1276 static void mxwriter_write_starttag(mxwriter *writer, const WCHAR *qname, int len) 1277 { 1278 static const WCHAR ltW[] = {'<'}; 1279 1280 close_element_starttag(writer); 1281 set_element_name(writer, qname ? qname : emptyW, qname ? len : 0); 1282 1283 write_node_indent(writer); 1284 1285 write_output_buffer(writer, ltW, 1); 1286 write_output_buffer(writer, qname ? qname : emptyW, qname ? len : 0); 1287 writer_inc_indent(writer); 1288 } 1289 1290 static HRESULT WINAPI SAXContentHandler_startElement( 1291 ISAXContentHandler *iface, 1292 const WCHAR *namespaceUri, 1293 int nnamespaceUri, 1294 const WCHAR *local_name, 1295 int nlocal_name, 1296 const WCHAR *QName, 1297 int nQName, 1298 ISAXAttributes *attr) 1299 { 1300 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1301 1302 TRACE("(%p)->(%s %s %s %p)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), 1303 debugstr_wn(local_name, nlocal_name), debugstr_wn(QName, nQName), attr); 1304 1305 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) || 1306 (nQName == -1 && This->class_version == MSXML6)) 1307 return E_INVALIDARG; 1308 1309 mxwriter_write_starttag(This, QName, nQName); 1310 1311 if (attr) 1312 { 1313 int length, i, escape; 1314 HRESULT hr; 1315 1316 hr = ISAXAttributes_getLength(attr, &length); 1317 if (FAILED(hr)) return hr; 1318 1319 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE || 1320 (This->class_version == MSXML4 || This->class_version == MSXML6); 1321 1322 for (i = 0; i < length; i++) 1323 { 1324 int qname_len = 0, value_len = 0; 1325 const WCHAR *qname, *value; 1326 1327 hr = ISAXAttributes_getQName(attr, i, &qname, &qname_len); 1328 if (FAILED(hr)) return hr; 1329 1330 hr = ISAXAttributes_getValue(attr, i, &value, &value_len); 1331 if (FAILED(hr)) return hr; 1332 1333 mxwriter_write_attribute(This, qname, qname_len, value, value_len, escape); 1334 } 1335 } 1336 1337 return S_OK; 1338 } 1339 1340 static HRESULT WINAPI SAXContentHandler_endElement( 1341 ISAXContentHandler *iface, 1342 const WCHAR *namespaceUri, 1343 int nnamespaceUri, 1344 const WCHAR * local_name, 1345 int nlocal_name, 1346 const WCHAR *QName, 1347 int nQName) 1348 { 1349 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1350 1351 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(namespaceUri, nnamespaceUri), nnamespaceUri, 1352 debugstr_wn(local_name, nlocal_name), nlocal_name, debugstr_wn(QName, nQName), nQName); 1353 1354 if (((!namespaceUri || !local_name || !QName) && This->class_version != MSXML6) || 1355 (nQName == -1 && This->class_version == MSXML6)) 1356 return E_INVALIDARG; 1357 1358 writer_dec_indent(This); 1359 1360 if (This->element) 1361 { 1362 static const WCHAR closeW[] = {'/','>'}; 1363 write_output_buffer(This, closeW, 2); 1364 } 1365 else 1366 { 1367 static const WCHAR closetagW[] = {'<','/'}; 1368 static const WCHAR gtW[] = {'>'}; 1369 1370 write_node_indent(This); 1371 write_output_buffer(This, closetagW, 2); 1372 write_output_buffer(This, QName, nQName); 1373 write_output_buffer(This, gtW, 1); 1374 } 1375 1376 set_element_name(This, NULL, 0); 1377 1378 return S_OK; 1379 } 1380 1381 static HRESULT WINAPI SAXContentHandler_characters( 1382 ISAXContentHandler *iface, 1383 const WCHAR *chars, 1384 int nchars) 1385 { 1386 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1387 1388 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars); 1389 1390 if (!chars) return E_INVALIDARG; 1391 1392 close_element_starttag(This); 1393 set_element_name(This, NULL, 0); 1394 1395 if (!This->cdata) 1396 This->text = TRUE; 1397 1398 if (nchars) 1399 { 1400 if (This->cdata || This->props[MXWriter_DisableEscaping] == VARIANT_TRUE) 1401 write_output_buffer(This, chars, nchars); 1402 else 1403 { 1404 int len = nchars; 1405 WCHAR *escaped; 1406 1407 escaped = get_escaped_string(chars, EscapeText, &len); 1408 write_output_buffer(This, escaped, len); 1409 heap_free(escaped); 1410 } 1411 } 1412 1413 return S_OK; 1414 } 1415 1416 static HRESULT WINAPI SAXContentHandler_ignorableWhitespace( 1417 ISAXContentHandler *iface, 1418 const WCHAR *chars, 1419 int nchars) 1420 { 1421 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1422 1423 TRACE("(%p)->(%s)\n", This, debugstr_wn(chars, nchars)); 1424 1425 if (!chars) return E_INVALIDARG; 1426 1427 write_output_buffer(This, chars, nchars); 1428 1429 return S_OK; 1430 } 1431 1432 static HRESULT WINAPI SAXContentHandler_processingInstruction( 1433 ISAXContentHandler *iface, 1434 const WCHAR *target, 1435 int ntarget, 1436 const WCHAR *data, 1437 int ndata) 1438 { 1439 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1440 static const WCHAR openpiW[] = {'<','?'}; 1441 static const WCHAR closepiW[] = {'?','>','\r','\n'}; 1442 1443 TRACE("(%p)->(%s %s)\n", This, debugstr_wn(target, ntarget), debugstr_wn(data, ndata)); 1444 1445 if (!target) return E_INVALIDARG; 1446 1447 write_node_indent(This); 1448 write_output_buffer(This, openpiW, ARRAY_SIZE(openpiW)); 1449 1450 if (*target) 1451 write_output_buffer(This, target, ntarget); 1452 1453 if (data && *data && ndata) 1454 { 1455 write_output_buffer(This, spaceW, 1); 1456 write_output_buffer(This, data, ndata); 1457 } 1458 1459 write_output_buffer(This, closepiW, ARRAY_SIZE(closepiW)); 1460 This->newline = TRUE; 1461 1462 return S_OK; 1463 } 1464 1465 static HRESULT WINAPI SAXContentHandler_skippedEntity( 1466 ISAXContentHandler *iface, 1467 const WCHAR *name, 1468 int nname) 1469 { 1470 mxwriter *This = impl_from_ISAXContentHandler( iface ); 1471 FIXME("(%p)->(%s)\n", This, debugstr_wn(name, nname)); 1472 return E_NOTIMPL; 1473 } 1474 1475 static const struct ISAXContentHandlerVtbl SAXContentHandlerVtbl = 1476 { 1477 SAXContentHandler_QueryInterface, 1478 SAXContentHandler_AddRef, 1479 SAXContentHandler_Release, 1480 SAXContentHandler_putDocumentLocator, 1481 SAXContentHandler_startDocument, 1482 SAXContentHandler_endDocument, 1483 SAXContentHandler_startPrefixMapping, 1484 SAXContentHandler_endPrefixMapping, 1485 SAXContentHandler_startElement, 1486 SAXContentHandler_endElement, 1487 SAXContentHandler_characters, 1488 SAXContentHandler_ignorableWhitespace, 1489 SAXContentHandler_processingInstruction, 1490 SAXContentHandler_skippedEntity 1491 }; 1492 1493 /*** ISAXLexicalHandler ***/ 1494 static HRESULT WINAPI SAXLexicalHandler_QueryInterface(ISAXLexicalHandler *iface, 1495 REFIID riid, void **obj) 1496 { 1497 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1498 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 1499 } 1500 1501 static ULONG WINAPI SAXLexicalHandler_AddRef(ISAXLexicalHandler *iface) 1502 { 1503 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1504 return IMXWriter_AddRef(&This->IMXWriter_iface); 1505 } 1506 1507 static ULONG WINAPI SAXLexicalHandler_Release(ISAXLexicalHandler *iface) 1508 { 1509 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1510 return IMXWriter_Release(&This->IMXWriter_iface); 1511 } 1512 1513 static HRESULT WINAPI SAXLexicalHandler_startDTD(ISAXLexicalHandler *iface, 1514 const WCHAR *name, int name_len, const WCHAR *publicId, int publicId_len, 1515 const WCHAR *systemId, int systemId_len) 1516 { 1517 static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '}; 1518 static const WCHAR openintW[] = {'[','\r','\n'}; 1519 1520 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1521 1522 TRACE("(%p)->(%s %s %s)\n", This, debugstr_wn(name, name_len), debugstr_wn(publicId, publicId_len), 1523 debugstr_wn(systemId, systemId_len)); 1524 1525 if (!name) return E_INVALIDARG; 1526 1527 write_output_buffer(This, doctypeW, ARRAY_SIZE(doctypeW)); 1528 1529 if (*name) 1530 { 1531 write_output_buffer(This, name, name_len); 1532 write_output_buffer(This, spaceW, 1); 1533 } 1534 1535 if (publicId) 1536 { 1537 write_output_buffer(This, publicW, ARRAY_SIZE(publicW)); 1538 write_output_buffer_quoted(This, publicId, publicId_len); 1539 1540 if (!systemId) return E_INVALIDARG; 1541 1542 if (*publicId) 1543 write_output_buffer(This, spaceW, 1); 1544 1545 write_output_buffer_quoted(This, systemId, systemId_len); 1546 1547 if (*systemId) 1548 write_output_buffer(This, spaceW, 1); 1549 } 1550 else if (systemId) 1551 { 1552 write_output_buffer(This, systemW, ARRAY_SIZE(systemW)); 1553 write_output_buffer_quoted(This, systemId, systemId_len); 1554 if (*systemId) 1555 write_output_buffer(This, spaceW, 1); 1556 } 1557 1558 write_output_buffer(This, openintW, ARRAY_SIZE(openintW)); 1559 1560 return S_OK; 1561 } 1562 1563 static HRESULT WINAPI SAXLexicalHandler_endDTD(ISAXLexicalHandler *iface) 1564 { 1565 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1566 static const WCHAR closedtdW[] = {']','>','\r','\n'}; 1567 1568 TRACE("(%p)\n", This); 1569 1570 write_output_buffer(This, closedtdW, ARRAY_SIZE(closedtdW)); 1571 1572 return S_OK; 1573 } 1574 1575 static HRESULT WINAPI SAXLexicalHandler_startEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len) 1576 { 1577 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1578 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len)); 1579 return E_NOTIMPL; 1580 } 1581 1582 static HRESULT WINAPI SAXLexicalHandler_endEntity(ISAXLexicalHandler *iface, const WCHAR *name, int len) 1583 { 1584 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1585 FIXME("(%p)->(%s): stub\n", This, debugstr_wn(name, len)); 1586 return E_NOTIMPL; 1587 } 1588 1589 static HRESULT WINAPI SAXLexicalHandler_startCDATA(ISAXLexicalHandler *iface) 1590 { 1591 static const WCHAR scdataW[] = {'<','!','[','C','D','A','T','A','['}; 1592 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1593 1594 TRACE("(%p)\n", This); 1595 1596 write_node_indent(This); 1597 write_output_buffer(This, scdataW, ARRAY_SIZE(scdataW)); 1598 This->cdata = TRUE; 1599 1600 return S_OK; 1601 } 1602 1603 static HRESULT WINAPI SAXLexicalHandler_endCDATA(ISAXLexicalHandler *iface) 1604 { 1605 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1606 static const WCHAR ecdataW[] = {']',']','>'}; 1607 1608 TRACE("(%p)\n", This); 1609 1610 write_output_buffer(This, ecdataW, ARRAY_SIZE(ecdataW)); 1611 This->cdata = FALSE; 1612 1613 return S_OK; 1614 } 1615 1616 static HRESULT WINAPI SAXLexicalHandler_comment(ISAXLexicalHandler *iface, const WCHAR *chars, int nchars) 1617 { 1618 mxwriter *This = impl_from_ISAXLexicalHandler( iface ); 1619 static const WCHAR copenW[] = {'<','!','-','-'}; 1620 static const WCHAR ccloseW[] = {'-','-','>','\r','\n'}; 1621 1622 TRACE("(%p)->(%s:%d)\n", This, debugstr_wn(chars, nchars), nchars); 1623 1624 if (!chars) return E_INVALIDARG; 1625 1626 close_element_starttag(This); 1627 write_node_indent(This); 1628 1629 write_output_buffer(This, copenW, ARRAY_SIZE(copenW)); 1630 if (nchars) 1631 write_output_buffer(This, chars, nchars); 1632 write_output_buffer(This, ccloseW, ARRAY_SIZE(ccloseW)); 1633 1634 return S_OK; 1635 } 1636 1637 static const struct ISAXLexicalHandlerVtbl SAXLexicalHandlerVtbl = 1638 { 1639 SAXLexicalHandler_QueryInterface, 1640 SAXLexicalHandler_AddRef, 1641 SAXLexicalHandler_Release, 1642 SAXLexicalHandler_startDTD, 1643 SAXLexicalHandler_endDTD, 1644 SAXLexicalHandler_startEntity, 1645 SAXLexicalHandler_endEntity, 1646 SAXLexicalHandler_startCDATA, 1647 SAXLexicalHandler_endCDATA, 1648 SAXLexicalHandler_comment 1649 }; 1650 1651 /*** ISAXDeclHandler ***/ 1652 static HRESULT WINAPI SAXDeclHandler_QueryInterface(ISAXDeclHandler *iface, 1653 REFIID riid, void **obj) 1654 { 1655 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1656 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 1657 } 1658 1659 static ULONG WINAPI SAXDeclHandler_AddRef(ISAXDeclHandler *iface) 1660 { 1661 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1662 return IMXWriter_AddRef(&This->IMXWriter_iface); 1663 } 1664 1665 static ULONG WINAPI SAXDeclHandler_Release(ISAXDeclHandler *iface) 1666 { 1667 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1668 return IMXWriter_Release(&This->IMXWriter_iface); 1669 } 1670 1671 static HRESULT WINAPI SAXDeclHandler_elementDecl(ISAXDeclHandler *iface, 1672 const WCHAR *name, int n_name, const WCHAR *model, int n_model) 1673 { 1674 static const WCHAR elementW[] = {'<','!','E','L','E','M','E','N','T',' '}; 1675 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1676 1677 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name, 1678 debugstr_wn(model, n_model), n_model); 1679 1680 if (!name || !model) return E_INVALIDARG; 1681 1682 write_output_buffer(This, elementW, ARRAY_SIZE(elementW)); 1683 if (n_name) { 1684 write_output_buffer(This, name, n_name); 1685 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1686 } 1687 if (n_model) 1688 write_output_buffer(This, model, n_model); 1689 write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW)); 1690 1691 return S_OK; 1692 } 1693 1694 static HRESULT WINAPI SAXDeclHandler_attributeDecl(ISAXDeclHandler *iface, 1695 const WCHAR *element, int n_element, const WCHAR *attr, int n_attr, 1696 const WCHAR *type, int n_type, const WCHAR *Default, int n_default, 1697 const WCHAR *value, int n_value) 1698 { 1699 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1700 static const WCHAR attlistW[] = {'<','!','A','T','T','L','I','S','T',' '}; 1701 static const WCHAR closetagW[] = {'>','\r','\n'}; 1702 1703 TRACE("(%p)->(%s:%d %s:%d %s:%d %s:%d %s:%d)\n", This, debugstr_wn(element, n_element), n_element, 1704 debugstr_wn(attr, n_attr), n_attr, debugstr_wn(type, n_type), n_type, debugstr_wn(Default, n_default), n_default, 1705 debugstr_wn(value, n_value), n_value); 1706 1707 write_output_buffer(This, attlistW, ARRAY_SIZE(attlistW)); 1708 if (n_element) { 1709 write_output_buffer(This, element, n_element); 1710 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1711 } 1712 1713 if (n_attr) { 1714 write_output_buffer(This, attr, n_attr); 1715 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1716 } 1717 1718 if (n_type) { 1719 write_output_buffer(This, type, n_type); 1720 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1721 } 1722 1723 if (n_default) { 1724 write_output_buffer(This, Default, n_default); 1725 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1726 } 1727 1728 if (n_value) 1729 write_output_buffer_quoted(This, value, n_value); 1730 1731 write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW)); 1732 1733 return S_OK; 1734 } 1735 1736 static HRESULT WINAPI SAXDeclHandler_internalEntityDecl(ISAXDeclHandler *iface, 1737 const WCHAR *name, int n_name, const WCHAR *value, int n_value) 1738 { 1739 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1740 1741 TRACE("(%p)->(%s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name, 1742 debugstr_wn(value, n_value), n_value); 1743 1744 if (!name || !value) return E_INVALIDARG; 1745 1746 write_output_buffer(This, entityW, ARRAY_SIZE(entityW)); 1747 if (n_name) { 1748 write_output_buffer(This, name, n_name); 1749 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1750 } 1751 1752 if (n_value) 1753 write_output_buffer_quoted(This, value, n_value); 1754 1755 write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW)); 1756 1757 return S_OK; 1758 } 1759 1760 static HRESULT WINAPI SAXDeclHandler_externalEntityDecl(ISAXDeclHandler *iface, 1761 const WCHAR *name, int n_name, const WCHAR *publicId, int n_publicId, 1762 const WCHAR *systemId, int n_systemId) 1763 { 1764 mxwriter *This = impl_from_ISAXDeclHandler( iface ); 1765 1766 TRACE("(%p)->(%s:%d %s:%d %s:%d)\n", This, debugstr_wn(name, n_name), n_name, 1767 debugstr_wn(publicId, n_publicId), n_publicId, debugstr_wn(systemId, n_systemId), n_systemId); 1768 1769 if (!name || !systemId) return E_INVALIDARG; 1770 1771 write_output_buffer(This, entityW, ARRAY_SIZE(entityW)); 1772 if (n_name) { 1773 write_output_buffer(This, name, n_name); 1774 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1775 } 1776 1777 if (publicId) 1778 { 1779 write_output_buffer(This, publicW, ARRAY_SIZE(publicW)); 1780 write_output_buffer_quoted(This, publicId, n_publicId); 1781 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 1782 write_output_buffer_quoted(This, systemId, n_systemId); 1783 } 1784 else 1785 { 1786 write_output_buffer(This, systemW, ARRAY_SIZE(systemW)); 1787 write_output_buffer_quoted(This, systemId, n_systemId); 1788 } 1789 1790 write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW)); 1791 1792 return S_OK; 1793 } 1794 1795 static const ISAXDeclHandlerVtbl SAXDeclHandlerVtbl = { 1796 SAXDeclHandler_QueryInterface, 1797 SAXDeclHandler_AddRef, 1798 SAXDeclHandler_Release, 1799 SAXDeclHandler_elementDecl, 1800 SAXDeclHandler_attributeDecl, 1801 SAXDeclHandler_internalEntityDecl, 1802 SAXDeclHandler_externalEntityDecl 1803 }; 1804 1805 /*** IVBSAXDeclHandler ***/ 1806 static HRESULT WINAPI VBSAXDeclHandler_QueryInterface(IVBSAXDeclHandler *iface, 1807 REFIID riid, void **obj) 1808 { 1809 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1810 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 1811 } 1812 1813 static ULONG WINAPI VBSAXDeclHandler_AddRef(IVBSAXDeclHandler *iface) 1814 { 1815 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1816 return IMXWriter_AddRef(&This->IMXWriter_iface); 1817 } 1818 1819 static ULONG WINAPI VBSAXDeclHandler_Release(IVBSAXDeclHandler *iface) 1820 { 1821 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1822 return IMXWriter_Release(&This->IMXWriter_iface); 1823 } 1824 1825 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfoCount(IVBSAXDeclHandler *iface, UINT* pctinfo) 1826 { 1827 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1828 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo); 1829 } 1830 1831 static HRESULT WINAPI VBSAXDeclHandler_GetTypeInfo(IVBSAXDeclHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 1832 { 1833 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1834 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo); 1835 } 1836 1837 static HRESULT WINAPI VBSAXDeclHandler_GetIDsOfNames(IVBSAXDeclHandler *iface, REFIID riid, LPOLESTR* rgszNames, 1838 UINT cNames, LCID lcid, DISPID* rgDispId ) 1839 { 1840 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1841 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId); 1842 } 1843 1844 static HRESULT WINAPI VBSAXDeclHandler_Invoke(IVBSAXDeclHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid, 1845 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) 1846 { 1847 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1848 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, 1849 pExcepInfo, puArgErr); 1850 } 1851 1852 static HRESULT WINAPI VBSAXDeclHandler_elementDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *model) 1853 { 1854 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1855 1856 TRACE("(%p)->(%p %p)\n", This, name, model); 1857 1858 if (!name || !model) 1859 return E_POINTER; 1860 1861 return ISAXDeclHandler_elementDecl(&This->ISAXDeclHandler_iface, *name, -1, *model, -1); 1862 } 1863 1864 static HRESULT WINAPI VBSAXDeclHandler_attributeDecl(IVBSAXDeclHandler *iface, 1865 BSTR *element, BSTR *attr, BSTR *type, BSTR *default_value, BSTR *value) 1866 { 1867 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1868 1869 TRACE("(%p)->(%p %p %p %p %p)\n", This, element, attr, type, default_value, value); 1870 1871 if (!element || !attr || !type || !default_value || !value) 1872 return E_POINTER; 1873 1874 return ISAXDeclHandler_attributeDecl(&This->ISAXDeclHandler_iface, *element, -1, *attr, -1, *type, -1, 1875 *default_value, -1, *value, -1); 1876 } 1877 1878 static HRESULT WINAPI VBSAXDeclHandler_internalEntityDecl(IVBSAXDeclHandler *iface, BSTR *name, BSTR *value) 1879 { 1880 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1881 1882 TRACE("(%p)->(%p %p)\n", This, name, value); 1883 1884 if (!name || !value) 1885 return E_POINTER; 1886 1887 return ISAXDeclHandler_internalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *value, -1); 1888 } 1889 1890 static HRESULT WINAPI VBSAXDeclHandler_externalEntityDecl(IVBSAXDeclHandler *iface, 1891 BSTR *name, BSTR *publicid, BSTR *systemid) 1892 { 1893 mxwriter *This = impl_from_IVBSAXDeclHandler( iface ); 1894 1895 TRACE("(%p)->(%p %p %p)\n", This, name, publicid, systemid); 1896 1897 if (!name || !publicid || !systemid) 1898 return E_POINTER; 1899 1900 return ISAXDeclHandler_externalEntityDecl(&This->ISAXDeclHandler_iface, *name, -1, *publicid, -1, *systemid, -1); 1901 } 1902 1903 static const IVBSAXDeclHandlerVtbl VBSAXDeclHandlerVtbl = { 1904 VBSAXDeclHandler_QueryInterface, 1905 VBSAXDeclHandler_AddRef, 1906 VBSAXDeclHandler_Release, 1907 VBSAXDeclHandler_GetTypeInfoCount, 1908 VBSAXDeclHandler_GetTypeInfo, 1909 VBSAXDeclHandler_GetIDsOfNames, 1910 VBSAXDeclHandler_Invoke, 1911 VBSAXDeclHandler_elementDecl, 1912 VBSAXDeclHandler_attributeDecl, 1913 VBSAXDeclHandler_internalEntityDecl, 1914 VBSAXDeclHandler_externalEntityDecl 1915 }; 1916 1917 /*** IVBSAXLexicalHandler ***/ 1918 static HRESULT WINAPI VBSAXLexicalHandler_QueryInterface(IVBSAXLexicalHandler *iface, 1919 REFIID riid, void **obj) 1920 { 1921 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1922 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 1923 } 1924 1925 static ULONG WINAPI VBSAXLexicalHandler_AddRef(IVBSAXLexicalHandler *iface) 1926 { 1927 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1928 return IMXWriter_AddRef(&This->IMXWriter_iface); 1929 } 1930 1931 static ULONG WINAPI VBSAXLexicalHandler_Release(IVBSAXLexicalHandler *iface) 1932 { 1933 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1934 return IMXWriter_Release(&This->IMXWriter_iface); 1935 } 1936 1937 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfoCount(IVBSAXLexicalHandler *iface, UINT* pctinfo) 1938 { 1939 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1940 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo); 1941 } 1942 1943 static HRESULT WINAPI VBSAXLexicalHandler_GetTypeInfo(IVBSAXLexicalHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 1944 { 1945 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1946 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo); 1947 } 1948 1949 static HRESULT WINAPI VBSAXLexicalHandler_GetIDsOfNames(IVBSAXLexicalHandler *iface, REFIID riid, LPOLESTR* rgszNames, 1950 UINT cNames, LCID lcid, DISPID* rgDispId ) 1951 { 1952 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1953 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId); 1954 } 1955 1956 static HRESULT WINAPI VBSAXLexicalHandler_Invoke(IVBSAXLexicalHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid, 1957 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) 1958 { 1959 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1960 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, 1961 pExcepInfo, puArgErr); 1962 } 1963 1964 static HRESULT WINAPI VBSAXLexicalHandler_startDTD(IVBSAXLexicalHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId) 1965 { 1966 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1967 1968 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId); 1969 1970 if (!name || !publicId || !systemId) 1971 return E_POINTER; 1972 1973 return ISAXLexicalHandler_startDTD(&This->ISAXLexicalHandler_iface, *name, -1, *publicId, -1, *systemId, -1); 1974 } 1975 1976 static HRESULT WINAPI VBSAXLexicalHandler_endDTD(IVBSAXLexicalHandler *iface) 1977 { 1978 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1979 return ISAXLexicalHandler_endDTD(&This->ISAXLexicalHandler_iface); 1980 } 1981 1982 static HRESULT WINAPI VBSAXLexicalHandler_startEntity(IVBSAXLexicalHandler *iface, BSTR *name) 1983 { 1984 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1985 1986 TRACE("(%p)->(%p)\n", This, name); 1987 1988 if (!name) 1989 return E_POINTER; 1990 1991 return ISAXLexicalHandler_startEntity(&This->ISAXLexicalHandler_iface, *name, -1); 1992 } 1993 1994 static HRESULT WINAPI VBSAXLexicalHandler_endEntity(IVBSAXLexicalHandler *iface, BSTR *name) 1995 { 1996 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 1997 1998 TRACE("(%p)->(%p)\n", This, name); 1999 2000 if (!name) 2001 return E_POINTER; 2002 2003 return ISAXLexicalHandler_endEntity(&This->ISAXLexicalHandler_iface, *name, -1); 2004 } 2005 2006 static HRESULT WINAPI VBSAXLexicalHandler_startCDATA(IVBSAXLexicalHandler *iface) 2007 { 2008 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 2009 return ISAXLexicalHandler_startCDATA(&This->ISAXLexicalHandler_iface); 2010 } 2011 2012 static HRESULT WINAPI VBSAXLexicalHandler_endCDATA(IVBSAXLexicalHandler *iface) 2013 { 2014 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 2015 return ISAXLexicalHandler_endCDATA(&This->ISAXLexicalHandler_iface); 2016 } 2017 2018 static HRESULT WINAPI VBSAXLexicalHandler_comment(IVBSAXLexicalHandler *iface, BSTR *chars) 2019 { 2020 mxwriter *This = impl_from_IVBSAXLexicalHandler( iface ); 2021 2022 TRACE("(%p)->(%p)\n", This, chars); 2023 2024 if (!chars) 2025 return E_POINTER; 2026 2027 return ISAXLexicalHandler_comment(&This->ISAXLexicalHandler_iface, *chars, -1); 2028 } 2029 2030 static const IVBSAXLexicalHandlerVtbl VBSAXLexicalHandlerVtbl = { 2031 VBSAXLexicalHandler_QueryInterface, 2032 VBSAXLexicalHandler_AddRef, 2033 VBSAXLexicalHandler_Release, 2034 VBSAXLexicalHandler_GetTypeInfoCount, 2035 VBSAXLexicalHandler_GetTypeInfo, 2036 VBSAXLexicalHandler_GetIDsOfNames, 2037 VBSAXLexicalHandler_Invoke, 2038 VBSAXLexicalHandler_startDTD, 2039 VBSAXLexicalHandler_endDTD, 2040 VBSAXLexicalHandler_startEntity, 2041 VBSAXLexicalHandler_endEntity, 2042 VBSAXLexicalHandler_startCDATA, 2043 VBSAXLexicalHandler_endCDATA, 2044 VBSAXLexicalHandler_comment 2045 }; 2046 2047 /*** IVBSAXContentHandler ***/ 2048 static HRESULT WINAPI VBSAXContentHandler_QueryInterface(IVBSAXContentHandler *iface, REFIID riid, void **obj) 2049 { 2050 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2051 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 2052 } 2053 2054 static ULONG WINAPI VBSAXContentHandler_AddRef(IVBSAXContentHandler *iface) 2055 { 2056 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2057 return IMXWriter_AddRef(&This->IMXWriter_iface); 2058 } 2059 2060 static ULONG WINAPI VBSAXContentHandler_Release(IVBSAXContentHandler *iface) 2061 { 2062 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2063 return IMXWriter_Release(&This->IMXWriter_iface); 2064 } 2065 2066 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfoCount(IVBSAXContentHandler *iface, UINT* pctinfo) 2067 { 2068 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2069 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo); 2070 } 2071 2072 static HRESULT WINAPI VBSAXContentHandler_GetTypeInfo(IVBSAXContentHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 2073 { 2074 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2075 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo); 2076 } 2077 2078 static HRESULT WINAPI VBSAXContentHandler_GetIDsOfNames(IVBSAXContentHandler *iface, REFIID riid, LPOLESTR* rgszNames, 2079 UINT cNames, LCID lcid, DISPID* rgDispId ) 2080 { 2081 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2082 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId); 2083 } 2084 2085 static HRESULT WINAPI VBSAXContentHandler_Invoke(IVBSAXContentHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid, 2086 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) 2087 { 2088 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2089 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, 2090 pExcepInfo, puArgErr); 2091 } 2092 2093 static HRESULT WINAPI VBSAXContentHandler_putref_documentLocator(IVBSAXContentHandler *iface, IVBSAXLocator *locator) 2094 { 2095 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2096 TRACE("(%p)->(%p)\n", This, locator); 2097 return S_OK; 2098 } 2099 2100 static HRESULT WINAPI VBSAXContentHandler_startDocument(IVBSAXContentHandler *iface) 2101 { 2102 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2103 return ISAXContentHandler_startDocument(&This->ISAXContentHandler_iface); 2104 } 2105 2106 static HRESULT WINAPI VBSAXContentHandler_endDocument(IVBSAXContentHandler *iface) 2107 { 2108 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2109 return ISAXContentHandler_endDocument(&This->ISAXContentHandler_iface); 2110 } 2111 2112 static HRESULT WINAPI VBSAXContentHandler_startPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix, BSTR *uri) 2113 { 2114 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2115 2116 TRACE("(%p)->(%p %p)\n", This, prefix, uri); 2117 2118 if (!prefix || !uri) 2119 return E_POINTER; 2120 2121 return ISAXContentHandler_startPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1, *uri, -1); 2122 } 2123 2124 static HRESULT WINAPI VBSAXContentHandler_endPrefixMapping(IVBSAXContentHandler *iface, BSTR *prefix) 2125 { 2126 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2127 2128 TRACE("(%p)->(%p)\n", This, prefix); 2129 2130 if (!prefix) 2131 return E_POINTER; 2132 2133 return ISAXContentHandler_endPrefixMapping(&This->ISAXContentHandler_iface, *prefix, -1); 2134 } 2135 2136 static HRESULT WINAPI VBSAXContentHandler_startElement(IVBSAXContentHandler *iface, 2137 BSTR *namespaceURI, BSTR *localName, BSTR *QName, IVBSAXAttributes *attrs) 2138 { 2139 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2140 2141 TRACE("(%p)->(%p %p %p %p)\n", This, namespaceURI, localName, QName, attrs); 2142 2143 if (!namespaceURI || !localName || !QName) 2144 return E_POINTER; 2145 2146 TRACE("(%s %s %s)\n", debugstr_w(*namespaceURI), debugstr_w(*localName), debugstr_w(*QName)); 2147 2148 mxwriter_write_starttag(This, *QName, SysStringLen(*QName)); 2149 2150 if (attrs) 2151 { 2152 int length, i, escape; 2153 HRESULT hr; 2154 2155 hr = IVBSAXAttributes_get_length(attrs, &length); 2156 if (FAILED(hr)) return hr; 2157 2158 escape = This->props[MXWriter_DisableEscaping] == VARIANT_FALSE || 2159 (This->class_version == MSXML4 || This->class_version == MSXML6); 2160 2161 for (i = 0; i < length; i++) 2162 { 2163 BSTR qname, value; 2164 2165 hr = IVBSAXAttributes_getQName(attrs, i, &qname); 2166 if (FAILED(hr)) return hr; 2167 2168 hr = IVBSAXAttributes_getValue(attrs, i, &value); 2169 if (FAILED(hr)) 2170 { 2171 SysFreeString(qname); 2172 return hr; 2173 } 2174 2175 mxwriter_write_attribute(This, qname, SysStringLen(qname), value, SysStringLen(value), escape); 2176 SysFreeString(qname); 2177 SysFreeString(value); 2178 } 2179 } 2180 2181 return S_OK; 2182 } 2183 2184 static HRESULT WINAPI VBSAXContentHandler_endElement(IVBSAXContentHandler *iface, BSTR *namespaceURI, 2185 BSTR *localName, BSTR *QName) 2186 { 2187 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2188 2189 TRACE("(%p)->(%p %p %p)\n", This, namespaceURI, localName, QName); 2190 2191 if (!namespaceURI || !localName || !QName) 2192 return E_POINTER; 2193 2194 return ISAXContentHandler_endElement(&This->ISAXContentHandler_iface, 2195 *namespaceURI, SysStringLen(*namespaceURI), 2196 *localName, SysStringLen(*localName), 2197 *QName, SysStringLen(*QName)); 2198 } 2199 2200 static HRESULT WINAPI VBSAXContentHandler_characters(IVBSAXContentHandler *iface, BSTR *chars) 2201 { 2202 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2203 2204 TRACE("(%p)->(%p)\n", This, chars); 2205 2206 if (!chars) 2207 return E_POINTER; 2208 2209 return ISAXContentHandler_characters(&This->ISAXContentHandler_iface, *chars, SysStringLen(*chars)); 2210 } 2211 2212 static HRESULT WINAPI VBSAXContentHandler_ignorableWhitespace(IVBSAXContentHandler *iface, BSTR *chars) 2213 { 2214 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2215 2216 TRACE("(%p)->(%p)\n", This, chars); 2217 2218 if (!chars) 2219 return E_POINTER; 2220 2221 return ISAXContentHandler_ignorableWhitespace(&This->ISAXContentHandler_iface, *chars, -1); 2222 } 2223 2224 static HRESULT WINAPI VBSAXContentHandler_processingInstruction(IVBSAXContentHandler *iface, 2225 BSTR *target, BSTR *data) 2226 { 2227 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2228 2229 TRACE("(%p)->(%p %p)\n", This, target, data); 2230 2231 if (!target || !data) 2232 return E_POINTER; 2233 2234 return ISAXContentHandler_processingInstruction(&This->ISAXContentHandler_iface, *target, -1, *data, -1); 2235 } 2236 2237 static HRESULT WINAPI VBSAXContentHandler_skippedEntity(IVBSAXContentHandler *iface, BSTR *name) 2238 { 2239 mxwriter *This = impl_from_IVBSAXContentHandler( iface ); 2240 2241 TRACE("(%p)->(%p)\n", This, name); 2242 2243 if (!name) 2244 return E_POINTER; 2245 2246 return ISAXContentHandler_skippedEntity(&This->ISAXContentHandler_iface, *name, -1); 2247 } 2248 2249 static const IVBSAXContentHandlerVtbl VBSAXContentHandlerVtbl = { 2250 VBSAXContentHandler_QueryInterface, 2251 VBSAXContentHandler_AddRef, 2252 VBSAXContentHandler_Release, 2253 VBSAXContentHandler_GetTypeInfoCount, 2254 VBSAXContentHandler_GetTypeInfo, 2255 VBSAXContentHandler_GetIDsOfNames, 2256 VBSAXContentHandler_Invoke, 2257 VBSAXContentHandler_putref_documentLocator, 2258 VBSAXContentHandler_startDocument, 2259 VBSAXContentHandler_endDocument, 2260 VBSAXContentHandler_startPrefixMapping, 2261 VBSAXContentHandler_endPrefixMapping, 2262 VBSAXContentHandler_startElement, 2263 VBSAXContentHandler_endElement, 2264 VBSAXContentHandler_characters, 2265 VBSAXContentHandler_ignorableWhitespace, 2266 VBSAXContentHandler_processingInstruction, 2267 VBSAXContentHandler_skippedEntity 2268 }; 2269 2270 static HRESULT WINAPI SAXDTDHandler_QueryInterface(ISAXDTDHandler *iface, REFIID riid, void **obj) 2271 { 2272 mxwriter *This = impl_from_ISAXDTDHandler( iface ); 2273 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 2274 } 2275 2276 static ULONG WINAPI SAXDTDHandler_AddRef(ISAXDTDHandler *iface) 2277 { 2278 mxwriter *This = impl_from_ISAXDTDHandler( iface ); 2279 return IMXWriter_AddRef(&This->IMXWriter_iface); 2280 } 2281 2282 static ULONG WINAPI SAXDTDHandler_Release(ISAXDTDHandler *iface) 2283 { 2284 mxwriter *This = impl_from_ISAXDTDHandler( iface ); 2285 return IMXWriter_Release(&This->IMXWriter_iface); 2286 } 2287 2288 static HRESULT WINAPI SAXDTDHandler_notationDecl(ISAXDTDHandler *iface, 2289 const WCHAR *name, INT n_name, 2290 const WCHAR *publicid, INT n_publicid, 2291 const WCHAR *systemid, INT n_systemid) 2292 { 2293 static const WCHAR notationW[] = {'<','!','N','O','T','A','T','I','O','N',' '}; 2294 mxwriter *This = impl_from_ISAXDTDHandler( iface ); 2295 2296 TRACE("(%p)->(%s:%d, %s:%d, %s:%d)\n", This, debugstr_wn(name, n_name), n_name, 2297 debugstr_wn(publicid, n_publicid), n_publicid, debugstr_wn(systemid, n_systemid), n_systemid); 2298 2299 if (!name || !n_name) 2300 return E_INVALIDARG; 2301 2302 write_output_buffer(This, notationW, ARRAY_SIZE(notationW)); 2303 write_output_buffer(This, name, n_name); 2304 2305 if (!publicid && !systemid) 2306 return E_INVALIDARG; 2307 2308 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 2309 if (publicid) 2310 { 2311 write_output_buffer(This, publicW, ARRAY_SIZE(publicW)); 2312 write_output_buffer_quoted(This, publicid, n_publicid); 2313 if (systemid) 2314 { 2315 write_output_buffer(This, spaceW, ARRAY_SIZE(spaceW)); 2316 write_output_buffer_quoted(This, systemid, n_systemid); 2317 } 2318 } 2319 else 2320 { 2321 write_output_buffer(This, systemW, ARRAY_SIZE(systemW)); 2322 write_output_buffer_quoted(This, systemid, n_systemid); 2323 } 2324 2325 write_output_buffer(This, closetagW, ARRAY_SIZE(closetagW)); 2326 2327 return S_OK; 2328 } 2329 2330 static HRESULT WINAPI SAXDTDHandler_unparsedEntityDecl(ISAXDTDHandler *iface, 2331 const WCHAR *name, INT nname, 2332 const WCHAR *publicid, INT npublicid, 2333 const WCHAR *systemid, INT nsystemid, 2334 const WCHAR *notation, INT nnotation) 2335 { 2336 mxwriter *This = impl_from_ISAXDTDHandler( iface ); 2337 FIXME("(%p)->(%s:%d, %s:%d, %s:%d, %s:%d): stub\n", This, debugstr_wn(name, nname), nname, 2338 debugstr_wn(publicid, npublicid), npublicid, debugstr_wn(systemid, nsystemid), nsystemid, 2339 debugstr_wn(notation, nnotation), nnotation); 2340 return E_NOTIMPL; 2341 } 2342 2343 static const ISAXDTDHandlerVtbl SAXDTDHandlerVtbl = { 2344 SAXDTDHandler_QueryInterface, 2345 SAXDTDHandler_AddRef, 2346 SAXDTDHandler_Release, 2347 SAXDTDHandler_notationDecl, 2348 SAXDTDHandler_unparsedEntityDecl 2349 }; 2350 2351 /*** IVBSAXDTDHandler ***/ 2352 static HRESULT WINAPI VBSAXDTDHandler_QueryInterface(IVBSAXDTDHandler *iface, REFIID riid, void **obj) 2353 { 2354 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2355 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 2356 } 2357 2358 static ULONG WINAPI VBSAXDTDHandler_AddRef(IVBSAXDTDHandler *iface) 2359 { 2360 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2361 return IMXWriter_AddRef(&This->IMXWriter_iface); 2362 } 2363 2364 static ULONG WINAPI VBSAXDTDHandler_Release(IVBSAXDTDHandler *iface) 2365 { 2366 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2367 return IMXWriter_Release(&This->IMXWriter_iface); 2368 } 2369 2370 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfoCount(IVBSAXDTDHandler *iface, UINT* pctinfo) 2371 { 2372 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2373 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo); 2374 } 2375 2376 static HRESULT WINAPI VBSAXDTDHandler_GetTypeInfo(IVBSAXDTDHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 2377 { 2378 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2379 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo); 2380 } 2381 2382 static HRESULT WINAPI VBSAXDTDHandler_GetIDsOfNames(IVBSAXDTDHandler *iface, REFIID riid, LPOLESTR* rgszNames, 2383 UINT cNames, LCID lcid, DISPID* rgDispId ) 2384 { 2385 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2386 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId); 2387 } 2388 2389 static HRESULT WINAPI VBSAXDTDHandler_Invoke(IVBSAXDTDHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid, 2390 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) 2391 { 2392 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2393 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, 2394 pExcepInfo, puArgErr); 2395 } 2396 2397 static HRESULT WINAPI VBSAXDTDHandler_notationDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId, BSTR *systemId) 2398 { 2399 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2400 2401 TRACE("(%p)->(%p %p %p)\n", This, name, publicId, systemId); 2402 2403 if (!name || !publicId || !systemId) 2404 return E_POINTER; 2405 2406 return ISAXDTDHandler_notationDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1, *systemId, -1); 2407 } 2408 2409 static HRESULT WINAPI VBSAXDTDHandler_unparsedEntityDecl(IVBSAXDTDHandler *iface, BSTR *name, BSTR *publicId, 2410 BSTR *systemId, BSTR *notation) 2411 { 2412 mxwriter *This = impl_from_IVBSAXDTDHandler( iface ); 2413 2414 TRACE("(%p)->(%p %p %p %p)\n", This, name, publicId, systemId, notation); 2415 2416 if (!name || !publicId || !systemId || !notation) 2417 return E_POINTER; 2418 2419 return ISAXDTDHandler_unparsedEntityDecl(&This->ISAXDTDHandler_iface, *name, -1, *publicId, -1, 2420 *systemId, -1, *notation, -1); 2421 } 2422 2423 static const IVBSAXDTDHandlerVtbl VBSAXDTDHandlerVtbl = { 2424 VBSAXDTDHandler_QueryInterface, 2425 VBSAXDTDHandler_AddRef, 2426 VBSAXDTDHandler_Release, 2427 VBSAXDTDHandler_GetTypeInfoCount, 2428 VBSAXDTDHandler_GetTypeInfo, 2429 VBSAXDTDHandler_GetIDsOfNames, 2430 VBSAXDTDHandler_Invoke, 2431 VBSAXDTDHandler_notationDecl, 2432 VBSAXDTDHandler_unparsedEntityDecl 2433 }; 2434 2435 /* ISAXErrorHandler */ 2436 static HRESULT WINAPI SAXErrorHandler_QueryInterface(ISAXErrorHandler *iface, REFIID riid, void **obj) 2437 { 2438 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2439 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 2440 } 2441 2442 static ULONG WINAPI SAXErrorHandler_AddRef(ISAXErrorHandler *iface) 2443 { 2444 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2445 return IMXWriter_AddRef(&This->IMXWriter_iface); 2446 } 2447 2448 static ULONG WINAPI SAXErrorHandler_Release(ISAXErrorHandler *iface) 2449 { 2450 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2451 return IMXWriter_Release(&This->IMXWriter_iface); 2452 } 2453 2454 static HRESULT WINAPI SAXErrorHandler_error(ISAXErrorHandler *iface, 2455 ISAXLocator *locator, const WCHAR *message, HRESULT hr) 2456 { 2457 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2458 2459 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr); 2460 2461 return E_NOTIMPL; 2462 } 2463 2464 static HRESULT WINAPI SAXErrorHandler_fatalError(ISAXErrorHandler *iface, 2465 ISAXLocator *locator, const WCHAR *message, HRESULT hr) 2466 { 2467 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2468 2469 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr); 2470 2471 return E_NOTIMPL; 2472 } 2473 2474 static HRESULT WINAPI SAXErrorHandler_ignorableWarning(ISAXErrorHandler *iface, 2475 ISAXLocator *locator, const WCHAR *message, HRESULT hr) 2476 { 2477 mxwriter *This = impl_from_ISAXErrorHandler( iface ); 2478 2479 FIXME("(%p)->(%p %s 0x%08x)\n", This, locator, debugstr_w(message), hr); 2480 2481 return E_NOTIMPL; 2482 } 2483 2484 static const ISAXErrorHandlerVtbl SAXErrorHandlerVtbl = { 2485 SAXErrorHandler_QueryInterface, 2486 SAXErrorHandler_AddRef, 2487 SAXErrorHandler_Release, 2488 SAXErrorHandler_error, 2489 SAXErrorHandler_fatalError, 2490 SAXErrorHandler_ignorableWarning 2491 }; 2492 2493 /*** IVBSAXErrorHandler ***/ 2494 static HRESULT WINAPI VBSAXErrorHandler_QueryInterface(IVBSAXErrorHandler *iface, REFIID riid, void **obj) 2495 { 2496 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2497 return IMXWriter_QueryInterface(&This->IMXWriter_iface, riid, obj); 2498 } 2499 2500 static ULONG WINAPI VBSAXErrorHandler_AddRef(IVBSAXErrorHandler *iface) 2501 { 2502 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2503 return IMXWriter_AddRef(&This->IMXWriter_iface); 2504 } 2505 2506 static ULONG WINAPI VBSAXErrorHandler_Release(IVBSAXErrorHandler *iface) 2507 { 2508 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2509 return IMXWriter_Release(&This->IMXWriter_iface); 2510 } 2511 2512 static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfoCount(IVBSAXErrorHandler *iface, UINT* pctinfo) 2513 { 2514 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2515 return IMXWriter_GetTypeInfoCount(&This->IMXWriter_iface, pctinfo); 2516 } 2517 2518 static HRESULT WINAPI VBSAXErrorHandler_GetTypeInfo(IVBSAXErrorHandler *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 2519 { 2520 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2521 return IMXWriter_GetTypeInfo(&This->IMXWriter_iface, iTInfo, lcid, ppTInfo); 2522 } 2523 2524 static HRESULT WINAPI VBSAXErrorHandler_GetIDsOfNames(IVBSAXErrorHandler *iface, REFIID riid, LPOLESTR* rgszNames, 2525 UINT cNames, LCID lcid, DISPID* rgDispId ) 2526 { 2527 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2528 return IMXWriter_GetIDsOfNames(&This->IMXWriter_iface, riid, rgszNames, cNames, lcid, rgDispId); 2529 } 2530 2531 static HRESULT WINAPI VBSAXErrorHandler_Invoke(IVBSAXErrorHandler *iface, DISPID dispIdMember, REFIID riid, LCID lcid, 2532 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr ) 2533 { 2534 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2535 return IMXWriter_Invoke(&This->IMXWriter_iface, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, 2536 pExcepInfo, puArgErr); 2537 } 2538 2539 static HRESULT WINAPI VBSAXErrorHandler_error(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code) 2540 { 2541 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2542 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code); 2543 return E_NOTIMPL; 2544 } 2545 2546 static HRESULT WINAPI VBSAXErrorHandler_fatalError(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code) 2547 { 2548 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2549 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code); 2550 return E_NOTIMPL; 2551 } 2552 2553 static HRESULT WINAPI VBSAXErrorHandler_ignorableWarning(IVBSAXErrorHandler *iface, IVBSAXLocator *locator, BSTR *message, LONG code) 2554 { 2555 mxwriter *This = impl_from_IVBSAXErrorHandler( iface ); 2556 FIXME("(%p)->(%p %p %x): stub\n", This, locator, message, code); 2557 return E_NOTIMPL; 2558 } 2559 2560 static const IVBSAXErrorHandlerVtbl VBSAXErrorHandlerVtbl = { 2561 VBSAXErrorHandler_QueryInterface, 2562 VBSAXErrorHandler_AddRef, 2563 VBSAXErrorHandler_Release, 2564 VBSAXErrorHandler_GetTypeInfoCount, 2565 VBSAXErrorHandler_GetTypeInfo, 2566 VBSAXErrorHandler_GetIDsOfNames, 2567 VBSAXErrorHandler_Invoke, 2568 VBSAXErrorHandler_error, 2569 VBSAXErrorHandler_fatalError, 2570 VBSAXErrorHandler_ignorableWarning 2571 }; 2572 2573 static const tid_t mxwriter_iface_tids[] = { 2574 IMXWriter_tid, 2575 0 2576 }; 2577 2578 static dispex_static_data_t mxwriter_dispex = { 2579 NULL, 2580 IMXWriter_tid, 2581 NULL, 2582 mxwriter_iface_tids 2583 }; 2584 2585 HRESULT MXWriter_create(MSXML_VERSION version, void **ppObj) 2586 { 2587 static const WCHAR version10W[] = {'1','.','0',0}; 2588 mxwriter *This; 2589 HRESULT hr; 2590 2591 TRACE("(%p)\n", ppObj); 2592 2593 This = heap_alloc( sizeof (*This) ); 2594 if(!This) 2595 return E_OUTOFMEMORY; 2596 2597 This->IMXWriter_iface.lpVtbl = &MXWriterVtbl; 2598 This->ISAXContentHandler_iface.lpVtbl = &SAXContentHandlerVtbl; 2599 This->ISAXLexicalHandler_iface.lpVtbl = &SAXLexicalHandlerVtbl; 2600 This->ISAXDeclHandler_iface.lpVtbl = &SAXDeclHandlerVtbl; 2601 This->ISAXDTDHandler_iface.lpVtbl = &SAXDTDHandlerVtbl; 2602 This->ISAXErrorHandler_iface.lpVtbl = &SAXErrorHandlerVtbl; 2603 This->IVBSAXDeclHandler_iface.lpVtbl = &VBSAXDeclHandlerVtbl; 2604 This->IVBSAXLexicalHandler_iface.lpVtbl = &VBSAXLexicalHandlerVtbl; 2605 This->IVBSAXContentHandler_iface.lpVtbl = &VBSAXContentHandlerVtbl; 2606 This->IVBSAXDTDHandler_iface.lpVtbl = &VBSAXDTDHandlerVtbl; 2607 This->IVBSAXErrorHandler_iface.lpVtbl = &VBSAXErrorHandlerVtbl; 2608 This->ref = 1; 2609 This->class_version = version; 2610 2611 This->props[MXWriter_BOM] = VARIANT_TRUE; 2612 This->props[MXWriter_DisableEscaping] = VARIANT_FALSE; 2613 This->props[MXWriter_Indent] = VARIANT_FALSE; 2614 This->props[MXWriter_OmitXmlDecl] = VARIANT_FALSE; 2615 This->props[MXWriter_Standalone] = VARIANT_FALSE; 2616 This->prop_changed = FALSE; 2617 This->encoding = SysAllocString(utf16W); 2618 This->version = SysAllocString(version10W); 2619 This->xml_enc = XmlEncoding_UTF16; 2620 2621 This->element = NULL; 2622 This->cdata = FALSE; 2623 This->indent = 0; 2624 This->text = FALSE; 2625 This->newline = FALSE; 2626 2627 This->dest = NULL; 2628 2629 hr = init_output_buffer(This->xml_enc, &This->buffer); 2630 if (hr != S_OK) { 2631 SysFreeString(This->encoding); 2632 SysFreeString(This->version); 2633 heap_free(This); 2634 return hr; 2635 } 2636 2637 init_dispex(&This->dispex, (IUnknown*)&This->IMXWriter_iface, &mxwriter_dispex); 2638 2639 *ppObj = &This->IMXWriter_iface; 2640 2641 TRACE("returning iface %p\n", *ppObj); 2642 2643 return S_OK; 2644 } 2645 2646 static HRESULT WINAPI MXAttributes_QueryInterface(IMXAttributes *iface, REFIID riid, void **ppObj) 2647 { 2648 mxattributes *This = impl_from_IMXAttributes( iface ); 2649 2650 TRACE("(%p)->(%s %p)\n", This, debugstr_guid( riid ), ppObj); 2651 2652 *ppObj = NULL; 2653 2654 if ( IsEqualGUID( riid, &IID_IUnknown ) || 2655 IsEqualGUID( riid, &IID_IDispatch ) || 2656 IsEqualGUID( riid, &IID_IMXAttributes )) 2657 { 2658 *ppObj = iface; 2659 } 2660 else if ( IsEqualGUID( riid, &IID_ISAXAttributes )) 2661 { 2662 *ppObj = &This->ISAXAttributes_iface; 2663 } 2664 else if ( IsEqualGUID( riid, &IID_IVBSAXAttributes )) 2665 { 2666 *ppObj = &This->IVBSAXAttributes_iface; 2667 } 2668 else if (dispex_query_interface(&This->dispex, riid, ppObj)) 2669 { 2670 return *ppObj ? S_OK : E_NOINTERFACE; 2671 } 2672 else 2673 { 2674 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 2675 return E_NOINTERFACE; 2676 } 2677 2678 IMXAttributes_AddRef( iface ); 2679 2680 return S_OK; 2681 } 2682 2683 static ULONG WINAPI MXAttributes_AddRef(IMXAttributes *iface) 2684 { 2685 mxattributes *This = impl_from_IMXAttributes( iface ); 2686 ULONG ref = InterlockedIncrement( &This->ref ); 2687 TRACE("(%p)->(%d)\n", This, ref ); 2688 return ref; 2689 } 2690 2691 static ULONG WINAPI MXAttributes_Release(IMXAttributes *iface) 2692 { 2693 mxattributes *This = impl_from_IMXAttributes( iface ); 2694 LONG ref = InterlockedDecrement( &This->ref ); 2695 2696 TRACE("(%p)->(%d)\n", This, ref); 2697 2698 if (ref == 0) 2699 { 2700 int i; 2701 2702 for (i = 0; i < This->length; i++) 2703 { 2704 SysFreeString(This->attr[i].qname); 2705 SysFreeString(This->attr[i].local); 2706 SysFreeString(This->attr[i].uri); 2707 SysFreeString(This->attr[i].type); 2708 SysFreeString(This->attr[i].value); 2709 } 2710 2711 heap_free(This->attr); 2712 heap_free(This); 2713 } 2714 2715 return ref; 2716 } 2717 2718 static HRESULT WINAPI MXAttributes_GetTypeInfoCount(IMXAttributes *iface, UINT* pctinfo) 2719 { 2720 mxattributes *This = impl_from_IMXAttributes( iface ); 2721 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 2722 } 2723 2724 static HRESULT WINAPI MXAttributes_GetTypeInfo(IMXAttributes *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) 2725 { 2726 mxattributes *This = impl_from_IMXAttributes( iface ); 2727 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 2728 } 2729 2730 static HRESULT WINAPI MXAttributes_GetIDsOfNames( 2731 IMXAttributes *iface, 2732 REFIID riid, 2733 LPOLESTR* rgszNames, 2734 UINT cNames, 2735 LCID lcid, 2736 DISPID* rgDispId) 2737 { 2738 mxattributes *This = impl_from_IMXAttributes( iface ); 2739 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, 2740 riid, rgszNames, cNames, lcid, rgDispId); 2741 } 2742 2743 static HRESULT WINAPI MXAttributes_Invoke( 2744 IMXAttributes *iface, 2745 DISPID dispIdMember, 2746 REFIID riid, 2747 LCID lcid, 2748 WORD wFlags, 2749 DISPPARAMS* pDispParams, 2750 VARIANT* pVarResult, 2751 EXCEPINFO* pExcepInfo, 2752 UINT* puArgErr) 2753 { 2754 mxattributes *This = impl_from_IMXAttributes( iface ); 2755 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, 2756 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 2757 } 2758 2759 static HRESULT WINAPI MXAttributes_addAttribute(IMXAttributes *iface, 2760 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value) 2761 { 2762 mxattributes *This = impl_from_IMXAttributes( iface ); 2763 mxattribute *attr; 2764 HRESULT hr; 2765 2766 TRACE("(%p)->(%s %s %s %s %s)\n", This, debugstr_w(uri), debugstr_w(localName), 2767 debugstr_w(QName), debugstr_w(type), debugstr_w(value)); 2768 2769 if ((!uri || !localName || !QName || !type || !value) && This->class_version != MSXML6) 2770 return E_INVALIDARG; 2771 2772 /* ensure array is large enough */ 2773 hr = mxattributes_grow(This); 2774 if (hr != S_OK) return hr; 2775 2776 attr = &This->attr[This->length]; 2777 2778 attr->qname = SysAllocString(QName); 2779 attr->local = SysAllocString(localName); 2780 attr->uri = SysAllocString(uri); 2781 attr->type = SysAllocString(type ? type : emptyW); 2782 attr->value = SysAllocString(value); 2783 This->length++; 2784 2785 return S_OK; 2786 } 2787 2788 static HRESULT WINAPI MXAttributes_addAttributeFromIndex(IMXAttributes *iface, 2789 VARIANT atts, int index) 2790 { 2791 mxattributes *This = impl_from_IMXAttributes( iface ); 2792 FIXME("(%p)->(%s %d): stub\n", This, debugstr_variant(&atts), index); 2793 return E_NOTIMPL; 2794 } 2795 2796 static HRESULT WINAPI MXAttributes_clear(IMXAttributes *iface) 2797 { 2798 mxattributes *This = impl_from_IMXAttributes( iface ); 2799 int i; 2800 2801 TRACE("(%p)\n", This); 2802 2803 for (i = 0; i < This->length; i++) 2804 { 2805 SysFreeString(This->attr[i].qname); 2806 SysFreeString(This->attr[i].local); 2807 SysFreeString(This->attr[i].uri); 2808 SysFreeString(This->attr[i].type); 2809 SysFreeString(This->attr[i].value); 2810 memset(&This->attr[i], 0, sizeof(mxattribute)); 2811 } 2812 2813 This->length = 0; 2814 2815 return S_OK; 2816 } 2817 2818 static mxattribute *get_attribute_byindex(mxattributes *attrs, int index) 2819 { 2820 if (index < 0 || index >= attrs->length) return NULL; 2821 return &attrs->attr[index]; 2822 } 2823 2824 static HRESULT WINAPI MXAttributes_removeAttribute(IMXAttributes *iface, int index) 2825 { 2826 mxattributes *This = impl_from_IMXAttributes( iface ); 2827 mxattribute *dst; 2828 2829 TRACE("(%p)->(%d)\n", This, index); 2830 2831 if (!(dst = get_attribute_byindex(This, index))) return E_INVALIDARG; 2832 2833 /* no need to remove last attribute, just make it inaccessible */ 2834 if (index + 1 == This->length) 2835 { 2836 This->length--; 2837 return S_OK; 2838 } 2839 2840 memmove(dst, dst + 1, (This->length-index-1)*sizeof(*dst)); 2841 This->length--; 2842 2843 return S_OK; 2844 } 2845 2846 static HRESULT WINAPI MXAttributes_setAttribute(IMXAttributes *iface, int index, 2847 BSTR uri, BSTR localName, BSTR QName, BSTR type, BSTR value) 2848 { 2849 mxattributes *This = impl_from_IMXAttributes( iface ); 2850 FIXME("(%p)->(%d %s %s %s %s %s): stub\n", This, index, debugstr_w(uri), 2851 debugstr_w(localName), debugstr_w(QName), debugstr_w(type), debugstr_w(value)); 2852 return E_NOTIMPL; 2853 } 2854 2855 static HRESULT WINAPI MXAttributes_setAttributes(IMXAttributes *iface, VARIANT atts) 2856 { 2857 mxattributes *This = impl_from_IMXAttributes( iface ); 2858 FIXME("(%p)->(%s): stub\n", This, debugstr_variant(&atts)); 2859 return E_NOTIMPL; 2860 } 2861 2862 static HRESULT WINAPI MXAttributes_setLocalName(IMXAttributes *iface, int index, 2863 BSTR localName) 2864 { 2865 mxattributes *This = impl_from_IMXAttributes( iface ); 2866 mxattribute *attr; 2867 2868 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(localName)); 2869 2870 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG; 2871 2872 SysFreeString(attr->local); 2873 attr->local = SysAllocString(localName); 2874 2875 return S_OK; 2876 } 2877 2878 static HRESULT WINAPI MXAttributes_setQName(IMXAttributes *iface, int index, BSTR QName) 2879 { 2880 mxattributes *This = impl_from_IMXAttributes( iface ); 2881 mxattribute *attr; 2882 2883 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(QName)); 2884 2885 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG; 2886 2887 SysFreeString(attr->qname); 2888 attr->qname = SysAllocString(QName); 2889 2890 return S_OK; 2891 } 2892 2893 static HRESULT WINAPI MXAttributes_setURI(IMXAttributes *iface, int index, BSTR uri) 2894 { 2895 mxattributes *This = impl_from_IMXAttributes( iface ); 2896 mxattribute *attr; 2897 2898 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(uri)); 2899 2900 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG; 2901 2902 SysFreeString(attr->uri); 2903 attr->uri = SysAllocString(uri); 2904 2905 return S_OK; 2906 } 2907 2908 static HRESULT WINAPI MXAttributes_setValue(IMXAttributes *iface, int index, BSTR value) 2909 { 2910 mxattributes *This = impl_from_IMXAttributes( iface ); 2911 mxattribute *attr; 2912 2913 TRACE("(%p)->(%d %s)\n", This, index, debugstr_w(value)); 2914 2915 if (!(attr = get_attribute_byindex(This, index))) return E_INVALIDARG; 2916 2917 SysFreeString(attr->value); 2918 attr->value = SysAllocString(value); 2919 2920 return S_OK; 2921 } 2922 2923 static const IMXAttributesVtbl MXAttributesVtbl = { 2924 MXAttributes_QueryInterface, 2925 MXAttributes_AddRef, 2926 MXAttributes_Release, 2927 MXAttributes_GetTypeInfoCount, 2928 MXAttributes_GetTypeInfo, 2929 MXAttributes_GetIDsOfNames, 2930 MXAttributes_Invoke, 2931 MXAttributes_addAttribute, 2932 MXAttributes_addAttributeFromIndex, 2933 MXAttributes_clear, 2934 MXAttributes_removeAttribute, 2935 MXAttributes_setAttribute, 2936 MXAttributes_setAttributes, 2937 MXAttributes_setLocalName, 2938 MXAttributes_setQName, 2939 MXAttributes_setURI, 2940 MXAttributes_setValue 2941 }; 2942 2943 static HRESULT WINAPI SAXAttributes_QueryInterface(ISAXAttributes *iface, REFIID riid, void **ppObj) 2944 { 2945 mxattributes *This = impl_from_ISAXAttributes( iface ); 2946 return IMXAttributes_QueryInterface(&This->IMXAttributes_iface, riid, ppObj); 2947 } 2948 2949 static ULONG WINAPI SAXAttributes_AddRef(ISAXAttributes *iface) 2950 { 2951 mxattributes *This = impl_from_ISAXAttributes( iface ); 2952 return IMXAttributes_AddRef(&This->IMXAttributes_iface); 2953 } 2954 2955 static ULONG WINAPI SAXAttributes_Release(ISAXAttributes *iface) 2956 { 2957 mxattributes *This = impl_from_ISAXAttributes( iface ); 2958 return IMXAttributes_Release(&This->IMXAttributes_iface); 2959 } 2960 2961 static HRESULT WINAPI SAXAttributes_getLength(ISAXAttributes *iface, int *length) 2962 { 2963 mxattributes *This = impl_from_ISAXAttributes( iface ); 2964 TRACE("(%p)->(%p)\n", This, length); 2965 2966 if (!length && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3)) 2967 return E_POINTER; 2968 2969 *length = This->length; 2970 2971 return S_OK; 2972 } 2973 2974 static HRESULT WINAPI SAXAttributes_getURI(ISAXAttributes *iface, int index, const WCHAR **uri, 2975 int *len) 2976 { 2977 mxattributes *This = impl_from_ISAXAttributes( iface ); 2978 2979 TRACE("(%p)->(%d %p %p)\n", This, index, uri, len); 2980 2981 if (index >= This->length || index < 0) return E_INVALIDARG; 2982 if (!uri || !len) return E_POINTER; 2983 2984 *len = SysStringLen(This->attr[index].uri); 2985 *uri = This->attr[index].uri; 2986 2987 return S_OK; 2988 } 2989 2990 static HRESULT WINAPI SAXAttributes_getLocalName(ISAXAttributes *iface, int index, const WCHAR **name, 2991 int *len) 2992 { 2993 mxattributes *This = impl_from_ISAXAttributes( iface ); 2994 2995 TRACE("(%p)->(%d %p %p)\n", This, index, name, len); 2996 2997 if (index >= This->length || index < 0) return E_INVALIDARG; 2998 if (!name || !len) return E_POINTER; 2999 3000 *len = SysStringLen(This->attr[index].local); 3001 *name = This->attr[index].local; 3002 3003 return S_OK; 3004 } 3005 3006 static HRESULT WINAPI SAXAttributes_getQName(ISAXAttributes *iface, int index, const WCHAR **qname, int *length) 3007 { 3008 mxattributes *This = impl_from_ISAXAttributes( iface ); 3009 3010 TRACE("(%p)->(%d %p %p)\n", This, index, qname, length); 3011 3012 if (index >= This->length) return E_INVALIDARG; 3013 if (!qname || !length) return E_POINTER; 3014 3015 *qname = This->attr[index].qname; 3016 *length = SysStringLen(This->attr[index].qname); 3017 3018 return S_OK; 3019 } 3020 3021 static HRESULT WINAPI SAXAttributes_getName(ISAXAttributes *iface, int index, const WCHAR **uri, int *uri_len, 3022 const WCHAR **local, int *local_len, const WCHAR **qname, int *qname_len) 3023 { 3024 mxattributes *This = impl_from_ISAXAttributes( iface ); 3025 3026 TRACE("(%p)->(%d %p %p %p %p %p %p)\n", This, index, uri, uri_len, local, local_len, qname, qname_len); 3027 3028 if (index >= This->length || index < 0) 3029 return E_INVALIDARG; 3030 3031 if (!uri || !uri_len || !local || !local_len || !qname || !qname_len) 3032 return E_POINTER; 3033 3034 *uri_len = SysStringLen(This->attr[index].uri); 3035 *uri = This->attr[index].uri; 3036 3037 *local_len = SysStringLen(This->attr[index].local); 3038 *local = This->attr[index].local; 3039 3040 *qname_len = SysStringLen(This->attr[index].qname); 3041 *qname = This->attr[index].qname; 3042 3043 TRACE("(%s, %s, %s)\n", debugstr_w(*uri), debugstr_w(*local), debugstr_w(*qname)); 3044 3045 return S_OK; 3046 } 3047 3048 static HRESULT WINAPI SAXAttributes_getIndexFromName(ISAXAttributes *iface, const WCHAR *uri, int uri_len, 3049 const WCHAR *name, int len, int *index) 3050 { 3051 mxattributes *This = impl_from_ISAXAttributes( iface ); 3052 int i; 3053 3054 TRACE("(%p)->(%s:%d %s:%d %p)\n", This, debugstr_wn(uri, uri_len), uri_len, 3055 debugstr_wn(name, len), len, index); 3056 3057 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3)) 3058 return E_POINTER; 3059 3060 if (!uri || !name || !index) return E_INVALIDARG; 3061 3062 for (i = 0; i < This->length; i++) 3063 { 3064 if (uri_len != SysStringLen(This->attr[i].uri)) continue; 3065 if (strncmpW(uri, This->attr[i].uri, uri_len)) continue; 3066 3067 if (len != SysStringLen(This->attr[i].local)) continue; 3068 if (strncmpW(name, This->attr[i].local, len)) continue; 3069 3070 *index = i; 3071 return S_OK; 3072 } 3073 3074 return E_INVALIDARG; 3075 } 3076 3077 static HRESULT WINAPI SAXAttributes_getIndexFromQName(ISAXAttributes *iface, const WCHAR *qname, 3078 int len, int *index) 3079 { 3080 mxattributes *This = impl_from_ISAXAttributes( iface ); 3081 int i; 3082 3083 TRACE("(%p)->(%s:%d %p)\n", This, debugstr_wn(qname, len), len, index); 3084 3085 if (!index && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3)) 3086 return E_POINTER; 3087 3088 if (!qname || !index || !len) return E_INVALIDARG; 3089 3090 for (i = 0; i < This->length; i++) 3091 { 3092 if (len != SysStringLen(This->attr[i].qname)) continue; 3093 if (strncmpW(qname, This->attr[i].qname, len)) continue; 3094 3095 *index = i; 3096 return S_OK; 3097 } 3098 3099 return E_INVALIDARG; 3100 } 3101 3102 static HRESULT WINAPI SAXAttributes_getType(ISAXAttributes *iface, int index, const WCHAR **type, 3103 int *len) 3104 { 3105 mxattributes *This = impl_from_ISAXAttributes( iface ); 3106 3107 TRACE("(%p)->(%d %p %p)\n", This, index, type, len); 3108 3109 if (index >= This->length) return E_INVALIDARG; 3110 3111 if ((!type || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3)) 3112 return E_POINTER; 3113 3114 *type = This->attr[index].type; 3115 *len = SysStringLen(This->attr[index].type); 3116 3117 return S_OK; 3118 } 3119 3120 static HRESULT WINAPI SAXAttributes_getTypeFromName(ISAXAttributes *iface, const WCHAR * pUri, int nUri, 3121 const WCHAR * pLocalName, int nLocalName, const WCHAR ** pType, int * nType) 3122 { 3123 mxattributes *This = impl_from_ISAXAttributes( iface ); 3124 FIXME("(%p)->(%s:%d %s:%d %p %p): stub\n", This, debugstr_wn(pUri, nUri), nUri, 3125 debugstr_wn(pLocalName, nLocalName), nLocalName, pType, nType); 3126 return E_NOTIMPL; 3127 } 3128 3129 static HRESULT WINAPI SAXAttributes_getTypeFromQName(ISAXAttributes *iface, const WCHAR * pQName, 3130 int nQName, const WCHAR ** pType, int * nType) 3131 { 3132 mxattributes *This = impl_from_ISAXAttributes( iface ); 3133 FIXME("(%p)->(%s:%d %p %p): stub\n", This, debugstr_wn(pQName, nQName), nQName, pType, nType); 3134 return E_NOTIMPL; 3135 } 3136 3137 static HRESULT WINAPI SAXAttributes_getValue(ISAXAttributes *iface, int index, const WCHAR **value, 3138 int *len) 3139 { 3140 mxattributes *This = impl_from_ISAXAttributes( iface ); 3141 3142 TRACE("(%p)->(%d %p %p)\n", This, index, value, len); 3143 3144 if (index >= This->length) return E_INVALIDARG; 3145 3146 if ((!value || !len) && (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3)) 3147 return E_POINTER; 3148 3149 *value = This->attr[index].value; 3150 *len = SysStringLen(This->attr[index].value); 3151 3152 return S_OK; 3153 } 3154 3155 static HRESULT WINAPI SAXAttributes_getValueFromName(ISAXAttributes *iface, const WCHAR *uri, 3156 int uri_len, const WCHAR *name, int name_len, const WCHAR **value, int *value_len) 3157 { 3158 mxattributes *This = impl_from_ISAXAttributes( iface ); 3159 HRESULT hr; 3160 int index; 3161 3162 TRACE("(%p)->(%s:%d %s:%d %p %p)\n", This, debugstr_wn(uri, uri_len), uri_len, 3163 debugstr_wn(name, name_len), name_len, value, value_len); 3164 3165 if (!uri || !name || !value || !value_len) 3166 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG; 3167 3168 hr = ISAXAttributes_getIndexFromName(iface, uri, uri_len, name, name_len, &index); 3169 if (hr == S_OK) 3170 hr = ISAXAttributes_getValue(iface, index, value, value_len); 3171 3172 return hr; 3173 } 3174 3175 static HRESULT WINAPI SAXAttributes_getValueFromQName(ISAXAttributes *iface, const WCHAR *qname, 3176 int qname_len, const WCHAR **value, int *value_len) 3177 { 3178 mxattributes *This = impl_from_ISAXAttributes( iface ); 3179 HRESULT hr; 3180 int index; 3181 3182 TRACE("(%p)->(%s:%d %p %p)\n", This, debugstr_wn(qname, qname_len), qname_len, value, value_len); 3183 3184 if (!qname || !value || !value_len) 3185 return (This->class_version == MSXML_DEFAULT || This->class_version == MSXML3) ? E_POINTER : E_INVALIDARG; 3186 3187 hr = ISAXAttributes_getIndexFromQName(iface, qname, qname_len, &index); 3188 if (hr == S_OK) 3189 hr = ISAXAttributes_getValue(iface, index, value, value_len); 3190 3191 return hr; 3192 } 3193 3194 static const ISAXAttributesVtbl SAXAttributesVtbl = { 3195 SAXAttributes_QueryInterface, 3196 SAXAttributes_AddRef, 3197 SAXAttributes_Release, 3198 SAXAttributes_getLength, 3199 SAXAttributes_getURI, 3200 SAXAttributes_getLocalName, 3201 SAXAttributes_getQName, 3202 SAXAttributes_getName, 3203 SAXAttributes_getIndexFromName, 3204 SAXAttributes_getIndexFromQName, 3205 SAXAttributes_getType, 3206 SAXAttributes_getTypeFromName, 3207 SAXAttributes_getTypeFromQName, 3208 SAXAttributes_getValue, 3209 SAXAttributes_getValueFromName, 3210 SAXAttributes_getValueFromQName 3211 }; 3212 3213 static HRESULT WINAPI VBSAXAttributes_QueryInterface( 3214 IVBSAXAttributes* iface, 3215 REFIID riid, 3216 void **ppvObject) 3217 { 3218 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3219 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); 3220 return ISAXAttributes_QueryInterface(&This->ISAXAttributes_iface, riid, ppvObject); 3221 } 3222 3223 static ULONG WINAPI VBSAXAttributes_AddRef(IVBSAXAttributes* iface) 3224 { 3225 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3226 return ISAXAttributes_AddRef(&This->ISAXAttributes_iface); 3227 } 3228 3229 static ULONG WINAPI VBSAXAttributes_Release(IVBSAXAttributes* iface) 3230 { 3231 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3232 return ISAXAttributes_Release(&This->ISAXAttributes_iface); 3233 } 3234 3235 static HRESULT WINAPI VBSAXAttributes_GetTypeInfoCount( IVBSAXAttributes *iface, UINT* pctinfo ) 3236 { 3237 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3238 3239 TRACE("(%p)->(%p)\n", This, pctinfo); 3240 3241 *pctinfo = 1; 3242 3243 return S_OK; 3244 } 3245 3246 static HRESULT WINAPI VBSAXAttributes_GetTypeInfo( 3247 IVBSAXAttributes *iface, 3248 UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo ) 3249 { 3250 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3251 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 3252 return get_typeinfo(IVBSAXAttributes_tid, ppTInfo); 3253 } 3254 3255 static HRESULT WINAPI VBSAXAttributes_GetIDsOfNames( 3256 IVBSAXAttributes *iface, 3257 REFIID riid, 3258 LPOLESTR* rgszNames, 3259 UINT cNames, 3260 LCID lcid, 3261 DISPID* rgDispId) 3262 { 3263 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3264 ITypeInfo *typeinfo; 3265 HRESULT hr; 3266 3267 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 3268 lcid, rgDispId); 3269 3270 if(!rgszNames || cNames == 0 || !rgDispId) 3271 return E_INVALIDARG; 3272 3273 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); 3274 if(SUCCEEDED(hr)) 3275 { 3276 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 3277 ITypeInfo_Release(typeinfo); 3278 } 3279 3280 return hr; 3281 } 3282 3283 static HRESULT WINAPI VBSAXAttributes_Invoke( 3284 IVBSAXAttributes *iface, 3285 DISPID dispIdMember, 3286 REFIID riid, 3287 LCID lcid, 3288 WORD wFlags, 3289 DISPPARAMS* pDispParams, 3290 VARIANT* pVarResult, 3291 EXCEPINFO* pExcepInfo, 3292 UINT* puArgErr) 3293 { 3294 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3295 ITypeInfo *typeinfo; 3296 HRESULT hr; 3297 3298 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 3299 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 3300 3301 hr = get_typeinfo(IVBSAXAttributes_tid, &typeinfo); 3302 if(SUCCEEDED(hr)) 3303 { 3304 hr = ITypeInfo_Invoke(typeinfo, &This->IVBSAXAttributes_iface, dispIdMember, wFlags, 3305 pDispParams, pVarResult, pExcepInfo, puArgErr); 3306 ITypeInfo_Release(typeinfo); 3307 } 3308 3309 return hr; 3310 } 3311 3312 static HRESULT WINAPI VBSAXAttributes_get_length(IVBSAXAttributes* iface, int *len) 3313 { 3314 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3315 return ISAXAttributes_getLength(&This->ISAXAttributes_iface, len); 3316 } 3317 3318 static HRESULT WINAPI VBSAXAttributes_getURI(IVBSAXAttributes* iface, int index, BSTR *uri) 3319 { 3320 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3321 const WCHAR *uriW; 3322 HRESULT hr; 3323 int len; 3324 3325 TRACE("(%p)->(%d %p)\n", This, index, uri); 3326 3327 if (!uri) 3328 return E_POINTER; 3329 3330 *uri = NULL; 3331 hr = ISAXAttributes_getURI(&This->ISAXAttributes_iface, index, &uriW, &len); 3332 if (FAILED(hr)) 3333 return hr; 3334 3335 return return_bstrn(uriW, len, uri); 3336 } 3337 3338 static HRESULT WINAPI VBSAXAttributes_getLocalName(IVBSAXAttributes* iface, int index, BSTR *name) 3339 { 3340 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3341 const WCHAR *nameW; 3342 HRESULT hr; 3343 int len; 3344 3345 TRACE("(%p)->(%d %p)\n", This, index, name); 3346 3347 if (!name) 3348 return E_POINTER; 3349 3350 *name = NULL; 3351 hr = ISAXAttributes_getLocalName(&This->ISAXAttributes_iface, index, &nameW, &len); 3352 if (FAILED(hr)) 3353 return hr; 3354 3355 return return_bstrn(nameW, len, name); 3356 } 3357 3358 static HRESULT WINAPI VBSAXAttributes_getQName(IVBSAXAttributes* iface, int index, BSTR *qname) 3359 { 3360 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3361 const WCHAR *qnameW; 3362 HRESULT hr; 3363 int len; 3364 3365 TRACE("(%p)->(%d %p)\n", This, index, qname); 3366 3367 if (!qname) 3368 return E_POINTER; 3369 3370 *qname = NULL; 3371 hr = ISAXAttributes_getQName(&This->ISAXAttributes_iface, index, &qnameW, &len); 3372 if (FAILED(hr)) 3373 return hr; 3374 3375 return return_bstrn(qnameW, len, qname); 3376 } 3377 3378 static HRESULT WINAPI VBSAXAttributes_getIndexFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, int *index) 3379 { 3380 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3381 return ISAXAttributes_getIndexFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), 3382 name, SysStringLen(name), index); 3383 } 3384 3385 static HRESULT WINAPI VBSAXAttributes_getIndexFromQName(IVBSAXAttributes* iface, BSTR qname, int *index) 3386 { 3387 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3388 return ISAXAttributes_getIndexFromQName(&This->ISAXAttributes_iface, qname, 3389 SysStringLen(qname), index); 3390 } 3391 3392 static HRESULT WINAPI VBSAXAttributes_getType(IVBSAXAttributes* iface, int index, BSTR *type) 3393 { 3394 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3395 const WCHAR *typeW; 3396 HRESULT hr; 3397 int len; 3398 3399 TRACE("(%p)->(%d %p)\n", This, index, type); 3400 3401 if (!type) 3402 return E_POINTER; 3403 3404 *type = NULL; 3405 hr = ISAXAttributes_getType(&This->ISAXAttributes_iface, index, &typeW, &len); 3406 if (FAILED(hr)) 3407 return hr; 3408 3409 return return_bstrn(typeW, len, type); 3410 } 3411 3412 static HRESULT WINAPI VBSAXAttributes_getTypeFromName(IVBSAXAttributes* iface, BSTR uri, 3413 BSTR name, BSTR *type) 3414 { 3415 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3416 const WCHAR *typeW; 3417 HRESULT hr; 3418 int len; 3419 3420 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), type); 3421 3422 if (!type) 3423 return E_POINTER; 3424 3425 *type = NULL; 3426 hr = ISAXAttributes_getTypeFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), 3427 name, SysStringLen(name), &typeW, &len); 3428 if (FAILED(hr)) 3429 return hr; 3430 3431 return return_bstrn(typeW, len, type); 3432 } 3433 3434 static HRESULT WINAPI VBSAXAttributes_getTypeFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *type) 3435 { 3436 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3437 const WCHAR *typeW; 3438 HRESULT hr; 3439 int len; 3440 3441 TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), type); 3442 3443 if (!type) 3444 return E_POINTER; 3445 3446 *type = NULL; 3447 hr = ISAXAttributes_getTypeFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname), 3448 &typeW, &len); 3449 if (FAILED(hr)) 3450 return hr; 3451 3452 return return_bstrn(typeW, len, type); 3453 } 3454 3455 static HRESULT WINAPI VBSAXAttributes_getValue(IVBSAXAttributes* iface, int index, BSTR *value) 3456 { 3457 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3458 const WCHAR *valueW; 3459 HRESULT hr; 3460 int len; 3461 3462 TRACE("(%p)->(%d %p)\n", This, index, value); 3463 3464 if (!value) 3465 return E_POINTER; 3466 3467 *value = NULL; 3468 hr = ISAXAttributes_getValue(&This->ISAXAttributes_iface, index, &valueW, &len); 3469 if (FAILED(hr)) 3470 return hr; 3471 3472 return return_bstrn(valueW, len, value); 3473 } 3474 3475 static HRESULT WINAPI VBSAXAttributes_getValueFromName(IVBSAXAttributes* iface, BSTR uri, BSTR name, 3476 BSTR *value) 3477 { 3478 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3479 const WCHAR *valueW; 3480 HRESULT hr; 3481 int len; 3482 3483 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(uri), debugstr_w(name), value); 3484 3485 if (!value) 3486 return E_POINTER; 3487 3488 *value = NULL; 3489 hr = ISAXAttributes_getValueFromName(&This->ISAXAttributes_iface, uri, SysStringLen(uri), 3490 name, SysStringLen(name), &valueW, &len); 3491 if (FAILED(hr)) 3492 return hr; 3493 3494 return return_bstrn(valueW, len, value); 3495 } 3496 3497 static HRESULT WINAPI VBSAXAttributes_getValueFromQName(IVBSAXAttributes* iface, BSTR qname, BSTR *value) 3498 { 3499 mxattributes *This = impl_from_IVBSAXAttributes( iface ); 3500 const WCHAR *valueW; 3501 HRESULT hr; 3502 int len; 3503 3504 TRACE("(%p)->(%s %p)\n", This, debugstr_w(qname), value); 3505 3506 if (!value) 3507 return E_POINTER; 3508 3509 *value = NULL; 3510 hr = ISAXAttributes_getValueFromQName(&This->ISAXAttributes_iface, qname, SysStringLen(qname), 3511 &valueW, &len); 3512 if (FAILED(hr)) 3513 return hr; 3514 3515 return return_bstrn(valueW, len, value); 3516 } 3517 3518 static const struct IVBSAXAttributesVtbl VBSAXAttributesVtbl = 3519 { 3520 VBSAXAttributes_QueryInterface, 3521 VBSAXAttributes_AddRef, 3522 VBSAXAttributes_Release, 3523 VBSAXAttributes_GetTypeInfoCount, 3524 VBSAXAttributes_GetTypeInfo, 3525 VBSAXAttributes_GetIDsOfNames, 3526 VBSAXAttributes_Invoke, 3527 VBSAXAttributes_get_length, 3528 VBSAXAttributes_getURI, 3529 VBSAXAttributes_getLocalName, 3530 VBSAXAttributes_getQName, 3531 VBSAXAttributes_getIndexFromName, 3532 VBSAXAttributes_getIndexFromQName, 3533 VBSAXAttributes_getType, 3534 VBSAXAttributes_getTypeFromName, 3535 VBSAXAttributes_getTypeFromQName, 3536 VBSAXAttributes_getValue, 3537 VBSAXAttributes_getValueFromName, 3538 VBSAXAttributes_getValueFromQName 3539 }; 3540 3541 static const tid_t mxattrs_iface_tids[] = { 3542 IMXAttributes_tid, 3543 0 3544 }; 3545 3546 static dispex_static_data_t mxattrs_dispex = { 3547 NULL, 3548 IMXAttributes_tid, 3549 NULL, 3550 mxattrs_iface_tids 3551 }; 3552 3553 HRESULT SAXAttributes_create(MSXML_VERSION version, void **ppObj) 3554 { 3555 static const int default_count = 10; 3556 mxattributes *This; 3557 3558 TRACE("(%p)\n", ppObj); 3559 3560 This = heap_alloc( sizeof (*This) ); 3561 if( !This ) 3562 return E_OUTOFMEMORY; 3563 3564 This->IMXAttributes_iface.lpVtbl = &MXAttributesVtbl; 3565 This->ISAXAttributes_iface.lpVtbl = &SAXAttributesVtbl; 3566 This->IVBSAXAttributes_iface.lpVtbl = &VBSAXAttributesVtbl; 3567 This->ref = 1; 3568 3569 This->class_version = version; 3570 3571 This->attr = heap_alloc(default_count*sizeof(mxattribute)); 3572 This->length = 0; 3573 This->allocated = default_count; 3574 3575 *ppObj = &This->IMXAttributes_iface; 3576 3577 init_dispex(&This->dispex, (IUnknown*)&This->IMXAttributes_iface, &mxattrs_dispex); 3578 3579 TRACE("returning iface %p\n", *ppObj); 3580 3581 return S_OK; 3582 } 3583