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 invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { dispex_data_t *data; func_info_t *func; HRESULT hres; data = get_dispex_data(This); if(!data) return E_FAIL; hres = get_builtin_func(data, id, &func); if(id == DISPID_VALUE && hres == DISP_E_UNKNOWNNAME) return dispex_value(This, lcid, flags, dp, res, ei, caller); if(FAILED(hres)) return hres; if(func->func_disp_idx != -1) return function_invoke(This, func, flags, dp, res, ei, caller); switch(flags) { case DISPATCH_PROPERTYPUT: if(res) V_VT(res) = VT_EMPTY; hres = builtin_propput(This, func, dp, caller); break; case DISPATCH_PROPERTYGET: hres = builtin_propget(This, func, dp, res); break; default: if(!func->get_vtbl_off) { hres = typeinfo_invoke(This, func, flags, dp, res, ei); }else { VARIANT v; hres = builtin_propget(This, func, NULL, &v); if(FAILED(hres)) return hres; if(flags != (DISPATCH_PROPERTYGET|DISPATCH_METHOD) || dp->cArgs) { if(V_VT(&v) != VT_DISPATCH) { FIXME("Not a function %s flags %08x\n", debugstr_variant(&v), flags); VariantClear(&v); return E_FAIL; } hres = invoke_disp_value(This, V_DISPATCH(&v), lcid, flags, dp, res, ei, caller); IDispatch_Release(V_DISPATCH(&v)); }else if(res) { *res = v; }else { VariantClear(&v); } } } return hres; }
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 WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { DispatchEx *This = DISPATCHEX_THIS(iface); dynamic_prop_t *dprop; dispex_data_t *data; int min, max, n, c; HRESULT hres; TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit)) FIXME("Unsupported grfdex %x\n", grfdex); data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; c = strcmpiW(data->name_table[n]->name, bstrName); if(!c) { if((grfdex & fdexNameCaseSensitive) && strcmpW(data->name_table[n]->name, bstrName)) break; *pid = data->name_table[n]->id; return S_OK; } if(c > 0) max = n-1; else min = n+1; } if(This->data->vtbl && This->data->vtbl->get_dispid) { HRESULT hres; hres = This->data->vtbl->get_dispid(This->outer, bstrName, grfdex, pid); if(hres != DISP_E_UNKNOWNNAME) return hres; } hres = get_dynamic_prop(This, bstrName, grfdex&fdexNameEnsure, &dprop); if(FAILED(hres)) return hres; *pid = DISPID_DYNPROP_0 + (dprop - This->dynamic_data->props); return S_OK; }
static HRESULT get_builtin_id(DispatchEx *This, BSTR name, DWORD grfdex, DISPID *ret) { dispex_data_t *data; int min, max, n, c; data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; c = strcmpiW(data->name_table[n]->name, name); if(!c) { if((grfdex & fdexNameCaseSensitive) && strcmpW(data->name_table[n]->name, name)) break; *ret = data->name_table[n]->id; return S_OK; } if(c > 0) max = n-1; else min = n+1; } if(This->data->vtbl && This->data->vtbl->get_dispid) { HRESULT hres; hres = This->data->vtbl->get_dispid(This, name, grfdex, ret); if(hres != DISP_E_UNKNOWNNAME) return hres; } return DISP_E_UNKNOWNNAME; }
static HRESULT invoke_builtin_prop(DispatchEx *This, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { dispex_data_t *data; func_info_t *func; HRESULT hres; data = get_dispex_data(This); if(!data) return E_FAIL; hres = get_builtin_func(data, id, &func); if(id == DISPID_VALUE && hres == DISP_E_UNKNOWNNAME) return dispex_value(This, lcid, flags, dp, res, ei, caller); if(FAILED(hres)) return hres; if(func->func_disp_idx == -1) hres = typeinfo_invoke(This, func, flags, dp, res, ei); else hres = function_invoke(This, func, flags, dp, res, ei); 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); IUnknown *unk; ITypeInfo *ti; dispex_data_t *data; UINT argerr=0; int min, max, n; 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->outer, id, lcid, wFlags, pdp, pvarRes, pei); if(wFlags == DISPATCH_CONSTRUCT) { FIXME("DISPATCH_CONSTRUCT not implemented\n"); return E_NOTIMPL; } if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; VARIANT *var; if(!This->dynamic_data || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; var = &This->dynamic_data->props[idx].var; switch(wFlags) { case INVOKE_PROPERTYGET: return VariantCopy(pvarRes, var); case INVOKE_PROPERTYPUT: VariantClear(var); return VariantCopy(var, pdp->rgvarg); default: FIXME("unhandled wFlags %x\n", wFlags); return E_NOTIMPL; } } data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; if(data->funcs[n].id == id) break; if(data->funcs[n].id < id) min = n+1; else max = n-1; } if(min > max) { WARN("invalid id %x\n", id); return DISP_E_UNKNOWNNAME; } hres = get_typeinfo(data->funcs[n].tid, &ti); if(FAILED(hres)) { ERR("Could not get type info: %08x\n", hres); return hres; } hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid], (void**)&unk); if(FAILED(hres)) { ERR("Could not get iface: %08x\n", hres); return E_FAIL; } hres = ITypeInfo_Invoke(ti, unk, id, wFlags, pdp, pvarRes, pei, &argerr); ITypeInfo_Release(ti); IUnknown_Release(unk); return hres; }
static HRESULT WINAPI DispatchEx_GetDispID(IDispatchEx *iface, BSTR bstrName, DWORD grfdex, DISPID *pid) { DispatchEx *This = impl_from_IDispatchEx(iface); dispex_data_t *data; int min, max, n, c; TRACE("(%p)->(%s %x %p)\n", This, debugstr_w(bstrName), grfdex, pid); if(grfdex & ~(fdexNameCaseSensitive|fdexNameEnsure|fdexNameImplicit)) FIXME("Unsupported grfdex %x\n", grfdex); data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; c = strcmpiW(data->name_table[n]->name, bstrName); if(!c) { if((grfdex & fdexNameCaseSensitive) && strcmpW(data->name_table[n]->name, bstrName)) break; *pid = data->name_table[n]->id; return S_OK; } if(c > 0) max = n-1; else min = n+1; } if(This->dynamic_data) { unsigned i; for(i=0; i < This->dynamic_data->prop_cnt; i++) { if(!strcmpW(This->dynamic_data->props[i].name, bstrName)) { *pid = DISPID_DYNPROP_0 + i; return S_OK; } } } if(This->data->vtbl && This->data->vtbl->get_dispid) { HRESULT hres; hres = This->data->vtbl->get_dispid(This->outer, bstrName, grfdex, pid); if(hres != DISP_E_UNKNOWNNAME) return hres; } if(grfdex & fdexNameEnsure) { dispex_dynamic_data_t *dynamic_data; TRACE("creating dynamic prop %s\n", debugstr_w(bstrName)); if(This->dynamic_data) { dynamic_data = This->dynamic_data; }else { dynamic_data = This->dynamic_data = heap_alloc_zero(sizeof(dispex_dynamic_data_t)); if(!dynamic_data) return E_OUTOFMEMORY; } if(!dynamic_data->buf_size) { dynamic_data->props = heap_alloc(sizeof(dynamic_prop_t)*4); if(!dynamic_data->props) return E_OUTOFMEMORY; dynamic_data->buf_size = 4; }else if(dynamic_data->buf_size == dynamic_data->prop_cnt) { dynamic_prop_t *new_props; new_props = heap_realloc(dynamic_data->props, sizeof(dynamic_prop_t)*(dynamic_data->buf_size<<1)); if(!new_props) return E_OUTOFMEMORY; dynamic_data->props = new_props; dynamic_data->buf_size <<= 1; } dynamic_data->props[dynamic_data->prop_cnt].name = heap_strdupW(bstrName); VariantInit(&dynamic_data->props[dynamic_data->prop_cnt].var); *pid = DISPID_DYNPROP_0 + dynamic_data->prop_cnt++; return S_OK; } TRACE("not found %s\n", debugstr_w(bstrName)); return DISP_E_UNKNOWNNAME; }
static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller) { DispatchEx *This = DISPATCHEX_THIS(iface); IUnknown *unk; ITypeInfo *ti; dispex_data_t *data; UINT argerr=0; int min, max, n; 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->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); if(wFlags == DISPATCH_CONSTRUCT) { FIXME("DISPATCH_CONSTRUCT not implemented\n"); return E_NOTIMPL; } if(is_dynamic_dispid(id)) { DWORD idx = id - DISPID_DYNPROP_0; VARIANT *var; if(!This->dynamic_data || This->dynamic_data->prop_cnt <= idx) return DISP_E_UNKNOWNNAME; var = &This->dynamic_data->props[idx].var; switch(wFlags) { case INVOKE_FUNC: { DISPID named_arg = DISPID_THIS; DISPPARAMS dp = {NULL, &named_arg, 0, 1}; IDispatchEx *dispex; if(V_VT(var) != VT_DISPATCH) { FIXME("invoke vt %d\n", V_VT(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*)DISPATCHEX(This); hres = IDispatch_QueryInterface(V_DISPATCH(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(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 INVOKE_PROPERTYGET: return VariantCopy(pvarRes, var); case INVOKE_PROPERTYPUT: VariantClear(var); return VariantCopy(var, pdp->rgvarg); default: FIXME("unhandled wFlags %x\n", wFlags); return E_NOTIMPL; } } data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; if(data->funcs[n].id == id) break; if(data->funcs[n].id < id) min = n+1; else max = n-1; } if(min > max) { WARN("invalid id %x\n", id); return DISP_E_UNKNOWNNAME; } hres = get_typeinfo(data->funcs[n].tid, &ti); if(FAILED(hres)) { ERR("Could not get type info: %08x\n", hres); return hres; } hres = IUnknown_QueryInterface(This->outer, tid_ids[data->funcs[n].tid], (void**)&unk); if(FAILED(hres)) { ERR("Could not get iface %s: %08x\n", debugstr_guid(tid_ids[data->funcs[n].tid]), hres); return E_FAIL; } hres = ITypeInfo_Invoke(ti, unk, id, wFlags, pdp, pvarRes, pei, &argerr); IUnknown_Release(unk); return hres; }
HRESULT remove_attribute(DispatchEx *This, DISPID id, VARIANT_BOOL *success) { switch(get_dispid_type(id)) { case DISPEXPROP_CUSTOM: FIXME("DISPEXPROP_CUSTOM not supported\n"); return E_NOTIMPL; case DISPEXPROP_DYNAMIC: { DWORD idx = id - DISPID_DYNPROP_0; dynamic_prop_t *prop; prop = This->dynamic_data->props+idx; VariantClear(&prop->var); prop->flags |= DYNPROP_DELETED; *success = VARIANT_TRUE; return S_OK; } case DISPEXPROP_BUILTIN: { VARIANT var; DISPPARAMS dp = {&var,NULL,1,0}; dispex_data_t *data; func_info_t *func; HRESULT hres; data = get_dispex_data(This); if(!data) return E_FAIL; hres = get_builtin_func(data, id, &func); if(FAILED(hres)) return hres; /* For builtin functions, we set their value to the original function. */ if(func->func_disp_idx != -1) { func_obj_entry_t *entry; if(!This->dynamic_data || !This->dynamic_data->func_disps || !This->dynamic_data->func_disps[func->func_disp_idx].func_obj) { *success = VARIANT_FALSE; return S_OK; } entry = This->dynamic_data->func_disps + func->func_disp_idx; if(V_VT(&entry->val) == VT_DISPATCH && V_DISPATCH(&entry->val) == (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface) { *success = VARIANT_FALSE; return S_OK; } VariantClear(&entry->val); V_VT(&entry->val) = VT_DISPATCH; V_DISPATCH(&entry->val) = (IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface; IDispatch_AddRef(V_DISPATCH(&entry->val)); *success = VARIANT_TRUE; return S_OK; } V_VT(&var) = VT_EMPTY; hres = builtin_propput(This, func, &dp, NULL); if(FAILED(hres)) return hres; *success = VARIANT_TRUE; return S_OK; } 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); IUnknown *unk; ITypeInfo *ti; dispex_data_t *data; UINT argerr=0; int min, max, n; HRESULT hres; TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller); if(This->data->vtbl && This->data->vtbl->invoke) { hres = This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei); if (hres != DISP_E_UNKNOWNNAME) return hres; } if(wFlags == DISPATCH_CONSTRUCT) { FIXME("DISPATCH_CONSTRUCT not implemented\n"); return E_NOTIMPL; } data = get_dispex_data(This); if(!data) return E_FAIL; min = 0; max = data->func_cnt-1; while(min <= max) { n = (min+max)/2; if(data->funcs[n].id == id) break; if(data->funcs[n].id < id) min = n+1; else max = n-1; } if(min > max) { WARN("invalid id %x\n", id); return DISP_E_UNKNOWNNAME; } hres = get_typeinfo(data->funcs[n].tid, &ti); if(FAILED(hres)) { ERR("Could not get type info: %08x\n", hres); return hres; } hres = IUnknown_QueryInterface(This->outer, get_riid_from_tid(data->funcs[n].tid), (void**)&unk); if(FAILED(hres)) { ERR("Could not get iface: %08x\n", hres); ITypeInfo_Release(ti); return E_FAIL; } if (is_propputref_id(id) && wFlags == DISPATCH_PROPERTYPUT) wFlags = DISPATCH_PROPERTYPUTREF; hres = ITypeInfo_Invoke(ti, unk, id, wFlags, pdp, pvarRes, pei, &argerr); ITypeInfo_Release(ti); IUnknown_Release(unk); return hres; }