From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/dispex.c | 133 +++++++++++++++++++---------------- dlls/mshtml/mshtml_private.h | 3 + 2 files changed, 76 insertions(+), 60 deletions(-)
diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c index b5d8ac83346..7352a8f3922 100644 --- a/dlls/mshtml/dispex.c +++ b/dlls/mshtml/dispex.c @@ -89,7 +89,6 @@ typedef struct {
typedef struct { DispatchEx dispex; - IUnknown IUnknown_iface; DispatchEx *obj; func_info_t *info; } func_disp_t; @@ -754,6 +753,22 @@ static HRESULT dispex_value(DispatchEx *This, LCID lcid, WORD flags, DISPPARAMS return S_OK; }
+static HRESULT query_typeinfo_interface(DispatchEx *This, const func_info_t *func, void **ppv) +{ + if(This->outer) + return IUnknown_QueryInterface(This->outer, tid_ids[func->tid], ppv); + + if(This->info->desc->vtbl->query_interface) { + *ppv = This->info->desc->vtbl->query_interface(This, tid_ids[func->tid]); + if(*ppv) { + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + } + + return E_NOINTERFACE; +} + static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei) { @@ -774,7 +789,7 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, return hres; }
- hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&unk); + hres = query_typeinfo_interface(This, func, (void**)&unk); if(FAILED(hres)) { ERR("Could not get iface %s: %08lx\n", debugstr_mshtml_guid(tid_ids[func->tid]), hres); return E_FAIL; @@ -786,56 +801,6 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags, return hres; }
-static inline func_disp_t *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, func_disp_t, IUnknown_iface); -} - -static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) -{ - func_disp_t *This = impl_from_IUnknown(iface); - - TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); - - if(IsEqualGUID(&IID_IUnknown, riid)) { - *ppv = &This->IUnknown_iface; - }else if(dispex_query_interface(&This->dispex, riid, ppv)) { - return *ppv ? S_OK : E_NOINTERFACE; - }else { - *ppv = NULL; - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown*)*ppv); - return S_OK; -} - -static ULONG WINAPI Function_AddRef(IUnknown *iface) -{ - func_disp_t *This = impl_from_IUnknown(iface); - LONG ref = dispex_ref_incr(&This->dispex); - - TRACE("(%p) ref=%ld\n", This, ref); - - return ref; -} - -static ULONG WINAPI Function_Release(IUnknown *iface) -{ - func_disp_t *This = impl_from_IUnknown(iface); - LONG ref = dispex_ref_decr(&This->dispex); - - TRACE("(%p) ref=%ld\n", This, ref); - - return ref; -} - -static const IUnknownVtbl FunctionUnkVtbl = { - Function_QueryInterface, - Function_AddRef, - Function_Release -}; - static inline func_disp_t *impl_from_DispatchEx(DispatchEx *iface) { return CONTAINING_RECORD(iface, func_disp_t, dispex); @@ -925,8 +890,7 @@ static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info) if(!ret) return NULL;
- ret->IUnknown_iface.lpVtbl = &FunctionUnkVtbl; - init_dispatch(&ret->dispex, &ret->IUnknown_iface, &function_dispex, dispex_compat_mode(obj)); + init_dispatch(&ret->dispex, NULL, &function_dispex, dispex_compat_mode(obj)); ret->obj = obj; ret->info = info;
@@ -1115,7 +1079,7 @@ static HRESULT builtin_propget(DispatchEx *This, func_info_t *func, DISPPARAMS *
assert(func->get_vtbl_off);
- hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface); + hres = query_typeinfo_interface(This, func, (void**)&iface); if(SUCCEEDED(hres)) { switch(func->prop_vt) { #define CASE_VT(vt,type,access) \ @@ -1172,7 +1136,7 @@ static HRESULT builtin_propput(DispatchEx *This, func_info_t *func, DISPPARAMS * v = &tmpv; }
- hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface); + hres = query_typeinfo_interface(This, func, (void**)&iface); if(SUCCEEDED(hres)) { switch(func->prop_vt) { #define CASE_VT(vt,type,access) \ @@ -1216,7 +1180,7 @@ static HRESULT invoke_builtin_function(DispatchEx *This, func_info_t *func, DISP return E_INVALIDARG; }
- hres = IUnknown_QueryInterface(This->outer, tid_ids[func->tid], (void**)&iface); + hres = query_typeinfo_interface(This, func, (void**)&iface); if(FAILED(hres)) return hres;
@@ -1591,21 +1555,70 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, { DispatchEx *This = impl_from_IDispatchEx(iface);
- return IUnknown_QueryInterface(This->outer, riid, ppv); + if(This->outer) + return IUnknown_QueryInterface(This->outer, riid, ppv); + + TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv); + + if(This->info->desc->vtbl->query_interface) { + *ppv = This->info->desc->vtbl->query_interface(This, riid); + if(*ppv) + goto ret; + } + + if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_IDispatchEx, riid)) + *ppv = &This->IDispatchEx_iface; + else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) { + *ppv = &dispex_ccp; + return S_OK; + }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) { + *ppv = &This->IDispatchEx_iface; + return S_OK; + }else if(IsEqualGUID(&IID_IDispatchJS, riid) || + IsEqualGUID(&IID_UndocumentedScriptIface, riid) || + IsEqualGUID(&IID_IMarshal, riid) || + IsEqualGUID(&IID_IManagedObject, riid)) { + *ppv = NULL; + return E_NOINTERFACE; + }else { + WARN("(%p)->%s\n", This, debugstr_mshtml_guid(riid)); + *ppv = NULL; + return E_NOINTERFACE; + } + +ret: + IDispatchEx_AddRef(&This->IDispatchEx_iface); + return S_OK; }
static ULONG WINAPI DispatchEx_AddRef(IDispatchEx *iface) { DispatchEx *This = impl_from_IDispatchEx(iface); + LONG ref; + + if(This->outer) + return IUnknown_AddRef(This->outer); + + ref = dispex_ref_incr(This);
- return IUnknown_AddRef(This->outer); + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; }
static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface) { DispatchEx *This = impl_from_IDispatchEx(iface); + LONG ref; + + if(This->outer) + return IUnknown_Release(This->outer);
- return IUnknown_Release(This->outer); + ref = dispex_ref_decr(This); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; }
static HRESULT WINAPI DispatchEx_GetTypeInfoCount(IDispatchEx *iface, UINT *pctinfo) diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index dfbbd3fec83..b29032e5840 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -352,6 +352,9 @@ typedef struct { - dynamic props: These props are generally allocated by external code (e.g. 'document.wine = 42' creates 'wine' dynamic prop on document) */ typedef struct { + /* Used to provide object specific interfaces (do not AddRef, just return the iface) */ + void *(*query_interface)(DispatchEx*,REFIID); + /* Used to implement Cycle Collection callbacks; note that the destructor is not optional! Unlike delete_cycle_collectable, unlink is called before the destructor (if available). */ void (*destructor)(DispatchEx*);