xref: /reactos/dll/win32/mshtml/htmloption.c (revision 4561998a)
1 /*
2  * Copyright 2007 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 "mshtml_private.h"
20 
21 struct HTMLOptionElement {
22     HTMLElement element;
23 
24     IHTMLOptionElement IHTMLOptionElement_iface;
25 
26     nsIDOMHTMLOptionElement *nsoption;
27 };
28 
29 static inline HTMLOptionElement *impl_from_IHTMLOptionElement(IHTMLOptionElement *iface)
30 {
31     return CONTAINING_RECORD(iface, HTMLOptionElement, IHTMLOptionElement_iface);
32 }
33 
34 static HRESULT WINAPI HTMLOptionElement_QueryInterface(IHTMLOptionElement *iface,
35         REFIID riid, void **ppv)
36 {
37     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
38 
39     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
40 }
41 
42 static ULONG WINAPI HTMLOptionElement_AddRef(IHTMLOptionElement *iface)
43 {
44     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
45 
46     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
47 }
48 
49 static ULONG WINAPI HTMLOptionElement_Release(IHTMLOptionElement *iface)
50 {
51     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
52 
53     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
54 }
55 
56 static HRESULT WINAPI HTMLOptionElement_GetTypeInfoCount(IHTMLOptionElement *iface, UINT *pctinfo)
57 {
58     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
59     return IDispatchEx_GetTypeInfoCount(&This->element.node.event_target.dispex.IDispatchEx_iface, pctinfo);
60 }
61 
62 static HRESULT WINAPI HTMLOptionElement_GetTypeInfo(IHTMLOptionElement *iface, UINT iTInfo,
63                                               LCID lcid, ITypeInfo **ppTInfo)
64 {
65     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
66     return IDispatchEx_GetTypeInfo(&This->element.node.event_target.dispex.IDispatchEx_iface, iTInfo, lcid,
67             ppTInfo);
68 }
69 
70 static HRESULT WINAPI HTMLOptionElement_GetIDsOfNames(IHTMLOptionElement *iface, REFIID riid,
71                                                 LPOLESTR *rgszNames, UINT cNames,
72                                                 LCID lcid, DISPID *rgDispId)
73 {
74     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
75     return IDispatchEx_GetIDsOfNames(&This->element.node.event_target.dispex.IDispatchEx_iface, riid, rgszNames,
76             cNames, lcid, rgDispId);
77 }
78 
79 static HRESULT WINAPI HTMLOptionElement_Invoke(IHTMLOptionElement *iface, DISPID dispIdMember,
80                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
81                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
82 {
83     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
84     return IDispatchEx_Invoke(&This->element.node.event_target.dispex.IDispatchEx_iface, dispIdMember, riid,
85             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
86 }
87 
88 static HRESULT WINAPI HTMLOptionElement_put_selected(IHTMLOptionElement *iface, VARIANT_BOOL v)
89 {
90     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
91     nsresult nsres;
92 
93     TRACE("(%p)->(%x)\n", This, v);
94 
95     nsres = nsIDOMHTMLOptionElement_SetSelected(This->nsoption, v != VARIANT_FALSE);
96     if(NS_FAILED(nsres)) {
97         ERR("SetSelected failed: %08x\n", nsres);
98         return E_FAIL;
99     }
100 
101     return S_OK;
102 }
103 
104 static HRESULT WINAPI HTMLOptionElement_get_selected(IHTMLOptionElement *iface, VARIANT_BOOL *p)
105 {
106     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
107     cpp_bool selected;
108     nsresult nsres;
109 
110     TRACE("(%p)->(%p)\n", This, p);
111 
112     nsres = nsIDOMHTMLOptionElement_GetSelected(This->nsoption, &selected);
113     if(NS_FAILED(nsres)) {
114         ERR("GetSelected failed: %08x\n", nsres);
115         return E_FAIL;
116     }
117 
118     *p = selected ? VARIANT_TRUE : VARIANT_FALSE;
119     return S_OK;
120 }
121 
122 static HRESULT WINAPI HTMLOptionElement_put_value(IHTMLOptionElement *iface, BSTR v)
123 {
124     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
125     nsAString value_str;
126     nsresult nsres;
127 
128     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
129 
130     nsAString_InitDepend(&value_str, v);
131     nsres = nsIDOMHTMLOptionElement_SetValue(This->nsoption, &value_str);
132     nsAString_Finish(&value_str);
133     if(NS_FAILED(nsres))
134         ERR("SetValue failed: %08x\n", nsres);
135 
136     return S_OK;
137 }
138 
139 static HRESULT WINAPI HTMLOptionElement_get_value(IHTMLOptionElement *iface, BSTR *p)
140 {
141     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
142     nsAString value_str;
143     nsresult nsres;
144 
145     TRACE("(%p)->(%p)\n", This, p);
146 
147     nsAString_Init(&value_str, NULL);
148     nsres = nsIDOMHTMLOptionElement_GetValue(This->nsoption, &value_str);
149     return return_nsstr(nsres, &value_str, p);
150 }
151 
152 static HRESULT WINAPI HTMLOptionElement_put_defaultSelected(IHTMLOptionElement *iface, VARIANT_BOOL v)
153 {
154     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
155     cpp_bool val, selected;
156     nsresult nsres;
157 
158     TRACE("(%p)->(%x)\n", This, v);
159 
160     val = (v == VARIANT_TRUE);
161 
162     nsres = nsIDOMHTMLOptionElement_GetSelected(This->nsoption, &selected);
163     if(NS_FAILED(nsres)) {
164         ERR("GetSelected failed: %08x\n", nsres);
165         return E_FAIL;
166     }
167 
168     nsres = nsIDOMHTMLOptionElement_SetDefaultSelected(This->nsoption, val);
169     if(NS_FAILED(nsres)) {
170         ERR("SetDefaultSelected failed: %08x\n", nsres);
171         return E_FAIL;
172     }
173 
174     if(val != selected) {
175         nsres = nsIDOMHTMLOptionElement_SetSelected(This->nsoption, selected); /* WinAPI will reserve selected property */
176         if(NS_FAILED(nsres)) {
177             ERR("SetSelected failed: %08x\n", nsres);
178             return E_FAIL;
179         }
180     }
181 
182     return S_OK;
183 }
184 
185 static HRESULT WINAPI HTMLOptionElement_get_defaultSelected(IHTMLOptionElement *iface, VARIANT_BOOL *p)
186 {
187     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
188     cpp_bool val;
189     nsresult nsres;
190 
191     TRACE("(%p)->(%p)\n", This, p);
192     if(!p)
193         return E_POINTER;
194     nsres = nsIDOMHTMLOptionElement_GetDefaultSelected(This->nsoption, &val);
195     if(NS_FAILED(nsres)) {
196         ERR("GetDefaultSelected failed: %08x\n", nsres);
197         return E_FAIL;
198     }
199 
200     *p = val ? VARIANT_TRUE : VARIANT_FALSE;
201     return S_OK;
202 }
203 
204 static HRESULT WINAPI HTMLOptionElement_put_index(IHTMLOptionElement *iface, LONG v)
205 {
206     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
207     FIXME("(%p)->(%d)\n", This, v);
208     return E_NOTIMPL;
209 }
210 
211 static HRESULT WINAPI HTMLOptionElement_get_index(IHTMLOptionElement *iface, LONG *p)
212 {
213     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
214     LONG val;
215     nsresult nsres;
216 
217     TRACE("(%p)->(%p)\n", This, p);
218 
219     if(!p)
220         return E_INVALIDARG;
221 
222     nsres = nsIDOMHTMLOptionElement_GetIndex(This->nsoption, &val);
223     if(NS_FAILED(nsres)) {
224         ERR("GetIndex failed: %08x\n", nsres);
225         return E_FAIL;
226     }
227     *p = val;
228     return S_OK;
229 }
230 
231 static HRESULT WINAPI HTMLOptionElement_put_text(IHTMLOptionElement *iface, BSTR v)
232 {
233     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
234     nsIDOMText *text_node;
235     nsAString text_str;
236     nsIDOMNode *tmp;
237     nsresult nsres;
238 
239     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
240 
241     if(!This->element.node.doc->nsdoc) {
242         WARN("NULL nsdoc\n");
243         return E_UNEXPECTED;
244     }
245 
246     while(1) {
247         nsIDOMNode *child;
248 
249         nsres = nsIDOMHTMLElement_GetFirstChild(This->element.nselem, &child);
250         if(NS_FAILED(nsres) || !child)
251             break;
252 
253         nsres = nsIDOMHTMLElement_RemoveChild(This->element.nselem, child, &tmp);
254         nsIDOMNode_Release(child);
255         if(NS_SUCCEEDED(nsres)) {
256             nsIDOMNode_Release(tmp);
257         }else {
258             ERR("RemoveChild failed: %08x\n", nsres);
259             break;
260         }
261     }
262 
263     nsAString_InitDepend(&text_str, v);
264     nsres = nsIDOMHTMLDocument_CreateTextNode(This->element.node.doc->nsdoc, &text_str, &text_node);
265     nsAString_Finish(&text_str);
266     if(NS_FAILED(nsres)) {
267         ERR("CreateTextNode failed: %08x\n", nsres);
268         return E_FAIL;
269     }
270 
271     nsres = nsIDOMHTMLElement_AppendChild(This->element.nselem, (nsIDOMNode*)text_node, &tmp);
272     if(NS_SUCCEEDED(nsres))
273         nsIDOMNode_Release(tmp);
274     else
275         ERR("AppendChild failed: %08x\n", nsres);
276 
277     return S_OK;
278 }
279 
280 static HRESULT WINAPI HTMLOptionElement_get_text(IHTMLOptionElement *iface, BSTR *p)
281 {
282     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
283     nsAString text_str;
284     nsresult nsres;
285 
286     TRACE("(%p)->(%p)\n", This, p);
287 
288     nsAString_Init(&text_str, NULL);
289     nsres = nsIDOMHTMLOptionElement_GetText(This->nsoption, &text_str);
290     return return_nsstr(nsres, &text_str, p);
291 }
292 
293 static HRESULT WINAPI HTMLOptionElement_get_form(IHTMLOptionElement *iface, IHTMLFormElement **p)
294 {
295     HTMLOptionElement *This = impl_from_IHTMLOptionElement(iface);
296     nsIDOMHTMLFormElement *nsform;
297     nsIDOMNode *form_node;
298     HTMLDOMNode *node;
299     HRESULT hres;
300     nsresult nsres;
301 
302     TRACE("(%p)->(%p)\n", This, p);
303 
304     if(!p)
305         return E_POINTER;
306 
307     nsres = nsIDOMHTMLOptionElement_GetForm(This->nsoption, &nsform);
308     if (NS_FAILED(nsres)) {
309         ERR("GetForm failed: %08x, nsform: %p\n", nsres, nsform);
310         *p = NULL;
311         return E_FAIL;
312     }
313     if (nsform == NULL) {
314         TRACE("nsform not found\n");
315         *p = NULL;
316         return S_OK;
317     }
318 
319     nsres = nsIDOMHTMLFormElement_QueryInterface(nsform, &IID_nsIDOMNode, (void**)&form_node);
320     nsIDOMHTMLFormElement_Release(nsform);
321     assert(nsres == NS_OK);
322 
323     hres = get_node(This->element.node.doc, form_node, TRUE, &node);
324     nsIDOMNode_Release(form_node);
325     if (FAILED(hres))
326         return hres;
327 
328     hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface, &IID_IHTMLElement, (void**)p);
329 
330     node_release(node);
331     return hres;
332 }
333 
334 static const IHTMLOptionElementVtbl HTMLOptionElementVtbl = {
335     HTMLOptionElement_QueryInterface,
336     HTMLOptionElement_AddRef,
337     HTMLOptionElement_Release,
338     HTMLOptionElement_GetTypeInfoCount,
339     HTMLOptionElement_GetTypeInfo,
340     HTMLOptionElement_GetIDsOfNames,
341     HTMLOptionElement_Invoke,
342     HTMLOptionElement_put_selected,
343     HTMLOptionElement_get_selected,
344     HTMLOptionElement_put_value,
345     HTMLOptionElement_get_value,
346     HTMLOptionElement_put_defaultSelected,
347     HTMLOptionElement_get_defaultSelected,
348     HTMLOptionElement_put_index,
349     HTMLOptionElement_get_index,
350     HTMLOptionElement_put_text,
351     HTMLOptionElement_get_text,
352     HTMLOptionElement_get_form
353 };
354 
355 static inline HTMLOptionElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
356 {
357     return CONTAINING_RECORD(iface, HTMLOptionElement, element.node);
358 }
359 
360 static HRESULT HTMLOptionElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
361 {
362     HTMLOptionElement *This = impl_from_HTMLDOMNode(iface);
363 
364     *ppv = NULL;
365 
366     if(IsEqualGUID(&IID_IUnknown, riid)) {
367         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
368         *ppv = &This->IHTMLOptionElement_iface;
369     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
370         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
371         *ppv = &This->IHTMLOptionElement_iface;
372     }else if(IsEqualGUID(&IID_IHTMLOptionElement, riid)) {
373         TRACE("(%p)->(IID_IHTMLOptionElement %p)\n", This, ppv);
374         *ppv = &This->IHTMLOptionElement_iface;
375     }
376 
377     if(*ppv) {
378         IUnknown_AddRef((IUnknown*)*ppv);
379         return S_OK;
380     }
381 
382     return HTMLElement_QI(&This->element.node, riid, ppv);
383 }
384 
385 static void HTMLOptionElement_traverse(HTMLDOMNode *iface, nsCycleCollectionTraversalCallback *cb)
386 {
387     HTMLOptionElement *This = impl_from_HTMLDOMNode(iface);
388 
389     if(This->nsoption)
390         note_cc_edge((nsISupports*)This->nsoption, "This->nsoption", cb);
391 }
392 
393 static void HTMLOptionElement_unlink(HTMLDOMNode *iface)
394 {
395     HTMLOptionElement *This = impl_from_HTMLDOMNode(iface);
396 
397     if(This->nsoption) {
398         nsIDOMHTMLOptionElement *nsoption = This->nsoption;
399 
400         This->nsoption = NULL;
401         nsIDOMHTMLOptionElement_Release(nsoption);
402     }
403 }
404 
405 static const NodeImplVtbl HTMLOptionElementImplVtbl = {
406     HTMLOptionElement_QI,
407     HTMLElement_destructor,
408     HTMLElement_cpc,
409     HTMLElement_clone,
410     HTMLElement_handle_event,
411     HTMLElement_get_attr_col,
412     NULL,
413     NULL,
414     NULL,
415     NULL,
416     NULL,
417     NULL,
418     NULL,
419     NULL,
420     NULL,
421     HTMLOptionElement_traverse,
422     HTMLOptionElement_unlink
423 };
424 
425 static const tid_t HTMLOptionElement_iface_tids[] = {
426     HTMLELEMENT_TIDS,
427     IHTMLOptionElement_tid,
428     0
429 };
430 static dispex_static_data_t HTMLOptionElement_dispex = {
431     NULL,
432     DispHTMLOptionElement_tid,
433     NULL,
434     HTMLOptionElement_iface_tids
435 };
436 
437 HRESULT HTMLOptionElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
438 {
439     HTMLOptionElement *ret;
440     nsresult nsres;
441 
442     ret = heap_alloc_zero(sizeof(HTMLOptionElement));
443     if(!ret)
444         return E_OUTOFMEMORY;
445 
446     ret->IHTMLOptionElement_iface.lpVtbl = &HTMLOptionElementVtbl;
447     ret->element.node.vtbl = &HTMLOptionElementImplVtbl;
448 
449     HTMLElement_Init(&ret->element, doc, nselem, &HTMLOptionElement_dispex);
450 
451     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLOptionElement, (void**)&ret->nsoption);
452     assert(nsres == NS_OK);
453 
454     *elem = &ret->element;
455     return S_OK;
456 }
457 
458 static inline HTMLOptionElementFactory *impl_from_IHTMLOptionElementFactory(IHTMLOptionElementFactory *iface)
459 {
460     return CONTAINING_RECORD(iface, HTMLOptionElementFactory, IHTMLOptionElementFactory_iface);
461 }
462 
463 static HRESULT WINAPI HTMLOptionElementFactory_QueryInterface(IHTMLOptionElementFactory *iface,
464                                                               REFIID riid, void **ppv)
465 {
466     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
467 
468     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
469 
470     if(IsEqualGUID(&IID_IUnknown, riid)) {
471         *ppv = &This->IHTMLOptionElementFactory_iface;
472     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
473         *ppv = &This->IHTMLOptionElementFactory_iface;
474     }else if(IsEqualGUID(&IID_IHTMLOptionElementFactory, riid)) {
475         *ppv = &This->IHTMLOptionElementFactory_iface;
476     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
477         return *ppv ? S_OK : E_NOINTERFACE;
478     }else {
479         *ppv = NULL;
480         WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
481         return E_NOINTERFACE;
482     }
483 
484     IUnknown_AddRef((IUnknown*)*ppv);
485     return S_OK;
486 }
487 
488 static ULONG WINAPI HTMLOptionElementFactory_AddRef(IHTMLOptionElementFactory *iface)
489 {
490     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
491     LONG ref = InterlockedIncrement(&This->ref);
492 
493     TRACE("(%p) ref=%d\n", This, ref);
494 
495     return ref;
496 }
497 
498 static ULONG WINAPI HTMLOptionElementFactory_Release(IHTMLOptionElementFactory *iface)
499 {
500     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
501     LONG ref = InterlockedDecrement(&This->ref);
502 
503     TRACE("(%p) ref=%d\n", This, ref);
504 
505     if(!ref) {
506         release_dispex(&This->dispex);
507         heap_free(This);
508     }
509 
510     return ref;
511 }
512 
513 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfoCount(IHTMLOptionElementFactory *iface, UINT *pctinfo)
514 {
515     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
516     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
517 }
518 
519 static HRESULT WINAPI HTMLOptionElementFactory_GetTypeInfo(IHTMLOptionElementFactory *iface, UINT iTInfo,
520                                               LCID lcid, ITypeInfo **ppTInfo)
521 {
522     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
523     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
524 }
525 
526 static HRESULT WINAPI HTMLOptionElementFactory_GetIDsOfNames(IHTMLOptionElementFactory *iface, REFIID riid,
527                                                 LPOLESTR *rgszNames, UINT cNames,
528                                                 LCID lcid, DISPID *rgDispId)
529 {
530     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
531     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames, lcid, rgDispId);
532 }
533 
534 static HRESULT WINAPI HTMLOptionElementFactory_Invoke(IHTMLOptionElementFactory *iface, DISPID dispIdMember,
535                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
536                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
537 {
538     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
539     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags, pDispParams,
540             pVarResult, pExcepInfo, puArgErr);
541 }
542 
543 static HRESULT WINAPI HTMLOptionElementFactory_create(IHTMLOptionElementFactory *iface,
544         VARIANT text, VARIANT value, VARIANT defaultselected, VARIANT selected,
545         IHTMLOptionElement **optelem)
546 {
547     HTMLOptionElementFactory *This = impl_from_IHTMLOptionElementFactory(iface);
548     nsIDOMHTMLElement *nselem;
549     HTMLDOMNode *node;
550     HRESULT hres;
551 
552     static const PRUnichar optionW[] = {'O','P','T','I','O','N',0};
553 
554     TRACE("(%p)->(%s %s %s %s %p)\n", This, debugstr_variant(&text), debugstr_variant(&value),
555           debugstr_variant(&defaultselected), debugstr_variant(&selected), optelem);
556 
557     if(!This->window || !This->window->doc) {
558         WARN("NULL doc\n");
559         return E_UNEXPECTED;
560     }
561 
562     *optelem = NULL;
563 
564     hres = create_nselem(This->window->doc, optionW, &nselem);
565     if(FAILED(hres))
566         return hres;
567 
568     hres = get_node(This->window->doc, (nsIDOMNode*)nselem, TRUE, &node);
569     nsIDOMHTMLElement_Release(nselem);
570     if(FAILED(hres))
571         return hres;
572 
573     hres = IHTMLDOMNode_QueryInterface(&node->IHTMLDOMNode_iface,
574             &IID_IHTMLOptionElement, (void**)optelem);
575     node_release(node);
576 
577     if(V_VT(&text) == VT_BSTR)
578         IHTMLOptionElement_put_text(*optelem, V_BSTR(&text));
579     else if(V_VT(&text) != VT_EMPTY)
580         FIXME("Unsupported text %s\n", debugstr_variant(&text));
581 
582     if(V_VT(&value) == VT_BSTR)
583         IHTMLOptionElement_put_value(*optelem, V_BSTR(&value));
584     else if(V_VT(&value) != VT_EMPTY)
585         FIXME("Unsupported value %s\n", debugstr_variant(&value));
586 
587     if(V_VT(&defaultselected) != VT_EMPTY)
588         FIXME("Unsupported defaultselected %s\n", debugstr_variant(&defaultselected));
589     if(V_VT(&selected) != VT_EMPTY)
590         FIXME("Unsupported selected %s\n", debugstr_variant(&selected));
591 
592     return S_OK;
593 }
594 
595 static const IHTMLOptionElementFactoryVtbl HTMLOptionElementFactoryVtbl = {
596     HTMLOptionElementFactory_QueryInterface,
597     HTMLOptionElementFactory_AddRef,
598     HTMLOptionElementFactory_Release,
599     HTMLOptionElementFactory_GetTypeInfoCount,
600     HTMLOptionElementFactory_GetTypeInfo,
601     HTMLOptionElementFactory_GetIDsOfNames,
602     HTMLOptionElementFactory_Invoke,
603     HTMLOptionElementFactory_create
604 };
605 
606 static const tid_t HTMLOptionElementFactory_iface_tids[] = {
607     IHTMLOptionElementFactory_tid,
608     0
609 };
610 
611 static dispex_static_data_t HTMLOptionElementFactory_dispex = {
612     NULL,
613     IHTMLOptionElementFactory_tid,
614     NULL,
615     HTMLOptionElementFactory_iface_tids
616 };
617 
618 HRESULT HTMLOptionElementFactory_Create(HTMLInnerWindow *window, HTMLOptionElementFactory **ret_ptr)
619 {
620     HTMLOptionElementFactory *ret;
621 
622     ret = heap_alloc(sizeof(*ret));
623     if(!ret)
624         return E_OUTOFMEMORY;
625 
626     ret->IHTMLOptionElementFactory_iface.lpVtbl = &HTMLOptionElementFactoryVtbl;
627     ret->ref = 1;
628     ret->window = window;
629 
630     init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLOptionElementFactory_iface,
631             &HTMLOptionElementFactory_dispex);
632 
633     *ret_ptr = ret;
634     return S_OK;
635 }
636