secur32/tests: Use importlib for functions available since Windows XP.
[wine.git] / dlls / mshtml / htmlnode.c
blob1ba477e041cdd26ebb52452cf9555cece11e8a1f
1 /*
2 * Copyright 2006 Jacek Caban for CodeWeavers
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.
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.
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
19 #include <stdarg.h>
20 #include <assert.h>
22 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
29 #include "wine/debug.h"
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
36 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
37 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
39 static ExternalCycleCollectionParticipant node_ccp;
41 typedef struct {
42 DispatchEx dispex;
43 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
45 LONG ref;
47 /* FIXME: implement weak reference */
48 HTMLDocumentNode *doc;
50 nsIDOMNodeList *nslist;
51 } HTMLDOMChildrenCollection;
53 typedef struct {
54 IEnumVARIANT IEnumVARIANT_iface;
56 LONG ref;
58 ULONG iter;
59 HTMLDOMChildrenCollection *col;
60 } HTMLDOMChildrenCollectionEnum;
62 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
64 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
67 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
69 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
71 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
73 if(IsEqualGUID(riid, &IID_IUnknown)) {
74 *ppv = &This->IEnumVARIANT_iface;
75 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
76 *ppv = &This->IEnumVARIANT_iface;
77 }else {
78 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
79 *ppv = NULL;
80 return E_NOINTERFACE;
83 IUnknown_AddRef((IUnknown*)*ppv);
84 return S_OK;
87 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
89 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
90 LONG ref = InterlockedIncrement(&This->ref);
92 TRACE("(%p) ref=%d\n", This, ref);
94 return ref;
97 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
99 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
100 LONG ref = InterlockedDecrement(&This->ref);
102 TRACE("(%p) ref=%d\n", This, ref);
104 if(!ref) {
105 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
106 heap_free(This);
109 return ref;
112 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
114 ULONG len;
115 nsresult nsres;
117 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
118 assert(nsres == NS_OK);
119 return len;
122 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
124 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
125 ULONG fetched = 0, len;
126 nsIDOMNode *nsnode;
127 HTMLDOMNode *node;
128 nsresult nsres;
129 HRESULT hres;
131 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
133 len = get_enum_len(This);
135 while(This->iter+fetched < len && fetched < celt) {
136 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
137 assert(nsres == NS_OK);
139 hres = get_node(This->col->doc, nsnode, TRUE, &node);
140 nsIDOMNode_Release(nsnode);
141 if(FAILED(hres)) {
142 ERR("get_node failed: %08x\n", hres);
143 break;
146 V_VT(rgVar+fetched) = VT_DISPATCH;
147 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
148 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
149 fetched++;
152 This->iter += fetched;
153 if(pCeltFetched)
154 *pCeltFetched = fetched;
155 return fetched == celt ? S_OK : S_FALSE;
158 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
160 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
161 ULONG len;
163 TRACE("(%p)->(%d)\n", This, celt);
165 len = get_enum_len(This);
166 if(This->iter + celt > len) {
167 This->iter = len;
168 return S_FALSE;
171 This->iter += celt;
172 return S_OK;
175 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
177 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
179 TRACE("(%p)->()\n", This);
181 This->iter = 0;
182 return S_OK;
185 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
187 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
188 FIXME("(%p)->(%p)\n", This, ppEnum);
189 return E_NOTIMPL;
192 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
193 HTMLDOMChildrenCollectionEnum_QueryInterface,
194 HTMLDOMChildrenCollectionEnum_AddRef,
195 HTMLDOMChildrenCollectionEnum_Release,
196 HTMLDOMChildrenCollectionEnum_Next,
197 HTMLDOMChildrenCollectionEnum_Skip,
198 HTMLDOMChildrenCollectionEnum_Reset,
199 HTMLDOMChildrenCollectionEnum_Clone
202 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
204 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
207 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
209 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
211 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
213 if(IsEqualGUID(&IID_IUnknown, riid)) {
214 *ppv = &This->IHTMLDOMChildrenCollection_iface;
215 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
216 *ppv = &This->IHTMLDOMChildrenCollection_iface;
217 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
218 return *ppv ? S_OK : E_NOINTERFACE;
219 }else {
220 *ppv = NULL;
221 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
222 return E_NOINTERFACE;
225 IUnknown_AddRef((IUnknown*)*ppv);
226 return S_OK;
229 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
231 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
232 LONG ref = InterlockedIncrement(&This->ref);
234 TRACE("(%p) ref=%d\n", This, ref);
236 return ref;
239 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
241 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
242 LONG ref = InterlockedDecrement(&This->ref);
244 TRACE("(%p) ref=%d\n", This, ref);
246 if(!ref) {
247 htmldoc_release(&This->doc->basedoc);
248 nsIDOMNodeList_Release(This->nslist);
249 heap_free(This);
252 return ref;
255 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
257 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
258 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
261 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
262 LCID lcid, ITypeInfo **ppTInfo)
264 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
265 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
268 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
269 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
271 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
272 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
273 lcid, rgDispId);
276 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
277 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
278 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
280 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
281 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
282 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
285 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
287 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
288 UINT32 length=0;
290 TRACE("(%p)->(%p)\n", This, p);
292 nsIDOMNodeList_GetLength(This->nslist, &length);
293 *p = length;
294 return S_OK;
297 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
299 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
300 HTMLDOMChildrenCollectionEnum *ret;
302 TRACE("(%p)->(%p)\n", This, p);
304 ret = heap_alloc(sizeof(*ret));
305 if(!ret)
306 return E_OUTOFMEMORY;
308 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
309 ret->ref = 1;
310 ret->iter = 0;
312 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
313 ret->col = This;
315 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
316 return S_OK;
319 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
321 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
322 nsIDOMNode *nsnode = NULL;
323 HTMLDOMNode *node;
324 UINT32 length=0;
325 nsresult nsres;
326 HRESULT hres;
328 TRACE("(%p)->(%d %p)\n", This, index, ppItem);
330 if (ppItem)
331 *ppItem = NULL;
332 else
333 return E_POINTER;
335 nsIDOMNodeList_GetLength(This->nslist, &length);
336 if(index < 0 || index >= length)
337 return E_INVALIDARG;
339 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
340 if(NS_FAILED(nsres) || !nsnode) {
341 ERR("Item failed: %08x\n", nsres);
342 return E_FAIL;
345 hres = get_node(This->doc, nsnode, TRUE, &node);
346 if(FAILED(hres))
347 return hres;
349 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
350 return S_OK;
353 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
354 HTMLDOMChildrenCollection_QueryInterface,
355 HTMLDOMChildrenCollection_AddRef,
356 HTMLDOMChildrenCollection_Release,
357 HTMLDOMChildrenCollection_GetTypeInfoCount,
358 HTMLDOMChildrenCollection_GetTypeInfo,
359 HTMLDOMChildrenCollection_GetIDsOfNames,
360 HTMLDOMChildrenCollection_Invoke,
361 HTMLDOMChildrenCollection_get_length,
362 HTMLDOMChildrenCollection_get__newEnum,
363 HTMLDOMChildrenCollection_item
366 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
368 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
371 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
373 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
375 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
376 WCHAR *ptr;
377 DWORD idx=0;
378 UINT32 len = 0;
380 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
381 idx = idx*10 + (*ptr-'0');
382 if(*ptr)
383 return DISP_E_UNKNOWNNAME;
385 nsIDOMNodeList_GetLength(This->nslist, &len);
386 if(idx >= len)
387 return DISP_E_UNKNOWNNAME;
389 *dispid = DISPID_CHILDCOL_0 + idx;
390 TRACE("ret %x\n", *dispid);
391 return S_OK;
394 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
395 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
397 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
399 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
401 switch(flags) {
402 case DISPATCH_PROPERTYGET: {
403 IDispatch *disp = NULL;
404 HRESULT hres;
406 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
407 id - DISPID_CHILDCOL_0, &disp);
408 if(FAILED(hres))
409 return hres;
411 V_VT(res) = VT_DISPATCH;
412 V_DISPATCH(res) = disp;
413 break;
416 default:
417 FIXME("unimplemented flags %x\n", flags);
418 return E_NOTIMPL;
421 return S_OK;
424 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
425 NULL,
426 HTMLDOMChildrenCollection_get_dispid,
427 HTMLDOMChildrenCollection_invoke,
428 NULL
431 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
432 IHTMLDOMChildrenCollection_tid,
436 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
437 &HTMLDOMChildrenCollection_dispex_vtbl,
438 DispDOMChildrenCollection_tid,
439 HTMLDOMChildrenCollection_iface_tids
442 IHTMLDOMChildrenCollection *create_child_collection(HTMLDocumentNode *doc, nsIDOMNodeList *nslist)
444 HTMLDOMChildrenCollection *ret;
446 ret = heap_alloc_zero(sizeof(*ret));
447 if(!ret)
448 return NULL;
450 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
451 ret->ref = 1;
453 nsIDOMNodeList_AddRef(nslist);
454 ret->nslist = nslist;
456 htmldoc_addref(&doc->basedoc);
457 ret->doc = doc;
459 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface,
460 &HTMLDOMChildrenCollection_dispex);
462 return &ret->IHTMLDOMChildrenCollection_iface;
465 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
467 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
470 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
471 REFIID riid, void **ppv)
473 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
475 return This->vtbl->qi(This, riid, ppv);
478 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
480 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
481 LONG ref;
483 ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
485 TRACE("(%p) ref=%d\n", This, ref);
487 return ref;
490 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
492 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
493 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface, /*&node_ccp*/ NULL);
495 TRACE("(%p) ref=%d\n", This, ref);
497 return ref;
500 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
502 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
503 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
506 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
507 LCID lcid, ITypeInfo **ppTInfo)
509 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
510 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
513 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
514 LPOLESTR *rgszNames, UINT cNames,
515 LCID lcid, DISPID *rgDispId)
517 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
518 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
519 lcid, rgDispId);
522 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
523 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
524 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
526 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
527 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
528 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
531 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
533 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
534 UINT16 type = -1;
536 TRACE("(%p)->(%p)\n", This, p);
538 nsIDOMNode_GetNodeType(This->nsnode, &type);
540 switch(type) {
541 case ELEMENT_NODE:
542 *p = 1;
543 break;
544 case TEXT_NODE:
545 *p = 3;
546 break;
547 case COMMENT_NODE:
548 case DOCUMENT_TYPE_NODE:
549 *p = 8;
550 break;
551 case DOCUMENT_NODE:
552 *p = 9;
553 break;
554 case DOCUMENT_FRAGMENT_NODE:
555 *p = 11;
556 break;
557 default:
559 * FIXME:
560 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
561 * It needs more tests.
563 FIXME("type %u\n", type);
564 *p = 0;
567 return S_OK;
570 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
572 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
573 HTMLDOMNode *node;
574 nsIDOMNode *nsnode;
575 nsresult nsres;
576 HRESULT hres;
578 TRACE("(%p)->(%p)\n", This, p);
580 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
581 if(NS_FAILED(nsres)) {
582 ERR("GetParentNode failed: %08x\n", nsres);
583 return E_FAIL;
586 if(!nsnode) {
587 *p = NULL;
588 return S_OK;
591 hres = get_node(This->doc, nsnode, TRUE, &node);
592 nsIDOMNode_Release(nsnode);
593 if(FAILED(hres))
594 return hres;
596 *p = &node->IHTMLDOMNode_iface;
597 return S_OK;
600 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
602 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
603 cpp_bool has_child = FALSE;
604 nsresult nsres;
606 TRACE("(%p)->(%p)\n", This, fChildren);
608 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
609 if(NS_FAILED(nsres))
610 ERR("HasChildNodes failed: %08x\n", nsres);
612 *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE;
613 return S_OK;
616 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
618 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
619 nsIDOMNodeList *nslist;
620 nsresult nsres;
622 TRACE("(%p)->(%p)\n", This, p);
624 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
625 if(NS_FAILED(nsres)) {
626 ERR("GetChildNodes failed: %08x\n", nsres);
627 return E_FAIL;
630 *p = (IDispatch*)create_child_collection(This->doc, nslist);
631 nsIDOMNodeList_Release(nslist);
633 return *p ? S_OK : E_OUTOFMEMORY;
636 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
638 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
639 HTMLAttributeCollection *col;
640 HRESULT hres;
642 TRACE("(%p)->(%p)\n", This, p);
644 if(This->vtbl->get_attr_col) {
645 hres = This->vtbl->get_attr_col(This, &col);
646 if(FAILED(hres))
647 return hres;
649 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
650 return S_OK;
653 *p = NULL;
654 return S_OK;
657 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
658 VARIANT refChild, IHTMLDOMNode **node)
660 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
661 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
662 nsIDOMNode *nsnode;
663 nsresult nsres;
664 HRESULT hres = S_OK;
666 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
668 new_child = get_node_obj(newChild);
669 if(!new_child) {
670 ERR("invalid newChild\n");
671 return E_INVALIDARG;
674 switch(V_VT(&refChild)) {
675 case VT_NULL:
676 break;
677 case VT_DISPATCH: {
678 IHTMLDOMNode *ref_iface;
680 if(!V_DISPATCH(&refChild))
681 break;
683 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
684 if(FAILED(hres))
685 break;
687 ref_node = get_node_obj(ref_iface);
688 IHTMLDOMNode_Release(ref_iface);
689 if(!ref_node) {
690 ERR("unvalid node\n");
691 hres = E_FAIL;
692 break;
694 break;
696 default:
697 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
698 hres = E_NOTIMPL;
701 if(SUCCEEDED(hres)) {
702 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
703 if(NS_FAILED(nsres)) {
704 ERR("InsertBefore failed: %08x\n", nsres);
705 hres = E_FAIL;
708 node_release(new_child);
709 if(ref_node)
710 node_release(ref_node);
711 if(FAILED(hres))
712 return hres;
714 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
715 nsIDOMNode_Release(nsnode);
716 if(FAILED(hres))
717 return hres;
719 *node = &node_obj->IHTMLDOMNode_iface;
720 return S_OK;
723 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
724 IHTMLDOMNode **node)
726 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
727 HTMLDOMNode *node_obj;
728 nsIDOMNode *nsnode;
729 nsresult nsres;
730 HRESULT hres;
732 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
734 node_obj = get_node_obj(oldChild);
735 if(!node_obj)
736 return E_FAIL;
738 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
739 node_release(node_obj);
740 if(NS_FAILED(nsres)) {
741 ERR("RemoveChild failed: %08x\n", nsres);
742 return E_FAIL;
745 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
746 nsIDOMNode_Release(nsnode);
747 if(FAILED(hres))
748 return hres;
750 /* FIXME: Make sure that node != newChild */
751 *node = &node_obj->IHTMLDOMNode_iface;
752 return S_OK;
755 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
756 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
758 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
759 HTMLDOMNode *node_new, *node_old, *ret_node;
760 nsIDOMNode *nsnode;
761 nsresult nsres;
762 HRESULT hres;
764 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
766 node_new = get_node_obj(newChild);
767 if(!node_new)
768 return E_FAIL;
770 node_old = get_node_obj(oldChild);
771 if(!node_old) {
772 node_release(node_new);
773 return E_FAIL;
776 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
777 node_release(node_new);
778 node_release(node_old);
779 if(NS_FAILED(nsres))
780 return E_FAIL;
782 hres = get_node(This->doc, nsnode, TRUE, &ret_node);
783 nsIDOMNode_Release(nsnode);
784 if(FAILED(hres))
785 return hres;
787 *node = &ret_node->IHTMLDOMNode_iface;
788 return S_OK;
791 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
792 IHTMLDOMNode **clonedNode)
794 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
795 HTMLDOMNode *new_node;
796 nsIDOMNode *nsnode;
797 nsresult nsres;
798 HRESULT hres;
800 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
802 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
803 if(NS_FAILED(nsres) || !nsnode) {
804 ERR("CloneNode failed: %08x\n", nsres);
805 return E_FAIL;
808 hres = This->vtbl->clone(This, nsnode, &new_node);
809 if(FAILED(hres))
810 return hres;
812 *clonedNode = &new_node->IHTMLDOMNode_iface;
813 return S_OK;
816 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
817 IHTMLDOMNode **removed)
819 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
820 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
821 return E_NOTIMPL;
824 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
825 IHTMLDOMNode **swappedNode)
827 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
828 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
829 return E_NOTIMPL;
832 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
833 IHTMLDOMNode **replaced)
835 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
836 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
837 return E_NOTIMPL;
840 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
841 IHTMLDOMNode **node)
843 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
844 HTMLDOMNode *node_obj;
845 nsIDOMNode *nsnode;
846 nsresult nsres;
847 HRESULT hres;
849 TRACE("(%p)->(%p %p)\n", This, newChild, node);
851 node_obj = get_node_obj(newChild);
852 if(!node_obj)
853 return E_FAIL;
855 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
856 node_release(node_obj);
857 if(NS_FAILED(nsres)) {
858 ERR("AppendChild failed: %08x\n", nsres);
859 return E_FAIL;
862 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
863 nsIDOMNode_Release(nsnode);
864 if(FAILED(hres))
865 return hres;
867 /* FIXME: Make sure that node != newChild */
868 *node = &node_obj->IHTMLDOMNode_iface;
869 return S_OK;
872 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
874 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
875 nsAString name;
876 nsresult nsres;
878 TRACE("(%p)->(%p)\n", This, p);
880 nsAString_Init(&name, NULL);
881 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
882 return return_nsstr(nsres, &name, p);
885 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
887 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
889 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
891 switch(V_VT(&v)) {
892 case VT_BSTR: {
893 nsAString val_str;
895 nsAString_InitDepend(&val_str, V_BSTR(&v));
896 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
897 nsAString_Finish(&val_str);
899 return S_OK;
902 default:
903 FIXME("unsupported value %s\n", debugstr_variant(&v));
906 return E_NOTIMPL;
909 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
911 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
912 const PRUnichar *val;
913 nsAString val_str;
915 TRACE("(%p)->(%p)\n", This, p);
917 nsAString_Init(&val_str, NULL);
918 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
919 nsAString_GetData(&val_str, &val);
921 if(*val) {
922 V_VT(p) = VT_BSTR;
923 V_BSTR(p) = SysAllocString(val);
924 }else {
925 V_VT(p) = VT_NULL;
928 nsAString_Finish(&val_str);
930 return S_OK;
933 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
935 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
936 nsIDOMNode *nschild = NULL;
937 HTMLDOMNode *node;
938 HRESULT hres;
940 TRACE("(%p)->(%p)\n", This, p);
942 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
943 if(!nschild) {
944 *p = NULL;
945 return S_OK;
948 hres = get_node(This->doc, nschild, TRUE, &node);
949 nsIDOMNode_Release(nschild);
950 if(FAILED(hres))
951 return hres;
953 *p = &node->IHTMLDOMNode_iface;
954 return S_OK;
957 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
959 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
960 nsIDOMNode *nschild = NULL;
961 HTMLDOMNode *node;
962 HRESULT hres;
964 TRACE("(%p)->(%p)\n", This, p);
966 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
967 if(!nschild) {
968 *p = NULL;
969 return S_OK;
972 hres = get_node(This->doc, nschild, TRUE, &node);
973 nsIDOMNode_Release(nschild);
974 if(FAILED(hres))
975 return hres;
977 *p = &node->IHTMLDOMNode_iface;
978 return S_OK;
981 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
983 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
984 nsIDOMNode *nschild = NULL;
985 HTMLDOMNode *node;
986 HRESULT hres;
988 TRACE("(%p)->(%p)\n", This, p);
990 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
991 if(!nschild) {
992 *p = NULL;
993 return S_OK;
996 hres = get_node(This->doc, nschild, TRUE, &node);
997 nsIDOMNode_Release(nschild);
998 if(FAILED(hres))
999 return hres;
1001 *p = &node->IHTMLDOMNode_iface;
1002 return S_OK;
1005 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1007 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1008 nsIDOMNode *nssibling = NULL;
1009 HTMLDOMNode *node;
1010 HRESULT hres;
1012 TRACE("(%p)->(%p)\n", This, p);
1014 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1015 if(!nssibling) {
1016 *p = NULL;
1017 return S_OK;
1020 hres = get_node(This->doc, nssibling, TRUE, &node);
1021 nsIDOMNode_Release(nssibling);
1022 if(FAILED(hres))
1023 return hres;
1025 *p = &node->IHTMLDOMNode_iface;
1026 return S_OK;
1029 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1030 HTMLDOMNode_QueryInterface,
1031 HTMLDOMNode_AddRef,
1032 HTMLDOMNode_Release,
1033 HTMLDOMNode_GetTypeInfoCount,
1034 HTMLDOMNode_GetTypeInfo,
1035 HTMLDOMNode_GetIDsOfNames,
1036 HTMLDOMNode_Invoke,
1037 HTMLDOMNode_get_nodeType,
1038 HTMLDOMNode_get_parentNode,
1039 HTMLDOMNode_hasChildNodes,
1040 HTMLDOMNode_get_childNodes,
1041 HTMLDOMNode_get_attributes,
1042 HTMLDOMNode_insertBefore,
1043 HTMLDOMNode_removeChild,
1044 HTMLDOMNode_replaceChild,
1045 HTMLDOMNode_cloneNode,
1046 HTMLDOMNode_removeNode,
1047 HTMLDOMNode_swapNode,
1048 HTMLDOMNode_replaceNode,
1049 HTMLDOMNode_appendChild,
1050 HTMLDOMNode_get_nodeName,
1051 HTMLDOMNode_put_nodeValue,
1052 HTMLDOMNode_get_nodeValue,
1053 HTMLDOMNode_get_firstChild,
1054 HTMLDOMNode_get_lastChild,
1055 HTMLDOMNode_get_previousSibling,
1056 HTMLDOMNode_get_nextSibling
1059 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1061 HTMLDOMNode *ret;
1063 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1064 return NULL;
1066 ret = impl_from_IHTMLDOMNode(iface);
1067 node_addref(ret);
1068 return ret;
1071 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1073 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1076 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1077 REFIID riid, void **ppv)
1079 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1081 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1084 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1086 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1088 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1091 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1093 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1095 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1098 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1100 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1101 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1104 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1105 LCID lcid, ITypeInfo **ppTInfo)
1107 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1108 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1111 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1112 LPOLESTR *rgszNames, UINT cNames,
1113 LCID lcid, DISPID *rgDispId)
1115 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1116 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1117 lcid, rgDispId);
1120 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1121 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1122 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1124 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1125 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1126 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1129 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1131 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1133 TRACE("(%p)->(%p)\n", This, p);
1135 /* FIXME: Better check for document node */
1136 if(This == &This->doc->node) {
1137 *p = NULL;
1138 }else {
1139 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
1140 IDispatch_AddRef(*p);
1142 return S_OK;
1145 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1146 HTMLDOMNode2_QueryInterface,
1147 HTMLDOMNode2_AddRef,
1148 HTMLDOMNode2_Release,
1149 HTMLDOMNode2_GetTypeInfoCount,
1150 HTMLDOMNode2_GetTypeInfo,
1151 HTMLDOMNode2_GetIDsOfNames,
1152 HTMLDOMNode2_Invoke,
1153 HTMLDOMNode2_get_ownerDocument
1156 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1158 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1160 if(IsEqualGUID(&IID_IUnknown, riid)) {
1161 *ppv = &This->IHTMLDOMNode_iface;
1162 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1163 *ppv = &This->IHTMLDOMNode_iface;
1164 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1165 *ppv = &This->IHTMLDOMNode_iface;
1166 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1167 *ppv = &This->IHTMLDOMNode2_iface;
1168 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1169 *ppv = &node_ccp;
1170 return S_OK;
1171 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1172 *ppv = &This->IHTMLDOMNode_iface;
1173 return S_OK;
1174 }else if(dispex_query_interface(&This->event_target.dispex, riid, ppv)) {
1175 return *ppv ? S_OK : E_NOINTERFACE;
1176 }else {
1177 *ppv = NULL;
1178 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1179 return E_NOINTERFACE;
1182 IUnknown_AddRef((IUnknown*)*ppv);
1183 return S_OK;
1186 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1188 if(This->nsnode)
1189 nsIDOMNode_Release(This->nsnode);
1190 if(This->doc && &This->doc->node != This)
1191 htmldoc_release(&This->doc->basedoc);
1192 if(This->event_target.ptr)
1193 release_event_target(This->event_target.ptr);
1196 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1198 return create_node(This->doc, nsnode, ret);
1201 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1203 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1204 HTMLDOMNode_QI,
1205 HTMLDOMNode_destructor,
1206 HTMLDOMNode_cpc,
1207 HTMLDOMNode_clone
1210 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode)
1212 nsresult nsres;
1214 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1215 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1217 ccref_init(&node->ccref, 1);
1219 if(&doc->node != node)
1220 htmldoc_addref(&doc->basedoc);
1221 node->doc = doc;
1223 nsIDOMNode_AddRef(nsnode);
1224 node->nsnode = nsnode;
1226 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1227 assert(nsres == NS_OK);
1230 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1232 UINT16 node_type;
1233 HRESULT hres;
1235 nsIDOMNode_GetNodeType(nsnode, &node_type);
1237 switch(node_type) {
1238 case ELEMENT_NODE: {
1239 HTMLElement *elem;
1240 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1241 if(FAILED(hres))
1242 return hres;
1243 *ret = &elem->node;
1244 break;
1246 case TEXT_NODE:
1247 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1248 if(FAILED(hres))
1249 return hres;
1250 break;
1251 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1252 case DOCUMENT_TYPE_NODE:
1253 case COMMENT_NODE: {
1254 HTMLElement *comment;
1255 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1256 if(FAILED(hres))
1257 return hres;
1258 *ret = &comment->node;
1259 break;
1261 case ATTRIBUTE_NODE:
1262 ERR("Called on attribute node\n");
1263 return E_UNEXPECTED;
1264 default: {
1265 HTMLDOMNode *node;
1267 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1268 if(!node)
1269 return E_OUTOFMEMORY;
1271 node->vtbl = &HTMLDOMNodeImplVtbl;
1272 HTMLDOMNode_Init(doc, node, nsnode);
1273 *ret = node;
1277 TRACE("type %d ret %p\n", node_type, *ret);
1278 return S_OK;
1281 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1283 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1285 TRACE("%p\n", This);
1287 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1289 if(This->nsnode)
1290 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1291 if(This->doc && &This->doc->node != This)
1292 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1293 dispex_traverse(&This->event_target.dispex, cb);
1295 if(This->vtbl->traverse)
1296 This->vtbl->traverse(This, cb);
1298 return NS_OK;
1301 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1303 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1305 TRACE("%p\n", This);
1307 if(This->vtbl->unlink)
1308 This->vtbl->unlink(This);
1310 dispex_unlink(&This->event_target.dispex);
1312 if(This->nsnode) {
1313 nsIDOMNode *nsnode = This->nsnode;
1314 This->nsnode = NULL;
1315 nsIDOMNode_Release(nsnode);
1318 if(This->doc && &This->doc->node != This) {
1319 HTMLDocument *doc = &This->doc->basedoc;
1320 This->doc = NULL;
1321 htmldoc_release(doc);
1322 }else {
1323 This->doc = NULL;
1326 return NS_OK;
1329 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p)
1331 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1333 TRACE("(%p)\n", This);
1335 if(This->vtbl->unlink)
1336 This->vtbl->unlink(This);
1337 This->vtbl->destructor(This);
1338 release_dispex(&This->event_target.dispex);
1339 heap_free(This);
1342 void init_node_cc(void)
1344 static const CCObjCallback node_ccp_callback = {
1345 HTMLDOMNode_traverse,
1346 HTMLDOMNode_unlink,
1347 HTMLDOMNode_delete_cycle_collectable
1350 ccp_init(&node_ccp, &node_ccp_callback);
1353 HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1355 nsISupports *unk = NULL;
1356 nsresult nsres;
1358 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1359 assert(nsres == NS_OK);
1361 if(unk) {
1362 *ret = get_node_obj((IHTMLDOMNode*)unk);
1363 nsISupports_Release(unk);
1364 return NS_OK;
1367 if(!create) {
1368 *ret = NULL;
1369 return S_OK;
1372 return create_node(This, nsnode, ret);