mshtml: Added IHTMLDOMNode::get_nodeValue implementation.
[wine] / dlls / mshtml / htmlnode.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "ole2.h"
27
28 #include "wine/debug.h"
29
30 #include "mshtml_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
33
34 typedef struct {
35     DispatchEx dispex;
36     const IHTMLDOMChildrenCollectionVtbl  *lpIHTMLDOMChildrenCollectionVtbl;
37
38     LONG ref;
39
40     /* FIXME: implement weak reference */
41     HTMLDocument *doc;
42
43     nsIDOMNodeList *nslist;
44 } HTMLDOMChildrenCollection;
45
46 #define HTMLCHILDCOL(x)  ((IHTMLDOMChildrenCollection*)  &(x)->lpIHTMLDOMChildrenCollectionVtbl)
47
48 #define HTMLCHILDCOL_THIS(iface) DEFINE_THIS(HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection, iface)
49
50 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
51 {
52     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
53
54     *ppv = NULL;
55
56     if(IsEqualGUID(&IID_IUnknown, riid)) {
57         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
58         *ppv = HTMLCHILDCOL(This);
59     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
60         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
61         *ppv = HTMLCHILDCOL(This);
62     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
63         TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
64         *ppv = DISPATCHEX(&This->dispex);
65     }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
66         TRACE("(%p)->(IID_IHTMLDOMChildrenCollection %p)\n", This, ppv);
67         *ppv = HTMLCHILDCOL(This);
68     }
69
70     if(*ppv) {
71         IUnknown_AddRef((IUnknown*)*ppv);
72         return S_OK;
73     }
74
75     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
76     return E_NOINTERFACE;
77 }
78
79 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
80 {
81     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
82     LONG ref = InterlockedIncrement(&This->ref);
83
84     TRACE("(%p) ref=%d\n", This, ref);
85
86     return ref;
87 }
88
89 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
90 {
91     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
92     LONG ref = InterlockedDecrement(&This->ref);
93
94     TRACE("(%p) ref=%d\n", This, ref);
95
96     if(!ref) {
97         nsIDOMNodeList_Release(This->nslist);
98         heap_free(This);
99     }
100
101     return ref;
102 }
103
104 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
105 {
106     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
107     FIXME("(%p)->(%p)\n", This, pctinfo);
108     return E_NOTIMPL;
109 }
110
111 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
112         LCID lcid, ITypeInfo **ppTInfo)
113 {
114     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
115     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
116     return E_NOTIMPL;
117 }
118
119 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
120         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
121 {
122     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
123     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
124           lcid, rgDispId);
125     return E_NOTIMPL;
126 }
127
128 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
129         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
130         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
131 {
132     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
133     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
134           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
135     return E_NOTIMPL;
136 }
137
138 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, long *p)
139 {
140     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
141     PRUint32 length=0;
142
143     TRACE("(%p)->(%p)\n", This, p);
144
145     nsIDOMNodeList_GetLength(This->nslist, &length);
146     *p = length;
147     return S_OK;
148 }
149
150 static HRESULT WINAPI HTMLDOMChildrenCollection__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
151 {
152     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
153     FIXME("(%p)->(%p)\n", This, p);
154     return E_NOTIMPL;
155 }
156
157 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, long index, IDispatch **ppItem)
158 {
159     HTMLDOMChildrenCollection *This = HTMLCHILDCOL_THIS(iface);
160     nsIDOMNode *nsnode = NULL;
161     PRUint32 length=0;
162     nsresult nsres;
163
164     TRACE("(%p)->(%ld %p)\n", This, index, ppItem);
165
166     nsIDOMNodeList_GetLength(This->nslist, &length);
167     if(index < 0 || index > length)
168         return E_INVALIDARG;
169
170     nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
171     if(NS_FAILED(nsres) || !nsnode) {
172         ERR("Item failed: %08x\n", nsres);
173         return E_FAIL;
174     }
175
176     *ppItem = (IDispatch*)get_node(This->doc, nsnode, TRUE);
177     IDispatch_AddRef(*ppItem);
178     return S_OK;
179 }
180
181 #undef HTMLCHILDCOL_THIS
182
183 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
184     HTMLDOMChildrenCollection_QueryInterface,
185     HTMLDOMChildrenCollection_AddRef,
186     HTMLDOMChildrenCollection_Release,
187     HTMLDOMChildrenCollection_GetTypeInfoCount,
188     HTMLDOMChildrenCollection_GetTypeInfo,
189     HTMLDOMChildrenCollection_GetIDsOfNames,
190     HTMLDOMChildrenCollection_Invoke,
191     HTMLDOMChildrenCollection_get_length,
192     HTMLDOMChildrenCollection__newEnum,
193     HTMLDOMChildrenCollection_item
194 };
195
196 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
197     IHTMLDOMChildrenCollection_tid,
198     0
199 };
200 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
201     NULL,
202     DispDOMChildrenCollection_tid,
203     NULL,
204     HTMLDOMChildrenCollection_iface_tids
205 };
206
207 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocument *doc, nsIDOMNodeList *nslist)
208 {
209     HTMLDOMChildrenCollection *ret;
210
211     ret = heap_alloc_zero(sizeof(*ret));
212     ret->lpIHTMLDOMChildrenCollectionVtbl = &HTMLDOMChildrenCollectionVtbl;
213     ret->ref = 1;
214
215     nsIDOMNodeList_AddRef(nslist);
216     ret->nslist = nslist;
217     ret->doc = doc;
218
219     init_dispex(&ret->dispex, (IUnknown*)HTMLCHILDCOL(ret), &HTMLDOMChildrenCollection_dispex);
220
221     return HTMLCHILDCOL(ret);
222 }
223
224 #define HTMLDOMNODE_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode, iface)
225
226 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
227                                                  REFIID riid, void **ppv)
228 {
229     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
230
231     return This->vtbl->qi(This, riid, ppv);
232 }
233
234 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
235 {
236     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
237     LONG ref = InterlockedIncrement(&This->ref);
238
239     TRACE("(%p) ref=%d\n", This, ref);
240
241     return ref;
242 }
243
244 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
245 {
246     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
247     LONG ref = InterlockedDecrement(&This->ref);
248
249     TRACE("(%p) ref=%d\n", This, ref);
250
251     if(!ref) {
252         This->vtbl->destructor(This);
253         heap_free(This);
254     }
255
256     return ref;
257 }
258
259 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
260 {
261     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
262     FIXME("(%p)->(%p)\n", This, pctinfo);
263     return E_NOTIMPL;
264 }
265
266 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
267                                               LCID lcid, ITypeInfo **ppTInfo)
268 {
269     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
270     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
271     return E_NOTIMPL;
272 }
273
274 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
275                                                 LPOLESTR *rgszNames, UINT cNames,
276                                                 LCID lcid, DISPID *rgDispId)
277 {
278     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
279     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
280                                         lcid, rgDispId);
281     return E_NOTIMPL;
282 }
283
284 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
285                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
286                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
287 {
288     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
289     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
290             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
291     return E_NOTIMPL;
292 }
293
294 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, long *p)
295 {
296     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
297     PRUint16 type = -1;
298
299     TRACE("(%p)->(%p)\n", This, p);
300
301     nsIDOMNode_GetNodeType(This->nsnode, &type);
302
303     switch(type) {
304     case ELEMENT_NODE:
305         *p = 1;
306         break;
307     case TEXT_NODE:
308         *p = 3;
309         break;
310     case COMMENT_NODE:
311         *p = 8;
312         break;
313     default:
314         /*
315          * FIXME:
316          * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
317          * It needs more tests.
318          */
319         FIXME("type %u\n", type);
320         *p = 0;
321     }
322
323     return S_OK;
324 }
325
326 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
327 {
328     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
329     FIXME("(%p)->(%p)\n", This, p);
330     return E_NOTIMPL;
331 }
332
333 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
334 {
335     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
336     FIXME("(%p)->(%p)\n", This, fChildren);
337     return E_NOTIMPL;
338 }
339
340 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
341 {
342     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
343     nsIDOMNodeList *nslist;
344     nsresult nsres;
345
346     TRACE("(%p)->(%p)\n", This, p);
347
348     nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
349     if(NS_FAILED(nsres)) {
350         ERR("GetChildNodes failed: %08x\n", nsres);
351         return E_FAIL;
352     }
353
354     *p = (IDispatch*)create_child_collection(This->doc, nslist);
355     nsIDOMNodeList_Release(nslist);
356
357     return S_OK;
358 }
359
360 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
361 {
362     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
363     FIXME("(%p)->(%p)\n", This, p);
364     return E_NOTIMPL;
365 }
366
367 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
368                                                VARIANT refChild, IHTMLDOMNode **node)
369 {
370     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
371     FIXME("(%p)->(%p v %p)\n", This, newChild, node);
372     return E_NOTIMPL;
373 }
374
375 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
376                                               IHTMLDOMNode **node)
377 {
378     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
379     FIXME("(%p)->(%p %p)\n", This, newChild, node);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
384                                                IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
385 {
386     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
387     FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
388     return E_NOTIMPL;
389 }
390
391 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
392                                             IHTMLDOMNode **clonedNode)
393 {
394     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
395     FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode);
396     return E_NOTIMPL;
397 }
398
399 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
400                                              IHTMLDOMNode **removed)
401 {
402     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
403     FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
404     return E_NOTIMPL;
405 }
406
407 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
408                                            IHTMLDOMNode **swappedNode)
409 {
410     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
411     FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
412     return E_NOTIMPL;
413 }
414
415 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
416                                               IHTMLDOMNode **replaced)
417 {
418     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
419     FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
420     return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
424                                               IHTMLDOMNode **node)
425 {
426     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
427     FIXME("(%p)->(%p %p)\n", This, newChild, node);
428     return E_NOTIMPL;
429 }
430
431 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
432 {
433     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
434
435     TRACE("(%p)->(%p)\n", This, p);
436
437     *p = NULL;
438
439     if(This->nsnode) {
440         nsAString name_str;
441         const PRUnichar *name;
442         nsresult nsres;
443
444         nsAString_Init(&name_str, NULL);
445         nsres = nsIDOMNode_GetNodeName(This->nsnode, &name_str);
446
447         if(NS_SUCCEEDED(nsres)) {
448             nsAString_GetData(&name_str, &name);
449             *p = SysAllocString(name);
450         }else {
451             ERR("GetNodeName failed: %08x\n", nsres);
452         }
453
454         nsAString_Finish(&name_str);
455     }
456
457     return S_OK;
458 }
459
460 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
461 {
462     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
463     FIXME("(%p)->()\n", This);
464     return E_NOTIMPL;
465 }
466
467 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
468 {
469     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
470     const PRUnichar *val;
471     nsAString val_str;
472
473     TRACE("(%p)->(%p)\n", This, p);
474
475     nsAString_Init(&val_str, NULL);
476     nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
477     nsAString_GetData(&val_str, &val);
478
479     if(*val) {
480         V_VT(p) = VT_BSTR;
481         V_BSTR(p) = SysAllocString(val);
482     }else {
483         V_VT(p) = VT_NULL;
484     }
485
486     nsAString_Finish(&val_str);
487
488     return S_OK;
489 }
490
491 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
492 {
493     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
494     nsIDOMNode *nschild = NULL;
495
496     TRACE("(%p)->(%p)\n", This, p);
497
498     nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
499     if(nschild) {
500         *p = HTMLDOMNODE(get_node(This->doc, nschild, TRUE));
501         IHTMLDOMNode_AddRef(*p);
502     }else {
503         *p = NULL;
504     }
505
506     return S_OK;
507 }
508
509 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
510 {
511     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
512     FIXME("(%p)->(%p)\n", This, p);
513     return E_NOTIMPL;
514 }
515
516 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
517 {
518     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
519     FIXME("(%p)->(%p)\n", This, p);
520     return E_NOTIMPL;
521 }
522
523 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
524 {
525     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
526     FIXME("(%p)->(%p)\n", This, p);
527     return E_NOTIMPL;
528 }
529
530 #undef HTMLDOMNODE_THIS
531
532 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
533     HTMLDOMNode_QueryInterface,
534     HTMLDOMNode_AddRef,
535     HTMLDOMNode_Release,
536     HTMLDOMNode_GetTypeInfoCount,
537     HTMLDOMNode_GetTypeInfo,
538     HTMLDOMNode_GetIDsOfNames,
539     HTMLDOMNode_Invoke,
540     HTMLDOMNode_get_nodeType,
541     HTMLDOMNode_get_parentNode,
542     HTMLDOMNode_hasChildNodes,
543     HTMLDOMNode_get_childNodes,
544     HTMLDOMNode_get_attributes,
545     HTMLDOMNode_insertBefore,
546     HTMLDOMNode_removeChild,
547     HTMLDOMNode_replaceChild,
548     HTMLDOMNode_cloneNode,
549     HTMLDOMNode_removeNode,
550     HTMLDOMNode_swapNode,
551     HTMLDOMNode_replaceNode,
552     HTMLDOMNode_appendChild,
553     HTMLDOMNode_get_nodeName,
554     HTMLDOMNode_put_nodeValue,
555     HTMLDOMNode_get_nodeValue,
556     HTMLDOMNode_get_firstChild,
557     HTMLDOMNode_get_lastChild,
558     HTMLDOMNode_get_previousSibling,
559     HTMLDOMNode_get_nextSibling
560 };
561
562 #define HTMLDOMNODE2_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode2, iface)
563
564 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
565         REFIID riid, void **ppv)
566 {
567     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
568
569     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(This), riid, ppv);
570 }
571
572 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
573 {
574     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
575
576     return IHTMLDOMNode_AddRef(HTMLDOMNODE(This));
577 }
578
579 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
580 {
581     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
582
583     return IHTMLDOMNode_Release(HTMLDOMNODE(This));
584 }
585
586 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
587 {
588     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
589     FIXME("(%p)->(%p)\n", This, pctinfo);
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
594         LCID lcid, ITypeInfo **ppTInfo)
595 {
596     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
597     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
598     return E_NOTIMPL;
599 }
600
601 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
602                                                 LPOLESTR *rgszNames, UINT cNames,
603                                                 LCID lcid, DISPID *rgDispId)
604 {
605     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
606     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
607           lcid, rgDispId);
608     return E_NOTIMPL;
609 }
610
611 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
612         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
613         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
614 {
615     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
616     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
617             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
618     return E_NOTIMPL;
619 }
620
621 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
622 {
623     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
624     FIXME("(%p)->(%p)\n", This, p);
625     return E_NOTIMPL;
626 }
627
628 #undef HTMLDOMNODE2_THIS
629
630 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
631     HTMLDOMNode2_QueryInterface,
632     HTMLDOMNode2_AddRef,
633     HTMLDOMNode2_Release,
634     HTMLDOMNode2_GetTypeInfoCount,
635     HTMLDOMNode2_GetTypeInfo,
636     HTMLDOMNode2_GetIDsOfNames,
637     HTMLDOMNode2_Invoke,
638     HTMLDOMNode2_get_ownerDocument
639 };
640
641 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
642 {
643     *ppv = NULL;
644
645     if(IsEqualGUID(&IID_IUnknown, riid)) {
646         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
647         *ppv = HTMLDOMNODE(This);
648     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
649         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
650         *ppv = HTMLDOMNODE(This);
651     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
652         if(This->dispex.data) {
653             TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
654             *ppv = DISPATCHEX(&This->dispex);
655         }else {
656             FIXME("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
657             return E_NOINTERFACE;
658         }
659     }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
660         TRACE("(%p)->(IID_IHTMLDOMNode %p)\n", This, ppv);
661         *ppv = HTMLDOMNODE(This);
662     }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
663         TRACE("(%p)->(IID_IHTMLDOMNode2 %p)\n", This, ppv);
664         *ppv = HTMLDOMNODE2(This);
665     }
666
667     if(*ppv) {
668         IUnknown_AddRef((IUnknown*)*ppv);
669         return S_OK;
670     }
671
672     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
673     return E_NOINTERFACE;
674 }
675
676 void HTMLDOMNode_destructor(HTMLDOMNode *This)
677 {
678     if(This->nsnode)
679         nsIDOMNode_Release(This->nsnode);
680     if(This->event_target)
681         release_event_target(This->event_target);
682 }
683
684 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
685     HTMLDOMNode_QI,
686     HTMLDOMNode_destructor
687 };
688
689 static HTMLDOMNode *create_node(HTMLDocument *doc, nsIDOMNode *nsnode)
690 {
691     HTMLDOMNode *ret;
692     PRUint16 node_type;
693
694     nsIDOMNode_GetNodeType(nsnode, &node_type);
695
696     switch(node_type) {
697     case ELEMENT_NODE:
698         ret = &HTMLElement_Create(nsnode)->node;
699         break;
700     case TEXT_NODE:
701         ret = HTMLDOMTextNode_Create(nsnode);
702         break;
703     case COMMENT_NODE:
704         ret = &HTMLCommentElement_Create(nsnode)->node;
705         break;
706     default:
707         ret = heap_alloc_zero(sizeof(HTMLDOMNode));
708         ret->vtbl = &HTMLDOMNodeImplVtbl;
709     }
710
711     ret->lpHTMLDOMNodeVtbl = &HTMLDOMNodeVtbl;
712     ret->lpHTMLDOMNode2Vtbl = &HTMLDOMNode2Vtbl;
713     ret->ref = 1;
714     ret->doc = doc;
715
716     nsIDOMNode_AddRef(nsnode);
717     ret->nsnode = nsnode;
718
719     TRACE("type %d ret %p\n", node_type, ret);
720
721     return ret;
722 }
723
724 /*
725  * FIXME
726  * List looks really ugly here. We should use a better data structure or
727  * (better) find a way to store HTMLDOMelement pointer in nsIDOMNode.
728  */
729
730 HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode, BOOL create)
731 {
732     HTMLDOMNode *iter = This->nodes, *ret;
733
734     while(iter) {
735         if(iter->nsnode == nsnode)
736             break;
737         iter = iter->next;
738     }
739
740     if(iter || !create)
741         return iter;
742
743     ret = create_node(This, nsnode);
744
745     ret->next = This->nodes;
746     This->nodes = ret;
747
748     return ret;
749 }
750
751 void release_nodes(HTMLDocument *This)
752 {
753     HTMLDOMNode *iter, *next;
754
755     if(!This->nodes)
756         return;
757
758     for(iter = This->nodes; iter; iter = next) {
759         next = iter->next;
760         iter->doc = NULL;
761         IHTMLDOMNode_Release(HTMLDOMNODE(iter));
762     }
763 }