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 #include <assert.h> 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winuser.h" 30 #include "winnls.h" 31 #include "ole2.h" 32 #include "msxml2.h" 33 34 #include "msxml_private.h" 35 36 #ifdef HAVE_LIBXSLT 37 # ifdef HAVE_LIBXSLT_PATTERN_H 38 # include <libxslt/pattern.h> 39 # endif 40 # ifdef HAVE_LIBXSLT_TRANSFORM_H 41 # include <libxslt/transform.h> 42 # endif 43 # include <libxslt/xsltutils.h> 44 # include <libxslt/xsltInternals.h> 45 #endif 46 47 #ifdef HAVE_LIBXML2 48 # include <libxml/HTMLtree.h> 49 #endif 50 51 #include "wine/debug.h" 52 53 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 54 55 #ifdef HAVE_LIBXML2 56 57 static const WCHAR szBinBase64[] = {'b','i','n','.','b','a','s','e','6','4',0}; 58 static const WCHAR szString[] = {'s','t','r','i','n','g',0}; 59 static const WCHAR szNumber[] = {'n','u','m','b','e','r',0}; 60 static const WCHAR szInt[] = {'I','n','t',0}; 61 static const WCHAR szFixed[] = {'F','i','x','e','d','.','1','4','.','4',0}; 62 static const WCHAR szBoolean[] = {'B','o','o','l','e','a','n',0}; 63 static const WCHAR szDateTime[] = {'d','a','t','e','T','i','m','e',0}; 64 static const WCHAR szDateTimeTZ[] = {'d','a','t','e','T','i','m','e','.','t','z',0}; 65 static const WCHAR szDate[] = {'D','a','t','e',0}; 66 static const WCHAR szTime[] = {'T','i','m','e',0}; 67 static const WCHAR szTimeTZ[] = {'T','i','m','e','.','t','z',0}; 68 static const WCHAR szI1[] = {'i','1',0}; 69 static const WCHAR szI2[] = {'i','2',0}; 70 static const WCHAR szI4[] = {'i','4',0}; 71 static const WCHAR szIU1[] = {'u','i','1',0}; 72 static const WCHAR szIU2[] = {'u','i','2',0}; 73 static const WCHAR szIU4[] = {'u','i','4',0}; 74 static const WCHAR szR4[] = {'r','4',0}; 75 static const WCHAR szR8[] = {'r','8',0}; 76 static const WCHAR szFloat[] = {'f','l','o','a','t',0}; 77 static const WCHAR szUUID[] = {'u','u','i','d',0}; 78 static const WCHAR szBinHex[] = {'b','i','n','.','h','e','x',0}; 79 80 static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface ) 81 { 82 return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl)); 83 } 84 85 xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) 86 { 87 xmlnode *This; 88 89 if ( !iface ) 90 return NULL; 91 This = impl_from_IXMLDOMNode( iface ); 92 if ( !This->node ) 93 return NULL; 94 if ( type && This->node->type != type ) 95 return NULL; 96 return This->node; 97 } 98 99 void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml ) 100 { 101 xmlnode *This = impl_from_IXMLDOMNode( node ); 102 103 if(This->node) 104 xmldoc_release(This->node->doc); 105 106 This->node = xml; 107 if(This->node) 108 xmldoc_add_ref(This->node->doc); 109 110 return; 111 } 112 113 static HRESULT WINAPI xmlnode_QueryInterface( 114 IXMLDOMNode *iface, 115 REFIID riid, 116 void** ppvObject ) 117 { 118 xmlnode *This = impl_from_IXMLDOMNode( iface ); 119 TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); 120 121 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); 122 } 123 124 static ULONG WINAPI xmlnode_AddRef( 125 IXMLDOMNode *iface ) 126 { 127 xmlnode *This = impl_from_IXMLDOMNode( iface ); 128 return IUnknown_AddRef(This->pUnkOuter); 129 } 130 131 static ULONG WINAPI xmlnode_Release( 132 IXMLDOMNode *iface ) 133 { 134 xmlnode *This = impl_from_IXMLDOMNode( iface ); 135 return IUnknown_Release(This->pUnkOuter); 136 } 137 138 static HRESULT WINAPI xmlnode_GetTypeInfoCount( 139 IXMLDOMNode *iface, 140 UINT* pctinfo ) 141 { 142 xmlnode *This = impl_from_IXMLDOMNode( iface ); 143 144 TRACE("(%p)->(%p)\n", This, pctinfo); 145 146 *pctinfo = 1; 147 148 return S_OK; 149 } 150 151 static HRESULT WINAPI xmlnode_GetTypeInfo( 152 IXMLDOMNode *iface, 153 UINT iTInfo, 154 LCID lcid, 155 ITypeInfo** ppTInfo ) 156 { 157 xmlnode *This = impl_from_IXMLDOMNode( iface ); 158 HRESULT hr; 159 160 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 161 162 hr = get_typeinfo(IXMLDOMNode_tid, ppTInfo); 163 164 return hr; 165 } 166 167 static HRESULT WINAPI xmlnode_GetIDsOfNames( 168 IXMLDOMNode *iface, 169 REFIID riid, 170 LPOLESTR* rgszNames, 171 UINT cNames, 172 LCID lcid, 173 DISPID* rgDispId ) 174 { 175 xmlnode *This = impl_from_IXMLDOMNode( iface ); 176 177 ITypeInfo *typeinfo; 178 HRESULT hr; 179 180 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 181 lcid, rgDispId); 182 183 if(!rgszNames || cNames == 0 || !rgDispId) 184 return E_INVALIDARG; 185 186 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo); 187 if(SUCCEEDED(hr)) 188 { 189 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 190 ITypeInfo_Release(typeinfo); 191 } 192 193 return hr; 194 } 195 196 static HRESULT WINAPI xmlnode_Invoke( 197 IXMLDOMNode *iface, 198 DISPID dispIdMember, 199 REFIID riid, 200 LCID lcid, 201 WORD wFlags, 202 DISPPARAMS* pDispParams, 203 VARIANT* pVarResult, 204 EXCEPINFO* pExcepInfo, 205 UINT* puArgErr ) 206 { 207 xmlnode *This = impl_from_IXMLDOMNode( iface ); 208 ITypeInfo *typeinfo; 209 HRESULT hr; 210 211 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 212 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 213 214 hr = get_typeinfo(IXMLDOMNode_tid, &typeinfo); 215 if(SUCCEEDED(hr)) 216 { 217 hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams, 218 pVarResult, pExcepInfo, puArgErr); 219 ITypeInfo_Release(typeinfo); 220 } 221 222 return hr; 223 } 224 225 static HRESULT WINAPI xmlnode_get_nodeName( 226 IXMLDOMNode *iface, 227 BSTR* name) 228 { 229 xmlnode *This = impl_from_IXMLDOMNode( iface ); 230 const xmlChar *str; 231 232 TRACE("%p\n", This ); 233 234 if (!name) 235 return E_INVALIDARG; 236 237 if ( !This->node ) 238 return E_FAIL; 239 240 switch( This->node->type ) 241 { 242 case XML_CDATA_SECTION_NODE: 243 str = (const xmlChar*) "#cdata-section"; 244 break; 245 case XML_COMMENT_NODE: 246 str = (const xmlChar*) "#comment"; 247 break; 248 case XML_DOCUMENT_FRAG_NODE: 249 str = (const xmlChar*) "#document-fragment"; 250 break; 251 case XML_TEXT_NODE: 252 str = (const xmlChar*) "#text"; 253 break; 254 case XML_DOCUMENT_NODE: 255 str = (const xmlChar*) "#document"; 256 break; 257 case XML_ATTRIBUTE_NODE: 258 case XML_ELEMENT_NODE: 259 case XML_PI_NODE: 260 str = This->node->name; 261 break; 262 default: 263 FIXME("nodeName not mapped correctly (%d)\n", This->node->type); 264 str = This->node->name; 265 break; 266 } 267 268 *name = bstr_from_xmlChar( str ); 269 if (!*name) 270 return S_FALSE; 271 272 return S_OK; 273 } 274 275 BSTR bstr_from_xmlChar( const xmlChar *buf ) 276 { 277 DWORD len; 278 LPWSTR str; 279 BSTR bstr; 280 281 if ( !buf ) 282 return NULL; 283 284 len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 ); 285 str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); 286 if ( !str ) 287 return NULL; 288 MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len ); 289 bstr = SysAllocString( str ); 290 HeapFree( GetProcessHeap(), 0, str ); 291 return bstr; 292 } 293 294 static HRESULT WINAPI xmlnode_get_nodeValue( 295 IXMLDOMNode *iface, 296 VARIANT* value) 297 { 298 xmlnode *This = impl_from_IXMLDOMNode( iface ); 299 HRESULT r = S_FALSE; 300 301 TRACE("%p %p\n", This, value); 302 303 if(!value) 304 return E_INVALIDARG; 305 306 V_BSTR(value) = NULL; 307 V_VT(value) = VT_NULL; 308 309 switch ( This->node->type ) 310 { 311 case XML_CDATA_SECTION_NODE: 312 case XML_COMMENT_NODE: 313 case XML_PI_NODE: 314 case XML_ATTRIBUTE_NODE: 315 { 316 xmlChar *content = xmlNodeGetContent(This->node); 317 V_VT(value) = VT_BSTR; 318 V_BSTR(value) = bstr_from_xmlChar( content ); 319 xmlFree(content); 320 r = S_OK; 321 break; 322 } 323 case XML_TEXT_NODE: 324 V_VT(value) = VT_BSTR; 325 V_BSTR(value) = bstr_from_xmlChar( This->node->content ); 326 r = S_OK; 327 break; 328 case XML_ELEMENT_NODE: 329 case XML_DOCUMENT_NODE: 330 /* these seem to return NULL */ 331 break; 332 333 default: 334 FIXME("node %p type %d\n", This, This->node->type); 335 } 336 337 TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) ); 338 339 return r; 340 } 341 342 static HRESULT WINAPI xmlnode_put_nodeValue( 343 IXMLDOMNode *iface, 344 VARIANT value) 345 { 346 xmlnode *This = impl_from_IXMLDOMNode( iface ); 347 HRESULT hr = S_FALSE; 348 xmlChar *str = NULL; 349 350 TRACE("%p type(%d)\n", This, This->node->type); 351 352 /* Document, Document Fragment, Document Type, Element, 353 Entity, Entity Reference, Notation aren't supported. */ 354 switch ( This->node->type ) 355 { 356 case XML_ATTRIBUTE_NODE: 357 case XML_CDATA_SECTION_NODE: 358 case XML_COMMENT_NODE: 359 case XML_PI_NODE: 360 case XML_TEXT_NODE: 361 { 362 str = xmlChar_from_wchar((WCHAR*)V_BSTR(&value)); 363 364 xmlNodeSetContent(This->node, str); 365 hr = S_OK; 366 break; 367 } 368 default: 369 /* Do nothing for unsupported types. */ 370 break; 371 } 372 373 return hr; 374 } 375 376 static HRESULT WINAPI xmlnode_get_nodeType( 377 IXMLDOMNode *iface, 378 DOMNodeType* type) 379 { 380 xmlnode *This = impl_from_IXMLDOMNode( iface ); 381 382 TRACE("%p %p\n", This, type); 383 384 assert( NODE_ELEMENT == XML_ELEMENT_NODE ); 385 assert( NODE_NOTATION == XML_NOTATION_NODE ); 386 387 *type = This->node->type; 388 389 return S_OK; 390 } 391 392 static HRESULT get_node( 393 xmlnode *This, 394 const char *name, 395 xmlNodePtr node, 396 IXMLDOMNode **out ) 397 { 398 TRACE("%p->%s %p\n", This, name, node ); 399 400 if ( !out ) 401 return E_INVALIDARG; 402 *out = create_node( node ); 403 if (!*out) 404 return S_FALSE; 405 return S_OK; 406 } 407 408 static HRESULT WINAPI xmlnode_get_parentNode( 409 IXMLDOMNode *iface, 410 IXMLDOMNode** parent) 411 { 412 xmlnode *This = impl_from_IXMLDOMNode( iface ); 413 return get_node( This, "parent", This->node->parent, parent ); 414 } 415 416 static HRESULT WINAPI xmlnode_get_childNodes( 417 IXMLDOMNode *iface, 418 IXMLDOMNodeList** childList) 419 { 420 xmlnode *This = impl_from_IXMLDOMNode( iface ); 421 422 TRACE("%p %p\n", This, childList ); 423 424 if ( !childList ) 425 return E_INVALIDARG; 426 427 *childList = create_children_nodelist(This->node); 428 if (*childList == NULL) 429 return E_OUTOFMEMORY; 430 431 return S_OK; 432 } 433 434 static HRESULT WINAPI xmlnode_get_firstChild( 435 IXMLDOMNode *iface, 436 IXMLDOMNode** firstChild) 437 { 438 xmlnode *This = impl_from_IXMLDOMNode( iface ); 439 return get_node( This, "firstChild", This->node->children, firstChild ); 440 } 441 442 static HRESULT WINAPI xmlnode_get_lastChild( 443 IXMLDOMNode *iface, 444 IXMLDOMNode** lastChild) 445 { 446 xmlnode *This = impl_from_IXMLDOMNode( iface ); 447 448 TRACE("%p\n", This ); 449 450 if (!lastChild) 451 return E_INVALIDARG; 452 453 switch( This->node->type ) 454 { 455 /* CDATASection, Comment, PI and Text Nodes do not support lastChild */ 456 case XML_TEXT_NODE: 457 case XML_CDATA_SECTION_NODE: 458 case XML_PI_NODE: 459 case XML_COMMENT_NODE: 460 *lastChild = NULL; 461 return S_FALSE; 462 default: 463 return get_node( This, "lastChild", This->node->last, lastChild ); 464 } 465 } 466 467 static HRESULT WINAPI xmlnode_get_previousSibling( 468 IXMLDOMNode *iface, 469 IXMLDOMNode** previousSibling) 470 { 471 xmlnode *This = impl_from_IXMLDOMNode( iface ); 472 473 TRACE("%p\n", This ); 474 475 if (!previousSibling) 476 return E_INVALIDARG; 477 478 switch( This->node->type ) 479 { 480 /* Attribute, Document and Document Fragment Nodes do not support previousSibling */ 481 case XML_DOCUMENT_NODE: 482 case XML_DOCUMENT_FRAG_NODE: 483 case XML_ATTRIBUTE_NODE: 484 *previousSibling = NULL; 485 return S_FALSE; 486 default: 487 return get_node( This, "previous", This->node->prev, previousSibling ); 488 } 489 } 490 491 static HRESULT WINAPI xmlnode_get_nextSibling( 492 IXMLDOMNode *iface, 493 IXMLDOMNode** nextSibling) 494 { 495 xmlnode *This = impl_from_IXMLDOMNode( iface ); 496 497 TRACE("%p\n", This ); 498 499 if (!nextSibling) 500 return E_INVALIDARG; 501 502 switch( This->node->type ) 503 { 504 /* Attribute, Document and Document Fragment Nodes do not support nextSibling */ 505 case XML_DOCUMENT_NODE: 506 case XML_DOCUMENT_FRAG_NODE: 507 case XML_ATTRIBUTE_NODE: 508 *nextSibling = NULL; 509 return S_FALSE; 510 default: 511 return get_node( This, "next", This->node->next, nextSibling ); 512 } 513 } 514 515 static HRESULT WINAPI xmlnode_get_attributes( 516 IXMLDOMNode *iface, 517 IXMLDOMNamedNodeMap** attributeMap) 518 { 519 xmlnode *This = impl_from_IXMLDOMNode( iface ); 520 TRACE("%p\n", This); 521 522 if (!attributeMap) 523 return E_INVALIDARG; 524 525 switch( This->node->type ) 526 { 527 /* Attribute, CDataSection, Comment, Documents, Documents Fragments, 528 Entity and Text Nodes does not support get_attributes */ 529 case XML_ATTRIBUTE_NODE: 530 case XML_CDATA_SECTION_NODE: 531 case XML_COMMENT_NODE: 532 case XML_DOCUMENT_NODE: 533 case XML_DOCUMENT_FRAG_NODE: 534 case XML_ENTITY_NODE: 535 case XML_ENTITY_REF_NODE: 536 case XML_TEXT_NODE: 537 *attributeMap = NULL; 538 return S_FALSE; 539 default: 540 *attributeMap = create_nodemap( iface ); 541 return S_OK; 542 } 543 } 544 545 static HRESULT WINAPI xmlnode_insertBefore( 546 IXMLDOMNode *iface, 547 IXMLDOMNode* newChild, 548 VARIANT refChild, 549 IXMLDOMNode** outNewChild) 550 { 551 xmlnode *This = impl_from_IXMLDOMNode( iface ); 552 xmlNodePtr before_node, new_child_node; 553 IXMLDOMNode *before = NULL, *new; 554 HRESULT hr; 555 556 TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild); 557 558 if (!newChild) 559 return E_INVALIDARG; 560 561 switch(V_VT(&refChild)) 562 { 563 case VT_EMPTY: 564 case VT_NULL: 565 break; 566 567 case VT_UNKNOWN: 568 hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before); 569 if(FAILED(hr)) return hr; 570 break; 571 572 case VT_DISPATCH: 573 hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before); 574 if(FAILED(hr)) return hr; 575 break; 576 577 default: 578 FIXME("refChild var type %x\n", V_VT(&refChild)); 579 return E_FAIL; 580 } 581 582 IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new); 583 new_child_node = impl_from_IXMLDOMNode(new)->node; 584 TRACE("new_child_node %p This->node %p\n", new_child_node, This->node); 585 586 if(before) 587 { 588 before_node = impl_from_IXMLDOMNode(before)->node; 589 xmlAddPrevSibling(before_node, new_child_node); 590 IXMLDOMNode_Release(before); 591 } 592 else 593 { 594 xmlAddChild(This->node, new_child_node); 595 } 596 597 IXMLDOMNode_Release(new); 598 IXMLDOMNode_AddRef(newChild); 599 if(outNewChild) 600 *outNewChild = newChild; 601 602 TRACE("ret S_OK\n"); 603 return S_OK; 604 } 605 606 static HRESULT WINAPI xmlnode_replaceChild( 607 IXMLDOMNode *iface, 608 IXMLDOMNode* newChild, 609 IXMLDOMNode* oldChild, 610 IXMLDOMNode** outOldChild) 611 { 612 FIXME("\n"); 613 return E_NOTIMPL; 614 } 615 616 static HRESULT WINAPI xmlnode_removeChild( 617 IXMLDOMNode *iface, 618 IXMLDOMNode* childNode, 619 IXMLDOMNode** oldChild) 620 { 621 xmlnode *This = impl_from_IXMLDOMNode( iface ); 622 xmlNode *ancestor, *child_node_ptr; 623 HRESULT hr; 624 IXMLDOMNode *child; 625 626 TRACE("%p->(%p, %p)\n", This, childNode, oldChild); 627 628 if(oldChild) 629 *oldChild = NULL; 630 631 if(!childNode) return E_INVALIDARG; 632 633 hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child); 634 if(FAILED(hr)) 635 return hr; 636 637 child_node_ptr = ancestor = impl_from_IXMLDOMNode(child)->node; 638 while(ancestor->parent) 639 { 640 if(ancestor->parent == This->node) 641 break; 642 ancestor = ancestor->parent; 643 } 644 if(!ancestor->parent) 645 { 646 WARN("childNode %p is not a child of %p\n", childNode, iface); 647 IXMLDOMNode_Release(child); 648 return E_INVALIDARG; 649 } 650 651 xmlUnlinkNode(child_node_ptr); 652 653 IXMLDOMNode_Release(child); 654 655 if(oldChild) 656 { 657 IXMLDOMNode_AddRef(childNode); 658 *oldChild = childNode; 659 } 660 661 return S_OK; 662 } 663 664 static HRESULT WINAPI xmlnode_appendChild( 665 IXMLDOMNode *iface, 666 IXMLDOMNode* newChild, 667 IXMLDOMNode** outNewChild) 668 { 669 xmlnode *This = impl_from_IXMLDOMNode( iface ); 670 DOMNodeType type; 671 VARIANT var; 672 HRESULT hr; 673 674 TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild); 675 676 hr = IXMLDOMNode_get_nodeType(newChild, &type); 677 if(FAILED(hr) || type == NODE_ATTRIBUTE) { 678 if(outNewChild) *outNewChild = NULL; 679 return E_FAIL; 680 } 681 682 VariantInit(&var); 683 return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild); 684 } 685 686 static HRESULT WINAPI xmlnode_hasChildNodes( 687 IXMLDOMNode *iface, 688 VARIANT_BOOL* hasChild) 689 { 690 xmlnode *This = impl_from_IXMLDOMNode( iface ); 691 692 TRACE("%p\n", This); 693 694 if (!hasChild) 695 return E_INVALIDARG; 696 if (!This->node->children) 697 { 698 *hasChild = VARIANT_FALSE; 699 return S_FALSE; 700 } 701 702 *hasChild = VARIANT_TRUE; 703 return S_OK; 704 } 705 706 static HRESULT WINAPI xmlnode_get_ownerDocument( 707 IXMLDOMNode *iface, 708 IXMLDOMDocument** DOMDocument) 709 { 710 xmlnode *This = impl_from_IXMLDOMNode( iface ); 711 712 TRACE("%p (%p)\n", This, DOMDocument); 713 714 return DOMDocument_create_from_xmldoc(This->node->doc, (IXMLDOMDocument2**)DOMDocument); 715 } 716 717 static HRESULT WINAPI xmlnode_cloneNode( 718 IXMLDOMNode *iface, 719 VARIANT_BOOL deep, 720 IXMLDOMNode** cloneRoot) 721 { 722 xmlnode *This = impl_from_IXMLDOMNode( iface ); 723 xmlNodePtr pClone = NULL; 724 IXMLDOMNode *pNode = NULL; 725 726 TRACE("%p (%d)\n", This, deep); 727 728 if(!cloneRoot) 729 return E_INVALIDARG; 730 731 pClone = xmlCopyNode(This->node, deep ? 1 : 2); 732 if(pClone) 733 { 734 pClone->doc = This->node->doc; 735 736 pNode = create_node(pClone); 737 if(!pNode) 738 { 739 ERR("Copy failed\n"); 740 return E_FAIL; 741 } 742 743 *cloneRoot = pNode; 744 } 745 else 746 { 747 ERR("Copy failed\n"); 748 return E_FAIL; 749 } 750 751 return S_OK; 752 } 753 754 static HRESULT WINAPI xmlnode_get_nodeTypeString( 755 IXMLDOMNode *iface, 756 BSTR* xmlnodeType) 757 { 758 xmlnode *This = impl_from_IXMLDOMNode( iface ); 759 const xmlChar *str; 760 761 TRACE("%p\n", This ); 762 763 if (!xmlnodeType) 764 return E_INVALIDARG; 765 766 if ( !This->node ) 767 return E_FAIL; 768 769 switch( This->node->type ) 770 { 771 case XML_ATTRIBUTE_NODE: 772 str = (const xmlChar*) "attribute"; 773 break; 774 case XML_CDATA_SECTION_NODE: 775 str = (const xmlChar*) "cdatasection"; 776 break; 777 case XML_COMMENT_NODE: 778 str = (const xmlChar*) "comment"; 779 break; 780 case XML_DOCUMENT_NODE: 781 str = (const xmlChar*) "document"; 782 break; 783 case XML_DOCUMENT_FRAG_NODE: 784 str = (const xmlChar*) "documentfragment"; 785 break; 786 case XML_ELEMENT_NODE: 787 str = (const xmlChar*) "element"; 788 break; 789 case XML_ENTITY_NODE: 790 str = (const xmlChar*) "entity"; 791 break; 792 case XML_ENTITY_REF_NODE: 793 str = (const xmlChar*) "entityreference"; 794 break; 795 case XML_NOTATION_NODE: 796 str = (const xmlChar*) "notation"; 797 break; 798 case XML_PI_NODE: 799 str = (const xmlChar*) "processinginstruction"; 800 break; 801 case XML_TEXT_NODE: 802 str = (const xmlChar*) "text"; 803 break; 804 default: 805 FIXME("Unknown node type (%d)\n", This->node->type); 806 str = This->node->name; 807 break; 808 } 809 810 *xmlnodeType = bstr_from_xmlChar( str ); 811 if (!*xmlnodeType) 812 return S_FALSE; 813 814 return S_OK; 815 } 816 817 static HRESULT WINAPI xmlnode_get_text( 818 IXMLDOMNode *iface, 819 BSTR* text) 820 { 821 xmlnode *This = impl_from_IXMLDOMNode( iface ); 822 BSTR str = NULL; 823 824 TRACE("%p\n", This); 825 826 if ( !text ) 827 return E_INVALIDARG; 828 829 switch(This->node->type) 830 { 831 case XML_ELEMENT_NODE: 832 case XML_ATTRIBUTE_NODE: 833 { 834 xmlNodePtr child = This->node->children; 835 if ( child && child->type == XML_TEXT_NODE ) 836 str = bstr_from_xmlChar( child->content ); 837 break; 838 } 839 840 case XML_TEXT_NODE: 841 case XML_CDATA_SECTION_NODE: 842 case XML_PI_NODE: 843 case XML_COMMENT_NODE: 844 str = bstr_from_xmlChar( This->node->content ); 845 break; 846 847 default: 848 FIXME("Unhandled node type %d\n", This->node->type); 849 } 850 851 /* Always return a string. */ 852 if (!str) str = SysAllocStringLen( NULL, 0 ); 853 854 TRACE("%p %s\n", This, debugstr_w(str) ); 855 *text = str; 856 857 return S_OK; 858 } 859 860 static HRESULT WINAPI xmlnode_put_text( 861 IXMLDOMNode *iface, 862 BSTR text) 863 { 864 xmlnode *This = impl_from_IXMLDOMNode( iface ); 865 xmlChar *str = NULL; 866 867 TRACE("%p\n", This); 868 869 switch(This->node->type) 870 { 871 case XML_DOCUMENT_NODE: 872 return E_FAIL; 873 default: 874 break; 875 } 876 877 str = xmlChar_from_wchar((WCHAR*)text); 878 879 /* Escape the string. */ 880 str = xmlEncodeEntitiesReentrant(This->node->doc, str); 881 str = xmlEncodeSpecialChars(This->node->doc, str); 882 883 xmlNodeSetContent(This->node, str); 884 xmlFree(str); 885 886 return S_OK; 887 } 888 889 static HRESULT WINAPI xmlnode_get_specified( 890 IXMLDOMNode *iface, 891 VARIANT_BOOL* isSpecified) 892 { 893 FIXME("\n"); 894 return E_NOTIMPL; 895 } 896 897 static HRESULT WINAPI xmlnode_get_definition( 898 IXMLDOMNode *iface, 899 IXMLDOMNode** definitionNode) 900 { 901 FIXME("\n"); 902 return E_NOTIMPL; 903 } 904 905 static HRESULT WINAPI xmlnode_get_nodeTypedValue( 906 IXMLDOMNode *iface, 907 VARIANT* typedValue) 908 { 909 FIXME("ignoring data type\n"); 910 return xmlnode_get_nodeValue(iface, typedValue); 911 } 912 913 static HRESULT WINAPI xmlnode_put_nodeTypedValue( 914 IXMLDOMNode *iface, 915 VARIANT typedValue) 916 { 917 FIXME("\n"); 918 return E_NOTIMPL; 919 } 920 921 static HRESULT WINAPI xmlnode_get_dataType( 922 IXMLDOMNode *iface, 923 VARIANT* dataTypeName) 924 { 925 xmlnode *This = impl_from_IXMLDOMNode( iface ); 926 xmlChar *pVal; 927 928 TRACE("iface %p\n", iface); 929 930 if(!dataTypeName) 931 return E_INVALIDARG; 932 933 /* Attribute, CDATA Section, Comment, Document, Document Fragment, 934 Entity, Notation, PI, and Text Node are non-typed. */ 935 V_BSTR(dataTypeName) = NULL; 936 V_VT(dataTypeName) = VT_NULL; 937 938 switch ( This->node->type ) 939 { 940 case XML_ELEMENT_NODE: 941 pVal = xmlGetNsProp(This->node, (xmlChar*)"dt", 942 (xmlChar*)"urn:schemas-microsoft-com:datatypes"); 943 if (pVal) 944 { 945 V_VT(dataTypeName) = VT_BSTR; 946 V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal ); 947 xmlFree(pVal); 948 } 949 break; 950 case XML_ENTITY_REF_NODE: 951 FIXME("XML_ENTITY_REF_NODE should return a valid value.\n"); 952 break; 953 default: 954 TRACE("Type %d returning NULL\n", This->node->type); 955 } 956 957 /* non-typed nodes return S_FALSE */ 958 if(V_VT(dataTypeName) == VT_NULL) 959 { 960 return S_FALSE; 961 } 962 963 return S_OK; 964 } 965 966 static HRESULT WINAPI xmlnode_put_dataType( 967 IXMLDOMNode *iface, 968 BSTR dataTypeName) 969 { 970 xmlnode *This = impl_from_IXMLDOMNode( iface ); 971 HRESULT hr = E_FAIL; 972 973 TRACE("iface %p\n", iface); 974 975 if(dataTypeName == NULL) 976 return E_INVALIDARG; 977 978 /* An example of this is. The Text in the node needs to be a 0 or 1 for a boolean type. 979 This applies to changing types (string->bool) or setting a new one 980 */ 981 FIXME("Need to Validate the data before allowing a type to be set.\n"); 982 983 /* Check all supported types. */ 984 if(lstrcmpiW(dataTypeName,szString) == 0 || 985 lstrcmpiW(dataTypeName,szNumber) == 0 || 986 lstrcmpiW(dataTypeName,szUUID) == 0 || 987 lstrcmpiW(dataTypeName,szInt) == 0 || 988 lstrcmpiW(dataTypeName,szI4) == 0 || 989 lstrcmpiW(dataTypeName,szFixed) == 0 || 990 lstrcmpiW(dataTypeName,szBoolean) == 0 || 991 lstrcmpiW(dataTypeName,szDateTime) == 0 || 992 lstrcmpiW(dataTypeName,szDateTimeTZ) == 0 || 993 lstrcmpiW(dataTypeName,szDate) == 0 || 994 lstrcmpiW(dataTypeName,szTime) == 0 || 995 lstrcmpiW(dataTypeName,szTimeTZ) == 0 || 996 lstrcmpiW(dataTypeName,szI1) == 0 || 997 lstrcmpiW(dataTypeName,szI2) == 0 || 998 lstrcmpiW(dataTypeName,szIU1) == 0 || 999 lstrcmpiW(dataTypeName,szIU2) == 0 || 1000 lstrcmpiW(dataTypeName,szIU4) == 0 || 1001 lstrcmpiW(dataTypeName,szR4) == 0 || 1002 lstrcmpiW(dataTypeName,szR8) == 0 || 1003 lstrcmpiW(dataTypeName,szFloat) == 0 || 1004 lstrcmpiW(dataTypeName,szBinHex) == 0 || 1005 lstrcmpiW(dataTypeName,szBinBase64) == 0) 1006 { 1007 xmlNsPtr pNS = NULL; 1008 xmlAttrPtr pAttr = NULL; 1009 xmlChar* str = xmlChar_from_wchar((WCHAR*)dataTypeName); 1010 1011 pAttr = xmlHasNsProp(This->node, (xmlChar*)"dt", 1012 (xmlChar*)"urn:schemas-microsoft-com:datatypes"); 1013 if (pAttr) 1014 { 1015 pAttr = xmlSetNsProp(This->node, pAttr->ns, (xmlChar*)"dt", str); 1016 1017 hr = S_OK; 1018 } 1019 else 1020 { 1021 pNS = xmlNewNs(This->node, (xmlChar*)"urn:schemas-microsoft-com:datatypes", (xmlChar*)"dt"); 1022 if(pNS) 1023 { 1024 pAttr = xmlNewNsProp(This->node, pNS, (xmlChar*)"dt", str); 1025 if(pAttr) 1026 { 1027 xmlAddChild(This->node, (xmlNodePtr)pAttr); 1028 1029 hr = S_OK; 1030 } 1031 else 1032 ERR("Failed to create Attribute\n"); 1033 } 1034 else 1035 ERR("Failed to Create Namepsace\n"); 1036 } 1037 } 1038 1039 return hr; 1040 } 1041 1042 static BSTR EnsureCorrectEOL(BSTR sInput) 1043 { 1044 static const WCHAR SZ_RETURN[] = {'\n',0}; 1045 static const WCHAR SZ_LINEFEED[] = {'\r',0}; 1046 int nNum = 0; 1047 BSTR sNew; 1048 int nLen; 1049 int i; 1050 1051 nLen = lstrlenW(sInput); 1052 /* Count line endings */ 1053 for(i=0; i < nLen; i++) 1054 { 1055 if(sInput[i] == SZ_RETURN[0]) 1056 nNum++; 1057 } 1058 1059 TRACE("len=%d, num=%d\n", nLen, nNum); 1060 1061 /* Add linefeed as needed */ 1062 if(nNum > 0) 1063 { 1064 int nPlace = 0; 1065 sNew = SysAllocStringLen(NULL, nLen + nNum+1); 1066 for(i=0; i < nLen; i++) 1067 { 1068 if(sInput[i] == SZ_RETURN[0]) 1069 { 1070 sNew[i+nPlace] = SZ_LINEFEED[0]; 1071 nPlace++; 1072 } 1073 sNew[i+nPlace] = sInput[i]; 1074 } 1075 1076 SysFreeString(sInput); 1077 } 1078 else 1079 { 1080 sNew = sInput; 1081 } 1082 1083 TRACE("len %d\n", lstrlenW(sNew)); 1084 1085 return sNew; 1086 } 1087 1088 /* 1089 * We are trying to replicate the same behaviour as msxml by converting 1090 * line endings to \r\n and using idents as \t. The problem is that msxml 1091 * only formats nodes that have a line ending. Using libxml we cannot 1092 * reproduce behaviour exactly. 1093 * 1094 */ 1095 static HRESULT WINAPI xmlnode_get_xml( 1096 IXMLDOMNode *iface, 1097 BSTR* xmlString) 1098 { 1099 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1100 xmlBufferPtr pXmlBuf; 1101 int nSize; 1102 1103 TRACE("iface %p %d\n", iface, This->node->type); 1104 1105 if(!xmlString) 1106 return E_INVALIDARG; 1107 1108 *xmlString = NULL; 1109 1110 pXmlBuf = xmlBufferCreate(); 1111 if(pXmlBuf) 1112 { 1113 nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 1); 1114 if(nSize > 0) 1115 { 1116 const xmlChar *pContent; 1117 BSTR bstrContent; 1118 1119 /* Attribute Nodes return a space in front of their name */ 1120 pContent = xmlBufferContent(pXmlBuf); 1121 if( ((char*)pContent)[0] == ' ') 1122 bstrContent = bstr_from_xmlChar(pContent+1); 1123 else 1124 bstrContent = bstr_from_xmlChar(pContent); 1125 1126 *xmlString = This->node->type == XML_ELEMENT_NODE ? EnsureCorrectEOL(bstrContent) : bstrContent; 1127 } 1128 1129 xmlBufferFree(pXmlBuf); 1130 } 1131 1132 /* Always returns a string. */ 1133 if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 ); 1134 1135 return S_OK; 1136 } 1137 1138 static HRESULT WINAPI xmlnode_transformNode( 1139 IXMLDOMNode *iface, 1140 IXMLDOMNode* styleSheet, 1141 BSTR* xmlString) 1142 { 1143 #ifdef HAVE_LIBXSLT 1144 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1145 xmlnode *pStyleSheet = NULL; 1146 xsltStylesheetPtr xsltSS = NULL; 1147 xmlDocPtr result = NULL; 1148 IXMLDOMNode *ssNew; 1149 1150 TRACE("%p %p %p\n", This, styleSheet, xmlString); 1151 1152 if(!styleSheet || !xmlString) 1153 return E_INVALIDARG; 1154 1155 *xmlString = NULL; 1156 1157 if(IXMLDOMNode_QueryInterface(styleSheet, &IID_IXMLDOMNode, (LPVOID)&ssNew) == S_OK) 1158 { 1159 pStyleSheet = impl_from_IXMLDOMNode( ssNew ); 1160 1161 xsltSS = xsltParseStylesheetDoc( pStyleSheet->node->doc); 1162 if(xsltSS) 1163 { 1164 result = xsltApplyStylesheet(xsltSS, This->node->doc, NULL); 1165 if(result) 1166 { 1167 const xmlChar *pContent; 1168 1169 if(result->type == XML_HTML_DOCUMENT_NODE) 1170 { 1171 xmlOutputBufferPtr pOutput = xmlAllocOutputBuffer(NULL); 1172 if(pOutput) 1173 { 1174 htmlDocContentDumpOutput(pOutput, result->doc, NULL); 1175 if(pOutput) 1176 { 1177 pContent = xmlBufferContent(pOutput->buffer); 1178 *xmlString = bstr_from_xmlChar(pContent); 1179 } 1180 1181 xmlOutputBufferClose(pOutput); 1182 } 1183 } 1184 else 1185 { 1186 xmlBufferPtr pXmlBuf; 1187 int nSize; 1188 1189 pXmlBuf = xmlBufferCreate(); 1190 if(pXmlBuf) 1191 { 1192 nSize = xmlNodeDump(pXmlBuf, NULL, (xmlNodePtr)result, 0, 0); 1193 if(nSize > 0) 1194 { 1195 pContent = xmlBufferContent(pXmlBuf); 1196 *xmlString = bstr_from_xmlChar(pContent); 1197 1198 xmlBufferFree(pXmlBuf); 1199 } 1200 } 1201 } 1202 } 1203 } 1204 1205 IXMLDOMNode_Release(ssNew); 1206 } 1207 1208 if(*xmlString == NULL) 1209 *xmlString = SysAllocStringLen(NULL, 0); 1210 1211 return S_OK; 1212 #else 1213 FIXME("libxslt headers were not found at compile time\n"); 1214 return E_NOTIMPL; 1215 #endif 1216 } 1217 1218 static HRESULT WINAPI xmlnode_selectNodes( 1219 IXMLDOMNode *iface, 1220 BSTR queryString, 1221 IXMLDOMNodeList** resultList) 1222 { 1223 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1224 1225 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList ); 1226 1227 return queryresult_create( This->node, queryString, resultList ); 1228 } 1229 1230 static HRESULT WINAPI xmlnode_selectSingleNode( 1231 IXMLDOMNode *iface, 1232 BSTR queryString, 1233 IXMLDOMNode** resultNode) 1234 { 1235 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1236 IXMLDOMNodeList *list; 1237 HRESULT r; 1238 1239 TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode ); 1240 1241 *resultNode = NULL; 1242 r = IXMLDOMNode_selectNodes(iface, queryString, &list); 1243 if(r == S_OK) 1244 { 1245 r = IXMLDOMNodeList_nextNode(list, resultNode); 1246 IXMLDOMNodeList_Release(list); 1247 } 1248 return r; 1249 } 1250 1251 static HRESULT WINAPI xmlnode_get_parsed( 1252 IXMLDOMNode *iface, 1253 VARIANT_BOOL* isParsed) 1254 { 1255 FIXME("\n"); 1256 return E_NOTIMPL; 1257 } 1258 1259 static HRESULT WINAPI xmlnode_get_namespaceURI( 1260 IXMLDOMNode *iface, 1261 BSTR* namespaceURI) 1262 { 1263 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1264 HRESULT hr = S_FALSE; 1265 xmlNsPtr *pNSList; 1266 1267 TRACE("%p %p\n", This, namespaceURI ); 1268 1269 if(!namespaceURI) 1270 return E_INVALIDARG; 1271 1272 *namespaceURI = NULL; 1273 1274 pNSList = xmlGetNsList(This->node->doc, This->node); 1275 if(pNSList) 1276 { 1277 *namespaceURI = bstr_from_xmlChar( pNSList[0]->href ); 1278 1279 hr = S_OK; 1280 } 1281 1282 return hr; 1283 } 1284 1285 static HRESULT WINAPI xmlnode_get_prefix( 1286 IXMLDOMNode *iface, 1287 BSTR* prefixString) 1288 { 1289 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1290 HRESULT hr = S_FALSE; 1291 xmlNsPtr *pNSList; 1292 1293 TRACE("%p %p\n", This, prefixString ); 1294 1295 if(!prefixString) 1296 return E_INVALIDARG; 1297 1298 *prefixString = NULL; 1299 1300 pNSList = xmlGetNsList(This->node->doc, This->node); 1301 if(pNSList) 1302 { 1303 *prefixString = bstr_from_xmlChar( pNSList[0]->prefix ); 1304 1305 hr = S_OK; 1306 } 1307 1308 return hr; 1309 } 1310 1311 static HRESULT WINAPI xmlnode_get_baseName( 1312 IXMLDOMNode *iface, 1313 BSTR* nameString) 1314 { 1315 xmlnode *This = impl_from_IXMLDOMNode( iface ); 1316 BSTR str = NULL; 1317 HRESULT r = S_FALSE; 1318 1319 TRACE("%p %p\n", This, nameString ); 1320 1321 if ( !nameString ) 1322 return E_INVALIDARG; 1323 1324 switch ( This->node->type ) 1325 { 1326 case XML_ELEMENT_NODE: 1327 case XML_ATTRIBUTE_NODE: 1328 str = bstr_from_xmlChar( This->node->name ); 1329 r = S_OK; 1330 break; 1331 case XML_TEXT_NODE: 1332 break; 1333 default: 1334 ERR("Unhandled type %d\n", This->node->type ); 1335 break; 1336 } 1337 1338 TRACE("returning %08x str = %s\n", r, debugstr_w( str ) ); 1339 1340 *nameString = str; 1341 return r; 1342 } 1343 1344 static HRESULT WINAPI xmlnode_transformNodeToObject( 1345 IXMLDOMNode *iface, 1346 IXMLDOMNode* stylesheet, 1347 VARIANT outputObject) 1348 { 1349 FIXME("\n"); 1350 return E_NOTIMPL; 1351 } 1352 1353 static const struct IXMLDOMNodeVtbl xmlnode_vtbl = 1354 { 1355 xmlnode_QueryInterface, 1356 xmlnode_AddRef, 1357 xmlnode_Release, 1358 xmlnode_GetTypeInfoCount, 1359 xmlnode_GetTypeInfo, 1360 xmlnode_GetIDsOfNames, 1361 xmlnode_Invoke, 1362 xmlnode_get_nodeName, 1363 xmlnode_get_nodeValue, 1364 xmlnode_put_nodeValue, 1365 xmlnode_get_nodeType, 1366 xmlnode_get_parentNode, 1367 xmlnode_get_childNodes, 1368 xmlnode_get_firstChild, 1369 xmlnode_get_lastChild, 1370 xmlnode_get_previousSibling, 1371 xmlnode_get_nextSibling, 1372 xmlnode_get_attributes, 1373 xmlnode_insertBefore, 1374 xmlnode_replaceChild, 1375 xmlnode_removeChild, 1376 xmlnode_appendChild, 1377 xmlnode_hasChildNodes, 1378 xmlnode_get_ownerDocument, 1379 xmlnode_cloneNode, 1380 xmlnode_get_nodeTypeString, 1381 xmlnode_get_text, 1382 xmlnode_put_text, 1383 xmlnode_get_specified, 1384 xmlnode_get_definition, 1385 xmlnode_get_nodeTypedValue, 1386 xmlnode_put_nodeTypedValue, 1387 xmlnode_get_dataType, 1388 xmlnode_put_dataType, 1389 xmlnode_get_xml, 1390 xmlnode_transformNode, 1391 xmlnode_selectNodes, 1392 xmlnode_selectSingleNode, 1393 xmlnode_get_parsed, 1394 xmlnode_get_namespaceURI, 1395 xmlnode_get_prefix, 1396 xmlnode_get_baseName, 1397 xmlnode_transformNodeToObject, 1398 }; 1399 1400 static HRESULT WINAPI Internal_QueryInterface( 1401 IUnknown *iface, 1402 REFIID riid, 1403 void** ppvObject ) 1404 { 1405 xmlnode *This = impl_from_InternalUnknown( iface ); 1406 1407 TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject); 1408 1409 1410 if ( IsEqualGUID( riid, &IID_IUnknown )) 1411 *ppvObject = iface; 1412 else if ( IsEqualGUID( riid, &IID_IDispatch ) || 1413 IsEqualGUID( riid, &IID_IXMLDOMNode ) ) 1414 *ppvObject = &This->lpVtbl; 1415 else 1416 { 1417 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 1418 *ppvObject = NULL; 1419 return E_NOINTERFACE; 1420 } 1421 1422 IUnknown_AddRef( (IUnknown*)*ppvObject ); 1423 1424 return S_OK; 1425 } 1426 1427 static ULONG WINAPI Internal_AddRef( 1428 IUnknown *iface ) 1429 { 1430 xmlnode *This = impl_from_InternalUnknown( iface ); 1431 return InterlockedIncrement( &This->ref ); 1432 } 1433 1434 static ULONG WINAPI Internal_Release( 1435 IUnknown *iface ) 1436 { 1437 xmlnode *This = impl_from_InternalUnknown( iface ); 1438 ULONG ref; 1439 1440 ref = InterlockedDecrement( &This->ref ); 1441 if ( ref == 0 ) 1442 { 1443 if( This->node ) 1444 xmldoc_release( This->node->doc ); 1445 HeapFree( GetProcessHeap(), 0, This ); 1446 } 1447 1448 return ref; 1449 } 1450 1451 static const struct IUnknownVtbl internal_unk_vtbl = 1452 { 1453 Internal_QueryInterface, 1454 Internal_AddRef, 1455 Internal_Release 1456 }; 1457 1458 IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter ) 1459 { 1460 xmlnode *This; 1461 1462 This = HeapAlloc( GetProcessHeap(), 0, sizeof *This ); 1463 if ( !This ) 1464 return NULL; 1465 1466 if(node) 1467 xmldoc_add_ref( node->doc ); 1468 1469 This->lpVtbl = &xmlnode_vtbl; 1470 This->lpInternalUnkVtbl = &internal_unk_vtbl; 1471 1472 if(pUnkOuter) 1473 This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */ 1474 else 1475 This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl; 1476 1477 This->ref = 1; 1478 This->node = node; 1479 1480 return (IUnknown*)&This->lpInternalUnkVtbl; 1481 } 1482 1483 IXMLDOMNode *create_node( xmlNodePtr node ) 1484 { 1485 IUnknown *pUnk; 1486 IXMLDOMNode *ret; 1487 HRESULT hr; 1488 1489 if ( !node ) 1490 return NULL; 1491 1492 TRACE("type %d\n", node->type); 1493 switch(node->type) 1494 { 1495 case XML_ELEMENT_NODE: 1496 pUnk = create_element( node, NULL ); 1497 break; 1498 case XML_ATTRIBUTE_NODE: 1499 pUnk = create_attribute( node ); 1500 break; 1501 case XML_TEXT_NODE: 1502 pUnk = create_text( node ); 1503 break; 1504 case XML_CDATA_SECTION_NODE: 1505 pUnk = create_cdata( node ); 1506 break; 1507 case XML_COMMENT_NODE: 1508 pUnk = create_comment( node ); 1509 break; 1510 case XML_DOCUMENT_NODE: 1511 pUnk = create_domdoc( node ); 1512 break; 1513 default: 1514 FIXME("only creating basic node for type %d\n", node->type); 1515 pUnk = create_basic_node( node, NULL ); 1516 } 1517 1518 hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret); 1519 IUnknown_Release(pUnk); 1520 if(FAILED(hr)) return NULL; 1521 return ret; 1522 } 1523 #endif 1524