1 /* 2 * Copyright 2006 Jacek Caban for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "mshtml_private.h" 20 21 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*); 22 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**); 23 24 static ExternalCycleCollectionParticipant node_ccp; 25 26 typedef struct { 27 DispatchEx dispex; 28 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface; 29 30 LONG ref; 31 32 /* FIXME: implement weak reference */ 33 HTMLDocumentNode *doc; 34 35 nsIDOMNodeList *nslist; 36 } HTMLDOMChildrenCollection; 37 38 typedef struct { 39 IEnumVARIANT IEnumVARIANT_iface; 40 41 LONG ref; 42 43 ULONG iter; 44 HTMLDOMChildrenCollection *col; 45 } HTMLDOMChildrenCollectionEnum; 46 47 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface) 48 { 49 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface); 50 } 51 52 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv) 53 { 54 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 55 56 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 57 58 if(IsEqualGUID(riid, &IID_IUnknown)) { 59 *ppv = &This->IEnumVARIANT_iface; 60 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) { 61 *ppv = &This->IEnumVARIANT_iface; 62 }else { 63 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 64 *ppv = NULL; 65 return E_NOINTERFACE; 66 } 67 68 IUnknown_AddRef((IUnknown*)*ppv); 69 return S_OK; 70 } 71 72 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface) 73 { 74 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 75 LONG ref = InterlockedIncrement(&This->ref); 76 77 TRACE("(%p) ref=%d\n", This, ref); 78 79 return ref; 80 } 81 82 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface) 83 { 84 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 85 LONG ref = InterlockedDecrement(&This->ref); 86 87 TRACE("(%p) ref=%d\n", This, ref); 88 89 if(!ref) { 90 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface); 91 heap_free(This); 92 } 93 94 return ref; 95 } 96 97 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This) 98 { 99 ULONG len; 100 nsresult nsres; 101 102 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len); 103 assert(nsres == NS_OK); 104 return len; 105 } 106 107 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched) 108 { 109 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 110 ULONG fetched = 0, len; 111 nsIDOMNode *nsnode; 112 HTMLDOMNode *node; 113 nsresult nsres; 114 HRESULT hres; 115 116 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched); 117 118 len = get_enum_len(This); 119 120 while(This->iter+fetched < len && fetched < celt) { 121 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode); 122 assert(nsres == NS_OK); 123 124 hres = get_node(This->col->doc, nsnode, TRUE, &node); 125 nsIDOMNode_Release(nsnode); 126 if(FAILED(hres)) { 127 ERR("get_node failed: %08x\n", hres); 128 break; 129 } 130 131 V_VT(rgVar+fetched) = VT_DISPATCH; 132 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface); 133 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface; 134 fetched++; 135 } 136 137 This->iter += fetched; 138 if(pCeltFetched) 139 *pCeltFetched = fetched; 140 return fetched == celt ? S_OK : S_FALSE; 141 } 142 143 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt) 144 { 145 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 146 ULONG len; 147 148 TRACE("(%p)->(%d)\n", This, celt); 149 150 len = get_enum_len(This); 151 if(This->iter + celt > len) { 152 This->iter = len; 153 return S_FALSE; 154 } 155 156 This->iter += celt; 157 return S_OK; 158 } 159 160 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface) 161 { 162 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 163 164 TRACE("(%p)->()\n", This); 165 166 This->iter = 0; 167 return S_OK; 168 } 169 170 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum) 171 { 172 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface); 173 FIXME("(%p)->(%p)\n", This, ppEnum); 174 return E_NOTIMPL; 175 } 176 177 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = { 178 HTMLDOMChildrenCollectionEnum_QueryInterface, 179 HTMLDOMChildrenCollectionEnum_AddRef, 180 HTMLDOMChildrenCollectionEnum_Release, 181 HTMLDOMChildrenCollectionEnum_Next, 182 HTMLDOMChildrenCollectionEnum_Skip, 183 HTMLDOMChildrenCollectionEnum_Reset, 184 HTMLDOMChildrenCollectionEnum_Clone 185 }; 186 187 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface) 188 { 189 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface); 190 } 191 192 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv) 193 { 194 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 195 196 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 197 198 if(IsEqualGUID(&IID_IUnknown, riid)) { 199 *ppv = &This->IHTMLDOMChildrenCollection_iface; 200 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) { 201 *ppv = &This->IHTMLDOMChildrenCollection_iface; 202 }else if(dispex_query_interface(&This->dispex, riid, ppv)) { 203 return *ppv ? S_OK : E_NOINTERFACE; 204 }else { 205 *ppv = NULL; 206 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 207 return E_NOINTERFACE; 208 } 209 210 IUnknown_AddRef((IUnknown*)*ppv); 211 return S_OK; 212 } 213 214 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface) 215 { 216 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 217 LONG ref = InterlockedIncrement(&This->ref); 218 219 TRACE("(%p) ref=%d\n", This, ref); 220 221 return ref; 222 } 223 224 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface) 225 { 226 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 227 LONG ref = InterlockedDecrement(&This->ref); 228 229 TRACE("(%p) ref=%d\n", This, ref); 230 231 if(!ref) { 232 htmldoc_release(&This->doc->basedoc); 233 nsIDOMNodeList_Release(This->nslist); 234 heap_free(This); 235 } 236 237 return ref; 238 } 239 240 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo) 241 { 242 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 243 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo); 244 } 245 246 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo, 247 LCID lcid, ITypeInfo **ppTInfo) 248 { 249 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 250 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 251 } 252 253 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid, 254 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) 255 { 256 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 257 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, 258 lcid, rgDispId); 259 } 260 261 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember, 262 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 263 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 264 { 265 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 266 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, 267 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 268 } 269 270 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p) 271 { 272 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 273 UINT32 length=0; 274 275 TRACE("(%p)->(%p)\n", This, p); 276 277 nsIDOMNodeList_GetLength(This->nslist, &length); 278 *p = length; 279 return S_OK; 280 } 281 282 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p) 283 { 284 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 285 HTMLDOMChildrenCollectionEnum *ret; 286 287 TRACE("(%p)->(%p)\n", This, p); 288 289 ret = heap_alloc(sizeof(*ret)); 290 if(!ret) 291 return E_OUTOFMEMORY; 292 293 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl; 294 ret->ref = 1; 295 ret->iter = 0; 296 297 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface); 298 ret->col = This; 299 300 *p = (IUnknown*)&ret->IEnumVARIANT_iface; 301 return S_OK; 302 } 303 304 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem) 305 { 306 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface); 307 nsIDOMNode *nsnode = NULL; 308 HTMLDOMNode *node; 309 UINT32 length=0; 310 nsresult nsres; 311 HRESULT hres; 312 313 TRACE("(%p)->(%d %p)\n", This, index, ppItem); 314 315 if (ppItem) 316 *ppItem = NULL; 317 else 318 return E_POINTER; 319 320 nsIDOMNodeList_GetLength(This->nslist, &length); 321 if(index < 0 || index >= length) 322 return E_INVALIDARG; 323 324 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode); 325 if(NS_FAILED(nsres) || !nsnode) { 326 ERR("Item failed: %08x\n", nsres); 327 return E_FAIL; 328 } 329 330 hres = get_node(This->doc, nsnode, TRUE, &node); 331 if(FAILED(hres)) 332 return hres; 333 334 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface; 335 return S_OK; 336 } 337 338 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = { 339 HTMLDOMChildrenCollection_QueryInterface, 340 HTMLDOMChildrenCollection_AddRef, 341 HTMLDOMChildrenCollection_Release, 342 HTMLDOMChildrenCollection_GetTypeInfoCount, 343 HTMLDOMChildrenCollection_GetTypeInfo, 344 HTMLDOMChildrenCollection_GetIDsOfNames, 345 HTMLDOMChildrenCollection_Invoke, 346 HTMLDOMChildrenCollection_get_length, 347 HTMLDOMChildrenCollection_get__newEnum, 348 HTMLDOMChildrenCollection_item 349 }; 350 351 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface) 352 { 353 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex); 354 } 355 356 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN 357 358 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid) 359 { 360 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex); 361 WCHAR *ptr; 362 DWORD idx=0; 363 UINT32 len = 0; 364 365 for(ptr = name; *ptr && isdigitW(*ptr); ptr++) 366 idx = idx*10 + (*ptr-'0'); 367 if(*ptr) 368 return DISP_E_UNKNOWNNAME; 369 370 nsIDOMNodeList_GetLength(This->nslist, &len); 371 if(idx >= len) 372 return DISP_E_UNKNOWNNAME; 373 374 *dispid = DISPID_CHILDCOL_0 + idx; 375 TRACE("ret %x\n", *dispid); 376 return S_OK; 377 } 378 379 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, 380 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) 381 { 382 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex); 383 384 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller); 385 386 switch(flags) { 387 case DISPATCH_PROPERTYGET: { 388 IDispatch *disp = NULL; 389 HRESULT hres; 390 391 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface, 392 id - DISPID_CHILDCOL_0, &disp); 393 if(FAILED(hres)) 394 return hres; 395 396 V_VT(res) = VT_DISPATCH; 397 V_DISPATCH(res) = disp; 398 break; 399 } 400 401 default: 402 FIXME("unimplemented flags %x\n", flags); 403 return E_NOTIMPL; 404 } 405 406 return S_OK; 407 } 408 409 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = { 410 NULL, 411 HTMLDOMChildrenCollection_get_dispid, 412 HTMLDOMChildrenCollection_invoke, 413 NULL 414 }; 415 416 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = { 417 IHTMLDOMChildrenCollection_tid, 418 0 419 }; 420 421 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = { 422 &HTMLDOMChildrenCollection_dispex_vtbl, 423 DispDOMChildrenCollection_tid, 424 NULL, 425 HTMLDOMChildrenCollection_iface_tids 426 }; 427 428 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocumentNode *doc, nsIDOMNodeList *nslist) 429 { 430 HTMLDOMChildrenCollection *ret; 431 432 ret = heap_alloc_zero(sizeof(*ret)); 433 if(!ret) 434 return NULL; 435 436 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl; 437 ret->ref = 1; 438 439 nsIDOMNodeList_AddRef(nslist); 440 ret->nslist = nslist; 441 442 htmldoc_addref(&doc->basedoc); 443 ret->doc = doc; 444 445 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface, 446 &HTMLDOMChildrenCollection_dispex); 447 448 return &ret->IHTMLDOMChildrenCollection_iface; 449 } 450 451 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface) 452 { 453 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface); 454 } 455 456 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface, 457 REFIID riid, void **ppv) 458 { 459 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 460 461 return This->vtbl->qi(This, riid, ppv); 462 } 463 464 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface) 465 { 466 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 467 LONG ref; 468 469 ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface); 470 471 TRACE("(%p) ref=%d\n", This, ref); 472 473 return ref; 474 } 475 476 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface) 477 { 478 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 479 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface, /*&node_ccp*/ NULL); 480 481 TRACE("(%p) ref=%d\n", This, ref); 482 483 return ref; 484 } 485 486 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo) 487 { 488 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 489 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo); 490 } 491 492 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo, 493 LCID lcid, ITypeInfo **ppTInfo) 494 { 495 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 496 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 497 } 498 499 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid, 500 LPOLESTR *rgszNames, UINT cNames, 501 LCID lcid, DISPID *rgDispId) 502 { 503 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 504 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames, 505 lcid, rgDispId); 506 } 507 508 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember, 509 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 510 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 511 { 512 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 513 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, 514 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 515 } 516 517 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p) 518 { 519 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 520 UINT16 type = -1; 521 522 TRACE("(%p)->(%p)\n", This, p); 523 524 nsIDOMNode_GetNodeType(This->nsnode, &type); 525 526 switch(type) { 527 case ELEMENT_NODE: 528 *p = 1; 529 break; 530 case TEXT_NODE: 531 *p = 3; 532 break; 533 case COMMENT_NODE: 534 case DOCUMENT_TYPE_NODE: 535 *p = 8; 536 break; 537 case DOCUMENT_NODE: 538 *p = 9; 539 break; 540 case DOCUMENT_FRAGMENT_NODE: 541 *p = 11; 542 break; 543 default: 544 /* 545 * FIXME: 546 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported. 547 * It needs more tests. 548 */ 549 FIXME("type %u\n", type); 550 *p = 0; 551 } 552 553 return S_OK; 554 } 555 556 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p) 557 { 558 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 559 HTMLDOMNode *node; 560 nsIDOMNode *nsnode; 561 nsresult nsres; 562 HRESULT hres; 563 564 TRACE("(%p)->(%p)\n", This, p); 565 566 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode); 567 if(NS_FAILED(nsres)) { 568 ERR("GetParentNode failed: %08x\n", nsres); 569 return E_FAIL; 570 } 571 572 if(!nsnode) { 573 *p = NULL; 574 return S_OK; 575 } 576 577 hres = get_node(This->doc, nsnode, TRUE, &node); 578 nsIDOMNode_Release(nsnode); 579 if(FAILED(hres)) 580 return hres; 581 582 *p = &node->IHTMLDOMNode_iface; 583 return S_OK; 584 } 585 586 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren) 587 { 588 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 589 cpp_bool has_child = FALSE; 590 nsresult nsres; 591 592 TRACE("(%p)->(%p)\n", This, fChildren); 593 594 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child); 595 if(NS_FAILED(nsres)) 596 ERR("HasChildNodes failed: %08x\n", nsres); 597 598 *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE; 599 return S_OK; 600 } 601 602 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p) 603 { 604 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 605 nsIDOMNodeList *nslist; 606 nsresult nsres; 607 608 TRACE("(%p)->(%p)\n", This, p); 609 610 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist); 611 if(NS_FAILED(nsres)) { 612 ERR("GetChildNodes failed: %08x\n", nsres); 613 return E_FAIL; 614 } 615 616 *p = (IDispatch*)create_child_collection(This->doc, nslist); 617 nsIDOMNodeList_Release(nslist); 618 619 return *p ? S_OK : E_OUTOFMEMORY; 620 } 621 622 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p) 623 { 624 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 625 HTMLAttributeCollection *col; 626 HRESULT hres; 627 628 TRACE("(%p)->(%p)\n", This, p); 629 630 if(This->vtbl->get_attr_col) { 631 hres = This->vtbl->get_attr_col(This, &col); 632 if(FAILED(hres)) 633 return hres; 634 635 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface; 636 return S_OK; 637 } 638 639 *p = NULL; 640 return S_OK; 641 } 642 643 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, 644 VARIANT refChild, IHTMLDOMNode **node) 645 { 646 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 647 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL; 648 nsIDOMNode *nsnode; 649 nsresult nsres; 650 HRESULT hres = S_OK; 651 652 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node); 653 654 new_child = get_node_obj(newChild); 655 if(!new_child) { 656 ERR("invalid newChild\n"); 657 return E_INVALIDARG; 658 } 659 660 switch(V_VT(&refChild)) { 661 case VT_NULL: 662 break; 663 case VT_DISPATCH: { 664 IHTMLDOMNode *ref_iface; 665 666 if(!V_DISPATCH(&refChild)) 667 break; 668 669 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface); 670 if(FAILED(hres)) 671 break; 672 673 ref_node = get_node_obj(ref_iface); 674 IHTMLDOMNode_Release(ref_iface); 675 if(!ref_node) { 676 ERR("unvalid node\n"); 677 hres = E_FAIL; 678 break; 679 } 680 break; 681 } 682 default: 683 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild)); 684 hres = E_NOTIMPL; 685 } 686 687 if(SUCCEEDED(hres)) { 688 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode); 689 if(NS_FAILED(nsres)) { 690 ERR("InsertBefore failed: %08x\n", nsres); 691 hres = E_FAIL; 692 } 693 } 694 node_release(new_child); 695 if(ref_node) 696 node_release(ref_node); 697 if(FAILED(hres)) 698 return hres; 699 700 hres = get_node(This->doc, nsnode, TRUE, &node_obj); 701 nsIDOMNode_Release(nsnode); 702 if(FAILED(hres)) 703 return hres; 704 705 *node = &node_obj->IHTMLDOMNode_iface; 706 return S_OK; 707 } 708 709 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild, 710 IHTMLDOMNode **node) 711 { 712 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 713 HTMLDOMNode *node_obj; 714 nsIDOMNode *nsnode; 715 nsresult nsres; 716 HRESULT hres; 717 718 TRACE("(%p)->(%p %p)\n", This, oldChild, node); 719 720 node_obj = get_node_obj(oldChild); 721 if(!node_obj) 722 return E_FAIL; 723 724 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode); 725 node_release(node_obj); 726 if(NS_FAILED(nsres)) { 727 ERR("RemoveChild failed: %08x\n", nsres); 728 return E_FAIL; 729 } 730 731 hres = get_node(This->doc, nsnode, TRUE, &node_obj); 732 nsIDOMNode_Release(nsnode); 733 if(FAILED(hres)) 734 return hres; 735 736 /* FIXME: Make sure that node != newChild */ 737 *node = &node_obj->IHTMLDOMNode_iface; 738 return S_OK; 739 } 740 741 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, 742 IHTMLDOMNode *oldChild, IHTMLDOMNode **node) 743 { 744 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 745 HTMLDOMNode *node_new, *node_old, *ret_node; 746 nsIDOMNode *nsnode; 747 nsresult nsres; 748 HRESULT hres; 749 750 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node); 751 752 node_new = get_node_obj(newChild); 753 if(!node_new) 754 return E_FAIL; 755 756 node_old = get_node_obj(oldChild); 757 if(!node_old) { 758 node_release(node_new); 759 return E_FAIL; 760 } 761 762 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode); 763 node_release(node_new); 764 node_release(node_old); 765 if(NS_FAILED(nsres)) 766 return E_FAIL; 767 768 hres = get_node(This->doc, nsnode, TRUE, &ret_node); 769 nsIDOMNode_Release(nsnode); 770 if(FAILED(hres)) 771 return hres; 772 773 *node = &ret_node->IHTMLDOMNode_iface; 774 return S_OK; 775 } 776 777 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep, 778 IHTMLDOMNode **clonedNode) 779 { 780 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 781 HTMLDOMNode *new_node; 782 nsIDOMNode *nsnode; 783 nsresult nsres; 784 HRESULT hres; 785 786 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode); 787 788 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode); 789 if(NS_FAILED(nsres) || !nsnode) { 790 ERR("CloneNode failed: %08x\n", nsres); 791 return E_FAIL; 792 } 793 794 hres = This->vtbl->clone(This, nsnode, &new_node); 795 if(FAILED(hres)) 796 return hres; 797 798 *clonedNode = &new_node->IHTMLDOMNode_iface; 799 return S_OK; 800 } 801 802 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep, 803 IHTMLDOMNode **removed) 804 { 805 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 806 FIXME("(%p)->(%x %p)\n", This, fDeep, removed); 807 return E_NOTIMPL; 808 } 809 810 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode, 811 IHTMLDOMNode **swappedNode) 812 { 813 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 814 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode); 815 return E_NOTIMPL; 816 } 817 818 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement, 819 IHTMLDOMNode **replaced) 820 { 821 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 822 FIXME("(%p)->(%p %p)\n", This, replacement, replaced); 823 return E_NOTIMPL; 824 } 825 826 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild, 827 IHTMLDOMNode **node) 828 { 829 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 830 HTMLDOMNode *node_obj; 831 nsIDOMNode *nsnode; 832 nsresult nsres; 833 HRESULT hres; 834 835 TRACE("(%p)->(%p %p)\n", This, newChild, node); 836 837 node_obj = get_node_obj(newChild); 838 if(!node_obj) 839 return E_FAIL; 840 841 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode); 842 node_release(node_obj); 843 if(NS_FAILED(nsres)) { 844 ERR("AppendChild failed: %08x\n", nsres); 845 return E_FAIL; 846 } 847 848 hres = get_node(This->doc, nsnode, TRUE, &node_obj); 849 nsIDOMNode_Release(nsnode); 850 if(FAILED(hres)) 851 return hres; 852 853 /* FIXME: Make sure that node != newChild */ 854 *node = &node_obj->IHTMLDOMNode_iface; 855 return S_OK; 856 } 857 858 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p) 859 { 860 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 861 nsAString name; 862 nsresult nsres; 863 864 TRACE("(%p)->(%p)\n", This, p); 865 866 nsAString_Init(&name, NULL); 867 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name); 868 return return_nsstr(nsres, &name, p); 869 } 870 871 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v) 872 { 873 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 874 875 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v)); 876 877 switch(V_VT(&v)) { 878 case VT_BSTR: { 879 nsAString val_str; 880 881 nsAString_InitDepend(&val_str, V_BSTR(&v)); 882 nsIDOMNode_SetNodeValue(This->nsnode, &val_str); 883 nsAString_Finish(&val_str); 884 885 return S_OK; 886 } 887 888 default: 889 FIXME("unsupported value %s\n", debugstr_variant(&v)); 890 } 891 892 return E_NOTIMPL; 893 } 894 895 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p) 896 { 897 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 898 const PRUnichar *val; 899 nsAString val_str; 900 901 TRACE("(%p)->(%p)\n", This, p); 902 903 nsAString_Init(&val_str, NULL); 904 nsIDOMNode_GetNodeValue(This->nsnode, &val_str); 905 nsAString_GetData(&val_str, &val); 906 907 if(*val) { 908 V_VT(p) = VT_BSTR; 909 V_BSTR(p) = SysAllocString(val); 910 }else { 911 V_VT(p) = VT_NULL; 912 } 913 914 nsAString_Finish(&val_str); 915 916 return S_OK; 917 } 918 919 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p) 920 { 921 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 922 nsIDOMNode *nschild = NULL; 923 HTMLDOMNode *node; 924 HRESULT hres; 925 926 TRACE("(%p)->(%p)\n", This, p); 927 928 nsIDOMNode_GetFirstChild(This->nsnode, &nschild); 929 if(!nschild) { 930 *p = NULL; 931 return S_OK; 932 } 933 934 hres = get_node(This->doc, nschild, TRUE, &node); 935 nsIDOMNode_Release(nschild); 936 if(FAILED(hres)) 937 return hres; 938 939 *p = &node->IHTMLDOMNode_iface; 940 return S_OK; 941 } 942 943 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p) 944 { 945 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 946 nsIDOMNode *nschild = NULL; 947 HTMLDOMNode *node; 948 HRESULT hres; 949 950 TRACE("(%p)->(%p)\n", This, p); 951 952 nsIDOMNode_GetLastChild(This->nsnode, &nschild); 953 if(!nschild) { 954 *p = NULL; 955 return S_OK; 956 } 957 958 hres = get_node(This->doc, nschild, TRUE, &node); 959 nsIDOMNode_Release(nschild); 960 if(FAILED(hres)) 961 return hres; 962 963 *p = &node->IHTMLDOMNode_iface; 964 return S_OK; 965 } 966 967 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p) 968 { 969 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 970 nsIDOMNode *nschild = NULL; 971 HTMLDOMNode *node; 972 HRESULT hres; 973 974 TRACE("(%p)->(%p)\n", This, p); 975 976 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild); 977 if(!nschild) { 978 *p = NULL; 979 return S_OK; 980 } 981 982 hres = get_node(This->doc, nschild, TRUE, &node); 983 nsIDOMNode_Release(nschild); 984 if(FAILED(hres)) 985 return hres; 986 987 *p = &node->IHTMLDOMNode_iface; 988 return S_OK; 989 } 990 991 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p) 992 { 993 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface); 994 nsIDOMNode *nssibling = NULL; 995 HTMLDOMNode *node; 996 HRESULT hres; 997 998 TRACE("(%p)->(%p)\n", This, p); 999 1000 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling); 1001 if(!nssibling) { 1002 *p = NULL; 1003 return S_OK; 1004 } 1005 1006 hres = get_node(This->doc, nssibling, TRUE, &node); 1007 nsIDOMNode_Release(nssibling); 1008 if(FAILED(hres)) 1009 return hres; 1010 1011 *p = &node->IHTMLDOMNode_iface; 1012 return S_OK; 1013 } 1014 1015 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = { 1016 HTMLDOMNode_QueryInterface, 1017 HTMLDOMNode_AddRef, 1018 HTMLDOMNode_Release, 1019 HTMLDOMNode_GetTypeInfoCount, 1020 HTMLDOMNode_GetTypeInfo, 1021 HTMLDOMNode_GetIDsOfNames, 1022 HTMLDOMNode_Invoke, 1023 HTMLDOMNode_get_nodeType, 1024 HTMLDOMNode_get_parentNode, 1025 HTMLDOMNode_hasChildNodes, 1026 HTMLDOMNode_get_childNodes, 1027 HTMLDOMNode_get_attributes, 1028 HTMLDOMNode_insertBefore, 1029 HTMLDOMNode_removeChild, 1030 HTMLDOMNode_replaceChild, 1031 HTMLDOMNode_cloneNode, 1032 HTMLDOMNode_removeNode, 1033 HTMLDOMNode_swapNode, 1034 HTMLDOMNode_replaceNode, 1035 HTMLDOMNode_appendChild, 1036 HTMLDOMNode_get_nodeName, 1037 HTMLDOMNode_put_nodeValue, 1038 HTMLDOMNode_get_nodeValue, 1039 HTMLDOMNode_get_firstChild, 1040 HTMLDOMNode_get_lastChild, 1041 HTMLDOMNode_get_previousSibling, 1042 HTMLDOMNode_get_nextSibling 1043 }; 1044 1045 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface) 1046 { 1047 HTMLDOMNode *ret; 1048 1049 if(iface->lpVtbl != &HTMLDOMNodeVtbl) 1050 return NULL; 1051 1052 ret = impl_from_IHTMLDOMNode(iface); 1053 node_addref(ret); 1054 return ret; 1055 } 1056 1057 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface) 1058 { 1059 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface); 1060 } 1061 1062 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface, 1063 REFIID riid, void **ppv) 1064 { 1065 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1066 1067 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv); 1068 } 1069 1070 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface) 1071 { 1072 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1073 1074 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface); 1075 } 1076 1077 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface) 1078 { 1079 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1080 1081 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface); 1082 } 1083 1084 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo) 1085 { 1086 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1087 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo); 1088 } 1089 1090 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo, 1091 LCID lcid, ITypeInfo **ppTInfo) 1092 { 1093 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1094 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo); 1095 } 1096 1097 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid, 1098 LPOLESTR *rgszNames, UINT cNames, 1099 LCID lcid, DISPID *rgDispId) 1100 { 1101 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1102 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames, 1103 lcid, rgDispId); 1104 } 1105 1106 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember, 1107 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 1108 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) 1109 { 1110 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1111 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid, 1112 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); 1113 } 1114 1115 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p) 1116 { 1117 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface); 1118 1119 TRACE("(%p)->(%p)\n", This, p); 1120 1121 /* FIXME: Better check for document node */ 1122 if(This == &This->doc->node) { 1123 *p = NULL; 1124 }else { 1125 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface; 1126 IDispatch_AddRef(*p); 1127 } 1128 return S_OK; 1129 } 1130 1131 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = { 1132 HTMLDOMNode2_QueryInterface, 1133 HTMLDOMNode2_AddRef, 1134 HTMLDOMNode2_Release, 1135 HTMLDOMNode2_GetTypeInfoCount, 1136 HTMLDOMNode2_GetTypeInfo, 1137 HTMLDOMNode2_GetIDsOfNames, 1138 HTMLDOMNode2_Invoke, 1139 HTMLDOMNode2_get_ownerDocument 1140 }; 1141 1142 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv) 1143 { 1144 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 1145 1146 if(IsEqualGUID(&IID_IUnknown, riid)) { 1147 *ppv = &This->IHTMLDOMNode_iface; 1148 }else if(IsEqualGUID(&IID_IDispatch, riid)) { 1149 *ppv = &This->IHTMLDOMNode_iface; 1150 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) { 1151 *ppv = &This->IHTMLDOMNode_iface; 1152 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) { 1153 *ppv = &This->IHTMLDOMNode2_iface; 1154 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) { 1155 *ppv = &node_ccp; 1156 return NS_OK; 1157 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) { 1158 *ppv = &This->IHTMLDOMNode_iface; 1159 return NS_OK; 1160 }else if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) { 1161 return *ppv ? S_OK : E_NOINTERFACE; 1162 }else { 1163 *ppv = NULL; 1164 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); 1165 return E_NOINTERFACE; 1166 } 1167 1168 IUnknown_AddRef((IUnknown*)*ppv); 1169 return S_OK; 1170 } 1171 1172 void HTMLDOMNode_destructor(HTMLDOMNode *This) 1173 { 1174 if(This->nsnode) 1175 nsIDOMNode_Release(This->nsnode); 1176 if(This->doc && &This->doc->node != This) 1177 htmldoc_release(&This->doc->basedoc); 1178 if(This->event_target.ptr) 1179 release_event_target(This->event_target.ptr); 1180 } 1181 1182 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret) 1183 { 1184 return create_node(This->doc, nsnode, ret); 1185 } 1186 1187 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}}; 1188 1189 static const NodeImplVtbl HTMLDOMNodeImplVtbl = { 1190 HTMLDOMNode_QI, 1191 HTMLDOMNode_destructor, 1192 HTMLDOMNode_cpc, 1193 HTMLDOMNode_clone 1194 }; 1195 1196 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode) 1197 { 1198 nsresult nsres; 1199 1200 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl; 1201 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl; 1202 1203 ccref_init(&node->ccref, 1); 1204 1205 if(&doc->node != node) 1206 htmldoc_addref(&doc->basedoc); 1207 node->doc = doc; 1208 1209 nsIDOMNode_AddRef(nsnode); 1210 node->nsnode = nsnode; 1211 1212 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface); 1213 assert(nsres == NS_OK); 1214 } 1215 1216 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret) 1217 { 1218 UINT16 node_type; 1219 HRESULT hres; 1220 1221 nsIDOMNode_GetNodeType(nsnode, &node_type); 1222 1223 switch(node_type) { 1224 case ELEMENT_NODE: { 1225 HTMLElement *elem; 1226 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem); 1227 if(FAILED(hres)) 1228 return hres; 1229 *ret = &elem->node; 1230 break; 1231 } 1232 case TEXT_NODE: 1233 hres = HTMLDOMTextNode_Create(doc, nsnode, ret); 1234 if(FAILED(hres)) 1235 return hres; 1236 break; 1237 /* doctype nodes are represented as comment nodes (at least in quirks mode) */ 1238 case DOCUMENT_TYPE_NODE: 1239 case COMMENT_NODE: { 1240 HTMLElement *comment; 1241 hres = HTMLCommentElement_Create(doc, nsnode, &comment); 1242 if(FAILED(hres)) 1243 return hres; 1244 *ret = &comment->node; 1245 break; 1246 } 1247 case ATTRIBUTE_NODE: 1248 ERR("Called on attribute node\n"); 1249 return E_UNEXPECTED; 1250 default: { 1251 HTMLDOMNode *node; 1252 1253 node = heap_alloc_zero(sizeof(HTMLDOMNode)); 1254 if(!node) 1255 return E_OUTOFMEMORY; 1256 1257 node->vtbl = &HTMLDOMNodeImplVtbl; 1258 HTMLDOMNode_Init(doc, node, nsnode); 1259 *ret = node; 1260 } 1261 } 1262 1263 TRACE("type %d ret %p\n", node_type, *ret); 1264 return S_OK; 1265 } 1266 1267 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb) 1268 { 1269 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p); 1270 1271 TRACE("%p\n", This); 1272 1273 describe_cc_node(&This->ccref, "HTMLDOMNode", cb); 1274 1275 if(This->nsnode) 1276 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb); 1277 if(This->doc && &This->doc->node != This) 1278 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb); 1279 dispex_traverse(&This->event_target.dispex, cb); 1280 1281 if(This->vtbl->traverse) 1282 This->vtbl->traverse(This, cb); 1283 1284 return NS_OK; 1285 } 1286 1287 static nsresult NSAPI HTMLDOMNode_unlink(void *p) 1288 { 1289 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p); 1290 1291 TRACE("%p\n", This); 1292 1293 if(This->vtbl->unlink) 1294 This->vtbl->unlink(This); 1295 1296 dispex_unlink(&This->event_target.dispex); 1297 1298 if(This->nsnode) { 1299 nsIDOMNode *nsnode = This->nsnode; 1300 This->nsnode = NULL; 1301 nsIDOMNode_Release(nsnode); 1302 } 1303 1304 if(This->doc && &This->doc->node != This) { 1305 HTMLDocument *doc = &This->doc->basedoc; 1306 This->doc = NULL; 1307 htmldoc_release(doc); 1308 }else { 1309 This->doc = NULL; 1310 } 1311 1312 return NS_OK; 1313 } 1314 1315 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p) 1316 { 1317 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p); 1318 1319 TRACE("(%p)\n", This); 1320 1321 if(This->vtbl->unlink) 1322 This->vtbl->unlink(This); 1323 This->vtbl->destructor(This); 1324 release_dispex(&This->event_target.dispex); 1325 heap_free(This); 1326 } 1327 1328 void init_node_cc(void) 1329 { 1330 static const CCObjCallback node_ccp_callback = { 1331 HTMLDOMNode_traverse, 1332 HTMLDOMNode_unlink, 1333 HTMLDOMNode_delete_cycle_collectable 1334 }; 1335 1336 ccp_init(&node_ccp, &node_ccp_callback); 1337 } 1338 1339 HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret) 1340 { 1341 nsISupports *unk = NULL; 1342 nsresult nsres; 1343 1344 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk); 1345 assert(nsres == NS_OK); 1346 1347 if(unk) { 1348 *ret = get_node_obj((IHTMLDOMNode*)unk); 1349 nsISupports_Release(unk); 1350 return NS_OK; 1351 } 1352 1353 if(!create) { 1354 *ret = NULL; 1355 return S_OK; 1356 } 1357 1358 return create_node(This, nsnode, ret); 1359 } 1360