1 /* 2 * Node implementation 3 * 4 * Copyright 2005 Mike McCormack 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 23 #define COBJMACROS 24 25 #include <stdarg.h> 26 27 #ifdef HAVE_LIBXML2 28 # include <libxml/parser.h> 29 # include <libxml/parserInternals.h> 30 # include <libxml/xmlerror.h> 31 # include <libxml/HTMLtree.h> 32 # ifdef SONAME_LIBXSLT 33 # ifdef HAVE_LIBXSLT_PATTERN_H 34 # include <libxslt/pattern.h> 35 # endif 36 # ifdef HAVE_LIBXSLT_TRANSFORM_H 37 # include <libxslt/transform.h> 38 # endif 39 # include <libxslt/imports.h> 40 # include <libxslt/variables.h> 41 # include <libxslt/xsltutils.h> 42 # include <libxslt/xsltInternals.h> 43 # include <libxslt/documents.h> 44 # endif 45 #endif 46 47 #include "windef.h" 48 #include "winbase.h" 49 #include "winuser.h" 50 #include "winnls.h" 51 #include "ole2.h" 52 #include "msxml6.h" 53 54 #include "msxml_private.h" 55 56 #include "wine/debug.h" 57 58 #ifdef HAVE_LIBXML2 59 60 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 61 62 #ifdef SONAME_LIBXSLT 63 extern void* libxslt_handle; 64 # define MAKE_FUNCPTR(f) extern typeof(f) * p##f 65 MAKE_FUNCPTR(xsltApplyStylesheet); 66 MAKE_FUNCPTR(xsltApplyStylesheetUser); 67 MAKE_FUNCPTR(xsltCleanupGlobals); 68 MAKE_FUNCPTR(xsltFreeStylesheet); 69 MAKE_FUNCPTR(xsltFreeTransformContext); 70 MAKE_FUNCPTR(xsltNewTransformContext); 71 MAKE_FUNCPTR(xsltNextImport); 72 MAKE_FUNCPTR(xsltParseStylesheetDoc); 73 MAKE_FUNCPTR(xsltQuoteUserParams); 74 MAKE_FUNCPTR(xsltSaveResultTo); 75 # undef MAKE_FUNCPTR 76 #else 77 WINE_DECLARE_DEBUG_CHANNEL(winediag); 78 #endif 79 80 static const IID IID_xmlnode = {0x4f2f4ba2,0xb822,0x11df,{0x8b,0x8a,0x68,0x50,0xdf,0xd7,0x20,0x85}}; 81 82 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) 83 { 84 xmlnode *This; 85 86 if ( !iface ) 87 return NULL; 88 This = get_node_obj( iface ); 89 if ( !This || !This->node ) 90 return NULL; 91 if ( type && This->node->type != type ) 92 return NULL; 93 return This->node; 94 } 95 96 BOOL node_query_interface(xmlnode *This, REFIID riid, void **ppv) 97 { 98 if(IsEqualGUID(&IID_xmlnode, riid)) { 99 TRACE("(%p)->(IID_xmlnode %p)\n", This, ppv); 100 *ppv = This; 101 return TRUE; 102 } 103 104 return dispex_query_interface(&This->dispex, riid, ppv); 105 } 106 107 /* common ISupportErrorInfo implementation */ 108 typedef struct { 109 ISupportErrorInfo ISupportErrorInfo_iface; 110 LONG ref; 111 112 const tid_t* iids; 113 } SupportErrorInfo; 114 115 static inline SupportErrorInfo *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface) 116 { 117 return CONTAINING_RECORD(iface, SupportErrorInfo, ISupportErrorInfo_iface); 118 } 119 120 static HRESULT WINAPI SupportErrorInfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj) 121 { 122 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface); 123 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 124 125 *obj = NULL; 126 127 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_ISupportErrorInfo)) { 128 *obj = iface; 129 ISupportErrorInfo_AddRef(iface); 130 return S_OK; 131 } 132 133 return E_NOINTERFACE; 134 } 135 136 static ULONG WINAPI SupportErrorInfo_AddRef(ISupportErrorInfo *iface) 137 { 138 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface); 139 ULONG ref = InterlockedIncrement(&This->ref); 140 TRACE("(%p)->(%d)\n", This, ref ); 141 return ref; 142 } 143 144 static ULONG WINAPI SupportErrorInfo_Release(ISupportErrorInfo *iface) 145 { 146 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface); 147 LONG ref = InterlockedDecrement(&This->ref); 148 149 TRACE("(%p)->(%d)\n", This, ref); 150 151 if (ref == 0) 152 heap_free(This); 153 154 return ref; 155 } 156 157 static HRESULT WINAPI SupportErrorInfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid) 158 { 159 SupportErrorInfo *This = impl_from_ISupportErrorInfo(iface); 160 enum tid_t const *tid; 161 162 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid)); 163 164 tid = This->iids; 165 while (*tid != NULL_tid) 166 { 167 if (IsEqualGUID(riid, get_riid_from_tid(*tid))) 168 return S_OK; 169 tid++; 170 } 171 172 return S_FALSE; 173 } 174 175 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl = { 176 SupportErrorInfo_QueryInterface, 177 SupportErrorInfo_AddRef, 178 SupportErrorInfo_Release, 179 SupportErrorInfo_InterfaceSupportsErrorInfo 180 }; 181 182 HRESULT node_create_supporterrorinfo(enum tid_t const *iids, void **obj) 183 { 184 SupportErrorInfo *This; 185 186 This = heap_alloc(sizeof(*This)); 187 if (!This) return E_OUTOFMEMORY; 188 189 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl; 190 This->ref = 1; 191 This->iids = iids; 192 193 *obj = &This->ISupportErrorInfo_iface; 194 195 return S_OK; 196 } 197 198 xmlnode *get_node_obj(IXMLDOMNode *node) 199 { 200 xmlnode *obj = NULL; 201 HRESULT hres; 202 203 hres = IXMLDOMNode_QueryInterface(node, &IID_xmlnode, (void**)&obj); 204 if (!obj) WARN("node is not our IXMLDOMNode implementation\n"); 205 return SUCCEEDED(hres) ? obj : NULL; 206 } 207 208 HRESULT node_get_nodeName(xmlnode *This, BSTR *name) 209 { 210 BSTR prefix, base; 211 HRESULT hr; 212 213 if (!name) 214 return E_INVALIDARG; 215 216 hr = node_get_base_name(This, &base); 217 if (hr != S_OK) return hr; 218 219 hr = node_get_prefix(This, &prefix); 220 if (hr == S_OK) 221 { 222 static const WCHAR colW = ':'; 223 WCHAR *ptr; 224 225 /* +1 for ':' */ 226 ptr = *name = SysAllocStringLen(NULL, SysStringLen(base) + SysStringLen(prefix) + 1); 227 memcpy(ptr, prefix, SysStringByteLen(prefix)); 228 ptr += SysStringLen(prefix); 229 memcpy(ptr++, &colW, sizeof(WCHAR)); 230 memcpy(ptr, base, SysStringByteLen(base)); 231 232 SysFreeString(base); 233 SysFreeString(prefix); 234 } 235 else 236 *name = base; 237 238 return S_OK; 239 } 240 241 HRESULT node_get_content(xmlnode *This, VARIANT *value) 242 { 243 xmlChar *content; 244 245 if(!value) 246 return E_INVALIDARG; 247 248 content = xmlNodeGetContent(This->node); 249 V_VT(value) = VT_BSTR; 250 V_BSTR(value) = bstr_from_xmlChar( content ); 251 xmlFree(content); 252 253 TRACE("%p returned %s\n", This, debugstr_w(V_BSTR(value))); 254 return S_OK; 255 } 256 257 HRESULT node_set_content(xmlnode *This, LPCWSTR value) 258 { 259 xmlChar *str; 260 261 TRACE("(%p)->(%s)\n", This, debugstr_w(value)); 262 str = xmlchar_from_wchar(value); 263 if(!str) 264 return E_OUTOFMEMORY; 265 266 xmlNodeSetContent(This->node, str); 267 heap_free(str); 268 return S_OK; 269 } 270 271 static HRESULT node_set_content_escaped(xmlnode *This, LPCWSTR value) 272 { 273 xmlChar *str, *escaped; 274 275 TRACE("(%p)->(%s)\n", This, debugstr_w(value)); 276 str = xmlchar_from_wchar(value); 277 if(!str) 278 return E_OUTOFMEMORY; 279 280 escaped = xmlEncodeSpecialChars(NULL, str); 281 if(!escaped) 282 { 283 heap_free(str); 284 return E_OUTOFMEMORY; 285 } 286 287 xmlNodeSetContent(This->node, escaped); 288 289 heap_free(str); 290 xmlFree(escaped); 291 292 return S_OK; 293 } 294 295 HRESULT node_put_value(xmlnode *This, VARIANT *value) 296 { 297 HRESULT hr; 298 299 if (V_VT(value) != VT_BSTR) 300 { 301 VARIANT string_value; 302 303 VariantInit(&string_value); 304 hr = VariantChangeType(&string_value, value, 0, VT_BSTR); 305 if(FAILED(hr)) { 306 WARN("Couldn't convert to VT_BSTR\n"); 307 return hr; 308 } 309 310 hr = node_set_content(This, V_BSTR(&string_value)); 311 VariantClear(&string_value); 312 } 313 else 314 hr = node_set_content(This, V_BSTR(value)); 315 316 return hr; 317 } 318 319 HRESULT node_put_value_escaped(xmlnode *This, VARIANT *value) 320 { 321 HRESULT hr; 322 323 if (V_VT(value) != VT_BSTR) 324 { 325 VARIANT string_value; 326 327 VariantInit(&string_value); 328 hr = VariantChangeType(&string_value, value, 0, VT_BSTR); 329 if(FAILED(hr)) { 330 WARN("Couldn't convert to VT_BSTR\n"); 331 return hr; 332 } 333 334 hr = node_set_content_escaped(This, V_BSTR(&string_value)); 335 VariantClear(&string_value); 336 } 337 else 338 hr = node_set_content_escaped(This, V_BSTR(value)); 339 340 return hr; 341 } 342 343 static HRESULT get_node( 344 xmlnode *This, 345 const char *name, 346 xmlNodePtr node, 347 IXMLDOMNode **out ) 348 { 349 TRACE("(%p)->(%s %p %p)\n", This, name, node, out ); 350 351 if ( !out ) 352 return E_INVALIDARG; 353 354 /* if we don't have a doc, use our parent. */ 355 if(node && !node->doc && node->parent) 356 node->doc = node->parent->doc; 357 358 *out = create_node( node ); 359 if (!*out) 360 return S_FALSE; 361 return S_OK; 362 } 363 364 HRESULT node_get_parent(xmlnode *This, IXMLDOMNode **parent) 365 { 366 return get_node( This, "parent", This->node->parent, parent ); 367 } 368 369 HRESULT node_get_child_nodes(xmlnode *This, IXMLDOMNodeList **ret) 370 { 371 if(!ret) 372 return E_INVALIDARG; 373 374 *ret = create_children_nodelist(This->node); 375 if(!*ret) 376 return E_OUTOFMEMORY; 377 378 return S_OK; 379 } 380 381 HRESULT node_get_first_child(xmlnode *This, IXMLDOMNode **ret) 382 { 383 return get_node(This, "firstChild", This->node->children, ret); 384 } 385 386 HRESULT node_get_last_child(xmlnode *This, IXMLDOMNode **ret) 387 { 388 return get_node(This, "lastChild", This->node->last, ret); 389 } 390 391 HRESULT node_get_previous_sibling(xmlnode *This, IXMLDOMNode **ret) 392 { 393 return get_node(This, "previous", This->node->prev, ret); 394 } 395 396 HRESULT node_get_next_sibling(xmlnode *This, IXMLDOMNode **ret) 397 { 398 return get_node(This, "next", This->node->next, ret); 399 } 400 401 static int node_get_inst_cnt(xmlNodePtr node) 402 { 403 int ret = *(LONG *)&node->_private & NODE_PRIV_REFCOUNT_MASK; 404 xmlNodePtr child; 405 406 /* add attribute counts */ 407 if (node->type == XML_ELEMENT_NODE) 408 { 409 xmlAttrPtr prop = node->properties; 410 411 while (prop) 412 { 413 ret += node_get_inst_cnt((xmlNodePtr)prop); 414 prop = prop->next; 415 } 416 } 417 418 /* add children counts */ 419 child = node->children; 420 while (child) 421 { 422 ret += node_get_inst_cnt(child); 423 child = child->next; 424 } 425 426 return ret; 427 } 428 429 int xmlnode_get_inst_cnt(xmlnode *node) 430 { 431 return node_get_inst_cnt(node->node); 432 } 433 434 /* _private field holds a number of COM instances spawned from this libxml2 node 435 * most significant bits are used to store information about ignorrable whitespace nodes */ 436 void xmlnode_add_ref(xmlNodePtr node) 437 { 438 if (node->type == XML_DOCUMENT_NODE) return; 439 InterlockedIncrement((LONG*)&node->_private); 440 } 441 442 void xmlnode_release(xmlNodePtr node) 443 { 444 if (node->type == XML_DOCUMENT_NODE) return; 445 InterlockedDecrement((LONG*)&node->_private); 446 } 447 448 HRESULT node_insert_before(xmlnode *This, IXMLDOMNode *new_child, const VARIANT *ref_child, 449 IXMLDOMNode **ret) 450 { 451 IXMLDOMNode *before = NULL; 452 xmlnode *node_obj; 453 int refcount = 0; 454 xmlDocPtr doc; 455 HRESULT hr; 456 457 if(!new_child) 458 return E_INVALIDARG; 459 460 node_obj = get_node_obj(new_child); 461 if(!node_obj) return E_FAIL; 462 463 switch(V_VT(ref_child)) 464 { 465 case VT_EMPTY: 466 case VT_NULL: 467 break; 468 469 case VT_UNKNOWN: 470 case VT_DISPATCH: 471 if (V_UNKNOWN(ref_child)) 472 { 473 hr = IUnknown_QueryInterface(V_UNKNOWN(ref_child), &IID_IXMLDOMNode, (void**)&before); 474 if(FAILED(hr)) return hr; 475 } 476 break; 477 478 default: 479 FIXME("refChild var type %x\n", V_VT(ref_child)); 480 return E_FAIL; 481 } 482 483 TRACE("new child %p, This->node %p\n", node_obj->node, This->node); 484 485 if(!node_obj->node->parent) 486 if(xmldoc_remove_orphan(node_obj->node->doc, node_obj->node) != S_OK) 487 WARN("%p is not an orphan of %p\n", node_obj->node, node_obj->node->doc); 488 489 refcount = xmlnode_get_inst_cnt(node_obj); 490 491 if(before) 492 { 493 xmlnode *before_node_obj = get_node_obj(before); 494 IXMLDOMNode_Release(before); 495 if(!before_node_obj) return E_FAIL; 496 } 497 498 /* unlink from current parent first */ 499 if(node_obj->parent) 500 { 501 hr = IXMLDOMNode_removeChild(node_obj->parent, node_obj->iface, NULL); 502 if (hr == S_OK) xmldoc_remove_orphan(node_obj->node->doc, node_obj->node); 503 } 504 doc = node_obj->node->doc; 505 506 if(before) 507 { 508 xmlNodePtr new_node; 509 xmlnode *before_node_obj = get_node_obj(before); 510 511 /* refs count including subtree */ 512 if (doc != before_node_obj->node->doc) 513 refcount = xmlnode_get_inst_cnt(node_obj); 514 515 if (refcount) xmldoc_add_refs(before_node_obj->node->doc, refcount); 516 new_node = xmlAddPrevSibling(before_node_obj->node, node_obj->node); 517 if (new_node != node_obj->node) 518 { 519 if (refcount != 1) 520 FIXME("referenced xmlNode was freed, expect crashes\n"); 521 xmlnode_add_ref(new_node); 522 node_obj->node = new_node; 523 } 524 if (refcount) xmldoc_release_refs(doc, refcount); 525 node_obj->parent = This->parent; 526 } 527 else 528 { 529 xmlNodePtr new_node; 530 531 if (doc != This->node->doc) 532 refcount = xmlnode_get_inst_cnt(node_obj); 533 534 if (refcount) xmldoc_add_refs(This->node->doc, refcount); 535 /* xmlAddChild doesn't unlink node from previous parent */ 536 xmlUnlinkNode(node_obj->node); 537 new_node = xmlAddChild(This->node, node_obj->node); 538 if (new_node != node_obj->node) 539 { 540 if (refcount != 1) 541 FIXME("referenced xmlNode was freed, expect crashes\n"); 542 xmlnode_add_ref(new_node); 543 node_obj->node = new_node; 544 } 545 if (refcount) xmldoc_release_refs(doc, refcount); 546 node_obj->parent = This->iface; 547 } 548 549 if(ret) 550 { 551 IXMLDOMNode_AddRef(new_child); 552 *ret = new_child; 553 } 554 555 TRACE("ret S_OK\n"); 556 return S_OK; 557 } 558 559 HRESULT node_replace_child(xmlnode *This, IXMLDOMNode *newChild, IXMLDOMNode *oldChild, 560 IXMLDOMNode **ret) 561 { 562 xmlnode *old_child, *new_child; 563 xmlDocPtr leaving_doc; 564 xmlNode *my_ancestor; 565 int refcount = 0; 566 567 /* Do not believe any documentation telling that newChild == NULL 568 means removal. It does certainly *not* apply to msxml3! */ 569 if(!newChild || !oldChild) 570 return E_INVALIDARG; 571 572 if(ret) 573 *ret = NULL; 574 575 old_child = get_node_obj(oldChild); 576 if(!old_child) return E_FAIL; 577 578 if(old_child->node->parent != This->node) 579 { 580 WARN("childNode %p is not a child of %p\n", oldChild, This); 581 return E_INVALIDARG; 582 } 583 584 new_child = get_node_obj(newChild); 585 if(!new_child) return E_FAIL; 586 587 my_ancestor = This->node; 588 while(my_ancestor) 589 { 590 if(my_ancestor == new_child->node) 591 { 592 WARN("tried to create loop\n"); 593 return E_FAIL; 594 } 595 my_ancestor = my_ancestor->parent; 596 } 597 598 if(!new_child->node->parent) 599 if(xmldoc_remove_orphan(new_child->node->doc, new_child->node) != S_OK) 600 WARN("%p is not an orphan of %p\n", new_child->node, new_child->node->doc); 601 602 leaving_doc = new_child->node->doc; 603 604 if (leaving_doc != old_child->node->doc) 605 refcount = xmlnode_get_inst_cnt(new_child); 606 607 if (refcount) xmldoc_add_refs(old_child->node->doc, refcount); 608 xmlReplaceNode(old_child->node, new_child->node); 609 if (refcount) xmldoc_release_refs(leaving_doc, refcount); 610 new_child->parent = old_child->parent; 611 old_child->parent = NULL; 612 613 xmldoc_add_orphan(old_child->node->doc, old_child->node); 614 615 if(ret) 616 { 617 IXMLDOMNode_AddRef(oldChild); 618 *ret = oldChild; 619 } 620 621 return S_OK; 622 } 623 624 HRESULT node_remove_child(xmlnode *This, IXMLDOMNode* child, IXMLDOMNode** oldChild) 625 { 626 xmlnode *child_node; 627 628 if(!child) return E_INVALIDARG; 629 630 if(oldChild) 631 *oldChild = NULL; 632 633 child_node = get_node_obj(child); 634 if(!child_node) return E_FAIL; 635 636 if(child_node->node->parent != This->node) 637 { 638 WARN("childNode %p is not a child of %p\n", child, This); 639 return E_INVALIDARG; 640 } 641 642 xmlUnlinkNode(child_node->node); 643 child_node->parent = NULL; 644 xmldoc_add_orphan(child_node->node->doc, child_node->node); 645 646 if(oldChild) 647 { 648 IXMLDOMNode_AddRef(child); 649 *oldChild = child; 650 } 651 652 return S_OK; 653 } 654 655 HRESULT node_append_child(xmlnode *This, IXMLDOMNode *child, IXMLDOMNode **outChild) 656 { 657 DOMNodeType type; 658 VARIANT var; 659 HRESULT hr; 660 661 if (!child) 662 return E_INVALIDARG; 663 664 hr = IXMLDOMNode_get_nodeType(child, &type); 665 if(FAILED(hr) || type == NODE_ATTRIBUTE) { 666 if (outChild) *outChild = NULL; 667 return E_FAIL; 668 } 669 670 VariantInit(&var); 671 return IXMLDOMNode_insertBefore(This->iface, child, var, outChild); 672 } 673 674 HRESULT node_has_childnodes(const xmlnode *This, VARIANT_BOOL *ret) 675 { 676 if (!ret) return E_INVALIDARG; 677 678 if (!This->node->children) 679 { 680 *ret = VARIANT_FALSE; 681 return S_FALSE; 682 } 683 684 *ret = VARIANT_TRUE; 685 return S_OK; 686 } 687 688 HRESULT node_get_owner_doc(const xmlnode *This, IXMLDOMDocument **doc) 689 { 690 if(!doc) 691 return E_INVALIDARG; 692 return get_domdoc_from_xmldoc(This->node->doc, (IXMLDOMDocument3**)doc); 693 } 694 695 HRESULT node_clone(xmlnode *This, VARIANT_BOOL deep, IXMLDOMNode **cloneNode) 696 { 697 IXMLDOMNode *node; 698 xmlNodePtr clone; 699 700 if(!cloneNode) return E_INVALIDARG; 701 702 clone = xmlCopyNode(This->node, deep ? 1 : 2); 703 if (clone) 704 { 705 xmlSetTreeDoc(clone, This->node->doc); 706 xmldoc_add_orphan(clone->doc, clone); 707 708 node = create_node(clone); 709 if (!node) 710 { 711 ERR("Copy failed\n"); 712 xmldoc_remove_orphan(clone->doc, clone); 713 xmlFreeNode(clone); 714 return E_FAIL; 715 } 716 717 *cloneNode = node; 718 } 719 else 720 { 721 ERR("Copy failed\n"); 722 return E_FAIL; 723 } 724 725 return S_OK; 726 } 727 728 static xmlChar* do_get_text(xmlNodePtr node, BOOL trim, DWORD *first, DWORD *last, BOOL *trail_ig_ws) 729 { 730 xmlNodePtr child; 731 xmlChar* str; 732 BOOL preserving = is_preserving_whitespace(node); 733 734 *first = -1; 735 *last = 0; 736 737 if (!node->children) 738 { 739 str = xmlNodeGetContent(node); 740 *trail_ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS; 741 } 742 else 743 { 744 BOOL ig_ws = FALSE; 745 xmlChar* tmp; 746 DWORD pos = 0; 747 str = xmlStrdup(BAD_CAST ""); 748 749 if (node->type != XML_DOCUMENT_NODE) 750 ig_ws = *(DWORD*)&node->_private & NODE_PRIV_CHILD_IGNORABLE_WS; 751 *trail_ig_ws = FALSE; 752 753 for (child = node->children; child != NULL; child = child->next) 754 { 755 switch (child->type) 756 { 757 case XML_ELEMENT_NODE: { 758 DWORD node_first, node_last; 759 760 tmp = do_get_text(child, FALSE, &node_first, &node_last, trail_ig_ws); 761 762 if (node_first!=-1 && pos+node_first<*first) 763 *first = pos+node_first; 764 if (node_last && pos+node_last>*last) 765 *last = pos+node_last; 766 break; 767 } 768 case XML_TEXT_NODE: 769 tmp = xmlNodeGetContent(child); 770 if (!preserving && tmp[0]) 771 { 772 xmlChar *beg; 773 774 for (beg = tmp; *beg; beg++) 775 if (!isspace(*beg)) break; 776 777 if (!*beg) 778 { 779 ig_ws = TRUE; 780 xmlFree(tmp); 781 tmp = NULL; 782 } 783 } 784 break; 785 case XML_CDATA_SECTION_NODE: 786 case XML_ENTITY_REF_NODE: 787 case XML_ENTITY_NODE: 788 tmp = xmlNodeGetContent(child); 789 break; 790 default: 791 tmp = NULL; 792 break; 793 } 794 795 if ((tmp && *tmp) || child->type==XML_CDATA_SECTION_NODE) 796 { 797 if (ig_ws && str[0]) 798 { 799 str = xmlStrcat(str, BAD_CAST " "); 800 pos++; 801 } 802 if (tmp && *tmp) str = xmlStrcat(str, tmp); 803 if (child->type==XML_CDATA_SECTION_NODE && pos<*first) 804 *first = pos; 805 if (tmp && *tmp) pos += xmlStrlen(tmp); 806 if (child->type==XML_CDATA_SECTION_NODE && pos>*last) 807 *last = pos; 808 ig_ws = FALSE; 809 } 810 if (tmp) xmlFree(tmp); 811 812 if (!ig_ws) 813 { 814 ig_ws = *(DWORD*)&child->_private & NODE_PRIV_TRAILING_IGNORABLE_WS; 815 } 816 if (!ig_ws) 817 ig_ws = *trail_ig_ws; 818 *trail_ig_ws = FALSE; 819 } 820 821 *trail_ig_ws = ig_ws; 822 } 823 824 switch (node->type) 825 { 826 case XML_ELEMENT_NODE: 827 case XML_TEXT_NODE: 828 case XML_ENTITY_REF_NODE: 829 case XML_ENTITY_NODE: 830 case XML_DOCUMENT_NODE: 831 case XML_DOCUMENT_FRAG_NODE: 832 if (trim && !preserving) 833 { 834 xmlChar* ret; 835 int len; 836 837 if (!str) 838 break; 839 840 for (ret = str; *ret && isspace(*ret) && (*first)--; ret++) 841 if (*last) (*last)--; 842 for (len = xmlStrlen(ret)-1; len >= 0 && len >= *last; len--) 843 if(!isspace(ret[len])) break; 844 845 ret = xmlStrndup(ret, len+1); 846 xmlFree(str); 847 str = ret; 848 break; 849 } 850 break; 851 default: 852 break; 853 } 854 855 return str; 856 } 857 858 HRESULT node_get_text(const xmlnode *This, BSTR *text) 859 { 860 BSTR str = NULL; 861 xmlChar *content; 862 DWORD first, last; 863 BOOL tmp; 864 865 if (!text) return E_INVALIDARG; 866 867 content = do_get_text(This->node, TRUE, &first, &last, &tmp); 868 if (content) 869 { 870 str = bstr_from_xmlChar(content); 871 xmlFree(content); 872 } 873 874 /* Always return a string. */ 875 if (!str) str = SysAllocStringLen( NULL, 0 ); 876 877 TRACE("%p %s\n", This, debugstr_w(str) ); 878 *text = str; 879 880 return S_OK; 881 } 882 883 HRESULT node_put_text(xmlnode *This, BSTR text) 884 { 885 xmlChar *str, *str2; 886 887 TRACE("(%p)->(%s)\n", This, debugstr_w(text)); 888 889 str = xmlchar_from_wchar(text); 890 891 /* Escape the string. */ 892 str2 = xmlEncodeEntitiesReentrant(This->node->doc, str); 893 heap_free(str); 894 895 xmlNodeSetContent(This->node, str2); 896 xmlFree(str2); 897 898 return S_OK; 899 } 900 901 BSTR EnsureCorrectEOL(BSTR sInput) 902 { 903 int nNum = 0; 904 BSTR sNew; 905 int nLen; 906 int i; 907 908 nLen = SysStringLen(sInput); 909 /* Count line endings */ 910 for(i=0; i < nLen; i++) 911 { 912 if(sInput[i] == '\n') 913 nNum++; 914 } 915 916 TRACE("len=%d, num=%d\n", nLen, nNum); 917 918 /* Add linefeed as needed */ 919 if(nNum > 0) 920 { 921 int nPlace = 0; 922 sNew = SysAllocStringLen(NULL, nLen + nNum); 923 for(i=0; i < nLen; i++) 924 { 925 if(sInput[i] == '\n') 926 { 927 sNew[i+nPlace] = '\r'; 928 nPlace++; 929 } 930 sNew[i+nPlace] = sInput[i]; 931 } 932 933 SysFreeString(sInput); 934 } 935 else 936 { 937 sNew = sInput; 938 } 939 940 TRACE("len %d\n", SysStringLen(sNew)); 941 942 return sNew; 943 } 944 945 /* 946 * We are trying to replicate the same behaviour as msxml by converting 947 * line endings to \r\n and using indents as \t. The problem is that msxml 948 * only formats nodes that have a line ending. Using libxml we cannot 949 * reproduce behaviour exactly. 950 * 951 */ 952 HRESULT node_get_xml(xmlnode *This, BOOL ensure_eol, BSTR *ret) 953 { 954 xmlBufferPtr xml_buf; 955 xmlNodePtr xmldecl; 956 int size; 957 958 if(!ret) 959 return E_INVALIDARG; 960 961 *ret = NULL; 962 963 xml_buf = xmlBufferCreate(); 964 if(!xml_buf) 965 return E_OUTOFMEMORY; 966 967 xmldecl = xmldoc_unlink_xmldecl( This->node->doc ); 968 969 size = xmlNodeDump(xml_buf, This->node->doc, This->node, 0, 1); 970 if(size > 0) { 971 const xmlChar *buf_content; 972 BSTR content; 973 974 /* Attribute Nodes return a space in front of their name */ 975 buf_content = xmlBufferContent(xml_buf); 976 977 content = bstr_from_xmlChar(buf_content + (buf_content[0] == ' ' ? 1 : 0)); 978 if(ensure_eol) 979 content = EnsureCorrectEOL(content); 980 981 *ret = content; 982 }else { 983 *ret = SysAllocStringLen(NULL, 0); 984 } 985 986 xmlBufferFree(xml_buf); 987 xmldoc_link_xmldecl( This->node->doc, xmldecl ); 988 return *ret ? S_OK : E_OUTOFMEMORY; 989 } 990 991 #ifdef SONAME_LIBXSLT 992 993 /* duplicates xmlBufferWriteQuotedString() logic */ 994 static void xml_write_quotedstring(xmlOutputBufferPtr buf, const xmlChar *string) 995 { 996 const xmlChar *cur, *base; 997 998 if (xmlStrchr(string, '\"')) 999 { 1000 if (xmlStrchr(string, '\'')) 1001 { 1002 xmlOutputBufferWrite(buf, 1, "\""); 1003 base = cur = string; 1004 1005 while (*cur) 1006 { 1007 if (*cur == '"') 1008 { 1009 if (base != cur) 1010 xmlOutputBufferWrite(buf, cur-base, (const char*)base); 1011 xmlOutputBufferWrite(buf, 6, """); 1012 cur++; 1013 base = cur; 1014 } 1015 else 1016 cur++; 1017 } 1018 if (base != cur) 1019 xmlOutputBufferWrite(buf, cur-base, (const char*)base); 1020 xmlOutputBufferWrite(buf, 1, "\""); 1021 } 1022 else 1023 { 1024 xmlOutputBufferWrite(buf, 1, "\'"); 1025 xmlOutputBufferWriteString(buf, (const char*)string); 1026 xmlOutputBufferWrite(buf, 1, "\'"); 1027 } 1028 } 1029 else 1030 { 1031 xmlOutputBufferWrite(buf, 1, "\""); 1032 xmlOutputBufferWriteString(buf, (const char*)string); 1033 xmlOutputBufferWrite(buf, 1, "\""); 1034 } 1035 } 1036 1037 static int XMLCALL transform_to_stream_write(void *context, const char *buffer, int len) 1038 { 1039 DWORD written; 1040 HRESULT hr = ISequentialStream_Write((ISequentialStream *)context, buffer, len, &written); 1041 return hr == S_OK ? written : -1; 1042 } 1043 1044 /* Output for method "text" */ 1045 static void transform_write_text(xmlDocPtr result, xsltStylesheetPtr style, xmlOutputBufferPtr output) 1046 { 1047 xmlNodePtr cur = result->children; 1048 while (cur) 1049 { 1050 if (cur->type == XML_TEXT_NODE) 1051 xmlOutputBufferWriteString(output, (const char*)cur->content); 1052 1053 /* skip to next node */ 1054 if (cur->children) 1055 { 1056 if ((cur->children->type != XML_ENTITY_DECL) && 1057 (cur->children->type != XML_ENTITY_REF_NODE) && 1058 (cur->children->type != XML_ENTITY_NODE)) 1059 { 1060 cur = cur->children; 1061 continue; 1062 } 1063 } 1064 1065 if (cur->next) { 1066 cur = cur->next; 1067 continue; 1068 } 1069 1070 do 1071 { 1072 cur = cur->parent; 1073 if (cur == NULL) 1074 break; 1075 if (cur == (xmlNodePtr) style->doc) { 1076 cur = NULL; 1077 break; 1078 } 1079 if (cur->next) { 1080 cur = cur->next; 1081 break; 1082 } 1083 } while (cur); 1084 } 1085 } 1086 1087 #undef XSLT_GET_IMPORT_PTR 1088 #define XSLT_GET_IMPORT_PTR(res, style, name) { \ 1089 xsltStylesheetPtr st = style; \ 1090 res = NULL; \ 1091 while (st != NULL) { \ 1092 if (st->name != NULL) { res = st->name; break; } \ 1093 st = pxsltNextImport(st); \ 1094 }} 1095 1096 #undef XSLT_GET_IMPORT_INT 1097 #define XSLT_GET_IMPORT_INT(res, style, name) { \ 1098 xsltStylesheetPtr st = style; \ 1099 res = -1; \ 1100 while (st != NULL) { \ 1101 if (st->name != -1) { res = st->name; break; } \ 1102 st = pxsltNextImport(st); \ 1103 }} 1104 1105 static void transform_write_xmldecl(xmlDocPtr result, xsltStylesheetPtr style, BOOL omit_encoding, xmlOutputBufferPtr output) 1106 { 1107 int omit_xmldecl, standalone; 1108 1109 XSLT_GET_IMPORT_INT(omit_xmldecl, style, omitXmlDeclaration); 1110 if (omit_xmldecl == 1) return; 1111 1112 XSLT_GET_IMPORT_INT(standalone, style, standalone); 1113 1114 xmlOutputBufferWriteString(output, "<?xml version="); 1115 if (result->version) 1116 { 1117 xmlOutputBufferWriteString(output, "\""); 1118 xmlOutputBufferWriteString(output, (const char *)result->version); 1119 xmlOutputBufferWriteString(output, "\""); 1120 } 1121 else 1122 xmlOutputBufferWriteString(output, "\"1.0\""); 1123 1124 if (!omit_encoding) 1125 { 1126 const xmlChar *encoding; 1127 1128 /* default encoding is UTF-16 */ 1129 XSLT_GET_IMPORT_PTR(encoding, style, encoding); 1130 xmlOutputBufferWriteString(output, " encoding="); 1131 xmlOutputBufferWriteString(output, "\""); 1132 xmlOutputBufferWriteString(output, encoding ? (const char *)encoding : "UTF-16"); 1133 xmlOutputBufferWriteString(output, "\""); 1134 } 1135 1136 /* standalone attribute */ 1137 if (standalone != -1) 1138 xmlOutputBufferWriteString(output, standalone == 0 ? " standalone=\"no\"" : " standalone=\"yes\""); 1139 1140 xmlOutputBufferWriteString(output, "?>"); 1141 } 1142 1143 static void htmldtd_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc) 1144 { 1145 xmlDtdPtr cur = doc->intSubset; 1146 1147 xmlOutputBufferWriteString(buf, "<!DOCTYPE "); 1148 xmlOutputBufferWriteString(buf, (const char *)cur->name); 1149 if (cur->ExternalID) 1150 { 1151 xmlOutputBufferWriteString(buf, " PUBLIC "); 1152 xml_write_quotedstring(buf, cur->ExternalID); 1153 if (cur->SystemID) 1154 { 1155 xmlOutputBufferWriteString(buf, " "); 1156 xml_write_quotedstring(buf, cur->SystemID); 1157 } 1158 } 1159 else if (cur->SystemID) 1160 { 1161 xmlOutputBufferWriteString(buf, " SYSTEM "); 1162 xml_write_quotedstring(buf, cur->SystemID); 1163 } 1164 xmlOutputBufferWriteString(buf, ">\n"); 1165 } 1166 1167 /* Duplicates htmlDocContentDumpFormatOutput() the way we need it - doesn't add trailing newline. */ 1168 static void htmldoc_dumpcontent(xmlOutputBufferPtr buf, xmlDocPtr doc, const char *encoding, int format) 1169 { 1170 xmlElementType type; 1171 1172 /* force HTML output */ 1173 type = doc->type; 1174 doc->type = XML_HTML_DOCUMENT_NODE; 1175 if (doc->intSubset) 1176 htmldtd_dumpcontent(buf, doc); 1177 if (doc->children) { 1178 xmlNodePtr cur = doc->children; 1179 while (cur) { 1180 htmlNodeDumpFormatOutput(buf, doc, cur, encoding, format); 1181 cur = cur->next; 1182 } 1183 } 1184 doc->type = type; 1185 } 1186 1187 static inline BOOL transform_is_empty_resultdoc(xmlDocPtr result) 1188 { 1189 return !result->children || ((result->children->type == XML_DTD_NODE) && !result->children->next); 1190 } 1191 1192 static inline BOOL transform_is_valid_method(xsltStylesheetPtr style) 1193 { 1194 return !style->methodURI || !(style->method && xmlStrEqual(style->method, (const xmlChar *)"xhtml")); 1195 } 1196 1197 /* Helper to write transformation result to specified output buffer. */ 1198 static HRESULT node_transform_write(xsltStylesheetPtr style, xmlDocPtr result, BOOL omit_encoding, const char *encoding, xmlOutputBufferPtr output) 1199 { 1200 const xmlChar *method; 1201 int indent; 1202 1203 if (!transform_is_valid_method(style)) 1204 { 1205 ERR("unknown output method\n"); 1206 return E_FAIL; 1207 } 1208 1209 XSLT_GET_IMPORT_PTR(method, style, method) 1210 XSLT_GET_IMPORT_INT(indent, style, indent); 1211 1212 if (!method && (result->type == XML_HTML_DOCUMENT_NODE)) 1213 method = (const xmlChar *) "html"; 1214 1215 if (method && xmlStrEqual(method, (const xmlChar *)"html")) 1216 { 1217 htmlSetMetaEncoding(result, (const xmlChar *)encoding); 1218 if (indent == -1) 1219 indent = 1; 1220 htmldoc_dumpcontent(output, result, encoding, indent); 1221 } 1222 else if (method && xmlStrEqual(method, (const xmlChar *)"xhtml")) 1223 { 1224 htmlSetMetaEncoding(result, (const xmlChar *) encoding); 1225 htmlDocContentDumpOutput(output, result, encoding); 1226 } 1227 else if (method && xmlStrEqual(method, (const xmlChar *)"text")) 1228 transform_write_text(result, style, output); 1229 else 1230 { 1231 transform_write_xmldecl(result, style, omit_encoding, output); 1232 1233 if (result->children) 1234 { 1235 xmlNodePtr child = result->children; 1236 1237 while (child) 1238 { 1239 xmlNodeDumpOutput(output, result, child, 0, indent == 1, encoding); 1240 if (indent && ((child->type == XML_DTD_NODE) || ((child->type == XML_COMMENT_NODE) && child->next))) 1241 xmlOutputBufferWriteString(output, "\r\n"); 1242 child = child->next; 1243 } 1244 } 1245 } 1246 1247 xmlOutputBufferFlush(output); 1248 return S_OK; 1249 } 1250 1251 /* For BSTR output is always UTF-16, without 'encoding' attribute */ 1252 static HRESULT node_transform_write_to_bstr(xsltStylesheetPtr style, xmlDocPtr result, BSTR *str) 1253 { 1254 HRESULT hr = S_OK; 1255 1256 if (transform_is_empty_resultdoc(result)) 1257 *str = SysAllocStringLen(NULL, 0); 1258 else 1259 { 1260 xmlOutputBufferPtr output = xmlAllocOutputBuffer(xmlFindCharEncodingHandler("UTF-16")); 1261 const xmlChar *content; 1262 size_t len; 1263 1264 *str = NULL; 1265 if (!output) 1266 return E_OUTOFMEMORY; 1267 1268 hr = node_transform_write(style, result, TRUE, "UTF-16", output); 1269 #ifdef LIBXML2_NEW_BUFFER 1270 content = xmlBufContent(output->conv); 1271 len = xmlBufUse(output->conv); 1272 #else 1273 content = xmlBufferContent(output->conv); 1274 len = xmlBufferLength(output->conv); 1275 #endif 1276 /* UTF-16 encoder places UTF-16 bom, we don't need it for BSTR */ 1277 content += sizeof(WCHAR); 1278 *str = SysAllocStringLen((WCHAR*)content, len/sizeof(WCHAR) - 1); 1279 xmlOutputBufferClose(output); 1280 } 1281 1282 return *str ? hr : E_OUTOFMEMORY; 1283 } 1284 1285 static HRESULT node_transform_write_to_stream(xsltStylesheetPtr style, xmlDocPtr result, ISequentialStream *stream) 1286 { 1287 static const xmlChar *utf16 = (const xmlChar*)"UTF-16"; 1288 xmlOutputBufferPtr output; 1289 const xmlChar *encoding; 1290 HRESULT hr; 1291 1292 if (transform_is_empty_resultdoc(result)) 1293 { 1294 WARN("empty result document\n"); 1295 return S_OK; 1296 } 1297 1298 if (style->methodURI && (!style->method || !xmlStrEqual(style->method, (const xmlChar *) "xhtml"))) 1299 { 1300 ERR("unknown output method\n"); 1301 return E_FAIL; 1302 } 1303 1304 /* default encoding is UTF-16 */ 1305 XSLT_GET_IMPORT_PTR(encoding, style, encoding); 1306 if (!encoding) 1307 encoding = utf16; 1308 1309 output = xmlOutputBufferCreateIO(transform_to_stream_write, NULL, stream, xmlFindCharEncodingHandler((const char*)encoding)); 1310 if (!output) 1311 return E_OUTOFMEMORY; 1312 1313 hr = node_transform_write(style, result, FALSE, (const char*)encoding, output); 1314 xmlOutputBufferClose(output); 1315 return hr; 1316 } 1317 1318 struct import_buffer 1319 { 1320 char *data; 1321 int cur; 1322 int len; 1323 }; 1324 1325 static int XMLCALL import_loader_io_read(void *context, char *out, int len) 1326 { 1327 struct import_buffer *buffer = (struct import_buffer *)context; 1328 1329 TRACE("%p, %p, %d\n", context, out, len); 1330 1331 if (buffer->cur == buffer->len) 1332 return 0; 1333 1334 len = min(len, buffer->len - buffer->cur); 1335 memcpy(out, &buffer->data[buffer->cur], len); 1336 buffer->cur += len; 1337 1338 TRACE("read %d\n", len); 1339 1340 return len; 1341 } 1342 1343 static int XMLCALL import_loader_io_close(void * context) 1344 { 1345 struct import_buffer *buffer = (struct import_buffer *)context; 1346 1347 TRACE("%p\n", context); 1348 1349 heap_free(buffer->data); 1350 heap_free(buffer); 1351 return 0; 1352 } 1353 1354 static HRESULT import_loader_onDataAvailable(void *ctxt, char *ptr, DWORD len) 1355 { 1356 xmlParserInputPtr *input = (xmlParserInputPtr *)ctxt; 1357 xmlParserInputBufferPtr inputbuffer; 1358 struct import_buffer *buffer; 1359 1360 buffer = heap_alloc(sizeof(*buffer)); 1361 1362 buffer->data = heap_alloc(len); 1363 memcpy(buffer->data, ptr, len); 1364 buffer->cur = 0; 1365 buffer->len = len; 1366 1367 inputbuffer = xmlParserInputBufferCreateIO(import_loader_io_read, import_loader_io_close, buffer, 1368 XML_CHAR_ENCODING_NONE); 1369 *input = xmlNewIOInputStream(ctxt, inputbuffer, XML_CHAR_ENCODING_NONE); 1370 if (!*input) 1371 xmlFreeParserInputBuffer(inputbuffer); 1372 1373 return *input ? S_OK : E_FAIL; 1374 } 1375 1376 static HRESULT xslt_doc_get_uri(const xmlChar *uri, void *_ctxt, xsltLoadType type, IUri **doc_uri) 1377 { 1378 xsltStylesheetPtr style = (xsltStylesheetPtr)_ctxt; 1379 IUri *href_uri; 1380 HRESULT hr; 1381 BSTR uriW; 1382 1383 *doc_uri = NULL; 1384 1385 uriW = bstr_from_xmlChar(uri); 1386 hr = CreateUri(uriW, Uri_CREATE_ALLOW_RELATIVE | Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &href_uri); 1387 SysFreeString(uriW); 1388 if (FAILED(hr)) 1389 { 1390 WARN("Failed to create href uri, %#x.\n", hr); 1391 return hr; 1392 } 1393 1394 if (type == XSLT_LOAD_STYLESHEET && style->doc && style->doc->name) 1395 { 1396 IUri *base_uri; 1397 BSTR baseuriW; 1398 1399 baseuriW = bstr_from_xmlChar((xmlChar *)style->doc->name); 1400 hr = CreateUri(baseuriW, Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME, 0, &base_uri); 1401 SysFreeString(baseuriW); 1402 if (FAILED(hr)) 1403 { 1404 WARN("Failed to create base uri, %#x.\n", hr); 1405 return hr; 1406 } 1407 1408 hr = CoInternetCombineIUri(base_uri, href_uri, 0, doc_uri, 0); 1409 IUri_Release(base_uri); 1410 if (FAILED(hr)) 1411 WARN("Failed to combine uris, %#x.\n", hr); 1412 } 1413 else 1414 { 1415 *doc_uri = href_uri; 1416 IUri_AddRef(*doc_uri); 1417 } 1418 1419 IUri_Release(href_uri); 1420 1421 return hr; 1422 } 1423 1424 xmlDocPtr xslt_doc_default_loader(const xmlChar *uri, xmlDictPtr dict, int options, 1425 void *_ctxt, xsltLoadType type) 1426 { 1427 IUri *import_uri = NULL; 1428 xmlParserInputPtr input; 1429 xmlParserCtxtPtr pctxt; 1430 xmlDocPtr doc = NULL; 1431 IMoniker *moniker; 1432 HRESULT hr; 1433 bsc_t *bsc; 1434 BSTR uriW; 1435 1436 TRACE("%s, %p, %#x, %p, %d\n", debugstr_a((const char *)uri), dict, options, _ctxt, type); 1437 1438 pctxt = xmlNewParserCtxt(); 1439 if (!pctxt) 1440 return NULL; 1441 1442 if (dict && pctxt->dict) 1443 { 1444 xmlDictFree(pctxt->dict); 1445 pctxt->dict = NULL; 1446 } 1447 1448 if (dict) 1449 { 1450 pctxt->dict = dict; 1451 xmlDictReference(pctxt->dict); 1452 } 1453 1454 xmlCtxtUseOptions(pctxt, options); 1455 1456 hr = xslt_doc_get_uri(uri, _ctxt, type, &import_uri); 1457 if (FAILED(hr)) 1458 goto failed; 1459 1460 hr = CreateURLMonikerEx2(NULL, import_uri, &moniker, 0); 1461 if (FAILED(hr)) 1462 goto failed; 1463 1464 hr = bind_url(moniker, import_loader_onDataAvailable, &input, &bsc); 1465 IMoniker_Release(moniker); 1466 if (FAILED(hr)) 1467 goto failed; 1468 1469 if (FAILED(detach_bsc(bsc))) 1470 goto failed; 1471 1472 if (!input) 1473 goto failed; 1474 1475 inputPush(pctxt, input); 1476 xmlParseDocument(pctxt); 1477 1478 if (pctxt->wellFormed) 1479 { 1480 doc = pctxt->myDoc; 1481 /* Set imported uri, to give nested imports a chance. */ 1482 if (IUri_GetPropertyBSTR(import_uri, Uri_PROPERTY_ABSOLUTE_URI, &uriW, 0) == S_OK) 1483 { 1484 doc->name = (char *)xmlchar_from_wcharn(uriW, SysStringLen(uriW), TRUE); 1485 SysFreeString(uriW); 1486 } 1487 } 1488 else 1489 { 1490 doc = NULL; 1491 xmlFreeDoc(pctxt->myDoc); 1492 pctxt->myDoc = NULL; 1493 } 1494 1495 failed: 1496 xmlFreeParserCtxt(pctxt); 1497 if (import_uri) 1498 IUri_Release(import_uri); 1499 1500 return doc; 1501 } 1502 1503 #endif /* SONAME_LIBXSLT */ 1504 1505 HRESULT node_transform_node_params(const xmlnode *This, IXMLDOMNode *stylesheet, BSTR *p, 1506 ISequentialStream *stream, const struct xslprocessor_params *params) 1507 { 1508 #ifdef SONAME_LIBXSLT 1509 xsltStylesheetPtr xsltSS; 1510 xmlDocPtr sheet_doc; 1511 HRESULT hr = S_OK; 1512 xmlnode *sheet; 1513 1514 if (!libxslt_handle) return E_NOTIMPL; 1515 if (!stylesheet || !p) return E_INVALIDARG; 1516 1517 *p = NULL; 1518 1519 sheet = get_node_obj(stylesheet); 1520 if(!sheet) return E_FAIL; 1521 1522 sheet_doc = xmlCopyDoc(sheet->node->doc, 1); 1523 xsltSS = pxsltParseStylesheetDoc(sheet_doc); 1524 if (xsltSS) 1525 { 1526 const char **xslparams = NULL; 1527 xmlDocPtr result; 1528 unsigned int i; 1529 1530 /* convert our parameter list to libxml2 format */ 1531 if (params && params->count) 1532 { 1533 struct xslprocessor_par *par; 1534 1535 i = 0; 1536 xslparams = heap_alloc((params->count*2 + 1)*sizeof(char*)); 1537 LIST_FOR_EACH_ENTRY(par, ¶ms->list, struct xslprocessor_par, entry) 1538 { 1539 xslparams[i++] = (char*)xmlchar_from_wchar(par->name); 1540 xslparams[i++] = (char*)xmlchar_from_wchar(par->value); 1541 } 1542 xslparams[i] = NULL; 1543 } 1544 1545 if (xslparams) 1546 { 1547 xsltTransformContextPtr ctxt = pxsltNewTransformContext(xsltSS, This->node->doc); 1548 1549 /* push parameters to user context */ 1550 pxsltQuoteUserParams(ctxt, xslparams); 1551 result = pxsltApplyStylesheetUser(xsltSS, This->node->doc, NULL, NULL, NULL, ctxt); 1552 pxsltFreeTransformContext(ctxt); 1553 1554 for (i = 0; i < params->count*2; i++) 1555 heap_free((char*)xslparams[i]); 1556 heap_free(xslparams); 1557 } 1558 else 1559 result = pxsltApplyStylesheet(xsltSS, This->node->doc, NULL); 1560 1561 if (result) 1562 { 1563 if (stream) 1564 hr = node_transform_write_to_stream(xsltSS, result, stream); 1565 else 1566 hr = node_transform_write_to_bstr(xsltSS, result, p); 1567 xmlFreeDoc(result); 1568 } 1569 1570 pxsltFreeStylesheet(xsltSS); 1571 } 1572 else 1573 xmlFreeDoc(sheet_doc); 1574 1575 if(!*p) *p = SysAllocStringLen(NULL, 0); 1576 1577 return hr; 1578 #else 1579 ERR_(winediag)("libxslt headers were not found at compile time. Expect problems.\n"); 1580 1581 return E_NOTIMPL; 1582 #endif 1583 } 1584 1585 HRESULT node_transform_node(const xmlnode *node, IXMLDOMNode *stylesheet, BSTR *p) 1586 { 1587 return node_transform_node_params(node, stylesheet, p, NULL, NULL); 1588 } 1589 1590 HRESULT node_select_nodes(const xmlnode *This, BSTR query, IXMLDOMNodeList **nodes) 1591 { 1592 xmlChar* str; 1593 HRESULT hr; 1594 1595 if (!query || !nodes) return E_INVALIDARG; 1596 1597 str = xmlchar_from_wchar(query); 1598 hr = create_selection(This->node, str, nodes); 1599 heap_free(str); 1600 1601 return hr; 1602 } 1603 1604 HRESULT node_select_singlenode(const xmlnode *This, BSTR query, IXMLDOMNode **node) 1605 { 1606 IXMLDOMNodeList *list; 1607 HRESULT hr; 1608 1609 hr = node_select_nodes(This, query, &list); 1610 if (hr == S_OK) 1611 { 1612 hr = IXMLDOMNodeList_nextNode(list, node); 1613 IXMLDOMNodeList_Release(list); 1614 } 1615 return hr; 1616 } 1617 1618 HRESULT node_get_namespaceURI(xmlnode *This, BSTR *namespaceURI) 1619 { 1620 xmlNsPtr ns = This->node->ns; 1621 1622 if(!namespaceURI) 1623 return E_INVALIDARG; 1624 1625 *namespaceURI = NULL; 1626 1627 if (ns && ns->href) 1628 *namespaceURI = bstr_from_xmlChar(ns->href); 1629 1630 TRACE("uri: %s\n", debugstr_w(*namespaceURI)); 1631 1632 return *namespaceURI ? S_OK : S_FALSE; 1633 } 1634 1635 HRESULT node_get_prefix(xmlnode *This, BSTR *prefix) 1636 { 1637 xmlNsPtr ns = This->node->ns; 1638 1639 if (!prefix) return E_INVALIDARG; 1640 1641 *prefix = NULL; 1642 1643 if (ns && ns->prefix) 1644 *prefix = bstr_from_xmlChar(ns->prefix); 1645 1646 TRACE("prefix: %s\n", debugstr_w(*prefix)); 1647 1648 return *prefix ? S_OK : S_FALSE; 1649 } 1650 1651 HRESULT node_get_base_name(xmlnode *This, BSTR *name) 1652 { 1653 if (!name) return E_INVALIDARG; 1654 1655 *name = bstr_from_xmlChar(This->node->name); 1656 if (!*name) return E_OUTOFMEMORY; 1657 1658 TRACE("returning %s\n", debugstr_w(*name)); 1659 1660 return S_OK; 1661 } 1662 1663 void destroy_xmlnode(xmlnode *This) 1664 { 1665 if(This->node) 1666 { 1667 xmlnode_release(This->node); 1668 xmldoc_release(This->node->doc); 1669 } 1670 } 1671 1672 void init_xmlnode(xmlnode *This, xmlNodePtr node, IXMLDOMNode *node_iface, dispex_static_data_t *dispex_data) 1673 { 1674 if(node) 1675 { 1676 xmlnode_add_ref(node); 1677 xmldoc_add_ref(node->doc); 1678 } 1679 1680 This->node = node; 1681 This->iface = node_iface; 1682 This->parent = NULL; 1683 1684 init_dispex(&This->dispex, (IUnknown*)This->iface, dispex_data); 1685 } 1686 1687 typedef struct { 1688 xmlnode node; 1689 IXMLDOMNode IXMLDOMNode_iface; 1690 LONG ref; 1691 } unknode; 1692 1693 static inline unknode *unknode_from_IXMLDOMNode(IXMLDOMNode *iface) 1694 { 1695 return CONTAINING_RECORD(iface, unknode, IXMLDOMNode_iface); 1696 } 1697 1698 static HRESULT WINAPI unknode_QueryInterface( 1699 IXMLDOMNode *iface, 1700 REFIID riid, 1701 void** ppvObject ) 1702 { 1703 unknode *This = unknode_from_IXMLDOMNode( iface ); 1704 1705 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 1706 1707 if (IsEqualGUID(riid, &IID_IUnknown)) { 1708 *ppvObject = iface; 1709 }else if (IsEqualGUID( riid, &IID_IDispatch) || 1710 IsEqualGUID( riid, &IID_IXMLDOMNode)) { 1711 *ppvObject = &This->IXMLDOMNode_iface; 1712 }else if(node_query_interface(&This->node, riid, ppvObject)) { 1713 return *ppvObject ? S_OK : E_NOINTERFACE; 1714 }else { 1715 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 1716 *ppvObject = NULL; 1717 return E_NOINTERFACE; 1718 } 1719 1720 IUnknown_AddRef((IUnknown*)*ppvObject); 1721 return S_OK; 1722 } 1723 1724 static ULONG WINAPI unknode_AddRef( 1725 IXMLDOMNode *iface ) 1726 { 1727 unknode *This = unknode_from_IXMLDOMNode( iface ); 1728 1729 return InterlockedIncrement(&This->ref); 1730 } 1731 1732 static ULONG WINAPI unknode_Release( 1733 IXMLDOMNode *iface ) 1734 { 1735 unknode *This = unknode_from_IXMLDOMNode( iface ); 1736 LONG ref; 1737 1738 ref = InterlockedDecrement( &This->ref ); 1739 if(!ref) { 1740 destroy_xmlnode(&This->node); 1741 heap_free(This); 1742 } 1743 1744 return ref; 1745 } 1746 1747 static HRESULT WINAPI unknode_GetTypeInfoCount( 1748 IXMLDOMNode *iface, 1749 UINT* pctinfo ) 1750 { 1751 unknode *This = unknode_from_IXMLDOMNode( iface ); 1752 1753 TRACE("(%p)->(%p)\n", This, pctinfo); 1754 1755 *pctinfo = 1; 1756 1757 return S_OK; 1758 } 1759 1760 static HRESULT WINAPI unknode_GetTypeInfo( 1761 IXMLDOMNode *iface, 1762 UINT iTInfo, 1763 LCID lcid, 1764 ITypeInfo** ppTInfo ) 1765 { 1766 unknode *This = unknode_from_IXMLDOMNode( iface ); 1767 HRESULT hr; 1768 1769 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 1770 1771 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo); 1772 1773 return hr; 1774 } 1775 1776 static HRESULT WINAPI unknode_GetIDsOfNames( 1777 IXMLDOMNode *iface, 1778 REFIID riid, 1779 LPOLESTR* rgszNames, 1780 UINT cNames, 1781 LCID lcid, 1782 DISPID* rgDispId ) 1783 { 1784 unknode *This = unknode_from_IXMLDOMNode( iface ); 1785 1786 ITypeInfo *typeinfo; 1787 HRESULT hr; 1788 1789 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 1790 lcid, rgDispId); 1791 1792 if(!rgszNames || cNames == 0 || !rgDispId) 1793 return E_INVALIDARG; 1794 1795 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo); 1796 if(SUCCEEDED(hr)) 1797 { 1798 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 1799 ITypeInfo_Release(typeinfo); 1800 } 1801 1802 return hr; 1803 } 1804 1805 static HRESULT WINAPI unknode_Invoke( 1806 IXMLDOMNode *iface, 1807 DISPID dispIdMember, 1808 REFIID riid, 1809 LCID lcid, 1810 WORD wFlags, 1811 DISPPARAMS* pDispParams, 1812 VARIANT* pVarResult, 1813 EXCEPINFO* pExcepInfo, 1814 UINT* puArgErr ) 1815 { 1816 unknode *This = unknode_from_IXMLDOMNode( iface ); 1817 ITypeInfo *typeinfo; 1818 HRESULT hr; 1819 1820 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 1821 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 1822 1823 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo); 1824 if(SUCCEEDED(hr)) 1825 { 1826 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMNode_iface, dispIdMember, wFlags, pDispParams, 1827 pVarResult, pExcepInfo, puArgErr); 1828 ITypeInfo_Release(typeinfo); 1829 } 1830 1831 return hr; 1832 } 1833 1834 static HRESULT WINAPI unknode_get_nodeName( 1835 IXMLDOMNode *iface, 1836 BSTR* p ) 1837 { 1838 unknode *This = unknode_from_IXMLDOMNode( iface ); 1839 1840 FIXME("(%p)->(%p)\n", This, p); 1841 1842 return node_get_nodeName(&This->node, p); 1843 } 1844 1845 static HRESULT WINAPI unknode_get_nodeValue( 1846 IXMLDOMNode *iface, 1847 VARIANT* value) 1848 { 1849 unknode *This = unknode_from_IXMLDOMNode( iface ); 1850 1851 FIXME("(%p)->(%p)\n", This, value); 1852 1853 if(!value) 1854 return E_INVALIDARG; 1855 1856 V_VT(value) = VT_NULL; 1857 return S_FALSE; 1858 } 1859 1860 static HRESULT WINAPI unknode_put_nodeValue( 1861 IXMLDOMNode *iface, 1862 VARIANT value) 1863 { 1864 unknode *This = unknode_from_IXMLDOMNode( iface ); 1865 FIXME("(%p)->(v%d)\n", This, V_VT(&value)); 1866 return E_FAIL; 1867 } 1868 1869 static HRESULT WINAPI unknode_get_nodeType( 1870 IXMLDOMNode *iface, 1871 DOMNodeType* domNodeType ) 1872 { 1873 unknode *This = unknode_from_IXMLDOMNode( iface ); 1874 1875 FIXME("(%p)->(%p)\n", This, domNodeType); 1876 1877 switch (This->node.node->type) 1878 { 1879 case XML_ELEMENT_NODE: 1880 case XML_ATTRIBUTE_NODE: 1881 case XML_TEXT_NODE: 1882 case XML_CDATA_SECTION_NODE: 1883 case XML_ENTITY_REF_NODE: 1884 case XML_ENTITY_NODE: 1885 case XML_PI_NODE: 1886 case XML_COMMENT_NODE: 1887 case XML_DOCUMENT_NODE: 1888 case XML_DOCUMENT_TYPE_NODE: 1889 case XML_DOCUMENT_FRAG_NODE: 1890 case XML_NOTATION_NODE: 1891 /* we only care about this set of types, libxml2 type values are 1892 exactly what we need */ 1893 *domNodeType = (DOMNodeType)This->node.node->type; 1894 break; 1895 default: 1896 *domNodeType = NODE_INVALID; 1897 break; 1898 } 1899 1900 return S_OK; 1901 } 1902 1903 static HRESULT WINAPI unknode_get_parentNode( 1904 IXMLDOMNode *iface, 1905 IXMLDOMNode** parent ) 1906 { 1907 unknode *This = unknode_from_IXMLDOMNode( iface ); 1908 FIXME("(%p)->(%p)\n", This, parent); 1909 if (!parent) return E_INVALIDARG; 1910 *parent = NULL; 1911 return S_FALSE; 1912 } 1913 1914 static HRESULT WINAPI unknode_get_childNodes( 1915 IXMLDOMNode *iface, 1916 IXMLDOMNodeList** outList) 1917 { 1918 unknode *This = unknode_from_IXMLDOMNode( iface ); 1919 1920 TRACE("(%p)->(%p)\n", This, outList); 1921 1922 return node_get_child_nodes(&This->node, outList); 1923 } 1924 1925 static HRESULT WINAPI unknode_get_firstChild( 1926 IXMLDOMNode *iface, 1927 IXMLDOMNode** domNode) 1928 { 1929 unknode *This = unknode_from_IXMLDOMNode( iface ); 1930 1931 TRACE("(%p)->(%p)\n", This, domNode); 1932 1933 return node_get_first_child(&This->node, domNode); 1934 } 1935 1936 static HRESULT WINAPI unknode_get_lastChild( 1937 IXMLDOMNode *iface, 1938 IXMLDOMNode** domNode) 1939 { 1940 unknode *This = unknode_from_IXMLDOMNode( iface ); 1941 1942 TRACE("(%p)->(%p)\n", This, domNode); 1943 1944 return node_get_last_child(&This->node, domNode); 1945 } 1946 1947 static HRESULT WINAPI unknode_get_previousSibling( 1948 IXMLDOMNode *iface, 1949 IXMLDOMNode** domNode) 1950 { 1951 unknode *This = unknode_from_IXMLDOMNode( iface ); 1952 1953 TRACE("(%p)->(%p)\n", This, domNode); 1954 1955 return node_get_previous_sibling(&This->node, domNode); 1956 } 1957 1958 static HRESULT WINAPI unknode_get_nextSibling( 1959 IXMLDOMNode *iface, 1960 IXMLDOMNode** domNode) 1961 { 1962 unknode *This = unknode_from_IXMLDOMNode( iface ); 1963 1964 TRACE("(%p)->(%p)\n", This, domNode); 1965 1966 return node_get_next_sibling(&This->node, domNode); 1967 } 1968 1969 static HRESULT WINAPI unknode_get_attributes( 1970 IXMLDOMNode *iface, 1971 IXMLDOMNamedNodeMap** attributeMap) 1972 { 1973 unknode *This = unknode_from_IXMLDOMNode( iface ); 1974 1975 FIXME("(%p)->(%p)\n", This, attributeMap); 1976 1977 return return_null_ptr((void**)attributeMap); 1978 } 1979 1980 static HRESULT WINAPI unknode_insertBefore( 1981 IXMLDOMNode *iface, 1982 IXMLDOMNode* newNode, VARIANT refChild, 1983 IXMLDOMNode** outOldNode) 1984 { 1985 unknode *This = unknode_from_IXMLDOMNode( iface ); 1986 1987 FIXME("(%p)->(%p x%d %p)\n", This, newNode, V_VT(&refChild), outOldNode); 1988 1989 return node_insert_before(&This->node, newNode, &refChild, outOldNode); 1990 } 1991 1992 static HRESULT WINAPI unknode_replaceChild( 1993 IXMLDOMNode *iface, 1994 IXMLDOMNode* newNode, 1995 IXMLDOMNode* oldNode, 1996 IXMLDOMNode** outOldNode) 1997 { 1998 unknode *This = unknode_from_IXMLDOMNode( iface ); 1999 2000 FIXME("(%p)->(%p %p %p)\n", This, newNode, oldNode, outOldNode); 2001 2002 return node_replace_child(&This->node, newNode, oldNode, outOldNode); 2003 } 2004 2005 static HRESULT WINAPI unknode_removeChild( 2006 IXMLDOMNode *iface, 2007 IXMLDOMNode* domNode, IXMLDOMNode** oldNode) 2008 { 2009 unknode *This = unknode_from_IXMLDOMNode( iface ); 2010 return node_remove_child(&This->node, domNode, oldNode); 2011 } 2012 2013 static HRESULT WINAPI unknode_appendChild( 2014 IXMLDOMNode *iface, 2015 IXMLDOMNode* newNode, IXMLDOMNode** outNewNode) 2016 { 2017 unknode *This = unknode_from_IXMLDOMNode( iface ); 2018 return node_append_child(&This->node, newNode, outNewNode); 2019 } 2020 2021 static HRESULT WINAPI unknode_hasChildNodes( 2022 IXMLDOMNode *iface, 2023 VARIANT_BOOL* pbool) 2024 { 2025 unknode *This = unknode_from_IXMLDOMNode( iface ); 2026 return node_has_childnodes(&This->node, pbool); 2027 } 2028 2029 static HRESULT WINAPI unknode_get_ownerDocument( 2030 IXMLDOMNode *iface, 2031 IXMLDOMDocument** domDocument) 2032 { 2033 unknode *This = unknode_from_IXMLDOMNode( iface ); 2034 return node_get_owner_doc(&This->node, domDocument); 2035 } 2036 2037 static HRESULT WINAPI unknode_cloneNode( 2038 IXMLDOMNode *iface, 2039 VARIANT_BOOL pbool, IXMLDOMNode** outNode) 2040 { 2041 unknode *This = unknode_from_IXMLDOMNode( iface ); 2042 return node_clone(&This->node, pbool, outNode ); 2043 } 2044 2045 static HRESULT WINAPI unknode_get_nodeTypeString( 2046 IXMLDOMNode *iface, 2047 BSTR* p) 2048 { 2049 unknode *This = unknode_from_IXMLDOMNode( iface ); 2050 2051 FIXME("(%p)->(%p)\n", This, p); 2052 2053 return node_get_nodeName(&This->node, p); 2054 } 2055 2056 static HRESULT WINAPI unknode_get_text( 2057 IXMLDOMNode *iface, 2058 BSTR* p) 2059 { 2060 unknode *This = unknode_from_IXMLDOMNode( iface ); 2061 return node_get_text(&This->node, p); 2062 } 2063 2064 static HRESULT WINAPI unknode_put_text( 2065 IXMLDOMNode *iface, 2066 BSTR p) 2067 { 2068 unknode *This = unknode_from_IXMLDOMNode( iface ); 2069 return node_put_text(&This->node, p); 2070 } 2071 2072 static HRESULT WINAPI unknode_get_specified( 2073 IXMLDOMNode *iface, 2074 VARIANT_BOOL* isSpecified) 2075 { 2076 unknode *This = unknode_from_IXMLDOMNode( iface ); 2077 FIXME("(%p)->(%p) stub!\n", This, isSpecified); 2078 *isSpecified = VARIANT_TRUE; 2079 return S_OK; 2080 } 2081 2082 static HRESULT WINAPI unknode_get_definition( 2083 IXMLDOMNode *iface, 2084 IXMLDOMNode** definitionNode) 2085 { 2086 unknode *This = unknode_from_IXMLDOMNode( iface ); 2087 FIXME("(%p)->(%p)\n", This, definitionNode); 2088 return E_NOTIMPL; 2089 } 2090 2091 static HRESULT WINAPI unknode_get_nodeTypedValue( 2092 IXMLDOMNode *iface, 2093 VARIANT* var1) 2094 { 2095 unknode *This = unknode_from_IXMLDOMNode( iface ); 2096 FIXME("(%p)->(%p)\n", This, var1); 2097 return return_null_var(var1); 2098 } 2099 2100 static HRESULT WINAPI unknode_put_nodeTypedValue( 2101 IXMLDOMNode *iface, 2102 VARIANT typedValue) 2103 { 2104 unknode *This = unknode_from_IXMLDOMNode( iface ); 2105 FIXME("(%p)->(%s)\n", This, debugstr_variant(&typedValue)); 2106 return E_NOTIMPL; 2107 } 2108 2109 static HRESULT WINAPI unknode_get_dataType( 2110 IXMLDOMNode *iface, 2111 VARIANT* var1) 2112 { 2113 unknode *This = unknode_from_IXMLDOMNode( iface ); 2114 TRACE("(%p)->(%p)\n", This, var1); 2115 return return_null_var(var1); 2116 } 2117 2118 static HRESULT WINAPI unknode_put_dataType( 2119 IXMLDOMNode *iface, 2120 BSTR p) 2121 { 2122 unknode *This = unknode_from_IXMLDOMNode( iface ); 2123 2124 FIXME("(%p)->(%s)\n", This, debugstr_w(p)); 2125 2126 if(!p) 2127 return E_INVALIDARG; 2128 2129 return E_FAIL; 2130 } 2131 2132 static HRESULT WINAPI unknode_get_xml( 2133 IXMLDOMNode *iface, 2134 BSTR* p) 2135 { 2136 unknode *This = unknode_from_IXMLDOMNode( iface ); 2137 2138 FIXME("(%p)->(%p)\n", This, p); 2139 2140 return node_get_xml(&This->node, FALSE, p); 2141 } 2142 2143 static HRESULT WINAPI unknode_transformNode( 2144 IXMLDOMNode *iface, 2145 IXMLDOMNode* domNode, BSTR* p) 2146 { 2147 unknode *This = unknode_from_IXMLDOMNode( iface ); 2148 return node_transform_node(&This->node, domNode, p); 2149 } 2150 2151 static HRESULT WINAPI unknode_selectNodes( 2152 IXMLDOMNode *iface, 2153 BSTR p, IXMLDOMNodeList** outList) 2154 { 2155 unknode *This = unknode_from_IXMLDOMNode( iface ); 2156 return node_select_nodes(&This->node, p, outList); 2157 } 2158 2159 static HRESULT WINAPI unknode_selectSingleNode( 2160 IXMLDOMNode *iface, 2161 BSTR p, IXMLDOMNode** outNode) 2162 { 2163 unknode *This = unknode_from_IXMLDOMNode( iface ); 2164 return node_select_singlenode(&This->node, p, outNode); 2165 } 2166 2167 static HRESULT WINAPI unknode_get_parsed( 2168 IXMLDOMNode *iface, 2169 VARIANT_BOOL* isParsed) 2170 { 2171 unknode *This = unknode_from_IXMLDOMNode( iface ); 2172 FIXME("(%p)->(%p) stub!\n", This, isParsed); 2173 *isParsed = VARIANT_TRUE; 2174 return S_OK; 2175 } 2176 2177 static HRESULT WINAPI unknode_get_namespaceURI( 2178 IXMLDOMNode *iface, 2179 BSTR* p) 2180 { 2181 unknode *This = unknode_from_IXMLDOMNode( iface ); 2182 TRACE("(%p)->(%p)\n", This, p); 2183 return node_get_namespaceURI(&This->node, p); 2184 } 2185 2186 static HRESULT WINAPI unknode_get_prefix( 2187 IXMLDOMNode *iface, 2188 BSTR* p) 2189 { 2190 unknode *This = unknode_from_IXMLDOMNode( iface ); 2191 return node_get_prefix(&This->node, p); 2192 } 2193 2194 static HRESULT WINAPI unknode_get_baseName( 2195 IXMLDOMNode *iface, 2196 BSTR* p) 2197 { 2198 unknode *This = unknode_from_IXMLDOMNode( iface ); 2199 return node_get_base_name(&This->node, p); 2200 } 2201 2202 static HRESULT WINAPI unknode_transformNodeToObject( 2203 IXMLDOMNode *iface, 2204 IXMLDOMNode* domNode, VARIANT var1) 2205 { 2206 unknode *This = unknode_from_IXMLDOMNode( iface ); 2207 FIXME("(%p)->(%p %s)\n", This, domNode, debugstr_variant(&var1)); 2208 return E_NOTIMPL; 2209 } 2210 2211 static const struct IXMLDOMNodeVtbl unknode_vtbl = 2212 { 2213 unknode_QueryInterface, 2214 unknode_AddRef, 2215 unknode_Release, 2216 unknode_GetTypeInfoCount, 2217 unknode_GetTypeInfo, 2218 unknode_GetIDsOfNames, 2219 unknode_Invoke, 2220 unknode_get_nodeName, 2221 unknode_get_nodeValue, 2222 unknode_put_nodeValue, 2223 unknode_get_nodeType, 2224 unknode_get_parentNode, 2225 unknode_get_childNodes, 2226 unknode_get_firstChild, 2227 unknode_get_lastChild, 2228 unknode_get_previousSibling, 2229 unknode_get_nextSibling, 2230 unknode_get_attributes, 2231 unknode_insertBefore, 2232 unknode_replaceChild, 2233 unknode_removeChild, 2234 unknode_appendChild, 2235 unknode_hasChildNodes, 2236 unknode_get_ownerDocument, 2237 unknode_cloneNode, 2238 unknode_get_nodeTypeString, 2239 unknode_get_text, 2240 unknode_put_text, 2241 unknode_get_specified, 2242 unknode_get_definition, 2243 unknode_get_nodeTypedValue, 2244 unknode_put_nodeTypedValue, 2245 unknode_get_dataType, 2246 unknode_put_dataType, 2247 unknode_get_xml, 2248 unknode_transformNode, 2249 unknode_selectNodes, 2250 unknode_selectSingleNode, 2251 unknode_get_parsed, 2252 unknode_get_namespaceURI, 2253 unknode_get_prefix, 2254 unknode_get_baseName, 2255 unknode_transformNodeToObject 2256 }; 2257 2258 IXMLDOMNode *create_node( xmlNodePtr node ) 2259 { 2260 IUnknown *pUnk; 2261 IXMLDOMNode *ret; 2262 HRESULT hr; 2263 2264 if ( !node ) 2265 return NULL; 2266 2267 TRACE("type %d\n", node->type); 2268 switch(node->type) 2269 { 2270 case XML_ELEMENT_NODE: 2271 pUnk = create_element( node ); 2272 break; 2273 case XML_ATTRIBUTE_NODE: 2274 pUnk = create_attribute( node, FALSE ); 2275 break; 2276 case XML_TEXT_NODE: 2277 pUnk = create_text( node ); 2278 break; 2279 case XML_CDATA_SECTION_NODE: 2280 pUnk = create_cdata( node ); 2281 break; 2282 case XML_ENTITY_REF_NODE: 2283 pUnk = create_doc_entity_ref( node ); 2284 break; 2285 case XML_PI_NODE: 2286 pUnk = create_pi( node ); 2287 break; 2288 case XML_COMMENT_NODE: 2289 pUnk = create_comment( node ); 2290 break; 2291 case XML_DOCUMENT_NODE: 2292 pUnk = create_domdoc( node ); 2293 break; 2294 case XML_DOCUMENT_FRAG_NODE: 2295 pUnk = create_doc_fragment( node ); 2296 break; 2297 case XML_DTD_NODE: 2298 case XML_DOCUMENT_TYPE_NODE: 2299 pUnk = create_doc_type( node ); 2300 break; 2301 case XML_ENTITY_NODE: 2302 case XML_NOTATION_NODE: { 2303 unknode *new_node; 2304 2305 FIXME("only creating basic node for type %d\n", node->type); 2306 2307 new_node = heap_alloc(sizeof(unknode)); 2308 if(!new_node) 2309 return NULL; 2310 2311 new_node->IXMLDOMNode_iface.lpVtbl = &unknode_vtbl; 2312 new_node->ref = 1; 2313 init_xmlnode(&new_node->node, node, &new_node->IXMLDOMNode_iface, NULL); 2314 pUnk = (IUnknown*)&new_node->IXMLDOMNode_iface; 2315 break; 2316 } 2317 default: 2318 ERR("Called for unsupported node type %d\n", node->type); 2319 return NULL; 2320 } 2321 2322 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret); 2323 IUnknown_Release(pUnk); 2324 if(FAILED(hr)) return NULL; 2325 return ret; 2326 } 2327 #endif 2328