windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / mshtml / htmlnode.c
blobb29383ad9fffbfd06ece0fb4adfde04f6a6b5750
1 /*
2 * Copyright 2006 Jacek Caban for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
36 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
38 static ExternalCycleCollectionParticipant node_ccp;
40 typedef struct {
41 DispatchEx dispex;
42 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
44 LONG ref;
46 nsIDOMNodeList *nslist;
47 } HTMLDOMChildrenCollection;
49 typedef struct {
50 IEnumVARIANT IEnumVARIANT_iface;
52 LONG ref;
54 ULONG iter;
55 HTMLDOMChildrenCollection *col;
56 } HTMLDOMChildrenCollectionEnum;
58 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
60 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
63 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
65 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
67 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
69 if(IsEqualGUID(riid, &IID_IUnknown)) {
70 *ppv = &This->IEnumVARIANT_iface;
71 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
72 *ppv = &This->IEnumVARIANT_iface;
73 }else {
74 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
75 *ppv = NULL;
76 return E_NOINTERFACE;
79 IUnknown_AddRef((IUnknown*)*ppv);
80 return S_OK;
83 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
85 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
86 LONG ref = InterlockedIncrement(&This->ref);
88 TRACE("(%p) ref=%ld\n", This, ref);
90 return ref;
93 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
95 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
96 LONG ref = InterlockedDecrement(&This->ref);
98 TRACE("(%p) ref=%ld\n", This, ref);
100 if(!ref) {
101 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
102 free(This);
105 return ref;
108 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
110 UINT32 len;
111 nsresult nsres;
113 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
114 assert(nsres == NS_OK);
115 return len;
118 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
120 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
121 ULONG fetched = 0, len;
122 nsIDOMNode *nsnode;
123 HTMLDOMNode *node;
124 nsresult nsres;
125 HRESULT hres;
127 TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched);
129 len = get_enum_len(This);
131 while(This->iter+fetched < len && fetched < celt) {
132 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
133 assert(nsres == NS_OK);
135 hres = get_node(nsnode, TRUE, &node);
136 nsIDOMNode_Release(nsnode);
137 if(FAILED(hres)) {
138 while(fetched--)
139 VariantClear(rgVar+fetched);
140 return hres;
143 V_VT(rgVar+fetched) = VT_DISPATCH;
144 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
145 fetched++;
148 This->iter += fetched;
149 if(pCeltFetched)
150 *pCeltFetched = fetched;
151 return fetched == celt ? S_OK : S_FALSE;
154 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
156 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
157 ULONG len;
159 TRACE("(%p)->(%ld)\n", This, celt);
161 len = get_enum_len(This);
162 if(This->iter + celt > len) {
163 This->iter = len;
164 return S_FALSE;
167 This->iter += celt;
168 return S_OK;
171 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
173 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
175 TRACE("(%p)->()\n", This);
177 This->iter = 0;
178 return S_OK;
181 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
183 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
184 FIXME("(%p)->(%p)\n", This, ppEnum);
185 return E_NOTIMPL;
188 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
189 HTMLDOMChildrenCollectionEnum_QueryInterface,
190 HTMLDOMChildrenCollectionEnum_AddRef,
191 HTMLDOMChildrenCollectionEnum_Release,
192 HTMLDOMChildrenCollectionEnum_Next,
193 HTMLDOMChildrenCollectionEnum_Skip,
194 HTMLDOMChildrenCollectionEnum_Reset,
195 HTMLDOMChildrenCollectionEnum_Clone
198 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
200 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
203 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
205 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
207 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
209 if(IsEqualGUID(&IID_IUnknown, riid)) {
210 *ppv = &This->IHTMLDOMChildrenCollection_iface;
211 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
212 *ppv = &This->IHTMLDOMChildrenCollection_iface;
213 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
214 return *ppv ? S_OK : E_NOINTERFACE;
215 }else {
216 *ppv = NULL;
217 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
218 return E_NOINTERFACE;
221 IUnknown_AddRef((IUnknown*)*ppv);
222 return S_OK;
225 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
227 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
228 LONG ref = InterlockedIncrement(&This->ref);
230 TRACE("(%p) ref=%ld\n", This, ref);
232 return ref;
235 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
237 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
238 LONG ref = InterlockedDecrement(&This->ref);
240 TRACE("(%p) ref=%ld\n", This, ref);
242 if(!ref) {
243 nsIDOMNodeList_Release(This->nslist);
244 free(This);
247 return ref;
250 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
252 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
253 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
256 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
257 LCID lcid, ITypeInfo **ppTInfo)
259 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
260 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
263 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
264 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
266 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
267 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
268 lcid, rgDispId);
271 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
272 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
273 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
275 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
276 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
277 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
280 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
282 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
283 UINT32 length=0;
285 TRACE("(%p)->(%p)\n", This, p);
287 nsIDOMNodeList_GetLength(This->nslist, &length);
288 *p = length;
289 return S_OK;
292 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
294 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
295 HTMLDOMChildrenCollectionEnum *ret;
297 TRACE("(%p)->(%p)\n", This, p);
299 ret = malloc(sizeof(*ret));
300 if(!ret)
301 return E_OUTOFMEMORY;
303 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
304 ret->ref = 1;
305 ret->iter = 0;
307 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
308 ret->col = This;
310 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
311 return S_OK;
314 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
316 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
317 nsIDOMNode *nsnode = NULL;
318 HTMLDOMNode *node;
319 UINT32 length=0;
320 nsresult nsres;
321 HRESULT hres;
323 TRACE("(%p)->(%ld %p)\n", This, index, ppItem);
325 if (ppItem)
326 *ppItem = NULL;
327 else
328 return E_POINTER;
330 nsIDOMNodeList_GetLength(This->nslist, &length);
331 if(index < 0 || index >= length)
332 return E_INVALIDARG;
334 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
335 if(NS_FAILED(nsres) || !nsnode) {
336 ERR("Item failed: %08lx\n", nsres);
337 return E_FAIL;
340 hres = get_node(nsnode, TRUE, &node);
341 nsIDOMNode_Release(nsnode);
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 %lx\n", *dispid);
387 return S_OK;
390 static HRESULT HTMLDOMChildrenCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name)
392 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
393 DWORD idx = id - DISPID_CHILDCOL_0;
394 UINT32 len = 0;
395 WCHAR buf[11];
397 nsIDOMNodeList_GetLength(This->nslist, &len);
398 if(idx >= len)
399 return DISP_E_MEMBERNOTFOUND;
401 len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx);
402 return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY;
405 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
406 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
408 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
410 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
412 switch(flags) {
413 case DISPATCH_PROPERTYGET: {
414 IDispatch *disp = NULL;
415 HRESULT hres;
417 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
418 id - DISPID_CHILDCOL_0, &disp);
419 if(FAILED(hres))
420 return hres;
422 V_VT(res) = VT_DISPATCH;
423 V_DISPATCH(res) = disp;
424 break;
427 default:
428 FIXME("unimplemented flags %x\n", flags);
429 return E_NOTIMPL;
432 return S_OK;
435 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
436 NULL,
437 HTMLDOMChildrenCollection_get_dispid,
438 HTMLDOMChildrenCollection_get_name,
439 HTMLDOMChildrenCollection_invoke,
440 NULL
443 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
444 IHTMLDOMChildrenCollection_tid,
448 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
449 L"NodeList",
450 &HTMLDOMChildrenCollection_dispex_vtbl,
451 DispDOMChildrenCollection_tid,
452 HTMLDOMChildrenCollection_iface_tids,
453 HTMLDOMNode_init_dispex_info
456 HRESULT create_child_collection(nsIDOMNodeList *nslist, compat_mode_t compat_mode, IHTMLDOMChildrenCollection **ret)
458 HTMLDOMChildrenCollection *collection;
460 if(!(collection = calloc(1, sizeof(*collection))))
461 return E_OUTOFMEMORY;
463 collection->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
464 collection->ref = 1;
466 nsIDOMNodeList_AddRef(nslist);
467 collection->nslist = nslist;
469 init_dispatch(&collection->dispex, (IUnknown*)&collection->IHTMLDOMChildrenCollection_iface,
470 &HTMLDOMChildrenCollection_dispex, compat_mode);
472 *ret = &collection->IHTMLDOMChildrenCollection_iface;
473 return S_OK;
476 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
478 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
481 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
482 REFIID riid, void **ppv)
484 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
486 return This->vtbl->qi(This, riid, ppv);
489 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
491 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
492 LONG ref;
494 ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
496 TRACE("(%p) ref=%ld\n", This, ref);
498 return ref;
501 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
503 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
504 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface, &node_ccp);
506 TRACE("(%p) ref=%ld\n", This, ref);
508 return ref;
511 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
513 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
514 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
517 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
518 LCID lcid, ITypeInfo **ppTInfo)
520 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
521 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
524 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
525 LPOLESTR *rgszNames, UINT cNames,
526 LCID lcid, DISPID *rgDispId)
528 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
529 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
530 lcid, rgDispId);
533 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
534 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
535 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
537 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
538 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
539 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
542 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
544 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
545 UINT16 type = -1;
547 TRACE("(%p)->(%p)\n", This, p);
549 nsIDOMNode_GetNodeType(This->nsnode, &type);
551 switch(type) {
552 case ELEMENT_NODE:
553 *p = 1;
554 break;
555 case TEXT_NODE:
556 *p = 3;
557 break;
558 case COMMENT_NODE:
559 case DOCUMENT_TYPE_NODE:
560 *p = 8;
561 break;
562 case DOCUMENT_NODE:
563 *p = 9;
564 break;
565 case DOCUMENT_FRAGMENT_NODE:
566 *p = 11;
567 break;
568 default:
570 * FIXME:
571 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
572 * It needs more tests.
574 FIXME("type %u\n", type);
575 *p = 0;
578 return S_OK;
581 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
583 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
584 HTMLDOMNode *node;
585 nsIDOMNode *nsnode;
586 nsresult nsres;
587 HRESULT hres;
589 TRACE("(%p)->(%p)\n", This, p);
591 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
592 if(NS_FAILED(nsres)) {
593 ERR("GetParentNode failed: %08lx\n", nsres);
594 return E_FAIL;
597 if(!nsnode) {
598 *p = NULL;
599 return S_OK;
602 hres = get_node(nsnode, TRUE, &node);
603 nsIDOMNode_Release(nsnode);
604 if(FAILED(hres))
605 return hres;
607 *p = &node->IHTMLDOMNode_iface;
608 return S_OK;
611 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
613 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
614 cpp_bool has_child = FALSE;
615 nsresult nsres;
617 TRACE("(%p)->(%p)\n", This, fChildren);
619 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
620 if(NS_FAILED(nsres))
621 ERR("HasChildNodes failed: %08lx\n", nsres);
623 *fChildren = variant_bool(has_child);
624 return S_OK;
627 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
629 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
630 nsIDOMNodeList *nslist;
631 HRESULT hres;
633 TRACE("(%p)->(%p)\n", This, p);
635 hres = map_nsresult(nsIDOMNode_GetChildNodes(This->nsnode, &nslist));
636 if(FAILED(hres)) {
637 ERR("GetChildNodes failed: %08lx\n", hres);
638 return hres;
641 hres = create_child_collection(nslist, dispex_compat_mode(&This->event_target.dispex),
642 (IHTMLDOMChildrenCollection**)p);
643 nsIDOMNodeList_Release(nslist);
644 return hres;
647 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
649 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
650 HTMLAttributeCollection *col;
651 HRESULT hres;
653 TRACE("(%p)->(%p)\n", This, p);
655 if(This->vtbl->get_attr_col) {
656 hres = This->vtbl->get_attr_col(This, &col);
657 if(FAILED(hres))
658 return hres;
660 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
661 return S_OK;
664 *p = NULL;
665 return S_OK;
668 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
669 VARIANT refChild, IHTMLDOMNode **node)
671 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
672 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
673 nsIDOMNode *nsnode;
674 nsresult nsres;
675 HRESULT hres = S_OK;
677 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
679 new_child = get_node_obj(newChild);
680 if(!new_child) {
681 ERR("invalid newChild\n");
682 return E_INVALIDARG;
685 switch(V_VT(&refChild)) {
686 case VT_NULL:
687 break;
688 case VT_DISPATCH: {
689 IHTMLDOMNode *ref_iface;
691 if(!V_DISPATCH(&refChild))
692 break;
694 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
695 if(FAILED(hres))
696 break;
698 ref_node = get_node_obj(ref_iface);
699 IHTMLDOMNode_Release(ref_iface);
700 if(!ref_node) {
701 ERR("unvalid node\n");
702 hres = E_FAIL;
703 break;
705 break;
707 default:
708 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
709 hres = E_NOTIMPL;
712 if(SUCCEEDED(hres)) {
713 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
714 if(NS_FAILED(nsres)) {
715 ERR("InsertBefore failed: %08lx\n", nsres);
716 hres = E_FAIL;
719 node_release(new_child);
720 if(ref_node)
721 node_release(ref_node);
722 if(FAILED(hres))
723 return hres;
725 hres = get_node(nsnode, TRUE, &node_obj);
726 nsIDOMNode_Release(nsnode);
727 if(FAILED(hres))
728 return hres;
730 *node = &node_obj->IHTMLDOMNode_iface;
731 return S_OK;
734 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
735 IHTMLDOMNode **node)
737 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
738 HTMLDOMNode *node_obj;
739 nsIDOMNode *nsnode;
740 nsresult nsres;
741 HRESULT hres;
743 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
745 node_obj = get_node_obj(oldChild);
746 if(!node_obj)
747 return E_FAIL;
749 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
750 node_release(node_obj);
751 if(NS_FAILED(nsres)) {
752 ERR("RemoveChild failed: %08lx\n", nsres);
753 return E_FAIL;
756 hres = get_node(nsnode, TRUE, &node_obj);
757 nsIDOMNode_Release(nsnode);
758 if(FAILED(hres))
759 return hres;
761 /* FIXME: Make sure that node != newChild */
762 *node = &node_obj->IHTMLDOMNode_iface;
763 return S_OK;
766 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
767 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
769 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
770 HTMLDOMNode *node_new, *node_old, *ret_node;
771 nsIDOMNode *nsnode;
772 nsresult nsres;
773 HRESULT hres;
775 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
777 node_new = get_node_obj(newChild);
778 if(!node_new)
779 return E_FAIL;
781 node_old = get_node_obj(oldChild);
782 if(!node_old) {
783 node_release(node_new);
784 return E_FAIL;
787 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
788 node_release(node_new);
789 node_release(node_old);
790 if(NS_FAILED(nsres))
791 return E_FAIL;
793 hres = get_node(nsnode, TRUE, &ret_node);
794 nsIDOMNode_Release(nsnode);
795 if(FAILED(hres))
796 return hres;
798 *node = &ret_node->IHTMLDOMNode_iface;
799 return S_OK;
802 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
803 IHTMLDOMNode **clonedNode)
805 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
806 HTMLDOMNode *new_node;
807 nsIDOMNode *nsnode;
808 nsresult nsres;
809 HRESULT hres;
811 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
813 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
814 if(NS_FAILED(nsres) || !nsnode) {
815 ERR("CloneNode failed: %08lx\n", nsres);
816 return E_FAIL;
819 hres = This->vtbl->clone(This, nsnode, &new_node);
820 nsIDOMNode_Release(nsnode);
821 if(FAILED(hres))
822 return hres;
824 *clonedNode = &new_node->IHTMLDOMNode_iface;
825 return S_OK;
828 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
829 IHTMLDOMNode **removed)
831 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
832 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
833 return E_NOTIMPL;
836 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
837 IHTMLDOMNode **swappedNode)
839 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
840 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
841 return E_NOTIMPL;
844 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
845 IHTMLDOMNode **replaced)
847 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
848 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
849 return E_NOTIMPL;
852 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
853 IHTMLDOMNode **node)
855 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
856 HTMLDOMNode *node_obj;
857 nsIDOMNode *nsnode;
858 nsresult nsres;
859 HRESULT hres;
861 TRACE("(%p)->(%p %p)\n", This, newChild, node);
863 node_obj = get_node_obj(newChild);
864 if(!node_obj)
865 return E_FAIL;
867 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
868 node_release(node_obj);
869 if(NS_FAILED(nsres)) {
870 ERR("AppendChild failed: %08lx\n", nsres);
871 return E_FAIL;
874 hres = get_node(nsnode, TRUE, &node_obj);
875 nsIDOMNode_Release(nsnode);
876 if(FAILED(hres))
877 return hres;
879 /* FIXME: Make sure that node != newChild */
880 *node = &node_obj->IHTMLDOMNode_iface;
881 return S_OK;
884 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
886 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
887 nsAString name;
888 nsresult nsres;
890 TRACE("(%p)->(%p)\n", This, p);
892 nsAString_Init(&name, NULL);
893 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
894 return return_nsstr(nsres, &name, p);
897 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
899 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
901 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
903 switch(V_VT(&v)) {
904 case VT_BSTR: {
905 nsAString val_str;
907 nsAString_InitDepend(&val_str, V_BSTR(&v));
908 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
909 nsAString_Finish(&val_str);
911 return S_OK;
914 default:
915 FIXME("unsupported value %s\n", debugstr_variant(&v));
918 return E_NOTIMPL;
921 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
923 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
924 const PRUnichar *val;
925 nsAString val_str;
927 TRACE("(%p)->(%p)\n", This, p);
929 nsAString_Init(&val_str, NULL);
930 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
931 nsAString_GetData(&val_str, &val);
933 if(*val) {
934 V_VT(p) = VT_BSTR;
935 V_BSTR(p) = SysAllocString(val);
936 }else {
937 V_VT(p) = VT_NULL;
940 nsAString_Finish(&val_str);
942 return S_OK;
945 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
947 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
948 nsIDOMNode *nschild = NULL;
949 HTMLDOMNode *node;
950 HRESULT hres;
952 TRACE("(%p)->(%p)\n", This, p);
954 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
955 if(!nschild) {
956 *p = NULL;
957 return S_OK;
960 hres = get_node(nschild, TRUE, &node);
961 nsIDOMNode_Release(nschild);
962 if(FAILED(hres))
963 return hres;
965 *p = &node->IHTMLDOMNode_iface;
966 return S_OK;
969 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
971 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
972 nsIDOMNode *nschild = NULL;
973 HTMLDOMNode *node;
974 HRESULT hres;
976 TRACE("(%p)->(%p)\n", This, p);
978 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
979 if(!nschild) {
980 *p = NULL;
981 return S_OK;
984 hres = get_node(nschild, TRUE, &node);
985 nsIDOMNode_Release(nschild);
986 if(FAILED(hres))
987 return hres;
989 *p = &node->IHTMLDOMNode_iface;
990 return S_OK;
993 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
995 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
996 nsIDOMNode *nschild = NULL;
997 HTMLDOMNode *node;
998 HRESULT hres;
1000 TRACE("(%p)->(%p)\n", This, p);
1002 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
1003 if(!nschild) {
1004 *p = NULL;
1005 return S_OK;
1008 hres = get_node(nschild, TRUE, &node);
1009 nsIDOMNode_Release(nschild);
1010 if(FAILED(hres))
1011 return hres;
1013 *p = &node->IHTMLDOMNode_iface;
1014 return S_OK;
1017 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1019 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1020 nsIDOMNode *nssibling = NULL;
1021 HTMLDOMNode *node;
1022 HRESULT hres;
1024 TRACE("(%p)->(%p)\n", This, p);
1026 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1027 if(!nssibling) {
1028 *p = NULL;
1029 return S_OK;
1032 hres = get_node(nssibling, TRUE, &node);
1033 nsIDOMNode_Release(nssibling);
1034 if(FAILED(hres))
1035 return hres;
1037 *p = &node->IHTMLDOMNode_iface;
1038 return S_OK;
1041 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1042 HTMLDOMNode_QueryInterface,
1043 HTMLDOMNode_AddRef,
1044 HTMLDOMNode_Release,
1045 HTMLDOMNode_GetTypeInfoCount,
1046 HTMLDOMNode_GetTypeInfo,
1047 HTMLDOMNode_GetIDsOfNames,
1048 HTMLDOMNode_Invoke,
1049 HTMLDOMNode_get_nodeType,
1050 HTMLDOMNode_get_parentNode,
1051 HTMLDOMNode_hasChildNodes,
1052 HTMLDOMNode_get_childNodes,
1053 HTMLDOMNode_get_attributes,
1054 HTMLDOMNode_insertBefore,
1055 HTMLDOMNode_removeChild,
1056 HTMLDOMNode_replaceChild,
1057 HTMLDOMNode_cloneNode,
1058 HTMLDOMNode_removeNode,
1059 HTMLDOMNode_swapNode,
1060 HTMLDOMNode_replaceNode,
1061 HTMLDOMNode_appendChild,
1062 HTMLDOMNode_get_nodeName,
1063 HTMLDOMNode_put_nodeValue,
1064 HTMLDOMNode_get_nodeValue,
1065 HTMLDOMNode_get_firstChild,
1066 HTMLDOMNode_get_lastChild,
1067 HTMLDOMNode_get_previousSibling,
1068 HTMLDOMNode_get_nextSibling
1071 HTMLDOMNode *unsafe_impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
1073 return iface->lpVtbl == &HTMLDOMNodeVtbl ? impl_from_IHTMLDOMNode(iface) : NULL;
1076 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1078 HTMLDOMNode *ret;
1080 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1081 return NULL;
1083 ret = impl_from_IHTMLDOMNode(iface);
1084 node_addref(ret);
1085 return ret;
1088 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1090 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1093 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1094 REFIID riid, void **ppv)
1096 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1098 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1101 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1103 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1105 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1108 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1110 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1112 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1115 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1117 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1118 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1121 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1122 LCID lcid, ITypeInfo **ppTInfo)
1124 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1125 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1128 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1129 LPOLESTR *rgszNames, UINT cNames,
1130 LCID lcid, DISPID *rgDispId)
1132 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1133 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1134 lcid, rgDispId);
1137 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1138 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1139 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1141 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1142 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1143 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1146 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1148 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1150 TRACE("(%p)->(%p)\n", This, p);
1152 /* FIXME: Better check for document node */
1153 if(This == &This->doc->node) {
1154 *p = NULL;
1155 }else {
1156 *p = (IDispatch*)&This->doc->IHTMLDocument2_iface;
1157 IDispatch_AddRef(*p);
1159 return S_OK;
1162 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1163 HTMLDOMNode2_QueryInterface,
1164 HTMLDOMNode2_AddRef,
1165 HTMLDOMNode2_Release,
1166 HTMLDOMNode2_GetTypeInfoCount,
1167 HTMLDOMNode2_GetTypeInfo,
1168 HTMLDOMNode2_GetIDsOfNames,
1169 HTMLDOMNode2_Invoke,
1170 HTMLDOMNode2_get_ownerDocument
1173 static inline HTMLDOMNode *impl_from_IHTMLDOMNode3(IHTMLDOMNode3 *iface)
1175 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode3_iface);
1178 static HRESULT WINAPI HTMLDOMNode3_QueryInterface(IHTMLDOMNode3 *iface, REFIID riid, void **ppv)
1180 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1181 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1184 static ULONG WINAPI HTMLDOMNode3_AddRef(IHTMLDOMNode3 *iface)
1186 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1188 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1191 static ULONG WINAPI HTMLDOMNode3_Release(IHTMLDOMNode3 *iface)
1193 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1195 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1198 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfoCount(IHTMLDOMNode3 *iface, UINT *pctinfo)
1200 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1201 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1204 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfo(IHTMLDOMNode3 *iface, UINT iTInfo,
1205 LCID lcid, ITypeInfo **ppTInfo)
1207 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1208 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1211 static HRESULT WINAPI HTMLDOMNode3_GetIDsOfNames(IHTMLDOMNode3 *iface, REFIID riid,
1212 LPOLESTR *rgszNames, UINT cNames,
1213 LCID lcid, DISPID *rgDispId)
1215 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1216 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1217 lcid, rgDispId);
1220 static HRESULT WINAPI HTMLDOMNode3_Invoke(IHTMLDOMNode3 *iface, DISPID dispIdMember,
1221 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1222 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1224 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1225 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1226 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1229 static HRESULT WINAPI HTMLDOMNode3_put_prefix(IHTMLDOMNode3 *iface, VARIANT v)
1231 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1232 FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1233 return E_NOTIMPL;
1236 static HRESULT WINAPI HTMLDOMNode3_get_prefix(IHTMLDOMNode3 *iface, VARIANT *p)
1238 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1239 FIXME("(%p)->(%p)\n", This, p);
1240 return E_NOTIMPL;
1243 static HRESULT WINAPI HTMLDOMNode3_get_localName(IHTMLDOMNode3 *iface, VARIANT *p)
1245 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1246 FIXME("(%p)->(%p)\n", This, p);
1247 return E_NOTIMPL;
1250 static HRESULT WINAPI HTMLDOMNode3_get_namespaceURI(IHTMLDOMNode3 *iface, VARIANT *p)
1252 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1253 nsAString nsstr;
1254 nsresult nsres;
1256 TRACE("(%p)->(%p)\n", This, p);
1258 nsAString_InitDepend(&nsstr, NULL);
1259 nsres = nsIDOMNode_GetNamespaceURI(This->nsnode, &nsstr);
1260 return return_nsstr_variant(nsres, &nsstr, 0, p);
1263 static HRESULT WINAPI HTMLDOMNode3_put_textContent(IHTMLDOMNode3 *iface, VARIANT v)
1265 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1266 nsAString nsstr;
1267 nsresult nsres;
1269 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1271 variant_to_nsstr(&v, FALSE, &nsstr);
1272 nsres = nsIDOMNode_SetTextContent(This->nsnode, &nsstr);
1273 nsAString_Finish(&nsstr);
1274 if(NS_FAILED(nsres)) {
1275 ERR("SetTextContent failed: %08lx\n", nsres);
1276 return E_FAIL;
1279 return S_OK;
1282 static HRESULT WINAPI HTMLDOMNode3_get_textContent(IHTMLDOMNode3 *iface, VARIANT *p)
1284 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1285 nsAString nsstr;
1286 nsresult nsres;
1288 TRACE("(%p)->(%p)\n", This, p);
1290 nsAString_Init(&nsstr, NULL);
1291 nsres = nsIDOMNode_GetTextContent(This->nsnode, &nsstr);
1292 return return_nsstr_variant(nsres, &nsstr, 0, p);
1295 static HRESULT WINAPI HTMLDOMNode3_isEqualNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isEqual)
1297 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1298 FIXME("(%p)->()\n", This);
1299 return E_NOTIMPL;
1302 static HRESULT WINAPI HTMLDOMNode3_lookupNamespaceURI(IHTMLDOMNode3 *iface, VARIANT *prefix, VARIANT *namespaceURI)
1304 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1305 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(prefix), namespaceURI);
1306 return E_NOTIMPL;
1309 static HRESULT WINAPI HTMLDOMNode3_lookupPrefix(IHTMLDOMNode3 *iface, VARIANT *namespaceURI, VARIANT *prefix)
1311 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1312 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(namespaceURI), prefix);
1313 return E_NOTIMPL;
1316 static HRESULT WINAPI HTMLDOMNode3_isDefaultNamespace(IHTMLDOMNode3 *iface, VARIANT *namespace, VARIANT_BOOL *pfDefaultNamespace)
1318 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1319 FIXME("(%p)->()\n", This);
1320 return E_NOTIMPL;
1323 static HRESULT WINAPI HTMLDOMNode3_appendChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode **node)
1325 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1326 TRACE("(%p)->()\n", This);
1327 return IHTMLDOMNode_appendChild(&This->IHTMLDOMNode_iface, newChild, node);
1330 static HRESULT WINAPI HTMLDOMNode3_insertBefore(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, VARIANT refChild, IHTMLDOMNode **node)
1332 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1333 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
1334 return IHTMLDOMNode_insertBefore(&This->IHTMLDOMNode_iface, newChild, refChild, node);
1337 static HRESULT WINAPI HTMLDOMNode3_removeChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1339 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1340 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
1341 return IHTMLDOMNode_removeChild(&This->IHTMLDOMNode_iface, oldChild, node);
1344 static HRESULT WINAPI HTMLDOMNode3_replaceChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1346 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1347 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
1348 return IHTMLDOMNode_replaceChild(&This->IHTMLDOMNode_iface, newChild, oldChild, node);
1351 static HRESULT WINAPI HTMLDOMNode3_isSameNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isSame)
1353 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1354 FIXME("(%p)->()\n", This);
1355 return E_NOTIMPL;
1358 static HRESULT WINAPI HTMLDOMNode3_compareDocumentPosition(IHTMLDOMNode3 *iface, IHTMLDOMNode *otherNode, USHORT *flags)
1360 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1361 HTMLDOMNode *other;
1362 UINT16 position;
1363 nsresult nsres;
1365 TRACE("(%p)->()\n", This);
1367 other = get_node_obj(otherNode);
1368 if(!other)
1369 return E_INVALIDARG;
1371 nsres = nsIDOMNode_CompareDocumentPosition(This->nsnode, other->nsnode, &position);
1372 IHTMLDOMNode_Release(&other->IHTMLDOMNode_iface);
1373 if(NS_FAILED(nsres)) {
1374 ERR("failed: %08lx\n", nsres);
1375 return E_FAIL;
1378 *flags = position;
1379 return S_OK;
1382 static HRESULT WINAPI HTMLDOMNode3_isSupported(IHTMLDOMNode3 *iface, BSTR feature, VARIANT version, VARIANT_BOOL *pfisSupported)
1384 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1385 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_variant(&version), pfisSupported);
1386 return E_NOTIMPL;
1389 static const IHTMLDOMNode3Vtbl HTMLDOMNode3Vtbl = {
1390 HTMLDOMNode3_QueryInterface,
1391 HTMLDOMNode3_AddRef,
1392 HTMLDOMNode3_Release,
1393 HTMLDOMNode3_GetTypeInfoCount,
1394 HTMLDOMNode3_GetTypeInfo,
1395 HTMLDOMNode3_GetIDsOfNames,
1396 HTMLDOMNode3_Invoke,
1397 HTMLDOMNode3_put_prefix,
1398 HTMLDOMNode3_get_prefix,
1399 HTMLDOMNode3_get_localName,
1400 HTMLDOMNode3_get_namespaceURI,
1401 HTMLDOMNode3_put_textContent,
1402 HTMLDOMNode3_get_textContent,
1403 HTMLDOMNode3_isEqualNode,
1404 HTMLDOMNode3_lookupNamespaceURI,
1405 HTMLDOMNode3_lookupPrefix,
1406 HTMLDOMNode3_isDefaultNamespace,
1407 HTMLDOMNode3_appendChild,
1408 HTMLDOMNode3_insertBefore,
1409 HTMLDOMNode3_removeChild,
1410 HTMLDOMNode3_replaceChild,
1411 HTMLDOMNode3_isSameNode,
1412 HTMLDOMNode3_compareDocumentPosition,
1413 HTMLDOMNode3_isSupported
1416 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
1418 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
1420 if(IsEqualGUID(&IID_IUnknown, riid)) {
1421 *ppv = &This->IHTMLDOMNode_iface;
1422 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1423 *ppv = &This->IHTMLDOMNode_iface;
1424 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1425 *ppv = &This->IHTMLDOMNode_iface;
1426 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1427 *ppv = &This->IHTMLDOMNode2_iface;
1428 }else if(IsEqualGUID(&IID_IHTMLDOMNode3, riid)) {
1429 *ppv = &This->IHTMLDOMNode3_iface;
1430 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1431 *ppv = &node_ccp;
1432 return S_OK;
1433 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1434 *ppv = &This->IHTMLDOMNode_iface;
1435 return S_OK;
1436 }else {
1437 return EventTarget_QI(&This->event_target, riid, ppv);
1440 IUnknown_AddRef((IUnknown*)*ppv);
1441 return S_OK;
1444 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1446 release_event_target(&This->event_target);
1447 if(This->nsnode)
1448 nsIDOMNode_Release(This->nsnode);
1449 if(This->doc && &This->doc->node != This)
1450 IHTMLDOMNode_Release(&This->doc->node.IHTMLDOMNode_iface);
1453 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1455 return create_node(This->doc, nsnode, ret);
1458 void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
1460 if(mode >= COMPAT_MODE_IE9)
1461 dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL);
1463 EventTarget_init_dispex_info(info, mode);
1466 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1468 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1469 NULL,
1470 HTMLDOMNode_QI,
1471 HTMLDOMNode_destructor,
1472 HTMLDOMNode_cpc,
1473 HTMLDOMNode_clone
1476 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode, dispex_static_data_t *dispex_data)
1478 nsresult nsres;
1480 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1481 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1482 node->IHTMLDOMNode3_iface.lpVtbl = &HTMLDOMNode3Vtbl;
1484 ccref_init(&node->ccref, 1);
1485 EventTarget_Init(&node->event_target, (IUnknown*)&node->IHTMLDOMNode_iface, dispex_data, doc->document_mode);
1487 if(&doc->node != node)
1488 IHTMLDOMNode_AddRef(&doc->node.IHTMLDOMNode_iface);
1489 node->doc = doc;
1491 nsIDOMNode_AddRef(nsnode);
1492 node->nsnode = nsnode;
1494 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1495 assert(nsres == NS_OK);
1498 static const tid_t HTMLDOMNode_iface_tids[] = {
1499 IHTMLDOMNode_tid,
1502 static dispex_static_data_t HTMLDOMNode_dispex = {
1503 L"Node",
1504 NULL,
1505 IHTMLDOMNode_tid,
1506 HTMLDOMNode_iface_tids,
1507 HTMLDOMNode_init_dispex_info
1510 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1512 UINT16 node_type;
1513 HRESULT hres;
1515 nsIDOMNode_GetNodeType(nsnode, &node_type);
1517 switch(node_type) {
1518 case ELEMENT_NODE: {
1519 HTMLElement *elem;
1520 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1521 if(FAILED(hres))
1522 return hres;
1523 *ret = &elem->node;
1524 break;
1526 case TEXT_NODE:
1527 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1528 if(FAILED(hres))
1529 return hres;
1530 break;
1531 case DOCUMENT_TYPE_NODE:
1532 if(dispex_compat_mode(&doc->node.event_target.dispex) >= COMPAT_MODE_IE9) {
1533 hres = create_doctype_node(doc, nsnode, ret);
1534 if(FAILED(hres))
1535 return hres;
1536 break;
1538 /* doctype nodes are represented as comment nodes in quirks mode */
1539 /* fall through */
1540 case COMMENT_NODE: {
1541 HTMLElement *comment;
1542 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1543 if(FAILED(hres))
1544 return hres;
1545 *ret = &comment->node;
1546 break;
1548 case ATTRIBUTE_NODE:
1549 ERR("Called on attribute node\n");
1550 return E_UNEXPECTED;
1551 default: {
1552 HTMLDOMNode *node;
1554 FIXME("unimplemented node type %u\n", node_type);
1556 node = calloc(1, sizeof(HTMLDOMNode));
1557 if(!node)
1558 return E_OUTOFMEMORY;
1560 node->vtbl = &HTMLDOMNodeImplVtbl;
1561 HTMLDOMNode_Init(doc, node, nsnode, &HTMLDOMNode_dispex);
1562 *ret = node;
1566 TRACE("type %d ret %p\n", node_type, *ret);
1567 return S_OK;
1570 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1572 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1574 TRACE("%p\n", This);
1576 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1578 if(This->nsnode)
1579 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1580 if(This->doc && &This->doc->node != This)
1581 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1582 dispex_traverse(&This->event_target.dispex, cb);
1584 if(This->vtbl->traverse)
1585 This->vtbl->traverse(This, cb);
1587 return NS_OK;
1590 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1592 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1594 TRACE("%p\n", This);
1596 if(This->vtbl->unlink)
1597 This->vtbl->unlink(This);
1599 dispex_unlink(&This->event_target.dispex);
1601 if(This->nsnode) {
1602 nsIDOMNode *nsnode = This->nsnode;
1603 This->nsnode = NULL;
1604 nsIDOMNode_Release(nsnode);
1607 if(This->doc && &This->doc->node != This) {
1608 HTMLDocumentNode *doc = This->doc;
1609 This->doc = NULL;
1610 IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface);
1611 }else {
1612 This->doc = NULL;
1615 return NS_OK;
1618 static void NSAPI HTMLDOMNode_delete_cycle_collectable(void *p)
1620 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1622 TRACE("(%p)\n", This);
1624 if(This->vtbl->unlink)
1625 This->vtbl->unlink(This);
1626 This->vtbl->destructor(This);
1627 release_dispex(&This->event_target.dispex);
1628 free(This);
1631 void init_node_cc(void)
1633 static const CCObjCallback node_ccp_callback = {
1634 HTMLDOMNode_traverse,
1635 HTMLDOMNode_unlink,
1636 HTMLDOMNode_delete_cycle_collectable
1639 ccp_init(&node_ccp, &node_ccp_callback);
1642 HRESULT get_node(nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1644 nsIDOMDocument *dom_document;
1645 HTMLDocumentNode *document;
1646 nsISupports *unk = NULL;
1647 nsresult nsres;
1648 HRESULT hres;
1650 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1651 assert(nsres == NS_OK);
1653 if(unk) {
1654 *ret = get_node_obj((IHTMLDOMNode*)unk);
1655 nsISupports_Release(unk);
1656 return NS_OK;
1659 if(!create) {
1660 *ret = NULL;
1661 return S_OK;
1664 nsres = nsIDOMNode_GetOwnerDocument(nsnode, &dom_document);
1665 if(NS_FAILED(nsres) || !dom_document) {
1666 ERR("GetOwnerDocument failed: %08lx\n", nsres);
1667 return E_FAIL;
1670 hres = get_document_node(dom_document, &document);
1671 nsIDOMDocument_Release(dom_document);
1672 if(!document)
1673 return E_FAIL;
1675 hres = create_node(document, nsnode, ret);
1676 IHTMLDOMNode_Release(&document->node.IHTMLDOMNode_iface);
1677 return hres;