Project

General

Profile

Bug #10697 » patch.txt

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

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

    
7
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
8
index 582ff32..11e4a3c 100644
9
--- a/ext/win32ole/win32ole.c
10
+++ b/ext/win32ole/win32ole.c
11
@@ -2509,7 +2509,7 @@ hash2named_arg(VALUE key, VALUE val, VALUE pop)
12
         }
13
         /* clear dispatch parameters */
14
         for(i = 0; i < index; i++ ) {
15
-            VariantClear(&(pOp->dp.rgvarg[i]));
16
+            ole_variant_clear(&(pOp->dp.rgvarg[i]));
17
         }
18
         /* raise an exception */
19
         rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
20
@@ -2528,6 +2528,19 @@ hash2named_arg(VALUE key, VALUE val, VALUE pop)
21
     return ST_CONTINUE;
22
 }
23
 
24
+void
25
+ole_variant_clear(VARIANT *pvar)
26
+{
27
+    if (V_VT(pvar) != VT_RECORD) {
28
+        VariantClear(pvar);
29
+    } else {
30
+        IRecordInfo *pri = V_RECORDINFO(pvar);
31
+        pri->lpVtbl->RecordDestroy(pri, V_RECORD(pvar));
32
+        pri->lpVtbl->Release(pri);
33
+        V_VT(pvar) = VT_EMPTY;
34
+    }
35
+}
36
+
37
 static VALUE
38
 set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
39
 {
40
@@ -2537,9 +2550,7 @@ set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
41
     rb_ary_clear(argv);
42
     while (end-- > beg) {
43
         rb_ary_push(argv, ole_variant2val(&realargs[end]));
44
-        if (V_VT(&realargs[end]) != VT_RECORD) {
45
-            VariantClear(&realargs[end]);
46
-        }
47
+        ole_variant_clear(&realargs[end]);
48
     }
49
     return argv;
50
 }
51
@@ -2635,7 +2646,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
52
         if(FAILED(hr)) {
53
             /* clear dispatch parameters */
54
             for(i = 0; i < op.dp.cArgs; i++ ) {
55
-                VariantClear(&op.dp.rgvarg[i]);
56
+                ole_variant_clear(&op.dp.rgvarg[i]);
57
             }
58
             ole_raise(hr, eWIN32OLERuntimeError,
59
                       "failed to get named argument info: `%s'",
60
@@ -2719,7 +2730,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
61
             for(i = cNamedArgs; i < op.dp.cArgs; i++) {
62
                 n = op.dp.cArgs - i + cNamedArgs - 1;
63
                 if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
64
-                    VariantClear(&op.dp.rgvarg[n]);
65
+                    ole_variant_clear(&op.dp.rgvarg[n]);
66
                 }
67
             }
68
         }
69
@@ -2743,9 +2754,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
70
                         &excepinfo, &argErr);
71
                 for(i = cNamedArgs; i < op.dp.cArgs; i++) {
72
                     n = op.dp.cArgs - i + cNamedArgs - 1;
73
-                    if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
74
-                        VariantClear(&op.dp.rgvarg[n]);
75
-                    }
76
+                    ole_variant_clear(&op.dp.rgvarg[n]);
77
                 }
78
             }
79
         }
80
@@ -2767,7 +2776,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
81
     }
82
     else {
83
         for(i = 0; i < op.dp.cArgs; i++) {
84
-            VariantClear(&op.dp.rgvarg[i]);
85
+            ole_variant_clear(&op.dp.rgvarg[i]);
86
         }
87
     }
88
 
89
@@ -2778,7 +2787,7 @@ ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
90
                   StringValuePtr(v));
91
     }
92
     obj = ole_variant2val(&result);
93
-    VariantClear(&result);
94
+    ole_variant_clear(&result);
95
     return obj;
96
 }
97
 
98
@@ -2987,7 +2996,7 @@ ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
99
     }
100
 
101
     obj = ole_variant2val(&result);
102
-    VariantClear(&result);
103
+    ole_variant_clear(&result);
104
     return obj;
105
 }
106
 
107
@@ -3156,7 +3165,7 @@ ole_propertyput(VALUE self, VALUE property, VALUE value)
108
                                          NULL, &excepinfo, &argErr);
109
 
110
     for(index = 0; index < dispParams.cArgs; ++index) {
111
-        VariantClear(&propertyValue[index]);
112
+        ole_variant_clear(&propertyValue[index]);
113
     }
114
     if (FAILED(hr)) {
115
         v = ole_excepinfo2msg(&excepinfo);
116
@@ -3195,7 +3204,7 @@ ole_each_sub(VALUE pEnumV)
117
     VariantInit(&variant);
118
     while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
119
         obj = ole_variant2val(&variant);
120
-        VariantClear(&variant);
121
+        ole_variant_clear(&variant);
122
         VariantInit(&variant);
123
         rb_yield(obj);
124
     }
125
@@ -3256,7 +3265,7 @@ fole_each(VALUE self)
126
                                          &excepinfo, &argErr);
127
 
128
     if (FAILED(hr)) {
129
-        VariantClear(&result);
130
+        ole_variant_clear(&result);
131
         ole_raise(hr, eWIN32OLERuntimeError, "failed to get IEnum Interface");
132
     }
133
 
134
@@ -3272,11 +3281,11 @@ fole_each(VALUE self)
135
         pEnum = p;
136
     }
137
     if (FAILED(hr) || !pEnum) {
138
-        VariantClear(&result);
139
+        ole_variant_clear(&result);
140
         ole_raise(hr, rb_eRuntimeError, "failed to get IEnum Interface");
141
     }
142
 
143
-    VariantClear(&result);
144
+    ole_variant_clear(&result);
145
     rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
146
     return Qnil;
147
 }
148
diff --git a/ext/win32ole/win32ole.h b/ext/win32ole/win32ole.h
149
index d61f5e2..ecf0b22 100644
150
--- a/ext/win32ole/win32ole.h
151
+++ b/ext/win32ole/win32ole.h
152
@@ -137,6 +137,7 @@ void ole_val2variant(VALUE val, VARIANT *var);
153
 void ole_val2variant2(VALUE val, VARIANT *var);
154
 void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
155
 VALUE ole_variant2val(VARIANT *pvar);
156
+void ole_variant_clear(VARIANT *pvar);
157
 HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
158
 VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
159
 HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
160
diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c
161
index 28d6238..69fb213 100644
162
--- a/ext/win32ole/win32ole_record.c
163
+++ b/ext/win32ole/win32ole_record.c
164
@@ -2,7 +2,6 @@
165
 
166
 struct olerecorddata {
167
     IRecordInfo *pri;
168
-    void *pdata;
169
 };
170
 
171
 static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
172
@@ -59,7 +58,7 @@ recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri)
173
 }
174
 
175
 static int
176
-hash2olerec(VALUE key, VALUE val, VALUE rec)
177
+hash2olerec(VALUE key, VALUE val, VALUE ary)
178
 {
179
     VARIANT var;
180
     OLECHAR *pbuf;
181
@@ -68,14 +67,14 @@ hash2olerec(VALUE key, VALUE val, VALUE rec)
182
     HRESULT hr;
183
 
184
     if (val != Qnil) {
185
-        TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
186
+        TypedData_Get_Struct(RARRAY_PTR(ary)[0], struct olerecorddata, &olerecord_datatype, prec);
187
         pri = prec->pri;
188
         VariantInit(&var);
189
         ole_val2variant(val, &var);
190
         pbuf = ole_vstr2wc(key);
191
-        hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, prec->pdata, pbuf, &var);
192
+        hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, (void *)NUM2SIZET(RARRAY_PTR(ary)[1]), pbuf, &var);
193
         SysFreeString(pbuf);
194
-        VariantClear(&var);
195
+        ole_variant_clear(&var);
196
         if (FAILED(hr)) {
197
             ole_raise(hr, eWIN32OLERuntimeError, "failed to putfield of `%s`", StringValuePtr(key));
198
         }
199
@@ -91,6 +90,7 @@ ole_rec2variant(VALUE rec, VARIANT *var)
200
     IRecordInfo *pri;
201
     HRESULT hr;
202
     VALUE fields;
203
+    void *pdata;
204
     TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
205
     pri = prec->pri;
206
     if (pri) {
207
@@ -98,21 +98,19 @@ ole_rec2variant(VALUE rec, VARIANT *var)
208
         if (FAILED(hr)) {
209
             ole_raise(hr, eWIN32OLERuntimeError, "failed to get size for allocation of VT_RECORD object");
210
         }
211
-        if (prec->pdata) {
212
-            free(prec->pdata);
213
-        }
214
-        prec->pdata = ALLOC_N(char, size);
215
-        if (!prec->pdata) {
216
+        pdata = pri->lpVtbl->RecordCreate(pri);
217
+        if (!pdata) {
218
             rb_raise(rb_eRuntimeError, "failed to memory allocation of %lu bytes", (unsigned long)size);
219
         }
220
-        hr = pri->lpVtbl->RecordInit(pri, prec->pdata);
221
+        hr = pri->lpVtbl->RecordInit(pri, pdata);
222
         if (FAILED(hr)) {
223
             ole_raise(hr, eWIN32OLERuntimeError, "failed to initialize VT_RECORD object");
224
         }
225
         fields = folerecord_to_h(rec);
226
-        rb_hash_foreach(fields, hash2olerec, rec);
227
+        rb_hash_foreach(fields, hash2olerec, rb_ary_new3(2, rec, SIZET2NUM((char *)pdata - (char *)NULL)));
228
+        pri->lpVtbl->AddRef(pri);
229
         V_RECORDINFO(var) = pri;
230
-        V_RECORD(var) = prec->pdata;
231
+        V_RECORD(var) = pdata;
232
         V_VT(var) = VT_RECORD;
233
     } else {
234
         rb_raise(eWIN32OLERuntimeError, "failed to retrieve IRecordInfo interface");
235
@@ -216,9 +214,6 @@ static void
236
 olerecord_free(void *ptr) {
237
     struct olerecorddata *pvar = ptr;
238
     OLE_FREE(pvar->pri);
239
-    if (pvar->pdata) {
240
-        free(pvar->pdata);
241
-    }
242
     free(pvar);
243
 }
244
 
245
@@ -247,7 +242,6 @@ folerecord_s_allocate(VALUE klass) {
246
     struct olerecorddata *pvar;
247
     obj = TypedData_Make_Struct(klass, struct olerecorddata, &olerecord_datatype, pvar);
248
     pvar->pri = NULL;
249
-    pvar->pdata = NULL;
250
     return obj;
251
 }
252
 
253
diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c
254
index 1731ab7..63a8a94 100644
255
--- a/ext/win32ole/win32ole_variant.c
256
+++ b/ext/win32ole/win32ole_variant.c
257
@@ -33,8 +33,8 @@ static void
258
 olevariant_free(void *ptr)
259
 {
260
     struct olevariantdata *pvar = ptr;
261
-    VariantClear(&(pvar->realvar));
262
-    VariantClear(&(pvar->var));
263
+    ole_variant_clear(&(pvar->realvar));
264
+    ole_variant_clear(&(pvar->var));
265
     free(pvar);
266
 }
267
 
268