mshtml: Added noscript tag handling tests.
[wine] / dlls / mshtml / htmlselect.c
1 /*
2  * Copyright 2006 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include <stdarg.h>
20 #include <assert.h>
21
22 #define COBJMACROS
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "ole2.h"
28
29 #include "wine/debug.h"
30
31 #include "mshtml_private.h"
32 #include "htmlevent.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
35
36 typedef struct {
37     HTMLElement element;
38
39     IHTMLSelectElement IHTMLSelectElement_iface;
40
41     nsIDOMHTMLSelectElement *nsselect;
42 } HTMLSelectElement;
43
44 static inline HTMLSelectElement *impl_from_IHTMLSelectElement(IHTMLSelectElement *iface)
45 {
46     return CONTAINING_RECORD(iface, HTMLSelectElement, IHTMLSelectElement_iface);
47 }
48
49 static HRESULT htmlselect_item(HTMLSelectElement *This, int i, IDispatch **ret)
50 {
51     nsIDOMHTMLOptionsCollection *nscol;
52     nsIDOMNode *nsnode;
53     nsresult nsres;
54     HRESULT hres;
55
56     nsres = nsIDOMHTMLSelectElement_GetOptions(This->nsselect, &nscol);
57     if(NS_FAILED(nsres)) {
58         ERR("GetOptions failed: %08x\n", nsres);
59         return E_FAIL;
60     }
61
62     nsres = nsIDOMHTMLOptionsCollection_Item(nscol, i, &nsnode);
63     nsIDOMHTMLOptionsCollection_Release(nscol);
64     if(NS_FAILED(nsres)) {
65         ERR("Item failed: %08x\n", nsres);
66         return E_FAIL;
67     }
68
69     if(nsnode) {
70         HTMLDOMNode *node;
71
72         hres = get_node(This->element.node.doc, nsnode, TRUE, &node);
73         nsIDOMNode_Release(nsnode);
74         if(FAILED(hres))
75             return hres;
76
77         *ret = (IDispatch*)&node->IHTMLDOMNode_iface;
78     }else {
79         *ret = NULL;
80     }
81     return S_OK;
82 }
83
84 static HRESULT WINAPI HTMLSelectElement_QueryInterface(IHTMLSelectElement *iface,
85                                                          REFIID riid, void **ppv)
86 {
87     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
88
89     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
90 }
91
92 static ULONG WINAPI HTMLSelectElement_AddRef(IHTMLSelectElement *iface)
93 {
94     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
95
96     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
97 }
98
99 static ULONG WINAPI HTMLSelectElement_Release(IHTMLSelectElement *iface)
100 {
101     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
102
103     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
104 }
105
106 static HRESULT WINAPI HTMLSelectElement_GetTypeInfoCount(IHTMLSelectElement *iface, UINT *pctinfo)
107 {
108     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
109
110     return IDispatchEx_GetTypeInfoCount(&This->element.node.dispex.IDispatchEx_iface, pctinfo);
111 }
112
113 static HRESULT WINAPI HTMLSelectElement_GetTypeInfo(IHTMLSelectElement *iface, UINT iTInfo,
114                                               LCID lcid, ITypeInfo **ppTInfo)
115 {
116     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
117
118     return IDispatchEx_GetTypeInfo(&This->element.node.dispex.IDispatchEx_iface, iTInfo, lcid,
119             ppTInfo);
120 }
121
122 static HRESULT WINAPI HTMLSelectElement_GetIDsOfNames(IHTMLSelectElement *iface, REFIID riid,
123                                                 LPOLESTR *rgszNames, UINT cNames,
124                                                 LCID lcid, DISPID *rgDispId)
125 {
126     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
127
128     return IDispatchEx_GetIDsOfNames(&This->element.node.dispex.IDispatchEx_iface, riid, rgszNames,
129             cNames, lcid, rgDispId);
130 }
131
132 static HRESULT WINAPI HTMLSelectElement_Invoke(IHTMLSelectElement *iface, DISPID dispIdMember,
133                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
134                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
135 {
136     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
137
138     return IDispatchEx_Invoke(&This->element.node.dispex.IDispatchEx_iface, dispIdMember, riid,
139             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
140 }
141
142 static HRESULT WINAPI HTMLSelectElement_put_size(IHTMLSelectElement *iface, LONG v)
143 {
144     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
145     FIXME("(%p)->(%d)\n", This, v);
146     return E_NOTIMPL;
147 }
148
149 static HRESULT WINAPI HTMLSelectElement_get_size(IHTMLSelectElement *iface, LONG *p)
150 {
151     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
152     FIXME("(%p)->(%p)\n", This, p);
153     return E_NOTIMPL;
154 }
155
156 static HRESULT WINAPI HTMLSelectElement_put_multiple(IHTMLSelectElement *iface, VARIANT_BOOL v)
157 {
158     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
159     FIXME("(%p)->(%x)\n", This, v);
160     return E_NOTIMPL;
161 }
162
163 static HRESULT WINAPI HTMLSelectElement_get_multiple(IHTMLSelectElement *iface, VARIANT_BOOL *p)
164 {
165     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
166     FIXME("(%p)->(%p)\n", This, p);
167     return E_NOTIMPL;
168 }
169
170 static HRESULT WINAPI HTMLSelectElement_put_name(IHTMLSelectElement *iface, BSTR v)
171 {
172     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
173     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
174     return E_NOTIMPL;
175 }
176
177 static HRESULT WINAPI HTMLSelectElement_get_name(IHTMLSelectElement *iface, BSTR *p)
178 {
179     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
180     nsAString name_str;
181     const PRUnichar *name = NULL;
182     nsresult nsres;
183
184     TRACE("(%p)->(%p)\n", This, p);
185
186     nsAString_Init(&name_str, NULL);
187
188     nsres = nsIDOMHTMLSelectElement_GetName(This->nsselect, &name_str);
189     if(NS_SUCCEEDED(nsres)) {
190         static const WCHAR wszGarbage[] = {'g','a','r','b','a','g','e',0};
191
192         nsAString_GetData(&name_str, &name);
193
194         /*
195          * Native never returns empty string here. If an element has no name,
196          * name of previous element or ramdom data is returned.
197          */
198         *p = SysAllocString(*name ? name : wszGarbage);
199     }else {
200         ERR("GetName failed: %08x\n", nsres);
201     }
202
203     nsAString_Finish(&name_str);
204
205     TRACE("name=%s\n", debugstr_w(*p));
206     return S_OK;
207 }
208
209 static HRESULT WINAPI HTMLSelectElement_get_options(IHTMLSelectElement *iface, IDispatch **p)
210 {
211     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
212
213     TRACE("(%p)->(%p)\n", This, p);
214
215     *p = (IDispatch*)&This->IHTMLSelectElement_iface;
216     IDispatch_AddRef(*p);
217     return S_OK;
218 }
219
220 static HRESULT WINAPI HTMLSelectElement_put_onchange(IHTMLSelectElement *iface, VARIANT v)
221 {
222     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
223
224     TRACE("(%p)->()\n", This);
225
226     return set_node_event(&This->element.node, EVENTID_CHANGE, &v);
227 }
228
229 static HRESULT WINAPI HTMLSelectElement_get_onchange(IHTMLSelectElement *iface, VARIANT *p)
230 {
231     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
232     FIXME("(%p)->(%p)\n", This, p);
233     return E_NOTIMPL;
234 }
235
236 static HRESULT WINAPI HTMLSelectElement_put_selectedIndex(IHTMLSelectElement *iface, LONG v)
237 {
238     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
239     nsresult nsres;
240
241     TRACE("(%p)->(%d)\n", This, v);
242
243     nsres = nsIDOMHTMLSelectElement_SetSelectedIndex(This->nsselect, v);
244     if(NS_FAILED(nsres))
245         ERR("SetSelectedIndex failed: %08x\n", nsres);
246
247     return S_OK;
248 }
249
250 static HRESULT WINAPI HTMLSelectElement_get_selectedIndex(IHTMLSelectElement *iface, LONG *p)
251 {
252     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
253     PRInt32 idx = 0;
254     nsresult nsres;
255
256     TRACE("(%p)->(%p)\n", This, p);
257
258     nsres = nsIDOMHTMLSelectElement_GetSelectedIndex(This->nsselect, &idx);
259     if(NS_FAILED(nsres))
260         ERR("GetSelectedIndex failed: %08x\n", nsres);
261
262     *p = idx;
263     return S_OK;
264 }
265
266 static HRESULT WINAPI HTMLSelectElement_get_type(IHTMLSelectElement *iface, BSTR *p)
267 {
268     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
269     nsAString type_str;
270     nsresult nsres;
271
272     TRACE("(%p)->(%p)\n", This, p);
273
274     nsAString_Init(&type_str, NULL);
275     nsres = nsIDOMHTMLSelectElement_GetType(This->nsselect, &type_str);
276     return return_nsstr(nsres, &type_str, p);
277 }
278
279 static HRESULT WINAPI HTMLSelectElement_put_value(IHTMLSelectElement *iface, BSTR v)
280 {
281     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
282     nsAString value_str;
283     nsresult nsres;
284
285     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
286
287     nsAString_InitDepend(&value_str, v);
288     nsres = nsIDOMHTMLSelectElement_SetValue(This->nsselect, &value_str);
289     nsAString_Finish(&value_str);
290     if(NS_FAILED(nsres))
291         ERR("SetValue failed: %08x\n", nsres);
292
293     return S_OK;
294 }
295
296 static HRESULT WINAPI HTMLSelectElement_get_value(IHTMLSelectElement *iface, BSTR *p)
297 {
298     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
299     nsAString value_str;
300     nsresult nsres;
301
302     TRACE("(%p)->(%p)\n", This, p);
303
304     nsAString_Init(&value_str, NULL);
305     nsres = nsIDOMHTMLSelectElement_GetValue(This->nsselect, &value_str);
306     return return_nsstr(nsres, &value_str, p);
307 }
308
309 static HRESULT WINAPI HTMLSelectElement_put_disabled(IHTMLSelectElement *iface, VARIANT_BOOL v)
310 {
311     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
312     nsresult nsres;
313
314     TRACE("(%p)->(%x)\n", This, v);
315
316     nsres = nsIDOMHTMLSelectElement_SetDisabled(This->nsselect, v != VARIANT_FALSE);
317     if(NS_FAILED(nsres)) {
318         ERR("SetDisabled failed: %08x\n", nsres);
319         return E_FAIL;
320     }
321
322     return S_OK;
323 }
324
325 static HRESULT WINAPI HTMLSelectElement_get_disabled(IHTMLSelectElement *iface, VARIANT_BOOL *p)
326 {
327     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
328     cpp_bool disabled = FALSE;
329     nsresult nsres;
330
331     TRACE("(%p)->(%p)\n", This, p);
332
333     nsres = nsIDOMHTMLSelectElement_GetDisabled(This->nsselect, &disabled);
334     if(NS_FAILED(nsres)) {
335         ERR("GetDisabled failed: %08x\n", nsres);
336         return E_FAIL;
337     }
338
339     *p = disabled ? VARIANT_TRUE : VARIANT_FALSE;
340     return S_OK;
341 }
342
343 static HRESULT WINAPI HTMLSelectElement_get_form(IHTMLSelectElement *iface, IHTMLFormElement **p)
344 {
345     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
346     FIXME("(%p)->(%p)\n", This, p);
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI HTMLSelectElement_add(IHTMLSelectElement *iface, IHTMLElement *element,
351                                             VARIANT before)
352 {
353     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
354     nsIWritableVariant *nsvariant;
355     HTMLElement *element_obj;
356     nsresult nsres;
357
358     TRACE("(%p)->(%p %s)\n", This, element, debugstr_variant(&before));
359
360     element_obj = unsafe_impl_from_IHTMLElement(element);
361     if(!element_obj) {
362         FIXME("External IHTMLElement implementation?\n");
363         return E_INVALIDARG;
364     }
365
366     nsvariant = create_nsvariant();
367     if(!nsvariant)
368         return E_FAIL;
369
370     switch(V_VT(&before)) {
371     case VT_EMPTY:
372         nsres = nsIWritableVariant_SetAsEmpty(nsvariant);
373         break;
374     case VT_I2:
375         nsres = nsIWritableVariant_SetAsInt16(nsvariant, V_I2(&before));
376         break;
377     default:
378         FIXME("unhandled before %s\n", debugstr_variant(&before));
379         nsIWritableVariant_Release(nsvariant);
380         return E_NOTIMPL;
381     }
382
383     if(NS_SUCCEEDED(nsres))
384         nsres = nsIDOMHTMLSelectElement_Add(This->nsselect, element_obj->nselem, (nsIVariant*)nsvariant);
385     nsIWritableVariant_Release(nsvariant);
386     if(NS_FAILED(nsres)) {
387         ERR("Add failed: %08x\n", nsres);
388         return E_FAIL;
389     }
390
391     return S_OK;
392 }
393
394 static HRESULT WINAPI HTMLSelectElement_remove(IHTMLSelectElement *iface, LONG index)
395 {
396     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
397     FIXME("(%p)->(%d)\n", This, index);
398     return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI HTMLSelectElement_put_length(IHTMLSelectElement *iface, LONG v)
402 {
403     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
404     nsresult nsres;
405
406     TRACE("(%p)->(%d)\n", This, v);
407
408     nsres = nsIDOMHTMLSelectElement_SetLength(This->nsselect, v);
409     if(NS_FAILED(nsres))
410         ERR("SetLength failed: %08x\n", nsres);
411
412     return S_OK;
413 }
414
415 static HRESULT WINAPI HTMLSelectElement_get_length(IHTMLSelectElement *iface, LONG *p)
416 {
417     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
418     PRUint32 length = 0;
419     nsresult nsres;
420
421     TRACE("(%p)->(%p)\n", This, p);
422
423     nsres = nsIDOMHTMLSelectElement_GetLength(This->nsselect, &length);
424     if(NS_FAILED(nsres))
425         ERR("GetLength failed: %08x\n", nsres);
426
427     *p = length;
428
429     TRACE("ret %d\n", *p);
430     return S_OK;
431 }
432
433 static HRESULT WINAPI HTMLSelectElement_get__newEnum(IHTMLSelectElement *iface, IUnknown **p)
434 {
435     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
436     FIXME("(%p)->(%p)\n", This, p);
437     return E_NOTIMPL;
438 }
439
440 static HRESULT WINAPI HTMLSelectElement_item(IHTMLSelectElement *iface, VARIANT name,
441                                              VARIANT index, IDispatch **pdisp)
442 {
443     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
444
445     TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
446
447     if(!pdisp)
448         return E_POINTER;
449     *pdisp = NULL;
450
451     if(V_VT(&name) == VT_I4) {
452         if(V_I4(&name) < 0)
453             return E_INVALIDARG;
454         return htmlselect_item(This, V_I4(&name), pdisp);
455     }
456
457     FIXME("Unsupported args\n");
458     return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI HTMLSelectElement_tags(IHTMLSelectElement *iface, VARIANT tagName,
462                                              IDispatch **pdisp)
463 {
464     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
465     FIXME("(%p)->(v %p)\n", This, pdisp);
466     return E_NOTIMPL;
467 }
468
469 static const IHTMLSelectElementVtbl HTMLSelectElementVtbl = {
470     HTMLSelectElement_QueryInterface,
471     HTMLSelectElement_AddRef,
472     HTMLSelectElement_Release,
473     HTMLSelectElement_GetTypeInfoCount,
474     HTMLSelectElement_GetTypeInfo,
475     HTMLSelectElement_GetIDsOfNames,
476     HTMLSelectElement_Invoke,
477     HTMLSelectElement_put_size,
478     HTMLSelectElement_get_size,
479     HTMLSelectElement_put_multiple,
480     HTMLSelectElement_get_multiple,
481     HTMLSelectElement_put_name,
482     HTMLSelectElement_get_name,
483     HTMLSelectElement_get_options,
484     HTMLSelectElement_put_onchange,
485     HTMLSelectElement_get_onchange,
486     HTMLSelectElement_put_selectedIndex,
487     HTMLSelectElement_get_selectedIndex,
488     HTMLSelectElement_get_type,
489     HTMLSelectElement_put_value,
490     HTMLSelectElement_get_value,
491     HTMLSelectElement_put_disabled,
492     HTMLSelectElement_get_disabled,
493     HTMLSelectElement_get_form,
494     HTMLSelectElement_add,
495     HTMLSelectElement_remove,
496     HTMLSelectElement_put_length,
497     HTMLSelectElement_get_length,
498     HTMLSelectElement_get__newEnum,
499     HTMLSelectElement_item,
500     HTMLSelectElement_tags
501 };
502
503 static inline HTMLSelectElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
504 {
505     return CONTAINING_RECORD(iface, HTMLSelectElement, element.node);
506 }
507
508 static HRESULT HTMLSelectElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
509 {
510     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
511
512     *ppv = NULL;
513
514     if(IsEqualGUID(&IID_IUnknown, riid)) {
515         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
516         *ppv = &This->IHTMLSelectElement_iface;
517     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
518         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
519         *ppv = &This->IHTMLSelectElement_iface;
520     }else if(IsEqualGUID(&IID_IHTMLSelectElement, riid)) {
521         TRACE("(%p)->(IID_IHTMLSelectElement %p)\n", This, ppv);
522         *ppv = &This->IHTMLSelectElement_iface;
523     }
524
525     if(*ppv) {
526         IUnknown_AddRef((IUnknown*)*ppv);
527         return S_OK;
528     }
529
530     return HTMLElement_QI(&This->element.node, riid, ppv);
531 }
532
533 static HRESULT HTMLSelectElementImpl_put_disabled(HTMLDOMNode *iface, VARIANT_BOOL v)
534 {
535     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
536     return IHTMLSelectElement_put_disabled(&This->IHTMLSelectElement_iface, v);
537 }
538
539 static HRESULT HTMLSelectElementImpl_get_disabled(HTMLDOMNode *iface, VARIANT_BOOL *p)
540 {
541     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
542     return IHTMLSelectElement_get_disabled(&This->IHTMLSelectElement_iface, p);
543 }
544
545 #define DISPID_OPTIONCOL_0 MSHTML_DISPID_CUSTOM_MIN
546
547 static HRESULT HTMLSelectElement_get_dispid(HTMLDOMNode *iface, BSTR name, DWORD flags, DISPID *dispid)
548 {
549     const WCHAR *ptr;
550     DWORD idx = 0;
551
552     for(ptr = name; *ptr && isdigitW(*ptr); ptr++) {
553         idx = idx*10 + (*ptr-'0');
554         if(idx > MSHTML_CUSTOM_DISPID_CNT) {
555             WARN("too big idx\n");
556             return DISP_E_UNKNOWNNAME;
557         }
558     }
559     if(*ptr)
560         return DISP_E_UNKNOWNNAME;
561
562     *dispid = DISPID_OPTIONCOL_0 + idx;
563     return S_OK;
564 }
565
566 static HRESULT HTMLSelectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
567         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
568 {
569     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
570
571     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
572
573     switch(flags) {
574     case DISPATCH_PROPERTYGET: {
575         IDispatch *ret;
576         HRESULT hres;
577
578         hres = htmlselect_item(This, id-DISPID_OPTIONCOL_0, &ret);
579         if(FAILED(hres))
580             return hres;
581
582         if(ret) {
583             V_VT(res) = VT_DISPATCH;
584             V_DISPATCH(res) = ret;
585         }else {
586             V_VT(res) = VT_NULL;
587         }
588         break;
589     }
590
591     default:
592         FIXME("unimplemented flags %x\n", flags);
593         return E_NOTIMPL;
594     }
595
596     return S_OK;
597 }
598
599 static const NodeImplVtbl HTMLSelectElementImplVtbl = {
600     HTMLSelectElement_QI,
601     HTMLElement_destructor,
602     HTMLElement_clone,
603     HTMLElement_handle_event,
604     HTMLElement_get_attr_col,
605     NULL,
606     NULL,
607     HTMLSelectElementImpl_put_disabled,
608     HTMLSelectElementImpl_get_disabled,
609     NULL,
610     NULL,
611     HTMLSelectElement_get_dispid,
612     HTMLSelectElement_invoke
613 };
614
615 static const tid_t HTMLSelectElement_tids[] = {
616     HTMLELEMENT_TIDS,
617     IHTMLSelectElement_tid,
618     0
619 };
620
621 static dispex_static_data_t HTMLSelectElement_dispex = {
622     NULL,
623     DispHTMLSelectElement_tid,
624     NULL,
625     HTMLSelectElement_tids
626 };
627
628 HRESULT HTMLSelectElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
629 {
630     HTMLSelectElement *ret;
631     nsresult nsres;
632
633     ret = heap_alloc_zero(sizeof(HTMLSelectElement));
634     if(!ret)
635         return E_OUTOFMEMORY;
636
637     ret->IHTMLSelectElement_iface.lpVtbl = &HTMLSelectElementVtbl;
638     ret->element.node.vtbl = &HTMLSelectElementImplVtbl;
639
640     HTMLElement_Init(&ret->element, doc, nselem, &HTMLSelectElement_dispex);
641
642     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLSelectElement,
643                                              (void**)&ret->nsselect);
644
645     /* Share nsselect reference with nsnode */
646     assert(nsres == NS_OK && (nsIDOMNode*)ret->nsselect == ret->element.node.nsnode);
647     nsIDOMNode_Release(ret->element.node.nsnode);
648
649     *elem = &ret->element;
650     return S_OK;
651 }