18 STDMETHOD(QueryInterface)(
25 STDMETHOD(GetTypeInfoCount)(
28 STDMETHOD(GetTypeInfo)(
33 STDMETHOD(GetIDsOfNames)(
67 static VALUE ary_ole_event;
78 STDMETHODIMP
EVENTSINK_Invoke(PEVENTSINK, DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
91 static void ole_val2ptr_variant(
VALUE val, VARIANT *var);
92 static void hash2ptr_dispparams(
VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
94 static void ary2ptr_dispparams(
VALUE ary, DISPPARAMS *pdispparams);
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);
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);
110 static void ole_msg_loop(
void);
121 static VALUE evs_delete(
long i);
122 static VALUE evs_entry(
long i);
123 static long evs_length(
void);
128 {
NULL, oleevent_free, oleevent_size,},
133 PEVENTSINK pEventSink,
138 DISPPARAMS *pdispparams,
140 EXCEPINFO *pexcepinfo,
148 ITypeInfo *pTypeInfo;
150 VALUE ary, obj, event, args, outargv, ev, result;
155 BOOL is_default_handler =
FALSE;
169 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
175 event = ole_search_event(ary, ev, &is_default_handler);
182 if (handler ==
Qnil) {
185 mid = ole_search_handler_method(handler, ev, &is_default_handler);
187 if (handler ==
Qnil || mid ==
Qnil) {
192 if (is_default_handler) {
197 for (i = 0; i < pdispparams->cArgs; ++i) {
198 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
202 if (is_outarg ==
Qtrue) {
219 rescue_callback(
Qnil);
222 hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
223 result = hash2result(result);
225 ary2ptr_dispparams(outargv, pdispparams);
229 VariantInit(pvarResult);
242 if (IsEqualIID(iid, &IID_IUnknown) ||
243 IsEqualIID(iid, &IID_IDispatch) ||
244 IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
249 return E_NOINTERFACE;
251 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
289 return DISP_E_BADINDEX;
293 PEVENTSINK pEventSink,
300 ITypeInfo *pTypeInfo;
304 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
306 return DISP_E_UNKNOWNNAME;
315 pEv->
lpVtbl = &vtEventSink;
324 PIEVENTSINKOBJ pEVObj
334 ole_val2ptr_variant(
VALUE val, VARIANT *var)
338 if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
344 case (VT_UI1 | VT_BYREF) :
347 case (VT_I2 | VT_BYREF) :
350 case (VT_I4 | VT_BYREF) :
353 case (VT_R4 | VT_BYREF) :
356 case (VT_R8 | VT_BYREF) :
365 case (VT_I2 | VT_BYREF) :
368 case (VT_I4 | VT_BYREF) :
371 case (VT_R4 | VT_BYREF) :
374 case (VT_R8 | VT_BYREF) :
382 if (V_VT(var) == (VT_R8 | VT_BYREF)) {
387 if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
388 *V_BOOLREF(var) = VARIANT_TRUE;
392 if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
393 *V_BOOLREF(var) = VARIANT_FALSE;
402 hash2ptr_dispparams(
VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
411 bstrs =
ALLOCA_N(BSTR, pdispparams->cArgs + 1);
412 hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
413 bstrs, pdispparams->cArgs + 1,
418 for (i = 0; i < len - 1; i++) {
425 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
426 ole_val2ptr_variant(val, pvar);
431 hash2result(
VALUE hash)
441 ary2ptr_dispparams(
VALUE ary, DISPPARAMS *pdispparams)
446 for(i = 0; i <
RARRAY_LEN(ary) && (
unsigned int) i < pdispparams->cArgs; i++) {
448 pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
449 ole_val2ptr_variant(v, pvar);
454 exec_callback(
VALUE arg)
457 VALUE handler = parg[0];
459 VALUE args = parg[2];
460 return rb_apply(handler, mid, args);
464 rescue_callback(
VALUE arg)
482 find_iid(
VALUE ole,
char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
486 ITypeInfo *pTypeInfo;
490 ITypeInfo *pImplTypeInfo;
491 TYPEATTR *pImplTypeAttr;
500 BOOL is_found =
FALSE;
507 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
511 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
519 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
525 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
526 for (index = 0; index <
count; index++) {
527 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
538 if(pTypeAttr->typekind == TKIND_COCLASS) {
539 for (type = 0; type < pTypeAttr->cImplTypes; type++) {
540 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
545 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
551 hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
560 if (strcmp(pitf, pstr) == 0) {
561 hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
565 *piid = pImplTypeAttr->guid;
567 *ppTypeInfo = pImplTypeInfo;
568 (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
570 pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
576 if (is_found || FAILED(hr))
583 if (is_found || FAILED(hr))
588 return E_NOINTERFACE;
594 ITypeInfo *pTypeInfo,
596 ITypeInfo **pCOTypeInfo,
597 TYPEATTR **pCOTypeAttr)
603 ITypeInfo *pTypeInfo2;
604 TYPEATTR *pTypeAttr2;
608 ITypeInfo *pRefTypeInfo;
609 TYPEATTR *pRefTypeAttr;
611 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib,
NULL);
615 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
616 for (i = 0; i < count && !found; i++) {
617 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
625 if (pTypeAttr2->typekind != TKIND_COCLASS) {
630 for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
631 hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
634 if (!(flags & IMPLTYPEFLAG_FDEFAULT))
636 hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
639 hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
647 if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
658 *pCOTypeInfo = pTypeInfo2;
659 *pCOTypeAttr = pTypeAttr2;
668 find_default_source_from_typeinfo(
669 ITypeInfo *pTypeInfo,
671 ITypeInfo **ppTypeInfo)
678 for (i = 0; i < pTypeAttr->cImplTypes; i++) {
679 hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
687 if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
688 (flags & IMPLTYPEFLAG_FSOURCE)) {
690 hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
694 hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
695 hRefType, ppTypeInfo);
704 find_default_source(
VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
707 IProvideClassInfo2 *pProvideClassInfo2;
708 IProvideClassInfo *pProvideClassInfo;
712 ITypeInfo *pTypeInfo;
713 ITypeInfo *pTypeInfo2 =
NULL;
715 TYPEATTR *pTypeAttr2 =
NULL;
721 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
722 &IID_IProvideClassInfo2,
725 pProvideClassInfo2 = p;
726 hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
727 GUIDKIND_DEFAULT_SOURCE_DISP_IID,
731 hr = find_iid(ole,
NULL, piid, ppTypeInfo);
737 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
738 &IID_IProvideClassInfo,
741 pProvideClassInfo = p;
742 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
747 hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0,
cWIN32OLE_lcid, &pTypeInfo );
758 hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
760 hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
762 hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
777 hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
779 *piid = pTypeAttr->guid;
780 (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
796 for(i = 0; i <
len; i++) {
814 ole_search_event(
VALUE ary,
VALUE ev, BOOL *is_default)
823 for(i = 0; i <
len; i++) {
826 if(
NIL_P(event_name)) {
839 ole_search_handler_method(
VALUE handler,
VALUE ev, BOOL *is_default_handler)
843 *is_default_handler =
FALSE;
850 *is_default_handler =
TRUE;
860 at = ole_search_event_at(ary, ev);
868 oleevent_free(
void *ptr)
881 oleevent_size(
const void *ptr)
887 fev_s_allocate(VALUE klass)
908 ITypeInfo *pTypeInfo = 0;
910 IConnectionPointContainer *pContainer;
911 IConnectionPoint *pConnectionPoint;
929 hr = find_iid(ole, pitf, &iid, &pTypeInfo);
932 hr = find_default_source(ole, &iid, &pTypeInfo);
940 hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
941 &IID_IConnectionPointContainer,
946 "failed to query IConnectionPointContainer");
950 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
960 hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
968 pIEV->m_event_id = evs_length();
969 pIEV->pTypeInfo = pTypeInfo;
972 poleev->
event_id = pIEV->m_event_id;
990 fev_initialize(
int argc,
VALUE *argv,
VALUE self)
992 ev_advise(argc, argv,
self);
995 fev_set_handler(
self,
Qnil);
1003 while(PeekMessage(&msg,
NULL,0,0,PM_REMOVE)) {
1004 TranslateMessage(&msg);
1005 DispatchMessage(&msg);
1016 fev_s_msg_loop(
VALUE klass)
1030 ole_delete_event(events, event);
1038 VALUE event, args, data;
1053 add_event_call_back(
self, event, data);
1087 fev_on_event(
int argc,
VALUE *argv,
VALUE self)
1089 return ev_on_event(argc, argv,
self,
Qfalse);
1107 fev_on_event_with_outargs(
int argc,
VALUE *argv,
VALUE self)
1109 return ev_on_event(argc, argv,
self,
Qtrue);
1128 fev_off_event(
int argc,
VALUE *argv,
VALUE self)
1143 if (
NIL_P(events)) {
1146 ole_delete_event(events, event);
1166 fev_unadvise(
VALUE self)
1259 fev_get_handler(
VALUE self)
VALUE rb_apply(VALUE, ID, VALUE)
Calls a method.
PIEVENTSINKOBJ EVENTSINK_Constructor(void)
VALUE eWIN32OLERuntimeError
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
VALUE rb_ary_entry(VALUE ary, long offset)
#define RUBY_TYPED_FREE_IMMEDIATELY
void ruby_finalize(void)
Runs the VM finalization processes.
struct oledata * oledata_get_struct(VALUE ole)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ary_delete_at(VALUE ary, long pos)
#define TypedData_Get_Struct(obj, type, data_type, sval)
static REFIID LPOLESTR __RPC_FAR UINT cNames
VALUE rb_ary_push(VALUE ary, VALUE item)
STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK pEV, UINT info, LCID lcid, ITypeInfo **pInfo)
LPWSTR ole_vstr2wc(VALUE vstr)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
const IEventSinkVtbl * lpVtbl
#define OLE_GET_TYPEATTR(X, Y)
VALUE rb_ivar_get(VALUE, ID)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
double rb_big2dbl(VALUE x)
int rb_str_cmp(VALUE, VALUE)
IConnectionPoint * pConnectionPoint
EVENTSINK_AddRef(PEVENTSINK pEV)
STDMETHODIMP_(STDMETHODIMP_() EVENTSINK_Release(PEVENTSINK) ULONG)
const char * rb_obj_classname(VALUE)
#define RB_TYPE_P(obj, type)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
static DISPID REFIID LCID WORD wFlags
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
void rb_ary_store(VALUE ary, long idx, VALUE val)
#define ALLOCA_N(type, n)
void rb_gc_register_mark_object(VALUE obj)
STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
VALUE ole_variant2val(VARIANT *pvar)
VALUE rb_sprintf(const char *format,...)
char * ole_wc2mb(LPWSTR pw)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_ivar_set(VALUE, ID, VALUE)
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
struct IEventSinkVtbl * lpVtbl
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ
struct tagIEVENTSINKOBJ IEVENTSINKOBJ
void EVENTSINK_Destructor(PIEVENTSINKOBJ)
int rb_respond_to(VALUE, ID)
register unsigned int len
void Init_win32ole_event(void)
VALUE rb_block_proc(void)
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
VALUE rb_hash_aref(VALUE hash, VALUE key)
STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK pEV, UINT *pct)
STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID *)
VALUE rb_errinfo(void)
The current exception in the current thread.
#define TypedData_Make_Struct(klass, type, data_type, sval)
#define OLE_RELEASE_TYPEATTR(X, Y)
STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK pEventSink, REFIID riid, OLECHAR **szNames, UINT cNames, LCID lcid, DISPID *pDispID)
#define StringValuePtr(v)
VALUE rb_str_intern(VALUE)
struct IEventSink * PEVENTSINK
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
RUBY_EXTERN void rb_write_error_str(VALUE mesg)
void ole_val2variant(VALUE val, VARIANT *var)