static HRESULT WINAPI DispatchEx_GetNextDispID(IDispatchEx *iface, DWORD grfdex, DISPID id, DISPID *pid) { DispatchEx *This = impl_from_IDispatchEx(iface); dispex_data_t *data; func_info_t *func; HRESULT hres; TRACE("(%p)->(%x %x %p)\n", This, grfdex, id, pid); if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; while(++idx < This->dynamic_data->prop_cnt && This->dynamic_data->props[idx].flags & DYNPROP_DELETED); if(idx == This->dynamic_data->prop_cnt) { *pid = DISPID_STARTENUM; return S_FALSE; } *pid = DISPID_DYNPROP_0+idx; return S_OK; } data = get_dispex_data(This); if(!data) return E_FAIL; if(id == DISPID_STARTENUM) { func = data->funcs; }else { hres = get_builtin_func(data, id, &func); if(FAILED(hres)) return hres; func++; } while(func < data->funcs+data->func_cnt) { /* FIXME: Skip hidden properties */ if(func->func_disp_idx == -1) { *pid = func->id; return S_OK; } func++; } if(get_dynamic_data(This) && This->dynamic_data->prop_cnt) { *pid = DISPID_DYNPROP_0; return S_OK; } *pid = DISPID_STARTENUM; return S_FALSE; }
static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_entry_t **ret) { dispex_dynamic_data_t *dynamic_data; func_obj_entry_t *entry; dynamic_data = get_dynamic_data(This); 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(*dynamic_data->func_disps)); if(!dynamic_data->func_disps) return E_OUTOFMEMORY; } entry = dynamic_data->func_disps + func->func_disp_idx; if(!entry->func_obj) { entry->func_obj = create_func_disp(This, func); if(!entry->func_obj) return E_OUTOFMEMORY; IDispatchEx_AddRef(&entry->func_obj->dispex.IDispatchEx_iface); V_VT(&entry->val) = VT_DISPATCH; V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface; } *ret = entry; return S_OK; }
static HRESULT WINAPI DispatchEx_GetMemberName(IDispatchEx *iface, DISPID id, BSTR *pbstrName) { DispatchEx *This = impl_from_IDispatchEx(iface); dispex_data_t *data; func_info_t *func; HRESULT hres; TRACE("(%p)->(%x %p)\n", This, id, pbstrName); if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; *pbstrName = SysAllocString(This->dynamic_data->props[idx].name); if(!*pbstrName) return E_OUTOFMEMORY; return S_OK; } data = get_dispex_data(This); if(!data) return E_FAIL; hres = get_builtin_func(data, id, &func); if(FAILED(hres)) return hres; *pbstrName = SysAllocString(func->name); if(!*pbstrName) return E_OUTOFMEMORY; return S_OK; }
static HRESULT get_dynamic_prop(DispatchEx *This, const WCHAR *name, DWORD flags, dynamic_prop_t **ret) { const BOOL alloc = flags & fdexNameEnsure; dispex_dynamic_data_t *data; dynamic_prop_t *prop; data = get_dynamic_data(This, alloc); if(!data) { if(alloc) return E_OUTOFMEMORY; TRACE("not found %s\n", debugstr_w(name)); return DISP_E_UNKNOWNNAME; } for(prop = data->props; prop < data->props+data->prop_cnt; prop++) { if(flags & fdexNameCaseInsensitive ? !strcmpiW(prop->name, name) : !strcmpW(prop->name, name)) { if(prop->flags & DYNPROP_DELETED) { if(!alloc) return DISP_E_UNKNOWNNAME; prop->flags &= ~DYNPROP_DELETED; } *ret = prop; return S_OK; } } if(!alloc) return DISP_E_UNKNOWNNAME; TRACE("creating dynamic prop %s\n", debugstr_w(name)); if(!data->buf_size) { data->props = heap_alloc(sizeof(dynamic_prop_t)*4); if(!data->props) return E_OUTOFMEMORY; data->buf_size = 4; }else if(data->buf_size == data->prop_cnt) { dynamic_prop_t *new_props; new_props = heap_realloc(data->props, sizeof(dynamic_prop_t)*(data->buf_size<<1)); if(!new_props) return E_OUTOFMEMORY; data->props = new_props; data->buf_size <<= 1; } prop = data->props + data->prop_cnt; prop->name = heap_strdupW(name); if(!prop->name) return E_OUTOFMEMORY; VariantInit(&prop->var); prop->flags = 0; data->prop_cnt++; *ret = prop; return S_OK; }
static HRESULT get_func_obj_entry(DispatchEx *This, func_info_t *func, func_obj_entry_t **ret) { dispex_dynamic_data_t *dynamic_data; dynamic_data = get_dynamic_data(This); 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(*dynamic_data->func_disps)); if(!dynamic_data->func_disps) return E_OUTOFMEMORY; } if(!dynamic_data->func_disps[func->func_disp_idx].func_obj) { func_disp_t *func_obj; func_obj = create_func_disp(This, func); if(!func_obj) return E_OUTOFMEMORY; dynamic_data->func_disps[func->func_disp_idx].func_obj = func_obj; IDispatchEx_AddRef(&func_obj->dispex.IDispatchEx_iface); dynamic_data->func_disps[func->func_disp_idx].val = (IDispatch*)&func_obj->dispex.IDispatchEx_iface; } *ret = dynamic_data->func_disps+func->func_disp_idx; return S_OK; }
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|DISPATCH_PROPERTYGET: if(!res) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: hres = typeinfo_invoke(This, func, flags, dp, res, ei); break; case DISPATCH_PROPERTYGET: { dispex_dynamic_data_t *dynamic_data; if(func->id == DISPID_VALUE) { BSTR ret; ret = SysAllocString(objectW); if(!ret) return E_OUTOFMEMORY; V_VT(res) = VT_BSTR; V_BSTR(res) = ret; return S_OK; } dynamic_data = get_dynamic_data(This); 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*)&dynamic_data->func_disps[func->func_disp_idx]->dispex.IDispatchEx_iface; IDispatch_AddRef(V_DISPATCH(res)); hres = S_OK; break; } default: FIXME("Unimplemented flags %x\n", flags); /* fall through */ case DISPATCH_PROPERTYPUT: hres = E_NOTIMPL; } return hres; }
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { DispatchEx *This = impl_from_IDispatchEx(iface); HRESULT hres; TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); if(wFlags == (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) wFlags = DISPATCH_PROPERTYPUT; switch(get_dispid_type(id)) { case DISPEXPROP_CUSTOM: if(!This->data->vtbl || !This->data->vtbl->invoke) return DISP_E_UNKNOWNNAME; return This->data->vtbl->invoke(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); case DISPEXPROP_DYNAMIC: { DWORD idx = id - DISPID_DYNPROP_0; dynamic_prop_t *prop; if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; prop = This->dynamic_data->props+idx; switch(wFlags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!pvarRes) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: if(V_VT(&prop->var) != VT_DISPATCH) { FIXME("invoke %s\n", debugstr_variant(&prop->var)); return E_NOTIMPL; } return invoke_disp_value(This, V_DISPATCH(&prop->var), lcid, wFlags, pdp, pvarRes, pei, pspCaller); case DISPATCH_PROPERTYGET: if(prop->flags & DYNPROP_DELETED) return DISP_E_UNKNOWNNAME; V_VT(pvarRes) = VT_EMPTY; return variant_copy(pvarRes, &prop->var); case DISPATCH_PROPERTYPUT: if(pdp->cArgs != 1 || (pdp->cNamedArgs == 1 && *pdp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || pdp->cNamedArgs > 1) { FIXME("invalid args\n"); return E_INVALIDARG; } TRACE("put %s\n", debugstr_variant(pdp->rgvarg)); VariantClear(&prop->var); hres = variant_copy(&prop->var, pdp->rgvarg); if(FAILED(hres)) return hres; prop->flags &= ~DYNPROP_DELETED; return S_OK; default: FIXME("unhandled wFlags %x\n", wFlags); return E_NOTIMPL; } } case DISPEXPROP_BUILTIN: if(wFlags == DISPATCH_CONSTRUCT) { if(id == DISPID_VALUE) { if(This->data->vtbl && This->data->vtbl->value) { return This->data->vtbl->value(This, lcid, wFlags, pdp, pvarRes, pei, pspCaller); } FIXME("DISPATCH_CONSTRUCT flag but missing value function\n"); return E_FAIL; } FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n"); return E_FAIL; } return invoke_builtin_prop(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); default: assert(0); return E_FAIL; } }
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { DispatchEx *This = impl_from_IDispatchEx(iface); HRESULT hres; TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); if(is_custom_dispid(id) && This->data->vtbl && This->data->vtbl->invoke) return This->data->vtbl->invoke(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); if(wFlags == DISPATCH_CONSTRUCT) { if(id == DISPID_VALUE) { if(This->data->vtbl && This->data->vtbl->value) { return This->data->vtbl->value(This, lcid, wFlags, pdp, pvarRes, pei, pspCaller); } FIXME("DISPATCH_CONSTRUCT flag but missing value function\n"); return E_FAIL; } FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n"); return E_FAIL; } if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; dynamic_prop_t *prop; if(!get_dynamic_data(This) || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; prop = This->dynamic_data->props+idx; switch(wFlags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!pvarRes) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: { DISPID named_arg = DISPID_THIS; DISPPARAMS dp = {NULL, &named_arg, 0, 1}; IDispatchEx *dispex; if(V_VT(&prop->var) != VT_DISPATCH) { FIXME("invoke %s\n", debugstr_variant(&prop->var)); return E_NOTIMPL; } if(pdp->cNamedArgs) { FIXME("named args not supported\n"); return E_NOTIMPL; } dp.rgvarg = heap_alloc((pdp->cArgs+1)*sizeof(VARIANTARG)); if(!dp.rgvarg) return E_OUTOFMEMORY; dp.cArgs = pdp->cArgs+1; memcpy(dp.rgvarg+1, pdp->rgvarg, pdp->cArgs*sizeof(VARIANTARG)); V_VT(dp.rgvarg) = VT_DISPATCH; V_DISPATCH(dp.rgvarg) = (IDispatch*)&This->IDispatchEx_iface; hres = IDispatch_QueryInterface(V_DISPATCH(&prop->var), &IID_IDispatchEx, (void**)&dispex); TRACE("%s call\n", debugstr_w(This->dynamic_data->props[idx].name)); if(SUCCEEDED(hres)) { hres = IDispatchEx_InvokeEx(dispex, DISPID_VALUE, lcid, wFlags, &dp, pvarRes, pei, pspCaller); IDispatchEx_Release(dispex); }else { ULONG err = 0; hres = IDispatch_Invoke(V_DISPATCH(&prop->var), DISPID_VALUE, &IID_NULL, lcid, wFlags, pdp, pvarRes, pei, &err); } TRACE("%s ret %08x\n", debugstr_w(This->dynamic_data->props[idx].name), hres); heap_free(dp.rgvarg); return hres; } case DISPATCH_PROPERTYGET: if(prop->flags & DYNPROP_DELETED) return DISP_E_UNKNOWNNAME; V_VT(pvarRes) = VT_EMPTY; return variant_copy(pvarRes, &prop->var); case DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF: case DISPATCH_PROPERTYPUT: if(pdp->cArgs != 1 || (pdp->cNamedArgs == 1 && *pdp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || pdp->cNamedArgs > 1) { FIXME("invalid args\n"); return E_INVALIDARG; } TRACE("put %s\n", debugstr_variant(pdp->rgvarg)); VariantClear(&prop->var); hres = variant_copy(&prop->var, pdp->rgvarg); if(FAILED(hres)) return hres; prop->flags &= ~DYNPROP_DELETED; return S_OK; default: FIXME("unhandled wFlags %x\n", wFlags); return E_NOTIMPL; } } return invoke_builtin_prop(This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); }