/* * call-seq: * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array. * * Returns the element of WIN32OLE_VARIANT object(OLE array). * This method is available only when the variant type of * WIN32OLE_VARIANT object is VT_ARRAY. * * REMARK: * The all indices should be 0 or natural number and * lower than or equal to max indices. * (This point is different with Ruby Array indices.) * * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]]) * p obj[0,0] # => 1 * p obj[1,0] # => 4 * p obj[2,0] # => WIN32OLERuntimeError * p obj[0, -1] # => WIN32OLERuntimeError * */ static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self) { struct olevariantdata *pvar; SAFEARRAY *psa; VALUE val = Qnil; VARIANT variant; LONG *pid; HRESULT hr; TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); if (!V_ISARRAY(&(pvar->var))) { rb_raise(eWIN32OLERuntimeError, "`[]' is not available for this variant type object"); } psa = get_locked_safe_array(self); if (psa == NULL) { return val; } pid = ary2safe_array_index(argc, argv, psa); VariantInit(&variant); V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF; hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant)); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex"); } val = ole_variant2val(&variant); unlock_safe_array(psa); if (pid) free(pid); return val; }
/* * call-seq: * WIN32OLE_VARIANT.value #=> Ruby object. * * Returns Ruby object value from OLE variant. * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR) * obj.value # => "1" (not Integer object, but String object "1") * */ static VALUE folevariant_value(VALUE self) { struct olevariantdata *pvar; VALUE val = Qnil; VARTYPE vt; int dim; SAFEARRAY *psa; TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar); val = ole_variant2val(&(pvar->var)); vt = V_VT(&(pvar->var)); if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) { if (vt & VT_BYREF) { psa = *V_ARRAYREF(&(pvar->var)); } else { psa = V_ARRAY(&(pvar->var)); } if (!psa) { return val; } dim = SafeArrayGetDim(psa); if (dim == 1) { val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*")); } } return val; }
static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index) { FUNCDESC *pFuncDesc; ELEMDESC *pElemDesc; PARAMDESCEX * pParamDescEx; HRESULT hr; USHORT wParamFlags; USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT; VALUE defval = Qnil; hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); if (FAILED(hr)) return defval; pElemDesc = &pFuncDesc->lprgelemdescParam[index]; wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags; if ((wParamFlags & mask) == mask) { pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex; defval = ole_variant2val(&pParamDescEx->varDefaultValue); } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); return defval; }
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; }