mshtml: Added IHTMLElement4 stub implementation.
[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
596     TRACE("(%p)->()\n", This);
597
598     return set_node_event(&This->node, EVENTID_MOUSEMOVE, &v);
599 }
600
601 static HRESULT WINAPI HTMLElement_get_onmousemove(IHTMLElement *iface, VARIANT *p)
602 {
603     HTMLElement *This = impl_from_IHTMLElement(iface);
604
605     TRACE("(%p)->(%p)\n", This, p);
606
607     return get_node_event(&This->node, EVENTID_MOUSEMOVE, p);
608 }
609
610 static HRESULT WINAPI HTMLElement_put_onmousedown(IHTMLElement *iface, VARIANT v)
611 {
612     HTMLElement *This = impl_from_IHTMLElement(iface);
613
614     TRACE("(%p)->()\n", This);
615
616     return set_node_event(&This->node, EVENTID_MOUSEDOWN, &v);
617 }
618
619 static HRESULT WINAPI HTMLElement_get_onmousedown(IHTMLElement *iface, VARIANT *p)
620 {
621     HTMLElement *This = impl_from_IHTMLElement(iface);
622
623     TRACE("(%p)->(%p)\n", This, p);
624
625     return get_node_event(&This->node, EVENTID_MOUSEDOWN, p);
626 }
627
628 static HRESULT WINAPI HTMLElement_put_onmouseup(IHTMLElement *iface, VARIANT v)
629 {
630     HTMLElement *This = impl_from_IHTMLElement(iface);
631
632     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
633
634     return set_node_event(&This->node, EVENTID_MOUSEUP, &v);
635 }
636
637 static HRESULT WINAPI HTMLElement_get_onmouseup(IHTMLElement *iface, VARIANT *p)
638 {
639     HTMLElement *This = impl_from_IHTMLElement(iface);
640
641     TRACE("(%p)->(%p)\n", This, p);
642
643     return get_node_event(&This->node, EVENTID_MOUSEUP, p);
644 }
645
646 static HRESULT WINAPI HTMLElement_get_document(IHTMLElement *iface, IDispatch **p)
647 {
648     HTMLElement *This = impl_from_IHTMLElement(iface);
649
650     TRACE("(%p)->(%p)\n", This, p);
651
652     if(!p)
653         return E_POINTER;
654
655     if(This->node.vtbl->get_document)
656         return This->node.vtbl->get_document(&This->node, p);
657
658     *p = (IDispatch*)&This->node.doc->basedoc.IHTMLDocument2_iface;
659     IDispatch_AddRef(*p);
660     return S_OK;
661 }
662
663 static const WCHAR titleW[] = {'t','i','t','l','e',0};
664
665 static HRESULT WINAPI HTMLElement_put_title(IHTMLElement *iface, BSTR v)
666 {
667     HTMLElement *This = impl_from_IHTMLElement(iface);
668     nsAString title_str;
669     nsresult nsres;
670
671     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
672
673     if(!This->nselem) {
674         VARIANT *var;
675         HRESULT hres;
676
677         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, TRUE, &var);
678         if(FAILED(hres))
679             return hres;
680
681         VariantClear(var);
682         V_VT(var) = VT_BSTR;
683         V_BSTR(var) = v ? SysAllocString(v) : NULL;
684         return S_OK;
685     }
686
687     nsAString_InitDepend(&title_str, v);
688     nsres = nsIDOMHTMLElement_SetTitle(This->nselem, &title_str);
689     nsAString_Finish(&title_str);
690     if(NS_FAILED(nsres))
691         ERR("SetTitle failed: %08x\n", nsres);
692
693     return S_OK;
694 }
695
696 static HRESULT WINAPI HTMLElement_get_title(IHTMLElement *iface, BSTR *p)
697 {
698     HTMLElement *This = impl_from_IHTMLElement(iface);
699     nsAString title_str;
700     nsresult nsres;
701
702     TRACE("(%p)->(%p)\n", This, p);
703
704     if(!This->nselem) {
705         VARIANT *var;
706         HRESULT hres;
707
708         hres = dispex_get_dprop_ref(&This->node.dispex, titleW, FALSE, &var);
709         if(hres == DISP_E_UNKNOWNNAME) {
710             *p = NULL;
711         }else if(V_VT(var) != VT_BSTR) {
712             FIXME("title = %s\n", debugstr_variant(var));
713             return E_FAIL;
714         }else {
715             *p = V_BSTR(var) ? SysAllocString(V_BSTR(var)) : NULL;
716         }
717
718         return S_OK;
719     }
720
721     nsAString_Init(&title_str, NULL);
722     nsres = nsIDOMHTMLElement_GetTitle(This->nselem, &title_str);
723     if(NS_SUCCEEDED(nsres)) {
724         const PRUnichar *title;
725
726         nsAString_GetData(&title_str, &title);
727         *p = *title ? SysAllocString(title) : NULL;
728     }else {
729         ERR("GetTitle failed: %08x\n", nsres);
730         return E_FAIL;
731     }
732
733     return S_OK;
734 }
735
736 static HRESULT WINAPI HTMLElement_put_language(IHTMLElement *iface, BSTR v)
737 {
738     HTMLElement *This = impl_from_IHTMLElement(iface);
739     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
740     return E_NOTIMPL;
741 }
742
743 static HRESULT WINAPI HTMLElement_get_language(IHTMLElement *iface, BSTR *p)
744 {
745     HTMLElement *This = impl_from_IHTMLElement(iface);
746     FIXME("(%p)->(%p)\n", This, p);
747     return E_NOTIMPL;
748 }
749
750 static HRESULT WINAPI HTMLElement_put_onselectstart(IHTMLElement *iface, VARIANT v)
751 {
752     HTMLElement *This = impl_from_IHTMLElement(iface);
753
754     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
755
756     return set_node_event(&This->node, EVENTID_SELECTSTART, &v);
757 }
758
759 static HRESULT WINAPI HTMLElement_get_onselectstart(IHTMLElement *iface, VARIANT *p)
760 {
761     HTMLElement *This = impl_from_IHTMLElement(iface);
762
763     TRACE("(%p)->(%p)\n", This, p);
764
765     return get_node_event(&This->node, EVENTID_SELECTSTART, p);
766 }
767
768 static HRESULT WINAPI HTMLElement_scrollIntoView(IHTMLElement *iface, VARIANT varargStart)
769 {
770     HTMLElement *This = impl_from_IHTMLElement(iface);
771     FIXME("(%p)->()\n", This);
772     return E_NOTIMPL;
773 }
774
775 static HRESULT WINAPI HTMLElement_contains(IHTMLElement *iface, IHTMLElement *pChild,
776                                            VARIANT_BOOL *pfResult)
777 {
778     HTMLElement *This = impl_from_IHTMLElement(iface);
779     FIXME("(%p)->(%p %p)\n", This, pChild, pfResult);
780     return E_NOTIMPL;
781 }
782
783 static HRESULT WINAPI HTMLElement_get_sourceIndex(IHTMLElement *iface, LONG *p)
784 {
785     HTMLElement *This = impl_from_IHTMLElement(iface);
786     FIXME("(%p)->(%p)\n", This, p);
787     return E_NOTIMPL;
788 }
789
790 static HRESULT WINAPI HTMLElement_get_recordNumber(IHTMLElement *iface, VARIANT *p)
791 {
792     HTMLElement *This = impl_from_IHTMLElement(iface);
793     FIXME("(%p)->(%p)\n", This, p);
794     return E_NOTIMPL;
795 }
796
797 static HRESULT WINAPI HTMLElement_put_lang(IHTMLElement *iface, BSTR v)
798 {
799     HTMLElement *This = impl_from_IHTMLElement(iface);
800     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
801     return E_NOTIMPL;
802 }
803
804 static HRESULT WINAPI HTMLElement_get_lang(IHTMLElement *iface, BSTR *p)
805 {
806     HTMLElement *This = impl_from_IHTMLElement(iface);
807     FIXME("(%p)->(%p)\n", This, p);
808     return E_NOTIMPL;
809 }
810
811 static HRESULT WINAPI HTMLElement_get_offsetLeft(IHTMLElement *iface, LONG *p)
812 {
813     HTMLElement *This = impl_from_IHTMLElement(iface);
814     FIXME("(%p)->(%p)\n", This, p);
815     return E_NOTIMPL;
816 }
817
818 static HRESULT WINAPI HTMLElement_get_offsetTop(IHTMLElement *iface, LONG *p)
819 {
820     HTMLElement *This = impl_from_IHTMLElement(iface);
821     nsIDOMNSHTMLElement *nselem;
822     PRInt32 top = 0;
823     nsresult nsres;
824
825     TRACE("(%p)->(%p)\n", This, p);
826
827     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
828     if(NS_FAILED(nsres)) {
829         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
830         return E_FAIL;
831     }
832
833     nsres = nsIDOMNSHTMLElement_GetOffsetTop(nselem, &top);
834     nsIDOMNSHTMLElement_Release(nselem);
835     if(NS_FAILED(nsres)) {
836         ERR("GetOffsetTop failed: %08x\n", nsres);
837         return E_FAIL;
838     }
839
840     *p = top;
841     return S_OK;
842 }
843
844 static HRESULT WINAPI HTMLElement_get_offsetWidth(IHTMLElement *iface, LONG *p)
845 {
846     HTMLElement *This = impl_from_IHTMLElement(iface);
847     nsIDOMNSHTMLElement *nselem;
848     PRInt32 offset = 0;
849     nsresult nsres;
850
851     TRACE("(%p)->(%p)\n", This, p);
852
853     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
854     if(NS_FAILED(nsres)) {
855         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
856         return E_FAIL;
857     }
858
859     nsres = nsIDOMNSHTMLElement_GetOffsetWidth(nselem, &offset);
860     nsIDOMNSHTMLElement_Release(nselem);
861     if(NS_FAILED(nsres)) {
862         ERR("GetOffsetWidth failed: %08x\n", nsres);
863         return E_FAIL;
864     }
865
866     *p = offset;
867     return S_OK;
868 }
869
870 static HRESULT WINAPI HTMLElement_get_offsetHeight(IHTMLElement *iface, LONG *p)
871 {
872     HTMLElement *This = impl_from_IHTMLElement(iface);
873     nsIDOMNSHTMLElement *nselem;
874     PRInt32 offset = 0;
875     nsresult nsres;
876
877     TRACE("(%p)->(%p)\n", This, p);
878
879     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
880     if(NS_FAILED(nsres)) {
881         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
882         return E_FAIL;
883     }
884
885     nsres = nsIDOMNSHTMLElement_GetOffsetHeight(nselem, &offset);
886     nsIDOMNSHTMLElement_Release(nselem);
887     if(NS_FAILED(nsres)) {
888         ERR("GetOffsetHeight failed: %08x\n", nsres);
889         return E_FAIL;
890     }
891
892     *p = offset;
893     return S_OK;
894 }
895
896 static HRESULT WINAPI HTMLElement_get_offsetParent(IHTMLElement *iface, IHTMLElement **p)
897 {
898     HTMLElement *This = impl_from_IHTMLElement(iface);
899     FIXME("(%p)->(%p)\n", This, p);
900     return E_NOTIMPL;
901 }
902
903 static HRESULT WINAPI HTMLElement_put_innerHTML(IHTMLElement *iface, BSTR v)
904 {
905     HTMLElement *This = impl_from_IHTMLElement(iface);
906     nsIDOMNSHTMLElement *nselem;
907     nsAString html_str;
908     nsresult nsres;
909
910     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
911
912     if(!This->nselem) {
913         FIXME("NULL nselem\n");
914         return E_NOTIMPL;
915     }
916
917     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
918     if(NS_FAILED(nsres)) {
919         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
920         return E_FAIL;
921     }
922
923     nsAString_InitDepend(&html_str, v);
924     nsres = nsIDOMNSHTMLElement_SetInnerHTML(nselem, &html_str);
925     nsAString_Finish(&html_str);
926
927     if(NS_FAILED(nsres)) {
928         FIXME("SetInnerHtml failed %08x\n", nsres);
929         return E_FAIL;
930     }
931
932     return S_OK;
933 }
934
935 static HRESULT WINAPI HTMLElement_get_innerHTML(IHTMLElement *iface, BSTR *p)
936 {
937     HTMLElement *This = impl_from_IHTMLElement(iface);
938     nsIDOMNSHTMLElement *nselem;
939     nsAString html_str;
940     nsresult nsres;
941
942     TRACE("(%p)->(%p)\n", This, p);
943
944     if(!This->nselem) {
945         FIXME("NULL nselem\n");
946         return E_NOTIMPL;
947     }
948
949     nsres = nsIDOMHTMLElement_QueryInterface(This->nselem, &IID_nsIDOMNSHTMLElement, (void**)&nselem);
950     if(NS_FAILED(nsres)) {
951         ERR("Could not get nsIDOMNSHTMLElement: %08x\n", nsres);
952         return E_FAIL;
953     }
954
955     nsAString_Init(&html_str, NULL);
956     nsres = nsIDOMNSHTMLElement_GetInnerHTML(nselem, &html_str);
957     if(NS_SUCCEEDED(nsres)) {
958         const PRUnichar *html;
959
960         nsAString_GetData(&html_str, &html);
961         *p = *html ? SysAllocString(html) : NULL;
962     }else {
963         FIXME("SetInnerHtml failed %08x\n", nsres);
964         *p = NULL;
965     }
966
967     nsAString_Finish(&html_str);
968     return S_OK;
969 }
970
971 static HRESULT WINAPI HTMLElement_put_innerText(IHTMLElement *iface, BSTR v)
972 {
973     HTMLElement *This = impl_from_IHTMLElement(iface);
974     nsIDOMNode *nschild, *tmp;
975     nsIDOMText *text_node;
976     nsAString text_str;
977     nsresult nsres;
978
979     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
980
981     while(1) {
982         nsres = nsIDOMHTMLElement_GetLastChild(This->nselem, &nschild);
983         if(NS_FAILED(nsres)) {
984             ERR("GetLastChild failed: %08x\n", nsres);
985             return E_FAIL;
986         }
987         if(!nschild)
988             break;
989
990         nsres = nsIDOMHTMLElement_RemoveChild(This->nselem, nschild, &tmp);
991         nsIDOMNode_Release(nschild);
992         if(NS_FAILED(nsres)) {
993             ERR("RemoveChild failed: %08x\n", nsres);
994             return E_FAIL;
995         }
996         nsIDOMNode_Release(tmp);
997     }
998
999     nsAString_InitDepend(&text_str, v);
1000     nsres = nsIDOMHTMLDocument_CreateTextNode(This->node.doc->nsdoc, &text_str, &text_node);
1001     nsAString_Finish(&text_str);
1002     if(NS_FAILED(nsres)) {
1003         ERR("CreateTextNode failed: %08x\n", nsres);
1004         return E_FAIL;
1005     }
1006
1007     nsres = nsIDOMHTMLElement_AppendChild(This->nselem, (nsIDOMNode*)text_node, &tmp);
1008     if(NS_FAILED(nsres)) {
1009         ERR("AppendChild failed: %08x\n", nsres);
1010         return E_FAIL;
1011     }
1012
1013     nsIDOMNode_Release(tmp);
1014     return S_OK;
1015 }
1016
1017 static HRESULT WINAPI HTMLElement_get_innerText(IHTMLElement *iface, BSTR *p)
1018 {
1019     HTMLElement *This = impl_from_IHTMLElement(iface);
1020
1021     TRACE("(%p)->(%p)\n", This, p);
1022
1023     return get_node_text(&This->node, p);
1024 }
1025
1026 static HRESULT WINAPI HTMLElement_put_outerHTML(IHTMLElement *iface, BSTR v)
1027 {
1028     HTMLElement *This = impl_from_IHTMLElement(iface);
1029     nsIDOMDocumentFragment *nsfragment;
1030     nsIDOMDocumentRange *nsdocrange;
1031     nsIDOMNSRange *nsrange;
1032     nsIDOMNode *nsparent;
1033     nsIDOMRange *range;
1034     nsAString html_str;
1035     nsresult nsres;
1036     HRESULT hres = S_OK;
1037
1038     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
1039
1040     nsres = nsIDOMHTMLDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void**)&nsdocrange);
1041     if(NS_FAILED(nsres))
1042         return E_FAIL;
1043
1044     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
1045     nsIDOMDocumentRange_Release(nsdocrange);
1046     if(NS_FAILED(nsres)) {
1047         ERR("CreateRange failed: %08x\n", nsres);
1048         return E_FAIL;
1049     }
1050
1051     nsres = nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void**)&nsrange);
1052     nsIDOMRange_Release(range);
1053     if(NS_FAILED(nsres)) {
1054         ERR("Could not get nsIDOMNSRange: %08x\n", nsres);
1055         return E_FAIL;
1056     }
1057
1058     nsAString_InitDepend(&html_str, v);
1059     nsIDOMNSRange_CreateContextualFragment(nsrange, &html_str, &nsfragment);
1060     nsIDOMNSRange_Release(nsrange);
1061     nsAString_Finish(&html_str);
1062     if(NS_FAILED(nsres)) {
1063         ERR("CreateContextualFragment failed: %08x\n", nsres);
1064         return E_FAIL;
1065     }
1066
1067     nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &nsparent);
1068     if(NS_SUCCEEDED(nsres) && nsparent) {
1069         nsIDOMNode *nstmp;
1070
1071         nsres = nsIDOMNode_ReplaceChild(nsparent, (nsIDOMNode*)nsfragment, This->node.nsnode, &nstmp);
1072         nsIDOMNode_Release(nsparent);
1073         if(NS_FAILED(nsres)) {
1074             ERR("ReplaceChild failed: %08x\n", nsres);
1075             hres = E_FAIL;
1076         }else if(nstmp) {
1077             nsIDOMNode_Release(nstmp);
1078         }
1079     }else {
1080         ERR("GetParentNode failed: %08x\n", nsres);
1081         hres = E_FAIL;
1082     }
1083
1084     nsIDOMDocumentFragment_Release(nsfragment);
1085     return hres;
1086 }
1087
1088 static HRESULT WINAPI HTMLElement_get_outerHTML(IHTMLElement *iface, BSTR *p)
1089 {
1090     HTMLElement *This = impl_from_IHTMLElement(iface);
1091     nsAString html_str;
1092     HRESULT hres;
1093
1094     WARN("(%p)->(%p) semi-stub\n", This, p);
1095
1096     nsAString_Init(&html_str, NULL);
1097     hres = nsnode_to_nsstring(This->node.nsnode, &html_str);
1098     if(SUCCEEDED(hres)) {
1099         const PRUnichar *html;
1100
1101         nsAString_GetData(&html_str, &html);
1102         *p = SysAllocString(html);
1103         if(!*p)
1104             hres = E_OUTOFMEMORY;
1105     }
1106
1107     nsAString_Finish(&html_str);
1108
1109     TRACE("ret %s\n", debugstr_w(*p));
1110     return S_OK;
1111 }
1112
1113 static HRESULT WINAPI HTMLElement_put_outerText(IHTMLElement *iface, BSTR v)
1114 {
1115     HTMLElement *This = impl_from_IHTMLElement(iface);
1116     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
1117     return E_NOTIMPL;
1118 }
1119
1120 static HRESULT WINAPI HTMLElement_get_outerText(IHTMLElement *iface, BSTR *p)
1121 {
1122     HTMLElement *This = impl_from_IHTMLElement(iface);
1123     FIXME("(%p)->(%p)\n", This, p);
1124     return E_NOTIMPL;
1125 }
1126
1127 static HRESULT HTMLElement_InsertAdjacentNode(HTMLElement *This, BSTR where, nsIDOMNode *nsnode)
1128 {
1129     static const WCHAR wszBeforeBegin[] = {'b','e','f','o','r','e','B','e','g','i','n',0};
1130     static const WCHAR wszAfterBegin[] = {'a','f','t','e','r','B','e','g','i','n',0};
1131     static const WCHAR wszBeforeEnd[] = {'b','e','f','o','r','e','E','n','d',0};
1132     static const WCHAR wszAfterEnd[] = {'a','f','t','e','r','E','n','d',0};
1133     nsresult nsres;
1134
1135     if (!strcmpiW(where, wszBeforeBegin))
1136     {
1137         nsIDOMNode *unused;
1138         nsIDOMNode *parent;
1139         nsres = nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1140         if (!parent) return E_INVALIDARG;
1141         nsres = nsIDOMNode_InsertBefore(parent, nsnode, This->node.nsnode, &unused);
1142         if (unused) nsIDOMNode_Release(unused);
1143         nsIDOMNode_Release(parent);
1144     }
1145     else if (!strcmpiW(where, wszAfterBegin))
1146     {
1147         nsIDOMNode *unused;
1148         nsIDOMNode *first_child;
1149         nsIDOMNode_GetFirstChild(This->node.nsnode, &first_child);
1150         nsres = nsIDOMNode_InsertBefore(This->node.nsnode, nsnode, first_child, &unused);
1151         if (unused) nsIDOMNode_Release(unused);
1152         if (first_child) nsIDOMNode_Release(first_child);
1153     }
1154     else if (!strcmpiW(where, wszBeforeEnd))
1155     {
1156         nsIDOMNode *unused;
1157         nsres = nsIDOMNode_AppendChild(This->node.nsnode, nsnode, &unused);
1158         if (unused) nsIDOMNode_Release(unused);
1159     }
1160     else if (!strcmpiW(where, wszAfterEnd))
1161     {
1162         nsIDOMNode *unused;
1163         nsIDOMNode *next_sibling;
1164         nsIDOMNode *parent;
1165         nsIDOMNode_GetParentNode(This->node.nsnode, &parent);
1166         if (!parent) return E_INVALIDARG;
1167
1168         nsIDOMNode_GetNextSibling(This->node.nsnode, &next_sibling);
1169         if (next_sibling)
1170         {
1171             nsres = nsIDOMNode_InsertBefore(parent, nsnode, next_sibling, &unused);
1172             nsIDOMNode_Release(next_sibling);
1173         }
1174         else
1175             nsres = nsIDOMNode_AppendChild(parent, nsnode, &unused);
1176         nsIDOMNode_Release(parent);
1177         if (unused) nsIDOMNode_Release(unused);
1178     }
1179     else
1180     {
1181         ERR("invalid where: %s\n", debugstr_w(where));
1182         return E_INVALIDARG;
1183     }
1184
1185     if (NS_FAILED(nsres))
1186         return E_FAIL;
1187     else
1188         return S_OK;
1189 }
1190
1191 static HRESULT WINAPI HTMLElement_insertAdjacentHTML(IHTMLElement *iface, BSTR where,
1192                                                      BSTR html)
1193 {
1194     HTMLElement *This = impl_from_IHTMLElement(iface);
1195     nsIDOMDocumentRange *nsdocrange;
1196     nsIDOMRange *range;
1197     nsIDOMNSRange *nsrange;
1198     nsIDOMNode *nsnode;
1199     nsAString ns_html;
1200     nsresult nsres;
1201     HRESULT hr;
1202
1203     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(html));
1204
1205     if(!This->node.doc->nsdoc) {
1206         WARN("NULL nsdoc\n");
1207         return E_UNEXPECTED;
1208     }
1209
1210     nsres = nsIDOMDocument_QueryInterface(This->node.doc->nsdoc, &IID_nsIDOMDocumentRange, (void **)&nsdocrange);
1211     if(NS_FAILED(nsres))
1212     {
1213         ERR("getting nsIDOMDocumentRange failed: %08x\n", nsres);
1214         return E_FAIL;
1215     }
1216     nsres = nsIDOMDocumentRange_CreateRange(nsdocrange, &range);
1217     nsIDOMDocumentRange_Release(nsdocrange);
1218     if(NS_FAILED(nsres))
1219     {
1220         ERR("CreateRange failed: %08x\n", nsres);
1221         return E_FAIL;
1222     }
1223
1224     nsIDOMRange_SetStartBefore(range, This->node.nsnode);
1225
1226     nsIDOMRange_QueryInterface(range, &IID_nsIDOMNSRange, (void **)&nsrange);
1227     nsIDOMRange_Release(range);
1228     if(NS_FAILED(nsres))
1229     {
1230         ERR("getting nsIDOMNSRange failed: %08x\n", nsres);
1231         return E_FAIL;
1232     }
1233
1234     nsAString_InitDepend(&ns_html, html);
1235
1236     nsres = nsIDOMNSRange_CreateContextualFragment(nsrange, &ns_html, (nsIDOMDocumentFragment **)&nsnode);
1237     nsIDOMNSRange_Release(nsrange);
1238     nsAString_Finish(&ns_html);
1239
1240     if(NS_FAILED(nsres) || !nsnode)
1241     {
1242         ERR("CreateTextNode failed: %08x\n", nsres);
1243         return E_FAIL;
1244     }
1245
1246     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1247     nsIDOMNode_Release(nsnode);
1248
1249     return hr;
1250 }
1251
1252 static HRESULT WINAPI HTMLElement_insertAdjacentText(IHTMLElement *iface, BSTR where,
1253                                                      BSTR text)
1254 {
1255     HTMLElement *This = impl_from_IHTMLElement(iface);
1256     nsIDOMNode *nsnode;
1257     nsAString ns_text;
1258     nsresult nsres;
1259     HRESULT hr;
1260
1261     TRACE("(%p)->(%s %s)\n", This, debugstr_w(where), debugstr_w(text));
1262
1263     if(!This->node.doc->nsdoc) {
1264         WARN("NULL nsdoc\n");
1265         return E_UNEXPECTED;
1266     }
1267
1268
1269     nsAString_InitDepend(&ns_text, text);
1270     nsres = nsIDOMDocument_CreateTextNode(This->node.doc->nsdoc, &ns_text, (nsIDOMText **)&nsnode);
1271     nsAString_Finish(&ns_text);
1272
1273     if(NS_FAILED(nsres) || !nsnode)
1274     {
1275         ERR("CreateTextNode failed: %08x\n", nsres);
1276         return E_FAIL;
1277     }
1278
1279     hr = HTMLElement_InsertAdjacentNode(This, where, nsnode);
1280     nsIDOMNode_Release(nsnode);
1281
1282     return hr;
1283 }
1284
1285 static HRESULT WINAPI HTMLElement_get_parentTextEdit(IHTMLElement *iface, IHTMLElement **p)
1286 {
1287     HTMLElement *This = impl_from_IHTMLElement(iface);
1288     FIXME("(%p)->(%p)\n", This, p);
1289     return E_NOTIMPL;
1290 }
1291
1292 static HRESULT WINAPI HTMLElement_get_isTextEdit(IHTMLElement *iface, VARIANT_BOOL *p)
1293 {
1294     HTMLElement *This = impl_from_IHTMLElement(iface);
1295     FIXME("(%p)->(%p)\n", This, p);
1296     return E_NOTIMPL;
1297 }
1298
1299 static HRESULT WINAPI HTMLElement_click(IHTMLElement *iface)
1300 {
1301     HTMLElement *This = impl_from_IHTMLElement(iface);
1302
1303     TRACE("(%p)\n", This);
1304
1305     return call_event(&This->node, EVENTID_CLICK);
1306 }
1307
1308 static HRESULT WINAPI HTMLElement_get_filters(IHTMLElement *iface,
1309                                               IHTMLFiltersCollection **p)
1310 {
1311     HTMLElement *This = impl_from_IHTMLElement(iface);
1312     TRACE("(%p)->(%p)\n", This, p);
1313
1314     if(!p)
1315         return E_POINTER;
1316
1317     *p = HTMLFiltersCollection_Create();
1318
1319     return S_OK;
1320 }
1321
1322 static HRESULT WINAPI HTMLElement_put_ondragstart(IHTMLElement *iface, VARIANT v)
1323 {
1324     HTMLElement *This = impl_from_IHTMLElement(iface);
1325     FIXME("(%p)->()\n", This);
1326     return E_NOTIMPL;
1327 }
1328
1329 static HRESULT WINAPI HTMLElement_get_ondragstart(IHTMLElement *iface, VARIANT *p)
1330 {
1331     HTMLElement *This = impl_from_IHTMLElement(iface);
1332     FIXME("(%p)->(%p)\n", This, p);
1333     return E_NOTIMPL;
1334 }
1335
1336 static HRESULT WINAPI HTMLElement_toString(IHTMLElement *iface, BSTR *String)
1337 {
1338     HTMLElement *This = impl_from_IHTMLElement(iface);
1339     FIXME("(%p)->(%p)\n", This, String);
1340     return E_NOTIMPL;
1341 }
1342
1343 static HRESULT WINAPI HTMLElement_put_onbeforeupdate(IHTMLElement *iface, VARIANT v)
1344 {
1345     HTMLElement *This = impl_from_IHTMLElement(iface);
1346     FIXME("(%p)->()\n", This);
1347     return E_NOTIMPL;
1348 }
1349
1350 static HRESULT WINAPI HTMLElement_get_onbeforeupdate(IHTMLElement *iface, VARIANT *p)
1351 {
1352     HTMLElement *This = impl_from_IHTMLElement(iface);
1353     FIXME("(%p)->(%p)\n", This, p);
1354     return E_NOTIMPL;
1355 }
1356
1357 static HRESULT WINAPI HTMLElement_put_onafterupdate(IHTMLElement *iface, VARIANT v)
1358 {
1359     HTMLElement *This = impl_from_IHTMLElement(iface);
1360     FIXME("(%p)->()\n", This);
1361     return E_NOTIMPL;
1362 }
1363
1364 static HRESULT WINAPI HTMLElement_get_onafterupdate(IHTMLElement *iface, VARIANT *p)
1365 {
1366     HTMLElement *This = impl_from_IHTMLElement(iface);
1367     FIXME("(%p)->(%p)\n", This, p);
1368     return E_NOTIMPL;
1369 }
1370
1371 static HRESULT WINAPI HTMLElement_put_onerrorupdate(IHTMLElement *iface, VARIANT v)
1372 {
1373     HTMLElement *This = impl_from_IHTMLElement(iface);
1374     FIXME("(%p)->()\n", This);
1375     return E_NOTIMPL;
1376 }
1377
1378 static HRESULT WINAPI HTMLElement_get_onerrorupdate(IHTMLElement *iface, VARIANT *p)
1379 {
1380     HTMLElement *This = impl_from_IHTMLElement(iface);
1381     FIXME("(%p)->(%p)\n", This, p);
1382     return E_NOTIMPL;
1383 }
1384
1385 static HRESULT WINAPI HTMLElement_put_onrowexit(IHTMLElement *iface, VARIANT v)
1386 {
1387     HTMLElement *This = impl_from_IHTMLElement(iface);
1388     FIXME("(%p)->()\n", This);
1389     return E_NOTIMPL;
1390 }
1391
1392 static HRESULT WINAPI HTMLElement_get_onrowexit(IHTMLElement *iface, VARIANT *p)
1393 {
1394     HTMLElement *This = impl_from_IHTMLElement(iface);
1395     FIXME("(%p)->(%p)\n", This, p);
1396     return E_NOTIMPL;
1397 }
1398
1399 static HRESULT WINAPI HTMLElement_put_onrowenter(IHTMLElement *iface, VARIANT v)
1400 {
1401     HTMLElement *This = impl_from_IHTMLElement(iface);
1402     FIXME("(%p)->()\n", This);
1403     return E_NOTIMPL;
1404 }
1405
1406 static HRESULT WINAPI HTMLElement_get_onrowenter(IHTMLElement *iface, VARIANT *p)
1407 {
1408     HTMLElement *This = impl_from_IHTMLElement(iface);
1409     FIXME("(%p)->(%p)\n", This, p);
1410     return E_NOTIMPL;
1411 }
1412
1413 static HRESULT WINAPI HTMLElement_put_ondatasetchanged(IHTMLElement *iface, VARIANT v)
1414 {
1415     HTMLElement *This = impl_from_IHTMLElement(iface);
1416     FIXME("(%p)->()\n", This);
1417     return E_NOTIMPL;
1418 }
1419
1420 static HRESULT WINAPI HTMLElement_get_ondatasetchanged(IHTMLElement *iface, VARIANT *p)
1421 {
1422     HTMLElement *This = impl_from_IHTMLElement(iface);
1423     FIXME("(%p)->(%p)\n", This, p);
1424     return E_NOTIMPL;
1425 }
1426
1427 static HRESULT WINAPI HTMLElement_put_ondataavailable(IHTMLElement *iface, VARIANT v)
1428 {
1429     HTMLElement *This = impl_from_IHTMLElement(iface);
1430     FIXME("(%p)->()\n", This);
1431     return E_NOTIMPL;
1432 }
1433
1434 static HRESULT WINAPI HTMLElement_get_ondataavailable(IHTMLElement *iface, VARIANT *p)
1435 {
1436     HTMLElement *This = impl_from_IHTMLElement(iface);
1437     FIXME("(%p)->(%p)\n", This, p);
1438     return E_NOTIMPL;
1439 }
1440
1441 static HRESULT WINAPI HTMLElement_put_ondatasetcomplete(IHTMLElement *iface, VARIANT v)
1442 {
1443     HTMLElement *This = impl_from_IHTMLElement(iface);
1444     FIXME("(%p)->()\n", This);
1445     return E_NOTIMPL;
1446 }
1447
1448 static HRESULT WINAPI HTMLElement_get_ondatasetcomplete(IHTMLElement *iface, VARIANT *p)
1449 {
1450     HTMLElement *This = impl_from_IHTMLElement(iface);
1451     FIXME("(%p)->(%p)\n", This, p);
1452     return E_NOTIMPL;
1453 }
1454
1455 static HRESULT WINAPI HTMLElement_put_onfilterchange(IHTMLElement *iface, VARIANT v)
1456 {
1457     HTMLElement *This = impl_from_IHTMLElement(iface);
1458     FIXME("(%p)->()\n", This);
1459     return E_NOTIMPL;
1460 }
1461
1462 static HRESULT WINAPI HTMLElement_get_onfilterchange(IHTMLElement *iface, VARIANT *p)
1463 {
1464     HTMLElement *This = impl_from_IHTMLElement(iface);
1465     FIXME("(%p)->(%p)\n", This, p);
1466     return E_NOTIMPL;
1467 }
1468
1469 static HRESULT WINAPI HTMLElement_get_children(IHTMLElement *iface, IDispatch **p)
1470 {
1471     HTMLElement *This = impl_from_IHTMLElement(iface);
1472     nsIDOMNodeList *nsnode_list;
1473     nsresult nsres;
1474
1475     TRACE("(%p)->(%p)\n", This, p);
1476
1477     nsres = nsIDOMNode_GetChildNodes(This->node.nsnode, &nsnode_list);
1478     if(NS_FAILED(nsres)) {
1479         ERR("GetChildNodes failed: %08x\n", nsres);
1480         return E_FAIL;
1481     }
1482
1483     *p = (IDispatch*)create_collection_from_nodelist(This->node.doc,
1484             (IUnknown*)&This->IHTMLElement_iface, nsnode_list);
1485
1486     nsIDOMNodeList_Release(nsnode_list);
1487     return S_OK;
1488 }
1489
1490 static HRESULT WINAPI HTMLElement_get_all(IHTMLElement *iface, IDispatch **p)
1491 {
1492     HTMLElement *This = impl_from_IHTMLElement(iface);
1493
1494     TRACE("(%p)->(%p)\n", This, p);
1495
1496     *p = (IDispatch*)create_all_collection(&This->node, FALSE);
1497     return S_OK;
1498 }
1499
1500 static const IHTMLElementVtbl HTMLElementVtbl = {
1501     HTMLElement_QueryInterface,
1502     HTMLElement_AddRef,
1503     HTMLElement_Release,
1504     HTMLElement_GetTypeInfoCount,
1505     HTMLElement_GetTypeInfo,
1506     HTMLElement_GetIDsOfNames,
1507     HTMLElement_Invoke,
1508     HTMLElement_setAttribute,
1509     HTMLElement_getAttribute,
1510     HTMLElement_removeAttribute,
1511     HTMLElement_put_className,
1512     HTMLElement_get_className,
1513     HTMLElement_put_id,
1514     HTMLElement_get_id,
1515     HTMLElement_get_tagName,
1516     HTMLElement_get_parentElement,
1517     HTMLElement_get_style,
1518     HTMLElement_put_onhelp,
1519     HTMLElement_get_onhelp,
1520     HTMLElement_put_onclick,
1521     HTMLElement_get_onclick,
1522     HTMLElement_put_ondblclick,
1523     HTMLElement_get_ondblclick,
1524     HTMLElement_put_onkeydown,
1525     HTMLElement_get_onkeydown,
1526     HTMLElement_put_onkeyup,
1527     HTMLElement_get_onkeyup,
1528     HTMLElement_put_onkeypress,
1529     HTMLElement_get_onkeypress,
1530     HTMLElement_put_onmouseout,
1531     HTMLElement_get_onmouseout,
1532     HTMLElement_put_onmouseover,
1533     HTMLElement_get_onmouseover,
1534     HTMLElement_put_onmousemove,
1535     HTMLElement_get_onmousemove,
1536     HTMLElement_put_onmousedown,
1537     HTMLElement_get_onmousedown,
1538     HTMLElement_put_onmouseup,
1539     HTMLElement_get_onmouseup,
1540     HTMLElement_get_document,
1541     HTMLElement_put_title,
1542     HTMLElement_get_title,
1543     HTMLElement_put_language,
1544     HTMLElement_get_language,
1545     HTMLElement_put_onselectstart,
1546     HTMLElement_get_onselectstart,
1547     HTMLElement_scrollIntoView,
1548     HTMLElement_contains,
1549     HTMLElement_get_sourceIndex,
1550     HTMLElement_get_recordNumber,
1551     HTMLElement_put_lang,
1552     HTMLElement_get_lang,
1553     HTMLElement_get_offsetLeft,
1554     HTMLElement_get_offsetTop,
1555     HTMLElement_get_offsetWidth,
1556     HTMLElement_get_offsetHeight,
1557     HTMLElement_get_offsetParent,
1558     HTMLElement_put_innerHTML,
1559     HTMLElement_get_innerHTML,
1560     HTMLElement_put_innerText,
1561     HTMLElement_get_innerText,
1562     HTMLElement_put_outerHTML,
1563     HTMLElement_get_outerHTML,
1564     HTMLElement_put_outerText,
1565     HTMLElement_get_outerText,
1566     HTMLElement_insertAdjacentHTML,
1567     HTMLElement_insertAdjacentText,
1568     HTMLElement_get_parentTextEdit,
1569     HTMLElement_get_isTextEdit,
1570     HTMLElement_click,
1571     HTMLElement_get_filters,
1572     HTMLElement_put_ondragstart,
1573     HTMLElement_get_ondragstart,
1574     HTMLElement_toString,
1575     HTMLElement_put_onbeforeupdate,
1576     HTMLElement_get_onbeforeupdate,
1577     HTMLElement_put_onafterupdate,
1578     HTMLElement_get_onafterupdate,
1579     HTMLElement_put_onerrorupdate,
1580     HTMLElement_get_onerrorupdate,
1581     HTMLElement_put_onrowexit,
1582     HTMLElement_get_onrowexit,
1583     HTMLElement_put_onrowenter,
1584     HTMLElement_get_onrowenter,
1585     HTMLElement_put_ondatasetchanged,
1586     HTMLElement_get_ondatasetchanged,
1587     HTMLElement_put_ondataavailable,
1588     HTMLElement_get_ondataavailable,
1589     HTMLElement_put_ondatasetcomplete,
1590     HTMLElement_get_ondatasetcomplete,
1591     HTMLElement_put_onfilterchange,
1592     HTMLElement_get_onfilterchange,
1593     HTMLElement_get_children,
1594     HTMLElement_get_all
1595 };
1596
1597 static inline HTMLElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
1598 {
1599     return CONTAINING_RECORD(iface, HTMLElement, node);
1600 }
1601
1602 HRESULT HTMLElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
1603 {
1604     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1605
1606     *ppv =  NULL;
1607
1608     if(IsEqualGUID(&IID_IUnknown, riid)) {
1609         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1610         *ppv = &This->IHTMLElement_iface;
1611     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
1612         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
1613         *ppv = &This->IHTMLElement_iface;
1614     }else if(IsEqualGUID(&IID_IHTMLElement, riid)) {
1615         TRACE("(%p)->(IID_IHTMLElement %p)\n", This, ppv);
1616         *ppv = &This->IHTMLElement_iface;
1617     }else if(IsEqualGUID(&IID_IHTMLElement2, riid)) {
1618         TRACE("(%p)->(IID_IHTMLElement2 %p)\n", This, ppv);
1619         *ppv = &This->IHTMLElement2_iface;
1620     }else if(IsEqualGUID(&IID_IHTMLElement3, riid)) {
1621         TRACE("(%p)->(IID_IHTMLElement3 %p)\n", This, ppv);
1622         *ppv = &This->IHTMLElement3_iface;
1623     }else if(IsEqualGUID(&IID_IHTMLElement4, riid)) {
1624         TRACE("(%p)->(IID_IHTMLElement4 %p)\n", This, ppv);
1625         *ppv = &This->IHTMLElement4_iface;
1626     }else if(IsEqualGUID(&IID_IConnectionPointContainer, riid)) {
1627         TRACE("(%p)->(IID_IConnectionPointContainer %p)\n", This, ppv);
1628         *ppv = &This->cp_container.IConnectionPointContainer_iface;
1629     }
1630
1631     if(*ppv) {
1632         IHTMLElement_AddRef(&This->IHTMLElement_iface);
1633         return S_OK;
1634     }
1635
1636     return HTMLDOMNode_QI(&This->node, riid, ppv);
1637 }
1638
1639 void HTMLElement_destructor(HTMLDOMNode *iface)
1640 {
1641     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1642
1643     ConnectionPointContainer_Destroy(&This->cp_container);
1644
1645     if(This->nselem)
1646         nsIDOMHTMLElement_Release(This->nselem);
1647
1648     HTMLDOMNode_destructor(&This->node);
1649 }
1650
1651 HRESULT HTMLElement_clone(HTMLDOMNode *iface, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1652 {
1653     HTMLElement *This = impl_from_HTMLDOMNode(iface);
1654     HTMLElement *new_elem;
1655     HRESULT hres;
1656
1657     hres = HTMLElement_Create(This->node.doc, nsnode, FALSE, &new_elem);
1658     if(FAILED(hres))
1659         return hres;
1660
1661     IHTMLElement_AddRef(&new_elem->IHTMLElement_iface);
1662     *ret = &new_elem->node;
1663     return S_OK;
1664 }
1665
1666 static const NodeImplVtbl HTMLElementImplVtbl = {
1667     HTMLElement_QI,
1668     HTMLElement_destructor,
1669     HTMLElement_clone
1670 };
1671
1672 static inline HTMLElement *impl_from_DispatchEx(DispatchEx *iface)
1673 {
1674     return CONTAINING_RECORD(iface, HTMLElement, node.dispex);
1675 }
1676
1677 static HRESULT HTMLElement_get_dispid(DispatchEx *dispex, BSTR name,
1678         DWORD grfdex, DISPID *pid)
1679 {
1680     HTMLElement *This = impl_from_DispatchEx(dispex);
1681
1682     if(This->node.vtbl->get_dispid)
1683         return This->node.vtbl->get_dispid(&This->node, name, grfdex, pid);
1684
1685     return DISP_E_UNKNOWNNAME;
1686 }
1687
1688 static HRESULT HTMLElement_invoke(DispatchEx *dispex, DISPID id, LCID lcid,
1689         WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei,
1690         IServiceProvider *caller)
1691 {
1692     HTMLElement *This = impl_from_DispatchEx(dispex);
1693
1694     if(This->node.vtbl->invoke)
1695         return This->node.vtbl->invoke(&This->node, id, lcid, flags,
1696                 params, res, ei, caller);
1697
1698     ERR("(%p): element has no invoke method\n", This);
1699     return E_NOTIMPL;
1700 }
1701
1702 static const tid_t HTMLElement_iface_tids[] = {
1703     HTMLELEMENT_TIDS,
1704     0
1705 };
1706
1707 static dispex_static_data_vtbl_t HTMLElement_dispex_vtbl = {
1708     NULL,
1709     HTMLElement_get_dispid,
1710     HTMLElement_invoke
1711 };
1712
1713 static dispex_static_data_t HTMLElement_dispex = {
1714     &HTMLElement_dispex_vtbl,
1715     DispHTMLUnknownElement_tid,
1716     NULL,
1717     HTMLElement_iface_tids
1718 };
1719
1720 void HTMLElement_Init(HTMLElement *This, HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, dispex_static_data_t *dispex_data)
1721 {
1722     This->IHTMLElement_iface.lpVtbl = &HTMLElementVtbl;
1723
1724     HTMLElement2_Init(This);
1725     HTMLElement3_Init(This);
1726
1727     if(dispex_data && !dispex_data->vtbl)
1728         dispex_data->vtbl = &HTMLElement_dispex_vtbl;
1729     init_dispex(&This->node.dispex, (IUnknown*)&This->IHTMLElement_iface,
1730             dispex_data ? dispex_data : &HTMLElement_dispex);
1731
1732     if(nselem)
1733         nsIDOMHTMLElement_AddRef(nselem);
1734     This->nselem = nselem;
1735
1736     HTMLDOMNode_Init(doc, &This->node, (nsIDOMNode*)nselem);
1737
1738     ConnectionPointContainer_Init(&This->cp_container, (IUnknown*)&This->IHTMLElement_iface);
1739 }
1740
1741 HRESULT HTMLElement_Create(HTMLDocumentNode *doc, nsIDOMNode *nsnode, BOOL use_generic, HTMLElement **ret)
1742 {
1743     nsIDOMHTMLElement *nselem;
1744     nsAString class_name_str;
1745     const PRUnichar *class_name;
1746     const tag_desc_t *tag;
1747     HTMLElement *elem;
1748     nsresult nsres;
1749     HRESULT hres;
1750
1751     nsres = nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMHTMLElement, (void**)&nselem);
1752     if(NS_FAILED(nsres))
1753         return E_FAIL;
1754
1755     nsAString_Init(&class_name_str, NULL);
1756     nsIDOMHTMLElement_GetTagName(nselem, &class_name_str);
1757
1758     nsAString_GetData(&class_name_str, &class_name);
1759
1760     tag = get_tag_desc(class_name);
1761     if(tag) {
1762         hres = tag->constructor(doc, nselem, &elem);
1763     }else if(use_generic) {
1764         hres = HTMLGenericElement_Create(doc, nselem, &elem);
1765     }else {
1766         elem = heap_alloc_zero(sizeof(HTMLElement));
1767         if(elem) {
1768             HTMLElement_Init(elem, doc, nselem, &HTMLElement_dispex);
1769             elem->node.vtbl = &HTMLElementImplVtbl;
1770             hres = S_OK;
1771         }else {
1772             hres = E_OUTOFMEMORY;
1773         }
1774     }
1775
1776     TRACE("%s ret %p\n", debugstr_w(class_name), elem);
1777
1778     nsIDOMElement_Release(nselem);
1779     nsAString_Finish(&class_name_str);
1780     if(FAILED(hres))
1781         return hres;
1782
1783     *ret = elem;
1784     return S_OK;
1785 }
1786
1787 /* interface IHTMLFiltersCollection */
1788 static HRESULT WINAPI HTMLFiltersCollection_QueryInterface(IHTMLFiltersCollection *iface, REFIID riid, void **ppv)
1789 {
1790     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1791
1792     TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppv );
1793
1794     if(IsEqualGUID(&IID_IUnknown, riid)) {
1795         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
1796         *ppv = &This->IHTMLFiltersCollection_iface;
1797     }else if(IsEqualGUID(&IID_IHTMLFiltersCollection, riid)) {
1798         TRACE("(%p)->(IID_IHTMLFiltersCollection %p)\n", This, ppv);
1799         *ppv = &This->IHTMLFiltersCollection_iface;
1800     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1801         return *ppv ? S_OK : E_NOINTERFACE;
1802     }
1803
1804     if(*ppv) {
1805         IUnknown_AddRef((IUnknown*)*ppv);
1806         return S_OK;
1807     }
1808
1809     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1810     return E_NOINTERFACE;
1811 }
1812
1813 static ULONG WINAPI HTMLFiltersCollection_AddRef(IHTMLFiltersCollection *iface)
1814 {
1815     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1816     LONG ref = InterlockedIncrement(&This->ref);
1817
1818     TRACE("(%p) ref=%d\n", This, ref);
1819
1820     return ref;
1821 }
1822
1823 static ULONG WINAPI HTMLFiltersCollection_Release(IHTMLFiltersCollection *iface)
1824 {
1825     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1826     LONG ref = InterlockedDecrement(&This->ref);
1827
1828     TRACE("(%p) ref=%d\n", This, ref);
1829
1830     if(!ref)
1831     {
1832         heap_free(This);
1833     }
1834
1835     return ref;
1836 }
1837
1838 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfoCount(IHTMLFiltersCollection *iface, UINT *pctinfo)
1839 {
1840     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1841     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
1842 }
1843
1844 static HRESULT WINAPI HTMLFiltersCollection_GetTypeInfo(IHTMLFiltersCollection *iface,
1845                                     UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1846 {
1847     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1848     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
1849 }
1850
1851 static HRESULT WINAPI HTMLFiltersCollection_GetIDsOfNames(IHTMLFiltersCollection *iface,
1852                                     REFIID riid, LPOLESTR *rgszNames, UINT cNames,
1853                                     LCID lcid, DISPID *rgDispId)
1854 {
1855     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1856     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
1857             lcid, rgDispId);
1858 }
1859
1860 static HRESULT WINAPI HTMLFiltersCollection_Invoke(IHTMLFiltersCollection *iface, DISPID dispIdMember, REFIID riid,
1861                                     LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1862                                     EXCEPINFO *pExcepInfo, UINT *puArgErr)
1863 {
1864     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1865     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
1866             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
1867 }
1868
1869 static HRESULT WINAPI HTMLFiltersCollection_get_length(IHTMLFiltersCollection *iface, LONG *p)
1870 {
1871     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1872
1873     if(!p)
1874         return E_POINTER;
1875
1876     FIXME("(%p)->(%p) Always returning 0\n", This, p);
1877     *p = 0;
1878
1879     return S_OK;
1880 }
1881
1882 static HRESULT WINAPI HTMLFiltersCollection_get__newEnum(IHTMLFiltersCollection *iface, IUnknown **p)
1883 {
1884     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1885     FIXME("(%p)->(%p)\n", This, p);
1886     return E_NOTIMPL;
1887 }
1888
1889 static HRESULT WINAPI HTMLFiltersCollection_item(IHTMLFiltersCollection *iface, VARIANT *pvarIndex, VARIANT *pvarResult)
1890 {
1891     HTMLFiltersCollection *This = impl_from_IHTMLFiltersCollection(iface);
1892     FIXME("(%p)->(%p, %p)\n", This, pvarIndex, pvarResult);
1893     return E_NOTIMPL;
1894 }
1895
1896 static const IHTMLFiltersCollectionVtbl HTMLFiltersCollectionVtbl = {
1897     HTMLFiltersCollection_QueryInterface,
1898     HTMLFiltersCollection_AddRef,
1899     HTMLFiltersCollection_Release,
1900     HTMLFiltersCollection_GetTypeInfoCount,
1901     HTMLFiltersCollection_GetTypeInfo,
1902     HTMLFiltersCollection_GetIDsOfNames,
1903     HTMLFiltersCollection_Invoke,
1904     HTMLFiltersCollection_get_length,
1905     HTMLFiltersCollection_get__newEnum,
1906     HTMLFiltersCollection_item
1907 };
1908
1909 static HRESULT HTMLFiltersCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
1910 {
1911     WCHAR *ptr;
1912     int idx = 0;
1913
1914     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
1915         idx = idx*10 + (*ptr-'0');
1916     if(*ptr)
1917         return DISP_E_UNKNOWNNAME;
1918
1919     *dispid = MSHTML_DISPID_CUSTOM_MIN + idx;
1920     TRACE("ret %x\n", *dispid);
1921     return S_OK;
1922 }
1923
1924 static HRESULT HTMLFiltersCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
1925         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
1926 {
1927     TRACE("(%p)->(%x %x %x %p %p %p)\n", dispex, id, lcid, flags, params, res, ei);
1928
1929     V_VT(res) = VT_DISPATCH;
1930     V_DISPATCH(res) = NULL;
1931
1932     FIXME("always returning NULL\n");
1933
1934     return S_OK;
1935 }
1936
1937 static const dispex_static_data_vtbl_t HTMLFiltersCollection_dispex_vtbl = {
1938     NULL,
1939     HTMLFiltersCollection_get_dispid,
1940     HTMLFiltersCollection_invoke
1941 };
1942
1943 static const tid_t HTMLFiltersCollection_iface_tids[] = {
1944     IHTMLFiltersCollection_tid,
1945     0
1946 };
1947 static dispex_static_data_t HTMLFiltersCollection_dispex = {
1948     &HTMLFiltersCollection_dispex_vtbl,
1949     IHTMLFiltersCollection_tid,
1950     NULL,
1951     HTMLFiltersCollection_iface_tids
1952 };
1953
1954 IHTMLFiltersCollection *HTMLFiltersCollection_Create()
1955 {
1956     HTMLFiltersCollection *ret = heap_alloc(sizeof(HTMLFiltersCollection));
1957
1958     ret->IHTMLFiltersCollection_iface.lpVtbl = &HTMLFiltersCollectionVtbl;
1959     ret->ref = 1;
1960
1961     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLFiltersCollection_iface,
1962             &HTMLFiltersCollection_dispex);
1963
1964     return &ret->IHTMLFiltersCollection_iface;
1965 }