25 STDMETHOD(GetTypeInfoCount)(
28 STDMETHOD(GetTypeInfo)(
33 STDMETHOD(GetIDsOfNames)(
67static VALUE ary_ole_event;
91static void ole_val2ptr_variant(
VALUE val, VARIANT *var);
92static void hash2ptr_dispparams(
VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
94static void ary2ptr_dispparams(
VALUE ary, DISPPARAMS *pdispparams);
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);
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);
110static void ole_msg_loop(
void);
121static VALUE evs_delete(
long i);
122static VALUE evs_entry(
long i);
123static long evs_length(
void);
128 {
NULL, oleevent_free, oleevent_size,},
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) ||
249 return E_NOINTERFACE;
251 ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
289 return DISP_E_BADINDEX;
300 ITypeInfo *pTypeInfo;
304 return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames,
cNames, pDispID);
306 return DISP_E_UNKNOWNNAME;
315 pEv->
lpVtbl = &vtEventSink;
334ole_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) :
372 *V_R4REF(var) = (float)
NUM2DBL(val);
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;
402hash2ptr_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);
431hash2result(
VALUE hash)
441ary2ptr_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);
457 VALUE handler = parg[0];
459 VALUE args = parg[2];
460 return rb_apply(handler, mid, args);
482find_iid(
VALUE ole,
char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
485 IDispatch *pDispatch;
486 ITypeInfo *pTypeInfo;
490 ITypeInfo *pImplTypeInfo;
491 TYPEATTR *pImplTypeAttr;
500 BOOL is_found =
FALSE;
511 hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
519 hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
525 count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
527 hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
538 if(pTypeAttr->typekind == TKIND_COCLASS) {
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;
668find_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);
704find_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;
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);
738 &IID_IProvideClassInfo,
741 pProvideClassInfo = p;
742 hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
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++) {
814ole_search_event(
VALUE ary,
VALUE ev, BOOL *is_default)
823 for(
i = 0;
i <
len;
i++) {
826 if(
NIL_P(event_name)) {
839ole_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);
868oleevent_free(
void *
ptr)
881oleevent_size(
const void *
ptr)
887fev_s_allocate(VALUE klass)
908 ITypeInfo *pTypeInfo = 0;
910 IConnectionPointContainer *pContainer;
911 IConnectionPoint *pConnectionPoint;
925 hr = find_iid(ole, pitf, &iid, &pTypeInfo);
928 hr = find_default_source(ole, &iid, &pTypeInfo);
937 &IID_IConnectionPointContainer,
942 "failed to query IConnectionPointContainer");
946 hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
964 pIEV->m_event_id = evs_length();
965 pIEV->pTypeInfo = pTypeInfo;
968 poleev->
event_id = pIEV->m_event_id;
991 fev_set_handler(
self,
Qnil);
999 while(PeekMessage(&msg,
NULL,0,0,PM_REMOVE)) {
1000 TranslateMessage(&msg);
1001 DispatchMessage(&msg);
1026 ole_delete_event(events, event);
1034 VALUE event, args, data;
1049 add_event_call_back(
self, event, data);
1139 if (
NIL_P(events)) {
1142 ole_delete_event(events, event);
1162fev_unadvise(
VALUE self)
1255fev_get_handler(
VALUE self)
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_cObject
Object class.
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
VALUE rb_errinfo(void)
The current exception in the current thread.
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
VALUE type(ANYARGS)
ANYARGS-ed function type.
struct IEventSinkVtbl * lpVtbl
STDMETHOD() QueryInterface(PEVENTSINK, REFIID, LPVOID *)
IConnectionPoint * pConnectionPoint
const IEventSinkVtbl * lpVtbl
LPWSTR ole_vstr2wc(VALUE vstr)
typedef HRESULT(STDAPICALLTYPE FNCOCREATEINSTANCEEX)(REFCLSID
static DISPID REFIID LCID WORD wFlags
VALUE ole_variant2val(VARIANT *pvar)
static DISPID REFIID LCID WORD DISPPARAMS __RPC_FAR VARIANT __RPC_FAR EXCEPINFO __RPC_FAR UINT __RPC_FAR * puArgErr
static REFIID LPOLESTR __RPC_FAR UINT cNames
char * ole_wc2mb(LPWSTR pw)
void ole_val2variant(VALUE val, VARIANT *var)
struct oledata * oledata_get_struct(VALUE ole)
#define OLE_RELEASE_TYPEATTR(X, Y)
#define OLE_GET_TYPEATTR(X, Y)
VALUE eWIN32OLERuntimeError
VALUE eWIN32OLEQueryInterfaceError
void ole_raise(HRESULT hr, VALUE ecs, const char *fmt,...)
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)
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)
struct tagIEVENTSINKOBJ * PIEVENTSINKOBJ