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 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 function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { func_disp_t *This = impl_from_DispatchEx(dispex); HRESULT hres; switch(flags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!res) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: if(!This->obj) return E_UNEXPECTED; hres = typeinfo_invoke(This->obj, This->info, flags, params, res, ei); break; case DISPATCH_PROPERTYGET: { unsigned name_len; WCHAR *ptr; BSTR str; static const WCHAR func_prefixW[] = {'\n','f','u','n','c','t','i','o','n',' '}; static const WCHAR func_suffixW[] = {'(',')',' ','{','\n',' ',' ',' ',' ','[','n','a','t','i','v','e',' ','c','o','d','e',']','\n','}','\n'}; /* FIXME: This probably should be more generic. Also we should try to get IID_IActiveScriptSite and SID_GetCaller. */ if(!caller) return E_ACCESSDENIED; name_len = SysStringLen(This->info->name); ptr = str = SysAllocStringLen(NULL, name_len + (sizeof(func_prefixW)+sizeof(func_suffixW))/sizeof(WCHAR)); if(!str) return E_OUTOFMEMORY; memcpy(ptr, func_prefixW, sizeof(func_prefixW)); ptr += sizeof(func_prefixW)/sizeof(WCHAR); memcpy(ptr, This->info->name, name_len*sizeof(WCHAR)); ptr += name_len; memcpy(ptr, func_suffixW, sizeof(func_suffixW)); V_VT(res) = VT_BSTR; V_BSTR(res) = str; return S_OK; } default: FIXME("Unimplemented flags %x\n", flags); hres = E_NOTIMPL; } return hres; }
static HRESULT function_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { func_disp_t *This = impl_from_DispatchEx(dispex); HRESULT hres; switch(flags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!res) return E_INVALIDARG; 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; }
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 function_invoke(DispatchEx *This, func_info_t *func, WORD flags, DISPPARAMS *dp, VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller) { HRESULT hres; switch(flags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: if(!res) return E_INVALIDARG; /* fall through */ case DISPATCH_METHOD: if(This->dynamic_data && This->dynamic_data->func_disps && This->dynamic_data->func_disps[func->func_disp_idx].func_obj) { func_obj_entry_t *entry = This->dynamic_data->func_disps + func->func_disp_idx; if(V_VT(&entry->val) != VT_DISPATCH) { FIXME("calling %s not supported\n", debugstr_variant(&entry->val)); return E_NOTIMPL; } if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != V_DISPATCH(&entry->val)) { if(!V_DISPATCH(&entry->val)) { FIXME("Calling null\n"); return E_FAIL; } hres = invoke_disp_value(This, V_DISPATCH(&entry->val), 0, flags, dp, res, ei, NULL); break; } } if(func->call_vtbl_off) hres = invoke_builtin_function(This, func, dp, res, caller); else hres = typeinfo_invoke(This, func, flags, dp, res, ei); break; case DISPATCH_PROPERTYGET: { func_obj_entry_t *entry; 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; } hres = get_func_obj_entry(This, func, &entry); if(FAILED(hres)) return hres; V_VT(res) = VT_EMPTY; return VariantCopy(res, &entry->val); } case DISPATCH_PROPERTYPUT: { func_obj_entry_t *entry; if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || dp->cNamedArgs > 1) { FIXME("invalid args\n"); return E_INVALIDARG; } /* * NOTE: Although we have IDispatchEx tests showing, that it's not allowed to set * function property using InvokeEx, it's possible to do that from jscript. * Native probably uses some undocumented interface in this case, but it should * be fine for us to allow IDispatchEx handle that. */ hres = get_func_obj_entry(This, func, &entry); if(FAILED(hres)) return hres; return VariantCopy(&entry->val, dp->rgvarg); } default: FIXME("Unimplemented flags %x\n", flags); hres = E_NOTIMPL; } return hres; }
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: if(This->dynamic_data && This->dynamic_data->func_disps && This->dynamic_data->func_disps[func->func_disp_idx].func_obj) { func_obj_entry_t *entry = This->dynamic_data->func_disps + func->func_disp_idx; if((IDispatch*)&entry->func_obj->dispex.IDispatchEx_iface != entry->val) { if(!entry->val) { FIXME("Calling null\n"); return E_FAIL; } hres = invoke_disp_value(This, entry->val, 0, flags, dp, res, ei, NULL); break; } } hres = typeinfo_invoke(This, func, flags, dp, res, ei); break; case DISPATCH_PROPERTYGET: { func_obj_entry_t *entry; 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; } hres = get_func_obj_entry(This, func, &entry); if(FAILED(hres)) return hres; V_VT(res) = VT_DISPATCH; V_DISPATCH(res) = entry->val; if(V_DISPATCH(res)) IDispatch_AddRef(V_DISPATCH(res)); hres = S_OK; break; } case DISPATCH_PROPERTYPUT: { func_obj_entry_t *entry; VARIANT *v; if(dp->cArgs != 1 || (dp->cNamedArgs == 1 && *dp->rgdispidNamedArgs != DISPID_PROPERTYPUT) || dp->cNamedArgs > 1) { FIXME("invalid args\n"); return E_INVALIDARG; } v = dp->rgvarg; /* FIXME: not exactly right */ if(V_VT(v) != VT_DISPATCH) return E_NOTIMPL; hres = get_func_obj_entry(This, func, &entry); if(FAILED(hres)) return hres; if(entry->val) IDispatch_Release(entry->val); entry->val = V_DISPATCH(v); if(entry->val) IDispatch_AddRef(entry->val); hres = S_OK; break; } default: FIXME("Unimplemented flags %x\n", flags); hres = E_NOTIMPL; } return hres; }