ddraw: Fix a typo.
[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     IHTMLSelectElement IHTMLSelectElement_iface;
39
40     nsIDOMHTMLSelectElement *nsselect;
41 } HTMLSelectElement;
42
43 static inline HTMLSelectElement *impl_from_IHTMLSelectElement(IHTMLSelectElement *iface)
44 {
45     return CONTAINING_RECORD(iface, HTMLSelectElement, IHTMLSelectElement_iface);
46 }
47
48 static HRESULT htmlselect_item(HTMLSelectElement *This, int i, IDispatch **ret)
49 {
50     nsIDOMHTMLOptionsCollection *nscol;
51     nsIDOMNode *nsnode;
52     nsresult nsres;
53     HRESULT hres;
54
55     nsres = nsIDOMHTMLSelectElement_GetOptions(This->nsselect, &nscol);
56     if(NS_FAILED(nsres)) {
57         ERR("GetOptions failed: %08x\n", nsres);
58         return E_FAIL;
59     }
60
61     nsres = nsIDOMHTMLOptionsCollection_Item(nscol, i, &nsnode);
62     nsIDOMHTMLOptionsCollection_Release(nscol);
63     if(NS_FAILED(nsres)) {
64         ERR("Item failed: %08x\n", nsres);
65         return E_FAIL;
66     }
67
68     if(nsnode) {
69         HTMLDOMNode *node;
70
71         hres = get_node(This->element.node.doc, nsnode, TRUE, &node);
72         nsIDOMNode_Release(nsnode);
73         if(FAILED(hres))
74             return hres;
75
76         IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
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     const PRUnichar *type;
270     nsAString type_str;
271     nsresult nsres;
272     HRESULT hres = S_OK;
273
274     TRACE("(%p)->(%p)\n", This, p);
275
276     nsAString_Init(&type_str, NULL);
277     nsres = nsIDOMHTMLSelectElement_GetType(This->nsselect, &type_str);
278     if(NS_SUCCEEDED(nsres)) {
279         nsAString_GetData(&type_str, &type);
280         *p = *type ? SysAllocString(type) : NULL;
281     }else {
282         ERR("GetType failed: %08x\n", nsres);
283         hres = E_FAIL;
284     }
285
286     nsAString_Finish(&type_str);
287
288     return hres;
289 }
290
291 static HRESULT WINAPI HTMLSelectElement_put_value(IHTMLSelectElement *iface, BSTR v)
292 {
293     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
294     nsAString value_str;
295     nsresult nsres;
296
297     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
298
299     nsAString_InitDepend(&value_str, v);
300     nsres = nsIDOMHTMLSelectElement_SetValue(This->nsselect, &value_str);
301     nsAString_Finish(&value_str);
302     if(NS_FAILED(nsres))
303         ERR("SetValue failed: %08x\n", nsres);
304
305     return S_OK;
306 }
307
308 static HRESULT WINAPI HTMLSelectElement_get_value(IHTMLSelectElement *iface, BSTR *p)
309 {
310     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
311     nsAString value_str;
312     const PRUnichar *value = NULL;
313     nsresult nsres;
314
315     TRACE("(%p)->(%p)\n", This, p);
316
317     nsAString_Init(&value_str, NULL);
318
319     nsres = nsIDOMHTMLSelectElement_GetValue(This->nsselect, &value_str);
320     if(NS_SUCCEEDED(nsres)) {
321         nsAString_GetData(&value_str, &value);
322         *p = *value ? SysAllocString(value) : NULL;
323     }else {
324         ERR("GetValue failed: %08x\n", nsres);
325     }
326
327     nsAString_Finish(&value_str);
328
329     TRACE("value=%s\n", debugstr_w(*p));
330     return S_OK;
331 }
332
333 static HRESULT WINAPI HTMLSelectElement_put_disabled(IHTMLSelectElement *iface, VARIANT_BOOL v)
334 {
335     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
336     nsresult nsres;
337
338     TRACE("(%p)->(%x)\n", This, v);
339
340     nsres = nsIDOMHTMLSelectElement_SetDisabled(This->nsselect, v != VARIANT_FALSE);
341     if(NS_FAILED(nsres)) {
342         ERR("SetDisabled failed: %08x\n", nsres);
343         return E_FAIL;
344     }
345
346     return S_OK;
347 }
348
349 static HRESULT WINAPI HTMLSelectElement_get_disabled(IHTMLSelectElement *iface, VARIANT_BOOL *p)
350 {
351     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
352     PRBool disabled = FALSE;
353     nsresult nsres;
354
355     TRACE("(%p)->(%p)\n", This, p);
356
357     nsres = nsIDOMHTMLSelectElement_GetDisabled(This->nsselect, &disabled);
358     if(NS_FAILED(nsres)) {
359         ERR("GetDisabled failed: %08x\n", nsres);
360         return E_FAIL;
361     }
362
363     *p = disabled ? VARIANT_TRUE : VARIANT_FALSE;
364     return S_OK;
365 }
366
367 static HRESULT WINAPI HTMLSelectElement_get_form(IHTMLSelectElement *iface, IHTMLFormElement **p)
368 {
369     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
370     FIXME("(%p)->(%p)\n", This, p);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI HTMLSelectElement_add(IHTMLSelectElement *iface, IHTMLElement *element,
375                                             VARIANT before)
376 {
377     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
378     nsIWritableVariant *nsvariant;
379     HTMLElement *element_obj;
380     nsresult nsres;
381
382     TRACE("(%p)->(%p %s)\n", This, element, debugstr_variant(&before));
383
384     element_obj = unsafe_impl_from_IHTMLElement(element);
385     if(!element_obj) {
386         FIXME("External IHTMLElement implementation?\n");
387         return E_INVALIDARG;
388     }
389
390     nsvariant = create_nsvariant();
391     if(!nsvariant)
392         return E_FAIL;
393
394     switch(V_VT(&before)) {
395     case VT_EMPTY:
396         nsres = nsIWritableVariant_SetAsEmpty(nsvariant);
397         break;
398     case VT_I2:
399         nsres = nsIWritableVariant_SetAsInt16(nsvariant, V_I2(&before));
400         break;
401     default:
402         FIXME("unhandled before %s\n", debugstr_variant(&before));
403         nsIWritableVariant_Release(nsvariant);
404         return E_NOTIMPL;
405     }
406
407     if(NS_SUCCEEDED(nsres))
408         nsres = nsIDOMHTMLSelectElement_Add(This->nsselect, element_obj->nselem, (nsIVariant*)nsvariant);
409     nsIWritableVariant_Release(nsvariant);
410     if(NS_FAILED(nsres)) {
411         ERR("Add failed: %08x\n", nsres);
412         return E_FAIL;
413     }
414
415     return S_OK;
416 }
417
418 static HRESULT WINAPI HTMLSelectElement_remove(IHTMLSelectElement *iface, LONG index)
419 {
420     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
421     FIXME("(%p)->(%d)\n", This, index);
422     return E_NOTIMPL;
423 }
424
425 static HRESULT WINAPI HTMLSelectElement_put_length(IHTMLSelectElement *iface, LONG v)
426 {
427     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
428     nsresult nsres;
429
430     TRACE("(%p)->(%d)\n", This, v);
431
432     nsres = nsIDOMHTMLSelectElement_SetLength(This->nsselect, v);
433     if(NS_FAILED(nsres))
434         ERR("SetLength failed: %08x\n", nsres);
435
436     return S_OK;
437 }
438
439 static HRESULT WINAPI HTMLSelectElement_get_length(IHTMLSelectElement *iface, LONG *p)
440 {
441     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
442     PRUint32 length = 0;
443     nsresult nsres;
444
445     TRACE("(%p)->(%p)\n", This, p);
446
447     nsres = nsIDOMHTMLSelectElement_GetLength(This->nsselect, &length);
448     if(NS_FAILED(nsres))
449         ERR("GetLength failed: %08x\n", nsres);
450
451     *p = length;
452
453     TRACE("ret %d\n", *p);
454     return S_OK;
455 }
456
457 static HRESULT WINAPI HTMLSelectElement_get__newEnum(IHTMLSelectElement *iface, IUnknown **p)
458 {
459     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
460     FIXME("(%p)->(%p)\n", This, p);
461     return E_NOTIMPL;
462 }
463
464 static HRESULT WINAPI HTMLSelectElement_item(IHTMLSelectElement *iface, VARIANT name,
465                                              VARIANT index, IDispatch **pdisp)
466 {
467     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
468
469     TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
470
471     if(!pdisp)
472         return E_POINTER;
473     *pdisp = NULL;
474
475     if(V_VT(&name) == VT_I4) {
476         if(V_I4(&name) < 0)
477             return E_INVALIDARG;
478         return htmlselect_item(This, V_I4(&name), pdisp);
479     }
480
481     FIXME("Unsupported args\n");
482     return E_NOTIMPL;
483 }
484
485 static HRESULT WINAPI HTMLSelectElement_tags(IHTMLSelectElement *iface, VARIANT tagName,
486                                              IDispatch **pdisp)
487 {
488     HTMLSelectElement *This = impl_from_IHTMLSelectElement(iface);
489     FIXME("(%p)->(v %p)\n", This, pdisp);
490     return E_NOTIMPL;
491 }
492
493 static const IHTMLSelectElementVtbl HTMLSelectElementVtbl = {
494     HTMLSelectElement_QueryInterface,
495     HTMLSelectElement_AddRef,
496     HTMLSelectElement_Release,
497     HTMLSelectElement_GetTypeInfoCount,
498     HTMLSelectElement_GetTypeInfo,
499     HTMLSelectElement_GetIDsOfNames,
500     HTMLSelectElement_Invoke,
501     HTMLSelectElement_put_size,
502     HTMLSelectElement_get_size,
503     HTMLSelectElement_put_multiple,
504     HTMLSelectElement_get_multiple,
505     HTMLSelectElement_put_name,
506     HTMLSelectElement_get_name,
507     HTMLSelectElement_get_options,
508     HTMLSelectElement_put_onchange,
509     HTMLSelectElement_get_onchange,
510     HTMLSelectElement_put_selectedIndex,
511     HTMLSelectElement_get_selectedIndex,
512     HTMLSelectElement_get_type,
513     HTMLSelectElement_put_value,
514     HTMLSelectElement_get_value,
515     HTMLSelectElement_put_disabled,
516     HTMLSelectElement_get_disabled,
517     HTMLSelectElement_get_form,
518     HTMLSelectElement_add,
519     HTMLSelectElement_remove,
520     HTMLSelectElement_put_length,
521     HTMLSelectElement_get_length,
522     HTMLSelectElement_get__newEnum,
523     HTMLSelectElement_item,
524     HTMLSelectElement_tags
525 };
526
527 static inline HTMLSelectElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
528 {
529     return CONTAINING_RECORD(iface, HTMLSelectElement, element.node);
530 }
531
532 static HRESULT HTMLSelectElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
533 {
534     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
535
536     *ppv = NULL;
537
538     if(IsEqualGUID(&IID_IUnknown, riid)) {
539         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
540         *ppv = &This->IHTMLSelectElement_iface;
541     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
542         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
543         *ppv = &This->IHTMLSelectElement_iface;
544     }else if(IsEqualGUID(&IID_IHTMLSelectElement, riid)) {
545         TRACE("(%p)->(IID_IHTMLSelectElement %p)\n", This, ppv);
546         *ppv = &This->IHTMLSelectElement_iface;
547     }
548
549     if(*ppv) {
550         IUnknown_AddRef((IUnknown*)*ppv);
551         return S_OK;
552     }
553
554     return HTMLElement_QI(&This->element.node, riid, ppv);
555 }
556
557 static void HTMLSelectElement_destructor(HTMLDOMNode *iface)
558 {
559     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
560
561     nsIDOMHTMLSelectElement_Release(This->nsselect);
562
563     HTMLElement_destructor(&This->element.node);
564 }
565
566 static HRESULT HTMLSelectElementImpl_put_disabled(HTMLDOMNode *iface, VARIANT_BOOL v)
567 {
568     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
569     return IHTMLSelectElement_put_disabled(&This->IHTMLSelectElement_iface, v);
570 }
571
572 static HRESULT HTMLSelectElementImpl_get_disabled(HTMLDOMNode *iface, VARIANT_BOOL *p)
573 {
574     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
575     return IHTMLSelectElement_get_disabled(&This->IHTMLSelectElement_iface, p);
576 }
577
578 #define DISPID_OPTIONCOL_0 MSHTML_DISPID_CUSTOM_MIN
579
580 static HRESULT HTMLSelectElement_get_dispid(HTMLDOMNode *iface, BSTR name, DWORD flags, DISPID *dispid)
581 {
582     const WCHAR *ptr;
583     DWORD idx = 0;
584
585     for(ptr = name; *ptr && isdigitW(*ptr); ptr++) {
586         idx = idx*10 + (*ptr-'0');
587         if(idx > MSHTML_CUSTOM_DISPID_CNT) {
588             WARN("too big idx\n");
589             return DISP_E_UNKNOWNNAME;
590         }
591     }
592     if(*ptr)
593         return DISP_E_UNKNOWNNAME;
594
595     *dispid = DISPID_OPTIONCOL_0 + idx;
596     return S_OK;
597 }
598
599 static HRESULT HTMLSelectElement_invoke(HTMLDOMNode *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
600         VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
601 {
602     HTMLSelectElement *This = impl_from_HTMLDOMNode(iface);
603
604     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
605
606     switch(flags) {
607     case DISPATCH_PROPERTYGET: {
608         IDispatch *ret;
609         HRESULT hres;
610
611         hres = htmlselect_item(This, id-DISPID_OPTIONCOL_0, &ret);
612         if(FAILED(hres))
613             return hres;
614
615         if(ret) {
616             V_VT(res) = VT_DISPATCH;
617             V_DISPATCH(res) = ret;
618         }else {
619             V_VT(res) = VT_NULL;
620         }
621         break;
622     }
623
624     default:
625         FIXME("unimplemented flags %x\n", flags);
626         return E_NOTIMPL;
627     }
628
629     return S_OK;
630 }
631
632 static const NodeImplVtbl HTMLSelectElementImplVtbl = {
633     HTMLSelectElement_QI,
634     HTMLSelectElement_destructor,
635     HTMLElement_clone,
636     HTMLElement_get_attr_col,
637     NULL,
638     NULL,
639     NULL,
640     HTMLSelectElementImpl_put_disabled,
641     HTMLSelectElementImpl_get_disabled,
642     NULL,
643     NULL,
644     HTMLSelectElement_get_dispid,
645     HTMLSelectElement_invoke
646 };
647
648 static const tid_t HTMLSelectElement_tids[] = {
649     HTMLELEMENT_TIDS,
650     IHTMLSelectElement_tid,
651     0
652 };
653
654 static dispex_static_data_t HTMLSelectElement_dispex = {
655     NULL,
656     DispHTMLSelectElement_tid,
657     NULL,
658     HTMLSelectElement_tids
659 };
660
661 HRESULT HTMLSelectElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
662 {
663     HTMLSelectElement *ret;
664     nsresult nsres;
665
666     ret = heap_alloc_zero(sizeof(HTMLSelectElement));
667     if(!ret)
668         return E_OUTOFMEMORY;
669
670     ret->IHTMLSelectElement_iface.lpVtbl = &HTMLSelectElementVtbl;
671     ret->element.node.vtbl = &HTMLSelectElementImplVtbl;
672
673     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLSelectElement,
674                                              (void**)&ret->nsselect);
675     if(NS_FAILED(nsres)) {
676         ERR("Could not get nsIDOMHTMLSelectElement interfce: %08x\n", nsres);
677         heap_free(ret);
678         return E_FAIL;
679     }
680
681     HTMLElement_Init(&ret->element, doc, nselem, &HTMLSelectElement_dispex);
682
683     *elem = &ret->element;
684     return S_OK;
685 }