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