1 /* 2 * XML Element implementation 3 * 4 * Copyright 2007 James Hawkins 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #define COBJMACROS 22 23 #include "config.h" 24 25 #include <stdarg.h> 26 #ifdef HAVE_LIBXML2 27 # include <libxml/parser.h> 28 # include <libxml/xmlerror.h> 29 #endif 30 31 #include "windef.h" 32 #include "winbase.h" 33 #include "winuser.h" 34 #include "ole2.h" 35 #include "msxml6.h" 36 #include "ocidl.h" 37 38 #include "wine/debug.h" 39 40 #include "msxml_private.h" 41 42 #ifdef HAVE_LIBXML2 43 44 WINE_DEFAULT_DEBUG_CHANNEL(msxml); 45 46 static HRESULT XMLElementCollection_create( xmlNodePtr node, LPVOID *ppObj ); 47 48 /********************************************************************** 49 * IXMLElement 50 */ 51 typedef struct _xmlelem 52 { 53 IXMLElement IXMLElement_iface; 54 LONG ref; 55 xmlNodePtr node; 56 BOOL own; 57 } xmlelem; 58 59 static inline xmlelem *impl_from_IXMLElement(IXMLElement *iface) 60 { 61 return CONTAINING_RECORD(iface, xmlelem, IXMLElement_iface); 62 } 63 64 static HRESULT WINAPI xmlelem_QueryInterface(IXMLElement *iface, REFIID riid, void** ppvObject) 65 { 66 xmlelem *This = impl_from_IXMLElement(iface); 67 68 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 69 70 if (IsEqualGUID(riid, &IID_IUnknown) || 71 IsEqualGUID(riid, &IID_IDispatch) || 72 IsEqualGUID(riid, &IID_IXMLElement)) 73 { 74 *ppvObject = iface; 75 } 76 else 77 { 78 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 79 *ppvObject = NULL; 80 return E_NOINTERFACE; 81 } 82 83 IXMLElement_AddRef(iface); 84 85 return S_OK; 86 } 87 88 static ULONG WINAPI xmlelem_AddRef(IXMLElement *iface) 89 { 90 xmlelem *This = impl_from_IXMLElement(iface); 91 TRACE("%p\n", This); 92 return InterlockedIncrement(&This->ref); 93 } 94 95 static ULONG WINAPI xmlelem_Release(IXMLElement *iface) 96 { 97 xmlelem *This = impl_from_IXMLElement(iface); 98 LONG ref; 99 100 TRACE("%p\n", This); 101 102 ref = InterlockedDecrement(&This->ref); 103 if (ref == 0) 104 { 105 if (This->own) xmlFreeNode(This->node); 106 heap_free(This); 107 } 108 109 return ref; 110 } 111 112 static HRESULT WINAPI xmlelem_GetTypeInfoCount(IXMLElement *iface, UINT* pctinfo) 113 { 114 xmlelem *This = impl_from_IXMLElement(iface); 115 116 TRACE("(%p)->(%p)\n", This, pctinfo); 117 118 *pctinfo = 1; 119 120 return S_OK; 121 } 122 123 static HRESULT WINAPI xmlelem_GetTypeInfo(IXMLElement *iface, UINT iTInfo, 124 LCID lcid, ITypeInfo** ppTInfo) 125 { 126 xmlelem *This = impl_from_IXMLElement(iface); 127 HRESULT hr; 128 129 TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo); 130 131 hr = get_typeinfo(IXMLElement_tid, ppTInfo); 132 133 return hr; 134 } 135 136 static HRESULT WINAPI xmlelem_GetIDsOfNames(IXMLElement *iface, REFIID riid, 137 LPOLESTR* rgszNames, UINT cNames, 138 LCID lcid, DISPID* rgDispId) 139 { 140 xmlelem *This = impl_from_IXMLElement(iface); 141 ITypeInfo *typeinfo; 142 HRESULT hr; 143 144 TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, 145 lcid, rgDispId); 146 147 if(!rgszNames || cNames == 0 || !rgDispId) 148 return E_INVALIDARG; 149 150 hr = get_typeinfo(IXMLElement_tid, &typeinfo); 151 if(SUCCEEDED(hr)) 152 { 153 hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId); 154 ITypeInfo_Release(typeinfo); 155 } 156 157 return hr; 158 } 159 160 static HRESULT WINAPI xmlelem_Invoke(IXMLElement *iface, DISPID dispIdMember, 161 REFIID riid, LCID lcid, WORD wFlags, 162 DISPPARAMS* pDispParams, VARIANT* pVarResult, 163 EXCEPINFO* pExcepInfo, UINT* puArgErr) 164 { 165 xmlelem *This = impl_from_IXMLElement(iface); 166 ITypeInfo *typeinfo; 167 HRESULT hr; 168 169 TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), 170 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 171 172 hr = get_typeinfo(IXMLElement_tid, &typeinfo); 173 if(SUCCEEDED(hr)) 174 { 175 hr = ITypeInfo_Invoke(typeinfo, &This->IXMLElement_iface, dispIdMember, wFlags, pDispParams, 176 pVarResult, pExcepInfo, puArgErr); 177 ITypeInfo_Release(typeinfo); 178 } 179 180 return hr; 181 } 182 183 static HRESULT WINAPI xmlelem_get_tagName(IXMLElement *iface, BSTR *p) 184 { 185 xmlelem *This = impl_from_IXMLElement(iface); 186 187 TRACE("(%p)->(%p)\n", This, p); 188 189 if (!p) 190 return E_INVALIDARG; 191 192 if (*This->node->name) { 193 *p = bstr_from_xmlChar(This->node->name); 194 CharUpperBuffW(*p, SysStringLen(*p)); 195 }else { 196 *p = NULL; 197 } 198 199 TRACE("returning %s\n", debugstr_w(*p)); 200 201 return S_OK; 202 } 203 204 static HRESULT WINAPI xmlelem_put_tagName(IXMLElement *iface, BSTR p) 205 { 206 xmlelem *This = impl_from_IXMLElement(iface); 207 208 FIXME("(%p)->(%s): stub\n", This, debugstr_w(p)); 209 210 if (!p) 211 return E_INVALIDARG; 212 213 return E_NOTIMPL; 214 } 215 216 static HRESULT WINAPI xmlelem_get_parent(IXMLElement *iface, IXMLElement **parent) 217 { 218 xmlelem *This = impl_from_IXMLElement(iface); 219 220 TRACE("(%p)->(%p)\n", This, parent); 221 222 if (!parent) 223 return E_INVALIDARG; 224 225 *parent = NULL; 226 227 if (!This->node->parent) 228 return S_FALSE; 229 230 return XMLElement_create(This->node->parent, (LPVOID *)parent, FALSE); 231 } 232 233 static HRESULT WINAPI xmlelem_setAttribute(IXMLElement *iface, BSTR strPropertyName, 234 VARIANT PropertyValue) 235 { 236 xmlelem *This = impl_from_IXMLElement(iface); 237 xmlChar *name, *value; 238 xmlAttrPtr attr; 239 240 TRACE("(%p)->(%s %s)\n", This, debugstr_w(strPropertyName), debugstr_variant(&PropertyValue)); 241 242 if (!strPropertyName || V_VT(&PropertyValue) != VT_BSTR) 243 return E_INVALIDARG; 244 245 name = xmlchar_from_wchar(strPropertyName); 246 value = xmlchar_from_wchar(V_BSTR(&PropertyValue)); 247 attr = xmlSetProp(This->node, name, value); 248 249 heap_free(name); 250 heap_free(value); 251 return (attr) ? S_OK : S_FALSE; 252 } 253 254 static HRESULT WINAPI xmlelem_getAttribute(IXMLElement *iface, BSTR name, 255 VARIANT *value) 256 { 257 static const WCHAR xmllangW[] = { 'x','m','l',':','l','a','n','g',0 }; 258 xmlelem *This = impl_from_IXMLElement(iface); 259 xmlChar *val = NULL; 260 261 TRACE("(%p)->(%s, %p)\n", This, debugstr_w(name), value); 262 263 if (!value) 264 return E_INVALIDARG; 265 266 VariantInit(value); 267 V_BSTR(value) = NULL; 268 269 if (!name) 270 return E_INVALIDARG; 271 272 /* case for xml:lang attribute */ 273 if (!lstrcmpiW(name, xmllangW)) 274 { 275 xmlNsPtr ns; 276 ns = xmlSearchNs(This->node->doc, This->node, (xmlChar*)"xml"); 277 val = xmlGetNsProp(This->node, (xmlChar*)"lang", ns->href); 278 } 279 else 280 { 281 xmlAttrPtr attr; 282 xmlChar *xml_name; 283 284 xml_name = xmlchar_from_wchar(name); 285 attr = This->node->properties; 286 while (attr) 287 { 288 BSTR attr_name; 289 290 attr_name = bstr_from_xmlChar(attr->name); 291 if (!lstrcmpiW(name, attr_name)) 292 { 293 val = xmlNodeListGetString(attr->doc, attr->children, 1); 294 SysFreeString(attr_name); 295 break; 296 } 297 298 attr = attr->next; 299 SysFreeString(attr_name); 300 } 301 302 heap_free(xml_name); 303 } 304 305 if (val) 306 { 307 V_VT(value) = VT_BSTR; 308 V_BSTR(value) = bstr_from_xmlChar(val); 309 } 310 311 xmlFree(val); 312 TRACE("returning %s\n", debugstr_w(V_BSTR(value))); 313 return (val) ? S_OK : S_FALSE; 314 } 315 316 static HRESULT WINAPI xmlelem_removeAttribute(IXMLElement *iface, BSTR strPropertyName) 317 { 318 xmlelem *This = impl_from_IXMLElement(iface); 319 xmlChar *name; 320 xmlAttrPtr attr; 321 int res; 322 HRESULT hr = S_FALSE; 323 324 TRACE("(%p)->(%s)\n", This, debugstr_w(strPropertyName)); 325 326 if (!strPropertyName) 327 return E_INVALIDARG; 328 329 name = xmlchar_from_wchar(strPropertyName); 330 attr = xmlHasProp(This->node, name); 331 if (!attr) 332 goto done; 333 334 res = xmlRemoveProp(attr); 335 336 if (res == 0) 337 hr = S_OK; 338 339 done: 340 heap_free(name); 341 return hr; 342 } 343 344 static HRESULT WINAPI xmlelem_get_children(IXMLElement *iface, IXMLElementCollection **p) 345 { 346 xmlelem *This = impl_from_IXMLElement(iface); 347 348 TRACE("(%p)->(%p)\n", This, p); 349 350 if (!p) 351 return E_INVALIDARG; 352 353 return XMLElementCollection_create(This->node, (LPVOID *)p); 354 } 355 356 static LONG type_libxml_to_msxml(xmlElementType type) 357 { 358 switch (type) 359 { 360 case XML_ELEMENT_NODE: 361 return XMLELEMTYPE_ELEMENT; 362 case XML_TEXT_NODE: 363 return XMLELEMTYPE_TEXT; 364 case XML_COMMENT_NODE: 365 return XMLELEMTYPE_COMMENT; 366 case XML_DOCUMENT_NODE: 367 return XMLELEMTYPE_DOCUMENT; 368 case XML_DTD_NODE: 369 return XMLELEMTYPE_DTD; 370 case XML_PI_NODE: 371 return XMLELEMTYPE_PI; 372 default: 373 break; 374 } 375 376 return XMLELEMTYPE_OTHER; 377 } 378 379 static HRESULT WINAPI xmlelem_get_type(IXMLElement *iface, LONG *p) 380 { 381 xmlelem *This = impl_from_IXMLElement(iface); 382 383 TRACE("(%p)->(%p)\n", This, p); 384 385 if (!p) 386 return E_INVALIDARG; 387 388 *p = type_libxml_to_msxml(This->node->type); 389 TRACE("returning %d\n", *p); 390 return S_OK; 391 } 392 393 static HRESULT WINAPI xmlelem_get_text(IXMLElement *iface, BSTR *p) 394 { 395 xmlelem *This = impl_from_IXMLElement(iface); 396 xmlChar *content; 397 398 TRACE("(%p)->(%p)\n", This, p); 399 400 if (!p) 401 return E_INVALIDARG; 402 403 content = xmlNodeGetContent(This->node); 404 *p = bstr_from_xmlChar(content); 405 TRACE("returning %s\n", debugstr_w(*p)); 406 407 xmlFree(content); 408 return S_OK; 409 } 410 411 static HRESULT WINAPI xmlelem_put_text(IXMLElement *iface, BSTR p) 412 { 413 xmlelem *This = impl_from_IXMLElement(iface); 414 xmlChar *content; 415 416 TRACE("(%p)->(%s)\n", This, debugstr_w(p)); 417 418 /* FIXME: test which types can be used */ 419 if (This->node->type == XML_ELEMENT_NODE) 420 return E_NOTIMPL; 421 422 content = xmlchar_from_wchar(p); 423 xmlNodeSetContent(This->node, content); 424 425 heap_free(content); 426 427 return S_OK; 428 } 429 430 static HRESULT WINAPI xmlelem_addChild(IXMLElement *iface, IXMLElement *pChildElem, 431 LONG lIndex, LONG lreserved) 432 { 433 xmlelem *This = impl_from_IXMLElement(iface); 434 xmlelem *childElem = impl_from_IXMLElement(pChildElem); 435 xmlNodePtr child; 436 437 TRACE("(%p)->(%p %d %d)\n", This, pChildElem, lIndex, lreserved); 438 439 if (lIndex == 0) 440 child = xmlAddChild(This->node, childElem->node); 441 else 442 child = xmlAddNextSibling(This->node, childElem->node->last); 443 444 /* parent is responsible for child data */ 445 if (child) childElem->own = FALSE; 446 447 return (child) ? S_OK : S_FALSE; 448 } 449 450 static HRESULT WINAPI xmlelem_removeChild(IXMLElement *iface, IXMLElement *pChildElem) 451 { 452 xmlelem *This = impl_from_IXMLElement(iface); 453 xmlelem *childElem = impl_from_IXMLElement(pChildElem); 454 455 TRACE("(%p)->(%p)\n", This, childElem); 456 457 if (!pChildElem) 458 return E_INVALIDARG; 459 460 /* only supported for This is childElem parent case */ 461 if (This->node != childElem->node->parent) 462 return E_INVALIDARG; 463 464 xmlUnlinkNode(childElem->node); 465 /* standalone element now */ 466 childElem->own = TRUE; 467 468 return S_OK; 469 } 470 471 static const struct IXMLElementVtbl xmlelem_vtbl = 472 { 473 xmlelem_QueryInterface, 474 xmlelem_AddRef, 475 xmlelem_Release, 476 xmlelem_GetTypeInfoCount, 477 xmlelem_GetTypeInfo, 478 xmlelem_GetIDsOfNames, 479 xmlelem_Invoke, 480 xmlelem_get_tagName, 481 xmlelem_put_tagName, 482 xmlelem_get_parent, 483 xmlelem_setAttribute, 484 xmlelem_getAttribute, 485 xmlelem_removeAttribute, 486 xmlelem_get_children, 487 xmlelem_get_type, 488 xmlelem_get_text, 489 xmlelem_put_text, 490 xmlelem_addChild, 491 xmlelem_removeChild 492 }; 493 494 HRESULT XMLElement_create(xmlNodePtr node, LPVOID *ppObj, BOOL own) 495 { 496 xmlelem *elem; 497 498 TRACE("(%p)\n", ppObj); 499 500 if (!ppObj) 501 return E_INVALIDARG; 502 503 *ppObj = NULL; 504 505 elem = heap_alloc(sizeof (*elem)); 506 if(!elem) 507 return E_OUTOFMEMORY; 508 509 elem->IXMLElement_iface.lpVtbl = &xmlelem_vtbl; 510 elem->ref = 1; 511 elem->node = node; 512 elem->own = own; 513 514 *ppObj = &elem->IXMLElement_iface; 515 516 TRACE("returning iface %p\n", *ppObj); 517 return S_OK; 518 } 519 520 /************************************************************************ 521 * IXMLElementCollection 522 */ 523 typedef struct _xmlelem_collection 524 { 525 IXMLElementCollection IXMLElementCollection_iface; 526 IEnumVARIANT IEnumVARIANT_iface; 527 LONG ref; 528 LONG length; 529 xmlNodePtr node; 530 531 /* IEnumVARIANT members */ 532 xmlNodePtr current; 533 } xmlelem_collection; 534 535 static inline LONG xmlelem_collection_updatelength(xmlelem_collection *collection) 536 { 537 xmlNodePtr ptr = collection->node->children; 538 539 collection->length = 0; 540 while (ptr) 541 { 542 collection->length++; 543 ptr = ptr->next; 544 } 545 return collection->length; 546 } 547 548 static inline xmlelem_collection *impl_from_IXMLElementCollection(IXMLElementCollection *iface) 549 { 550 return CONTAINING_RECORD(iface, xmlelem_collection, IXMLElementCollection_iface); 551 } 552 553 static inline xmlelem_collection *impl_from_IEnumVARIANT(IEnumVARIANT *iface) 554 { 555 return CONTAINING_RECORD(iface, xmlelem_collection, IEnumVARIANT_iface); 556 } 557 558 static HRESULT WINAPI xmlelem_collection_QueryInterface(IXMLElementCollection *iface, REFIID riid, void** ppvObject) 559 { 560 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 561 562 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject); 563 564 if (IsEqualGUID(riid, &IID_IUnknown) || 565 IsEqualGUID(riid, &IID_IXMLElementCollection)) 566 { 567 *ppvObject = iface; 568 } 569 else if (IsEqualGUID(riid, &IID_IEnumVARIANT)) 570 { 571 *ppvObject = &This->IEnumVARIANT_iface; 572 } 573 else 574 { 575 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 576 *ppvObject = NULL; 577 return E_NOINTERFACE; 578 } 579 580 IXMLElementCollection_AddRef(iface); 581 582 return S_OK; 583 } 584 585 static ULONG WINAPI xmlelem_collection_AddRef(IXMLElementCollection *iface) 586 { 587 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 588 TRACE("(%p)\n", This); 589 return InterlockedIncrement(&This->ref); 590 } 591 592 static ULONG WINAPI xmlelem_collection_Release(IXMLElementCollection *iface) 593 { 594 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 595 LONG ref; 596 597 TRACE("(%p)\n", This); 598 599 ref = InterlockedDecrement(&This->ref); 600 if (ref == 0) 601 { 602 heap_free(This); 603 } 604 605 return ref; 606 } 607 608 static HRESULT WINAPI xmlelem_collection_GetTypeInfoCount(IXMLElementCollection *iface, UINT* pctinfo) 609 { 610 FIXME("\n"); 611 return E_NOTIMPL; 612 } 613 614 static HRESULT WINAPI xmlelem_collection_GetTypeInfo(IXMLElementCollection *iface, UINT iTInfo, 615 LCID lcid, ITypeInfo** ppTInfo) 616 { 617 FIXME("\n"); 618 return E_NOTIMPL; 619 } 620 621 static HRESULT WINAPI xmlelem_collection_GetIDsOfNames(IXMLElementCollection *iface, REFIID riid, 622 LPOLESTR* rgszNames, UINT cNames, 623 LCID lcid, DISPID* rgDispId) 624 { 625 FIXME("\n"); 626 return E_NOTIMPL; 627 } 628 629 static HRESULT WINAPI xmlelem_collection_Invoke(IXMLElementCollection *iface, DISPID dispIdMember, 630 REFIID riid, LCID lcid, WORD wFlags, 631 DISPPARAMS* pDispParams, VARIANT* pVarResult, 632 EXCEPINFO* pExcepInfo, UINT* puArgErr) 633 { 634 FIXME("\n"); 635 return E_NOTIMPL; 636 } 637 638 static HRESULT WINAPI xmlelem_collection_put_length(IXMLElementCollection *iface, LONG v) 639 { 640 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 641 TRACE("(%p)->(%d)\n", This, v); 642 return E_FAIL; 643 } 644 645 static HRESULT WINAPI xmlelem_collection_get_length(IXMLElementCollection *iface, LONG *p) 646 { 647 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 648 649 TRACE("(%p)->(%p)\n", This, p); 650 651 if (!p) 652 return E_INVALIDARG; 653 654 *p = xmlelem_collection_updatelength(This); 655 return S_OK; 656 } 657 658 static HRESULT WINAPI xmlelem_collection_get__newEnum(IXMLElementCollection *iface, IUnknown **ppUnk) 659 { 660 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 661 662 TRACE("(%p)->(%p)\n", This, ppUnk); 663 664 if (!ppUnk) 665 return E_INVALIDARG; 666 667 IXMLElementCollection_AddRef(iface); 668 *ppUnk = (IUnknown *)&This->IEnumVARIANT_iface; 669 return S_OK; 670 } 671 672 static HRESULT WINAPI xmlelem_collection_item(IXMLElementCollection *iface, VARIANT var1, 673 VARIANT var2, IDispatch **ppDisp) 674 { 675 xmlelem_collection *This = impl_from_IXMLElementCollection(iface); 676 xmlNodePtr ptr = This->node->children; 677 int index, i; 678 679 TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&var1), debugstr_variant(&var2), ppDisp); 680 681 if (!ppDisp) 682 return E_INVALIDARG; 683 684 *ppDisp = NULL; 685 686 index = V_I4(&var1); 687 if (index < 0) 688 return E_INVALIDARG; 689 690 xmlelem_collection_updatelength(This); 691 if (index >= This->length) 692 return E_FAIL; 693 694 for (i = 0; i < index; i++) 695 ptr = ptr->next; 696 697 return XMLElement_create(ptr, (LPVOID *)ppDisp, FALSE); 698 } 699 700 static const struct IXMLElementCollectionVtbl xmlelem_collection_vtbl = 701 { 702 xmlelem_collection_QueryInterface, 703 xmlelem_collection_AddRef, 704 xmlelem_collection_Release, 705 xmlelem_collection_GetTypeInfoCount, 706 xmlelem_collection_GetTypeInfo, 707 xmlelem_collection_GetIDsOfNames, 708 xmlelem_collection_Invoke, 709 xmlelem_collection_put_length, 710 xmlelem_collection_get_length, 711 xmlelem_collection_get__newEnum, 712 xmlelem_collection_item 713 }; 714 715 /************************************************************************ 716 * xmlelem_collection implementation of IEnumVARIANT. 717 */ 718 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_QueryInterface( 719 IEnumVARIANT *iface, REFIID riid, LPVOID *ppvObj) 720 { 721 xmlelem_collection *this = impl_from_IEnumVARIANT(iface); 722 723 TRACE("(%p)->(%s %p)\n", this, debugstr_guid(riid), ppvObj); 724 725 if (IsEqualGUID(riid, &IID_IUnknown) || 726 IsEqualGUID(riid, &IID_IEnumVARIANT)) 727 { 728 *ppvObj = iface; 729 IEnumVARIANT_AddRef(iface); 730 return S_OK; 731 } 732 733 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 734 *ppvObj = NULL; 735 return E_NOINTERFACE; 736 } 737 738 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_AddRef( 739 IEnumVARIANT *iface) 740 { 741 xmlelem_collection *this = impl_from_IEnumVARIANT(iface); 742 return IXMLElementCollection_AddRef(&this->IXMLElementCollection_iface); 743 } 744 745 static ULONG WINAPI xmlelem_collection_IEnumVARIANT_Release( 746 IEnumVARIANT *iface) 747 { 748 xmlelem_collection *this = impl_from_IEnumVARIANT(iface); 749 return IXMLElementCollection_Release(&this->IXMLElementCollection_iface); 750 } 751 752 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Next( 753 IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *fetched) 754 { 755 xmlelem_collection *This = impl_from_IEnumVARIANT(iface); 756 xmlNodePtr ptr = This->current; 757 758 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, fetched); 759 760 if (!rgVar) 761 return E_INVALIDARG; 762 763 /* FIXME: handle celt */ 764 if (fetched) 765 *fetched = 1; 766 767 if (This->current) 768 This->current = This->current->next; 769 else 770 { 771 V_VT(rgVar) = VT_EMPTY; 772 if (fetched) *fetched = 0; 773 return S_FALSE; 774 } 775 776 V_VT(rgVar) = VT_DISPATCH; 777 return XMLElement_create(ptr, (LPVOID *)&V_DISPATCH(rgVar), FALSE); 778 } 779 780 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Skip( 781 IEnumVARIANT *iface, ULONG celt) 782 { 783 xmlelem_collection *This = impl_from_IEnumVARIANT(iface); 784 FIXME("(%p)->(%d): stub\n", This, celt); 785 return E_NOTIMPL; 786 } 787 788 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Reset( 789 IEnumVARIANT *iface) 790 { 791 xmlelem_collection *This = impl_from_IEnumVARIANT(iface); 792 TRACE("(%p)\n", This); 793 This->current = This->node->children; 794 return S_OK; 795 } 796 797 static HRESULT WINAPI xmlelem_collection_IEnumVARIANT_Clone( 798 IEnumVARIANT *iface, IEnumVARIANT **ppEnum) 799 { 800 xmlelem_collection *This = impl_from_IEnumVARIANT(iface); 801 FIXME("(%p)->(%p): stub\n", This, ppEnum); 802 return E_NOTIMPL; 803 } 804 805 static const struct IEnumVARIANTVtbl xmlelem_collection_IEnumVARIANTvtbl = 806 { 807 xmlelem_collection_IEnumVARIANT_QueryInterface, 808 xmlelem_collection_IEnumVARIANT_AddRef, 809 xmlelem_collection_IEnumVARIANT_Release, 810 xmlelem_collection_IEnumVARIANT_Next, 811 xmlelem_collection_IEnumVARIANT_Skip, 812 xmlelem_collection_IEnumVARIANT_Reset, 813 xmlelem_collection_IEnumVARIANT_Clone 814 }; 815 816 static HRESULT XMLElementCollection_create(xmlNodePtr node, LPVOID *ppObj) 817 { 818 xmlelem_collection *collection; 819 820 TRACE("(%p)\n", ppObj); 821 822 *ppObj = NULL; 823 824 if (!node->children) 825 return S_FALSE; 826 827 collection = heap_alloc(sizeof (*collection)); 828 if(!collection) 829 return E_OUTOFMEMORY; 830 831 collection->IXMLElementCollection_iface.lpVtbl = &xmlelem_collection_vtbl; 832 collection->IEnumVARIANT_iface.lpVtbl = &xmlelem_collection_IEnumVARIANTvtbl; 833 collection->ref = 1; 834 collection->length = 0; 835 collection->node = node; 836 collection->current = node->children; 837 xmlelem_collection_updatelength(collection); 838 839 *ppObj = &collection->IXMLElementCollection_iface; 840 841 TRACE("returning iface %p\n", *ppObj); 842 return S_OK; 843 } 844 845 #endif 846