summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/win32ole/win32ole.c81
-rw-r--r--test/win32ole/test_win32ole_variant.rb33
3 files changed, 100 insertions, 23 deletions
diff --git a/ChangeLog b/ChangeLog
index 5101b1e2f0..168bb48abd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Thu Feb 8 22:44:04 2007 Masaki Suketa <masaki.suketa@nifty.ne.jp>
+
+ * ext/win32ole/win32ole.c (ole_set_safe_array, ole_variant2val,
+ ole_val_ary2variant_ary): fix WIN32OLE_VARIANT.new bug when
+ 1st argument is empty array, and when 2nd argument is
+ VT_ARRAY|VT_BYREF.
+
+ * test/win32ole/test_win32ole_variant.rb: ditto.
+
Thu Feb 8 22:39:09 2007 Koichi Sasada <ko1@atdot.net>
* yarvtest/yarvtest.rb: check target command names.
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index d4109fcb38..7d725e4737 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -80,7 +80,7 @@
#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-#define WIN32OLE_VERSION "0.9.1"
+#define WIN32OLE_VERSION "0.9.2"
typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
(REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -239,6 +239,7 @@ static LPWSTR ole_mb2wc(char *pm, int len);
static VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
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 void ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vtype);
static long dimension(VALUE val);
static long ary_len_of_dim(VALUE ary, long dim);
@@ -253,6 +254,8 @@ static VALUE default_inspect(VALUE self, const char *class_name);
static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
static VALUE fole_s_allocate(VALUE klass);
static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
+static VALUE ary_new_dim(VALUE myary, long *pid, long *plb, long dim);
+static void ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val);
static VALUE ole_variant2val(VARIANT *pvar);
static LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
static LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
@@ -982,22 +985,34 @@ static void * 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
ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long dim, VARTYPE vtype)
{
VALUE val1;
- HRESULT hr;
+ HRESULT hr = S_OK;
VARIANT var;
VARIANT vart;
VOID *p = NULL;
VariantInit(&var);
VariantInit(&vart);
if(n < 0) return;
- if(n == dim) {
+ if(n == dim - 1) {
val1 = ole_ary_m_entry(val, pid);
ole_val2variant2(val1, &var);
VariantInit(&vart);
- if (vtype == VT_VARIANT) {
+ if ((vtype & ~VT_BYREF) == VT_VARIANT) {
p = &var;
} else if (vtype != V_VT(&var)) {
hr = VariantChangeTypeEx(&vart, &var,
@@ -1013,14 +1028,16 @@ ole_set_safe_array(long n, SAFEARRAY *psa, long *pid, long *pub, VALUE val, long
if (p == NULL) {
rb_raise(rb_eRuntimeError, "failed to get ponter of variant");
}
- hr = SafeArrayPutElement(psa, pid, p);
+ if (is_all_index_under(pid, pub, dim) == Qtrue) {
+ hr = SafeArrayPutElement(psa, pid, p);
+ }
if (FAILED(hr)) {
ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
}
}
pid[n] += 1;
- if (pid[n] < pub[n]) {
- ole_set_safe_array(dim, psa, pid, pub, val, dim, vtype);
+ if (pid[n] <= pub[n]) {
+ ole_set_safe_array(dim-1, psa, pid, pub, val, dim, vtype);
}
else {
pid[n] = 0;
@@ -1102,12 +1119,12 @@ ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vtype)
for (i = 0; i < dim; i++) {
psab[i].cElements = ary_len_of_dim(val, i);
psab[i].lLbound = 0;
- pub[i] = psab[i].cElements;
+ pub[i] = psab[i].cElements - 1;
pid[i] = 0;
}
/* Create and fill VARIANT array */
- if (vtype == VT_ARRAY) {
+ if ((vtype & ~VT_BYREF) == VT_ARRAY) {
vtype = (vtype | VT_VARIANT);
}
psa = SafeArrayCreate(vtype & VT_TYPEMASK, dim, psab);
@@ -1116,7 +1133,7 @@ ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vtype)
else
hr = SafeArrayLock(psa);
if (SUCCEEDED(hr)) {
- ole_set_safe_array(dim-1, psa, pid, pub, val, dim-1, vtype & VT_TYPEMASK);
+ ole_set_safe_array(dim-1, psa, pid, pub, val, dim, vtype & VT_TYPEMASK);
hr = SafeArrayUnlock(psa);
}
@@ -1278,7 +1295,7 @@ ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vtype)
V_VARIANTREF(var) = realvar;
} else {
if (V_VT(realvar) != (vtype & ~VT_BYREF)) {
- rb_raise(eWIN32OLERuntimeError, "type mismatch");
+ rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
}
switch(vtype & ~VT_BYREF) {
case VT_UI1:
@@ -1355,9 +1372,14 @@ ole_val2olevariantdata(VALUE val, VARTYPE vtype, struct olevariantdata *pvar)
SafeArrayDestroy(psa);
}
} else if (vtype & VT_ARRAY) {
- hr = ole_val_ary2variant_ary(val, &(pvar->realvar), vtype);
+ hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (vtype & ~VT_BYREF));
if (SUCCEEDED(hr)) {
- hr = VariantCopy(&(pvar->var), &(pvar->realvar));
+ if (vtype & VT_BYREF) {
+ V_VT(&(pvar->var)) = V_VT(&(pvar->realvar)) | VT_BYREF;
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
+ } else {
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
+ }
}
} else {
if (val == Qnil) {
@@ -1463,8 +1485,8 @@ create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
return obj;
}
-static void
-ary_store_dim(VALUE myary, long *pID, long *pLB, long dim, VALUE val) {
+static VALUE
+ary_new_dim(VALUE myary, long *pid, long *plb, long dim) {
long i;
VALUE obj = Qnil;
VALUE pobj = Qnil;
@@ -1473,7 +1495,7 @@ ary_store_dim(VALUE myary, long *pID, long *pLB, long dim, VALUE val) {
rb_raise(rb_eRuntimeError, "memory allocation error");
}
for(i = 0; i < dim; i++) {
- ids[i] = pID[i] - pLB[i];
+ ids[i] = pid[i] - plb[i];
}
obj = myary;
pobj = myary;
@@ -1485,8 +1507,15 @@ ary_store_dim(VALUE myary, long *pID, long *pLB, long dim, VALUE val) {
obj = rb_ary_entry(pobj, ids[i]);
pobj = obj;
}
- rb_ary_store(obj, ids[dim-1], val);
if (ids) free(ids);
+ return obj;
+}
+
+static void
+ary_store_dim(VALUE myary, long *pid, long *plb, long dim, VALUE val) {
+ long id = pid[dim - 1] - plb[dim - 1];
+ VALUE obj = ary_new_dim(myary, pid, plb, dim);
+ rb_ary_store(obj, id, val);
}
static VALUE
@@ -1503,7 +1532,11 @@ ole_variant2val(VARIANT *pvar)
long *pid, *plb, *pub;
VARIANT variant;
VALUE val;
- int dim = SafeArrayGetDim(psa);
+ UINT dim = 0;
+ if (!psa) {
+ return obj;
+ }
+ dim = SafeArrayGetDim(psa);
VariantInit(&variant);
V_VT(&variant) = (V_VT(pvar) & ~VT_ARRAY) | VT_BYREF;
@@ -1527,11 +1560,12 @@ ole_variant2val(VARIANT *pvar)
if (SUCCEEDED(hr)) {
obj = rb_ary_new();
while (i >= 0) {
+ ary_new_dim(obj, pid, plb, dim);
hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
- if (FAILED(hr))
- break;
- val = ole_variant2val(&variant);
- ary_store_dim(obj, pid, plb, dim, val);
+ if (SUCCEEDED(hr)) {
+ val = ole_variant2val(&variant);
+ ary_store_dim(obj, pid, plb, dim, val);
+ }
for (i = dim-1 ; i >= 0 ; --i) {
if (++pid[i] <= pub[i])
break;
@@ -7272,6 +7306,9 @@ folevariant_value(VALUE self)
} else {
psa = V_ARRAY(&(pvar->var));
}
+ if (!psa) {
+ return val;
+ }
dim = SafeArrayGetDim(psa);
if (dim == 1) {
args = rb_ary_new3(1, rb_str_new2("C*"));
diff --git a/test/win32ole/test_win32ole_variant.rb b/test/win32ole/test_win32ole_variant.rb
index 418ce57751..b84f5855cf 100644
--- a/test/win32ole/test_win32ole_variant.rb
+++ b/test/win32ole/test_win32ole_variant.rb
@@ -7,6 +7,7 @@ require "test/unit"
if defined?(WIN32OLE_VARIANT)
class TestWIN32OLE_VARIANT < Test::Unit::TestCase
+
def test_new
obj = WIN32OLE_VARIANT.new('foo')
assert_instance_of(WIN32OLE_VARIANT, obj)
@@ -94,6 +95,10 @@ if defined?(WIN32OLE_VARIANT)
obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8)
assert_equal([1.2, 2.3], obj.value)
assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8, obj.vartype)
+
+ obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([1.2, 2.3], obj.value)
+ assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8|WIN32OLE::VARIANT::VT_BYREF, obj.vartype)
end
def test_create_vt_array2
@@ -106,12 +111,39 @@ if defined?(WIN32OLE_VARIANT)
assert_equal(WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_VARIANT, obj.vartype)
end
+
def test_create_vt_nested_array
obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]], WIN32OLE::VARIANT::VT_ARRAY)
assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value)
obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"]])
assert_equal([[1.2, "a", "b"], [3.4, "C", "D"]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]])
+ assert_equal([[1.2, "a", "b"], [3.4, "C", "D"], [5.6, "E", "F"]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]])
+ assert_equal([[[1.2], [3.4]], [[5.6], [7.8]], [[9.1],[9.2]]], obj.value)
+ end
+
+ def test_create_vt_array3
+ obj = WIN32OLE_VARIANT.new([])
+ assert_equal([], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[]])
+ assert_equal([[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[],[]])
+ assert_equal([[],[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([[]], obj.value)
+
+ obj = WIN32OLE_VARIANT.new([[],[]], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ assert_equal([[],[]], obj.value)
end
def test_create_vt_array_exc
@@ -168,6 +200,5 @@ if defined?(WIN32OLE_VARIANT)
assert_nil(WIN32OLE_VARIANT::Null.value)
end
-
end
end