Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
0
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;
}
Пример #11
0
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;
}
Пример #12
0
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);
}
Пример #13
0
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;
    }
}
Пример #14
0
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*/);
}
Пример #15
0
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);
}
Пример #16
0
/* 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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
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;
}
Пример #20
0
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;
}
Пример #21
0
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;
}
Пример #22
0
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;
}
Пример #23
0
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;
}