shlwapi/tests: Add some tests for memory stream.
[wine.git] / dlls / mshtml / htmlnode.c
blobaec12fcb719b142b92224d63c18968acb1557ff1
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 && isdigitW(*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 FIXME("(%p)->(%p)\n", This, p);
1231 return E_NOTIMPL;
1234 static HRESULT WINAPI HTMLDOMNode3_put_textContent(IHTMLDOMNode3 *iface, VARIANT v)
1236 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1237 nsAString nsstr;
1238 nsresult nsres;
1240 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1242 if(V_VT(&v) != VT_BSTR) {
1243 FIXME("unsupported argument %s\n", debugstr_variant(&v));
1244 return E_NOTIMPL;
1247 nsAString_Init(&nsstr, V_BSTR(&v));
1248 nsres = nsIDOMNode_SetTextContent(This->nsnode, &nsstr);
1249 nsAString_Finish(&nsstr);
1250 if(NS_FAILED(nsres)) {
1251 ERR("SetTextContent failed: %08x\n", nsres);
1252 return E_FAIL;
1255 return S_OK;
1258 static HRESULT WINAPI HTMLDOMNode3_get_textContent(IHTMLDOMNode3 *iface, VARIANT *p)
1260 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1261 nsAString nsstr;
1262 nsresult nsres;
1264 TRACE("(%p)->(%p)\n", This, p);
1266 nsAString_Init(&nsstr, NULL);
1267 nsres = nsIDOMNode_GetTextContent(This->nsnode, &nsstr);
1268 return return_nsstr_variant(nsres, &nsstr, p);
1271 static HRESULT WINAPI HTMLDOMNode3_isEqualNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isEqual)
1273 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1274 FIXME("(%p)->()\n", This);
1275 return E_NOTIMPL;
1278 static HRESULT WINAPI HTMLDOMNode3_lookupNamespaceURI(IHTMLDOMNode3 *iface, VARIANT *prefix, VARIANT *namespaceURI)
1280 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1281 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(prefix), namespaceURI);
1282 return E_NOTIMPL;
1285 static HRESULT WINAPI HTMLDOMNode3_lookupPrefix(IHTMLDOMNode3 *iface, VARIANT *namespaceURI, VARIANT *prefix)
1287 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1288 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(namespaceURI), prefix);
1289 return E_NOTIMPL;
1292 static HRESULT WINAPI HTMLDOMNode3_isDefaultNamespace(IHTMLDOMNode3 *iface, VARIANT *namespace, VARIANT_BOOL *pfDefaultNamespace)
1294 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1295 FIXME("(%p)->()\n", This);
1296 return E_NOTIMPL;
1299 static HRESULT WINAPI HTMLDOMNode3_appendChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode **node)
1301 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1302 TRACE("(%p)->()\n", This);
1303 return IHTMLDOMNode_appendChild(&This->IHTMLDOMNode_iface, newChild, node);
1306 static HRESULT WINAPI HTMLDOMNode3_insertBefore(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, VARIANT refChild, IHTMLDOMNode **node)
1308 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1309 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
1310 return IHTMLDOMNode_insertBefore(&This->IHTMLDOMNode_iface, newChild, refChild, node);
1313 static HRESULT WINAPI HTMLDOMNode3_removeChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1315 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1316 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
1317 return IHTMLDOMNode_removeChild(&This->IHTMLDOMNode_iface, oldChild, node);
1320 static HRESULT WINAPI HTMLDOMNode3_replaceChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1322 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1323 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
1324 return IHTMLDOMNode_replaceChild(&This->IHTMLDOMNode_iface, newChild, oldChild, node);
1327 static HRESULT WINAPI HTMLDOMNode3_isSameNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isSame)
1329 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1330 FIXME("(%p)->()\n", This);
1331 return E_NOTIMPL;
1334 static HRESULT WINAPI HTMLDOMNode3_compareDocumentPosition(IHTMLDOMNode3 *iface, IHTMLDOMNode *otherNode, USHORT *flags)
1336 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1337 HTMLDOMNode *other;
1338 UINT16 position;
1339 nsresult nsres;
1341 TRACE("(%p)->()\n", This);
1343 other = get_node_obj(otherNode);
1344 if(!other)
1345 return E_INVALIDARG;
1347 nsres = nsIDOMNode_CompareDocumentPosition(This->nsnode, other->nsnode, &position);
1348 IHTMLDOMNode_Release(&other->IHTMLDOMNode_iface);
1349 if(NS_FAILED(nsres)) {
1350 ERR("failed: %08x\n", nsres);
1351 return E_FAIL;
1354 *flags = position;
1355 return S_OK;
1358 static HRESULT WINAPI HTMLDOMNode3_isSupported(IHTMLDOMNode3 *iface, BSTR feature, VARIANT version, VARIANT_BOOL *pfisSupported)
1360 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1361 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_variant(&version), pfisSupported);
1362 return E_NOTIMPL;
1365 static const IHTMLDOMNode3Vtbl HTMLDOMNode3Vtbl = {
1366 HTMLDOMNode3_QueryInterface,
1367 HTMLDOMNode3_AddRef,
1368 HTMLDOMNode3_Release,
1369 HTMLDOMNode3_GetTypeInfoCount,
1370 HTMLDOMNode3_GetTypeInfo,
1371 HTMLDOMNode3_GetIDsOfNames,
1372 HTMLDOMNode3_Invoke,
1373 HTMLDOMNode3_put_prefix,
1374 HTMLDOMNode3_get_prefix,
1375 HTMLDOMNode3_get_localName,
1376 HTMLDOMNode3_get_namespaceURI,
1377 HTMLDOMNode3_put_textContent,
1378 HTMLDOMNode3_get_textContent,
1379 HTMLDOMNode3_isEqualNode,
1380 HTMLDOMNode3_lookupNamespaceURI,
1381 HTMLDOMNode3_lookupPrefix,
1382 HTMLDOMNode3_isDefaultNamespace,
1383 HTMLDOMNode3_appendChild,
1384 HTMLDOMNode3_insertBefore,
1385 HTMLDOMNode3_removeChild,
1386 HTMLDOMNode3_replaceChild,
1387 HTMLDOMNode3_isSameNode,
1388 HTMLDOMNode3_compareDocumentPosition,
1389 HTMLDOMNode3_isSupported
1392 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1394 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1396 if(IsEqualGUID(&IID_IUnknown, riid)) {
1397 *ppv = &This->IHTMLDOMNode_iface;
1398 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1399 *ppv = &This->IHTMLDOMNode_iface;
1400 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1401 *ppv = &This->IHTMLDOMNode_iface;
1402 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1403 *ppv = &This->IHTMLDOMNode2_iface;
1404 }else if(IsEqualGUID(&IID_IHTMLDOMNode3, riid)) {
1405 *ppv = &This->IHTMLDOMNode3_iface;
1406 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1407 *ppv = &node_ccp;
1408 return S_OK;
1409 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1410 *ppv = &This->IHTMLDOMNode_iface;
1411 return S_OK;
1412 }else {
1413 return EventTarget_QI(&This->event_target, riid, ppv);
1416 IUnknown_AddRef((IUnknown*)*ppv);
1417 return S_OK;
1420 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1422 release_event_target(&This->event_target);
1423 if(This->nsnode)
1424 nsIDOMNode_Release(This->nsnode);
1425 if(This->doc && &This->doc->node != This)
1426 htmldoc_release(&This->doc->basedoc);
1429 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1431 return create_node(This->doc, nsnode, ret);
1434 void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
1436 if(mode >= COMPAT_MODE_IE9)
1437 dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL);
1439 EventTarget_init_dispex_info(info, mode);
1442 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1444 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1445 NULL,
1446 HTMLDOMNode_QI,
1447 HTMLDOMNode_destructor,
1448 HTMLDOMNode_cpc,
1449 HTMLDOMNode_clone
1452 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode, dispex_static_data_t *dispex_data)
1454 nsresult nsres;
1456 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1457 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1458 node->IHTMLDOMNode3_iface.lpVtbl = &HTMLDOMNode3Vtbl;
1460 ccref_init(&node->ccref, 1);
1461 EventTarget_Init(&node->event_target, (IUnknown*)&node->IHTMLDOMNode_iface, dispex_data, doc->document_mode);
1463 if(&doc->node != node)
1464 htmldoc_addref(&doc->basedoc);
1465 node->doc = doc;
1467 nsIDOMNode_AddRef(nsnode);
1468 node->nsnode = nsnode;
1470 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1471 assert(nsres == NS_OK);
1474 static const tid_t HTMLDOMNode_iface_tids[] = {
1475 IHTMLDOMNode_tid,
1478 static dispex_static_data_t HTMLDOMNode_dispex = {
1479 NULL,
1480 IHTMLDOMNode_tid,
1481 HTMLDOMNode_iface_tids,
1482 HTMLDOMNode_init_dispex_info
1485 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1487 UINT16 node_type;
1488 HRESULT hres;
1490 nsIDOMNode_GetNodeType(nsnode, &node_type);
1492 switch(node_type) {
1493 case ELEMENT_NODE: {
1494 HTMLElement *elem;
1495 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1496 if(FAILED(hres))
1497 return hres;
1498 *ret = &elem->node;
1499 break;
1501 case TEXT_NODE:
1502 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1503 if(FAILED(hres))
1504 return hres;
1505 break;
1506 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1507 case DOCUMENT_TYPE_NODE:
1508 case COMMENT_NODE: {
1509 HTMLElement *comment;
1510 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1511 if(FAILED(hres))
1512 return hres;
1513 *ret = &comment->node;
1514 break;
1516 case ATTRIBUTE_NODE:
1517 ERR("Called on attribute node\n");
1518 return E_UNEXPECTED;
1519 default: {
1520 HTMLDOMNode *node;
1522 FIXME("unimplemented node type %u\n", node_type);
1524 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1525 if(!node)
1526 return E_OUTOFMEMORY;
1528 node->vtbl = &HTMLDOMNodeImplVtbl;
1529 HTMLDOMNode_Init(doc, node, nsnode, &HTMLDOMNode_dispex);
1530 *ret = node;
1534 TRACE("type %d ret %p\n", node_type, *ret);
1535 return S_OK;
1538 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1540 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1542 TRACE("%p\n", This);
1544 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1546 if(This->nsnode)
1547 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1548 if(This->doc && &This->doc->node != This)
1549 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1550 dispex_traverse(&This->event_target.dispex, cb);
1552 if(This->vtbl->traverse)
1553 This->vtbl->traverse(This, cb);
1555 return NS_OK;
1558 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1560 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1562 TRACE("%p\n", This);
1564 if(This->vtbl->unlink)
1565 This->vtbl->unlink(This);
1567 dispex_unlink(&This->event_target.dispex);
1569 if(This->nsnode) {
1570 nsIDOMNode *nsnode = This->nsnode;
1571 This->nsnode = NULL;
1572 nsIDOMNode_Release(nsnode);
1575 if(This->doc && &This->doc->node != This) {
1576 HTMLDocument *doc = &This->doc->basedoc;
1577 This->doc = NULL;
1578 htmldoc_release(doc);
1579 }else {
1580 This->doc = NULL;
1583 return NS_OK;
1586 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p)
1588 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1590 TRACE("(%p)\n", This);
1592 if(This->vtbl->unlink)
1593 This->vtbl->unlink(This);
1594 This->vtbl->destructor(This);
1595 release_dispex(&This->event_target.dispex);
1596 heap_free(This);
1599 void init_node_cc(void)
1601 static const CCObjCallback node_ccp_callback = {
1602 HTMLDOMNode_traverse,
1603 HTMLDOMNode_unlink,
1604 HTMLDOMNode_delete_cycle_collectable
1607 ccp_init(&node_ccp, &node_ccp_callback);
1610 HRESULT get_node(nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1612 nsIDOMDocument *dom_document;
1613 HTMLDocumentNode *document;
1614 nsISupports *unk = NULL;
1615 nsresult nsres;
1616 HRESULT hres;
1618 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1619 assert(nsres == NS_OK);
1621 if(unk) {
1622 *ret = get_node_obj((IHTMLDOMNode*)unk);
1623 nsISupports_Release(unk);
1624 return NS_OK;
1627 if(!create) {
1628 *ret = NULL;
1629 return S_OK;
1632 nsres = nsIDOMNode_GetOwnerDocument(nsnode, &dom_document);
1633 if(NS_FAILED(nsres) || !dom_document) {
1634 ERR("GetOwnerDocument failed: %08x\n", nsres);
1635 return E_FAIL;
1638 hres = get_document_node(dom_document, &document);
1639 nsIDOMDocument_Release(dom_document);
1640 if(!document)
1641 return E_FAIL;
1643 hres = create_node(document, nsnode, ret);
1644 htmldoc_release(&document->basedoc);
1645 return hres;