static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) { FUNCDESC *pFuncDesc; HRESULT hr; BSTR *bstrs; UINT len, i; VALUE param; VALUE params = rb_ary_new(); hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); if (FAILED(hr)) return params; len = 0; bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, bstrs, pFuncDesc->cParams + 1, &len); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); return params; } SysFreeString(bstrs[0]); if (pFuncDesc->cParams > 0) { for(i = 1; i < len; i++) { param = create_win32ole_param(pTypeInfo, method_index, i-1, WC2VSTR(bstrs[i])); rb_ary_push(params, param); } } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); return params; }
/* * call-seq: * WIN32OLE_TYPELIB#path -> The type library file path. * * Returns the type library file path. * * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') * puts tlib.path #-> 'C:\...\EXCEL9.OLB' */ static VALUE foletypelib_path(VALUE self) { TLIBATTR *pTLibAttr; HRESULT hr = S_OK; BSTR bstr; LCID lcid = cWIN32OLE_lcid; VALUE path; ITypeLib *pTypeLib; pTypeLib = itypelib(self); oletypelib_get_libattr(pTypeLib, &pTLibAttr); hr = QueryPathOfRegTypeLib(&pTLibAttr->guid, pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum, lcid, &bstr); if (FAILED(hr)) { pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib"); } pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr); path = WC2VSTR(bstr); return path; }
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_variables(ITypeInfo *pTypeInfo) { HRESULT hr; TYPEATTR *pTypeAttr; WORD i; UINT len; BSTR bstr; VARDESC *pVarDesc; VALUE var; VALUE variables = rb_ary_new(); hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cVars; i++) { hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc); if(FAILED(hr)) continue; len = 0; hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr, 1, &len); if(FAILED(hr) || len == 0 || !bstr) continue; var = create_win32ole_variable(pTypeInfo, i, WC2VSTR(bstr)); rb_ary_push(variables, var); pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc); pVarDesc = NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return variables; }
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; }
static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams) { BSTR *bstrs; HRESULT hr; UINT len, i; VARIANT *pvar; VALUE val; VALUE key; len = 0; bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1); hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, bstrs, pdispparams->cArgs + 1, &len); if (FAILED(hr)) return; for (i = 0; i < len - 1; i++) { key = WC2VSTR(bstrs[i + 1]); val = rb_hash_aref(hash, INT2FIX(i)); if (val == Qnil) val = rb_hash_aref(hash, key); if (val == Qnil) val = rb_hash_aref(hash, rb_str_intern(key)); pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; ole_val2ptr_variant(val, pvar); } }
static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index) { HRESULT hr; BSTR bhelpfile; hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, NULL, &bhelpfile); if (FAILED(hr)) return Qnil; return WC2VSTR(bhelpfile); }
static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo) { HRESULT hr; BSTR bhelpfile; hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile); if(FAILED(hr)) { return Qnil; } return WC2VSTR(bhelpfile); }
/* * call-seq: * WIN32OLE_METHOD#event_interface * * Returns event interface name if the method is event. * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') * method = WIN32OLE_METHOD.new(tobj, 'SheetActivate') * puts method.event_interface # => WorkbookEvents */ static VALUE folemethod_event_interface(VALUE self) { BSTR name; struct olemethoddata *pmethod; HRESULT hr; TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod); if(folemethod_event(self) == Qtrue) { hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL); if(SUCCEEDED(hr)) return WC2VSTR(name); } return Qnil; }
/* * call-seq: * WIN32OLE_TYPELIB#library_name * * Returns library name. * If the method fails to access library name, WIN32OLERuntimeError is raised. * * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') * tlib.library_name # => Excel */ static VALUE foletypelib_library_name(VALUE self) { HRESULT hr; ITypeLib *pTypeLib = NULL; VALUE libname = Qnil; BSTR bstr; pTypeLib = itypelib(self); hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name"); } libname = WC2VSTR(bstr); return libname; }
/* * call-seq: * WIN32OLE_TYPELIB#name -> The type library name * * Returns the type library name. * * tlib = WIN32OLE_TYPELIB.new('Microsoft Excel 9.0 Object Library') * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library' */ static VALUE foletypelib_name(VALUE self) { ITypeLib *pTypeLib; HRESULT hr; BSTR bstr; VALUE name; pTypeLib = itypelib(self); hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1, NULL, &bstr, NULL, NULL); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib"); } name = WC2VSTR(bstr); return name; }
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 oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index) { FUNCDESC *pFuncDesc; HRESULT hr; BSTR *bstrs; UINT len; struct oleparamdata *pparam; hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); if (FAILED(hr)) ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc"); len = 0; bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1); hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid, bstrs, pFuncDesc->cParams + 1, &len); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames"); } SysFreeString(bstrs[0]); if (param_index < 1 || len <= (UINT)param_index) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); rb_raise(rb_eIndexError, "index of param must be in 1..%d", len); } TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam); pparam->pTypeInfo = pTypeInfo; OLE_ADDREF(pTypeInfo); pparam->method_index = method_index; pparam->index = param_index - 1; rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index])); pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); return self; }
static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask) { HRESULT hr; TYPEATTR *pTypeAttr; BSTR bstr; FUNCDESC *pFuncDesc; VALUE method; WORD i; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cFuncs; i++) { hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); continue; } if(pFuncDesc->invkind & mask) { method = folemethod_s_allocate(cWIN32OLE_METHOD); olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo, i, WC2VSTR(bstr)); rb_ary_push(methods, method); } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); pFuncDesc=NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return methods; }
static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name) { HRESULT hr; TYPEATTR *pTypeAttr; BSTR bstr; FUNCDESC *pFuncDesc; WORD i; VALUE fname; VALUE method = Qnil; hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr); if (FAILED(hr)) { ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr"); } for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) { hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc); if (FAILED(hr)) continue; hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, &bstr, NULL, NULL, NULL); if (FAILED(hr)) { pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); continue; } fname = WC2VSTR(bstr); if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) { olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname); method = self; } pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); pFuncDesc=NULL; } OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr); return method; }
STDMETHODIMP EVENTSINK_Invoke( PEVENTSINK pEventSink, DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr ) { HRESULT hr; BSTR bstr; unsigned int count; unsigned int i; ITypeInfo *pTypeInfo; VARIANT *pvar; VALUE ary, obj, event, args, outargv, ev, result; VALUE handler = Qnil; VALUE arg[3]; VALUE mid; VALUE is_outarg = Qfalse; BOOL is_default_handler = FALSE; int state; PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink; pTypeInfo = pEV->pTypeInfo; obj = evs_entry(pEV->m_event_id); if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) { return NOERROR; } ary = rb_ivar_get(obj, id_events); if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) { return NOERROR; } hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, &bstr, 1, &count); if (FAILED(hr)) { return NOERROR; } ev = WC2VSTR(bstr); event = ole_search_event(ary, ev, &is_default_handler); if (RB_TYPE_P(event, T_ARRAY)) { handler = rb_ary_entry(event, 0); mid = rb_intern("call"); is_outarg = rb_ary_entry(event, 3); } else { handler = rb_ivar_get(obj, rb_intern("handler")); if (handler == Qnil) { return NOERROR; } mid = ole_search_handler_method(handler, ev, &is_default_handler); } if (handler == Qnil || mid == Qnil) { return NOERROR; } args = rb_ary_new(); if (is_default_handler) { rb_ary_push(args, ev); } /* make argument of event handler */ for (i = 0; i < pdispparams->cArgs; ++i) { pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1]; rb_ary_push(args, ole_variant2val(pvar)); } outargv = Qnil; if (is_outarg == Qtrue) { outargv = rb_ary_new(); rb_ary_push(args, outargv); } /* * if exception raised in event callback, * then you receive cfp consistency error. * to avoid this error we use begin rescue end. * and the exception raised then error message print * and exit ruby process by Win32OLE itself. */ arg[0] = handler; arg[1] = mid; arg[2] = args; result = rb_protect(exec_callback, (VALUE)arg, &state); if (state != 0) { rescue_callback(Qnil); } if(RB_TYPE_P(result, T_HASH)) { hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams); result = hash2result(result); }else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) { ary2ptr_dispparams(outargv, pdispparams); } if (pvarResult) { VariantInit(pvarResult); ole_val2variant(result, pvarResult); } return NOERROR; }
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; }