Ruby  2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)
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*);
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 
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);
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 
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));
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  hr = find_iid(ole, pitf, &iid, &pTypeInfo);
926  }
927  else {
928  hr = find_default_source(ole, &iid, &pTypeInfo);
929  }
930  if (FAILED(hr)) {
931  ole_raise(hr, rb_eRuntimeError, "interface not found");
932  }
933 
934  pole = oledata_get_struct(ole);
935  pDispatch = pole->pDispatch;
936  hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
937  &IID_IConnectionPointContainer,
938  &p);
939  if (FAILED(hr)) {
940  OLE_RELEASE(pTypeInfo);
942  "failed to query IConnectionPointContainer");
943  }
944  pContainer = p;
945 
946  hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
947  &iid,
949  OLE_RELEASE(pContainer);
950  if (FAILED(hr)) {
951  OLE_RELEASE(pTypeInfo);
952  ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to query IConnectionPoint");
953  }
954  pIEV = EVENTSINK_Constructor();
955  pIEV->m_iid = iid;
956  hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
957  (IUnknown*)pIEV,
958  &dwCookie);
959  if (FAILED(hr)) {
960  ole_raise(hr, eWIN32OLEQueryInterfaceError, "Advise Error");
961  }
962 
963  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
964  pIEV->m_event_id = evs_length();
965  pIEV->pTypeInfo = pTypeInfo;
966  poleev->dwCookie = dwCookie;
968  poleev->event_id = pIEV->m_event_id;
969  poleev->pDispatch = pDispatch;
971 
972  return self;
973 }
974 
975 /*
976  * call-seq:
977  * WIN32OLE_EVENT.new(ole, event) #=> WIN32OLE_EVENT object.
978  *
979  * Returns OLE event object.
980  * The first argument specifies WIN32OLE object.
981  * The second argument specifies OLE event name.
982  * ie = WIN32OLE.new('InternetExplorer.Application')
983  * ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
984  */
985 static VALUE
986 fev_initialize(int argc, VALUE *argv, VALUE self)
987 {
988  ev_advise(argc, argv, self);
989  evs_push(self);
990  rb_ivar_set(self, id_events, rb_ary_new());
991  fev_set_handler(self, Qnil);
992  return self;
993 }
994 
995 static void
996 ole_msg_loop(void)
997 {
998  MSG msg;
999  while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
1000  TranslateMessage(&msg);
1001  DispatchMessage(&msg);
1002  }
1003 }
1004 
1005 /*
1006  * call-seq:
1007  * WIN32OLE_EVENT.message_loop
1008  *
1009  * Translates and dispatches Windows message.
1010  */
1011 static VALUE
1012 fev_s_msg_loop(VALUE klass)
1013 {
1014  ole_msg_loop();
1015  return Qnil;
1016 }
1017 
1018 static void
1019 add_event_call_back(VALUE obj, VALUE event, VALUE data)
1020 {
1021  VALUE events = rb_ivar_get(obj, id_events);
1022  if (NIL_P(events) || !RB_TYPE_P(events, T_ARRAY)) {
1023  events = rb_ary_new();
1024  rb_ivar_set(obj, id_events, events);
1025  }
1026  ole_delete_event(events, event);
1027  rb_ary_push(events, data);
1028 }
1029 
1030 static VALUE
1031 ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
1032 {
1033  struct oleeventdata *poleev;
1034  VALUE event, args, data;
1035  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
1036  if (poleev->pConnectionPoint == NULL) {
1037  rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
1038  }
1039  rb_scan_args(argc, argv, "01*", &event, &args);
1040  if(!NIL_P(event)) {
1041  if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
1042  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
1043  }
1044  if (RB_TYPE_P(event, T_SYMBOL)) {
1045  event = rb_sym2str(event);
1046  }
1047  }
1048  data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
1049  add_event_call_back(self, event, data);
1050  return Qnil;
1051 }
1052 
1053 /*
1054  * call-seq:
1055  * WIN32OLE_EVENT#on_event([event]){...}
1056  *
1057  * Defines the callback event.
1058  * If argument is omitted, this method defines the callback of all events.
1059  * If you want to modify reference argument in callback, return hash in
1060  * callback. If you want to return value to OLE server as result of callback
1061  * use `return' or :return.
1062  *
1063  * ie = WIN32OLE.new('InternetExplorer.Application')
1064  * ev = WIN32OLE_EVENT.new(ie)
1065  * ev.on_event("NavigateComplete") {|url| puts url}
1066  * ev.on_event() {|ev, *args| puts "#{ev} fired"}
1067  *
1068  * ev.on_event("BeforeNavigate2") {|*args|
1069  * ...
1070  * # set true to BeforeNavigate reference argument `Cancel'.
1071  * # Cancel is 7-th argument of BeforeNavigate,
1072  * # so you can use 6 as key of hash instead of 'Cancel'.
1073  * # The argument is counted from 0.
1074  * # The hash key of 0 means first argument.)
1075  * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
1076  * }
1077  *
1078  * ev.on_event(...) {|*args|
1079  * {:return => 1, :xxx => yyy}
1080  * }
1081  */
1082 static VALUE
1083 fev_on_event(int argc, VALUE *argv, VALUE self)
1084 {
1085  return ev_on_event(argc, argv, self, Qfalse);
1086 }
1087 
1088 /*
1089  * call-seq:
1090  * WIN32OLE_EVENT#on_event_with_outargs([event]){...}
1091  *
1092  * Defines the callback of event.
1093  * If you want modify argument in callback,
1094  * you could use this method instead of WIN32OLE_EVENT#on_event.
1095  *
1096  * ie = WIN32OLE.new('InternetExplorer.Application')
1097  * ev = WIN32OLE_EVENT.new(ie)
1098  * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
1099  * args.last[6] = true
1100  * }
1101  */
1102 static VALUE
1103 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
1104 {
1105  return ev_on_event(argc, argv, self, Qtrue);
1106 }
1107 
1108 /*
1109  * call-seq:
1110  * WIN32OLE_EVENT#off_event([event])
1111  *
1112  * removes the callback of event.
1113  *
1114  * ie = WIN32OLE.new('InternetExplorer.Application')
1115  * ev = WIN32OLE_EVENT.new(ie)
1116  * ev.on_event('BeforeNavigate2') {|*args|
1117  * args.last[6] = true
1118  * }
1119  * ...
1120  * ev.off_event('BeforeNavigate2')
1121  * ...
1122  */
1123 static VALUE
1124 fev_off_event(int argc, VALUE *argv, VALUE self)
1125 {
1126  VALUE event = Qnil;
1127  VALUE events;
1128 
1129  rb_scan_args(argc, argv, "01", &event);
1130  if(!NIL_P(event)) {
1131  if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
1132  rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
1133  }
1134  if (RB_TYPE_P(event, T_SYMBOL)) {
1135  event = rb_sym2str(event);
1136  }
1137  }
1138  events = rb_ivar_get(self, id_events);
1139  if (NIL_P(events)) {
1140  return Qnil;
1141  }
1142  ole_delete_event(events, event);
1143  return Qnil;
1144 }
1145 
1146 /*
1147  * call-seq:
1148  * WIN32OLE_EVENT#unadvise -> nil
1149  *
1150  * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object
1151  * does not receive the OLE server event any more.
1152  * This method is trial implementation.
1153  *
1154  * ie = WIN32OLE.new('InternetExplorer.Application')
1155  * ev = WIN32OLE_EVENT.new(ie)
1156  * ev.on_event() {...}
1157  * ...
1158  * ev.unadvise
1159  *
1160  */
1161 static VALUE
1162 fev_unadvise(VALUE self)
1163 {
1164  struct oleeventdata *poleev;
1165  TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
1166  if (poleev->pConnectionPoint) {
1167  ole_msg_loop();
1168  evs_delete(poleev->event_id);
1169  poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
1170  OLE_RELEASE(poleev->pConnectionPoint);
1171  poleev->pConnectionPoint = NULL;
1172  }
1173  OLE_FREE(poleev->pDispatch);
1174  return Qnil;
1175 }
1176 
1177 static VALUE
1178 evs_push(VALUE ev)
1179 {
1180  return rb_ary_push(ary_ole_event, ev);
1181 }
1182 
1183 static VALUE
1184 evs_delete(long i)
1185 {
1186  rb_ary_store(ary_ole_event, i, Qnil);
1187  return Qnil;
1188 }
1189 
1190 static VALUE
1191 evs_entry(long i)
1192 {
1193  return rb_ary_entry(ary_ole_event, i);
1194 }
1195 
1196 static long
1197 evs_length(void)
1198 {
1199  return RARRAY_LEN(ary_ole_event);
1200 }
1201 
1202 /*
1203  * call-seq:
1204  * WIN32OLE_EVENT#handler=
1205  *
1206  * sets event handler object. If handler object has onXXX
1207  * method according to XXX event, then onXXX method is called
1208  * when XXX event occurs.
1209  *
1210  * If handler object has method_missing and there is no
1211  * method according to the event, then method_missing
1212  * called and 1-st argument is event name.
1213  *
1214  * If handler object has onXXX method and there is block
1215  * defined by WIN32OLE_EVENT#on_event('XXX'){},
1216  * then block is executed but handler object method is not called
1217  * when XXX event occurs.
1218  *
1219  * class Handler
1220  * def onStatusTextChange(text)
1221  * puts "StatusTextChanged"
1222  * end
1223  * def onPropertyChange(prop)
1224  * puts "PropertyChanged"
1225  * end
1226  * def method_missing(ev, *arg)
1227  * puts "other event #{ev}"
1228  * end
1229  * end
1230  *
1231  * handler = Handler.new
1232  * ie = WIN32OLE.new('InternetExplorer.Application')
1233  * ev = WIN32OLE_EVENT.new(ie)
1234  * ev.on_event("StatusTextChange") {|*args|
1235  * puts "this block executed."
1236  * puts "handler.onStatusTextChange method is not called."
1237  * }
1238  * ev.handler = handler
1239  *
1240  */
1241 static VALUE
1242 fev_set_handler(VALUE self, VALUE val)
1243 {
1244  return rb_ivar_set(self, rb_intern("handler"), val);
1245 }
1246 
1247 /*
1248  * call-seq:
1249  * WIN32OLE_EVENT#handler
1250  *
1251  * returns handler object.
1252  *
1253  */
1254 static VALUE
1255 fev_get_handler(VALUE self)
1256 {
1257  return rb_ivar_get(self, rb_intern("handler"));
1258 }
1259 
1260 void
1262 {
1263 #undef rb_intern
1264  ary_ole_event = rb_ary_new();
1265  rb_gc_register_mark_object(ary_ole_event);
1266  id_events = rb_intern("events");
1267  cWIN32OLE_EVENT = rb_define_class("WIN32OLE_EVENT", rb_cObject);
1268  rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
1269  rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
1270  rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
1271  rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
1272  rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
1273  rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
1274  rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
1275  rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
1276  rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
1277 }
EVENTSINK_Destructor
void EVENTSINK_Destructor(PIEVENTSINKOBJ)
Definition: win32ole_event.c:323
ole_val2variant
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1249
ID
unsigned long ID
Definition: ruby.h:103
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
EVENTSINK_Invoke
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
Definition: win32ole_event.c:132
T_FALSE
#define T_FALSE
Definition: ruby.h:537
IEventSinkVtbl::QueryInterface
STDMETHOD() QueryInterface(PEVENTSINK, REFIID, LPVOID *)
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
TRUE
#define TRUE
Definition: nkf.h:175
T_FLOAT
#define T_FLOAT
Definition: ruby.h:527
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
win32ole.h
EVENTSINK_QueryInterface
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID *)
Definition: win32ole_event.c:237
ole_variant2val
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1418
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7063
eWIN32OLEQueryInterfaceError
VALUE eWIN32OLEQueryInterfaceError
Definition: win32ole_error.h:5
oleeventdata::event_id
long event_id
Definition: win32ole_event.c:64
EVENTSINK_GetTypeInfoCount
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK pEV, UINT *pct)
Definition: win32ole_event.c:274
short
#define short
Definition: rb_mjit_min_header-2.7.0.h:2877
tagIEVENTSINKOBJ::m_cRef
DWORD m_cRef
Definition: win32ole_event.c:54
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.0.h:6372
tagIEVENTSINKOBJ::m_iid
IID m_iid
Definition: win32ole_event.c:55
OLE_RELEASE_TYPEATTR
#define OLE_RELEASE_TYPEATTR(X, Y)
Definition: win32ole.h:109
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:1964
PIEVENTSINKOBJ
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ
EVENTSINK_AddRef
EVENTSINK_AddRef(PEVENTSINK pEV)
Definition: win32ole_event.c:256
VALUE
unsigned long VALUE
Definition: ruby.h:102
index
int index
Definition: rb_mjit_min_header-2.7.0.h:11246
rb_intern
#define rb_intern(str)
rb_ary_store
void rb_ary_store(VALUE ary, long idx, VALUE val)
Definition: array.c:1079
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
TYPE
#define TYPE(x)
Definition: ruby.h:554
tagIEVENTSINKOBJ::m_event_id
long m_event_id
Definition: win32ole_event.c:56
int
__inline__ int
Definition: rb_mjit_min_header-2.7.0.h:2839
Init_win32ole_event
void Init_win32ole_event(void)
Definition: win32ole_event.c:1261
DWORD
IUnknown DWORD
Definition: win32ole.c:33
puArgErr
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
Definition: win32ole.c:89
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
WC2VSTR
#define WC2VSTR(x)
Definition: win32ole.h:130
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ptr
struct RIMemo * ptr
Definition: debug.c:74
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_ary_new3
#define rb_ary_new3
Definition: intern.h:104
OLE_RELEASE
#define OLE_RELEASE(X)
Definition: win32ole.h:98
ruby_finalize
void ruby_finalize(void)
Runs the VM finalization processes.
Definition: eval.c:162
NULL
#define NULL
Definition: _sdbm.c:101
exit
void exit(int __status) __attribute__((__noreturn__))
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
error
const rb_iseq_t const char * error
Definition: rb_mjit_min_header-2.7.0.h:13506
T_SYMBOL
#define T_SYMBOL
Definition: ruby.h:540
EVENTSINK_Constructor
PIEVENTSINKOBJ EVENTSINK_Constructor(void)
Definition: win32ole_event.c:310
eWIN32OLERuntimeError
VALUE eWIN32OLERuntimeError
Definition: win32ole_error.h:4
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1071
v
int VALUE v
Definition: rb_mjit_min_header-2.7.0.h:12332
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_ivar_get
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
riid
static REFIID riid
Definition: win32ole.c:83
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.0.h:5742
lcid
static UINT LCID lcid
Definition: win32ole.c:87
rb_backtrace
void rb_backtrace(void)
Definition: vm_backtrace.c:829
oledata
Definition: win32ole.h:111
tagIEVENTSINKOBJ::pTypeInfo
ITypeInfo * pTypeInfo
Definition: win32ole_event.c:57
rb_str_intern
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
RB_UINT2NUM
#define RB_UINT2NUM(x)
Definition: ruby.h:1607
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
i
uint32_t i
Definition: rb_mjit_min_header-2.7.0.h:5464
rb_to_id
ID rb_to_id(VALUE)
Definition: string.c:11146
rb_errinfo
VALUE rb_errinfo(void)
The current exception in the current thread.
Definition: eval.c:1881
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
oleeventdata
Definition: win32ole_event.c:60
wFlags
static DISPID REFIID LCID WORD wFlags
Definition: win32ole.c:89
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
oledata::pDispatch
IDispatch * pDispatch
Definition: win32ole.h:112
ALLOCA_N
#define ALLOCA_N(type, n)
Definition: ruby.h:1684
StringValuePtr
#define StringValuePtr(v)
Definition: ruby.h:603
FALSE
#define FALSE
Definition: nkf.h:174
cNames
static REFIID LPOLESTR __RPC_FAR UINT cNames
Definition: win32ole.c:88
IEventSink
Definition: win32ole_event.c:11
oleeventdata::pDispatch
IDispatch * pDispatch
Definition: win32ole_event.c:63
cWIN32OLE_EVENT
VALUE cWIN32OLE_EVENT
Definition: win32ole_event.c:70
cWIN32OLE
VALUE cWIN32OLE
Definition: win32ole.c:38
RB_NUM2INT
#define RB_NUM2INT(x)
Definition: ruby.h:710
key
key
Definition: openssl_missing.h:181
T_HASH
#define T_HASH
Definition: ruby.h:531
strcmp
int strcmp(const char *, const char *)
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
EVENTSINK_GetTypeInfo
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK pEV, UINT info, LCID lcid, ITypeInfo **pInfo)
Definition: win32ole_event.c:282
OLE_FREE
#define OLE_FREE(x)
Definition: win32ole.h:99
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
oleeventdata::dwCookie
DWORD dwCookie
Definition: win32ole_event.c:61
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
TypedData_Get_Struct
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1252
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.0.h:6585
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.0.h:5601
argv
char ** argv
Definition: ruby.c:223
IEventSinkVtbl
Definition: win32ole_event.c:17
rb_write_error_str
RUBY_EXTERN void rb_write_error_str(VALUE mesg)
Definition: io.c:7936
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.0.h:13254
IEventSink::lpVtbl
struct IEventSinkVtbl * lpVtbl
Definition: win32ole_event.c:12
T_NIL
#define T_NIL
Definition: ruby.h:522
RB_NUM2CHR
#define RB_NUM2CHR(x)
Definition: ruby.h:1640
rb_ary_delete_at
VALUE rb_ary_delete_at(VALUE ary, long pos)
Definition: array.c:3419
HRESULT
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
OLE_ADDREF
#define OLE_ADDREF(X)
Definition: win32ole.h:97
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argc
int argc
Definition: ruby.c:222
rb_obj_classname
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
free
#define free(x)
Definition: dln.c:52
RUBY_EXTERN
#define RUBY_EXTERN
Definition: missing.h:77
rb_data_type_struct
Definition: ruby.h:1148
ole_vstr2wc
LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:865
PEVENTSINK
struct IEventSink * PEVENTSINK
count
int count
Definition: encoding.c:57
Qtrue
#define Qtrue
Definition: ruby.h:468
tagIEVENTSINKOBJ::lpVtbl
const IEventSinkVtbl * lpVtbl
Definition: win32ole_event.c:53
rb_apply
VALUE rb_apply(VALUE, ID, VALUE)
Calls a method.
Definition: vm_eval.c:890
len
uint8_t len
Definition: escape.c:17
oleeventdata::pConnectionPoint
IConnectionPoint * pConnectionPoint
Definition: win32ole_event.c:62
oledata_get_struct
struct oledata * oledata_get_struct(VALUE ole)
Definition: win32ole.c:857
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
cWIN32OLE_lcid
LCID cWIN32OLE_lcid
Definition: win32ole.h:116
rb_sym2str
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
ole_raise
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
Definition: win32ole_error.c:46
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
rb_big2dbl
double rb_big2dbl(VALUE x)
Definition: bignum.c:5310
Qnil
#define Qnil
Definition: ruby.h:469
NUM2DBL
#define NUM2DBL(x)
Definition: ruby.h:774
MSG
#define MSG(s)
OLE_GET_TYPEATTR
#define OLE_GET_TYPEATTR(X, Y)
Definition: win32ole.h:108
T_TRUE
#define T_TRUE
Definition: ruby.h:536
rb_obj_is_kind_of
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
STDMETHODIMP_
STDMETHODIMP_(STDMETHODIMP_() EVENTSINK_Release(PEVENTSINK) ULONG)
Definition: win32ole_event.c:73
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
ole_wc2mb
char * ole_wc2mb(LPWSTR pw)
Definition: win32ole.c:743
IEVENTSINKOBJ
struct tagIEVENTSINKOBJ IEVENTSINKOBJ
EVENTSINK_GetIDsOfNames
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK pEventSink, REFIID riid, OLECHAR **szNames, UINT cNames, LCID lcid, DISPID *pDispID)
Definition: win32ole_event.c:292
tagIEVENTSINKOBJ
Definition: win32ole_event.c:52
rb_str_cmp
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3228
rb_block_proc
VALUE rb_block_proc(void)
Definition: proc.c:837