Ruby  2.5.0dev(2017-10-22revision60238)
win32ole_method.c
Go to the documentation of this file.
1 #include "win32ole.h"
2 
3 static void olemethod_free(void *ptr);
4 static size_t olemethod_size(const void *ptr);
5 static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name);
6 static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
7 static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask);
8 static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name);
9 static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method);
10 static VALUE folemethod_name(VALUE self);
11 static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index);
12 static VALUE folemethod_return_type(VALUE self);
13 static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index);
14 static VALUE folemethod_return_vtype(VALUE self);
15 static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index);
16 static VALUE folemethod_return_type_detail(VALUE self);
17 static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index);
18 static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index);
19 static VALUE folemethod_invkind(VALUE self);
20 static VALUE folemethod_invoke_kind(VALUE self);
21 static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index);
22 static VALUE folemethod_visible(VALUE self);
23 static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name);
24 static VALUE folemethod_event(VALUE self);
25 static VALUE folemethod_event_interface(VALUE self);
26 static HRESULT ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
27 static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index);
28 static VALUE folemethod_helpstring(VALUE self);
29 static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index);
30 static VALUE folemethod_helpfile(VALUE self);
31 static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index);
32 static VALUE folemethod_helpcontext(VALUE self);
33 static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index);
34 static VALUE folemethod_dispid(VALUE self);
35 static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index);
36 static VALUE folemethod_offset_vtbl(VALUE self);
37 static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index);
38 static VALUE folemethod_size_params(VALUE self);
39 static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index);
40 static VALUE folemethod_size_opt_params(VALUE self);
41 static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index);
42 static VALUE folemethod_params(VALUE self);
43 static VALUE folemethod_inspect(VALUE self);
44 
45 static const rb_data_type_t olemethod_datatype = {
46  "win32ole_method",
47  {NULL, olemethod_free, olemethod_size,},
49 };
50 
51 static void
52 olemethod_free(void *ptr)
53 {
54  struct olemethoddata *polemethod = ptr;
55  OLE_FREE(polemethod->pTypeInfo);
56  OLE_FREE(polemethod->pOwnerTypeInfo);
57  free(polemethod);
58 }
59 
60 static size_t
61 olemethod_size(const void *ptr)
62 {
63  return ptr ? sizeof(struct olemethoddata) : 0;
64 }
65 
66 struct olemethoddata *
68 {
69  struct olemethoddata *pmethod;
70  TypedData_Get_Struct(obj, struct olemethoddata, &olemethod_datatype, pmethod);
71  return pmethod;
72 }
73 
74 static VALUE
75 ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
76 {
77  HRESULT hr;
78  TYPEATTR *pTypeAttr;
79  BSTR bstr;
80  FUNCDESC *pFuncDesc;
81  WORD i;
82  VALUE fname;
83  VALUE method = Qnil;
84  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
85  if (FAILED(hr)) {
86  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
87  }
88  for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) {
89  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
90  if (FAILED(hr))
91  continue;
92 
93  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
94  &bstr, NULL, NULL, NULL);
95  if (FAILED(hr)) {
96  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
97  continue;
98  }
99  fname = WC2VSTR(bstr);
100  if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) {
101  olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname);
102  method = self;
103  }
104  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
105  pFuncDesc=NULL;
106  }
107  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
108  return method;
109 }
110 
111 VALUE
112 ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
113 {
114  HRESULT hr;
115  TYPEATTR *pTypeAttr;
116  WORD i;
117  HREFTYPE href;
118  ITypeInfo *pRefTypeInfo;
119  VALUE methods = rb_ary_new();
120  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
121  if (FAILED(hr)) {
122  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
123  }
124 
125  ole_methods_sub(0, pTypeInfo, methods, mask);
126  for(i=0; i < pTypeAttr->cImplTypes; i++){
127  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
128  if(FAILED(hr))
129  continue;
130  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
131  if (FAILED(hr))
132  continue;
133  ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask);
134  OLE_RELEASE(pRefTypeInfo);
135  }
136  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
137  return methods;
138 }
139 
140 static VALUE
141 olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
142 {
143  HRESULT hr;
144  TYPEATTR *pTypeAttr;
145  WORD i;
146  HREFTYPE href;
147  ITypeInfo *pRefTypeInfo;
148  VALUE method = Qnil;
149  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
150  if (FAILED(hr)) {
151  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
152  }
153  method = ole_method_sub(self, 0, pTypeInfo, name);
154  if (method != Qnil) {
155  return method;
156  }
157  for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){
158  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
159  if(FAILED(hr))
160  continue;
161  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
162  if (FAILED(hr))
163  continue;
164  method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name);
165  OLE_RELEASE(pRefTypeInfo);
166  }
167  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
168  return method;
169 }
170 
171 static VALUE
172 ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
173 {
174  HRESULT hr;
175  TYPEATTR *pTypeAttr;
176  BSTR bstr;
177  FUNCDESC *pFuncDesc;
178  VALUE method;
179  WORD i;
180  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
181  if (FAILED(hr)) {
182  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
183  }
184  for(i = 0; i < pTypeAttr->cFuncs; i++) {
185  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
186  if (FAILED(hr))
187  continue;
188 
189  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
190  &bstr, NULL, NULL, NULL);
191  if (FAILED(hr)) {
192  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
193  continue;
194  }
195  if(pFuncDesc->invkind & mask) {
197  olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo,
198  i, WC2VSTR(bstr));
199  rb_ary_push(methods, method);
200  }
201  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
202  pFuncDesc=NULL;
203  }
204  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
205 
206  return methods;
207 }
208 
209 VALUE
210 create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name)
211 {
212 
214  VALUE obj = olemethod_from_typeinfo(method, pTypeInfo, name);
215  return obj;
216 }
217 
218 /*
219  * Document-class: WIN32OLE_METHOD
220  *
221  * <code>WIN32OLE_METHOD</code> objects represent OLE method information.
222  */
223 
224 static VALUE
225 olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
226 {
227  struct olemethoddata *pmethod;
228  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
229  pmethod->pTypeInfo = pTypeInfo;
230  OLE_ADDREF(pTypeInfo);
231  pmethod->pOwnerTypeInfo = pOwnerTypeInfo;
232  OLE_ADDREF(pOwnerTypeInfo);
233  pmethod->index = index;
234  rb_ivar_set(self, rb_intern("name"), name);
235  return self;
236 }
237 
238 VALUE
240 {
241  struct olemethoddata *pmethod;
242  VALUE obj;
243  obj = TypedData_Make_Struct(klass,
244  struct olemethoddata,
245  &olemethod_datatype, pmethod);
246  pmethod->pTypeInfo = NULL;
247  pmethod->pOwnerTypeInfo = NULL;
248  pmethod->index = 0;
249  return obj;
250 }
251 
252 /*
253  * call-seq:
254  * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object
255  *
256  * Returns a new WIN32OLE_METHOD object which represents the information
257  * about OLE method.
258  * The first argument <i>ole_type</i> specifies WIN32OLE_TYPE object.
259  * The second argument <i>method</i> specifies OLE method name defined OLE class
260  * which represents WIN32OLE_TYPE object.
261  *
262  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
263  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
264  */
265 static VALUE
266 folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
267 {
268  VALUE obj = Qnil;
269  ITypeInfo *pTypeInfo;
270  if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) {
271  SafeStringValue(method);
272  pTypeInfo = itypeinfo(oletype);
273  obj = olemethod_from_typeinfo(self, pTypeInfo, method);
274  if (obj == Qnil) {
275  rb_raise(eWIN32OLERuntimeError, "not found %s",
276  StringValuePtr(method));
277  }
278  }
279  else {
280  rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object");
281  }
282  return obj;
283 }
284 
285 /*
286  * call-seq
287  * WIN32OLE_METHOD#name
288  *
289  * Returns the name of the method.
290  *
291  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
292  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
293  * puts method.name # => SaveAs
294  *
295  */
296 static VALUE
297 folemethod_name(VALUE self)
298 {
299  return rb_ivar_get(self, rb_intern("name"));
300 }
301 
302 static VALUE
303 ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
304 {
305  FUNCDESC *pFuncDesc;
306  HRESULT hr;
307  VALUE type;
308 
309  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
310  if (FAILED(hr))
311  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
312 
313  type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil);
314  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
315  return type;
316 }
317 
318 /*
319  * call-seq:
320  * WIN32OLE_METHOD#return_type
321  *
322  * Returns string of return value type of method.
323  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
324  * method = WIN32OLE_METHOD.new(tobj, 'Add')
325  * puts method.return_type # => Workbook
326  *
327  */
328 static VALUE
329 folemethod_return_type(VALUE self)
330 {
331  struct olemethoddata *pmethod;
332  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
333  return ole_method_return_type(pmethod->pTypeInfo, pmethod->index);
334 }
335 
336 static VALUE
337 ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
338 {
339  FUNCDESC *pFuncDesc;
340  HRESULT hr;
341  VALUE vvt;
342 
343  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
344  if (FAILED(hr))
345  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
346 
347  vvt = RB_INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
348  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
349  return vvt;
350 }
351 
352 /*
353  * call-seq:
354  * WIN32OLE_METHOD#return_vtype
355  *
356  * Returns number of return value type of method.
357  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
358  * method = WIN32OLE_METHOD.new(tobj, 'Add')
359  * puts method.return_vtype # => 26
360  *
361  */
362 static VALUE
363 folemethod_return_vtype(VALUE self)
364 {
365  struct olemethoddata *pmethod;
366  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
367  return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index);
368 }
369 
370 static VALUE
371 ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
372 {
373  FUNCDESC *pFuncDesc;
374  HRESULT hr;
375  VALUE type = rb_ary_new();
376 
377  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
378  if (FAILED(hr))
379  return type;
380 
381  ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type);
382  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
383  return type;
384 }
385 
386 /*
387  * call-seq:
388  * WIN32OLE_METHOD#return_type_detail
389  *
390  * Returns detail information of return value type of method.
391  * The information is array.
392  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
393  * method = WIN32OLE_METHOD.new(tobj, 'Add')
394  * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
395  */
396 static VALUE
397 folemethod_return_type_detail(VALUE self)
398 {
399  struct olemethoddata *pmethod;
400  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
401  return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index);
402 }
403 
404 static VALUE
405 ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
406 {
407  FUNCDESC *pFuncDesc;
408  HRESULT hr;
409  VALUE invkind;
410  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
411  if(FAILED(hr))
412  ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
413  invkind = RB_INT2FIX(pFuncDesc->invkind);
414  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
415  return invkind;
416 }
417 
418 static VALUE
419 ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
420 {
421  VALUE type = rb_str_new2("UNKNOWN");
422  VALUE invkind = ole_method_invkind(pTypeInfo, method_index);
423  if((RB_FIX2INT(invkind) & INVOKE_PROPERTYGET) &&
424  (RB_FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) {
425  type = rb_str_new2("PROPERTY");
426  } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYGET) {
427  type = rb_str_new2("PROPERTYGET");
428  } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYPUT) {
429  type = rb_str_new2("PROPERTYPUT");
430  } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) {
431  type = rb_str_new2("PROPERTYPUTREF");
432  } else if(RB_FIX2INT(invkind) & INVOKE_FUNC) {
433  type = rb_str_new2("FUNC");
434  }
435  return type;
436 }
437 
438 /*
439  * call-seq:
440  * WIN32OLE_MTHOD#invkind
441  *
442  * Returns the method invoke kind.
443  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
444  * method = WIN32OLE_METHOD.new(tobj, 'Add')
445  * puts method.invkind # => 1
446  *
447  */
448 static VALUE
449 folemethod_invkind(VALUE self)
450 {
451  struct olemethoddata *pmethod;
452  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
453  return ole_method_invkind(pmethod->pTypeInfo, pmethod->index);
454 }
455 
456 /*
457  * call-seq:
458  * WIN32OLE_METHOD#invoke_kind
459  *
460  * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY"
461  * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF"
462  * or "FUNC".
463  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
464  * method = WIN32OLE_METHOD.new(tobj, 'Add')
465  * puts method.invoke_kind # => "FUNC"
466  */
467 static VALUE
468 folemethod_invoke_kind(VALUE self)
469 {
470  struct olemethoddata *pmethod;
471  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
472  return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index);
473 }
474 
475 static VALUE
476 ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
477 {
478  FUNCDESC *pFuncDesc;
479  HRESULT hr;
480  VALUE visible;
481  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
482  if(FAILED(hr))
483  return Qfalse;
484  if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED |
485  FUNCFLAG_FHIDDEN |
486  FUNCFLAG_FNONBROWSABLE)) {
487  visible = Qfalse;
488  } else {
489  visible = Qtrue;
490  }
491  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
492  return visible;
493 }
494 
495 /*
496  * call-seq:
497  * WIN32OLE_METHOD#visible?
498  *
499  * Returns true if the method is public.
500  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
501  * method = WIN32OLE_METHOD.new(tobj, 'Add')
502  * puts method.visible? # => true
503  */
504 static VALUE
505 folemethod_visible(VALUE self)
506 {
507  struct olemethoddata *pmethod;
508  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
509  return ole_method_visible(pmethod->pTypeInfo, pmethod->index);
510 }
511 
512 static VALUE
513 ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
514 {
515  TYPEATTR *pTypeAttr;
516  HRESULT hr;
517  WORD i;
518  int flags;
519  HREFTYPE href;
520  ITypeInfo *pRefTypeInfo;
521  FUNCDESC *pFuncDesc;
522  BSTR bstr;
523  VALUE name;
524  VALUE event = Qfalse;
525 
526  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
527  if (FAILED(hr))
528  return event;
529  if(pTypeAttr->typekind != TKIND_COCLASS) {
530  pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
531  return event;
532  }
533  for (i = 0; i < pTypeAttr->cImplTypes; i++) {
534  hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
535  if (FAILED(hr))
536  continue;
537 
538  if (flags & IMPLTYPEFLAG_FSOURCE) {
539  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
540  i, &href);
541  if (FAILED(hr))
542  continue;
543  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
544  href, &pRefTypeInfo);
545  if (FAILED(hr))
546  continue;
547  hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index,
548  &pFuncDesc);
549  if (FAILED(hr)) {
550  OLE_RELEASE(pRefTypeInfo);
551  continue;
552  }
553 
554  hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo,
555  pFuncDesc->memid,
556  &bstr, NULL, NULL, NULL);
557  if (FAILED(hr)) {
558  pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
559  OLE_RELEASE(pRefTypeInfo);
560  continue;
561  }
562 
563  name = WC2VSTR(bstr);
564  pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
565  OLE_RELEASE(pRefTypeInfo);
566  if (rb_str_cmp(method_name, name) == 0) {
567  event = Qtrue;
568  break;
569  }
570  }
571  }
572  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
573  return event;
574 }
575 
576 /*
577  * call-seq:
578  * WIN32OLE_METHOD#event?
579  *
580  * Returns true if the method is event.
581  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
582  * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
583  * puts method.event? # => true
584  *
585  */
586 static VALUE
587 folemethod_event(VALUE self)
588 {
589  struct olemethoddata *pmethod;
590  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
591  if (!pmethod->pOwnerTypeInfo)
592  return Qfalse;
593  return ole_method_event(pmethod->pOwnerTypeInfo,
594  pmethod->index,
595  rb_ivar_get(self, rb_intern("name")));
596 }
597 
598 /*
599  * call-seq:
600  * WIN32OLE_METHOD#event_interface
601  *
602  * Returns event interface name if the method is event.
603  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
604  * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate')
605  * puts method.event_interface # => WorkbookEvents
606  */
607 static VALUE
608 folemethod_event_interface(VALUE self)
609 {
610  BSTR name;
611  struct olemethoddata *pmethod;
612  HRESULT hr;
613  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
614  if(folemethod_event(self) == Qtrue) {
615  hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL);
616  if(SUCCEEDED(hr))
617  return WC2VSTR(name);
618  }
619  return Qnil;
620 }
621 
622 static HRESULT
623 ole_method_docinfo_from_type(
624  ITypeInfo *pTypeInfo,
625  UINT method_index,
626  BSTR *name,
627  BSTR *helpstr,
628  DWORD *helpcontext,
629  BSTR *helpfile
630  )
631 {
632  FUNCDESC *pFuncDesc;
633  HRESULT hr;
634  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
635  if (FAILED(hr))
636  return hr;
637  hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
638  name, helpstr,
639  helpcontext, helpfile);
640  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
641  return hr;
642 }
643 
644 static VALUE
645 ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
646 {
647  HRESULT hr;
648  BSTR bhelpstring;
649  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring,
650  NULL, NULL);
651  if (FAILED(hr))
652  return Qnil;
653  return WC2VSTR(bhelpstring);
654 }
655 
656 /*
657  * call-seq:
658  * WIN32OLE_METHOD#helpstring
659  *
660  * Returns help string of OLE method. If the help string is not found,
661  * then the method returns nil.
662  * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser')
663  * method = WIN32OLE_METHOD.new(tobj, 'Navigate')
664  * puts method.helpstring # => Navigates to a URL or file.
665  *
666  */
667 static VALUE
668 folemethod_helpstring(VALUE self)
669 {
670  struct olemethoddata *pmethod;
671  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
672  return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index);
673 }
674 
675 static VALUE
676 ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
677 {
678  HRESULT hr;
679  BSTR bhelpfile;
680  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
681  NULL, &bhelpfile);
682  if (FAILED(hr))
683  return Qnil;
684  return WC2VSTR(bhelpfile);
685 }
686 
687 /*
688  * call-seq:
689  * WIN32OLE_METHOD#helpfile
690  *
691  * Returns help file. If help file is not found, then
692  * the method returns nil.
693  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
694  * method = WIN32OLE_METHOD.new(tobj, 'Add')
695  * puts method.helpfile # => C:\...\VBAXL9.CHM
696  */
697 static VALUE
698 folemethod_helpfile(VALUE self)
699 {
700  struct olemethoddata *pmethod;
701  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
702 
703  return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index);
704 }
705 
706 static VALUE
707 ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
708 {
709  HRESULT hr;
710  DWORD helpcontext = 0;
711  hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
712  &helpcontext, NULL);
713  if (FAILED(hr))
714  return Qnil;
715  return RB_INT2FIX(helpcontext);
716 }
717 
718 /*
719  * call-seq:
720  * WIN32OLE_METHOD#helpcontext
721  *
722  * Returns help context.
723  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
724  * method = WIN32OLE_METHOD.new(tobj, 'Add')
725  * puts method.helpcontext # => 65717
726  */
727 static VALUE
728 folemethod_helpcontext(VALUE self)
729 {
730  struct olemethoddata *pmethod;
731  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
732  return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index);
733 }
734 
735 static VALUE
736 ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
737 {
738  FUNCDESC *pFuncDesc;
739  HRESULT hr;
740  VALUE dispid = Qnil;
741  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
742  if (FAILED(hr))
743  return dispid;
744  dispid = RB_INT2NUM(pFuncDesc->memid);
745  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
746  return dispid;
747 }
748 
749 /*
750  * call-seq:
751  * WIN32OLE_METHOD#dispid
752  *
753  * Returns dispatch ID.
754  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
755  * method = WIN32OLE_METHOD.new(tobj, 'Add')
756  * puts method.dispid # => 181
757  */
758 static VALUE
759 folemethod_dispid(VALUE self)
760 {
761  struct olemethoddata *pmethod;
762  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
763  return ole_method_dispid(pmethod->pTypeInfo, pmethod->index);
764 }
765 
766 static VALUE
767 ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
768 {
769  FUNCDESC *pFuncDesc;
770  HRESULT hr;
771  VALUE offset_vtbl = Qnil;
772  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
773  if (FAILED(hr))
774  return offset_vtbl;
775  offset_vtbl = RB_INT2FIX(pFuncDesc->oVft);
776  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
777  return offset_vtbl;
778 }
779 
780 /*
781  * call-seq:
782  * WIN32OLE_METHOD#offset_vtbl
783  *
784  * Returns the offset ov VTBL.
785  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
786  * method = WIN32OLE_METHOD.new(tobj, 'Add')
787  * puts method.offset_vtbl # => 40
788  */
789 static VALUE
790 folemethod_offset_vtbl(VALUE self)
791 {
792  struct olemethoddata *pmethod;
793  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
794  return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index);
795 }
796 
797 static VALUE
798 ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
799 {
800  FUNCDESC *pFuncDesc;
801  HRESULT hr;
802  VALUE size_params = Qnil;
803  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
804  if (FAILED(hr))
805  return size_params;
806  size_params = RB_INT2FIX(pFuncDesc->cParams);
807  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
808  return size_params;
809 }
810 
811 /*
812  * call-seq:
813  * WIN32OLE_METHOD#size_params
814  *
815  * Returns the size of arguments of the method.
816  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
817  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
818  * puts method.size_params # => 11
819  *
820  */
821 static VALUE
822 folemethod_size_params(VALUE self)
823 {
824  struct olemethoddata *pmethod;
825  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
826  return ole_method_size_params(pmethod->pTypeInfo, pmethod->index);
827 }
828 
829 static VALUE
830 ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
831 {
832  FUNCDESC *pFuncDesc;
833  HRESULT hr;
834  VALUE size_opt_params = Qnil;
835  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
836  if (FAILED(hr))
837  return size_opt_params;
838  size_opt_params = RB_INT2FIX(pFuncDesc->cParamsOpt);
839  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
840  return size_opt_params;
841 }
842 
843 /*
844  * call-seq:
845  * WIN32OLE_METHOD#size_opt_params
846  *
847  * Returns the size of optional parameters.
848  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
849  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
850  * puts method.size_opt_params # => 4
851  */
852 static VALUE
853 folemethod_size_opt_params(VALUE self)
854 {
855  struct olemethoddata *pmethod;
856  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
857  return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index);
858 }
859 
860 static VALUE
861 ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
862 {
863  FUNCDESC *pFuncDesc;
864  HRESULT hr;
865  BSTR *bstrs;
866  UINT len, i;
867  VALUE param;
868  VALUE params = rb_ary_new();
869  hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
870  if (FAILED(hr))
871  return params;
872 
873  len = 0;
874  bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
875  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
876  bstrs, pFuncDesc->cParams + 1,
877  &len);
878  if (FAILED(hr)) {
879  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
880  return params;
881  }
882  SysFreeString(bstrs[0]);
883  if (pFuncDesc->cParams > 0) {
884  for(i = 1; i < len; i++) {
885  param = create_win32ole_param(pTypeInfo, method_index, i-1, WC2VSTR(bstrs[i]));
886  rb_ary_push(params, param);
887  }
888  }
889  pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
890  return params;
891 }
892 
893 /*
894  * call-seq:
895  * WIN32OLE_METHOD#params
896  *
897  * returns array of WIN32OLE_PARAM object corresponding with method parameters.
898  * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook')
899  * method = WIN32OLE_METHOD.new(tobj, 'SaveAs')
900  * p method.params # => [Filename, FileFormat, Password, WriteResPassword,
901  * ReadOnlyRecommended, CreateBackup, AccessMode,
902  * ConflictResolution, AddToMru, TextCodepage,
903  * TextVisualLayout]
904  */
905 static VALUE
906 folemethod_params(VALUE self)
907 {
908  struct olemethoddata *pmethod;
909  TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
910  return ole_method_params(pmethod->pTypeInfo, pmethod->index);
911 }
912 
913 /*
914  * call-seq:
915  * WIN32OLE_METHOD#inspect -> String
916  *
917  * Returns the method name with class name.
918  *
919  */
920 static VALUE
921 folemethod_inspect(VALUE self)
922 {
923  return default_inspect(self, "WIN32OLE_METHOD");
924 }
925 
927 {
928  cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject);
930  rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
931  rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0);
932  rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0);
933  rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0);
934  rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0);
935  rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0);
936  rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0);
937  rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0);
938  rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0);
939  rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0);
940  rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0);
941  rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0);
942  rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0);
943  rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0);
944  rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0);
945  rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0);
946  rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0);
947  rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0);
948  rb_define_alias(cWIN32OLE_METHOD, "to_s", "name");
949  rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0);
950 }
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
VALUE cWIN32OLE_METHOD
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
void Init_win32ole_method(void)
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
#define strcasecmp
Definition: win32.h:191
VALUE folemethod_s_allocate(VALUE klass)
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
#define OLE_GET_TYPEATTR(X, Y)
Definition: win32ole.h:108
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1210
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3159
#define RB_INT2NUM(x)
Definition: ruby.h:1526
VALUE cWIN32OLE_TYPE
Definition: win32ole_type.h:3
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 * pOwnerTypeInfo
VALUE default_inspect(VALUE self, const char *class_name)
Definition: win32ole.c:1344
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
IUnknown DWORD
Definition: win32ole.c:32
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 WC2VSTR(x)
Definition: win32ole.h:130
VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
#define Qfalse
Definition: ruby.h:436
#define ALLOCA_N(type, n)
Definition: ruby.h:1593
#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
#define OLE_RELEASE(X)
Definition: win32ole.h:98
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 create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name)
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
#define OLE_RELEASE_TYPEATTR(X, Y)
Definition: win32ole.h:109
#define SafeStringValue(v)
Definition: ruby.h:574
const char * name
Definition: nkf.c:208
#define StringValuePtr(v)
Definition: ruby.h:570
#define RB_FIX2INT(x)
Definition: ruby.h:681
ITypeInfo * itypeinfo(VALUE self)
Definition: win32ole_type.c:76
#define RB_INT2FIX(i)
Definition: ruby.h:231
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
Definition: win32ole.c:3656
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