Ruby  2.5.0dev(2017-10-22revision60238)
win32ole_event.c
Go to the documentation of this file.
1 #include "win32ole.h"
2 
3 /*
4  * Document-class: WIN32OLE_EVENT
5  *
6  * <code>WIN32OLE_EVENT</code> objects controls OLE event.
7  */
8 
10 
11 typedef struct {
14 
16 
18  STDMETHOD(QueryInterface)(
19  PEVENTSINK,
20  REFIID,
21  LPVOID *);
22  STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
23  STDMETHOD_(ULONG, Release)(PEVENTSINK);
24 
25  STDMETHOD(GetTypeInfoCount)(
26  PEVENTSINK,
27  UINT *);
28  STDMETHOD(GetTypeInfo)(
29  PEVENTSINK,
30  UINT,
31  LCID,
32  ITypeInfo **);
33  STDMETHOD(GetIDsOfNames)(
34  PEVENTSINK,
35  REFIID,
36  OLECHAR **,
37  UINT,
38  LCID,
39  DISPID *);
40  STDMETHOD(Invoke)(
41  PEVENTSINK,
42  DISPID,
43  REFIID,
44  LCID,
45  WORD,
46  DISPPARAMS *,
47  VARIANT *,
48  EXCEPINFO *,
49  UINT *);
50 };
51 
52 typedef struct tagIEVENTSINKOBJ {
55  IID m_iid;
56  long m_event_id;
57  ITypeInfo *pTypeInfo;
59 
60 struct oleeventdata {
62  IConnectionPoint *pConnectionPoint;
63  IDispatch *pDispatch;
64  long event_id;
65 };
66 
67 static VALUE ary_ole_event;
68 static ID id_events;
69 
71 
72 STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID*);
73 STDMETHODIMP_(ULONG) EVENTSINK_AddRef(PEVENTSINK);
74 STDMETHODIMP_(ULONG) EVENTSINK_Release(PEVENTSINK);
75 STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK, UINT*);
76 STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK, UINT, LCID, ITypeInfo**);
77 STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK, REFIID, OLECHAR**, UINT, LCID, DISPID*);
78 STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK, DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
79 
80 static const IEventSinkVtbl vtEventSink = {
83  EVENTSINK_Release,
88 };
89 
90 void EVENTSINK_Destructor(PIEVENTSINKOBJ);
91 static void ole_val2ptr_variant(VALUE val, VARIANT *var);
92 static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
93 static VALUE hash2result(VALUE hash);
94 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
95 static VALUE exec_callback(VALUE arg);
96 static VALUE rescue_callback(VALUE arg);
97 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
98 static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
99 static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
100 static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
101 static long ole_search_event_at(VALUE ary, VALUE ev);
102 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
103 static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
104 static void ole_delete_event(VALUE ary, VALUE ev);
105 static void oleevent_free(void *ptr);
106 static size_t oleevent_size(const void *ptr);
107 static VALUE fev_s_allocate(VALUE klass);
108 static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
109 static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
110 static void ole_msg_loop(void);
111 static VALUE fev_s_msg_loop(VALUE klass);
112 static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
113 static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
114 static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
115 static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
116 static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
117 static VALUE fev_unadvise(VALUE self);
118 static VALUE fev_set_handler(VALUE self, VALUE val);
119 static VALUE fev_get_handler(VALUE self);
120 static VALUE evs_push(VALUE ev);
121 static VALUE evs_delete(long i);
122 static VALUE evs_entry(long i);
123 static long evs_length(void);
124 
125 
126 static const rb_data_type_t oleevent_datatype = {
127  "win32ole_event",
128  {NULL, oleevent_free, oleevent_size,},
130 };
131 
132 STDMETHODIMP EVENTSINK_Invoke(
133  PEVENTSINK pEventSink,
134  DISPID dispid,
135  REFIID riid,
136  LCID lcid,
137  WORD wFlags,
138  DISPPARAMS *pdispparams,
139  VARIANT *pvarResult,
140  EXCEPINFO *pexcepinfo,
141  UINT *puArgErr
142  ) {
143 
144  HRESULT hr;
145  BSTR bstr;
146  unsigned int count;
147  unsigned int i;
148  ITypeInfo *pTypeInfo;
149  VARIANT *pvar;
150  VALUE ary, obj, event, args, outargv, ev, result;
151  VALUE handler = Qnil;
152  VALUE arg[3];
153  VALUE mid;
154  VALUE is_outarg = Qfalse;
155  BOOL is_default_handler = FALSE;
156  int state;
157 
158  PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
159  pTypeInfo = pEV->pTypeInfo;
160  obj = evs_entry(pEV->m_event_id);
161  if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
162  return NOERROR;
163  }
164 
165  ary = rb_ivar_get(obj, id_events);
166  if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) {
167  return NOERROR;
168  }
169  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
170  &bstr, 1, &count);
171  if (FAILED(hr)) {
172  return NOERROR;
173  }
174  ev = WC2VSTR(bstr);
175  event = ole_search_event(ary, ev, &is_default_handler);
176  if (RB_TYPE_P(event, T_ARRAY)) {
177  handler = rb_ary_entry(event, 0);
178  mid = rb_intern("call");
179  is_outarg = rb_ary_entry(event, 3);
180  } else {
181  handler = rb_ivar_get(obj, rb_intern("handler"));
182  if (handler == Qnil) {
183  return NOERROR;
184  }
185  mid = ole_search_handler_method(handler, ev, &is_default_handler);
186  }
187  if (handler == Qnil || mid == Qnil) {
188  return NOERROR;
189  }
190 
191  args = rb_ary_new();
192  if (is_default_handler) {
193  rb_ary_push(args, ev);
194  }
195 
196  /* make argument of event handler */
197  for (i = 0; i < pdispparams->cArgs; ++i) {
198  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
199  rb_ary_push(args, ole_variant2val(pvar));
200  }
201  outargv = Qnil;
202  if (is_outarg == Qtrue) {
203  outargv = rb_ary_new();
204  rb_ary_push(args, outargv);
205  }
206 
207  /*
208  * if exception raised in event callback,
209  * then you receive cfp consistency error.
210  * to avoid this error we use begin rescue end.
211  * and the exception raised then error message print
212  * and exit ruby process by Win32OLE itself.
213  */
214  arg[0] = handler;
215  arg[1] = mid;
216  arg[2] = args;
217  result = rb_protect(exec_callback, (VALUE)arg, &state);
218  if (state != 0) {
219  rescue_callback(Qnil);
220  }
221  if(RB_TYPE_P(result, T_HASH)) {
222  hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
223  result = hash2result(result);
224  }else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) {
225  ary2ptr_dispparams(outargv, pdispparams);
226  }
227 
228  if (pvarResult) {
229  VariantInit(pvarResult);
230  ole_val2variant(result, pvarResult);
231  }
232 
233  return NOERROR;
234 }
235 
236 STDMETHODIMP
238  PEVENTSINK pEV,
239  REFIID iid,
240  LPVOID* ppv
241  ) {
242  if (IsEqualIID(iid, &IID_IUnknown) ||
243  IsEqualIID(iid, &IID_IDispatch) ||
244  IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
245  *ppv = pEV;
246  }
247  else {
248  *ppv = NULL;
249  return E_NOINTERFACE;
250  }
251  ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
252  return NOERROR;
253 }
254 
255 STDMETHODIMP_(ULONG)
257  PEVENTSINK pEV
258  ){
259  PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
260  return ++pEVObj->m_cRef;
261 }
262 
263 STDMETHODIMP_(ULONG) EVENTSINK_Release(
264  PEVENTSINK pEV
265  ) {
266  PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
267  --pEVObj->m_cRef;
268  if(pEVObj->m_cRef != 0)
269  return pEVObj->m_cRef;
270  EVENTSINK_Destructor(pEVObj);
271  return 0;
272 }
273 
275  PEVENTSINK pEV,
276  UINT *pct
277  ) {
278  *pct = 0;
279  return NOERROR;
280 }
281 
283  PEVENTSINK pEV,
284  UINT info,
285  LCID lcid,
286  ITypeInfo **pInfo
287  ) {
288  *pInfo = NULL;
289  return DISP_E_BADINDEX;
290 }
291 
293  PEVENTSINK pEventSink,
294  REFIID riid,
295  OLECHAR **szNames,
296  UINT cNames,
297  LCID lcid,
298  DISPID *pDispID
299  ) {
300  ITypeInfo *pTypeInfo;
301  PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
302  pTypeInfo = pEV->pTypeInfo;
303  if (pTypeInfo) {
304  return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
305  }
306  return DISP_E_UNKNOWNNAME;
307 }
308 
309 PIEVENTSINKOBJ
311 {
312  PIEVENTSINKOBJ pEv;
313  pEv = ALLOC_N(IEVENTSINKOBJ, 1);
314  if(pEv == NULL) return NULL;
315  pEv->lpVtbl = &vtEventSink;
316  pEv->m_cRef = 0;
317  pEv->m_event_id = 0;
318  pEv->pTypeInfo = NULL;
319  return pEv;
320 }
321 
322 void
324  PIEVENTSINKOBJ pEVObj
325  ) {
326  if(pEVObj != NULL) {
327  OLE_RELEASE(pEVObj->pTypeInfo);
328  free(pEVObj);
329  pEVObj = NULL;
330  }
331 }
332 
333 static void
334 ole_val2ptr_variant(VALUE val, VARIANT *var)
335 {
336  switch (TYPE(val)) {
337  case T_STRING:
338  if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
339  *V_BSTRREF(var) = ole_vstr2wc(val);
340  }
341  break;
342  case T_FIXNUM:
343  switch(V_VT(var)) {
344  case (VT_UI1 | VT_BYREF) :
345  *V_UI1REF(var) = RB_NUM2CHR(val);
346  break;
347  case (VT_I2 | VT_BYREF) :
348  *V_I2REF(var) = (short)RB_NUM2INT(val);
349  break;
350  case (VT_I4 | VT_BYREF) :
351  *V_I4REF(var) = RB_NUM2INT(val);
352  break;
353  case (VT_R4 | VT_BYREF) :
354  *V_R4REF(var) = (float)RB_NUM2INT(val);
355  break;
356  case (VT_R8 | VT_BYREF) :
357  *V_R8REF(var) = RB_NUM2INT(val);
358  break;
359  default:
360  break;
361  }
362  break;
363  case T_FLOAT:
364  switch(V_VT(var)) {
365  case (VT_I2 | VT_BYREF) :
366  *V_I2REF(var) = (short)RB_NUM2INT(val);
367  break;
368  case (VT_I4 | VT_BYREF) :
369  *V_I4REF(var) = RB_NUM2INT(val);
370  break;
371  case (VT_R4 | VT_BYREF) :
372  *V_R4REF(var) = (float)NUM2DBL(val);
373  break;
374  case (VT_R8 | VT_BYREF) :
375  *V_R8REF(var) = NUM2DBL(val);
376  break;
377  default:
378  break;
379  }
380  break;
381  case T_BIGNUM:
382  if (V_VT(var) == (VT_R8 | VT_BYREF)) {
383  *V_R8REF(var) = rb_big2dbl(val);
384  }
385  break;
386  case T_TRUE:
387  if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
388  *V_BOOLREF(var) = VARIANT_TRUE;
389  }
390  break;
391  case T_FALSE:
392  if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
393  *V_BOOLREF(var) = VARIANT_FALSE;
394  }
395  break;
396  default:
397  break;
398  }
399 }
400 
401 static void
402 hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
403 {
404  BSTR *bstrs;
405  HRESULT hr;
406  UINT len, i;
407  VARIANT *pvar;
408  VALUE val;
409  VALUE key;
410  len = 0;
411  bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
412  hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
413  bstrs, pdispparams->cArgs + 1,
414  &len);
415  if (FAILED(hr))
416  return;
417 
418  for (i = 0; i < len - 1; i++) {
419  key = WC2VSTR(bstrs[i + 1]);
420  val = rb_hash_aref(hash, RB_UINT2NUM(i));
421  if (val == Qnil)
422  val = rb_hash_aref(hash, key);
423  if (val == Qnil)
424  val = rb_hash_aref(hash, rb_str_intern(key));
425  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
426  ole_val2ptr_variant(val, pvar);
427  }
428 }
429 
430 static VALUE
431 hash2result(VALUE hash)
432 {
433  VALUE ret = Qnil;
434  ret = rb_hash_aref(hash, rb_str_new2("return"));
435  if (ret == Qnil)
436  ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
437  return ret;
438 }
439 
440 static void
441 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
442 {
443  int i;
444  VALUE v;
445  VARIANT *pvar;
446  for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
447  v = rb_ary_entry(ary, i);
448  pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
449  ole_val2ptr_variant(v, pvar);
450  }
451 }
452 
453 static VALUE
454 exec_callback(VALUE arg)
455 {
456  VALUE *parg = (VALUE *)arg;
457  VALUE handler = parg[0];
458  VALUE mid = parg[1];
459  VALUE args = parg[2];
460  return rb_apply(handler, mid, args);
461 }
462 
463 static VALUE
464 rescue_callback(VALUE arg)
465 {
466 
467  VALUE error;
468  VALUE e = rb_errinfo();
469  VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
470  VALUE msg = rb_funcall(e, rb_intern("message"), 0);
471  bt = rb_ary_entry(bt, 0);
472  error = rb_sprintf("%"PRIsVALUE": %"PRIsVALUE" (%s)\n", bt, msg, rb_obj_classname(e));
473  rb_write_error_str(error);
474  rb_backtrace();
475  ruby_finalize();
476  exit(-1);
477 
478  return Qnil;
479 }
480 
481 static HRESULT
482 find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
483 {
484  HRESULT hr;
485  IDispatch *pDispatch;
486  ITypeInfo *pTypeInfo;
487  ITypeLib *pTypeLib;
488  TYPEATTR *pTypeAttr;
489  HREFTYPE RefType;
490  ITypeInfo *pImplTypeInfo;
491  TYPEATTR *pImplTypeAttr;
492 
493  struct oledata *pole = NULL;
494  unsigned int index;
495  unsigned int count;
496  int type;
497  BSTR bstr;
498  char *pstr;
499 
500  BOOL is_found = FALSE;
501  LCID lcid = cWIN32OLE_lcid;
502 
503  pole = oledata_get_struct(ole);
504 
505  pDispatch = pole->pDispatch;
506 
507  hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
508  if (FAILED(hr))
509  return hr;
510 
511  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
512  &pTypeLib,
513  &index);
514  OLE_RELEASE(pTypeInfo);
515  if (FAILED(hr))
516  return hr;
517 
518  if (!pitf) {
519  hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
520  piid,
521  ppTypeInfo);
522  OLE_RELEASE(pTypeLib);
523  return hr;
524  }
525  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
526  for (index = 0; index < count; index++) {
527  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
528  index,
529  &pTypeInfo);
530  if (FAILED(hr))
531  break;
532  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
533 
534  if(FAILED(hr)) {
535  OLE_RELEASE(pTypeInfo);
536  break;
537  }
538  if(pTypeAttr->typekind == TKIND_COCLASS) {
539  for (type = 0; type < pTypeAttr->cImplTypes; type++) {
540  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
541  type,
542  &RefType);
543  if (FAILED(hr))
544  break;
545  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
546  RefType,
547  &pImplTypeInfo);
548  if (FAILED(hr))
549  break;
550 
551  hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
552  -1,
553  &bstr,
554  NULL, NULL, NULL);
555  if (FAILED(hr)) {
556  OLE_RELEASE(pImplTypeInfo);
557  break;
558  }
559  pstr = ole_wc2mb(bstr);
560  if (strcmp(pitf, pstr) == 0) {
561  hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
562  &pImplTypeAttr);
563  if (SUCCEEDED(hr)) {
564  is_found = TRUE;
565  *piid = pImplTypeAttr->guid;
566  if (ppTypeInfo) {
567  *ppTypeInfo = pImplTypeInfo;
568  (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
569  }
570  pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
571  pImplTypeAttr);
572  }
573  }
574  free(pstr);
575  OLE_RELEASE(pImplTypeInfo);
576  if (is_found || FAILED(hr))
577  break;
578  }
579  }
580 
581  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
582  OLE_RELEASE(pTypeInfo);
583  if (is_found || FAILED(hr))
584  break;
585  }
586  OLE_RELEASE(pTypeLib);
587  if(!is_found)
588  return E_NOINTERFACE;
589  return hr;
590 }
591 
592 static HRESULT
593 find_coclass(
594  ITypeInfo *pTypeInfo,
595  TYPEATTR *pTypeAttr,
596  ITypeInfo **pCOTypeInfo,
597  TYPEATTR **pCOTypeAttr)
598 {
599  HRESULT hr = E_NOINTERFACE;
600  ITypeLib *pTypeLib;
601  int count;
602  BOOL found = FALSE;
603  ITypeInfo *pTypeInfo2;
604  TYPEATTR *pTypeAttr2;
605  int flags;
606  int i,j;
607  HREFTYPE href;
608  ITypeInfo *pRefTypeInfo;
609  TYPEATTR *pRefTypeAttr;
610 
611  hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
612  if (FAILED(hr)) {
613  return hr;
614  }
615  count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
616  for (i = 0; i < count && !found; i++) {
617  hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
618  if (FAILED(hr))
619  continue;
620  hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
621  if (FAILED(hr)) {
622  OLE_RELEASE(pTypeInfo2);
623  continue;
624  }
625  if (pTypeAttr2->typekind != TKIND_COCLASS) {
626  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
627  OLE_RELEASE(pTypeInfo2);
628  continue;
629  }
630  for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
631  hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
632  if (FAILED(hr))
633  continue;
634  if (!(flags & IMPLTYPEFLAG_FDEFAULT))
635  continue;
636  hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
637  if (FAILED(hr))
638  continue;
639  hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
640  if (FAILED(hr))
641  continue;
642  hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
643  if (FAILED(hr)) {
644  OLE_RELEASE(pRefTypeInfo);
645  continue;
646  }
647  if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
648  found = TRUE;
649  }
650  }
651  if (!found) {
652  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
653  OLE_RELEASE(pTypeInfo2);
654  }
655  }
656  OLE_RELEASE(pTypeLib);
657  if (found) {
658  *pCOTypeInfo = pTypeInfo2;
659  *pCOTypeAttr = pTypeAttr2;
660  hr = S_OK;
661  } else {
662  hr = E_NOINTERFACE;
663  }
664  return hr;
665 }
666 
667 static HRESULT
668 find_default_source_from_typeinfo(
669  ITypeInfo *pTypeInfo,
670  TYPEATTR *pTypeAttr,
671  ITypeInfo **ppTypeInfo)
672 {
673  int i = 0;
674  HRESULT hr = E_NOINTERFACE;
675  int flags;
676  HREFTYPE hRefType;
677  /* Enumerate all implemented types of the COCLASS */
678  for (i = 0; i < pTypeAttr->cImplTypes; i++) {
679  hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
680  if (FAILED(hr))
681  continue;
682 
683  /*
684  looking for the [default] [source]
685  we just hope that it is a dispinterface :-)
686  */
687  if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
688  (flags & IMPLTYPEFLAG_FSOURCE)) {
689 
690  hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
691  i, &hRefType);
692  if (FAILED(hr))
693  continue;
694  hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
695  hRefType, ppTypeInfo);
696  if (SUCCEEDED(hr))
697  break;
698  }
699  }
700  return hr;
701 }
702 
703 static HRESULT
704 find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
705 {
706  HRESULT hr;
707  IProvideClassInfo2 *pProvideClassInfo2;
708  IProvideClassInfo *pProvideClassInfo;
709  void *p;
710 
711  IDispatch *pDispatch;
712  ITypeInfo *pTypeInfo;
713  ITypeInfo *pTypeInfo2 = NULL;
714  TYPEATTR *pTypeAttr;
715  TYPEATTR *pTypeAttr2 = NULL;
716 
717  struct oledata *pole = NULL;
718 
719  pole = oledata_get_struct(ole);
720  pDispatch = pole->pDispatch;
721  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
722  &IID_IProvideClassInfo2,
723  &p);
724  if (SUCCEEDED(hr)) {
725  pProvideClassInfo2 = p;
726  hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
727  GUIDKIND_DEFAULT_SOURCE_DISP_IID,
728  piid);
729  OLE_RELEASE(pProvideClassInfo2);
730  if (SUCCEEDED(hr)) {
731  hr = find_iid(ole, NULL, piid, ppTypeInfo);
732  }
733  }
734  if (SUCCEEDED(hr)) {
735  return hr;
736  }
737  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
738  &IID_IProvideClassInfo,
739  &p);
740  if (SUCCEEDED(hr)) {
741  pProvideClassInfo = p;
742  hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
743  &pTypeInfo);
744  OLE_RELEASE(pProvideClassInfo);
745  }
746  if (FAILED(hr)) {
747  hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
748  }
749  if (FAILED(hr))
750  return hr;
751  hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
752  if (FAILED(hr)) {
753  OLE_RELEASE(pTypeInfo);
754  return hr;
755  }
756 
757  *ppTypeInfo = 0;
758  hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
759  if (!*ppTypeInfo) {
760  hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
761  if (SUCCEEDED(hr)) {
762  hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
763  OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
764  OLE_RELEASE(pTypeInfo2);
765  }
766  }
767  OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
768  OLE_RELEASE(pTypeInfo);
769  /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
770  if (!*ppTypeInfo) {
771  if (SUCCEEDED(hr))
772  hr = E_UNEXPECTED;
773  return hr;
774  }
775 
776  /* Determine IID of default source interface */
777  hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
778  if (SUCCEEDED(hr)) {
779  *piid = pTypeAttr->guid;
780  (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
781  }
782  else
783  OLE_RELEASE(*ppTypeInfo);
784 
785  return hr;
786 }
787 
788 static long
789 ole_search_event_at(VALUE ary, VALUE ev)
790 {
791  VALUE event;
792  VALUE event_name;
793  long i, len;
794  long ret = -1;
795  len = RARRAY_LEN(ary);
796  for(i = 0; i < len; i++) {
797  event = rb_ary_entry(ary, i);
798  event_name = rb_ary_entry(event, 1);
799  if(NIL_P(event_name) && NIL_P(ev)) {
800  ret = i;
801  break;
802  }
803  else if (RB_TYPE_P(ev, T_STRING) &&
804  RB_TYPE_P(event_name, T_STRING) &&
805  rb_str_cmp(ev, event_name) == 0) {
806  ret = i;
807  break;
808  }
809  }
810  return ret;
811 }
812 
813 static VALUE
814 ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
815 {
816  VALUE event;
817  VALUE def_event;
818  VALUE event_name;
819  int i, len;
820  *is_default = FALSE;
821  def_event = Qnil;
822  len = RARRAY_LEN(ary);
823  for(i = 0; i < len; i++) {
824  event = rb_ary_entry(ary, i);
825  event_name = rb_ary_entry(event, 1);
826  if(NIL_P(event_name)) {
827  *is_default = TRUE;
828  def_event = event;
829  }
830  else if (rb_str_cmp(ev, event_name) == 0) {
831  *is_default = FALSE;
832  return event;
833  }
834  }
835  return def_event;
836 }
837 
838 static VALUE
839 ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
840 {
841  VALUE mid;
842 
843  *is_default_handler = FALSE;
844  mid = rb_to_id(rb_sprintf("on%"PRIsVALUE, ev));
845  if (rb_respond_to(handler, mid)) {
846  return mid;
847  }
848  mid = rb_intern("method_missing");
849  if (rb_respond_to(handler, mid)) {
850  *is_default_handler = TRUE;
851  return mid;
852  }
853  return Qnil;
854 }
855 
856 static void
857 ole_delete_event(VALUE ary, VALUE ev)
858 {
859  long at = -1;
860  at = ole_search_event_at(ary, ev);
861  if (at >= 0) {
862  rb_ary_delete_at(ary, at);
863  }
864 }
865 
866 
867 static void
868 oleevent_free(void *ptr)
869 {
870  struct oleeventdata *poleev = ptr;
871  if (poleev->pConnectionPoint) {
872  poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
873  OLE_RELEASE(poleev->pConnectionPoint);
874  poleev->pConnectionPoint = NULL;
875  }
876  OLE_RELEASE(poleev->pDispatch);
877  free(poleev);
878 }
879 
880 static size_t
881 oleevent_size(const void *ptr)
882 {
883  return ptr ? sizeof(struct oleeventdata) : 0;
884 }
885 
886 static VALUE
887 fev_s_allocate(VALUE klass)
888 {
889  VALUE obj;
890  struct oleeventdata *poleev;
891  obj = TypedData_Make_Struct(klass, struct oleeventdata, &oleevent_datatype, poleev);
892  poleev->dwCookie = 0;
893  poleev->pConnectionPoint = NULL;
894  poleev->event_id = 0;
895  poleev->pDispatch = NULL;
896  return obj;
897 }
898 
899 static VALUE
900 ev_advise(int argc, VALUE *argv, VALUE self)
901 {
902 
903  VALUE ole, itf;
904  struct oledata *pole = NULL;
905  char *pitf;
906  HRESULT hr;
907  IID iid;
908  ITypeInfo *pTypeInfo = 0;
909  IDispatch *pDispatch;
910  IConnectionPointContainer *pContainer;
911  IConnectionPoint *pConnectionPoint;
912  IEVENTSINKOBJ *pIEV;
913  DWORD dwCookie;
914  struct oleeventdata *poleev;
915  void *p;
916 
917  rb_scan_args(argc, argv, "11", &ole, &itf);
918 
919  if (!rb_obj_is_kind_of(ole, cWIN32OLE)) {
920  rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object");
921  }
922 
923  if(!RB_TYPE_P(itf, T_NIL)) {
924  pitf = StringValuePtr(itf);
925  if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) {
926  rb_raise(rb_eSecurityError, "insecure event creation - `%s'",
927  StringValuePtr(itf));
928  }
929  hr = find_iid(ole, pitf, &iid, &pTypeInfo);
930  }
931  else {
932  hr = find_default_source(ole, &iid, &pTypeInfo);
933  }
934  if (FAILED(hr)) {
935  ole_raise(hr, rb_eRuntimeError, "interface not found");
936  }
937 
938  pole = oledata_get_struct(ole);
939  pDispatch = pole->pDispatch;
940  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
941  &IID_IConnectionPointContainer,
942  &p);
943  if (FAILED(hr)) {
944  OLE_RELEASE(pTypeInfo);
946  "failed to query IConnectionPointContainer");
947  }
948  pContainer = p;
949 
950  hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
951  &iid,
952  &pConnectionPoint);
953  OLE_RELEASE(pContainer);
954  if (FAILED(hr)) {
955  OLE_RELEASE(pTypeInfo);
956  ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint");
957  }
958  pIEV = EVENTSINK_Constructor();
959  pIEV->m_iid = iid;
960  hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
961  (IUnknown*)pIEV,
962  &dwCookie);
963  if (FAILED(hr)) {
964  ole_raise(hr, rb_eRuntimeError, "Advise Error");
965  }
966 
967  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
968  pIEV->m_event_id = evs_length();
969  pIEV->pTypeInfo = pTypeInfo;
970  poleev->dwCookie = dwCookie;
972  poleev->event_id = pIEV->m_event_id;
973  poleev->pDispatch = pDispatch;
974  OLE_ADDREF(pDispatch);
975 
976  return self;
977 }
978 
979 /*
980  * call-seq:
981  * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
982  *
983  * Returns OLE event object.
984  * The first argument specifies WIN32OLE object.
985  * The second argument specifies OLE event name.
986  * ie = WIN32OLE.new('InternetExplorer.Application')
987  * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
988  */
989 static VALUE
990 fev_initialize(int argc, VALUE *argv, VALUE self)
991 {
992  ev_advise(argc, argv, self);
993  evs_push(self);
994  rb_ivar_set(self, id_events, rb_ary_new());
995  fev_set_handler(self, Qnil);
996  return self;
997 }
998 
999 static void
1000 ole_msg_loop(void)
1001 {
1002  MSG msg;
1003  while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
1004  TranslateMessage(&msg);
1005  DispatchMessage(&msg);
1006  }
1007 }
1008 
1009 /*
1010  * call-seq:
1011  * WIN32OLE_EVENT.message_loop
1012  *
1013  * Translates and dispatches Windows message.
1014  */
1015 static VALUE
1016 fev_s_msg_loop(VALUE klass)
1017 {
1018  ole_msg_loop();
1019  return Qnil;
1020 }
1021 
1022 static void
1023 add_event_call_back(VALUE obj, VALUE event, VALUE data)
1024 {
1025  VALUE events = rb_ivar_get(obj, id_events);
1026  if (NIL_P(events) || !RB_TYPE_P(events, T_ARRAY)) {
1027  events = rb_ary_new();
1028  rb_ivar_set(obj, id_events, events);
1029  }
1030  ole_delete_event(events, event);
1031  rb_ary_push(events, data);
1032 }
1033 
1034 static VALUE
1035 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
1036 {
1037  struct oleeventdata *poleev;
1038  VALUE event, args, data;
1039  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
1040  if (poleev->pConnectionPoint == NULL) {
1041  rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
1042  }
1043  rb_scan_args(argc, argv, "01*", &event, &args);
1044  if(!NIL_P(event)) {
1045  if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
1046  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
1047  }
1048  if (RB_TYPE_P(event, T_SYMBOL)) {
1049  event = rb_sym2str(event);
1050  }
1051  }
1052  data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
1053  add_event_call_back(self, event, data);
1054  return Qnil;
1055 }
1056 
1057 /*
1058  * call-seq:
1059  * WIN32OLE_EVENT#on_event([event]){...}
1060  *
1061  * Defines the callback event.
1062  * If argument is omitted, this method defines the callback of all events.
1063  * If you want to modify reference argument in callback, return hash in
1064  * callback. If you want to return value to OLE server as result of callback
1065  * use `return' or :return.
1066  *
1067  * ie = WIN32OLE.new('InternetExplorer.Application')
1068  * ev = WIN32OLE_EVENT.new(ie)
1069  * ev.on_event("NavigateComplete") {|url| puts url}
1070  * ev.on_event() {|ev, *args| puts "#{ev} fired"}
1071  *
1072  * ev.on_event("BeforeNavigate2") {|*args|
1073  * ...
1074  * # set true to BeforeNavigate reference argument `Cancel'.
1075  * # Cancel is 7-th argument of BeforeNavigate,
1076  * # so you can use 6 as key of hash instead of 'Cancel'.
1077  * # The argument is counted from 0.
1078  * # The hash key of 0 means first argument.)
1079  * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
1080  * }
1081  *
1082  * ev.on_event(...) {|*args|
1083  * {:return => 1, :xxx => yyy}
1084  * }
1085  */
1086 static VALUE
1087 fev_on_event(int argc, VALUE *argv, VALUE self)
1088 {
1089  return ev_on_event(argc, argv, self, Qfalse);
1090 }
1091 
1092 /*
1093  * call-seq:
1094  * WIN32OLE_EVENT#on_event_with_outargs([event]){...}
1095  *
1096  * Defines the callback of event.
1097  * If you want modify argument in callback,
1098  * you could use this method instead of WIN32OLE_EVENT#on_event.
1099  *
1100  * ie = WIN32OLE.new('InternetExplorer.Application')
1101  * ev = WIN32OLE_EVENT.new(ie)
1102  * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
1103  * args.last[6] = true
1104  * }
1105  */
1106 static VALUE
1107 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
1108 {
1109  return ev_on_event(argc, argv, self, Qtrue);
1110 }
1111 
1112 /*
1113  * call-seq:
1114  * WIN32OLE_EVENT#off_event([event])
1115  *
1116  * removes the callback of event.
1117  *
1118  * ie = WIN32OLE.new('InternetExplorer.Application')
1119  * ev = WIN32OLE_EVENT.new(ie)
1120  * ev.on_event('BeforeNavigate2') {|*args|
1121  * args.last[6] = true
1122  * }
1123  * ...
1124  * ev.off_event('BeforeNavigate2')
1125  * ...
1126  */
1127 static VALUE
1128 fev_off_event(int argc, VALUE *argv, VALUE self)
1129 {
1130  VALUE event = Qnil;
1131  VALUE events;
1132 
1133  rb_scan_args(argc, argv, "01", &event);
1134  if(!NIL_P(event)) {
1135  if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
1136  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
1137  }
1138  if (RB_TYPE_P(event, T_SYMBOL)) {
1139  event = rb_sym2str(event);
1140  }
1141  }
1142  events = rb_ivar_get(self, id_events);
1143  if (NIL_P(events)) {
1144  return Qnil;
1145  }
1146  ole_delete_event(events, event);
1147  return Qnil;
1148 }
1149 
1150 /*
1151  * call-seq:
1152  * WIN32OLE_EVENT#unadvise -> nil
1153  *
1154  * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
1155  * does not receive the OLE server event any more.
1156  * This method is trial implementation.
1157  *
1158  * ie = WIN32OLE.new('InternetExplorer.Application')
1159  * ev = WIN32OLE_EVENT.new(ie)
1160  * ev.on_event() {...}
1161  * ...
1162  * ev.unadvise
1163  *
1164  */
1165 static VALUE
1166 fev_unadvise(VALUE self)
1167 {
1168  struct oleeventdata *poleev;
1169  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
1170  if (poleev->pConnectionPoint) {
1171  ole_msg_loop();
1172  evs_delete(poleev->event_id);
1173  poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
1174  OLE_RELEASE(poleev->pConnectionPoint);
1175  poleev->pConnectionPoint = NULL;
1176  }
1177  OLE_FREE(poleev->pDispatch);
1178  return Qnil;
1179 }
1180 
1181 static VALUE
1182 evs_push(VALUE ev)
1183 {
1184  return rb_ary_push(ary_ole_event, ev);
1185 }
1186 
1187 static VALUE
1188 evs_delete(long i)
1189 {
1190  rb_ary_store(ary_ole_event, i, Qnil);
1191  return Qnil;
1192 }
1193 
1194 static VALUE
1195 evs_entry(long i)
1196 {
1197  return rb_ary_entry(ary_ole_event, i);
1198 }
1199 
1200 static long
1201 evs_length(void)
1202 {
1203  return RARRAY_LEN(ary_ole_event);
1204 }
1205 
1206 /*
1207  * call-seq:
1208  * WIN32OLE_EVENT#handler=
1209  *
1210  * sets event handler object. If handler object has onXXX
1211  * method according to XXX event, then onXXX method is called
1212  * when XXX event occurs.
1213  *
1214  * If handler object has method_missing and there is no
1215  * method according to the event, then method_missing
1216  * called and 1-st argument is event name.
1217  *
1218  * If handler object has onXXX method and there is block
1219  * defined by WIN32OLE_EVENT#on_event('XXX'){},
1220  * then block is executed but handler object method is not called
1221  * when XXX event occurs.
1222  *
1223  * class Handler
1224  * def onStatusTextChange(text)
1225  * puts "StatusTextChanged"
1226  * end
1227  * def onPropertyChange(prop)
1228  * puts "PropertyChanged"
1229  * end
1230  * def method_missing(ev, *arg)
1231  * puts "other event #{ev}"
1232  * end
1233  * end
1234  *
1235  * handler = Handler.new
1236  * ie = WIN32OLE.new('InternetExplorer.Application')
1237  * ev = WIN32OLE_EVENT.new(ie)
1238  * ev.on_event("StatusTextChange") {|*args|
1239  * puts "this block executed."
1240  * puts "handler.onStatusTextChange method is not called."
1241  * }
1242  * ev.handler = handler
1243  *
1244  */
1245 static VALUE
1246 fev_set_handler(VALUE self, VALUE val)
1247 {
1248  return rb_ivar_set(self, rb_intern("handler"), val);
1249 }
1250 
1251 /*
1252  * call-seq:
1253  * WIN32OLE_EVENT#handler
1254  *
1255  * returns handler object.
1256  *
1257  */
1258 static VALUE
1259 fev_get_handler(VALUE self)
1260 {
1261  return rb_ivar_get(self, rb_intern("handler"));
1262 }
1263 
1264 void
1266 {
1267  ary_ole_event = rb_ary_new();
1268  rb_gc_register_mark_object(ary_ole_event);
1269  id_events = rb_intern("events");
1270  cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
1271  rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
1272  rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
1273  rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
1274  rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
1275  rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
1276  rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
1277  rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
1278  rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
1279  rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
1280 }
VALUE rb_apply(VALUE, ID, VALUE)
Calls a method.
Definition: vm_eval.c:744
#define T_SYMBOL
Definition: ruby.h:508
IDispatch * pDispatch
PIEVENTSINKOBJ EVENTSINK_Constructor(void)
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:992
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define RARRAY_LEN(a)
Definition: ruby.h:1019
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define T_FIXNUM
Definition: ruby.h:503
void ruby_finalize(void)
Runs the VM finalization processes.
Definition: eval.c:144
LCID cWIN32OLE_lcid
Definition: win32ole.h:116
int count
Definition: encoding.c:56
struct oledata * oledata_get_struct(VALUE ole)
Definition: win32ole.c:856
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
VALUE rb_ary_delete_at(VALUE ary, long pos)
Definition: array.c:3059
#define Qtrue
Definition: ruby.h:437
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1183
VALUE cWIN32OLE
Definition: win32ole.c:37
static REFIID LPOLESTR __RPC_FAR UINT cNames
Definition: win32ole.c:87
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK pEV, UINT info, LCID lcid, ITypeInfo **pInfo)
LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:864
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
const IEventSinkVtbl * lpVtbl
#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)
void rb_backtrace(void)
Definition: vm_backtrace.c:770
#define T_HASH
Definition: ruby.h:499
#define T_ARRAY
Definition: ruby.h:498
double rb_big2dbl(VALUE x)
Definition: bignum.c:5270
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3159
IConnectionPoint * pConnectionPoint
EVENTSINK_AddRef(PEVENTSINK pEV)
VALUE cWIN32OLE_EVENT
STDMETHODIMP_(STDMETHODIMP_() EVENTSINK_Release(PEVENTSINK) ULONG)
#define NUM2DBL(x)
Definition: ruby.h:743
const char * rb_obj_classname(VALUE)
Definition: variable.c:459
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
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
static DISPID REFIID LCID WORD wFlags
Definition: win32ole.c:88
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
ITypeInfo * pTypeInfo
#define ALLOC_N(type, n)
Definition: ruby.h:1587
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
IUnknown DWORD
Definition: win32ole.c:32
#define T_NIL
Definition: ruby.h:490
VALUE rb_ary_new(void)
Definition: array.c:499
#define T_TRUE
Definition: ruby.h:504
#define NIL_P(v)
Definition: ruby.h:451
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:815
#define WC2VSTR(x)
Definition: win32ole.h:130
#define T_FLOAT
Definition: ruby.h:495
#define RB_UINT2NUM(x)
Definition: ruby.h:1536
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
#define Qfalse
Definition: ruby.h:436
#define ALLOCA_N(type, n)
Definition: ruby.h:1593
#define T_BIGNUM
Definition: ruby.h:501
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:6227
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
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
#define TRUE
Definition: nkf.h:175
#define RUBY_EXTERN
Definition: missing.h:77
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
char * ole_wc2mb(LPWSTR pw)
Definition: win32ole.c:742
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define Qnil
Definition: ruby.h:438
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
Definition: win32ole.c:88
unsigned long VALUE
Definition: ruby.h:85
#define OBJ_TAINTED(x)
Definition: ruby.h:1296
struct IEventSinkVtbl * lpVtbl
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ
VALUE rb_eSecurityError
Definition: error.c:810
VALUE rb_eTypeError
Definition: error.c:801
static REFIID riid
Definition: win32ole.c:82
#define rb_ary_new3
Definition: intern.h:91
struct tagIEVENTSINKOBJ IEVENTSINKOBJ
#define MSG(s)
void EVENTSINK_Destructor(PIEVENTSINKOBJ)
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1994
register unsigned int len
Definition: zonetab.h:51
void Init_win32ole_event(void)
#define OLE_RELEASE(X)
Definition: win32ole.h:98
int rb_safe_level(void)
Definition: safe.c:35
VALUE rb_block_proc(void)
Definition: proc.c:780
IDispatch * pDispatch
Definition: win32ole.h:112
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:831
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK pEV, UINT *pct)
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID *)
#define T_STRING
Definition: ruby.h:496
static UINT LCID lcid
Definition: win32ole.c:86
#define T_FALSE
Definition: ruby.h:505
VALUE rb_errinfo(void)
The current exception in the current thread.
Definition: eval.c:1777
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
#define OLE_RELEASE_TYPEATTR(X, Y)
Definition: win32ole.h:109
#define RB_NUM2INT(x)
Definition: ruby.h:679
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK pEventSink, REFIID riid, OLECHAR **szNames, UINT cNames, LCID lcid, DISPID *pDispID)
#define StringValuePtr(v)
Definition: ruby.h:570
#define RB_NUM2CHR(x)
Definition: ruby.h:1569
VALUE rb_str_intern(VALUE)
Definition: symbol.c:661
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
struct IEventSink * PEVENTSINK
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
free(psz)
ID rb_to_id(VALUE)
Definition: string.c:10496
#define OLE_FREE(x)
Definition: win32ole.h:99
char ** argv
Definition: ruby.c:188
RUBY_EXTERN void rb_write_error_str(VALUE mesg)
Definition: io.c:7580
#define rb_sym2str(sym)
Definition: console.c:107
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1248