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.event_target.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.event_target.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.event_target.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.event_target.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 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 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 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 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 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 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 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 565 static inline HTMLFormElement *impl_from_HTMLDOMNode(HTMLDOMNode *iface) 566 { 567 return CONTAINING_RECORD(iface, HTMLFormElement, element.node); 568 } 569 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 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 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 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 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 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 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