mshtml: COM cleanup for the IHTMLElement3 iface.
[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 #include "wine/unicode.h"
33
34 #include "mshtml_private.h"
35 #include "htmlevent.h"
36
37 static const WCHAR aW[]        = {'A',0};
38 static const WCHAR bodyW[]     = {'B','O','D','Y',0};
39 static const WCHAR embedW[]    = {'E','M','B','E','D',0};
40 static const WCHAR formW[]     = {'F','O','R','M',0};
41 static const WCHAR frameW[]    = {'F','R','A','M','E',0};
42 static const WCHAR iframeW[]   = {'I','F','R','A','M','E',0};
43 static const WCHAR imgW[]      = {'I','M','G',0};
44 static const WCHAR inputW[]    = {'I','N','P','U','T',0};
45 static const WCHAR objectW[]   = {'O','B','J','E','C','T',0};
46 static const WCHAR optionW[]   = {'O','P','T','I','O','N',0};
47 static const WCHAR scriptW[]   = {'S','C','R','I','P','T',0};
48 static const WCHAR selectW[]   = {'S','E','L','E','C','T',0};
49 static const WCHAR styleW[]    = {'S','T','Y','L','E',0};
50 static const WCHAR tableW[]    = {'T','A','B','L','E',0};
51 static const WCHAR textareaW[] = {'T','E','X','T','A','R','E','A',0};
52 static const WCHAR trW[]       = {'T','R',0};
53
54 typedef struct {
55     const WCHAR *name;
56     HRESULT (*constructor)(HTMLDocumentNode*,nsIDOMHTMLElement*,HTMLElement**);
57 } tag_desc_t;
58
59 static const tag_desc_t tag_descs[] = {
60     {aW,         HTMLAnchorElement_Create},
61     {bodyW,      HTMLBodyElement_Create},
62     {embedW,     HTMLEmbedElement_Create},
63     {formW,      HTMLFormElement_Create},
64     {frameW,     HTMLFrameElement_Create},
65     {iframeW,    HTMLIFrame_Create},
66     {imgW,       HTMLImgElement_Create},
67     {inputW,     HTMLInputElement_Create},
68     {objectW,    HTMLObjectElement_Create},
69     {optionW,    HTMLOptionElement_Create},
70     {scriptW,    HTMLScriptElement_Create},
71     {selectW,    HTMLSelectElement_Create},
72     {styleW,     HTMLStyleElement_Create},
73     {tableW,     HTMLTable_Create},
74     {textareaW,  HTMLTextAreaElement_Create},
75     {trW,        HTMLTableRow_Create}
76 };
77
78 static const tag_desc_t *get_tag_desc(const WCHAR *tag_name)
79 {
80     DWORD min=0, max=sizeof(tag_descs)/sizeof(*tag_descs)-1, i;
81     int r;
82
83     while(min <= max) {
84         i = (min+max)/2;
85         r = strcmpW(tag_name, tag_descs[i].name);
86         if(!r)
87             return tag_descs+i;
88
89         if(r < 0)
90             max = i-1;
91         else
92             min = i+1;
93     }
94
95     return NULL;
96 }
97
98 typedef struct
99 {
100     DispatchEx dispex;
101     const IHTMLFiltersCollectionVtbl *lpHTMLFiltersCollectionVtbl;
102
103     LONG ref;
104 } HTMLFiltersCollection;
105
106 #define HTMLFILTERSCOLLECTION(x)     ((IHTMLFiltersCollection*)  &(x)->lpHTMLFiltersCollectionVtbl)
107
108 #define HTMLFILTERSCOLLECTION_THIS(iface) \
109     DEFINE_THIS(HTMLFiltersCollection, HTMLFiltersCollection, iface)
110
111 IHTMLFiltersCollection *HTMLFiltersCollection_Create(void);
112
113
114 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
115
116 static inline HTMLElement *impl_from_IHTMLElement(IHTMLElement *iface)
117 {
118     return CONTAINING_RECORD(iface, HTMLElement, IHTMLElement_iface);
119 }
120
121 HRESULT create_nselem(HTMLDocumentNode *doc, const WCHAR *tag, nsIDOMHTMLElement **ret)
122 {
123     nsIDOMElement *nselem;
124     nsAString tag_str;
125     nsresult nsres;
126
127     if(!doc->nsdoc) {
128         WARN("NULL nsdoc\n");
129         return E_UNEXPECTED;
130     }
131
132     nsAString_InitDepend(&tag_str, tag);
133     nsres = nsIDOMDocument_CreateElement(doc->nsdoc, &tag_str, &nselem);
134     nsAString_Finish(&tag_str);
135     if(NS_FAILED(nsres)) {
136         ERR("CreateElement failed: %08x\n", nsres);
137         return E_FAIL;
138     }
139
140     nsres = nsIDOMElement_QueryInterface(nselem, &IID_nsIDOMHTMLElement, (void**)ret);
141     nsIDOMElement_Release(nselem);
142     if(NS_FAILED(nsres)) {
143         ERR("Could not get nsIDOMHTMLElement iface: %08x\n", nsres);
144         return E_FAIL;
145     }
146
147     return S_OK;
148 }
149
150 static HRESULT WINAPI HTMLElement_QueryInterface(IHTMLElement *iface,
151                                                  REFIID riid, void **ppv)
152 {
153     HTMLElement *This = impl_from_IHTMLElement(iface);
154
155     return IHTMLDOMNode_QueryInterface(HTMLDOMNODE(&This->node), riid, ppv);
156 }
157
158 static ULONG WINAPI HTMLElement_AddRef(IHTMLElement *iface)
159 {
160     HTMLElement *This = impl_from_IHTMLElement(iface);
161
162     return IHTMLDOMNode_AddRef(HTMLDOMNODE(&This->node));
163 }
164
165 static ULONG WINAPI HTMLElement_Release(IHTMLElement *iface)
166 {
167     HTMLElement *This = impl_from_IHTMLElement(iface);
168
169     return IHTMLDOMNode_Release(HTMLDOMNODE(&This->node));
170 }
171
172 static HRESULT WINAPI HTMLElement_GetTypeInfoCount(IHTMLElement *iface, UINT *pctinfo)
173 {
174     HTMLElement *This = impl_from_IHTMLElement(iface);
175     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->node.dispex), pctinfo);
176 }
177
178 static HRESULT WINAPI HTMLElement_GetTypeInfo(IHTMLElement *iface, UINT iTInfo,
179                                               LCID lcid, ITypeInfo **ppTInfo)
180 {
181     HTMLElement *This = impl_from_IHTMLElement(iface);
182     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->node.dispex), iTInfo, lcid, ppTInfo);
183 }
184
185 static HRESULT WINAPI HTMLElement_GetIDsOfNames(IHTMLElement *iface, REFIID riid,
186                                                 LPOLESTR *rgszNames, UINT cNames,
187                                                 LCID lcid, DISPID *rgDispId)
188 {
189     HTMLElement *This = impl_from_IHTMLElement(iface);
190     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->node.dispex), riid, rgszNames, cNames, lcid, rgDispId);
191 }
192
193 static HRESULT WINAPI HTMLElement_Invoke(IHTMLElement *iface, DISPID dispIdMember,
194                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
195                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
196 {
197     HTMLElement *This = impl_from_IHTMLElement(iface);
198     return IDispatchEx_Invoke(DISPATCHEX(&This->node.dispex), dispIdMember, riid, lcid,
199             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
200 }
201
202 static HRESULT WINAPI HTMLElement_setAttribute(IHTMLElement *iface, BSTR strAttributeName,
203                                                VARIANT AttributeValue, LONG lFlags)
204 {
205     HTMLElement *This = impl_from_IHTMLElement(iface);
206     HRESULT hres;
207     DISPID dispid, dispidNamed = DISPID_PROPERTYPUT;
208     DISPPARAMS dispParams;
209     EXCEPINFO excep;
210
211     TRACE("(%p)->(%s . %08x)\n", This, debugstr_w(strAttributeName), lFlags);
212
213     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
214             fdexNameCaseInsensitive | fdexNameEnsure, &dispid);
215     if(FAILED(hres))
216         return hres;
217
218     dispParams.cArgs = 1;
219     dispParams.cNamedArgs = 1;
220     dispParams.rgdispidNamedArgs = &dispidNamed;
221     dispParams.rgvarg = &AttributeValue;
222
223     hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
224             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &dispParams,
225             NULL, &excep, NULL);
226     return hres;
227 }
228
229 static HRESULT WINAPI HTMLElement_getAttribute(IHTMLElement *iface, BSTR strAttributeName,
230                                                LONG lFlags, VARIANT *AttributeValue)
231 {
232     HTMLElement *This = impl_from_IHTMLElement(iface);
233     DISPID dispid;
234     HRESULT hres;
235     DISPPARAMS dispParams = {NULL, NULL, 0, 0};
236     EXCEPINFO excep;
237
238     TRACE("(%p)->(%s %08x %p)\n", This, debugstr_w(strAttributeName), lFlags, AttributeValue);
239
240     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->node.dispex), strAttributeName,
241             fdexNameCaseInsensitive, &dispid);
242     if(hres == DISP_E_UNKNOWNNAME) {
243         V_VT(AttributeValue) = VT_NULL;
244         return S_OK;
245     }
246
247     if(FAILED(hres)) {
248         V_VT(AttributeValue) = VT_NULL;
249         return hres;
250     }
251
252     hres = IDispatchEx_InvokeEx(DISPATCHEX(&This->node.dispex), dispid,
253             LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dispParams,
254             AttributeValue, &excep, NULL);
255
256     return hres;
257 }
258
259 static HRESULT WINAPI HTMLElement_removeAttribute(IHTMLElement *iface, BSTR strAttributeName,
260                                                   LONG lFlags, VARIANT_BOOL *pfSuccess)
261 {
262     HTMLElement *This = impl_from_IHTMLElement(iface);
263
264     TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(strAttributeName), lFlags, pfSuccess);
265
266     return remove_prop(&This->node.dispex, strAttributeName, pfSuccess);
267 }
268
269 static HRESULT WINAPI HTMLElement_put_className(IHTMLElement *iface, BSTR v)
270 {
271     HTMLElement *This = impl_from_IHTMLElement(iface);
272     nsAString classname_str;
273     nsresult nsres;
274
275     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
276
277     if(!This->nselem) {
278         FIXME("NULL nselem\n");
279         return E_NOTIMPL;
280     }
281
282     nsAString_InitDepend(&classname_str, v);
283     nsres = nsIDOMHTMLElement_SetClassName(This->nselem, &classname_str);
284     nsAString_Finish(&classname_str);
285     if(NS_FAILED(nsres))
286         ERR("SetClassName failed: %08x\n", nsres);
287
288     return S_OK;
289 }
290
291 static HRESULT WINAPI HTMLElement_get_className(IHTMLElement *iface, BSTR *p)
292 {
293     HTMLElement *This = impl_from_IHTMLElement(iface);
294     nsAString class_str;
295     nsresult nsres;
296     HRESULT hres = S_OK;
297
298     TRACE("(%p)->(%p)\n", This, p);
299
300     if(!This->nselem) {
301         FIXME("NULL nselem\n");
302         return E_NOTIMPL;
303     }
304
305     nsAString_Init(&class_str, NULL);
306     nsres = nsIDOMHTMLElement_GetClassName(This->nselem, &class_str);
307
308     if(NS_SUCCEEDED(nsres)) {
309         const PRUnichar *class;
310         nsAString_GetData(&class_str, &class);
311         *p = *class ? SysAllocString(class) : NULL;
312     }else {
313         ERR("GetClassName failed: %08x\n", nsres);
314         hres = E_FAIL;
315     }
316
317     nsAString_Finish(&class_str);
318
319     TRACE("className=%s\n", debugstr_w(*p));
320     return hres;
321 }
322
323 static HRESULT WINAPI HTMLElement_put_id(IHTMLElement *iface, BSTR v)
324 {
325     HTMLElement *This = impl_from_IHTMLElement(iface);
326     nsAString id_str;
327     nsresult nsres;
328
329     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
330
331     if(!This->nselem) {
332         FIXME("nselem == NULL\n");
333         return S_OK;
334     }
335
336     nsAString_InitDepend(&id_str, v);
337     nsres = nsIDOMHTMLElement_SetId(This->nselem, &id_str);
338     nsAString_Finish(&id_str);
339     if(NS_FAILED(nsres))
340         ERR("SetId failed: %08x\n", nsres);
341
342     return S_OK;
343 }
344
345 static HRESULT WINAPI HTMLElement_get_id(IHTMLElement *iface, BSTR *p)
346 {
347     HTMLElement *This = impl_from_IHTMLElement(iface);
348     const PRUnichar *id;
349     nsAString id_str;
350     nsresult nsres;
351
352     TRACE("(%p)->(%p)\n", This, p);
353
354     *p = NULL;
355
356     if(!This->nselem)
357         return S_OK;
358
359     nsAString_Init(&id_str, NULL);
360     nsres = nsIDOMHTMLElement_GetId(This->nselem, &id_str);
361     nsAString_GetData(&id_str, &id);
362
363     if(NS_FAILED(nsres))
364         ERR("GetId failed: %08x\n", nsres);
365     else if(*id)
366         *p = SysAllocString(id);
367
368     nsAString_Finish(&id_str);
369     return S_OK;
370 }
371
372 static HRESULT WINAPI HTMLElement_get_tagName(IHTMLElement *iface, BSTR *p)
373 {
374     HTMLElement *This = impl_from_IHTMLElement(iface);
375     const PRUnichar *tag;
376     nsAString tag_str;
377     nsresult nsres;
378
379     TRACE("(%p)->(%p)\n", This, p);
380
381     if(!This->nselem) {
382         static const WCHAR comment_tagW[] = {'!',0};
383
384         WARN("NULL nselem, assuming comment\n");
385
386         *p = SysAllocString(comment_tagW);
387         return S_OK;
388     }
389
390     nsAString_Init(&tag_str, NULL);
391     nsres = nsIDOMHTMLElement_GetTagName(This->nselem, &tag_str);
392     if(NS_SUCCEEDED(nsres)) {
393         nsAString_GetData(&tag_str, &tag);
394         *p = SysAllocString(tag);
395     }else {
396         ERR("GetTagName failed: %08x\n", nsres);
397         *p = NULL;
398     }
399     nsAString_Finish(&tag_str);
400
401     return S_OK;
402 }
403
404 static HRESULT WINAPI HTMLElement_get_parentElement(IHTMLElement *iface, IHTMLElement **p)
405 {
406     HTMLElement *This = impl_from_IHTMLElement(iface);
407     IHTMLDOMNode *node;
408     HRESULT hres;
409
410     TRACE("(%p)->(%p)\n", This, p);
411
412     hres = IHTMLDOMNode_get_parentNode(HTMLDOMNODE(&This->node), &node);
413     if(FAILED(hres))
414         return hres;
415
416     hres = IHTMLDOMNode_QueryInterface(node, &IID_IHTMLElement, (void**)p);
417     IHTMLDOMNode_Release(node);
418     if(FAILED(hres))
419         *p = NULL;
420
421     return S_OK;
422 }
423
424 static HRESULT WINAPI HTMLElement_get_style(IHTMLElement *iface, IHTMLStyle **p)
425 {
426     HTMLElement *This = impl_from_IHTMLElement(iface);
427     nsIDOMElementCSSInlineStyle *nselemstyle;
428     nsIDOMCSSStyleDeclaration *nsstyle;
429     nsresult nsres;
430
431     TRACE("(%p)->(%p)\n", This, p);
432
433     if(!This->nselem) {
434         FIXME("NULL nselem\n");
435         return E_NOTIMPL;
436     }
437
438     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMElementCSSInlineStyle,
439                                              (void**)&nselemstyle);
440     if(NS_FAILED(nsres)) {
441         ERR("Coud not get nsIDOMCSSStyleDeclaration interface: %08x\n", nsres);
442         return E_FAIL;
443     }
444
445     nsres = nsIDOMElementCSSInlineStyle_GetStyle(nselemstyle, &nsstyle);
446     nsIDOMElementCSSInlineStyle_Release(nselemstyle);
447     if(NS_FAILED(nsres)) {
448         ERR("GetStyle failed: %08x\n", nsres);
449         return E_FAIL;
450     }
451
452     /* FIXME: Store style instead of creating a new instance in each call */
453     *p = HTMLStyle_Create(nsstyle);
454
455     nsIDOMCSSStyleDeclaration_Release(nsstyle);
456     return S_OK;
457 }
458
459 static HRESULT WINAPI HTMLElement_put_onhelp(IHTMLElement *iface, VARIANT v)
460 {
461     HTMLElement *This = impl_from_IHTMLElement(iface);
462     FIXME("(%p)->()\n", This);
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI HTMLElement_get_onhelp(IHTMLElement *iface, VARIANT *p)
467 {
468     HTMLElement *This = impl_from_IHTMLElement(iface);
469     FIXME("(%p)->(%p)\n", This, p);
470     return E_NOTIMPL;
471 }
472
473 static HRESULT WINAPI HTMLElement_put_onclick(IHTMLElement *iface, VARIANT v)
474 {
475     HTMLElement *This = impl_from_IHTMLElement(iface);
476
477     TRACE("(%p)->()\n", This);
478
479     return set_node_event(&This->node, EVENTID_CLICK, &v);
480 }
481
482 static HRESULT WINAPI HTMLElement_get_onclick(IHTMLElement *iface, VARIANT *p)
483 {
484     HTMLElement *This = impl_from_IHTMLElement(iface);
485
486     TRACE("(%p)->(%p)\n", This, p);
487
488     return get_node_event(&This->node, EVENTID_CLICK, p);
489 }
490
491 static HRESULT WINAPI HTMLElement_put_ondblclick(IHTMLElement *iface, VARIANT v)
492 {
493     HTMLElement *This = impl_from_IHTMLElement(iface);
494
495     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
496
497     return set_node_event(&This->node, EVENTID_DBLCLICK, &v);
498 }
499
500 static HRESULT WINAPI HTMLElement_get_ondblclick(IHTMLElement *iface, VARIANT *p)
501 {
502     HTMLElement *This = impl_from_IHTMLElement(iface);
503
504     TRACE("(%p)->(%p)\n", This, p);
505
506     return get_node_event(&This->node, EVENTID_DBLCLICK, p);
507 }
508
509 static HRESULT WINAPI HTMLElement_put_onkeydown(IHTMLElement *iface, VARIANT v)
510 {
511     HTMLElement *This = impl_from_IHTMLElement(iface);
512
513     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
514
515     return set_node_event(&This->node, EVENTID_KEYDOWN, &v);
516 }
517
518 static HRESULT WINAPI HTMLElement_get_onkeydown(IHTMLElement *iface, VARIANT *p)
519 {
520     HTMLElement *This = impl_from_IHTMLElement(iface);
521
522     TRACE("(%p)->(%p)\n", This, p);
523
524     return get_node_event(&This->node, EVENTID_KEYDOWN, p);
525 }
526
527 static HRESULT WINAPI HTMLElement_put_onkeyup(IHTMLElement *iface, VARIANT v)
528 {
529     HTMLElement *This = impl_from_IHTMLElement(iface);
530
531     TRACE("(%p)->()\n", This);
532
533     return set_node_event(&This->node, EVENTID_KEYUP, &v);
534 }
535
536 static HRESULT WINAPI HTMLElement_get_onkeyup(IHTMLElement *iface, VARIANT *p)
537 {
538     HTMLElement *This = impl_from_IHTMLElement(iface);
539     FIXME("(%p)->(%p)\n", This, p);
540     return E_NOTIMPL;
541 }
542
543 static HRESULT WINAPI HTMLElement_put_onkeypress(IHTMLElement *iface, VARIANT v)
544 {
545     HTMLElement *This = impl_from_IHTMLElement(iface);
546     FIXME("(%p)->()\n", This);
547     return E_NOTIMPL;
548 }
549
550 static HRESULT WINAPI HTMLElement_get_onkeypress(IHTMLElement *iface, VARIANT *p)
551 {
552     HTMLElement *This = impl_from_IHTMLElement(iface);
553     FIXME("(%p)->(%p)\n", This, p);
554     return E_NOTIMPL;
555 }
556
557 static HRESULT WINAPI HTMLElement_put_onmouseout(IHTMLElement *iface, VARIANT v)
558 {
559     HTMLElement *This = impl_from_IHTMLElement(iface);
560
561     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
562
563     return set_node_event(&This->node, EVENTID_MOUSEOUT, &v);
564 }
565
566 static HRESULT WINAPI HTMLElement_get_onmouseout(IHTMLElement *iface, VARIANT *p)
567 {
568     HTMLElement *This = impl_from_IHTMLElement(iface);
569
570     TRACE("(%p)->(%p)\n", This, p);
571
572     return get_node_event(&This->node, EVENTID_MOUSEOUT, p);
573 }
574
575 static HRESULT WINAPI HTMLElement_put_onmouseover(IHTMLElement *iface, VARIANT v)
576 {
577     HTMLElement *This = impl_from_IHTMLElement(iface);
578
579     TRACE("(%p)->()\n", This);
580
581     return set_node_event(&This->node, EVENTID_MOUSEOVER, &v);
582 }
583
584 static HRESULT WINAPI HTMLElement_get_onmouseover(IHTMLElement *iface, VARIANT *p)
585 {
586     HTMLElement *This = impl_from_IHTMLElement(iface);
587
588     TRACE("(%p)->(%p)\n", This, p);
589
590     return get_node_event(&This->node, EVENTID_MOUSEOVER, p);
591 }
592
593 static HRESULT WINAPI HTMLElement_put_onmousemove(IHTMLElement *iface, VARIANT v)
594 {
595     HTMLElement *This = impl_from_IHTMLElement(iface);
596     FIXME("(%p)->()\n", This);
597     return E_NOTIMPL;
598 }
599
600 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
601 {
602     HTMLElement *This = impl_from_IHTMLElement(iface);
603     FIXME("(%p)->(%p)\n", This, p);
604     return E_NOTIMPL;
605 }
606
607 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
608 {
609     HTMLElement *This = impl_from_IHTMLElement(iface);
610
611     TRACE("(%p)->()\n", This);
612
613     return set_node_event(&This->node, EVENTID_MOUSEDOWN, &v);
614 }
615
616 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
617 {
618     HTMLElement *This = impl_from_IHTMLElement(iface);
619
620     TRACE("(%p)->(%p)\n", This, p);
621
622     return get_node_event(&This->node, EVENTID_MOUSEDOWN, p);
623 }
624
625 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
626 {
627     HTMLElement *This = impl_from_IHTMLElement(iface);
628
629     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
630
631     return set_node_event(&This->node, EVENTID_MOUSEUP, &v);
632 }
633
634 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
635 {
636     HTMLElement *This = impl_from_IHTMLElement(iface);
637
638     TRACE("(%p)->(%p)\n", This, p);
639
640     return get_node_event(&This->node, EVENTID_MOUSEUP, p);
641 }
642
643 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
644 {
645     HTMLElement *This = impl_from_IHTMLElement(iface);
646
647     TRACE("(%p)->(%p)\n", This, p);
648
649     if(!p)
650         return E_POINTER;
651
652     if(This->node.vtbl->get_document)
653         return This->node.vtbl->get_document(&This->node, p);
654
655     *p = (IDispatch*)&This->node.doc->basedoc.IHTMLDocument2_iface;
656     IDispatch_AddRef(*p);
657     return S_OK;
658 }
659
660 static const WCHAR titleW[] = {'t','i','t','l','e',0};
661
662 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
663 {
664     HTMLElement *This = impl_from_IHTMLElement(iface);
665     nsAString title_str;
666     nsresult nsres;
667
668     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
669
670     if(!This->nselem) {
671         VARIANT *var;
672         HRESULT hres;
673
674         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, TRUE, &var);
675         if(FAILED(hres))
676             return hres;
677
678         VariantClear(var);
679         V_VT(var) = VT_BSTR;
680         V_BSTR(var) = v ? SysAllocString(v) : NULL;
681         return S_OK;
682     }
683
684     nsAString_InitDepend(&title_str, v);
685     nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str);
686     nsAString_Finish(&title_str);
687     if(NS_FAILED(nsres))
688         ERR("SetTitle failed: %08x\n", nsres);
689
690     return S_OK;
691 }
692
693 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
694 {
695     HTMLElement *This = impl_from_IHTMLElement(iface);
696     nsAString title_str;
697     nsresult nsres;
698
699     TRACE("(%p)->(%p)\n", This, p);
700
701     if(!This->nselem) {
702         VARIANT *var;
703         HRESULT hres;
704
705         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, FALSE, &var);
706         if(hres == DISP_E_UNKNOWNNAME) {
707             *p = NULL;
708         }else if(V_VT(var) != VT_BSTR) {
709             FIXME("title = %s\n", debugstr_variant(var));
710             return E_FAIL;
711         }else {
712             *p = V_BSTR(var) ? SysAllocString(V_BSTR(var)) : NULL;
713         }
714
715         return S_OK;
716     }
717
718     nsAString_Init(&title_str, NULL);
719     nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str);
720     if(NS_SUCCEEDED(nsres)) {
721         const PRUnichar *title;
722
723         nsAString_GetData(&title_str, &title);
724         *p = *title ? SysAllocString(title) : NULL;
725     }else {
726         ERR("GetTitle failed: %08x\n", nsres);
727         return E_FAIL;
728     }
729
730     return S_OK;
731 }
732
733 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
734 {
735     HTMLElement *This = impl_from_IHTMLElement(iface);
736     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
737     return E_NOTIMPL;
738 }
739
740 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
741 {
742     HTMLElement *This = impl_from_IHTMLElement(iface);
743     FIXME("(%p)->(%p)\n", This, p);
744     return E_NOTIMPL;
745 }
746
747 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
748 {
749     HTMLElement *This = impl_from_IHTMLElement(iface);
750
751     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
752
753     return set_node_event(&This->node, EVENTID_SELECTSTART, &v);
754 }
755
756 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
757 {
758     HTMLElement *This = impl_from_IHTMLElement(iface);
759
760     TRACE("(%p)->(%p)\n", This, p);
761
762     return get_node_event(&This->node, EVENTID_SELECTSTART, p);
763 }
764
765 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
766 {
767     HTMLElement *This = impl_from_IHTMLElement(iface);
768     FIXME("(%p)->()\n", This);
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
773                                            VARIANT_BOOL *pfResult)
774 {
775     HTMLElement *This = impl_from_IHTMLElement(iface);
776     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
777     return E_NOTIMPL;
778 }
779
780 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
781 {
782     HTMLElement *This = impl_from_IHTMLElement(iface);
783     FIXME("(%p)->(%p)\n", This, p);
784     return E_NOTIMPL;
785 }
786
787 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
788 {
789     HTMLElement *This = impl_from_IHTMLElement(iface);
790     FIXME("(%p)->(%p)\n", This, p);
791     return E_NOTIMPL;
792 }
793
794 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
795 {
796     HTMLElement *This = impl_from_IHTMLElement(iface);
797     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
798     return E_NOTIMPL;
799 }
800
801 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
802 {
803     HTMLElement *This = impl_from_IHTMLElement(iface);
804     FIXME("(%p)->(%p)\n", This, p);
805     return E_NOTIMPL;
806 }
807
808 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, LONG *p)
809 {
810     HTMLElement *This = impl_from_IHTMLElement(iface);
811     FIXME("(%p)->(%p)\n", This, p);
812     return E_NOTIMPL;
813 }
814
815 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, LONG *p)
816 {
817     HTMLElement *This = impl_from_IHTMLElement(iface);
818     nsIDOMNSHTMLElement *nselem;
819     PRInt32 top = 0;
820     nsresult nsres;
821
822     TRACE("(%p)->(%p)\n", This, p);
823
824     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
825     if(NS_FAILED(nsres)) {
826         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
827         return E_FAIL;
828     }
829
830     nsres = nsIDOMNSHTMLElement_GetOffsetTop(nselem, &top);
831     nsIDOMNSHTMLElement_Release(nselem);
832     if(NS_FAILED(nsres)) {
833         ERR("GetOffsetTop failed: %08x\n", nsres);
834         return E_FAIL;
835     }
836
837     *p = top;
838     return S_OK;
839 }
840
841 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, LONG *p)
842 {
843     HTMLElement *This = impl_from_IHTMLElement(iface);
844     nsIDOMNSHTMLElement *nselem;
845     PRInt32 offset = 0;
846     nsresult nsres;
847
848     TRACE("(%p)->(%p)\n", This, p);
849
850     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
851     if(NS_FAILED(nsres)) {
852         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
853         return E_FAIL;
854     }
855
856     nsres = nsIDOMNSHTMLElement_GetOffsetWidth(nselem, &offset);
857     nsIDOMNSHTMLElement_Release(nselem);
858     if(NS_FAILED(nsres)) {
859         ERR("GetOffsetWidth failed: %08x\n", nsres);
860         return E_FAIL;
861     }
862
863     *p = offset;
864     return S_OK;
865 }
866
867 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, LONG *p)
868 {
869     HTMLElement *This = impl_from_IHTMLElement(iface);
870     nsIDOMNSHTMLElement *nselem;
871     PRInt32 offset = 0;
872     nsresult nsres;
873
874     TRACE("(%p)->(%p)\n", This, p);
875
876     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
877     if(NS_FAILED(nsres)) {
878         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
879         return E_FAIL;
880     }
881
882     nsres = nsIDOMNSHTMLElement_GetOffsetHeight(nselem, &offset);
883     nsIDOMNSHTMLElement_Release(nselem);
884     if(NS_FAILED(nsres)) {
885         ERR("GetOffsetHeight failed: %08x\n", nsres);
886         return E_FAIL;
887     }
888
889     *p = offset;
890     return S_OK;
891 }
892
893 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
894 {
895     HTMLElement *This = impl_from_IHTMLElement(iface);
896     FIXME("(%p)->(%p)\n", This, p);
897     return E_NOTIMPL;
898 }
899
900 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
901 {
902     HTMLElement *This = impl_from_IHTMLElement(iface);
903     nsIDOMNSHTMLElement *nselem;
904     nsAString html_str;
905     nsresult nsres;
906
907     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
908
909     if(!This->nselem) {
910         FIXME("NULL nselem\n");
911         return E_NOTIMPL;
912     }
913
914     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
915     if(NS_FAILED(nsres)) {
916         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
917         return E_FAIL;
918     }
919
920     nsAString_InitDepend(&html_str, v);
921     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
922     nsAString_Finish(&html_str);
923
924     if(NS_FAILED(nsres)) {
925         FIXME("SetInnerHtml failed %08x\n", nsres);
926         return E_FAIL;
927     }
928
929     return S_OK;
930 }
931
932 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
933 {
934     HTMLElement *This = impl_from_IHTMLElement(iface);
935     nsIDOMNSHTMLElement *nselem;
936     nsAString html_str;
937     nsresult nsres;
938
939     TRACE("(%p)->(%p)\n", This, p);
940
941     if(!This->nselem) {
942         FIXME("NULL nselem\n");
943         return E_NOTIMPL;
944     }
945
946     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
947     if(NS_FAILED(nsres)) {
948         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
949         return E_FAIL;
950     }
951
952     nsAString_Init(&html_str, NULL);
953     nsres = nsIDOMNSHTMLElement_GetInnerHTML(nselem, &html_str);
954     if(NS_SUCCEEDED(nsres)) {
955         const PRUnichar *html;
956
957         nsAString_GetData(&html_str, &html);
958         *p = *html ? SysAllocString(html) : NULL;
959     }else {
960         FIXME("SetInnerHtml failed %08x\n", nsres);
961         *p = NULL;
962     }
963
964     nsAString_Finish(&html_str);
965     return S_OK;
966 }
967
968 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
969 {
970     HTMLElement *This = impl_from_IHTMLElement(iface);
971     nsIDOMNode *nschild, *tmp;
972     nsIDOMText *text_node;
973     nsAString text_str;
974     nsresult nsres;
975
976     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
977
978     while(1) {
979         nsres = nsIDOMHTMLElement_GetLastChild(This->nselem, &nschild);
980         if(NS_FAILED(nsres)) {
981             ERR("GetLastChild failed: %08x\n", nsres);
982             return E_FAIL;
983         }
984         if(!nschild)
985             break;
986
987         nsres = nsIDOMHTMLElement_RemoveChild(This->nselem, nschild, &tmp);
988         nsIDOMNode_Release(nschild);
989         if(NS_FAILED(nsres)) {
990             ERR("RemoveChild failed: %08x\n", nsres);
991             return E_FAIL;
992         }
993         nsIDOMNode_Release(tmp);
994     }
995
996     nsAString_InitDepend(&text_str, v);
997     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &text_str, &text_node);
998     nsAString_Finish(&text_str);
999     if(NS_FAILED(nsres)) {
1000         ERR("CreateTextNode failed: %08x\n", nsres);
1001         return E_FAIL;
1002     }
1003
1004     nsres = nsIDOMHTMLElement_AppendChild(This->nselem, (nsIDOMNode*)text_node, &tmp);
1005     if(NS_FAILED(nsres)) {
1006         ERR("AppendChild failed: %08x\n", nsres);
1007         return E_FAIL;
1008     }
1009
1010     nsIDOMNode_Release(tmp);
1011     return S_OK;
1012 }
1013
1014 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
1015 {
1016     HTMLElement *This = impl_from_IHTMLElement(iface);
1017
1018     TRACE("(%p)->(%p)\n", This, p);
1019
1020     return get_node_text(&This->node, p);
1021 }
1022
1023 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
1024 {
1025     HTMLElement *This = impl_from_IHTMLElement(iface);
1026     nsIDOMDocumentFragment *nsfragment;
1027     nsIDOMDocumentRange *nsdocrange;
1028     nsIDOMNSRange *nsrange;
1029     nsIDOMNode *nsparent;
1030     nsIDOMRange *range;
1031     nsAString html_str;
1032     nsresult nsres;
1033     HRESULT hres = S_OK;
1034
1035     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1036
1037     nsres = nsIDOMHTMLDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
1038     if(NS_FAILED(nsres))
1039         return E_FAIL;
1040
1041     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
1042     nsIDOMDocumentRange_Release(nsdocrange);
1043     if(NS_FAILED(nsres)) {
1044         ERR("CreateRange failed: %08x\n", nsres);
1045         return E_FAIL;
1046     }
1047
1048     nsres = nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void**)&nsrange);
1049     nsIDOMRange_Release(range);
1050     if(NS_FAILED(nsres)) {
1051         ERR("Could not get nsIDOMNSRange: %08x\n", nsres);
1052         return E_FAIL;
1053     }
1054
1055     nsAString_InitDepend(&html_str, v);
1056     nsIDOMNSRange_CreateContextualFragment(nsrange, &html_str, &nsfragment);
1057     nsIDOMNSRange_Release(nsrange);
1058     nsAString_Finish(&html_str);
1059     if(NS_FAILED(nsres)) {
1060         ERR("CreateContextualFragment failed: %08x\n", nsres);
1061         return E_FAIL;
1062     }
1063
1064     nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &nsparent);
1065     if(NS_SUCCEEDED(nsres) && nsparent) {
1066         nsIDOMNode *nstmp;
1067
1068         nsres = nsIDOMNode_ReplaceChild(nsparent, (nsIDOMNode*)nsfragment, This->node.nsnode, &nstmp);
1069         nsIDOMNode_Release(nsparent);
1070         if(NS_FAILED(nsres)) {
1071             ERR("ReplaceChild failed: %08x\n", nsres);
1072             hres = E_FAIL;
1073         }else if(nstmp) {
1074             nsIDOMNode_Release(nstmp);
1075         }
1076     }else {
1077         ERR("GetParentNode failed: %08x\n", nsres);
1078         hres = E_FAIL;
1079     }
1080
1081     nsIDOMDocumentFragment_Release(nsfragment);
1082     return hres;
1083 }
1084
1085 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
1086 {
1087     HTMLElement *This = impl_from_IHTMLElement(iface);
1088     nsAString html_str;
1089     HRESULT hres;
1090
1091     WARN("(%p)->(%p) semi-stub\n", This, p);
1092
1093     nsAString_Init(&html_str, NULL);
1094     hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
1095     if(SUCCEEDED(hres)) {
1096         const PRUnichar *html;
1097
1098         nsAString_GetData(&html_str, &html);
1099         *p = SysAllocString(html);
1100         if(!*p)
1101             hres = E_OUTOFMEMORY;
1102     }
1103
1104     nsAString_Finish(&html_str);
1105
1106     TRACE("ret %s\n", debugstr_w(*p));
1107     return S_OK;
1108 }
1109
1110 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
1111 {
1112     HTMLElement *This = impl_from_IHTMLElement(iface);
1113     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
1114     return E_NOTIMPL;
1115 }
1116
1117 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
1118 {
1119     HTMLElement *This = impl_from_IHTMLElement(iface);
1120     FIXME("(%p)->(%p)\n", This, p);
1121     return E_NOTIMPL;
1122 }
1123
1124 static HRESULT HTMLElement_InsertAdjacentNode(HTMLElement *This, BSTR where, nsIDOMNode *nsnode)
1125 {
1126     static const WCHAR wszBeforeBegin[] = {'b','e','f','o','r','e','B','e','g','i','n',0};
1127     static const WCHAR wszAfterBegin[] = {'a','f','t','e','r','B','e','g','i','n',0};
1128     static const WCHAR wszBeforeEnd[] = {'b','e','f','o','r','e','E','n','d',0};
1129     static const WCHAR wszAfterEnd[] = {'a','f','t','e','r','E','n','d',0};
1130     nsresult nsres;
1131
1132     if (!strcmpiW(where, wszBeforeBegin))
1133     {
1134         nsIDOMNode *unused;
1135         nsIDOMNode *parent;
1136         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1137         if (!parent) return E_INVALIDARG;
1138         nsres = nsIDOMNode_InsertBefore(parent, nsnode, This->node.nsnode, &unused);
1139         if (unused) nsIDOMNode_Release(unused);
1140         nsIDOMNode_Release(parent);
1141     }
1142     else if (!strcmpiW(where, wszAfterBegin))
1143     {
1144         nsIDOMNode *unused;
1145         nsIDOMNode *first_child;
1146         nsIDOMNode_GetFirstChild(This->node.nsnode, &first_child);
1147         nsres = nsIDOMNode_InsertBefore(This->node.nsnode, nsnode, first_child, &unused);
1148         if (unused) nsIDOMNode_Release(unused);
1149         if (first_child) nsIDOMNode_Release(first_child);
1150     }
1151     else if (!strcmpiW(where, wszBeforeEnd))
1152     {
1153         nsIDOMNode *unused;
1154         nsres = nsIDOMNode_AppendChild(This->node.nsnode, nsnode, &unused);
1155         if (unused) nsIDOMNode_Release(unused);
1156     }
1157     else if (!strcmpiW(where, wszAfterEnd))
1158     {
1159         nsIDOMNode *unused;
1160         nsIDOMNode *next_sibling;
1161         nsIDOMNode *parent;
1162         nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1163         if (!parent) return E_INVALIDARG;
1164
1165         nsIDOMNode_GetNextSibling(This->node.nsnode, &next_sibling);
1166         if (next_sibling)
1167         {
1168             nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &unused);
1169             nsIDOMNode_Release(next_sibling);
1170         }
1171         else
1172             nsres = nsIDOMNode_AppendChild(parent, nsnode, &unused);
1173         nsIDOMNode_Release(parent);
1174         if (unused) nsIDOMNode_Release(unused);
1175     }
1176     else
1177     {
1178         ERR("invalid where: %s\n", debugstr_w(where));
1179         return E_INVALIDARG;
1180     }
1181
1182     if (NS_FAILED(nsres))
1183         return E_FAIL;
1184     else
1185         return S_OK;
1186 }
1187
1188 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
1189                                                      BSTR html)
1190 {
1191     HTMLElement *This = impl_from_IHTMLElement(iface);
1192     nsIDOMDocumentRange *nsdocrange;
1193     nsIDOMRange *range;
1194     nsIDOMNSRange *nsrange;
1195     nsIDOMNode *nsnode;
1196     nsAString ns_html;
1197     nsresult nsres;
1198     HRESULT hr;
1199
1200     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
1201
1202     if(!This->node.doc->nsdoc) {
1203         WARN("NULL nsdoc\n");
1204         return E_UNEXPECTED;
1205     }
1206
1207     nsres = nsIDOMDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void **)&nsdocrange);
1208     if(NS_FAILED(nsres))
1209     {
1210         ERR("getting nsIDOMDocumentRange failed: %08x\n", nsres);
1211         return E_FAIL;
1212     }
1213     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
1214     nsIDOMDocumentRange_Release(nsdocrange);
1215     if(NS_FAILED(nsres))
1216     {
1217         ERR("CreateRange failed: %08x\n", nsres);
1218         return E_FAIL;
1219     }
1220
1221     nsIDOMRange_SetStartBefore(range, This->node.nsnode);
1222
1223     nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void **)&nsrange);
1224     nsIDOMRange_Release(range);
1225     if(NS_FAILED(nsres))
1226     {
1227         ERR("getting nsIDOMNSRange failed: %08x\n", nsres);
1228         return E_FAIL;
1229     }
1230
1231     nsAString_InitDepend(&ns_html, html);
1232
1233     nsres = nsIDOMNSRange_CreateContextualFragment(nsrange, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
1234     nsIDOMNSRange_Release(nsrange);
1235     nsAString_Finish(&ns_html);
1236
1237     if(NS_FAILED(nsres) || !nsnode)
1238     {
1239         ERR("CreateTextNode failed: %08x\n", nsres);
1240         return E_FAIL;
1241     }
1242
1243     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1244     nsIDOMNode_Release(nsnode);
1245
1246     return hr;
1247 }
1248
1249 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
1250                                                      BSTR text)
1251 {
1252     HTMLElement *This = impl_from_IHTMLElement(iface);
1253     nsIDOMNode *nsnode;
1254     nsAString ns_text;
1255     nsresult nsres;
1256     HRESULT hr;
1257
1258     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
1259
1260     if(!This->node.doc->nsdoc) {
1261         WARN("NULL nsdoc\n");
1262         return E_UNEXPECTED;
1263     }
1264
1265
1266     nsAString_InitDepend(&ns_text, text);
1267     nsres = nsIDOMDocument_CreateTextNode(This->node.doc->nsdoc, &ns_text, (nsIDOMText **)&nsnode);
1268     nsAString_Finish(&ns_text);
1269
1270     if(NS_FAILED(nsres) || !nsnode)
1271     {
1272         ERR("CreateTextNode failed: %08x\n", nsres);
1273         return E_FAIL;
1274     }
1275
1276     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1277     nsIDOMNode_Release(nsnode);
1278
1279     return hr;
1280 }
1281
1282 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
1283 {
1284     HTMLElement *This = impl_from_IHTMLElement(iface);
1285     FIXME("(%p)->(%p)\n", This, p);
1286     return E_NOTIMPL;
1287 }
1288
1289 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
1290 {
1291     HTMLElement *This = impl_from_IHTMLElement(iface);
1292     FIXME("(%p)->(%p)\n", This, p);
1293     return E_NOTIMPL;
1294 }
1295
1296 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
1297 {
1298     HTMLElement *This = impl_from_IHTMLElement(iface);
1299
1300     TRACE("(%p)\n", This);
1301
1302     return call_event(&This->node, EVENTID_CLICK);
1303 }
1304
1305 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
1306                                               IHTMLFiltersCollection **p)
1307 {
1308     HTMLElement *This = impl_from_IHTMLElement(iface);
1309     TRACE("(%p)->(%p)\n", This, p);
1310
1311     if(!p)
1312         return E_POINTER;
1313
1314     *p = HTMLFiltersCollection_Create();
1315
1316     return S_OK;
1317 }
1318
1319 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
1320 {
1321     HTMLElement *This = impl_from_IHTMLElement(iface);
1322     FIXME("(%p)->()\n", This);
1323     return E_NOTIMPL;
1324 }
1325
1326 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
1327 {
1328     HTMLElement *This = impl_from_IHTMLElement(iface);
1329     FIXME("(%p)->(%p)\n", This, p);
1330     return E_NOTIMPL;
1331 }
1332
1333 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
1334 {
1335     HTMLElement *This = impl_from_IHTMLElement(iface);
1336     FIXME("(%p)->(%p)\n", This, String);
1337     return E_NOTIMPL;
1338 }
1339
1340 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
1341 {
1342     HTMLElement *This = impl_from_IHTMLElement(iface);
1343     FIXME("(%p)->()\n", This);
1344     return E_NOTIMPL;
1345 }
1346
1347 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
1348 {
1349     HTMLElement *This = impl_from_IHTMLElement(iface);
1350     FIXME("(%p)->(%p)\n", This, p);
1351     return E_NOTIMPL;
1352 }
1353
1354 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
1355 {
1356     HTMLElement *This = impl_from_IHTMLElement(iface);
1357     FIXME("(%p)->()\n", This);
1358     return E_NOTIMPL;
1359 }
1360
1361 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
1362 {
1363     HTMLElement *This = impl_from_IHTMLElement(iface);
1364     FIXME("(%p)->(%p)\n", This, p);
1365     return E_NOTIMPL;
1366 }
1367
1368 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
1369 {
1370     HTMLElement *This = impl_from_IHTMLElement(iface);
1371     FIXME("(%p)->()\n", This);
1372     return E_NOTIMPL;
1373 }
1374
1375 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
1376 {
1377     HTMLElement *This = impl_from_IHTMLElement(iface);
1378     FIXME("(%p)->(%p)\n", This, p);
1379     return E_NOTIMPL;
1380 }
1381
1382 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
1383 {
1384     HTMLElement *This = impl_from_IHTMLElement(iface);
1385     FIXME("(%p)->()\n", This);
1386     return E_NOTIMPL;
1387 }
1388
1389 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
1390 {
1391     HTMLElement *This = impl_from_IHTMLElement(iface);
1392     FIXME("(%p)->(%p)\n", This, p);
1393     return E_NOTIMPL;
1394 }
1395
1396 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
1397 {
1398     HTMLElement *This = impl_from_IHTMLElement(iface);
1399     FIXME("(%p)->()\n", This);
1400     return E_NOTIMPL;
1401 }
1402
1403 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
1404 {
1405     HTMLElement *This = impl_from_IHTMLElement(iface);
1406     FIXME("(%p)->(%p)\n", This, p);
1407     return E_NOTIMPL;
1408 }
1409
1410 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
1411 {
1412     HTMLElement *This = impl_from_IHTMLElement(iface);
1413     FIXME("(%p)->()\n", This);
1414     return E_NOTIMPL;
1415 }
1416
1417 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
1418 {
1419     HTMLElement *This = impl_from_IHTMLElement(iface);
1420     FIXME("(%p)->(%p)\n", This, p);
1421     return E_NOTIMPL;
1422 }
1423
1424 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
1425 {
1426     HTMLElement *This = impl_from_IHTMLElement(iface);
1427     FIXME("(%p)->()\n", This);
1428     return E_NOTIMPL;
1429 }
1430
1431 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
1432 {
1433     HTMLElement *This = impl_from_IHTMLElement(iface);
1434     FIXME("(%p)->(%p)\n", This, p);
1435     return E_NOTIMPL;
1436 }
1437
1438 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
1439 {
1440     HTMLElement *This = impl_from_IHTMLElement(iface);
1441     FIXME("(%p)->()\n", This);
1442     return E_NOTIMPL;
1443 }
1444
1445 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
1446 {
1447     HTMLElement *This = impl_from_IHTMLElement(iface);
1448     FIXME("(%p)->(%p)\n", This, p);
1449     return E_NOTIMPL;
1450 }
1451
1452 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
1453 {
1454     HTMLElement *This = impl_from_IHTMLElement(iface);
1455     FIXME("(%p)->()\n", This);
1456     return E_NOTIMPL;
1457 }
1458
1459 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
1460 {
1461     HTMLElement *This = impl_from_IHTMLElement(iface);
1462     FIXME("(%p)->(%p)\n", This, p);
1463     return E_NOTIMPL;
1464 }
1465
1466 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
1467 {
1468     HTMLElement *This = impl_from_IHTMLElement(iface);
1469     nsIDOMNodeList *nsnode_list;
1470     nsresult nsres;
1471
1472     TRACE("(%p)->(%p)\n", This, p);
1473
1474     nsres = nsIDOMNode_GetChildNodes(This->node.nsnode, &nsnode_list);
1475     if(NS_FAILED(nsres)) {
1476         ERR("GetChildNodes failed: %08x\n", nsres);
1477         return E_FAIL;
1478     }
1479
1480     *p = (IDispatch*)create_collection_from_nodelist(This->node.doc,
1481             (IUnknown*)&This->IHTMLElement_iface, nsnode_list);
1482
1483     nsIDOMNodeList_Release(nsnode_list);
1484     return S_OK;
1485 }
1486
1487 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1488 {
1489     HTMLElement *This = impl_from_IHTMLElement(iface);
1490
1491     TRACE("(%p)->(%p)\n", This, p);
1492
1493     *p = (IDispatch*)create_all_collection(&This->node, FALSE);
1494     return S_OK;
1495 }
1496
1497 static const IHTMLElementVtbl HTMLElementVtbl = {
1498     HTMLElement_QueryInterface,
1499     HTMLElement_AddRef,
1500     HTMLElement_Release,
1501     HTMLElement_GetTypeInfoCount,
1502     HTMLElement_GetTypeInfo,
1503     HTMLElement_GetIDsOfNames,
1504     HTMLElement_Invoke,
1505     HTMLElement_setAttribute,
1506     HTMLElement_getAttribute,
1507     HTMLElement_removeAttribute,
1508     HTMLElement_put_className,
1509     HTMLElement_get_className,
1510     HTMLElement_put_id,
1511     HTMLElement_get_id,
1512     HTMLElement_get_tagName,
1513     HTMLElement_get_parentElement,
1514     HTMLElement_get_style,
1515     HTMLElement_put_onhelp,
1516     HTMLElement_get_onhelp,
1517     HTMLElement_put_onclick,
1518     HTMLElement_get_onclick,
1519     HTMLElement_put_ondblclick,
1520     HTMLElement_get_ondblclick,
1521     HTMLElement_put_onkeydown,
1522     HTMLElement_get_onkeydown,
1523     HTMLElement_put_onkeyup,
1524     HTMLElement_get_onkeyup,
1525     HTMLElement_put_onkeypress,
1526     HTMLElement_get_onkeypress,
1527     HTMLElement_put_onmouseout,
1528     HTMLElement_get_onmouseout,
1529     HTMLElement_put_onmouseover,
1530     HTMLElement_get_onmouseover,
1531     HTMLElement_put_onmousemove,
1532     HTMLElement_get_onmousemove,
1533     HTMLElement_put_onmousedown,
1534     HTMLElement_get_onmousedown,
1535     HTMLElement_put_onmouseup,
1536     HTMLElement_get_onmouseup,
1537     HTMLElement_get_document,
1538     HTMLElement_put_title,
1539     HTMLElement_get_title,
1540     HTMLElement_put_language,
1541     HTMLElement_get_language,
1542     HTMLElement_put_onselectstart,
1543     HTMLElement_get_onselectstart,
1544     HTMLElement_scrollIntoView,
1545     HTMLElement_contains,
1546     HTMLElement_get_sourceIndex,
1547     HTMLElement_get_recordNumber,
1548     HTMLElement_put_lang,
1549     HTMLElement_get_lang,
1550     HTMLElement_get_offsetLeft,
1551     HTMLElement_get_offsetTop,
1552     HTMLElement_get_offsetWidth,
1553     HTMLElement_get_offsetHeight,
1554     HTMLElement_get_offsetParent,
1555     HTMLElement_put_innerHTML,
1556     HTMLElement_get_innerHTML,
1557     HTMLElement_put_innerText,
1558     HTMLElement_get_innerText,
1559     HTMLElement_put_outerHTML,
1560     HTMLElement_get_outerHTML,
1561     HTMLElement_put_outerText,
1562     HTMLElement_get_outerText,
1563     HTMLElement_insertAdjacentHTML,
1564     HTMLElement_insertAdjacentText,
1565     HTMLElement_get_parentTextEdit,
1566     HTMLElement_get_isTextEdit,
1567     HTMLElement_click,
1568     HTMLElement_get_filters,
1569     HTMLElement_put_ondragstart,
1570     HTMLElement_get_ondragstart,
1571     HTMLElement_toString,
1572     HTMLElement_put_onbeforeupdate,
1573     HTMLElement_get_onbeforeupdate,
1574     HTMLElement_put_onafterupdate,
1575     HTMLElement_get_onafterupdate,
1576     HTMLElement_put_onerrorupdate,
1577     HTMLElement_get_onerrorupdate,
1578     HTMLElement_put_onrowexit,
1579     HTMLElement_get_onrowexit,
1580     HTMLElement_put_onrowenter,
1581     HTMLElement_get_onrowenter,
1582     HTMLElement_put_ondatasetchanged,
1583     HTMLElement_get_ondatasetchanged,
1584     HTMLElement_put_ondataavailable,
1585     HTMLElement_get_ondataavailable,
1586     HTMLElement_put_ondatasetcomplete,
1587     HTMLElement_get_ondatasetcomplete,
1588     HTMLElement_put_onfilterchange,
1589     HTMLElement_get_onfilterchange,
1590     HTMLElement_get_children,
1591     HTMLElement_get_all
1592 };
1593
1594 static inline HTMLElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
1595 {
1596     return CONTAINING_RECORD(iface, HTMLElement, node);
1597 }
1598
1599 HRESULT HTMLElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
1600 {
1601     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1602
1603     *ppv =  NULL;
1604
1605     if(IsEqualGUID(&IID_IUnknown, riid)) {
1606         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1607         *ppv = &This->IHTMLElement_iface;
1608     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1609         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1610         *ppv = &This->IHTMLElement_iface;
1611     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1612         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1613         *ppv = &This->IHTMLElement_iface;
1614     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1615         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1616         *ppv = &This->IHTMLElement2_iface;
1617     }else if(IsEqualGUID(&IID_IHTMLElement3, riid)) {
1618         TRACE("(%p)->(IID_IHTMLElement3 %p)\n", This, ppv);
1619         *ppv = &This->IHTMLElement3_iface;
1620     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1621         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1622         *ppv = CONPTCONT(&This->cp_container);
1623     }
1624
1625     if(*ppv) {
1626         IHTMLElement_AddRef(&This->IHTMLElement_iface);
1627         return S_OK;
1628     }
1629
1630     return HTMLDOMNode_QI(&This->node, riid, ppv);
1631 }
1632
1633 void HTMLElement_destructor(HTMLDOMNode *iface)
1634 {
1635     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1636
1637     ConnectionPointContainer_Destroy(&This->cp_container);
1638
1639     if(This->nselem)
1640         nsIDOMHTMLElement_Release(This->nselem);
1641
1642     HTMLDOMNode_destructor(&This->node);
1643 }
1644
1645 HRESULT HTMLElement_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1646 {
1647     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1648     HTMLElement *new_elem;
1649     HRESULT hres;
1650
1651     hres = HTMLElement_Create(This->node.doc, nsnode, FALSE, &new_elem);
1652     if(FAILED(hres))
1653         return hres;
1654
1655     IHTMLElement_AddRef(&new_elem->IHTMLElement_iface);
1656     *ret = &new_elem->node;
1657     return S_OK;
1658 }
1659
1660 static const NodeImplVtbl HTMLElementImplVtbl = {
1661     HTMLElement_QI,
1662     HTMLElement_destructor,
1663     HTMLElement_clone
1664 };
1665
1666 static inline HTMLElement *impl_from_DispatchEx(DispatchEx *iface)
1667 {
1668     return CONTAINING_RECORD(iface, HTMLElement, node.dispex);
1669 }
1670
1671 static HRESULT HTMLElement_get_dispid(DispatchEx *dispex, BSTR name,
1672         DWORD grfdex, DISPID *pid)
1673 {
1674     HTMLElement *This = impl_from_DispatchEx(dispex);
1675
1676     if(This->node.vtbl->get_dispid)
1677         return This->node.vtbl->get_dispid(&This->node, name, grfdex, pid);
1678
1679     return DISP_E_UNKNOWNNAME;
1680 }
1681
1682 static HRESULT HTMLElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
1683         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei,
1684         IServiceProvider *caller)
1685 {
1686     HTMLElement *This = impl_from_DispatchEx(dispex);
1687
1688     if(This->node.vtbl->invoke)
1689         return This->node.vtbl->invoke(&This->node, id, lcid, flags,
1690                 params, res, ei, caller);
1691
1692     ERR("(%p): element has no invoke method\n", This);
1693     return E_NOTIMPL;
1694 }
1695
1696 static const tid_t HTMLElement_iface_tids[] = {
1697     HTMLELEMENT_TIDS,
1698     0
1699 };
1700
1701 static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
1702     NULL,
1703     HTMLElement_get_dispid,
1704     HTMLElement_invoke
1705 };
1706
1707 static dispex_static_data_t HTMLElement_dispex = {
1708     &HTMLElement_dispex_vtbl,
1709     DispHTMLUnknownElement_tid,
1710     NULL,
1711     HTMLElement_iface_tids
1712 };
1713
1714 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, dispex_static_data_t *dispex_data)
1715 {
1716     This->IHTMLElement_iface.lpVtbl = &HTMLElementVtbl;
1717
1718     HTMLElement2_Init(This);
1719     HTMLElement3_Init(This);
1720
1721     if(dispex_data && !dispex_data->vtbl)
1722         dispex_data->vtbl = &HTMLElement_dispex_vtbl;
1723     init_dispex(&This->node.dispex, (IUnknown*)&This->IHTMLElement_iface,
1724             dispex_data ? dispex_data : &HTMLElement_dispex);
1725
1726     if(nselem)
1727         nsIDOMHTMLElement_AddRef(nselem);
1728     This->nselem = nselem;
1729
1730     HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem);
1731
1732     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface);
1733 }
1734
1735 HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_generic, HTMLElement **ret)
1736 {
1737     nsIDOMHTMLElement *nselem;
1738     nsAString class_name_str;
1739     const PRUnichar *class_name;
1740     const tag_desc_t *tag;
1741     HTMLElement *elem;
1742     nsresult nsres;
1743     HRESULT hres;
1744
1745     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1746     if(NS_FAILED(nsres))
1747         return E_FAIL;
1748
1749     nsAString_Init(&class_name_str, NULL);
1750     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1751
1752     nsAString_GetData(&class_name_str, &class_name);
1753
1754     tag = get_tag_desc(class_name);
1755     if(tag) {
1756         hres = tag->constructor(doc, nselem, &elem);
1757     }else if(use_generic) {
1758         hres = HTMLGenericElement_Create(doc, nselem, &elem);
1759     }else {
1760         elem = heap_alloc_zero(sizeof(HTMLElement));
1761         if(elem) {
1762             HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
1763             elem->node.vtbl = &HTMLElementImplVtbl;
1764             hres = S_OK;
1765         }else {
1766             hres = E_OUTOFMEMORY;
1767         }
1768     }
1769
1770     TRACE("%s ret %p\n", debugstr_w(class_name), elem);
1771
1772     nsIDOMElement_Release(nselem);
1773     nsAString_Finish(&class_name_str);
1774     if(FAILED(hres))
1775         return hres;
1776
1777     *ret = elem;
1778     return S_OK;
1779 }
1780
1781 /* interface IHTMLFiltersCollection */
1782 static HRESULT WINAPI HTMLFiltersCollection_QueryInterface(IHTMLFiltersCollection *iface, REFIID riid, void **ppv)
1783 {
1784     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1785
1786     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppv );
1787
1788     if(IsEqualGUID(&IID_IUnknown, riid)) {
1789         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1790         *ppv = HTMLFILTERSCOLLECTION(This);
1791     }else if(IsEqualGUID(&IID_IHTMLFiltersCollection, riid)) {
1792         TRACE("(%p)->(IID_IHTMLFiltersCollection %p)\n", This, ppv);
1793         *ppv = HTMLFILTERSCOLLECTION(This);
1794     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1795         return *ppv ? S_OK : E_NOINTERFACE;
1796     }
1797
1798     if(*ppv) {
1799         IUnknown_AddRef((IUnknown*)*ppv);
1800         return S_OK;
1801     }
1802
1803     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1804     return E_NOINTERFACE;
1805 }
1806
1807 static ULONG WINAPI HTMLFiltersCollection_AddRef(IHTMLFiltersCollection *iface)
1808 {
1809     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1810     LONG ref = InterlockedIncrement(&This->ref);
1811
1812     TRACE("(%p) ref=%d\n", This, ref);
1813
1814     return ref;
1815 }
1816
1817 static ULONG WINAPI HTMLFiltersCollection_Release(IHTMLFiltersCollection *iface)
1818 {
1819     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1820     LONG ref = InterlockedDecrement(&This->ref);
1821
1822     TRACE("(%p) ref=%d\n", This, ref);
1823
1824     if(!ref)
1825     {
1826         heap_free(This);
1827     }
1828
1829     return ref;
1830 }
1831
1832 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfoCount(IHTMLFiltersCollection *iface, UINT *pctinfo)
1833 {
1834     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1835     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
1836 }
1837
1838 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfo(IHTMLFiltersCollection *iface,
1839                                     UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1840 {
1841     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1842     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
1843 }
1844
1845 static HRESULT WINAPI HTMLFiltersCollection_GetIDsOfNames(IHTMLFiltersCollection *iface,
1846                                     REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1847                                     LCID lcid, DISPID *rgDispId)
1848 {
1849     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1850     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
1851 }
1852
1853 static HRESULT WINAPI HTMLFiltersCollection_Invoke(IHTMLFiltersCollection *iface, DISPID dispIdMember, REFIID riid,
1854                                     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1855                                     EXCEPINFO *pExcepInfo, UINT *puArgErr)
1856 {
1857     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1858     return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
1859             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1860 }
1861
1862 static HRESULT WINAPI HTMLFiltersCollection_get_length(IHTMLFiltersCollection *iface, LONG *p)
1863 {
1864     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1865
1866     if(!p)
1867         return E_POINTER;
1868
1869     FIXME("(%p)->(%p) Always returning 0\n", This, p);
1870     *p = 0;
1871
1872     return S_OK;
1873 }
1874
1875 static HRESULT WINAPI HTMLFiltersCollection_get__newEnum(IHTMLFiltersCollection *iface, IUnknown **p)
1876 {
1877     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1878     FIXME("(%p)->(%p)\n", This, p);
1879     return E_NOTIMPL;
1880 }
1881
1882 static HRESULT WINAPI HTMLFiltersCollection_item(IHTMLFiltersCollection *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
1883 {
1884     HTMLFiltersCollection *This = HTMLFILTERSCOLLECTION_THIS(iface);
1885     FIXME("(%p)->(%p, %p)\n", This, pvarIndex, pvarResult);
1886     return E_NOTIMPL;
1887 }
1888
1889 static const IHTMLFiltersCollectionVtbl HTMLFiltersCollectionVtbl = {
1890     HTMLFiltersCollection_QueryInterface,
1891     HTMLFiltersCollection_AddRef,
1892     HTMLFiltersCollection_Release,
1893     HTMLFiltersCollection_GetTypeInfoCount,
1894     HTMLFiltersCollection_GetTypeInfo,
1895     HTMLFiltersCollection_GetIDsOfNames,
1896     HTMLFiltersCollection_Invoke,
1897     HTMLFiltersCollection_get_length,
1898     HTMLFiltersCollection_get__newEnum,
1899     HTMLFiltersCollection_item
1900 };
1901
1902 static HRESULT HTMLFiltersCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
1903 {
1904     WCHAR *ptr;
1905     int idx = 0;
1906
1907     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
1908         idx = idx*10 + (*ptr-'0');
1909     if(*ptr)
1910         return DISP_E_UNKNOWNNAME;
1911
1912     *dispid = MSHTML_DISPID_CUSTOM_MIN + idx;
1913     TRACE("ret %x\n", *dispid);
1914     return S_OK;
1915 }
1916
1917 static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1918         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1919 {
1920     TRACE("(%p)->(%x %x %x %p %p %p)\n", dispex, id, lcid, flags, params, res, ei);
1921
1922     V_VT(res) = VT_DISPATCH;
1923     V_DISPATCH(res) = NULL;
1924
1925     FIXME("always returning NULL\n");
1926
1927     return S_OK;
1928 }
1929
1930 static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = {
1931     NULL,
1932     HTMLFiltersCollection_get_dispid,
1933     HTMLFiltersCollection_invoke
1934 };
1935
1936 static const tid_t HTMLFiltersCollection_iface_tids[] = {
1937     IHTMLFiltersCollection_tid,
1938     0
1939 };
1940 static dispex_static_data_t HTMLFiltersCollection_dispex = {
1941     &HTMLFiltersCollection_dispex_vtbl,
1942     IHTMLFiltersCollection_tid,
1943     NULL,
1944     HTMLFiltersCollection_iface_tids
1945 };
1946
1947 IHTMLFiltersCollection *HTMLFiltersCollection_Create()
1948 {
1949     HTMLFiltersCollection *ret = heap_alloc(sizeof(HTMLFiltersCollection));
1950
1951     ret->lpHTMLFiltersCollectionVtbl = &HTMLFiltersCollectionVtbl;
1952     ret->ref = 1;
1953
1954     init_dispex(&ret->dispex, (IUnknown*)HTMLFILTERSCOLLECTION(ret),  &HTMLFiltersCollection_dispex);
1955
1956     return HTMLFILTERSCOLLECTION(ret);
1957 }