mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* ext/win32ole/win32ole.c: seperate WIN32OLE_VARIANT src from
win32ole.c. * ext/win32ole/win32ole.h: ditto. * ext/win32ole/win32ole_variant.c: ditto. * ext/win32ole/win32ole_variant.c: ditto. * ext/win32ole/depend: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47172 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
02c86ce1ee
commit
51b4ccd618
6 changed files with 787 additions and 758 deletions
|
@ -1,3 +1,12 @@
|
||||||
|
Wed Aug 13 21:41:04 2014 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
||||||
|
|
||||||
|
* ext/win32ole/win32ole.c: seperate WIN32OLE_VARIANT src from
|
||||||
|
win32ole.c.
|
||||||
|
* ext/win32ole/win32ole.h: ditto.
|
||||||
|
* ext/win32ole/win32ole_variant.c: ditto.
|
||||||
|
* ext/win32ole/win32ole_variant.c: ditto.
|
||||||
|
* ext/win32ole/depend: ditto.
|
||||||
|
|
||||||
Wed Aug 13 20:09:37 2014 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
Wed Aug 13 20:09:37 2014 Masaki Suketa <masaki.suketa@nifty.ne.jp>
|
||||||
|
|
||||||
* ext/win32ole/win32ole.c: remove unused variable.
|
* ext/win32ole/win32ole.c: remove unused variable.
|
||||||
|
|
|
@ -6,4 +6,5 @@ win32ole_type.o : win32ole_type.c $(WIN32OLE_HEADERS)
|
||||||
win32ole_variable.o : win32ole_variable.c $(WIN32OLE_HEADERS)
|
win32ole_variable.o : win32ole_variable.c $(WIN32OLE_HEADERS)
|
||||||
win32ole_method.o : win32ole_method.c $(WIN32OLE_HEADERS)
|
win32ole_method.o : win32ole_method.c $(WIN32OLE_HEADERS)
|
||||||
win32ole_param.o : win32ole_param.c $(WIN32OLE_HEADERS)
|
win32ole_param.o : win32ole_param.c $(WIN32OLE_HEADERS)
|
||||||
|
win32ole_variant.o : win32ole_variant.c $(WIN32OLE_HEADERS)
|
||||||
win32ole_error.o : win32ole_error.c $(WIN32OLE_HEADERS)
|
win32ole_error.o : win32ole_error.c $(WIN32OLE_HEADERS)
|
||||||
|
|
|
@ -33,17 +33,6 @@ const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00,
|
||||||
}\
|
}\
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LONG_LONG
|
|
||||||
#define I8_2_NUM LL2NUM
|
|
||||||
#define UI8_2_NUM ULL2NUM
|
|
||||||
#define NUM2I8 NUM2LL
|
|
||||||
#define NUM2UI8 NUM2ULL
|
|
||||||
#else
|
|
||||||
#define I8_2_NUM INT2NUM
|
|
||||||
#define UI8_2_NUM UINT2NUM
|
|
||||||
#define NUM2I8 NUM2INT
|
|
||||||
#define NUM2UI8 NUM2UINT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WIN32OLE_VERSION "1.7.7"
|
#define WIN32OLE_VERSION "1.7.7"
|
||||||
|
|
||||||
|
@ -104,11 +93,11 @@ typedef struct tagIEVENTSINKOBJ {
|
||||||
|
|
||||||
VALUE cWIN32OLE;
|
VALUE cWIN32OLE;
|
||||||
VALUE cWIN32OLE_EVENT;
|
VALUE cWIN32OLE_EVENT;
|
||||||
VALUE cWIN32OLE_VARIANT;
|
|
||||||
VALUE cWIN32OLE_RECORD;
|
VALUE cWIN32OLE_RECORD;
|
||||||
|
|
||||||
static VALUE ary_ole_event;
|
static VALUE ary_ole_event;
|
||||||
static ID id_events;
|
static ID id_events;
|
||||||
|
|
||||||
#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__))
|
#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__) || defined(__MINGW32__))
|
||||||
static RB_THREAD_SPECIFIC BOOL g_ole_initialized;
|
static RB_THREAD_SPECIFIC BOOL g_ole_initialized;
|
||||||
# define g_ole_initialized_init() ((void)0)
|
# define g_ole_initialized_init() ((void)0)
|
||||||
|
@ -162,11 +151,6 @@ struct oleparam {
|
||||||
OLECHAR** pNamedArgs;
|
OLECHAR** pNamedArgs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct olevariantdata {
|
|
||||||
VARIANT realvar;
|
|
||||||
VARIANT var;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct olerecorddata {
|
struct olerecorddata {
|
||||||
IRecordInfo *pri;
|
IRecordInfo *pri;
|
||||||
void *pdata;
|
void *pdata;
|
||||||
|
@ -196,20 +180,14 @@ static void ole_msg_loop(void);
|
||||||
static void ole_free(struct oledata *pole);
|
static void ole_free(struct oledata *pole);
|
||||||
static LPWSTR ole_mb2wc(char *pm, int len);
|
static LPWSTR ole_mb2wc(char *pm, int len);
|
||||||
static VALUE ole_ary_m_entry(VALUE val, LONG *pid);
|
static VALUE ole_ary_m_entry(VALUE val, LONG *pid);
|
||||||
static void * get_ptr_of_variant(VARIANT *pvar);
|
|
||||||
static VALUE is_all_index_under(LONG *pid, long *pub, long dim);
|
static VALUE is_all_index_under(LONG *pid, long *pub, long dim);
|
||||||
|
static void * get_ptr_of_variant(VARIANT *pvar);
|
||||||
static void ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt);
|
static void ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt);
|
||||||
static long dimension(VALUE val);
|
static long dimension(VALUE val);
|
||||||
static long ary_len_of_dim(VALUE ary, long dim);
|
static long ary_len_of_dim(VALUE ary, long dim);
|
||||||
static HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
|
|
||||||
static int hash2olerec(VALUE key, VALUE val, VALUE rec);
|
static int hash2olerec(VALUE key, VALUE val, VALUE rec);
|
||||||
static void ole_rec2variant(VALUE rec, VARIANT *var);
|
static void ole_rec2variant(VALUE rec, VARIANT *var);
|
||||||
static void ole_val2variant(VALUE val, VARIANT *var);
|
|
||||||
static void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
|
|
||||||
static void ole_val2ptr_variant(VALUE val, VARIANT *var);
|
static void ole_val2ptr_variant(VALUE val, VARIANT *var);
|
||||||
static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
|
|
||||||
static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
|
|
||||||
static void ole_val2variant2(VALUE val, VARIANT *var);
|
|
||||||
static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
|
static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
|
||||||
static VALUE fole_s_allocate(VALUE klass);
|
static VALUE fole_s_allocate(VALUE klass);
|
||||||
static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
|
static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
|
||||||
|
@ -301,20 +279,7 @@ static VALUE evs_push(VALUE ev);
|
||||||
static VALUE evs_delete(long i);
|
static VALUE evs_delete(long i);
|
||||||
static VALUE evs_entry(long i);
|
static VALUE evs_entry(long i);
|
||||||
static VALUE evs_length(void);
|
static VALUE evs_length(void);
|
||||||
static void olevariant_free(struct olevariantdata *pvar);
|
|
||||||
static VALUE folevariant_s_allocate(VALUE klass);
|
|
||||||
static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
|
|
||||||
static void check_type_val2variant(VALUE val);
|
|
||||||
static VALUE folevariant_initialize(VALUE self, VALUE args);
|
|
||||||
static LONG *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
|
|
||||||
static void unlock_safe_array(SAFEARRAY *psa);
|
|
||||||
static SAFEARRAY *get_locked_safe_array(VALUE val);
|
|
||||||
static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
|
|
||||||
static VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
|
|
||||||
static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
|
|
||||||
static VALUE folevariant_value(VALUE self);
|
|
||||||
static VALUE folevariant_vartype(VALUE self);
|
|
||||||
static VALUE folevariant_set_value(VALUE self, VALUE val);
|
|
||||||
static HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
|
static HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
|
||||||
static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
|
static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
|
||||||
static void olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec);
|
static void olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec);
|
||||||
|
@ -1075,6 +1040,77 @@ ole_ary_m_entry(VALUE val, LONG *pid)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
is_all_index_under(LONG *pid, long *pub, long dim)
|
||||||
|
{
|
||||||
|
long i = 0;
|
||||||
|
for (i = 0; i < dim; i++) {
|
||||||
|
if (pid[i] > pub[i]) {
|
||||||
|
return Qfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Qtrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
|
||||||
|
{
|
||||||
|
if (val == Qnil) {
|
||||||
|
if (vt == VT_VARIANT) {
|
||||||
|
ole_val2variant2(val, var);
|
||||||
|
} else {
|
||||||
|
V_VT(var) = (vt & ~VT_BYREF);
|
||||||
|
if (V_VT(var) == VT_DISPATCH) {
|
||||||
|
V_DISPATCH(var) = NULL;
|
||||||
|
} else if (V_VT(var) == VT_UNKNOWN) {
|
||||||
|
V_UNKNOWN(var) = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||||
|
switch(vt & ~VT_BYREF) {
|
||||||
|
case VT_I8:
|
||||||
|
V_VT(var) = VT_I8;
|
||||||
|
V_I8(var) = NUM2I8 (val);
|
||||||
|
break;
|
||||||
|
case VT_UI8:
|
||||||
|
V_VT(var) = VT_UI8;
|
||||||
|
V_UI8(var) = NUM2UI8(val);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ole_val2variant2(val, var);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
|
||||||
|
ole_val2variant2(val, var);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID *
|
||||||
|
val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
|
||||||
|
{
|
||||||
|
VOID *p = NULL;
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
ole_val2variant_ex(val, var, vt);
|
||||||
|
if ((vt & ~VT_BYREF) == VT_VARIANT) {
|
||||||
|
p = var;
|
||||||
|
} else {
|
||||||
|
if ( (vt & ~VT_BYREF) != V_VT(var)) {
|
||||||
|
hr = VariantChangeTypeEx(var, var,
|
||||||
|
cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ole_raise(hr, rb_eRuntimeError, "failed to change type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = get_ptr_of_variant(var);
|
||||||
|
}
|
||||||
|
if (p == NULL) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static void *
|
static void *
|
||||||
get_ptr_of_variant(VARIANT *pvar)
|
get_ptr_of_variant(VARIANT *pvar)
|
||||||
{
|
{
|
||||||
|
@ -1144,18 +1180,6 @@ get_ptr_of_variant(VARIANT *pvar)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
|
||||||
is_all_index_under(LONG *pid, long *pub, long dim)
|
|
||||||
{
|
|
||||||
long i = 0;
|
|
||||||
for (i = 0; i < dim; i++) {
|
|
||||||
if (pid[i] > pub[i]) {
|
|
||||||
return Qfalse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Qtrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt)
|
ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt)
|
||||||
{
|
{
|
||||||
|
@ -1233,7 +1257,7 @@ ary_len_of_dim(VALUE ary, long dim) {
|
||||||
return ary_len;
|
return ary_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT
|
HRESULT
|
||||||
ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
|
ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
|
||||||
{
|
{
|
||||||
long dim = 0;
|
long dim = 0;
|
||||||
|
@ -1356,7 +1380,7 @@ ole_rec2variant(VALUE rec, VARIANT *var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
ole_val2variant(VALUE val, VARIANT *var)
|
ole_val2variant(VALUE val, VARIANT *var)
|
||||||
{
|
{
|
||||||
struct oledata *pole;
|
struct oledata *pole;
|
||||||
|
@ -1425,41 +1449,6 @@ ole_val2variant(VALUE val, VARIANT *var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
|
|
||||||
{
|
|
||||||
if (val == Qnil) {
|
|
||||||
if (vt == VT_VARIANT) {
|
|
||||||
ole_val2variant2(val, var);
|
|
||||||
} else {
|
|
||||||
V_VT(var) = (vt & ~VT_BYREF);
|
|
||||||
if (V_VT(var) == VT_DISPATCH) {
|
|
||||||
V_DISPATCH(var) = NULL;
|
|
||||||
} else if (V_VT(var) == VT_UNKNOWN) {
|
|
||||||
V_UNKNOWN(var) = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
|
||||||
switch(vt & ~VT_BYREF) {
|
|
||||||
case VT_I8:
|
|
||||||
V_VT(var) = VT_I8;
|
|
||||||
V_I8(var) = NUM2I8 (val);
|
|
||||||
break;
|
|
||||||
case VT_UI8:
|
|
||||||
V_VT(var) = VT_UI8;
|
|
||||||
V_UI8(var) = NUM2UI8(val);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ole_val2variant2(val, var);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else /* (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__) */
|
|
||||||
ole_val2variant2(val, var);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ole_val2ptr_variant(VALUE val, VARIANT *var)
|
ole_val2ptr_variant(VALUE val, VARIANT *var)
|
||||||
{
|
{
|
||||||
|
@ -1528,191 +1517,7 @@ ole_val2ptr_variant(VALUE val, VARIANT *var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
|
|
||||||
{
|
|
||||||
V_VT(var) = vt;
|
|
||||||
if (vt == (VT_VARIANT|VT_BYREF)) {
|
|
||||||
V_VARIANTREF(var) = realvar;
|
|
||||||
} else {
|
|
||||||
if (V_VT(realvar) != (vt & ~VT_BYREF)) {
|
|
||||||
rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
|
|
||||||
}
|
|
||||||
switch(vt & ~VT_BYREF) {
|
|
||||||
case VT_I1:
|
|
||||||
V_I1REF(var) = &V_I1(realvar);
|
|
||||||
break;
|
|
||||||
case VT_UI1:
|
|
||||||
V_UI1REF(var) = &V_UI1(realvar);
|
|
||||||
break;
|
|
||||||
case VT_I2:
|
|
||||||
V_I2REF(var) = &V_I2(realvar);
|
|
||||||
break;
|
|
||||||
case VT_UI2:
|
|
||||||
V_UI2REF(var) = &V_UI2(realvar);
|
|
||||||
break;
|
|
||||||
case VT_I4:
|
|
||||||
V_I4REF(var) = &V_I4(realvar);
|
|
||||||
break;
|
|
||||||
case VT_UI4:
|
|
||||||
V_UI4REF(var) = &V_UI4(realvar);
|
|
||||||
break;
|
|
||||||
case VT_R4:
|
|
||||||
V_R4REF(var) = &V_R4(realvar);
|
|
||||||
break;
|
|
||||||
case VT_R8:
|
|
||||||
V_R8REF(var) = &V_R8(realvar);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
|
||||||
#ifdef V_I8REF
|
|
||||||
case VT_I8:
|
|
||||||
V_I8REF(var) = &V_I8(realvar);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef V_UI8REF
|
|
||||||
case VT_UI8:
|
|
||||||
V_UI8REF(var) = &V_UI8(realvar);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
case VT_INT:
|
|
||||||
V_INTREF(var) = &V_INT(realvar);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VT_UINT:
|
|
||||||
V_UINTREF(var) = &V_UINT(realvar);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case VT_CY:
|
|
||||||
V_CYREF(var) = &V_CY(realvar);
|
|
||||||
break;
|
|
||||||
case VT_DATE:
|
|
||||||
V_DATEREF(var) = &V_DATE(realvar);
|
|
||||||
break;
|
|
||||||
case VT_BSTR:
|
|
||||||
V_BSTRREF(var) = &V_BSTR(realvar);
|
|
||||||
break;
|
|
||||||
case VT_DISPATCH:
|
|
||||||
V_DISPATCHREF(var) = &V_DISPATCH(realvar);
|
|
||||||
break;
|
|
||||||
case VT_ERROR:
|
|
||||||
V_ERRORREF(var) = &V_ERROR(realvar);
|
|
||||||
break;
|
|
||||||
case VT_BOOL:
|
|
||||||
V_BOOLREF(var) = &V_BOOL(realvar);
|
|
||||||
break;
|
|
||||||
case VT_UNKNOWN:
|
|
||||||
V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
|
|
||||||
break;
|
|
||||||
case VT_ARRAY:
|
|
||||||
V_ARRAYREF(var) = &V_ARRAY(realvar);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) {
|
|
||||||
long len = RSTRING_LEN(val);
|
|
||||||
void *pdest = NULL;
|
|
||||||
SAFEARRAY *p = NULL;
|
|
||||||
SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
|
|
||||||
if (!psa) {
|
|
||||||
rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
|
|
||||||
}
|
|
||||||
hr = SafeArrayAccessData(psa, &pdest);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
memcpy(pdest, RSTRING_PTR(val), len);
|
|
||||||
SafeArrayUnaccessData(psa);
|
|
||||||
V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
|
|
||||||
p = V_ARRAY(&(pvar->realvar));
|
|
||||||
if (p != NULL) {
|
|
||||||
SafeArrayDestroy(p);
|
|
||||||
}
|
|
||||||
V_ARRAY(&(pvar->realvar)) = psa;
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
|
||||||
} else {
|
|
||||||
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (psa)
|
|
||||||
SafeArrayDestroy(psa);
|
|
||||||
}
|
|
||||||
} else if (vt & VT_ARRAY) {
|
|
||||||
if (val == Qnil) {
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
|
||||||
} else {
|
|
||||||
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
|
||||||
} else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
|
|
||||||
ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
|
|
||||||
ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
if (val == Qnil) {
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
if (vt == (VT_BYREF | VT_VARIANT)) {
|
|
||||||
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
|
||||||
} else {
|
|
||||||
V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
|
|
||||||
if (vt == (VT_BYREF | VT_VARIANT)) {
|
|
||||||
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
|
||||||
} else if (vt & VT_BYREF) {
|
|
||||||
if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
|
|
||||||
hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
|
|
||||||
cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
|
|
||||||
}
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (vt == V_VT(&(pvar->realvar))) {
|
|
||||||
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
|
||||||
} else {
|
|
||||||
hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
|
|
||||||
cWIN32OLE_lcid, 0, vt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ole_val2variant2(VALUE val, VARIANT *var)
|
ole_val2variant2(VALUE val, VARIANT *var)
|
||||||
{
|
{
|
||||||
g_nil_to = VT_EMPTY;
|
g_nil_to = VT_EMPTY;
|
||||||
|
@ -5313,468 +5118,6 @@ fev_get_handler(VALUE self)
|
||||||
return rb_ivar_get(self, rb_intern("handler"));
|
return rb_ivar_get(self, rb_intern("handler"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
olevariant_free(struct olevariantdata *pvar)
|
|
||||||
{
|
|
||||||
VariantClear(&(pvar->realvar));
|
|
||||||
VariantClear(&(pvar->var));
|
|
||||||
free(pvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
folevariant_s_allocate(VALUE klass)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
VALUE obj;
|
|
||||||
ole_initialize();
|
|
||||||
obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar);
|
|
||||||
VariantInit(&(pvar->var));
|
|
||||||
VariantInit(&(pvar->realvar));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* WIN32OLE_VARIANT.array(ary, vt)
|
|
||||||
*
|
|
||||||
* Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
|
|
||||||
* The first argument should be Array object which specifies dimensions
|
|
||||||
* and each size of dimensions of OLE array.
|
|
||||||
* The second argument specifies variant type of the element of OLE array.
|
|
||||||
*
|
|
||||||
* The following create 2 dimensions OLE array. The first dimensions size
|
|
||||||
* is 3, and the second is 4.
|
|
||||||
*
|
|
||||||
* ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
|
|
||||||
* ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
|
|
||||||
{
|
|
||||||
VALUE obj = Qnil;
|
|
||||||
VARTYPE vt;
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
SAFEARRAYBOUND *psab = NULL;
|
|
||||||
SAFEARRAY *psa = NULL;
|
|
||||||
UINT dim = 0;
|
|
||||||
UINT i = 0;
|
|
||||||
|
|
||||||
ole_initialize();
|
|
||||||
|
|
||||||
vt = NUM2UINT(vvt);
|
|
||||||
vt = (vt | VT_ARRAY);
|
|
||||||
Check_Type(elems, T_ARRAY);
|
|
||||||
obj = folevariant_s_allocate(klass);
|
|
||||||
|
|
||||||
Data_Get_Struct(obj, struct olevariantdata, pvar);
|
|
||||||
dim = RARRAY_LEN(elems);
|
|
||||||
|
|
||||||
psab = ALLOC_N(SAFEARRAYBOUND, dim);
|
|
||||||
|
|
||||||
if(!psab) {
|
|
||||||
rb_raise(rb_eRuntimeError, "memory allocation error");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dim; i++) {
|
|
||||||
psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
|
|
||||||
psab[i].lLbound = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
|
|
||||||
if (psa == NULL) {
|
|
||||||
if (psab) free(psab);
|
|
||||||
rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
|
|
||||||
}
|
|
||||||
|
|
||||||
V_VT(&(pvar->var)) = vt;
|
|
||||||
if (vt & VT_BYREF) {
|
|
||||||
V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
|
|
||||||
V_ARRAY(&(pvar->realvar)) = psa;
|
|
||||||
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
|
||||||
} else {
|
|
||||||
V_ARRAY(&(pvar->var)) = psa;
|
|
||||||
}
|
|
||||||
if (psab) free(psab);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_type_val2variant(VALUE val)
|
|
||||||
{
|
|
||||||
VALUE elem;
|
|
||||||
int len = 0;
|
|
||||||
int i = 0;
|
|
||||||
if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
|
|
||||||
!rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
|
|
||||||
!rb_obj_is_kind_of(val, rb_cTime)) {
|
|
||||||
switch (TYPE(val)) {
|
|
||||||
case T_ARRAY:
|
|
||||||
len = RARRAY_LEN(val);
|
|
||||||
for(i = 0; i < len; i++) {
|
|
||||||
elem = rb_ary_entry(val, i);
|
|
||||||
check_type_val2variant(elem);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_STRING:
|
|
||||||
case T_FIXNUM:
|
|
||||||
case T_BIGNUM:
|
|
||||||
case T_FLOAT:
|
|
||||||
case T_TRUE:
|
|
||||||
case T_FALSE:
|
|
||||||
case T_NIL:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
|
|
||||||
rb_obj_classname(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Document-class: WIN32OLE_VARIANT
|
|
||||||
*
|
|
||||||
* <code>WIN32OLE_VARIANT</code> objects represents OLE variant.
|
|
||||||
*
|
|
||||||
* Win32OLE converts Ruby object into OLE variant automatically when
|
|
||||||
* invoking OLE methods. If OLE method requires the argument which is
|
|
||||||
* different from the variant by automatic conversion of Win32OLE, you
|
|
||||||
* can convert the specfied variant type by using WIN32OLE_VARIANT class.
|
|
||||||
*
|
|
||||||
* param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4)
|
|
||||||
* oleobj.method(param)
|
|
||||||
*
|
|
||||||
* WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD
|
|
||||||
* class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
if (len < 1 || len > 3) {
|
|
||||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
|
|
||||||
}
|
|
||||||
VariantInit(&var);
|
|
||||||
val = rb_ary_entry(args, 0);
|
|
||||||
|
|
||||||
check_type_val2variant(val);
|
|
||||||
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, pvar);
|
|
||||||
if (len == 1) {
|
|
||||||
ole_val2variant(val, &(pvar->var));
|
|
||||||
} else {
|
|
||||||
vvt = rb_ary_entry(args, 1);
|
|
||||||
vt = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SAFEARRAY *
|
|
||||||
get_locked_safe_array(VALUE val)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
SAFEARRAY *psa = NULL;
|
|
||||||
HRESULT hr;
|
|
||||||
Data_Get_Struct(val, struct olevariantdata, pvar);
|
|
||||||
if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
|
|
||||||
rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
|
|
||||||
}
|
|
||||||
psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
|
|
||||||
if (psa == NULL) {
|
|
||||||
return psa;
|
|
||||||
}
|
|
||||||
hr = SafeArrayLock(psa);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
|
|
||||||
}
|
|
||||||
return psa;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LONG *
|
|
||||||
ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
|
|
||||||
{
|
|
||||||
long dim;
|
|
||||||
LONG *pid;
|
|
||||||
long i;
|
|
||||||
dim = SafeArrayGetDim(psa);
|
|
||||||
if (dim != ary_size) {
|
|
||||||
rb_raise(rb_eArgError, "unmatch number of indices");
|
|
||||||
}
|
|
||||||
pid = ALLOC_N(LONG, dim);
|
|
||||||
if (pid == NULL) {
|
|
||||||
rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
|
|
||||||
}
|
|
||||||
for (i = 0; i < dim; i++) {
|
|
||||||
pid[i] = NUM2INT(ary[i]);
|
|
||||||
}
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
unlock_safe_array(SAFEARRAY *psa)
|
|
||||||
{
|
|
||||||
HRESULT hr;
|
|
||||||
hr = SafeArrayUnlock(psa);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 indicies should be 0 or natural number and
|
|
||||||
* lower than or equal to max indicies.
|
|
||||||
* (This point is different with Ruby Array indicies.)
|
|
||||||
*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID *
|
|
||||||
val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
|
|
||||||
{
|
|
||||||
VOID *p = NULL;
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
ole_val2variant_ex(val, var, vt);
|
|
||||||
if ((vt & ~VT_BYREF) == VT_VARIANT) {
|
|
||||||
p = var;
|
|
||||||
} else {
|
|
||||||
if ( (vt & ~VT_BYREF) != V_VT(var)) {
|
|
||||||
hr = VariantChangeTypeEx(var, var,
|
|
||||||
cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
ole_raise(hr, rb_eRuntimeError, "failed to change type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p = get_ptr_of_variant(var);
|
|
||||||
}
|
|
||||||
if (p == NULL) {
|
|
||||||
rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
|
|
||||||
*
|
|
||||||
* Set the element of WIN32OLE_VARIANT object(OLE array) to val.
|
|
||||||
* This method is available only when the variant type of
|
|
||||||
* WIN32OLE_VARIANT object is VT_ARRAY.
|
|
||||||
*
|
|
||||||
* REMARK:
|
|
||||||
* The all indicies should be 0 or natural number and
|
|
||||||
* lower than or equal to max indicies.
|
|
||||||
* (This point is different with Ruby Array indicies.)
|
|
||||||
*
|
|
||||||
* obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
|
|
||||||
* obj[0,0] = 7
|
|
||||||
* obj[1,0] = 8
|
|
||||||
* p obj.value # => [[7,2,3], [8,5,6]]
|
|
||||||
* obj[2,0] = 9 # => WIN32OLERuntimeError
|
|
||||||
* obj[0, -1] = 9 # => WIN32OLERuntimeError
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
SAFEARRAY *psa;
|
|
||||||
VARIANT var;
|
|
||||||
VARTYPE vt;
|
|
||||||
LONG *pid;
|
|
||||||
HRESULT hr;
|
|
||||||
VOID *p = NULL;
|
|
||||||
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, 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) {
|
|
||||||
rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = ary2safe_array_index(argc-1, argv, psa);
|
|
||||||
|
|
||||||
VariantInit(&var);
|
|
||||||
vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
|
|
||||||
p = val2variant_ptr(argv[argc-1], &var, vt);
|
|
||||||
if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
|
|
||||||
(V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
|
|
||||||
rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
|
|
||||||
}
|
|
||||||
hr = SafeArrayPutElement(psa, pid, p);
|
|
||||||
if (FAILED(hr)) {
|
|
||||||
ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
|
|
||||||
}
|
|
||||||
|
|
||||||
unlock_safe_array(psa);
|
|
||||||
if (pid) free(pid);
|
|
||||||
return argv[argc-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 Fixnum object, but String object "1")
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
folevariant_value(VALUE self)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
VALUE val = Qnil;
|
|
||||||
VARTYPE vt;
|
|
||||||
int dim;
|
|
||||||
SAFEARRAY *psa;
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* WIN32OLE_VARIANT.vartype #=> OLE variant type.
|
|
||||||
*
|
|
||||||
* Returns OLE variant type.
|
|
||||||
* obj = WIN32OLE_VARIANT.new("string")
|
|
||||||
* obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
folevariant_vartype(VALUE self)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, pvar);
|
|
||||||
return INT2FIX(V_VT(&pvar->var));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
|
|
||||||
*
|
|
||||||
* Sets variant value to val. If the val type does not match variant value
|
|
||||||
* type(vartype), then val is changed to match variant value type(vartype)
|
|
||||||
* before setting val.
|
|
||||||
* Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
|
|
||||||
* If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
|
|
||||||
*
|
|
||||||
* obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
|
|
||||||
* obj.value = 3.2 # 3.2 is changed to 3 when setting value.
|
|
||||||
* p obj.value # => 3
|
|
||||||
*/
|
|
||||||
static VALUE
|
|
||||||
folevariant_set_value(VALUE self, VALUE val)
|
|
||||||
{
|
|
||||||
struct olevariantdata *pvar;
|
|
||||||
VARTYPE vt;
|
|
||||||
Data_Get_Struct(self, struct olevariantdata, pvar);
|
|
||||||
vt = V_VT(&(pvar->var));
|
|
||||||
if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) {
|
|
||||||
rb_raise(eWIN32OLERuntimeError,
|
|
||||||
"`value=' is not available for this variant type object");
|
|
||||||
}
|
|
||||||
ole_val2olevariantdata(val, vt, pvar);
|
|
||||||
return Qnil;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT
|
static HRESULT
|
||||||
typelib_from_val(VALUE obj, ITypeLib **pTypeLib)
|
typelib_from_val(VALUE obj, ITypeLib **pTypeLib)
|
||||||
{
|
{
|
||||||
|
@ -6457,30 +5800,7 @@ Init_win32ole(void)
|
||||||
rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
|
rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
|
||||||
rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
|
rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
|
||||||
|
|
||||||
cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
|
Init_win32ole_variant();
|
||||||
rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
|
|
||||||
rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
|
|
||||||
rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* represents VT_EMPTY OLE object.
|
|
||||||
*/
|
|
||||||
rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY)));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* represents VT_NULL OLE object.
|
|
||||||
*/
|
|
||||||
rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL)));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* represents Nothing of VB.NET or VB.
|
|
||||||
*/
|
|
||||||
rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH)));
|
|
||||||
|
|
||||||
cWIN32OLE_RECORD = rb_define_class("WIN32OLE_RECORD", rb_cObject);
|
cWIN32OLE_RECORD = rb_define_class("WIN32OLE_RECORD", rb_cObject);
|
||||||
rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
|
rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
|
||||||
|
|
|
@ -82,6 +82,18 @@
|
||||||
#define V_UINTREF(X) V_UNION(X, puintVal)
|
#define V_UINTREF(X) V_UNION(X, puintVal)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LONG_LONG
|
||||||
|
#define I8_2_NUM LL2NUM
|
||||||
|
#define UI8_2_NUM ULL2NUM
|
||||||
|
#define NUM2I8 NUM2LL
|
||||||
|
#define NUM2UI8 NUM2ULL
|
||||||
|
#else
|
||||||
|
#define I8_2_NUM INT2NUM
|
||||||
|
#define UI8_2_NUM UINT2NUM
|
||||||
|
#define NUM2I8 NUM2INT
|
||||||
|
#define NUM2UI8 NUM2UINT
|
||||||
|
#endif
|
||||||
|
|
||||||
#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
|
#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
|
||||||
#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
|
#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
|
||||||
#define OLE_FREE(x) {\
|
#define OLE_FREE(x) {\
|
||||||
|
@ -116,7 +128,12 @@ BOOL ole_initialized();
|
||||||
HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
|
HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
|
||||||
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
|
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
|
||||||
VALUE make_inspect(const char *class_name, VALUE detail);
|
VALUE make_inspect(const char *class_name, VALUE detail);
|
||||||
|
void ole_val2variant(VALUE val, VARIANT *var);
|
||||||
|
void ole_val2variant2(VALUE val, VARIANT *var);
|
||||||
|
void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
|
||||||
VALUE ole_variant2val(VARIANT *pvar);
|
VALUE ole_variant2val(VARIANT *pvar);
|
||||||
|
HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
|
||||||
|
VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
|
||||||
|
|
||||||
#include "win32ole_variant_m.h"
|
#include "win32ole_variant_m.h"
|
||||||
#include "win32ole_typelib.h"
|
#include "win32ole_typelib.h"
|
||||||
|
@ -124,6 +141,7 @@ VALUE ole_variant2val(VARIANT *pvar);
|
||||||
#include "win32ole_variable.h"
|
#include "win32ole_variable.h"
|
||||||
#include "win32ole_method.h"
|
#include "win32ole_method.h"
|
||||||
#include "win32ole_param.h"
|
#include "win32ole_param.h"
|
||||||
|
#include "win32ole_variant.h"
|
||||||
#include "win32ole_error.h"
|
#include "win32ole_error.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
668
ext/win32ole/win32ole_variant.c
Normal file
668
ext/win32ole/win32ole_variant.c
Normal file
|
@ -0,0 +1,668 @@
|
||||||
|
#include "win32ole.h"
|
||||||
|
|
||||||
|
static void olevariant_free(struct olevariantdata *pvar);
|
||||||
|
static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
|
||||||
|
static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
|
||||||
|
static VALUE folevariant_s_allocate(VALUE klass);
|
||||||
|
static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
|
||||||
|
static void check_type_val2variant(VALUE val);
|
||||||
|
static VALUE folevariant_initialize(VALUE self, VALUE args);
|
||||||
|
static LONG *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
|
||||||
|
static void unlock_safe_array(SAFEARRAY *psa);
|
||||||
|
static SAFEARRAY *get_locked_safe_array(VALUE val);
|
||||||
|
static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
|
||||||
|
static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
|
||||||
|
static VALUE folevariant_value(VALUE self);
|
||||||
|
static VALUE folevariant_vartype(VALUE self);
|
||||||
|
static VALUE folevariant_set_value(VALUE self, VALUE val);
|
||||||
|
|
||||||
|
static void
|
||||||
|
olevariant_free(struct olevariantdata *pvar)
|
||||||
|
{
|
||||||
|
VariantClear(&(pvar->realvar));
|
||||||
|
VariantClear(&(pvar->var));
|
||||||
|
free(pvar);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) {
|
||||||
|
long len = RSTRING_LEN(val);
|
||||||
|
void *pdest = NULL;
|
||||||
|
SAFEARRAY *p = NULL;
|
||||||
|
SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
|
||||||
|
if (!psa) {
|
||||||
|
rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
|
||||||
|
}
|
||||||
|
hr = SafeArrayAccessData(psa, &pdest);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
memcpy(pdest, RSTRING_PTR(val), len);
|
||||||
|
SafeArrayUnaccessData(psa);
|
||||||
|
V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
|
||||||
|
p = V_ARRAY(&(pvar->realvar));
|
||||||
|
if (p != NULL) {
|
||||||
|
SafeArrayDestroy(p);
|
||||||
|
}
|
||||||
|
V_ARRAY(&(pvar->realvar)) = psa;
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
||||||
|
} else {
|
||||||
|
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (psa)
|
||||||
|
SafeArrayDestroy(psa);
|
||||||
|
}
|
||||||
|
} else if (vt & VT_ARRAY) {
|
||||||
|
if (val == Qnil) {
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
||||||
|
} else {
|
||||||
|
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||||
|
} else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
|
||||||
|
ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
|
||||||
|
ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (val == Qnil) {
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
if (vt == (VT_BYREF | VT_VARIANT)) {
|
||||||
|
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
||||||
|
} else {
|
||||||
|
V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
|
||||||
|
if (vt == (VT_BYREF | VT_VARIANT)) {
|
||||||
|
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
||||||
|
} else if (vt & VT_BYREF) {
|
||||||
|
if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
|
||||||
|
hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
|
||||||
|
cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (vt == V_VT(&(pvar->realvar))) {
|
||||||
|
hr = VariantCopy(&(pvar->var), &(pvar->realvar));
|
||||||
|
} else {
|
||||||
|
hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
|
||||||
|
cWIN32OLE_lcid, 0, vt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
|
||||||
|
{
|
||||||
|
V_VT(var) = vt;
|
||||||
|
if (vt == (VT_VARIANT|VT_BYREF)) {
|
||||||
|
V_VARIANTREF(var) = realvar;
|
||||||
|
} else {
|
||||||
|
if (V_VT(realvar) != (vt & ~VT_BYREF)) {
|
||||||
|
rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
|
||||||
|
}
|
||||||
|
switch(vt & ~VT_BYREF) {
|
||||||
|
case VT_I1:
|
||||||
|
V_I1REF(var) = &V_I1(realvar);
|
||||||
|
break;
|
||||||
|
case VT_UI1:
|
||||||
|
V_UI1REF(var) = &V_UI1(realvar);
|
||||||
|
break;
|
||||||
|
case VT_I2:
|
||||||
|
V_I2REF(var) = &V_I2(realvar);
|
||||||
|
break;
|
||||||
|
case VT_UI2:
|
||||||
|
V_UI2REF(var) = &V_UI2(realvar);
|
||||||
|
break;
|
||||||
|
case VT_I4:
|
||||||
|
V_I4REF(var) = &V_I4(realvar);
|
||||||
|
break;
|
||||||
|
case VT_UI4:
|
||||||
|
V_UI4REF(var) = &V_UI4(realvar);
|
||||||
|
break;
|
||||||
|
case VT_R4:
|
||||||
|
V_R4REF(var) = &V_R4(realvar);
|
||||||
|
break;
|
||||||
|
case VT_R8:
|
||||||
|
V_R8REF(var) = &V_R8(realvar);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
|
||||||
|
#ifdef V_I8REF
|
||||||
|
case VT_I8:
|
||||||
|
V_I8REF(var) = &V_I8(realvar);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef V_UI8REF
|
||||||
|
case VT_UI8:
|
||||||
|
V_UI8REF(var) = &V_UI8(realvar);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
case VT_INT:
|
||||||
|
V_INTREF(var) = &V_INT(realvar);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VT_UINT:
|
||||||
|
V_UINTREF(var) = &V_UINT(realvar);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VT_CY:
|
||||||
|
V_CYREF(var) = &V_CY(realvar);
|
||||||
|
break;
|
||||||
|
case VT_DATE:
|
||||||
|
V_DATEREF(var) = &V_DATE(realvar);
|
||||||
|
break;
|
||||||
|
case VT_BSTR:
|
||||||
|
V_BSTRREF(var) = &V_BSTR(realvar);
|
||||||
|
break;
|
||||||
|
case VT_DISPATCH:
|
||||||
|
V_DISPATCHREF(var) = &V_DISPATCH(realvar);
|
||||||
|
break;
|
||||||
|
case VT_ERROR:
|
||||||
|
V_ERRORREF(var) = &V_ERROR(realvar);
|
||||||
|
break;
|
||||||
|
case VT_BOOL:
|
||||||
|
V_BOOLREF(var) = &V_BOOL(realvar);
|
||||||
|
break;
|
||||||
|
case VT_UNKNOWN:
|
||||||
|
V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
|
||||||
|
break;
|
||||||
|
case VT_ARRAY:
|
||||||
|
V_ARRAYREF(var) = &V_ARRAY(realvar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
folevariant_s_allocate(VALUE klass)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
VALUE obj;
|
||||||
|
ole_initialize();
|
||||||
|
obj = Data_Make_Struct(klass,struct olevariantdata,0,olevariant_free,pvar);
|
||||||
|
VariantInit(&(pvar->var));
|
||||||
|
VariantInit(&(pvar->realvar));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* WIN32OLE_VARIANT.array(ary, vt)
|
||||||
|
*
|
||||||
|
* Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
|
||||||
|
* The first argument should be Array object which specifies dimensions
|
||||||
|
* and each size of dimensions of OLE array.
|
||||||
|
* The second argument specifies variant type of the element of OLE array.
|
||||||
|
*
|
||||||
|
* The following create 2 dimensions OLE array. The first dimensions size
|
||||||
|
* is 3, and the second is 4.
|
||||||
|
*
|
||||||
|
* ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
|
||||||
|
* ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
|
||||||
|
{
|
||||||
|
VALUE obj = Qnil;
|
||||||
|
VARTYPE vt;
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
SAFEARRAYBOUND *psab = NULL;
|
||||||
|
SAFEARRAY *psa = NULL;
|
||||||
|
UINT dim = 0;
|
||||||
|
UINT i = 0;
|
||||||
|
|
||||||
|
ole_initialize();
|
||||||
|
|
||||||
|
vt = NUM2UINT(vvt);
|
||||||
|
vt = (vt | VT_ARRAY);
|
||||||
|
Check_Type(elems, T_ARRAY);
|
||||||
|
obj = folevariant_s_allocate(klass);
|
||||||
|
|
||||||
|
Data_Get_Struct(obj, struct olevariantdata, pvar);
|
||||||
|
dim = RARRAY_LEN(elems);
|
||||||
|
|
||||||
|
psab = ALLOC_N(SAFEARRAYBOUND, dim);
|
||||||
|
|
||||||
|
if(!psab) {
|
||||||
|
rb_raise(rb_eRuntimeError, "memory allocation error");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < dim; i++) {
|
||||||
|
psab[i].cElements = FIX2INT(rb_ary_entry(elems, i));
|
||||||
|
psab[i].lLbound = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
|
||||||
|
if (psa == NULL) {
|
||||||
|
if (psab) free(psab);
|
||||||
|
rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
|
||||||
|
}
|
||||||
|
|
||||||
|
V_VT(&(pvar->var)) = vt;
|
||||||
|
if (vt & VT_BYREF) {
|
||||||
|
V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
|
||||||
|
V_ARRAY(&(pvar->realvar)) = psa;
|
||||||
|
V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
|
||||||
|
} else {
|
||||||
|
V_ARRAY(&(pvar->var)) = psa;
|
||||||
|
}
|
||||||
|
if (psab) free(psab);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_type_val2variant(VALUE val)
|
||||||
|
{
|
||||||
|
VALUE elem;
|
||||||
|
int len = 0;
|
||||||
|
int i = 0;
|
||||||
|
if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
|
||||||
|
!rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
|
||||||
|
!rb_obj_is_kind_of(val, rb_cTime)) {
|
||||||
|
switch (TYPE(val)) {
|
||||||
|
case T_ARRAY:
|
||||||
|
len = RARRAY_LEN(val);
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
elem = rb_ary_entry(val, i);
|
||||||
|
check_type_val2variant(elem);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_STRING:
|
||||||
|
case T_FIXNUM:
|
||||||
|
case T_BIGNUM:
|
||||||
|
case T_FLOAT:
|
||||||
|
case T_TRUE:
|
||||||
|
case T_FALSE:
|
||||||
|
case T_NIL:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
|
||||||
|
rb_obj_classname(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Document-class: WIN32OLE_VARIANT
|
||||||
|
*
|
||||||
|
* <code>WIN32OLE_VARIANT</code> objects represents OLE variant.
|
||||||
|
*
|
||||||
|
* Win32OLE converts Ruby object into OLE variant automatically when
|
||||||
|
* invoking OLE methods. If OLE method requires the argument which is
|
||||||
|
* different from the variant by automatic conversion of Win32OLE, you
|
||||||
|
* can convert the specfied variant type by using WIN32OLE_VARIANT class.
|
||||||
|
*
|
||||||
|
* param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4)
|
||||||
|
* oleobj.method(param)
|
||||||
|
*
|
||||||
|
* WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD
|
||||||
|
* class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
if (len < 1 || len > 3) {
|
||||||
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..3)", len);
|
||||||
|
}
|
||||||
|
VariantInit(&var);
|
||||||
|
val = rb_ary_entry(args, 0);
|
||||||
|
|
||||||
|
check_type_val2variant(val);
|
||||||
|
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, pvar);
|
||||||
|
if (len == 1) {
|
||||||
|
ole_val2variant(val, &(pvar->var));
|
||||||
|
} else {
|
||||||
|
vvt = rb_ary_entry(args, 1);
|
||||||
|
vt = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SAFEARRAY *
|
||||||
|
get_locked_safe_array(VALUE val)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
SAFEARRAY *psa = NULL;
|
||||||
|
HRESULT hr;
|
||||||
|
Data_Get_Struct(val, struct olevariantdata, pvar);
|
||||||
|
if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
|
||||||
|
rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
|
||||||
|
}
|
||||||
|
psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
|
||||||
|
if (psa == NULL) {
|
||||||
|
return psa;
|
||||||
|
}
|
||||||
|
hr = SafeArrayLock(psa);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
|
||||||
|
}
|
||||||
|
return psa;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG *
|
||||||
|
ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
|
||||||
|
{
|
||||||
|
long dim;
|
||||||
|
LONG *pid;
|
||||||
|
long i;
|
||||||
|
dim = SafeArrayGetDim(psa);
|
||||||
|
if (dim != ary_size) {
|
||||||
|
rb_raise(rb_eArgError, "unmatch number of indices");
|
||||||
|
}
|
||||||
|
pid = ALLOC_N(LONG, dim);
|
||||||
|
if (pid == NULL) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
|
||||||
|
}
|
||||||
|
for (i = 0; i < dim; i++) {
|
||||||
|
pid[i] = NUM2INT(ary[i]);
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
unlock_safe_array(SAFEARRAY *psa)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
hr = SafeArrayUnlock(psa);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 indicies should be 0 or natural number and
|
||||||
|
* lower than or equal to max indicies.
|
||||||
|
* (This point is different with Ruby Array indicies.)
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, 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[i,j,...] = val #=> set the element of OLE array
|
||||||
|
*
|
||||||
|
* Set the element of WIN32OLE_VARIANT object(OLE array) to val.
|
||||||
|
* This method is available only when the variant type of
|
||||||
|
* WIN32OLE_VARIANT object is VT_ARRAY.
|
||||||
|
*
|
||||||
|
* REMARK:
|
||||||
|
* The all indicies should be 0 or natural number and
|
||||||
|
* lower than or equal to max indicies.
|
||||||
|
* (This point is different with Ruby Array indicies.)
|
||||||
|
*
|
||||||
|
* obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
|
||||||
|
* obj[0,0] = 7
|
||||||
|
* obj[1,0] = 8
|
||||||
|
* p obj.value # => [[7,2,3], [8,5,6]]
|
||||||
|
* obj[2,0] = 9 # => WIN32OLERuntimeError
|
||||||
|
* obj[0, -1] = 9 # => WIN32OLERuntimeError
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
SAFEARRAY *psa;
|
||||||
|
VARIANT var;
|
||||||
|
VARTYPE vt;
|
||||||
|
LONG *pid;
|
||||||
|
HRESULT hr;
|
||||||
|
VOID *p = NULL;
|
||||||
|
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, 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) {
|
||||||
|
rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = ary2safe_array_index(argc-1, argv, psa);
|
||||||
|
|
||||||
|
VariantInit(&var);
|
||||||
|
vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
|
||||||
|
p = val2variant_ptr(argv[argc-1], &var, vt);
|
||||||
|
if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
|
||||||
|
(V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
|
||||||
|
rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
|
||||||
|
}
|
||||||
|
hr = SafeArrayPutElement(psa, pid, p);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_safe_array(psa);
|
||||||
|
if (pid) free(pid);
|
||||||
|
return argv[argc-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 Fixnum object, but String object "1")
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
folevariant_value(VALUE self)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
VALUE val = Qnil;
|
||||||
|
VARTYPE vt;
|
||||||
|
int dim;
|
||||||
|
SAFEARRAY *psa;
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* WIN32OLE_VARIANT.vartype #=> OLE variant type.
|
||||||
|
*
|
||||||
|
* Returns OLE variant type.
|
||||||
|
* obj = WIN32OLE_VARIANT.new("string")
|
||||||
|
* obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
folevariant_vartype(VALUE self)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, pvar);
|
||||||
|
return INT2FIX(V_VT(&pvar->var));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
|
||||||
|
*
|
||||||
|
* Sets variant value to val. If the val type does not match variant value
|
||||||
|
* type(vartype), then val is changed to match variant value type(vartype)
|
||||||
|
* before setting val.
|
||||||
|
* Thie method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
|
||||||
|
* If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
|
||||||
|
*
|
||||||
|
* obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
|
||||||
|
* obj.value = 3.2 # 3.2 is changed to 3 when setting value.
|
||||||
|
* p obj.value # => 3
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
folevariant_set_value(VALUE self, VALUE val)
|
||||||
|
{
|
||||||
|
struct olevariantdata *pvar;
|
||||||
|
VARTYPE vt;
|
||||||
|
Data_Get_Struct(self, struct olevariantdata, pvar);
|
||||||
|
vt = V_VT(&(pvar->var));
|
||||||
|
if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) {
|
||||||
|
rb_raise(eWIN32OLERuntimeError,
|
||||||
|
"`value=' is not available for this variant type object");
|
||||||
|
}
|
||||||
|
ole_val2olevariantdata(val, vt, pvar);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Init_win32ole_variant()
|
||||||
|
{
|
||||||
|
cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
|
||||||
|
rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
|
||||||
|
rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
|
||||||
|
rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* represents VT_EMPTY OLE object.
|
||||||
|
*/
|
||||||
|
rb_define_const(cWIN32OLE_VARIANT, "Empty", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_EMPTY)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* represents VT_NULL OLE object.
|
||||||
|
*/
|
||||||
|
rb_define_const(cWIN32OLE_VARIANT, "Null", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_NULL)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* represents Nothing of VB.NET or VB.
|
||||||
|
*/
|
||||||
|
rb_define_const(cWIN32OLE_VARIANT, "Nothing", rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, INT2FIX(VT_DISPATCH)));
|
||||||
|
}
|
13
ext/win32ole/win32ole_variant.h
Normal file
13
ext/win32ole/win32ole_variant.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef WIN32OLE_VARIANT_H
|
||||||
|
#define WIN32OLE_VARIANT_H 1
|
||||||
|
|
||||||
|
struct olevariantdata {
|
||||||
|
VARIANT realvar;
|
||||||
|
VARIANT var;
|
||||||
|
};
|
||||||
|
|
||||||
|
VALUE cWIN32OLE_VARIANT;
|
||||||
|
void Init_win32ole_variant();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue