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
9 RUBY_EXTERN void rb_write_error_str(VALUE mesg);
10
11 typedef struct {
12 struct IEventSinkVtbl * lpVtbl;
13 } IEventSink, *PEVENTSINK;
14
15 typedef struct IEventSinkVtbl IEventSinkVtbl;
16
17 struct IEventSinkVtbl {
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 {
53 const IEventSinkVtbl *lpVtbl;
54 DWORD m_cRef;
55 IID m_iid;
56 long m_event_id;
57 ITypeInfo *pTypeInfo;
58 }IEVENTSINKOBJ, *PIEVENTSINKOBJ;
59
60 struct oleeventdata {
61 DWORD dwCookie;
62 IConnectionPoint *pConnectionPoint;
63 IDispatch *pDispatch;
64 long event_id;
65 };
66
67 static VALUE ary_ole_event;
68 static ID id_events;
69
70 VALUE cWIN32OLE_EVENT;
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 = {
81 EVENTSINK_QueryInterface,
82 EVENTSINK_AddRef,
83 EVENTSINK_Release,
84 EVENTSINK_GetTypeInfoCount,
85 EVENTSINK_GetTypeInfo,
86 EVENTSINK_GetIDsOfNames,
87 EVENTSINK_Invoke,
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,},
129 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
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
237 EVENTSINK_QueryInterface(
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)
256 EVENTSINK_AddRef(
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
274 STDMETHODIMP EVENTSINK_GetTypeInfoCount(
275 PEVENTSINK pEV,
276 UINT *pct
277 ) {
278 *pct = 0;
279 return NOERROR;
280 }
281
282 STDMETHODIMP EVENTSINK_GetTypeInfo(
283 PEVENTSINK pEV,
284 UINT info,
285 LCID lcid,
286 ITypeInfo **pInfo
287 ) {
288 *pInfo = NULL;
289 return DISP_E_BADINDEX;
290 }
291
292 STDMETHODIMP EVENTSINK_GetIDsOfNames(
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
310 EVENTSINK_Constructor(void)
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
323 EVENTSINK_Destructor(
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 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);
941 ole_raise(hr, eWIN32OLEQueryInterfaceError,
942 "failed to query IConnectionPointContainer");
943 }
944 pContainer = p;
945
946 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
947 &iid,
948 &pConnectionPoint);
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;
967 poleev->pConnectionPoint = pConnectionPoint;
968 poleev->event_id = pIEV->m_event_id;
969 poleev->pDispatch = pDispatch;
970 OLE_ADDREF(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
1261 Init_win32ole_event(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