static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid, void **ppv) { DispatchEx *This = DISPATCHEX_THIS(iface); if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); *ppv = _IDispatchEx_(This); }else if(IsEqualGUID(&IID_IDispatch, riid)) { TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv); *ppv = _IDispatchEx_(This); }else if(IsEqualGUID(&IID_IDispatchEx, riid)) { TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv); *ppv = _IDispatchEx_(This); }else if(IsEqualGUID(&IID_IDispatchJS, riid)) { TRACE("(%p)->(IID_IDispatchJS %p)\n", This, ppv); IUnknown_AddRef(_IDispatchEx_(This)); *ppv = This; return S_OK; }else { WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); *ppv = NULL; return E_NOINTERFACE; } IUnknown_AddRef((IUnknown*)*ppv); return S_OK; }
static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { DispatchEx *this_obj; VARIANT var; HRESULT hres; hres = create_object(ctx, &function->dispex, &this_obj); if(FAILED(hres)) return hres; hres = invoke_source(ctx, function, (IDispatch*)_IDispatchEx_(this_obj), dp, &var, ei, caller); if(FAILED(hres)) { jsdisp_release(this_obj); return hres; } V_VT(retv) = VT_DISPATCH; if(V_VT(&var) == VT_DISPATCH) { jsdisp_release(this_obj); V_DISPATCH(retv) = V_DISPATCH(&var); }else { VariantClear(&var); V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj); } return S_OK; }
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret) { DispatchEx *var_disp, *arg_disp; HRESULT hres; static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0}; hres = create_dispex(ctx, NULL, NULL, &var_disp); if(FAILED(hres)) return hres; hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex), dp, ei, caller, &arg_disp); if(SUCCEEDED(hres)) { VARIANT var; V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp); hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller); jsdisp_release(arg_disp); } if(SUCCEEDED(hres)) hres = init_parameters(var_disp, function, dp, ei, caller); if(FAILED(hres)) { jsdisp_release(var_disp); return hres; } *ret = var_disp; return S_OK; }
static HRESULT constructor_call(DispatchEx *constr, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { if(flags != DISPATCH_PROPERTYGET) return jsdisp_call_value(constr, flags, dp, retv, ei, sp); V_VT(retv) = VT_DISPATCH; V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(constr); IDispatchEx_AddRef(_IDispatchEx_(constr)); return S_OK; }
HRESULT init_dispex(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *prototype) { TRACE("%p (%p)\n", dispex, prototype); dispex->lpIDispatchExVtbl = &DispatchExVtbl; dispex->ref = 1; dispex->builtin_info = builtin_info; dispex->props = heap_alloc((dispex->buf_size=4) * sizeof(dispex_prop_t)); if(!dispex->props) return E_OUTOFMEMORY; dispex->prototype = prototype; if(prototype) IDispatchEx_AddRef(_IDispatchEx_(prototype)); dispex->prop_cnt = 1; dispex->props[0].name = NULL; dispex->props[0].flags = 0; if(builtin_info->value_prop.invoke) { dispex->props[0].type = PROP_BUILTIN; dispex->props[0].u.p = &builtin_info->value_prop; }else { dispex->props[0].type = PROP_DELETED; } script_addref(ctx); dispex->ctx = ctx; return S_OK; }
HRESULT init_dispex_from_constr(DispatchEx *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, DispatchEx *constr) { DispatchEx *prot = NULL; dispex_prop_t *prop; HRESULT hres; static const WCHAR prototypeW[] = {'p','r','o','t','o','t','y','p','e',0}; hres = find_prop_name_prot(constr, prototypeW, FALSE, &prop); if(SUCCEEDED(hres) && prop) { jsexcept_t jsexcept; VARIANT var; V_VT(&var) = VT_EMPTY; memset(&jsexcept, 0, sizeof(jsexcept)); hres = prop_get(constr, prop, ctx->lcid, NULL, &var, &jsexcept, NULL/*FIXME*/); if(FAILED(hres)) { ERR("Could not get prototype\n"); return hres; } if(V_VT(&var) == VT_DISPATCH) prot = iface_to_jsdisp((IUnknown*)V_DISPATCH(&var)); VariantClear(&var); } hres = init_dispex(dispex, ctx, builtin_info, prot); if(prot) IDispatchEx_Release(_IDispatchEx_(prot)); return hres; }
HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) { DISPID dispid = DISPID_PROPERTYPUT; DISPPARAMS dp = {val, &dispid, 1, 1}; IDispatchEx *dispex; DispatchEx *jsdisp; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { dispex_prop_t *prop; prop = get_prop(jsdisp, id); if(prop) hres = prop_put(jsdisp, prop, lcid, &dp, ei, caller); else hres = DISP_E_MEMBERNOTFOUND; IDispatchEx_Release(_IDispatchEx_(jsdisp)); return hres; } hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(FAILED(hres)) { ULONG err = 0; TRACE("using IDispatch\n"); return IDispatch_Invoke(disp, id, &IID_NULL, DISPATCH_PROPERTYPUT, lcid, &dp, NULL, &ei->ei, &err); } hres = IDispatchEx_InvokeEx(dispex, id, lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, caller); IDispatchEx_Release(dispex); return hres; }
static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptParseProcedure2 *iface, LPCOLESTR pstrCode, LPCOLESTR pstrFormalParams, LPCOLESTR pstrProcedureName, LPCOLESTR pstrItemName, IUnknown *punkContext, LPCOLESTR pstrDelimiter, CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) { JScript *This = ASPARSEPROC_THIS(iface); parser_ctx_t *parser_ctx; DispatchEx *dispex; HRESULT hres; TRACE("(%p)->(%s %s %s %s %p %s %s %u %x %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrFormalParams), debugstr_w(pstrProcedureName), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter), wine_dbgstr_longlong(dwSourceContextCookie), ulStartingLineNumber, dwFlags, ppdisp); if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED; hres = script_parse(This->ctx, pstrCode, pstrDelimiter, &parser_ctx); if(FAILED(hres)) { WARN("Parse failed %08x\n", hres); return hres; } hres = create_source_function(parser_ctx, NULL, parser_ctx->source, NULL, NULL, 0, &dispex); parser_release(parser_ctx); if(FAILED(hres)) return hres; *ppdisp = (IDispatch*)_IDispatchEx_(dispex); return S_OK; }
static HRESULT throw_error(script_ctx_t *ctx, jsexcept_t *ei, UINT id, const WCHAR *str, DispatchEx *constr) { WCHAR buf[1024], *pos = NULL; DispatchEx *err; HRESULT hres; buf[0] = '\0'; LoadStringW(jscript_hinstance, id&0xFFFF, buf, sizeof(buf)/sizeof(WCHAR)); if(str) pos = strchrW(buf, '|'); if(pos) { int len = strlenW(str); memmove(pos+len, pos+1, (strlenW(pos+1)+1)*sizeof(WCHAR)); memcpy(pos, str, len*sizeof(WCHAR)); } WARN("%s\n", debugstr_w(buf)); id |= JSCRIPT_ERROR; hres = create_error(ctx, constr, &id, buf, &err); if(FAILED(hres)) return hres; if(!ei) return id; V_VT(&ei->var) = VT_DISPATCH; V_DISPATCH(&ei->var) = (IDispatch*)_IDispatchEx_(err); return id; }
HRESULT disp_propget(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexcept_t *ei, IServiceProvider *caller) { DISPPARAMS dp = {NULL,NULL,0,0}; IDispatchEx *dispex; DispatchEx *jsdisp; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { hres = jsdisp_propget(jsdisp, id, lcid, val, ei, caller); IDispatchEx_Release(_IDispatchEx_(jsdisp)); return hres; } hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(FAILED(hres)) { ULONG err = 0; TRACE("using IDispatch\n"); return IDispatch_Invoke(disp, id, &IID_NULL, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err); } hres = IDispatchEx_InvokeEx(dispex, id, lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, caller); IDispatchEx_Release(dispex); return hres; }
static HRESULT invoke_constructor(FunctionInstance *function, LCID lcid, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { DispatchEx *this_obj; HRESULT hres; hres = create_object(function->dispex.ctx, &function->dispex, &this_obj); if(FAILED(hres)) return hres; hres = invoke_source(function, (IDispatch*)_IDispatchEx_(this_obj), lcid, dp, retv, ei, caller); jsdisp_release(this_obj); if(FAILED(hres)) return hres; V_VT(retv) = VT_DISPATCH; V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(this_obj); return S_OK; }
static HRESULT invoke_function(FunctionInstance *function, LCID lcid, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { IDispatch *this_obj; if(!(this_obj = get_this(dp))) this_obj = (IDispatch*)_IDispatchEx_(function->dispex.ctx->script_disp); return invoke_source(function, this_obj, lcid, dp, retv, ei, caller); }
static HRESULT error_constr(script_ctx_t *ctx, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, DispatchEx *constr) { DispatchEx *err; VARIANT numv; UINT num; BSTR msg = NULL; HRESULT hres; V_VT(&numv) = VT_NULL; if(arg_cnt(dp)) { hres = to_number(ctx, get_arg(dp, 0), ei, &numv); if(FAILED(hres) || (V_VT(&numv)==VT_R8 && isnan(V_R8(&numv)))) hres = to_string(ctx, get_arg(dp, 0), ei, &msg); else if(V_VT(&numv) == VT_I4) num = V_I4(&numv); else num = V_R8(&numv); if(FAILED(hres)) return hres; } if(arg_cnt(dp)>1 && !msg) { hres = to_string(ctx, get_arg(dp, 1), ei, &msg); if(FAILED(hres)) return hres; } switch(flags) { case INVOKE_FUNC: case DISPATCH_CONSTRUCT: if(V_VT(&numv) == VT_NULL) hres = create_error(ctx, constr, NULL, msg, &err); else hres = create_error(ctx, constr, &num, msg, &err); SysFreeString(msg); if(FAILED(hres)) return hres; if(retv) { V_VT(retv) = VT_DISPATCH; V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(err); } else jsdisp_release(err); return S_OK; default: FIXME("unimplemented flags %x\n", flags); return E_NOTIMPL; } }
static HRESULT set_prototype(script_ctx_t *ctx, DispatchEx *dispex, DispatchEx *prototype) { jsexcept_t jsexcept; VARIANT var; V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype); memset(&jsexcept, 0, sizeof(jsexcept)); return jsdisp_propput_name(dispex, prototypeW, &var, &jsexcept, NULL/*FIXME*/); }
static HRESULT WINAPI DispatchEx_Invoke(IDispatchEx *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) { DispatchEx *This = DISPATCHEX_THIS(iface); TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid), lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); return IDispatchEx_InvokeEx(_IDispatchEx_(This), dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, NULL); }
/* ECMA-262 3rd Edition 9.9 */ HRESULT to_object(exec_ctx_t *ctx, VARIANT *v, IDispatch **disp) { DispatchEx *dispex; HRESULT hres; switch(V_VT(v)) { case VT_BSTR: hres = create_string(ctx->parser->script, V_BSTR(v), SysStringLen(V_BSTR(v)), &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; case VT_I4: case VT_R8: hres = create_number(ctx->parser->script, v, &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; case VT_DISPATCH: IDispatch_AddRef(V_DISPATCH(v)); *disp = V_DISPATCH(v); break; case VT_BOOL: hres = create_bool(ctx->parser->script, V_BOOL(v), &dispex); if(FAILED(hres)) return hres; *disp = (IDispatch*)_IDispatchEx_(dispex); break; default: FIXME("unsupported vt %d\n", V_VT(v)); return E_NOTIMPL; } return S_OK; }
static HRESULT create_function(script_ctx_t *ctx, DWORD flags, BOOL funcprot, DispatchEx *prototype, FunctionInstance **ret) { FunctionInstance *function; HRESULT hres; function = heap_alloc_zero(sizeof(FunctionInstance)); if(!function) return E_OUTOFMEMORY; if(funcprot) hres = init_dispex(&function->dispex, ctx, &Function_info, prototype); else hres = init_dispex_from_constr(&function->dispex, ctx, &Function_info, ctx->function_constr); if(FAILED(hres)) return hres; function->flags = flags; function->length = flags & PROPF_ARGMASK; if(prototype) { jsexcept_t jsexcept; VARIANT var; V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(prototype); memset(&jsexcept, 0, sizeof(jsexcept)); hres = jsdisp_propput_name(&function->dispex, prototypeW, ctx->lcid, &var, &jsexcept, NULL/*FIXME*/); if(FAILED(hres)) { IDispatchEx_Release(_IDispatchEx_(&function->dispex)); return hres; } } *ret = function; return S_OK; }
static HRESULT invoke_prop_func(DispatchEx *This, DispatchEx *jsthis, dispex_prop_t *prop, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { HRESULT hres; switch(prop->type) { case PROP_BUILTIN: if(flags == DISPATCH_CONSTRUCT && (prop->flags & DISPATCH_METHOD)) { WARN("%s is not a constructor\n", debugstr_w(prop->name)); return E_INVALIDARG; } return prop->u.p->invoke(jsthis, lcid, flags, dp, retv, ei, caller); case PROP_PROTREF: return invoke_prop_func(This->prototype, jsthis, This->prototype->props+prop->u.ref, lcid, flags, dp, retv, ei, caller); case PROP_VARIANT: { DISPPARAMS new_dp; if(V_VT(&prop->u.var) != VT_DISPATCH) { FIXME("invoke vt %d\n", V_VT(&prop->u.var)); return E_FAIL; } TRACE("call %s %p\n", debugstr_w(prop->name), V_DISPATCH(&prop->u.var)); hres = set_this(&new_dp, dp, (IDispatch*)_IDispatchEx_(jsthis)); if(FAILED(hres)) return hres; hres = disp_call(V_DISPATCH(&prop->u.var), DISPID_VALUE, lcid, flags, &new_dp, retv, ei, caller); if(new_dp.rgvarg != dp->rgvarg) { heap_free(new_dp.rgvarg); if(new_dp.cNamedArgs > 1) heap_free(new_dp.rgdispidNamedArgs); } return hres; } default: ERR("type %d\n", prop->type); } return E_FAIL; }
static HRESULT WINAPI DispatchEx_GetIDsOfNames(IDispatchEx *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) { DispatchEx *This = DISPATCHEX_THIS(iface); UINT i; HRESULT hres; TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId); for(i=0; i < cNames; i++) { hres = IDispatchEx_GetDispID(_IDispatchEx_(This), rgszNames[i], 0, rgDispId+i); if(FAILED(hres)) return hres; } return S_OK; }
static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR pstrItemName, IDispatch **ppdisp) { JScript *This = ACTSCRIPT_THIS(iface); TRACE("(%p)->(%p)\n", This, ppdisp); if(!ppdisp) return E_POINTER; if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) { *ppdisp = NULL; return E_UNEXPECTED; } *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global); IDispatch_AddRef(*ppdisp); return S_OK; }
static HRESULT prop_get(DispatchEx *This, dispex_prop_t *prop, LCID lcid, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { HRESULT hres; switch(prop->type) { case PROP_BUILTIN: if(prop->u.p->flags & PROPF_METHOD) { DispatchEx *obj; hres = create_builtin_function(This->ctx, prop->u.p->invoke, prop->u.p->flags, NULL, &obj); if(FAILED(hres)) break; prop->type = PROP_VARIANT; V_VT(&prop->u.var) = VT_DISPATCH; V_DISPATCH(&prop->u.var) = (IDispatch*)_IDispatchEx_(obj); hres = VariantCopy(retv, &prop->u.var); }else { hres = prop->u.p->invoke(This, lcid, DISPATCH_PROPERTYGET, dp, retv, ei, caller); } break; case PROP_PROTREF: hres = prop_get(This->prototype, This->prototype->props+prop->u.ref, lcid, dp, retv, ei, caller); break; case PROP_VARIANT: hres = VariantCopy(retv, &prop->u.var); break; default: ERR("type %d\n", prop->type); return E_FAIL; } if(FAILED(hres)) { TRACE("fail %08x\n", hres); return hres; } TRACE("%s ret %s\n", debugstr_w(prop->name), debugstr_variant(retv)); return hres; }
HRESULT disp_call(IDispatch *disp, DISPID id, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller) { DispatchEx *jsdisp; IDispatchEx *dispex; HRESULT hres; jsdisp = iface_to_jsdisp((IUnknown*)disp); if(jsdisp) { hres = jsdisp_call(jsdisp, id, lcid, flags, dp, retv, ei, caller); IDispatchEx_Release(_IDispatchEx_(jsdisp)); return hres; } memset(ei, 0, sizeof(*ei)); if(retv) V_VT(retv) = VT_EMPTY; hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex); if(FAILED(hres)) { UINT err = 0; if(flags == DISPATCH_CONSTRUCT) { WARN("IDispatch cannot be constructor\n"); return DISP_E_MEMBERNOTFOUND; } TRACE("using IDispatch\n"); return IDispatch_Invoke(disp, id, &IID_NULL, lcid, flags, dp, retv, &ei->ei, &err); } hres = IDispatchEx_InvokeEx(dispex, id, lcid, flags, dp, retv, &ei->ei, caller); IDispatchEx_Release(dispex); return hres; }
static HRESULT construct_function(script_ctx_t *ctx, DISPPARAMS *dp, jsexcept_t *ei, IDispatch **ret) { function_expression_t *expr; WCHAR *str = NULL, *ptr; DWORD argc, len = 0, l; parser_ctx_t *parser; DispatchEx *function; BSTR *params = NULL; int i=0, j=0; HRESULT hres = S_OK; static const WCHAR function_anonymousW[] = {'f','u','n','c','t','i','o','n',' ','a','n','o','n','y','m','o','u','s','('}; static const WCHAR function_beginW[] = {')',' ','{','\n'}; static const WCHAR function_endW[] = {'\n','}',0}; argc = arg_cnt(dp); if(argc) { params = heap_alloc(argc*sizeof(BSTR)); if(!params) return E_OUTOFMEMORY; if(argc > 2) len = (argc-2)*2; /* separating commas */ for(i=0; i < argc; i++) { hres = to_string(ctx, get_arg(dp,i), ei, params+i); if(FAILED(hres)) break; len += SysStringLen(params[i]); } } if(SUCCEEDED(hres)) { len += (sizeof(function_anonymousW) + sizeof(function_beginW) + sizeof(function_endW)) / sizeof(WCHAR); str = heap_alloc(len*sizeof(WCHAR)); if(str) { memcpy(str, function_anonymousW, sizeof(function_anonymousW)); ptr = str + sizeof(function_anonymousW)/sizeof(WCHAR); if(argc > 1) { while(1) { l = SysStringLen(params[j]); memcpy(ptr, params[j], l*sizeof(WCHAR)); ptr += l; if(++j == argc-1) break; *ptr++ = ','; *ptr++ = ' '; } } memcpy(ptr, function_beginW, sizeof(function_beginW)); ptr += sizeof(function_beginW)/sizeof(WCHAR); if(argc) { l = SysStringLen(params[argc-1]); memcpy(ptr, params[argc-1], l*sizeof(WCHAR)); ptr += l; } memcpy(ptr, function_endW, sizeof(function_endW)); TRACE("%s\n", debugstr_w(str)); }else { hres = E_OUTOFMEMORY; } } while(--i >= 0) SysFreeString(params[i]); heap_free(params); if(FAILED(hres)) return hres; hres = script_parse(ctx, str, NULL, &parser); heap_free(str); if(FAILED(hres)) return hres; if(!parser->source || !parser->source->functions || parser->source->functions->next || parser->source->variables) { ERR("Invalid parser result!\n"); parser_release(parser); return E_UNEXPECTED; } expr = parser->source->functions->expr; hres = create_source_function(parser, expr->parameter_list, expr->source_elements, NULL, expr->src_str, expr->src_len, &function); parser_release(parser); if(FAILED(hres)) return hres; *ret = (IDispatch*)_IDispatchEx_(function); return S_OK; }