|
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);
|
|
}
|
|
|
|
|