xmllite: Drop superfluous casts to self.
[wine.git] / dlls / mshtml / htmlnode.c
blobb2d35f466015b995b854c3242c5ea51f44639b93
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 nsIDOMNodeList *nslist;
48 } HTMLDOMChildrenCollection;
50 typedef struct {
51 IEnumVARIANT IEnumVARIANT_iface;
53 LONG ref;
55 ULONG iter;
56 HTMLDOMChildrenCollection *col;
57 } HTMLDOMChildrenCollectionEnum;
59 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
61 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
64 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
66 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
68 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
70 if(IsEqualGUID(riid, &IID_IUnknown)) {
71 *ppv = &This->IEnumVARIANT_iface;
72 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
73 *ppv = &This->IEnumVARIANT_iface;
74 }else {
75 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
76 *ppv = NULL;
77 return E_NOINTERFACE;
80 IUnknown_AddRef((IUnknown*)*ppv);
81 return S_OK;
84 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
86 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
87 LONG ref = InterlockedIncrement(&This->ref);
89 TRACE("(%p) ref=%d\n", This, ref);
91 return ref;
94 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
96 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
97 LONG ref = InterlockedDecrement(&This->ref);
99 TRACE("(%p) ref=%d\n", This, ref);
101 if(!ref) {
102 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
103 heap_free(This);
106 return ref;
109 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
111 ULONG len;
112 nsresult nsres;
114 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
115 assert(nsres == NS_OK);
116 return len;
119 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
121 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
122 ULONG fetched = 0, len;
123 nsIDOMNode *nsnode;
124 HTMLDOMNode *node;
125 nsresult nsres;
126 HRESULT hres;
128 TRACE("(%p)->(%d %p %p)\n", This, celt, rgVar, pCeltFetched);
130 len = get_enum_len(This);
132 while(This->iter+fetched < len && fetched < celt) {
133 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
134 assert(nsres == NS_OK);
136 hres = get_node(nsnode, TRUE, &node);
137 nsIDOMNode_Release(nsnode);
138 if(FAILED(hres)) {
139 ERR("get_node failed: %08x\n", hres);
140 break;
143 V_VT(rgVar+fetched) = VT_DISPATCH;
144 IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
145 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
146 fetched++;
149 This->iter += fetched;
150 if(pCeltFetched)
151 *pCeltFetched = fetched;
152 return fetched == celt ? S_OK : S_FALSE;
155 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
157 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
158 ULONG len;
160 TRACE("(%p)->(%d)\n", This, celt);
162 len = get_enum_len(This);
163 if(This->iter + celt > len) {
164 This->iter = len;
165 return S_FALSE;
168 This->iter += celt;
169 return S_OK;
172 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
174 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
176 TRACE("(%p)->()\n", This);
178 This->iter = 0;
179 return S_OK;
182 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
184 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
185 FIXME("(%p)->(%p)\n", This, ppEnum);
186 return E_NOTIMPL;
189 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
190 HTMLDOMChildrenCollectionEnum_QueryInterface,
191 HTMLDOMChildrenCollectionEnum_AddRef,
192 HTMLDOMChildrenCollectionEnum_Release,
193 HTMLDOMChildrenCollectionEnum_Next,
194 HTMLDOMChildrenCollectionEnum_Skip,
195 HTMLDOMChildrenCollectionEnum_Reset,
196 HTMLDOMChildrenCollectionEnum_Clone
199 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
201 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
204 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
206 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
208 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
210 if(IsEqualGUID(&IID_IUnknown, riid)) {
211 *ppv = &This->IHTMLDOMChildrenCollection_iface;
212 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
213 *ppv = &This->IHTMLDOMChildrenCollection_iface;
214 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
215 return *ppv ? S_OK : E_NOINTERFACE;
216 }else {
217 *ppv = NULL;
218 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
219 return E_NOINTERFACE;
222 IUnknown_AddRef((IUnknown*)*ppv);
223 return S_OK;
226 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
228 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
229 LONG ref = InterlockedIncrement(&This->ref);
231 TRACE("(%p) ref=%d\n", This, ref);
233 return ref;
236 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
238 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
239 LONG ref = InterlockedDecrement(&This->ref);
241 TRACE("(%p) ref=%d\n", This, ref);
243 if(!ref) {
244 nsIDOMNodeList_Release(This->nslist);
245 heap_free(This);
248 return ref;
251 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
253 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
254 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
257 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
258 LCID lcid, ITypeInfo **ppTInfo)
260 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
261 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
264 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
265 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
267 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
268 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
269 lcid, rgDispId);
272 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
273 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
274 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
276 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
277 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
278 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
281 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
283 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
284 UINT32 length=0;
286 TRACE("(%p)->(%p)\n", This, p);
288 nsIDOMNodeList_GetLength(This->nslist, &length);
289 *p = length;
290 return S_OK;
293 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
295 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
296 HTMLDOMChildrenCollectionEnum *ret;
298 TRACE("(%p)->(%p)\n", This, p);
300 ret = heap_alloc(sizeof(*ret));
301 if(!ret)
302 return E_OUTOFMEMORY;
304 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
305 ret->ref = 1;
306 ret->iter = 0;
308 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
309 ret->col = This;
311 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
312 return S_OK;
315 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
317 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
318 nsIDOMNode *nsnode = NULL;
319 HTMLDOMNode *node;
320 UINT32 length=0;
321 nsresult nsres;
322 HRESULT hres;
324 TRACE("(%p)->(%d %p)\n", This, index, ppItem);
326 if (ppItem)
327 *ppItem = NULL;
328 else
329 return E_POINTER;
331 nsIDOMNodeList_GetLength(This->nslist, &length);
332 if(index < 0 || index >= length)
333 return E_INVALIDARG;
335 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
336 if(NS_FAILED(nsres) || !nsnode) {
337 ERR("Item failed: %08x\n", nsres);
338 return E_FAIL;
341 hres = get_node(nsnode, TRUE, &node);
342 if(FAILED(hres))
343 return hres;
345 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
346 return S_OK;
349 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
350 HTMLDOMChildrenCollection_QueryInterface,
351 HTMLDOMChildrenCollection_AddRef,
352 HTMLDOMChildrenCollection_Release,
353 HTMLDOMChildrenCollection_GetTypeInfoCount,
354 HTMLDOMChildrenCollection_GetTypeInfo,
355 HTMLDOMChildrenCollection_GetIDsOfNames,
356 HTMLDOMChildrenCollection_Invoke,
357 HTMLDOMChildrenCollection_get_length,
358 HTMLDOMChildrenCollection_get__newEnum,
359 HTMLDOMChildrenCollection_item
362 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
364 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
367 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
369 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
371 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
372 WCHAR *ptr;
373 DWORD idx=0;
374 UINT32 len = 0;
376 for(ptr = name; *ptr && is_digit(*ptr); ptr++)
377 idx = idx*10 + (*ptr-'0');
378 if(*ptr)
379 return DISP_E_UNKNOWNNAME;
381 nsIDOMNodeList_GetLength(This->nslist, &len);
382 if(idx >= len)
383 return DISP_E_UNKNOWNNAME;
385 *dispid = DISPID_CHILDCOL_0 + idx;
386 TRACE("ret %x\n", *dispid);
387 return S_OK;
390 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
391 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
393 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
395 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
397 switch(flags) {
398 case DISPATCH_PROPERTYGET: {
399 IDispatch *disp = NULL;
400 HRESULT hres;
402 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
403 id - DISPID_CHILDCOL_0, &disp);
404 if(FAILED(hres))
405 return hres;
407 V_VT(res) = VT_DISPATCH;
408 V_DISPATCH(res) = disp;
409 break;
412 default:
413 FIXME("unimplemented flags %x\n", flags);
414 return E_NOTIMPL;
417 return S_OK;
420 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
421 NULL,
422 HTMLDOMChildrenCollection_get_dispid,
423 HTMLDOMChildrenCollection_invoke,
424 NULL
427 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
428 IHTMLDOMChildrenCollection_tid,
432 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
433 &HTMLDOMChildrenCollection_dispex_vtbl,
434 DispDOMChildrenCollection_tid,
435 HTMLDOMChildrenCollection_iface_tids,
436 HTMLDOMNode_init_dispex_info
439 IHTMLDOMChildrenCollection *create_child_collection(nsIDOMNodeList *nslist)
441 HTMLDOMChildrenCollection *ret;
443 ret = heap_alloc_zero(sizeof(*ret));
444 if(!ret)
445 return NULL;
447 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
448 ret->ref = 1;
450 nsIDOMNodeList_AddRef(nslist);
451 ret->nslist = nslist;
453 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface,
454 &HTMLDOMChildrenCollection_dispex);
456 return &ret->IHTMLDOMChildrenCollection_iface;
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=%d\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=%d\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: %08x\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: %08x\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 nsresult nsres;
616 TRACE("(%p)->(%p)\n", This, p);
618 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
619 if(NS_FAILED(nsres)) {
620 ERR("GetChildNodes failed: %08x\n", nsres);
621 return E_FAIL;
624 *p = (IDispatch*)create_child_collection(nslist);
625 nsIDOMNodeList_Release(nslist);
627 return *p ? S_OK : E_OUTOFMEMORY;
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: %08x\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: %08x\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: %08x\n", nsres);
799 return E_FAIL;
802 hres = This->vtbl->clone(This, nsnode, &new_node);
803 if(FAILED(hres))
804 return hres;
806 *clonedNode = &new_node->IHTMLDOMNode_iface;
807 return S_OK;
810 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
811 IHTMLDOMNode **removed)
813 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
814 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
815 return E_NOTIMPL;
818 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
819 IHTMLDOMNode **swappedNode)
821 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
822 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
823 return E_NOTIMPL;
826 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
827 IHTMLDOMNode **replaced)
829 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
830 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
831 return E_NOTIMPL;
834 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
835 IHTMLDOMNode **node)
837 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
838 HTMLDOMNode *node_obj;
839 nsIDOMNode *nsnode;
840 nsresult nsres;
841 HRESULT hres;
843 TRACE("(%p)->(%p %p)\n", This, newChild, node);
845 node_obj = get_node_obj(newChild);
846 if(!node_obj)
847 return E_FAIL;
849 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
850 node_release(node_obj);
851 if(NS_FAILED(nsres)) {
852 ERR("AppendChild failed: %08x\n", nsres);
853 return E_FAIL;
856 hres = get_node(nsnode, TRUE, &node_obj);
857 nsIDOMNode_Release(nsnode);
858 if(FAILED(hres))
859 return hres;
861 /* FIXME: Make sure that node != newChild */
862 *node = &node_obj->IHTMLDOMNode_iface;
863 return S_OK;
866 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
868 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
869 nsAString name;
870 nsresult nsres;
872 TRACE("(%p)->(%p)\n", This, p);
874 nsAString_Init(&name, NULL);
875 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
876 return return_nsstr(nsres, &name, p);
879 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
881 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
883 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
885 switch(V_VT(&v)) {
886 case VT_BSTR: {
887 nsAString val_str;
889 nsAString_InitDepend(&val_str, V_BSTR(&v));
890 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
891 nsAString_Finish(&val_str);
893 return S_OK;
896 default:
897 FIXME("unsupported value %s\n", debugstr_variant(&v));
900 return E_NOTIMPL;
903 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
905 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
906 const PRUnichar *val;
907 nsAString val_str;
909 TRACE("(%p)->(%p)\n", This, p);
911 nsAString_Init(&val_str, NULL);
912 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
913 nsAString_GetData(&val_str, &val);
915 if(*val) {
916 V_VT(p) = VT_BSTR;
917 V_BSTR(p) = SysAllocString(val);
918 }else {
919 V_VT(p) = VT_NULL;
922 nsAString_Finish(&val_str);
924 return S_OK;
927 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
929 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
930 nsIDOMNode *nschild = NULL;
931 HTMLDOMNode *node;
932 HRESULT hres;
934 TRACE("(%p)->(%p)\n", This, p);
936 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
937 if(!nschild) {
938 *p = NULL;
939 return S_OK;
942 hres = get_node(nschild, TRUE, &node);
943 nsIDOMNode_Release(nschild);
944 if(FAILED(hres))
945 return hres;
947 *p = &node->IHTMLDOMNode_iface;
948 return S_OK;
951 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
953 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
954 nsIDOMNode *nschild = NULL;
955 HTMLDOMNode *node;
956 HRESULT hres;
958 TRACE("(%p)->(%p)\n", This, p);
960 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
961 if(!nschild) {
962 *p = NULL;
963 return S_OK;
966 hres = get_node(nschild, TRUE, &node);
967 nsIDOMNode_Release(nschild);
968 if(FAILED(hres))
969 return hres;
971 *p = &node->IHTMLDOMNode_iface;
972 return S_OK;
975 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
977 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
978 nsIDOMNode *nschild = NULL;
979 HTMLDOMNode *node;
980 HRESULT hres;
982 TRACE("(%p)->(%p)\n", This, p);
984 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
985 if(!nschild) {
986 *p = NULL;
987 return S_OK;
990 hres = get_node(nschild, TRUE, &node);
991 nsIDOMNode_Release(nschild);
992 if(FAILED(hres))
993 return hres;
995 *p = &node->IHTMLDOMNode_iface;
996 return S_OK;
999 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1001 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1002 nsIDOMNode *nssibling = NULL;
1003 HTMLDOMNode *node;
1004 HRESULT hres;
1006 TRACE("(%p)->(%p)\n", This, p);
1008 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1009 if(!nssibling) {
1010 *p = NULL;
1011 return S_OK;
1014 hres = get_node(nssibling, TRUE, &node);
1015 nsIDOMNode_Release(nssibling);
1016 if(FAILED(hres))
1017 return hres;
1019 *p = &node->IHTMLDOMNode_iface;
1020 return S_OK;
1023 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1024 HTMLDOMNode_QueryInterface,
1025 HTMLDOMNode_AddRef,
1026 HTMLDOMNode_Release,
1027 HTMLDOMNode_GetTypeInfoCount,
1028 HTMLDOMNode_GetTypeInfo,
1029 HTMLDOMNode_GetIDsOfNames,
1030 HTMLDOMNode_Invoke,
1031 HTMLDOMNode_get_nodeType,
1032 HTMLDOMNode_get_parentNode,
1033 HTMLDOMNode_hasChildNodes,
1034 HTMLDOMNode_get_childNodes,
1035 HTMLDOMNode_get_attributes,
1036 HTMLDOMNode_insertBefore,
1037 HTMLDOMNode_removeChild,
1038 HTMLDOMNode_replaceChild,
1039 HTMLDOMNode_cloneNode,
1040 HTMLDOMNode_removeNode,
1041 HTMLDOMNode_swapNode,
1042 HTMLDOMNode_replaceNode,
1043 HTMLDOMNode_appendChild,
1044 HTMLDOMNode_get_nodeName,
1045 HTMLDOMNode_put_nodeValue,
1046 HTMLDOMNode_get_nodeValue,
1047 HTMLDOMNode_get_firstChild,
1048 HTMLDOMNode_get_lastChild,
1049 HTMLDOMNode_get_previousSibling,
1050 HTMLDOMNode_get_nextSibling
1053 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1055 HTMLDOMNode *ret;
1057 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1058 return NULL;
1060 ret = impl_from_IHTMLDOMNode(iface);
1061 node_addref(ret);
1062 return ret;
1065 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1067 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1070 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1071 REFIID riid, void **ppv)
1073 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1075 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1078 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1080 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1082 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1085 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1087 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1089 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1092 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1094 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1095 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1098 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1099 LCID lcid, ITypeInfo **ppTInfo)
1101 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1102 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1105 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1106 LPOLESTR *rgszNames, UINT cNames,
1107 LCID lcid, DISPID *rgDispId)
1109 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1110 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1111 lcid, rgDispId);
1114 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1115 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1116 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1118 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1119 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1120 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1123 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1125 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1127 TRACE("(%p)->(%p)\n", This, p);
1129 /* FIXME: Better check for document node */
1130 if(This == &This->doc->node) {
1131 *p = NULL;
1132 }else {
1133 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
1134 IDispatch_AddRef(*p);
1136 return S_OK;
1139 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1140 HTMLDOMNode2_QueryInterface,
1141 HTMLDOMNode2_AddRef,
1142 HTMLDOMNode2_Release,
1143 HTMLDOMNode2_GetTypeInfoCount,
1144 HTMLDOMNode2_GetTypeInfo,
1145 HTMLDOMNode2_GetIDsOfNames,
1146 HTMLDOMNode2_Invoke,
1147 HTMLDOMNode2_get_ownerDocument
1150 static inline HTMLDOMNode *impl_from_IHTMLDOMNode3(IHTMLDOMNode3 *iface)
1152 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode3_iface);
1155 static HRESULT WINAPI HTMLDOMNode3_QueryInterface(IHTMLDOMNode3 *iface, REFIID riid, void **ppv)
1157 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1158 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1161 static ULONG WINAPI HTMLDOMNode3_AddRef(IHTMLDOMNode3 *iface)
1163 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1165 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1168 static ULONG WINAPI HTMLDOMNode3_Release(IHTMLDOMNode3 *iface)
1170 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1172 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1175 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfoCount(IHTMLDOMNode3 *iface, UINT *pctinfo)
1177 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1178 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1181 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfo(IHTMLDOMNode3 *iface, UINT iTInfo,
1182 LCID lcid, ITypeInfo **ppTInfo)
1184 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1185 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1188 static HRESULT WINAPI HTMLDOMNode3_GetIDsOfNames(IHTMLDOMNode3 *iface, REFIID riid,
1189 LPOLESTR *rgszNames, UINT cNames,
1190 LCID lcid, DISPID *rgDispId)
1192 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1193 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1194 lcid, rgDispId);
1197 static HRESULT WINAPI HTMLDOMNode3_Invoke(IHTMLDOMNode3 *iface, DISPID dispIdMember,
1198 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1199 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1201 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1202 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1203 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1206 static HRESULT WINAPI HTMLDOMNode3_put_prefix(IHTMLDOMNode3 *iface, VARIANT v)
1208 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1209 FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1210 return E_NOTIMPL;
1213 static HRESULT WINAPI HTMLDOMNode3_get_prefix(IHTMLDOMNode3 *iface, VARIANT *p)
1215 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1216 FIXME("(%p)->(%p)\n", This, p);
1217 return E_NOTIMPL;
1220 static HRESULT WINAPI HTMLDOMNode3_get_localName(IHTMLDOMNode3 *iface, VARIANT *p)
1222 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1223 FIXME("(%p)->(%p)\n", This, p);
1224 return E_NOTIMPL;
1227 static HRESULT WINAPI HTMLDOMNode3_get_namespaceURI(IHTMLDOMNode3 *iface, VARIANT *p)
1229 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1230 nsAString nsstr;
1231 nsresult nsres;
1233 TRACE("(%p)->(%p)\n", This, p);
1235 nsAString_InitDepend(&nsstr, NULL);
1236 nsres = nsIDOMNode_GetNamespaceURI(This->nsnode, &nsstr);
1237 return return_nsstr_variant(nsres, &nsstr, 0, p);
1240 static HRESULT WINAPI HTMLDOMNode3_put_textContent(IHTMLDOMNode3 *iface, VARIANT v)
1242 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1243 nsAString nsstr;
1244 nsresult nsres;
1246 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1248 variant_to_nsstr(&v, FALSE, &nsstr);
1249 nsres = nsIDOMNode_SetTextContent(This->nsnode, &nsstr);
1250 nsAString_Finish(&nsstr);
1251 if(NS_FAILED(nsres)) {
1252 ERR("SetTextContent failed: %08x\n", nsres);
1253 return E_FAIL;
1256 return S_OK;
1259 static HRESULT WINAPI HTMLDOMNode3_get_textContent(IHTMLDOMNode3 *iface, VARIANT *p)
1261 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1262 nsAString nsstr;
1263 nsresult nsres;
1265 TRACE("(%p)->(%p)\n", This, p);
1267 nsAString_Init(&nsstr, NULL);
1268 nsres = nsIDOMNode_GetTextContent(This->nsnode, &nsstr);
1269 return return_nsstr_variant(nsres, &nsstr, 0, p);
1272 static HRESULT WINAPI HTMLDOMNode3_isEqualNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isEqual)
1274 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1275 FIXME("(%p)->()\n", This);
1276 return E_NOTIMPL;
1279 static HRESULT WINAPI HTMLDOMNode3_lookupNamespaceURI(IHTMLDOMNode3 *iface, VARIANT *prefix, VARIANT *namespaceURI)
1281 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1282 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(prefix), namespaceURI);
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI HTMLDOMNode3_lookupPrefix(IHTMLDOMNode3 *iface, VARIANT *namespaceURI, VARIANT *prefix)
1288 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1289 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(namespaceURI), prefix);
1290 return E_NOTIMPL;
1293 static HRESULT WINAPI HTMLDOMNode3_isDefaultNamespace(IHTMLDOMNode3 *iface, VARIANT *namespace, VARIANT_BOOL *pfDefaultNamespace)
1295 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1296 FIXME("(%p)->()\n", This);
1297 return E_NOTIMPL;
1300 static HRESULT WINAPI HTMLDOMNode3_appendChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode **node)
1302 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1303 TRACE("(%p)->()\n", This);
1304 return IHTMLDOMNode_appendChild(&This->IHTMLDOMNode_iface, newChild, node);
1307 static HRESULT WINAPI HTMLDOMNode3_insertBefore(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, VARIANT refChild, IHTMLDOMNode **node)
1309 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1310 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
1311 return IHTMLDOMNode_insertBefore(&This->IHTMLDOMNode_iface, newChild, refChild, node);
1314 static HRESULT WINAPI HTMLDOMNode3_removeChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1316 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1317 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
1318 return IHTMLDOMNode_removeChild(&This->IHTMLDOMNode_iface, oldChild, node);
1321 static HRESULT WINAPI HTMLDOMNode3_replaceChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1323 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1324 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
1325 return IHTMLDOMNode_replaceChild(&This->IHTMLDOMNode_iface, newChild, oldChild, node);
1328 static HRESULT WINAPI HTMLDOMNode3_isSameNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isSame)
1330 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1331 FIXME("(%p)->()\n", This);
1332 return E_NOTIMPL;
1335 static HRESULT WINAPI HTMLDOMNode3_compareDocumentPosition(IHTMLDOMNode3 *iface, IHTMLDOMNode *otherNode, USHORT *flags)
1337 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1338 HTMLDOMNode *other;
1339 UINT16 position;
1340 nsresult nsres;
1342 TRACE("(%p)->()\n", This);
1344 other = get_node_obj(otherNode);
1345 if(!other)
1346 return E_INVALIDARG;
1348 nsres = nsIDOMNode_CompareDocumentPosition(This->nsnode, other->nsnode, &position);
1349 IHTMLDOMNode_Release(&other->IHTMLDOMNode_iface);
1350 if(NS_FAILED(nsres)) {
1351 ERR("failed: %08x\n", nsres);
1352 return E_FAIL;
1355 *flags = position;
1356 return S_OK;
1359 static HRESULT WINAPI HTMLDOMNode3_isSupported(IHTMLDOMNode3 *iface, BSTR feature, VARIANT version, VARIANT_BOOL *pfisSupported)
1361 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1362 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_variant(&version), pfisSupported);
1363 return E_NOTIMPL;
1366 static const IHTMLDOMNode3Vtbl HTMLDOMNode3Vtbl = {
1367 HTMLDOMNode3_QueryInterface,
1368 HTMLDOMNode3_AddRef,
1369 HTMLDOMNode3_Release,
1370 HTMLDOMNode3_GetTypeInfoCount,
1371 HTMLDOMNode3_GetTypeInfo,
1372 HTMLDOMNode3_GetIDsOfNames,
1373 HTMLDOMNode3_Invoke,
1374 HTMLDOMNode3_put_prefix,
1375 HTMLDOMNode3_get_prefix,
1376 HTMLDOMNode3_get_localName,
1377 HTMLDOMNode3_get_namespaceURI,
1378 HTMLDOMNode3_put_textContent,
1379 HTMLDOMNode3_get_textContent,
1380 HTMLDOMNode3_isEqualNode,
1381 HTMLDOMNode3_lookupNamespaceURI,
1382 HTMLDOMNode3_lookupPrefix,
1383 HTMLDOMNode3_isDefaultNamespace,
1384 HTMLDOMNode3_appendChild,
1385 HTMLDOMNode3_insertBefore,
1386 HTMLDOMNode3_removeChild,
1387 HTMLDOMNode3_replaceChild,
1388 HTMLDOMNode3_isSameNode,
1389 HTMLDOMNode3_compareDocumentPosition,
1390 HTMLDOMNode3_isSupported
1393 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1395 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1397 if(IsEqualGUID(&IID_IUnknown, riid)) {
1398 *ppv = &This->IHTMLDOMNode_iface;
1399 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1400 *ppv = &This->IHTMLDOMNode_iface;
1401 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1402 *ppv = &This->IHTMLDOMNode_iface;
1403 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1404 *ppv = &This->IHTMLDOMNode2_iface;
1405 }else if(IsEqualGUID(&IID_IHTMLDOMNode3, riid)) {
1406 *ppv = &This->IHTMLDOMNode3_iface;
1407 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1408 *ppv = &node_ccp;
1409 return S_OK;
1410 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1411 *ppv = &This->IHTMLDOMNode_iface;
1412 return S_OK;
1413 }else {
1414 return EventTarget_QI(&This->event_target, riid, ppv);
1417 IUnknown_AddRef((IUnknown*)*ppv);
1418 return S_OK;
1421 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1423 release_event_target(&This->event_target);
1424 if(This->nsnode)
1425 nsIDOMNode_Release(This->nsnode);
1426 if(This->doc && &This->doc->node != This)
1427 htmldoc_release(&This->doc->basedoc);
1430 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1432 return create_node(This->doc, nsnode, ret);
1435 void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
1437 if(mode >= COMPAT_MODE_IE9)
1438 dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL);
1440 EventTarget_init_dispex_info(info, mode);
1443 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1445 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1446 NULL,
1447 HTMLDOMNode_QI,
1448 HTMLDOMNode_destructor,
1449 HTMLDOMNode_cpc,
1450 HTMLDOMNode_clone
1453 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode, dispex_static_data_t *dispex_data)
1455 nsresult nsres;
1457 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1458 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1459 node->IHTMLDOMNode3_iface.lpVtbl = &HTMLDOMNode3Vtbl;
1461 ccref_init(&node->ccref, 1);
1462 EventTarget_Init(&node->event_target, (IUnknown*)&node->IHTMLDOMNode_iface, dispex_data, doc->document_mode);
1464 if(&doc->node != node)
1465 htmldoc_addref(&doc->basedoc);
1466 node->doc = doc;
1468 nsIDOMNode_AddRef(nsnode);
1469 node->nsnode = nsnode;
1471 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1472 assert(nsres == NS_OK);
1475 static const tid_t HTMLDOMNode_iface_tids[] = {
1476 IHTMLDOMNode_tid,
1479 static dispex_static_data_t HTMLDOMNode_dispex = {
1480 NULL,
1481 IHTMLDOMNode_tid,
1482 HTMLDOMNode_iface_tids,
1483 HTMLDOMNode_init_dispex_info
1486 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1488 UINT16 node_type;
1489 HRESULT hres;
1491 nsIDOMNode_GetNodeType(nsnode, &node_type);
1493 switch(node_type) {
1494 case ELEMENT_NODE: {
1495 HTMLElement *elem;
1496 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1497 if(FAILED(hres))
1498 return hres;
1499 *ret = &elem->node;
1500 break;
1502 case TEXT_NODE:
1503 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1504 if(FAILED(hres))
1505 return hres;
1506 break;
1507 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1508 case DOCUMENT_TYPE_NODE:
1509 case COMMENT_NODE: {
1510 HTMLElement *comment;
1511 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1512 if(FAILED(hres))
1513 return hres;
1514 *ret = &comment->node;
1515 break;
1517 case ATTRIBUTE_NODE:
1518 ERR("Called on attribute node\n");
1519 return E_UNEXPECTED;
1520 default: {
1521 HTMLDOMNode *node;
1523 FIXME("unimplemented node type %u\n", node_type);
1525 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1526 if(!node)
1527 return E_OUTOFMEMORY;
1529 node->vtbl = &HTMLDOMNodeImplVtbl;
1530 HTMLDOMNode_Init(doc, node, nsnode, &HTMLDOMNode_dispex);
1531 *ret = node;
1535 TRACE("type %d ret %p\n", node_type, *ret);
1536 return S_OK;
1539 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1541 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1543 TRACE("%p\n", This);
1545 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1547 if(This->nsnode)
1548 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1549 if(This->doc && &This->doc->node != This)
1550 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1551 dispex_traverse(&This->event_target.dispex, cb);
1553 if(This->vtbl->traverse)
1554 This->vtbl->traverse(This, cb);
1556 return NS_OK;
1559 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1561 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1563 TRACE("%p\n", This);
1565 if(This->vtbl->unlink)
1566 This->vtbl->unlink(This);
1568 dispex_unlink(&This->event_target.dispex);
1570 if(This->nsnode) {
1571 nsIDOMNode *nsnode = This->nsnode;
1572 This->nsnode = NULL;
1573 nsIDOMNode_Release(nsnode);
1576 if(This->doc && &This->doc->node != This) {
1577 HTMLDocumentNode *doc = This->doc;
1578 This->doc = NULL;
1579 htmldoc_release(&doc->basedoc);
1580 }else {
1581 This->doc = NULL;
1584 return NS_OK;
1587 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p)
1589 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1591 TRACE("(%p)\n", This);
1593 if(This->vtbl->unlink)
1594 This->vtbl->unlink(This);
1595 This->vtbl->destructor(This);
1596 release_dispex(&This->event_target.dispex);
1597 heap_free(This);
1600 void init_node_cc(void)
1602 static const CCObjCallback node_ccp_callback = {
1603 HTMLDOMNode_traverse,
1604 HTMLDOMNode_unlink,
1605 HTMLDOMNode_delete_cycle_collectable
1608 ccp_init(&node_ccp, &node_ccp_callback);
1611 HRESULT get_node(nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1613 nsIDOMDocument *dom_document;
1614 HTMLDocumentNode *document;
1615 nsISupports *unk = NULL;
1616 nsresult nsres;
1617 HRESULT hres;
1619 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1620 assert(nsres == NS_OK);
1622 if(unk) {
1623 *ret = get_node_obj((IHTMLDOMNode*)unk);
1624 nsISupports_Release(unk);
1625 return NS_OK;
1628 if(!create) {
1629 *ret = NULL;
1630 return S_OK;
1633 nsres = nsIDOMNode_GetOwnerDocument(nsnode, &dom_document);
1634 if(NS_FAILED(nsres) || !dom_document) {
1635 ERR("GetOwnerDocument failed: %08x\n", nsres);
1636 return E_FAIL;
1639 hres = get_document_node(dom_document, &document);
1640 nsIDOMDocument_Release(dom_document);
1641 if(!document)
1642 return E_FAIL;
1644 hres = create_node(document, nsnode, ret);
1645 htmldoc_release(&document->basedoc);
1646 return hres;