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