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