Release 1.5.29.
[wine] / dlls / mshtml / tests / events.c
1 /*
2  * Copyright 2008-2011 Jacek Caban 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 #define COBJMACROS
20 #define CONST_VTABLE
21
22 #include <wine/test.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ole2.h"
29 #include "mshtml.h"
30 #include "mshtmdid.h"
31 #include "docobj.h"
32 #include "hlink.h"
33 #include "dispex.h"
34
35 #define DEFINE_EXPECT(func) \
36     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37
38 #define SET_EXPECT(func) \
39     do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
40
41 #define CHECK_EXPECT2(func) \
42     do { \
43     trace(#func "\n"); \
44         ok(expect_ ##func, "unexpected call " #func "\n"); \
45         called_ ## func = TRUE; \
46     }while(0)
47
48 #define CHECK_EXPECT(func) \
49     do { \
50         CHECK_EXPECT2(func); \
51         expect_ ## func = FALSE; \
52     }while(0)
53
54 #define CHECK_CALLED(func) \
55     do { \
56         ok(called_ ## func, "expected " #func "\n"); \
57         expect_ ## func = called_ ## func = FALSE; \
58     }while(0)
59
60 DEFINE_EXPECT(document_onclick);
61 DEFINE_EXPECT(body_onclick);
62 DEFINE_EXPECT(doc_onclick_attached);
63 DEFINE_EXPECT(div_onclick);
64 DEFINE_EXPECT(div_onclick_attached);
65 DEFINE_EXPECT(timeout);
66 DEFINE_EXPECT(doccp_onclick);
67 DEFINE_EXPECT(doccp_onclick_cancel);
68 DEFINE_EXPECT(div_onclick_disp);
69 DEFINE_EXPECT(invoke_onclick);
70 DEFINE_EXPECT(iframe_onreadystatechange_loading);
71 DEFINE_EXPECT(iframe_onreadystatechange_interactive);
72 DEFINE_EXPECT(iframe_onreadystatechange_complete);
73 DEFINE_EXPECT(iframedoc_onreadystatechange);
74 DEFINE_EXPECT(img_onload);
75 DEFINE_EXPECT(img_onerror);
76 DEFINE_EXPECT(input_onfocus);
77 DEFINE_EXPECT(input_onblur);
78 DEFINE_EXPECT(form_onsubmit);
79 DEFINE_EXPECT(form_onclick);
80 DEFINE_EXPECT(submit_onclick);
81 DEFINE_EXPECT(submit_onclick_cancel);
82 DEFINE_EXPECT(submit_onclick_attached);
83 DEFINE_EXPECT(submit_onclick_attached_check_cancel);
84 DEFINE_EXPECT(submit_onclick_setret);
85 DEFINE_EXPECT(elem2_cp_onclick);
86
87 static HWND container_hwnd = NULL;
88 static IHTMLWindow2 *window;
89 static IOleDocumentView *view;
90 static BOOL xy_todo;
91
92 typedef struct {
93     LONG x;
94     LONG y;
95     LONG offset_x;
96     LONG offset_y;
97 } xy_test_t;
98
99 static const xy_test_t no_xy = {-10,-10,-10,-10};
100 static const xy_test_t zero_xy = {0,0,0,0};
101
102 static const char empty_doc_str[] =
103     "<html></html>";
104
105 static const char click_doc_str[] =
106     "<html><body>"
107     "<div id=\"clickdiv\" style=\"text-align: center; background: red; font-size: 32\">click here</div>"
108     "</body></html>";
109
110 static const char readystate_doc_str[] =
111     "<html><body><iframe id=\"iframe\"></iframe></body></html>";
112
113 static const char img_doc_str[] =
114     "<html><body><img id=\"imgid\"></img></body></html>";
115
116 static const char input_doc_str[] =
117     "<html><body><input id=\"inputid\"></input></body></html>";    
118
119 static const char iframe_doc_str[] =
120     "<html><body><iframe id=\"ifr\">Testing</iframe></body></html>";
121
122 static const char form_doc_str[] =
123     "<html><body><form id=\"formid\" method=\"post\" action=\"about:blank\">"
124     "<input type=\"text\" value=\"test\" name=\"i\"/>"
125     "<input type=\"submit\" id=\"submitid\" />"
126     "</form></body></html>";
127
128 static const char *debugstr_guid(REFIID riid)
129 {
130     static char buf[50];
131
132     sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
133             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
134             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
135             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
136
137     return buf;
138 }
139
140 static int strcmp_wa(LPCWSTR strw, const char *stra)
141 {
142     CHAR buf[512];
143     WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL);
144     return lstrcmpA(stra, buf);
145 }
146
147 static BSTR a2bstr(const char *str)
148 {
149     BSTR ret;
150     int len;
151
152     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
153     ret = SysAllocStringLen(NULL, len-1);
154     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
155
156     return ret;
157 }
158
159 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
160 {
161     IUnknown *unk1, *unk2;
162
163     if(iface1 == iface2)
164         return TRUE;
165
166     IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
167     IUnknown_Release(unk1);
168     IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk2);
169     IUnknown_Release(unk2);
170
171     return unk1 == unk2;
172 }
173
174 #define test_disp(u,id) _test_disp(__LINE__,u,id)
175 static void _test_disp(unsigned line, IUnknown *unk, const IID *diid)
176 {
177     IDispatchEx *dispex;
178     ITypeInfo *typeinfo;
179     UINT ticnt;
180     HRESULT hres;
181
182     hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex);
183     ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatch: %08x\n", hres);
184     if(FAILED(hres))
185         return;
186
187     ticnt = 0xdeadbeef;
188     hres = IDispatchEx_GetTypeInfoCount(dispex, &ticnt);
189     ok_(__FILE__,line) (hres == S_OK, "GetTypeInfoCount failed: %08x\n", hres);
190     ok_(__FILE__,line) (ticnt == 1, "ticnt=%u\n", ticnt);
191
192     hres = IDispatchEx_GetTypeInfo(dispex, 0, 0, &typeinfo);
193     ok_(__FILE__,line) (hres == S_OK, "GetTypeInfo failed: %08x\n", hres);
194
195     if(SUCCEEDED(hres)) {
196         TYPEATTR *type_attr;
197
198         hres = ITypeInfo_GetTypeAttr(typeinfo, &type_attr);
199         ok_(__FILE__,line) (hres == S_OK, "GetTypeAttr failed: %08x\n", hres);
200         ok_(__FILE__,line) (IsEqualGUID(&type_attr->guid, diid), "unexpected guid %s\n",
201                             debugstr_guid(&type_attr->guid));
202
203         ITypeInfo_ReleaseTypeAttr(typeinfo, type_attr);
204         ITypeInfo_Release(typeinfo);
205     }
206
207     IDispatchEx_Release(dispex);
208 }
209
210 #define get_doc3_iface(u) _get_doc3_iface(__LINE__,u)
211 static IHTMLDocument3 *_get_doc3_iface(unsigned line, IUnknown *unk)
212 {
213     IHTMLDocument3 *doc3;
214     HRESULT hres;
215
216     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument3, (void**)&doc3);
217     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres);
218
219     return doc3;
220 }
221
222 #define get_elem_iface(u) _get_elem_iface(__LINE__,u)
223 static IHTMLElement *_get_elem_iface(unsigned line, IUnknown *unk)
224 {
225     IHTMLElement *elem;
226     HRESULT hres;
227
228     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement, (void**)&elem);
229     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement iface: %08x\n", hres);
230
231     return elem;
232 }
233
234 #define get_elem2_iface(u) _get_elem2_iface(__LINE__,u)
235 static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk)
236 {
237     IHTMLElement2 *elem2;
238     HRESULT hres;
239
240     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement2, (void**)&elem2);
241     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement2 iface: %08x\n", hres);
242
243     return elem2;
244 }
245
246 #define get_elem3_iface(u) _get_elem3_iface(__LINE__,u)
247 static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk)
248 {
249     IHTMLElement3 *elem3;
250     HRESULT hres;
251
252     hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement3, (void**)&elem3);
253     ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement3 iface: %08x\n", hres);
254
255     return elem3;
256 }
257
258 #define doc_get_body(d) _doc_get_body(__LINE__,d)
259 static IHTMLElement *_doc_get_body(unsigned line, IHTMLDocument2 *doc)
260 {
261     IHTMLElement *body = NULL;
262     HRESULT hres;
263
264     hres = IHTMLDocument2_get_body(doc, &body);
265     ok_(__FILE__,line) (hres == S_OK, "get_body failed: %08x\n", hres);
266     ok_(__FILE__,line) (body != NULL, "body == NULL\n");
267
268     return body;
269 }
270
271 #define get_elem_id(d,i) _get_elem_id(__LINE__,d,i)
272 static IHTMLElement *_get_elem_id(unsigned line, IHTMLDocument2 *doc, const char *id)
273 {
274     IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc);
275     IHTMLElement *elem;
276     BSTR str;
277     HRESULT hres;
278
279     str = a2bstr(id);
280     hres = IHTMLDocument3_getElementById(doc3, str, &elem);
281     SysFreeString(str);
282     IHTMLDocument3_Release(doc3);
283     ok_(__FILE__,line) (hres == S_OK, "getElementById failed: %08x\n", hres);
284
285     return elem;
286 }
287
288 #define test_elem_tag(u,n) _test_elem_tag(__LINE__,u,n)
289 static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag)
290 {
291     IHTMLElement *elem = _get_elem_iface(line, unk);
292     BSTR tag;
293     HRESULT hres;
294
295     hres = IHTMLElement_get_tagName(elem, &tag);
296     IHTMLElement_Release(elem);
297     ok_(__FILE__, line) (hres == S_OK, "get_tagName failed: %08x\n", hres);
298     ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", wine_dbgstr_w(tag), extag);
299
300     SysFreeString(tag);
301 }
302
303 #define get_event_obj() _get_event_obj(__LINE__)
304 static IHTMLEventObj *_get_event_obj(unsigned line)
305 {
306     IHTMLEventObj *event = NULL;
307     HRESULT hres;
308
309     hres = IHTMLWindow2_get_event(window, &event);
310     ok_(__FILE__,line) (hres == S_OK, "get_event failed: %08x\n", hres);
311     ok_(__FILE__,line) (event != NULL, "event = NULL\n");
312     _test_disp(line, (IUnknown*)event, &DIID_DispCEventObj);
313
314     return event;
315 }
316
317 #define elem_fire_event(a,b,c) _elem_fire_event(__LINE__,a,b,c)
318 static void _elem_fire_event(unsigned line, IUnknown *unk, const char *event, VARIANT *evobj)
319 {
320     IHTMLElement3 *elem3 = _get_elem3_iface(line, unk);
321     VARIANT_BOOL b;
322     BSTR str;
323     HRESULT hres;
324
325     b = 100;
326     str = a2bstr(event);
327     hres = IHTMLElement3_fireEvent(elem3, str, evobj, &b);
328     SysFreeString(str);
329     ok_(__FILE__,line)(hres == S_OK, "fireEvent failed: %08x\n", hres);
330     ok_(__FILE__,line)(b == VARIANT_TRUE, "fireEvent returned %x\n", b);
331 }
332
333 #define test_event_args(a,b,c,d,e,f,g) _test_event_args(__LINE__,a,b,c,d,e,f,g)
334 static void _test_event_args(unsigned line, const IID *dispiid, DISPID id, WORD wFlags, DISPPARAMS *pdp,
335         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
336 {
337     ok_(__FILE__,line) (id == DISPID_VALUE, "id = %d\n", id);
338     ok_(__FILE__,line) (wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags);
339     ok_(__FILE__,line) (pdp != NULL, "pdp == NULL\n");
340     ok_(__FILE__,line) (pdp->cArgs == 1, "pdp->cArgs = %d\n", pdp->cArgs);
341     ok_(__FILE__,line) (pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
342     ok_(__FILE__,line) (pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n",
343                         pdp->rgdispidNamedArgs[0]);
344     ok_(__FILE__,line) (V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg));
345     ok_(__FILE__,line) (pvarRes != NULL, "pvarRes == NULL\n");
346     ok_(__FILE__,line) (pei != NULL, "pei == NULL");
347     ok_(__FILE__,line) (!pspCaller, "pspCaller != NULL\n");
348
349     if(dispiid)
350         _test_disp(line, (IUnknown*)V_DISPATCH(pdp->rgvarg), dispiid);
351 }
352
353 #define test_attached_event_args(a,b,c,d,e) _test_attached_event_args(__LINE__,a,b,c,d,e)
354 static void _test_attached_event_args(unsigned line, DISPID id, WORD wFlags, DISPPARAMS *pdp,
355         VARIANT *pvarRes, EXCEPINFO *pei)
356 {
357     IHTMLEventObj *event;
358
359     ok(id == DISPID_VALUE, "id = %d\n", id);
360     ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags);
361     ok(pdp != NULL, "pDispParams == NULL\n");
362     ok(pdp->cArgs == 1, "pdp->cArgs = %d\n", pdp->cArgs);
363     ok(!pdp->cNamedArgs, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs);
364     ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs = %p\n", pdp->rgdispidNamedArgs);
365     ok(pdp->rgvarg != NULL, "rgvarg = NULL\n");
366     ok(pvarRes != NULL, "pvarRes = NULL\n");
367     ok(pei != NULL, "pei = NULL\n");
368     ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pVarRes) = %d\n", V_VT(pvarRes));
369     ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg));
370     ok(V_DISPATCH(pdp->rgvarg) != NULL, "V_DISPATCH(pdp->rgvarg) = %p\n", V_DISPATCH(pdp->rgvarg));
371
372     event = _get_event_obj(line);
373     ok(iface_cmp((IUnknown*)event, (IUnknown*)V_DISPATCH(pdp->rgvarg)), "event != arg0\n");
374     IHTMLEventObj_Release(event);
375 }
376
377 #define get_event_src() _get_event_src(__LINE__)
378 static IHTMLElement *_get_event_src(unsigned line)
379 {
380     IHTMLEventObj *event = _get_event_obj(line);
381     IHTMLElement *src_elem = NULL;
382     HRESULT hres;
383
384     hres = IHTMLEventObj_get_srcElement(event, &src_elem);
385     IHTMLEventObj_Release(event);
386     ok_(__FILE__,line) (hres == S_OK, "get_srcElement failed: %08x\n", hres);
387
388     return src_elem;
389 }
390
391 #define test_event_src(t) _test_event_src(__LINE__,t)
392 static void _test_event_src(unsigned line, const char *src_tag)
393 {
394     IHTMLElement *src_elem = _get_event_src(line);
395
396     if(src_tag) {
397         ok_(__FILE__,line) (src_elem != NULL, "src_elem = NULL\n");
398         _test_elem_tag(line, (IUnknown*)src_elem, src_tag);
399         IHTMLElement_Release(src_elem);
400     }else {
401         ok_(__FILE__,line) (!src_elem, "src_elem != NULL\n");
402     }
403 }
404
405 static void _test_event_altkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval)
406 {
407     VARIANT_BOOL b;
408     HRESULT hres;
409
410     hres = IHTMLEventObj_get_altKey(event, &b);
411     ok_(__FILE__,line)(hres == S_OK, "get_altKey failed: %08x\n", hres);
412     ok_(__FILE__,line)(b == exval, "altKey = %x, expected %x\n", b, exval);
413 }
414
415 static void _test_event_ctrlkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval)
416 {
417     VARIANT_BOOL b;
418     HRESULT hres;
419
420     hres = IHTMLEventObj_get_ctrlKey(event, &b);
421     ok_(__FILE__,line)(hres == S_OK, "get_ctrlKey failed: %08x\n", hres);
422     ok_(__FILE__,line)(b == exval, "ctrlKey = %x, expected %x\n", b, exval);
423 }
424
425 static void _test_event_shiftkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval)
426 {
427     VARIANT_BOOL b;
428     HRESULT hres;
429
430     hres = IHTMLEventObj_get_shiftKey(event, &b);
431     ok_(__FILE__,line)(hres == S_OK, "get_shiftKey failed: %08x\n", hres);
432     ok_(__FILE__,line)(b == exval, "shiftKey = %x, expected %x\n", b, exval);
433 }
434
435 #define test_event_cancelbubble(a,b) _test_event_cancelbubble(__LINE__,a,b)
436 static void _test_event_cancelbubble(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval)
437 {
438     VARIANT_BOOL b;
439     HRESULT hres;
440
441     hres = IHTMLEventObj_get_cancelBubble(event, &b);
442     ok_(__FILE__,line)(hres == S_OK, "get_cancelBubble failed: %08x\n", hres);
443     ok_(__FILE__,line)(b == exval, "cancelBubble = %x, expected %x\n", b, exval);
444 }
445
446 static void _test_event_fromelem(unsigned line, IHTMLEventObj *event, const char *from_tag)
447 {
448     IHTMLElement *elem;
449     HRESULT hres;
450
451     hres = IHTMLEventObj_get_fromElement(event, &elem);
452     ok_(__FILE__,line)(hres == S_OK, "get_fromElement failed: %08x\n", hres);
453     if(from_tag)
454         _test_elem_tag(line, (IUnknown*)elem, from_tag);
455     else
456         ok_(__FILE__,line)(elem == NULL, "fromElement != NULL\n");
457     if(elem)
458         IHTMLElement_Release(elem);
459 }
460
461 static void _test_event_toelem(unsigned line, IHTMLEventObj *event, const char *to_tag)
462 {
463     IHTMLElement *elem;
464     HRESULT hres;
465
466     hres = IHTMLEventObj_get_toElement(event, &elem);
467     ok_(__FILE__,line)(hres == S_OK, "get_toElement failed: %08x\n", hres);
468     if(to_tag)
469         _test_elem_tag(line, (IUnknown*)elem, to_tag);
470     else
471         ok_(__FILE__,line)(elem == NULL, "toElement != NULL\n");
472     if(elem)
473         IHTMLElement_Release(elem);
474 }
475
476 static void _test_event_keycode(unsigned line, IHTMLEventObj *event, LONG exl)
477 {
478     LONG l;
479     HRESULT hres;
480
481     hres = IHTMLEventObj_get_keyCode(event, &l);
482     ok_(__FILE__,line)(hres == S_OK, "get_keyCode failed: %08x\n", hres);
483     ok_(__FILE__,line)(l == exl, "keyCode = %x, expected %x\n", l, exl);
484 }
485
486 static void _test_event_button(unsigned line, IHTMLEventObj *event, LONG exl)
487 {
488     LONG l;
489     HRESULT hres;
490
491     hres = IHTMLEventObj_get_button(event, &l);
492     ok_(__FILE__,line)(hres == S_OK, "get_button failed: %08x\n", hres);
493     ok_(__FILE__,line)(l == exl, "button = %x, expected %x\n", l, exl);
494 }
495
496 static void _test_event_reason(unsigned line, IHTMLEventObj *event, LONG exl)
497 {
498     LONG l;
499     HRESULT hres;
500
501     hres = IHTMLEventObj_get_reason(event, &l);
502     ok_(__FILE__,line)(hres == S_OK, "get_reason failed: %08x\n", hres);
503     ok_(__FILE__,line)(l == exl, "reason = %x, expected %x\n", l, exl);
504 }
505
506 static void _test_event_x(unsigned line, IHTMLEventObj *event, LONG exl)
507 {
508     LONG l;
509     HRESULT hres;
510
511     hres = IHTMLEventObj_get_x(event, &l);
512     ok_(__FILE__,line)(hres == S_OK, "get_x failed: %08x\n", hres);
513     if(exl != -10) /* don't test the exact value */
514         ok_(__FILE__,line)(l == exl, "x = %d, expected %d\n", l, exl);
515 }
516
517 static void _test_event_y(unsigned line, IHTMLEventObj *event, LONG exl)
518 {
519     LONG l;
520     HRESULT hres;
521
522     hres = IHTMLEventObj_get_y(event, &l);
523     ok_(__FILE__,line)(hres == S_OK, "get_y failed: %08x\n", hres);
524     if(exl != -10) /* don't test the exact value */
525         ok_(__FILE__,line)(l == exl, "y = %d, expected %d\n", l, exl);
526 }
527
528 static void _test_event_clientx(unsigned line, IHTMLEventObj *event, LONG exl)
529 {
530     LONG l;
531     HRESULT hres;
532
533     hres = IHTMLEventObj_get_clientX(event, &l);
534     ok_(__FILE__,line)(hres == S_OK, "get_clientX failed: %08x\n", hres);
535     if(exl != -10) /* don't test the exact value */
536         ok_(__FILE__,line)(l == exl, "clientX = %d, expected %d\n", l, exl);
537 }
538
539 static void _test_event_clienty(unsigned line, IHTMLEventObj *event, LONG exl)
540 {
541     LONG l;
542     HRESULT hres;
543
544     hres = IHTMLEventObj_get_clientY(event, &l);
545     ok_(__FILE__,line)(hres == S_OK, "get_clientY failed: %08x\n", hres);
546     if(exl != -10) /* don't test the exact value */
547         ok_(__FILE__,line)(l == exl, "clientY = %d, expected %d\n", l, exl);
548 }
549
550 static void _test_event_offsetx(unsigned line, IHTMLEventObj *event, LONG exl)
551 {
552     LONG l;
553     HRESULT hres;
554
555     hres = IHTMLEventObj_get_offsetX(event, &l);
556     ok_(__FILE__,line)(hres == S_OK, "get_offsetX failed: %08x\n", hres);
557     if(exl != -10) /* don't test the exact value */
558         ok_(__FILE__,line)(l == exl, "offsetX = %d, expected %d\n", l, exl);
559 }
560
561 static void _test_event_offsety(unsigned line, IHTMLEventObj *event, LONG exl)
562 {
563     LONG l;
564     HRESULT hres;
565
566     hres = IHTMLEventObj_get_offsetY(event, &l);
567     ok_(__FILE__,line)(hres == S_OK, "get_offsetY failed: %08x\n", hres);
568     if(exl != -10) /* don't test the exact value */
569         ok_(__FILE__,line)(l == exl, "offsetY = %d, expected %d\n", l, exl);
570 }
571
572 static void _test_event_screenx(unsigned line, IHTMLEventObj *event, LONG exl)
573 {
574     LONG l;
575     HRESULT hres;
576
577     hres = IHTMLEventObj_get_screenX(event, &l);
578     ok_(__FILE__,line)(hres == S_OK, "get_screenX failed: %08x\n", hres);
579     if(exl != -10) /* don't test the exact value */
580         ok_(__FILE__,line)(l == exl, "screenX = %d, expected %d\n", l, exl);
581 }
582
583 static void _test_event_screeny(unsigned line, IHTMLEventObj *event, LONG exl)
584 {
585     LONG l;
586     HRESULT hres;
587
588     hres = IHTMLEventObj_get_screenY(event, &l);
589     ok_(__FILE__,line)(hres == S_OK, "get_screenY failed: %08x\n", hres);
590     if(exl != -10) /* don't test the exact value for -10 */
591         ok_(__FILE__,line)(l == exl, "screenY = %d, expected %d\n", l, exl);
592 }
593
594 static void _test_event_type(unsigned line, IHTMLEventObj *event, const char *exstr)
595 {
596     BSTR str;
597     HRESULT hres;
598
599     hres = IHTMLEventObj_get_type(event, &str);
600     ok_(__FILE__,line)(hres == S_OK, "get_type failed: %08x\n", hres);
601     ok_(__FILE__,line)(!strcmp_wa(str, exstr), "type = %s, expected %s\n", wine_dbgstr_w(str), exstr);
602 }
603
604 static void _test_event_qualifier(unsigned line, IHTMLEventObj *event, const char *exstr)
605 {
606     BSTR str;
607     HRESULT hres;
608
609     hres = IHTMLEventObj_get_qualifier(event, &str);
610     ok_(__FILE__,line)(hres == S_OK, "get_qualifier failed: %08x\n", hres);
611     if(exstr)
612         ok_(__FILE__,line)(!strcmp_wa(str, exstr), "qualifier = %s, expected %s\n", wine_dbgstr_w(str), exstr);
613     else
614         ok_(__FILE__,line)(!str, "qualifier != NULL\n");
615 }
616
617 static void _test_event_srcfilter(unsigned line, IHTMLEventObj *event)
618 {
619     IDispatch *disp;
620     HRESULT hres;
621
622     hres = IHTMLEventObj_get_srcFilter(event, &disp);
623     ok_(__FILE__,line)(hres == S_OK, "get_srcFilter failed: %08x\n", hres);
624     ok_(__FILE__,line)(!disp, "srcFilter != NULL\n");
625 }
626
627 #define test_event_obj(t,x) _test_event_obj(__LINE__,t,x)
628 static void _test_event_obj(unsigned line, const char *type, const xy_test_t *xy)
629 {
630     IHTMLEventObj *event = _get_event_obj(line);
631     VARIANT v;
632     HRESULT hres;
633
634     _test_event_altkey(line, event, VARIANT_FALSE);
635     _test_event_ctrlkey(line, event, VARIANT_FALSE);
636     _test_event_shiftkey(line, event, VARIANT_FALSE);
637     _test_event_cancelbubble(line, event, VARIANT_FALSE);
638     _test_event_fromelem(line, event, NULL);
639     _test_event_toelem(line, event, NULL);
640     _test_event_keycode(line, event, 0);
641     _test_event_button(line, event, 0);
642     _test_event_type(line, event, type);
643     _test_event_qualifier(line, event, NULL);
644     _test_event_reason(line, event, 0);
645     _test_event_srcfilter(line, event);
646     _test_event_x(line, event, xy->x);
647     _test_event_y(line, event, xy->y);
648     _test_event_clientx(line, event, -10);
649     _test_event_clienty(line, event, -10);
650     _test_event_offsetx(line, event, xy->offset_x);
651     _test_event_offsety(line, event, xy->offset_y);
652     _test_event_screenx(line, event, -10);
653     _test_event_screeny(line, event, -10);
654
655     V_VT(&v) = VT_NULL;
656     hres = IHTMLEventObj_get_returnValue(event, &v);
657     ok_(__FILE__,line)(hres == S_OK, "get_returnValue failed: %08x\n", hres);
658     ok_(__FILE__,line)(V_VT(&v) == VT_EMPTY, "V_VT(returnValue) = %d\n", V_VT(&v));
659
660     IHTMLEventObj_Release(event);
661 }
662
663 #define elem_attach_event(a,b,c) _elem_attach_event(__LINE__,a,b,c)
664 static void _elem_attach_event(unsigned line, IUnknown *unk, const char *namea, IDispatch *disp)
665 {
666     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
667     VARIANT_BOOL res;
668     BSTR name;
669     HRESULT hres;
670
671     name = a2bstr(namea);
672     hres = IHTMLElement2_attachEvent(elem, name, disp, &res);
673     IHTMLElement2_Release(elem);
674     SysFreeString(name);
675     ok_(__FILE__,line)(hres == S_OK, "attachEvent failed: %08x\n", hres);
676     ok_(__FILE__,line)(res == VARIANT_TRUE, "attachEvent returned %x\n", res);
677 }
678
679 #define elem_detach_event(a,b,c) _elem_detach_event(__LINE__,a,b,c)
680 static void _elem_detach_event(unsigned line, IUnknown *unk, const char *namea, IDispatch *disp)
681 {
682     IHTMLElement2 *elem = _get_elem2_iface(line, unk);
683     BSTR name;
684     HRESULT hres;
685
686     name = a2bstr(namea);
687     hres = IHTMLElement2_detachEvent(elem, name, disp);
688     IHTMLElement2_Release(elem);
689     SysFreeString(name);
690     ok_(__FILE__,line)(hres == S_OK, "detachEvent failed: %08x\n", hres);
691 }
692
693 #define doc_attach_event(a,b,c) _doc_attach_event(__LINE__,a,b,c)
694 static void _doc_attach_event(unsigned line, IHTMLDocument2 *doc, const char *namea, IDispatch *disp)
695 {
696     IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc);
697     VARIANT_BOOL res;
698     BSTR name;
699     HRESULT hres;
700
701     name = a2bstr(namea);
702     hres = IHTMLDocument3_attachEvent(doc3, name, disp, &res);
703     IHTMLDocument3_Release(doc3);
704     SysFreeString(name);
705     ok_(__FILE__,line)(hres == S_OK, "attachEvent failed: %08x\n", hres);
706     ok_(__FILE__,line)(res == VARIANT_TRUE, "attachEvent returned %x\n", res);
707 }
708
709 #define doc_detach_event(a,b,c) _doc_detach_event(__LINE__,a,b,c)
710 static void _doc_detach_event(unsigned line, IHTMLDocument2 *doc, const char *namea, IDispatch *disp)
711 {
712     IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc);
713     BSTR name;
714     HRESULT hres;
715
716     name = a2bstr(namea);
717     hres = IHTMLDocument3_detachEvent(doc3, name, disp);
718     IHTMLDocument3_Release(doc3);
719     SysFreeString(name);
720     ok_(__FILE__,line)(hres == S_OK, "detachEvent failed: %08x\n", hres);
721 }
722
723 static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
724 {
725     *ppv = NULL;
726
727     if(IsEqualGUID(riid, &IID_IUnknown)
728        || IsEqualGUID(riid, &IID_IDispatch)
729        || IsEqualGUID(riid, &IID_IDispatchEx))
730         *ppv = iface;
731     else {
732         ok(0, "unexpected riid %s\n", debugstr_guid(riid));
733         return E_NOINTERFACE;
734     }
735
736     return S_OK;
737 }
738
739 static HRESULT WINAPI Dispatch_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
740 {
741     *ppv = NULL;
742
743     if(IsEqualGUID(riid, &IID_IUnknown)
744        || IsEqualGUID(riid, &IID_IDispatch)) {
745         *ppv = iface;
746     }else if(IsEqualGUID(riid, &IID_IDispatchEx)) {
747         return E_NOINTERFACE;
748     }else {
749         ok(0, "unexpected riid %s\n", debugstr_guid(riid));
750         return E_NOINTERFACE;
751     }
752
753     return S_OK;
754 }
755
756 static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface)
757 {
758     return 2;
759 }
760
761 static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
762 {
763     return 1;
764 }
765
766 static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo)
767 {
768     ok(0, "unexpected call\n");
769     return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo,
773                                               LCID lcid, ITypeInfo **ppTInfo)
774 {
775     ok(0, "unexpected call\n");
776     return E_NOTIMPL;
777 }
778
779 static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid,
780                                                 LPOLESTR *rgszNames, UINT cNames,
781                                                 LCID lcid, DISPID *rgDispId)
782 {
783     ok(0, "unexpected call\n");
784     return E_NOTIMPL;
785 }
786
787 static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember,
788                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
789                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
790 {
791     ok(0, "unexpected call\n");
792     return E_NOTIMPL;
793 }
794
795 static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid)
796 {
797     ok(0, "unexpected call\n");
798     return E_NOTIMPL;
799 }
800
801 static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
802         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
803 {
804     ok(0, "unexpected call\n");
805     return E_NOTIMPL;
806 }
807
808 static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
809 {
810     ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex);
811     return E_NOTIMPL;
812 }
813
814 static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id)
815 {
816     ok(0, "unexpected call\n");
817     return E_NOTIMPL;
818 }
819
820 static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex)
821 {
822     ok(0, "unexpected call\n");
823     return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName)
827 {
828     ok(0, "unexpected call\n");
829     return E_NOTIMPL;
830 }
831
832 static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid)
833 {
834     ok(0, "unexpected call\n");
835     return E_NOTIMPL;
836 }
837
838 static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk)
839 {
840     ok(0, "unexpected call\n");
841     return E_NOTIMPL;
842 }
843
844 #define EVENT_HANDLER_FUNC_OBJ(event) \
845     static IDispatchExVtbl event ## FuncVtbl = { \
846         DispatchEx_QueryInterface, \
847         DispatchEx_AddRef, \
848         DispatchEx_Release, \
849         DispatchEx_GetTypeInfoCount, \
850         DispatchEx_GetTypeInfo, \
851         DispatchEx_GetIDsOfNames, \
852         DispatchEx_Invoke, \
853         DispatchEx_GetDispID, \
854         event, \
855         DispatchEx_DeleteMemberByName, \
856         DispatchEx_DeleteMemberByDispID, \
857         DispatchEx_GetMemberProperties, \
858         DispatchEx_GetMemberName, \
859         DispatchEx_GetNextDispID, \
860         DispatchEx_GetNameSpaceParent \
861     }; \
862     static IDispatchEx event ## _obj = { &event ## FuncVtbl };
863
864 static HRESULT WINAPI document_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
865         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
866 {
867     IHTMLDocument3 *doc3;
868     CHECK_EXPECT(document_onclick);
869     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
870     doc3 = get_doc3_iface((IUnknown*)V_DISPATCH(pdp->rgvarg));
871     IHTMLDocument3_Release(doc3);
872     test_event_src("DIV");
873     test_event_obj("click", &no_xy);
874     return S_OK;
875 }
876
877 EVENT_HANDLER_FUNC_OBJ(document_onclick);
878
879 static HRESULT WINAPI div_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
880         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
881 {
882     CHECK_EXPECT(div_onclick);
883     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
884     test_event_src("DIV");
885     return S_OK;
886 }
887
888 EVENT_HANDLER_FUNC_OBJ(div_onclick);
889
890 static HRESULT WINAPI div_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
891         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
892 {
893     CHECK_EXPECT(div_onclick_attached);
894
895     test_attached_event_args(id, wFlags, pdp, pvarRes, pei);
896     test_event_src("DIV");
897     return S_OK;
898 }
899
900 EVENT_HANDLER_FUNC_OBJ(div_onclick_attached);
901
902 static HRESULT WINAPI doc_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
903         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
904 {
905     CHECK_EXPECT(doc_onclick_attached);
906
907     test_attached_event_args(id, wFlags, pdp, pvarRes, pei);
908     test_event_src("DIV");
909     return S_OK;
910 }
911
912 EVENT_HANDLER_FUNC_OBJ(doc_onclick_attached);
913
914 static HRESULT WINAPI body_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
915         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
916 {
917     CHECK_EXPECT(body_onclick);
918     test_event_args(&DIID_DispHTMLBody, id, wFlags, pdp, pvarRes, pei, pspCaller);
919     test_event_src("DIV");
920     return S_OK;
921 }
922
923 EVENT_HANDLER_FUNC_OBJ(body_onclick);
924
925 static HRESULT WINAPI img_onload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
926         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
927 {
928     CHECK_EXPECT(img_onload);
929     test_event_args(&DIID_DispHTMLImg, id, wFlags, pdp, pvarRes, pei, pspCaller);
930     test_event_src("IMG");
931     return S_OK;
932 }
933
934 EVENT_HANDLER_FUNC_OBJ(img_onload);
935
936 static HRESULT WINAPI img_onerror(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
937         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
938 {
939     CHECK_EXPECT(img_onerror);
940     test_event_args(&DIID_DispHTMLImg, id, wFlags, pdp, pvarRes, pei, pspCaller);
941     test_event_src("IMG");
942     return S_OK;
943 }
944
945 EVENT_HANDLER_FUNC_OBJ(img_onerror);
946
947 static HRESULT WINAPI input_onfocus(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
948         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
949 {
950     CHECK_EXPECT(input_onfocus);
951     test_event_args(&DIID_DispHTMLInputElement, id, wFlags, pdp, pvarRes, pei, pspCaller);
952     test_event_src("INPUT");
953     return S_OK;
954 }
955
956 EVENT_HANDLER_FUNC_OBJ(input_onfocus);
957
958 static HRESULT WINAPI input_onblur(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
959         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
960 {
961     CHECK_EXPECT(input_onblur);
962     test_event_args(&DIID_DispHTMLInputElement, id, wFlags, pdp, pvarRes, pei, pspCaller);
963     test_event_src("INPUT");
964     return S_OK;
965 }
966
967 EVENT_HANDLER_FUNC_OBJ(input_onblur);
968
969 static HRESULT WINAPI form_onsubmit(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
970         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
971 {
972     CHECK_EXPECT(form_onsubmit);
973     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
974     test_event_src("FORM");
975
976     V_VT(pvarRes) = VT_BOOL;
977     V_BOOL(pvarRes) = VARIANT_FALSE;
978     return S_OK;
979 }
980
981 EVENT_HANDLER_FUNC_OBJ(form_onsubmit);
982
983 static HRESULT WINAPI form_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
984         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
985 {
986     CHECK_EXPECT(form_onclick);
987     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
988
989     return S_OK;
990 }
991
992 EVENT_HANDLER_FUNC_OBJ(form_onclick);
993
994 static HRESULT WINAPI submit_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
995         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
996 {
997     CHECK_EXPECT(submit_onclick);
998     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
999     test_event_src("INPUT");
1000
1001     V_VT(pvarRes) = VT_BOOL;
1002     V_BOOL(pvarRes) = VARIANT_FALSE;
1003     return S_OK;
1004 }
1005
1006 EVENT_HANDLER_FUNC_OBJ(submit_onclick);
1007
1008 static HRESULT WINAPI submit_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1009         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1010 {
1011     CHECK_EXPECT(submit_onclick_attached);
1012     test_attached_event_args(id, wFlags, pdp, pvarRes, pei);
1013     test_event_src("INPUT");
1014
1015     V_VT(pvarRes) = VT_BOOL;
1016     V_BOOL(pvarRes) = VARIANT_FALSE;
1017     return S_OK;
1018 }
1019
1020 EVENT_HANDLER_FUNC_OBJ(submit_onclick_attached);
1021
1022 static HRESULT WINAPI submit_onclick_attached_check_cancel(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1023         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1024 {
1025     IHTMLEventObj *event;
1026     HRESULT hres;
1027
1028     CHECK_EXPECT(submit_onclick_attached_check_cancel);
1029     test_attached_event_args(id, wFlags, pdp, pvarRes, pei);
1030     test_event_src("INPUT");
1031
1032     event = NULL;
1033     hres = IHTMLWindow2_get_event(window, &event);
1034     ok(hres == S_OK, "get_event failed: %08x\n", hres);
1035     ok(event != NULL, "event == NULL\n");
1036
1037     test_event_cancelbubble(event, VARIANT_TRUE);
1038     return S_OK;
1039 }
1040
1041 EVENT_HANDLER_FUNC_OBJ(submit_onclick_attached_check_cancel);
1042
1043 static VARIANT onclick_retval, onclick_event_retval;
1044
1045 static HRESULT WINAPI submit_onclick_setret(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1046         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1047 {
1048     IHTMLEventObj *event;
1049     HRESULT hres;
1050
1051     CHECK_EXPECT(submit_onclick_setret);
1052     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
1053     test_event_src("INPUT");
1054
1055     event = NULL;
1056     hres = IHTMLWindow2_get_event(window, &event);
1057     ok(hres == S_OK, "get_event failed: %08x\n", hres);
1058     ok(event != NULL, "event == NULL\n");
1059
1060     hres = IHTMLEventObj_put_returnValue(event, onclick_event_retval);
1061     ok(hres == S_OK, "put_returnValue failed: %08x\n", hres);
1062     IHTMLEventObj_Release(event);
1063
1064     *pvarRes = onclick_retval;
1065     return S_OK;
1066 }
1067
1068 EVENT_HANDLER_FUNC_OBJ(submit_onclick_setret);
1069
1070 static HRESULT WINAPI submit_onclick_cancel(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1071         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1072 {
1073     IHTMLEventObj *event;
1074     HRESULT hres;
1075
1076     CHECK_EXPECT(submit_onclick_cancel);
1077     test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller);
1078     test_event_src("INPUT");
1079
1080     event = NULL;
1081     hres = IHTMLWindow2_get_event(window, &event);
1082     ok(hres == S_OK, "get_event failed: %08x\n", hres);
1083     ok(event != NULL, "event == NULL\n");
1084
1085     test_event_cancelbubble(event, VARIANT_FALSE);
1086
1087     hres = IHTMLEventObj_put_cancelBubble(event, VARIANT_TRUE);
1088     ok(hres == S_OK, "put_returnValue failed: %08x\n", hres);
1089     IHTMLEventObj_Release(event);
1090
1091     test_event_cancelbubble(event, VARIANT_TRUE);
1092     return S_OK;
1093 }
1094
1095 EVENT_HANDLER_FUNC_OBJ(submit_onclick_cancel);
1096
1097 static HRESULT WINAPI iframedoc_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1098         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1099 {
1100     IHTMLEventObj *event = NULL;
1101     HRESULT hres;
1102
1103     CHECK_EXPECT2(iframedoc_onreadystatechange);
1104     test_event_args(&DIID_DispHTMLDocument, id, wFlags, pdp, pvarRes, pei, pspCaller);
1105
1106     event = (void*)0xdeadbeef;
1107     hres = IHTMLWindow2_get_event(window, &event);
1108     ok(hres == S_OK, "get_event failed: %08x\n", hres);
1109     ok(!event, "event = %p\n", event);
1110
1111     return S_OK;
1112 }
1113
1114 EVENT_HANDLER_FUNC_OBJ(iframedoc_onreadystatechange);
1115
1116 static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1117         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1118 {
1119     IHTMLWindow2 *iframe_window;
1120     IHTMLDocument2 *iframe_doc;
1121     IHTMLFrameBase2 *iframe;
1122     IHTMLElement2 *elem2;
1123     IHTMLElement *elem;
1124     VARIANT v;
1125     BSTR str, str2;
1126     HRESULT hres;
1127
1128     test_event_args(&DIID_DispHTMLIFrame, id, wFlags, pdp, pvarRes, pei, pspCaller);
1129     test_event_src("IFRAME");
1130
1131     elem = get_event_src();
1132     elem2 = get_elem2_iface((IUnknown*)elem);
1133     IHTMLElement_Release(elem);
1134
1135     V_VT(&v) = VT_EMPTY;
1136     hres = IHTMLElement2_get_readyState(elem2, &v);
1137     ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
1138     ok(V_VT(&v) == VT_BSTR, "V_VT(readyState) = %d\n", V_VT(&v));
1139
1140     hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase2, (void**)&iframe);
1141     IHTMLElement2_Release(elem2);
1142     ok(hres == S_OK, "Could not get IHTMLFrameBase2 iface: %08x\n", hres);
1143
1144     str = NULL;
1145     hres = IHTMLFrameBase2_get_readyState(iframe, &str);
1146     ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
1147     ok(str != NULL, "readyState == NULL\n");
1148     ok(!lstrcmpW(str, V_BSTR(&v)), "ready states differ\n");
1149     VariantClear(&v);
1150
1151     hres = IHTMLFrameBase2_get_contentWindow(iframe, &iframe_window);
1152     ok(hres == S_OK, "get_contentDocument failed: %08x\n", hres);
1153
1154     hres = IHTMLWindow2_get_document(iframe_window, &iframe_doc);
1155     IHTMLWindow2_Release(iframe_window);
1156     ok(hres == S_OK, "get_document failed: %08x\n", hres);
1157
1158     hres = IHTMLDocument2_get_readyState(iframe_doc, &str2);
1159     ok(hres == S_OK, "get_document failed: %08x\n", hres);
1160     ok(!lstrcmpW(str, str2), "unexpected document readyState %s\n", wine_dbgstr_w(str2));
1161     SysFreeString(str2);
1162
1163     if(!strcmp_wa(str, "loading")) {
1164         CHECK_EXPECT(iframe_onreadystatechange_loading);
1165
1166         V_VT(&v) = VT_DISPATCH;
1167         V_DISPATCH(&v) = (IDispatch*)&iframedoc_onreadystatechange_obj;
1168         hres = IHTMLDocument2_put_onreadystatechange(iframe_doc, v);
1169         ok(hres == S_OK, "put_onreadystatechange: %08x\n", hres);
1170     }else if(!strcmp_wa(str, "interactive"))
1171         CHECK_EXPECT(iframe_onreadystatechange_interactive);
1172     else if(!strcmp_wa(str, "complete"))
1173         CHECK_EXPECT(iframe_onreadystatechange_complete);
1174     else
1175         ok(0, "unexpected state %s\n", wine_dbgstr_w(str));
1176
1177     SysFreeString(str);
1178     IHTMLDocument2_Release(iframe_doc);
1179     IHTMLFrameBase2_Release(iframe);
1180     return S_OK;
1181 }
1182
1183 EVENT_HANDLER_FUNC_OBJ(iframe_onreadystatechange);
1184
1185 static HRESULT WINAPI nocall(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1186         VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller)
1187 {
1188     ok(0, "unexpected call\n");
1189     return S_OK;
1190 }
1191
1192 EVENT_HANDLER_FUNC_OBJ(nocall);
1193
1194 #define CONNECTION_POINT_OBJ(cpname, diid) \
1195     static HRESULT WINAPI cpname ## _QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) \
1196     { \
1197         *ppv = NULL; \
1198         if(IsEqualGUID(riid, &IID_IUnknown) \
1199            || IsEqualGUID(riid, &IID_IDispatch) \
1200            || IsEqualGUID(riid, &diid)) \
1201             *ppv = iface; \
1202         else { \
1203             ok(0, "unexpected riid %s\n", debugstr_guid(riid)); \
1204             return E_NOINTERFACE; \
1205         } \
1206         return S_OK; \
1207     } \
1208     static IDispatchExVtbl cpname ## Vtbl = { \
1209         cpname ## _QueryInterface, \
1210         DispatchEx_AddRef,  \
1211         DispatchEx_Release, \
1212         DispatchEx_GetTypeInfoCount, \
1213         DispatchEx_GetTypeInfo, \
1214         DispatchEx_GetIDsOfNames, \
1215         cpname, \
1216         DispatchEx_GetDispID, \
1217         DispatchEx_InvokeEx, \
1218         DispatchEx_DeleteMemberByName, \
1219         DispatchEx_DeleteMemberByDispID, \
1220         DispatchEx_GetMemberProperties, \
1221         DispatchEx_GetMemberName, \
1222         DispatchEx_GetNextDispID, \
1223         DispatchEx_GetNameSpaceParent \
1224     }; \
1225     static IDispatchEx cpname ## _obj = { &cpname ## Vtbl }
1226
1227 #define test_cp_args(a,b,c,d,e,f) _test_cp_args(__LINE__,a,b,c,d,e,f)
1228 static void _test_cp_args(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp, VARIANT *vres, EXCEPINFO *ei, UINT *argerr)
1229 {
1230     ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid));
1231     ok_(__FILE__,line)(flags == DISPATCH_METHOD, "flags = %x\n", flags);
1232     ok_(__FILE__,line)(dp != NULL, "dp == NULL\n");
1233     ok_(__FILE__,line)(!dp->cArgs, "dp->cArgs = %d\n", dp->cArgs);
1234     ok_(__FILE__,line)(!dp->rgvarg, "dp->rgvarg = %p\n", dp->rgvarg);
1235     ok_(__FILE__,line)(!dp->cNamedArgs, "dp->cNamedArgs = %d\n", dp->cNamedArgs);
1236     ok_(__FILE__,line)(!dp->rgdispidNamedArgs, "dp->rgdispidNamedArgs = %p\n", dp->rgdispidNamedArgs);
1237     ok_(__FILE__,line)(vres != NULL, "vres == NULL\n");
1238     ok_(__FILE__,line)(V_VT(vres) == VT_EMPTY, "V_VT(vres) = %d\n", V_VT(vres));
1239     ok_(__FILE__,line)(ei != NULL, "ei == NULL\n");
1240     ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n");
1241 }
1242
1243 #define test_cp_eventarg(a,b,c,d,e,f) _test_cp_eventarg(__LINE__,a,b,c,d,e,f)
1244 static void _test_cp_eventarg(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp, VARIANT *vres, EXCEPINFO *ei, UINT *argerr)
1245 {
1246     IHTMLEventObj *event;
1247
1248     ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid));
1249     ok_(__FILE__,line)(flags == DISPATCH_METHOD, "flags = %x\n", flags);
1250     ok_(__FILE__,line)(dp != NULL, "dp == NULL\n");
1251     ok_(__FILE__,line)(dp->cArgs == 1, "dp->cArgs = %d\n", dp->cArgs);
1252     ok_(__FILE__,line)(dp->rgvarg != NULL, "dp->rgvarg = %p\n", dp->rgvarg);
1253     ok_(__FILE__,line)(!dp->cNamedArgs, "dp->cNamedArgs = %d\n", dp->cNamedArgs);
1254     ok_(__FILE__,line)(!dp->rgdispidNamedArgs, "dp->rgdispidNamedArgs = %p\n", dp->rgdispidNamedArgs);
1255     ok_(__FILE__,line)(vres != NULL, "vres == NULL\n");
1256     ok_(__FILE__,line)(V_VT(vres) == VT_EMPTY, "V_VT(vres) = %d\n", V_VT(vres));
1257     ok_(__FILE__,line)(ei != NULL, "ei == NULL\n");
1258     ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n");
1259
1260     ok(V_VT(dp->rgvarg) == VT_DISPATCH, "V_VT(dp->rgvarg) = %d\n", V_VT(dp->rgvarg));
1261     ok(V_DISPATCH(dp->rgvarg) != NULL, "V_DISPATCH(dp->rgvarg) = %p\n", V_DISPATCH(dp->rgvarg));
1262
1263     event = _get_event_obj(line);
1264     ok(iface_cmp((IUnknown*)event, (IUnknown*)V_DISPATCH(dp->rgvarg)), "event != arg0\n");
1265     IHTMLEventObj_Release(event);
1266 }
1267
1268 static HRESULT WINAPI doccp(IDispatchEx *iface, DISPID dispIdMember,
1269                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1270                             VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr)
1271 {
1272     switch(dispIdMember) {
1273     case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
1274         CHECK_EXPECT(doccp_onclick);
1275         test_cp_args(riid, wFlags, pdp, pVarResult, pei, puArgErr);
1276         break;
1277     default:
1278         ok(0, "unexpected call %d\n", dispIdMember);
1279         return E_NOTIMPL;
1280     }
1281
1282     return S_OK;
1283 }
1284
1285 CONNECTION_POINT_OBJ(doccp, DIID_HTMLDocumentEvents);
1286
1287 static HRESULT WINAPI doccp_onclick_cancel(IDispatchEx *iface, DISPID dispIdMember,
1288         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr)
1289 {
1290     switch(dispIdMember) {
1291     case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
1292         CHECK_EXPECT(doccp_onclick_cancel);
1293         test_cp_args(riid, wFlags, pdp, pVarResult, pei, puArgErr);
1294         V_VT(pVarResult) = VT_BOOL;
1295         V_BOOL(pVarResult) = VARIANT_FALSE;
1296         break;
1297     default:
1298         ok(0, "unexpected call %d\n", dispIdMember);
1299         return E_NOTIMPL;
1300     }
1301
1302     return S_OK;
1303 }
1304
1305 CONNECTION_POINT_OBJ(doccp_onclick_cancel, DIID_HTMLDocumentEvents);
1306
1307 static HRESULT WINAPI elem2_cp(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
1308         WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr)
1309 {
1310     switch(dispIdMember) {
1311     case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
1312         CHECK_EXPECT(elem2_cp_onclick);
1313         test_cp_eventarg(riid, wFlags, pdp, pVarResult, pei, puArgErr);
1314         break;
1315     default:
1316         ok(0, "unexpected call %d\n", dispIdMember);
1317         return E_NOTIMPL;
1318     }
1319
1320     return S_OK;
1321 }
1322
1323 CONNECTION_POINT_OBJ(elem2_cp, DIID_HTMLElementEvents2);
1324
1325 static HRESULT WINAPI timeoutFunc_Invoke(IDispatchEx *iface, DISPID dispIdMember,
1326                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
1327                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
1328 {
1329     CHECK_EXPECT(timeout);
1330
1331     ok(dispIdMember == DISPID_VALUE, "dispIdMember = %d\n", dispIdMember);
1332     ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid));
1333     ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags);
1334     ok(!lcid, "lcid = %x\n", lcid);
1335     ok(pDispParams != NULL, "pDispParams == NULL\n");
1336     ok(!pDispParams->cArgs, "pdp->cArgs = %d\n", pDispParams->cArgs);
1337     ok(!pDispParams->cNamedArgs, "pdp->cNamedArgs = %d\n", pDispParams->cNamedArgs);
1338     ok(!pDispParams->rgdispidNamedArgs, "pdp->rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs);
1339     ok(!pDispParams->rgvarg, "rgvarg = %p\n", pDispParams->rgvarg);
1340     ok(pVarResult != NULL, "pVarResult = NULL\n");
1341     ok(pExcepInfo != NULL, "pExcepInfo = NULL\n");
1342     ok(!puArgErr, "puArgErr = %p\n", puArgErr);
1343     ok(V_VT(pVarResult) == VT_EMPTY, "V_VT(pVarResult) = %d\n", V_VT(pVarResult));
1344
1345     return S_OK;
1346 }
1347
1348 static const IDispatchExVtbl timeoutFuncVtbl = {
1349     DispatchEx_QueryInterface,
1350     DispatchEx_AddRef,
1351     DispatchEx_Release,
1352     DispatchEx_GetTypeInfoCount,
1353     DispatchEx_GetTypeInfo,
1354     DispatchEx_GetIDsOfNames,
1355     timeoutFunc_Invoke,
1356     DispatchEx_GetDispID,
1357     DispatchEx_InvokeEx,
1358     DispatchEx_DeleteMemberByName,
1359     DispatchEx_DeleteMemberByDispID,
1360     DispatchEx_GetMemberProperties,
1361     DispatchEx_GetMemberName,
1362     DispatchEx_GetNextDispID,
1363     DispatchEx_GetNameSpaceParent
1364 };
1365
1366 static IDispatchEx timeoutFunc = { &timeoutFuncVtbl };
1367
1368 static HRESULT WINAPI div_onclick_disp_Invoke(IDispatchEx *iface, DISPID id,
1369         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
1370         VARIANT *pvarRes, EXCEPINFO *pei, UINT *puArgErr)
1371 {
1372     CHECK_EXPECT(div_onclick_disp);
1373
1374     test_attached_event_args(id, wFlags, pdp, pvarRes, pei);
1375
1376     ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid));
1377     ok(!puArgErr, "puArgErr = %p\n", puArgErr);
1378
1379     return S_OK;
1380 }
1381
1382 static const IDispatchExVtbl div_onclick_dispVtbl = {
1383     Dispatch_QueryInterface,
1384     DispatchEx_AddRef,
1385     DispatchEx_Release,
1386     DispatchEx_GetTypeInfoCount,
1387     DispatchEx_GetTypeInfo,
1388     DispatchEx_GetIDsOfNames,
1389     div_onclick_disp_Invoke,
1390 };
1391
1392 static IDispatchEx div_onclick_disp = { &div_onclick_dispVtbl };
1393
1394 static void pump_msgs(BOOL *b)
1395 {
1396     MSG msg;
1397
1398     if(b) {
1399         while(!*b && GetMessageW(&msg, NULL, 0, 0)) {
1400             TranslateMessage(&msg);
1401             DispatchMessage(&msg);
1402         }
1403     }else {
1404         while(!b && PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
1405             TranslateMessage(&msg);
1406             DispatchMessage(&msg);
1407         }
1408     }
1409 }
1410
1411 static IConnectionPoint *get_cp(IUnknown *unk, REFIID riid)
1412 {
1413     IConnectionPointContainer *cp_container;
1414     IConnectionPoint *cp;
1415     HRESULT hres;
1416
1417     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&cp_container);
1418     ok(hres == S_OK, "Could not get IConnectionPointContainer: %08x\n", hres);
1419
1420     hres = IConnectionPointContainer_FindConnectionPoint(cp_container, riid, &cp);
1421     IConnectionPointContainer_Release(cp_container);
1422     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
1423
1424     return cp;
1425 }
1426
1427 static DWORD register_cp(IUnknown *unk, REFIID riid, IUnknown *sink)
1428 {
1429     IConnectionPoint *cp;
1430     DWORD cookie;
1431     HRESULT hres;
1432
1433     cp = get_cp(unk, riid);
1434     hres = IConnectionPoint_Advise(cp, sink, &cookie);
1435     IConnectionPoint_Release(cp);
1436     ok(hres == S_OK, "Advise failed: %08x\n", hres);
1437
1438     return cookie;
1439 }
1440
1441 static void unregister_cp(IUnknown *unk, REFIID riid, DWORD cookie)
1442 {
1443     IConnectionPoint *cp;
1444     HRESULT hres;
1445
1446     cp = get_cp(unk, riid);
1447     hres = IConnectionPoint_Unadvise(cp, cookie);
1448     IConnectionPoint_Release(cp);
1449     ok(hres == S_OK, "Unadvise failed: %08x\n", hres);
1450 }
1451
1452 static HRESULT WINAPI EventDispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
1453 {
1454     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) {
1455         *ppv = iface;
1456         return S_OK;
1457     }
1458
1459     ok(0, "Unexpected call\n");
1460     return E_NOINTERFACE;
1461 }
1462
1463 static DWORD WINAPI EventDispatch_AddRef(IDispatch *iface)
1464 {
1465     return 2;
1466 }
1467
1468 static DWORD WINAPI EventDispatch_Release(IDispatch *iface)
1469 {
1470     return 1;
1471 }
1472
1473 static HRESULT WINAPI EventDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
1474 {
1475     ok(0, "Unexpected call\n");
1476     return E_NOTIMPL;
1477 }
1478
1479 static HRESULT WINAPI EventDispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
1480 {
1481     ok(0, "Unexpected call\n");
1482     return E_NOTIMPL;
1483 }
1484
1485 static HRESULT WINAPI EventDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames,
1486         UINT cNames, LCID lcid, DISPID *rgDispId)
1487 {
1488     ok(0, "Unexpected call\n");
1489     return E_NOTIMPL;
1490 }
1491
1492 static HRESULT WINAPI EventDispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid,
1493         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
1494         EXCEPINFO *pExcepInfo, UINT *puArgErr)
1495 {
1496     ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid));
1497     ok(pDispParams != NULL, "pDispParams == NULL\n");
1498     ok(pExcepInfo != NULL, "pExcepInfo == NULL\n");
1499     ok(puArgErr != NULL, "puArgErr == NULL\n");
1500     ok(V_VT(pVarResult) == 0, "V_VT(pVarResult) = %d\n", V_VT(pVarResult));
1501     ok(wFlags == DISPATCH_METHOD, "wFlags = %d\n", wFlags);
1502
1503     switch(dispIdMember) {
1504     case DISPID_HTMLDOCUMENTEVENTS_ONCLICK:
1505         CHECK_EXPECT2(invoke_onclick);
1506         break;
1507     case DISPID_HTMLDOCUMENTEVENTS2_ONPROPERTYCHANGE:
1508     case DISPID_HTMLDOCUMENTEVENTS2_ONREADYSTATECHANGE:
1509     case 1027:
1510     case 1034:
1511     case 1037:
1512     case 1044:
1513     case 1045:
1514     case 1047:
1515     case 1048:
1516     case 1049:
1517         break; /* TODO */
1518     default:
1519         ok(0, "Unexpected call: %d\n", dispIdMember);
1520     }
1521
1522     return S_OK;
1523 }
1524
1525 static const IDispatchVtbl EventDispatchVtbl = {
1526     EventDispatch_QueryInterface,
1527     EventDispatch_AddRef,
1528     EventDispatch_Release,
1529     EventDispatch_GetTypeInfoCount,
1530     EventDispatch_GetTypeInfo,
1531     EventDispatch_GetIDsOfNames,
1532     EventDispatch_Invoke
1533 };
1534
1535 static IDispatch EventDispatch = { &EventDispatchVtbl };
1536
1537 static void test_onclick(IHTMLDocument2 *doc)
1538 {
1539     DWORD cp_cookie, elem2_cp_cookie;
1540     IHTMLElement *div, *body;
1541     VARIANT v;
1542     HRESULT hres;
1543
1544     register_cp((IUnknown*)doc, &IID_IDispatch, (IUnknown*)&EventDispatch);
1545
1546     div = get_elem_id(doc, "clickdiv");
1547
1548     elem_attach_event((IUnknown*)div, "abcde", (IDispatch*)&nocall_obj);
1549     elem_attach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_attached_obj);
1550
1551     V_VT(&v) = VT_EMPTY;
1552     hres = IHTMLElement_get_onclick(div, &v);
1553     ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1554     ok(V_VT(&v) == VT_NULL, "V_VT(onclick) = %d\n", V_VT(&v));
1555
1556     V_VT(&v) = VT_EMPTY;
1557     hres = IHTMLElement_put_onclick(div, v);
1558     ok(hres == E_NOTIMPL, "put_onclick failed: %08x\n", hres);
1559
1560     V_VT(&v) = VT_BSTR;
1561     V_BSTR(&v) = a2bstr("function();");
1562     hres = IHTMLElement_put_onclick(div, v);
1563     todo_wine ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1564
1565     if(hres == S_OK) {
1566         V_VT(&v) = VT_EMPTY;
1567         hres = IHTMLElement_get_onclick(div, &v);
1568         ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1569         ok(V_VT(&v) == VT_BSTR, "V_VT(onclick) = %d\n", V_VT(&v));
1570         ok(!strcmp_wa(V_BSTR(&v), "function();"), "V_BSTR(onclick) = %s\n", wine_dbgstr_w(V_BSTR(&v)));
1571     }
1572     VariantClear(&v);
1573
1574     V_VT(&v) = VT_DISPATCH;
1575     V_DISPATCH(&v) = (IDispatch*)&div_onclick_obj;
1576     hres = IHTMLElement_put_onclick(div, v);
1577     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1578
1579     V_VT(&v) = VT_NULL;
1580     hres = IHTMLElement_put_ondblclick(div, v);
1581     ok(hres == S_OK, "put_ondblclick failed: %08x\n", hres);
1582
1583     V_VT(&v) = VT_EMPTY;
1584     hres = IHTMLElement_get_onclick(div, &v);
1585     ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1586     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onclick) = %d\n", V_VT(&v));
1587     ok(V_DISPATCH(&v) == (IDispatch*)&div_onclick_obj, "V_DISPATCH(onclick) != onclickFunc\n");
1588     VariantClear(&v);
1589
1590     V_VT(&v) = VT_EMPTY;
1591     hres = IHTMLDocument2_get_onclick(doc, &v);
1592     ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1593     ok(V_VT(&v) == VT_NULL, "V_VT(onclick) = %d\n", V_VT(&v));
1594
1595     V_VT(&v) = VT_DISPATCH;
1596     V_DISPATCH(&v) = (IDispatch*)&document_onclick_obj;
1597     hres = IHTMLDocument2_put_onclick(doc, v);
1598     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1599
1600     V_VT(&v) = VT_EMPTY;
1601     hres = IHTMLDocument2_get_onclick(doc, &v);
1602     ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1603     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onclick) = %d\n", V_VT(&v));
1604     ok(V_DISPATCH(&v) == (IDispatch*)&document_onclick_obj, "V_DISPATCH(onclick) != onclickFunc\n");
1605     VariantClear(&v);
1606
1607     body = doc_get_body(doc);
1608
1609     V_VT(&v) = VT_DISPATCH;
1610     V_DISPATCH(&v) = (IDispatch*)&body_onclick_obj;
1611     hres = IHTMLElement_put_onclick(body, v);
1612     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1613
1614     if(winetest_interactive) {
1615         SET_EXPECT(div_onclick);
1616         SET_EXPECT(div_onclick_attached);
1617         SET_EXPECT(body_onclick);
1618         SET_EXPECT(document_onclick);
1619         SET_EXPECT(invoke_onclick);
1620         pump_msgs(&called_document_onclick);
1621         CHECK_CALLED(div_onclick);
1622         CHECK_CALLED(div_onclick_attached);
1623         CHECK_CALLED(body_onclick);
1624         CHECK_CALLED(document_onclick);
1625         CHECK_CALLED(invoke_onclick);
1626     }
1627
1628     xy_todo = TRUE;
1629
1630     SET_EXPECT(div_onclick);
1631     SET_EXPECT(div_onclick_attached);
1632     SET_EXPECT(body_onclick);
1633     SET_EXPECT(document_onclick);
1634     SET_EXPECT(invoke_onclick);
1635
1636     hres = IHTMLElement_click(div);
1637     ok(hres == S_OK, "click failed: %08x\n", hres);
1638
1639     CHECK_CALLED(div_onclick);
1640     CHECK_CALLED(div_onclick_attached);
1641     CHECK_CALLED(body_onclick);
1642     CHECK_CALLED(document_onclick);
1643     CHECK_CALLED(invoke_onclick);
1644
1645     SET_EXPECT(div_onclick);
1646     SET_EXPECT(div_onclick_attached);
1647     SET_EXPECT(body_onclick);
1648     SET_EXPECT(document_onclick);
1649     SET_EXPECT(invoke_onclick);
1650
1651     V_VT(&v) = VT_EMPTY;
1652     elem_fire_event((IUnknown*)div, "onclick", &v);
1653
1654     CHECK_CALLED(div_onclick);
1655     CHECK_CALLED(div_onclick_attached);
1656     CHECK_CALLED(body_onclick);
1657     CHECK_CALLED(document_onclick);
1658     CHECK_CALLED(invoke_onclick);
1659
1660     cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_obj);
1661     elem_attach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp);
1662     doc_attach_event(doc, "onclick", (IDispatch*)&doc_onclick_attached_obj);
1663
1664     SET_EXPECT(div_onclick);
1665     SET_EXPECT(div_onclick_disp);
1666     SET_EXPECT(div_onclick_attached);
1667     SET_EXPECT(body_onclick);
1668     SET_EXPECT(document_onclick);
1669     SET_EXPECT(doc_onclick_attached);
1670     SET_EXPECT(doccp_onclick);
1671     SET_EXPECT(invoke_onclick);
1672
1673     hres = IHTMLElement_click(div);
1674     ok(hres == S_OK, "click failed: %08x\n", hres);
1675
1676     CHECK_CALLED(div_onclick);
1677     CHECK_CALLED(div_onclick_disp);
1678     CHECK_CALLED(div_onclick_attached);
1679     CHECK_CALLED(body_onclick);
1680     CHECK_CALLED(document_onclick);
1681     CHECK_CALLED(doc_onclick_attached);
1682     CHECK_CALLED(doccp_onclick);
1683     CHECK_CALLED(invoke_onclick);
1684
1685     elem2_cp_cookie = register_cp((IUnknown*)div, &DIID_HTMLElementEvents2, (IUnknown*)&elem2_cp_obj);
1686
1687     SET_EXPECT(div_onclick);
1688     SET_EXPECT(div_onclick_disp);
1689     SET_EXPECT(div_onclick_attached);
1690     SET_EXPECT(elem2_cp_onclick);
1691     SET_EXPECT(body_onclick);
1692     SET_EXPECT(document_onclick);
1693     SET_EXPECT(doc_onclick_attached);
1694     SET_EXPECT(doccp_onclick);
1695     SET_EXPECT(invoke_onclick);
1696
1697     trace("click >>>\n");
1698     hres = IHTMLElement_click(div);
1699     ok(hres == S_OK, "click failed: %08x\n", hres);
1700     trace("click <<<\n");
1701
1702     CHECK_CALLED(div_onclick);
1703     CHECK_CALLED(div_onclick_disp);
1704     CHECK_CALLED(div_onclick_attached);
1705     CHECK_CALLED(elem2_cp_onclick);
1706     CHECK_CALLED(body_onclick);
1707     CHECK_CALLED(document_onclick);
1708     CHECK_CALLED(doc_onclick_attached);
1709     CHECK_CALLED(doccp_onclick);
1710     CHECK_CALLED(invoke_onclick);
1711
1712     unregister_cp((IUnknown*)div, &DIID_HTMLElementEvents2, elem2_cp_cookie);
1713     unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie);
1714
1715     V_VT(&v) = VT_NULL;
1716     hres = IHTMLElement_put_onclick(div, v);
1717     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1718
1719     hres = IHTMLElement_get_onclick(div, &v);
1720     ok(hres == S_OK, "get_onclick failed: %08x\n", hres);
1721     ok(V_VT(&v) == VT_NULL, "get_onclick returned vt %d\n", V_VT(&v));
1722
1723     elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp);
1724     elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp);
1725     elem_detach_event((IUnknown*)div, "test", (IDispatch*)&div_onclick_disp);
1726     doc_detach_event(doc, "onclick", (IDispatch*)&doc_onclick_attached_obj);
1727
1728     SET_EXPECT(div_onclick_attached);
1729     SET_EXPECT(body_onclick);
1730     SET_EXPECT(document_onclick);
1731     SET_EXPECT(invoke_onclick);
1732
1733     hres = IHTMLElement_click(div);
1734     ok(hres == S_OK, "click failed: %08x\n", hres);
1735
1736     CHECK_CALLED(div_onclick_attached);
1737     CHECK_CALLED(body_onclick);
1738     CHECK_CALLED(document_onclick);
1739     CHECK_CALLED(invoke_onclick);
1740
1741     IHTMLElement_Release(div);
1742     IHTMLElement_Release(body);
1743 }
1744
1745 static void test_onreadystatechange(IHTMLDocument2 *doc)
1746 {
1747     IHTMLFrameBase *iframe;
1748     IHTMLElement2 *elem2;
1749     IHTMLElement *elem;
1750     VARIANT v;
1751     BSTR str;
1752     HRESULT hres;
1753
1754     elem = get_elem_id(doc, "iframe");
1755     elem2 = get_elem2_iface((IUnknown*)elem);
1756     IHTMLElement_Release(elem);
1757
1758     V_VT(&v) = VT_EMPTY;
1759     hres = IHTMLElement2_get_onreadystatechange(elem2, &v);
1760     ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres);
1761     ok(V_VT(&v) == VT_NULL, "V_VT(onreadystatechange) = %d\n", V_VT(&v));
1762
1763     V_VT(&v) = VT_DISPATCH;
1764     V_DISPATCH(&v) = (IDispatch*)&iframe_onreadystatechange_obj;
1765     hres = IHTMLElement2_put_onreadystatechange(elem2, v);
1766     ok(hres == S_OK, "put_onreadystatechange failed: %08x\n", hres);
1767
1768     V_VT(&v) = VT_EMPTY;
1769     hres = IHTMLElement2_get_onreadystatechange(elem2, &v);
1770     ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres);
1771     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onreadystatechange) = %d\n", V_VT(&v));
1772     ok(V_DISPATCH(&v) == (IDispatch*)&iframe_onreadystatechange_obj, "unexpected onreadystatechange value\n");
1773
1774     hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase, (void**)&iframe);
1775     IHTMLElement2_Release(elem2);
1776     ok(hres == S_OK, "Could not get IHTMLFrameBase iface: %08x\n", hres);
1777
1778     hres = IHTMLFrameBase_put_src(iframe, (str = a2bstr("about:blank")));
1779     SysFreeString(str);
1780     ok(hres == S_OK, "put_src failed: %08x\n", hres);
1781
1782     SET_EXPECT(iframe_onreadystatechange_loading);
1783     SET_EXPECT(iframedoc_onreadystatechange);
1784     SET_EXPECT(iframe_onreadystatechange_interactive);
1785     SET_EXPECT(iframe_onreadystatechange_complete);
1786     pump_msgs(&called_iframe_onreadystatechange_complete);
1787     CHECK_CALLED(iframe_onreadystatechange_loading);
1788     CHECK_CALLED(iframedoc_onreadystatechange);
1789     CHECK_CALLED(iframe_onreadystatechange_interactive);
1790     CHECK_CALLED(iframe_onreadystatechange_complete);
1791
1792     IHTMLFrameBase_Release(iframe);
1793 }
1794
1795 static void test_imgload(IHTMLDocument2 *doc)
1796 {
1797     IHTMLImgElement *img;
1798     IHTMLElement *elem;
1799     VARIANT v;
1800     BSTR str;
1801     HRESULT hres;
1802
1803     elem = get_elem_id(doc, "imgid");
1804     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLImgElement, (void**)&img);
1805     IHTMLElement_Release(elem);
1806     ok(hres == S_OK, "Could not get IHTMLImgElement iface: %08x\n", hres);
1807
1808     V_VT(&v) = VT_EMPTY;
1809     hres = IHTMLImgElement_get_onload(img, &v);
1810     ok(hres == S_OK, "get_onload failed: %08x\n", hres);
1811     ok(V_VT(&v) == VT_NULL, "V_VT(onload) = %d\n", V_VT(&v));
1812
1813     V_VT(&v) = VT_DISPATCH;
1814     V_DISPATCH(&v) = (IDispatch*)&img_onload_obj;
1815     hres = IHTMLImgElement_put_onload(img, v);
1816     ok(hres == S_OK, "put_onload failed: %08x\n", hres);
1817
1818     V_VT(&v) = VT_EMPTY;
1819     hres = IHTMLImgElement_get_onload(img, &v);
1820     ok(hres == S_OK, "get_onload failed: %08x\n", hres);
1821     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onload) = %d\n", V_VT(&v));
1822     ok(V_DISPATCH(&v) == (IDispatch*)&img_onload_obj, "V_DISPATCH(onload) != onloadkFunc\n");
1823     VariantClear(&v);
1824
1825     V_VT(&v) = VT_DISPATCH;
1826     V_DISPATCH(&v) = (IDispatch*)&img_onerror_obj;
1827     hres = IHTMLImgElement_put_onerror(img, v);
1828     ok(hres == S_OK, "put_onerror failed: %08x\n", hres);
1829
1830     V_VT(&v) = VT_EMPTY;
1831     hres = IHTMLImgElement_get_onerror(img, &v);
1832     ok(hres == S_OK, "get_onerror failed: %08x\n", hres);
1833     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onerror) = %d\n", V_VT(&v));
1834     ok(V_DISPATCH(&v) == (IDispatch*)&img_onerror_obj, "V_DISPATCH(onerror) != onerrorFunc\n");
1835     VariantClear(&v);
1836
1837     str = a2bstr("http://www.winehq.org/images/winehq_logo_text.png");
1838     hres = IHTMLImgElement_put_src(img, str);
1839     ok(hres == S_OK, "put_src failed: %08x\n", hres);
1840     SysFreeString(str);
1841
1842     SET_EXPECT(img_onload);
1843     pump_msgs(&called_img_onload);
1844     CHECK_CALLED(img_onload);
1845
1846     SET_EXPECT(img_onerror);
1847
1848     str = a2bstr("about:blank");
1849     hres = IHTMLImgElement_put_src(img, str);
1850     ok(hres == S_OK, "put_src failed: %08x\n", hres);
1851     SysFreeString(str);
1852
1853     pump_msgs(&called_img_onerror); /* FIXME: should not be needed */
1854
1855     CHECK_CALLED(img_onerror);
1856
1857     IHTMLImgElement_Release(img);
1858 }
1859
1860 static void test_focus(IHTMLDocument2 *doc)
1861 {
1862     IHTMLElement2 *elem2;
1863     IHTMLElement *elem;
1864     VARIANT v;
1865     HRESULT hres;
1866
1867     elem = get_elem_id(doc, "inputid");
1868     elem2 = get_elem2_iface((IUnknown*)elem);
1869     IHTMLElement_Release(elem);
1870
1871     V_VT(&v) = VT_EMPTY;
1872     hres = IHTMLElement2_get_onfocus(elem2, &v);
1873     ok(hres == S_OK, "get_onfocus failed: %08x\n", hres);
1874     ok(V_VT(&v) == VT_NULL, "V_VT(onfocus) = %d\n", V_VT(&v));
1875
1876     V_VT(&v) = VT_DISPATCH;
1877     V_DISPATCH(&v) = (IDispatch*)&input_onfocus_obj;
1878     hres = IHTMLElement2_put_onfocus(elem2, v);
1879     ok(hres == S_OK, "put_onfocus failed: %08x\n", hres);
1880
1881     V_VT(&v) = VT_EMPTY;
1882     hres = IHTMLElement2_get_onfocus(elem2, &v);
1883     ok(hres == S_OK, "get_onfocus failed: %08x\n", hres);
1884     ok(V_VT(&v) == VT_DISPATCH, "V_VT(onfocus) = %d\n", V_VT(&v));
1885     ok(V_DISPATCH(&v) == (IDispatch*)&input_onfocus_obj, "V_DISPATCH(onfocus) != onfocusFunc\n");
1886     VariantClear(&v);
1887
1888     if(!winetest_interactive)
1889         ShowWindow(container_hwnd, SW_SHOW);
1890
1891     SetFocus(NULL);
1892     ok(!IsChild(container_hwnd, GetFocus()), "focus belongs to document window\n");
1893
1894     hres = IHTMLWindow2_focus(window);
1895     ok(hres == S_OK, "focus failed: %08x\n", hres);
1896
1897     ok(IsChild(container_hwnd, GetFocus()), "focus does not belong to document window\n");
1898     pump_msgs(NULL);
1899
1900     SET_EXPECT(input_onfocus);
1901     hres = IHTMLElement2_focus(elem2);
1902     pump_msgs(NULL);
1903     CHECK_CALLED(input_onfocus);
1904     ok(hres == S_OK, "focus failed: %08x\n", hres);
1905
1906     V_VT(&v) = VT_DISPATCH;
1907     V_DISPATCH(&v) = (IDispatch*)&input_onblur_obj;
1908     hres = IHTMLElement2_put_onblur(elem2, v);
1909     ok(hres == S_OK, "put_onblur failed: %08x\n", hres);
1910
1911     SET_EXPECT(input_onblur);
1912     hres = IHTMLElement2_blur(elem2);
1913     pump_msgs(NULL);
1914     CHECK_CALLED(input_onblur);
1915     ok(hres == S_OK, "blur failed: %08x\n", hres);
1916
1917     if(!winetest_interactive)
1918         ShowWindow(container_hwnd, SW_HIDE);
1919
1920     IHTMLElement2_Release(elem2);
1921 }
1922
1923 static void test_submit(IHTMLDocument2 *doc)
1924 {
1925     IHTMLElement *elem, *submit;
1926     IHTMLFormElement *form;
1927     VARIANT v;
1928     DWORD cp_cookie;
1929     HRESULT hres;
1930
1931     elem = get_elem_id(doc, "formid");
1932
1933     V_VT(&v) = VT_DISPATCH;
1934     V_DISPATCH(&v) = (IDispatch*)&form_onclick_obj;
1935     hres = IHTMLElement_put_onclick(elem, v);
1936     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1937
1938     hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLFormElement, (void**)&form);
1939     IHTMLElement_Release(elem);
1940     ok(hres == S_OK, "Could not get IHTMLFormElement iface: %08x\n", hres);
1941
1942     V_VT(&v) = VT_DISPATCH;
1943     V_DISPATCH(&v) = (IDispatch*)&form_onsubmit_obj;
1944     hres = IHTMLFormElement_put_onsubmit(form, v);
1945     ok(hres == S_OK, "put_onsubmit failed: %08x\n", hres);
1946
1947     IHTMLFormElement_Release(form);
1948
1949     submit = get_elem_id(doc, "submitid");
1950
1951     SET_EXPECT(form_onclick);
1952     SET_EXPECT(form_onsubmit);
1953     hres = IHTMLElement_click(submit);
1954     ok(hres == S_OK, "click failed: %08x\n", hres);
1955     CHECK_CALLED(form_onclick);
1956     CHECK_CALLED(form_onsubmit);
1957
1958     V_VT(&v) = VT_DISPATCH;
1959     V_DISPATCH(&v) = (IDispatch*)&submit_onclick_obj;
1960     hres = IHTMLElement_put_onclick(submit, v);
1961     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1962
1963     SET_EXPECT(form_onclick);
1964     SET_EXPECT(submit_onclick);
1965     hres = IHTMLElement_click(submit);
1966     ok(hres == S_OK, "click failed: %08x\n", hres);
1967     CHECK_CALLED(form_onclick);
1968     CHECK_CALLED(submit_onclick);
1969
1970     elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj);
1971
1972     SET_EXPECT(form_onclick);
1973     SET_EXPECT(submit_onclick);
1974     SET_EXPECT(submit_onclick_attached);
1975     hres = IHTMLElement_click(submit);
1976     ok(hres == S_OK, "click failed: %08x\n", hres);
1977     CHECK_CALLED(form_onclick);
1978     CHECK_CALLED(submit_onclick);
1979     CHECK_CALLED(submit_onclick_attached);
1980
1981     V_VT(&v) = VT_NULL;
1982     hres = IHTMLElement_put_onclick(submit, v);
1983     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
1984
1985     SET_EXPECT(form_onclick);
1986     SET_EXPECT(submit_onclick_attached);
1987     hres = IHTMLElement_click(submit);
1988     ok(hres == S_OK, "click failed: %08x\n", hres);
1989     CHECK_CALLED(form_onclick);
1990     CHECK_CALLED(submit_onclick_attached);
1991
1992     elem_detach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj);
1993
1994     cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_onclick_cancel_obj);
1995
1996     SET_EXPECT(form_onclick);
1997     SET_EXPECT(doccp_onclick_cancel);
1998     hres = IHTMLElement_click(submit);
1999     ok(hres == S_OK, "click failed: %08x\n", hres);
2000     CHECK_CALLED(form_onclick);
2001     CHECK_CALLED(doccp_onclick_cancel);
2002
2003     unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie);
2004
2005     V_VT(&v) = VT_DISPATCH;
2006     V_DISPATCH(&v) = (IDispatch*)&submit_onclick_setret_obj;
2007     hres = IHTMLElement_put_onclick(submit, v);
2008     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
2009
2010     V_VT(&onclick_retval) = VT_BOOL;
2011     V_BOOL(&onclick_retval) = VARIANT_TRUE;
2012     V_VT(&onclick_event_retval) = VT_BOOL;
2013     V_BOOL(&onclick_event_retval) = VARIANT_TRUE;
2014
2015     SET_EXPECT(submit_onclick_setret);
2016     SET_EXPECT(form_onclick);
2017     SET_EXPECT(form_onsubmit);
2018     hres = IHTMLElement_click(submit);
2019     ok(hres == S_OK, "click failed: %08x\n", hres);
2020     CHECK_CALLED(submit_onclick_setret);
2021     CHECK_CALLED(form_onclick);
2022     CHECK_CALLED(form_onsubmit);
2023
2024     V_VT(&onclick_event_retval) = VT_BOOL;
2025     V_BOOL(&onclick_event_retval) = VARIANT_FALSE;
2026
2027     SET_EXPECT(submit_onclick_setret);
2028     SET_EXPECT(form_onclick);
2029     hres = IHTMLElement_click(submit);
2030     ok(hres == S_OK, "click failed: %08x\n", hres);
2031     CHECK_CALLED(submit_onclick_setret);
2032     CHECK_CALLED(form_onclick);
2033
2034     V_VT(&onclick_retval) = VT_BOOL;
2035     V_BOOL(&onclick_retval) = VARIANT_FALSE;
2036     V_VT(&onclick_event_retval) = VT_BOOL;
2037     V_BOOL(&onclick_event_retval) = VARIANT_TRUE;
2038
2039     SET_EXPECT(submit_onclick_setret);
2040     SET_EXPECT(form_onclick);
2041     hres = IHTMLElement_click(submit);
2042     ok(hres == S_OK, "click failed: %08x\n", hres);
2043     CHECK_CALLED(submit_onclick_setret);
2044     CHECK_CALLED(form_onclick);
2045
2046     V_VT(&onclick_event_retval) = VT_BOOL;
2047     V_BOOL(&onclick_event_retval) = VARIANT_FALSE;
2048
2049     SET_EXPECT(submit_onclick_setret);
2050     SET_EXPECT(form_onclick);
2051     hres = IHTMLElement_click(submit);
2052     ok(hres == S_OK, "click failed: %08x\n", hres);
2053     CHECK_CALLED(submit_onclick_setret);
2054     CHECK_CALLED(form_onclick);
2055
2056     elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_obj);
2057     elem_attach_event((IUnknown*)submit, "onclick", (IDispatch*)&submit_onclick_attached_check_cancel_obj);
2058
2059     V_VT(&v) = VT_DISPATCH;
2060     V_DISPATCH(&v) = (IDispatch*)&submit_onclick_cancel_obj;
2061     hres = IHTMLElement_put_onclick(submit, v);
2062     ok(hres == S_OK, "put_onclick failed: %08x\n", hres);
2063
2064     SET_EXPECT(submit_onclick_cancel);
2065     SET_EXPECT(submit_onclick_attached_check_cancel);
2066     SET_EXPECT(submit_onclick_attached);
2067     hres = IHTMLElement_click(submit);
2068     ok(hres == S_OK, "click failed: %08x\n", hres);
2069     CHECK_CALLED(submit_onclick_cancel);
2070     CHECK_CALLED(submit_onclick_attached_check_cancel);
2071     CHECK_CALLED(submit_onclick_attached);
2072
2073     IHTMLElement_Release(submit);
2074 }
2075
2076 static void test_timeout(IHTMLDocument2 *doc)
2077 {
2078     IHTMLWindow3 *win3;
2079     VARIANT expr, var;
2080     LONG id;
2081     HRESULT hres;
2082
2083     hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow3, (void**)&win3);
2084     ok(hres == S_OK, "Could not get IHTMLWindow3 iface: %08x\n", hres);
2085
2086     V_VT(&expr) = VT_DISPATCH;
2087     V_DISPATCH(&expr) = (IDispatch*)&timeoutFunc;
2088     V_VT(&var) = VT_EMPTY;
2089     id = 0;
2090     hres = IHTMLWindow3_setTimeout(win3, &expr, 0, &var, &id);
2091     ok(hres == S_OK, "setTimeout failed: %08x\n", hres);
2092     ok(id, "id = 0\n");
2093
2094     SET_EXPECT(timeout);
2095     pump_msgs(&called_timeout);
2096     CHECK_CALLED(timeout);
2097
2098     V_VT(&expr) = VT_DISPATCH;
2099     V_DISPATCH(&expr) = (IDispatch*)&timeoutFunc;
2100     V_VT(&var) = VT_EMPTY;
2101     id = 0;
2102     hres = IHTMLWindow3_setTimeout(win3, &expr, 0, &var, &id);
2103     ok(hres == S_OK, "setTimeout failed: %08x\n", hres);
2104     ok(id, "id = 0\n");
2105
2106     hres = IHTMLWindow2_clearTimeout(window, id);
2107     ok(hres == S_OK, "clearTimeout failed: %08x\n", hres);
2108
2109     IHTMLWindow3_Release(win3);
2110 }
2111
2112 static IHTMLElement* find_element_by_id(IHTMLDocument2 *doc, const char *id)
2113 {
2114     HRESULT hres;
2115     IHTMLDocument3 *doc3;
2116     IHTMLElement *result;
2117     BSTR idW = a2bstr(id);
2118
2119     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
2120     ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
2121
2122     hres = IHTMLDocument3_getElementById(doc3, idW, &result);
2123     ok(hres == S_OK, "getElementById failed: %08x\n", hres);
2124     ok(result != NULL, "result == NULL\n");
2125     SysFreeString(idW);
2126
2127     IHTMLDocument3_Release(doc3);
2128     return result;
2129 }
2130
2131 static IHTMLDocument2* get_iframe_doc(IHTMLIFrameElement *iframe)
2132 {
2133     HRESULT hres;
2134     IHTMLFrameBase2 *base;
2135     IHTMLDocument2 *result = NULL;
2136
2137     hres = IHTMLIFrameElement_QueryInterface(iframe, &IID_IHTMLFrameBase2, (void**)&base);
2138     ok(hres == S_OK, "QueryInterface(IID_IHTMLFrameBase2) failed: %08x\n", hres);
2139     if(hres == S_OK) {
2140         IHTMLWindow2 *window;
2141
2142         hres = IHTMLFrameBase2_get_contentWindow(base, &window);
2143         ok(hres == S_OK, "get_contentWindow failed: %08x\n", hres);
2144         ok(window != NULL, "window == NULL\n");
2145         if(window) {
2146             hres = IHTMLWindow2_get_document(window, &result);
2147             ok(hres == S_OK, "get_document failed: %08x\n", hres);
2148             ok(result != NULL, "result == NULL\n");
2149             IHTMLWindow2_Release(window);
2150         }
2151     }
2152     if(base) IHTMLFrameBase2_Release(base);
2153
2154     return result;
2155 }
2156
2157 static void test_iframe_connections(IHTMLDocument2 *doc)
2158 {
2159     HRESULT hres;
2160     IHTMLIFrameElement *iframe;
2161     IHTMLDocument2 *iframes_doc;
2162     DWORD cookie;
2163     IConnectionPoint *cp;
2164     IHTMLElement *element = find_element_by_id(doc, "ifr");
2165
2166     hres = IHTMLElement_QueryInterface(element, &IID_IHTMLIFrameElement, (void**)&iframe);
2167     IHTMLElement_Release(element);
2168     ok(hres == S_OK, "QueryInterface(IID_IHTMLIFrameElement) failed: %08x\n", hres);
2169
2170     iframes_doc = get_iframe_doc(iframe);
2171     IHTMLIFrameElement_Release(iframe);
2172
2173     cookie = register_cp((IUnknown*)iframes_doc, &IID_IDispatch, (IUnknown*)&div_onclick_disp);
2174
2175     cp = get_cp((IUnknown*)doc, &IID_IDispatch);
2176     hres = IConnectionPoint_Unadvise(cp, cookie);
2177     IConnectionPoint_Release(cp);
2178     ok(hres == CONNECT_E_NOCONNECTION, "Unadvise returned %08x, expected CONNECT_E_NOCONNECTION\n", hres);
2179
2180     IHTMLDocument2_Release(iframes_doc);
2181 }
2182
2183 static HRESULT QueryInterface(REFIID,void**);
2184
2185 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv)
2186 {
2187     return E_NOINTERFACE;
2188 }
2189
2190 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
2191 {
2192     return 2;
2193 }
2194
2195 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
2196 {
2197     return 1;
2198 }
2199
2200 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
2201 {
2202     return E_NOTIMPL;
2203 }
2204
2205 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
2206 {
2207     return E_NOTIMPL;
2208 }
2209
2210 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
2211 {
2212     return E_NOTIMPL;
2213 }
2214
2215 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
2216         LPCBORDERWIDTHS pborderwidths)
2217 {
2218     return E_NOTIMPL;
2219 }
2220
2221 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
2222         LPCBORDERWIDTHS pborderwidths)
2223 {
2224     return S_OK;
2225 }
2226
2227 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface,
2228         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
2229 {
2230     return S_OK;
2231 }
2232
2233 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
2234         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
2235 {
2236     return S_OK;
2237 }
2238
2239 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
2240         LPOLEMENUGROUPWIDTHS lpMenuWidths)
2241 {
2242     return E_NOTIMPL;
2243 }
2244
2245 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
2246         HOLEMENU holemenu, HWND hwndActiveObject)
2247 {
2248     ok(0, "unexpected call\n");
2249     return E_NOTIMPL;
2250 }
2251
2252 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
2253 {
2254     ok(0, "unexpected call\n");
2255     return E_NOTIMPL;
2256 }
2257
2258 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText)
2259 {
2260     return S_OK;
2261 }
2262
2263 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
2264 {
2265     return E_NOTIMPL;
2266 }
2267
2268 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
2269 {
2270     ok(0, "unexpected call\n");
2271     return E_NOTIMPL;
2272 }
2273
2274 static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
2275     InPlaceFrame_QueryInterface,
2276     InPlaceFrame_AddRef,
2277     InPlaceFrame_Release,
2278     InPlaceFrame_GetWindow,
2279     InPlaceFrame_ContextSensitiveHelp,
2280     InPlaceFrame_GetBorder,
2281     InPlaceFrame_RequestBorderSpace,
2282     InPlaceFrame_SetBorderSpace,
2283     InPlaceFrame_SetActiveObject,
2284     InPlaceFrame_InsertMenus,
2285     InPlaceFrame_SetMenu,
2286     InPlaceFrame_RemoveMenus,
2287     InPlaceFrame_SetStatusText,
2288     InPlaceFrame_EnableModeless,
2289     InPlaceFrame_TranslateAccelerator
2290 };
2291
2292 static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
2293
2294 static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = {
2295     InPlaceFrame_QueryInterface,
2296     InPlaceFrame_AddRef,
2297     InPlaceFrame_Release,
2298     InPlaceFrame_GetWindow,
2299     InPlaceFrame_ContextSensitiveHelp,
2300     InPlaceFrame_GetBorder,
2301     InPlaceFrame_RequestBorderSpace,
2302     InPlaceFrame_SetBorderSpace,
2303     InPlaceUIWindow_SetActiveObject,
2304 };
2305
2306 static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl };
2307
2308 static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
2309 {
2310     return QueryInterface(riid, ppv);
2311 }
2312
2313 static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface)
2314 {
2315     return 2;
2316 }
2317
2318 static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface)
2319 {
2320     return 1;
2321 }
2322
2323 static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd)
2324 {
2325     *phwnd = container_hwnd;
2326     return S_OK;
2327 }
2328
2329 static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
2330 {
2331     ok(0, "unexpected call\n");
2332     return E_NOTIMPL;
2333 }
2334
2335 static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface)
2336 {
2337     return S_OK;
2338 }
2339
2340 static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface)
2341 {
2342     return S_OK;
2343 }
2344
2345 static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface)
2346 {
2347     return S_OK;
2348 }
2349
2350 static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface,
2351         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
2352         LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
2353 {
2354     static const RECT rect = {0,0,300,300};
2355
2356     *ppFrame = &InPlaceFrame;
2357     *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow;
2358     *lprcPosRect = rect;
2359     *lprcClipRect = rect;
2360
2361     ok(lpFrameInfo->cb == sizeof(*lpFrameInfo), "lpFrameInfo->cb = %u, expected %u\n", lpFrameInfo->cb, (unsigned)sizeof(*lpFrameInfo));
2362     lpFrameInfo->fMDIApp = FALSE;
2363     lpFrameInfo->hwndFrame = container_hwnd;
2364     lpFrameInfo->haccel = NULL;
2365     lpFrameInfo->cAccelEntries = 0;
2366
2367     return S_OK;
2368 }
2369
2370 static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant)
2371 {
2372     return E_NOTIMPL;
2373 }
2374
2375 static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
2376 {
2377     return S_OK;
2378 }
2379
2380 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface)
2381 {
2382     return S_OK;
2383 }
2384
2385 static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface)
2386 {
2387     return E_NOTIMPL;
2388 }
2389
2390 static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface)
2391 {
2392     return E_NOTIMPL;
2393 }
2394
2395 static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
2396 {
2397     return E_NOTIMPL;
2398 }
2399
2400 static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = {
2401     InPlaceSite_QueryInterface,
2402     InPlaceSite_AddRef,
2403     InPlaceSite_Release,
2404     InPlaceSite_GetWindow,
2405     InPlaceSite_ContextSensitiveHelp,
2406     InPlaceSite_CanInPlaceActivate,
2407     InPlaceSite_OnInPlaceActivate,
2408     InPlaceSite_OnUIActivate,
2409     InPlaceSite_GetWindowContext,
2410     InPlaceSite_Scroll,
2411     InPlaceSite_OnUIDeactivate,
2412     InPlaceSite_OnInPlaceDeactivate,
2413     InPlaceSite_DiscardUndoState,
2414     InPlaceSite_DeactivateAndUndo,
2415     InPlaceSite_OnPosRectChange,
2416 };
2417
2418 static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl };
2419
2420 static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
2421 {
2422     return QueryInterface(riid, ppv);
2423 }
2424
2425 static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
2426 {
2427     return 2;
2428 }
2429
2430 static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
2431 {
2432     return 1;
2433 }
2434
2435 static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
2436 {
2437     ok(0, "unexpected call\n");
2438     return E_NOTIMPL;
2439 }
2440
2441 static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker,
2442         IMoniker **ppmon)
2443 {
2444     ok(0, "unexpected call\n");
2445     return E_NOTIMPL;
2446 }
2447
2448 static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
2449 {
2450     return E_NOTIMPL;
2451 }
2452
2453 static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
2454 {
2455     ok(0, "unexpected call\n");
2456     return E_NOTIMPL;
2457 }
2458
2459 static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
2460 {
2461     ok(0, "unexpected call\n");
2462     return E_NOTIMPL;
2463 }
2464
2465 static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
2466 {
2467     ok(0, "unexpected call\n");
2468     return E_NOTIMPL;
2469 }
2470
2471 static const IOleClientSiteVtbl ClientSiteVtbl = {
2472     ClientSite_QueryInterface,
2473     ClientSite_AddRef,
2474     ClientSite_Release,
2475     ClientSite_SaveObject,
2476     ClientSite_GetMoniker,
2477     ClientSite_GetContainer,
2478     ClientSite_ShowObject,
2479     ClientSite_OnShowWindow,
2480     ClientSite_RequestNewObjectLayout
2481 };
2482
2483 static IOleClientSite ClientSite = { &ClientSiteVtbl };
2484
2485 static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv)
2486 {
2487     return QueryInterface(riid, ppv);
2488 }
2489
2490 static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface)
2491 {
2492     return 2;
2493 }
2494
2495 static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface)
2496 {
2497     return 1;
2498 }
2499
2500 static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate)
2501 {
2502     RECT rect = {0,0,300,300};
2503     IOleDocument *document;
2504     HRESULT hres;
2505
2506     hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document);
2507     ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres);
2508
2509     hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view);
2510     IOleDocument_Release(document);
2511     ok(hres == S_OK, "CreateView failed: %08x\n", hres);
2512
2513     hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite);
2514     ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres);
2515
2516     hres = IOleDocumentView_UIActivate(view, TRUE);
2517     ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
2518
2519     hres = IOleDocumentView_SetRect(view, &rect);
2520     ok(hres == S_OK, "SetRect failed: %08x\n", hres);
2521
2522     hres = IOleDocumentView_Show(view, TRUE);
2523     ok(hres == S_OK, "Show failed: %08x\n", hres);
2524
2525     return S_OK;
2526 }
2527
2528 static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
2529     DocumentSite_QueryInterface,
2530     DocumentSite_AddRef,
2531     DocumentSite_Release,
2532     DocumentSite_ActivateMe
2533 };
2534
2535 static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
2536
2537 static HRESULT QueryInterface(REFIID riid, void **ppv)
2538 {
2539     *ppv = NULL;
2540
2541     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid))
2542         *ppv = &ClientSite;
2543     else if(IsEqualGUID(&IID_IOleDocumentSite, riid))
2544         *ppv = &DocumentSite;
2545     else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid))
2546         *ppv = &InPlaceSite;
2547
2548     return *ppv ? S_OK : E_NOINTERFACE;
2549 }
2550
2551 static IHTMLDocument2 *notif_doc;
2552 static BOOL doc_complete;
2553
2554 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
2555         REFIID riid, void**ppv)
2556 {
2557     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
2558         *ppv = iface;
2559         return S_OK;
2560     }
2561
2562     ok(0, "unexpected call\n");
2563     return E_NOINTERFACE;
2564 }
2565
2566 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
2567 {
2568     return 2;
2569 }
2570
2571 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
2572 {
2573     return 1;
2574 }
2575
2576 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
2577 {
2578     if(dispID == DISPID_READYSTATE){
2579         BSTR state;
2580         HRESULT hres;
2581
2582         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
2583         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
2584
2585         if(!strcmp_wa(state, "complete"))
2586             doc_complete = TRUE;
2587
2588         SysFreeString(state);
2589     }
2590
2591     return S_OK;
2592 }
2593
2594 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
2595 {
2596     ok(0, "unexpected call\n");
2597     return E_NOTIMPL;
2598 }
2599
2600 static const IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
2601     PropertyNotifySink_QueryInterface,
2602     PropertyNotifySink_AddRef,
2603     PropertyNotifySink_Release,
2604     PropertyNotifySink_OnChanged,
2605     PropertyNotifySink_OnRequestEdit
2606 };
2607
2608 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
2609
2610 static void doc_load_string(IHTMLDocument2 *doc, const char *str)
2611 {
2612     IPersistStreamInit *init;
2613     IStream *stream;
2614     HGLOBAL mem;
2615     SIZE_T len;
2616
2617     notif_doc = doc;
2618
2619     doc_complete = FALSE;
2620     len = strlen(str);
2621     mem = GlobalAlloc(0, len);
2622     memcpy(mem, str, len);
2623     CreateStreamOnHGlobal(mem, TRUE, &stream);
2624
2625     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
2626
2627     IPersistStreamInit_Load(init, stream);
2628     IPersistStreamInit_Release(init);
2629     IStream_Release(stream);
2630 }
2631
2632 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
2633 {
2634     IConnectionPointContainer *container;
2635     IConnectionPoint *cp;
2636     DWORD cookie;
2637     HRESULT hres;
2638
2639     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
2640     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
2641
2642     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
2643     IConnectionPointContainer_Release(container);
2644     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
2645
2646     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
2647     IConnectionPoint_Release(cp);
2648     ok(hres == S_OK, "Advise failed: %08x\n", hres);
2649 }
2650
2651 static void set_client_site(IHTMLDocument2 *doc, BOOL set)
2652 {
2653     IOleObject *oleobj;
2654     HRESULT hres;
2655
2656     if(!set && view) {
2657         IOleDocumentView_Show(view, FALSE);
2658         IOleDocumentView_CloseView(view, 0);
2659         IOleDocumentView_SetInPlaceSite(view, NULL);
2660         IOleDocumentView_Release(view);
2661         view = NULL;
2662     }
2663
2664     hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
2665     ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres);
2666
2667     hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL);
2668     ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
2669
2670     if(set) {
2671         IHlinkTarget *hlink;
2672
2673         hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink);
2674         ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres);
2675
2676         hres = IHlinkTarget_Navigate(hlink, 0, NULL);
2677         ok(hres == S_OK, "Navgate failed: %08x\n", hres);
2678
2679         IHlinkTarget_Release(hlink);
2680     }
2681
2682     IOleObject_Release(oleobj);
2683 }
2684 static IHTMLDocument2 *create_document(void)
2685 {
2686     IHTMLDocument2 *doc;
2687     IHTMLDocument5 *doc5;
2688     HRESULT hres;
2689
2690     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2691             &IID_IHTMLDocument2, (void**)&doc);
2692     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2693     if (FAILED(hres))
2694         return NULL;
2695
2696     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5);
2697     if(FAILED(hres)) {
2698         win_skip("Could not get IHTMLDocument5 interface, probably too old IE\n");
2699         IHTMLDocument2_Release(doc);
2700         return NULL;
2701     }
2702
2703     IHTMLDocument5_Release(doc5);
2704     return doc;
2705 }
2706
2707
2708 typedef void (*testfunc_t)(IHTMLDocument2*);
2709
2710 static void run_test(const char *str, testfunc_t test)
2711 {
2712     IHTMLDocument2 *doc;
2713     IHTMLElement *body = NULL;
2714     MSG msg;
2715     HRESULT hres;
2716
2717     xy_todo = FALSE;
2718     doc = create_document();
2719     if (!doc)
2720         return;
2721     set_client_site(doc, TRUE);
2722     doc_load_string(doc, str);
2723     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
2724
2725     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
2726         TranslateMessage(&msg);
2727         DispatchMessage(&msg);
2728     }
2729
2730     hres = IHTMLDocument2_get_body(doc, &body);
2731     ok(hres == S_OK, "get_body failed: %08x\n", hres);
2732
2733     if(body) {
2734         IHTMLElement_Release(body);
2735
2736         hres = IHTMLDocument2_get_parentWindow(doc, &window);
2737         ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
2738         ok(window != NULL, "window == NULL\n");
2739
2740         test(doc);
2741
2742         IHTMLWindow2_Release(window);
2743         window = NULL;
2744     }else {
2745         skip("Could not get document body. Assuming no Gecko installed.\n");
2746     }
2747
2748     set_client_site(doc, FALSE);
2749     IHTMLDocument2_Release(doc);
2750 }
2751
2752 static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2753 {
2754     return DefWindowProc(hwnd, msg, wParam, lParam);
2755 }
2756
2757 static HWND create_container_window(void)
2758 {
2759     static const CHAR szHTMLDocumentTest[] = "HTMLDocumentTest";
2760     static WNDCLASSEXA wndclass = {
2761         sizeof(WNDCLASSEXA),
2762         0,
2763         wnd_proc,
2764         0, 0, NULL, NULL, NULL, NULL, NULL,
2765         szHTMLDocumentTest,
2766         NULL
2767     };
2768
2769     RegisterClassExA(&wndclass);
2770     return CreateWindowA(szHTMLDocumentTest, szHTMLDocumentTest,
2771             WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
2772             300, 300, NULL, NULL, NULL, NULL);
2773 }
2774
2775 static void test_empty_document(void)
2776 {
2777     HRESULT hres;
2778     IHTMLWindow2 *window;
2779     IHTMLDocument2 *windows_doc, *doc;
2780     IConnectionPoint *cp;
2781     DWORD cookie;
2782
2783     doc = create_document();
2784     if(!doc)
2785         return;
2786
2787     hres = IHTMLDocument2_get_parentWindow(doc, &window);
2788     ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres);
2789
2790     hres = IHTMLWindow2_get_document(window, &windows_doc);
2791     IHTMLWindow2_Release(window);
2792     ok(hres == S_OK, "get_document failed: %08x\n", hres);
2793
2794     cookie = register_cp((IUnknown*)windows_doc, &IID_IDispatch, (IUnknown*)&div_onclick_disp);
2795
2796     cp = get_cp((IUnknown*)doc, &IID_IDispatch);
2797     hres = IConnectionPoint_Unadvise(cp, cookie);
2798     IConnectionPoint_Release(cp);
2799     ok(hres == S_OK, "Unadvise failed: %08x\n", hres);
2800
2801     IHTMLDocument2_Release(windows_doc);
2802     IHTMLDocument2_Release(doc);
2803 }
2804
2805 START_TEST(events)
2806 {
2807     CoInitialize(NULL);
2808     container_hwnd = create_container_window();
2809
2810     if(winetest_interactive)
2811         ShowWindow(container_hwnd, SW_SHOW);
2812
2813     run_test(empty_doc_str, test_timeout);
2814     run_test(click_doc_str, test_onclick);
2815     run_test(readystate_doc_str, test_onreadystatechange);
2816     run_test(img_doc_str, test_imgload);
2817     run_test(input_doc_str, test_focus);
2818     run_test(form_doc_str, test_submit);
2819     run_test(iframe_doc_str, test_iframe_connections);
2820
2821     test_empty_document();
2822
2823     DestroyWindow(container_hwnd);
2824     CoUninitialize();
2825 }