mlang/tests: Reduce the size of the test output a little.
[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     FIXME("(%p)->(%p)\n", This, p);
471     return E_NOTIMPL;
472 }
473
474 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
475 {
476     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
477     nsIDOMNode *nschild = NULL;
478
479     TRACE("(%p)->(%p)\n", This, p);
480
481     nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
482     if(nschild) {
483         *p = HTMLDOMNODE(get_node(This->doc, nschild, TRUE));
484         IHTMLDOMNode_AddRef(*p);
485     }else {
486         *p = NULL;
487     }
488
489     return S_OK;
490 }
491
492 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
493 {
494     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
495     FIXME("(%p)->(%p)\n", This, p);
496     return E_NOTIMPL;
497 }
498
499 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
500 {
501     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
502     FIXME("(%p)->(%p)\n", This, p);
503     return E_NOTIMPL;
504 }
505
506 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
507 {
508     HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
509     FIXME("(%p)->(%p)\n", This, p);
510     return E_NOTIMPL;
511 }
512
513 #undef HTMLDOMNODE_THIS
514
515 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
516     HTMLDOMNode_QueryInterface,
517     HTMLDOMNode_AddRef,
518     HTMLDOMNode_Release,
519     HTMLDOMNode_GetTypeInfoCount,
520     HTMLDOMNode_GetTypeInfo,
521     HTMLDOMNode_GetIDsOfNames,
522     HTMLDOMNode_Invoke,
523     HTMLDOMNode_get_nodeType,
524     HTMLDOMNode_get_parentNode,
525     HTMLDOMNode_hasChildNodes,
526     HTMLDOMNode_get_childNodes,
527     HTMLDOMNode_get_attributes,
528     HTMLDOMNode_insertBefore,
529     HTMLDOMNode_removeChild,
530     HTMLDOMNode_replaceChild,
531     HTMLDOMNode_cloneNode,
532     HTMLDOMNode_removeNode,
533     HTMLDOMNode_swapNode,
534     HTMLDOMNode_replaceNode,
535     HTMLDOMNode_appendChild,
536     HTMLDOMNode_get_nodeName,
537     HTMLDOMNode_put_nodeValue,
538     HTMLDOMNode_get_nodeValue,
539     HTMLDOMNode_get_firstChild,
540     HTMLDOMNode_get_lastChild,
541     HTMLDOMNode_get_previousSibling,
542     HTMLDOMNode_get_nextSibling
543 };
544
545 #define HTMLDOMNODE2_THIS(iface) DEFINE_THIS(HTMLDOMNode, HTMLDOMNode2, iface)
546
547 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
548         REFIID riid, void **ppv)
549 {
550     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
551
552     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(This), riid, ppv);
553 }
554
555 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
556 {
557     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
558
559     return IHTMLDOMNode_AddRef(HTMLDOMNODE(This));
560 }
561
562 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
563 {
564     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
565
566     return IHTMLDOMNode_Release(HTMLDOMNODE(This));
567 }
568
569 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
570 {
571     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
572     FIXME("(%p)->(%p)\n", This, pctinfo);
573     return E_NOTIMPL;
574 }
575
576 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
577         LCID lcid, ITypeInfo **ppTInfo)
578 {
579     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
580     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
581     return E_NOTIMPL;
582 }
583
584 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
585                                                 LPOLESTR *rgszNames, UINT cNames,
586                                                 LCID lcid, DISPID *rgDispId)
587 {
588     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
589     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
590           lcid, rgDispId);
591     return E_NOTIMPL;
592 }
593
594 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
595         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
596         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
597 {
598     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
599     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
600             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
601     return E_NOTIMPL;
602 }
603
604 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
605 {
606     HTMLDOMNode *This = HTMLDOMNODE2_THIS(iface);
607     FIXME("(%p)->(%p)\n", This, p);
608     return E_NOTIMPL;
609 }
610
611 #undef HTMLDOMNODE2_THIS
612
613 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
614     HTMLDOMNode2_QueryInterface,
615     HTMLDOMNode2_AddRef,
616     HTMLDOMNode2_Release,
617     HTMLDOMNode2_GetTypeInfoCount,
618     HTMLDOMNode2_GetTypeInfo,
619     HTMLDOMNode2_GetIDsOfNames,
620     HTMLDOMNode2_Invoke,
621     HTMLDOMNode2_get_ownerDocument
622 };
623
624 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
625 {
626     *ppv = NULL;
627
628     if(IsEqualGUID(&IID_IUnknown, riid)) {
629         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
630         *ppv = HTMLDOMNODE(This);
631     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
632         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
633         *ppv = HTMLDOMNODE(This);
634     }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
635         if(This->dispex.data) {
636             TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
637             *ppv = DISPATCHEX(&This->dispex);
638         }else {
639             FIXME("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
640             return E_NOINTERFACE;
641         }
642     }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
643         TRACE("(%p)->(IID_IHTMLDOMNode %p)\n", This, ppv);
644         *ppv = HTMLDOMNODE(This);
645     }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
646         TRACE("(%p)->(IID_IHTMLDOMNode2 %p)\n", This, ppv);
647         *ppv = HTMLDOMNODE2(This);
648     }
649
650     if(*ppv) {
651         IUnknown_AddRef((IUnknown*)*ppv);
652         return S_OK;
653     }
654
655     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
656     return E_NOINTERFACE;
657 }
658
659 void HTMLDOMNode_destructor(HTMLDOMNode *This)
660 {
661     if(This->nsnode)
662         nsIDOMNode_Release(This->nsnode);
663     if(This->event_target)
664         release_event_target(This->event_target);
665 }
666
667 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
668     HTMLDOMNode_QI,
669     HTMLDOMNode_destructor
670 };
671
672 static HTMLDOMNode *create_node(HTMLDocument *doc, nsIDOMNode *nsnode)
673 {
674     HTMLDOMNode *ret;
675     PRUint16 node_type;
676
677     nsIDOMNode_GetNodeType(nsnode, &node_type);
678
679     switch(node_type) {
680     case ELEMENT_NODE:
681         ret = &HTMLElement_Create(nsnode)->node;
682         break;
683     case TEXT_NODE:
684         ret = HTMLDOMTextNode_Create(nsnode);
685         break;
686     case COMMENT_NODE:
687         ret = &HTMLCommentElement_Create(nsnode)->node;
688         break;
689     default:
690         ret = heap_alloc_zero(sizeof(HTMLDOMNode));
691         ret->vtbl = &HTMLDOMNodeImplVtbl;
692     }
693
694     ret->lpHTMLDOMNodeVtbl = &HTMLDOMNodeVtbl;
695     ret->lpHTMLDOMNode2Vtbl = &HTMLDOMNode2Vtbl;
696     ret->ref = 1;
697     ret->doc = doc;
698
699     nsIDOMNode_AddRef(nsnode);
700     ret->nsnode = nsnode;
701
702     TRACE("type %d ret %p\n", node_type, ret);
703
704     return ret;
705 }
706
707 /*
708  * FIXME
709  * List looks really ugly here. We should use a better data structure or
710  * (better) find a way to store HTMLDOMelement pointer in nsIDOMNode.
711  */
712
713 HTMLDOMNode *get_node(HTMLDocument *This, nsIDOMNode *nsnode, BOOL create)
714 {
715     HTMLDOMNode *iter = This->nodes, *ret;
716
717     while(iter) {
718         if(iter->nsnode == nsnode)
719             break;
720         iter = iter->next;
721     }
722
723     if(iter || !create)
724         return iter;
725
726     ret = create_node(This, nsnode);
727
728     ret->next = This->nodes;
729     This->nodes = ret;
730
731     return ret;
732 }
733
734 void release_nodes(HTMLDocument *This)
735 {
736     HTMLDOMNode *iter, *next;
737
738     if(!This->nodes)
739         return;
740
741     for(iter = This->nodes; iter; iter = next) {
742         next = iter->next;
743         iter->doc = NULL;
744         IHTMLDOMNode_Release(HTMLDOMNODE(iter));
745     }
746 }