mshtml: Added function object implementation.
This commit is contained in:
parent
55d6bcb036
commit
65d0929cfc
|
@ -35,12 +35,14 @@ typedef struct {
|
||||||
DISPID id;
|
DISPID id;
|
||||||
BSTR name;
|
BSTR name;
|
||||||
tid_t tid;
|
tid_t tid;
|
||||||
|
int func_disp_idx;
|
||||||
} func_info_t;
|
} func_info_t;
|
||||||
|
|
||||||
struct dispex_data_t {
|
struct dispex_data_t {
|
||||||
DWORD func_cnt;
|
DWORD func_cnt;
|
||||||
func_info_t *funcs;
|
func_info_t *funcs;
|
||||||
func_info_t **name_table;
|
func_info_t **name_table;
|
||||||
|
DWORD func_disp_cnt;
|
||||||
|
|
||||||
struct list entry;
|
struct list entry;
|
||||||
};
|
};
|
||||||
|
@ -50,10 +52,20 @@ typedef struct {
|
||||||
LPWSTR name;
|
LPWSTR name;
|
||||||
} dynamic_prop_t;
|
} dynamic_prop_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DispatchEx dispex;
|
||||||
|
const IUnknownVtbl *lpIUnknownVtbl;
|
||||||
|
DispatchEx *obj;
|
||||||
|
func_info_t *info;
|
||||||
|
} func_disp_t;
|
||||||
|
|
||||||
|
#define FUNCUNKNOWN(x) ((IUnknown*) &(x)->lpIUnknownVtbl)
|
||||||
|
|
||||||
struct dispex_dynamic_data_t {
|
struct dispex_dynamic_data_t {
|
||||||
DWORD buf_size;
|
DWORD buf_size;
|
||||||
DWORD prop_cnt;
|
DWORD prop_cnt;
|
||||||
dynamic_prop_t *props;
|
dynamic_prop_t *props;
|
||||||
|
func_disp_t **func_disps;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DISPID_DYNPROP_0 0x50000000
|
#define DISPID_DYNPROP_0 0x50000000
|
||||||
|
@ -188,22 +200,23 @@ void release_typelib(void)
|
||||||
ITypeLib_Release(typelib);
|
ITypeLib_Release(typelib);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, DISPID id, ITypeInfo *dti)
|
static void add_func_info(dispex_data_t *data, DWORD *size, tid_t tid, const FUNCDESC *desc, ITypeInfo *dti)
|
||||||
{
|
{
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
if(data->func_cnt && data->funcs[data->func_cnt-1].id == id)
|
if(data->func_cnt && data->funcs[data->func_cnt-1].id == desc->memid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(data->func_cnt == *size)
|
if(data->func_cnt == *size)
|
||||||
data->funcs = heap_realloc(data->funcs, (*size <<= 1)*sizeof(func_info_t));
|
data->funcs = heap_realloc(data->funcs, (*size <<= 1)*sizeof(func_info_t));
|
||||||
|
|
||||||
hres = ITypeInfo_GetDocumentation(dti, id, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
|
hres = ITypeInfo_GetDocumentation(dti, desc->memid, &data->funcs[data->func_cnt].name, NULL, NULL, NULL);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
data->funcs[data->func_cnt].id = id;
|
data->funcs[data->func_cnt].id = desc->memid;
|
||||||
data->funcs[data->func_cnt].tid = tid;
|
data->funcs[data->func_cnt].tid = tid;
|
||||||
|
data->funcs[data->func_cnt].func_disp_idx = desc->invkind == INVOKE_FUNC ? data->func_disp_cnt++ : -1;
|
||||||
|
|
||||||
data->func_cnt++;
|
data->func_cnt++;
|
||||||
}
|
}
|
||||||
|
@ -237,6 +250,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This)
|
||||||
|
|
||||||
data = heap_alloc(sizeof(dispex_data_t));
|
data = heap_alloc(sizeof(dispex_data_t));
|
||||||
data->func_cnt = 0;
|
data->func_cnt = 0;
|
||||||
|
data->func_disp_cnt = 0;
|
||||||
data->funcs = heap_alloc(size*sizeof(func_info_t));
|
data->funcs = heap_alloc(size*sizeof(func_info_t));
|
||||||
list_add_tail(&dispex_data_list, &data->entry);
|
list_add_tail(&dispex_data_list, &data->entry);
|
||||||
|
|
||||||
|
@ -251,7 +265,7 @@ static dispex_data_t *preprocess_dispex_data(DispatchEx *This)
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
add_func_info(data, &size, *tid, funcdesc->memid, dti);
|
add_func_info(data, &size, *tid, funcdesc, dti);
|
||||||
ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
|
ITypeInfo_ReleaseFuncDesc(ti, funcdesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +471,142 @@ static HRESULT typeinfo_invoke(DispatchEx *This, func_info_t *func, WORD flags,
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FUNCTION_THIS(iface) DEFINE_THIS(func_disp_t, IUnknown, iface)
|
||||||
|
|
||||||
|
static HRESULT WINAPI Function_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
|
||||||
|
{
|
||||||
|
func_disp_t *This = FUNCTION_THIS(iface);
|
||||||
|
|
||||||
|
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
||||||
|
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
||||||
|
*ppv = FUNCUNKNOWN(This);
|
||||||
|
}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 = FUNCTION_THIS(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
return IDispatchEx_AddRef(DISPATCHEX(This->obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI Function_Release(IUnknown *iface)
|
||||||
|
{
|
||||||
|
func_disp_t *This = FUNCTION_THIS(iface);
|
||||||
|
|
||||||
|
TRACE("(%p)\n", This);
|
||||||
|
|
||||||
|
return IDispatchEx_Release(DISPATCHEX(This->obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT function_value(IUnknown *iface, LCID lcid, WORD flags, DISPPARAMS *params,
|
||||||
|
VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
|
||||||
|
{
|
||||||
|
func_disp_t *This = FUNCTION_THIS(iface);
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
switch(flags) {
|
||||||
|
case DISPATCH_METHOD:
|
||||||
|
hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("Unimplemented flags %x\n", flags);
|
||||||
|
hres = E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef FUNCTION_THIS
|
||||||
|
|
||||||
|
static const IUnknownVtbl FunctionUnkVtbl = {
|
||||||
|
Function_QueryInterface,
|
||||||
|
Function_AddRef,
|
||||||
|
Function_Release
|
||||||
|
};
|
||||||
|
|
||||||
|
static const dispex_static_data_vtbl_t function_dispex_vtbl = {
|
||||||
|
function_value,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static dispex_static_data_t function_dispex = {
|
||||||
|
&function_dispex_vtbl,
|
||||||
|
LAST_tid,
|
||||||
|
NULL,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static func_disp_t *create_func_disp(DispatchEx *obj, func_info_t *info)
|
||||||
|
{
|
||||||
|
func_disp_t *ret;
|
||||||
|
|
||||||
|
ret = heap_alloc_zero(sizeof(func_disp_t));
|
||||||
|
if(!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret->lpIUnknownVtbl = &FunctionUnkVtbl;
|
||||||
|
init_dispex(&ret->dispex, FUNCUNKNOWN(ret), &function_dispex);
|
||||||
|
ret->obj = obj;
|
||||||
|
ret->info = info;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res,
|
||||||
|
EXCEPINFO *ei)
|
||||||
|
{
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
|
switch(flags) {
|
||||||
|
case DISPATCH_METHOD:
|
||||||
|
hres = typeinfo_invoke(This, func, flags, dp, res, ei);
|
||||||
|
break;
|
||||||
|
case DISPATCH_PROPERTYGET: {
|
||||||
|
dispex_dynamic_data_t *dynamic_data;
|
||||||
|
|
||||||
|
dynamic_data = get_dynamic_data(This, TRUE);
|
||||||
|
if(!dynamic_data)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if(!dynamic_data->func_disps) {
|
||||||
|
dynamic_data->func_disps = heap_alloc_zero(This->data->data->func_disp_cnt * sizeof(func_disp_t*));
|
||||||
|
if(!dynamic_data->func_disps)
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!dynamic_data->func_disps[func->func_disp_idx]) {
|
||||||
|
dynamic_data->func_disps[func->func_disp_idx] = create_func_disp(This, func);
|
||||||
|
if(!dynamic_data->func_disps[func->func_disp_idx])
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
V_VT(res) = VT_DISPATCH;
|
||||||
|
V_DISPATCH(res) = (IDispatch*)DISPATCHEX(&dynamic_data->func_disps[func->func_disp_idx]->dispex);
|
||||||
|
IDispatch_AddRef(V_DISPATCH(res));
|
||||||
|
hres = S_OK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
FIXME("Unimplemented flags %x\n", flags);
|
||||||
|
case DISPATCH_PROPERTYPUT:
|
||||||
|
hres = E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
|
|
||||||
#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
|
#define DISPATCHEX_THIS(iface) DEFINE_THIS(DispatchEx, IDispatchEx, iface)
|
||||||
|
|
||||||
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
|
static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv)
|
||||||
|
@ -698,7 +848,12 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc
|
||||||
return DISP_E_UNKNOWNNAME;
|
return DISP_E_UNKNOWNNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeinfo_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
|
if(data->funcs[n].func_disp_idx == -1)
|
||||||
|
hres = typeinfo_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
|
||||||
|
else
|
||||||
|
hres = function_invoke(This, data->funcs+n, wFlags, pdp, pvarRes, pei);
|
||||||
|
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
|
static HRESULT WINAPI DispatchEx_DeleteMemberByName(IDispatchEx *iface, BSTR bstrName, DWORD grfdex)
|
||||||
|
|
Loading…
Reference in New Issue