Exemple #1
0
/*
 *  call-seq:
 *     WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
 *
 *  Returns Ruby object wrapping OLE variant.
 *  The first argument specifies Ruby object to convert OLE variant variable.
 *  The second argument specifies VARIANT type.
 *  In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
 *
 *     shell = WIN32OLE.new("Shell.Application")
 *     folder = shell.NameSpace("C:\\Windows")
 *     item = folder.ParseName("tmp.txt")
 *     # You can't use Ruby String object to call FolderItem.InvokeVerb.
 *     # Instead, you have to use WIN32OLE_VARIANT object to call the method.
 *     shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
 *     item.invokeVerb(shortcut)
 *
 */
static VALUE
folevariant_initialize(VALUE self, VALUE args)
{
    int len = 0;
    VARIANT var;
    VALUE val;
    VALUE vvt;
    VARTYPE vt;
    struct olevariantdata *pvar;

    len = RARRAY_LEN(args);
    rb_check_arity(len, 1, 3);
    VariantInit(&var);
    val = rb_ary_entry(args, 0);

    check_type_val2variant(val);

    TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
    if (len == 1) {
        ole_val2variant(val, &(pvar->var));
    } else {
        vvt = rb_ary_entry(args, 1);
        vt = RB_NUM2INT(vvt);
        if ((vt & VT_TYPEMASK) == VT_RECORD) {
            rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE_VARIANT object");
        }
        ole_val2olevariantdata(val, vt, pvar);
    }
    return self;
}
Exemple #2
0
STDMETHODIMP EVENTSINK_Invoke(
    PEVENTSINK pEventSink,
    DISPID dispid,
    REFIID riid,
    LCID lcid,
    WORD wFlags,
    DISPPARAMS *pdispparams,
    VARIANT *pvarResult,
    EXCEPINFO *pexcepinfo,
    UINT *puArgErr
    ) {

    HRESULT hr;
    BSTR bstr;
    unsigned int count;
    unsigned int i;
    ITypeInfo *pTypeInfo;
    VARIANT *pvar;
    VALUE ary, obj, event, args, outargv, ev, result;
    VALUE handler = Qnil;
    VALUE arg[3];
    VALUE mid;
    VALUE is_outarg = Qfalse;
    BOOL is_default_handler = FALSE;
    int state;

    PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
    pTypeInfo = pEV->pTypeInfo;
    obj = evs_entry(pEV->m_event_id);
    if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
        return NOERROR;
    }

    ary = rb_ivar_get(obj, id_events);
    if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) {
        return NOERROR;
    }
    hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
                                     &bstr, 1, &count);
    if (FAILED(hr)) {
        return NOERROR;
    }
    ev = WC2VSTR(bstr);
    event = ole_search_event(ary, ev, &is_default_handler);
    if (RB_TYPE_P(event, T_ARRAY)) {
        handler = rb_ary_entry(event, 0);
        mid = rb_intern("call");
        is_outarg = rb_ary_entry(event, 3);
    } else {
        handler = rb_ivar_get(obj, rb_intern("handler"));
        if (handler == Qnil) {
            return NOERROR;
        }
        mid = ole_search_handler_method(handler, ev, &is_default_handler);
    }
    if (handler == Qnil || mid == Qnil) {
        return NOERROR;
    }

    args = rb_ary_new();
    if (is_default_handler) {
        rb_ary_push(args, ev);
    }

    /* make argument of event handler */
    for (i = 0; i < pdispparams->cArgs; ++i) {
        pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
        rb_ary_push(args, ole_variant2val(pvar));
    }
    outargv = Qnil;
    if (is_outarg == Qtrue) {
	outargv = rb_ary_new();
        rb_ary_push(args, outargv);
    }

    /*
     * if exception raised in event callback,
     * then you receive cfp consistency error.
     * to avoid this error we use begin rescue end.
     * and the exception raised then error message print
     * and exit ruby process by Win32OLE itself.
     */
    arg[0] = handler;
    arg[1] = mid;
    arg[2] = args;
    result = rb_protect(exec_callback, (VALUE)arg, &state);
    if (state != 0) {
        rescue_callback(Qnil);
    }
    if(RB_TYPE_P(result, T_HASH)) {
        hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
        result = hash2result(result);
    }else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) {
        ary2ptr_dispparams(outargv, pdispparams);
    }

    if (pvarResult) {
        VariantInit(pvarResult);
        ole_val2variant(result, pvarResult);
    }

    return NOERROR;
}