ntdll: Connect syscall frames across user callbacks on x86-64.
[wine.git] / dlls / mshtml / htmlnode.c
blobcc458c82e3258e7fdfc5e95b5dfef6a08c593094
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 typedef struct {
39 DispatchEx dispex;
40 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
42 nsIDOMNodeList *nslist;
43 } HTMLDOMChildrenCollection;
45 typedef struct {
46 IEnumVARIANT IEnumVARIANT_iface;
48 LONG ref;
50 ULONG iter;
51 HTMLDOMChildrenCollection *col;
52 } HTMLDOMChildrenCollectionEnum;
54 static inline HTMLDOMChildrenCollectionEnum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
56 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollectionEnum, IEnumVARIANT_iface);
59 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **ppv)
61 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
63 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
65 if(IsEqualGUID(riid, &IID_IUnknown)) {
66 *ppv = &This->IEnumVARIANT_iface;
67 }else if(IsEqualGUID(riid, &IID_IEnumVARIANT)) {
68 *ppv = &This->IEnumVARIANT_iface;
69 }else {
70 FIXME("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
71 *ppv = NULL;
72 return E_NOINTERFACE;
75 IUnknown_AddRef((IUnknown*)*ppv);
76 return S_OK;
79 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_AddRef(IEnumVARIANT *iface)
81 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
82 LONG ref = InterlockedIncrement(&This->ref);
84 TRACE("(%p) ref=%ld\n", This, ref);
86 return ref;
89 static ULONG WINAPI HTMLDOMChildrenCollectionEnum_Release(IEnumVARIANT *iface)
91 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
92 LONG ref = InterlockedDecrement(&This->ref);
94 TRACE("(%p) ref=%ld\n", This, ref);
96 if(!ref) {
97 IHTMLDOMChildrenCollection_Release(&This->col->IHTMLDOMChildrenCollection_iface);
98 free(This);
101 return ref;
104 static ULONG get_enum_len(HTMLDOMChildrenCollectionEnum *This)
106 UINT32 len;
107 nsresult nsres;
109 nsres = nsIDOMNodeList_GetLength(This->col->nslist, &len);
110 assert(nsres == NS_OK);
111 return len;
114 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Next(IEnumVARIANT *iface, ULONG celt, VARIANT *rgVar, ULONG *pCeltFetched)
116 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
117 ULONG fetched = 0, len;
118 nsIDOMNode *nsnode;
119 HTMLDOMNode *node;
120 nsresult nsres;
121 HRESULT hres;
123 TRACE("(%p)->(%ld %p %p)\n", This, celt, rgVar, pCeltFetched);
125 len = get_enum_len(This);
127 while(This->iter+fetched < len && fetched < celt) {
128 nsres = nsIDOMNodeList_Item(This->col->nslist, This->iter+fetched, &nsnode);
129 assert(nsres == NS_OK);
131 hres = get_node(nsnode, TRUE, &node);
132 nsIDOMNode_Release(nsnode);
133 if(FAILED(hres)) {
134 while(fetched--)
135 VariantClear(rgVar+fetched);
136 return hres;
139 V_VT(rgVar+fetched) = VT_DISPATCH;
140 V_DISPATCH(rgVar+fetched) = (IDispatch*)&node->IHTMLDOMNode_iface;
141 fetched++;
144 This->iter += fetched;
145 if(pCeltFetched)
146 *pCeltFetched = fetched;
147 return fetched == celt ? S_OK : S_FALSE;
150 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Skip(IEnumVARIANT *iface, ULONG celt)
152 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
153 ULONG len;
155 TRACE("(%p)->(%ld)\n", This, celt);
157 len = get_enum_len(This);
158 if(This->iter + celt > len) {
159 This->iter = len;
160 return S_FALSE;
163 This->iter += celt;
164 return S_OK;
167 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Reset(IEnumVARIANT *iface)
169 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
171 TRACE("(%p)->()\n", This);
173 This->iter = 0;
174 return S_OK;
177 static HRESULT WINAPI HTMLDOMChildrenCollectionEnum_Clone(IEnumVARIANT *iface, IEnumVARIANT **ppEnum)
179 HTMLDOMChildrenCollectionEnum *This = impl_from_IEnumVARIANT(iface);
180 FIXME("(%p)->(%p)\n", This, ppEnum);
181 return E_NOTIMPL;
184 static const IEnumVARIANTVtbl HTMLDOMChildrenCollectionEnumVtbl = {
185 HTMLDOMChildrenCollectionEnum_QueryInterface,
186 HTMLDOMChildrenCollectionEnum_AddRef,
187 HTMLDOMChildrenCollectionEnum_Release,
188 HTMLDOMChildrenCollectionEnum_Next,
189 HTMLDOMChildrenCollectionEnum_Skip,
190 HTMLDOMChildrenCollectionEnum_Reset,
191 HTMLDOMChildrenCollectionEnum_Clone
194 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
196 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
199 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
201 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
202 return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
205 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
207 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
208 return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
211 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
213 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
214 return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
217 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
219 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
220 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
223 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
224 LCID lcid, ITypeInfo **ppTInfo)
226 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
227 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
230 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
231 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
233 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
234 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
235 lcid, rgDispId);
238 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
239 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
240 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
242 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
243 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
244 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
247 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
249 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
250 UINT32 length=0;
252 TRACE("(%p)->(%p)\n", This, p);
254 nsIDOMNodeList_GetLength(This->nslist, &length);
255 *p = length;
256 return S_OK;
259 static HRESULT WINAPI HTMLDOMChildrenCollection_get__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
261 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
262 HTMLDOMChildrenCollectionEnum *ret;
264 TRACE("(%p)->(%p)\n", This, p);
266 ret = malloc(sizeof(*ret));
267 if(!ret)
268 return E_OUTOFMEMORY;
270 ret->IEnumVARIANT_iface.lpVtbl = &HTMLDOMChildrenCollectionEnumVtbl;
271 ret->ref = 1;
272 ret->iter = 0;
274 IHTMLDOMChildrenCollection_AddRef(&This->IHTMLDOMChildrenCollection_iface);
275 ret->col = This;
277 *p = (IUnknown*)&ret->IEnumVARIANT_iface;
278 return S_OK;
281 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
283 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
284 nsIDOMNode *nsnode = NULL;
285 HTMLDOMNode *node;
286 UINT32 length=0;
287 nsresult nsres;
288 HRESULT hres;
290 TRACE("(%p)->(%ld %p)\n", This, index, ppItem);
292 if (ppItem)
293 *ppItem = NULL;
294 else
295 return E_POINTER;
297 nsIDOMNodeList_GetLength(This->nslist, &length);
298 if(index < 0 || index >= length)
299 return E_INVALIDARG;
301 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
302 if(NS_FAILED(nsres) || !nsnode) {
303 ERR("Item failed: %08lx\n", nsres);
304 return E_FAIL;
307 hres = get_node(nsnode, TRUE, &node);
308 nsIDOMNode_Release(nsnode);
309 if(FAILED(hres))
310 return hres;
312 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
313 return S_OK;
316 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
317 HTMLDOMChildrenCollection_QueryInterface,
318 HTMLDOMChildrenCollection_AddRef,
319 HTMLDOMChildrenCollection_Release,
320 HTMLDOMChildrenCollection_GetTypeInfoCount,
321 HTMLDOMChildrenCollection_GetTypeInfo,
322 HTMLDOMChildrenCollection_GetIDsOfNames,
323 HTMLDOMChildrenCollection_Invoke,
324 HTMLDOMChildrenCollection_get_length,
325 HTMLDOMChildrenCollection_get__newEnum,
326 HTMLDOMChildrenCollection_item
329 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
331 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
334 static void *HTMLDOMChildrenCollection_query_interface(DispatchEx *dispex, REFIID riid)
336 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
338 if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid))
339 return &This->IHTMLDOMChildrenCollection_iface;
341 return NULL;
344 static void HTMLDOMChildrenCollection_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
346 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
347 if(This->nslist)
348 note_cc_edge((nsISupports*)This->nslist, "nslist", cb);
351 static void HTMLDOMChildrenCollection_unlink(DispatchEx *dispex)
353 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
354 unlink_ref(&This->nslist);
357 static void HTMLDOMChildrenCollection_destructor(DispatchEx *dispex)
359 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
360 free(This);
363 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
365 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
367 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
368 WCHAR *ptr;
369 DWORD idx=0;
370 UINT32 len = 0;
372 for(ptr = name; *ptr && is_digit(*ptr); ptr++)
373 idx = idx*10 + (*ptr-'0');
374 if(*ptr)
375 return DISP_E_UNKNOWNNAME;
377 nsIDOMNodeList_GetLength(This->nslist, &len);
378 if(idx >= len)
379 return DISP_E_UNKNOWNNAME;
381 *dispid = DISPID_CHILDCOL_0 + idx;
382 TRACE("ret %lx\n", *dispid);
383 return S_OK;
386 static HRESULT HTMLDOMChildrenCollection_get_name(DispatchEx *dispex, DISPID id, BSTR *name)
388 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
389 DWORD idx = id - DISPID_CHILDCOL_0;
390 UINT32 len = 0;
391 WCHAR buf[11];
393 nsIDOMNodeList_GetLength(This->nslist, &len);
394 if(idx >= len)
395 return DISP_E_MEMBERNOTFOUND;
397 len = swprintf(buf, ARRAY_SIZE(buf), L"%u", idx);
398 return (*name = SysAllocStringLen(buf, len)) ? S_OK : E_OUTOFMEMORY;
401 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
402 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
404 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
406 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
408 switch(flags) {
409 case DISPATCH_PROPERTYGET: {
410 IDispatch *disp = NULL;
411 HRESULT hres;
413 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
414 id - DISPID_CHILDCOL_0, &disp);
415 if(FAILED(hres))
416 return hres;
418 V_VT(res) = VT_DISPATCH;
419 V_DISPATCH(res) = disp;
420 break;
423 default:
424 FIXME("unimplemented flags %x\n", flags);
425 return E_NOTIMPL;
428 return S_OK;
431 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
432 .query_interface = HTMLDOMChildrenCollection_query_interface,
433 .destructor = HTMLDOMChildrenCollection_destructor,
434 .traverse = HTMLDOMChildrenCollection_traverse,
435 .unlink = HTMLDOMChildrenCollection_unlink,
436 .get_dispid = HTMLDOMChildrenCollection_get_dispid,
437 .get_name = HTMLDOMChildrenCollection_get_name,
438 .invoke = HTMLDOMChildrenCollection_invoke,
441 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
442 IHTMLDOMChildrenCollection_tid,
446 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
447 "NodeList",
448 &HTMLDOMChildrenCollection_dispex_vtbl,
449 DispDOMChildrenCollection_tid,
450 HTMLDOMChildrenCollection_iface_tids,
451 HTMLDOMNode_init_dispex_info
454 HRESULT create_child_collection(nsIDOMNodeList *nslist, compat_mode_t compat_mode, IHTMLDOMChildrenCollection **ret)
456 HTMLDOMChildrenCollection *collection;
458 if(!(collection = calloc(1, sizeof(*collection))))
459 return E_OUTOFMEMORY;
461 collection->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
463 nsIDOMNodeList_AddRef(nslist);
464 collection->nslist = nslist;
466 init_dispatch(&collection->dispex, &HTMLDOMChildrenCollection_dispex, compat_mode);
468 *ret = &collection->IHTMLDOMChildrenCollection_iface;
469 return S_OK;
472 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
474 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
477 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
478 REFIID riid, void **ppv)
480 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
481 return IDispatchEx_QueryInterface(&This->event_target.dispex.IDispatchEx_iface, riid, ppv);
484 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
486 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
487 return IDispatchEx_AddRef(&This->event_target.dispex.IDispatchEx_iface);
490 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
492 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
493 return IDispatchEx_Release(&This->event_target.dispex.IDispatchEx_iface);
496 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
498 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
499 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
502 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
503 LCID lcid, ITypeInfo **ppTInfo)
505 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
506 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
509 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
510 LPOLESTR *rgszNames, UINT cNames,
511 LCID lcid, DISPID *rgDispId)
513 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
514 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
515 lcid, rgDispId);
518 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
519 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
520 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
522 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
523 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
524 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
527 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
529 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
530 UINT16 type = -1;
532 TRACE("(%p)->(%p)\n", This, p);
534 nsIDOMNode_GetNodeType(This->nsnode, &type);
536 switch(type) {
537 case ELEMENT_NODE:
538 *p = 1;
539 break;
540 case TEXT_NODE:
541 *p = 3;
542 break;
543 case COMMENT_NODE:
544 case DOCUMENT_TYPE_NODE:
545 *p = 8;
546 break;
547 case DOCUMENT_NODE:
548 *p = 9;
549 break;
550 case DOCUMENT_FRAGMENT_NODE:
551 *p = 11;
552 break;
553 default:
555 * FIXME:
556 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
557 * It needs more tests.
559 FIXME("type %u\n", type);
560 *p = 0;
563 return S_OK;
566 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
568 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
569 HTMLDOMNode *node;
570 nsIDOMNode *nsnode;
571 nsresult nsres;
572 HRESULT hres;
574 TRACE("(%p)->(%p)\n", This, p);
576 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
577 if(NS_FAILED(nsres)) {
578 ERR("GetParentNode failed: %08lx\n", nsres);
579 return E_FAIL;
582 if(!nsnode) {
583 *p = NULL;
584 return S_OK;
587 hres = get_node(nsnode, TRUE, &node);
588 nsIDOMNode_Release(nsnode);
589 if(FAILED(hres))
590 return hres;
592 *p = &node->IHTMLDOMNode_iface;
593 return S_OK;
596 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
598 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
599 cpp_bool has_child = FALSE;
600 nsresult nsres;
602 TRACE("(%p)->(%p)\n", This, fChildren);
604 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
605 if(NS_FAILED(nsres))
606 ERR("HasChildNodes failed: %08lx\n", nsres);
608 *fChildren = variant_bool(has_child);
609 return S_OK;
612 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
614 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
615 nsIDOMNodeList *nslist;
616 HRESULT hres;
618 TRACE("(%p)->(%p)\n", This, p);
620 hres = map_nsresult(nsIDOMNode_GetChildNodes(This->nsnode, &nslist));
621 if(FAILED(hres)) {
622 ERR("GetChildNodes failed: %08lx\n", hres);
623 return hres;
626 hres = create_child_collection(nslist, dispex_compat_mode(&This->event_target.dispex),
627 (IHTMLDOMChildrenCollection**)p);
628 nsIDOMNodeList_Release(nslist);
629 return hres;
632 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
634 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
635 HTMLAttributeCollection *col;
636 HRESULT hres;
638 TRACE("(%p)->(%p)\n", This, p);
640 if(This->vtbl->get_attr_col) {
641 hres = This->vtbl->get_attr_col(This, &col);
642 if(FAILED(hres))
643 return hres;
645 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
646 return S_OK;
649 *p = NULL;
650 return S_OK;
653 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
654 VARIANT refChild, IHTMLDOMNode **node)
656 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
657 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
658 nsIDOMNode *nsnode;
659 nsresult nsres;
660 HRESULT hres = S_OK;
662 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
664 new_child = get_node_obj(newChild);
665 if(!new_child) {
666 ERR("invalid newChild\n");
667 return E_INVALIDARG;
670 switch(V_VT(&refChild)) {
671 case VT_NULL:
672 break;
673 case VT_DISPATCH: {
674 IHTMLDOMNode *ref_iface;
676 if(!V_DISPATCH(&refChild))
677 break;
679 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
680 if(FAILED(hres))
681 break;
683 ref_node = get_node_obj(ref_iface);
684 IHTMLDOMNode_Release(ref_iface);
685 if(!ref_node) {
686 ERR("unvalid node\n");
687 hres = E_FAIL;
688 break;
690 break;
692 default:
693 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
694 hres = E_NOTIMPL;
697 if(SUCCEEDED(hres)) {
698 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
699 if(NS_FAILED(nsres)) {
700 ERR("InsertBefore failed: %08lx\n", nsres);
701 hres = E_FAIL;
704 node_release(new_child);
705 if(ref_node)
706 node_release(ref_node);
707 if(FAILED(hres))
708 return hres;
710 hres = get_node(nsnode, TRUE, &node_obj);
711 nsIDOMNode_Release(nsnode);
712 if(FAILED(hres))
713 return hres;
715 *node = &node_obj->IHTMLDOMNode_iface;
716 return S_OK;
719 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
720 IHTMLDOMNode **node)
722 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
723 HTMLDOMNode *node_obj;
724 nsIDOMNode *nsnode;
725 nsresult nsres;
726 HRESULT hres;
728 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
730 node_obj = get_node_obj(oldChild);
731 if(!node_obj)
732 return E_FAIL;
734 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
735 node_release(node_obj);
736 if(NS_FAILED(nsres)) {
737 ERR("RemoveChild failed: %08lx\n", nsres);
738 return E_FAIL;
741 hres = get_node(nsnode, TRUE, &node_obj);
742 nsIDOMNode_Release(nsnode);
743 if(FAILED(hres))
744 return hres;
746 /* FIXME: Make sure that node != newChild */
747 *node = &node_obj->IHTMLDOMNode_iface;
748 return S_OK;
751 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
752 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
754 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
755 HTMLDOMNode *node_new, *node_old, *ret_node;
756 nsIDOMNode *nsnode;
757 nsresult nsres;
758 HRESULT hres;
760 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
762 node_new = get_node_obj(newChild);
763 if(!node_new)
764 return E_FAIL;
766 node_old = get_node_obj(oldChild);
767 if(!node_old) {
768 node_release(node_new);
769 return E_FAIL;
772 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
773 node_release(node_new);
774 node_release(node_old);
775 if(NS_FAILED(nsres))
776 return E_FAIL;
778 hres = get_node(nsnode, TRUE, &ret_node);
779 nsIDOMNode_Release(nsnode);
780 if(FAILED(hres))
781 return hres;
783 *node = &ret_node->IHTMLDOMNode_iface;
784 return S_OK;
787 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
788 IHTMLDOMNode **clonedNode)
790 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
791 HTMLDOMNode *new_node;
792 nsIDOMNode *nsnode;
793 nsresult nsres;
794 HRESULT hres;
796 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
798 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
799 if(NS_FAILED(nsres) || !nsnode) {
800 ERR("CloneNode failed: %08lx\n", nsres);
801 return E_FAIL;
804 hres = This->vtbl->clone(This, nsnode, &new_node);
805 nsIDOMNode_Release(nsnode);
806 if(FAILED(hres))
807 return hres;
809 *clonedNode = &new_node->IHTMLDOMNode_iface;
810 return S_OK;
813 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
814 IHTMLDOMNode **removed)
816 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
817 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
818 return E_NOTIMPL;
821 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
822 IHTMLDOMNode **swappedNode)
824 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
825 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
826 return E_NOTIMPL;
829 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
830 IHTMLDOMNode **replaced)
832 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
833 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
834 return E_NOTIMPL;
837 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
838 IHTMLDOMNode **node)
840 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
841 HTMLDOMNode *node_obj;
842 nsIDOMNode *nsnode;
843 nsresult nsres;
844 HRESULT hres;
846 TRACE("(%p)->(%p %p)\n", This, newChild, node);
848 node_obj = get_node_obj(newChild);
849 if(!node_obj)
850 return E_FAIL;
852 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
853 node_release(node_obj);
854 if(NS_FAILED(nsres)) {
855 ERR("AppendChild failed: %08lx\n", nsres);
856 return E_FAIL;
859 hres = get_node(nsnode, TRUE, &node_obj);
860 nsIDOMNode_Release(nsnode);
861 if(FAILED(hres))
862 return hres;
864 /* FIXME: Make sure that node != newChild */
865 *node = &node_obj->IHTMLDOMNode_iface;
866 return S_OK;
869 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
871 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
872 nsAString name;
873 nsresult nsres;
875 TRACE("(%p)->(%p)\n", This, p);
877 nsAString_Init(&name, NULL);
878 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
879 return return_nsstr(nsres, &name, p);
882 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
884 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
886 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
888 switch(V_VT(&v)) {
889 case VT_BSTR: {
890 nsAString val_str;
892 nsAString_InitDepend(&val_str, V_BSTR(&v));
893 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
894 nsAString_Finish(&val_str);
896 return S_OK;
899 default:
900 FIXME("unsupported value %s\n", debugstr_variant(&v));
903 return E_NOTIMPL;
906 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
908 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
909 const PRUnichar *val;
910 nsAString val_str;
912 TRACE("(%p)->(%p)\n", This, p);
914 nsAString_Init(&val_str, NULL);
915 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
916 nsAString_GetData(&val_str, &val);
918 if(*val) {
919 V_VT(p) = VT_BSTR;
920 V_BSTR(p) = SysAllocString(val);
921 }else {
922 V_VT(p) = VT_NULL;
925 nsAString_Finish(&val_str);
927 return S_OK;
930 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
932 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
933 nsIDOMNode *nschild = NULL;
934 HTMLDOMNode *node;
935 HRESULT hres;
937 TRACE("(%p)->(%p)\n", This, p);
939 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
940 if(!nschild) {
941 *p = NULL;
942 return S_OK;
945 hres = get_node(nschild, TRUE, &node);
946 nsIDOMNode_Release(nschild);
947 if(FAILED(hres))
948 return hres;
950 *p = &node->IHTMLDOMNode_iface;
951 return S_OK;
954 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
956 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
957 nsIDOMNode *nschild = NULL;
958 HTMLDOMNode *node;
959 HRESULT hres;
961 TRACE("(%p)->(%p)\n", This, p);
963 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
964 if(!nschild) {
965 *p = NULL;
966 return S_OK;
969 hres = get_node(nschild, TRUE, &node);
970 nsIDOMNode_Release(nschild);
971 if(FAILED(hres))
972 return hres;
974 *p = &node->IHTMLDOMNode_iface;
975 return S_OK;
978 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
980 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
981 nsIDOMNode *nschild = NULL;
982 HTMLDOMNode *node;
983 HRESULT hres;
985 TRACE("(%p)->(%p)\n", This, p);
987 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
988 if(!nschild) {
989 *p = NULL;
990 return S_OK;
993 hres = get_node(nschild, TRUE, &node);
994 nsIDOMNode_Release(nschild);
995 if(FAILED(hres))
996 return hres;
998 *p = &node->IHTMLDOMNode_iface;
999 return S_OK;
1002 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
1004 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
1005 nsIDOMNode *nssibling = NULL;
1006 HTMLDOMNode *node;
1007 HRESULT hres;
1009 TRACE("(%p)->(%p)\n", This, p);
1011 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
1012 if(!nssibling) {
1013 *p = NULL;
1014 return S_OK;
1017 hres = get_node(nssibling, TRUE, &node);
1018 nsIDOMNode_Release(nssibling);
1019 if(FAILED(hres))
1020 return hres;
1022 *p = &node->IHTMLDOMNode_iface;
1023 return S_OK;
1026 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
1027 HTMLDOMNode_QueryInterface,
1028 HTMLDOMNode_AddRef,
1029 HTMLDOMNode_Release,
1030 HTMLDOMNode_GetTypeInfoCount,
1031 HTMLDOMNode_GetTypeInfo,
1032 HTMLDOMNode_GetIDsOfNames,
1033 HTMLDOMNode_Invoke,
1034 HTMLDOMNode_get_nodeType,
1035 HTMLDOMNode_get_parentNode,
1036 HTMLDOMNode_hasChildNodes,
1037 HTMLDOMNode_get_childNodes,
1038 HTMLDOMNode_get_attributes,
1039 HTMLDOMNode_insertBefore,
1040 HTMLDOMNode_removeChild,
1041 HTMLDOMNode_replaceChild,
1042 HTMLDOMNode_cloneNode,
1043 HTMLDOMNode_removeNode,
1044 HTMLDOMNode_swapNode,
1045 HTMLDOMNode_replaceNode,
1046 HTMLDOMNode_appendChild,
1047 HTMLDOMNode_get_nodeName,
1048 HTMLDOMNode_put_nodeValue,
1049 HTMLDOMNode_get_nodeValue,
1050 HTMLDOMNode_get_firstChild,
1051 HTMLDOMNode_get_lastChild,
1052 HTMLDOMNode_get_previousSibling,
1053 HTMLDOMNode_get_nextSibling
1056 HTMLDOMNode *unsafe_impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
1058 return iface->lpVtbl == &HTMLDOMNodeVtbl ? impl_from_IHTMLDOMNode(iface) : NULL;
1061 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
1063 HTMLDOMNode *ret;
1065 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
1066 return NULL;
1068 ret = impl_from_IHTMLDOMNode(iface);
1069 node_addref(ret);
1070 return ret;
1073 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
1075 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
1078 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
1079 REFIID riid, void **ppv)
1081 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1083 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1086 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
1088 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1090 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1093 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
1095 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1097 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1100 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
1102 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1103 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1106 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
1107 LCID lcid, ITypeInfo **ppTInfo)
1109 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1110 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1113 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
1114 LPOLESTR *rgszNames, UINT cNames,
1115 LCID lcid, DISPID *rgDispId)
1117 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1118 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1119 lcid, rgDispId);
1122 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
1123 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1124 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1126 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1127 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1128 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1131 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
1133 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
1135 TRACE("(%p)->(%p)\n", This, p);
1137 /* FIXME: Better check for document node */
1138 if(This == &This->doc->node) {
1139 *p = NULL;
1140 }else {
1141 *p = (IDispatch*)&This->doc->IHTMLDocument2_iface;
1142 IDispatch_AddRef(*p);
1144 return S_OK;
1147 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
1148 HTMLDOMNode2_QueryInterface,
1149 HTMLDOMNode2_AddRef,
1150 HTMLDOMNode2_Release,
1151 HTMLDOMNode2_GetTypeInfoCount,
1152 HTMLDOMNode2_GetTypeInfo,
1153 HTMLDOMNode2_GetIDsOfNames,
1154 HTMLDOMNode2_Invoke,
1155 HTMLDOMNode2_get_ownerDocument
1158 static inline HTMLDOMNode *impl_from_IHTMLDOMNode3(IHTMLDOMNode3 *iface)
1160 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode3_iface);
1163 static HRESULT WINAPI HTMLDOMNode3_QueryInterface(IHTMLDOMNode3 *iface, REFIID riid, void **ppv)
1165 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1166 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
1169 static ULONG WINAPI HTMLDOMNode3_AddRef(IHTMLDOMNode3 *iface)
1171 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1173 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
1176 static ULONG WINAPI HTMLDOMNode3_Release(IHTMLDOMNode3 *iface)
1178 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1180 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
1183 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfoCount(IHTMLDOMNode3 *iface, UINT *pctinfo)
1185 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1186 return IDispatchEx_GetTypeInfoCount(&This->event_target.dispex.IDispatchEx_iface, pctinfo);
1189 static HRESULT WINAPI HTMLDOMNode3_GetTypeInfo(IHTMLDOMNode3 *iface, UINT iTInfo,
1190 LCID lcid, ITypeInfo **ppTInfo)
1192 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1193 return IDispatchEx_GetTypeInfo(&This->event_target.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1196 static HRESULT WINAPI HTMLDOMNode3_GetIDsOfNames(IHTMLDOMNode3 *iface, REFIID riid,
1197 LPOLESTR *rgszNames, UINT cNames,
1198 LCID lcid, DISPID *rgDispId)
1200 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1201 return IDispatchEx_GetIDsOfNames(&This->event_target.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1202 lcid, rgDispId);
1205 static HRESULT WINAPI HTMLDOMNode3_Invoke(IHTMLDOMNode3 *iface, DISPID dispIdMember,
1206 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1207 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1209 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1210 return IDispatchEx_Invoke(&This->event_target.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1211 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1214 static HRESULT WINAPI HTMLDOMNode3_put_prefix(IHTMLDOMNode3 *iface, VARIANT v)
1216 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1217 FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
1218 return E_NOTIMPL;
1221 static HRESULT WINAPI HTMLDOMNode3_get_prefix(IHTMLDOMNode3 *iface, VARIANT *p)
1223 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1224 FIXME("(%p)->(%p)\n", This, p);
1225 return E_NOTIMPL;
1228 static HRESULT WINAPI HTMLDOMNode3_get_localName(IHTMLDOMNode3 *iface, VARIANT *p)
1230 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1231 FIXME("(%p)->(%p)\n", This, p);
1232 return E_NOTIMPL;
1235 static HRESULT WINAPI HTMLDOMNode3_get_namespaceURI(IHTMLDOMNode3 *iface, VARIANT *p)
1237 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1238 nsAString nsstr;
1239 nsresult nsres;
1241 TRACE("(%p)->(%p)\n", This, p);
1243 nsAString_InitDepend(&nsstr, NULL);
1244 nsres = nsIDOMNode_GetNamespaceURI(This->nsnode, &nsstr);
1245 return return_nsstr_variant(nsres, &nsstr, 0, p);
1248 static HRESULT WINAPI HTMLDOMNode3_put_textContent(IHTMLDOMNode3 *iface, VARIANT v)
1250 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1251 nsAString nsstr;
1252 nsresult nsres;
1254 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
1256 variant_to_nsstr(&v, FALSE, &nsstr);
1257 nsres = nsIDOMNode_SetTextContent(This->nsnode, &nsstr);
1258 nsAString_Finish(&nsstr);
1259 if(NS_FAILED(nsres)) {
1260 ERR("SetTextContent failed: %08lx\n", nsres);
1261 return E_FAIL;
1264 return S_OK;
1267 static HRESULT WINAPI HTMLDOMNode3_get_textContent(IHTMLDOMNode3 *iface, VARIANT *p)
1269 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1270 nsAString nsstr;
1271 nsresult nsres;
1273 TRACE("(%p)->(%p)\n", This, p);
1275 nsAString_Init(&nsstr, NULL);
1276 nsres = nsIDOMNode_GetTextContent(This->nsnode, &nsstr);
1277 return return_nsstr_variant(nsres, &nsstr, 0, p);
1280 static HRESULT WINAPI HTMLDOMNode3_isEqualNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isEqual)
1282 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1283 FIXME("(%p)->()\n", This);
1284 return E_NOTIMPL;
1287 static HRESULT WINAPI HTMLDOMNode3_lookupNamespaceURI(IHTMLDOMNode3 *iface, VARIANT *prefix, VARIANT *namespaceURI)
1289 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1290 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(prefix), namespaceURI);
1291 return E_NOTIMPL;
1294 static HRESULT WINAPI HTMLDOMNode3_lookupPrefix(IHTMLDOMNode3 *iface, VARIANT *namespaceURI, VARIANT *prefix)
1296 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1297 FIXME("(%p)->(%s %p)\n", This, debugstr_variant(namespaceURI), prefix);
1298 return E_NOTIMPL;
1301 static HRESULT WINAPI HTMLDOMNode3_isDefaultNamespace(IHTMLDOMNode3 *iface, VARIANT *namespace, VARIANT_BOOL *pfDefaultNamespace)
1303 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1304 FIXME("(%p)->()\n", This);
1305 return E_NOTIMPL;
1308 static HRESULT WINAPI HTMLDOMNode3_appendChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode **node)
1310 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1311 TRACE("(%p)->()\n", This);
1312 return IHTMLDOMNode_appendChild(&This->IHTMLDOMNode_iface, newChild, node);
1315 static HRESULT WINAPI HTMLDOMNode3_insertBefore(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, VARIANT refChild, IHTMLDOMNode **node)
1317 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1318 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
1319 return IHTMLDOMNode_insertBefore(&This->IHTMLDOMNode_iface, newChild, refChild, node);
1322 static HRESULT WINAPI HTMLDOMNode3_removeChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1324 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1325 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
1326 return IHTMLDOMNode_removeChild(&This->IHTMLDOMNode_iface, oldChild, node);
1329 static HRESULT WINAPI HTMLDOMNode3_replaceChild(IHTMLDOMNode3 *iface, IHTMLDOMNode *newChild, IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
1331 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1332 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
1333 return IHTMLDOMNode_replaceChild(&This->IHTMLDOMNode_iface, newChild, oldChild, node);
1336 static HRESULT WINAPI HTMLDOMNode3_isSameNode(IHTMLDOMNode3 *iface, IHTMLDOMNode3 *otherNode, VARIANT_BOOL *isSame)
1338 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1339 FIXME("(%p)->()\n", This);
1340 return E_NOTIMPL;
1343 static HRESULT WINAPI HTMLDOMNode3_compareDocumentPosition(IHTMLDOMNode3 *iface, IHTMLDOMNode *otherNode, USHORT *flags)
1345 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1346 HTMLDOMNode *other;
1347 UINT16 position;
1348 nsresult nsres;
1350 TRACE("(%p)->()\n", This);
1352 other = get_node_obj(otherNode);
1353 if(!other)
1354 return E_INVALIDARG;
1356 nsres = nsIDOMNode_CompareDocumentPosition(This->nsnode, other->nsnode, &position);
1357 IHTMLDOMNode_Release(&other->IHTMLDOMNode_iface);
1358 if(NS_FAILED(nsres)) {
1359 ERR("failed: %08lx\n", nsres);
1360 return E_FAIL;
1363 *flags = position;
1364 return S_OK;
1367 static HRESULT WINAPI HTMLDOMNode3_isSupported(IHTMLDOMNode3 *iface, BSTR feature, VARIANT version, VARIANT_BOOL *pfisSupported)
1369 HTMLDOMNode *This = impl_from_IHTMLDOMNode3(iface);
1370 FIXME("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_variant(&version), pfisSupported);
1371 return E_NOTIMPL;
1374 static const IHTMLDOMNode3Vtbl HTMLDOMNode3Vtbl = {
1375 HTMLDOMNode3_QueryInterface,
1376 HTMLDOMNode3_AddRef,
1377 HTMLDOMNode3_Release,
1378 HTMLDOMNode3_GetTypeInfoCount,
1379 HTMLDOMNode3_GetTypeInfo,
1380 HTMLDOMNode3_GetIDsOfNames,
1381 HTMLDOMNode3_Invoke,
1382 HTMLDOMNode3_put_prefix,
1383 HTMLDOMNode3_get_prefix,
1384 HTMLDOMNode3_get_localName,
1385 HTMLDOMNode3_get_namespaceURI,
1386 HTMLDOMNode3_put_textContent,
1387 HTMLDOMNode3_get_textContent,
1388 HTMLDOMNode3_isEqualNode,
1389 HTMLDOMNode3_lookupNamespaceURI,
1390 HTMLDOMNode3_lookupPrefix,
1391 HTMLDOMNode3_isDefaultNamespace,
1392 HTMLDOMNode3_appendChild,
1393 HTMLDOMNode3_insertBefore,
1394 HTMLDOMNode3_removeChild,
1395 HTMLDOMNode3_replaceChild,
1396 HTMLDOMNode3_isSameNode,
1397 HTMLDOMNode3_compareDocumentPosition,
1398 HTMLDOMNode3_isSupported
1401 static inline HTMLDOMNode *HTMLDOMNode_from_DispatchEx(DispatchEx *iface)
1403 return CONTAINING_RECORD(iface, HTMLDOMNode, event_target.dispex);
1406 void *HTMLDOMNode_query_interface(DispatchEx *dispex, REFIID riid)
1408 HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex);
1410 if(IsEqualGUID(&IID_IUnknown, riid))
1411 return &This->IHTMLDOMNode_iface;
1412 if(IsEqualGUID(&IID_IDispatch, riid))
1413 return &This->IHTMLDOMNode_iface;
1414 if(IsEqualGUID(&IID_IHTMLDOMNode, riid))
1415 return &This->IHTMLDOMNode_iface;
1416 if(IsEqualGUID(&IID_IHTMLDOMNode2, riid))
1417 return &This->IHTMLDOMNode2_iface;
1418 if(IsEqualGUID(&IID_IHTMLDOMNode3, riid))
1419 return &This->IHTMLDOMNode3_iface;
1421 return EventTarget_query_interface(&This->event_target, riid);
1424 void HTMLDOMNode_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
1426 HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex);
1428 traverse_event_target(&This->event_target, cb);
1429 if(This->nsnode)
1430 note_cc_edge((nsISupports*)This->nsnode, "nsnode", cb);
1431 if(This->doc && &This->doc->node != This)
1432 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "doc", cb);
1435 void HTMLDOMNode_unlink(DispatchEx *dispex)
1437 HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex);
1439 release_event_target(&This->event_target);
1440 unlink_ref(&This->nsnode);
1442 if(This->doc) {
1443 HTMLDocumentNode *doc = This->doc;
1444 This->doc = NULL;
1445 if(&doc->node != This)
1446 IHTMLDOMNode_Release(&doc->node.IHTMLDOMNode_iface);
1450 void HTMLDOMNode_destructor(DispatchEx *dispex)
1452 HTMLDOMNode *This = HTMLDOMNode_from_DispatchEx(dispex);
1453 free(This);
1456 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1458 return create_node(This->doc, nsnode, ret);
1461 void HTMLDOMNode_init_dispex_info(dispex_data_t *info, compat_mode_t mode)
1463 if(mode >= COMPAT_MODE_IE9)
1464 dispex_info_add_interface(info, IHTMLDOMNode3_tid, NULL);
1466 EventTarget_init_dispex_info(info, mode);
1469 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1471 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1472 .cpc_entries = HTMLDOMNode_cpc,
1473 .clone = 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 EventTarget_Init(&node->event_target, dispex_data, doc->document_mode);
1486 if(&doc->node != node)
1487 IHTMLDOMNode_AddRef(&doc->node.IHTMLDOMNode_iface);
1488 node->doc = doc;
1490 nsIDOMNode_AddRef(nsnode);
1491 node->nsnode = nsnode;
1493 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1494 assert(nsres == NS_OK);
1497 static const dispex_static_data_vtbl_t HTMLDOMNode_dispex_vtbl = {
1498 .query_interface = HTMLDOMNode_query_interface,
1499 .destructor = HTMLDOMNode_destructor,
1500 .traverse = HTMLDOMNode_traverse,
1501 .unlink = HTMLDOMNode_unlink
1504 static const tid_t HTMLDOMNode_iface_tids[] = {
1505 IHTMLDOMNode_tid,
1508 static dispex_static_data_t HTMLDOMNode_dispex = {
1509 "Node",
1510 &HTMLDOMNode_dispex_vtbl,
1511 IHTMLDOMNode_tid,
1512 HTMLDOMNode_iface_tids,
1513 HTMLDOMNode_init_dispex_info
1516 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1518 UINT16 node_type;
1519 HRESULT hres;
1521 nsIDOMNode_GetNodeType(nsnode, &node_type);
1523 switch(node_type) {
1524 case ELEMENT_NODE: {
1525 HTMLElement *elem;
1526 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1527 if(FAILED(hres))
1528 return hres;
1529 *ret = &elem->node;
1530 break;
1532 case TEXT_NODE:
1533 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1534 if(FAILED(hres))
1535 return hres;
1536 break;
1537 case DOCUMENT_TYPE_NODE:
1538 if(dispex_compat_mode(&doc->node.event_target.dispex) >= COMPAT_MODE_IE9) {
1539 hres = create_doctype_node(doc, nsnode, ret);
1540 if(FAILED(hres))
1541 return hres;
1542 break;
1544 /* doctype nodes are represented as comment nodes in quirks mode */
1545 /* fall through */
1546 case COMMENT_NODE: {
1547 HTMLElement *comment;
1548 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1549 if(FAILED(hres))
1550 return hres;
1551 *ret = &comment->node;
1552 break;
1554 case ATTRIBUTE_NODE:
1555 ERR("Called on attribute node\n");
1556 return E_UNEXPECTED;
1557 default: {
1558 HTMLDOMNode *node;
1560 FIXME("unimplemented node type %u\n", node_type);
1562 node = calloc(1, sizeof(HTMLDOMNode));
1563 if(!node)
1564 return E_OUTOFMEMORY;
1566 node->vtbl = &HTMLDOMNodeImplVtbl;
1567 HTMLDOMNode_Init(doc, node, nsnode, &HTMLDOMNode_dispex);
1568 *ret = node;
1572 TRACE("type %d ret %p\n", node_type, *ret);
1573 return S_OK;
1576 HRESULT get_node(nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1578 nsIDOMDocument *dom_document;
1579 HTMLDocumentNode *document;
1580 nsISupports *unk = NULL;
1581 nsresult nsres;
1582 HRESULT hres;
1584 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1585 assert(nsres == NS_OK);
1587 if(unk) {
1588 *ret = get_node_obj((IHTMLDOMNode*)unk);
1589 nsISupports_Release(unk);
1590 return NS_OK;
1593 if(!create) {
1594 *ret = NULL;
1595 return S_OK;
1598 nsres = nsIDOMNode_GetOwnerDocument(nsnode, &dom_document);
1599 if(NS_FAILED(nsres) || !dom_document) {
1600 ERR("GetOwnerDocument failed: %08lx\n", nsres);
1601 return E_FAIL;
1604 hres = get_document_node(dom_document, &document);
1605 nsIDOMDocument_Release(dom_document);
1606 if(!document)
1607 return E_FAIL;
1609 hres = create_node(document, nsnode, ret);
1610 IHTMLDOMNode_Release(&document->node.IHTMLDOMNode_iface);
1611 return hres;