Project

General

Profile

Bug #10697 » patch.txt

sdottaka (Takashi Sawanaka), 01/05/2015 02:33 PM

 
ext/win32ole/win32ole.c | 43 +++++++++++++++++++++++++----------------
ext/win32ole/win32ole.h | 1 +
ext/win32ole/win32ole_record.c | 28 +++++++++++----------------
ext/win32ole/win32ole_variant.c | 4 ++--
4 files changed, 40 insertions(+), 36 deletions(-)

diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 582ff32..11e4a3c 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -2509,7 +2509,7 @@ hash2named_arg(VALUE key, VALUE val, VALUE pop)
}
/* clear dispatch parameters */
for(i = 0; i < index; i++ ) {
- VariantClear(&(pOp->dp.rgvarg[i]));
+ ole_variant_clear(&(pOp->dp.rgvarg[i]));
}
/* raise an exception */
rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
@@ -2528,6 +2528,19 @@ hash2named_arg(VALUE key, VALUE val, VALUE pop)
return ST_CONTINUE;
}
+void
+ole_variant_clear(VARIANT *pvar)
+{
+ if (V_VT(pvar) != VT_RECORD) {
+ VariantClear(pvar);
+ } else {
+ IRecordInfo *pri = V_RECORDINFO(pvar);
+ pri->lpVtbl->RecordDestroy(pri, V_RECORD(pvar));
+ pri->lpVtbl->Release(pri);
+ V_VT(pvar) = VT_EMPTY;
+ }
+}
+
static VALUE
set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
{
@@ -2537,9 +2550,7 @@ set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
rb_ary_clear(argv);
while (end-- > beg) {
rb_ary_push(argv, ole_variant2val(&realargs[end]));
- if (V_VT(&realargs[end]) != VT_RECORD) {
- VariantClear(&realargs[end]);
- }
+ ole_variant_clear(&realargs[end]);
}
return argv;
}
@@ -2635,7 +2646,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
if(FAILED(hr)) {
/* clear dispatch parameters */
for(i = 0; i < op.dp.cArgs; i++ ) {
- VariantClear(&op.dp.rgvarg[i]);
+ ole_variant_clear(&op.dp.rgvarg[i]);
}
ole_raise(hr, eWIN32OLERuntimeError,
"failed to get named argument info: `%s'",
@@ -2719,7 +2730,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
n = op.dp.cArgs - i + cNamedArgs - 1;
if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
- VariantClear(&op.dp.rgvarg[n]);
+ ole_variant_clear(&op.dp.rgvarg[n]);
}
}
}
@@ -2743,9 +2754,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
&excepinfo, &argErr);
for(i = cNamedArgs; i < op.dp.cArgs; i++) {
n = op.dp.cArgs - i + cNamedArgs - 1;
- if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
- VariantClear(&op.dp.rgvarg[n]);
- }
+ ole_variant_clear(&op.dp.rgvarg[n]);
}
}
}
@@ -2767,7 +2776,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
}
else {
for(i = 0; i < op.dp.cArgs; i++) {
- VariantClear(&op.dp.rgvarg[i]);
+ ole_variant_clear(&op.dp.rgvarg[i]);
}
}
@@ -2778,7 +2787,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
StringValuePtr(v));
}
obj = ole_variant2val(&result);
- VariantClear(&result);
+ ole_variant_clear(&result);
return obj;
}
@@ -2987,7 +2996,7 @@ ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
}
obj = ole_variant2val(&result);
- VariantClear(&result);
+ ole_variant_clear(&result);
return obj;
}
@@ -3156,7 +3165,7 @@ ole_propertyput(VALUE self, VALUE property, VALUE value)
NULL, &excepinfo, &argErr);
for(index = 0; index < dispParams.cArgs; ++index) {
- VariantClear(&propertyValue[index]);
+ ole_variant_clear(&propertyValue[index]);
}
if (FAILED(hr)) {
v = ole_excepinfo2msg(&excepinfo);
@@ -3195,7 +3204,7 @@ ole_each_sub(VALUE pEnumV)
VariantInit(&variant);
while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
obj = ole_variant2val(&variant);
- VariantClear(&variant);
+ ole_variant_clear(&variant);
VariantInit(&variant);
rb_yield(obj);
}
@@ -3256,7 +3265,7 @@ fole_each(VALUE self)
&excepinfo, &argErr);
if (FAILED(hr)) {
- VariantClear(&result);
+ ole_variant_clear(&result);
ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface");
}
@@ -3272,11 +3281,11 @@ fole_each(VALUE self)
pEnum = p;
}
if (FAILED(hr) || !pEnum) {
- VariantClear(&result);
+ ole_variant_clear(&result);
ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface");
}
- VariantClear(&result);
+ ole_variant_clear(&result);
rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
return Qnil;
}
diff --git a/ext/win32ole/win32ole.h b/ext/win32ole/win32ole.h
index d61f5e2..ecf0b22 100644
--- a/ext/win32ole/win32ole.h
+++ b/ext/win32ole/win32ole.h
@@ -137,6 +137,7 @@ 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);
+void ole_variant_clear(VARIANT *pvar);
HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c
index 28d6238..69fb213 100644
--- a/ext/win32ole/win32ole_record.c
+++ b/ext/win32ole/win32ole_record.c
@@ -2,7 +2,6 @@
struct olerecorddata {
IRecordInfo *pri;
- void *pdata;
};
static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
@@ -59,7 +58,7 @@ recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri)
}
static int
-hash2olerec(VALUE key, VALUE val, VALUE rec)
+hash2olerec(VALUE key, VALUE val, VALUE ary)
{
VARIANT var;
OLECHAR *pbuf;
@@ -68,14 +67,14 @@ hash2olerec(VALUE key, VALUE val, VALUE rec)
HRESULT hr;
if (val != Qnil) {
- TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
+ TypedData_Get_Struct(RARRAY_PTR(ary)[0], struct olerecorddata, &olerecord_datatype, prec);
pri = prec->pri;
VariantInit(&var);
ole_val2variant(val, &var);
pbuf = ole_vstr2wc(key);
- hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, prec->pdata, pbuf, &var);
+ hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, (void *)NUM2SIZET(RARRAY_PTR(ary)[1]), pbuf, &var);
SysFreeString(pbuf);
- VariantClear(&var);
+ ole_variant_clear(&var);
if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError, "failed to putfield of `%s`", StringValuePtr(key));
}
@@ -91,6 +90,7 @@ ole_rec2variant(VALUE rec, VARIANT *var)
IRecordInfo *pri;
HRESULT hr;
VALUE fields;
+ void *pdata;
TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
pri = prec->pri;
if (pri) {
@@ -98,21 +98,19 @@ ole_rec2variant(VALUE rec, VARIANT *var)
if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError, "failed to get size for allocation of VT_RECORD object");
}
- if (prec->pdata) {
- free(prec->pdata);
- }
- prec->pdata = ALLOC_N(char, size);
- if (!prec->pdata) {
+ pdata = pri->lpVtbl->RecordCreate(pri);
+ if (!pdata) {
rb_raise(rb_eRuntimeError, "failed to memory allocation of %lu bytes", (unsigned long)size);
}
- hr = pri->lpVtbl->RecordInit(pri, prec->pdata);
+ hr = pri->lpVtbl->RecordInit(pri, pdata);
if (FAILED(hr)) {
ole_raise(hr, eWIN32OLERuntimeError, "failed to initialize VT_RECORD object");
}
fields = folerecord_to_h(rec);
- rb_hash_foreach(fields, hash2olerec, rec);
+ rb_hash_foreach(fields, hash2olerec, rb_ary_new3(2, rec, SIZET2NUM((char *)pdata - (char *)NULL)));
+ pri->lpVtbl->AddRef(pri);
V_RECORDINFO(var) = pri;
- V_RECORD(var) = prec->pdata;
+ V_RECORD(var) = pdata;
V_VT(var) = VT_RECORD;
} else {
rb_raise(eWIN32OLERuntimeError, "failed to retrieve IRecordInfo interface");
@@ -216,9 +214,6 @@ static void
olerecord_free(void *ptr) {
struct olerecorddata *pvar = ptr;
OLE_FREE(pvar->pri);
- if (pvar->pdata) {
- free(pvar->pdata);
- }
free(pvar);
}
@@ -247,7 +242,6 @@ folerecord_s_allocate(VALUE klass) {
struct olerecorddata *pvar;
obj = TypedData_Make_Struct(klass, struct olerecorddata, &olerecord_datatype, pvar);
pvar->pri = NULL;
- pvar->pdata = NULL;
return obj;
}
diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c
index 1731ab7..63a8a94 100644
--- a/ext/win32ole/win32ole_variant.c
+++ b/ext/win32ole/win32ole_variant.c
@@ -33,8 +33,8 @@ static void
olevariant_free(void *ptr)
{
struct olevariantdata *pvar = ptr;
- VariantClear(&(pvar->realvar));
- VariantClear(&(pvar->var));
+ ole_variant_clear(&(pvar->realvar));
+ ole_variant_clear(&(pvar->var));
free(pvar);
}

    (1-1/1)