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