* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11670 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
eb6153b37d
commit
990ae267cd
@ -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.
|
||||
|
@ -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*"));
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user