2 * Copyright 2009 Andrew Eikum for CodeWeavers
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.
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.
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
28 #include "wine/debug.h"
30 #include "mshtml_private.h"
31 #include "htmlevent.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
36 struct HTMLFormElement
{
39 IHTMLFormElement IHTMLFormElement_iface
;
41 nsIDOMHTMLFormElement
*nsform
;
45 IEnumVARIANT IEnumVARIANT_iface
;
50 HTMLFormElement
*elem
;
51 } HTMLFormElementEnum
;
53 HRESULT
return_nsform(nsresult nsres
, nsIDOMHTMLFormElement
*form
, IHTMLFormElement
**p
)
55 nsIDOMNode
*form_node
;
59 if (NS_FAILED(nsres
)) {
60 ERR("GetForm failed: %08lx\n", nsres
);
70 nsres
= nsIDOMHTMLFormElement_QueryInterface(form
, &IID_nsIDOMNode
, (void**)&form_node
);
71 nsIDOMHTMLFormElement_Release(form
);
72 assert(nsres
== NS_OK
);
74 hres
= get_node(form_node
, TRUE
, &node
);
75 nsIDOMNode_Release(form_node
);
79 TRACE("node %p\n", node
);
80 hres
= IHTMLDOMNode_QueryInterface(&node
->IHTMLDOMNode_iface
, &IID_IHTMLFormElement
, (void**)p
);
85 static HRESULT
htmlform_item(HTMLFormElement
*This
, int i
, IDispatch
**ret
)
87 nsIDOMHTMLCollection
*elements
;
93 nsres
= nsIDOMHTMLFormElement_GetElements(This
->nsform
, &elements
);
94 if(NS_FAILED(nsres
)) {
95 FIXME("GetElements failed: 0x%08lx\n", nsres
);
99 nsres
= nsIDOMHTMLCollection_Item(elements
, i
, &item
);
100 nsIDOMHTMLCollection_Release(elements
);
101 if(NS_FAILED(nsres
)) {
102 FIXME("Item failed: 0x%08lx\n", nsres
);
107 hres
= get_node(item
, TRUE
, &node
);
111 nsIDOMNode_Release(item
);
112 *ret
= (IDispatch
*)&node
->IHTMLDOMNode_iface
;
120 static inline HTMLFormElementEnum
*impl_from_IEnumVARIANT(IEnumVARIANT
*iface
)
122 return CONTAINING_RECORD(iface
, HTMLFormElementEnum
, IEnumVARIANT_iface
);
125 static HRESULT WINAPI
HTMLFormElementEnum_QueryInterface(IEnumVARIANT
*iface
, REFIID riid
, void **ppv
)
127 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
129 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
131 if(IsEqualGUID(riid
, &IID_IUnknown
)) {
132 *ppv
= &This
->IEnumVARIANT_iface
;
133 }else if(IsEqualGUID(riid
, &IID_IEnumVARIANT
)) {
134 *ppv
= &This
->IEnumVARIANT_iface
;
136 FIXME("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
138 return E_NOINTERFACE
;
141 IUnknown_AddRef((IUnknown
*)*ppv
);
145 static ULONG WINAPI
HTMLFormElementEnum_AddRef(IEnumVARIANT
*iface
)
147 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
148 LONG ref
= InterlockedIncrement(&This
->ref
);
150 TRACE("(%p) ref=%ld\n", This
, ref
);
155 static ULONG WINAPI
HTMLFormElementEnum_Release(IEnumVARIANT
*iface
)
157 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
158 LONG ref
= InterlockedDecrement(&This
->ref
);
160 TRACE("(%p) ref=%ld\n", This
, ref
);
163 IHTMLFormElement_Release(&This
->elem
->IHTMLFormElement_iface
);
170 static HRESULT WINAPI
HTMLFormElementEnum_Next(IEnumVARIANT
*iface
, ULONG celt
, VARIANT
*rgVar
, ULONG
*pCeltFetched
)
172 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
178 TRACE("(%p)->(%lu %p %p)\n", This
, celt
, rgVar
, pCeltFetched
);
180 nsres
= nsIDOMHTMLFormElement_GetLength(This
->elem
->nsform
, &len
);
183 num
= min(len
- This
->iter
, celt
);
185 for(i
= 0; i
< num
; i
++) {
186 hres
= htmlform_item(This
->elem
, This
->iter
+ i
, &V_DISPATCH(&rgVar
[i
]));
189 VariantClear(&rgVar
[i
]);
192 V_VT(&rgVar
[i
]) = VT_DISPATCH
;
198 return num
== celt
? S_OK
: S_FALSE
;
201 static HRESULT WINAPI
HTMLFormElementEnum_Skip(IEnumVARIANT
*iface
, ULONG celt
)
203 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
207 TRACE("(%p)->(%lu)\n", This
, celt
);
209 nsres
= nsIDOMHTMLFormElement_GetLength(This
->elem
->nsform
, &len
);
213 if(This
->iter
+ celt
> len
) {
222 static HRESULT WINAPI
HTMLFormElementEnum_Reset(IEnumVARIANT
*iface
)
224 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
226 TRACE("(%p)->()\n", This
);
232 static HRESULT WINAPI
HTMLFormElementEnum_Clone(IEnumVARIANT
*iface
, IEnumVARIANT
**ppEnum
)
234 HTMLFormElementEnum
*This
= impl_from_IEnumVARIANT(iface
);
235 FIXME("(%p)->(%p)\n", This
, ppEnum
);
239 static const IEnumVARIANTVtbl HTMLFormElementEnumVtbl
= {
240 HTMLFormElementEnum_QueryInterface
,
241 HTMLFormElementEnum_AddRef
,
242 HTMLFormElementEnum_Release
,
243 HTMLFormElementEnum_Next
,
244 HTMLFormElementEnum_Skip
,
245 HTMLFormElementEnum_Reset
,
246 HTMLFormElementEnum_Clone
249 static inline HTMLFormElement
*impl_from_IHTMLFormElement(IHTMLFormElement
*iface
)
251 return CONTAINING_RECORD(iface
, HTMLFormElement
, IHTMLFormElement_iface
);
254 static HRESULT WINAPI
HTMLFormElement_QueryInterface(IHTMLFormElement
*iface
,
255 REFIID riid
, void **ppv
)
257 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
259 return IHTMLDOMNode_QueryInterface(&This
->element
.node
.IHTMLDOMNode_iface
, riid
, ppv
);
262 static ULONG WINAPI
HTMLFormElement_AddRef(IHTMLFormElement
*iface
)
264 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
266 return IHTMLDOMNode_AddRef(&This
->element
.node
.IHTMLDOMNode_iface
);
269 static ULONG WINAPI
HTMLFormElement_Release(IHTMLFormElement
*iface
)
271 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
273 return IHTMLDOMNode_Release(&This
->element
.node
.IHTMLDOMNode_iface
);
276 static HRESULT WINAPI
HTMLFormElement_GetTypeInfoCount(IHTMLFormElement
*iface
, UINT
*pctinfo
)
278 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
279 return IDispatchEx_GetTypeInfoCount(&This
->element
.node
.event_target
.dispex
.IDispatchEx_iface
, pctinfo
);
282 static HRESULT WINAPI
HTMLFormElement_GetTypeInfo(IHTMLFormElement
*iface
, UINT iTInfo
,
283 LCID lcid
, ITypeInfo
**ppTInfo
)
285 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
286 return IDispatchEx_GetTypeInfo(&This
->element
.node
.event_target
.dispex
.IDispatchEx_iface
, iTInfo
, lcid
,
290 static HRESULT WINAPI
HTMLFormElement_GetIDsOfNames(IHTMLFormElement
*iface
, REFIID riid
,
291 LPOLESTR
*rgszNames
, UINT cNames
,
292 LCID lcid
, DISPID
*rgDispId
)
294 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
295 return IDispatchEx_GetIDsOfNames(&This
->element
.node
.event_target
.dispex
.IDispatchEx_iface
, riid
, rgszNames
,
296 cNames
, lcid
, rgDispId
);
299 static HRESULT WINAPI
HTMLFormElement_Invoke(IHTMLFormElement
*iface
, DISPID dispIdMember
,
300 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
301 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
303 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
304 return IDispatchEx_Invoke(&This
->element
.node
.event_target
.dispex
.IDispatchEx_iface
, dispIdMember
, riid
,
305 lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
308 static HRESULT WINAPI
HTMLFormElement_put_action(IHTMLFormElement
*iface
, BSTR v
)
310 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
311 nsAString action_str
;
314 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
316 nsAString_InitDepend(&action_str
, v
);
317 nsres
= nsIDOMHTMLFormElement_SetAction(This
->nsform
, &action_str
);
318 nsAString_Finish(&action_str
);
319 if(NS_FAILED(nsres
)) {
320 ERR("SetAction failed: %08lx\n", nsres
);
327 static HRESULT WINAPI
HTMLFormElement_get_action(IHTMLFormElement
*iface
, BSTR
*p
)
329 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
330 nsAString action_str
;
334 TRACE("(%p)->(%p)\n", This
, p
);
336 nsAString_Init(&action_str
, NULL
);
337 nsres
= nsIDOMHTMLFormElement_GetAction(This
->nsform
, &action_str
);
338 if(NS_SUCCEEDED(nsres
)) {
339 const PRUnichar
*action
;
340 nsAString_GetData(&action_str
, &action
);
341 hres
= nsuri_to_url(action
, FALSE
, p
);
343 ERR("GetAction failed: %08lx\n", nsres
);
347 nsAString_Finish(&action_str
);
351 static HRESULT WINAPI
HTMLFormElement_put_dir(IHTMLFormElement
*iface
, BSTR v
)
353 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
354 FIXME("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
358 static HRESULT WINAPI
HTMLFormElement_get_dir(IHTMLFormElement
*iface
, BSTR
*p
)
360 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
361 FIXME("(%p)->(%p)\n", This
, p
);
365 static HRESULT WINAPI
HTMLFormElement_put_encoding(IHTMLFormElement
*iface
, BSTR v
)
367 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
368 nsAString encoding_str
;
371 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
373 if(lstrcmpiW(v
, L
"application/x-www-form-urlencoded") && lstrcmpiW(v
, L
"multipart/form-data")
374 && lstrcmpiW(v
, L
"text/plain")) {
375 WARN("incorrect enctype\n");
379 nsAString_InitDepend(&encoding_str
, v
);
380 nsres
= nsIDOMHTMLFormElement_SetEnctype(This
->nsform
, &encoding_str
);
381 nsAString_Finish(&encoding_str
);
388 static HRESULT WINAPI
HTMLFormElement_get_encoding(IHTMLFormElement
*iface
, BSTR
*p
)
390 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
391 nsAString encoding_str
;
394 TRACE("(%p)->(%p)\n", This
, p
);
396 nsAString_Init(&encoding_str
, NULL
);
397 nsres
= nsIDOMHTMLFormElement_GetEnctype(This
->nsform
, &encoding_str
);
398 return return_nsstr(nsres
, &encoding_str
, p
);
401 static HRESULT WINAPI
HTMLFormElement_put_method(IHTMLFormElement
*iface
, BSTR v
)
403 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
404 nsAString method_str
;
407 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
409 if(lstrcmpiW(v
, L
"POST") && lstrcmpiW(v
, L
"GET")) {
410 WARN("unrecognized method\n");
414 nsAString_InitDepend(&method_str
, v
);
415 nsres
= nsIDOMHTMLFormElement_SetMethod(This
->nsform
, &method_str
);
416 nsAString_Finish(&method_str
);
423 static HRESULT WINAPI
HTMLFormElement_get_method(IHTMLFormElement
*iface
, BSTR
*p
)
425 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
426 nsAString method_str
;
429 TRACE("(%p)->(%p)\n", This
, p
);
431 nsAString_Init(&method_str
, NULL
);
432 nsres
= nsIDOMHTMLFormElement_GetMethod(This
->nsform
, &method_str
);
433 return return_nsstr(nsres
, &method_str
, p
);
436 static HRESULT WINAPI
HTMLFormElement_get_elements(IHTMLFormElement
*iface
, IDispatch
**p
)
438 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
439 nsIDOMHTMLCollection
*elements
;
442 TRACE("(%p)->(%p)\n", This
, p
);
444 if(dispex_compat_mode(&This
->element
.node
.event_target
.dispex
) < COMPAT_MODE_IE9
) {
445 IDispatch_AddRef(*p
= (IDispatch
*)&This
->IHTMLFormElement_iface
);
449 nsres
= nsIDOMHTMLFormElement_GetElements(This
->nsform
, &elements
);
450 if(NS_FAILED(nsres
)) {
451 ERR("GetElements failed: %08lx\n", nsres
);
455 *p
= (IDispatch
*)create_collection_from_htmlcol(elements
, dispex_compat_mode(&This
->element
.node
.event_target
.dispex
));
456 nsIDOMHTMLCollection_Release(elements
);
460 static HRESULT WINAPI
HTMLFormElement_put_target(IHTMLFormElement
*iface
, BSTR v
)
462 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
466 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
468 nsAString_InitDepend(&str
, v
);
470 nsres
= nsIDOMHTMLFormElement_SetTarget(This
->nsform
, &str
);
472 nsAString_Finish(&str
);
473 if (NS_FAILED(nsres
)) {
474 ERR("Set Target(%s) failed: %08lx\n", wine_dbgstr_w(v
), nsres
);
481 static HRESULT WINAPI
HTMLFormElement_get_target(IHTMLFormElement
*iface
, BSTR
*p
)
483 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
487 TRACE("(%p)->(%p)\n", This
, p
);
489 nsAString_Init(&str
, NULL
);
490 nsres
= nsIDOMHTMLFormElement_GetTarget(This
->nsform
, &str
);
492 return return_nsstr(nsres
, &str
, p
);
495 static HRESULT WINAPI
HTMLFormElement_put_name(IHTMLFormElement
*iface
, BSTR v
)
497 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
501 TRACE("(%p)->(%s)\n", This
, wine_dbgstr_w(v
));
503 nsAString_InitDepend(&name_str
, v
);
504 nsres
= nsIDOMHTMLFormElement_SetName(This
->nsform
, &name_str
);
505 nsAString_Finish(&name_str
);
512 static HRESULT WINAPI
HTMLFormElement_get_name(IHTMLFormElement
*iface
, BSTR
*p
)
514 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
518 TRACE("(%p)->(%p)\n", This
, p
);
520 nsAString_Init(&name_str
, NULL
);
521 nsres
= nsIDOMHTMLFormElement_GetName(This
->nsform
, &name_str
);
522 return return_nsstr(nsres
, &name_str
, p
);
525 static HRESULT WINAPI
HTMLFormElement_put_onsubmit(IHTMLFormElement
*iface
, VARIANT v
)
527 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
529 TRACE("(%p)->(%s)\n", This
, debugstr_variant(&v
));
531 return set_node_event(&This
->element
.node
, EVENTID_SUBMIT
, &v
);
534 static HRESULT WINAPI
HTMLFormElement_get_onsubmit(IHTMLFormElement
*iface
, VARIANT
*p
)
536 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
538 TRACE("(%p)->(%p)\n", This
, p
);
540 return get_node_event(&This
->element
.node
, EVENTID_SUBMIT
, p
);
543 static HRESULT WINAPI
HTMLFormElement_put_onreset(IHTMLFormElement
*iface
, VARIANT v
)
545 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
546 FIXME("(%p)->(%s)\n", This
, debugstr_variant(&v
));
550 static HRESULT WINAPI
HTMLFormElement_get_onreset(IHTMLFormElement
*iface
, VARIANT
*p
)
552 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
553 FIXME("(%p)->(%p)\n", This
, p
);
557 static HRESULT WINAPI
HTMLFormElement_submit(IHTMLFormElement
*iface
)
559 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
560 HTMLOuterWindow
*window
= NULL
, *this_window
= NULL
;
561 nsAString action_uri_str
, target_str
, method_str
;
562 nsIInputStream
*post_stream
;
563 BOOL is_post_submit
= FALSE
;
567 BOOL use_new_window
= FALSE
;
569 TRACE("(%p)\n", This
);
571 if(This
->element
.node
.doc
) {
572 HTMLDocumentNode
*doc
= This
->element
.node
.doc
;
573 if(doc
->window
&& doc
->window
->base
.outer_window
)
574 this_window
= doc
->window
->base
.outer_window
;
577 TRACE("No outer window\n");
581 nsAString_Init(&target_str
, NULL
);
582 nsres
= nsIDOMHTMLFormElement_GetTarget(This
->nsform
, &target_str
);
583 if(NS_SUCCEEDED(nsres
))
584 window
= get_target_window(this_window
, &target_str
, &use_new_window
);
586 if(!window
&& !use_new_window
) {
587 nsAString_Finish(&target_str
);
591 nsAString_Init(&method_str
, NULL
);
592 nsres
= nsIDOMHTMLFormElement_GetMethod(This
->nsform
, &method_str
);
593 if(NS_SUCCEEDED(nsres
)) {
594 const PRUnichar
*method
;
596 nsAString_GetData(&method_str
, &method
);
597 TRACE("method is %s\n", debugstr_w(method
));
598 is_post_submit
= !wcsicmp(method
, L
"post");
600 nsAString_Finish(&method_str
);
603 * FIXME: We currently use our submit implementation for POST submit. We should always use it.
605 if(window
&& !is_post_submit
) {
606 nsres
= nsIDOMHTMLFormElement_Submit(This
->nsform
);
607 nsAString_Finish(&target_str
);
608 IHTMLWindow2_Release(&window
->base
.IHTMLWindow2_iface
);
609 if(NS_FAILED(nsres
)) {
610 ERR("Submit failed: %08lx\n", nsres
);
617 nsAString_Init(&action_uri_str
, NULL
);
618 nsres
= nsIDOMHTMLFormElement_GetFormData(This
->nsform
, NULL
, &action_uri_str
, &post_stream
);
619 if(NS_SUCCEEDED(nsres
)) {
620 const PRUnichar
*action_uri
;
622 nsAString_GetData(&action_uri_str
, &action_uri
);
623 hres
= create_uri(action_uri
, 0, &uri
);
625 ERR("GetFormData failed: %08lx\n", nsres
);
628 nsAString_Finish(&action_uri_str
);
629 if(SUCCEEDED(hres
)) {
630 const PRUnichar
*target
;
632 nsAString_GetData(&target_str
, &target
);
633 hres
= submit_form(window
, target
, uri
, post_stream
);
637 nsAString_Finish(&target_str
);
639 IHTMLWindow2_Release(&window
->base
.IHTMLWindow2_iface
);
641 nsIInputStream_Release(post_stream
);
645 static HRESULT WINAPI
HTMLFormElement_reset(IHTMLFormElement
*iface
)
647 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
650 TRACE("(%p)->()\n", This
);
651 nsres
= nsIDOMHTMLFormElement_Reset(This
->nsform
);
652 if (NS_FAILED(nsres
)) {
653 ERR("Reset failed: %08lx\n", nsres
);
660 static HRESULT WINAPI
HTMLFormElement_put_length(IHTMLFormElement
*iface
, LONG v
)
662 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
663 FIXME("(%p)->(%ld)\n", This
, v
);
667 static HRESULT WINAPI
HTMLFormElement_get_length(IHTMLFormElement
*iface
, LONG
*p
)
669 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
672 TRACE("(%p)->(%p)\n", This
, p
);
674 nsres
= nsIDOMHTMLFormElement_GetLength(This
->nsform
, p
);
675 if(NS_FAILED(nsres
)) {
676 ERR("GetLength failed: %08lx\n", nsres
);
683 static HRESULT WINAPI
HTMLFormElement__newEnum(IHTMLFormElement
*iface
, IUnknown
**p
)
685 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
686 HTMLFormElementEnum
*ret
;
688 TRACE("(%p)->(%p)\n", This
, p
);
690 ret
= heap_alloc(sizeof(*ret
));
692 return E_OUTOFMEMORY
;
694 ret
->IEnumVARIANT_iface
.lpVtbl
= &HTMLFormElementEnumVtbl
;
698 HTMLFormElement_AddRef(&This
->IHTMLFormElement_iface
);
701 *p
= (IUnknown
*)&ret
->IEnumVARIANT_iface
;
705 static HRESULT WINAPI
HTMLFormElement_item(IHTMLFormElement
*iface
, VARIANT name
,
706 VARIANT index
, IDispatch
**pdisp
)
708 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
710 TRACE("(%p)->(%s %s %p)\n", This
, debugstr_variant(&name
), debugstr_variant(&index
), pdisp
);
716 if(V_VT(&name
) == VT_I4
) {
717 if(V_I4(&name
) < 0) {
719 return dispex_compat_mode(&This
->element
.node
.event_target
.dispex
) >= COMPAT_MODE_IE9
720 ? S_OK
: E_INVALIDARG
;
722 return htmlform_item(This
, V_I4(&name
), pdisp
);
725 FIXME("Unsupported args\n");
729 static HRESULT WINAPI
HTMLFormElement_tags(IHTMLFormElement
*iface
, VARIANT tagName
,
732 HTMLFormElement
*This
= impl_from_IHTMLFormElement(iface
);
733 FIXME("(%p)->(v %p)\n", This
, pdisp
);
737 static const IHTMLFormElementVtbl HTMLFormElementVtbl
= {
738 HTMLFormElement_QueryInterface
,
739 HTMLFormElement_AddRef
,
740 HTMLFormElement_Release
,
741 HTMLFormElement_GetTypeInfoCount
,
742 HTMLFormElement_GetTypeInfo
,
743 HTMLFormElement_GetIDsOfNames
,
744 HTMLFormElement_Invoke
,
745 HTMLFormElement_put_action
,
746 HTMLFormElement_get_action
,
747 HTMLFormElement_put_dir
,
748 HTMLFormElement_get_dir
,
749 HTMLFormElement_put_encoding
,
750 HTMLFormElement_get_encoding
,
751 HTMLFormElement_put_method
,
752 HTMLFormElement_get_method
,
753 HTMLFormElement_get_elements
,
754 HTMLFormElement_put_target
,
755 HTMLFormElement_get_target
,
756 HTMLFormElement_put_name
,
757 HTMLFormElement_get_name
,
758 HTMLFormElement_put_onsubmit
,
759 HTMLFormElement_get_onsubmit
,
760 HTMLFormElement_put_onreset
,
761 HTMLFormElement_get_onreset
,
762 HTMLFormElement_submit
,
763 HTMLFormElement_reset
,
764 HTMLFormElement_put_length
,
765 HTMLFormElement_get_length
,
766 HTMLFormElement__newEnum
,
767 HTMLFormElement_item
,
771 static inline HTMLFormElement
*impl_from_HTMLDOMNode(HTMLDOMNode
*iface
)
773 return CONTAINING_RECORD(iface
, HTMLFormElement
, element
.node
);
776 static HRESULT
HTMLFormElement_QI(HTMLDOMNode
*iface
, REFIID riid
, void **ppv
)
778 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
782 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
783 TRACE("(%p)->(IID_IUnknown %p)\n", This
, ppv
);
784 *ppv
= &This
->IHTMLFormElement_iface
;
785 }else if(IsEqualGUID(&IID_IDispatch
, riid
)) {
786 TRACE("(%p)->(IID_IDispatch %p)\n", This
, ppv
);
787 *ppv
= &This
->IHTMLFormElement_iface
;
788 }else if(IsEqualGUID(&IID_IHTMLFormElement
, riid
)) {
789 TRACE("(%p)->(IID_IHTMLFormElement %p)\n", This
, ppv
);
790 *ppv
= &This
->IHTMLFormElement_iface
;
791 }else if(IsEqualGUID(&DIID_DispHTMLFormElement
, riid
)) {
792 TRACE("(%p)->(DIID_DispHTMLFormElement %p)\n", This
, ppv
);
793 *ppv
= &This
->IHTMLFormElement_iface
;
797 IUnknown_AddRef((IUnknown
*)*ppv
);
801 return HTMLElement_QI(&This
->element
.node
, riid
, ppv
);
804 static HRESULT
HTMLFormElement_get_dispid(HTMLDOMNode
*iface
,
805 BSTR name
, DWORD grfdex
, DISPID
*pid
)
807 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
808 nsIDOMHTMLCollection
*elements
;
809 nsAString nsstr
, name_str
;
812 HRESULT hres
= DISP_E_UNKNOWNNAME
;
814 TRACE("(%p)->(%s %lx %p)\n", This
, wine_dbgstr_w(name
), grfdex
, pid
);
816 nsres
= nsIDOMHTMLFormElement_GetElements(This
->nsform
, &elements
);
817 if(NS_FAILED(nsres
)) {
818 FIXME("GetElements failed: 0x%08lx\n", nsres
);
822 nsres
= nsIDOMHTMLCollection_GetLength(elements
, &len
);
823 if(NS_FAILED(nsres
)) {
824 FIXME("GetLength failed: 0x%08lx\n", nsres
);
825 nsIDOMHTMLCollection_Release(elements
);
829 if(len
> MSHTML_CUSTOM_DISPID_CNT
)
830 len
= MSHTML_CUSTOM_DISPID_CNT
;
832 /* FIXME: Implement in more generic way */
833 if('0' <= *name
&& *name
<= '9') {
836 i
= wcstoul(name
, &end_ptr
, 10);
837 if(!*end_ptr
&& i
< len
) {
838 *pid
= MSHTML_DISPID_CUSTOM_MIN
+ i
;
843 nsAString_Init(&nsstr
, NULL
);
844 for(i
= 0; i
< len
; ++i
) {
847 const PRUnichar
*str
;
849 nsres
= nsIDOMHTMLCollection_Item(elements
, i
, &nsitem
);
850 if(NS_FAILED(nsres
)) {
851 FIXME("Item failed: 0x%08lx\n", nsres
);
856 nsres
= nsIDOMNode_QueryInterface(nsitem
, &IID_nsIDOMElement
, (void**)&elem
);
857 nsIDOMNode_Release(nsitem
);
858 if(NS_FAILED(nsres
)) {
859 FIXME("Failed to get nsIDOMHTMLNode interface: 0x%08lx\n", nsres
);
864 /* compare by id attr */
865 nsres
= nsIDOMElement_GetId(elem
, &nsstr
);
866 if(NS_FAILED(nsres
)) {
867 FIXME("GetId failed: 0x%08lx\n", nsres
);
868 nsIDOMElement_Release(elem
);
872 nsAString_GetData(&nsstr
, &str
);
873 if(!wcsicmp(str
, name
)) {
874 nsIDOMElement_Release(elem
);
875 /* FIXME: using index for dispid */
876 *pid
= MSHTML_DISPID_CUSTOM_MIN
+ i
;
881 /* compare by name attr */
882 nsres
= get_elem_attr_value(elem
, L
"name", &name_str
, &str
);
883 nsIDOMElement_Release(elem
);
884 if(NS_SUCCEEDED(nsres
)) {
885 if(!wcsicmp(str
, name
)) {
886 nsAString_Finish(&name_str
);
887 /* FIXME: using index for dispid */
888 *pid
= MSHTML_DISPID_CUSTOM_MIN
+ i
;
892 nsAString_Finish(&name_str
);
896 nsAString_Finish(&nsstr
);
897 nsIDOMHTMLCollection_Release(elements
);
901 static HRESULT
HTMLFormElement_dispex_get_name(HTMLDOMNode
*iface
, DISPID id
, BSTR
*name
)
903 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
904 DWORD idx
= id
- MSHTML_DISPID_CUSTOM_MIN
;
905 nsIDOMHTMLCollection
*elements
;
910 nsres
= nsIDOMHTMLFormElement_GetElements(This
->nsform
, &elements
);
912 return map_nsresult(nsres
);
914 nsres
= nsIDOMHTMLCollection_GetLength(elements
, &len
);
915 nsIDOMHTMLCollection_Release(elements
);
917 return map_nsresult(nsres
);
920 return DISP_E_MEMBERNOTFOUND
;
922 len
= swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", idx
);
923 return (*name
= SysAllocStringLen(buf
, len
)) ? S_OK
: E_OUTOFMEMORY
;
926 static HRESULT
HTMLFormElement_invoke(HTMLDOMNode
*iface
,
927 DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
, VARIANT
*res
,
928 EXCEPINFO
*ei
, IServiceProvider
*caller
)
930 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
934 TRACE("(%p)->(%lx %lx %x %p %p %p %p)\n", This
, id
, lcid
, flags
, params
, res
, ei
, caller
);
936 hres
= htmlform_item(This
, id
- MSHTML_DISPID_CUSTOM_MIN
, &ret
);
941 V_VT(res
) = VT_DISPATCH
;
942 V_DISPATCH(res
) = ret
;
949 static HRESULT
HTMLFormElement_handle_event(HTMLDOMNode
*iface
, DWORD eid
, nsIDOMEvent
*event
, BOOL
*prevent_default
)
951 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
953 if(eid
== EVENTID_SUBMIT
) {
954 *prevent_default
= TRUE
;
955 return IHTMLFormElement_submit(&This
->IHTMLFormElement_iface
);
958 return HTMLElement_handle_event(&This
->element
.node
, eid
, event
, prevent_default
);
961 static void HTMLFormElement_traverse(HTMLDOMNode
*iface
, nsCycleCollectionTraversalCallback
*cb
)
963 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
966 note_cc_edge((nsISupports
*)This
->nsform
, "This->nsform", cb
);
969 static void HTMLFormElement_unlink(HTMLDOMNode
*iface
)
971 HTMLFormElement
*This
= impl_from_HTMLDOMNode(iface
);
974 nsIDOMHTMLFormElement
*nsform
= This
->nsform
;
977 nsIDOMHTMLFormElement_Release(nsform
);
981 static const NodeImplVtbl HTMLFormElementImplVtbl
= {
982 &CLSID_HTMLFormElement
,
984 HTMLElement_destructor
,
987 HTMLFormElement_handle_event
,
988 HTMLElement_get_attr_col
,
994 HTMLFormElement_get_dispid
,
995 HTMLFormElement_dispex_get_name
,
996 HTMLFormElement_invoke
,
998 HTMLFormElement_traverse
,
999 HTMLFormElement_unlink
1002 static const tid_t HTMLFormElement_iface_tids
[] = {
1004 IHTMLFormElement_tid
,
1008 static dispex_static_data_t HTMLFormElement_dispex
= {
1011 DispHTMLFormElement_tid
,
1012 HTMLFormElement_iface_tids
,
1013 HTMLElement_init_dispex_info
1016 HRESULT
HTMLFormElement_Create(HTMLDocumentNode
*doc
, nsIDOMElement
*nselem
, HTMLElement
**elem
)
1018 HTMLFormElement
*ret
;
1021 ret
= heap_alloc_zero(sizeof(HTMLFormElement
));
1023 return E_OUTOFMEMORY
;
1025 ret
->IHTMLFormElement_iface
.lpVtbl
= &HTMLFormElementVtbl
;
1026 ret
->element
.node
.vtbl
= &HTMLFormElementImplVtbl
;
1028 HTMLElement_Init(&ret
->element
, doc
, nselem
, &HTMLFormElement_dispex
);
1030 nsres
= nsIDOMElement_QueryInterface(nselem
, &IID_nsIDOMHTMLFormElement
, (void**)&ret
->nsform
);
1031 assert(nsres
== NS_OK
);
1033 *elem
= &ret
->element
;