wininet: Keep handles invalid but reserved in InternetCloseHandle.
[wine] / dlls / mshtml / htmlform.c
1 /*
2  * Copyright 2009 Andrew Eikum 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
32 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
33
34 struct HTMLFormElement {
35     HTMLElement element;
36
37     IHTMLFormElement IHTMLFormElement_iface;
38
39     nsIDOMHTMLFormElement *nsform;
40 };
41
42 static HRESULT htmlform_item(HTMLFormElement *This, int i, IDispatch **ret)
43 {
44     nsIDOMHTMLCollection *elements;
45     nsIDOMNode *item;
46     HTMLDOMNode *node;
47     nsresult nsres;
48     HRESULT hres;
49
50     nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements);
51     if(NS_FAILED(nsres)) {
52         FIXME("GetElements failed: 0x%08x\n", nsres);
53         return E_FAIL;
54     }
55
56     nsres = nsIDOMHTMLCollection_Item(elements, i, &item);
57     nsIDOMHTMLCollection_Release(elements);
58     if(NS_FAILED(nsres)) {
59         FIXME("Item failed: 0x%08x\n", nsres);
60         return E_FAIL;
61     }
62
63     if(item) {
64         hres = get_node(This->element.node.doc, item, TRUE, &node);
65         if(FAILED(hres))
66             return hres;
67
68         IHTMLDOMNode_AddRef(&node->IHTMLDOMNode_iface);
69         nsIDOMNode_Release(item);
70         *ret = (IDispatch*)&node->IHTMLDOMNode_iface;
71     }else {
72         *ret = NULL;
73     }
74
75     return S_OK;
76 }
77
78 static inline HTMLFormElement *impl_from_IHTMLFormElement(IHTMLFormElement *iface)
79 {
80     return CONTAINING_RECORD(iface, HTMLFormElement, IHTMLFormElement_iface);
81 }
82
83 static HRESULT WINAPI HTMLFormElement_QueryInterface(IHTMLFormElement *iface,
84         REFIID riid, void **ppv)
85 {
86     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
87
88     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
89 }
90
91 static ULONG WINAPI HTMLFormElement_AddRef(IHTMLFormElement *iface)
92 {
93     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
94
95     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
96 }
97
98 static ULONG WINAPI HTMLFormElement_Release(IHTMLFormElement *iface)
99 {
100     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
101
102     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
103 }
104
105 static HRESULT WINAPI HTMLFormElement_GetTypeInfoCount(IHTMLFormElement *iface, UINT *pctinfo)
106 {
107     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
108     return IDispatchEx_GetTypeInfoCount(&This->element.node.dispex.IDispatchEx_iface, pctinfo);
109 }
110
111 static HRESULT WINAPI HTMLFormElement_GetTypeInfo(IHTMLFormElement *iface, UINT iTInfo,
112                                               LCID lcid, ITypeInfo **ppTInfo)
113 {
114     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
115     return IDispatchEx_GetTypeInfo(&This->element.node.dispex.IDispatchEx_iface, iTInfo, lcid,
116             ppTInfo);
117 }
118
119 static HRESULT WINAPI HTMLFormElement_GetIDsOfNames(IHTMLFormElement *iface, REFIID riid,
120                                                 LPOLESTR *rgszNames, UINT cNames,
121                                                 LCID lcid, DISPID *rgDispId)
122 {
123     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
124     return IDispatchEx_GetIDsOfNames(&This->element.node.dispex.IDispatchEx_iface, riid, rgszNames,
125             cNames, lcid, rgDispId);
126 }
127
128 static HRESULT WINAPI HTMLFormElement_Invoke(IHTMLFormElement *iface, DISPID dispIdMember,
129                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
130                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
131 {
132     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
133     return IDispatchEx_Invoke(&This->element.node.dispex.IDispatchEx_iface, dispIdMember, riid,
134             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
135 }
136
137 static HRESULT WINAPI HTMLFormElement_put_action(IHTMLFormElement *iface, BSTR v)
138 {
139     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
140     nsAString action_str;
141     nsresult nsres;
142
143     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
144
145     nsAString_InitDepend(&action_str, v);
146     nsres = nsIDOMHTMLFormElement_SetAction(This->nsform, &action_str);
147     nsAString_Finish(&action_str);
148     if(NS_FAILED(nsres)) {
149         ERR("SetAction failed: %08x\n", nsres);
150         return E_FAIL;
151     }
152
153     return S_OK;
154 }
155
156 static HRESULT WINAPI HTMLFormElement_get_action(IHTMLFormElement *iface, BSTR *p)
157 {
158     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
159     nsAString action_str;
160     nsresult nsres;
161     HRESULT hres;
162
163     TRACE("(%p)->(%p)\n", This, p);
164
165     nsAString_Init(&action_str, NULL);
166     nsres = nsIDOMHTMLFormElement_GetAction(This->nsform, &action_str);
167     if(NS_SUCCEEDED(nsres)) {
168         const PRUnichar *action;
169         nsAString_GetData(&action_str, &action);
170         hres = nsuri_to_url(action, FALSE, p);
171     }else {
172         ERR("GetAction failed: %08x\n", nsres);
173         hres = E_FAIL;
174     }
175
176     return hres;
177 }
178
179 static HRESULT WINAPI HTMLFormElement_put_dir(IHTMLFormElement *iface, BSTR v)
180 {
181     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
182     FIXME("(%p)->(%s)\n", This, wine_dbgstr_w(v));
183     return E_NOTIMPL;
184 }
185
186 static HRESULT WINAPI HTMLFormElement_get_dir(IHTMLFormElement *iface, BSTR *p)
187 {
188     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
189     FIXME("(%p)->(%p)\n", This, p);
190     return E_NOTIMPL;
191 }
192
193 static HRESULT WINAPI HTMLFormElement_put_encoding(IHTMLFormElement *iface, BSTR v)
194 {
195     static const WCHAR urlencodedW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
196         'x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
197     static const WCHAR dataW[] = {'m','u','l','t','i','p','a','r','t','/',
198         'f','o','r','m','-','d','a','t','a',0};
199     static const WCHAR plainW[] = {'t','e','x','t','/','p','l','a','i','n',0};
200
201     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
202     nsAString encoding_str;
203     nsresult nsres;
204
205     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
206
207     if(lstrcmpiW(v, urlencodedW) && lstrcmpiW(v, dataW) && lstrcmpiW(v, plainW)) {
208         WARN("incorrect enctype\n");
209         return E_INVALIDARG;
210     }
211
212     nsAString_InitDepend(&encoding_str, v);
213     nsres = nsIDOMHTMLFormElement_SetEnctype(This->nsform, &encoding_str);
214     nsAString_Finish(&encoding_str);
215     if(NS_FAILED(nsres))
216         return E_FAIL;
217
218     return S_OK;
219 }
220
221 static HRESULT WINAPI HTMLFormElement_get_encoding(IHTMLFormElement *iface, BSTR *p)
222 {
223     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
224     nsAString encoding_str;
225     nsresult nsres;
226
227     TRACE("(%p)->(%p)\n", This, p);
228
229     nsAString_Init(&encoding_str, NULL);
230     nsres = nsIDOMHTMLFormElement_GetEnctype(This->nsform, &encoding_str);
231     return return_nsstr(nsres, &encoding_str, p);
232 }
233
234 static HRESULT WINAPI HTMLFormElement_put_method(IHTMLFormElement *iface, BSTR v)
235 {
236     static const WCHAR postW[] = {'P','O','S','T',0};
237     static const WCHAR getW[] = {'G','E','T',0};
238
239     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
240     nsAString method_str;
241     nsresult nsres;
242
243     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
244
245     if(lstrcmpiW(v, postW) && lstrcmpiW(v, getW)) {
246         WARN("unrecognized method\n");
247         return E_INVALIDARG;
248     }
249
250     nsAString_InitDepend(&method_str, v);
251     nsres = nsIDOMHTMLFormElement_SetMethod(This->nsform, &method_str);
252     nsAString_Finish(&method_str);
253     if(NS_FAILED(nsres))
254         return E_FAIL;
255
256     return S_OK;
257 }
258
259 static HRESULT WINAPI HTMLFormElement_get_method(IHTMLFormElement *iface, BSTR *p)
260 {
261     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
262     nsAString method_str;
263     nsresult nsres;
264
265     TRACE("(%p)->(%p)\n", This, p);
266
267     nsAString_Init(&method_str, NULL);
268     nsres = nsIDOMHTMLFormElement_GetMethod(This->nsform, &method_str);
269     return return_nsstr(nsres, &method_str, p);
270 }
271
272 static HRESULT WINAPI HTMLFormElement_get_elements(IHTMLFormElement *iface, IDispatch **p)
273 {
274     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
275     FIXME("(%p)->(%p)\n", This, p);
276     return E_NOTIMPL;
277 }
278
279 static HRESULT WINAPI HTMLFormElement_put_target(IHTMLFormElement *iface, BSTR v)
280 {
281     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
282     FIXME("(%p)->(%s)\n", This, wine_dbgstr_w(v));
283     return E_NOTIMPL;
284 }
285
286 static HRESULT WINAPI HTMLFormElement_get_target(IHTMLFormElement *iface, BSTR *p)
287 {
288     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
289     FIXME("(%p)->(%p)\n", This, p);
290     return E_NOTIMPL;
291 }
292
293 static HRESULT WINAPI HTMLFormElement_put_name(IHTMLFormElement *iface, BSTR v)
294 {
295     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
296     nsAString name_str;
297     nsresult nsres;
298
299     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
300
301     nsAString_InitDepend(&name_str, v);
302     nsres = nsIDOMHTMLFormElement_SetName(This->nsform, &name_str);
303     nsAString_Finish(&name_str);
304     if(NS_FAILED(nsres))
305         return E_FAIL;
306
307     return S_OK;
308 }
309
310 static HRESULT WINAPI HTMLFormElement_get_name(IHTMLFormElement *iface, BSTR *p)
311 {
312     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
313     nsAString name_str;
314     nsresult nsres;
315
316     TRACE("(%p)->(%p)\n", This, p);
317
318     nsAString_Init(&name_str, NULL);
319     nsres = nsIDOMHTMLFormElement_GetName(This->nsform, &name_str);
320     return return_nsstr(nsres, &name_str, p);
321 }
322
323 static HRESULT WINAPI HTMLFormElement_put_onsubmit(IHTMLFormElement *iface, VARIANT v)
324 {
325     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
326     FIXME("(%p)->(v)\n", This);
327     return E_NOTIMPL;
328 }
329
330 static HRESULT WINAPI HTMLFormElement_get_onsubmit(IHTMLFormElement *iface, VARIANT *p)
331 {
332     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
333     FIXME("(%p)->(%p)\n", This, p);
334     return E_NOTIMPL;
335 }
336
337 static HRESULT WINAPI HTMLFormElement_put_onreset(IHTMLFormElement *iface, VARIANT v)
338 {
339     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
340     FIXME("(%p)->(v)\n", This);
341     return E_NOTIMPL;
342 }
343
344 static HRESULT WINAPI HTMLFormElement_get_onreset(IHTMLFormElement *iface, VARIANT *p)
345 {
346     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
347     FIXME("(%p)->(%p)\n", This, p);
348     return E_NOTIMPL;
349 }
350
351 static HRESULT WINAPI HTMLFormElement_submit(IHTMLFormElement *iface)
352 {
353     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
354     FIXME("(%p)->()\n", This);
355     return E_NOTIMPL;
356 }
357
358 static HRESULT WINAPI HTMLFormElement_reset(IHTMLFormElement *iface)
359 {
360     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
361     FIXME("(%p)->()\n", This);
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI HTMLFormElement_put_length(IHTMLFormElement *iface, LONG v)
366 {
367     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
368     FIXME("(%p)->(%d)\n", This, v);
369     return E_NOTIMPL;
370 }
371
372 static HRESULT WINAPI HTMLFormElement_get_length(IHTMLFormElement *iface, LONG *p)
373 {
374     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
375     PRInt32 length;
376     nsresult nsres;
377
378     TRACE("(%p)->(%p)\n", This, p);
379
380     nsres = nsIDOMHTMLFormElement_GetLength(This->nsform, &length);
381     if(NS_FAILED(nsres)) {
382         ERR("GetLength failed: %08x\n", nsres);
383         return E_FAIL;
384     }
385
386     *p = length;
387     return S_OK;
388 }
389
390 static HRESULT WINAPI HTMLFormElement__newEnum(IHTMLFormElement *iface, IUnknown **p)
391 {
392     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
393     FIXME("(%p)->(%p)\n", This, p);
394     return E_NOTIMPL;
395 }
396
397 static HRESULT WINAPI HTMLFormElement_item(IHTMLFormElement *iface, VARIANT name,
398         VARIANT index, IDispatch **pdisp)
399 {
400     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
401
402     TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
403
404     if(!pdisp)
405         return E_INVALIDARG;
406     *pdisp = NULL;
407
408     if(V_VT(&name) == VT_I4) {
409         if(V_I4(&name) < 0)
410             return E_INVALIDARG;
411         return htmlform_item(This, V_I4(&name), pdisp);
412     }
413
414     FIXME("Unsupported args\n");
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI HTMLFormElement_tags(IHTMLFormElement *iface, VARIANT tagName,
419         IDispatch **pdisp)
420 {
421     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
422     FIXME("(%p)->(v %p)\n", This, pdisp);
423     return E_NOTIMPL;
424 }
425
426 static const IHTMLFormElementVtbl HTMLFormElementVtbl = {
427     HTMLFormElement_QueryInterface,
428     HTMLFormElement_AddRef,
429     HTMLFormElement_Release,
430     HTMLFormElement_GetTypeInfoCount,
431     HTMLFormElement_GetTypeInfo,
432     HTMLFormElement_GetIDsOfNames,
433     HTMLFormElement_Invoke,
434     HTMLFormElement_put_action,
435     HTMLFormElement_get_action,
436     HTMLFormElement_put_dir,
437     HTMLFormElement_get_dir,
438     HTMLFormElement_put_encoding,
439     HTMLFormElement_get_encoding,
440     HTMLFormElement_put_method,
441     HTMLFormElement_get_method,
442     HTMLFormElement_get_elements,
443     HTMLFormElement_put_target,
444     HTMLFormElement_get_target,
445     HTMLFormElement_put_name,
446     HTMLFormElement_get_name,
447     HTMLFormElement_put_onsubmit,
448     HTMLFormElement_get_onsubmit,
449     HTMLFormElement_put_onreset,
450     HTMLFormElement_get_onreset,
451     HTMLFormElement_submit,
452     HTMLFormElement_reset,
453     HTMLFormElement_put_length,
454     HTMLFormElement_get_length,
455     HTMLFormElement__newEnum,
456     HTMLFormElement_item,
457     HTMLFormElement_tags
458 };
459
460 static inline HTMLFormElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
461 {
462     return CONTAINING_RECORD(iface, HTMLFormElement, element.node);
463 }
464
465 static HRESULT HTMLFormElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
466 {
467     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
468
469     *ppv = NULL;
470
471     if(IsEqualGUID(&IID_IUnknown, riid)) {
472         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
473         *ppv = &This->IHTMLFormElement_iface;
474     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
475         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
476         *ppv = &This->IHTMLFormElement_iface;
477     }else if(IsEqualGUID(&IID_IHTMLFormElement, riid)) {
478         TRACE("(%p)->(IID_IHTMLFormElement %p)\n", This, ppv);
479         *ppv = &This->IHTMLFormElement_iface;
480     }
481
482     if(*ppv) {
483         IUnknown_AddRef((IUnknown*)*ppv);
484         return S_OK;
485     }
486
487     return HTMLElement_QI(&This->element.node, riid, ppv);
488 }
489
490 static void HTMLFormElement_destructor(HTMLDOMNode *iface)
491 {
492     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
493
494     if(This->nsform)
495         nsIDOMHTMLFormElement_Release(This->nsform);
496
497     HTMLElement_destructor(&This->element.node);
498 }
499
500 static HRESULT HTMLFormElement_get_dispid(HTMLDOMNode *iface,
501         BSTR name, DWORD grfdex, DISPID *pid)
502 {
503     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
504     nsIDOMHTMLCollection *elements;
505     nsAString nsname, nsstr;
506     PRUint32 len, i;
507     nsresult nsres;
508     HRESULT hres = DISP_E_UNKNOWNNAME;
509
510     static const PRUnichar nameW[] = {'n','a','m','e',0};
511
512     TRACE("(%p)->(%s %x %p)\n", This, wine_dbgstr_w(name), grfdex, pid);
513
514     nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements);
515     if(NS_FAILED(nsres)) {
516         FIXME("GetElements failed: 0x%08x\n", nsres);
517         return E_FAIL;
518     }
519
520     nsres = nsIDOMHTMLCollection_GetLength(elements, &len);
521     if(NS_FAILED(nsres)) {
522         FIXME("GetLength failed: 0x%08x\n", nsres);
523         nsIDOMHTMLCollection_Release(elements);
524         return E_FAIL;
525     }
526
527     nsAString_InitDepend(&nsname, nameW);
528     nsAString_Init(&nsstr, NULL);
529     for(i = 0; i < len; ++i) {
530         nsIDOMNode *nsitem;
531         nsIDOMHTMLElement *nshtml_elem;
532         const PRUnichar *str;
533
534         nsres = nsIDOMHTMLCollection_Item(elements, i, &nsitem);
535         if(NS_FAILED(nsres)) {
536             FIXME("Item failed: 0x%08x\n", nsres);
537             hres = E_FAIL;
538             break;
539         }
540
541         nsres = nsIDOMNode_QueryInterface(nsitem, &IID_nsIDOMHTMLElement, (void**)&nshtml_elem);
542         nsIDOMNode_Release(nsitem);
543         if(NS_FAILED(nsres)) {
544             FIXME("Failed to get nsIDOMHTMLNode interface: 0x%08x\n", nsres);
545             hres = E_FAIL;
546             break;
547         }
548
549         /* compare by id attr */
550         nsres = nsIDOMHTMLElement_GetId(nshtml_elem, &nsstr);
551         if(NS_FAILED(nsres)) {
552             FIXME("GetId failed: 0x%08x\n", nsres);
553             nsIDOMHTMLElement_Release(nshtml_elem);
554             hres = E_FAIL;
555             break;
556         }
557         nsAString_GetData(&nsstr, &str);
558         if(!strcmpiW(str, name)) {
559             nsIDOMHTMLElement_Release(nshtml_elem);
560             /* FIXME: using index for dispid */
561             *pid = MSHTML_DISPID_CUSTOM_MIN + i;
562             hres = S_OK;
563             break;
564         }
565
566         /* compare by name attr */
567         nsres = nsIDOMHTMLElement_GetAttribute(nshtml_elem, &nsname, &nsstr);
568         nsIDOMHTMLElement_Release(nshtml_elem);
569         nsAString_GetData(&nsstr, &str);
570         if(!strcmpiW(str, name)) {
571             /* FIXME: using index for dispid */
572             *pid = MSHTML_DISPID_CUSTOM_MIN + i;
573             hres = S_OK;
574             break;
575         }
576     }
577     nsAString_Finish(&nsname);
578     nsAString_Finish(&nsstr);
579
580     nsIDOMHTMLCollection_Release(elements);
581
582     return hres;
583 }
584
585 static HRESULT HTMLFormElement_invoke(HTMLDOMNode *iface,
586         DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res,
587         EXCEPINFO *ei, IServiceProvider *caller)
588 {
589     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
590     IDispatch *ret;
591     HRESULT hres;
592
593     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
594
595     hres = htmlform_item(This, id - MSHTML_DISPID_CUSTOM_MIN, &ret);
596     if(FAILED(hres))
597         return hres;
598
599     if(ret) {
600         V_VT(res) = VT_DISPATCH;
601         V_DISPATCH(res) = ret;
602     }else {
603         V_VT(res) = VT_NULL;
604     }
605     return S_OK;
606 }
607
608 static const NodeImplVtbl HTMLFormElementImplVtbl = {
609     HTMLFormElement_QI,
610     HTMLFormElement_destructor,
611     HTMLElement_clone,
612     NULL,
613     NULL,
614     NULL,
615     NULL,
616     NULL,
617     NULL,
618     HTMLFormElement_get_dispid,
619     HTMLFormElement_invoke
620 };
621
622 static const tid_t HTMLFormElement_iface_tids[] = {
623     HTMLELEMENT_TIDS,
624     IHTMLFormElement_tid,
625     0
626 };
627
628 static dispex_static_data_t HTMLFormElement_dispex = {
629     NULL,
630     DispHTMLFormElement_tid,
631     NULL,
632     HTMLFormElement_iface_tids
633 };
634
635 HRESULT HTMLFormElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
636 {
637     HTMLFormElement *ret;
638     nsresult nsres;
639
640     ret = heap_alloc_zero(sizeof(HTMLFormElement));
641     if(!ret)
642         return E_OUTOFMEMORY;
643
644     ret->IHTMLFormElement_iface.lpVtbl = &HTMLFormElementVtbl;
645     ret->element.node.vtbl = &HTMLFormElementImplVtbl;
646
647     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLFormElement, (void**)&ret->nsform);
648     if(NS_FAILED(nsres)) {
649         ERR("Could not get nsIDOMHTMLFormElement interface: %08x\n", nsres);
650         heap_free(ret);
651         return E_FAIL;
652     }
653
654     HTMLElement_Init(&ret->element, doc, nselem, &HTMLFormElement_dispex);
655
656     *elem = &ret->element;
657     return S_OK;
658 }