Ruby  2.5.0dev(2017-10-22revision60238)
win32ole_variable.c
Go to the documentation of this file.
1 #include "win32ole.h"
2 
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,},
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;
56  &olevariable_datatype, pvar);
57  pvar->pTypeInfo = 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 
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 }
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define V_UNION1(X, Y)
Definition: win32ole.h:47
#define Qtrue
Definition: ruby.h:437
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
ITypeInfo * pTypeInfo
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
VALUE make_inspect(const char *class_name, VALUE detail)
Definition: win32ole.c:1332
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
void Init_win32ole_variable(void)
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
VALUE rb_ary_new(void)
Definition: array.c:499
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
#define Qfalse
Definition: ruby.h:436
VALUE cWIN32OLE_VARIABLE
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1417
#define rb_str_new2
Definition: intern.h:835
#define OLE_ADDREF(X)
Definition: win32ole.h:97
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
VALUE create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name)
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
#define PRIsVALUE
Definition: ruby.h:135
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:3717
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
const char * name
Definition: nkf.c:208
#define RB_INT2FIX(i)
Definition: ruby.h:231
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
free(psz)
#define OLE_FREE(x)
Definition: win32ole.h:99