Ruby  2.5.0dev(2017-10-22revision60238)
win32ole_param.c
Go to the documentation of this file.
1 #include "win32ole.h"
2 
4 
5 struct oleparamdata {
6  ITypeInfo *pTypeInfo;
8  UINT index;
9 };
10 
11 static void oleparam_free(void *ptr);
12 static size_t oleparam_size(const void *ptr);
13 static VALUE foleparam_s_allocate(VALUE klass);
14 static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index);
15 static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n);
16 static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n);
17 static VALUE foleparam_name(VALUE self);
18 static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
19 static VALUE foleparam_ole_type(VALUE self);
20 static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
21 static VALUE foleparam_ole_type_detail(VALUE self);
22 static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
23 static VALUE foleparam_input(VALUE self);
24 static VALUE foleparam_output(VALUE self);
25 static VALUE foleparam_optional(VALUE self);
26 static VALUE foleparam_retval(VALUE self);
27 static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
28 static VALUE foleparam_default(VALUE self);
29 static VALUE foleparam_inspect(VALUE self);
30 
31 static const rb_data_type_t oleparam_datatype = {
32  "win32ole_param",
33  {NULL, oleparam_free, oleparam_size,},
35 };
36 
37 static void
38 oleparam_free(void *ptr)
39 {
40  struct oleparamdata *pole = ptr;
41  OLE_FREE(pole->pTypeInfo);
42  free(pole);
43 }
44 
45 static size_t
46 oleparam_size(const void *ptr)
47 {
48  return ptr ? sizeof(struct oleparamdata) : 0;
49 }
50 
51 VALUE
52 create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name)
53 {
54  struct oleparamdata *pparam;
55  VALUE obj = foleparam_s_allocate(cWIN32OLE_PARAM);
56  TypedData_Get_Struct(obj, struct oleparamdata, &oleparam_datatype, pparam);
57 
58  pparam->pTypeInfo = pTypeInfo;
60  pparam->method_index = method_index;
61  pparam->index = index;
62  rb_ivar_set(obj, rb_intern("name"), name);
63  return obj;
64 }
65 
66 /*
67  * Document-class: WIN32OLE_PARAM
68  *
69  * <code>WIN32OLE_PARAM</code> objects represent param information of
70  * the OLE method.
71  */
72 static VALUE
73 foleparam_s_allocate(VALUE klass)
74 {
75  struct oleparamdata *pparam;
76  VALUE obj;
77  obj = TypedData_Make_Struct(klass,
78  struct oleparamdata,
79  &oleparam_datatype, pparam);
80  pparam->pTypeInfo = NULL;
81  pparam->method_index = 0;
82  pparam->index = 0;
83  return obj;
84 }
85 
86 static VALUE
87 oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index)
88 {
89  FUNCDESC *pFuncDesc;
90  HRESULT hr;
91  BSTR *bstrs;
92  UINT len;
93  struct oleparamdata *pparam;
94  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
95  if (FAILED(hr))
96  ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc");
97 
98  len = 0;
99  bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
100  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
101  bstrs, pFuncDesc->cParams + 1,
102  &len);
103  if (FAILED(hr)) {
104  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
105  ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames");
106  }
107  SysFreeString(bstrs[0]);
108  if (param_index < 1 || len <= (UINT)param_index)
109  {
110  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
111  rb_raise(rb_eIndexError, "index of param must be in 1..%d", len);
112  }
113 
114  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
115  pparam->pTypeInfo = pTypeInfo;
116  OLE_ADDREF(pTypeInfo);
117  pparam->method_index = method_index;
118  pparam->index = param_index - 1;
119  rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index]));
120 
121  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
122  return self;
123 }
124 
125 static VALUE
126 oleparam_ole_param(VALUE self, VALUE olemethod, int n)
127 {
128  struct olemethoddata *pmethod = olemethod_data_get_struct(olemethod);
129  return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n);
130 }
131 
132 /*
133  * call-seq:
134  * WIN32OLE_PARAM.new(method, n) -> WIN32OLE_PARAM object
135  *
136  * Returns WIN32OLE_PARAM object which represents OLE parameter information.
137  * 1st argument should be WIN32OLE_METHOD object.
138  * 2nd argument `n' is n-th parameter of the method specified by 1st argument.
139  *
140  * tobj = WIN32OLE_TYPE.new('Microsoft Scripting Runtime', 'IFileSystem')
141  * method = WIN32OLE_METHOD.new(tobj, 'CreateTextFile')
142  * param = WIN32OLE_PARAM.new(method, 2) # => #<WIN32OLE_PARAM:Overwrite=true>
143  *
144  */
145 static VALUE
146 foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
147 {
148  int idx;
149  if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) {
150  rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE_METHOD object");
151  }
152  idx = RB_FIX2INT(n);
153  return oleparam_ole_param(self, olemethod, idx);
154 }
155 
156 /*
157  * call-seq:
158  * WIN32OLE_PARAM#name
159  *
160  * Returns name.
161  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
162  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
163  * param1 = method.params[0]
164  * puts param1.name # => Filename
165  */
166 static VALUE
167 foleparam_name(VALUE self)
168 {
169  return rb_ivar_get(self, rb_intern("name"));
170 }
171 
172 static VALUE
173 ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
174 {
175  FUNCDESC *pFuncDesc;
176  HRESULT hr;
177  VALUE type = rb_str_new2("unknown type");
178  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
179  if (FAILED(hr))
180  return type;
181  type = ole_typedesc2val(pTypeInfo,
182  &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil);
183  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
184  return type;
185 }
186 
187 /*
188  * call-seq:
189  * WIN32OLE_PARAM#ole_type
190  *
191  * Returns OLE type of WIN32OLE_PARAM object(parameter of OLE method).
192  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
193  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
194  * param1 = method.params[0]
195  * puts param1.ole_type # => VARIANT
196  */
197 static VALUE
198 foleparam_ole_type(VALUE self)
199 {
200  struct oleparamdata *pparam;
201  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
202  return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index,
203  pparam->index);
204 }
205 
206 static VALUE
207 ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
208 {
209  FUNCDESC *pFuncDesc;
210  HRESULT hr;
211  VALUE typedetail = rb_ary_new();
212  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
213  if (FAILED(hr))
214  return typedetail;
215  ole_typedesc2val(pTypeInfo,
216  &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail);
217  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
218  return typedetail;
219 }
220 
221 /*
222  * call-seq:
223  * WIN32OLE_PARAM#ole_type_detail
224  *
225  * Returns detail information of type of argument.
226  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
227  * method = WIN32OLE_METHOD.new(tobj, 'SumIf')
228  * param1 = method.params[0]
229  * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
230  */
231 static VALUE
232 foleparam_ole_type_detail(VALUE self)
233 {
234  struct oleparamdata *pparam;
235  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
236  return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index,
237  pparam->index);
238 }
239 
240 static VALUE
241 ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
242 {
243  FUNCDESC *pFuncDesc;
244  HRESULT hr;
245  VALUE ret = Qfalse;
246  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
247  if(FAILED(hr))
248  return ret;
249  if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask)
250  ret = Qtrue;
251  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
252  return ret;
253 }
254 
255 /*
256  * call-seq:
257  * WIN32OLE_PARAM#input?
258  *
259  * Returns true if the parameter is input.
260  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
261  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
262  * param1 = method.params[0]
263  * puts param1.input? # => true
264  */
265 static VALUE
266 foleparam_input(VALUE self)
267 {
268  struct oleparamdata *pparam;
269  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
270  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
271  pparam->index, PARAMFLAG_FIN);
272 }
273 
274 /*
275  * call-seq:
276  * WIN32OLE#output?
277  *
278  * Returns true if argument is output.
279  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents')
280  * method = WIN32OLE_METHOD.new(tobj, 'NewWindow')
281  * method.params.each do |param|
282  * puts "#{param.name} #{param.output?}"
283  * end
284  *
285  * The result of above script is following:
286  * URL false
287  * Flags false
288  * TargetFrameName false
289  * PostData false
290  * Headers false
291  * Processed true
292  */
293 static VALUE
294 foleparam_output(VALUE self)
295 {
296  struct oleparamdata *pparam;
297  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
298  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
299  pparam->index, PARAMFLAG_FOUT);
300 }
301 
302 /*
303  * call-seq:
304  * WIN32OLE_PARAM#optional?
305  *
306  * Returns true if argument is optional.
307  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
308  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
309  * param1 = method.params[0]
310  * puts "#{param1.name} #{param1.optional?}" # => Filename true
311  */
312 static VALUE
313 foleparam_optional(VALUE self)
314 {
315  struct oleparamdata *pparam;
316  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
317  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
318  pparam->index, PARAMFLAG_FOPT);
319 }
320 
321 /*
322  * call-seq:
323  * WIN32OLE_PARAM#retval?
324  *
325  * Returns true if argument is return value.
326  * tobj = WIN32OLE_TYPE.new('DirectX 7 for Visual Basic Type Library',
327  * 'DirectPlayLobbyConnection')
328  * method = WIN32OLE_METHOD.new(tobj, 'GetPlayerShortName')
329  * param = method.params[0]
330  * puts "#{param.name} #{param.retval?}" # => name true
331  */
332 static VALUE
333 foleparam_retval(VALUE self)
334 {
335  struct oleparamdata *pparam;
336  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
337  return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
338  pparam->index, PARAMFLAG_FRETVAL);
339 }
340 
341 static VALUE
342 ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
343 {
344  FUNCDESC *pFuncDesc;
345  ELEMDESC *pElemDesc;
346  PARAMDESCEX * pParamDescEx;
347  HRESULT hr;
348  USHORT wParamFlags;
349  USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT;
350  VALUE defval = Qnil;
351  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
352  if (FAILED(hr))
353  return defval;
354  pElemDesc = &pFuncDesc->lprgelemdescParam[index];
355  wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags;
356  if ((wParamFlags & mask) == mask) {
357  pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex;
358  defval = ole_variant2val(&pParamDescEx->varDefaultValue);
359  }
360  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
361  return defval;
362 }
363 
364 /*
365  * call-seq:
366  * WIN32OLE_PARAM#default
367  *
368  * Returns default value. If the default value does not exist,
369  * this method returns nil.
370  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
371  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
372  * method.params.each do |param|
373  * if param.default
374  * puts "#{param.name} (= #{param.default})"
375  * else
376  * puts "#{param}"
377  * end
378  * end
379  *
380  * The above script result is following:
381  * Filename
382  * FileFormat
383  * Password
384  * WriteResPassword
385  * ReadOnlyRecommended
386  * CreateBackup
387  * AccessMode (= 1)
388  * ConflictResolution
389  * AddToMru
390  * TextCodepage
391  * TextVisualLayout
392  */
393 static VALUE
394 foleparam_default(VALUE self)
395 {
396  struct oleparamdata *pparam;
397  TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
398  return ole_param_default(pparam->pTypeInfo, pparam->method_index,
399  pparam->index);
400 }
401 
402 /*
403  * call-seq:
404  * WIN32OLE_PARAM#inspect -> String
405  *
406  * Returns the parameter name with class name. If the parameter has default value,
407  * then returns name=value string with class name.
408  *
409  */
410 static VALUE
411 foleparam_inspect(VALUE self)
412 {
413  VALUE detail = foleparam_name(self);
414  VALUE defval = foleparam_default(self);
415  if (defval != Qnil) {
416  rb_str_cat2(detail, "=");
417  rb_str_concat(detail, rb_inspect(defval));
418  }
419  return make_inspect("WIN32OLE_PARAM", detail);
420 }
421 
422 void
424 {
425  cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject);
426  rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate);
427  rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2);
428  rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0);
429  rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0);
430  rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0);
431  rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0);
432  rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0);
433  rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0);
434  rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0);
435  rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0);
436  rb_define_alias(cWIN32OLE_PARAM, "to_s", "name");
437  rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0);
438 }
void Init_win32ole_param(void)
VALUE cWIN32OLE_METHOD
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define V_UNION1(X, Y)
Definition: win32ole.h:47
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define Qtrue
Definition: ruby.h:437
ITypeInfo * pTypeInfo
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
VALUE cWIN32OLE_PARAM
Definition: win32ole_param.c:3
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2999
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
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
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,...)
ITypeInfo * pTypeInfo
Definition: win32ole_param.c:6
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_ary_new(void)
Definition: array.c:499
VALUE rb_eIndexError
Definition: error.c:803
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
#define WC2VSTR(x)
Definition: win32ole.h:130
#define Qfalse
Definition: ruby.h:436
#define ALLOCA_N(type, n)
Definition: ruby.h:1593
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_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
VALUE rb_eTypeError
Definition: error.c:801
struct olemethoddata * olemethod_data_get_struct(VALUE obj)
register unsigned int len
Definition: zonetab.h:51
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:3717
VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name)
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE rb_eRuntimeError
Definition: error.c:800
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
const char * name
Definition: nkf.c:208
#define RB_FIX2INT(x)
Definition: ruby.h:681
#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