Ruby  2.5.0dev(2017-10-22revision60238)
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,},
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;
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) &&
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))) {
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))) {
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))) {
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
694 {
695  cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
696  rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
697  rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
698  rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
699  rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
700  rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
701  rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
702  rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
703  rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
704 
705  /*
706  * represents VT_EMPTY OLE object.
707  */
709  rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_EMPTY)));
710 
711  /*
712  * represents VT_NULL OLE object.
713  */
715  rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_NULL)));
716 
717  /*
718  * represents Nothing of VB.NET or VB.
719  */
721  rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_DISPATCH)));
722 
723  /*
724  * represents VT_ERROR variant with DISP_E_PARAMNOTFOUND.
725  * This constants is used for not specified parameter.
726  *
727  * fso = WIN32OLE.new("Scripting.FileSystemObject")
728  * fso.openTextFile(filename, WIN32OLE_VARIANT::NoParam, false)
729  */
731  rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), RB_INT2FIX(VT_ERROR)));
732 }
#define V_UINT(X)
Definition: win32ole.h:78
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define INT2NUM(x)
Definition: ruby.h:1538
#define T_FIXNUM
Definition: ruby.h:503
LCID cWIN32OLE_lcid
Definition: win32ole.h:116
VOID * val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1016
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
#define V_UI2REF(X)
Definition: win32ole.h:66
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
void ole_variant2variant(VALUE val, VARIANT *var)
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
VALUE cWIN32OLE
Definition: win32ole.c:37
#define rb_check_arity
Definition: intern.h:298
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
#define Check_Type(v, t)
Definition: ruby.h:562
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
void ole_initialize(void)
Definition: win32ole.c:812
#define T_ARRAY
Definition: ruby.h:498
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
void Init_win32ole_variant(void)
const char * rb_obj_classname(VALUE)
Definition: variable.c:459
VALUE rb_eArgError
Definition: error.c:802
#define RB_NUM2LONG(x)
Definition: ruby.h:647
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
Definition: object.c:842
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
#define ALLOC_N(type, n)
Definition: ruby.h:1587
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
#define T_NIL
Definition: ruby.h:490
#define T_TRUE
Definition: ruby.h:504
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2691
#define T_FLOAT
Definition: ruby.h:495
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
#define V_INT(X)
Definition: win32ole.h:70
#define T_BIGNUM
Definition: ruby.h:501
void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:981
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1417
#define rb_str_new2
Definition: intern.h:835
#define RB_NUM2UINT(x)
Definition: ruby.h:680
VALUE cWIN32OLE_VARIANT
#define RSTRING_LEN(str)
Definition: ruby.h:971
#define PRIsVALUE
Definition: ruby.h:135
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
VALUE rb_eTypeError
Definition: error.c:801
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:975
#define V_I1REF(X)
Definition: win32ole.h:62
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE rb_eRuntimeError
Definition: error.c:800
#define T_STRING
Definition: ruby.h:496
#define T_FALSE
Definition: ruby.h:505
#define V_UINTREF(X)
Definition: win32ole.h:82
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
#define RB_NUM2INT(x)
Definition: ruby.h:679
HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
Definition: win32ole.c:1186
#define RB_FIX2INT(x)
Definition: ruby.h:681
#define RB_INT2FIX(i)
Definition: ruby.h:231
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
#define V_INTREF(X)
Definition: win32ole.h:74
RUBY_EXTERN VALUE rb_cTime
Definition: ruby.h:1931
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
free(psz)
char ** argv
Definition: ruby.c:188
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1248