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