win32ole 1.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +56 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/ext/win32ole/depend +12 -0
  11. data/ext/win32ole/extconf.rb +45 -0
  12. data/ext/win32ole/sample/excel1.rb +37 -0
  13. data/ext/win32ole/sample/excel2.rb +31 -0
  14. data/ext/win32ole/sample/excel3.rb +21 -0
  15. data/ext/win32ole/sample/ie.rb +12 -0
  16. data/ext/win32ole/sample/ieconst.rb +33 -0
  17. data/ext/win32ole/sample/ienavi.rb +41 -0
  18. data/ext/win32ole/sample/ienavi2.rb +41 -0
  19. data/ext/win32ole/sample/oledirs.rb +24 -0
  20. data/ext/win32ole/sample/olegen.rb +348 -0
  21. data/ext/win32ole/sample/xml.rb +7307 -0
  22. data/ext/win32ole/win32ole.c +4140 -0
  23. data/ext/win32ole/win32ole.h +155 -0
  24. data/ext/win32ole/win32ole_error.c +84 -0
  25. data/ext/win32ole/win32ole_error.h +9 -0
  26. data/ext/win32ole/win32ole_event.c +1277 -0
  27. data/ext/win32ole/win32ole_event.h +6 -0
  28. data/ext/win32ole/win32ole_method.c +950 -0
  29. data/ext/win32ole/win32ole_method.h +16 -0
  30. data/ext/win32ole/win32ole_param.c +438 -0
  31. data/ext/win32ole/win32ole_param.h +8 -0
  32. data/ext/win32ole/win32ole_record.c +604 -0
  33. data/ext/win32ole/win32ole_record.h +10 -0
  34. data/ext/win32ole/win32ole_type.c +915 -0
  35. data/ext/win32ole/win32ole_type.h +8 -0
  36. data/ext/win32ole/win32ole_typelib.c +844 -0
  37. data/ext/win32ole/win32ole_typelib.h +11 -0
  38. data/ext/win32ole/win32ole_variable.c +380 -0
  39. data/ext/win32ole/win32ole_variable.h +8 -0
  40. data/ext/win32ole/win32ole_variant.c +733 -0
  41. data/ext/win32ole/win32ole_variant.h +9 -0
  42. data/ext/win32ole/win32ole_variant_m.c +149 -0
  43. data/ext/win32ole/win32ole_variant_m.h +7 -0
  44. data/lib/win32ole.rb +33 -0
  45. data/lib/win32ole/property.rb +17 -0
  46. data/win32ole.gemspec +22 -0
  47. metadata +91 -0
@@ -0,0 +1,11 @@
1
+ #ifndef WIN32OLE_TYPELIB_H
2
+ #define WIN32OLE_TYPELIB_H 1
3
+
4
+ VALUE cWIN32OLE_TYPELIB;
5
+
6
+ void Init_win32ole_typelib(void);
7
+ ITypeLib * itypelib(VALUE self);
8
+ VALUE typelib_file(VALUE ole);
9
+ VALUE create_win32ole_typelib(ITypeLib *pTypeLib);
10
+ VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo);
11
+ #endif
@@ -0,0 +1,380 @@
1
+ #include "win32ole.h"
2
+
3
+ struct olevariabledata {
4
+ ITypeInfo *pTypeInfo;
5
+ UINT index;
6
+ };
7
+
8
+ static void olevariable_free(void *ptr);
9
+ static size_t olevariable_size(const void *ptr);
10
+ static VALUE folevariable_name(VALUE self);
11
+ static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index);
12
+ static VALUE folevariable_ole_type(VALUE self);
13
+ static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index);
14
+ static VALUE folevariable_ole_type_detail(VALUE self);
15
+ static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index);
16
+ static VALUE folevariable_value(VALUE self);
17
+ static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index);
18
+ static VALUE folevariable_visible(VALUE self);
19
+ static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index);
20
+ static VALUE folevariable_variable_kind(VALUE self);
21
+ static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index);
22
+ static VALUE folevariable_varkind(VALUE self);
23
+ static VALUE folevariable_inspect(VALUE self);
24
+
25
+ static const rb_data_type_t olevariable_datatype = {
26
+ "win32ole_variable",
27
+ {NULL, olevariable_free, olevariable_size,},
28
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
29
+ };
30
+
31
+ static void
32
+ olevariable_free(void *ptr)
33
+ {
34
+ struct olevariabledata *polevar = ptr;
35
+ OLE_FREE(polevar->pTypeInfo);
36
+ free(polevar);
37
+ }
38
+
39
+ static size_t
40
+ olevariable_size(const void *ptr)
41
+ {
42
+ return ptr ? sizeof(struct olevariabledata) : 0;
43
+ }
44
+
45
+ /*
46
+ * Document-class: WIN32OLE_VARIABLE
47
+ *
48
+ * <code>WIN32OLE_VARIABLE</code> objects represent OLE variable information.
49
+ */
50
+
51
+ VALUE
52
+ create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name)
53
+ {
54
+ struct olevariabledata *pvar;
55
+ VALUE obj = TypedData_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata,
56
+ &olevariable_datatype, pvar);
57
+ pvar->pTypeInfo = pTypeInfo;
58
+ OLE_ADDREF(pTypeInfo);
59
+ pvar->index = index;
60
+ rb_ivar_set(obj, rb_intern("name"), name);
61
+ return obj;
62
+ }
63
+
64
+ /*
65
+ * call-seq:
66
+ * WIN32OLE_VARIABLE#name
67
+ *
68
+ * Returns the name of variable.
69
+ *
70
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
71
+ * variables = tobj.variables
72
+ * variables.each do |variable|
73
+ * puts "#{variable.name}"
74
+ * end
75
+ *
76
+ * The result of above script is following:
77
+ * xlChart
78
+ * xlDialogSheet
79
+ * xlExcel4IntlMacroSheet
80
+ * xlExcel4MacroSheet
81
+ * xlWorksheet
82
+ *
83
+ */
84
+ static VALUE
85
+ folevariable_name(VALUE self)
86
+ {
87
+ return rb_ivar_get(self, rb_intern("name"));
88
+ }
89
+
90
+ static VALUE
91
+ ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
92
+ {
93
+ VARDESC *pVarDesc;
94
+ HRESULT hr;
95
+ VALUE type;
96
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
97
+ if (FAILED(hr))
98
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
99
+ type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil);
100
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
101
+ return type;
102
+ }
103
+
104
+ /*
105
+ * call-seq:
106
+ * WIN32OLE_VARIABLE#ole_type
107
+ *
108
+ * Returns OLE type string.
109
+ *
110
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
111
+ * variables = tobj.variables
112
+ * variables.each do |variable|
113
+ * puts "#{variable.ole_type} #{variable.name}"
114
+ * end
115
+ *
116
+ * The result of above script is following:
117
+ * INT xlChart
118
+ * INT xlDialogSheet
119
+ * INT xlExcel4IntlMacroSheet
120
+ * INT xlExcel4MacroSheet
121
+ * INT xlWorksheet
122
+ *
123
+ */
124
+ static VALUE
125
+ folevariable_ole_type(VALUE self)
126
+ {
127
+ struct olevariabledata *pvar;
128
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
129
+ return ole_variable_ole_type(pvar->pTypeInfo, pvar->index);
130
+ }
131
+
132
+ static VALUE
133
+ ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
134
+ {
135
+ VARDESC *pVarDesc;
136
+ HRESULT hr;
137
+ VALUE type = rb_ary_new();
138
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
139
+ if (FAILED(hr))
140
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
141
+ ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type);
142
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
143
+ return type;
144
+ }
145
+
146
+ /*
147
+ * call-seq:
148
+ * WIN32OLE_VARIABLE#ole_type_detail
149
+ *
150
+ * Returns detail information of type. The information is array of type.
151
+ *
152
+ * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
153
+ * variable = tobj.variables.find {|variable| variable.name == 'lFlags'}
154
+ * tdetail = variable.ole_type_detail
155
+ * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"]
156
+ *
157
+ */
158
+ static VALUE
159
+ folevariable_ole_type_detail(VALUE self)
160
+ {
161
+ struct olevariabledata *pvar;
162
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
163
+ return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index);
164
+ }
165
+
166
+ static VALUE
167
+ ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
168
+ {
169
+ VARDESC *pVarDesc;
170
+ HRESULT hr;
171
+ VALUE val = Qnil;
172
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
173
+ if (FAILED(hr))
174
+ return Qnil;
175
+ if(pVarDesc->varkind == VAR_CONST)
176
+ val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
177
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
178
+ return val;
179
+ }
180
+
181
+ /*
182
+ * call-seq:
183
+ * WIN32OLE_VARIABLE#value
184
+ *
185
+ * Returns value if value is exists. If the value does not exist,
186
+ * this method returns nil.
187
+ *
188
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
189
+ * variables = tobj.variables
190
+ * variables.each do |variable|
191
+ * puts "#{variable.name} #{variable.value}"
192
+ * end
193
+ *
194
+ * The result of above script is following:
195
+ * xlChart = -4109
196
+ * xlDialogSheet = -4116
197
+ * xlExcel4IntlMacroSheet = 4
198
+ * xlExcel4MacroSheet = 3
199
+ * xlWorksheet = -4167
200
+ *
201
+ */
202
+ static VALUE
203
+ folevariable_value(VALUE self)
204
+ {
205
+ struct olevariabledata *pvar;
206
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
207
+ return ole_variable_value(pvar->pTypeInfo, pvar->index);
208
+ }
209
+
210
+ static VALUE
211
+ ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
212
+ {
213
+ VARDESC *pVarDesc;
214
+ HRESULT hr;
215
+ VALUE visible = Qfalse;
216
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
217
+ if (FAILED(hr))
218
+ return visible;
219
+ if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
220
+ VARFLAG_FRESTRICTED |
221
+ VARFLAG_FNONBROWSABLE))) {
222
+ visible = Qtrue;
223
+ }
224
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
225
+ return visible;
226
+ }
227
+
228
+ /*
229
+ * call-seq:
230
+ * WIN32OLE_VARIABLE#visible?
231
+ *
232
+ * Returns true if the variable is public.
233
+ *
234
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
235
+ * variables = tobj.variables
236
+ * variables.each do |variable|
237
+ * puts "#{variable.name} #{variable.visible?}"
238
+ * end
239
+ *
240
+ * The result of above script is following:
241
+ * xlChart true
242
+ * xlDialogSheet true
243
+ * xlExcel4IntlMacroSheet true
244
+ * xlExcel4MacroSheet true
245
+ * xlWorksheet true
246
+ *
247
+ */
248
+ static VALUE
249
+ folevariable_visible(VALUE self)
250
+ {
251
+ struct olevariabledata *pvar;
252
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
253
+ return ole_variable_visible(pvar->pTypeInfo, pvar->index);
254
+ }
255
+
256
+ static VALUE
257
+ ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
258
+ {
259
+ VARDESC *pVarDesc;
260
+ HRESULT hr;
261
+ VALUE kind = rb_str_new2("UNKNOWN");
262
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
263
+ if (FAILED(hr))
264
+ return kind;
265
+ switch(pVarDesc->varkind) {
266
+ case VAR_PERINSTANCE:
267
+ kind = rb_str_new2("PERINSTANCE");
268
+ break;
269
+ case VAR_STATIC:
270
+ kind = rb_str_new2("STATIC");
271
+ break;
272
+ case VAR_CONST:
273
+ kind = rb_str_new2("CONSTANT");
274
+ break;
275
+ case VAR_DISPATCH:
276
+ kind = rb_str_new2("DISPATCH");
277
+ break;
278
+ default:
279
+ break;
280
+ }
281
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
282
+ return kind;
283
+ }
284
+
285
+ /*
286
+ * call-seq:
287
+ * WIN32OLE_VARIABLE#variable_kind
288
+ *
289
+ * Returns variable kind string.
290
+ *
291
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
292
+ * variables = tobj.variables
293
+ * variables.each do |variable|
294
+ * puts "#{variable.name} #{variable.variable_kind}"
295
+ * end
296
+ *
297
+ * The result of above script is following:
298
+ * xlChart CONSTANT
299
+ * xlDialogSheet CONSTANT
300
+ * xlExcel4IntlMacroSheet CONSTANT
301
+ * xlExcel4MacroSheet CONSTANT
302
+ * xlWorksheet CONSTANT
303
+ */
304
+ static VALUE
305
+ folevariable_variable_kind(VALUE self)
306
+ {
307
+ struct olevariabledata *pvar;
308
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
309
+ return ole_variable_kind(pvar->pTypeInfo, pvar->index);
310
+ }
311
+
312
+ static VALUE
313
+ ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
314
+ {
315
+ VARDESC *pVarDesc;
316
+ HRESULT hr;
317
+ VALUE kind = Qnil;
318
+ hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
319
+ if (FAILED(hr))
320
+ return kind;
321
+ pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
322
+ kind = RB_INT2FIX(pVarDesc->varkind);
323
+ return kind;
324
+ }
325
+
326
+ /*
327
+ * call-seq:
328
+ * WIN32OLE_VARIABLE#varkind
329
+ *
330
+ * Returns the number which represents variable kind.
331
+ * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
332
+ * variables = tobj.variables
333
+ * variables.each do |variable|
334
+ * puts "#{variable.name} #{variable.varkind}"
335
+ * end
336
+ *
337
+ * The result of above script is following:
338
+ * xlChart 2
339
+ * xlDialogSheet 2
340
+ * xlExcel4IntlMacroSheet 2
341
+ * xlExcel4MacroSheet 2
342
+ * xlWorksheet 2
343
+ */
344
+ static VALUE
345
+ folevariable_varkind(VALUE self)
346
+ {
347
+ struct olevariabledata *pvar;
348
+ TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
349
+ return ole_variable_varkind(pvar->pTypeInfo, pvar->index);
350
+ }
351
+
352
+ /*
353
+ * call-seq:
354
+ * WIN32OLE_VARIABLE#inspect -> String
355
+ *
356
+ * Returns the OLE variable name and the value with class name.
357
+ *
358
+ */
359
+ static VALUE
360
+ folevariable_inspect(VALUE self)
361
+ {
362
+ VALUE v = rb_inspect(folevariable_value(self));
363
+ VALUE n = folevariable_name(self);
364
+ VALUE detail = rb_sprintf("%"PRIsVALUE"=%"PRIsVALUE, n, v);
365
+ return make_inspect("WIN32OLE_VARIABLE", detail);
366
+ }
367
+
368
+ void Init_win32ole_variable(void)
369
+ {
370
+ cWIN32OLE_VARIABLE = rb_define_class("WIN32OLE_VARIABLE", rb_cObject);
371
+ rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
372
+ rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0);
373
+ rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0);
374
+ rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0);
375
+ rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0);
376
+ rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0);
377
+ rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0);
378
+ rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0);
379
+ rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name");
380
+ }
@@ -0,0 +1,8 @@
1
+ #ifndef WIN32OLE_VARIABLE_H
2
+ #define WIN32OLE_VARIABLE_H 1
3
+
4
+ VALUE cWIN32OLE_VARIABLE;
5
+ VALUE create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name);
6
+ void Init_win32ole_variable(void);
7
+
8
+ #endif
@@ -0,0 +1,733 @@
1
+ #include "win32ole.h"
2
+
3
+ struct olevariantdata {
4
+ VARIANT realvar;
5
+ VARIANT var;
6
+ };
7
+
8
+ static void olevariant_free(void *ptr);
9
+ static size_t olevariant_size(const void *ptr);
10
+ static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
11
+ static void ole_val2variant_err(VALUE val, VARIANT *var);
12
+ static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
13
+ static VALUE folevariant_s_allocate(VALUE klass);
14
+ static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
15
+ static void check_type_val2variant(VALUE val);
16
+ static VALUE folevariant_initialize(VALUE self, VALUE args);
17
+ static LONG *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
18
+ static void unlock_safe_array(SAFEARRAY *psa);
19
+ static SAFEARRAY *get_locked_safe_array(VALUE val);
20
+ static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
21
+ static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
22
+ static VALUE folevariant_value(VALUE self);
23
+ static VALUE folevariant_vartype(VALUE self);
24
+ static VALUE folevariant_set_value(VALUE self, VALUE val);
25
+
26
+ static const rb_data_type_t olevariant_datatype = {
27
+ "win32ole_variant",
28
+ {NULL, olevariant_free, olevariant_size,},
29
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
30
+ };
31
+
32
+ static void
33
+ olevariant_free(void *ptr)
34
+ {
35
+ struct olevariantdata *pvar = ptr;
36
+ VariantClear(&(pvar->realvar));
37
+ VariantClear(&(pvar->var));
38
+ free(pvar);
39
+ }
40
+
41
+ static size_t
42
+ olevariant_size(const void *ptr)
43
+ {
44
+ return ptr ? sizeof(struct olevariantdata) : 0;
45
+ }
46
+
47
+ static void
48
+ ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
49
+ {
50
+ HRESULT hr = S_OK;
51
+
52
+ if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) {
53
+ long len = RSTRING_LEN(val);
54
+ void *pdest = NULL;
55
+ SAFEARRAY *p = NULL;
56
+ SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
57
+ if (!psa) {
58
+ rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
59
+ }
60
+ hr = SafeArrayAccessData(psa, &pdest);
61
+ if (SUCCEEDED(hr)) {
62
+ memcpy(pdest, RSTRING_PTR(val), len);
63
+ SafeArrayUnaccessData(psa);
64
+ V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
65
+ p = V_ARRAY(&(pvar->realvar));
66
+ if (p != NULL) {
67
+ SafeArrayDestroy(p);
68
+ }
69
+ V_ARRAY(&(pvar->realvar)) = psa;
70
+ if (vt & VT_BYREF) {
71
+ V_VT(&(pvar->var)) = vt;
72
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
73
+ } else {
74
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
75
+ }
76
+ } else {
77
+ if (psa)
78
+ SafeArrayDestroy(psa);
79
+ }
80
+ } else if (vt & VT_ARRAY) {
81
+ if (val == Qnil) {
82
+ V_VT(&(pvar->var)) = vt;
83
+ if (vt & VT_BYREF) {
84
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
85
+ }
86
+ } else {
87
+ hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
88
+ if (SUCCEEDED(hr)) {
89
+ if (vt & VT_BYREF) {
90
+ V_VT(&(pvar->var)) = vt;
91
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
92
+ } else {
93
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
94
+ }
95
+ }
96
+ }
97
+ #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
98
+ } else if ( (vt & ~VT_BYREF) == VT_I8 || (vt & ~VT_BYREF) == VT_UI8) {
99
+ ole_val2variant_ex(val, &(pvar->realvar), (vt & ~VT_BYREF));
100
+ ole_val2variant_ex(val, &(pvar->var), (vt & ~VT_BYREF));
101
+ V_VT(&(pvar->var)) = vt;
102
+ if (vt & VT_BYREF) {
103
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
104
+ }
105
+ #endif
106
+ } else if ( (vt & ~VT_BYREF) == VT_ERROR) {
107
+ ole_val2variant_err(val, &(pvar->realvar));
108
+ if (vt & VT_BYREF) {
109
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
110
+ } else {
111
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
112
+ }
113
+ } else {
114
+ if (val == Qnil) {
115
+ V_VT(&(pvar->var)) = vt;
116
+ if (vt == (VT_BYREF | VT_VARIANT)) {
117
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
118
+ } else {
119
+ V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
120
+ if (vt & VT_BYREF) {
121
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
122
+ }
123
+ }
124
+ } else {
125
+ ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
126
+ if (vt == (VT_BYREF | VT_VARIANT)) {
127
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
128
+ } else if (vt & VT_BYREF) {
129
+ if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
130
+ hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
131
+ cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
132
+ }
133
+ if (SUCCEEDED(hr)) {
134
+ ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
135
+ }
136
+ } else {
137
+ if (vt == V_VT(&(pvar->realvar))) {
138
+ hr = VariantCopy(&(pvar->var), &(pvar->realvar));
139
+ } else {
140
+ hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
141
+ cWIN32OLE_lcid, 0, vt);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ if (FAILED(hr)) {
147
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
148
+ }
149
+ }
150
+
151
+ static void
152
+ ole_val2variant_err(VALUE val, VARIANT *var)
153
+ {
154
+ VALUE v = val;
155
+ if (rb_obj_is_kind_of(v, cWIN32OLE_VARIANT)) {
156
+ v = folevariant_value(v);
157
+ }
158
+ if (!(FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || v == Qnil)) {
159
+ rb_raise(eWIN32OLERuntimeError, "failed to convert VT_ERROR VARIANT:`%"PRIsVALUE"'", rb_inspect(v));
160
+ }
161
+ V_VT(var) = VT_ERROR;
162
+ if (v != Qnil) {
163
+ V_ERROR(var) = RB_NUM2LONG(val);
164
+ } else {
165
+ V_ERROR(var) = 0;
166
+ }
167
+ }
168
+
169
+ static void
170
+ ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
171
+ {
172
+ V_VT(var) = vt;
173
+ if (vt == (VT_VARIANT|VT_BYREF)) {
174
+ V_VARIANTREF(var) = realvar;
175
+ } else {
176
+ if (V_VT(realvar) != (vt & ~VT_BYREF)) {
177
+ rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
178
+ }
179
+ switch(vt & ~VT_BYREF) {
180
+ case VT_I1:
181
+ V_I1REF(var) = &V_I1(realvar);
182
+ break;
183
+ case VT_UI1:
184
+ V_UI1REF(var) = &V_UI1(realvar);
185
+ break;
186
+ case VT_I2:
187
+ V_I2REF(var) = &V_I2(realvar);
188
+ break;
189
+ case VT_UI2:
190
+ V_UI2REF(var) = &V_UI2(realvar);
191
+ break;
192
+ case VT_I4:
193
+ V_I4REF(var) = &V_I4(realvar);
194
+ break;
195
+ case VT_UI4:
196
+ V_UI4REF(var) = &V_UI4(realvar);
197
+ break;
198
+ case VT_R4:
199
+ V_R4REF(var) = &V_R4(realvar);
200
+ break;
201
+ case VT_R8:
202
+ V_R8REF(var) = &V_R8(realvar);
203
+ break;
204
+
205
+ #if (_MSC_VER >= 1300) || defined(__CYGWIN__) || defined(__MINGW32__)
206
+ #ifdef V_I8REF
207
+ case VT_I8:
208
+ V_I8REF(var) = &V_I8(realvar);
209
+ break;
210
+ #endif
211
+ #ifdef V_UI8REF
212
+ case VT_UI8:
213
+ V_UI8REF(var) = &V_UI8(realvar);
214
+ break;
215
+ #endif
216
+ #endif
217
+ case VT_INT:
218
+ V_INTREF(var) = &V_INT(realvar);
219
+ break;
220
+
221
+ case VT_UINT:
222
+ V_UINTREF(var) = &V_UINT(realvar);
223
+ break;
224
+
225
+ case VT_CY:
226
+ V_CYREF(var) = &V_CY(realvar);
227
+ break;
228
+ case VT_DATE:
229
+ V_DATEREF(var) = &V_DATE(realvar);
230
+ break;
231
+ case VT_BSTR:
232
+ V_BSTRREF(var) = &V_BSTR(realvar);
233
+ break;
234
+ case VT_DISPATCH:
235
+ V_DISPATCHREF(var) = &V_DISPATCH(realvar);
236
+ break;
237
+ case VT_ERROR:
238
+ V_ERRORREF(var) = &V_ERROR(realvar);
239
+ break;
240
+ case VT_BOOL:
241
+ V_BOOLREF(var) = &V_BOOL(realvar);
242
+ break;
243
+ case VT_UNKNOWN:
244
+ V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
245
+ break;
246
+ case VT_ARRAY:
247
+ V_ARRAYREF(var) = &V_ARRAY(realvar);
248
+ break;
249
+ default:
250
+ rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
251
+ break;
252
+ }
253
+ }
254
+ }
255
+
256
+ static VALUE
257
+ folevariant_s_allocate(VALUE klass)
258
+ {
259
+ struct olevariantdata *pvar;
260
+ VALUE obj;
261
+ ole_initialize();
262
+ obj = TypedData_Make_Struct(klass, struct olevariantdata, &olevariant_datatype, pvar);
263
+ VariantInit(&(pvar->var));
264
+ VariantInit(&(pvar->realvar));
265
+ return obj;
266
+ }
267
+
268
+ /*
269
+ * call-seq:
270
+ * WIN32OLE_VARIANT.array(ary, vt)
271
+ *
272
+ * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
273
+ * The first argument should be Array object which specifies dimensions
274
+ * and each size of dimensions of OLE array.
275
+ * The second argument specifies variant type of the element of OLE array.
276
+ *
277
+ * The following create 2 dimensions OLE array. The first dimensions size
278
+ * is 3, and the second is 4.
279
+ *
280
+ * ole_ary = WIN32OLE_VARIANT.array([3,4], VT_I4)
281
+ * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
282
+ *
283
+ */
284
+ static VALUE
285
+ folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
286
+ {
287
+ VALUE obj = Qnil;
288
+ VARTYPE vt;
289
+ struct olevariantdata *pvar;
290
+ SAFEARRAYBOUND *psab = NULL;
291
+ SAFEARRAY *psa = NULL;
292
+ UINT dim = 0;
293
+ UINT i = 0;
294
+
295
+ ole_initialize();
296
+
297
+ vt = RB_NUM2UINT(vvt);
298
+ vt = (vt | VT_ARRAY);
299
+ Check_Type(elems, T_ARRAY);
300
+ obj = folevariant_s_allocate(klass);
301
+
302
+ TypedData_Get_Struct(obj, struct olevariantdata, &olevariant_datatype, pvar);
303
+ dim = RARRAY_LEN(elems);
304
+
305
+ psab = ALLOC_N(SAFEARRAYBOUND, dim);
306
+
307
+ if(!psab) {
308
+ rb_raise(rb_eRuntimeError, "memory allocation error");
309
+ }
310
+
311
+ for (i = 0; i < dim; i++) {
312
+ psab[i].cElements = RB_FIX2INT(rb_ary_entry(elems, i));
313
+ psab[i].lLbound = 0;
314
+ }
315
+
316
+ psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
317
+ if (psa == NULL) {
318
+ if (psab) free(psab);
319
+ rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
320
+ }
321
+
322
+ V_VT(&(pvar->var)) = vt;
323
+ if (vt & VT_BYREF) {
324
+ V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
325
+ V_ARRAY(&(pvar->realvar)) = psa;
326
+ V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
327
+ } else {
328
+ V_ARRAY(&(pvar->var)) = psa;
329
+ }
330
+ if (psab) free(psab);
331
+ return obj;
332
+ }
333
+
334
+ static void
335
+ check_type_val2variant(VALUE val)
336
+ {
337
+ VALUE elem;
338
+ int len = 0;
339
+ int i = 0;
340
+ if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
341
+ !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
342
+ !rb_obj_is_kind_of(val, rb_cTime)) {
343
+ switch (TYPE(val)) {
344
+ case T_ARRAY:
345
+ len = RARRAY_LEN(val);
346
+ for(i = 0; i < len; i++) {
347
+ elem = rb_ary_entry(val, i);
348
+ check_type_val2variant(elem);
349
+ }
350
+ break;
351
+ case T_STRING:
352
+ case T_FIXNUM:
353
+ case T_BIGNUM:
354
+ case T_FLOAT:
355
+ case T_TRUE:
356
+ case T_FALSE:
357
+ case T_NIL:
358
+ break;
359
+ default:
360
+ rb_raise(rb_eTypeError, "can not convert WIN32OLE_VARIANT from type %s",
361
+ rb_obj_classname(val));
362
+ }
363
+ }
364
+ }
365
+
366
+ /*
367
+ * Document-class: WIN32OLE_VARIANT
368
+ *
369
+ * <code>WIN32OLE_VARIANT</code> objects represents OLE variant.
370
+ *
371
+ * Win32OLE converts Ruby object into OLE variant automatically when
372
+ * invoking OLE methods. If OLE method requires the argument which is
373
+ * different from the variant by automatic conversion of Win32OLE, you
374
+ * can convert the specfied variant type by using WIN32OLE_VARIANT class.
375
+ *
376
+ * param = WIN32OLE_VARIANT.new(10, WIN32OLE::VARIANT::VT_R4)
377
+ * oleobj.method(param)
378
+ *
379
+ * WIN32OLE_VARIANT does not support VT_RECORD variant. Use WIN32OLE_RECORD
380
+ * class instead of WIN32OLE_VARIANT if the VT_RECORD variant is needed.
381
+ */
382
+
383
+ /*
384
+ * call-seq:
385
+ * WIN32OLE_VARIANT.new(val, vartype) #=> WIN32OLE_VARIANT object.
386
+ *
387
+ * Returns Ruby object wrapping OLE variant.
388
+ * The first argument specifies Ruby object to convert OLE variant variable.
389
+ * The second argument specifies VARIANT type.
390
+ * In some situation, you need the WIN32OLE_VARIANT object to pass OLE method
391
+ *
392
+ * shell = WIN32OLE.new("Shell.Application")
393
+ * folder = shell.NameSpace("C:\\Windows")
394
+ * item = folder.ParseName("tmp.txt")
395
+ * # You can't use Ruby String object to call FolderItem.InvokeVerb.
396
+ * # Instead, you have to use WIN32OLE_VARIANT object to call the method.
397
+ * shortcut = WIN32OLE_VARIANT.new("Create Shortcut(\&S)")
398
+ * item.invokeVerb(shortcut)
399
+ *
400
+ */
401
+ static VALUE
402
+ folevariant_initialize(VALUE self, VALUE args)
403
+ {
404
+ int len = 0;
405
+ VARIANT var;
406
+ VALUE val;
407
+ VALUE vvt;
408
+ VARTYPE vt;
409
+ struct olevariantdata *pvar;
410
+
411
+ len = RARRAY_LEN(args);
412
+ rb_check_arity(len, 1, 3);
413
+ VariantInit(&var);
414
+ val = rb_ary_entry(args, 0);
415
+
416
+ check_type_val2variant(val);
417
+
418
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
419
+ if (len == 1) {
420
+ ole_val2variant(val, &(pvar->var));
421
+ } else {
422
+ vvt = rb_ary_entry(args, 1);
423
+ vt = RB_NUM2INT(vvt);
424
+ if ((vt & VT_TYPEMASK) == VT_RECORD) {
425
+ rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE_VARIANT object");
426
+ }
427
+ ole_val2olevariantdata(val, vt, pvar);
428
+ }
429
+ return self;
430
+ }
431
+
432
+ static SAFEARRAY *
433
+ get_locked_safe_array(VALUE val)
434
+ {
435
+ struct olevariantdata *pvar;
436
+ SAFEARRAY *psa = NULL;
437
+ HRESULT hr;
438
+ TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar);
439
+ if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
440
+ rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
441
+ }
442
+ psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
443
+ if (psa == NULL) {
444
+ return psa;
445
+ }
446
+ hr = SafeArrayLock(psa);
447
+ if (FAILED(hr)) {
448
+ ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
449
+ }
450
+ return psa;
451
+ }
452
+
453
+ static LONG *
454
+ ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
455
+ {
456
+ long dim;
457
+ LONG *pid;
458
+ long i;
459
+ dim = SafeArrayGetDim(psa);
460
+ if (dim != ary_size) {
461
+ rb_raise(rb_eArgError, "unmatch number of indices");
462
+ }
463
+ pid = ALLOC_N(LONG, dim);
464
+ if (pid == NULL) {
465
+ rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
466
+ }
467
+ for (i = 0; i < dim; i++) {
468
+ pid[i] = RB_NUM2INT(ary[i]);
469
+ }
470
+ return pid;
471
+ }
472
+
473
+ static void
474
+ unlock_safe_array(SAFEARRAY *psa)
475
+ {
476
+ HRESULT hr;
477
+ hr = SafeArrayUnlock(psa);
478
+ if (FAILED(hr)) {
479
+ ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
480
+ }
481
+ }
482
+
483
+ /*
484
+ * call-seq:
485
+ * WIN32OLE_VARIANT[i,j,...] #=> element of OLE array.
486
+ *
487
+ * Returns the element of WIN32OLE_VARIANT object(OLE array).
488
+ * This method is available only when the variant type of
489
+ * WIN32OLE_VARIANT object is VT_ARRAY.
490
+ *
491
+ * REMARK:
492
+ * The all indices should be 0 or natural number and
493
+ * lower than or equal to max indices.
494
+ * (This point is different with Ruby Array indices.)
495
+ *
496
+ * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
497
+ * p obj[0,0] # => 1
498
+ * p obj[1,0] # => 4
499
+ * p obj[2,0] # => WIN32OLERuntimeError
500
+ * p obj[0, -1] # => WIN32OLERuntimeError
501
+ *
502
+ */
503
+ static VALUE
504
+ folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
505
+ {
506
+ struct olevariantdata *pvar;
507
+ SAFEARRAY *psa;
508
+ VALUE val = Qnil;
509
+ VARIANT variant;
510
+ LONG *pid;
511
+ HRESULT hr;
512
+
513
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
514
+ if (!V_ISARRAY(&(pvar->var))) {
515
+ rb_raise(eWIN32OLERuntimeError,
516
+ "`[]' is not available for this variant type object");
517
+ }
518
+ psa = get_locked_safe_array(self);
519
+ if (psa == NULL) {
520
+ return val;
521
+ }
522
+
523
+ pid = ary2safe_array_index(argc, argv, psa);
524
+
525
+ VariantInit(&variant);
526
+ V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
527
+ hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
528
+ if (FAILED(hr)) {
529
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
530
+ }
531
+ val = ole_variant2val(&variant);
532
+
533
+ unlock_safe_array(psa);
534
+ if (pid) free(pid);
535
+ return val;
536
+ }
537
+
538
+ /*
539
+ * call-seq:
540
+ * WIN32OLE_VARIANT[i,j,...] = val #=> set the element of OLE array
541
+ *
542
+ * Set the element of WIN32OLE_VARIANT object(OLE array) to val.
543
+ * This method is available only when the variant type of
544
+ * WIN32OLE_VARIANT object is VT_ARRAY.
545
+ *
546
+ * REMARK:
547
+ * The all indices should be 0 or natural number and
548
+ * lower than or equal to max indices.
549
+ * (This point is different with Ruby Array indices.)
550
+ *
551
+ * obj = WIN32OLE_VARIANT.new([[1,2,3],[4,5,6]])
552
+ * obj[0,0] = 7
553
+ * obj[1,0] = 8
554
+ * p obj.value # => [[7,2,3], [8,5,6]]
555
+ * obj[2,0] = 9 # => WIN32OLERuntimeError
556
+ * obj[0, -1] = 9 # => WIN32OLERuntimeError
557
+ *
558
+ */
559
+ static VALUE
560
+ folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
561
+ {
562
+ struct olevariantdata *pvar;
563
+ SAFEARRAY *psa;
564
+ VARIANT var;
565
+ VARTYPE vt;
566
+ LONG *pid;
567
+ HRESULT hr;
568
+ VOID *p = NULL;
569
+
570
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
571
+ if (!V_ISARRAY(&(pvar->var))) {
572
+ rb_raise(eWIN32OLERuntimeError,
573
+ "`[]' is not available for this variant type object");
574
+ }
575
+ psa = get_locked_safe_array(self);
576
+ if (psa == NULL) {
577
+ rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
578
+ }
579
+
580
+ pid = ary2safe_array_index(argc-1, argv, psa);
581
+
582
+ VariantInit(&var);
583
+ vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
584
+ p = val2variant_ptr(argv[argc-1], &var, vt);
585
+ if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
586
+ (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
587
+ rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
588
+ }
589
+ hr = SafeArrayPutElement(psa, pid, p);
590
+ if (FAILED(hr)) {
591
+ ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
592
+ }
593
+
594
+ unlock_safe_array(psa);
595
+ if (pid) free(pid);
596
+ return argv[argc-1];
597
+ }
598
+
599
+ /*
600
+ * call-seq:
601
+ * WIN32OLE_VARIANT.value #=> Ruby object.
602
+ *
603
+ * Returns Ruby object value from OLE variant.
604
+ * obj = WIN32OLE_VARIANT.new(1, WIN32OLE::VARIANT::VT_BSTR)
605
+ * obj.value # => "1" (not Integer object, but String object "1")
606
+ *
607
+ */
608
+ static VALUE
609
+ folevariant_value(VALUE self)
610
+ {
611
+ struct olevariantdata *pvar;
612
+ VALUE val = Qnil;
613
+ VARTYPE vt;
614
+ int dim;
615
+ SAFEARRAY *psa;
616
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
617
+
618
+ val = ole_variant2val(&(pvar->var));
619
+ vt = V_VT(&(pvar->var));
620
+
621
+ if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
622
+ if (vt & VT_BYREF) {
623
+ psa = *V_ARRAYREF(&(pvar->var));
624
+ } else {
625
+ psa = V_ARRAY(&(pvar->var));
626
+ }
627
+ if (!psa) {
628
+ return val;
629
+ }
630
+ dim = SafeArrayGetDim(psa);
631
+ if (dim == 1) {
632
+ val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
633
+ }
634
+ }
635
+ return val;
636
+ }
637
+
638
+ /*
639
+ * call-seq:
640
+ * WIN32OLE_VARIANT.vartype #=> OLE variant type.
641
+ *
642
+ * Returns OLE variant type.
643
+ * obj = WIN32OLE_VARIANT.new("string")
644
+ * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
645
+ *
646
+ */
647
+ static VALUE
648
+ folevariant_vartype(VALUE self)
649
+ {
650
+ struct olevariantdata *pvar;
651
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
652
+ return RB_INT2FIX(V_VT(&pvar->var));
653
+ }
654
+
655
+ /*
656
+ * call-seq:
657
+ * WIN32OLE_VARIANT.value = val #=> set WIN32OLE_VARIANT value to val.
658
+ *
659
+ * Sets variant value to val. If the val type does not match variant value
660
+ * type(vartype), then val is changed to match variant value type(vartype)
661
+ * before setting val.
662
+ * This method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
663
+ * If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
664
+ *
665
+ * obj = WIN32OLE_VARIANT.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
666
+ * obj.value = 3.2 # 3.2 is changed to 3 when setting value.
667
+ * p obj.value # => 3
668
+ */
669
+ static VALUE
670
+ folevariant_set_value(VALUE self, VALUE val)
671
+ {
672
+ struct olevariantdata *pvar;
673
+ VARTYPE vt;
674
+ TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
675
+ vt = V_VT(&(pvar->var));
676
+ if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) {
677
+ rb_raise(eWIN32OLERuntimeError,
678
+ "`value=' is not available for this variant type object");
679
+ }
680
+ ole_val2olevariantdata(val, vt, pvar);
681
+ return Qnil;
682
+ }
683
+
684
+ void
685
+ ole_variant2variant(VALUE val, VARIANT *var)
686
+ {
687
+ struct olevariantdata *pvar;
688
+ TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar);
689
+ VariantCopy(var, &(pvar->var));
690
+ }
691
+
692
+ void
693
+ Init_win32ole_variant(void)
694
+ {
695
+ #undef rb_intern
696
+ cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
697
+ rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
698
+ rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
699
+ rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
700
+ rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
701
+ rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
702
+ rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
703
+ rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
704
+ rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
705
+
706
+ /*
707
+ * represents VT_EMPTY OLE object.
708
+ */
709
+ rb_define_const(cWIN32OLE_VARIANT, "Empty",
710
+ rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_EMPTY)));
711
+
712
+ /*
713
+ * represents VT_NULL OLE object.
714
+ */
715
+ rb_define_const(cWIN32OLE_VARIANT, "Null",
716
+ rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_NULL)));
717
+
718
+ /*
719
+ * represents Nothing of VB.NET or VB.
720
+ */
721
+ rb_define_const(cWIN32OLE_VARIANT, "Nothing",
722
+ rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_DISPATCH)));
723
+
724
+ /*
725
+ * represents VT_ERROR variant with DISP_E_PARAMNOTFOUND.
726
+ * This constants is used for not specified parameter.
727
+ *
728
+ * fso = WIN32OLE.new("Scripting.FileSystemObject")
729
+ * fso.openTextFile(filename, WIN32OLE_VARIANT::NoParam, false)
730
+ */
731
+ rb_define_const(cWIN32OLE_VARIANT, "NoParam",
732
+ rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), RB_INT2FIX(VT_ERROR)));
733
+ }