msi: Fix a typo.
[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 dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
197     NULL,
198     DispDOMChildrenCollection_tid,
199     NULL,
200     {
201         IHTMLDOMChildrenCollection_tid,
202         0
203     }
204 };
205
206 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocument *doc, nsIDOMNodeList *nslist)
207 {
208     HTMLDOMChildrenCollection *ret;
209
210     ret = heap_alloc_zero(sizeof(*ret));
211     ret->lpIHTMLDOMChildrenCollectionVtbl = &HTMLDOMChildrenCollectionVtbl;
212     ret->ref = 1;
213
214     nsIDOMNodeList_AddRef(nslist);
215     ret->nslist = nslist;
216     ret->doc = doc;
217
218     init_dispex(&ret->dispex, (IUnknown*)HTMLCHILDCOL(ret), &HTMLDOMChildrenCollection_dispex);
219
220     return HTMLCHILDCOL(ret);
221 }
222
223 #define HTMLDOMNODE_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode, iface)
224
225 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
226                                                  REFIID riid, void **ppv)
227 {
228     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
229
230     return This->vtbl->qi(This, riid, ppv);
231 }
232
233 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
234 {
235     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
236     LONG ref = InterlockedIncrement(&This->ref);
237
238     TRACE("(%p) ref=%d\n", This, ref);
239
240     return ref;
241 }
242
243 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
244 {
245     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
246     LONG ref = InterlockedDecrement(&This->ref);
247
248     TRACE("(%p) ref=%d\n", This, ref);
249
250     if(!ref) {
251         This->vtbl->destructor(This);
252         heap_free(This);
253     }
254
255     return ref;
256 }
257
258 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
259 {
260     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
261     FIXME("(%p)->(%p)\n", This, pctinfo);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
266                                               LCID lcid, ITypeInfo **ppTInfo)
267 {
268     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
269     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
270     return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
274                                                 LPOLESTR *rgszNames, UINT cNames,
275                                                 LCID lcid, DISPID *rgDispId)
276 {
277     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
278     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
279                                         lcid, rgDispId);
280     return E_NOTIMPL;
281 }
282
283 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
284                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
285                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
286 {
287     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
288     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
289             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
290     return E_NOTIMPL;
291 }
292
293 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, long *p)
294 {
295     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
296     PRUint16 type = -1;
297
298     TRACE("(%p)->(%p)\n", This, p);
299
300     nsIDOMNode_GetNodeType(This->nsnode, &type);
301
302     switch(type) {
303     case ELEMENT_NODE:
304         *p = 1;
305         break;
306     case TEXT_NODE:
307         *p = 3;
308         break;
309     case COMMENT_NODE:
310         *p = 8;
311         break;
312     default:
313         /*
314          * FIXME:
315          * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
316          * It needs more tests.
317          */
318         FIXME("type %u\n", type);
319         *p = 0;
320     }
321
322     return S_OK;
323 }
324
325 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
326 {
327     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
328     FIXME("(%p)->(%p)\n", This, p);
329     return E_NOTIMPL;
330 }
331
332 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
333 {
334     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
335     FIXME("(%p)->(%p)\n", This, fChildren);
336     return E_NOTIMPL;
337 }
338
339 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
340 {
341     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
342     nsIDOMNodeList *nslist;
343     nsresult nsres;
344
345     TRACE("(%p)->(%p)\n", This, p);
346
347     nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
348     if(NS_FAILED(nsres)) {
349         ERR("GetChildNodes failed: %08x\n", nsres);
350         return E_FAIL;
351     }
352
353     *p = (IDispatch*)create_child_collection(This->doc, nslist);
354     nsIDOMNodeList_Release(nslist);
355
356     return S_OK;
357 }
358
359 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
360 {
361     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
362     FIXME("(%p)->(%p)\n", This, p);
363     return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
367                                                VARIANT refChild, IHTMLDOMNode **node)
368 {
369     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
370     FIXME("(%p)->(%p v %p)\n", This, newChild, node);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
375                                               IHTMLDOMNode **node)
376 {
377     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
378     FIXME("(%p)->(%p %p)\n", This, newChild, node);
379     return E_NOTIMPL;
380 }
381
382 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
383                                                IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
384 {
385     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
386     FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
387     return E_NOTIMPL;
388 }
389
390 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
391                                             IHTMLDOMNode **clonedNode)
392 {
393     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
394     FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode);
395     return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
399                                              IHTMLDOMNode **removed)
400 {
401     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
402     FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
403     return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
407                                            IHTMLDOMNode **swappedNode)
408 {
409     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
410     FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
411     return E_NOTIMPL;
412 }
413
414 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
415                                               IHTMLDOMNode **replaced)
416 {
417     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
418     FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
419     return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
423                                               IHTMLDOMNode **node)
424 {
425     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
426     FIXME("(%p)->(%p %p)\n", This, newChild, node);
427     return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
431 {
432     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
433
434     TRACE("(%p)->(%p)\n", This, p);
435
436     *p = NULL;
437
438     if(This->nsnode) {
439         nsAString name_str;
440         const PRUnichar *name;
441         nsresult nsres;
442
443         nsAString_Init(&name_str, NULL);
444         nsres = nsIDOMNode_GetNodeName(This->nsnode, &name_str);
445
446         if(NS_SUCCEEDED(nsres)) {
447             nsAString_GetData(&name_str, &name);
448             *p = SysAllocString(name);
449         }else {
450             ERR("GetNodeName failed: %08x\n", nsres);
451         }
452
453         nsAString_Finish(&name_str);
454     }
455
456     return S_OK;
457 }
458
459 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
460 {
461     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
462     FIXME("(%p)->()\n", This);
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
467 {
468     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
469     FIXME("(%p)->(%p)\n", This, p);
470     return E_NOTIMPL;
471 }
472
473 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
474 {
475     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
476     nsIDOMNode *nschild = NULL;
477
478     TRACE("(%p)->(%p)\n", This, p);
479
480     nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
481     if(nschild) {
482         *p = HTMLDOMNODE(get_node(This->doc, nschild, TRUE));
483         IHTMLDOMNode_AddRef(*p);
484     }else {
485         *p = NULL;
486     }
487
488     return S_OK;
489 }
490
491 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
492 {
493     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
494     FIXME("(%p)->(%p)\n", This, p);
495     return E_NOTIMPL;
496 }
497
498 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
499 {
500     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
501     FIXME("(%p)->(%p)\n", This, p);
502     return E_NOTIMPL;
503 }
504
505 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
506 {
507     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
508     FIXME("(%p)->(%p)\n", This, p);
509     return E_NOTIMPL;
510 }
511
512 #undef HTMLDOMNODE_THIS
513
514 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
515     HTMLDOMNode_QueryInterface,
516     HTMLDOMNode_AddRef,
517     HTMLDOMNode_Release,
518     HTMLDOMNode_GetTypeInfoCount,
519     HTMLDOMNode_GetTypeInfo,
520     HTMLDOMNode_GetIDsOfNames,
521     HTMLDOMNode_Invoke,
522     HTMLDOMNode_get_nodeType,
523     HTMLDOMNode_get_parentNode,
524     HTMLDOMNode_hasChildNodes,
525     HTMLDOMNode_get_childNodes,
526     HTMLDOMNode_get_attributes,
527     HTMLDOMNode_insertBefore,
528     HTMLDOMNode_removeChild,
529     HTMLDOMNode_replaceChild,
530     HTMLDOMNode_cloneNode,
531     HTMLDOMNode_removeNode,
532     HTMLDOMNode_swapNode,
533     HTMLDOMNode_replaceNode,
534     HTMLDOMNode_appendChild,
535     HTMLDOMNode_get_nodeName,
536     HTMLDOMNode_put_nodeValue,
537     HTMLDOMNode_get_nodeValue,
538     HTMLDOMNode_get_firstChild,
539     HTMLDOMNode_get_lastChild,
540     HTMLDOMNode_get_previousSibling,
541     HTMLDOMNode_get_nextSibling
542 };
543
544 #define HTMLDOMNODE2_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode2, iface)
545
546 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
547         REFIID riid, void **ppv)
548 {
549     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
550
551     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(This), riid, ppv);
552 }
553
554 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
555 {
556     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
557
558     return IHTMLDOMNode_AddRef(HTMLDOMNODE(This));
559 }
560
561 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
562 {
563     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
564
565     return IHTMLDOMNode_Release(HTMLDOMNODE(This));
566 }
567
568 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
569 {
570     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
571     FIXME("(%p)->(%p)\n", This, pctinfo);
572     return E_NOTIMPL;
573 }
574
575 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
576         LCID lcid, ITypeInfo **ppTInfo)
577 {
578     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
579     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
580     return E_NOTIMPL;
581 }
582
583 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
584                                                 LPOLESTR *rgszNames, UINT cNames,
585                                                 LCID lcid, DISPID *rgDispId)
586 {
587     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
588     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
589           lcid, rgDispId);
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
594         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
595         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
596 {
597     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
598     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
599             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
600     return E_NOTIMPL;
601 }
602
603 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
604 {
605     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
606     FIXME("(%p)->(%p)\n", This, p);
607     return E_NOTIMPL;
608 }
609
610 #undef HTMLDOMNODE2_THIS
611
612 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
613     HTMLDOMNode2_QueryInterface,
614     HTMLDOMNode2_AddRef,
615     HTMLDOMNode2_Release,
616     HTMLDOMNode2_GetTypeInfoCount,
617     HTMLDOMNode2_GetTypeInfo,
618     HTMLDOMNode2_GetIDsOfNames,
619     HTMLDOMNode2_Invoke,
620     HTMLDOMNode2_get_ownerDocument
621 };
622
623 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
624 {
625     *ppv = NULL;
626
627     if(IsEqualGUID(&IID_IUnknown, riid)) {
628         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
629         *ppv = HTMLDOMNODE(This);
630     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
631         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
632         *ppv = HTMLDOMNODE(This);
633     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
634         if(This->dispex.data) {
635             TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
636             *ppv = DISPATCHEX(&This->dispex);
637         }else {
638             FIXME("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
639             return E_NOINTERFACE;
640         }
641     }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
642         TRACE("(%p)->(IID_IHTMLDOMNode %p)\n", This, ppv);
643         *ppv = HTMLDOMNODE(This);
644     }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
645         TRACE("(%p)->(IID_IHTMLDOMNode2 %p)\n", This, ppv);
646         *ppv = HTMLDOMNODE2(This);
647     }
648
649     if(*ppv) {
650         IUnknown_AddRef((IUnknown*)*ppv);
651         return S_OK;
652     }
653
654     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
655     return E_NOINTERFACE;
656 }
657
658 void HTMLDOMNode_destructor(HTMLDOMNode *This)
659 {
660     if(This->nsnode)
661         nsIDOMNode_Release(This->nsnode);
662     if(This->event_target)
663         release_event_target(This->event_target);
664 }
665
666 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
667     HTMLDOMNode_QI,
668     HTMLDOMNode_destructor
669 };
670
671 static HTMLDOMNode *create_node(HTMLDocument *doc, nsIDOMNode *nsnode)
672 {
673     HTMLDOMNode *ret;
674     PRUint16 node_type;
675
676     nsIDOMNode_GetNodeType(nsnode, &node_type);
677
678     switch(node_type) {
679     case ELEMENT_NODE:
680         ret = &HTMLElement_Create(nsnode)->node;
681         break;
682     case TEXT_NODE:
683         ret = HTMLDOMTextNode_Create(nsnode);
684         break;
685     case COMMENT_NODE:
686         ret = &HTMLCommentElement_Create(nsnode)->node;
687         break;
688     default:
689         ret = heap_alloc_zero(sizeof(HTMLDOMNode));
690         ret->vtbl = &HTMLDOMNodeImplVtbl;
691     }
692
693     ret->lpHTMLDOMNodeVtbl = &HTMLDOMNodeVtbl;
694     ret->lpHTMLDOMNode2Vtbl = &HTMLDOMNode2Vtbl;
695     ret->ref = 1;
696     ret->doc = doc;
697
698     nsIDOMNode_AddRef(nsnode);
699     ret->nsnode = nsnode;
700
701     TRACE("type %d ret %p\n", node_type, ret);
702
703     return ret;
704 }
705
706 /*
707  * FIXME
708  * List looks really ugly here. We should use a better data structure or
709  * (better) find a way to store HTMLDOMelement pointer in nsIDOMNode.
710  */
711
712 HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode, BOOL create)
713 {
714     HTMLDOMNode *iter = This->nodes, *ret;
715
716     while(iter) {
717         if(iter->nsnode == nsnode)
718             break;
719         iter = iter->next;
720     }
721
722     if(iter || !create)
723         return iter;
724
725     ret = create_node(This, nsnode);
726
727     ret->next = This->nodes;
728     This->nodes = ret;
729
730     return ret;
731 }
732
733 void release_nodes(HTMLDocument *This)
734 {
735     HTMLDOMNode *iter, *next;
736
737     if(!This->nodes)
738         return;
739
740     for(iter = This->nodes; iter; iter = next) {
741         next = iter->next;
742         iter->doc = NULL;
743         IHTMLDOMNode_Release(HTMLDOMNODE(iter));
744     }
745 }