[MSHTML]
[reactos.git] / reactos / dll / win32 / 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 "mshtml_private.h"
20
21 struct HTMLFormElement {
22 HTMLElement element;
23
24 IHTMLFormElement IHTMLFormElement_iface;
25
26 nsIDOMHTMLFormElement *nsform;
27 };
28
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
64 static inline HTMLFormElement *impl_from_IHTMLFormElement(IHTMLFormElement *iface)
65 {
66 return CONTAINING_RECORD(iface, HTMLFormElement, IHTMLFormElement_iface);
67 }
68
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
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
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
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.dispex.IDispatchEx_iface, pctinfo);
95 }
96
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.dispex.IDispatchEx_iface, iTInfo, lcid,
102 ppTInfo);
103 }
104
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.dispex.IDispatchEx_iface, riid, rgszNames,
111 cNames, lcid, rgDispId);
112 }
113
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.dispex.IDispatchEx_iface, dispIdMember, riid,
120 lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
121 }
122
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
367 static HRESULT WINAPI HTMLFormElement_submit(IHTMLFormElement *iface)
368 {
369 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
370 HTMLOuterWindow *window = NULL, *this_window = NULL;
371 nsIInputStream *post_stream;
372 nsAString action_uri_str, target_str;
373 IUri *uri;
374 nsresult nsres;
375 HRESULT hres;
376
377 TRACE("(%p)->()\n", This);
378
379 if(This->element.node.doc) {
380 HTMLDocumentNode *doc = This->element.node.doc;
381 if(doc->window && doc->window->base.outer_window)
382 this_window = doc->window->base.outer_window;
383 }
384 if(!this_window) {
385 TRACE("No outer window\n");
386 return S_OK;
387 }
388
389 nsAString_Init(&target_str, NULL);
390 nsres = nsIDOMHTMLFormElement_GetTarget(This->nsform, &target_str);
391 if(NS_SUCCEEDED(nsres)) {
392 BOOL use_new_window;
393 window = get_target_window(this_window, &target_str, &use_new_window);
394 if(use_new_window)
395 FIXME("submit to new window is not supported\n");
396 }
397 nsAString_Finish(&target_str);
398 if(!window)
399 return S_OK;
400
401 /*
402 * FIXME: We currently don't use our submit implementation for sub-windows because
403 * load_nsuri can't support post data. We should fix it.
404 */
405 if(!window->doc_obj || window->doc_obj->basedoc.window != window) {
406 nsres = nsIDOMHTMLFormElement_Submit(This->nsform);
407 IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
408 if(NS_FAILED(nsres)) {
409 ERR("Submit failed: %08x\n", nsres);
410 return E_FAIL;
411 }
412
413 return S_OK;
414 }
415
416 nsAString_Init(&action_uri_str, NULL);
417 nsres = nsIDOMHTMLFormElement_GetFormData(This->nsform, NULL, &action_uri_str, &post_stream);
418 if(NS_SUCCEEDED(nsres)) {
419 const PRUnichar *action_uri;
420
421 nsAString_GetData(&action_uri_str, &action_uri);
422 hres = create_uri(action_uri, 0, &uri);
423 }else {
424 ERR("GetFormData failed: %08x\n", nsres);
425 hres = E_FAIL;
426 }
427 nsAString_Finish(&action_uri_str);
428 if(SUCCEEDED(hres)) {
429 window->readystate_locked++;
430 hres = submit_form(window, uri, post_stream);
431 window->readystate_locked--;
432 IUri_Release(uri);
433 }
434
435 IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
436 if(post_stream)
437 nsIInputStream_Release(post_stream);
438 return hres;
439 }
440
441 static HRESULT WINAPI HTMLFormElement_reset(IHTMLFormElement *iface)
442 {
443 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
444 nsresult nsres;
445
446 TRACE("(%p)->()\n", This);
447 nsres = nsIDOMHTMLFormElement_Reset(This->nsform);
448 if (NS_FAILED(nsres)) {
449 ERR("Reset failed: %08x\n", nsres);
450 return E_FAIL;
451 }
452
453 return S_OK;
454 }
455
456 static HRESULT WINAPI HTMLFormElement_put_length(IHTMLFormElement *iface, LONG v)
457 {
458 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
459 FIXME("(%p)->(%d)\n", This, v);
460 return E_NOTIMPL;
461 }
462
463 static HRESULT WINAPI HTMLFormElement_get_length(IHTMLFormElement *iface, LONG *p)
464 {
465 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
466 nsresult nsres;
467
468 TRACE("(%p)->(%p)\n", This, p);
469
470 nsres = nsIDOMHTMLFormElement_GetLength(This->nsform, p);
471 if(NS_FAILED(nsres)) {
472 ERR("GetLength failed: %08x\n", nsres);
473 return E_FAIL;
474 }
475
476 return S_OK;
477 }
478
479 static HRESULT WINAPI HTMLFormElement__newEnum(IHTMLFormElement *iface, IUnknown **p)
480 {
481 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
482 FIXME("(%p)->(%p)\n", This, p);
483 return E_NOTIMPL;
484 }
485
486 static HRESULT WINAPI HTMLFormElement_item(IHTMLFormElement *iface, VARIANT name,
487 VARIANT index, IDispatch **pdisp)
488 {
489 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
490
491 TRACE("(%p)->(%s %s %p)\n", This, debugstr_variant(&name), debugstr_variant(&index), pdisp);
492
493 if(!pdisp)
494 return E_INVALIDARG;
495 *pdisp = NULL;
496
497 if(V_VT(&name) == VT_I4) {
498 if(V_I4(&name) < 0)
499 return E_INVALIDARG;
500 return htmlform_item(This, V_I4(&name), pdisp);
501 }
502
503 FIXME("Unsupported args\n");
504 return E_NOTIMPL;
505 }
506
507 static HRESULT WINAPI HTMLFormElement_tags(IHTMLFormElement *iface, VARIANT tagName,
508 IDispatch **pdisp)
509 {
510 HTMLFormElement *This = impl_from_IHTMLFormElement(iface);
511 FIXME("(%p)->(v %p)\n", This, pdisp);
512 return E_NOTIMPL;
513 }
514
515 static const IHTMLFormElementVtbl HTMLFormElementVtbl = {
516 HTMLFormElement_QueryInterface,
517 HTMLFormElement_AddRef,
518 HTMLFormElement_Release,
519 HTMLFormElement_GetTypeInfoCount,
520 HTMLFormElement_GetTypeInfo,
521 HTMLFormElement_GetIDsOfNames,
522 HTMLFormElement_Invoke,
523 HTMLFormElement_put_action,
524 HTMLFormElement_get_action,
525 HTMLFormElement_put_dir,
526 HTMLFormElement_get_dir,
527 HTMLFormElement_put_encoding,
528 HTMLFormElement_get_encoding,
529 HTMLFormElement_put_method,
530 HTMLFormElement_get_method,
531 HTMLFormElement_get_elements,
532 HTMLFormElement_put_target,
533 HTMLFormElement_get_target,
534 HTMLFormElement_put_name,
535 HTMLFormElement_get_name,
536 HTMLFormElement_put_onsubmit,
537 HTMLFormElement_get_onsubmit,
538 HTMLFormElement_put_onreset,
539 HTMLFormElement_get_onreset,
540 HTMLFormElement_submit,
541 HTMLFormElement_reset,
542 HTMLFormElement_put_length,
543 HTMLFormElement_get_length,
544 HTMLFormElement__newEnum,
545 HTMLFormElement_item,
546 HTMLFormElement_tags
547 };
548
549 static inline HTMLFormElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface)
550 {
551 return CONTAINING_RECORD(iface, HTMLFormElement, element.node);
552 }
553
554 static HRESULT HTMLFormElement_QI(HTMLDOMNode *iface, REFIID riid, void **ppv)
555 {
556 HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
557
558 *ppv = NULL;
559
560 if(IsEqualGUID(&IID_IUnknown, riid)) {
561 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
562 *ppv = &This->IHTMLFormElement_iface;
563 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
564 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
565 *ppv = &This->IHTMLFormElement_iface;
566 }else if(IsEqualGUID(&IID_IHTMLFormElement, riid)) {
567 TRACE("(%p)->(IID_IHTMLFormElement %p)\n", This, ppv);
568 *ppv = &This->IHTMLFormElement_iface;
569 }
570
571 if(*ppv) {
572 IUnknown_AddRef((IUnknown*)*ppv);
573 return S_OK;
574 }
575
576 return HTMLElement_QI(&This->element.node, riid, ppv);
577 }
578
579 static HRESULT HTMLFormElement_get_dispid(HTMLDOMNode *iface,
580 BSTR name, DWORD grfdex, DISPID *pid)
581 {
582 HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
583 nsIDOMHTMLCollection *elements;
584 nsAString nsstr, name_str;
585 UINT32 len, i;
586 nsresult nsres;
587 HRESULT hres = DISP_E_UNKNOWNNAME;
588
589 static const PRUnichar nameW[] = {'n','a','m','e',0};
590
591 TRACE("(%p)->(%s %x %p)\n", This, wine_dbgstr_w(name), grfdex, pid);
592
593 nsres = nsIDOMHTMLFormElement_GetElements(This->nsform, &elements);
594 if(NS_FAILED(nsres)) {
595 FIXME("GetElements failed: 0x%08x\n", nsres);
596 return E_FAIL;
597 }
598
599 nsres = nsIDOMHTMLCollection_GetLength(elements, &len);
600 if(NS_FAILED(nsres)) {
601 FIXME("GetLength failed: 0x%08x\n", nsres);
602 nsIDOMHTMLCollection_Release(elements);
603 return E_FAIL;
604 }
605
606 if(len > MSHTML_CUSTOM_DISPID_CNT)
607 len = MSHTML_CUSTOM_DISPID_CNT;
608
609 /* FIXME: Implement in more generic way */
610 if('0' <= *name && *name <= '9') {
611 WCHAR *end_ptr;
612
613 i = strtoulW(name, &end_ptr, 10);
614 if(!*end_ptr && i < len) {
615 *pid = MSHTML_DISPID_CUSTOM_MIN + i;
616 return S_OK;
617 }
618 }
619
620 nsAString_Init(&nsstr, NULL);
621 for(i = 0; i < len; ++i) {
622 nsIDOMNode *nsitem;
623 nsIDOMHTMLElement *nshtml_elem;
624 const PRUnichar *str;
625
626 nsres = nsIDOMHTMLCollection_Item(elements, i, &nsitem);
627 if(NS_FAILED(nsres)) {
628 FIXME("Item failed: 0x%08x\n", nsres);
629 hres = E_FAIL;
630 break;
631 }
632
633 nsres = nsIDOMNode_QueryInterface(nsitem, &IID_nsIDOMHTMLElement, (void**)&nshtml_elem);
634 nsIDOMNode_Release(nsitem);
635 if(NS_FAILED(nsres)) {
636 FIXME("Failed to get nsIDOMHTMLNode interface: 0x%08x\n", nsres);
637 hres = E_FAIL;
638 break;
639 }
640
641 /* compare by id attr */
642 nsres = nsIDOMHTMLElement_GetId(nshtml_elem, &nsstr);
643 if(NS_FAILED(nsres)) {
644 FIXME("GetId failed: 0x%08x\n", nsres);
645 nsIDOMHTMLElement_Release(nshtml_elem);
646 hres = E_FAIL;
647 break;
648 }
649 nsAString_GetData(&nsstr, &str);
650 if(!strcmpiW(str, name)) {
651 nsIDOMHTMLElement_Release(nshtml_elem);
652 /* FIXME: using index for dispid */
653 *pid = MSHTML_DISPID_CUSTOM_MIN + i;
654 hres = S_OK;
655 break;
656 }
657
658 /* compare by name attr */
659 nsres = get_elem_attr_value(nshtml_elem, nameW, &name_str, &str);
660 nsIDOMHTMLElement_Release(nshtml_elem);
661 if(NS_SUCCEEDED(nsres)) {
662 if(!strcmpiW(str, name)) {
663 nsAString_Finish(&name_str);
664 /* FIXME: using index for dispid */
665 *pid = MSHTML_DISPID_CUSTOM_MIN + i;
666 hres = S_OK;
667 break;
668 }
669 nsAString_Finish(&name_str);
670 }
671 }
672
673 nsAString_Finish(&nsstr);
674 nsIDOMHTMLCollection_Release(elements);
675 return hres;
676 }
677
678 static HRESULT HTMLFormElement_invoke(HTMLDOMNode *iface,
679 DISPID id, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res,
680 EXCEPINFO *ei, IServiceProvider *caller)
681 {
682 HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
683 IDispatch *ret;
684 HRESULT hres;
685
686 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
687
688 hres = htmlform_item(This, id - MSHTML_DISPID_CUSTOM_MIN, &ret);
689 if(FAILED(hres))
690 return hres;
691
692 if(ret) {
693 V_VT(res) = VT_DISPATCH;
694 V_DISPATCH(res) = ret;
695 }else {
696 V_VT(res) = VT_NULL;
697 }
698 return S_OK;
699 }
700
701 static HRESULT HTMLFormElement_handle_event(HTMLDOMNode *iface, eventid_t eid, nsIDOMEvent *event, BOOL *prevent_default)
702 {
703 HTMLFormElement *This = impl_from_HTMLDOMNode(iface);
704
705 if(eid == EVENTID_SUBMIT) {
706 *prevent_default = TRUE;
707 return IHTMLFormElement_submit(&This->IHTMLFormElement_iface);
708 }
709
710 return HTMLElement_handle_event(&This->element.node, eid, event, prevent_default);
711 }
712
713 static const NodeImplVtbl HTMLFormElementImplVtbl = {
714 HTMLFormElement_QI,
715 HTMLElement_destructor,
716 HTMLElement_cpc,
717 HTMLElement_clone,
718 HTMLFormElement_handle_event,
719 HTMLElement_get_attr_col,
720 NULL,
721 NULL,
722 NULL,
723 NULL,
724 NULL,
725 NULL,
726 HTMLFormElement_get_dispid,
727 HTMLFormElement_invoke
728 };
729
730 static const tid_t HTMLFormElement_iface_tids[] = {
731 HTMLELEMENT_TIDS,
732 IHTMLFormElement_tid,
733 0
734 };
735
736 static dispex_static_data_t HTMLFormElement_dispex = {
737 NULL,
738 DispHTMLFormElement_tid,
739 NULL,
740 HTMLFormElement_iface_tids
741 };
742
743 HRESULT HTMLFormElement_Create(HTMLDocumentNode *doc, nsIDOMHTMLElement *nselem, HTMLElement **elem)
744 {
745 HTMLFormElement *ret;
746 nsresult nsres;
747
748 ret = heap_alloc_zero(sizeof(HTMLFormElement));
749 if(!ret)
750 return E_OUTOFMEMORY;
751
752 ret->IHTMLFormElement_iface.lpVtbl = &HTMLFormElementVtbl;
753 ret->element.node.vtbl = &HTMLFormElementImplVtbl;
754
755 HTMLElement_Init(&ret->element, doc, nselem, &HTMLFormElement_dispex);
756
757 nsres = nsIDOMHTMLElement_QueryInterface(nselem, &IID_nsIDOMHTMLFormElement, (void**)&ret->nsform);
758
759 /* Share the reference with nsnode */
760 assert(nsres == NS_OK && (nsIDOMNode*)ret->nsform == ret->element.node.nsnode);
761 nsIDOMNode_Release(ret->element.node.nsnode);
762
763 *elem = &ret->element;
764 return S_OK;
765 }