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