qcap: Cast-qual warnings fix.
[wine] / dlls / mshtml / htmlelem.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 "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winnls.h"
30 #include "ole2.h"
31
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34
35 #include "mshtml_private.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 static HRESULT HTMLElementCollection_Create(IUnknown*,HTMLElement**,DWORD,IDispatch**);
40
41 typedef struct {
42     HTMLElement **buf;
43     DWORD len;
44     DWORD size;
45 } elem_vector;
46
47 static void elem_vector_add(elem_vector *buf, HTMLElement *elem)
48 {
49     if(buf->len == buf->size) {
50         buf->size <<= 1;
51         buf->buf = mshtml_realloc(buf->buf, buf->size*sizeof(HTMLElement**));
52     }
53
54     buf->buf[buf->len++] = elem;
55 }
56
57 #define HTMLELEM_THIS(iface) DEFINE_THIS(HTMLElement, HTMLElement, iface)
58
59 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
60                                                  REFIID riid, void **ppv)
61 {
62     HTMLElement *This = HTMLELEM_THIS(iface);
63     HRESULT hres;
64
65     if(This->impl)
66         return IUnknown_QueryInterface(This->impl, riid, ppv);
67
68     hres = HTMLElement_QI(This, riid, ppv);
69     if(FAILED(hres))
70         WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
71
72     return hres;
73 }
74
75 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
76 {
77     HTMLElement *This = HTMLELEM_THIS(iface);
78
79     if(This->impl)
80         return IUnknown_AddRef(This->impl);
81
82     TRACE("(%p)\n", This);
83     return IHTMLDocument2_AddRef(HTMLDOC(This->node->doc));
84 }
85
86 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
87 {
88     HTMLElement *This = HTMLELEM_THIS(iface);
89
90     if(This->impl)
91         return IUnknown_Release(This->impl);
92
93     TRACE("(%p)\n", This);
94     return IHTMLDocument2_Release(HTMLDOC(This->node->doc));
95 }
96
97 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
98 {
99     HTMLElement *This = HTMLELEM_THIS(iface);
100     FIXME("(%p)->(%p)\n", This, pctinfo);
101     return E_NOTIMPL;
102 }
103
104 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
105                                               LCID lcid, ITypeInfo **ppTInfo)
106 {
107     HTMLElement *This = HTMLELEM_THIS(iface);
108     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
109     return E_NOTIMPL;
110 }
111
112 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
113                                                 LPOLESTR *rgszNames, UINT cNames,
114                                                 LCID lcid, DISPID *rgDispId)
115 {
116     HTMLElement *This = HTMLELEM_THIS(iface);
117     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
118                                         lcid, rgDispId);
119     return E_NOTIMPL;
120 }
121
122 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
123                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
124                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
125 {
126     HTMLElement *This = HTMLELEM_THIS(iface);
127     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
128             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
129     return E_NOTIMPL;
130 }
131
132 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
133                                                VARIANT AttributeValue, LONG lFlags)
134 {
135     HTMLElement *This = HTMLELEM_THIS(iface);
136     FIXME("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
137     return E_NOTIMPL;
138 }
139
140 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
141                                                LONG lFlags, VARIANT *AttributeValue)
142 {
143     HTMLElement *This = HTMLELEM_THIS(iface);
144     nsAString attr_str;
145     nsAString value_str;
146     const PRUnichar *value;
147     nsresult nsres;
148     HRESULT hres = S_OK;
149
150     WARN("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
151
152     nsAString_Init(&attr_str, strAttributeName);
153     nsAString_Init(&value_str, NULL);
154
155     nsres = nsIDOMHTMLElement_GetAttribute(This->nselem, &attr_str, &value_str);
156     nsAString_Finish(&attr_str);
157
158     if(NS_SUCCEEDED(nsres)) {
159         nsAString_GetData(&value_str, &value, NULL);
160         V_VT(AttributeValue) = VT_BSTR;
161         V_BSTR(AttributeValue) = SysAllocString(value);
162         TRACE("attr_value=%s\n", debugstr_w(V_BSTR(AttributeValue)));
163     }else {
164         ERR("GetAttribute failed: %08x\n", nsres);
165         hres = E_FAIL;
166     }
167
168     nsAString_Finish(&value_str);
169
170     return hres;
171 }
172
173 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
174                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
175 {
176     HTMLElement *This = HTMLELEM_THIS(iface);
177     FIXME("(%p)->()\n", This);
178     return E_NOTIMPL;
179 }
180
181 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
182 {
183     HTMLElement *This = HTMLELEM_THIS(iface);
184     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
185     return E_NOTIMPL;
186 }
187
188 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
189 {
190     HTMLElement *This = HTMLELEM_THIS(iface);
191     nsAString class_str;
192     nsresult nsres;
193     HRESULT hres = S_OK;
194
195     TRACE("(%p)->(%p)\n", This, p);
196
197     nsAString_Init(&class_str, NULL);
198     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
199
200     if(NS_SUCCEEDED(nsres)) {
201         const PRUnichar *class;
202         nsAString_GetData(&class_str, &class, NULL);
203         *p = SysAllocString(class);
204     }else {
205         ERR("GetClassName failed: %08x\n", nsres);
206         hres = E_FAIL;
207     }
208
209     nsAString_Finish(&class_str);
210
211     TRACE("className=%s\n", debugstr_w(*p));
212     return hres;
213 }
214
215 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
216 {
217     HTMLElement *This = HTMLELEM_THIS(iface);
218     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
223 {
224     HTMLElement *This = HTMLELEM_THIS(iface);
225     FIXME("(%p)->(%p)\n", This, p);
226     return E_NOTIMPL;
227 }
228
229 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
230 {
231     HTMLElement *This = HTMLELEM_THIS(iface);
232     FIXME("(%p)->(%p)\n", This, p);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
237 {
238     HTMLElement *This = HTMLELEM_THIS(iface);
239     FIXME("(%p)->(%p)\n", This, p);
240     return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
244 {
245     HTMLElement *This = HTMLELEM_THIS(iface);
246     FIXME("(%p)->(%p)\n", This, p);
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
251 {
252     HTMLElement *This = HTMLELEM_THIS(iface);
253     FIXME("(%p)->()\n", This);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
258 {
259     HTMLElement *This = HTMLELEM_THIS(iface);
260     FIXME("(%p)->(%p)\n", This, p);
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
265 {
266     HTMLElement *This = HTMLELEM_THIS(iface);
267     FIXME("(%p)->()\n", This);
268     return E_NOTIMPL;
269 }
270
271 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
272 {
273     HTMLElement *This = HTMLELEM_THIS(iface);
274     FIXME("(%p)->(%p)\n", This, p);
275     return E_NOTIMPL;
276 }
277
278 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
279 {
280     HTMLElement *This = HTMLELEM_THIS(iface);
281     FIXME("(%p)->()\n", This);
282     return E_NOTIMPL;
283 }
284
285 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
286 {
287     HTMLElement *This = HTMLELEM_THIS(iface);
288     FIXME("(%p)->(%p)\n", This, p);
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
293 {
294     HTMLElement *This = HTMLELEM_THIS(iface);
295     FIXME("(%p)->()\n", This);
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
300 {
301     HTMLElement *This = HTMLELEM_THIS(iface);
302     FIXME("(%p)->(%p)\n", This, p);
303     return E_NOTIMPL;
304 }
305
306 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
307 {
308     HTMLElement *This = HTMLELEM_THIS(iface);
309     FIXME("(%p)->()\n", This);
310     return E_NOTIMPL;
311 }
312
313 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
314 {
315     HTMLElement *This = HTMLELEM_THIS(iface);
316     FIXME("(%p)->(%p)\n", This, p);
317     return E_NOTIMPL;
318 }
319
320 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
321 {
322     HTMLElement *This = HTMLELEM_THIS(iface);
323     FIXME("(%p)->()\n", This);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
328 {
329     HTMLElement *This = HTMLELEM_THIS(iface);
330     FIXME("(%p)->(%p)\n", This, p);
331     return E_NOTIMPL;
332 }
333
334 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
335 {
336     HTMLElement *This = HTMLELEM_THIS(iface);
337     FIXME("(%p)->()\n", This);
338     return E_NOTIMPL;
339 }
340
341 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
342 {
343     HTMLElement *This = HTMLELEM_THIS(iface);
344     FIXME("(%p)->(%p)\n", This, p);
345     return E_NOTIMPL;
346 }
347
348 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
349 {
350     HTMLElement *This = HTMLELEM_THIS(iface);
351     FIXME("(%p)->()\n", This);
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
356 {
357     HTMLElement *This = HTMLELEM_THIS(iface);
358     FIXME("(%p)->(%p)\n", This, p);
359     return E_NOTIMPL;
360 }
361
362 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
363 {
364     HTMLElement *This = HTMLELEM_THIS(iface);
365     FIXME("(%p)->()\n", This);
366     return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
370 {
371     HTMLElement *This = HTMLELEM_THIS(iface);
372     FIXME("(%p)->(%p)\n", This, p);
373     return E_NOTIMPL;
374 }
375
376 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
377 {
378     HTMLElement *This = HTMLELEM_THIS(iface);
379     FIXME("(%p)->()\n", This);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
384 {
385     HTMLElement *This = HTMLELEM_THIS(iface);
386     FIXME("(%p)->(%p)\n", This, p);
387     return E_NOTIMPL;
388 }
389
390 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
391 {
392     HTMLElement *This = HTMLELEM_THIS(iface);
393     FIXME("(%p)->()\n", This);
394     return E_NOTIMPL;
395 }
396
397 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
398 {
399     HTMLElement *This = HTMLELEM_THIS(iface);
400     FIXME("(%p)->(%p)\n", This, p);
401     return E_NOTIMPL;
402 }
403
404 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
405 {
406     HTMLElement *This = HTMLELEM_THIS(iface);
407     FIXME("(%p)->(%p)\n", This, p);
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
412 {
413     HTMLElement *This = HTMLELEM_THIS(iface);
414     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
419 {
420     HTMLElement *This = HTMLELEM_THIS(iface);
421     FIXME("(%p)->(%p)\n", This, p);
422     return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
426 {
427     HTMLElement *This = HTMLELEM_THIS(iface);
428     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
429     return E_NOTIMPL;
430 }
431
432 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
433 {
434     HTMLElement *This = HTMLELEM_THIS(iface);
435     FIXME("(%p)->(%p)\n", This, p);
436     return E_NOTIMPL;
437 }
438
439 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
440 {
441     HTMLElement *This = HTMLELEM_THIS(iface);
442     FIXME("(%p)->()\n", This);
443     return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
447 {
448     HTMLElement *This = HTMLELEM_THIS(iface);
449     FIXME("(%p)->(%p)\n", This, p);
450     return E_NOTIMPL;
451 }
452
453 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
454 {
455     HTMLElement *This = HTMLELEM_THIS(iface);
456     FIXME("(%p)->()\n", This);
457     return E_NOTIMPL;
458 }
459
460 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
461                                            VARIANT_BOOL *pfResult)
462 {
463     HTMLElement *This = HTMLELEM_THIS(iface);
464     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
465     return E_NOTIMPL;
466 }
467
468 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, long *p)
469 {
470     HTMLElement *This = HTMLELEM_THIS(iface);
471     FIXME("(%p)->(%p)\n", This, p);
472     return E_NOTIMPL;
473 }
474
475 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
476 {
477     HTMLElement *This = HTMLELEM_THIS(iface);
478     FIXME("(%p)->(%p)\n", This, p);
479     return E_NOTIMPL;
480 }
481
482 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
483 {
484     HTMLElement *This = HTMLELEM_THIS(iface);
485     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
486     return E_NOTIMPL;
487 }
488
489 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
490 {
491     HTMLElement *This = HTMLELEM_THIS(iface);
492     FIXME("(%p)->(%p)\n", This, p);
493     return E_NOTIMPL;
494 }
495
496 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, long *p)
497 {
498     HTMLElement *This = HTMLELEM_THIS(iface);
499     FIXME("(%p)->(%p)\n", This, p);
500     return E_NOTIMPL;
501 }
502
503 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, long *p)
504 {
505     HTMLElement *This = HTMLELEM_THIS(iface);
506     FIXME("(%p)->(%p)\n", This, p);
507     return E_NOTIMPL;
508 }
509
510 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, long *p)
511 {
512     HTMLElement *This = HTMLELEM_THIS(iface);
513     FIXME("(%p)->(%p)\n", This, p);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, long *p)
518 {
519     HTMLElement *This = HTMLELEM_THIS(iface);
520     FIXME("(%p)->(%p)\n", This, p);
521     return E_NOTIMPL;
522 }
523
524 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
525 {
526     HTMLElement *This = HTMLELEM_THIS(iface);
527     FIXME("(%p)->(%p)\n", This, p);
528     return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
532 {
533     HTMLElement *This = HTMLELEM_THIS(iface);
534     nsIDOMNSHTMLElement *nselem;
535     nsAString html_str;
536     nsresult nsres;
537
538     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
539
540     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
541     if(NS_FAILED(nsres)) {
542         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
543         return E_FAIL;
544     }
545
546     nsAString_Init(&html_str, v);
547     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
548     nsAString_Finish(&html_str);
549
550     if(NS_FAILED(nsres)) {
551         FIXME("SetInnerHtml failed %08x\n", nsres);
552         return E_FAIL;
553     }
554
555     return S_OK;
556 }
557
558 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
559 {
560     HTMLElement *This = HTMLELEM_THIS(iface);
561     FIXME("(%p)->(%p)\n", This, p);
562     return E_NOTIMPL;
563 }
564
565 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
566 {
567     HTMLElement *This = HTMLELEM_THIS(iface);
568     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
569     return E_NOTIMPL;
570 }
571
572 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
573 {
574     HTMLElement *This = HTMLELEM_THIS(iface);
575     FIXME("(%p)->(%p)\n", This, p);
576     return E_NOTIMPL;
577 }
578
579 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
580 {
581     HTMLElement *This = HTMLELEM_THIS(iface);
582     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
583     return E_NOTIMPL;
584 }
585
586 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
587 {
588     HTMLElement *This = HTMLELEM_THIS(iface);
589     FIXME("(%p)->(%p)\n", This, p);
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
594 {
595     HTMLElement *This = HTMLELEM_THIS(iface);
596     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
597     return E_NOTIMPL;
598 }
599
600 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
601 {
602     HTMLElement *This = HTMLELEM_THIS(iface);
603     FIXME("(%p)->(%p)\n", This, p);
604     return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
608                                                      BSTR html)
609 {
610     HTMLElement *This = HTMLELEM_THIS(iface);
611     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
612     return E_NOTIMPL;
613 }
614
615 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
616                                                      BSTR text)
617 {
618     HTMLElement *This = HTMLELEM_THIS(iface);
619     FIXME("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
620     return E_NOTIMPL;
621 }
622
623 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
624 {
625     HTMLElement *This = HTMLELEM_THIS(iface);
626     FIXME("(%p)->(%p)\n", This, p);
627     return E_NOTIMPL;
628 }
629
630 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
631 {
632     HTMLElement *This = HTMLELEM_THIS(iface);
633     FIXME("(%p)->(%p)\n", This, p);
634     return E_NOTIMPL;
635 }
636
637 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
638 {
639     HTMLElement *This = HTMLELEM_THIS(iface);
640     FIXME("(%p)\n", This);
641     return E_NOTIMPL;
642 }
643
644 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
645                                               IHTMLFiltersCollection **p)
646 {
647     HTMLElement *This = HTMLELEM_THIS(iface);
648     FIXME("(%p)->(%p)\n", This, p);
649     return E_NOTIMPL;
650 }
651
652 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
653 {
654     HTMLElement *This = HTMLELEM_THIS(iface);
655     FIXME("(%p)->()\n", This);
656     return E_NOTIMPL;
657 }
658
659 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
660 {
661     HTMLElement *This = HTMLELEM_THIS(iface);
662     FIXME("(%p)->(%p)\n", This, p);
663     return E_NOTIMPL;
664 }
665
666 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
667 {
668     HTMLElement *This = HTMLELEM_THIS(iface);
669     FIXME("(%p)->(%p)\n", This, String);
670     return E_NOTIMPL;
671 }
672
673 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
674 {
675     HTMLElement *This = HTMLELEM_THIS(iface);
676     FIXME("(%p)->()\n", This);
677     return E_NOTIMPL;
678 }
679
680 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
681 {
682     HTMLElement *This = HTMLELEM_THIS(iface);
683     FIXME("(%p)->(%p)\n", This, p);
684     return E_NOTIMPL;
685 }
686
687 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
688 {
689     HTMLElement *This = HTMLELEM_THIS(iface);
690     FIXME("(%p)->()\n", This);
691     return E_NOTIMPL;
692 }
693
694 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
695 {
696     HTMLElement *This = HTMLELEM_THIS(iface);
697     FIXME("(%p)->(%p)\n", This, p);
698     return E_NOTIMPL;
699 }
700
701 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
702 {
703     HTMLElement *This = HTMLELEM_THIS(iface);
704     FIXME("(%p)->()\n", This);
705     return E_NOTIMPL;
706 }
707
708 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
709 {
710     HTMLElement *This = HTMLELEM_THIS(iface);
711     FIXME("(%p)->(%p)\n", This, p);
712     return E_NOTIMPL;
713 }
714
715 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
716 {
717     HTMLElement *This = HTMLELEM_THIS(iface);
718     FIXME("(%p)->()\n", This);
719     return E_NOTIMPL;
720 }
721
722 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
723 {
724     HTMLElement *This = HTMLELEM_THIS(iface);
725     FIXME("(%p)->(%p)\n", This, p);
726     return E_NOTIMPL;
727 }
728
729 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
730 {
731     HTMLElement *This = HTMLELEM_THIS(iface);
732     FIXME("(%p)->()\n", This);
733     return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
737 {
738     HTMLElement *This = HTMLELEM_THIS(iface);
739     FIXME("(%p)->(%p)\n", This, p);
740     return E_NOTIMPL;
741 }
742
743 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
744 {
745     HTMLElement *This = HTMLELEM_THIS(iface);
746     FIXME("(%p)->()\n", This);
747     return E_NOTIMPL;
748 }
749
750 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
751 {
752     HTMLElement *This = HTMLELEM_THIS(iface);
753     FIXME("(%p)->(%p)\n", This, p);
754     return E_NOTIMPL;
755 }
756
757 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
758 {
759     HTMLElement *This = HTMLELEM_THIS(iface);
760     FIXME("(%p)->()\n", This);
761     return E_NOTIMPL;
762 }
763
764 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
765 {
766     HTMLElement *This = HTMLELEM_THIS(iface);
767     FIXME("(%p)->(%p)\n", This, p);
768     return E_NOTIMPL;
769 }
770
771 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
772 {
773     HTMLElement *This = HTMLELEM_THIS(iface);
774     FIXME("(%p)->()\n", This);
775     return E_NOTIMPL;
776 }
777
778 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
779 {
780     HTMLElement *This = HTMLELEM_THIS(iface);
781     FIXME("(%p)->(%p)\n", This, p);
782     return E_NOTIMPL;
783 }
784
785 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
786 {
787     HTMLElement *This = HTMLELEM_THIS(iface);
788     FIXME("(%p)->()\n", This);
789     return E_NOTIMPL;
790 }
791
792 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
793 {
794     HTMLElement *This = HTMLELEM_THIS(iface);
795     FIXME("(%p)->(%p)\n", This, p);
796     return E_NOTIMPL;
797 }
798
799 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
800 {
801     HTMLElement *This = HTMLELEM_THIS(iface);
802     FIXME("(%p)->(%p)\n", This, p);
803     return E_NOTIMPL;
804 }
805
806 static void create_all_list(HTMLDocument *doc, HTMLElement *elem, elem_vector *buf)
807 {
808     nsIDOMNodeList *nsnode_list;
809     nsIDOMNode *iter;
810     PRUint32 list_len = 0, i;
811     HTMLDOMNode *node;
812     nsresult nsres;
813
814     nsres = nsIDOMNode_GetChildNodes(elem->node->nsnode, &nsnode_list);
815     if(NS_FAILED(nsres)) {
816         ERR("GetChildNodes failed: %08x\n", nsres);
817         return;
818     }
819
820     nsIDOMNodeList_GetLength(nsnode_list, &list_len);
821     if(!list_len)
822         return;
823
824     for(i=0; i<list_len; i++) {
825         nsres = nsIDOMNodeList_Item(nsnode_list, i, &iter);
826         if(NS_FAILED(nsres)) {
827             ERR("Item failed: %08x\n", nsres);
828             continue;
829         }
830
831         node = get_node(doc, iter);
832         if(node->node_type != NT_HTMLELEM)
833             continue;
834
835         elem_vector_add(buf, (HTMLElement*)node->impl.elem);
836         create_all_list(doc, (HTMLElement*)node->impl.elem, buf);
837     }
838 }
839
840 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
841 {
842     HTMLElement *This = HTMLELEM_THIS(iface);
843     elem_vector buf = {NULL, 0, 8};
844
845     TRACE("(%p)->(%p)\n", This, p);
846
847     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement**));
848
849     create_all_list(This->node->doc, This, &buf);
850
851     if(!buf.len) {
852         mshtml_free(buf.buf);
853         buf.buf = NULL;
854     }else if(buf.size > buf.len) {
855         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement**));
856     }
857
858     return HTMLElementCollection_Create((IUnknown*)HTMLELEM(This), buf.buf, buf.len, p);
859 }
860
861 static void HTMLElement_destructor(IUnknown *iface)
862 {
863     HTMLElement *This = HTMLELEM_THIS(iface);
864
865     if(This->destructor)
866         This->destructor(This->impl);
867
868     if(This->nselem)
869         nsIDOMHTMLElement_Release(This->nselem);
870
871     mshtml_free(This);
872 }
873
874 #undef HTMLELEM_THIS
875
876 static const IHTMLElementVtbl HTMLElementVtbl = {
877     HTMLElement_QueryInterface,
878     HTMLElement_AddRef,
879     HTMLElement_Release,
880     HTMLElement_GetTypeInfoCount,
881     HTMLElement_GetTypeInfo,
882     HTMLElement_GetIDsOfNames,
883     HTMLElement_Invoke,
884     HTMLElement_setAttribute,
885     HTMLElement_getAttribute,
886     HTMLElement_removeAttribute,
887     HTMLElement_put_className,
888     HTMLElement_get_className,
889     HTMLElement_put_id,
890     HTMLElement_get_id,
891     HTMLElement_get_tagName,
892     HTMLElement_get_parentElement,
893     HTMLElement_get_style,
894     HTMLElement_put_onhelp,
895     HTMLElement_get_onhelp,
896     HTMLElement_put_onclick,
897     HTMLElement_get_onclick,
898     HTMLElement_put_ondblclick,
899     HTMLElement_get_ondblclick,
900     HTMLElement_put_onkeydown,
901     HTMLElement_get_onkeydown,
902     HTMLElement_put_onkeyup,
903     HTMLElement_get_onkeyup,
904     HTMLElement_put_onkeypress,
905     HTMLElement_get_onkeypress,
906     HTMLElement_put_onmouseout,
907     HTMLElement_get_onmouseout,
908     HTMLElement_put_onmouseover,
909     HTMLElement_get_onmouseover,
910     HTMLElement_put_onmousemove,
911     HTMLElement_get_onmousemove,
912     HTMLElement_put_onmousedown,
913     HTMLElement_get_onmousedown,
914     HTMLElement_put_onmouseup,
915     HTMLElement_get_onmouseup,
916     HTMLElement_get_document,
917     HTMLElement_put_title,
918     HTMLElement_get_title,
919     HTMLElement_put_language,
920     HTMLElement_get_language,
921     HTMLElement_put_onselectstart,
922     HTMLElement_get_onselectstart,
923     HTMLElement_scrollIntoView,
924     HTMLElement_contains,
925     HTMLElement_get_sourceIndex,
926     HTMLElement_get_recordNumber,
927     HTMLElement_put_lang,
928     HTMLElement_get_lang,
929     HTMLElement_get_offsetLeft,
930     HTMLElement_get_offsetTop,
931     HTMLElement_get_offsetWidth,
932     HTMLElement_get_offsetHeight,
933     HTMLElement_get_offsetParent,
934     HTMLElement_put_innerHTML,
935     HTMLElement_get_innerHTML,
936     HTMLElement_put_innerText,
937     HTMLElement_get_innerText,
938     HTMLElement_put_outerHTML,
939     HTMLElement_get_outerHTML,
940     HTMLElement_put_outerText,
941     HTMLElement_get_outerText,
942     HTMLElement_insertAdjacentHTML,
943     HTMLElement_insertAdjacentText,
944     HTMLElement_get_parentTextEdit,
945     HTMLElement_get_isTextEdit,
946     HTMLElement_click,
947     HTMLElement_get_filters,
948     HTMLElement_put_ondragstart,
949     HTMLElement_get_ondragstart,
950     HTMLElement_toString,
951     HTMLElement_put_onbeforeupdate,
952     HTMLElement_get_onbeforeupdate,
953     HTMLElement_put_onafterupdate,
954     HTMLElement_get_onafterupdate,
955     HTMLElement_put_onerrorupdate,
956     HTMLElement_get_onerrorupdate,
957     HTMLElement_put_onrowexit,
958     HTMLElement_get_onrowexit,
959     HTMLElement_put_onrowenter,
960     HTMLElement_get_onrowenter,
961     HTMLElement_put_ondatasetchanged,
962     HTMLElement_get_ondatasetchanged,
963     HTMLElement_put_ondataavailable,
964     HTMLElement_get_ondataavailable,
965     HTMLElement_put_ondatasetcomplete,
966     HTMLElement_get_ondatasetcomplete,
967     HTMLElement_put_onfilterchange,
968     HTMLElement_get_onfilterchange,
969     HTMLElement_get_children,
970     HTMLElement_get_all
971 };
972
973 HRESULT HTMLElement_QI(HTMLElement *This, REFIID riid, void **ppv)
974 {
975     *ppv =  NULL;
976
977     if(IsEqualGUID(&IID_IUnknown, riid)) {
978         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
979         *ppv = HTMLELEM(This);
980     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
981         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
982         *ppv = HTMLELEM(This);
983     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
984         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
985         *ppv = HTMLELEM(This);
986     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
987         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
988         *ppv = HTMLELEM2(This);
989     }
990
991     if(*ppv) {
992         IHTMLElement_AddRef(HTMLELEM(This));
993         return S_OK;
994     }
995
996     return HTMLDOMNode_QI(This->node, riid, ppv);
997 }
998
999 void HTMLElement_Create(HTMLDOMNode *node)
1000 {
1001     HTMLElement *ret;
1002     nsAString class_name_str;
1003     const PRUnichar *class_name;
1004     nsresult nsres;
1005
1006     static const WCHAR wszBODY[]     = {'B','O','D','Y',0};
1007     static const WCHAR wszINPUT[]    = {'I','N','P','U','T',0};
1008     static const WCHAR wszSELECT[]   = {'S','E','L','E','C','T',0};
1009     static const WCHAR wszTEXTAREA[] = {'T','E','X','T','A','R','E','A',0};
1010
1011     ret = mshtml_alloc(sizeof(HTMLElement));
1012     ret->lpHTMLElementVtbl = &HTMLElementVtbl;
1013     ret->node = node;
1014     ret->impl = NULL;
1015     ret->destructor = NULL;
1016
1017     node->node_type = NT_HTMLELEM;
1018     node->impl.elem = HTMLELEM(ret);
1019     node->destructor = HTMLElement_destructor;
1020
1021     HTMLElement2_Init(ret);
1022
1023     nsres = nsIDOMNode_QueryInterface(node->nsnode, &IID_nsIDOMHTMLElement, (void**)&ret->nselem);
1024     if(NS_FAILED(nsres))
1025         return;
1026
1027     nsAString_Init(&class_name_str, NULL);
1028     nsIDOMHTMLElement_GetTagName(ret->nselem, &class_name_str);
1029
1030     nsAString_GetData(&class_name_str, &class_name, NULL);
1031
1032     if(!strcmpW(class_name, wszBODY))
1033         HTMLBodyElement_Create(ret);
1034     else if(!strcmpW(class_name, wszINPUT))
1035         HTMLInputElement_Create(ret);
1036     else if(!strcmpW(class_name, wszSELECT))
1037         HTMLSelectElement_Create(ret);
1038     else if(!strcmpW(class_name, wszTEXTAREA))
1039         HTMLTextAreaElement_Create(ret);
1040
1041     nsAString_Finish(&class_name_str);
1042 }
1043
1044 typedef struct {
1045     const IHTMLElementCollectionVtbl *lpHTMLElementCollectionVtbl;
1046
1047     IUnknown *ref_unk;
1048     HTMLElement **elems;
1049     DWORD len;
1050
1051     LONG ref;
1052 } HTMLElementCollection;
1053
1054 #define HTMLELEMCOL(x)  ((IHTMLElementCollection*) &(x)->lpHTMLElementCollectionVtbl)
1055
1056 #define ELEMCOL_THIS(iface) DEFINE_THIS(HTMLElementCollection, HTMLElementCollection, iface)
1057
1058 static HRESULT WINAPI HTMLElementCollection_QueryInterface(IHTMLElementCollection *iface,
1059                                                            REFIID riid, void **ppv)
1060 {
1061     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1062
1063     *ppv = NULL;
1064
1065     if(IsEqualGUID(&IID_IUnknown, riid)) {
1066         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1067         *ppv = HTMLELEMCOL(This);
1068     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1069         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1070         *ppv = HTMLELEMCOL(This);
1071     }else if(IsEqualGUID(&IID_IHTMLElementCollection, riid)) {
1072         TRACE("(%p)->(IID_IHTMLElementCollection %p)\n", This, ppv);
1073         *ppv = HTMLELEMCOL(This);
1074     }
1075
1076     if(*ppv) {
1077         IHTMLElementCollection_AddRef(HTMLELEMCOL(This));
1078         return S_OK;
1079     }
1080
1081     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1082     return E_NOINTERFACE;
1083 }
1084
1085 static ULONG WINAPI HTMLElementCollection_AddRef(IHTMLElementCollection *iface)
1086 {
1087     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1088     LONG ref = InterlockedIncrement(&This->ref);
1089
1090     TRACE("(%p) ref=%d\n", This, ref);
1091
1092     return ref;
1093 }
1094
1095 static ULONG WINAPI HTMLElementCollection_Release(IHTMLElementCollection *iface)
1096 {
1097     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1098     LONG ref = InterlockedDecrement(&This->ref);
1099
1100     TRACE("(%p) ref=%d\n", This, ref);
1101
1102     if(!ref) {
1103         IUnknown_Release(This->ref_unk);
1104         mshtml_free(This->elems);
1105         mshtml_free(This);
1106     }
1107
1108     return ref;
1109 }
1110
1111 static HRESULT WINAPI HTMLElementCollection_GetTypeInfoCount(IHTMLElementCollection *iface,
1112                                                              UINT *pctinfo)
1113 {
1114     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1115     FIXME("(%p)->(%p)\n", This, pctinfo);
1116     return E_NOTIMPL;
1117 }
1118
1119 static HRESULT WINAPI HTMLElementCollection_GetTypeInfo(IHTMLElementCollection *iface,
1120         UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1121 {
1122     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1123     FIXME("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
1124     return E_NOTIMPL;
1125 }
1126
1127 static HRESULT WINAPI HTMLElementCollection_GetIDsOfNames(IHTMLElementCollection *iface,
1128         REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
1129 {
1130     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1131     FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
1132                                         lcid, rgDispId);
1133     return E_NOTIMPL;
1134 }
1135
1136 static HRESULT WINAPI HTMLElementCollection_Invoke(IHTMLElementCollection *iface,
1137         DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1138         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1139 {
1140     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1141     FIXME("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
1142             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1143     return E_NOTIMPL;
1144 }
1145
1146 static HRESULT WINAPI HTMLElementCollection_toString(IHTMLElementCollection *iface,
1147                                                      BSTR *String)
1148 {
1149     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1150     FIXME("(%p)->(%p)\n", This, String);
1151     return E_NOTIMPL;
1152 }
1153
1154 static HRESULT WINAPI HTMLElementCollection_put_length(IHTMLElementCollection *iface,
1155                                                        long v)
1156 {
1157     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1158     FIXME("(%p)->(%ld)\n", This, v);
1159     return E_NOTIMPL;
1160 }
1161
1162 static HRESULT WINAPI HTMLElementCollection_get_length(IHTMLElementCollection *iface,
1163                                                        long *p)
1164 {
1165     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1166
1167     TRACE("(%p)->(%p)\n", This, p);
1168
1169     *p = This->len;
1170     return S_OK;
1171 }
1172
1173 static HRESULT WINAPI HTMLElementCollection_get__newEnum(IHTMLElementCollection *iface,
1174                                                          IUnknown **p)
1175 {
1176     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1177     FIXME("(%p)->(%p)\n", This, p);
1178     return E_NOTIMPL;
1179 }
1180
1181 static HRESULT WINAPI HTMLElementCollection_item(IHTMLElementCollection *iface,
1182         VARIANT name, VARIANT index, IDispatch **pdisp)
1183 {
1184     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1185
1186     if(V_VT(&index) != VT_I4) {
1187         WARN("Invalid index vt=%d\n", V_VT(&index));
1188         return E_INVALIDARG;
1189     }
1190
1191     if(V_VT(&name) != VT_I4 || V_I4(&name) != V_I4(&index))
1192         FIXME("Unsupproted name vt=%d\n", V_VT(&name));
1193
1194     TRACE("(%p)->(%d %d %p)\n", This, V_I4(&name), V_I4(&index), pdisp);
1195
1196     if(V_I4(&index) < 0 || V_I4(&index) >= This->len)
1197         return E_INVALIDARG;
1198
1199     *pdisp = (IDispatch*)This->elems[V_I4(&index)];
1200     IDispatch_AddRef(*pdisp);
1201     return S_OK;
1202 }
1203
1204 static HRESULT WINAPI HTMLElementCollection_tags(IHTMLElementCollection *iface,
1205                                                  VARIANT tagName, IDispatch **pdisp)
1206 {
1207     HTMLElementCollection *This = ELEMCOL_THIS(iface);
1208     DWORD i;
1209     nsAString tag_str;
1210     const PRUnichar *tag;
1211     elem_vector buf = {NULL, 0, 8};
1212
1213     if(V_VT(&tagName) != VT_BSTR) {
1214         WARN("Invalid arg\n");
1215         return DISP_E_MEMBERNOTFOUND;
1216     }
1217
1218     TRACE("(%p)->(%s %p)\n", This, debugstr_w(V_BSTR(&tagName)), pdisp);
1219
1220     buf.buf = mshtml_alloc(buf.size*sizeof(HTMLElement*));
1221
1222     nsAString_Init(&tag_str, NULL);
1223
1224     for(i=0; i<This->len; i++) {
1225         if(!This->elems[i]->nselem)
1226             continue;
1227
1228         nsIDOMElement_GetTagName(This->elems[i]->nselem, &tag_str);
1229         nsAString_GetData(&tag_str, &tag, NULL);
1230
1231         if(CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, tag, -1,
1232                           V_BSTR(&tagName), -1) == CSTR_EQUAL)
1233             elem_vector_add(&buf, This->elems[i]);
1234     }
1235
1236     nsAString_Finish(&tag_str);
1237
1238     TRACE("fount %d tags\n", buf.len);
1239
1240     if(!buf.len) {
1241         mshtml_free(buf.buf);
1242         buf.buf = NULL;
1243     }else if(buf.size > buf.len) {
1244         buf.buf = mshtml_realloc(buf.buf, buf.len*sizeof(HTMLElement*));
1245     }
1246
1247     return HTMLElementCollection_Create(This->ref_unk, buf.buf, buf.len, pdisp);
1248 }
1249
1250 #undef ELEMCOL_THIS
1251
1252 static const IHTMLElementCollectionVtbl HTMLElementCollectionVtbl = {
1253     HTMLElementCollection_QueryInterface,
1254     HTMLElementCollection_AddRef,
1255     HTMLElementCollection_Release,
1256     HTMLElementCollection_GetTypeInfoCount,
1257     HTMLElementCollection_GetTypeInfo,
1258     HTMLElementCollection_GetIDsOfNames,
1259     HTMLElementCollection_Invoke,
1260     HTMLElementCollection_toString,
1261     HTMLElementCollection_put_length,
1262     HTMLElementCollection_get_length,
1263     HTMLElementCollection_get__newEnum,
1264     HTMLElementCollection_item,
1265     HTMLElementCollection_tags
1266 };
1267
1268 static HRESULT HTMLElementCollection_Create(IUnknown *ref_unk, HTMLElement **elems, DWORD len,
1269                                             IDispatch **p)
1270 {
1271     HTMLElementCollection *ret = mshtml_alloc(sizeof(HTMLElementCollection));
1272
1273     ret->lpHTMLElementCollectionVtbl = &HTMLElementCollectionVtbl;
1274     ret->ref = 1;
1275     ret->elems = elems;
1276     ret->len = len;
1277
1278     IUnknown_AddRef(ref_unk);
1279     ret->ref_unk = ref_unk;
1280
1281     TRACE("ret=%p len=%d\n", ret, len);
1282
1283     *p = (IDispatch*)ret;
1284     return S_OK;
1285 }