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