mshtml: Added IEventTarget stub implementation.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-09-21 23:25:55 +02:00 committed by Alexandre Julliard
parent 632d897c10
commit 455d684671
4 changed files with 162 additions and 2 deletions

View File

@ -1346,6 +1346,11 @@ HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success)
}
}
compat_mode_t dispex_compat_mode(DispatchEx *dispex)
{
return dispex->info->desc->vtbl->get_compat_mode(dispex);
}
static dispex_data_t *ensure_dispex_info(dispex_static_data_t *desc, compat_mode_t compat_mode)
{
if(!desc->info_cache[compat_mode]) {
@ -1362,8 +1367,7 @@ static BOOL ensure_real_info(DispatchEx *dispex)
if(dispex->info != dispex->info->desc->delayed_init_info)
return TRUE;
dispex->info = ensure_dispex_info(dispex->info->desc,
dispex->info->desc->vtbl->get_compat_mode(dispex));
dispex->info = ensure_dispex_info(dispex->info->desc, dispex_compat_mode(dispex));
return dispex->info != NULL;
}

View File

@ -1638,8 +1638,120 @@ HRESULT doc_init_events(HTMLDocumentNode *doc)
return S_OK;
}
static inline EventTarget *impl_from_IEventTarget(IEventTarget *iface)
{
return CONTAINING_RECORD(iface, EventTarget, IEventTarget_iface);
}
static HRESULT WINAPI EventTarget_QueryInterface(IEventTarget *iface, REFIID riid, void **ppv)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_QueryInterface(&This->dispex.IDispatchEx_iface, riid, ppv);
}
static ULONG WINAPI EventTarget_AddRef(IEventTarget *iface)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_AddRef(&This->dispex.IDispatchEx_iface);
}
static ULONG WINAPI EventTarget_Release(IEventTarget *iface)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_Release(&This->dispex.IDispatchEx_iface);
}
static HRESULT WINAPI EventTarget_GetTypeInfoCount(IEventTarget *iface, UINT *pctinfo)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
}
static HRESULT WINAPI EventTarget_GetTypeInfo(IEventTarget *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
}
static HRESULT WINAPI EventTarget_GetIDsOfNames(IEventTarget *iface, REFIID riid, LPOLESTR *rgszNames,
UINT cNames, LCID lcid, DISPID *rgDispId)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid,
rgszNames, cNames, lcid, rgDispId);
}
static HRESULT WINAPI EventTarget_Invoke(IEventTarget *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
EventTarget *This = impl_from_IEventTarget(iface);
return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember,
riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}
static HRESULT WINAPI EventTarget_addEventListener(IEventTarget *iface, BSTR type,
IDispatch *listener, VARIANT_BOOL capture)
{
EventTarget *This = impl_from_IEventTarget(iface);
FIXME("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
return E_NOTIMPL;
}
static HRESULT WINAPI EventTarget_removeEventListener(IEventTarget *iface, BSTR type,
IDispatch *listener, VARIANT_BOOL capture)
{
EventTarget *This = impl_from_IEventTarget(iface);
FIXME("(%p)->(%s %p %x)\n", This, debugstr_w(type), listener, capture);
return E_NOTIMPL;
}
static HRESULT WINAPI EventTarget_dispatchEvent(IEventTarget *iface, IDOMEvent *event, VARIANT_BOOL *result)
{
EventTarget *This = impl_from_IEventTarget(iface);
FIXME("(%p)->(%p %p)\n", This, event, result);
return E_NOTIMPL;
}
static const IEventTargetVtbl EventTargetVtbl = {
EventTarget_QueryInterface,
EventTarget_AddRef,
EventTarget_Release,
EventTarget_GetTypeInfoCount,
EventTarget_GetTypeInfo,
EventTarget_GetIDsOfNames,
EventTarget_Invoke,
EventTarget_addEventListener,
EventTarget_removeEventListener,
EventTarget_dispatchEvent
};
#define DELAY_INIT_VTBL ((const IEventTargetVtbl*)1)
static BOOL use_event_quirks(EventTarget *event_target)
{
if(event_target->IEventTarget_iface.lpVtbl == DELAY_INIT_VTBL) {
event_target->IEventTarget_iface.lpVtbl =
dispex_compat_mode(&event_target->dispex) >= COMPAT_MODE_IE9
? &EventTargetVtbl : NULL;
}
return !event_target->IEventTarget_iface.lpVtbl;
}
HRESULT EventTarget_QI(EventTarget *event_target, REFIID riid, void **ppv)
{
if(IsEqualGUID(riid, &IID_IEventTarget)) {
if(use_event_quirks(event_target)) {
WARN("IEventTarget queried, but not supported by in document mode\n");
*ppv = NULL;
return E_NOINTERFACE;
}
IEventTarget_AddRef(&event_target->IEventTarget_iface);
*ppv = &event_target->IEventTarget_iface;
return S_OK;
}
if(dispex_query_interface(&event_target->dispex, riid, ppv))
return *ppv ? S_OK : E_NOINTERFACE;
@ -1658,6 +1770,20 @@ void EventTarget_Init(EventTarget *event_target, IUnknown *outer, dispex_static_
{
init_dispex_with_compat_mode(&event_target->dispex, outer, dispex_data, compat_mode);
wine_rb_init(&event_target->handler_map, event_id_cmp);
/*
* IEventTarget is supported by the object or not depending on compatibility mode.
* We use NULL vtbl for objects in compatibility mode not supporting the interface.
* For targets that don't know compatibility mode at creation time, we set vtbl
* to special DELAY_INIT_VTBL value so that vtbl will be set to proper value
* when it's needed.
*/
if(compat_mode == COMPAT_MODE_QUIRKS && dispex_data->vtbl && dispex_data->vtbl->get_compat_mode)
event_target->IEventTarget_iface.lpVtbl = DELAY_INIT_VTBL;
else if(compat_mode < COMPAT_MODE_IE9)
event_target->IEventTarget_iface.lpVtbl = NULL;
else
event_target->IEventTarget_iface.lpVtbl = &EventTargetVtbl;
}
void release_event_target(EventTarget *event_target)

View File

@ -333,6 +333,7 @@ void release_typelib(void) DECLSPEC_HIDDEN;
HRESULT get_class_typeinfo(const CLSID*,ITypeInfo**) DECLSPEC_HIDDEN;
const dispex_static_data_vtbl_t *dispex_get_vtbl(DispatchEx*) DECLSPEC_HIDDEN;
void dispex_info_add_interface(dispex_data_t*,tid_t,const DISPID*) DECLSPEC_HIDDEN;
compat_mode_t dispex_compat_mode(DispatchEx*) DECLSPEC_HIDDEN;
static inline void init_dispex(DispatchEx *dispex, IUnknown *outer, dispex_static_data_t *desc)
{
@ -379,6 +380,7 @@ typedef struct {
struct EventTarget {
DispatchEx dispex;
IEventTarget IEventTarget_iface;
struct wine_rb_tree handler_map;
};

View File

@ -10582,7 +10582,10 @@ static float expected_document_mode;
static void test_document_mode(IHTMLDocument2 *doc2)
{
IEventTarget *event_target;
IHTMLDocument2 *doc_node;
IHTMLDocument6 *doc;
IHTMLElement *body;
VARIANT v;
HRESULT hres;
@ -10605,6 +10608,31 @@ static void test_document_mode(IHTMLDocument2 *doc2)
ok(V_VT(&v) == VT_R4, "V_VT(documentMode) = %u\n", V_VT(&v));
ok(V_R4(&v) == expected_document_mode, "documentMode = %f\n", V_R4(&v));
IHTMLDocument6_Release(doc);
doc_node = get_doc_node(doc2);
hres = IHTMLDocument2_QueryInterface(doc_node, &IID_IEventTarget, (void**)&event_target);
if(expected_document_mode >= 9) {
ok(hres == S_OK, "Could not get IEventTarget interface: %08x\n", hres);
IEventTarget_Release(event_target);
}else {
ok(hres == E_NOINTERFACE, "QI(IEventTarget) returned %08x\n", hres);
}
IHTMLDocument2_Release(doc_node);
body = doc_get_body(doc2);
hres = IHTMLElement_QueryInterface(body, &IID_IEventTarget, (void**)&event_target);
if(expected_document_mode >= 9) {
ok(hres == S_OK, "Could not get IEventTarget interface: %08x\n", hres);
IEventTarget_Release(event_target);
}else {
ok(hres == E_NOINTERFACE, "QI(IEventTarget) returned %08x\n", hres);
}
IHTMLElement_Release(body);
}
static void test_quirks_mode(void)