| /* |
| * Copyright 2008-2009 Jacek Caban for CodeWeavers |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #define COBJMACROS |
| #define CONST_VTABLE |
| |
| #include <wine/test.h> |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "ole2.h" |
| #include "mshtml.h" |
| #include "mshtmdid.h" |
| #include "docobj.h" |
| #include "hlink.h" |
| #include "dispex.h" |
| |
| #define DEFINE_EXPECT(func) \ |
| static BOOL expect_ ## func = FALSE, called_ ## func = FALSE |
| |
| #define SET_EXPECT(func) \ |
| do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0) |
| |
| #define CHECK_EXPECT2(func) \ |
| do { \ |
| trace(#func "\n"); \ |
| ok(expect_ ##func, "unexpected call " #func "\n"); \ |
| called_ ## func = TRUE; \ |
| }while(0) |
| |
| #define CHECK_EXPECT(func) \ |
| do { \ |
| CHECK_EXPECT2(func); \ |
| expect_ ## func = FALSE; \ |
| }while(0) |
| |
| #define CHECK_CALLED(func) \ |
| do { \ |
| ok(called_ ## func, "expected " #func "\n"); \ |
| expect_ ## func = called_ ## func = FALSE; \ |
| }while(0) |
| |
| DEFINE_EXPECT(document_onclick); |
| DEFINE_EXPECT(body_onclick); |
| DEFINE_EXPECT(div_onclick); |
| DEFINE_EXPECT(div_onclick_attached); |
| DEFINE_EXPECT(timeout); |
| DEFINE_EXPECT(doccp_onclick); |
| DEFINE_EXPECT(div_onclick_disp); |
| DEFINE_EXPECT(iframe_onreadystatechange_loading); |
| DEFINE_EXPECT(iframe_onreadystatechange_interactive); |
| DEFINE_EXPECT(iframe_onreadystatechange_complete); |
| DEFINE_EXPECT(iframedoc_onreadystatechange); |
| DEFINE_EXPECT(img_onload); |
| |
| static HWND container_hwnd = NULL; |
| static IHTMLWindow2 *window; |
| static IOleDocumentView *view; |
| static BOOL xy_todo; |
| |
| typedef struct { |
| LONG x; |
| LONG y; |
| LONG offset_x; |
| LONG offset_y; |
| } xy_test_t; |
| |
| static const xy_test_t no_xy = {-10,-10,-10,-10}; |
| static const xy_test_t zero_xy = {0,0,0,0}; |
| |
| static const char empty_doc_str[] = |
| "<html></html>"; |
| |
| static const char click_doc_str[] = |
| "<html><body>" |
| "<div id=\"clickdiv\" style=\"text-align: center; background: red; font-size: 32\">click here</div>" |
| "</body></html>"; |
| |
| static const char readystate_doc_str[] = |
| "<html><body><iframe id=\"iframe\"></iframe></body></html>"; |
| |
| static const char img_doc_str[] = |
| "<html><body><img id=\"imgid\"></img></body></html>"; |
| |
| static const char *debugstr_guid(REFIID riid) |
| { |
| static char buf[50]; |
| |
| sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", |
| riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], |
| riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4], |
| riid->Data4[5], riid->Data4[6], riid->Data4[7]); |
| |
| return buf; |
| } |
| |
| static int strcmp_wa(LPCWSTR strw, const char *stra) |
| { |
| CHAR buf[512]; |
| WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); |
| return lstrcmpA(stra, buf); |
| } |
| |
| static BSTR a2bstr(const char *str) |
| { |
| BSTR ret; |
| int len; |
| |
| len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); |
| ret = SysAllocStringLen(NULL, len-1); |
| MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); |
| |
| return ret; |
| } |
| |
| static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2) |
| { |
| IUnknown *unk1, *unk2; |
| |
| if(iface1 == iface2) |
| return TRUE; |
| |
| IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1); |
| IUnknown_Release(unk1); |
| IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk2); |
| IUnknown_Release(unk2); |
| |
| return unk1 == unk2; |
| } |
| |
| #define test_disp(u,id) _test_disp(__LINE__,u,id) |
| static void _test_disp(unsigned line, IUnknown *unk, const IID *diid) |
| { |
| IDispatchEx *dispex; |
| ITypeInfo *typeinfo; |
| UINT ticnt; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IDispatchEx, (void**)&dispex); |
| ok_(__FILE__,line) (hres == S_OK, "Could not get IDispatch: %08x\n", hres); |
| if(FAILED(hres)) |
| return; |
| |
| ticnt = 0xdeadbeef; |
| hres = IDispatchEx_GetTypeInfoCount(dispex, &ticnt); |
| ok_(__FILE__,line) (hres == S_OK, "GetTypeInfoCount failed: %08x\n", hres); |
| ok_(__FILE__,line) (ticnt == 1, "ticnt=%u\n", ticnt); |
| |
| hres = IDispatchEx_GetTypeInfo(dispex, 0, 0, &typeinfo); |
| ok_(__FILE__,line) (hres == S_OK, "GetTypeInfo failed: %08x\n", hres); |
| |
| if(SUCCEEDED(hres)) { |
| TYPEATTR *type_attr; |
| |
| hres = ITypeInfo_GetTypeAttr(typeinfo, &type_attr); |
| ok_(__FILE__,line) (hres == S_OK, "GetTypeAttr failed: %08x\n", hres); |
| ok_(__FILE__,line) (IsEqualGUID(&type_attr->guid, diid), "unexpected guid %s\n", |
| debugstr_guid(&type_attr->guid)); |
| |
| ITypeInfo_ReleaseTypeAttr(typeinfo, type_attr); |
| ITypeInfo_Release(typeinfo); |
| } |
| |
| IDispatchEx_Release(dispex); |
| } |
| |
| #define get_doc3_iface(u) _get_doc3_iface(__LINE__,u) |
| static IHTMLDocument3 *_get_doc3_iface(unsigned line, IUnknown *unk) |
| { |
| IHTMLDocument3 *doc3; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument3, (void**)&doc3); |
| ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 iface: %08x\n", hres); |
| |
| return doc3; |
| } |
| |
| #define get_elem_iface(u) _get_elem_iface(__LINE__,u) |
| static IHTMLElement *_get_elem_iface(unsigned line, IUnknown *unk) |
| { |
| IHTMLElement *elem; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement, (void**)&elem); |
| ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement iface: %08x\n", hres); |
| |
| return elem; |
| } |
| |
| #define get_elem2_iface(u) _get_elem2_iface(__LINE__,u) |
| static IHTMLElement2 *_get_elem2_iface(unsigned line, IUnknown *unk) |
| { |
| IHTMLElement2 *elem2; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement2, (void**)&elem2); |
| ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement2 iface: %08x\n", hres); |
| |
| return elem2; |
| } |
| |
| #define get_elem3_iface(u) _get_elem3_iface(__LINE__,u) |
| static IHTMLElement3 *_get_elem3_iface(unsigned line, IUnknown *unk) |
| { |
| IHTMLElement3 *elem3; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IHTMLElement3, (void**)&elem3); |
| ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLElement3 iface: %08x\n", hres); |
| |
| return elem3; |
| } |
| |
| #define doc_get_body(d) _doc_get_body(__LINE__,d) |
| static IHTMLElement *_doc_get_body(unsigned line, IHTMLDocument2 *doc) |
| { |
| IHTMLElement *body = NULL; |
| HRESULT hres; |
| |
| hres = IHTMLDocument2_get_body(doc, &body); |
| ok_(__FILE__,line) (hres == S_OK, "get_body failed: %08x\n", hres); |
| ok_(__FILE__,line) (body != NULL, "body == NULL\n"); |
| |
| return body; |
| } |
| |
| #define get_elem_id(d,i) _get_elem_id(__LINE__,d,i) |
| static IHTMLElement *_get_elem_id(unsigned line, IHTMLDocument2 *doc, const char *id) |
| { |
| IHTMLDocument3 *doc3 = _get_doc3_iface(line, (IUnknown*)doc); |
| IHTMLElement *elem; |
| BSTR str; |
| HRESULT hres; |
| |
| str = a2bstr(id); |
| hres = IHTMLDocument3_getElementById(doc3, str, &elem); |
| SysFreeString(str); |
| IHTMLDocument3_Release(doc3); |
| ok_(__FILE__,line) (hres == S_OK, "getElementById failed: %08x\n", hres); |
| |
| return elem; |
| } |
| |
| #define test_elem_tag(u,n) _test_elem_tag(__LINE__,u,n) |
| static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag) |
| { |
| IHTMLElement *elem = _get_elem_iface(line, unk); |
| BSTR tag; |
| HRESULT hres; |
| |
| hres = IHTMLElement_get_tagName(elem, &tag); |
| IHTMLElement_Release(elem); |
| ok_(__FILE__, line) (hres == S_OK, "get_tagName failed: %08x\n", hres); |
| ok_(__FILE__, line) (!strcmp_wa(tag, extag), "got tag: %s, expected %s\n", wine_dbgstr_w(tag), extag); |
| |
| SysFreeString(tag); |
| } |
| |
| #define get_event_obj() _get_event_obj(__LINE__) |
| static IHTMLEventObj *_get_event_obj(unsigned line) |
| { |
| IHTMLEventObj *event = NULL; |
| HRESULT hres; |
| |
| hres = IHTMLWindow2_get_event(window, &event); |
| ok_(__FILE__,line) (hres == S_OK, "get_event failed: %08x\n", hres); |
| ok_(__FILE__,line) (event != NULL, "event = NULL\n"); |
| _test_disp(line, (IUnknown*)event, &DIID_DispCEventObj); |
| |
| return event; |
| } |
| |
| #define elem_fire_event(a,b,c) _elem_fire_event(__LINE__,a,b,c) |
| static void _elem_fire_event(unsigned line, IUnknown *unk, const char *event, VARIANT *evobj) |
| { |
| IHTMLElement3 *elem3 = _get_elem3_iface(line, unk); |
| VARIANT_BOOL b; |
| BSTR str; |
| HRESULT hres; |
| |
| b = 100; |
| str = a2bstr(event); |
| hres = IHTMLElement3_fireEvent(elem3, str, evobj, &b); |
| SysFreeString(str); |
| ok_(__FILE__,line)(hres == S_OK, "fireEvent failed: %08x\n", hres); |
| ok_(__FILE__,line)(b == VARIANT_TRUE, "fireEvent returned %x\n", b); |
| } |
| |
| #define test_event_args(a,b,c,d,e,f,g) _test_event_args(__LINE__,a,b,c,d,e,f,g) |
| static void _test_event_args(unsigned line, const IID *dispiid, DISPID id, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| ok_(__FILE__,line) (id == DISPID_VALUE, "id = %d\n", id); |
| ok_(__FILE__,line) (wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); |
| ok_(__FILE__,line) (pdp != NULL, "pdp == NULL\n"); |
| ok_(__FILE__,line) (pdp->cArgs == 1, "pdp->cArgs = %d\n", pdp->cArgs); |
| ok_(__FILE__,line) (pdp->cNamedArgs == 1, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); |
| ok_(__FILE__,line) (pdp->rgdispidNamedArgs[0] == DISPID_THIS, "pdp->rgdispidNamedArgs[0] = %d\n", |
| pdp->rgdispidNamedArgs[0]); |
| ok_(__FILE__,line) (V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(rgvarg) = %d\n", V_VT(pdp->rgvarg)); |
| ok_(__FILE__,line) (pvarRes != NULL, "pvarRes == NULL\n"); |
| ok_(__FILE__,line) (pei != NULL, "pei == NULL"); |
| ok_(__FILE__,line) (!pspCaller, "pspCaller != NULL\n"); |
| |
| if(dispiid) |
| _test_disp(line, (IUnknown*)V_DISPATCH(pdp->rgvarg), dispiid); |
| } |
| |
| #define test_attached_event_args(a,b,c,d,e) _test_attached_event_args(__LINE__,a,b,c,d,e) |
| static void _test_attached_event_args(unsigned line, DISPID id, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei) |
| { |
| IHTMLEventObj *event; |
| |
| ok(id == DISPID_VALUE, "id = %d\n", id); |
| ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); |
| ok(pdp != NULL, "pDispParams == NULL\n"); |
| ok(pdp->cArgs == 1, "pdp->cArgs = %d\n", pdp->cArgs); |
| ok(!pdp->cNamedArgs, "pdp->cNamedArgs = %d\n", pdp->cNamedArgs); |
| ok(!pdp->rgdispidNamedArgs, "pdp->rgdispidNamedArgs = %p\n", pdp->rgdispidNamedArgs); |
| ok(pdp->rgvarg != NULL, "rgvarg = NULL\n"); |
| ok(pvarRes != NULL, "pvarRes = NULL\n"); |
| ok(pei != NULL, "pei = NULL\n"); |
| ok(V_VT(pvarRes) == VT_EMPTY, "V_VT(pVarRes) = %d\n", V_VT(pvarRes)); |
| ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(pdp->rgvarg) = %d\n", V_VT(pdp->rgvarg)); |
| ok(V_DISPATCH(pdp->rgvarg) != NULL, "V_DISPATCH(pdp->rgvarg) = %p\n", V_DISPATCH(pdp->rgvarg)); |
| |
| event = _get_event_obj(line); |
| ok(iface_cmp((IUnknown*)event, (IUnknown*)V_DISPATCH(pdp->rgvarg)), "event != arg0\n"); |
| IHTMLEventObj_Release(event); |
| } |
| |
| #define get_event_src() _get_event_src(__LINE__) |
| static IHTMLElement *_get_event_src(unsigned line) |
| { |
| IHTMLEventObj *event = _get_event_obj(line); |
| IHTMLElement *src_elem = NULL; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_srcElement(event, &src_elem); |
| IHTMLEventObj_Release(event); |
| ok_(__FILE__,line) (hres == S_OK, "get_srcElement failed: %08x\n", hres); |
| |
| return src_elem; |
| } |
| |
| #define test_event_src(t) _test_event_src(__LINE__,t) |
| static void _test_event_src(unsigned line, const char *src_tag) |
| { |
| IHTMLElement *src_elem = _get_event_src(line); |
| |
| if(src_tag) { |
| ok_(__FILE__,line) (src_elem != NULL, "src_elem = NULL\n"); |
| _test_elem_tag(line, (IUnknown*)src_elem, src_tag); |
| IHTMLElement_Release(src_elem); |
| }else { |
| ok_(__FILE__,line) (!src_elem, "src_elem != NULL\n"); |
| } |
| } |
| |
| static void _test_event_altkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval) |
| { |
| VARIANT_BOOL b; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_altKey(event, &b); |
| ok_(__FILE__,line)(hres == S_OK, "get_altKey failed: %08x\n", hres); |
| ok_(__FILE__,line)(b == exval, "altKey = %x, expected %x\n", b, exval); |
| } |
| |
| static void _test_event_ctrlkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval) |
| { |
| VARIANT_BOOL b; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_ctrlKey(event, &b); |
| ok_(__FILE__,line)(hres == S_OK, "get_ctrlKey failed: %08x\n", hres); |
| ok_(__FILE__,line)(b == exval, "ctrlKey = %x, expected %x\n", b, exval); |
| } |
| |
| static void _test_event_shiftkey(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval) |
| { |
| VARIANT_BOOL b; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_shiftKey(event, &b); |
| ok_(__FILE__,line)(hres == S_OK, "get_shiftKey failed: %08x\n", hres); |
| ok_(__FILE__,line)(b == exval, "shiftKey = %x, expected %x\n", b, exval); |
| } |
| |
| static void _test_event_cancelbubble(unsigned line, IHTMLEventObj *event, VARIANT_BOOL exval) |
| { |
| VARIANT_BOOL b; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_cancelBubble(event, &b); |
| ok_(__FILE__,line)(hres == S_OK, "get_cancelBubble failed: %08x\n", hres); |
| ok_(__FILE__,line)(b == exval, "cancelBubble = %x, expected %x\n", b, exval); |
| } |
| |
| static void _test_event_fromelem(unsigned line, IHTMLEventObj *event, const char *from_tag) |
| { |
| IHTMLElement *elem; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_fromElement(event, &elem); |
| ok_(__FILE__,line)(hres == S_OK, "get_fromElement failed: %08x\n", hres); |
| if(from_tag) |
| _test_elem_tag(line, (IUnknown*)elem, from_tag); |
| else |
| ok_(__FILE__,line)(elem == NULL, "fromElement != NULL\n"); |
| if(elem) |
| IHTMLElement_Release(elem); |
| } |
| |
| static void _test_event_toelem(unsigned line, IHTMLEventObj *event, const char *to_tag) |
| { |
| IHTMLElement *elem; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_toElement(event, &elem); |
| ok_(__FILE__,line)(hres == S_OK, "get_toElement failed: %08x\n", hres); |
| if(to_tag) |
| _test_elem_tag(line, (IUnknown*)elem, to_tag); |
| else |
| ok_(__FILE__,line)(elem == NULL, "toElement != NULL\n"); |
| if(elem) |
| IHTMLElement_Release(elem); |
| } |
| |
| static void _test_event_keycode(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_keyCode(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_keyCode failed: %08x\n", hres); |
| ok_(__FILE__,line)(l == exl, "keyCode = %x, expected %x\n", l, exl); |
| } |
| |
| static void _test_event_button(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_button(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_button failed: %08x\n", hres); |
| ok_(__FILE__,line)(l == exl, "button = %x, expected %x\n", l, exl); |
| } |
| |
| static void _test_event_reason(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_reason(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_reason failed: %08x\n", hres); |
| ok_(__FILE__,line)(l == exl, "reason = %x, expected %x\n", l, exl); |
| } |
| |
| static void _test_event_x(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_x(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_x failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "x = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_y(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_y(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_y failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "y = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_clientx(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_clientX(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_clientX failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "clientX = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_clienty(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_clientY(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_clientY failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "clientY = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_offsetx(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_offsetX(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_offsetX failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "offsetX = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_offsety(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_offsetY(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_offsetY failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "offsetY = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_screenx(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_screenX(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_screenX failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value */ |
| ok_(__FILE__,line)(l == exl, "screenX = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_screeny(unsigned line, IHTMLEventObj *event, LONG exl) |
| { |
| LONG l; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_screenY(event, &l); |
| ok_(__FILE__,line)(hres == S_OK, "get_screenY failed: %08x\n", hres); |
| if(exl != -10) /* don't test the exact value for -10 */ |
| ok_(__FILE__,line)(l == exl, "screenY = %d, expected %d\n", l, exl); |
| } |
| |
| static void _test_event_type(unsigned line, IHTMLEventObj *event, const char *exstr) |
| { |
| BSTR str; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_type(event, &str); |
| ok_(__FILE__,line)(hres == S_OK, "get_type failed: %08x\n", hres); |
| ok_(__FILE__,line)(!strcmp_wa(str, exstr), "type = %s, expected %s\n", wine_dbgstr_w(str), exstr); |
| } |
| |
| static void _test_event_qualifier(unsigned line, IHTMLEventObj *event, const char *exstr) |
| { |
| BSTR str; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_qualifier(event, &str); |
| ok_(__FILE__,line)(hres == S_OK, "get_qualifier failed: %08x\n", hres); |
| if(exstr) |
| ok_(__FILE__,line)(!strcmp_wa(str, exstr), "qualifier = %s, expected %s\n", wine_dbgstr_w(str), exstr); |
| else |
| ok_(__FILE__,line)(!str, "qualifier != NULL\n"); |
| } |
| |
| static void _test_event_srcfilter(unsigned line, IHTMLEventObj *event) |
| { |
| IDispatch *disp; |
| HRESULT hres; |
| |
| hres = IHTMLEventObj_get_srcFilter(event, &disp); |
| ok_(__FILE__,line)(hres == S_OK, "get_srcFilter failed: %08x\n", hres); |
| ok_(__FILE__,line)(!disp, "srcFilter != NULL\n"); |
| } |
| |
| #define test_event_obj(t,x) _test_event_obj(__LINE__,t,x) |
| static void _test_event_obj(unsigned line, const char *type, const xy_test_t *xy) |
| { |
| IHTMLEventObj *event = _get_event_obj(line); |
| VARIANT v; |
| HRESULT hres; |
| |
| _test_event_altkey(line, event, VARIANT_FALSE); |
| _test_event_ctrlkey(line, event, VARIANT_FALSE); |
| _test_event_shiftkey(line, event, VARIANT_FALSE); |
| _test_event_cancelbubble(line, event, VARIANT_FALSE); |
| _test_event_fromelem(line, event, NULL); |
| _test_event_toelem(line, event, NULL); |
| _test_event_keycode(line, event, 0); |
| _test_event_button(line, event, 0); |
| _test_event_type(line, event, type); |
| _test_event_qualifier(line, event, NULL); |
| _test_event_reason(line, event, 0); |
| _test_event_srcfilter(line, event); |
| _test_event_x(line, event, xy->x); |
| _test_event_y(line, event, xy->y); |
| _test_event_clientx(line, event, -10); |
| _test_event_clienty(line, event, -10); |
| _test_event_offsetx(line, event, xy->offset_x); |
| _test_event_offsety(line, event, xy->offset_y); |
| _test_event_screenx(line, event, -10); |
| _test_event_screeny(line, event, -10); |
| |
| hres = IHTMLEventObj_get_returnValue(event, &v); |
| ok_(__FILE__,line)(hres == S_OK, "get_returnValue failed: %08x\n", hres); |
| ok_(__FILE__,line)(V_VT(&v) == VT_EMPTY, "V_VT(returnValue) = %d\n", V_VT(&v)); |
| |
| IHTMLEventObj_Release(event); |
| } |
| |
| #define elem_attach_event(a,b,c) _elem_attach_event(__LINE__,a,b,c) |
| static void _elem_attach_event(unsigned line, IUnknown *unk, const char *namea, IDispatch *disp) |
| { |
| IHTMLElement2 *elem = _get_elem2_iface(line, unk); |
| VARIANT_BOOL res; |
| BSTR name; |
| HRESULT hres; |
| |
| name = a2bstr(namea); |
| hres = IHTMLElement2_attachEvent(elem, name, disp, &res); |
| IHTMLElement2_Release(elem); |
| SysFreeString(name); |
| ok_(__FILE__,line)(hres == S_OK, "attachEvent failed: %08x\n", hres); |
| ok_(__FILE__,line)(res == VARIANT_TRUE, "attachEvent returned %x\n", res); |
| } |
| |
| #define elem_detach_event(a,b,c) _elem_detach_event(__LINE__,a,b,c) |
| static void _elem_detach_event(unsigned line, IUnknown *unk, const char *namea, IDispatch *disp) |
| { |
| IHTMLElement2 *elem = _get_elem2_iface(line, unk); |
| BSTR name; |
| HRESULT hres; |
| |
| name = a2bstr(namea); |
| hres = IHTMLElement2_detachEvent(elem, name, disp); |
| IHTMLElement2_Release(elem); |
| SysFreeString(name); |
| ok_(__FILE__,line)(hres == S_OK, "detachEvent failed: %08x\n", hres); |
| } |
| |
| static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) |
| { |
| *ppv = NULL; |
| |
| if(IsEqualGUID(riid, &IID_IUnknown) |
| || IsEqualGUID(riid, &IID_IDispatch) |
| || IsEqualGUID(riid, &IID_IDispatchEx)) |
| *ppv = iface; |
| else { |
| ok(0, "unexpected riid %s\n", debugstr_guid(riid)); |
| return E_NOINTERFACE; |
| } |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI Dispatch_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) |
| { |
| *ppv = NULL; |
| |
| if(IsEqualGUID(riid, &IID_IUnknown) |
| || IsEqualGUID(riid, &IID_IDispatch)) { |
| *ppv = iface; |
| }else if(IsEqualGUID(riid, &IID_IDispatchEx)) { |
| return E_NOINTERFACE; |
| }else { |
| ok(0, "unexpected riid %s\n", debugstr_guid(riid)); |
| return E_NOINTERFACE; |
| } |
| |
| return S_OK; |
| } |
| |
| static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetTypeInfo(IDispatchEx *iface, UINT iTInfo, |
| LCID lcid, ITypeInfo **ppTInfo) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, |
| LPOLESTR *rgszNames, UINT cNames, |
| LCID lcid, DISPID *rgDispId) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, |
| REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, |
| VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex) |
| { |
| ok(0, "unexpected call %s %x\n", wine_dbgstr_w(bstrName), grfdex); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_DeleteMemberByDispID(IDispatchEx *iface, DISPID id) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetMemberProperties(IDispatchEx *iface, DISPID id, DWORD grfdexFetch, DWORD *pgrfdex) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI DispatchEx_GetNameSpaceParent(IDispatchEx *iface, IUnknown **ppunk) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| #define EVENT_HANDLER_FUNC_OBJ(event) \ |
| static IDispatchExVtbl event ## FuncVtbl = { \ |
| DispatchEx_QueryInterface, \ |
| DispatchEx_AddRef, \ |
| DispatchEx_Release, \ |
| DispatchEx_GetTypeInfoCount, \ |
| DispatchEx_GetTypeInfo, \ |
| DispatchEx_GetIDsOfNames, \ |
| DispatchEx_Invoke, \ |
| DispatchEx_GetDispID, \ |
| event, \ |
| DispatchEx_DeleteMemberByName, \ |
| DispatchEx_DeleteMemberByDispID, \ |
| DispatchEx_GetMemberProperties, \ |
| DispatchEx_GetMemberName, \ |
| DispatchEx_GetNextDispID, \ |
| DispatchEx_GetNameSpaceParent \ |
| }; \ |
| static IDispatchEx event ## _obj = { &event ## FuncVtbl }; |
| |
| static HRESULT WINAPI document_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| IHTMLDocument3 *doc3; |
| CHECK_EXPECT(document_onclick); |
| test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| doc3 = get_doc3_iface((IUnknown*)V_DISPATCH(pdp->rgvarg)); |
| IHTMLDocument3_Release(doc3); |
| test_event_src("DIV"); |
| test_event_obj("click", &no_xy); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(document_onclick); |
| |
| static HRESULT WINAPI div_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| CHECK_EXPECT(div_onclick); |
| test_event_args(NULL, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| test_event_src("DIV"); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(div_onclick); |
| |
| static HRESULT WINAPI div_onclick_attached(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| CHECK_EXPECT(div_onclick_attached); |
| |
| test_attached_event_args(id, wFlags, pdp, pvarRes, pei); |
| test_event_src("DIV"); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(div_onclick_attached); |
| |
| static HRESULT WINAPI body_onclick(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| CHECK_EXPECT(body_onclick); |
| test_event_args(&DIID_DispHTMLBody, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| test_event_src("DIV"); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(body_onclick); |
| |
| static HRESULT WINAPI img_onload(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| CHECK_EXPECT(img_onload); |
| test_event_args(&DIID_DispHTMLImg, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| test_event_src("IMG"); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(img_onload); |
| |
| static HRESULT WINAPI iframedoc_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| IHTMLEventObj *event = NULL; |
| HRESULT hres; |
| |
| CHECK_EXPECT2(iframedoc_onreadystatechange); |
| test_event_args(&DIID_DispHTMLDocument, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| |
| event = (void*)0xdeadbeef; |
| hres = IHTMLWindow2_get_event(window, &event); |
| ok(hres == S_OK, "get_event failed: %08x\n", hres); |
| ok(!event, "event = %p\n", event); |
| |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(iframedoc_onreadystatechange); |
| |
| static HRESULT WINAPI iframe_onreadystatechange(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| IHTMLWindow2 *iframe_window; |
| IHTMLDocument2 *iframe_doc; |
| IHTMLFrameBase2 *iframe; |
| IHTMLElement2 *elem2; |
| IHTMLElement *elem; |
| VARIANT v; |
| BSTR str, str2; |
| HRESULT hres; |
| |
| test_event_args(&DIID_DispHTMLIFrame, id, wFlags, pdp, pvarRes, pei, pspCaller); |
| test_event_src("IFRAME"); |
| |
| elem = get_event_src(); |
| elem2 = get_elem2_iface((IUnknown*)elem); |
| IHTMLElement_Release(elem); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement2_get_readyState(elem2, &v); |
| ok(hres == S_OK, "get_readyState failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_BSTR, "V_VT(readyState) = %d\n", V_VT(&v)); |
| |
| hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase2, (void**)&iframe); |
| IHTMLElement2_Release(elem2); |
| ok(hres == S_OK, "Could not get IHTMLFrameBase2 iface: %08x\n", hres); |
| |
| str = NULL; |
| hres = IHTMLFrameBase2_get_readyState(iframe, &str); |
| IHTMLFrameBase2_Release(iframe); |
| ok(hres == S_OK, "get_readyState failed: %08x\n", hres); |
| ok(str != NULL, "readyState == NULL\n"); |
| ok(!lstrcmpW(str, V_BSTR(&v)), "ready states differ\n"); |
| VariantClear(&v); |
| |
| hres = IHTMLFrameBase2_get_contentWindow(iframe, &iframe_window); |
| ok(hres == S_OK, "get_contentDocument failed: %08x\n", hres); |
| |
| hres = IHTMLWindow2_get_document(iframe_window, &iframe_doc); |
| IHTMLWindow2_Release(iframe_window); |
| ok(hres == S_OK, "get_document failed: %08x\n", hres); |
| |
| hres = IHTMLDocument2_get_readyState(iframe_doc, &str2); |
| ok(!lstrcmpW(str, str2), "unexpected document readyState %s\n", wine_dbgstr_w(str2)); |
| SysFreeString(str2); |
| |
| if(!strcmp_wa(str, "loading")) { |
| CHECK_EXPECT(iframe_onreadystatechange_loading); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&iframedoc_onreadystatechange_obj; |
| hres = IHTMLDocument2_put_onreadystatechange(iframe_doc, v); |
| ok(hres == S_OK, "put_onreadystatechange: %08x\n", hres); |
| }else if(!strcmp_wa(str, "interactive")) |
| CHECK_EXPECT(iframe_onreadystatechange_interactive); |
| else if(!strcmp_wa(str, "complete")) |
| CHECK_EXPECT(iframe_onreadystatechange_complete); |
| else |
| ok(0, "unexpected state %s\n", wine_dbgstr_w(str)); |
| |
| IHTMLDocument2_Release(iframe_doc); |
| IHTMLFrameBase2_Release(iframe); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(iframe_onreadystatechange); |
| |
| static HRESULT WINAPI nocall(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) |
| { |
| ok(0, "unexpected call\n"); |
| return S_OK; |
| } |
| |
| EVENT_HANDLER_FUNC_OBJ(nocall); |
| |
| #define CONNECTION_POINT_OBJ(cpname, diid) \ |
| static HRESULT WINAPI cpname ## _QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) \ |
| { \ |
| *ppv = NULL; \ |
| if(IsEqualGUID(riid, &IID_IUnknown) \ |
| || IsEqualGUID(riid, &IID_IDispatch) \ |
| || IsEqualGUID(riid, &diid)) \ |
| *ppv = iface; \ |
| else { \ |
| ok(0, "unexpected riid %s\n", debugstr_guid(riid)); \ |
| return E_NOINTERFACE; \ |
| } \ |
| return S_OK; \ |
| } \ |
| static IDispatchExVtbl cpname ## Vtbl = { \ |
| cpname ## _QueryInterface, \ |
| DispatchEx_AddRef, \ |
| DispatchEx_Release, \ |
| DispatchEx_GetTypeInfoCount, \ |
| DispatchEx_GetTypeInfo, \ |
| DispatchEx_GetIDsOfNames, \ |
| cpname, \ |
| DispatchEx_GetDispID, \ |
| DispatchEx_InvokeEx, \ |
| DispatchEx_DeleteMemberByName, \ |
| DispatchEx_DeleteMemberByDispID, \ |
| DispatchEx_GetMemberProperties, \ |
| DispatchEx_GetMemberName, \ |
| DispatchEx_GetNextDispID, \ |
| DispatchEx_GetNameSpaceParent \ |
| }; \ |
| static IDispatchEx cpname ## _obj = { &cpname ## Vtbl } |
| |
| #define test_cp_args(a,b,c,d,e,f) _test_cp_args(__LINE__,a,b,c,d,e,f) |
| static void _test_cp_args(unsigned line, REFIID riid, WORD flags, DISPPARAMS *dp, VARIANT *vres, EXCEPINFO *ei, UINT *argerr) |
| { |
| ok_(__FILE__,line)(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); |
| ok_(__FILE__,line)(flags == DISPATCH_METHOD, "flags = %x\n", flags); |
| ok_(__FILE__,line)(dp != NULL, "dp == NULL\n"); |
| ok_(__FILE__,line)(!dp->cArgs, "dp->cArgs = %d\n", dp->cArgs); |
| ok_(__FILE__,line)(!dp->rgvarg, "dp->rgvarg = %p\n", dp->rgvarg); |
| ok_(__FILE__,line)(!dp->cNamedArgs, "dp->cNamedArgs = %d\n", dp->cNamedArgs); |
| ok_(__FILE__,line)(!dp->rgdispidNamedArgs, "dp->rgdispidNamedArgs = %p\n", dp->rgdispidNamedArgs); |
| ok_(__FILE__,line)(vres != NULL, "vres == NULL\n"); |
| ok_(__FILE__,line)(V_VT(vres) == VT_EMPTY, "V_VT(vres) = %d\n", V_VT(vres)); |
| ok_(__FILE__,line)(ei != NULL, "ei == NULL\n"); |
| ok_(__FILE__,line)(argerr != NULL, "argerr == NULL\n"); |
| } |
| |
| static HRESULT WINAPI doccp(IDispatchEx *iface, DISPID dispIdMember, |
| REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pVarResult, EXCEPINFO *pei, UINT *puArgErr) |
| { |
| switch(dispIdMember) { |
| case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: |
| CHECK_EXPECT(doccp_onclick); |
| test_cp_args(riid, wFlags, pdp, pVarResult, pei, puArgErr); |
| break; |
| default: |
| ok(0, "unexpected call %d\n", dispIdMember); |
| return E_NOTIMPL; |
| } |
| |
| return S_OK; |
| } |
| |
| CONNECTION_POINT_OBJ(doccp, DIID_HTMLDocumentEvents); |
| |
| static HRESULT WINAPI timeoutFunc_Invoke(IDispatchEx *iface, DISPID dispIdMember, |
| REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, |
| VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) |
| { |
| CHECK_EXPECT(timeout); |
| |
| ok(dispIdMember == DISPID_VALUE, "dispIdMember = %d\n", dispIdMember); |
| ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); |
| ok(wFlags == DISPATCH_METHOD, "wFlags = %x\n", wFlags); |
| ok(!lcid, "lcid = %x\n", lcid); |
| ok(pDispParams != NULL, "pDispParams == NULL\n"); |
| ok(!pDispParams->cArgs, "pdp->cArgs = %d\n", pDispParams->cArgs); |
| ok(!pDispParams->cNamedArgs, "pdp->cNamedArgs = %d\n", pDispParams->cNamedArgs); |
| ok(!pDispParams->rgdispidNamedArgs, "pdp->rgdispidNamedArgs = %p\n", pDispParams->rgdispidNamedArgs); |
| ok(!pDispParams->rgvarg, "rgvarg = %p\n", pDispParams->rgvarg); |
| ok(pVarResult != NULL, "pVarResult = NULL\n"); |
| ok(pExcepInfo != NULL, "pExcepInfo = NULL\n"); |
| ok(!puArgErr, "puArgErr = %p\n", puArgErr); |
| ok(V_VT(pVarResult) == VT_EMPTY, "V_VT(pVarResult) = %d\n", V_VT(pVarResult)); |
| |
| return S_OK; |
| } |
| |
| static IDispatchExVtbl timeoutFuncVtbl = { |
| DispatchEx_QueryInterface, |
| DispatchEx_AddRef, |
| DispatchEx_Release, |
| DispatchEx_GetTypeInfoCount, |
| DispatchEx_GetTypeInfo, |
| DispatchEx_GetIDsOfNames, |
| timeoutFunc_Invoke, |
| DispatchEx_GetDispID, |
| DispatchEx_InvokeEx, |
| DispatchEx_DeleteMemberByName, |
| DispatchEx_DeleteMemberByDispID, |
| DispatchEx_GetMemberProperties, |
| DispatchEx_GetMemberName, |
| DispatchEx_GetNextDispID, |
| DispatchEx_GetNameSpaceParent |
| }; |
| |
| static IDispatchEx timeoutFunc = { &timeoutFuncVtbl }; |
| |
| static HRESULT WINAPI div_onclick_disp_Invoke(IDispatchEx *iface, DISPID id, |
| REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdp, |
| VARIANT *pvarRes, EXCEPINFO *pei, UINT *puArgErr) |
| { |
| CHECK_EXPECT(div_onclick_disp); |
| |
| test_attached_event_args(id, wFlags, pdp, pvarRes, pei); |
| |
| ok(IsEqualGUID(&IID_NULL, riid), "riid = %s\n", debugstr_guid(riid)); |
| ok(!puArgErr, "puArgErr = %p\n", puArgErr); |
| |
| return S_OK; |
| } |
| |
| static IDispatchExVtbl div_onclick_dispVtbl = { |
| Dispatch_QueryInterface, |
| DispatchEx_AddRef, |
| DispatchEx_Release, |
| DispatchEx_GetTypeInfoCount, |
| DispatchEx_GetTypeInfo, |
| DispatchEx_GetIDsOfNames, |
| div_onclick_disp_Invoke, |
| }; |
| |
| static IDispatchEx div_onclick_disp = { &div_onclick_dispVtbl }; |
| |
| static void pump_msgs(BOOL *b) |
| { |
| MSG msg; |
| while(!*b && GetMessage(&msg, NULL, 0, 0)) { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| } |
| |
| static IConnectionPoint *get_cp(IUnknown *unk, REFIID riid) |
| { |
| IConnectionPointContainer *cp_container; |
| IConnectionPoint *cp; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&cp_container); |
| ok(hres == S_OK, "Could not get IConnectionPointContainer: %08x\n", hres); |
| |
| hres = IConnectionPointContainer_FindConnectionPoint(cp_container, riid, &cp); |
| IConnectionPointContainer_Release(cp_container); |
| ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); |
| |
| return cp; |
| } |
| |
| static DWORD register_cp(IUnknown *unk, REFIID riid, IUnknown *sink) |
| { |
| IConnectionPoint *cp; |
| DWORD cookie; |
| HRESULT hres; |
| |
| cp = get_cp(unk, riid); |
| hres = IConnectionPoint_Advise(cp, sink, &cookie); |
| IConnectionPoint_Release(cp); |
| ok(hres == S_OK, "Advise failed: %08x\n", hres); |
| |
| return cookie; |
| } |
| |
| static void unregister_cp(IUnknown *unk, REFIID riid, DWORD cookie) |
| { |
| IConnectionPoint *cp; |
| HRESULT hres; |
| |
| cp = get_cp(unk, riid); |
| hres = IConnectionPoint_Unadvise(cp, cookie); |
| IConnectionPoint_Release(cp); |
| ok(hres == S_OK, "Unadvise failed: %08x\n", hres); |
| } |
| |
| static void test_onclick(IHTMLDocument2 *doc) |
| { |
| IHTMLElement *div, *body; |
| DWORD cp_cookie; |
| VARIANT v; |
| HRESULT hres; |
| |
| div = get_elem_id(doc, "clickdiv"); |
| |
| elem_attach_event((IUnknown*)div, "abcde", (IDispatch*)&nocall_obj); |
| elem_attach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_attached_obj); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement_get_onclick(div, &v); |
| ok(hres == S_OK, "get_onclick failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_NULL, "V_VT(onclick) = %d\n", V_VT(&v)); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement_put_onclick(div, v); |
| ok(hres == E_NOTIMPL, "put_onclick failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&div_onclick_obj; |
| hres = IHTMLElement_put_onclick(div, v); |
| ok(hres == S_OK, "put_onclick failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_NULL; |
| hres = IHTMLElement_put_ondblclick(div, v); |
| ok(hres == S_OK, "put_ondblclick failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement_get_onclick(div, &v); |
| ok(hres == S_OK, "get_onclick failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_DISPATCH, "V_VT(onclick) = %d\n", V_VT(&v)); |
| ok(V_DISPATCH(&v) == (IDispatch*)&div_onclick_obj, "V_DISPATCH(onclick) != onclickFunc\n"); |
| VariantClear(&v); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLDocument2_get_onclick(doc, &v); |
| ok(hres == S_OK, "get_onclick failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_NULL, "V_VT(onclick) = %d\n", V_VT(&v)); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&document_onclick_obj; |
| hres = IHTMLDocument2_put_onclick(doc, v); |
| ok(hres == S_OK, "put_onclick failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLDocument2_get_onclick(doc, &v); |
| ok(hres == S_OK, "get_onclick failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_DISPATCH, "V_VT(onclick) = %d\n", V_VT(&v)); |
| ok(V_DISPATCH(&v) == (IDispatch*)&document_onclick_obj, "V_DISPATCH(onclick) != onclickFunc\n"); |
| VariantClear(&v); |
| |
| body = doc_get_body(doc); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&body_onclick_obj; |
| hres = IHTMLElement_put_onclick(body, v); |
| ok(hres == S_OK, "put_onclick failed: %08x\n", hres); |
| |
| if(winetest_interactive) { |
| SET_EXPECT(div_onclick); |
| SET_EXPECT(div_onclick_attached); |
| SET_EXPECT(body_onclick); |
| SET_EXPECT(document_onclick); |
| pump_msgs(&called_document_onclick); |
| CHECK_CALLED(div_onclick); |
| CHECK_CALLED(div_onclick_attached); |
| CHECK_CALLED(body_onclick); |
| CHECK_CALLED(document_onclick); |
| } |
| |
| xy_todo = TRUE; |
| |
| SET_EXPECT(div_onclick); |
| SET_EXPECT(div_onclick_attached); |
| SET_EXPECT(body_onclick); |
| SET_EXPECT(document_onclick); |
| |
| hres = IHTMLElement_click(div); |
| ok(hres == S_OK, "click failed: %08x\n", hres); |
| |
| CHECK_CALLED(div_onclick); |
| CHECK_CALLED(div_onclick_attached); |
| CHECK_CALLED(body_onclick); |
| CHECK_CALLED(document_onclick); |
| |
| SET_EXPECT(div_onclick); |
| SET_EXPECT(div_onclick_attached); |
| SET_EXPECT(body_onclick); |
| SET_EXPECT(document_onclick); |
| |
| V_VT(&v) = VT_EMPTY; |
| elem_fire_event((IUnknown*)div, "onclick", &v); |
| |
| CHECK_CALLED(div_onclick); |
| CHECK_CALLED(div_onclick_attached); |
| CHECK_CALLED(body_onclick); |
| CHECK_CALLED(document_onclick); |
| |
| cp_cookie = register_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, (IUnknown*)&doccp_obj); |
| elem_attach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); |
| |
| SET_EXPECT(div_onclick); |
| SET_EXPECT(div_onclick_disp); |
| SET_EXPECT(div_onclick_attached); |
| SET_EXPECT(body_onclick); |
| SET_EXPECT(document_onclick); |
| SET_EXPECT(doccp_onclick); |
| |
| hres = IHTMLElement_click(div); |
| ok(hres == S_OK, "click failed: %08x\n", hres); |
| |
| CHECK_CALLED(div_onclick); |
| CHECK_CALLED(div_onclick_disp); |
| CHECK_CALLED(div_onclick_attached); |
| CHECK_CALLED(body_onclick); |
| CHECK_CALLED(document_onclick); |
| CHECK_CALLED(doccp_onclick); |
| |
| unregister_cp((IUnknown*)doc, &DIID_HTMLDocumentEvents, cp_cookie); |
| |
| V_VT(&v) = VT_NULL; |
| hres = IHTMLElement_put_onclick(div, v); |
| ok(hres == S_OK, "put_onclick failed: %08x\n", hres); |
| |
| hres = IHTMLElement_get_onclick(div, &v); |
| ok(hres == S_OK, "get_onclick failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_NULL, "get_onclick returned vt %d\n", V_VT(&v)); |
| |
| elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); |
| elem_detach_event((IUnknown*)div, "onclick", (IDispatch*)&div_onclick_disp); |
| elem_detach_event((IUnknown*)div, "test", (IDispatch*)&div_onclick_disp); |
| |
| SET_EXPECT(div_onclick_attached); |
| SET_EXPECT(body_onclick); |
| SET_EXPECT(document_onclick); |
| |
| hres = IHTMLElement_click(div); |
| ok(hres == S_OK, "click failed: %08x\n", hres); |
| |
| CHECK_CALLED(div_onclick_attached); |
| CHECK_CALLED(body_onclick); |
| CHECK_CALLED(document_onclick); |
| |
| IHTMLElement_Release(div); |
| IHTMLElement_Release(body); |
| } |
| |
| static void test_onreadystatechange(IHTMLDocument2 *doc) |
| { |
| IHTMLFrameBase *iframe; |
| IHTMLElement2 *elem2; |
| IHTMLElement *elem; |
| VARIANT v; |
| BSTR str; |
| HRESULT hres; |
| |
| elem = get_elem_id(doc, "iframe"); |
| elem2 = get_elem2_iface((IUnknown*)elem); |
| IHTMLElement_Release(elem); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement2_get_onreadystatechange(elem2, &v); |
| ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_NULL, "V_VT(onreadystatechange) = %d\n", V_VT(&v)); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&iframe_onreadystatechange_obj; |
| hres = IHTMLElement2_put_onreadystatechange(elem2, v); |
| ok(hres == S_OK, "put_onreadystatechange failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLElement2_get_onreadystatechange(elem2, &v); |
| ok(hres == S_OK, "get_onreadystatechange failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_DISPATCH, "V_VT(onreadystatechange) = %d\n", V_VT(&v)); |
| ok(V_DISPATCH(&v) == (IDispatch*)&iframe_onreadystatechange_obj, "unexpected onreadystatechange value\n"); |
| |
| hres = IHTMLElement2_QueryInterface(elem2, &IID_IHTMLFrameBase, (void**)&iframe); |
| IHTMLElement2_Release(elem2); |
| ok(hres == S_OK, "Could not get IHTMLFrameBase iface: %08x\n", hres); |
| |
| hres = IHTMLFrameBase_put_src(iframe, (str = a2bstr("about:blank"))); |
| SysFreeString(str); |
| ok(hres == S_OK, "put_src failed: %08x\n", hres); |
| |
| SET_EXPECT(iframe_onreadystatechange_loading); |
| SET_EXPECT(iframedoc_onreadystatechange); |
| SET_EXPECT(iframe_onreadystatechange_interactive); |
| SET_EXPECT(iframe_onreadystatechange_complete); |
| pump_msgs(&called_iframe_onreadystatechange_complete); |
| CHECK_CALLED(iframe_onreadystatechange_loading); |
| CHECK_CALLED(iframedoc_onreadystatechange); |
| CHECK_CALLED(iframe_onreadystatechange_interactive); |
| CHECK_CALLED(iframe_onreadystatechange_complete); |
| |
| IHTMLFrameBase_Release(iframe); |
| } |
| |
| static void test_imgload(IHTMLDocument2 *doc) |
| { |
| IHTMLImgElement *img; |
| IHTMLElement *elem; |
| VARIANT v; |
| BSTR str; |
| HRESULT hres; |
| |
| elem = get_elem_id(doc, "imgid"); |
| hres = IHTMLElement_QueryInterface(elem, &IID_IHTMLImgElement, (void**)&img); |
| IHTMLElement_Release(elem); |
| ok(hres == S_OK, "Could not get IHTMLImgElement iface: %08x\n", hres); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLImgElement_get_onload(img, &v); |
| ok(hres == S_OK, "get_onload failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_NULL, "V_VT(onload) = %d\n", V_VT(&v)); |
| |
| V_VT(&v) = VT_DISPATCH; |
| V_DISPATCH(&v) = (IDispatch*)&img_onload_obj; |
| hres = IHTMLImgElement_put_onload(img, v); |
| ok(hres == S_OK, "put_onload failed: %08x\n", hres); |
| |
| V_VT(&v) = VT_EMPTY; |
| hres = IHTMLImgElement_get_onload(img, &v); |
| ok(hres == S_OK, "get_onload failed: %08x\n", hres); |
| ok(V_VT(&v) == VT_DISPATCH, "V_VT(onload) = %d\n", V_VT(&v)); |
| ok(V_DISPATCH(&v) == (IDispatch*)&img_onload_obj, "V_DISPATCH(onload) != onloadkFunc\n"); |
| VariantClear(&v); |
| |
| str = a2bstr("http://www.winehq.org/images/winehq_logo_text.png"); |
| hres = IHTMLImgElement_put_src(img, str); |
| ok(hres == S_OK, "put_src failed: %08x\n", hres); |
| SysFreeString(str); |
| |
| SET_EXPECT(img_onload); |
| pump_msgs(&called_img_onload); |
| CHECK_CALLED(img_onload); |
| |
| IHTMLImgElement_Release(img); |
| } |
| |
| static void test_timeout(IHTMLDocument2 *doc) |
| { |
| IHTMLWindow3 *win3; |
| VARIANT expr, var; |
| LONG id; |
| HRESULT hres; |
| |
| hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow3, (void**)&win3); |
| ok(hres == S_OK, "Could not get IHTMLWindow3 iface: %08x\n", hres); |
| |
| V_VT(&expr) = VT_DISPATCH; |
| V_DISPATCH(&expr) = (IDispatch*)&timeoutFunc; |
| V_VT(&var) = VT_EMPTY; |
| id = 0; |
| hres = IHTMLWindow3_setTimeout(win3, &expr, 0, &var, &id); |
| ok(hres == S_OK, "setTimeout failed: %08x\n", hres); |
| ok(id, "id = 0\n"); |
| |
| SET_EXPECT(timeout); |
| pump_msgs(&called_timeout); |
| CHECK_CALLED(timeout); |
| |
| V_VT(&expr) = VT_DISPATCH; |
| V_DISPATCH(&expr) = (IDispatch*)&timeoutFunc; |
| V_VT(&var) = VT_EMPTY; |
| id = 0; |
| hres = IHTMLWindow3_setTimeout(win3, &expr, 0, &var, &id); |
| ok(hres == S_OK, "setTimeout failed: %08x\n", hres); |
| ok(id, "id = 0\n"); |
| |
| hres = IHTMLWindow2_clearTimeout(window, id); |
| ok(hres == S_OK, "clearTimeout failed: %08x\n", hres); |
| |
| IHTMLWindow3_Release(win3); |
| } |
| |
| static HRESULT QueryInterface(REFIID,void**); |
| |
| static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv) |
| { |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface, |
| LPCBORDERWIDTHS pborderwidths) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface, |
| LPCBORDERWIDTHS pborderwidths) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface, |
| IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface, |
| IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared, |
| LPOLEMENUGROUPWIDTHS lpMenuWidths) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared, |
| HOLEMENU holemenu, HWND hwndActiveObject) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = { |
| InPlaceFrame_QueryInterface, |
| InPlaceFrame_AddRef, |
| InPlaceFrame_Release, |
| InPlaceFrame_GetWindow, |
| InPlaceFrame_ContextSensitiveHelp, |
| InPlaceFrame_GetBorder, |
| InPlaceFrame_RequestBorderSpace, |
| InPlaceFrame_SetBorderSpace, |
| InPlaceFrame_SetActiveObject, |
| InPlaceFrame_InsertMenus, |
| InPlaceFrame_SetMenu, |
| InPlaceFrame_RemoveMenus, |
| InPlaceFrame_SetStatusText, |
| InPlaceFrame_EnableModeless, |
| InPlaceFrame_TranslateAccelerator |
| }; |
| |
| static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl }; |
| |
| static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = { |
| InPlaceFrame_QueryInterface, |
| InPlaceFrame_AddRef, |
| InPlaceFrame_Release, |
| InPlaceFrame_GetWindow, |
| InPlaceFrame_ContextSensitiveHelp, |
| InPlaceFrame_GetBorder, |
| InPlaceFrame_RequestBorderSpace, |
| InPlaceFrame_SetBorderSpace, |
| InPlaceUIWindow_SetActiveObject, |
| }; |
| |
| static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl }; |
| |
| static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv) |
| { |
| return QueryInterface(riid, ppv); |
| } |
| |
| static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd) |
| { |
| *phwnd = container_hwnd; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface, |
| IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect, |
| LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo) |
| { |
| static const RECT rect = {0,0,300,300}; |
| |
| *ppFrame = &InPlaceFrame; |
| *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow; |
| *lprcPosRect = rect; |
| *lprcClipRect = rect; |
| |
| lpFrameInfo->cb = sizeof(*lpFrameInfo); |
| lpFrameInfo->fMDIApp = FALSE; |
| lpFrameInfo->hwndFrame = container_hwnd; |
| lpFrameInfo->haccel = NULL; |
| lpFrameInfo->cAccelEntries = 0; |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface) |
| { |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = { |
| InPlaceSite_QueryInterface, |
| InPlaceSite_AddRef, |
| InPlaceSite_Release, |
| InPlaceSite_GetWindow, |
| InPlaceSite_ContextSensitiveHelp, |
| InPlaceSite_CanInPlaceActivate, |
| InPlaceSite_OnInPlaceActivate, |
| InPlaceSite_OnUIActivate, |
| InPlaceSite_GetWindowContext, |
| InPlaceSite_Scroll, |
| InPlaceSite_OnUIDeactivate, |
| InPlaceSite_OnInPlaceDeactivate, |
| InPlaceSite_DiscardUndoState, |
| InPlaceSite_DeactivateAndUndo, |
| InPlaceSite_OnPosRectChange, |
| }; |
| |
| static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl }; |
| |
| static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) |
| { |
| return QueryInterface(riid, ppv); |
| } |
| |
| static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI ClientSite_Release(IOleClientSite *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker, |
| IMoniker **ppmon) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer) |
| { |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static const IOleClientSiteVtbl ClientSiteVtbl = { |
| ClientSite_QueryInterface, |
| ClientSite_AddRef, |
| ClientSite_Release, |
| ClientSite_SaveObject, |
| ClientSite_GetMoniker, |
| ClientSite_GetContainer, |
| ClientSite_ShowObject, |
| ClientSite_OnShowWindow, |
| ClientSite_RequestNewObjectLayout |
| }; |
| |
| static IOleClientSite ClientSite = { &ClientSiteVtbl }; |
| |
| static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv) |
| { |
| return QueryInterface(riid, ppv); |
| } |
| |
| static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate) |
| { |
| RECT rect = {0,0,300,300}; |
| IOleDocument *document; |
| HRESULT hres; |
| |
| hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document); |
| ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres); |
| |
| hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view); |
| IOleDocument_Release(document); |
| ok(hres == S_OK, "CreateView failed: %08x\n", hres); |
| |
| hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite); |
| ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres); |
| |
| hres = IOleDocumentView_UIActivate(view, TRUE); |
| ok(hres == S_OK, "UIActivate failed: %08x\n", hres); |
| |
| hres = IOleDocumentView_SetRect(view, &rect); |
| ok(hres == S_OK, "SetRect failed: %08x\n", hres); |
| |
| hres = IOleDocumentView_Show(view, TRUE); |
| ok(hres == S_OK, "Show failed: %08x\n", hres); |
| |
| return S_OK; |
| } |
| |
| static const IOleDocumentSiteVtbl DocumentSiteVtbl = { |
| DocumentSite_QueryInterface, |
| DocumentSite_AddRef, |
| DocumentSite_Release, |
| DocumentSite_ActivateMe |
| }; |
| |
| static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl }; |
| |
| static HRESULT QueryInterface(REFIID riid, void **ppv) |
| { |
| *ppv = NULL; |
| |
| if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid)) |
| *ppv = &ClientSite; |
| else if(IsEqualGUID(&IID_IOleDocumentSite, riid)) |
| *ppv = &DocumentSite; |
| else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid)) |
| *ppv = &InPlaceSite; |
| |
| return *ppv ? S_OK : E_NOINTERFACE; |
| } |
| |
| static IHTMLDocument2 *notif_doc; |
| static BOOL doc_complete; |
| |
| static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface, |
| REFIID riid, void**ppv) |
| { |
| if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) { |
| *ppv = iface; |
| return S_OK; |
| } |
| |
| ok(0, "unexpected call\n"); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface) |
| { |
| return 2; |
| } |
| |
| static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface) |
| { |
| return 1; |
| } |
| |
| static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID) |
| { |
| if(dispID == DISPID_READYSTATE){ |
| BSTR state; |
| HRESULT hres; |
| |
| hres = IHTMLDocument2_get_readyState(notif_doc, &state); |
| ok(hres == S_OK, "get_readyState failed: %08x\n", hres); |
| |
| if(!strcmp_wa(state, "complete")) |
| doc_complete = TRUE; |
| |
| SysFreeString(state); |
| } |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID) |
| { |
| ok(0, "unexpected call\n"); |
| return E_NOTIMPL; |
| } |
| |
| static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = { |
| PropertyNotifySink_QueryInterface, |
| PropertyNotifySink_AddRef, |
| PropertyNotifySink_Release, |
| PropertyNotifySink_OnChanged, |
| PropertyNotifySink_OnRequestEdit |
| }; |
| |
| static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl }; |
| |
| static void doc_load_string(IHTMLDocument2 *doc, const char *str) |
| { |
| IPersistStreamInit *init; |
| IStream *stream; |
| HGLOBAL mem; |
| SIZE_T len; |
| |
| notif_doc = doc; |
| |
| doc_complete = FALSE; |
| len = strlen(str); |
| mem = GlobalAlloc(0, len); |
| memcpy(mem, str, len); |
| CreateStreamOnHGlobal(mem, TRUE, &stream); |
| |
| IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); |
| |
| IPersistStreamInit_Load(init, stream); |
| IPersistStreamInit_Release(init); |
| IStream_Release(stream); |
| } |
| |
| static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise) |
| { |
| IConnectionPointContainer *container; |
| IConnectionPoint *cp; |
| DWORD cookie; |
| HRESULT hres; |
| |
| hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container); |
| ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres); |
| |
| hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp); |
| IConnectionPointContainer_Release(container); |
| ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres); |
| |
| hres = IConnectionPoint_Advise(cp, unk_advise, &cookie); |
| IConnectionPoint_Release(cp); |
| ok(hres == S_OK, "Advise failed: %08x\n", hres); |
| } |
| |
| static void set_client_site(IHTMLDocument2 *doc, BOOL set) |
| { |
| IOleObject *oleobj; |
| HRESULT hres; |
| |
| if(!set && view) { |
| IOleDocumentView_Show(view, FALSE); |
| IOleDocumentView_CloseView(view, 0); |
| IOleDocumentView_SetInPlaceSite(view, NULL); |
| IOleDocumentView_Release(view); |
| view = NULL; |
| } |
| |
| hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj); |
| ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres); |
| |
| hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL); |
| ok(hres == S_OK, "SetClientSite failed: %08x\n", hres); |
| |
| if(set) { |
| IHlinkTarget *hlink; |
| |
| hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink); |
| ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres); |
| |
| hres = IHlinkTarget_Navigate(hlink, 0, NULL); |
| ok(hres == S_OK, "Navgate failed: %08x\n", hres); |
| |
| IHlinkTarget_Release(hlink); |
| } |
| |
| IOleObject_Release(oleobj); |
| } |
| static IHTMLDocument2 *create_document(void) |
| { |
| IHTMLDocument2 *doc; |
| IHTMLDocument5 *doc5; |
| HRESULT hres; |
| |
| hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, |
| &IID_IHTMLDocument2, (void**)&doc); |
| ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres); |
| if (FAILED(hres)) |
| return NULL; |
| |
| hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument5, (void**)&doc5); |
| if(FAILED(hres)) { |
| win_skip("Could not get IHTMLDocument5 interface, probably too old IE\n"); |
| IHTMLDocument2_Release(doc); |
| return NULL; |
| } |
| |
| IHTMLDocument5_Release(doc5); |
| return doc; |
| } |
| |
| |
| typedef void (*testfunc_t)(IHTMLDocument2*); |
| |
| static void run_test(const char *str, testfunc_t test) |
| { |
| IHTMLDocument2 *doc; |
| IHTMLElement *body = NULL; |
| MSG msg; |
| HRESULT hres; |
| |
| xy_todo = FALSE; |
| doc = create_document(); |
| if (!doc) |
| return; |
| set_client_site(doc, TRUE); |
| doc_load_string(doc, str); |
| do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); |
| |
| while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) { |
| TranslateMessage(&msg); |
| DispatchMessage(&msg); |
| } |
| |
| hres = IHTMLDocument2_get_body(doc, &body); |
| ok(hres == S_OK, "get_body failed: %08x\n", hres); |
| |
| if(body) { |
| IHTMLElement_Release(body); |
| |
| hres = IHTMLDocument2_get_parentWindow(doc, &window); |
| ok(hres == S_OK, "get_parentWindow failed: %08x\n", hres); |
| ok(window != NULL, "window == NULL\n"); |
| |
| test(doc); |
| |
| IHTMLWindow2_Release(window); |
| window = NULL; |
| }else { |
| skip("Could not get document body. Assuming no Gecko installed.\n"); |
| } |
| |
| set_client_site(doc, FALSE); |
| IHTMLDocument2_Release(doc); |
| } |
| |
| static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) |
| { |
| return DefWindowProc(hwnd, msg, wParam, lParam); |
| } |
| |
| static HWND create_container_window(void) |
| { |
| static const CHAR szHTMLDocumentTest[] = "HTMLDocumentTest"; |
| static WNDCLASSEXA wndclass = { |
| sizeof(WNDCLASSEXA), |
| 0, |
| wnd_proc, |
| 0, 0, NULL, NULL, NULL, NULL, NULL, |
| szHTMLDocumentTest, |
| NULL |
| }; |
| |
| RegisterClassExA(&wndclass); |
| return CreateWindowA(szHTMLDocumentTest, szHTMLDocumentTest, |
| WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, |
| 300, 300, NULL, NULL, NULL, NULL); |
| } |
| |
| START_TEST(events) |
| { |
| CoInitialize(NULL); |
| container_hwnd = create_container_window(); |
| |
| if(winetest_interactive) |
| ShowWindow(container_hwnd, SW_SHOW); |
| |
| run_test(empty_doc_str, test_timeout); |
| run_test(click_doc_str, test_onclick); |
| run_test(readystate_doc_str, test_onreadystatechange); |
| run_test(img_doc_str, test_imgload); |
| |
| DestroyWindow(container_hwnd); |
| CoUninitialize(); |
| } |