Ruby: ext/win32ole/win32ole_param.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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
11static void oleparam_free(void *ptr);
12static size_t oleparam_size(const void *ptr);
13static VALUE foleparam_s_allocate(VALUE klass);
14static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index);
15static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n);
16static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n);
17static VALUE foleparam_name(VALUE self);
18static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
19static VALUE foleparam_ole_type(VALUE self);
20static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
21static VALUE foleparam_ole_type_detail(VALUE self);
22static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
23static VALUE foleparam_input(VALUE self);
24static VALUE foleparam_output(VALUE self);
25static VALUE foleparam_optional(VALUE self);
26static VALUE foleparam_retval(VALUE self);
27static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
28static VALUE foleparam_default(VALUE self);
29static VALUE foleparam_inspect(VALUE self);
30
31static 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
37static void
38oleparam_free(void *ptr)
39{
40 struct oleparamdata *pole = ptr;
41 OLE_FREE(pole->pTypeInfo);
42 free(pole);
43}
44
45static size_t
46oleparam_size(const void *ptr)
47{
48 return ptr ? sizeof(struct oleparamdata) : 0;
49}
50
51 VALUE
52create_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 */
72static VALUE
73foleparam_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
86static VALUE
87oleparam_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
125static VALUE
126oleparam_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 */
145static VALUE
146foleparam_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 */
166static VALUE
167foleparam_name(VALUE self)
168{
169 return rb_ivar_get(self, rb_intern("name"));
170}
171
172static VALUE
173ole_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 */
197static VALUE
198foleparam_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
206static VALUE
207ole_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 */
231static VALUE
232foleparam_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
240static VALUE
241ole_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 */
265static VALUE
266foleparam_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 */
293static VALUE
294foleparam_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 */
312static VALUE
313foleparam_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 */
332static VALUE
333foleparam_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
341static VALUE
342ole_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 */
393static VALUE
394foleparam_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 */
410static VALUE
411foleparam_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
422void
423Init_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_ary_new
VALUE rb_ary_new(void)
Definition: array.c:749
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
mask
enum @11::@13::@14 mask
ptr
struct RIMemo * ptr
Definition: debug.c:88
free
#define free(x)
Definition: dln.c:52
len
uint8_t len
Definition: escape.c:17
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:748
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1999
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:1057
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:1055
rb_eIndexError
VALUE rb_eIndexError
Definition: error.c:1059
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:585
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:724
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_str_concat
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:3217
rb_str_cat2
#define rb_str_cat2
Definition: string.h:285
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1234
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1493
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:785
ALLOCA_N
#define ALLOCA_N(type, n)
Definition: memory.h:112
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
name
const char * name
Definition: nkf.c:208
NULL
#define NULL
Definition: regenc.h:69
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: rtypeddata.h:130
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: rtypeddata.h:122
Qtrue
#define Qtrue
Definition: special_consts.h:52
Qnil
#define Qnil
Definition: special_consts.h:51
Qfalse
#define Qfalse
Definition: special_consts.h:50
olemethoddata
Definition: win32ole_method.h:4
olemethoddata::index
UINT index
Definition: win32ole_method.h:7
olemethoddata::pTypeInfo
ITypeInfo * pTypeInfo
Definition: win32ole_method.h:6
oleparamdata
Definition: win32ole_param.c:5
oleparamdata::index
UINT index
Definition: win32ole_param.c:8
oleparamdata::pTypeInfo
ITypeInfo * pTypeInfo
Definition: win32ole_param.c:6
oleparamdata::method_index
UINT method_index
Definition: win32ole_param.c:7
rb_data_type_struct
Definition: rtypeddata.h:70
VALUE
unsigned long VALUE
Definition: value.h:38
ole_typedesc2val
VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
Definition: win32ole.c:3709
HRESULT
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
ole_variant2val
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1419
make_inspect
VALUE make_inspect(const char *class_name, VALUE detail)
Definition: win32ole.c:1334
win32ole.h
OLE_FREE
#define OLE_FREE(x)
Definition: win32ole.h:99
OLE_ADDREF
#define OLE_ADDREF(X)
Definition: win32ole.h:97
V_UNION1
#define V_UNION1(X, Y)
Definition: win32ole.h:47
WC2VSTR
#define WC2VSTR(x)
Definition: win32ole.h:130
ole_raise
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
Definition: win32ole_error.c:46
cWIN32OLE_METHOD
VALUE cWIN32OLE_METHOD
Definition: win32ole_method.c:926
olemethod_data_get_struct
struct olemethoddata * olemethod_data_get_struct(VALUE obj)
Definition: win32ole_method.c:67
cWIN32OLE_PARAM
VALUE cWIN32OLE_PARAM
Definition: win32ole_param.c:3
create_win32ole_param
VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name)
Definition: win32ole_param.c:52
Init_win32ole_param
void Init_win32ole_param(void)
Definition: win32ole_param.c:423