Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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
11typedef struct {
14
16
18 STDMETHOD(QueryInterface)(
20 REFIID,
21 LPVOID *);
22 STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
23 STDMETHOD_(ULONG, Release)(PEVENTSINK);
24
25 STDMETHOD(GetTypeInfoCount)(
27 UINT *);
28 STDMETHOD(GetTypeInfo)(
30 UINT,
31 LCID,
32 ITypeInfo **);
33 STDMETHOD(GetIDsOfNames)(
35 REFIID,
36 OLECHAR **,
37 UINT,
38 LCID,
39 DISPID *);
40 STDMETHOD(Invoke)(
42 DISPID,
43 REFIID,
44 LCID,
45 WORD,
46 DISPPARAMS *,
47 VARIANT *,
48 EXCEPINFO *,
49 UINT *);
50};
51
52typedef struct tagIEVENTSINKOBJ {
55 IID m_iid;
57 ITypeInfo *pTypeInfo;
59
62 IConnectionPoint *pConnectionPoint;
63 IDispatch *pDispatch;
65};
66
67static VALUE ary_ole_event;
68static ID id_events;
69
71
72STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID*);
74STDMETHODIMP_(ULONG) EVENTSINK_Release(PEVENTSINK);
75STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK, UINT*);
76STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK, UINT, LCID, ITypeInfo**);
77STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK, REFIID, OLECHAR**, UINT, LCID, DISPID*);
78STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK, DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
79
80static const IEventSinkVtbl vtEventSink = {
83 EVENTSINK_Release,
88};
89
91static void ole_val2ptr_variant(VALUE val, VARIANT *var);
92static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
93static VALUE hash2result(VALUE hash);
94static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
95static VALUE exec_callback(VALUE arg);
96static VALUE rescue_callback(VALUE arg);
97static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
98static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
99static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
100static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
101static long ole_search_event_at(VALUE ary, VALUE ev);
102static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
103static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
104static void ole_delete_event(VALUE ary, VALUE ev);
105static void oleevent_free(void *ptr);
106static size_t oleevent_size(const void *ptr);
107static VALUE fev_s_allocate(VALUE klass);
108static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
109static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
110static void ole_msg_loop(void);
111static VALUE fev_s_msg_loop(VALUE klass);
112static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
113static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
114static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
115static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
116static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
117static VALUE fev_unadvise(VALUE self);
118static VALUE fev_set_handler(VALUE self, VALUE val);
119static VALUE fev_get_handler(VALUE self);
120static VALUE evs_push(VALUE ev);
121static VALUE evs_delete(long i);
122static VALUE evs_entry(long i);
123static long evs_length(void);
124
125
126static const rb_data_type_t oleevent_datatype = {
127 "win32ole_event",
128 {NULL, oleevent_free, oleevent_size,},
130};
131
132STDMETHODIMP 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
236STDMETHODIMP
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
255STDMETHODIMP_(ULONG)
257 PEVENTSINK pEV
258 ){
259 PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
260 return ++pEVObj->m_cRef;
261}
262
263STDMETHODIMP_(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
322void
324 PIEVENTSINKOBJ pEVObj
325 ) {
326 if(pEVObj != NULL) {
327 OLE_RELEASE(pEVObj->pTypeInfo);
328 free(pEVObj);
329 pEVObj = NULL;
330 }
331}
332
333static void
334ole_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
401static void
402hash2ptr_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
430static VALUE
431hash2result(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
440static void
441ary2ptr_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
453static VALUE
454exec_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
463static VALUE
464rescue_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();
476 exit(-1);
477
478 return Qnil;
479}
480
481static HRESULT
482find_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
592static HRESULT
593find_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
667static HRESULT
668find_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
703static HRESULT
704find_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
788static long
789ole_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
813static VALUE
814ole_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
838static VALUE
839ole_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
856static void
857ole_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
867static void
868oleevent_free(void *ptr)
869{
870 struct oleeventdata *poleev = ptr;
871 if (poleev->pConnectionPoint) {
872 poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
874 poleev->pConnectionPoint = NULL;
875 }
876 OLE_RELEASE(poleev->pDispatch);
877 free(poleev);
878}
879
880static size_t
881oleevent_size(const void *ptr)
882{
883 return ptr ? sizeof(struct oleeventdata) : 0;
884}
885
886static VALUE
887fev_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
899static VALUE
900ev_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 */
985static VALUE
986fev_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
995static void
996ole_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 */
1011static VALUE
1012fev_s_msg_loop(VALUE klass)
1013{
1014 ole_msg_loop();
1015 return Qnil;
1016}
1017
1018static void
1019add_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
1030static VALUE
1031ev_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 */
1082static VALUE
1083fev_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 */
1102static VALUE
1103fev_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 */
1123static VALUE
1124fev_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 */
1161static VALUE
1162fev_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);
1171 poleev->pConnectionPoint = NULL;
1172 }
1173 OLE_FREE(poleev->pDispatch);
1174 return Qnil;
1175}
1176
1177static VALUE
1178evs_push(VALUE ev)
1179{
1180 return rb_ary_push(ary_ole_event, ev);
1181}
1182
1183static VALUE
1184evs_delete(long i)
1185{
1186 rb_ary_store(ary_ole_event, i, Qnil);
1187 return Qnil;
1188}
1189
1190static VALUE
1191evs_entry(long i)
1192{
1193 return rb_ary_entry(ary_ole_event, i);
1194}
1195
1196static long
1197evs_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 */
1241static VALUE
1242fev_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 */
1254static VALUE
1255fev_get_handler(VALUE self)
1256{
1257 return rb_ivar_get(self, rb_intern("handler"));
1258}
1259
1260void
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}
struct RIMemo * ptr
Definition: debug.c:65
#define free(x)
Definition: dln.c:52
int count
Definition: encoding.c:57
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
VALUE rb_eRuntimeError
Definition: error.c:922
VALUE rb_errinfo(void)
The current exception in the current thread.
Definition: eval.c:1882
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
#define MSG(s)
#define RARRAY_LEN(a)
#define RB_UINT2NUM(v)
#define rb_str_new2
#define NULL
#define NUM2DBL(x)
#define ALLOCA_N(type, n)
int strcmp(const char *, const char *)
#define T_STRING
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:2037
#define StringValuePtr(v)
double rb_big2dbl(VALUE)
Definition: bignum.c:5310
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
const VALUE VALUE obj
#define TYPE(x)
#define T_NIL
#define T_FLOAT
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:7079
const rb_iseq_t const char * error
#define T_BIGNUM
#define NIL_P(v)
#define T_FIXNUM
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2207
unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
void ruby_finalize(void)
Runs the VM finalization processes.
Definition: eval.c:163
VALUE rb_sym2str(VALUE)
Definition: symbol.c:784
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
__inline__ const void *__restrict__ size_t len
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
#define ALLOC_N(type, n)
VALUE rb_block_proc(void)
Definition: proc.c:837
#define T_TRUE
#define T_HASH
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RUBY_TYPED_FREE_IMMEDIATELY
#define TypedData_Get_Struct(obj, type, data_type, sval)
#define PRIsVALUE
#define rb_ary_new3
#define rb_funcall(recv, mid, argc,...)
int VALUE v
VALUE rb_ary_new(void)
Definition: array.c:723
#define rb_scan_args(argc, argvp, fmt,...)
#define short
#define T_FALSE
#define rb_intern(str)
#define TRUE
VALUE rb_apply(VALUE, ID, VALUE)
Calls a method.
Definition: vm_eval.c:890
#define FALSE
int rb_str_cmp(VALUE, VALUE)
Definition: string.c:3228
#define Qtrue
void exit(int __status) __attribute__((__noreturn__))
#define Qnil
#define Qfalse
#define T_ARRAY
VALUE rb_str_intern(VALUE)
Definition: symbol.c:710
#define RB_TYPE_P(obj, type)
#define T_SYMBOL
#define TypedData_Make_Struct(klass, type, data_type, sval)
const VALUE * argv
__inline__ int
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
VALUE rb_ary_delete_at(VALUE, long)
Definition: array.c:3419
#define RUBY_EXTERN
#define RB_NUM2CHR(x)
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
unsigned long ID
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
void rb_backtrace(void)
Definition: vm_backtrace.c:829
void rb_ary_store(VALUE, long, VALUE)
Definition: array.c:1079
#define RB_NUM2INT(x)
VALUE rb_ary_entry(VALUE, long)
Definition: array.c:1512
ID rb_to_id(VALUE)
Definition: string.c:11146
struct IEventSinkVtbl * lpVtbl
STDMETHOD() QueryInterface(PEVENTSINK, REFIID, LPVOID *)
IDispatch * pDispatch
Definition: win32ole.h:112
IConnectionPoint * pConnectionPoint
IDispatch * pDispatch
ITypeInfo * pTypeInfo
const IEventSinkVtbl * lpVtbl
LPWSTR ole_vstr2wc(VALUE vstr)
Definition: win32ole.c:865
static REFIID riid
Definition: win32ole.c:83
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
static DISPID REFIID LCID WORD wFlags
Definition: win32ole.c:89
VALUE ole_variant2val(VARIANT *pvar)
Definition: win32ole.c:1418
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
Definition: win32ole.c:89
static REFIID LPOLESTR __RPC_FAR UINT cNames
Definition: win32ole.c:88
IUnknown DWORD
Definition: win32ole.c:33
char * ole_wc2mb(LPWSTR pw)
Definition: win32ole.c:743
VALUE cWIN32OLE
Definition: win32ole.c:38
void ole_val2variant(VALUE val, VARIANT *var)
Definition: win32ole.c:1249
LCID cWIN32OLE_lcid
Definition: win32ole.c:3965
struct oledata * oledata_get_struct(VALUE ole)
Definition: win32ole.c:857
static UINT LCID lcid
Definition: win32ole.c:87
#define OLE_RELEASE(X)
Definition: win32ole.h:98
#define OLE_FREE(x)
Definition: win32ole.h:99
#define OLE_ADDREF(X)
Definition: win32ole.h:97
#define OLE_RELEASE_TYPEATTR(X, Y)
Definition: win32ole.h:109
#define WC2VSTR(x)
Definition: win32ole.h:130
#define OLE_GET_TYPEATTR(X, Y)
Definition: win32ole.h:108
VALUE eWIN32OLERuntimeError
VALUE eWIN32OLEQueryInterfaceError
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
STDMETHODIMP_(ULONG)
EVENTSINK_AddRef(PEVENTSINK pEV)
PIEVENTSINKOBJ EVENTSINK_Constructor(void)
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
struct IEventSink * PEVENTSINK
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK pEV, UINT info, LCID lcid, ITypeInfo **pInfo)
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID *)
void EVENTSINK_Destructor(PIEVENTSINKOBJ)
RUBY_EXTERN void rb_write_error_str(VALUE mesg)
Definition: io.c:7940
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK pEV, UINT *pct)
struct tagIEVENTSINKOBJ IEVENTSINKOBJ
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK pEventSink, REFIID riid, OLECHAR **szNames, UINT cNames, LCID lcid, DISPID *pDispID)
void Init_win32ole_event(void)
VALUE cWIN32OLE_EVENT
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ