xref: /reactos/dll/win32/mshtml/htmlform.c (revision 990e7dfd)
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 "mshtml_private.h"
20 
21 struct HTMLFormElement {
22     HTMLElement element;
23 
24     IHTMLFormElement IHTMLFormElement_iface;
25 
26     nsIDOMHTMLFormElement *nsform;
27 };
28 
htmlform_item(HTMLFormElement * This,int i,IDispatch ** ret)29 static HRESULT htmlform_item(HTMLFormElement *This, int i, IDispatch **ret)
30 {
31     nsIDOMHTMLCollection *elements;
32     nsIDOMNode *item;
33     HTMLDOMNode *node;
34     nsresult nsres;
35     HRESULT hres;
36 
37     nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements);
38     if(NS_FAILED(nsres)) {
39         FIXME("GetElements failed: 0x%08x\n", nsres);
40         return E_FAIL;
41     }
42 
43     nsres = nsIDOMHTMLCollection_Item(elements, i, &item);
44     nsIDOMHTMLCollection_Release(elements);
45     if(NS_FAILED(nsres)) {
46         FIXME("Item failed: 0x%08x\n", nsres);
47         return E_FAIL;
48     }
49 
50     if(item) {
51         hres = get_node(This->element.node.doc, item, TRUE, &node);
52         if(FAILED(hres))
53             return hres;
54 
55         nsIDOMNode_Release(item);
56         *ret = (IDispatch*)&node->IHTMLDOMNode_iface;
57     }else {
58         *ret = NULL;
59     }
60 
61     return S_OK;
62 }
63 
impl_from_IHTMLFormElement(IHTMLFormElement * iface)64 static inline HTMLFormElement *impl_from_IHTMLFormElement(IHTMLFormElement *iface)
65 {
66     return CONTAINING_RECORD(iface, HTMLFormElement, IHTMLFormElement_iface);
67 }
68 
HTMLFormElement_QueryInterface(IHTMLFormElement * iface,REFIID riid,void ** ppv)69 static HRESULT WINAPI HTMLFormElement_QueryInterface(IHTMLFormElement *iface,
70         REFIID riid, void **ppv)
71 {
72     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
73 
74     return IHTMLDOMNode_QueryInterface(&This->element.node.IHTMLDOMNode_iface, riid, ppv);
75 }
76 
HTMLFormElement_AddRef(IHTMLFormElement * iface)77 static ULONG WINAPI HTMLFormElement_AddRef(IHTMLFormElement *iface)
78 {
79     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
80 
81     return IHTMLDOMNode_AddRef(&This->element.node.IHTMLDOMNode_iface);
82 }
83 
HTMLFormElement_Release(IHTMLFormElement * iface)84 static ULONG WINAPI HTMLFormElement_Release(IHTMLFormElement *iface)
85 {
86     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
87 
88     return IHTMLDOMNode_Release(&This->element.node.IHTMLDOMNode_iface);
89 }
90 
HTMLFormElement_GetTypeInfoCount(IHTMLFormElement * iface,UINT * pctinfo)91 static HRESULT WINAPI HTMLFormElement_GetTypeInfoCount(IHTMLFormElement *iface, UINT *pctinfo)
92 {
93     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
94     return IDispatchEx_GetTypeInfoCount(&This->element.node.event_target.dispex.IDispatchEx_iface, pctinfo);
95 }
96 
HTMLFormElement_GetTypeInfo(IHTMLFormElement * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)97 static HRESULT WINAPI HTMLFormElement_GetTypeInfo(IHTMLFormElement *iface, UINT iTInfo,
98                                               LCID lcid, ITypeInfo **ppTInfo)
99 {
100     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
101     return IDispatchEx_GetTypeInfo(&This->element.node.event_target.dispex.IDispatchEx_iface, iTInfo, lcid,
102             ppTInfo);
103 }
104 
HTMLFormElement_GetIDsOfNames(IHTMLFormElement * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)105 static HRESULT WINAPI HTMLFormElement_GetIDsOfNames(IHTMLFormElement *iface, REFIID riid,
106                                                 LPOLESTR *rgszNames, UINT cNames,
107                                                 LCID lcid, DISPID *rgDispId)
108 {
109     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
110     return IDispatchEx_GetIDsOfNames(&This->element.node.event_target.dispex.IDispatchEx_iface, riid, rgszNames,
111             cNames, lcid, rgDispId);
112 }
113 
HTMLFormElement_Invoke(IHTMLFormElement * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pDispParams,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)114 static HRESULT WINAPI HTMLFormElement_Invoke(IHTMLFormElement *iface, DISPID dispIdMember,
115                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
116                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
117 {
118     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
119     return IDispatchEx_Invoke(&This->element.node.event_target.dispex.IDispatchEx_iface, dispIdMember, riid,
120             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
121 }
122 
HTMLFormElement_put_action(IHTMLFormElement * iface,BSTR v)123 static HRESULT WINAPI HTMLFormElement_put_action(IHTMLFormElement *iface, BSTR v)
124 {
125     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
126     nsAString action_str;
127     nsresult nsres;
128 
129     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
130 
131     nsAString_InitDepend(&action_str, v);
132     nsres = nsIDOMHTMLFormElement_SetAction(This->nsform, &action_str);
133     nsAString_Finish(&action_str);
134     if(NS_FAILED(nsres)) {
135         ERR("SetAction failed: %08x\n", nsres);
136         return E_FAIL;
137     }
138 
139     return S_OK;
140 }
141 
HTMLFormElement_get_action(IHTMLFormElement * iface,BSTR * p)142 static HRESULT WINAPI HTMLFormElement_get_action(IHTMLFormElement *iface, BSTR *p)
143 {
144     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
145     nsAString action_str;
146     nsresult nsres;
147     HRESULT hres;
148 
149     TRACE("(%p)->(%p)\n", This, p);
150 
151     nsAString_Init(&action_str, NULL);
152     nsres = nsIDOMHTMLFormElement_GetAction(This->nsform, &action_str);
153     if(NS_SUCCEEDED(nsres)) {
154         const PRUnichar *action;
155         nsAString_GetData(&action_str, &action);
156         hres = nsuri_to_url(action, FALSE, p);
157     }else {
158         ERR("GetAction failed: %08x\n", nsres);
159         hres = E_FAIL;
160     }
161 
162     nsAString_Finish(&action_str);
163     return hres;
164 }
165 
HTMLFormElement_put_dir(IHTMLFormElement * iface,BSTR v)166 static HRESULT WINAPI HTMLFormElement_put_dir(IHTMLFormElement *iface, BSTR v)
167 {
168     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
169     FIXME("(%p)->(%s)\n", This, wine_dbgstr_w(v));
170     return E_NOTIMPL;
171 }
172 
HTMLFormElement_get_dir(IHTMLFormElement * iface,BSTR * p)173 static HRESULT WINAPI HTMLFormElement_get_dir(IHTMLFormElement *iface, BSTR *p)
174 {
175     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
176     FIXME("(%p)->(%p)\n", This, p);
177     return E_NOTIMPL;
178 }
179 
HTMLFormElement_put_encoding(IHTMLFormElement * iface,BSTR v)180 static HRESULT WINAPI HTMLFormElement_put_encoding(IHTMLFormElement *iface, BSTR v)
181 {
182     static const WCHAR urlencodedW[] = {'a','p','p','l','i','c','a','t','i','o','n','/',
183         'x','-','w','w','w','-','f','o','r','m','-','u','r','l','e','n','c','o','d','e','d',0};
184     static const WCHAR dataW[] = {'m','u','l','t','i','p','a','r','t','/',
185         'f','o','r','m','-','d','a','t','a',0};
186     static const WCHAR plainW[] = {'t','e','x','t','/','p','l','a','i','n',0};
187 
188     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
189     nsAString encoding_str;
190     nsresult nsres;
191 
192     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
193 
194     if(lstrcmpiW(v, urlencodedW) && lstrcmpiW(v, dataW) && lstrcmpiW(v, plainW)) {
195         WARN("incorrect enctype\n");
196         return E_INVALIDARG;
197     }
198 
199     nsAString_InitDepend(&encoding_str, v);
200     nsres = nsIDOMHTMLFormElement_SetEnctype(This->nsform, &encoding_str);
201     nsAString_Finish(&encoding_str);
202     if(NS_FAILED(nsres))
203         return E_FAIL;
204 
205     return S_OK;
206 }
207 
HTMLFormElement_get_encoding(IHTMLFormElement * iface,BSTR * p)208 static HRESULT WINAPI HTMLFormElement_get_encoding(IHTMLFormElement *iface, BSTR *p)
209 {
210     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
211     nsAString encoding_str;
212     nsresult nsres;
213 
214     TRACE("(%p)->(%p)\n", This, p);
215 
216     nsAString_Init(&encoding_str, NULL);
217     nsres = nsIDOMHTMLFormElement_GetEnctype(This->nsform, &encoding_str);
218     return return_nsstr(nsres, &encoding_str, p);
219 }
220 
HTMLFormElement_put_method(IHTMLFormElement * iface,BSTR v)221 static HRESULT WINAPI HTMLFormElement_put_method(IHTMLFormElement *iface, BSTR v)
222 {
223     static const WCHAR postW[] = {'P','O','S','T',0};
224     static const WCHAR getW[] = {'G','E','T',0};
225 
226     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
227     nsAString method_str;
228     nsresult nsres;
229 
230     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
231 
232     if(lstrcmpiW(v, postW) && lstrcmpiW(v, getW)) {
233         WARN("unrecognized method\n");
234         return E_INVALIDARG;
235     }
236 
237     nsAString_InitDepend(&method_str, v);
238     nsres = nsIDOMHTMLFormElement_SetMethod(This->nsform, &method_str);
239     nsAString_Finish(&method_str);
240     if(NS_FAILED(nsres))
241         return E_FAIL;
242 
243     return S_OK;
244 }
245 
HTMLFormElement_get_method(IHTMLFormElement * iface,BSTR * p)246 static HRESULT WINAPI HTMLFormElement_get_method(IHTMLFormElement *iface, BSTR *p)
247 {
248     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
249     nsAString method_str;
250     nsresult nsres;
251 
252     TRACE("(%p)->(%p)\n", This, p);
253 
254     nsAString_Init(&method_str, NULL);
255     nsres = nsIDOMHTMLFormElement_GetMethod(This->nsform, &method_str);
256     return return_nsstr(nsres, &method_str, p);
257 }
258 
HTMLFormElement_get_elements(IHTMLFormElement * iface,IDispatch ** p)259 static HRESULT WINAPI HTMLFormElement_get_elements(IHTMLFormElement *iface, IDispatch **p)
260 {
261     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
262 
263     TRACE("(%p)->(%p)\n", This, p);
264 
265     *p = (IDispatch*)&This->IHTMLFormElement_iface;
266     IDispatch_AddRef(*p);
267     return S_OK;
268 }
269 
HTMLFormElement_put_target(IHTMLFormElement * iface,BSTR v)270 static HRESULT WINAPI HTMLFormElement_put_target(IHTMLFormElement *iface, BSTR v)
271 {
272     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
273     nsAString str;
274     nsresult nsres;
275 
276     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
277 
278     nsAString_InitDepend(&str, v);
279 
280     nsres = nsIDOMHTMLFormElement_SetTarget(This->nsform, &str);
281 
282     nsAString_Finish(&str);
283     if (NS_FAILED(nsres)) {
284         ERR("Set Target(%s) failed: %08x\n", wine_dbgstr_w(v), nsres);
285         return E_FAIL;
286     }
287 
288     return S_OK;
289 }
290 
HTMLFormElement_get_target(IHTMLFormElement * iface,BSTR * p)291 static HRESULT WINAPI HTMLFormElement_get_target(IHTMLFormElement *iface, BSTR *p)
292 {
293     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
294     nsAString str;
295     nsresult nsres;
296 
297     TRACE("(%p)->(%p)\n", This, p);
298 
299     nsAString_Init(&str, NULL);
300     nsres = nsIDOMHTMLFormElement_GetTarget(This->nsform, &str);
301 
302     return return_nsstr(nsres, &str, p);
303 }
304 
HTMLFormElement_put_name(IHTMLFormElement * iface,BSTR v)305 static HRESULT WINAPI HTMLFormElement_put_name(IHTMLFormElement *iface, BSTR v)
306 {
307     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
308     nsAString name_str;
309     nsresult nsres;
310 
311     TRACE("(%p)->(%s)\n", This, wine_dbgstr_w(v));
312 
313     nsAString_InitDepend(&name_str, v);
314     nsres = nsIDOMHTMLFormElement_SetName(This->nsform, &name_str);
315     nsAString_Finish(&name_str);
316     if(NS_FAILED(nsres))
317         return E_FAIL;
318 
319     return S_OK;
320 }
321 
HTMLFormElement_get_name(IHTMLFormElement * iface,BSTR * p)322 static HRESULT WINAPI HTMLFormElement_get_name(IHTMLFormElement *iface, BSTR *p)
323 {
324     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
325     nsAString name_str;
326     nsresult nsres;
327 
328     TRACE("(%p)->(%p)\n", This, p);
329 
330     nsAString_Init(&name_str, NULL);
331     nsres = nsIDOMHTMLFormElement_GetName(This->nsform, &name_str);
332     return return_nsstr(nsres, &name_str, p);
333 }
334 
HTMLFormElement_put_onsubmit(IHTMLFormElement * iface,VARIANT v)335 static HRESULT WINAPI HTMLFormElement_put_onsubmit(IHTMLFormElement *iface, VARIANT v)
336 {
337     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
338 
339     TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
340 
341     return set_node_event(&This->element.node, EVENTID_SUBMIT, &v);
342 }
343 
HTMLFormElement_get_onsubmit(IHTMLFormElement * iface,VARIANT * p)344 static HRESULT WINAPI HTMLFormElement_get_onsubmit(IHTMLFormElement *iface, VARIANT *p)
345 {
346     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
347 
348     TRACE("(%p)->(%p)\n", This, p);
349 
350     return get_node_event(&This->element.node, EVENTID_SUBMIT, p);
351 }
352 
HTMLFormElement_put_onreset(IHTMLFormElement * iface,VARIANT v)353 static HRESULT WINAPI HTMLFormElement_put_onreset(IHTMLFormElement *iface, VARIANT v)
354 {
355     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
356     FIXME("(%p)->(%s)\n", This, debugstr_variant(&v));
357     return E_NOTIMPL;
358 }
359 
HTMLFormElement_get_onreset(IHTMLFormElement * iface,VARIANT * p)360 static HRESULT WINAPI HTMLFormElement_get_onreset(IHTMLFormElement *iface, VARIANT *p)
361 {
362     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
363     FIXME("(%p)->(%p)\n", This, p);
364     return E_NOTIMPL;
365 }
366 
HTMLFormElement_submit(IHTMLFormElement * iface)367 static HRESULT WINAPI HTMLFormElement_submit(IHTMLFormElement *iface)
368 {
369     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
370     HTMLOuterWindow *window = NULL, *this_window = NULL;
371     nsAString action_uri_str, target_str, method_str;
372     nsIInputStream *post_stream;
373     BOOL is_post_submit = FALSE;
374     IUri *uri;
375     nsresult nsres;
376     HRESULT hres;
377     BOOL use_new_window = FALSE;
378 
379     TRACE("(%p)\n", This);
380 
381     if(This->element.node.doc) {
382         HTMLDocumentNode *doc = This->element.node.doc;
383         if(doc->window && doc->window->base.outer_window)
384             this_window = doc->window->base.outer_window;
385     }
386     if(!this_window) {
387         TRACE("No outer window\n");
388         return S_OK;
389     }
390 
391     nsAString_Init(&target_str, NULL);
392     nsres = nsIDOMHTMLFormElement_GetTarget(This->nsform, &target_str);
393     if(NS_SUCCEEDED(nsres))
394         window = get_target_window(this_window, &target_str, &use_new_window);
395 
396     if(!window && !use_new_window) {
397         nsAString_Finish(&target_str);
398         return S_OK;
399     }
400 
401     nsAString_Init(&method_str, NULL);
402     nsres = nsIDOMHTMLFormElement_GetMethod(This->nsform, &method_str);
403     if(NS_SUCCEEDED(nsres)) {
404         const PRUnichar *method;
405 
406         static const PRUnichar postW[] = {'p','o','s','t',0};
407 
408         nsAString_GetData(&method_str, &method);
409         TRACE("method is %s\n", debugstr_w(method));
410         is_post_submit = !strcmpiW(method, postW);
411     }
412     nsAString_Finish(&method_str);
413 
414     /*
415      * FIXME: We currently use our submit implementation for POST submit. We should always use it.
416      */
417     if(window && !is_post_submit) {
418         nsres = nsIDOMHTMLFormElement_Submit(This->nsform);
419         nsAString_Finish(&target_str);
420         IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
421         if(NS_FAILED(nsres)) {
422             ERR("Submit failed: %08x\n", nsres);
423             return E_FAIL;
424         }
425 
426         return S_OK;
427     }
428 
429     nsAString_Init(&action_uri_str, NULL);
430     nsres = nsIDOMHTMLFormElement_GetFormData(This->nsform, NULL, &action_uri_str, &post_stream);
431     if(NS_SUCCEEDED(nsres)) {
432         const PRUnichar *action_uri;
433 
434         nsAString_GetData(&action_uri_str, &action_uri);
435         hres = create_uri(action_uri, 0, &uri);
436     }else {
437         ERR("GetFormData failed: %08x\n", nsres);
438         hres = E_FAIL;
439     }
440     nsAString_Finish(&action_uri_str);
441     if(SUCCEEDED(hres)) {
442         const PRUnichar *target;
443 
444         nsAString_GetData(&target_str, &target);
445         hres = submit_form(window, target, uri, post_stream);
446         IUri_Release(uri);
447     }
448 
449     nsAString_Finish(&target_str);
450     if(window)
451         IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
452     if(post_stream)
453         nsIInputStream_Release(post_stream);
454     return hres;
455 }
456 
HTMLFormElement_reset(IHTMLFormElement * iface)457 static HRESULT WINAPI HTMLFormElement_reset(IHTMLFormElement *iface)
458 {
459     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
460     nsresult nsres;
461 
462     TRACE("(%p)->()\n", This);
463     nsres = nsIDOMHTMLFormElement_Reset(This->nsform);
464     if (NS_FAILED(nsres)) {
465         ERR("Reset failed: %08x\n", nsres);
466         return E_FAIL;
467     }
468 
469     return S_OK;
470 }
471 
HTMLFormElement_put_length(IHTMLFormElement * iface,LONG v)472 static HRESULT WINAPI HTMLFormElement_put_length(IHTMLFormElement *iface, LONG v)
473 {
474     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
475     FIXME("(%p)->(%d)\n", This, v);
476     return E_NOTIMPL;
477 }
478 
HTMLFormElement_get_length(IHTMLFormElement * iface,LONG * p)479 static HRESULT WINAPI HTMLFormElement_get_length(IHTMLFormElement *iface, LONG *p)
480 {
481     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
482     nsresult nsres;
483 
484     TRACE("(%p)->(%p)\n", This, p);
485 
486     nsres = nsIDOMHTMLFormElement_GetLength(This->nsform, p);
487     if(NS_FAILED(nsres)) {
488         ERR("GetLength failed: %08x\n", nsres);
489         return E_FAIL;
490     }
491 
492     return S_OK;
493 }
494 
HTMLFormElement__newEnum(IHTMLFormElement * iface,IUnknown ** p)495 static HRESULT WINAPI HTMLFormElement__newEnum(IHTMLFormElement *iface, IUnknown **p)
496 {
497     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
498     FIXME("(%p)->(%p)\n", This, p);
499     return E_NOTIMPL;
500 }
501 
HTMLFormElement_item(IHTMLFormElement * iface,VARIANT name,VARIANT index,IDispatch ** pdisp)502 static HRESULT WINAPI HTMLFormElement_item(IHTMLFormElement *iface, VARIANT name,
503         VARIANT index, IDispatch **pdisp)
504 {
505     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
506 
507     TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
508 
509     if(!pdisp)
510         return E_INVALIDARG;
511     *pdisp = NULL;
512 
513     if(V_VT(&name) == VT_I4) {
514         if(V_I4(&name) < 0)
515             return E_INVALIDARG;
516         return htmlform_item(This, V_I4(&name), pdisp);
517     }
518 
519     FIXME("Unsupported args\n");
520     return E_NOTIMPL;
521 }
522 
HTMLFormElement_tags(IHTMLFormElement * iface,VARIANT tagName,IDispatch ** pdisp)523 static HRESULT WINAPI HTMLFormElement_tags(IHTMLFormElement *iface, VARIANT tagName,
524         IDispatch **pdisp)
525 {
526     HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
527     FIXME("(%p)->(v %p)\n", This, pdisp);
528     return E_NOTIMPL;
529 }
530 
531 static const IHTMLFormElementVtbl HTMLFormElementVtbl = {
532     HTMLFormElement_QueryInterface,
533     HTMLFormElement_AddRef,
534     HTMLFormElement_Release,
535     HTMLFormElement_GetTypeInfoCount,
536     HTMLFormElement_GetTypeInfo,
537     HTMLFormElement_GetIDsOfNames,
538     HTMLFormElement_Invoke,
539     HTMLFormElement_put_action,
540     HTMLFormElement_get_action,
541     HTMLFormElement_put_dir,
542     HTMLFormElement_get_dir,
543     HTMLFormElement_put_encoding,
544     HTMLFormElement_get_encoding,
545     HTMLFormElement_put_method,
546     HTMLFormElement_get_method,
547     HTMLFormElement_get_elements,
548     HTMLFormElement_put_target,
549     HTMLFormElement_get_target,
550     HTMLFormElement_put_name,
551     HTMLFormElement_get_name,
552     HTMLFormElement_put_onsubmit,
553     HTMLFormElement_get_onsubmit,
554     HTMLFormElement_put_onreset,
555     HTMLFormElement_get_onreset,
556     HTMLFormElement_submit,
557     HTMLFormElement_reset,
558     HTMLFormElement_put_length,
559     HTMLFormElement_get_length,
560     HTMLFormElement__newEnum,
561     HTMLFormElement_item,
562     HTMLFormElement_tags
563 };
564 
impl_from_HTMLDOMNode(HTMLDOMNode * iface)565 static inline HTMLFormElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
566 {
567     return CONTAINING_RECORD(iface, HTMLFormElement, element.node);
568 }
569 
HTMLFormElement_QI(HTMLDOMNode * iface,REFIID riid,void ** ppv)570 static HRESULT HTMLFormElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
571 {
572     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
573 
574     *ppv = NULL;
575 
576     if(IsEqualGUID(&IID_IUnknown, riid)) {
577         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
578         *ppv = &This->IHTMLFormElement_iface;
579     }else if(IsEqualGUID(&IID_IDispatch, riid)) {
580         TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
581         *ppv = &This->IHTMLFormElement_iface;
582     }else if(IsEqualGUID(&IID_IHTMLFormElement, riid)) {
583         TRACE("(%p)->(IID_IHTMLFormElement %p)\n", This, ppv);
584         *ppv = &This->IHTMLFormElement_iface;
585     }else if(IsEqualGUID(&DIID_DispHTMLFormElement, riid)) {
586         TRACE("(%p)->(DIID_DispHTMLFormElement %p)\n", This, ppv);
587         *ppv = &This->IHTMLFormElement_iface;
588     }
589 
590     if(*ppv) {
591         IUnknown_AddRef((IUnknown*)*ppv);
592         return S_OK;
593     }
594 
595     return HTMLElement_QI(&This->element.node, riid, ppv);
596 }
597 
HTMLFormElement_get_dispid(HTMLDOMNode * iface,BSTR name,DWORD grfdex,DISPID * pid)598 static HRESULT HTMLFormElement_get_dispid(HTMLDOMNode *iface,
599         BSTR name, DWORD grfdex, DISPID *pid)
600 {
601     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
602     nsIDOMHTMLCollection *elements;
603     nsAString nsstr, name_str;
604     UINT32 len, i;
605     nsresult nsres;
606     HRESULT hres = DISP_E_UNKNOWNNAME;
607 
608     static const PRUnichar nameW[] = {'n','a','m','e',0};
609 
610     TRACE("(%p)->(%s %x %p)\n", This, wine_dbgstr_w(name), grfdex, pid);
611 
612     nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements);
613     if(NS_FAILED(nsres)) {
614         FIXME("GetElements failed: 0x%08x\n", nsres);
615         return E_FAIL;
616     }
617 
618     nsres = nsIDOMHTMLCollection_GetLength(elements, &len);
619     if(NS_FAILED(nsres)) {
620         FIXME("GetLength failed: 0x%08x\n", nsres);
621         nsIDOMHTMLCollection_Release(elements);
622         return E_FAIL;
623     }
624 
625     if(len > MSHTML_CUSTOM_DISPID_CNT)
626         len = MSHTML_CUSTOM_DISPID_CNT;
627 
628     /* FIXME: Implement in more generic way */
629     if('0' <= *name && *name <= '9') {
630         WCHAR *end_ptr;
631 
632         i = strtoulW(name, &end_ptr, 10);
633         if(!*end_ptr && i < len) {
634             *pid = MSHTML_DISPID_CUSTOM_MIN + i;
635             return S_OK;
636         }
637     }
638 
639     nsAString_Init(&nsstr, NULL);
640     for(i = 0; i < len; ++i) {
641         nsIDOMNode *nsitem;
642         nsIDOMHTMLElement *nshtml_elem;
643         const PRUnichar *str;
644 
645         nsres = nsIDOMHTMLCollection_Item(elements, i, &nsitem);
646         if(NS_FAILED(nsres)) {
647             FIXME("Item failed: 0x%08x\n", nsres);
648             hres = E_FAIL;
649             break;
650         }
651 
652         nsres = nsIDOMNode_QueryInterface(nsitem, &IID_nsIDOMHTMLElement, (void**)&nshtml_elem);
653         nsIDOMNode_Release(nsitem);
654         if(NS_FAILED(nsres)) {
655             FIXME("Failed to get nsIDOMHTMLNode interface: 0x%08x\n", nsres);
656             hres = E_FAIL;
657             break;
658         }
659 
660         /* compare by id attr */
661         nsres = nsIDOMHTMLElement_GetId(nshtml_elem, &nsstr);
662         if(NS_FAILED(nsres)) {
663             FIXME("GetId failed: 0x%08x\n", nsres);
664             nsIDOMHTMLElement_Release(nshtml_elem);
665             hres = E_FAIL;
666             break;
667         }
668         nsAString_GetData(&nsstr, &str);
669         if(!strcmpiW(str, name)) {
670             nsIDOMHTMLElement_Release(nshtml_elem);
671             /* FIXME: using index for dispid */
672             *pid = MSHTML_DISPID_CUSTOM_MIN + i;
673             hres = S_OK;
674             break;
675         }
676 
677         /* compare by name attr */
678         nsres = get_elem_attr_value(nshtml_elem, nameW, &name_str, &str);
679         nsIDOMHTMLElement_Release(nshtml_elem);
680         if(NS_SUCCEEDED(nsres)) {
681             if(!strcmpiW(str, name)) {
682                 nsAString_Finish(&name_str);
683                 /* FIXME: using index for dispid */
684                 *pid = MSHTML_DISPID_CUSTOM_MIN + i;
685                 hres = S_OK;
686                 break;
687             }
688             nsAString_Finish(&name_str);
689         }
690     }
691 
692     nsAString_Finish(&nsstr);
693     nsIDOMHTMLCollection_Release(elements);
694     return hres;
695 }
696 
HTMLFormElement_invoke(HTMLDOMNode * iface,DISPID id,LCID lcid,WORD flags,DISPPARAMS * params,VARIANT * res,EXCEPINFO * ei,IServiceProvider * caller)697 static HRESULT HTMLFormElement_invoke(HTMLDOMNode *iface,
698         DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res,
699         EXCEPINFO *ei, IServiceProvider *caller)
700 {
701     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
702     IDispatch *ret;
703     HRESULT hres;
704 
705     TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
706 
707     hres = htmlform_item(This, id - MSHTML_DISPID_CUSTOM_MIN, &ret);
708     if(FAILED(hres))
709         return hres;
710 
711     if(ret) {
712         V_VT(res) = VT_DISPATCH;
713         V_DISPATCH(res) = ret;
714     }else {
715         V_VT(res) = VT_NULL;
716     }
717     return S_OK;
718 }
719 
HTMLFormElement_handle_event(HTMLDOMNode * iface,DWORD eid,nsIDOMEvent * event,BOOL * prevent_default)720 static HRESULT HTMLFormElement_handle_event(HTMLDOMNode *iface, DWORD eid, nsIDOMEvent *event, BOOL *prevent_default)
721 {
722     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
723 
724     if(eid == EVENTID_SUBMIT) {
725         *prevent_default = TRUE;
726         return IHTMLFormElement_submit(&This->IHTMLFormElement_iface);
727     }
728 
729     return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default);
730 }
731 
HTMLFormElement_traverse(HTMLDOMNode * iface,nsCycleCollectionTraversalCallback * cb)732 static void HTMLFormElement_traverse(HTMLDOMNode *iface, nsCycleCollectionTraversalCallback *cb)
733 {
734     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
735 
736     if(This->nsform)
737         note_cc_edge((nsISupports*)This->nsform, "This->nsform", cb);
738 }
739 
HTMLFormElement_unlink(HTMLDOMNode * iface)740 static void HTMLFormElement_unlink(HTMLDOMNode *iface)
741 {
742     HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
743 
744     if(This->nsform) {
745         nsIDOMHTMLFormElement *nsform = This->nsform;
746 
747         This->nsform = NULL;
748         nsIDOMHTMLFormElement_Release(nsform);
749     }
750 }
751 
752 static const NodeImplVtbl HTMLFormElementImplVtbl = {
753     HTMLFormElement_QI,
754     HTMLElement_destructor,
755     HTMLElement_cpc,
756     HTMLElement_clone,
757     HTMLFormElement_handle_event,
758     HTMLElement_get_attr_col,
759     NULL,
760     NULL,
761     NULL,
762     NULL,
763     NULL,
764     NULL,
765     HTMLFormElement_get_dispid,
766     HTMLFormElement_invoke,
767     NULL,
768     HTMLFormElement_traverse,
769     HTMLFormElement_unlink
770 };
771 
772 static const tid_t HTMLFormElement_iface_tids[] = {
773     HTMLELEMENT_TIDS,
774     IHTMLFormElement_tid,
775     0
776 };
777 
778 static dispex_static_data_t HTMLFormElement_dispex = {
779     NULL,
780     DispHTMLFormElement_tid,
781     NULL,
782     HTMLFormElement_iface_tids
783 };
784 
HTMLFormElement_Create(HTMLDocumentNode * doc,nsIDOMHTMLElement * nselem,HTMLElement ** elem)785 HRESULT HTMLFormElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
786 {
787     HTMLFormElement *ret;
788     nsresult nsres;
789 
790     ret = heap_alloc_zero(sizeof(HTMLFormElement));
791     if(!ret)
792         return E_OUTOFMEMORY;
793 
794     ret->IHTMLFormElement_iface.lpVtbl = &HTMLFormElementVtbl;
795     ret->element.node.vtbl = &HTMLFormElementImplVtbl;
796 
797     HTMLElement_Init(&ret->element, doc, nselem, &HTMLFormElement_dispex);
798 
799     nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLFormElement, (void**)&ret->nsform);
800     assert(nsres == NS_OK);
801 
802     *elem = &ret->element;
803     return S_OK;
804 }
805