From 1a83b211895b86c681b74f24e0db19201ae60bc3 Mon Sep 17 00:00:00 2001 From: suke Date: Mon, 11 Aug 2014 21:20:10 +0000 Subject: [PATCH] * ext/win32ole/win32ole.c: seperate WIN32OLE_METHOD src from win32ole.c. * ext/win32ole/win32ole.h: ditto. * ext/win32ole/win32ole_method.c: ditto. * ext/win32ole/win32ole_method.h: ditto. * ext/win32ole/depend: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47145 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 9 + ext/win32ole/depend | 1 + ext/win32ole/win32ole.c | 915 +-------------------------------- ext/win32ole/win32ole.h | 7 +- ext/win32ole/win32ole_method.c | 888 ++++++++++++++++++++++++++++++++ ext/win32ole/win32ole_method.h | 15 + 6 files changed, 933 insertions(+), 902 deletions(-) create mode 100644 ext/win32ole/win32ole_method.c create mode 100644 ext/win32ole/win32ole_method.h diff --git a/ChangeLog b/ChangeLog index 05e9d8f919..b2777e36f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Tue Aug 12 06:16:09 2014 Masaki Suketa + + * ext/win32ole/win32ole.c: seperate WIN32OLE_METHOD src from + win32ole.c. + * ext/win32ole/win32ole.h: ditto. + * ext/win32ole/win32ole_method.c: ditto. + * ext/win32ole/win32ole_method.h: ditto. + * ext/win32ole/depend: ditto. + Mon Aug 11 22:19:15 2014 Masaki Suketa * ext/win32ole/win32ole_variable.c (folevariable_inspect): refactoring. diff --git a/ext/win32ole/depend b/ext/win32ole/depend index 6682f3da5c..ce3fe96d33 100644 --- a/ext/win32ole/depend +++ b/ext/win32ole/depend @@ -4,4 +4,5 @@ win32ole_variant_m.o : win32ole_variant_m.c $(WIN32OLE_HEADERS) win32ole_typelib.o : win32ole_typelib.c $(WIN32OLE_HEADERS) win32ole_type.o : win32ole_type.c $(WIN32OLE_HEADERS) win32ole_variable.o : win32ole_variable.c $(WIN32OLE_HEADERS) +win32ole_method.o : win32ole_method.c $(WIN32OLE_HEADERS) win32ole_error.o : win32ole_error.c $(WIN32OLE_HEADERS) diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index 495d4698bc..b40030a877 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -26,10 +26,6 @@ const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}}; #endif - - - - #define OLEData_Get_Struct(obj, pole) {\ Data_Get_Struct(obj, struct oledata, pole);\ if(!pole->pDispatch) {\ @@ -157,12 +153,6 @@ struct oledata { IDispatch *pDispatch; }; -struct olemethoddata { - ITypeInfo *pOwnerTypeInfo; - ITypeInfo *pTypeInfo; - UINT index; -}; - struct oleparamdata { ITypeInfo *pTypeInfo; UINT method_index; @@ -212,7 +202,6 @@ static void ole_freeexceptinfo(EXCEPINFO *pExInfo); static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo); static void ole_msg_loop(void); static void ole_free(struct oledata *pole); -static void olemethod_free(struct olemethoddata *polemethod); static void oleparam_free(struct oleparamdata *pole); static LPWSTR ole_mb2wc(char *pm, int len); static VALUE ole_ary_m_entry(VALUE val, LONG *pid); @@ -275,9 +264,6 @@ static VALUE ole_each_sub(VALUE pEnumV); static VALUE ole_ienum_free(VALUE pEnumV); static VALUE fole_each(VALUE self); static VALUE fole_missing(int argc, VALUE *argv, VALUE self); -static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name); -static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name); -static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask); static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti); static VALUE ole_methods(VALUE self, int mask); static VALUE fole_methods(VALUE self); @@ -292,43 +278,7 @@ static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE t static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); static VALUE fole_method_help(VALUE self, VALUE cmdname); static VALUE fole_activex_initialize(VALUE self); -static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name); -static VALUE folemethod_s_allocate(VALUE klass); -static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method); -static VALUE folemethod_name(VALUE self); -static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_return_type(VALUE self); -static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_return_vtype(VALUE self); -static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_return_type_detail(VALUE self); -static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_invkind(VALUE self); -static VALUE folemethod_invoke_kind(VALUE self); -static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_visible(VALUE self); -static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name); -static VALUE folemethod_event(VALUE self); -static VALUE folemethod_event_interface(VALUE self); -static HRESULT ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); -static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_helpstring(VALUE self); -static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_helpfile(VALUE self); -static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_helpcontext(VALUE self); -static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_dispid(VALUE self); -static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_offset_vtbl(VALUE self); -static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_size_params(VALUE self); -static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_size_opt_params(VALUE self); -static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index); -static VALUE folemethod_params(VALUE self); -static VALUE folemethod_inspect(VALUE self); + static VALUE foleparam_s_allocate(VALUE klass); static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index); static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n); @@ -1035,14 +985,6 @@ ole_free(struct oledata *pole) free(pole); } -static void -olemethod_free(struct olemethoddata *polemethod) -{ - OLE_FREE(polemethod->pTypeInfo); - OLE_FREE(polemethod->pOwnerTypeInfo); - free(polemethod); -} - static void oleparam_free(struct oleparamdata *pole) { @@ -3812,112 +3754,6 @@ fole_missing(int argc, VALUE *argv, VALUE self) } } -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; -} - -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; -} - -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; -} - VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask) { @@ -4457,8 +4293,10 @@ fole_method_help(VALUE self, VALUE cmdname) hr = typeinfo_from_ole(pole, &pTypeInfo); if(FAILED(hr)) ole_raise(hr, rb_eRuntimeError, "failed to get ITypeInfo"); + method = folemethod_s_allocate(cWIN32OLE_METHOD); obj = olemethod_from_typeinfo(method, pTypeInfo, cmdname); + OLE_RELEASE(pTypeInfo); if (obj == Qnil) rb_raise(eWIN32OLERuntimeError, "not found %s", @@ -4514,729 +4352,30 @@ fole_activex_initialize(VALUE self) return Qnil; } -/* - * Document-class: WIN32OLE_METHOD - * - * WIN32OLE_METHOD objects represent OLE method information. - */ - -static VALUE -olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) +VALUE +create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name) { - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - pmethod->pTypeInfo = pTypeInfo; - OLE_ADDREF(pTypeInfo); - pmethod->pOwnerTypeInfo = pOwnerTypeInfo; - if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo); - pmethod->index = index; - rb_ivar_set(self, rb_intern("name"), name); - return self; -} - -static VALUE -folemethod_s_allocate(VALUE klass) -{ - struct olemethoddata *pmethod; - VALUE obj; - obj = Data_Make_Struct(klass, - struct olemethoddata, - 0, olemethod_free, pmethod); - pmethod->pTypeInfo = NULL; - pmethod->pOwnerTypeInfo = NULL; - pmethod->index = 0; - return obj; -} - -/* - * call-seq: - * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object - * - * Returns a new WIN32OLE_METHOD object which represents the information - * about OLE method. - * The first argument ole_type specifies WIN32OLE_TYPE object. - * The second argument method specifies OLE method name defined OLE class - * which represents WIN32OLE_TYPE object. - * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') - */ -static VALUE -folemethod_initialize(VALUE self, VALUE oletype, VALUE method) -{ - VALUE obj = Qnil; - ITypeInfo *pTypeInfo; - if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { - SafeStringValue(method); - pTypeInfo = itypeinfo(oletype); - obj = olemethod_from_typeinfo(self, pTypeInfo, method); - if (obj == Qnil) { - rb_raise(eWIN32OLERuntimeError, "not found %s", - StringValuePtr(method)); - } - } - else { - rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); - } - return obj; -} - -/* - * call-seq - * WIN32OLE_METHOD#name - * - * Returns the name of the method. - * - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') - * puts method.name # => SaveAs - * - */ -static VALUE -folemethod_name(VALUE self) -{ - return rb_ivar_get(self, rb_intern("name")); -} - -static VALUE -ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE type; - - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); - - type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return type; -} - -/* - * call-seq: - * WIN32OLE_METHOD#return_type - * - * Returns string of return value type of method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.return_type # => Workbook - * - */ -static VALUE -folemethod_return_type(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE vvt; - - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); - - vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return vvt; -} - -/* - * call-seq: - * WIN32OLE_METHOD#return_vtype - * - * Returns number of return value type of method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.return_vtype # => 26 - * - */ -static VALUE -folemethod_return_vtype(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE type = rb_ary_new(); - - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return type; - - ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return type; -} - -/* - * call-seq: - * WIN32OLE_METHOD#return_type_detail - * - * Returns detail information of return value type of method. - * The information is array. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] - */ -static VALUE -folemethod_return_type_detail(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE invkind; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if(FAILED(hr)) - ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); - invkind = INT2FIX(pFuncDesc->invkind); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return invkind; -} - -static VALUE -ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) -{ - VALUE type = rb_str_new2("UNKNOWN"); - VALUE invkind = ole_method_invkind(pTypeInfo, method_index); - if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && - (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { - type = rb_str_new2("PROPERTY"); - } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { - type = rb_str_new2("PROPERTYGET"); - } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { - type = rb_str_new2("PROPERTYPUT"); - } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { - type = rb_str_new2("PROPERTYPUTREF"); - } else if(FIX2INT(invkind) & INVOKE_FUNC) { - type = rb_str_new2("FUNC"); - } - return type; -} - -/* - * call-seq: - * WIN32OLE_MTHOD#invkind - * - * Returns the method invoke kind. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.invkind # => 1 - * - */ -static VALUE -folemethod_invkind(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); -} - -/* - * call-seq: - * WIN32OLE_METHOD#invoke_kind - * - * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" - * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" - * or "FUNC". - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.invoke_kind # => "FUNC" - */ -static VALUE -folemethod_invoke_kind(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE visible; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if(FAILED(hr)) - return Qfalse; - if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | - FUNCFLAG_FHIDDEN | - FUNCFLAG_FNONBROWSABLE)) { - visible = Qfalse; - } else { - visible = Qtrue; - } - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return visible; -} - -/* - * call-seq: - * WIN32OLE_METHOD#visible? - * - * Returns true if the method is public. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.visible? # => true - */ -static VALUE -folemethod_visible(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_visible(pmethod->pTypeInfo, pmethod->index); -} - -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; -} - -/* - * call-seq: - * WIN32OLE_METHOD#event? - * - * Returns true 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? # => true - * - */ -static VALUE -folemethod_event(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - if (!pmethod->pOwnerTypeInfo) - return Qfalse; - return ole_method_event(pmethod->pOwnerTypeInfo, - pmethod->index, - rb_ivar_get(self, rb_intern("name"))); -} - -/* - * 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; - Data_Get_Struct(self, struct olemethoddata, 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; -} - -static HRESULT -ole_method_docinfo_from_type( - ITypeInfo *pTypeInfo, - UINT method_index, - BSTR *name, - BSTR *helpstr, - DWORD *helpcontext, - BSTR *helpfile - ) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return hr; - hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, - name, helpstr, - helpcontext, helpfile); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return hr; -} - -static VALUE -ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) -{ - HRESULT hr; - BSTR bhelpstring; - hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, - NULL, NULL); - if (FAILED(hr)) - return Qnil; - return WC2VSTR(bhelpstring); -} - -/* - * call-seq: - * WIN32OLE_METHOD#helpstring - * - * Returns help string of OLE method. If the help string is not found, - * then the method returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') - * method = WIN32OLE_METHOD.new(tobj, 'Navigate') - * puts method.helpstring # => Navigates to a URL or file. - * - */ -static VALUE -folemethod_helpstring(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); -} - -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); -} - -/* - * call-seq: - * WIN32OLE_METHOD#helpfile - * - * Returns help file. If help file is not found, then - * the method returns nil. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.helpfile # => C:\...\VBAXL9.CHM - */ -static VALUE -folemethod_helpfile(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - - return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) -{ - HRESULT hr; - DWORD helpcontext = 0; - hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, - &helpcontext, NULL); - if (FAILED(hr)) - return Qnil; - return INT2FIX(helpcontext); -} - -/* - * call-seq: - * WIN32OLE_METHOD#helpcontext - * - * Returns help context. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.helpcontext # => 65717 - */ -static VALUE -folemethod_helpcontext(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE dispid = Qnil; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return dispid; - dispid = INT2NUM(pFuncDesc->memid); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return dispid; -} - -/* - * call-seq: - * WIN32OLE_METHOD#dispid - * - * Returns dispatch ID. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.dispid # => 181 - */ -static VALUE -folemethod_dispid(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE offset_vtbl = Qnil; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return offset_vtbl; - offset_vtbl = INT2FIX(pFuncDesc->oVft); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return offset_vtbl; -} - -/* - * call-seq: - * WIN32OLE_METHOD#offset_vtbl - * - * Returns the offset ov VTBL. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') - * method = WIN32OLE_METHOD.new(tobj, 'Add') - * puts method.offset_vtbl # => 40 - */ -static VALUE -folemethod_offset_vtbl(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE size_params = Qnil; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return size_params; - size_params = INT2FIX(pFuncDesc->cParams); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return size_params; -} - -/* - * call-seq: - * WIN32OLE_METHOD#size_params - * - * Returns the size of arguments of the method. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') - * puts method.size_params # => 11 - * - */ -static VALUE -folemethod_size_params(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - VALUE size_opt_params = Qnil; - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return size_opt_params; - size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return size_opt_params; -} - -/* - * call-seq: - * WIN32OLE_METHOD#size_opt_params - * - * Returns the size of optional parameters. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') - * puts method.size_opt_params # => 4 - */ -static VALUE -folemethod_size_opt_params(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); -} - -static VALUE -ole_method_params(ITypeInfo *pTypeInfo, UINT method_index) -{ - FUNCDESC *pFuncDesc; - HRESULT hr; - BSTR *bstrs; - UINT len, i; struct oleparamdata *pparam; - VALUE param; - VALUE params = rb_ary_new(); - hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); - if (FAILED(hr)) - return params; + VALUE obj = foleparam_s_allocate(cWIN32OLE_PARAM); + Data_Get_Struct(obj, struct oleparamdata, pparam); - 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 = Data_Make_Struct(cWIN32OLE_PARAM, struct oleparamdata, 0, - oleparam_free, pparam); - pparam->pTypeInfo = pTypeInfo; - OLE_ADDREF(pTypeInfo); - pparam->method_index = method_index; - pparam->index = i - 1; - rb_ivar_set(param, rb_intern("name"), WC2VSTR(bstrs[i])); - rb_ary_push(params, param); - } - } - pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); - return params; + pparam->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pparam->method_index = method_index; + pparam->index = index; + rb_ivar_set(obj, rb_intern("name"), name); + return obj; } -/* - * call-seq: - * WIN32OLE_METHOD#params - * - * returns array of WIN32OLE_PARAM object corresponding with method parameters. - * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') - * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') - * p method.params # => [Filename, FileFormat, Password, WriteResPassword, - * ReadOnlyRecommended, CreateBackup, AccessMode, - * ConflictResolution, AddToMru, TextCodepage, - * TextVisualLayout] - */ -static VALUE -folemethod_params(VALUE self) -{ - struct olemethoddata *pmethod; - Data_Get_Struct(self, struct olemethoddata, pmethod); - return ole_method_params(pmethod->pTypeInfo, pmethod->index); -} - -/* - * call-seq: - * WIN32OLE_METHOD#inspect -> String - * - * Returns the method name with class name. - * - */ -static VALUE -folemethod_inspect(VALUE self) -{ - return default_inspect(self, "WIN32OLE_METHOD"); -} - /* * Document-class: WIN32OLE_PARAM * * WIN32OLE_PARAM objects represent param information of * the OLE method. */ -static VALUE foleparam_s_allocate(VALUE klass) +static VALUE +foleparam_s_allocate(VALUE klass) { struct oleparamdata *pparam; VALUE obj; @@ -7773,29 +6912,7 @@ Init_win32ole(void) Init_win32ole_typelib(); Init_win32ole_type(); Init_win32ole_variable(); - - cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); - rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); - rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); - rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); - rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); - rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); - rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); - rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); - rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); - rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); - rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); - rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); - rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); - rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); - rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); - rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); - rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); - rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); - rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); - rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); - rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); - rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); + Init_win32ole_method(); cWIN32OLE_PARAM = rb_define_class("WIN32OLE_PARAM", rb_cObject); rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate); diff --git a/ext/win32ole/win32ole.h b/ext/win32ole/win32ole.h index 2a5af705af..cda45fd048 100644 --- a/ext/win32ole/win32ole.h +++ b/ext/win32ole/win32ole.h @@ -96,10 +96,10 @@ #define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y))) #define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y))) + VALUE cWIN32OLE; LCID cWIN32OLE_lcid; - LPWSTR ole_vstr2wc(VALUE vstr); LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey); LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey); @@ -113,18 +113,19 @@ VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree); #define WC2VSTR(x) ole_wc2vstr((x), TRUE) BOOL ole_initialized(); -VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails); VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo); VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo); VALUE make_inspect(const char *class_name, VALUE detail); VALUE ole_variant2val(VARIANT *pvar); - +VALUE ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask); +VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name); #include "win32ole_variant_m.h" #include "win32ole_typelib.h" #include "win32ole_type.h" #include "win32ole_variable.h" +#include "win32ole_method.h" #include "win32ole_error.h" #endif diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c new file mode 100644 index 0000000000..9da7021d96 --- /dev/null +++ b/ext/win32ole/win32ole_method.c @@ -0,0 +1,888 @@ +#include "win32ole.h" + +static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name); +static void olemethod_free(struct olemethoddata *polemethod); +static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name); +static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method); +static VALUE folemethod_name(VALUE self); +static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_type(VALUE self); +static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_vtype(VALUE self); +static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_return_type_detail(VALUE self); +static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_invkind(VALUE self); +static VALUE folemethod_invoke_kind(VALUE self); +static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_visible(VALUE self); +static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name); +static VALUE folemethod_event(VALUE self); +static VALUE folemethod_event_interface(VALUE self); +static HRESULT ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile); +static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpstring(VALUE self); +static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpfile(VALUE self); +static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_helpcontext(VALUE self); +static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_dispid(VALUE self); +static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_offset_vtbl(VALUE self); +static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_size_params(VALUE self); +static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_size_opt_params(VALUE self); +static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index); +static VALUE folemethod_params(VALUE self); +static VALUE folemethod_inspect(VALUE self); + +static void +olemethod_free(struct olemethoddata *polemethod) +{ + OLE_FREE(polemethod->pTypeInfo); + OLE_FREE(polemethod->pOwnerTypeInfo); + free(polemethod); +} + +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; +} + +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_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; +} + +/* + * Document-class: WIN32OLE_METHOD + * + * WIN32OLE_METHOD objects represent OLE method information. + */ + +static VALUE +olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + pmethod->pTypeInfo = pTypeInfo; + OLE_ADDREF(pTypeInfo); + pmethod->pOwnerTypeInfo = pOwnerTypeInfo; + if(pOwnerTypeInfo) OLE_ADDREF(pOwnerTypeInfo); + pmethod->index = index; + rb_ivar_set(self, rb_intern("name"), name); + return self; +} + +VALUE +folemethod_s_allocate(VALUE klass) +{ + struct olemethoddata *pmethod; + VALUE obj; + obj = Data_Make_Struct(klass, + struct olemethoddata, + 0, olemethod_free, pmethod); + pmethod->pTypeInfo = NULL; + pmethod->pOwnerTypeInfo = NULL; + pmethod->index = 0; + return obj; +} + +/* + * call-seq: + * WIN32OLE_METHOD.new(ole_type, method) -> WIN32OLE_METHOD object + * + * Returns a new WIN32OLE_METHOD object which represents the information + * about OLE method. + * The first argument ole_type specifies WIN32OLE_TYPE object. + * The second argument method specifies OLE method name defined OLE class + * which represents WIN32OLE_TYPE object. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + */ +static VALUE +folemethod_initialize(VALUE self, VALUE oletype, VALUE method) +{ + VALUE obj = Qnil; + ITypeInfo *pTypeInfo; + if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) { + SafeStringValue(method); + pTypeInfo = itypeinfo(oletype); + obj = olemethod_from_typeinfo(self, pTypeInfo, method); + if (obj == Qnil) { + rb_raise(eWIN32OLERuntimeError, "not found %s", + StringValuePtr(method)); + } + } + else { + rb_raise(rb_eTypeError, "1st argument should be WIN32OLE_TYPE object"); + } + return obj; +} + +/* + * call-seq + * WIN32OLE_METHOD#name + * + * Returns the name of the method. + * + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.name # => SaveAs + * + */ +static VALUE +folemethod_name(VALUE self) +{ + return rb_ivar_get(self, rb_intern("name")); +} + +static VALUE +ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE type; + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + + type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_type + * + * Returns string of return value type of method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.return_type # => Workbook + * + */ +static VALUE +folemethod_return_type(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_return_type(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE vvt; + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + + vvt = INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return vvt; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_vtype + * + * Returns number of return value type of method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.return_vtype # => 26 + * + */ +static VALUE +folemethod_return_vtype(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE type = rb_ary_new(); + + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return type; + + ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return type; +} + +/* + * call-seq: + * WIN32OLE_METHOD#return_type_detail + * + * Returns detail information of return value type of method. + * The information is array. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"] + */ +static VALUE +folemethod_return_type_detail(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE invkind; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if(FAILED(hr)) + ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc"); + invkind = INT2FIX(pFuncDesc->invkind); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return invkind; +} + +static VALUE +ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index) +{ + VALUE type = rb_str_new2("UNKNOWN"); + VALUE invkind = ole_method_invkind(pTypeInfo, method_index); + if((FIX2INT(invkind) & INVOKE_PROPERTYGET) && + (FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) { + type = rb_str_new2("PROPERTY"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYGET) { + type = rb_str_new2("PROPERTYGET"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUT) { + type = rb_str_new2("PROPERTYPUT"); + } else if(FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) { + type = rb_str_new2("PROPERTYPUTREF"); + } else if(FIX2INT(invkind) & INVOKE_FUNC) { + type = rb_str_new2("FUNC"); + } + return type; +} + +/* + * call-seq: + * WIN32OLE_MTHOD#invkind + * + * Returns the method invoke kind. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.invkind # => 1 + * + */ +static VALUE +folemethod_invkind(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_invkind(pmethod->pTypeInfo, pmethod->index); +} + +/* + * call-seq: + * WIN32OLE_METHOD#invoke_kind + * + * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY" + * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF" + * or "FUNC". + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.invoke_kind # => "FUNC" + */ +static VALUE +folemethod_invoke_kind(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE visible; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if(FAILED(hr)) + return Qfalse; + if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED | + FUNCFLAG_FHIDDEN | + FUNCFLAG_FNONBROWSABLE)) { + visible = Qfalse; + } else { + visible = Qtrue; + } + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return visible; +} + +/* + * call-seq: + * WIN32OLE_METHOD#visible? + * + * Returns true if the method is public. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.visible? # => true + */ +static VALUE +folemethod_visible(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_visible(pmethod->pTypeInfo, pmethod->index); +} + +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; +} + +/* + * call-seq: + * WIN32OLE_METHOD#event? + * + * Returns true 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? # => true + * + */ +static VALUE +folemethod_event(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + if (!pmethod->pOwnerTypeInfo) + return Qfalse; + return ole_method_event(pmethod->pOwnerTypeInfo, + pmethod->index, + rb_ivar_get(self, rb_intern("name"))); +} + +/* + * 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; + Data_Get_Struct(self, struct olemethoddata, 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; +} + +static HRESULT +ole_method_docinfo_from_type( + ITypeInfo *pTypeInfo, + UINT method_index, + BSTR *name, + BSTR *helpstr, + DWORD *helpcontext, + BSTR *helpfile + ) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return hr; + hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid, + name, helpstr, + helpcontext, helpfile); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return hr; +} + +static VALUE +ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index) +{ + HRESULT hr; + BSTR bhelpstring; + hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring, + NULL, NULL); + if (FAILED(hr)) + return Qnil; + return WC2VSTR(bhelpstring); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpstring + * + * Returns help string of OLE method. If the help string is not found, + * then the method returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'IWebBrowser') + * method = WIN32OLE_METHOD.new(tobj, 'Navigate') + * puts method.helpstring # => Navigates to a URL or file. + * + */ +static VALUE +folemethod_helpstring(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index); +} + +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); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpfile + * + * Returns help file. If help file is not found, then + * the method returns nil. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.helpfile # => C:\...\VBAXL9.CHM + */ +static VALUE +folemethod_helpfile(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + + return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index) +{ + HRESULT hr; + DWORD helpcontext = 0; + hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL, + &helpcontext, NULL); + if (FAILED(hr)) + return Qnil; + return INT2FIX(helpcontext); +} + +/* + * call-seq: + * WIN32OLE_METHOD#helpcontext + * + * Returns help context. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.helpcontext # => 65717 + */ +static VALUE +folemethod_helpcontext(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE dispid = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return dispid; + dispid = INT2NUM(pFuncDesc->memid); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return dispid; +} + +/* + * call-seq: + * WIN32OLE_METHOD#dispid + * + * Returns dispatch ID. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.dispid # => 181 + */ +static VALUE +folemethod_dispid(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_dispid(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE offset_vtbl = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return offset_vtbl; + offset_vtbl = INT2FIX(pFuncDesc->oVft); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return offset_vtbl; +} + +/* + * call-seq: + * WIN32OLE_METHOD#offset_vtbl + * + * Returns the offset ov VTBL. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbooks') + * method = WIN32OLE_METHOD.new(tobj, 'Add') + * puts method.offset_vtbl # => 40 + */ +static VALUE +folemethod_offset_vtbl(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE size_params = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return size_params; + size_params = INT2FIX(pFuncDesc->cParams); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return size_params; +} + +/* + * call-seq: + * WIN32OLE_METHOD#size_params + * + * Returns the size of arguments of the method. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.size_params # => 11 + * + */ +static VALUE +folemethod_size_params(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_size_params(pmethod->pTypeInfo, pmethod->index); +} + +static VALUE +ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index) +{ + FUNCDESC *pFuncDesc; + HRESULT hr; + VALUE size_opt_params = Qnil; + hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc); + if (FAILED(hr)) + return size_opt_params; + size_opt_params = INT2FIX(pFuncDesc->cParamsOpt); + pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc); + return size_opt_params; +} + +/* + * call-seq: + * WIN32OLE_METHOD#size_opt_params + * + * Returns the size of optional parameters. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * puts method.size_opt_params # => 4 + */ +static VALUE +folemethod_size_opt_params(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index); +} + +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_METHOD#params + * + * returns array of WIN32OLE_PARAM object corresponding with method parameters. + * tobj = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'Workbook') + * method = WIN32OLE_METHOD.new(tobj, 'SaveAs') + * p method.params # => [Filename, FileFormat, Password, WriteResPassword, + * ReadOnlyRecommended, CreateBackup, AccessMode, + * ConflictResolution, AddToMru, TextCodepage, + * TextVisualLayout] + */ +static VALUE +folemethod_params(VALUE self) +{ + struct olemethoddata *pmethod; + Data_Get_Struct(self, struct olemethoddata, pmethod); + return ole_method_params(pmethod->pTypeInfo, pmethod->index); +} + +/* + * call-seq: + * WIN32OLE_METHOD#inspect -> String + * + * Returns the method name with class name. + * + */ +static VALUE +folemethod_inspect(VALUE self) +{ + return default_inspect(self, "WIN32OLE_METHOD"); +} + +void Init_win32ole_method() +{ + cWIN32OLE_METHOD = rb_define_class("WIN32OLE_METHOD", rb_cObject); + rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate); + rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2); + rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0); + rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0); + rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0); + rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0); + rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0); + rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0); + rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0); + rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0); + rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0); + rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0); + rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0); + rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0); + rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0); + rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0); + rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0); + rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0); + rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0); + rb_define_alias(cWIN32OLE_METHOD, "to_s", "name"); + rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0); +} diff --git a/ext/win32ole/win32ole_method.h b/ext/win32ole/win32ole_method.h new file mode 100644 index 0000000000..962a59c0d2 --- /dev/null +++ b/ext/win32ole/win32ole_method.h @@ -0,0 +1,15 @@ +#ifndef WIN32OLE_METHOD_H +#define WIN32OLE_METHOD_H 1 + +struct olemethoddata { + ITypeInfo *pOwnerTypeInfo; + ITypeInfo *pTypeInfo; + UINT index; +}; + +VALUE cWIN32OLE_METHOD; +VALUE folemethod_s_allocate(VALUE klass); +VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name); +VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask); +void Init_win32ole_method(); +#endif