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