Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

win32ole_variant.c
Go to the documentation of this file.
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 }
ole_val2variant
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1249
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
T_FALSE
#define T_FALSE
Definition: ruby.h:537
void
void
Definition: rb_mjit_min_header-2.7.0.h:13273
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
win32ole.h
olevariantdata::realvar
VARIANT realvar
Definition: win32ole_variant.c:4
ole_variant2val
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1418
ole_val2variant_ex
void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:982
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
V_I1REF
#define V_I1REF(X)
Definition: win32ole.h:62
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
rb_intern
#define rb_intern(str)
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_cTime
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:2048
TYPE
#define TYPE(x)
Definition: ruby.h:554
ole_variant2variant
void ole_variant2variant(VALUE val, VARIANT *var)
Definition: win32ole_variant.c:685
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
ole_initialize
void ole_initialize(void)
Definition: win32ole.c:813
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
ptr
struct RIMemo * ptr
Definition: debug.c:74
olevariantdata
Definition: win32ole_variant.c:3
NULL
#define NULL
Definition: _sdbm.c:101
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
eWIN32OLERuntimeError
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
RB_NUM2UINT
#define RB_NUM2UINT(x)
Definition: ruby.h:711
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
ole_val_ary2variant_ary
HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1187
V_UI2REF
#define V_UI2REF(X)
Definition: win32ole.h:66
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
val2variant_ptr
VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1017
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
V_UINT
#define V_UINT(X)
Definition: win32ole.h:78
RB_FIX2INT
#define RB_FIX2INT(x)
Definition: ruby.h:712
cWIN32OLE
VALUE cWIN32OLE
Definition: win32ole.c:38
RB_NUM2INT
#define RB_NUM2INT(x)
Definition: ruby.h:710
V_INT
#define V_INT(X)
Definition: win32ole.h:70
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
Init_win32ole_variant
void Init_win32ole_variant(void)
Definition: win32ole_variant.c:693
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1252
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
argv
char ** argv
Definition: ruby.c:223
RB_INT2FIX
#define RB_INT2FIX(i)
Definition: ruby.h:262
cWIN32OLE_VARIANT
VALUE cWIN32OLE_VARIANT
Definition: win32ole_variant.h:4
V_UINTREF
#define V_UINTREF(X)
Definition: win32ole.h:82
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
T_NIL
#define T_NIL
Definition: ruby.h:522
HRESULT
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
argc
int argc
Definition: ruby.c:222
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
V_INTREF
#define V_INTREF(X)
Definition: win32ole.h:74
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
free
#define free(x)
Definition: dln.c:52
rb_data_type_struct
Definition: ruby.h:1148
olevariantdata::var
VARIANT var
Definition: win32ole_variant.c:5
len
uint8_t len
Definition: escape.c:17
T_STRING
#define T_STRING
Definition: ruby.h:528
cWIN32OLE_lcid
LCID cWIN32OLE_lcid
Definition: win32ole.h:116
ole_raise
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
Definition: win32ole_error.c:46
Qnil
#define Qnil
Definition: ruby.h:469
RB_NUM2LONG
#define RB_NUM2LONG(x)
Definition: ruby.h:678
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
T_TRUE
#define T_TRUE
Definition: ruby.h:536
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)