mshtml: Don't cache HTMLAttributesCollection results.
[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
20 #include <stdarg.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winreg.h"
28 #include "ole2.h"
29 #include "shlwapi.h"
30
31 #include "wine/debug.h"
32
33 #include "mshtml_private.h"
34 #include "htmlevent.h"
35 #include "htmlstyle.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 static const WCHAR aW[]        = {'A',0};
40 static const WCHAR bodyW[]     = {'B','O','D','Y',0};
41 static const WCHAR embedW[]    = {'E','M','B','E','D',0};
42 static const WCHAR formW[]     = {'F','O','R','M',0};
43 static const WCHAR frameW[]    = {'F','R','A','M','E',0};
44 static const WCHAR headW[]     = {'H','E','A','D',0};
45 static const WCHAR iframeW[]   = {'I','F','R','A','M','E',0};
46 static const WCHAR imgW[]      = {'I','M','G',0};
47 static const WCHAR inputW[]    = {'I','N','P','U','T',0};
48 static const WCHAR objectW[]   = {'O','B','J','E','C','T',0};
49 static const WCHAR optionW[]   = {'O','P','T','I','O','N',0};
50 static const WCHAR scriptW[]   = {'S','C','R','I','P','T',0};
51 static const WCHAR selectW[]   = {'S','E','L','E','C','T',0};
52 static const WCHAR styleW[]    = {'S','T','Y','L','E',0};
53 static const WCHAR tableW[]    = {'T','A','B','L','E',0};
54 static const WCHAR textareaW[] = {'T','E','X','T','A','R','E','A',0};
55 static const WCHAR title_tagW[]= {'T','I','T','L','E',0};
56 static const WCHAR trW[]       = {'T','R',0};
57
58 typedef struct {
59     const WCHAR *name;
60     HRESULT (*constructor)(HTMLDocumentNode*,nsIDOMHTMLElement*,HTMLElement**);
61 } tag_desc_t;
62
63 static const tag_desc_t tag_descs[] = {
64     {aW,         HTMLAnchorElement_Create},
65     {bodyW,      HTMLBodyElement_Create},
66     {embedW,     HTMLEmbedElement_Create},
67     {formW,      HTMLFormElement_Create},
68     {frameW,     HTMLFrameElement_Create},
69     {headW,      HTMLHeadElement_Create},
70     {iframeW,    HTMLIFrame_Create},
71     {imgW,       HTMLImgElement_Create},
72     {inputW,     HTMLInputElement_Create},
73     {objectW,    HTMLObjectElement_Create},
74     {optionW,    HTMLOptionElement_Create},
75     {scriptW,    HTMLScriptElement_Create},
76     {selectW,    HTMLSelectElement_Create},
77     {styleW,     HTMLStyleElement_Create},
78     {tableW,     HTMLTable_Create},
79     {textareaW,  HTMLTextAreaElement_Create},
80     {title_tagW, HTMLTitleElement_Create},
81     {trW,        HTMLTableRow_Create}
82 };
83
84 static const tag_desc_t *get_tag_desc(const WCHAR *tag_name)
85 {
86     DWORD min=0, max=sizeof(tag_descs)/sizeof(*tag_descs)-1, i;
87     int r;
88
89     while(min <= max) {
90         i = (min+max)/2;
91         r = strcmpW(tag_name, tag_descs[i].name);
92         if(!r)
93             return tag_descs+i;
94
95         if(r < 0)
96             max = i-1;
97         else
98             min = i+1;
99     }
100
101     return NULL;
102 }
103
104 HRESULT replace_node_by_html(nsIDOMHTMLDocument *nsdoc, nsIDOMNode *nsnode, const WCHAR *html)
105 {
106     nsIDOMDocumentFragment *nsfragment;
107     nsIDOMNSRange *nsrange;
108     nsIDOMNode *nsparent;
109     nsIDOMRange *range;
110     nsAString html_str;
111     nsresult nsres;
112     HRESULT hres = S_OK;
113
114     nsres = nsIDOMHTMLDocument_CreateRange(nsdoc, &range);
115     if(NS_FAILED(nsres)) {
116         ERR("CreateRange failed: %08x\n", nsres);
117         return E_FAIL;
118     }
119
120     nsres = nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void**)&nsrange);
121     nsIDOMRange_Release(range);
122     if(NS_FAILED(nsres)) {
123         ERR("Could not get nsIDOMNSRange: %08x\n", nsres);
124         return E_FAIL;
125     }
126
127     nsAString_InitDepend(&html_str, html);
128     nsIDOMNSRange_CreateContextualFragment(nsrange, &html_str, &nsfragment);
129     nsIDOMNSRange_Release(nsrange);
130     nsAString_Finish(&html_str);
131     if(NS_FAILED(nsres)) {
132         ERR("CreateContextualFragment failed: %08x\n", nsres);
133         return E_FAIL;
134     }
135
136     nsres = nsIDOMNode_GetParentNode(nsnode, &nsparent);
137     if(NS_SUCCEEDED(nsres) && nsparent) {
138         nsIDOMNode *nstmp;
139
140         nsres = nsIDOMNode_ReplaceChild(nsparent, (nsIDOMNode*)nsfragment, nsnode, &nstmp);
141         nsIDOMNode_Release(nsparent);
142         if(NS_FAILED(nsres)) {
143             ERR("ReplaceChild failed: %08x\n", nsres);
144             hres = E_FAIL;
145         }else if(nstmp) {
146             nsIDOMNode_Release(nstmp);
147         }
148     }else {
149         ERR("GetParentNode failed: %08x\n", nsres);
150         hres = E_FAIL;
151     }
152
153     nsIDOMDocumentFragment_Release(nsfragment);
154     return hres;
155 }
156
157 typedef struct
158 {
159     DispatchEx dispex;
160     IHTMLFiltersCollection IHTMLFiltersCollection_iface;
161
162     LONG ref;
163 } HTMLFiltersCollection;
164
165 static inline HTMLFiltersCollection *impl_from_IHTMLFiltersCollection(IHTMLFiltersCollection *iface)
166 {
167     return CONTAINING_RECORD(iface, HTMLFiltersCollection, IHTMLFiltersCollection_iface);
168 }
169
170 static IHTMLFiltersCollection *HTMLFiltersCollection_Create(void);
171
172 static inline HTMLElement *impl_from_IHTMLElement(IHTMLElement *iface)
173 {
174     return CONTAINING_RECORD(iface, HTMLElement, IHTMLElement_iface);
175 }
176
177 HRESULT create_nselem(HTMLDocumentNode *doc, const WCHAR *tag, nsIDOMHTMLElement **ret)
178 {
179     nsIDOMElement *nselem;
180     nsAString tag_str;
181     nsresult nsres;
182
183     if(!doc->nsdoc) {
184         WARN("NULL nsdoc\n");
185         return E_UNEXPECTED;
186     }
187
188     nsAString_InitDepend(&tag_str, tag);
189     nsres = nsIDOMDocument_CreateElement(doc->nsdoc, &tag_str, &nselem);
190     nsAString_Finish(&tag_str);
191     if(NS_FAILED(nsres)) {
192         ERR("CreateElement failed: %08x\n", nsres);
193         return E_FAIL;
194     }
195
196     nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)ret);
197     nsIDOMElement_Release(nselem);
198     if(NS_FAILED(nsres)) {
199         ERR("Could not get nsIDOMHTMLElement iface: %08x\n", nsres);
200         return E_FAIL;
201     }
202
203     return S_OK;
204 }
205
206 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
207                                                  REFIID riid, void **ppv)
208 {
209     HTMLElement *This = impl_from_IHTMLElement(iface);
210
211     return IHTMLDOMNode_QueryInterface(&This->node.IHTMLDOMNode_iface, riid, ppv);
212 }
213
214 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
215 {
216     HTMLElement *This = impl_from_IHTMLElement(iface);
217
218     return IHTMLDOMNode_AddRef(&This->node.IHTMLDOMNode_iface);
219 }
220
221 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
222 {
223     HTMLElement *This = impl_from_IHTMLElement(iface);
224
225     return IHTMLDOMNode_Release(&This->node.IHTMLDOMNode_iface);
226 }
227
228 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
229 {
230     HTMLElement *This = impl_from_IHTMLElement(iface);
231     return IDispatchEx_GetTypeInfoCount(&This->node.dispex.IDispatchEx_iface, pctinfo);
232 }
233
234 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
235                                               LCID lcid, ITypeInfo **ppTInfo)
236 {
237     HTMLElement *This = impl_from_IHTMLElement(iface);
238     return IDispatchEx_GetTypeInfo(&This->node.dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
239 }
240
241 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
242                                                 LPOLESTR *rgszNames, UINT cNames,
243                                                 LCID lcid, DISPID *rgDispId)
244 {
245     HTMLElement *This = impl_from_IHTMLElement(iface);
246     return IDispatchEx_GetIDsOfNames(&This->node.dispex.IDispatchEx_iface, riid, rgszNames, cNames,
247             lcid, rgDispId);
248 }
249
250 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
251                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
252                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
253 {
254     HTMLElement *This = impl_from_IHTMLElement(iface);
255     return IDispatchEx_Invoke(&This->node.dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
256             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
257 }
258
259 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
260                                                VARIANT AttributeValue, LONG lFlags)
261 {
262     HTMLElement *This = impl_from_IHTMLElement(iface);
263     HRESULT hres;
264     DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
265     DISPPARAMS dispParams;
266     EXCEPINFO excep;
267
268     TRACE("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
269
270     hres = IDispatchEx_GetDispID(&This->node.dispex.IDispatchEx_iface, strAttributeName,
271             fdexNameCaseInsensitive | fdexNameEnsure, &dispid);
272     if(FAILED(hres))
273         return hres;
274
275     dispParams.cArgs = 1;
276     dispParams.cNamedArgs = 1;
277     dispParams.rgdispidNamedArgs = &dispidNamed;
278     dispParams.rgvarg = &AttributeValue;
279
280     hres = IDispatchEx_InvokeEx(&This->node.dispex.IDispatchEx_iface, dispid,
281             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams, NULL, &excep, NULL);
282     return hres;
283 }
284
285 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
286                                                LONG lFlags, VARIANT *AttributeValue)
287 {
288     HTMLElement *This = impl_from_IHTMLElement(iface);
289     DISPID dispid;
290     HRESULT hres;
291     DISPPARAMS dispParams = {NULL, NULL, 0, 0};
292     EXCEPINFO excep;
293
294     TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
295
296     hres = IDispatchEx_GetDispID(&This->node.dispex.IDispatchEx_iface, strAttributeName,
297             fdexNameCaseInsensitive, &dispid);
298     if(hres == DISP_E_UNKNOWNNAME) {
299         V_VT(AttributeValue) = VT_NULL;
300         return S_OK;
301     }
302
303     if(FAILED(hres)) {
304         V_VT(AttributeValue) = VT_NULL;
305         return hres;
306     }
307
308     hres = IDispatchEx_InvokeEx(&This->node.dispex.IDispatchEx_iface, dispid, LOCALE_SYSTEM_DEFAULT,
309             DISPATCH_PROPERTYGET, &dispParams, AttributeValue, &excep, NULL);
310
311     return hres;
312 }
313
314 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
315                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
316 {
317     HTMLElement *This = impl_from_IHTMLElement(iface);
318
319     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(strAttributeName), lFlags, pfSuccess);
320
321     return remove_prop(&This->node.dispex, strAttributeName, pfSuccess);
322 }
323
324 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
325 {
326     HTMLElement *This = impl_from_IHTMLElement(iface);
327     nsAString classname_str;
328     nsresult nsres;
329
330     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
331
332     if(!This->nselem) {
333         FIXME("NULL nselem\n");
334         return E_NOTIMPL;
335     }
336
337     nsAString_InitDepend(&classname_str, v);
338     nsres = nsIDOMHTMLElement_SetClassName(This->nselem, &classname_str);
339     nsAString_Finish(&classname_str);
340     if(NS_FAILED(nsres))
341         ERR("SetClassName failed: %08x\n", nsres);
342
343     return S_OK;
344 }
345
346 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
347 {
348     HTMLElement *This = impl_from_IHTMLElement(iface);
349     nsAString class_str;
350     nsresult nsres;
351     HRESULT hres = S_OK;
352
353     TRACE("(%p)->(%p)\n", This, p);
354
355     if(!This->nselem) {
356         FIXME("NULL nselem\n");
357         return E_NOTIMPL;
358     }
359
360     nsAString_Init(&class_str, NULL);
361     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
362
363     if(NS_SUCCEEDED(nsres)) {
364         const PRUnichar *class;
365         nsAString_GetData(&class_str, &class);
366         *p = *class ? SysAllocString(class) : NULL;
367     }else {
368         ERR("GetClassName failed: %08x\n", nsres);
369         hres = E_FAIL;
370     }
371
372     nsAString_Finish(&class_str);
373
374     TRACE("className=%s\n", debugstr_w(*p));
375     return hres;
376 }
377
378 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
379 {
380     HTMLElement *This = impl_from_IHTMLElement(iface);
381     nsAString id_str;
382     nsresult nsres;
383
384     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
385
386     if(!This->nselem) {
387         FIXME("nselem == NULL\n");
388         return S_OK;
389     }
390
391     nsAString_InitDepend(&id_str, v);
392     nsres = nsIDOMHTMLElement_SetId(This->nselem, &id_str);
393     nsAString_Finish(&id_str);
394     if(NS_FAILED(nsres))
395         ERR("SetId failed: %08x\n", nsres);
396
397     return S_OK;
398 }
399
400 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
401 {
402     HTMLElement *This = impl_from_IHTMLElement(iface);
403     const PRUnichar *id;
404     nsAString id_str;
405     nsresult nsres;
406
407     TRACE("(%p)->(%p)\n", This, p);
408
409     *p = NULL;
410
411     if(!This->nselem)
412         return S_OK;
413
414     nsAString_Init(&id_str, NULL);
415     nsres = nsIDOMHTMLElement_GetId(This->nselem, &id_str);
416     nsAString_GetData(&id_str, &id);
417
418     if(NS_FAILED(nsres))
419         ERR("GetId failed: %08x\n", nsres);
420     else if(*id)
421         *p = SysAllocString(id);
422
423     nsAString_Finish(&id_str);
424     return S_OK;
425 }
426
427 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
428 {
429     HTMLElement *This = impl_from_IHTMLElement(iface);
430     const PRUnichar *tag;
431     nsAString tag_str;
432     nsresult nsres;
433
434     TRACE("(%p)->(%p)\n", This, p);
435
436     if(!This->nselem) {
437         static const WCHAR comment_tagW[] = {'!',0};
438
439         WARN("NULL nselem, assuming comment\n");
440
441         *p = SysAllocString(comment_tagW);
442         return S_OK;
443     }
444
445     nsAString_Init(&tag_str, NULL);
446     nsres = nsIDOMHTMLElement_GetTagName(This->nselem, &tag_str);
447     if(NS_SUCCEEDED(nsres)) {
448         nsAString_GetData(&tag_str, &tag);
449         *p = SysAllocString(tag);
450     }else {
451         ERR("GetTagName failed: %08x\n", nsres);
452         *p = NULL;
453     }
454     nsAString_Finish(&tag_str);
455
456     return S_OK;
457 }
458
459 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
460 {
461     HTMLElement *This = impl_from_IHTMLElement(iface);
462     IHTMLDOMNode *node;
463     HRESULT hres;
464
465     TRACE("(%p)->(%p)\n", This, p);
466
467     hres = IHTMLDOMNode_get_parentNode(&This->node.IHTMLDOMNode_iface, &node);
468     if(FAILED(hres))
469         return hres;
470
471     hres = IHTMLDOMNode_QueryInterface(node, &IID_IHTMLElement, (void**)p);
472     IHTMLDOMNode_Release(node);
473     if(FAILED(hres))
474         *p = NULL;
475
476     return S_OK;
477 }
478
479 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
480 {
481     HTMLElement *This = impl_from_IHTMLElement(iface);
482
483     TRACE("(%p)->(%p)\n", This, p);
484
485     if(!This->style) {
486         nsIDOMElementCSSInlineStyle *nselemstyle;
487         nsIDOMCSSStyleDeclaration *nsstyle;
488         nsresult nsres;
489         HRESULT hres;
490
491         if(!This->nselem) {
492             FIXME("NULL nselem\n");
493             return E_NOTIMPL;
494         }
495
496         nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMElementCSSInlineStyle,
497                 (void**)&nselemstyle);
498         if(NS_FAILED(nsres)) {
499             ERR("Could not get nsIDOMCSSStyleDeclaration interface: %08x\n", nsres);
500             return E_FAIL;
501         }
502
503         nsres = nsIDOMElementCSSInlineStyle_GetStyle(nselemstyle, &nsstyle);
504         nsIDOMElementCSSInlineStyle_Release(nselemstyle);
505         if(NS_FAILED(nsres)) {
506             ERR("GetStyle failed: %08x\n", nsres);
507             return E_FAIL;
508         }
509
510         hres = HTMLStyle_Create(nsstyle, &This->style);
511         nsIDOMCSSStyleDeclaration_Release(nsstyle);
512         if(FAILED(hres))
513             return hres;
514     }
515
516     *p = &This->style->IHTMLStyle_iface;
517     IHTMLStyle_AddRef(*p);
518     return S_OK;
519 }
520
521 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
522 {
523     HTMLElement *This = impl_from_IHTMLElement(iface);
524     FIXME("(%p)->()\n", This);
525     return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
529 {
530     HTMLElement *This = impl_from_IHTMLElement(iface);
531     FIXME("(%p)->(%p)\n", This, p);
532     return E_NOTIMPL;
533 }
534
535 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
536 {
537     HTMLElement *This = impl_from_IHTMLElement(iface);
538
539     TRACE("(%p)->()\n", This);
540
541     return set_node_event(&This->node, EVENTID_CLICK, &v);
542 }
543
544 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
545 {
546     HTMLElement *This = impl_from_IHTMLElement(iface);
547
548     TRACE("(%p)->(%p)\n", This, p);
549
550     return get_node_event(&This->node, EVENTID_CLICK, p);
551 }
552
553 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
554 {
555     HTMLElement *This = impl_from_IHTMLElement(iface);
556
557     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
558
559     return set_node_event(&This->node, EVENTID_DBLCLICK, &v);
560 }
561
562 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
563 {
564     HTMLElement *This = impl_from_IHTMLElement(iface);
565
566     TRACE("(%p)->(%p)\n", This, p);
567
568     return get_node_event(&This->node, EVENTID_DBLCLICK, p);
569 }
570
571 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
572 {
573     HTMLElement *This = impl_from_IHTMLElement(iface);
574
575     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
576
577     return set_node_event(&This->node, EVENTID_KEYDOWN, &v);
578 }
579
580 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
581 {
582     HTMLElement *This = impl_from_IHTMLElement(iface);
583
584     TRACE("(%p)->(%p)\n", This, p);
585
586     return get_node_event(&This->node, EVENTID_KEYDOWN, p);
587 }
588
589 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
590 {
591     HTMLElement *This = impl_from_IHTMLElement(iface);
592
593     TRACE("(%p)->()\n", This);
594
595     return set_node_event(&This->node, EVENTID_KEYUP, &v);
596 }
597
598 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
599 {
600     HTMLElement *This = impl_from_IHTMLElement(iface);
601     FIXME("(%p)->(%p)\n", This, p);
602     return E_NOTIMPL;
603 }
604
605 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
606 {
607     HTMLElement *This = impl_from_IHTMLElement(iface);
608     FIXME("(%p)->()\n", This);
609     return E_NOTIMPL;
610 }
611
612 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
613 {
614     HTMLElement *This = impl_from_IHTMLElement(iface);
615     FIXME("(%p)->(%p)\n", This, p);
616     return E_NOTIMPL;
617 }
618
619 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
620 {
621     HTMLElement *This = impl_from_IHTMLElement(iface);
622
623     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
624
625     return set_node_event(&This->node, EVENTID_MOUSEOUT, &v);
626 }
627
628 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
629 {
630     HTMLElement *This = impl_from_IHTMLElement(iface);
631
632     TRACE("(%p)->(%p)\n", This, p);
633
634     return get_node_event(&This->node, EVENTID_MOUSEOUT, p);
635 }
636
637 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
638 {
639     HTMLElement *This = impl_from_IHTMLElement(iface);
640
641     TRACE("(%p)->()\n", This);
642
643     return set_node_event(&This->node, EVENTID_MOUSEOVER, &v);
644 }
645
646 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
647 {
648     HTMLElement *This = impl_from_IHTMLElement(iface);
649
650     TRACE("(%p)->(%p)\n", This, p);
651
652     return get_node_event(&This->node, EVENTID_MOUSEOVER, p);
653 }
654
655 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
656 {
657     HTMLElement *This = impl_from_IHTMLElement(iface);
658
659     TRACE("(%p)->()\n", This);
660
661     return set_node_event(&This->node, EVENTID_MOUSEMOVE, &v);
662 }
663
664 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
665 {
666     HTMLElement *This = impl_from_IHTMLElement(iface);
667
668     TRACE("(%p)->(%p)\n", This, p);
669
670     return get_node_event(&This->node, EVENTID_MOUSEMOVE, p);
671 }
672
673 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
674 {
675     HTMLElement *This = impl_from_IHTMLElement(iface);
676
677     TRACE("(%p)->()\n", This);
678
679     return set_node_event(&This->node, EVENTID_MOUSEDOWN, &v);
680 }
681
682 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
683 {
684     HTMLElement *This = impl_from_IHTMLElement(iface);
685
686     TRACE("(%p)->(%p)\n", This, p);
687
688     return get_node_event(&This->node, EVENTID_MOUSEDOWN, p);
689 }
690
691 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
692 {
693     HTMLElement *This = impl_from_IHTMLElement(iface);
694
695     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
696
697     return set_node_event(&This->node, EVENTID_MOUSEUP, &v);
698 }
699
700 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
701 {
702     HTMLElement *This = impl_from_IHTMLElement(iface);
703
704     TRACE("(%p)->(%p)\n", This, p);
705
706     return get_node_event(&This->node, EVENTID_MOUSEUP, p);
707 }
708
709 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
710 {
711     HTMLElement *This = impl_from_IHTMLElement(iface);
712
713     TRACE("(%p)->(%p)\n", This, p);
714
715     if(!p)
716         return E_POINTER;
717
718     if(This->node.vtbl->get_document)
719         return This->node.vtbl->get_document(&This->node, p);
720
721     *p = (IDispatch*)&This->node.doc->basedoc.IHTMLDocument2_iface;
722     IDispatch_AddRef(*p);
723     return S_OK;
724 }
725
726 static const WCHAR titleW[] = {'t','i','t','l','e',0};
727
728 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
729 {
730     HTMLElement *This = impl_from_IHTMLElement(iface);
731     nsAString title_str;
732     nsresult nsres;
733
734     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
735
736     if(!This->nselem) {
737         VARIANT *var;
738         HRESULT hres;
739
740         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, TRUE, &var);
741         if(FAILED(hres))
742             return hres;
743
744         VariantClear(var);
745         V_VT(var) = VT_BSTR;
746         V_BSTR(var) = v ? SysAllocString(v) : NULL;
747         return S_OK;
748     }
749
750     nsAString_InitDepend(&title_str, v);
751     nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str);
752     nsAString_Finish(&title_str);
753     if(NS_FAILED(nsres))
754         ERR("SetTitle failed: %08x\n", nsres);
755
756     return S_OK;
757 }
758
759 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
760 {
761     HTMLElement *This = impl_from_IHTMLElement(iface);
762     nsAString title_str;
763     nsresult nsres;
764
765     TRACE("(%p)->(%p)\n", This, p);
766
767     if(!This->nselem) {
768         VARIANT *var;
769         HRESULT hres;
770
771         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, FALSE, &var);
772         if(hres == DISP_E_UNKNOWNNAME) {
773             *p = NULL;
774         }else if(V_VT(var) != VT_BSTR) {
775             FIXME("title = %s\n", debugstr_variant(var));
776             return E_FAIL;
777         }else {
778             *p = V_BSTR(var) ? SysAllocString(V_BSTR(var)) : NULL;
779         }
780
781         return S_OK;
782     }
783
784     nsAString_Init(&title_str, NULL);
785     nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str);
786     if(NS_SUCCEEDED(nsres)) {
787         const PRUnichar *title;
788
789         nsAString_GetData(&title_str, &title);
790         *p = *title ? SysAllocString(title) : NULL;
791     }else {
792         ERR("GetTitle failed: %08x\n", nsres);
793         return E_FAIL;
794     }
795
796     return S_OK;
797 }
798
799 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
800 {
801     HTMLElement *This = impl_from_IHTMLElement(iface);
802     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
803     return E_NOTIMPL;
804 }
805
806 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
807 {
808     HTMLElement *This = impl_from_IHTMLElement(iface);
809     FIXME("(%p)->(%p)\n", This, p);
810     return E_NOTIMPL;
811 }
812
813 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
814 {
815     HTMLElement *This = impl_from_IHTMLElement(iface);
816
817     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
818
819     return set_node_event(&This->node, EVENTID_SELECTSTART, &v);
820 }
821
822 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
823 {
824     HTMLElement *This = impl_from_IHTMLElement(iface);
825
826     TRACE("(%p)->(%p)\n", This, p);
827
828     return get_node_event(&This->node, EVENTID_SELECTSTART, p);
829 }
830
831 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
832 {
833     HTMLElement *This = impl_from_IHTMLElement(iface);
834     FIXME("(%p)->()\n", This);
835     return E_NOTIMPL;
836 }
837
838 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
839                                            VARIANT_BOOL *pfResult)
840 {
841     HTMLElement *This = impl_from_IHTMLElement(iface);
842     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
843     return E_NOTIMPL;
844 }
845
846 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
847 {
848     HTMLElement *This = impl_from_IHTMLElement(iface);
849     FIXME("(%p)->(%p)\n", This, p);
850     return E_NOTIMPL;
851 }
852
853 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
854 {
855     HTMLElement *This = impl_from_IHTMLElement(iface);
856     FIXME("(%p)->(%p)\n", This, p);
857     return E_NOTIMPL;
858 }
859
860 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
861 {
862     HTMLElement *This = impl_from_IHTMLElement(iface);
863     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
864     return E_NOTIMPL;
865 }
866
867 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
868 {
869     HTMLElement *This = impl_from_IHTMLElement(iface);
870     FIXME("(%p)->(%p)\n", This, p);
871     return E_NOTIMPL;
872 }
873
874 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, LONG *p)
875 {
876     HTMLElement *This = impl_from_IHTMLElement(iface);
877     nsIDOMNSHTMLElement *nselem;
878     PRInt32 off_left = 0;
879     nsresult nsres;
880
881     TRACE("(%p)->(%p)\n", This, p);
882
883     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
884     if(NS_FAILED(nsres)) {
885         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
886         return E_FAIL;
887     }
888
889     nsres = nsIDOMNSHTMLElement_GetOffsetLeft(nselem, &off_left);
890     nsIDOMNSHTMLElement_Release(nselem);
891     if(NS_FAILED(nsres)) {
892         ERR("GetOffsetLeft failed: %08x\n", nsres);
893         return E_FAIL;
894     }
895
896     *p = off_left;
897     return S_OK;
898 }
899
900 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, LONG *p)
901 {
902     HTMLElement *This = impl_from_IHTMLElement(iface);
903     nsIDOMNSHTMLElement *nselem;
904     PRInt32 top = 0;
905     nsresult nsres;
906
907     TRACE("(%p)->(%p)\n", This, p);
908
909     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
910     if(NS_FAILED(nsres)) {
911         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
912         return E_FAIL;
913     }
914
915     nsres = nsIDOMNSHTMLElement_GetOffsetTop(nselem, &top);
916     nsIDOMNSHTMLElement_Release(nselem);
917     if(NS_FAILED(nsres)) {
918         ERR("GetOffsetTop failed: %08x\n", nsres);
919         return E_FAIL;
920     }
921
922     *p = top;
923     return S_OK;
924 }
925
926 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, LONG *p)
927 {
928     HTMLElement *This = impl_from_IHTMLElement(iface);
929     nsIDOMNSHTMLElement *nselem;
930     PRInt32 offset = 0;
931     nsresult nsres;
932
933     TRACE("(%p)->(%p)\n", This, p);
934
935     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
936     if(NS_FAILED(nsres)) {
937         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
938         return E_FAIL;
939     }
940
941     nsres = nsIDOMNSHTMLElement_GetOffsetWidth(nselem, &offset);
942     nsIDOMNSHTMLElement_Release(nselem);
943     if(NS_FAILED(nsres)) {
944         ERR("GetOffsetWidth failed: %08x\n", nsres);
945         return E_FAIL;
946     }
947
948     *p = offset;
949     return S_OK;
950 }
951
952 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, LONG *p)
953 {
954     HTMLElement *This = impl_from_IHTMLElement(iface);
955     nsIDOMNSHTMLElement *nselem;
956     PRInt32 offset = 0;
957     nsresult nsres;
958
959     TRACE("(%p)->(%p)\n", This, p);
960
961     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
962     if(NS_FAILED(nsres)) {
963         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
964         return E_FAIL;
965     }
966
967     nsres = nsIDOMNSHTMLElement_GetOffsetHeight(nselem, &offset);
968     nsIDOMNSHTMLElement_Release(nselem);
969     if(NS_FAILED(nsres)) {
970         ERR("GetOffsetHeight failed: %08x\n", nsres);
971         return E_FAIL;
972     }
973
974     *p = offset;
975     return S_OK;
976 }
977
978 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
979 {
980     HTMLElement *This = impl_from_IHTMLElement(iface);
981     nsIDOMNSHTMLElement *nselem;
982     nsIDOMElement *nsparent;
983     nsresult nsres;
984     HRESULT hres;
985
986     TRACE("(%p)->(%p)\n", This, p);
987
988     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
989     if(NS_FAILED(nsres)) {
990         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
991         return E_FAIL;
992     }
993
994     nsres = nsIDOMNSHTMLElement_GetOffsetParent(nselem, &nsparent);
995     nsIDOMNSHTMLElement_Release(nselem);
996     if(NS_FAILED(nsres)) {
997         ERR("GetOffsetParent failed: %08x\n", nsres);
998         return E_FAIL;
999     }
1000
1001     if(nsparent) {
1002         HTMLDOMNode *node;
1003
1004         hres = get_node(This->node.doc, (nsIDOMNode*)nsparent, TRUE, &node);
1005         nsIDOMElement_Release(nsparent);
1006         if(FAILED(hres))
1007             return hres;
1008
1009         hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)p);
1010     }else {
1011         *p = NULL;
1012         hres = S_OK;
1013     }
1014
1015     return hres;
1016 }
1017
1018 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
1019 {
1020     HTMLElement *This = impl_from_IHTMLElement(iface);
1021     nsIDOMNSHTMLElement *nselem;
1022     nsAString html_str;
1023     nsresult nsres;
1024
1025     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1026
1027     if(!This->nselem) {
1028         FIXME("NULL nselem\n");
1029         return E_NOTIMPL;
1030     }
1031
1032     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
1033     if(NS_FAILED(nsres)) {
1034         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
1035         return E_FAIL;
1036     }
1037
1038     nsAString_InitDepend(&html_str, v);
1039     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
1040     nsAString_Finish(&html_str);
1041
1042     if(NS_FAILED(nsres)) {
1043         FIXME("SetInnerHtml failed %08x\n", nsres);
1044         return E_FAIL;
1045     }
1046
1047     return S_OK;
1048 }
1049
1050 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
1051 {
1052     HTMLElement *This = impl_from_IHTMLElement(iface);
1053     nsIDOMNSHTMLElement *nselem;
1054     nsAString html_str;
1055     nsresult nsres;
1056
1057     TRACE("(%p)->(%p)\n", This, p);
1058
1059     if(!This->nselem) {
1060         FIXME("NULL nselem\n");
1061         return E_NOTIMPL;
1062     }
1063
1064     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
1065     if(NS_FAILED(nsres)) {
1066         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
1067         return E_FAIL;
1068     }
1069
1070     nsAString_Init(&html_str, NULL);
1071     nsres = nsIDOMNSHTMLElement_GetInnerHTML(nselem, &html_str);
1072     if(NS_SUCCEEDED(nsres)) {
1073         const PRUnichar *html;
1074
1075         nsAString_GetData(&html_str, &html);
1076         *p = *html ? SysAllocString(html) : NULL;
1077     }else {
1078         FIXME("SetInnerHtml failed %08x\n", nsres);
1079         *p = NULL;
1080     }
1081
1082     nsAString_Finish(&html_str);
1083     return S_OK;
1084 }
1085
1086 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
1087 {
1088     HTMLElement *This = impl_from_IHTMLElement(iface);
1089     nsIDOMNode *nschild, *tmp;
1090     nsIDOMText *text_node;
1091     nsAString text_str;
1092     nsresult nsres;
1093
1094     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1095
1096     while(1) {
1097         nsres = nsIDOMHTMLElement_GetLastChild(This->nselem, &nschild);
1098         if(NS_FAILED(nsres)) {
1099             ERR("GetLastChild failed: %08x\n", nsres);
1100             return E_FAIL;
1101         }
1102         if(!nschild)
1103             break;
1104
1105         nsres = nsIDOMHTMLElement_RemoveChild(This->nselem, nschild, &tmp);
1106         nsIDOMNode_Release(nschild);
1107         if(NS_FAILED(nsres)) {
1108             ERR("RemoveChild failed: %08x\n", nsres);
1109             return E_FAIL;
1110         }
1111         nsIDOMNode_Release(tmp);
1112     }
1113
1114     nsAString_InitDepend(&text_str, v);
1115     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &text_str, &text_node);
1116     nsAString_Finish(&text_str);
1117     if(NS_FAILED(nsres)) {
1118         ERR("CreateTextNode failed: %08x\n", nsres);
1119         return E_FAIL;
1120     }
1121
1122     nsres = nsIDOMHTMLElement_AppendChild(This->nselem, (nsIDOMNode*)text_node, &tmp);
1123     if(NS_FAILED(nsres)) {
1124         ERR("AppendChild failed: %08x\n", nsres);
1125         return E_FAIL;
1126     }
1127
1128     nsIDOMNode_Release(tmp);
1129     return S_OK;
1130 }
1131
1132 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
1133 {
1134     HTMLElement *This = impl_from_IHTMLElement(iface);
1135
1136     TRACE("(%p)->(%p)\n", This, p);
1137
1138     return get_node_text(&This->node, p);
1139 }
1140
1141 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
1142 {
1143     HTMLElement *This = impl_from_IHTMLElement(iface);
1144
1145     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1146
1147     return replace_node_by_html(This->node.doc->nsdoc, This->node.nsnode, v);
1148 }
1149
1150 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
1151 {
1152     HTMLElement *This = impl_from_IHTMLElement(iface);
1153     nsAString html_str;
1154     HRESULT hres;
1155
1156     WARN("(%p)->(%p) semi-stub\n", This, p);
1157
1158     nsAString_Init(&html_str, NULL);
1159     hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
1160     if(SUCCEEDED(hres)) {
1161         const PRUnichar *html;
1162
1163         nsAString_GetData(&html_str, &html);
1164         *p = SysAllocString(html);
1165         if(!*p)
1166             hres = E_OUTOFMEMORY;
1167     }
1168
1169     nsAString_Finish(&html_str);
1170
1171     TRACE("ret %s\n", debugstr_w(*p));
1172     return S_OK;
1173 }
1174
1175 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
1176 {
1177     HTMLElement *This = impl_from_IHTMLElement(iface);
1178     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
1179     return E_NOTIMPL;
1180 }
1181
1182 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
1183 {
1184     HTMLElement *This = impl_from_IHTMLElement(iface);
1185     FIXME("(%p)->(%p)\n", This, p);
1186     return E_NOTIMPL;
1187 }
1188
1189 static HRESULT HTMLElement_InsertAdjacentNode(HTMLElement *This, BSTR where, nsIDOMNode *nsnode)
1190 {
1191     static const WCHAR wszBeforeBegin[] = {'b','e','f','o','r','e','B','e','g','i','n',0};
1192     static const WCHAR wszAfterBegin[] = {'a','f','t','e','r','B','e','g','i','n',0};
1193     static const WCHAR wszBeforeEnd[] = {'b','e','f','o','r','e','E','n','d',0};
1194     static const WCHAR wszAfterEnd[] = {'a','f','t','e','r','E','n','d',0};
1195     nsresult nsres;
1196
1197     if (!strcmpiW(where, wszBeforeBegin))
1198     {
1199         nsIDOMNode *unused;
1200         nsIDOMNode *parent;
1201         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1202         if (!parent) return E_INVALIDARG;
1203         nsres = nsIDOMNode_InsertBefore(parent, nsnode, This->node.nsnode, &unused);
1204         if (unused) nsIDOMNode_Release(unused);
1205         nsIDOMNode_Release(parent);
1206     }
1207     else if (!strcmpiW(where, wszAfterBegin))
1208     {
1209         nsIDOMNode *unused;
1210         nsIDOMNode *first_child;
1211         nsIDOMNode_GetFirstChild(This->node.nsnode, &first_child);
1212         nsres = nsIDOMNode_InsertBefore(This->node.nsnode, nsnode, first_child, &unused);
1213         if (unused) nsIDOMNode_Release(unused);
1214         if (first_child) nsIDOMNode_Release(first_child);
1215     }
1216     else if (!strcmpiW(where, wszBeforeEnd))
1217     {
1218         nsIDOMNode *unused;
1219         nsres = nsIDOMNode_AppendChild(This->node.nsnode, nsnode, &unused);
1220         if (unused) nsIDOMNode_Release(unused);
1221     }
1222     else if (!strcmpiW(where, wszAfterEnd))
1223     {
1224         nsIDOMNode *unused;
1225         nsIDOMNode *next_sibling;
1226         nsIDOMNode *parent;
1227         nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1228         if (!parent) return E_INVALIDARG;
1229
1230         nsIDOMNode_GetNextSibling(This->node.nsnode, &next_sibling);
1231         if (next_sibling)
1232         {
1233             nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &unused);
1234             nsIDOMNode_Release(next_sibling);
1235         }
1236         else
1237             nsres = nsIDOMNode_AppendChild(parent, nsnode, &unused);
1238         nsIDOMNode_Release(parent);
1239         if (unused) nsIDOMNode_Release(unused);
1240     }
1241     else
1242     {
1243         ERR("invalid where: %s\n", debugstr_w(where));
1244         return E_INVALIDARG;
1245     }
1246
1247     if (NS_FAILED(nsres))
1248         return E_FAIL;
1249     else
1250         return S_OK;
1251 }
1252
1253 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
1254                                                      BSTR html)
1255 {
1256     HTMLElement *This = impl_from_IHTMLElement(iface);
1257     nsIDOMRange *range;
1258     nsIDOMNSRange *nsrange;
1259     nsIDOMNode *nsnode;
1260     nsAString ns_html;
1261     nsresult nsres;
1262     HRESULT hr;
1263
1264     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
1265
1266     if(!This->node.doc->nsdoc) {
1267         WARN("NULL nsdoc\n");
1268         return E_UNEXPECTED;
1269     }
1270
1271     nsres = nsIDOMHTMLDocument_CreateRange(This->node.doc->nsdoc, &range);
1272     if(NS_FAILED(nsres))
1273     {
1274         ERR("CreateRange failed: %08x\n", nsres);
1275         return E_FAIL;
1276     }
1277
1278     nsIDOMRange_SetStartBefore(range, This->node.nsnode);
1279
1280     nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void **)&nsrange);
1281     nsIDOMRange_Release(range);
1282     if(NS_FAILED(nsres))
1283     {
1284         ERR("getting nsIDOMNSRange failed: %08x\n", nsres);
1285         return E_FAIL;
1286     }
1287
1288     nsAString_InitDepend(&ns_html, html);
1289
1290     nsres = nsIDOMNSRange_CreateContextualFragment(nsrange, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
1291     nsIDOMNSRange_Release(nsrange);
1292     nsAString_Finish(&ns_html);
1293
1294     if(NS_FAILED(nsres) || !nsnode)
1295     {
1296         ERR("CreateTextNode failed: %08x\n", nsres);
1297         return E_FAIL;
1298     }
1299
1300     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1301     nsIDOMNode_Release(nsnode);
1302
1303     return hr;
1304 }
1305
1306 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
1307                                                      BSTR text)
1308 {
1309     HTMLElement *This = impl_from_IHTMLElement(iface);
1310     nsIDOMNode *nsnode;
1311     nsAString ns_text;
1312     nsresult nsres;
1313     HRESULT hr;
1314
1315     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
1316
1317     if(!This->node.doc->nsdoc) {
1318         WARN("NULL nsdoc\n");
1319         return E_UNEXPECTED;
1320     }
1321
1322
1323     nsAString_InitDepend(&ns_text, text);
1324     nsres = nsIDOMDocument_CreateTextNode(This->node.doc->nsdoc, &ns_text, (nsIDOMText **)&nsnode);
1325     nsAString_Finish(&ns_text);
1326
1327     if(NS_FAILED(nsres) || !nsnode)
1328     {
1329         ERR("CreateTextNode failed: %08x\n", nsres);
1330         return E_FAIL;
1331     }
1332
1333     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1334     nsIDOMNode_Release(nsnode);
1335
1336     return hr;
1337 }
1338
1339 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
1340 {
1341     HTMLElement *This = impl_from_IHTMLElement(iface);
1342     FIXME("(%p)->(%p)\n", This, p);
1343     return E_NOTIMPL;
1344 }
1345
1346 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
1347 {
1348     HTMLElement *This = impl_from_IHTMLElement(iface);
1349     FIXME("(%p)->(%p)\n", This, p);
1350     return E_NOTIMPL;
1351 }
1352
1353 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
1354 {
1355     HTMLElement *This = impl_from_IHTMLElement(iface);
1356
1357     TRACE("(%p)\n", This);
1358
1359     return call_fire_event(&This->node, EVENTID_CLICK);
1360 }
1361
1362 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
1363                                               IHTMLFiltersCollection **p)
1364 {
1365     HTMLElement *This = impl_from_IHTMLElement(iface);
1366     TRACE("(%p)->(%p)\n", This, p);
1367
1368     if(!p)
1369         return E_POINTER;
1370
1371     *p = HTMLFiltersCollection_Create();
1372
1373     return S_OK;
1374 }
1375
1376 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
1377 {
1378     HTMLElement *This = impl_from_IHTMLElement(iface);
1379     FIXME("(%p)->()\n", This);
1380     return E_NOTIMPL;
1381 }
1382
1383 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
1384 {
1385     HTMLElement *This = impl_from_IHTMLElement(iface);
1386     FIXME("(%p)->(%p)\n", This, p);
1387     return E_NOTIMPL;
1388 }
1389
1390 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
1391 {
1392     HTMLElement *This = impl_from_IHTMLElement(iface);
1393     FIXME("(%p)->(%p)\n", This, String);
1394     return E_NOTIMPL;
1395 }
1396
1397 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
1398 {
1399     HTMLElement *This = impl_from_IHTMLElement(iface);
1400     FIXME("(%p)->()\n", This);
1401     return E_NOTIMPL;
1402 }
1403
1404 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
1405 {
1406     HTMLElement *This = impl_from_IHTMLElement(iface);
1407     FIXME("(%p)->(%p)\n", This, p);
1408     return E_NOTIMPL;
1409 }
1410
1411 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
1412 {
1413     HTMLElement *This = impl_from_IHTMLElement(iface);
1414     FIXME("(%p)->()\n", This);
1415     return E_NOTIMPL;
1416 }
1417
1418 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
1419 {
1420     HTMLElement *This = impl_from_IHTMLElement(iface);
1421     FIXME("(%p)->(%p)\n", This, p);
1422     return E_NOTIMPL;
1423 }
1424
1425 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
1426 {
1427     HTMLElement *This = impl_from_IHTMLElement(iface);
1428     FIXME("(%p)->()\n", This);
1429     return E_NOTIMPL;
1430 }
1431
1432 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
1433 {
1434     HTMLElement *This = impl_from_IHTMLElement(iface);
1435     FIXME("(%p)->(%p)\n", This, p);
1436     return E_NOTIMPL;
1437 }
1438
1439 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
1440 {
1441     HTMLElement *This = impl_from_IHTMLElement(iface);
1442     FIXME("(%p)->()\n", This);
1443     return E_NOTIMPL;
1444 }
1445
1446 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
1447 {
1448     HTMLElement *This = impl_from_IHTMLElement(iface);
1449     FIXME("(%p)->(%p)\n", This, p);
1450     return E_NOTIMPL;
1451 }
1452
1453 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
1454 {
1455     HTMLElement *This = impl_from_IHTMLElement(iface);
1456     FIXME("(%p)->()\n", This);
1457     return E_NOTIMPL;
1458 }
1459
1460 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
1461 {
1462     HTMLElement *This = impl_from_IHTMLElement(iface);
1463     FIXME("(%p)->(%p)\n", This, p);
1464     return E_NOTIMPL;
1465 }
1466
1467 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
1468 {
1469     HTMLElement *This = impl_from_IHTMLElement(iface);
1470     FIXME("(%p)->()\n", This);
1471     return E_NOTIMPL;
1472 }
1473
1474 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
1475 {
1476     HTMLElement *This = impl_from_IHTMLElement(iface);
1477     FIXME("(%p)->(%p)\n", This, p);
1478     return E_NOTIMPL;
1479 }
1480
1481 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
1482 {
1483     HTMLElement *This = impl_from_IHTMLElement(iface);
1484     FIXME("(%p)->()\n", This);
1485     return E_NOTIMPL;
1486 }
1487
1488 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
1489 {
1490     HTMLElement *This = impl_from_IHTMLElement(iface);
1491     FIXME("(%p)->(%p)\n", This, p);
1492     return E_NOTIMPL;
1493 }
1494
1495 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
1496 {
1497     HTMLElement *This = impl_from_IHTMLElement(iface);
1498     FIXME("(%p)->()\n", This);
1499     return E_NOTIMPL;
1500 }
1501
1502 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
1503 {
1504     HTMLElement *This = impl_from_IHTMLElement(iface);
1505     FIXME("(%p)->(%p)\n", This, p);
1506     return E_NOTIMPL;
1507 }
1508
1509 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
1510 {
1511     HTMLElement *This = impl_from_IHTMLElement(iface);
1512     FIXME("(%p)->()\n", This);
1513     return E_NOTIMPL;
1514 }
1515
1516 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
1517 {
1518     HTMLElement *This = impl_from_IHTMLElement(iface);
1519     FIXME("(%p)->(%p)\n", This, p);
1520     return E_NOTIMPL;
1521 }
1522
1523 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
1524 {
1525     HTMLElement *This = impl_from_IHTMLElement(iface);
1526     nsIDOMNodeList *nsnode_list;
1527     nsresult nsres;
1528
1529     TRACE("(%p)->(%p)\n", This, p);
1530
1531     nsres = nsIDOMNode_GetChildNodes(This->node.nsnode, &nsnode_list);
1532     if(NS_FAILED(nsres)) {
1533         ERR("GetChildNodes failed: %08x\n", nsres);
1534         return E_FAIL;
1535     }
1536
1537     *p = (IDispatch*)create_collection_from_nodelist(This->node.doc,
1538             (IUnknown*)&This->IHTMLElement_iface, nsnode_list);
1539
1540     nsIDOMNodeList_Release(nsnode_list);
1541     return S_OK;
1542 }
1543
1544 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1545 {
1546     HTMLElement *This = impl_from_IHTMLElement(iface);
1547
1548     TRACE("(%p)->(%p)\n", This, p);
1549
1550     *p = (IDispatch*)create_all_collection(&This->node, FALSE);
1551     return S_OK;
1552 }
1553
1554 static const IHTMLElementVtbl HTMLElementVtbl = {
1555     HTMLElement_QueryInterface,
1556     HTMLElement_AddRef,
1557     HTMLElement_Release,
1558     HTMLElement_GetTypeInfoCount,
1559     HTMLElement_GetTypeInfo,
1560     HTMLElement_GetIDsOfNames,
1561     HTMLElement_Invoke,
1562     HTMLElement_setAttribute,
1563     HTMLElement_getAttribute,
1564     HTMLElement_removeAttribute,
1565     HTMLElement_put_className,
1566     HTMLElement_get_className,
1567     HTMLElement_put_id,
1568     HTMLElement_get_id,
1569     HTMLElement_get_tagName,
1570     HTMLElement_get_parentElement,
1571     HTMLElement_get_style,
1572     HTMLElement_put_onhelp,
1573     HTMLElement_get_onhelp,
1574     HTMLElement_put_onclick,
1575     HTMLElement_get_onclick,
1576     HTMLElement_put_ondblclick,
1577     HTMLElement_get_ondblclick,
1578     HTMLElement_put_onkeydown,
1579     HTMLElement_get_onkeydown,
1580     HTMLElement_put_onkeyup,
1581     HTMLElement_get_onkeyup,
1582     HTMLElement_put_onkeypress,
1583     HTMLElement_get_onkeypress,
1584     HTMLElement_put_onmouseout,
1585     HTMLElement_get_onmouseout,
1586     HTMLElement_put_onmouseover,
1587     HTMLElement_get_onmouseover,
1588     HTMLElement_put_onmousemove,
1589     HTMLElement_get_onmousemove,
1590     HTMLElement_put_onmousedown,
1591     HTMLElement_get_onmousedown,
1592     HTMLElement_put_onmouseup,
1593     HTMLElement_get_onmouseup,
1594     HTMLElement_get_document,
1595     HTMLElement_put_title,
1596     HTMLElement_get_title,
1597     HTMLElement_put_language,
1598     HTMLElement_get_language,
1599     HTMLElement_put_onselectstart,
1600     HTMLElement_get_onselectstart,
1601     HTMLElement_scrollIntoView,
1602     HTMLElement_contains,
1603     HTMLElement_get_sourceIndex,
1604     HTMLElement_get_recordNumber,
1605     HTMLElement_put_lang,
1606     HTMLElement_get_lang,
1607     HTMLElement_get_offsetLeft,
1608     HTMLElement_get_offsetTop,
1609     HTMLElement_get_offsetWidth,
1610     HTMLElement_get_offsetHeight,
1611     HTMLElement_get_offsetParent,
1612     HTMLElement_put_innerHTML,
1613     HTMLElement_get_innerHTML,
1614     HTMLElement_put_innerText,
1615     HTMLElement_get_innerText,
1616     HTMLElement_put_outerHTML,
1617     HTMLElement_get_outerHTML,
1618     HTMLElement_put_outerText,
1619     HTMLElement_get_outerText,
1620     HTMLElement_insertAdjacentHTML,
1621     HTMLElement_insertAdjacentText,
1622     HTMLElement_get_parentTextEdit,
1623     HTMLElement_get_isTextEdit,
1624     HTMLElement_click,
1625     HTMLElement_get_filters,
1626     HTMLElement_put_ondragstart,
1627     HTMLElement_get_ondragstart,
1628     HTMLElement_toString,
1629     HTMLElement_put_onbeforeupdate,
1630     HTMLElement_get_onbeforeupdate,
1631     HTMLElement_put_onafterupdate,
1632     HTMLElement_get_onafterupdate,
1633     HTMLElement_put_onerrorupdate,
1634     HTMLElement_get_onerrorupdate,
1635     HTMLElement_put_onrowexit,
1636     HTMLElement_get_onrowexit,
1637     HTMLElement_put_onrowenter,
1638     HTMLElement_get_onrowenter,
1639     HTMLElement_put_ondatasetchanged,
1640     HTMLElement_get_ondatasetchanged,
1641     HTMLElement_put_ondataavailable,
1642     HTMLElement_get_ondataavailable,
1643     HTMLElement_put_ondatasetcomplete,
1644     HTMLElement_get_ondatasetcomplete,
1645     HTMLElement_put_onfilterchange,
1646     HTMLElement_get_onfilterchange,
1647     HTMLElement_get_children,
1648     HTMLElement_get_all
1649 };
1650
1651 static inline HTMLElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
1652 {
1653     return CONTAINING_RECORD(iface, HTMLElement, node);
1654 }
1655
1656 HRESULT HTMLElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
1657 {
1658     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1659
1660     *ppv =  NULL;
1661
1662     if(IsEqualGUID(&IID_IUnknown, riid)) {
1663         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1664         *ppv = &This->IHTMLElement_iface;
1665     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1666         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1667         *ppv = &This->IHTMLElement_iface;
1668     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1669         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1670         *ppv = &This->IHTMLElement_iface;
1671     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1672         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1673         *ppv = &This->IHTMLElement2_iface;
1674     }else if(IsEqualGUID(&IID_IHTMLElement3, riid)) {
1675         TRACE("(%p)->(IID_IHTMLElement3 %p)\n", This, ppv);
1676         *ppv = &This->IHTMLElement3_iface;
1677     }else if(IsEqualGUID(&IID_IHTMLElement4, riid)) {
1678         TRACE("(%p)->(IID_IHTMLElement4 %p)\n", This, ppv);
1679         *ppv = &This->IHTMLElement4_iface;
1680     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1681         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1682         *ppv = &This->cp_container.IConnectionPointContainer_iface;
1683     }
1684
1685     if(*ppv) {
1686         IHTMLElement_AddRef(&This->IHTMLElement_iface);
1687         return S_OK;
1688     }
1689
1690     return HTMLDOMNode_QI(&This->node, riid, ppv);
1691 }
1692
1693 void HTMLElement_destructor(HTMLDOMNode *iface)
1694 {
1695     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1696     HTMLDOMAttribute *attr;
1697
1698     while(!list_empty(&This->attrs)) {
1699         attr = LIST_ENTRY(list_head(&This->attrs), HTMLDOMAttribute, entry);
1700
1701         list_remove(&attr->entry);
1702         attr->elem = NULL;
1703         IHTMLDOMAttribute_Release(&attr->IHTMLDOMAttribute_iface);
1704     }
1705
1706     ConnectionPointContainer_Destroy(&This->cp_container);
1707
1708     if(This->nselem)
1709         nsIDOMHTMLElement_Release(This->nselem);
1710     if(This->style)
1711         IHTMLStyle_Release(&This->style->IHTMLStyle_iface);
1712
1713     HTMLDOMNode_destructor(&This->node);
1714 }
1715
1716 HRESULT HTMLElement_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1717 {
1718     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1719     HTMLElement *new_elem;
1720     HRESULT hres;
1721
1722     hres = HTMLElement_Create(This->node.doc, nsnode, FALSE, &new_elem);
1723     if(FAILED(hres))
1724         return hres;
1725
1726     IHTMLElement_AddRef(&new_elem->IHTMLElement_iface);
1727     *ret = &new_elem->node;
1728     return S_OK;
1729 }
1730
1731 static const NodeImplVtbl HTMLElementImplVtbl = {
1732     HTMLElement_QI,
1733     HTMLElement_destructor,
1734     HTMLElement_clone,
1735     HTMLElement_get_attr_col
1736 };
1737
1738 static inline HTMLElement *impl_from_DispatchEx(DispatchEx *iface)
1739 {
1740     return CONTAINING_RECORD(iface, HTMLElement, node.dispex);
1741 }
1742
1743 static HRESULT HTMLElement_get_dispid(DispatchEx *dispex, BSTR name,
1744         DWORD grfdex, DISPID *pid)
1745 {
1746     HTMLElement *This = impl_from_DispatchEx(dispex);
1747
1748     if(This->node.vtbl->get_dispid)
1749         return This->node.vtbl->get_dispid(&This->node, name, grfdex, pid);
1750
1751     return DISP_E_UNKNOWNNAME;
1752 }
1753
1754 static HRESULT HTMLElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
1755         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei,
1756         IServiceProvider *caller)
1757 {
1758     HTMLElement *This = impl_from_DispatchEx(dispex);
1759
1760     if(This->node.vtbl->invoke)
1761         return This->node.vtbl->invoke(&This->node, id, lcid, flags,
1762                 params, res, ei, caller);
1763
1764     ERR("(%p): element has no invoke method\n", This);
1765     return E_NOTIMPL;
1766 }
1767
1768 static HRESULT HTMLElement_populate_props(DispatchEx *dispex)
1769 {
1770     HTMLElement *This = impl_from_DispatchEx(dispex);
1771     nsIDOMNamedNodeMap *attrs;
1772     nsIDOMNode *node;
1773     nsAString nsstr;
1774     const PRUnichar *str;
1775     BSTR name;
1776     VARIANT value;
1777     unsigned i;
1778     PRUint32 len;
1779     DISPID id;
1780     nsresult nsres;
1781     HRESULT hres;
1782
1783     if(!This->nselem)
1784         return S_FALSE;
1785
1786     nsres = nsIDOMHTMLElement_GetAttributes(This->nselem, &attrs);
1787     if(NS_FAILED(nsres))
1788         return E_FAIL;
1789
1790     nsres = nsIDOMNamedNodeMap_GetLength(attrs, &len);
1791     if(NS_FAILED(nsres)) {
1792         nsIDOMNamedNodeMap_Release(attrs);
1793         return E_FAIL;
1794     }
1795
1796     nsAString_Init(&nsstr, NULL);
1797     for(i=0; i<len; i++) {
1798         nsres = nsIDOMNamedNodeMap_Item(attrs, i, &node);
1799         if(NS_FAILED(nsres))
1800             continue;
1801
1802         nsres = nsIDOMNode_GetNodeName(node, &nsstr);
1803         if(NS_FAILED(nsres)) {
1804             nsIDOMNode_Release(node);
1805             continue;
1806         }
1807
1808         nsAString_GetData(&nsstr, &str);
1809         name = SysAllocString(str);
1810         if(!name) {
1811             nsIDOMNode_Release(node);
1812             continue;
1813         }
1814
1815         hres = IDispatchEx_GetDispID(&dispex->IDispatchEx_iface, name, fdexNameCaseInsensitive, &id);
1816         if(hres != DISP_E_UNKNOWNNAME) {
1817             nsIDOMNode_Release(node);
1818             SysFreeString(name);
1819             continue;
1820         }
1821
1822         nsres = nsIDOMNode_GetNodeValue(node, &nsstr);
1823         nsIDOMNode_Release(node);
1824         if(NS_FAILED(nsres)) {
1825             SysFreeString(name);
1826             continue;
1827         }
1828
1829         nsAString_GetData(&nsstr, &str);
1830         V_VT(&value) = VT_BSTR;
1831         if(*str) {
1832             V_BSTR(&value) = SysAllocString(str);
1833             if(!V_BSTR(&value)) {
1834                 SysFreeString(name);
1835                 continue;
1836             }
1837         } else
1838             V_BSTR(&value) = NULL;
1839
1840         IHTMLElement_setAttribute(&This->IHTMLElement_iface, name, value, 0);
1841         SysFreeString(name);
1842         VariantClear(&value);
1843     }
1844     nsAString_Finish(&nsstr);
1845
1846     nsIDOMNamedNodeMap_Release(attrs);
1847     return S_OK;
1848 }
1849
1850 static const tid_t HTMLElement_iface_tids[] = {
1851     HTMLELEMENT_TIDS,
1852     0
1853 };
1854
1855 static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
1856     NULL,
1857     HTMLElement_get_dispid,
1858     HTMLElement_invoke,
1859     HTMLElement_populate_props
1860 };
1861
1862 static dispex_static_data_t HTMLElement_dispex = {
1863     &HTMLElement_dispex_vtbl,
1864     DispHTMLUnknownElement_tid,
1865     NULL,
1866     HTMLElement_iface_tids
1867 };
1868
1869 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, dispex_static_data_t *dispex_data)
1870 {
1871     This->IHTMLElement_iface.lpVtbl = &HTMLElementVtbl;
1872
1873     HTMLElement2_Init(This);
1874     HTMLElement3_Init(This);
1875
1876     if(dispex_data && !dispex_data->vtbl)
1877         dispex_data->vtbl = &HTMLElement_dispex_vtbl;
1878     init_dispex(&This->node.dispex, (IUnknown*)&This->IHTMLElement_iface,
1879             dispex_data ? dispex_data : &HTMLElement_dispex);
1880
1881     if(nselem)
1882         nsIDOMHTMLElement_AddRef(nselem);
1883     This->nselem = nselem;
1884     list_init(&This->attrs);
1885
1886     HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem);
1887
1888     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface);
1889 }
1890
1891 HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_generic, HTMLElement **ret)
1892 {
1893     nsIDOMHTMLElement *nselem;
1894     nsAString class_name_str;
1895     const PRUnichar *class_name;
1896     const tag_desc_t *tag;
1897     HTMLElement *elem;
1898     nsresult nsres;
1899     HRESULT hres;
1900
1901     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1902     if(NS_FAILED(nsres))
1903         return E_FAIL;
1904
1905     nsAString_Init(&class_name_str, NULL);
1906     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1907
1908     nsAString_GetData(&class_name_str, &class_name);
1909
1910     tag = get_tag_desc(class_name);
1911     if(tag) {
1912         hres = tag->constructor(doc, nselem, &elem);
1913     }else if(use_generic) {
1914         hres = HTMLGenericElement_Create(doc, nselem, &elem);
1915     }else {
1916         elem = heap_alloc_zero(sizeof(HTMLElement));
1917         if(elem) {
1918             HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
1919             elem->node.vtbl = &HTMLElementImplVtbl;
1920             hres = S_OK;
1921         }else {
1922             hres = E_OUTOFMEMORY;
1923         }
1924     }
1925
1926     TRACE("%s ret %p\n", debugstr_w(class_name), elem);
1927
1928     nsIDOMElement_Release(nselem);
1929     nsAString_Finish(&class_name_str);
1930     if(FAILED(hres))
1931         return hres;
1932
1933     *ret = elem;
1934     return S_OK;
1935 }
1936
1937 /* interface IHTMLFiltersCollection */
1938 static HRESULT WINAPI HTMLFiltersCollection_QueryInterface(IHTMLFiltersCollection *iface, REFIID riid, void **ppv)
1939 {
1940     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1941
1942     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppv );
1943
1944     if(IsEqualGUID(&IID_IUnknown, riid)) {
1945         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1946         *ppv = &This->IHTMLFiltersCollection_iface;
1947     }else if(IsEqualGUID(&IID_IHTMLFiltersCollection, riid)) {
1948         TRACE("(%p)->(IID_IHTMLFiltersCollection %p)\n", This, ppv);
1949         *ppv = &This->IHTMLFiltersCollection_iface;
1950     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1951         return *ppv ? S_OK : E_NOINTERFACE;
1952     }
1953
1954     if(*ppv) {
1955         IUnknown_AddRef((IUnknown*)*ppv);
1956         return S_OK;
1957     }
1958
1959     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1960     return E_NOINTERFACE;
1961 }
1962
1963 static ULONG WINAPI HTMLFiltersCollection_AddRef(IHTMLFiltersCollection *iface)
1964 {
1965     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1966     LONG ref = InterlockedIncrement(&This->ref);
1967
1968     TRACE("(%p) ref=%d\n", This, ref);
1969
1970     return ref;
1971 }
1972
1973 static ULONG WINAPI HTMLFiltersCollection_Release(IHTMLFiltersCollection *iface)
1974 {
1975     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1976     LONG ref = InterlockedDecrement(&This->ref);
1977
1978     TRACE("(%p) ref=%d\n", This, ref);
1979
1980     if(!ref)
1981     {
1982         heap_free(This);
1983     }
1984
1985     return ref;
1986 }
1987
1988 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfoCount(IHTMLFiltersCollection *iface, UINT *pctinfo)
1989 {
1990     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1991     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1992 }
1993
1994 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfo(IHTMLFiltersCollection *iface,
1995                                     UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1996 {
1997     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1998     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1999 }
2000
2001 static HRESULT WINAPI HTMLFiltersCollection_GetIDsOfNames(IHTMLFiltersCollection *iface,
2002                                     REFIID riid, LPOLESTR *rgszNames, UINT cNames,
2003                                     LCID lcid, DISPID *rgDispId)
2004 {
2005     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2006     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2007             lcid, rgDispId);
2008 }
2009
2010 static HRESULT WINAPI HTMLFiltersCollection_Invoke(IHTMLFiltersCollection *iface, DISPID dispIdMember, REFIID riid,
2011                                     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
2012                                     EXCEPINFO *pExcepInfo, UINT *puArgErr)
2013 {
2014     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2015     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2016             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2017 }
2018
2019 static HRESULT WINAPI HTMLFiltersCollection_get_length(IHTMLFiltersCollection *iface, LONG *p)
2020 {
2021     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2022
2023     if(!p)
2024         return E_POINTER;
2025
2026     FIXME("(%p)->(%p) Always returning 0\n", This, p);
2027     *p = 0;
2028
2029     return S_OK;
2030 }
2031
2032 static HRESULT WINAPI HTMLFiltersCollection_get__newEnum(IHTMLFiltersCollection *iface, IUnknown **p)
2033 {
2034     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2035     FIXME("(%p)->(%p)\n", This, p);
2036     return E_NOTIMPL;
2037 }
2038
2039 static HRESULT WINAPI HTMLFiltersCollection_item(IHTMLFiltersCollection *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
2040 {
2041     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
2042     FIXME("(%p)->(%p, %p)\n", This, pvarIndex, pvarResult);
2043     return E_NOTIMPL;
2044 }
2045
2046 static const IHTMLFiltersCollectionVtbl HTMLFiltersCollectionVtbl = {
2047     HTMLFiltersCollection_QueryInterface,
2048     HTMLFiltersCollection_AddRef,
2049     HTMLFiltersCollection_Release,
2050     HTMLFiltersCollection_GetTypeInfoCount,
2051     HTMLFiltersCollection_GetTypeInfo,
2052     HTMLFiltersCollection_GetIDsOfNames,
2053     HTMLFiltersCollection_Invoke,
2054     HTMLFiltersCollection_get_length,
2055     HTMLFiltersCollection_get__newEnum,
2056     HTMLFiltersCollection_item
2057 };
2058
2059 static HRESULT HTMLFiltersCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
2060 {
2061     WCHAR *ptr;
2062     int idx = 0;
2063
2064     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
2065         idx = idx*10 + (*ptr-'0');
2066     if(*ptr)
2067         return DISP_E_UNKNOWNNAME;
2068
2069     *dispid = MSHTML_DISPID_CUSTOM_MIN + idx;
2070     TRACE("ret %x\n", *dispid);
2071     return S_OK;
2072 }
2073
2074 static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
2075         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
2076 {
2077     TRACE("(%p)->(%x %x %x %p %p %p)\n", dispex, id, lcid, flags, params, res, ei);
2078
2079     V_VT(res) = VT_DISPATCH;
2080     V_DISPATCH(res) = NULL;
2081
2082     FIXME("always returning NULL\n");
2083
2084     return S_OK;
2085 }
2086
2087 static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = {
2088     NULL,
2089     HTMLFiltersCollection_get_dispid,
2090     HTMLFiltersCollection_invoke,
2091     NULL
2092 };
2093
2094 static const tid_t HTMLFiltersCollection_iface_tids[] = {
2095     IHTMLFiltersCollection_tid,
2096     0
2097 };
2098 static dispex_static_data_t HTMLFiltersCollection_dispex = {
2099     &HTMLFiltersCollection_dispex_vtbl,
2100     IHTMLFiltersCollection_tid,
2101     NULL,
2102     HTMLFiltersCollection_iface_tids
2103 };
2104
2105 static IHTMLFiltersCollection *HTMLFiltersCollection_Create(void)
2106 {
2107     HTMLFiltersCollection *ret = heap_alloc(sizeof(HTMLFiltersCollection));
2108
2109     ret->IHTMLFiltersCollection_iface.lpVtbl = &HTMLFiltersCollectionVtbl;
2110     ret->ref = 1;
2111
2112     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLFiltersCollection_iface,
2113             &HTMLFiltersCollection_dispex);
2114
2115     return &ret->IHTMLFiltersCollection_iface;
2116 }
2117
2118 /* interface IHTMLAttributeCollection */
2119 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection(IHTMLAttributeCollection *iface)
2120 {
2121     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection_iface);
2122 }
2123
2124 static HRESULT WINAPI HTMLAttributeCollection_QueryInterface(IHTMLAttributeCollection *iface, REFIID riid, void **ppv)
2125 {
2126     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2127
2128     *ppv = NULL;
2129
2130     if(IsEqualGUID(&IID_IUnknown, riid)) {
2131         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
2132         *ppv = &This->IHTMLAttributeCollection_iface;
2133     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection, riid)) {
2134         TRACE("(%p)->(IID_IHTMLAttributeCollection %p)\n", This, ppv);
2135         *ppv = &This->IHTMLAttributeCollection_iface;
2136     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection2, riid)) {
2137         TRACE("(%p)->(IID_IHTMLAttributeCollection2 %p)\n", This, ppv);
2138         *ppv = &This->IHTMLAttributeCollection2_iface;
2139     }else if(IsEqualGUID(&IID_IHTMLAttributeCollection3, riid)) {
2140         TRACE("(%p)->(IID_IHTMLAttributeCollection3 %p)\n", This, ppv);
2141         *ppv = &This->IHTMLAttributeCollection3_iface;
2142     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
2143         return *ppv ? S_OK : E_NOINTERFACE;
2144     }
2145
2146     if(*ppv) {
2147         IUnknown_AddRef((IUnknown*)*ppv);
2148         return S_OK;
2149     }
2150
2151     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
2152     return E_NOINTERFACE;
2153 }
2154
2155 static ULONG WINAPI HTMLAttributeCollection_AddRef(IHTMLAttributeCollection *iface)
2156 {
2157     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2158     LONG ref = InterlockedIncrement(&This->ref);
2159
2160     TRACE("(%p) ref=%d\n", This, ref);
2161
2162     return ref;
2163 }
2164
2165 static ULONG WINAPI HTMLAttributeCollection_Release(IHTMLAttributeCollection *iface)
2166 {
2167     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2168     LONG ref = InterlockedDecrement(&This->ref);
2169
2170     TRACE("(%p) ref=%d\n", This, ref);
2171
2172     if(!ref) {
2173         IHTMLElement_Release(&This->elem->IHTMLElement_iface);
2174         heap_free(This);
2175     }
2176
2177     return ref;
2178 }
2179
2180 static HRESULT WINAPI HTMLAttributeCollection_GetTypeInfoCount(IHTMLAttributeCollection *iface, UINT *pctinfo)
2181 {
2182     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2183     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2184 }
2185
2186 static HRESULT WINAPI HTMLAttributeCollection_GetTypeInfo(IHTMLAttributeCollection *iface, UINT iTInfo,
2187         LCID lcid, ITypeInfo **ppTInfo)
2188 {
2189     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2190     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2191 }
2192
2193 static HRESULT WINAPI HTMLAttributeCollection_GetIDsOfNames(IHTMLAttributeCollection *iface, REFIID riid,
2194         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2195 {
2196     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2197     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2198             lcid, rgDispId);
2199 }
2200
2201 static HRESULT WINAPI HTMLAttributeCollection_Invoke(IHTMLAttributeCollection *iface, DISPID dispIdMember,
2202         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2203         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2204 {
2205     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2206     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2207             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2208 }
2209
2210 static HRESULT get_attr_dispid_by_idx(HTMLAttributeCollection *This, LONG *idx, DISPID *dispid)
2211 {
2212     IDispatchEx *dispex = &This->elem->node.dispex.IDispatchEx_iface;
2213     DISPID id = DISPID_STARTENUM;
2214     LONG len = -1;
2215     HRESULT hres;
2216
2217     FIXME("filter non-enumerable attributes out\n");
2218
2219     while(1) {
2220         hres = IDispatchEx_GetNextDispID(dispex, fdexEnumAll, id, &id);
2221         if(FAILED(hres))
2222             return hres;
2223         else if(hres == S_FALSE)
2224             break;
2225
2226         len++;
2227         if(len == *idx)
2228             break;
2229     }
2230
2231     if(dispid) {
2232         *dispid = id;
2233         return *idx==len ? S_OK : DISP_E_UNKNOWNNAME;
2234     }
2235
2236     *idx = len+1;
2237     return S_OK;
2238 }
2239
2240 static inline HRESULT get_attr_dispid_by_name(HTMLAttributeCollection *This, BSTR name, DISPID *id)
2241 {
2242     HRESULT hres;
2243
2244     if(name[0]>='0' && name[0]<='9') {
2245         WCHAR *end_ptr;
2246         LONG idx;
2247
2248         idx = strtoulW(name, &end_ptr, 10);
2249         if(!*end_ptr) {
2250             hres = get_attr_dispid_by_idx(This, &idx, id);
2251             if(SUCCEEDED(hres))
2252                 return hres;
2253         }
2254     }
2255
2256     hres = IDispatchEx_GetDispID(&This->elem->node.dispex.IDispatchEx_iface,
2257             name, fdexNameCaseInsensitive, id);
2258     return hres;
2259 }
2260
2261 static inline HRESULT get_domattr(HTMLElement *elem, DISPID id, HTMLDOMAttribute **attr)
2262 {
2263     HTMLDOMAttribute *iter;
2264     HRESULT hres;
2265
2266     *attr = NULL;
2267     LIST_FOR_EACH_ENTRY(iter, &elem->attrs, HTMLDOMAttribute, entry) {
2268         if(iter->dispid == id) {
2269             *attr = iter;
2270             break;
2271         }
2272     }
2273
2274     if(!*attr) {
2275         hres = HTMLDOMAttribute_Create(elem, id, attr);
2276         if(FAILED(hres))
2277             return hres;
2278     }
2279
2280     IHTMLDOMAttribute_AddRef(&(*attr)->IHTMLDOMAttribute_iface);
2281     return S_OK;
2282 }
2283
2284 static HRESULT WINAPI HTMLAttributeCollection_get_length(IHTMLAttributeCollection *iface, LONG *p)
2285 {
2286     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2287     HRESULT hres;
2288
2289     TRACE("(%p)->(%p)\n", This, p);
2290
2291     *p = -1;
2292     hres = get_attr_dispid_by_idx(This, p, NULL);
2293     return hres;
2294 }
2295
2296 static HRESULT WINAPI HTMLAttributeCollection__newEnum(IHTMLAttributeCollection *iface, IUnknown **p)
2297 {
2298     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2299     FIXME("(%p)->(%p)\n", This, p);
2300     return E_NOTIMPL;
2301 }
2302
2303 static HRESULT WINAPI HTMLAttributeCollection_item(IHTMLAttributeCollection *iface, VARIANT *name, IDispatch **ppItem)
2304 {
2305     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection(iface);
2306     HTMLDOMAttribute *attr;
2307     DISPID id;
2308     HRESULT hres;
2309
2310     TRACE("(%p)->(%s %p)\n", This, debugstr_variant(name), ppItem);
2311
2312     switch(V_VT(name)) {
2313     case VT_I4:
2314         hres = get_attr_dispid_by_idx(This, &V_I4(name), &id);
2315         break;
2316     case VT_BSTR:
2317         hres = get_attr_dispid_by_name(This, V_BSTR(name), &id);
2318         break;
2319     default:
2320         FIXME("unsupported vt %x\n", V_VT(name));
2321         hres = E_NOTIMPL;
2322     }
2323     if(hres == DISP_E_UNKNOWNNAME)
2324         return E_INVALIDARG;
2325     if(FAILED(hres))
2326         return hres;
2327
2328     hres = get_domattr(This->elem, id, &attr);
2329     if(FAILED(hres))
2330         return hres;
2331
2332     *ppItem = (IDispatch*)&attr->IHTMLDOMAttribute_iface;
2333     return S_OK;
2334 }
2335
2336 static const IHTMLAttributeCollectionVtbl HTMLAttributeCollectionVtbl = {
2337     HTMLAttributeCollection_QueryInterface,
2338     HTMLAttributeCollection_AddRef,
2339     HTMLAttributeCollection_Release,
2340     HTMLAttributeCollection_GetTypeInfoCount,
2341     HTMLAttributeCollection_GetTypeInfo,
2342     HTMLAttributeCollection_GetIDsOfNames,
2343     HTMLAttributeCollection_Invoke,
2344     HTMLAttributeCollection_get_length,
2345     HTMLAttributeCollection__newEnum,
2346     HTMLAttributeCollection_item
2347 };
2348
2349 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection2(IHTMLAttributeCollection2 *iface)
2350 {
2351     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection2_iface);
2352 }
2353
2354 static HRESULT WINAPI HTMLAttributeCollection2_QueryInterface(IHTMLAttributeCollection2 *iface, REFIID riid, void **ppv)
2355 {
2356     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2357     return IHTMLAttributeCollection_QueryInterface(&This->IHTMLAttributeCollection_iface, riid, ppv);
2358 }
2359
2360 static ULONG WINAPI HTMLAttributeCollection2_AddRef(IHTMLAttributeCollection2 *iface)
2361 {
2362     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2363     return IHTMLAttributeCollection_AddRef(&This->IHTMLAttributeCollection_iface);
2364 }
2365
2366 static ULONG WINAPI HTMLAttributeCollection2_Release(IHTMLAttributeCollection2 *iface)
2367 {
2368     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2369     return IHTMLAttributeCollection_Release(&This->IHTMLAttributeCollection_iface);
2370 }
2371
2372 static HRESULT WINAPI HTMLAttributeCollection2_GetTypeInfoCount(IHTMLAttributeCollection2 *iface, UINT *pctinfo)
2373 {
2374     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2375     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2376 }
2377
2378 static HRESULT WINAPI HTMLAttributeCollection2_GetTypeInfo(IHTMLAttributeCollection2 *iface, UINT iTInfo,
2379         LCID lcid, ITypeInfo **ppTInfo)
2380 {
2381     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2382     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2383 }
2384
2385 static HRESULT WINAPI HTMLAttributeCollection2_GetIDsOfNames(IHTMLAttributeCollection2 *iface, REFIID riid,
2386         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2387 {
2388     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2389     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2390             lcid, rgDispId);
2391 }
2392
2393 static HRESULT WINAPI HTMLAttributeCollection2_Invoke(IHTMLAttributeCollection2 *iface, DISPID dispIdMember,
2394         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2395         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2396 {
2397     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2398     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2399             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2400 }
2401
2402 static HRESULT WINAPI HTMLAttributeCollection2_getNamedItem(IHTMLAttributeCollection2 *iface, BSTR bstrName,
2403         IHTMLDOMAttribute **newretNode)
2404 {
2405     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2406     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), newretNode);
2407     return E_NOTIMPL;
2408 }
2409
2410 static HRESULT WINAPI HTMLAttributeCollection2_setNamedItem(IHTMLAttributeCollection2 *iface,
2411         IHTMLDOMAttribute *ppNode, IHTMLDOMAttribute **newretNode)
2412 {
2413     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2414     FIXME("(%p)->(%p %p)\n", This, ppNode, newretNode);
2415     return E_NOTIMPL;
2416 }
2417
2418 static HRESULT WINAPI HTMLAttributeCollection2_removeNamedItem(IHTMLAttributeCollection2 *iface,
2419         BSTR bstrName, IHTMLDOMAttribute **newretNode)
2420 {
2421     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection2(iface);
2422     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), newretNode);
2423     return E_NOTIMPL;
2424 }
2425
2426 static const IHTMLAttributeCollection2Vtbl HTMLAttributeCollection2Vtbl = {
2427     HTMLAttributeCollection2_QueryInterface,
2428     HTMLAttributeCollection2_AddRef,
2429     HTMLAttributeCollection2_Release,
2430     HTMLAttributeCollection2_GetTypeInfoCount,
2431     HTMLAttributeCollection2_GetTypeInfo,
2432     HTMLAttributeCollection2_GetIDsOfNames,
2433     HTMLAttributeCollection2_Invoke,
2434     HTMLAttributeCollection2_getNamedItem,
2435     HTMLAttributeCollection2_setNamedItem,
2436     HTMLAttributeCollection2_removeNamedItem
2437 };
2438
2439 static inline HTMLAttributeCollection *impl_from_IHTMLAttributeCollection3(IHTMLAttributeCollection3 *iface)
2440 {
2441     return CONTAINING_RECORD(iface, HTMLAttributeCollection, IHTMLAttributeCollection3_iface);
2442 }
2443
2444 static HRESULT WINAPI HTMLAttributeCollection3_QueryInterface(IHTMLAttributeCollection3 *iface, REFIID riid, void **ppv)
2445 {
2446     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2447     return IHTMLAttributeCollection_QueryInterface(&This->IHTMLAttributeCollection_iface, riid, ppv);
2448 }
2449
2450 static ULONG WINAPI HTMLAttributeCollection3_AddRef(IHTMLAttributeCollection3 *iface)
2451 {
2452     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2453     return IHTMLAttributeCollection_AddRef(&This->IHTMLAttributeCollection_iface);
2454 }
2455
2456 static ULONG WINAPI HTMLAttributeCollection3_Release(IHTMLAttributeCollection3 *iface)
2457 {
2458     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2459     return IHTMLAttributeCollection_Release(&This->IHTMLAttributeCollection_iface);
2460 }
2461
2462 static HRESULT WINAPI HTMLAttributeCollection3_GetTypeInfoCount(IHTMLAttributeCollection3 *iface, UINT *pctinfo)
2463 {
2464     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2465     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
2466 }
2467
2468 static HRESULT WINAPI HTMLAttributeCollection3_GetTypeInfo(IHTMLAttributeCollection3 *iface, UINT iTInfo,
2469         LCID lcid, ITypeInfo **ppTInfo)
2470 {
2471     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2472     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
2473 }
2474
2475 static HRESULT WINAPI HTMLAttributeCollection3_GetIDsOfNames(IHTMLAttributeCollection3 *iface, REFIID riid,
2476         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
2477 {
2478     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2479     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
2480             lcid, rgDispId);
2481 }
2482
2483 static HRESULT WINAPI HTMLAttributeCollection3_Invoke(IHTMLAttributeCollection3 *iface, DISPID dispIdMember,
2484         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
2485         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
2486 {
2487     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2488     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
2489             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
2490 }
2491
2492 static HRESULT WINAPI HTMLAttributeCollection3_getNamedItem(IHTMLAttributeCollection3 *iface, BSTR bstrName,
2493         IHTMLDOMAttribute **ppNodeOut)
2494 {
2495     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2496     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), ppNodeOut);
2497     return E_NOTIMPL;
2498 }
2499
2500 static HRESULT WINAPI HTMLAttributeCollection3_setNamedItem(IHTMLAttributeCollection3 *iface,
2501         IHTMLDOMAttribute *pNodeIn, IHTMLDOMAttribute **ppNodeOut)
2502 {
2503     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2504     FIXME("(%p)->(%p %p)\n", This, pNodeIn, ppNodeOut);
2505     return E_NOTIMPL;
2506 }
2507
2508 static HRESULT WINAPI HTMLAttributeCollection3_removeNamedItem(IHTMLAttributeCollection3 *iface,
2509         BSTR bstrName, IHTMLDOMAttribute **ppNodeOut)
2510 {
2511     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2512     FIXME("(%p)->(%s %p)\n", This, debugstr_w(bstrName), ppNodeOut);
2513     return E_NOTIMPL;
2514 }
2515
2516 static HRESULT WINAPI HTMLAttributeCollection3_item(IHTMLAttributeCollection3 *iface, LONG index, IHTMLDOMAttribute **ppNodeOut)
2517 {
2518     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2519     HTMLDOMAttribute *attr;
2520     DISPID id;
2521     HRESULT hres;
2522
2523     TRACE("(%p)->(%d %p)\n", This, index, ppNodeOut);
2524
2525     hres = get_attr_dispid_by_idx(This, &index, &id);
2526     if(hres == DISP_E_UNKNOWNNAME)
2527         return E_INVALIDARG;
2528     if(FAILED(hres))
2529         return hres;
2530
2531     hres = get_domattr(This->elem, id, &attr);
2532     if(FAILED(hres))
2533         return hres;
2534
2535     *ppNodeOut = &attr->IHTMLDOMAttribute_iface;
2536     return S_OK;
2537 }
2538
2539 static HRESULT WINAPI HTMLAttributeCollection3_get_length(IHTMLAttributeCollection3 *iface, LONG *p)
2540 {
2541     HTMLAttributeCollection *This = impl_from_IHTMLAttributeCollection3(iface);
2542     return IHTMLAttributeCollection_get_length(&This->IHTMLAttributeCollection_iface, p);
2543 }
2544
2545 static const IHTMLAttributeCollection3Vtbl HTMLAttributeCollection3Vtbl = {
2546     HTMLAttributeCollection3_QueryInterface,
2547     HTMLAttributeCollection3_AddRef,
2548     HTMLAttributeCollection3_Release,
2549     HTMLAttributeCollection3_GetTypeInfoCount,
2550     HTMLAttributeCollection3_GetTypeInfo,
2551     HTMLAttributeCollection3_GetIDsOfNames,
2552     HTMLAttributeCollection3_Invoke,
2553     HTMLAttributeCollection3_getNamedItem,
2554     HTMLAttributeCollection3_setNamedItem,
2555     HTMLAttributeCollection3_removeNamedItem,
2556     HTMLAttributeCollection3_item,
2557     HTMLAttributeCollection3_get_length
2558 };
2559
2560 static inline HTMLAttributeCollection *HTMLAttributeCollection_from_DispatchEx(DispatchEx *iface)
2561 {
2562     return CONTAINING_RECORD(iface, HTMLAttributeCollection, dispex);
2563 }
2564
2565 static HRESULT HTMLAttributeCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
2566 {
2567     HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex);
2568     FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(name), flags, dispid);
2569     return E_NOTIMPL;
2570 }
2571
2572 static HRESULT HTMLAttributeCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
2573         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
2574 {
2575     HTMLAttributeCollection *This = HTMLAttributeCollection_from_DispatchEx(dispex);
2576     FIXME("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
2577     return E_NOTIMPL;
2578 }
2579
2580 static const dispex_static_data_vtbl_t HTMLAttributeCollection_dispex_vtbl = {
2581     NULL,
2582     HTMLAttributeCollection_get_dispid,
2583     HTMLAttributeCollection_invoke,
2584     NULL
2585 };
2586
2587 static const tid_t HTMLAttributeCollection_iface_tids[] = {
2588     IHTMLAttributeCollection_tid,
2589     IHTMLAttributeCollection2_tid,
2590     IHTMLAttributeCollection3_tid,
2591     0
2592 };
2593
2594 static dispex_static_data_t HTMLAttributeCollection_dispex = {
2595     &HTMLAttributeCollection_dispex_vtbl,
2596     DispHTMLAttributeCollection_tid,
2597     NULL,
2598     HTMLAttributeCollection_iface_tids
2599 };
2600
2601 HRESULT HTMLElement_get_attr_col(HTMLDOMNode *iface, HTMLAttributeCollection **ac)
2602 {
2603     HTMLElement *This = impl_from_HTMLDOMNode(iface);
2604     HTMLAttributeCollection *ret;
2605
2606     ret = heap_alloc_zero(sizeof(*ret));
2607     if(!ret)
2608         return E_OUTOFMEMORY;
2609
2610     ret->IHTMLAttributeCollection_iface.lpVtbl = &HTMLAttributeCollectionVtbl;
2611     ret->IHTMLAttributeCollection2_iface.lpVtbl = &HTMLAttributeCollection2Vtbl;
2612     ret->IHTMLAttributeCollection3_iface.lpVtbl = &HTMLAttributeCollection3Vtbl;
2613     ret->ref = 1;
2614
2615     IHTMLElement_AddRef(&This->IHTMLElement_iface);
2616     ret->elem = This;
2617
2618     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLAttributeCollection_iface,
2619             &HTMLAttributeCollection_dispex);
2620
2621     *ac = ret;
2622     return S_OK;
2623 }