win32ole 1.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ext/win32ole/depend +12 -0
- data/ext/win32ole/extconf.rb +45 -0
- data/ext/win32ole/sample/excel1.rb +37 -0
- data/ext/win32ole/sample/excel2.rb +31 -0
- data/ext/win32ole/sample/excel3.rb +21 -0
- data/ext/win32ole/sample/ie.rb +12 -0
- data/ext/win32ole/sample/ieconst.rb +33 -0
- data/ext/win32ole/sample/ienavi.rb +41 -0
- data/ext/win32ole/sample/ienavi2.rb +41 -0
- data/ext/win32ole/sample/oledirs.rb +24 -0
- data/ext/win32ole/sample/olegen.rb +348 -0
- data/ext/win32ole/sample/xml.rb +7307 -0
- data/ext/win32ole/win32ole.c +4140 -0
- data/ext/win32ole/win32ole.h +155 -0
- data/ext/win32ole/win32ole_error.c +84 -0
- data/ext/win32ole/win32ole_error.h +9 -0
- data/ext/win32ole/win32ole_event.c +1277 -0
- data/ext/win32ole/win32ole_event.h +6 -0
- data/ext/win32ole/win32ole_method.c +950 -0
- data/ext/win32ole/win32ole_method.h +16 -0
- data/ext/win32ole/win32ole_param.c +438 -0
- data/ext/win32ole/win32ole_param.h +8 -0
- data/ext/win32ole/win32ole_record.c +604 -0
- data/ext/win32ole/win32ole_record.h +10 -0
- data/ext/win32ole/win32ole_type.c +915 -0
- data/ext/win32ole/win32ole_type.h +8 -0
- data/ext/win32ole/win32ole_typelib.c +844 -0
- data/ext/win32ole/win32ole_typelib.h +11 -0
- data/ext/win32ole/win32ole_variable.c +380 -0
- data/ext/win32ole/win32ole_variable.h +8 -0
- data/ext/win32ole/win32ole_variant.c +733 -0
- data/ext/win32ole/win32ole_variant.h +9 -0
- data/ext/win32ole/win32ole_variant_m.c +149 -0
- data/ext/win32ole/win32ole_variant_m.h +7 -0
- data/lib/win32ole.rb +33 -0
- data/lib/win32ole/property.rb +17 -0
- data/win32ole.gemspec +22 -0
- 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,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
|
+
}
|