maintainers: Update the Direct3D section.
[wine.git] / dlls / mshtml / htmlnode.c
blob13f178fc33b0eef6d67838950302159de3cf8751
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>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
36 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
38 static ExternalCycleCollectionParticipant node_ccp;
40 typedef struct {
41 DispatchEx dispex;
42 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
44 LONG ref;
46 nsIDOMNodeList *nslist;
47 } HTMLDOMChildrenCollection;
49 typedef struct {
50 IEnumVARIANT IEnumVARIANT_iface;
52 LONG ref;
54 ULONG iter;
55 HTMLDOMChildrenCollection *col;
56 } HTMLDOMChildrenCollectionEnum;
58 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
60 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
63 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
65 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
67 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
69 if(IsEqualGUID(riid, &IID_IUnknown)) {
70 *ppv = &This->IEnumVARIANT_iface;
71 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
72 *ppv = &This->IEnumVARIANT_iface;
73 }else {
74 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
75 *ppv = NULL;
76 return E_NOINTERFACE;
79 IUnknown_AddRef((IUnknown*)*ppv);
80 return S_OK;
83 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
85 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
86 LONG ref = InterlockedIncrement(&This->ref);
88 TRACE("(%p) ref=%ld\n", This, ref);
90 return ref;
93 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
95 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
96 LONG ref = InterlockedDecrement(&This->ref);
98 TRACE("(%p) ref=%ld\n", This, ref);
100 if(!ref) {
101 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
102 heap_free(This);
105 return ref;
108 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
110 UINT32 len;
111 nsresult nsres;
113 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
114 assert(nsres == NS_OK);
115 return len;
118 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
120 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
121 ULONG fetched = 0, len;
122 nsIDOMNode *nsnode;
123 HTMLDOMNode *node;
124 nsresult nsres;
125 HRESULT hres;
127 TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched);
129 len = get_enum_len(This);
131 while(This->iter+fetched < len && fetched < celt) {
132 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
133 assert(nsres == NS_OK);
135 hres = get_node(nsnode, TRUE, &node);
136 nsIDOMNode_Release(nsnode);
137 if(FAILED(hres)) {
138 ERR("get_node failed: %08lx\n", hres);
139 break;
142 V_VT(rgVar+fetched) = VT_DISPATCH;
143 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
144 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
145 fetched++;
148 This->iter += fetched;
149 if(pCeltFetched)
150 *pCeltFetched = fetched;
151 return fetched == celt ? S_OK : S_FALSE;
154 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
156 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
157 ULONG len;
159 TRACE("(%p)->(%ld)\n", This, celt);
161 len = get_enum_len(This);
162 if(This->iter + celt > len) {
163 This->iter = len;
164 return S_FALSE;
167 This->iter += celt;
168 return S_OK;
171 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
173 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
175 TRACE("(%p)->()\n", This);
177 This->iter = 0;
178 return S_OK;
181 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
183 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
184 FIXME("(%p)->(%p)\n", This, ppEnum);
185 return E_NOTIMPL;
188 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
189 HTMLDOMChildrenCollectionEnum_QueryInterface,
190 HTMLDOMChildrenCollectionEnum_AddRef,
191 HTMLDOMChildrenCollectionEnum_Release,
192 HTMLDOMChildrenCollectionEnum_Next,
193 HTMLDOMChildrenCollectionEnum_Skip,
194 HTMLDOMChildrenCollectionEnum_Reset,
195 HTMLDOMChildrenCollectionEnum_Clone
198 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
200 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
203 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
205 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
207 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
209 if(IsEqualGUID(&IID_IUnknown, riid)) {
210 *ppv = &This->IHTMLDOMChildrenCollection_iface;
211 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
212 *ppv = &This->IHTMLDOMChildrenCollection_iface;
213 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
214 return *ppv ? S_OK : E_NOINTERFACE;
215 }else {
216 *ppv = NULL;
217 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
218 return E_NOINTERFACE;
221 IUnknown_AddRef((IUnknown*)*ppv);
222 return S_OK;
225 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
227 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
228 LONG ref = InterlockedIncrement(&This->ref);
230 TRACE("(%p) ref=%ld\n", This, ref);
232 return ref;
235 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
237 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
238 LONG ref = InterlockedDecrement(&This->ref);
240 TRACE("(%p) ref=%ld\n", This, ref);
242 if(!ref) {
243 nsIDOMNodeList_Release(This->nslist);
244 heap_free(This);
247 return ref;
250 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
252 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
253 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
256 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
257 LCID lcid, ITypeInfo **ppTInfo)
259 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
260 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
263 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
264 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
266 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
267 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
268 lcid, rgDispId);
271 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
272 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
273 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
275 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
276 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
277 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
280 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
282 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
283 UINT32 length=0;
285 TRACE("(%p)->(%p)\n", This, p);
287 nsIDOMNodeList_GetLength(This->nslist, &length);
288 *p = length;
289 return S_OK;
292 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
294 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
295 HTMLDOMChildrenCollectionEnum *ret;
297 TRACE("(%p)->(%p)\n", This, p);
299 ret = heap_alloc(sizeof(*ret));
300 if(!ret)
301 return E_OUTOFMEMORY;
303 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
304 ret->ref = 1;
305 ret->iter = 0;
307 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
308 ret->col = This;
310 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
311 return S_OK;
314 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
316 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
317 nsIDOMNode *nsnode = NULL;
318 HTMLDOMNode *node;
319 UINT32 length=0;
320 nsresult nsres;
321 HRESULT hres;
323 TRACE("(%p)->(%ld %p)\n", This, index, ppItem);
325 if (ppItem)
326 *ppItem = NULL;
327 else
328 return E_POINTER;
330 nsIDOMNodeList_GetLength(This->nslist, &length);
331 if(index < 0 || index >= length)
332 return E_INVALIDARG;
334 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
335 if(NS_FAILED(nsres) || !nsnode) {
336 ERR("Item failed: %08lx\n", nsres);
337 return E_FAIL;
340 hres = get_node(nsnode, TRUE, &node);
341 if(FAILED(hres))
342 return hres;
344 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
345 return S_OK;
348 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
349 HTMLDOMChildrenCollection_QueryInterface,
350 HTMLDOMChildrenCollection_AddRef,
351 HTMLDOMChildrenCollection_Release,
352 HTMLDOMChildrenCollection_GetTypeInfoCount,
353 HTMLDOMChildrenCollection_GetTypeInfo,
354 HTMLDOMChildrenCollection_GetIDsOfNames,
355 HTMLDOMChildrenCollection_Invoke,
356 HTMLDOMChildrenCollection_get_length,
357 HTMLDOMChildrenCollection_get__newEnum,
358 HTMLDOMChildrenCollection_item
361 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
363 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
366 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
368 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
370 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
371 WCHAR *ptr;
372 DWORD idx=0;
373 UINT32 len = 0;
375 for(ptr = name; *ptr && is_digit(*ptr); ptr++)
376 idx = idx*10 + (*ptr-'0');
377 if(*ptr)
378 return DISP_E_UNKNOWNNAME;
380 nsIDOMNodeList_GetLength(This->nslist, &len);
381 if(idx >= len)
382 return DISP_E_UNKNOWNNAME;
384 *dispid = DISPID_CHILDCOL_0 + idx;
385 TRACE("ret %lx\n", *dispid);
386 return S_OK;
389 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
390 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
392 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
394 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
396 switch(flags) {
397 case DISPATCH_PROPERTYGET: {
398 IDispatch *disp = NULL;
399 HRESULT hres;
401 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
402 id - DISPID_CHILDCOL_0, &disp);
403 if(FAILED(hres))
404 return hres;
406 V_VT(res) = VT_DISPATCH;
407 V_DISPATCH(res) = disp;
408 break;
411 default:
412 FIXME("unimplemented flags %x\n", flags);
413 return E_NOTIMPL;
416 return S_OK;
419 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
420 NULL,
421 HTMLDOMChildrenCollection_get_dispid,
422 HTMLDOMChildrenCollection_invoke,
423 NULL
426 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
427 IHTMLDOMChildrenCollection_tid,
431 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
432 L"NodeList",
433 &HTMLDOMChildrenCollection_dispex_vtbl,
434 DispDOMChildrenCollection_tid,
435 HTMLDOMChildrenCollection_iface_tids,
436 HTMLDOMNode_init_dispex_info
439 HRESULT create_child_collection(nsIDOMNodeList *nslist, compat_mode_t compat_mode, IHTMLDOMChildrenCollection **ret)
441 HTMLDOMChildrenCollection *collection;
443 if(!(collection = heap_alloc_zero(sizeof(*collection))))
444 return E_OUTOFMEMORY;
446 collection->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
447 collection->ref = 1;
449 nsIDOMNodeList_AddRef(nslist);
450 collection->nslist = nslist;
452 init_dispatch(&collection->dispex, (IUnknown*)&collection->IHTMLDOMChildrenCollection_iface,
453 &HTMLDOMChildrenCollection_dispex, compat_mode);
455 *ret = &collection->IHTMLDOMChildrenCollection_iface;
456 return S_OK;
459 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
461 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
464 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
465 REFIID riid, void **ppv)
467 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
469 return This->vtbl->qi(This, riid, ppv);
472 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
474 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
475 LONG ref;
477 ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
479 TRACE("(%p) ref=%ld\n", This, ref);
481 return ref;
484 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
486 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
487 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface, /*&node_ccp*/ NULL);
489 TRACE("(%p) ref=%ld\n", This, ref);
491 return ref;
494 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
496 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
497 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
500 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
501 LCID lcid, ITypeInfo **ppTInfo)
503 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
504 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
507 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
508 LPOLESTR *rgszNames, UINT cNames,
509 LCID lcid, DISPID *rgDispId)
511 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
512 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
513 lcid, rgDispId);
516 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
517 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
518 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
520 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
521 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
522 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
525 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
527 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
528 UINT16 type = -1;
530 TRACE("(%p)->(%p)\n", This, p);
532 nsIDOMNode_GetNodeType(This->nsnode, &type);
534 switch(type) {
535 case ELEMENT_NODE:
536 *p = 1;
537 break;
538 case TEXT_NODE:
539 *p = 3;
540 break;
541 case COMMENT_NODE:
542 case DOCUMENT_TYPE_NODE:
543 *p = 8;
544 break;
545 case DOCUMENT_NODE:
546 *p = 9;
547 break;
548 case DOCUMENT_FRAGMENT_NODE:
549 *p = 11;
550 break;
551 default:
553 * FIXME:
554 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
555 * It needs more tests.
557 FIXME("type %u\n", type);
558 *p = 0;
561 return S_OK;
564 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
566 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
567 HTMLDOMNode *node;
568 nsIDOMNode *nsnode;
569 nsresult nsres;
570 HRESULT hres;
572 TRACE("(%p)->(%p)\n", This, p);
574 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
575 if(NS_FAILED(nsres)) {
576 ERR("GetParentNode failed: %08lx\n", nsres);
577 return E_FAIL;
580 if(!nsnode) {
581 *p = NULL;
582 return S_OK;
585 hres = get_node(nsnode, TRUE, &node);
586 nsIDOMNode_Release(nsnode);
587 if(FAILED(hres))
588 return hres;
590 *p = &node->IHTMLDOMNode_iface;
591 return S_OK;
594 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
596 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
597 cpp_bool has_child = FALSE;
598 nsresult nsres;
600 TRACE("(%p)->(%p)\n", This, fChildren);
602 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
603 if(NS_FAILED(nsres))
604 ERR("HasChildNodes failed: %08lx\n", nsres);
606 *fChildren = variant_bool(has_child);
607 return S_OK;
610 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
612 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
613 nsIDOMNodeList *nslist;
614 HRESULT hres;
616 TRACE("(%p)->(%p)\n", This, p);
618 hres = map_nsresult(nsIDOMNode_GetChildNodes(This->nsnode, &nslist));
619 if(FAILED(hres)) {
620 ERR("GetChildNodes failed: %08lx\n", hres);
621 return hres;
624 hres = create_child_collection(nslist, dispex_compat_mode(&This->event_target.dispex),
625 (IHTMLDOMChildrenCollection**)p);
626 nsIDOMNodeList_Release(nslist);
627 return hres;
630 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
632 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
633 HTMLAttributeCollection *col;
634 HRESULT hres;
636 TRACE("(%p)->(%p)\n", This, p);
638 if(This->vtbl->get_attr_col) {
639 hres = This->vtbl->get_attr_col(This, &col);
640 if(FAILED(hres))
641 return hres;
643 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
644 return S_OK;
647 *p = NULL;
648 return S_OK;
651 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
652 VARIANT refChild, IHTMLDOMNode **node)
654 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
655 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
656 nsIDOMNode *nsnode;
657 nsresult nsres;
658 HRESULT hres = S_OK;
660 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
662 new_child = get_node_obj(newChild);
663 if(!new_child) {
664 ERR("invalid newChild\n");
665 return E_INVALIDARG;
668 switch(V_VT(&refChild)) {
669 case VT_NULL:
670 break;
671 case VT_DISPATCH: {
672 IHTMLDOMNode *ref_iface;
674 if(!V_DISPATCH(&refChild))
675 break;
677 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
678 if(FAILED(hres))
679 break;
681 ref_node = get_node_obj(ref_iface);
682 IHTMLDOMNode_Release(ref_iface);
683 if(!ref_node) {
684 ERR("unvalid node\n");
685 hres = E_FAIL;
686 break;
688 break;
690 default:
691 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
692 hres = E_NOTIMPL;
695 if(SUCCEEDED(hres)) {
696 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
697 if(NS_FAILED(nsres)) {
698 ERR("InsertBefore failed: %08lx\n", nsres);
699 hres = E_FAIL;
702 node_release(new_child);
703 if(ref_node)
704 node_release(ref_node);
705 if(FAILED(hres))
706 return hres;
708 hres = get_node(nsnode, TRUE, &node_obj);
709 nsIDOMNode_Release(nsnode);
710 if(FAILED(hres))
711 return hres;
713 *node = &node_obj->IHTMLDOMNode_iface;
714 return S_OK;
717 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
718 IHTMLDOMNode **node)
720 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
721 HTMLDOMNode *node_obj;
722 nsIDOMNode *nsnode;
723 nsresult nsres;
724 HRESULT hres;
726 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
728 node_obj = get_node_obj(oldChild);
729 if(!node_obj)
730 return E_FAIL;
732 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
733 node_release(node_obj);
734 if(NS_FAILED(nsres)) {
735 ERR("RemoveChild failed: %08lx\n", nsres);
736 return E_FAIL;
739 hres = get_node(nsnode, TRUE, &node_obj);
740 nsIDOMNode_Release(nsnode);
741 if(FAILED(hres))
742 return hres;
744 /* FIXME: Make sure that node != newChild */
745 *node = &node_obj->IHTMLDOMNode_iface;
746 return S_OK;
749 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
750 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
752 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
753 HTMLDOMNode *node_new, *node_old, *ret_node;
754 nsIDOMNode *nsnode;
755 nsresult nsres;
756 HRESULT hres;
758 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
760 node_new = get_node_obj(newChild);
761 if(!node_new)
762 return E_FAIL;
764 node_old = get_node_obj(oldChild);
765 if(!node_old) {
766 node_release(node_new);
767 return E_FAIL;
770 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
771 node_release(node_new);
772 node_release(node_old);
773 if(NS_FAILED(nsres))
774 return E_FAIL;
776 hres = get_node(nsnode, TRUE, &ret_node);
777 nsIDOMNode_Release(nsnode);
778 if(FAILED(hres))
779 return hres;
781 *node = &ret_node->IHTMLDOMNode_iface;
782 return S_OK;
785 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
786 IHTMLDOMNode **clonedNode)
788 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
789 HTMLDOMNode *new_node;
790 nsIDOMNode *nsnode;
791 nsresult nsres;
792 HRESULT hres;
794 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
796 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
797 if(NS_FAILED(nsres) || !nsnode) {
798 ERR("CloneNode failed: %08lx\n", nsres);
799 return E_FAIL;
802 hres = This->vtbl->clone(This, nsnode, &new_node);
803 nsIDOMNode_Release(nsnode);
804 if(FAILED(hres))
805 return hres;
807 *clonedNode = &new_node->IHTMLDOMNode_iface;
808 return S_OK;
811 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
812 IHTMLDOMNode **removed)
814 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
815 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
816 return E_NOTIMPL;
819 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
820 IHTMLDOMNode **swappedNode)
822 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
823 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
824 return E_NOTIMPL;
827 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
828 IHTMLDOMNode **replaced)
830 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
831 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
832 return E_NOTIMPL;
835 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
836 IHTMLDOMNode **node)
838 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
839 HTMLDOMNode *node_obj;
840 nsIDOMNode *nsnode;
841 nsresult nsres;
842 HRESULT hres;
844 TRACE("(%p)->(%p %p)\n", This, newChild, node);
846 node_obj = get_node_obj(newChild);
847 if(!node_obj)
848 return E_FAIL;
850 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
851 node_release(node_obj);
852 if(NS_FAILED(nsres)) {
853 ERR("AppendChild failed: %08lx\n", nsres);
854 return E_FAIL;
857 hres = get_node(nsnode, TRUE, &node_obj);
858 nsIDOMNode_Release(nsnode);
859 if(FAILED(hres))
860 return hres;
862 /* FIXME: Make sure that node != newChild */
863 *node = &node_obj->IHTMLDOMNode_iface;
864 return S_OK;
867 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
869 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
870 nsAString name;
871 nsresult nsres;
873 TRACE("(%p)->(%p)\n", This, p);
875 nsAString_Init(&name, NULL);
876 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
877 return return_nsstr(nsres, &name, p);
880 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
882 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
884 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
886 switch(V_VT(&v)) {
887 case VT_BSTR: {
888 nsAString val_str;
890 nsAString_InitDepend(&val_str, V_BSTR(&v));
891 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
892 nsAString_Finish(&val_str);
894 return S_OK;
897 default:
898 FIXME("unsupported value %s\n", debugstr_variant(&v));
901 return E_NOTIMPL;
904 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
906 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
907 const PRUnichar *val;
908 nsAString val_str;
910 TRACE("(%p)->(%p)\n", This, p);
912 nsAString_Init(&val_str, NULL);
913 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
914 nsAString_GetData(&val_str, &val);
916 if(*val) {
917 V_VT(p) = VT_BSTR;
918 V_BSTR(p) = SysAllocString(val);
919 }else {
920 V_VT(p) = VT_NULL;
923 nsAString_Finish(&val_str);
925 return S_OK;
928 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
930 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
931 nsIDOMNode *nschild = NULL;
932 HTMLDOMNode *node;
933 HRESULT hres;
935 TRACE("(%p)->(%p)\n", This, p);
937 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
938 if(!nschild) {
939 *p = NULL;
940 return S_OK;
943 hres = get_node(nschild, TRUE, &node);
944 nsIDOMNode_Release(nschild);
945 if(FAILED(hres))
946 return hres;
948 *p = &node->IHTMLDOMNode_iface;
949 return S_OK;
952 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
954 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
955 nsIDOMNode *nschild = NULL;
956 HTMLDOMNode *node;
957 HRESULT hres;
959 TRACE("(%p)->(%p)\n", This, p);
961 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
962 if(!nschild) {
963 *p = NULL;
964 return S_OK;
967 hres = get_node(nschild, TRUE, &node);
968 nsIDOMNode_Release(nschild);
969 if(FAILED(hres))
970 return hres;
972 *p = &node->IHTMLDOMNode_iface;
973 return S_OK;
976 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
978 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
979 nsIDOMNode *nschild = NULL;
980 HTMLDOMNode *node;
981 HRESULT hres;
983 TRACE("(%p)->(%p)\n", This, p);
985 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
986 if(!nschild) {
987 *p = NULL;
988 return S_OK;
991 hres = get_node(nschild, TRUE, &node);
992 nsIDOMNode_Release(nschild);
993 if(FAILED(hres))
994 return hres;
996 *p = &node->IHTMLDOMNode_iface;
997 return S_OK;
1000 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1002 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1003 nsIDOMNode *nssibling = NULL;
1004 HTMLDOMNode *node;
1005 HRESULT hres;
1007 TRACE("(%p)->(%p)\n", This, p);
1009 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1010 if(!nssibling) {
1011 *p = NULL;
1012 return S_OK;
1015 hres = get_node(nssibling, TRUE, &node);
1016 nsIDOMNode_Release(nssibling);
1017 if(FAILED(hres))
1018 return hres;
1020 *p = &node->IHTMLDOMNode_iface;
1021 return S_OK;
1024 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1025 HTMLDOMNode_QueryInterface,
1026 HTMLDOMNode_AddRef,
1027 HTMLDOMNode_Release,
1028 HTMLDOMNode_GetTypeInfoCount,
1029 HTMLDOMNode_GetTypeInfo,
1030 HTMLDOMNode_GetIDsOfNames,
1031 HTMLDOMNode_Invoke,
1032 HTMLDOMNode_get_nodeType,
1033 HTMLDOMNode_get_parentNode,
1034 HTMLDOMNode_hasChildNodes,
1035 HTMLDOMNode_get_childNodes,
1036 HTMLDOMNode_get_attributes,
1037 HTMLDOMNode_insertBefore,
1038 HTMLDOMNode_removeChild,
1039 HTMLDOMNode_replaceChild,
1040 HTMLDOMNode_cloneNode,
1041 HTMLDOMNode_removeNode,
1042 HTMLDOMNode_swapNode,
1043 HTMLDOMNode_replaceNode,
1044 HTMLDOMNode_appendChild,
1045 HTMLDOMNode_get_nodeName,
1046 HTMLDOMNode_put_nodeValue,
1047 HTMLDOMNode_get_nodeValue,
1048 HTMLDOMNode_get_firstChild,
1049 HTMLDOMNode_get_lastChild,
1050 HTMLDOMNode_get_previousSibling,
1051 HTMLDOMNode_get_nextSibling
1054 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1056 HTMLDOMNode *ret;
1058 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1059 return NULL;
1061 ret = impl_from_IHTMLDOMNode(iface);
1062 node_addref(ret);
1063 return ret;
1066 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1068 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1071 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1072 REFIID riid, void **ppv)
1074 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1076 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1079 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1081 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1083 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1086 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1088 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1090 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1093 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1095 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1096 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1099 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1100 LCID lcid, ITypeInfo **ppTInfo)
1102 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1103 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1106 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1107 LPOLESTR *rgszNames, UINT cNames,
1108 LCID lcid, DISPID *rgDispId)
1110 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1111 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1112 lcid, rgDispId);
1115 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1116 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1117 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1119 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1120 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1121 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1124 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1126 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1128 TRACE("(%p)->(%p)\n", This, p);
1130 /* FIXME: Better check for document node */
1131 if(This == &This->doc->node) {
1132 *p = NULL;
1133 }else {
1134 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
1135 IDispatch_AddRef(*p);
1137 return S_OK;
1140 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1141 HTMLDOMNode2_QueryInterface,
1142 HTMLDOMNode2_AddRef,
1143 HTMLDOMNode2_Release,
1144 HTMLDOMNode2_GetTypeInfoCount,
1145 HTMLDOMNode2_GetTypeInfo,
1146 HTMLDOMNode2_GetIDsOfNames,
1147 HTMLDOMNode2_Invoke,
1148 HTMLDOMNode2_get_ownerDocument
1151 static inline HTMLDOMNode *impl_from_IHTMLDOMNode3(IHTMLDOMNode3 *iface)
1153 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode3_iface);
1156 static HRESULT WINAPI HTMLDOMNode3_QueryInterface(IHTMLDOMNode3 *iface, REFIID riid, void **ppv)
1158 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1159 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1162 static ULONG WINAPI HTMLDOMNode3_AddRef(IHTMLDOMNode3 *iface)
1164 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1166 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1169 static ULONG WINAPI HTMLDOMNode3_Release(IHTMLDOMNode3 *iface)
1171 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1173 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1176 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfoCount(IHTMLDOMNode3 *iface, UINT *pctinfo)
1178 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1179 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1182 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfo(IHTMLDOMNode3 *iface, UINT iTInfo,
1183 LCID lcid, ITypeInfo **ppTInfo)
1185 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1186 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1189 static HRESULT WINAPI HTMLDOMNode3_GetIDsOfNames(IHTMLDOMNode3 *iface, REFIID riid,
1190 LPOLESTR *rgszNames, UINT cNames,
1191 LCID lcid, DISPID *rgDispId)
1193 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1194 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1195 lcid, rgDispId);
1198 static HRESULT WINAPI HTMLDOMNode3_Invoke(IHTMLDOMNode3 *iface, DISPID dispIdMember,
1199 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1200 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1202 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1203 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1204 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1207 static HRESULT WINAPI HTMLDOMNode3_put_prefix(IHTMLDOMNode3 *iface, VARIANT v)
1209 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1210 FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1211 return E_NOTIMPL;
1214 static HRESULT WINAPI HTMLDOMNode3_get_prefix(IHTMLDOMNode3 *iface, VARIANT *p)
1216 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1217 FIXME("(%p)->(%p)\n", This, p);
1218 return E_NOTIMPL;
1221 static HRESULT WINAPI HTMLDOMNode3_get_localName(IHTMLDOMNode3 *iface, VARIANT *p)
1223 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1224 FIXME("(%p)->(%p)\n", This, p);
1225 return E_NOTIMPL;
1228 static HRESULT WINAPI HTMLDOMNode3_get_namespaceURI(IHTMLDOMNode3 *iface, VARIANT *p)
1230 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1231 nsAString nsstr;
1232 nsresult nsres;
1234 TRACE("(%p)->(%p)\n", This, p);
1236 nsAString_InitDepend(&nsstr, NULL);
1237 nsres = nsIDOMNode_GetNamespaceURI(This->nsnode, &nsstr);
1238 return return_nsstr_variant(nsres, &nsstr, 0, p);
1241 static HRESULT WINAPI HTMLDOMNode3_put_textContent(IHTMLDOMNode3 *iface, VARIANT v)
1243 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1244 nsAString nsstr;
1245 nsresult nsres;
1247 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1249 variant_to_nsstr(&v, FALSE, &nsstr);
1250 nsres = nsIDOMNode_SetTextContent(This->nsnode, &nsstr);
1251 nsAString_Finish(&nsstr);
1252 if(NS_FAILED(nsres)) {
1253 ERR("SetTextContent failed: %08lx\n", nsres);
1254 return E_FAIL;
1257 return S_OK;
1260 static HRESULT WINAPI HTMLDOMNode3_get_textContent(IHTMLDOMNode3 *iface, VARIANT *p)
1262 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1263 nsAString nsstr;
1264 nsresult nsres;
1266 TRACE("(%p)->(%p)\n", This, p);
1268 nsAString_Init(&nsstr, NULL);
1269 nsres = nsIDOMNode_GetTextContent(This->nsnode, &nsstr);
1270 return return_nsstr_variant(nsres, &nsstr, 0, p);
1273 static HRESULT WINAPI HTMLDOMNode3_isEqualNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isEqual)
1275 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1276 FIXME("(%p)->()\n", This);
1277 return E_NOTIMPL;
1280 static HRESULT WINAPI HTMLDOMNode3_lookupNamespaceURI(IHTMLDOMNode3 *iface, VARIANT *prefix, VARIANT *namespaceURI)
1282 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1283 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(prefix), namespaceURI);
1284 return E_NOTIMPL;
1287 static HRESULT WINAPI HTMLDOMNode3_lookupPrefix(IHTMLDOMNode3 *iface, VARIANT *namespaceURI, VARIANT *prefix)
1289 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1290 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(namespaceURI), prefix);
1291 return E_NOTIMPL;
1294 static HRESULT WINAPI HTMLDOMNode3_isDefaultNamespace(IHTMLDOMNode3 *iface, VARIANT *namespace, VARIANT_BOOL *pfDefaultNamespace)
1296 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1297 FIXME("(%p)->()\n", This);
1298 return E_NOTIMPL;
1301 static HRESULT WINAPI HTMLDOMNode3_appendChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode **node)
1303 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1304 TRACE("(%p)->()\n", This);
1305 return IHTMLDOMNode_appendChild(&This->IHTMLDOMNode_iface, newChild, node);
1308 static HRESULT WINAPI HTMLDOMNode3_insertBefore(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, VARIANT refChild, IHTMLDOMNode **node)
1310 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1311 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
1312 return IHTMLDOMNode_insertBefore(&This->IHTMLDOMNode_iface, newChild, refChild, node);
1315 static HRESULT WINAPI HTMLDOMNode3_removeChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1317 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1318 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
1319 return IHTMLDOMNode_removeChild(&This->IHTMLDOMNode_iface, oldChild, node);
1322 static HRESULT WINAPI HTMLDOMNode3_replaceChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1324 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1325 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
1326 return IHTMLDOMNode_replaceChild(&This->IHTMLDOMNode_iface, newChild, oldChild, node);
1329 static HRESULT WINAPI HTMLDOMNode3_isSameNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isSame)
1331 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1332 FIXME("(%p)->()\n", This);
1333 return E_NOTIMPL;
1336 static HRESULT WINAPI HTMLDOMNode3_compareDocumentPosition(IHTMLDOMNode3 *iface, IHTMLDOMNode *otherNode, USHORT *flags)
1338 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1339 HTMLDOMNode *other;
1340 UINT16 position;
1341 nsresult nsres;
1343 TRACE("(%p)->()\n", This);
1345 other = get_node_obj(otherNode);
1346 if(!other)
1347 return E_INVALIDARG;
1349 nsres = nsIDOMNode_CompareDocumentPosition(This->nsnode, other->nsnode, &position);
1350 IHTMLDOMNode_Release(&other->IHTMLDOMNode_iface);
1351 if(NS_FAILED(nsres)) {
1352 ERR("failed: %08lx\n", nsres);
1353 return E_FAIL;
1356 *flags = position;
1357 return S_OK;
1360 static HRESULT WINAPI HTMLDOMNode3_isSupported(IHTMLDOMNode3 *iface, BSTR feature, VARIANT version, VARIANT_BOOL *pfisSupported)
1362 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1363 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_variant(&version), pfisSupported);
1364 return E_NOTIMPL;
1367 static const IHTMLDOMNode3Vtbl HTMLDOMNode3Vtbl = {
1368 HTMLDOMNode3_QueryInterface,
1369 HTMLDOMNode3_AddRef,
1370 HTMLDOMNode3_Release,
1371 HTMLDOMNode3_GetTypeInfoCount,
1372 HTMLDOMNode3_GetTypeInfo,
1373 HTMLDOMNode3_GetIDsOfNames,
1374 HTMLDOMNode3_Invoke,
1375 HTMLDOMNode3_put_prefix,
1376 HTMLDOMNode3_get_prefix,
1377 HTMLDOMNode3_get_localName,
1378 HTMLDOMNode3_get_namespaceURI,
1379 HTMLDOMNode3_put_textContent,
1380 HTMLDOMNode3_get_textContent,
1381 HTMLDOMNode3_isEqualNode,
1382 HTMLDOMNode3_lookupNamespaceURI,
1383 HTMLDOMNode3_lookupPrefix,
1384 HTMLDOMNode3_isDefaultNamespace,
1385 HTMLDOMNode3_appendChild,
1386 HTMLDOMNode3_insertBefore,
1387 HTMLDOMNode3_removeChild,
1388 HTMLDOMNode3_replaceChild,
1389 HTMLDOMNode3_isSameNode,
1390 HTMLDOMNode3_compareDocumentPosition,
1391 HTMLDOMNode3_isSupported
1394 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1396 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1398 if(IsEqualGUID(&IID_IUnknown, riid)) {
1399 *ppv = &This->IHTMLDOMNode_iface;
1400 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1401 *ppv = &This->IHTMLDOMNode_iface;
1402 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1403 *ppv = &This->IHTMLDOMNode_iface;
1404 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1405 *ppv = &This->IHTMLDOMNode2_iface;
1406 }else if(IsEqualGUID(&IID_IHTMLDOMNode3, riid)) {
1407 *ppv = &This->IHTMLDOMNode3_iface;
1408 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1409 *ppv = &node_ccp;
1410 return S_OK;
1411 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1412 *ppv = &This->IHTMLDOMNode_iface;
1413 return S_OK;
1414 }else {
1415 return EventTarget_QI(&This->event_target, riid, ppv);
1418 IUnknown_AddRef((IUnknown*)*ppv);
1419 return S_OK;
1422 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1424 release_event_target(&This->event_target);
1425 if(This->nsnode)
1426 nsIDOMNode_Release(This->nsnode);
1427 if(This->doc && &This->doc->node != This)
1428 htmldoc_release(&This->doc->basedoc);
1431 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1433 return create_node(This->doc, nsnode, ret);
1436 void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
1438 if(mode >= COMPAT_MODE_IE9)
1439 dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL);
1441 EventTarget_init_dispex_info(info, mode);
1444 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1446 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1447 NULL,
1448 HTMLDOMNode_QI,
1449 HTMLDOMNode_destructor,
1450 HTMLDOMNode_cpc,
1451 HTMLDOMNode_clone
1454 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode, dispex_static_data_t *dispex_data)
1456 nsresult nsres;
1458 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1459 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1460 node->IHTMLDOMNode3_iface.lpVtbl = &HTMLDOMNode3Vtbl;
1462 ccref_init(&node->ccref, 1);
1463 EventTarget_Init(&node->event_target, (IUnknown*)&node->IHTMLDOMNode_iface, dispex_data, doc->document_mode);
1465 if(&doc->node != node)
1466 htmldoc_addref(&doc->basedoc);
1467 node->doc = doc;
1469 nsIDOMNode_AddRef(nsnode);
1470 node->nsnode = nsnode;
1472 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1473 assert(nsres == NS_OK);
1476 static const tid_t HTMLDOMNode_iface_tids[] = {
1477 IHTMLDOMNode_tid,
1480 static dispex_static_data_t HTMLDOMNode_dispex = {
1481 L"Node",
1482 NULL,
1483 IHTMLDOMNode_tid,
1484 HTMLDOMNode_iface_tids,
1485 HTMLDOMNode_init_dispex_info
1488 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1490 UINT16 node_type;
1491 HRESULT hres;
1493 nsIDOMNode_GetNodeType(nsnode, &node_type);
1495 switch(node_type) {
1496 case ELEMENT_NODE: {
1497 HTMLElement *elem;
1498 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1499 if(FAILED(hres))
1500 return hres;
1501 *ret = &elem->node;
1502 break;
1504 case TEXT_NODE:
1505 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1506 if(FAILED(hres))
1507 return hres;
1508 break;
1509 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1510 case DOCUMENT_TYPE_NODE:
1511 case COMMENT_NODE: {
1512 HTMLElement *comment;
1513 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1514 if(FAILED(hres))
1515 return hres;
1516 *ret = &comment->node;
1517 break;
1519 case ATTRIBUTE_NODE:
1520 ERR("Called on attribute node\n");
1521 return E_UNEXPECTED;
1522 default: {
1523 HTMLDOMNode *node;
1525 FIXME("unimplemented node type %u\n", node_type);
1527 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1528 if(!node)
1529 return E_OUTOFMEMORY;
1531 node->vtbl = &HTMLDOMNodeImplVtbl;
1532 HTMLDOMNode_Init(doc, node, nsnode, &HTMLDOMNode_dispex);
1533 *ret = node;
1537 TRACE("type %d ret %p\n", node_type, *ret);
1538 return S_OK;
1541 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1543 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1545 TRACE("%p\n", This);
1547 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1549 if(This->nsnode)
1550 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1551 if(This->doc && &This->doc->node != This)
1552 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1553 dispex_traverse(&This->event_target.dispex, cb);
1555 if(This->vtbl->traverse)
1556 This->vtbl->traverse(This, cb);
1558 return NS_OK;
1561 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1563 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1565 TRACE("%p\n", This);
1567 if(This->vtbl->unlink)
1568 This->vtbl->unlink(This);
1570 dispex_unlink(&This->event_target.dispex);
1572 if(This->nsnode) {
1573 nsIDOMNode *nsnode = This->nsnode;
1574 This->nsnode = NULL;
1575 nsIDOMNode_Release(nsnode);
1578 if(This->doc && &This->doc->node != This) {
1579 HTMLDocumentNode *doc = This->doc;
1580 This->doc = NULL;
1581 htmldoc_release(&doc->basedoc);
1582 }else {
1583 This->doc = NULL;
1586 return NS_OK;
1589 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p)
1591 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1593 TRACE("(%p)\n", This);
1595 if(This->vtbl->unlink)
1596 This->vtbl->unlink(This);
1597 This->vtbl->destructor(This);
1598 release_dispex(&This->event_target.dispex);
1599 heap_free(This);
1602 void init_node_cc(void)
1604 static const CCObjCallback node_ccp_callback = {
1605 HTMLDOMNode_traverse,
1606 HTMLDOMNode_unlink,
1607 HTMLDOMNode_delete_cycle_collectable
1610 ccp_init(&node_ccp, &node_ccp_callback);
1613 HRESULT get_node(nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1615 nsIDOMDocument *dom_document;
1616 HTMLDocumentNode *document;
1617 nsISupports *unk = NULL;
1618 nsresult nsres;
1619 HRESULT hres;
1621 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1622 assert(nsres == NS_OK);
1624 if(unk) {
1625 *ret = get_node_obj((IHTMLDOMNode*)unk);
1626 nsISupports_Release(unk);
1627 return NS_OK;
1630 if(!create) {
1631 *ret = NULL;
1632 return S_OK;
1635 nsres = nsIDOMNode_GetOwnerDocument(nsnode, &dom_document);
1636 if(NS_FAILED(nsres) || !dom_document) {
1637 ERR("GetOwnerDocument failed: %08lx\n", nsres);
1638 return E_FAIL;
1641 hres = get_document_node(dom_document, &document);
1642 nsIDOMDocument_Release(dom_document);
1643 if(!document)
1644 return E_FAIL;
1646 hres = create_node(document, nsnode, ret);
1647 htmldoc_release(&document->basedoc);
1648 return hres;