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