/* * call-seq: * WIN32OLE_TYPE.new(typelib, ole_class) -> WIN32OLE_TYPE object * * Returns a new WIN32OLE_TYPE object. * The first argument <i>typelib</i> specifies OLE type library name. * The second argument specifies OLE class name. * * WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Application') * # => WIN32OLE_TYPE object of Application class of Excel. */ static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass) { VALUE file; OLECHAR * pbuf; ITypeLib *pTypeLib; HRESULT hr; SafeStringValue(oleclass); SafeStringValue(typelib); file = typelib_file(typelib); if (file == Qnil) { file = typelib; } pbuf = ole_vstr2wc(file); hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib); if (FAILED(hr)) ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx"); SysFreeString(pbuf); if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) { OLE_RELEASE(pTypeLib); rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`", StringValuePtr(oleclass), StringValuePtr(typelib)); } OLE_RELEASE(pTypeLib); return self; }
static void ole_event_free(struct oleeventdata *poleev) { if (poleev->pConnectionPoint) { poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); OLE_RELEASE(poleev->pConnectionPoint); poleev->pConnectionPoint = NULL; } OLE_RELEASE(poleev->pDispatch); free(poleev); }
static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; HREFTYPE href; ITypeInfo *pRefTypeInfo; VALUE method = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } method = ole_method_sub(self, 0, pTypeInfo, name); if (method != Qnil) { return method; } for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if(FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name); OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return method; }
VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; HREFTYPE href; ITypeInfo *pRefTypeInfo; VALUE methods = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } ole_methods_sub(0, pTypeInfo, methods, mask); for(i=0; i < pTypeAttr->cImplTypes; i++){ hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if(FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask); OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return methods; }
static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass) { long count; int i; HRESULT hr; BSTR bstr; VALUE typelib; ITypeInfo *pTypeInfo; VALUE found = Qfalse; count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); for (i = 0; i < count && found == Qfalse; i++) { hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); if (FAILED(hr)) continue; hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, &bstr, NULL, NULL, NULL); if (FAILED(hr)) continue; typelib = WC2VSTR(bstr); if (rb_str_cmp(oleclass, typelib) == 0) { oletype_set_member(self, pTypeInfo, typelib); found = Qtrue; } OLE_RELEASE(pTypeInfo); } return found; }
static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes) { long count; int i; HRESULT hr; BSTR bstr; ITypeInfo *pTypeInfo; VALUE type; count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); for (i = 0; i < count; i++) { hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i, &bstr, NULL, NULL, NULL); if (FAILED(hr)) continue; hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo); if (FAILED(hr)) continue; type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr)); rb_ary_push(classes, type); OLE_RELEASE(pTypeInfo); } return classes; }
void EVENTSINK_Destructor( PIEVENTSINKOBJ pEVObj ) { if(pEVObj != NULL) { OLE_RELEASE(pEVObj->pTypeInfo); free(pEVObj); pEVObj = NULL; } }
/* * call-seq: * WIN32OLE_EVENT#unadvise -> nil * * disconnects OLE server. If this method called, then the WIN32OLE_EVENT object * does not receive the OLE server event any more. * This method is trial implementation. * * ie = WIN32OLE.new('InternetExplorer.Application') * ev = WIN32OLE_EVENT.new(ie) * ev.on_event() {...} * ... * ev.unadvise * */ static VALUE fev_unadvise(VALUE self) { struct oleeventdata *poleev; Data_Get_Struct(self, struct oleeventdata, poleev); if (poleev->pConnectionPoint) { ole_msg_loop(); evs_delete(poleev->event_id); poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie); OLE_RELEASE(poleev->pConnectionPoint); poleev->pConnectionPoint = NULL; } OLE_FREE(poleev->pDispatch); return Qnil; }
static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags) { HRESULT hr; ITypeInfo *pRefTypeInfo; HREFTYPE href; WORD i; VALUE type; TYPEATTR *pTypeAttr; int flags; VALUE types = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { return types; } for (i = 0; i < pTypeAttr->cImplTypes; i++) { hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; if ((flags & implflags) == implflags) { type = ole_type_from_itypeinfo(pRefTypeInfo); if (type != Qnil) { rb_ary_push(types, type); } } OLE_RELEASE(pRefTypeInfo); } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return types; }
VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo) { ITypeLib *pTypeLib; VALUE type = Qnil; HRESULT hr; unsigned int index; BSTR bstr; hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index ); if(FAILED(hr)) { return Qnil; } hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index, &bstr, NULL, NULL, NULL); OLE_RELEASE(pTypeLib); if (FAILED(hr)) { return Qnil; } type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr)); return type; }
static VALUE ev_advise(int argc, VALUE *argv, VALUE self) { VALUE ole, itf; struct oledata *pole; char *pitf; HRESULT hr; IID iid; ITypeInfo *pTypeInfo = 0; IDispatch *pDispatch; IConnectionPointContainer *pContainer; IConnectionPoint *pConnectionPoint; IEVENTSINKOBJ *pIEV; DWORD dwCookie; struct oleeventdata *poleev; void *p; rb_scan_args(argc, argv, "11", &ole, &itf); if (!rb_obj_is_kind_of(ole, cWIN32OLE)) { rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object"); } if(!RB_TYPE_P(itf, T_NIL)) { pitf = StringValuePtr(itf); if (rb_safe_level() > 0 && OBJ_TAINTED(itf)) { rb_raise(rb_eSecurityError, "insecure event creation - `%s'", StringValuePtr(itf)); } hr = find_iid(ole, pitf, &iid, &pTypeInfo); } else { hr = find_default_source(ole, &iid, &pTypeInfo); } if (FAILED(hr)) { ole_raise(hr, rb_eRuntimeError, "interface not found"); } OLEData_Get_Struct(ole, pole); pDispatch = pole->pDispatch; hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IConnectionPointContainer, &p); if (FAILED(hr)) { OLE_RELEASE(pTypeInfo); ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPointContainer"); } pContainer = p; hr = pContainer->lpVtbl->FindConnectionPoint(pContainer, &iid, &pConnectionPoint); OLE_RELEASE(pContainer); if (FAILED(hr)) { OLE_RELEASE(pTypeInfo); ole_raise(hr, rb_eRuntimeError, "failed to query IConnectionPoint"); } pIEV = EVENTSINK_Constructor(); pIEV->m_iid = iid; hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint, (IUnknown*)pIEV, &dwCookie); if (FAILED(hr)) { ole_raise(hr, rb_eRuntimeError, "Advise Error"); } Data_Get_Struct(self, struct oleeventdata, poleev); pIEV->m_event_id = evs_length(); pIEV->pTypeInfo = pTypeInfo; poleev->dwCookie = dwCookie; poleev->pConnectionPoint = pConnectionPoint; poleev->event_id = pIEV->m_event_id; poleev->pDispatch = pDispatch; OLE_ADDREF(pDispatch); return self; }
static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo) { HRESULT hr; IProvideClassInfo2 *pProvideClassInfo2; IProvideClassInfo *pProvideClassInfo; void *p; IDispatch *pDispatch; ITypeInfo *pTypeInfo; ITypeInfo *pTypeInfo2 = NULL; TYPEATTR *pTypeAttr; TYPEATTR *pTypeAttr2 = NULL; struct oledata *pole; OLEData_Get_Struct(ole, pole); pDispatch = pole->pDispatch; hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IProvideClassInfo2, &p); if (SUCCEEDED(hr)) { pProvideClassInfo2 = p; hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2, GUIDKIND_DEFAULT_SOURCE_DISP_IID, piid); OLE_RELEASE(pProvideClassInfo2); if (SUCCEEDED(hr)) { hr = find_iid(ole, NULL, piid, ppTypeInfo); } } if (SUCCEEDED(hr)) { return hr; } hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IProvideClassInfo, &p); if (SUCCEEDED(hr)) { pProvideClassInfo = p; hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo, &pTypeInfo); OLE_RELEASE(pProvideClassInfo); } if (FAILED(hr)) { hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo ); } if (FAILED(hr)) return hr; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { OLE_RELEASE(pTypeInfo); return hr; } *ppTypeInfo = 0; hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo); if (!*ppTypeInfo) { hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2); if (SUCCEEDED(hr)) { hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo); OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); OLE_RELEASE(pTypeInfo2); } } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); OLE_RELEASE(pTypeInfo); /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */ if (!*ppTypeInfo) { if (SUCCEEDED(hr)) hr = E_UNEXPECTED; return hr; } /* Determine IID of default source interface */ hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr); if (SUCCEEDED(hr)) { *piid = pTypeAttr->guid; (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr); } else OLE_RELEASE(*ppTypeInfo); return hr; }
static HRESULT find_coclass( ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pCOTypeInfo, TYPEATTR **pCOTypeAttr) { HRESULT hr = E_NOINTERFACE; ITypeLib *pTypeLib; int count; BOOL found = FALSE; ITypeInfo *pTypeInfo2; TYPEATTR *pTypeAttr2; int flags; int i,j; HREFTYPE href; ITypeInfo *pRefTypeInfo; TYPEATTR *pRefTypeAttr; hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL); if (FAILED(hr)) { return hr; } count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); for (i = 0; i < count && !found; i++) { hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2); if (FAILED(hr)) continue; hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2); if (FAILED(hr)) { OLE_RELEASE(pTypeInfo2); continue; } if (pTypeAttr2->typekind != TKIND_COCLASS) { OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); OLE_RELEASE(pTypeInfo2); continue; } for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) { hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags); if (FAILED(hr)) continue; if (!(flags & IMPLTYPEFLAG_FDEFAULT)) continue; hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href); if (FAILED(hr)) continue; hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo); if (FAILED(hr)) continue; hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr); if (FAILED(hr)) { OLE_RELEASE(pRefTypeInfo); continue; } if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) { found = TRUE; } } if (!found) { OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2); OLE_RELEASE(pTypeInfo2); } } OLE_RELEASE(pTypeLib); if (found) { *pCOTypeInfo = pTypeInfo2; *pCOTypeAttr = pTypeAttr2; hr = S_OK; } else { hr = E_NOINTERFACE; } return hr; }
static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo) { HRESULT hr; IDispatch *pDispatch; ITypeInfo *pTypeInfo; ITypeLib *pTypeLib; TYPEATTR *pTypeAttr; HREFTYPE RefType; ITypeInfo *pImplTypeInfo; TYPEATTR *pImplTypeAttr; struct oledata *pole; unsigned int index; unsigned int count; int type; BSTR bstr; char *pstr; BOOL is_found = FALSE; LCID lcid = cWIN32OLE_lcid; OLEData_Get_Struct(ole, pole); pDispatch = pole->pDispatch; hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo); if (FAILED(hr)) return hr; hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index); OLE_RELEASE(pTypeInfo); if (FAILED(hr)) return hr; if (!pitf) { hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib, piid, ppTypeInfo); OLE_RELEASE(pTypeLib); return hr; } count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib); for (index = 0; index < count; index++) { hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo); if (FAILED(hr)) break; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if(FAILED(hr)) { OLE_RELEASE(pTypeInfo); break; } if(pTypeAttr->typekind == TKIND_COCLASS) { for (type = 0; type < pTypeAttr->cImplTypes; type++) { hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, type, &RefType); if (FAILED(hr)) break; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, RefType, &pImplTypeInfo); if (FAILED(hr)) break; hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo, -1, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { OLE_RELEASE(pImplTypeInfo); break; } pstr = ole_wc2mb(bstr); if (strcmp(pitf, pstr) == 0) { hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo, &pImplTypeAttr); if (SUCCEEDED(hr)) { is_found = TRUE; *piid = pImplTypeAttr->guid; if (ppTypeInfo) { *ppTypeInfo = pImplTypeInfo; (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo)); } pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo, pImplTypeAttr); } } free(pstr); OLE_RELEASE(pImplTypeInfo); if (is_found || FAILED(hr)) break; } } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); OLE_RELEASE(pTypeInfo); if (is_found || FAILED(hr)) break; } OLE_RELEASE(pTypeLib); if(!is_found) return E_NOINTERFACE; return hr; }
static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name) { TYPEATTR *pTypeAttr; HRESULT hr; WORD i; int flags; HREFTYPE href; ITypeInfo *pRefTypeInfo; FUNCDESC *pFuncDesc; BSTR bstr; VALUE name; VALUE event = Qfalse; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) return event; if(pTypeAttr->typekind != TKIND_COCLASS) { pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr); return event; } for (i = 0; i < pTypeAttr->cImplTypes; i++) { hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags); if (FAILED(hr)) continue; if (flags & IMPLTYPEFLAG_FSOURCE) { hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo); if (FAILED(hr)) continue; hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index, &pFuncDesc); if (FAILED(hr)) { OLE_RELEASE(pRefTypeInfo); continue; } hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); OLE_RELEASE(pRefTypeInfo); continue; } name = WC2VSTR(bstr); pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc); OLE_RELEASE(pRefTypeInfo); if (rb_str_cmp(method_name, name) == 0) { event = Qtrue; break; } } } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return event; }