Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

win32ole_param.c
Go to the documentation of this file.
1 #include "win32ole.h"
2
3 VALUE cWIN32OLE_PARAM;
4
5 struct oleparamdata {
6 ITypeInfo *pTypeInfo;
7 UINT method_index;
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,},
34 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
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;
59 OLE_ADDREF(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
423 Init_win32ole_param(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 }
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:3065
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
oleparamdata::index
UINT index
Definition: win32ole_param.c:8
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
win32ole.h
ole_variant2val
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1418
olemethoddata::index
UINT index
Definition: win32ole_method.h:7
create_win32ole_param
VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name)
Definition: win32ole_param.c:52
VALUE
unsigned long VALUE
Definition: ruby.h:102
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
rb_intern
#define rb_intern(str)
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:924
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
WC2VSTR
#define WC2VSTR(x)
Definition: win32ole.h:130
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
Qfalse
#define Qfalse
Definition: ruby.h:467
NULL
#define NULL
Definition: _sdbm.c:101
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
oleparamdata::pTypeInfo
ITypeInfo * pTypeInfo
Definition: win32ole_param.c:6
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
ole_typedesc2val
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:3708
oleparamdata::method_index
UINT method_index
Definition: win32ole_param.c:7
mask
enum @11::@13::@14 mask
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
ALLOCA_N
#define ALLOCA_N(type, n)
Definition: ruby.h:1684
V_UNION1
#define V_UNION1(X, Y)
Definition: win32ole.h:47
RB_FIX2INT
#define RB_FIX2INT(x)
Definition: ruby.h:712
Init_win32ole_param
void Init_win32ole_param(void)
Definition: win32ole_param.c:423
oleparamdata
Definition: win32ole_param.c:5
olemethoddata::pTypeInfo
ITypeInfo * pTypeInfo
Definition: win32ole_method.h:6
cWIN32OLE_METHOD
VALUE cWIN32OLE_METHOD
Definition: win32ole_method.h:10
OLE_FREE
#define OLE_FREE(x)
Definition: win32ole.h:99
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
n
const char size_t n
Definition: rb_mjit_min_header-2.7.0.h:5456
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1252
olemethoddata
Definition: win32ole_method.h:4
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
HRESULT
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
OLE_ADDREF
#define OLE_ADDREF(X)
Definition: win32ole.h:97
free
#define free(x)
Definition: dln.c:52
rb_data_type_struct
Definition: ruby.h:1148
cWIN32OLE_PARAM
VALUE cWIN32OLE_PARAM
Definition: win32ole_param.c:3
Qtrue
#define Qtrue
Definition: ruby.h:468
len
uint8_t len
Definition: escape.c:17
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
ole_raise
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
Definition: win32ole_error.c:46
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
Qnil
#define Qnil
Definition: ruby.h:469
make_inspect
VALUE make_inspect(const char *class_name, VALUE detail)
Definition: win32ole.c:1333
olemethod_data_get_struct
struct olemethoddata * olemethod_data_get_struct(VALUE obj)
Definition: win32ole_method.c:67
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)
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
name
const char * name
Definition: nkf.c:208